diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-bbb-bone-buses.dtsi b/arch/arm/boot/dts/am335x-bbb-bone-buses.dtsi
--- a/arch/arm/boot/dts/am335x-bbb-bone-buses.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-bbb-bone-buses.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020 Deepak Khatri <deepaklorkhatri7@gmail.com>
+ * Copyright (C) 2021 Robert Nelson <robertcnelson@gmail.com>
+ * See Cape Interface Spec page for more info on Bone Buses
+ * https://elinux.org/Beagleboard:BeagleBone_cape_interface_spec
+ * https://docs.beagleboard.io/latest/boards/capes/cape-interface-spec.html
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+
+// For dummy refrence when peripheral is not available.
+&{/} {
+	not_available: not_available {
+		// Use &not_available when required.
+		// This node is responsible to create these entries,
+		// /sys/firmware/devicetree/base/__symbols__/not_available
+		// /sys/firmware/devicetree/base/not_available
+	};
+};
+
+// For compatible bone pinmuxing
+bone_pinmux: &am33xx_pinmux {
+	bborg_comms_can_pins: pinmux_comms_can_pins {
+		pinctrl-single,pins = <
+			0x184 (PIN_INPUT_PULLUP | MUX_MODE2)	/* P9_24: uart1_txd.d_can1_rx */
+			0x180 (PIN_OUTPUT_PULLUP | MUX_MODE2)	/* P9_26: uart1_rxd.d_can1_tx */
+		>;
+	};
+
+	bborg_comms_rs485_pins: pinmux_comms_rs485_pins {
+		pinctrl-single,pins = <
+			0x074 (PIN_OUTPUT | MUX_MODE6)	/* P9_13: gpmc_wpn.uart4_txd_mux2 */
+			0x070 (PIN_INPUT  | MUX_MODE6)	/* P9_11: gpmc_wait0.uart4_rxd_mux2 */
+		>;
+	};
+};
+
+// ADC
+bone_adc: &tscadc {
+
+};
+
+// CAN
+// https://docs.beagleboard.io/latest/boards/capes/cape-interface-spec.html#can
+bone_can_1: &dcan1 {
+	symlink = "bone/can/1";
+	status = "disabled";
+	pinctrl-names = "default";
+//	pinctrl-0 = <
+//		&P9_26_can_pin /* tx */
+//		&P9_24_can_pin /* rx */
+//	>;
+	pinctrl-0 = <&bborg_comms_can_pins>;
+};
+
+// UART
+// https://docs.beagleboard.io/latest/boards/capes/cape-interface-spec.html#uart
+bone_uart_4: &uart4 {
+	symlink = "bone/uart/4";
+	status = "disabled";
+	pinctrl-names = "default";
+	pinctrl-0 = <&bborg_comms_rs485_pins>;
+	//rs485-rts-delay = <0 0>;
+	//rts-gpio = <&gpio3 19 1>; /*  GPIO_ACTIVE_HIGH>; */
+	//rs485-rts-active-high;
+	//linux,rs485-enabled-at-boot-time;
+};
\ No newline at end of file
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts
--- a/arch/arm/boot/dts/am335x-boneblack.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-boneblack.dts	2024-01-28 14:01:31.236353764 -0500
@@ -12,6 +12,11 @@
 / {
 	model = "TI AM335x BeagleBone Black";
 	compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+
+	chosen {
+		base_dtb = "am335x-boneblack.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
 };
 
 &cpu0_opp_table {
@@ -21,6 +26,7 @@
 	 * to support 1GHz OPP so enable it for PG 2.0 on this board.
 	 */
 	oppnitro-1000000000 {
+		/* OPP Nitro */
 		opp-supported-hw = <0x06 0x0100>;
 	};
 };
@@ -34,7 +40,7 @@
 		"P9_18 [spi0_d1]",
 		"P9_17 [spi0_cs0]",
 		"[mmc0_cd]",
-		"P8_42A [ecappwm0]",
+		"P9_42A [ecappwm0]",
 		"P8_35 [lcd d12]",
 		"P8_33 [lcd d13]",
 		"P8_31 [lcd d14]",
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi b/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi
--- a/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -7,7 +7,7 @@
 #include <dt-bindings/interrupt-controller/irq.h>
 
 &am33xx_pinmux {
-	nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+	nxp_hdmi_bonelt_pins: nxp-hdmi-bonelt-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)
 			AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
@@ -33,13 +33,13 @@
 		>;
 	};
 
-	nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+	nxp_hdmi_bonelt_off_pins: nxp-hdmi-bonelt-off-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)
 		>;
 	};
 
-	mcasp0_pins: mcasp0_pins {
+	mcasp0_pins: mcasp0-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLUP, MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
 			AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
@@ -85,8 +85,13 @@
 		audio-ports = <	TDA998x_I2S	0x03>;
 
 		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
 			port@0 {
-				hdmi_0: endpoint@0 {
+				reg = <0>;
+
+				hdmi_0: endpoint {
 					remote-endpoint = <&lcdc_0>;
 				};
 			};
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-boneblack-pps.dts b/arch/arm/boot/dts/am335x-boneblack-pps.dts
--- a/arch/arm/boot/dts/am335x-boneblack-pps.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-boneblack-pps.dts	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include "am335x-boneblack.dts"
+
+&am33xx_pinmux {
+	pwm7_pins: pinmux_pwm7_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_OEN_REN, PIN_OUTPUT_PULLDOWN, MUX_MODE2)
+		>;
+	};
+};
+
+/{
+	pwm7: dmtimer-pwm7 {
+		compatible = "ti,omap-dmtimer-pwm";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pwm7_pins>;
+		#pwm-cells = <3>;
+		ti,timers = <&timer7>;
+		ti,clock-source = <0x00>; /* timer_sys_ck */
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-boneblack-uboot.dts b/arch/arm/boot/dts/am335x-boneblack-uboot.dts
--- a/arch/arm/boot/dts/am335x-boneblack-uboot.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-boneblack-uboot.dts	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+#include "am335x-bbb-bone-buses.dtsi"
+
+/ {
+	model = "TI AM335x BeagleBone Black";
+	compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+
+	chosen {
+		base_dtb = "am335x-boneblack-uboot.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+};
+
+&cpu0_opp_table {
+	/*
+	 * All PG 2.0 silicon may not support 1GHz but some of the early
+	 * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+	 * to support 1GHz OPP so enable it for PG 2.0 on this board.
+	 */
+	oppnitro-1000000000 {
+		/* OPP Nitro */
+		opp-supported-hw = <0x06 0x0100>;
+	};
+};
+
+&ldo3_reg {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-always-on;
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&gpio0 {
+	gpio-line-names =
+		"[mdio_data]",
+		"[mdio_clk]",
+		"P9_22 [spi0_sclk]",
+		"P9_21 [spi0_d0]",
+		"P9_18 [spi0_d1]",
+		"P9_17 [spi0_cs0]",
+		"[mmc0_cd]",
+		"P9_42A [ecappwm0]",
+		"P8_35 [lcd d12]",
+		"P8_33 [lcd d13]",
+		"P8_31 [lcd d14]",
+		"P8_32 [lcd d15]",
+		"P9_20 [i2c2_sda]",
+		"P9_19 [i2c2_scl]",
+		"P9_26 [uart1_rxd]",
+		"P9_24 [uart1_txd]",
+		"[rmii1_txd3]",
+		"[rmii1_txd2]",
+		"[usb0_drvvbus]",
+		"[hdmi cec]",
+		"P9_41B",
+		"[rmii1_txd1]",
+		"P8_19 [ehrpwm2a]",
+		"P8_13 [ehrpwm2b]",
+		"NC",
+		"NC",
+		"P8_14",
+		"P8_17",
+		"[rmii1_txd0]",
+		"[rmii1_refclk]",
+		"P9_11 [uart4_rxd]",
+		"P9_13 [uart4_txd]";
+};
+
+&gpio1 {
+	gpio-line-names =
+		"P8_25 [mmc1_dat0]",
+		"[mmc1_dat1]",
+		"P8_5 [mmc1_dat2]",
+		"P8_6 [mmc1_dat3]",
+		"P8_23 [mmc1_dat4]",
+		"P8_22 [mmc1_dat5]",
+		"P8_3 [mmc1_dat6]",
+		"P8_4 [mmc1_dat7]",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"P8_12",
+		"P8_11",
+		"P8_16",
+		"P8_15",
+		"P9_15A",
+		"P9_23",
+		"P9_14 [ehrpwm1a]",
+		"P9_16 [ehrpwm1b]",
+		"[emmc rst]",
+		"[usr0 led]",
+		"[usr1 led]",
+		"[usr2 led]",
+		"[usr3 led]",
+		"[hdmi irq]",
+		"[usb vbus oc]",
+		"[hdmi audio]",
+		"P9_12",
+		"P8_26",
+		"P8_21 [emmc]",
+		"P8_20 [emmc]";
+};
+
+&gpio2 {
+	gpio-line-names =
+		"P9_15B",
+		"P8_18",
+		"P8_7",
+		"P8_8",
+		"P8_10",
+		"P8_9",
+		"P8_45 [hdmi]",
+		"P8_46 [hdmi]",
+		"P8_43 [hdmi]",
+		"P8_44 [hdmi]",
+		"P8_41 [hdmi]",
+		"P8_42 [hdmi]",
+		"P8_39 [hdmi]",
+		"P8_40 [hdmi]",
+		"P8_37 [hdmi]",
+		"P8_38 [hdmi]",
+		"P8_36 [hdmi]",
+		"P8_34 [hdmi]",
+		"[rmii1_rxd3]",
+		"[rmii1_rxd2]",
+		"[rmii1_rxd1]",
+		"[rmii1_rxd0]",
+		"P8_27 [hdmi]",
+		"P8_29 [hdmi]",
+		"P8_28 [hdmi]",
+		"P8_30 [hdmi]",
+		"[mmc0_dat3]",
+		"[mmc0_dat2]",
+		"[mmc0_dat1]",
+		"[mmc0_dat0]",
+		"[mmc0_clk]",
+		"[mmc0_cmd]";
+};
+
+&gpio3 {
+	gpio-line-names =
+		"[mii col]",
+		"[mii crs]",
+		"[mii rx err]",
+		"[mii tx en]",
+		"[mii rx dv]",
+		"[i2c0 sda]",
+		"[i2c0 scl]",
+		"[jtag emu0]",
+		"[jtag emu1]",
+		"[mii tx clk]",
+		"[mii rx clk]",
+		"NC",
+		"NC",
+		"[usb vbus en]",
+		"P9_31 [spi1_sclk]",
+		"P9_29 [spi1_d0]",
+		"P9_30 [spi1_d1]",
+		"P9_28 [spi1_cs0]",
+		"P9_42B [ecappwm0]",
+		"P9_27",
+		"P9_41A",
+		"P9_25",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC";
+};
+
+&baseboard_eeprom {
+	vcc-supply = <&ldo4_reg>;
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-boneblack-uboot-univ.dts b/arch/arm/boot/dts/am335x-boneblack-uboot-univ.dts
--- a/arch/arm/boot/dts/am335x-boneblack-uboot-univ.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-boneblack-uboot-univ.dts	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+#include "am335x-bone-common-univ.dtsi"
+
+/ {
+	model = "TI AM335x BeagleBone Black";
+	compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+
+	chosen {
+		base_dtb = "am335x-boneblack-uboot-univ.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		reg = <0x80000000 0x20000000>; /* 512 MB */
+	};
+};
+
+&cpu0_opp_table {
+	/*
+	 * All PG 2.0 silicon may not support 1GHz but some of the early
+	 * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+	 * to support 1GHz OPP so enable it for PG 2.0 on this board.
+	 */
+	oppnitro-1000000000 {
+		opp-supported-hw = <0x06 0x0100>;
+	};
+};
+
+&ldo3_reg {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-always-on;
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&gpio0 {
+	gpio-line-names =
+		"[mdio_data]",
+		"[mdio_clk]",
+		"P9_22 [spi0_sclk]",
+		"P9_21 [spi0_d0]",
+		"P9_18 [spi0_d1]",
+		"P9_17 [spi0_cs0]",
+		"[mmc0_cd]",
+		"P8_42A [ecappwm0]",
+		"P8_35 [lcd d12]",
+		"P8_33 [lcd d13]",
+		"P8_31 [lcd d14]",
+		"P8_32 [lcd d15]",
+		"P9_20 [i2c2_sda]",
+		"P9_19 [i2c2_scl]",
+		"P9_26 [uart1_rxd]",
+		"P9_24 [uart1_txd]",
+		"[rmii1_txd3]",
+		"[rmii1_txd2]",
+		"[usb0_drvvbus]",
+		"[hdmi cec]",
+		"P9_41B",
+		"[rmii1_txd1]",
+		"P8_19 [ehrpwm2a]",
+		"P8_13 [ehrpwm2b]",
+		"NC",
+		"NC",
+		"P8_14",
+		"P8_17",
+		"[rmii1_txd0]",
+		"[rmii1_refclk]",
+		"P9_11 [uart4_rxd]",
+		"P9_13 [uart4_txd]";
+};
+
+&gpio1 {
+	gpio-line-names =
+		"P8_25 [mmc1_dat0]",
+		"[mmc1_dat1]",
+		"P8_5 [mmc1_dat2]",
+		"P8_6 [mmc1_dat3]",
+		"P8_23 [mmc1_dat4]",
+		"P8_22 [mmc1_dat5]",
+		"P8_3 [mmc1_dat6]",
+		"P8_4 [mmc1_dat7]",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"P8_12",
+		"P8_11",
+		"P8_16",
+		"P8_15",
+		"P9_15A",
+		"P9_23",
+		"P9_14 [ehrpwm1a]",
+		"P9_16 [ehrpwm1b]",
+		"[emmc rst]",
+		"[usr0 led]",
+		"[usr1 led]",
+		"[usr2 led]",
+		"[usr3 led]",
+		"[hdmi irq]",
+		"[usb vbus oc]",
+		"[hdmi audio]",
+		"P9_12",
+		"P8_26",
+		"P8_21 [emmc]",
+		"P8_20 [emmc]";
+};
+
+&gpio2 {
+	gpio-line-names =
+		"P9_15B",
+		"P8_18",
+		"P8_7",
+		"P8_8",
+		"P8_10",
+		"P8_9",
+		"P8_45 [hdmi]",
+		"P8_46 [hdmi]",
+		"P8_43 [hdmi]",
+		"P8_44 [hdmi]",
+		"P8_41 [hdmi]",
+		"P8_42 [hdmi]",
+		"P8_39 [hdmi]",
+		"P8_40 [hdmi]",
+		"P8_37 [hdmi]",
+		"P8_38 [hdmi]",
+		"P8_36 [hdmi]",
+		"P8_34 [hdmi]",
+		"[rmii1_rxd3]",
+		"[rmii1_rxd2]",
+		"[rmii1_rxd1]",
+		"[rmii1_rxd0]",
+		"P8_27 [hdmi]",
+		"P8_29 [hdmi]",
+		"P8_28 [hdmi]",
+		"P8_30 [hdmi]",
+		"[mmc0_dat3]",
+		"[mmc0_dat2]",
+		"[mmc0_dat1]",
+		"[mmc0_dat0]",
+		"[mmc0_clk]",
+		"[mmc0_cmd]";
+};
+
+&gpio3 {
+	gpio-line-names =
+		"[mii col]",
+		"[mii crs]",
+		"[mii rx err]",
+		"[mii tx en]",
+		"[mii rx dv]",
+		"[i2c0 sda]",
+		"[i2c0 scl]",
+		"[jtag emu0]",
+		"[jtag emu1]",
+		"[mii tx clk]",
+		"[mii rx clk]",
+		"NC",
+		"NC",
+		"[usb vbus en]",
+		"P9_31 [spi1_sclk]",
+		"P9_29 [spi1_d0]",
+		"P9_30 [spi1_d1]",
+		"P9_28 [spi1_cs0]",
+		"P9_42B [ecappwm0]",
+		"P9_27",
+		"P9_41A",
+		"P9_25",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC";
+};
+
+&baseboard_eeprom {
+	vcc-supply = <&ldo4_reg>;
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-boneblack-wireless.dts b/arch/arm/boot/dts/am335x-boneblack-wireless.dts
--- a/arch/arm/boot/dts/am335x-boneblack-wireless.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-boneblack-wireless.dts	2024-01-28 14:01:31.236353764 -0500
@@ -14,6 +14,11 @@
 	model = "TI AM335x BeagleBone Black Wireless";
 	compatible = "ti,am335x-bone-black-wireless", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
 
+	chosen {
+		base_dtb = "am335x-boneblack-wireless.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
+
 	wlan_en_reg: fixedregulator@2 {
 		compatible = "regulator-fixed";
 		regulator-name = "wlan-en-regulator";
@@ -28,13 +33,13 @@
 };
 
 &am33xx_pinmux {
-	bt_pins: pinmux_bt_pins {
+	bt_pins: bt-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gmii1_txd0.gpio0_28 - BT_EN */
 		>;
 	};
 
-	mmc3_pins: pinmux_mmc3_pins {
+	mmc3_pins: mmc3-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */
 			AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */
@@ -45,7 +50,7 @@
 		>;
 	};
 
-	uart3_pins: pinmux_uart3_pins {
+	uart3_pins: uart3-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1)	/* gmii1_rxd3.uart3_rxd */
 			AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1)	/* gmii1_rxd2.uart3_txd */
@@ -54,7 +59,7 @@
 		>;
 	};
 
-	wl18xx_pins: pinmux_wl18xx_pins {
+	wl18xx_pins: wl18xx-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gmii1_txclk.gpio3_9 WL_EN */
 			AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)	/* rmii1_refclk.gpio0_29 WL_IRQ */
@@ -64,6 +69,9 @@
 };
 
 &mac_sw {
+	/delete-property/pinctrl-names;
+	/delete-property/pinctrl-0;
+	/delete-property/pinctrl-1;
 	status = "disabled";
 };
 
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-boneblue.dts b/arch/arm/boot/dts/am335x-boneblue.dts
--- a/arch/arm/boot/dts/am335x-boneblue.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-boneblue.dts	2024-01-28 14:01:31.236353764 -0500
@@ -14,6 +14,8 @@
 
 	chosen {
 		stdout-path = &uart0;
+		base_dtb = "am335x-boneblue.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
 	};
 
 	leds {
@@ -115,7 +117,7 @@
 };
 
 &am33xx_pinmux {
-	user_leds_s0: user_leds_s0 {
+	user_leds_s0: user-leds-s0-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT, MUX_MODE7) /* (V15) gpmc_a5.gpio1[21] - USR_LED_0 */
 			AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT, MUX_MODE7) /* (U15) gpmc_a6.gpio1[22] - USR_LED_1 */
@@ -132,7 +134,7 @@
 		>;
 	};
 
-	i2c2_pins: pinmux_i2c2_pins {
+	i2c2_pins: i2c2-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3)	/* (D18) uart1_ctsn.I2C2_SDA */
 			AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLUP, MUX_MODE3)	/* (D17) uart1_rtsn.I2C2_SCL */
@@ -140,7 +142,7 @@
 	};
 
 	/* UT0 */
-	uart0_pins: pinmux_uart0_pins {
+	uart0_pins: uart0-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
 			AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
@@ -148,7 +150,7 @@
 	};
 
 	/* UT1 */
-	uart1_pins: pinmux_uart1_pins {
+	uart1_pins: uart1-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
 			AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
@@ -156,7 +158,7 @@
 	};
 
 	/* GPS */
-	uart2_pins: pinmux_uart2_pins {
+	uart2_pins: uart2-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE1)	/* (A17) spi0_sclk.uart2_rxd */
 			AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT_PULLDOWN, MUX_MODE1)	/* (B17) spi0_d0.uart2_txd */
@@ -164,27 +166,27 @@
 	};
 
 	/* DSM2 */
-	uart4_pins: pinmux_uart4_pins {
+	uart4_pins: uart4-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE6)	/* (T17) gpmc_wait0.uart4_rxd */
 		>;
 	};
 
 	/* UT5 */
-	uart5_pins: pinmux_uart5_pins {
+	uart5_pins: uart5-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_INPUT_PULLUP, MUX_MODE4)	/* (U2) lcd_data9.uart5_rxd */
 			AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT_PULLDOWN, MUX_MODE4)	/* (U1) lcd_data8.uart5_txd */
 		>;
 	};
 
-	mmc1_pins: pinmux_mmc1_pins {
+	mmc1_pins: mmc1-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7)		/* (C15) spi0_cs1.gpio0[6] */
 		>;
 	};
 
-	mmc2_pins: pinmux_mmc2_pins {
+	mmc2_pins: mmc2-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2)	/* (U9) gpmc_csn1.mmc1_clk */
 			AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2)	/* (V9) gpmc_csn2.mmc1_cmd */
@@ -199,7 +201,7 @@
 		>;
 	};
 
-	mmc3_pins: pinmux_mmc3_pins {
+	mmc3_pins: mmc3-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6)	/* (L15) gmii1_rxd1.mmc2_clk */
 			AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6)	/* (J16) gmii1_txen.mmc2_cmd */
@@ -210,13 +212,13 @@
 		>;
 	};
 
-	bt_pins: pinmux_bt_pins {
+	bt_pins: bt-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* (K17) gmii1_txd0.gpio0[28] - BT_EN */
 		>;
 	};
 
-	uart3_pins: pinmux_uart3_pins {
+	uart3_pins: uart3-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1)	/* (L17) gmii1_rxd3.uart3_rxd */
 			AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1)	/* (L16) gmii1_rxd2.uart3_txd */
@@ -225,7 +227,7 @@
 		>;
 	};
 
-	wl18xx_pins: pinmux_wl18xx_pins {
+	wl18xx_pins: wl18xx-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* (K18) gmii1_txclk.gpio3[9] - WL_EN */
 			AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_INPUT_PULLDOWN, MUX_MODE7)	/* (K16) gmii1_txd1.gpio0[21] - WL_IRQ */
@@ -234,7 +236,7 @@
 	};
 
 	/* DCAN */
-	dcan1_pins: pinmux_dcan1_pins {
+	dcan1_pins: dcan1-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT, MUX_MODE2)		/* (E17) uart0_rtsn.dcan1_rx */
 			AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT, MUX_MODE2)		/* (E18) uart0_ctsn.dcan1_tx */
@@ -243,7 +245,7 @@
 	};
 
 	/* E1 */
-	eqep0_pins: pinmux_eqep0_pins {
+	eqep0_pins: eqep0-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_INPUT, MUX_MODE1)		/* (B12) mcasp0_aclkr.eQEP0A_in */
 			AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_INPUT, MUX_MODE1)		/* (C13) mcasp0_fsr.eQEP0B_in */
@@ -251,7 +253,7 @@
 	};
 
 	/* E2 */
-	eqep1_pins: pinmux_eqep1_pins {
+	eqep1_pins: eqep1-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_INPUT, MUX_MODE2)		/* (V2) lcd_data12.eQEP1A_in */
 			AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_INPUT, MUX_MODE2)		/* (V3) lcd_data13.eQEP1B_in */
@@ -259,7 +261,7 @@
 	};
 
 	/* E3 */
-	eqep2_pins: pinmux_eqep2_pins {
+	eqep2_pins: eqep2-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT, MUX_MODE4)		/* (T12) gpmc_ad12.eQEP2A_in */
 			AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT, MUX_MODE4)		/* (R12) gpmc_ad13.eQEP2B_in */
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
--- a/arch/arm/boot/dts/am335x-bone-common.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -3,6 +3,8 @@
  * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
  */
 
+#include "am335x-bbb-bone-buses.dtsi"
+
 / {
 	cpus {
 		cpu@0 {
@@ -26,14 +28,14 @@
 		compatible = "gpio-leds";
 
 		led2 {
-			label = "beaglebone:green:heartbeat";
+			label = "beaglebone:green:usr0";
 			gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "heartbeat";
 			default-state = "off";
 		};
 
 		led3 {
-			label = "beaglebone:green:mmc0";
+			label = "beaglebone:green:usr1";
 			gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "mmc0";
 			default-state = "off";
@@ -63,10 +65,7 @@
 };
 
 &am33xx_pinmux {
-	pinctrl-names = "default";
-	pinctrl-0 = <&clkout2_pin>;
-
-	user_leds_s0: user_leds_s0 {
+	user_leds_s0: user-leds-s0-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gpmc_a5.gpio1_21 */
 			AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_a6.gpio1_22 */
@@ -75,34 +74,28 @@
 		>;
 	};
 
-	i2c0_pins: pinmux_i2c0_pins {
+	i2c0_pins: i2c0-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_I2C0_SDA, PIN_INPUT_PULLUP, MUX_MODE0)	/* i2c0_sda.i2c0_sda */
 			AM33XX_PADCONF(AM335X_PIN_I2C0_SCL, PIN_INPUT_PULLUP, MUX_MODE0)	/* i2c0_scl.i2c0_scl */
 		>;
 	};
 
-	i2c2_pins: pinmux_i2c2_pins {
+	i2c2_pins: i2c2-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3)	/* uart1_ctsn.i2c2_sda */
 			AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLUP, MUX_MODE3)	/* uart1_rtsn.i2c2_scl */
 		>;
 	};
 
-	uart0_pins: pinmux_uart0_pins {
+	uart0_pins: uart0-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_UART0_RXD, PIN_INPUT_PULLUP, MUX_MODE0)
 			AM33XX_PADCONF(AM335X_PIN_UART0_TXD, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
 		>;
 	};
 
-	clkout2_pin: pinmux_clkout2_pin {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3)	/* xdma_event_intr1.clkout2 */
-		>;
-	};
-
-	cpsw_default: cpsw_default {
+	cpsw_default: cpsw-default-pins {
 		pinctrl-single,pins = <
 			/* Slave 1 */
 			AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLUP, MUX_MODE0)
@@ -121,7 +114,7 @@
 		>;
 	};
 
-	cpsw_sleep: cpsw_sleep {
+	cpsw_sleep: cpsw-sleep-pins {
 		pinctrl-single,pins = <
 			/* Slave 1 reset value */
 			AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7)
@@ -140,23 +133,27 @@
 		>;
 	};
 
-	davinci_mdio_default: davinci_mdio_default {
+	davinci_mdio_default: davinci-mdio-default-pins {
 		pinctrl-single,pins = <
 			/* MDIO */
 			AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
 			AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLUP, MUX_MODE0)
+			/* Added to support GPIO controlled PHY reset */
+			AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_OUTPUT_PULLUP, MUX_MODE7)
 		>;
 	};
 
-	davinci_mdio_sleep: davinci_mdio_sleep {
+	davinci_mdio_sleep: davinci-mdio-sleep-pins {
 		pinctrl-single,pins = <
 			/* MDIO reset value */
 			AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
 			AM33XX_PADCONF(AM335X_PIN_MDC, PIN_INPUT_PULLDOWN, MUX_MODE7)
+			/* Added to support GPIO controlled PHY reset */
+			AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLDOWN, MUX_MODE7)
 		>;
 	};
 
-	mmc1_pins: pinmux_mmc1_pins {
+	mmc1_pins: mmc1-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_SPI0_CS1, PIN_INPUT, MUX_MODE7)		/* spio0_cs1.gpio0_6 */
 			AM33XX_PADCONF(AM335X_PIN_MMC0_DAT0, PIN_INPUT_PULLUP, MUX_MODE0)
@@ -168,7 +165,7 @@
 		>;
 	};
 
-	emmc_pins: pinmux_emmc_pins {
+	emmc_pins: emmc-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn1.mmc1_clk */
 			AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
@@ -189,6 +186,7 @@
 	pinctrl-0 = <&uart0_pins>;
 
 	status = "okay";
+	symlink = "bone/uart/0";
 };
 
 &usb0 {
@@ -207,6 +205,7 @@
 
 	status = "okay";
 	clock-frequency = <400000>;
+	symlink = "bone/i2c/0";
 
 	tps: tps@24 {
 		reg = <0x24>;
@@ -215,6 +214,7 @@
 	baseboard_eeprom: baseboard_eeprom@50 {
 		compatible = "atmel,24c256";
 		reg = <0x50>;
+		vcc-supply = <&ldo4_reg>;
 
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -230,6 +230,7 @@
 
 	status = "okay";
 	clock-frequency = <100000>;
+	symlink = "bone/i2c/2";
 
 	cape_eeprom0: cape_eeprom0@54 {
 		compatible = "atmel,24c256";
@@ -377,6 +378,10 @@
 
 	ethphy0: ethernet-phy@0 {
 		reg = <0>;
+		/* Support GPIO reset on revision C3 boards */
+		reset-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
+		reset-assert-us = <300>;
+		reset-deassert-us = <6500>;
 	};
 };
 
@@ -409,3 +414,12 @@
 &wkup_m3_ipc {
 	firmware-name = "am335x-bone-scale-data.bin";
 };
+
+&tscadc {
+	adc {
+		ti,adc-channels = <0 1 2 3 4 5 6 7>;
+		ti,chan-step-avg = <16 16 16 16 16 16 16 16>;
+		ti,chan-step-opendelay = <0x98 0x98 0x98 0x98 0x98 0x98 0x98 0x98>;
+		ti,chan-step-sampledelay = <0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0>;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-bone-common-univ.dtsi b/arch/arm/boot/dts/am335x-bone-common-univ.dtsi
--- a/arch/arm/boot/dts/am335x-bone-common-univ.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-bone-common-univ.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,2289 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+#include <dt-bindings/board/am335x-bone-pins.h>
+
+&am33xx_pinmux {
+
+/* macro: BONE_PIN( <pin>, <mode_name>, <register_value_macro(s)> */
+#define BONE_PIN(XX,ZZ,QQ) \
+	XX##_##ZZ##_pin: pinmux_##XX##_##ZZ##_pin { pinctrl-single,pins = < QQ >; };
+
+	/************************/
+	/* P8 Header */
+	/************************/
+
+	/* P8_01                GND */
+
+	/* P8_02                GND */
+
+
+	/* P8_03 (ZCZ ball R9) gpmc_ad6 (emmc) */
+	BONE_PIN(P8_03, default, P8_03(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_03, gpio, P8_03(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_03, gpio_pu, P8_03(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_03, gpio_pd, P8_03(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_04 (ZCZ ball T9) gpmc_ad7 (emmc) */
+	BONE_PIN(P8_04, default, P8_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_04, gpio, P8_04(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_04, gpio_pu, P8_04(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_04, gpio_pd, P8_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_05 (ZCZ ball R8) gpmc_ad2 (emmc) */
+	BONE_PIN(P8_05, default, P8_05(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_05, gpio, P8_05(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_05, gpio_pu, P8_05(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_05, gpio_pd, P8_05(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_06 (ZCZ ball T8) gpmc_ad3 (emmc) */
+	BONE_PIN(P8_06, default, P8_06(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_06, gpio, P8_06(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_06, gpio_pu, P8_06(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_06, gpio_pd, P8_06(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_07 (ZCZ ball R7) gpmc_advn_ale (gpio2_2) */
+	BONE_PIN(P8_07, default, P8_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_07, gpio, P8_07(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_07, gpio_pu, P8_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_07, gpio_pd, P8_07(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_07, timer, P8_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_08 (ZCZ ball T7) gpmc_oen_ren (gpio2_3) */
+	BONE_PIN(P8_08, default, P8_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_08, gpio, P8_08(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_08, gpio_pu, P8_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_08, gpio_pd, P8_08(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_08, timer, P8_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_09 (ZCZ ball T6) gpmc_be0n_cle (gpio2_5) */
+	BONE_PIN(P8_09, default, P8_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_09, gpio, P8_09(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_09, gpio_pu, P8_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_09, gpio_pd, P8_09(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_09, timer, P8_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_10 (ZCZ ball U6) gpmc_wen (gpio2_4) */
+	BONE_PIN(P8_10, default, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_10, gpio, P8_10(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_10, gpio_pu, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_10, gpio_pd, P8_10(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_10, timer, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_11 (ZCZ ball R12) gpmc_ad13 (gpio1_13) */
+	BONE_PIN(P8_11, default, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_11, gpio, P8_11(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_11, gpio_pu, P8_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_11, gpio_pd, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_11, eqep, P8_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P8_11, pruout, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P8_12 (ZCZ ball T12) gpmc_ad12 (gpio1_12) */
+	BONE_PIN(P8_12, default, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_12, gpio, P8_12(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_12, gpio_pu, P8_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_12, gpio_pd, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_12, eqep, P8_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P8_12, pruout, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P8_13 (ZCZ ball T10) gpmc_ad9 (gpio0_23) */
+	BONE_PIN(P8_13, default, P8_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_13, gpio, P8_13(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_13, gpio_pu, P8_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_13, gpio_pd, P8_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_13, pwm, P8_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4))
+
+	/* P8_14 (ZCZ ball T11) gpmc_ad10 (gpio0_26) */
+	BONE_PIN(P8_14, default, P8_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_14, gpio, P8_14(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_14, gpio_pu, P8_14(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_14, gpio_pd, P8_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_14, pwm, P8_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4))
+
+	/* P8_15 (ZCZ ball U13) gpmc_ad15 (gpio1_15) */
+	BONE_PIN(P8_15, default, P8_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_15, gpio, P8_15(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_15, gpio_pu, P8_15(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_15, gpio_pd, P8_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_15, eqep, P8_15(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P8_15, pru_ecap_pwm, P8_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_15, pruin, P8_15(PIN_INPUT | MUX_MODE6))
+
+	/* P8_16 (ZCZ ball V13) gpmc_ad14 (gpio1_14) */
+	BONE_PIN(P8_16, default, P8_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_16, gpio, P8_16(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_16, gpio_pu, P8_16(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_16, gpio_pd, P8_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_16, eqep, P8_16(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P8_16, pruin, P8_16(PIN_INPUT | MUX_MODE6))
+
+	/* P8_17 (ZCZ ball U12) gpmc_ad11 (gpio0_27) */
+	BONE_PIN(P8_17, default, P8_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_17, gpio, P8_17(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_17, gpio_pu, P8_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_17, gpio_pd, P8_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_17, pwm, P8_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4))
+
+	/* P8_18 (ZCZ ball V12) gpmc_clk (gpio2_1) */
+	BONE_PIN(P8_18, default, P8_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_18, gpio, P8_18(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_18, gpio_pu, P8_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_18, gpio_pd, P8_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_19 (ZCZ ball U10) gpmc_ad8 (gpio0_22) */
+	BONE_PIN(P8_19, default, P8_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_19, gpio, P8_19(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_19, gpio_pu, P8_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_19, gpio_pd, P8_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_19, pwm, P8_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4))
+
+	/* P8_20 (ZCZ ball V9) gpmc_csn2 (emmc) */
+	BONE_PIN(P8_20, default, P8_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_20, gpio, P8_20(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_20, gpio_pu, P8_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_20, gpio_pd, P8_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_20, pruout, P8_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_20, pruin, P8_20(PIN_INPUT | MUX_MODE6))
+
+	/* P8_21 (ZCZ ball U9) gpmc_csn1 (emmc) */
+	BONE_PIN(P8_21, default, P8_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_21, gpio, P8_21(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_21, gpio_pu, P8_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_21, gpio_pd, P8_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_21, pruout, P8_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_21, pruin, P8_21(PIN_INPUT | MUX_MODE6))
+
+	/* P8_22 (ZCZ ball V8) gpmc_ad5 (emmc) */
+	BONE_PIN(P8_22, default, P8_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_22, gpio, P8_22(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_22, gpio_pu, P8_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_22, gpio_pd, P8_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_23 (ZCZ ball U8) gpmc_ad4 (emmc) */
+	BONE_PIN(P8_23, default, P8_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_23, gpio, P8_23(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_23, gpio_pu, P8_23(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_23, gpio_pd, P8_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_24 (ZCZ ball V7) gpmc_ad1 (emmc) */
+	BONE_PIN(P8_24, default, P8_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_24, gpio, P8_24(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_24, gpio_pu, P8_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_24, gpio_pd, P8_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_25 (ZCZ ball U7) gpmc_ad0 (emmc) */
+	BONE_PIN(P8_25, default, P8_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_25, gpio, P8_25(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_25, gpio_pu, P8_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_25, gpio_pd, P8_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_26 (ZCZ ball V6) gpmc_csn0 (gpio1_29) */
+	BONE_PIN(P8_26, default, P8_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_26, gpio, P8_26(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_26, gpio_pu, P8_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_26, gpio_pd, P8_26(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_27 (ZCZ ball U5) lcd_vsync (hdmi) */
+	BONE_PIN(P8_27, default, P8_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_27, gpio, P8_27(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_27, gpio_pu, P8_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_27, gpio_pd, P8_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_27, pruout, P8_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_27, pruin, P8_27(PIN_INPUT | MUX_MODE6))
+
+	/* P8_28 (ZCZ ball V5) lcd_pclk (hdmi) */
+	BONE_PIN(P8_28, default, P8_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_28, gpio, P8_28(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_28, gpio_pu, P8_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_28, gpio_pd, P8_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_28, pruout, P8_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_28, pruin, P8_28(PIN_INPUT | MUX_MODE6))
+
+	/* P8_29 (ZCZ ball R5) lcd_hsync (hdmi) */
+	BONE_PIN(P8_29, default, P8_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_29, gpio, P8_29(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_29, gpio_pu, P8_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_29, gpio_pd, P8_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_29, pruout, P8_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_29, pruin, P8_29(PIN_INPUT | MUX_MODE6))
+
+	/* P8_30 (ZCZ ball R6) lcd_ac_bias_en (hdmi) */
+	BONE_PIN(P8_30, default, P8_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_30, gpio, P8_30(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_30, gpio_pu, P8_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_30, gpio_pd, P8_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_30, pruout, P8_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_30, pruin, P8_30(PIN_INPUT | MUX_MODE6))
+
+	/* P8_31 (ZCZ ball V4) lcd_data14 (hdmi) */
+	BONE_PIN(P8_31, default, P8_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_31, gpio, P8_31(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_31, gpio_pu, P8_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_31, gpio_pd, P8_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_31, eqep, P8_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P8_31, uart, P8_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P8_32 (ZCZ ball T5) lcd_data15 (hdmi) */
+	BONE_PIN(P8_32, default, P8_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_32, gpio, P8_32(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_32, gpio_pu, P8_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_32, gpio_pd, P8_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_32, eqep, P8_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_33 (ZCZ ball V3) lcd_data13 (hdmi) */
+	BONE_PIN(P8_33, default, P8_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_33, gpio, P8_33(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_33, gpio_pu, P8_33(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_33, gpio_pd, P8_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_33, eqep, P8_33(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_34 (ZCZ ball U4) lcd_data11 (hdmi) */
+	BONE_PIN(P8_34, default, P8_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_34, gpio, P8_34(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_34, gpio_pu, P8_34(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_34, gpio_pd, P8_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_34, pwm, P8_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2))
+
+	/* P8_35 (ZCZ ball V2) lcd_data12 (hdmi) */
+	BONE_PIN(P8_35, default, P8_35(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_35, gpio, P8_35(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_35, gpio_pu, P8_35(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_35, gpio_pd, P8_35(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_35, eqep, P8_35(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_36 (ZCZ ball U3) lcd_data10 (hdmi) */
+	BONE_PIN(P8_36, default, P8_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_36, gpio, P8_36(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_36, gpio_pu, P8_36(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_36, gpio_pd, P8_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_36, pwm, P8_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2))
+
+	/* P8_37 (ZCZ ball U1) lcd_data8 (hdmi) */
+	BONE_PIN(P8_37, default, P8_37(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_37, gpio, P8_37(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_37, gpio_pu, P8_37(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_37, gpio_pd, P8_37(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_37, pwm, P8_37(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P8_37, uart, P8_37(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P8_38 (ZCZ ball U2) lcd_data9 (hdmi) */
+	BONE_PIN(P8_38, default, P8_38(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_38, gpio, P8_38(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_38, gpio_pu, P8_38(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_38, gpio_pd, P8_38(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_38, pwm, P8_38(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P8_38, uart, P8_38(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P8_39 (ZCZ ball T3) lcd_data6 (hdmi) */
+	BONE_PIN(P8_39, default, P8_39(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_39, gpio, P8_39(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_39, gpio_pu, P8_39(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_39, gpio_pd, P8_39(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_39, eqep, P8_39(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_39, pruout, P8_39(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_39, pruin, P8_39(PIN_INPUT | MUX_MODE6))
+
+	/* P8_40 (ZCZ ball T4) lcd_data7 (hdmi) */
+	BONE_PIN(P8_40, default, P8_40(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_40, gpio, P8_40(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_40, gpio_pu, P8_40(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_40, gpio_pd, P8_40(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_40, eqep, P8_40(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_40, pruout, P8_40(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_40, pruin, P8_40(PIN_INPUT | MUX_MODE6))
+
+	/* P8_41 (ZCZ ball T1) lcd_data4 (hdmi) */
+	BONE_PIN(P8_41, default, P8_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_41, gpio, P8_41(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_41, gpio_pu, P8_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_41, gpio_pd, P8_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_41, eqep, P8_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_41, pruout, P8_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_41, pruin, P8_41(PIN_INPUT | MUX_MODE6))
+
+	/* P8_42 (ZCZ ball T2) lcd_data5 (hdmi) */
+	BONE_PIN(P8_42, default, P8_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_42, gpio, P8_42(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_42, gpio_pu, P8_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_42, gpio_pd, P8_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_42, eqep, P8_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_42, pruout, P8_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_42, pruin, P8_42(PIN_INPUT | MUX_MODE6))
+
+	/* P8_43 (ZCZ ball R3) lcd_data2 (hdmi) */
+	BONE_PIN(P8_43, default, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_43, gpio, P8_43(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_43, gpio_pu, P8_43(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_43, gpio_pd, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_43, pwm, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_43, pruout, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_43, pruin, P8_43(PIN_INPUT | MUX_MODE6))
+
+	/* P8_44 (ZCZ ball R4) lcd_data3 (hdmi) */
+	BONE_PIN(P8_44, default, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_44, gpio, P8_44(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_44, gpio_pu, P8_44(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_44, gpio_pd, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_44, pwm, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_44, pruout, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_44, pruin, P8_44(PIN_INPUT | MUX_MODE6))
+
+	/* P8_45 (ZCZ ball R1) lcd_data0 (hdmi) */
+	BONE_PIN(P8_45, default, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_45, gpio, P8_45(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_45, gpio_pu, P8_45(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_45, gpio_pd, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_45, pwm, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_45, pruout, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_45, pruin, P8_45(PIN_INPUT | MUX_MODE6))
+
+	/* P8_46 (ZCZ ball R2) lcd_data1 (hdmi) */
+	BONE_PIN(P8_46, default, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_46, gpio, P8_46(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_46, gpio_pu, P8_46(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_46, gpio_pd, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_46, pwm, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_46, pruout, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_46, pruin, P8_46(PIN_INPUT | MUX_MODE6))
+
+	/************************/
+	/* P9 Header */
+	/************************/
+
+	/* P9_01                GND */
+
+	/* P9_02                GND */
+
+	/* P9_03                3V3 */
+
+	/* P9_04                3V3 */
+
+	/* P9_05                VDD_5V */
+
+	/* P9_06                VDD_5V */
+
+	/* P9_07                SYS_5V */
+
+	/* P9_08                SYS_5V */
+
+	/* P9_09                PWR_BUT */
+
+	/* P9_10                RSTn */
+
+	/* P9_11 (ZCZ ball T17) gpmc_wait0 (gpio0_30) */
+	BONE_PIN(P9_11, default, P9_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_11, gpio, P9_11(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_11, gpio_pu, P9_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_11, gpio_pd, P9_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_11, uart, P9_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6))
+
+	/* P9_12 (ZCZ ball U18) gpmc_be1n (gpio1_28) */
+	BONE_PIN(P9_12, default, P9_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_12, gpio, P9_12(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_12, gpio_pu, P9_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_12, gpio_pd, P9_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P9_13 (ZCZ ball U17) gpmc_wpn (gpio0_31) */
+	BONE_PIN(P9_13, default, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_13, gpio, P9_13(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_13, gpio_pu, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_13, gpio_pd, P9_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_13, uart, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6))
+
+	/* P9_14 (ZCZ ball U14) gpmc_a2 (gpio1_18) */
+	BONE_PIN(P9_14, default, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_14, gpio, P9_14(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_14, gpio_pu, P9_14(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_14, gpio_pd, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_14, pwm, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P9_15 (ZCZ ball R13) gpmc_a0 (gpio1_16) */
+	BONE_PIN(P9_15, default, P9_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_15, gpio, P9_15(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_15, gpio_pu, P9_15(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_15, gpio_pd, P9_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_15, pwm, P9_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P9_16 (ZCZ ball T14) gpmc_a3 (gpio1_19) */
+	BONE_PIN(P9_16, default, P9_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_16, gpio, P9_16(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_16, gpio_pu, P9_16(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_16, gpio_pd, P9_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_16, pwm, P9_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P9_17 (ZCZ ball A16) spi0_cs0 (gpio0_5) */
+	BONE_PIN(P9_17, default, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_17, gpio, P9_17(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_17, gpio_pu, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_17, gpio_pd, P9_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_17, spi_cs, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P9_17, i2c, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P9_17, pwm, P9_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_17, pru_uart, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P9_18 (ZCZ ball B16) spi0_d1 (gpio0_4) */
+	BONE_PIN(P9_18, default, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_18, gpio, P9_18(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_18, gpio_pu, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_18, gpio_pd, P9_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_18, spi, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P9_18, i2c, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P9_18, pwm, P9_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_18, pru_uart, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P9_19 (ZCZ ball D17) uart1_rtsn (i2c2_scl) */
+	BONE_PIN(P9_19, default, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_19, gpio, P9_19(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_19, gpio_pu, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_19, gpio_pd, P9_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_19, timer, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_19, can, P9_19(PIN_INPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P9_19, i2c, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_19, spi_cs, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P9_19, pru_uart, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+
+	/* P9_20 (ZCZ ball D18) uart1_ctsn (i2c2_sda) */
+	BONE_PIN(P9_20, default, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_20, gpio, P9_20(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_20, gpio_pu, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_20, gpio_pd, P9_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_20, timer, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_20, can, P9_20(PIN_OUTPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P9_20, i2c, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_20, spi_cs, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P9_20, pru_uart, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+
+	/* P9_21 (ZCZ ball B17) spi0_d0 (gpio0_3) */
+	BONE_PIN(P9_21, default, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_21, gpio, P9_21(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_21, gpio_pu, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_21, gpio_pd, P9_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_21, spi, P9_21(PIN_INPUT_PULLUP | MUX_MODE0))
+	BONE_PIN(P9_21, uart, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_21, i2c, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P9_21, pwm, P9_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_21, pru_uart, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P9_22 (ZCZ ball A17) spi0_sclk (gpio0_2) */
+	BONE_PIN(P9_22, default, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_22, gpio, P9_22(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_22, gpio_pu, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_22, gpio_pd, P9_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_22, spi_sclk, P9_22(PIN_INPUT_PULLUP | MUX_MODE0))
+	BONE_PIN(P9_22, uart, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_22, i2c, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P9_22, pwm, P9_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_22, pru_uart, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P9_23 (ZCZ ball V14) gpmc_a1 (gpio1_17) */
+	BONE_PIN(P9_23, default, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_23, gpio, P9_23(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_23, gpio_pu, P9_23(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_23, gpio_pd, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_23, pwm, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P9_24 (ZCZ ball D15) uart1_txd (gpio0_15) */
+	BONE_PIN(P9_24, default, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_24, gpio, P9_24(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_24, gpio_pu, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_24, gpio_pd, P9_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_24, uart, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P9_24, can, P9_24(PIN_INPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P9_24, i2c, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_24, pru_uart, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_24, pruin, P9_24(PIN_INPUT | MUX_MODE6))
+
+	/* P9_25 (ZCZ ball A14) mcasp0_ahclkx (audio) */
+	BONE_PIN(P9_25, default, P9_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_25, gpio, P9_25(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_25, gpio_pu, P9_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_25, gpio_pd, P9_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_25, eqep, P9_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_25, pruout, P9_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_25, pruin, P9_25(PIN_INPUT | MUX_MODE6))
+
+	/* P9_26 (ZCZ ball D16) uart1_rxd (gpio0_14) */
+	BONE_PIN(P9_26, default, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_26, gpio, P9_26(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_26, gpio_pu, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_26, gpio_pd, P9_26(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_26, uart, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P9_26, can, P9_26(PIN_OUTPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P9_26, i2c, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_26, pru_uart, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_26, pruin, P9_26(PIN_INPUT | MUX_MODE6))
+
+	/* P9_27 (ZCZ ball C13) mcasp0_fsr (gpio3_19) */
+	BONE_PIN(P9_27, default, P9_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_27, gpio, P9_27(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_27, gpio_pu, P9_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_27, gpio_pd, P9_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_27, eqep, P9_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_27, pruout, P9_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_27, pruin, P9_27(PIN_INPUT | MUX_MODE6))
+
+	/* P9_28 (ZCZ ball C12) mcasp0_ahclkr (audio) */
+	BONE_PIN(P9_28, default, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_28, gpio, P9_28(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_28, gpio_pu, P9_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_28, gpio_pd, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_28, pwm, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_28, spi_cs, P9_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_28, pwm2, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P9_28, pruout, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_28, pruin, P9_28(PIN_INPUT | MUX_MODE6))
+
+	/* P9_29 (ZCZ ball B13) mcasp0_fsx (audio) */
+	BONE_PIN(P9_29, default, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_29, gpio, P9_29(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_29, gpio_pu, P9_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_29, gpio_pd, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_29, pwm, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_29, spi, P9_29(PIN_INPUT_PULLUP | MUX_MODE3))
+	BONE_PIN(P9_29, pruout, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_29, pruin, P9_29(PIN_INPUT | MUX_MODE6))
+
+	/* P9_30 (ZCZ ball D12) mcasp0_axr0 (gpio3_16) */
+	BONE_PIN(P9_30, default, P9_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_30, gpio, P9_30(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_30, gpio_pu, P9_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_30, gpio_pd, P9_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_30, pwm, P9_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_30, spi, P9_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_30, pruout, P9_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_30, pruin, P9_30(PIN_INPUT | MUX_MODE6))
+
+	/* P9_31 (ZCZ ball A13) mcasp0_aclkx (audio) */
+	BONE_PIN(P9_31, default, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_31, gpio, P9_31(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_31, gpio_pu, P9_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_31, gpio_pd, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_31, pwm, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_31, spi_sclk, P9_31(PIN_INPUT_PULLUP | MUX_MODE3))
+	BONE_PIN(P9_31, pruout, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_31, pruin, P9_31(PIN_INPUT | MUX_MODE6))
+
+	/* P9_32                VADC */
+
+	/* P9_33 (ZCZ ball C8)  AIN4 */
+
+	/* P9_34                AGND */
+
+	/* P9_35 (ZCZ ball A8)  AIN6 */
+
+	/* P9_36 (ZCZ ball B8)  AIN5 */
+
+	/* P9_37 (ZCZ ball B7)  AIN2 */
+
+	/* P9_38 (ZCZ ball A7)  AIN3 */
+
+	/* P9_39 (ZCZ ball B6)  AIN0 */
+
+	/* P9_40 (ZCZ ball C7)  AIN1 */
+
+	/* P9_41 (ZCZ ball D14) xdma_event_intr1 (gpio0_20) */
+	BONE_PIN(P9_41, default, P9_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_41, gpio, P9_41(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_41, gpio_pu, P9_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_41, gpio_pd, P9_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_41, timer, P9_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P9_41, pruin, P9_41(PIN_INPUT | MUX_MODE5))
+
+	/* P9_41.1 */
+	/* P9_91 (ZCZ ball D13) mcasp0_axr1 (gpio3_20) */
+	BONE_PIN(P9_91, default, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_91, gpio, P9_91(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_91, gpio_pu, P9_91(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_91, gpio_pd, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_91, eqep, P9_91(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_91, pruout, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_91, pruin, P9_91(PIN_INPUT | MUX_MODE6))
+
+	/* P9_42 (ZCZ ball C18) eCAP0_in_PWM0_out (gpio0_7) */
+	BONE_PIN(P9_42, default, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_42, gpio, P9_42(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_42, gpio_pu, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_42, gpio_pd, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_42, pwm, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P9_42, uart, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_42, spi_cs, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P9_42, pru_ecap_pwm, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_42, spi_sclk, P9_42(PIN_INPUT_PULLUP | MUX_MODE4))
+
+	/* P9_42.1 */
+	/* P9_92 (ZCZ ball B12) mcasp0_aclkr (gpio3_18) */
+	BONE_PIN(P9_92, default, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_92, gpio, P9_92(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_92, gpio_pu, P9_92(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_92, gpio_pd, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_92, eqep, P9_92(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_92, pruout, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_92, pruin, P9_92(PIN_INPUT | MUX_MODE6))
+
+	/* P9_43                GND */
+
+	/* P9_44                GND */
+
+	/* P9_45                GND */
+
+	/* P9_46                GND */
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+
+	clock-frequency = <100000>;
+	symlink = "bone/i2c/1";
+};
+
+&i2c2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+
+	clock-frequency = <100000>;
+	symlink = "bone/i2c/2";
+};
+
+&uart1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/uart/1";
+};
+
+&uart2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/uart/2";
+};
+
+&uart3 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/uart/3";
+};
+
+&uart4 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/uart/4";
+};
+
+&uart5 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/uart/5";
+};
+
+&dcan0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/can/0";
+};
+
+&dcan1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/can/1";
+};
+
+&eqep0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/eqep/0";
+};
+
+&eqep1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/eqep/1";
+};
+
+&eqep2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/eqep/2";
+};
+
+&epwmss0 {
+	status = "okay";
+};
+
+&epwmss1 {
+	status = "okay";
+};
+
+&epwmss2 {
+	status = "okay";
+};
+
+&ehrpwm0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&ehrpwm1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&ehrpwm2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&ecap0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&ecap1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&ecap2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&spi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+
+	channel@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/0.0";
+
+		reg = <0>;
+		spi-max-frequency = <16000000>;
+		spi-cpha;
+	};
+
+	channel@1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/0.1";
+
+		reg = <1>;
+		spi-max-frequency = <16000000>;
+	};
+};
+
+&spi1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+
+	channel@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/1.0";
+
+		reg = <0>;
+		spi-max-frequency = <16000000>;
+		spi-cpha;
+	};
+
+	channel@1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/1.1";
+
+		reg = <1>;
+		spi-max-frequency = <16000000>;
+	};
+};
+
+/**********************************************************************/
+/* Pin Multiplex Helpers                                              */
+/*                                                                    */
+/* These provide userspace runtime pin configuration for the          */
+/* BeagleBone cape expansion headers                                  */
+/**********************************************************************/
+
+&ocp {
+	/************************/
+	/* P8 Header */
+	/************************/
+
+	/* P8_01                GND */
+
+	/* P8_02                GND */
+
+
+	/* P8_03 (ZCZ ball R9) emmc */
+	P8_03_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_03_default_pin>;
+		pinctrl-1 = <&P8_03_gpio_pin>;
+		pinctrl-2 = <&P8_03_gpio_pu_pin>;
+		pinctrl-3 = <&P8_03_gpio_pd_pin>;
+	};
+
+	/* P8_04 (ZCZ ball T9) emmc */
+	P8_04_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_04_default_pin>;
+		pinctrl-1 = <&P8_04_gpio_pin>;
+		pinctrl-2 = <&P8_04_gpio_pu_pin>;
+		pinctrl-3 = <&P8_04_gpio_pd_pin>;
+	};
+
+	/* P8_05 (ZCZ ball R8) emmc */
+	P8_05_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_05_default_pin>;
+		pinctrl-1 = <&P8_05_gpio_pin>;
+		pinctrl-2 = <&P8_05_gpio_pu_pin>;
+		pinctrl-3 = <&P8_05_gpio_pd_pin>;
+	};
+
+	/* P8_06 (ZCZ ball T8) emmc */
+	P8_06_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_06_default_pin>;
+		pinctrl-1 = <&P8_06_gpio_pin>;
+		pinctrl-2 = <&P8_06_gpio_pu_pin>;
+		pinctrl-3 = <&P8_06_gpio_pd_pin>;
+	};
+
+	/* P8_07 (ZCZ ball R7) */
+	P8_07_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer";
+		pinctrl-0 = <&P8_07_default_pin>;
+		pinctrl-1 = <&P8_07_gpio_pin>;
+		pinctrl-2 = <&P8_07_gpio_pu_pin>;
+		pinctrl-3 = <&P8_07_gpio_pd_pin>;
+		pinctrl-4 = <&P8_07_timer_pin>;
+	};
+
+	/* P8_08 (ZCZ ball T7) */
+	P8_08_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer";
+		pinctrl-0 = <&P8_08_default_pin>;
+		pinctrl-1 = <&P8_08_gpio_pin>;
+		pinctrl-2 = <&P8_08_gpio_pu_pin>;
+		pinctrl-3 = <&P8_08_gpio_pd_pin>;
+		pinctrl-4 = <&P8_08_timer_pin>;
+	};
+
+	/* P8_09 (ZCZ ball T6) */
+	P8_09_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer";
+		pinctrl-0 = <&P8_09_default_pin>;
+		pinctrl-1 = <&P8_09_gpio_pin>;
+		pinctrl-2 = <&P8_09_gpio_pu_pin>;
+		pinctrl-3 = <&P8_09_gpio_pd_pin>;
+		pinctrl-4 = <&P8_09_timer_pin>;
+	};
+
+	/* P8_10 (ZCZ ball U6) */
+	P8_10_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer";
+		pinctrl-0 = <&P8_10_default_pin>;
+		pinctrl-1 = <&P8_10_gpio_pin>;
+		pinctrl-2 = <&P8_10_gpio_pu_pin>;
+		pinctrl-3 = <&P8_10_gpio_pd_pin>;
+		pinctrl-4 = <&P8_10_timer_pin>;
+	};
+
+	/* P8_11 (ZCZ ball R12) */
+	P8_11_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout";
+		pinctrl-0 = <&P8_11_default_pin>;
+		pinctrl-1 = <&P8_11_gpio_pin>;
+		pinctrl-2 = <&P8_11_gpio_pu_pin>;
+		pinctrl-3 = <&P8_11_gpio_pd_pin>;
+		pinctrl-4 = <&P8_11_eqep_pin>;
+		pinctrl-5 = <&P8_11_pruout_pin>;
+	};
+
+	/* P8_12 (ZCZ ball T12) */
+	P8_12_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout";
+		pinctrl-0 = <&P8_12_default_pin>;
+		pinctrl-1 = <&P8_12_gpio_pin>;
+		pinctrl-2 = <&P8_12_gpio_pu_pin>;
+		pinctrl-3 = <&P8_12_gpio_pd_pin>;
+		pinctrl-4 = <&P8_12_eqep_pin>;
+		pinctrl-5 = <&P8_12_pruout_pin>;
+	};
+
+	/* P8_13 (ZCZ ball T10) */
+	P8_13_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P8_13_default_pin>;
+		pinctrl-1 = <&P8_13_gpio_pin>;
+		pinctrl-2 = <&P8_13_gpio_pu_pin>;
+		pinctrl-3 = <&P8_13_gpio_pd_pin>;
+		pinctrl-4 = <&P8_13_pwm_pin>;
+	};
+
+	/* P8_14 (ZCZ ball T11) */
+	P8_14_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P8_14_default_pin>;
+		pinctrl-1 = <&P8_14_gpio_pin>;
+		pinctrl-2 = <&P8_14_gpio_pu_pin>;
+		pinctrl-3 = <&P8_14_gpio_pd_pin>;
+		pinctrl-4 = <&P8_14_pwm_pin>;
+	};
+
+	/* P8_15 (ZCZ ball U13) */
+	P8_15_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pru_ecap_pwm", "pruin";
+		pinctrl-0 = <&P8_15_default_pin>;
+		pinctrl-1 = <&P8_15_gpio_pin>;
+		pinctrl-2 = <&P8_15_gpio_pu_pin>;
+		pinctrl-3 = <&P8_15_gpio_pd_pin>;
+		pinctrl-4 = <&P8_15_eqep_pin>;
+		pinctrl-5 = <&P8_15_pru_ecap_pwm_pin>;
+		pinctrl-6 = <&P8_15_pruin_pin>;
+	};
+
+	/* P8_16 (ZCZ ball V13) */
+	P8_16_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruin";
+		pinctrl-0 = <&P8_16_default_pin>;
+		pinctrl-1 = <&P8_16_gpio_pin>;
+		pinctrl-2 = <&P8_16_gpio_pu_pin>;
+		pinctrl-3 = <&P8_16_gpio_pd_pin>;
+		pinctrl-4 = <&P8_16_eqep_pin>;
+		pinctrl-5 = <&P8_16_pruin_pin>;
+	};
+
+	/* P8_17 (ZCZ ball U12) */
+	P8_17_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P8_17_default_pin>;
+		pinctrl-1 = <&P8_17_gpio_pin>;
+		pinctrl-2 = <&P8_17_gpio_pu_pin>;
+		pinctrl-3 = <&P8_17_gpio_pd_pin>;
+		pinctrl-4 = <&P8_17_pwm_pin>;
+	};
+
+	/* P8_18 (ZCZ ball V12) */
+	P8_18_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_18_default_pin>;
+		pinctrl-1 = <&P8_18_gpio_pin>;
+		pinctrl-2 = <&P8_18_gpio_pu_pin>;
+		pinctrl-3 = <&P8_18_gpio_pd_pin>;
+	};
+
+	/* P8_19 (ZCZ ball U10) */
+	P8_19_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P8_19_default_pin>;
+		pinctrl-1 = <&P8_19_gpio_pin>;
+		pinctrl-2 = <&P8_19_gpio_pu_pin>;
+		pinctrl-3 = <&P8_19_gpio_pd_pin>;
+		pinctrl-4 = <&P8_19_pwm_pin>;
+	};
+
+	/* P8_20 (ZCZ ball V9) emmc */
+	P8_20_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P8_20_default_pin>;
+		pinctrl-1 = <&P8_20_gpio_pin>;
+		pinctrl-2 = <&P8_20_gpio_pu_pin>;
+		pinctrl-3 = <&P8_20_gpio_pd_pin>;
+		pinctrl-4 = <&P8_20_pruout_pin>;
+		pinctrl-5 = <&P8_20_pruin_pin>;
+	};
+
+	/* P8_21 (ZCZ ball U9) emmc */
+	P8_21_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P8_21_default_pin>;
+		pinctrl-1 = <&P8_21_gpio_pin>;
+		pinctrl-2 = <&P8_21_gpio_pu_pin>;
+		pinctrl-3 = <&P8_21_gpio_pd_pin>;
+		pinctrl-4 = <&P8_21_pruout_pin>;
+		pinctrl-5 = <&P8_21_pruin_pin>;
+	};
+
+	/* P8_22 (ZCZ ball V8) emmc */
+	P8_22_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_22_default_pin>;
+		pinctrl-1 = <&P8_22_gpio_pin>;
+		pinctrl-2 = <&P8_22_gpio_pu_pin>;
+		pinctrl-3 = <&P8_22_gpio_pd_pin>;
+	};
+
+	/* P8_23 (ZCZ ball U8) emmc */
+	P8_23_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_23_default_pin>;
+		pinctrl-1 = <&P8_23_gpio_pin>;
+		pinctrl-2 = <&P8_23_gpio_pu_pin>;
+		pinctrl-3 = <&P8_23_gpio_pd_pin>;
+	};
+
+	/* P8_24 (ZCZ ball V7) emmc */
+	P8_24_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_24_default_pin>;
+		pinctrl-1 = <&P8_24_gpio_pin>;
+		pinctrl-2 = <&P8_24_gpio_pu_pin>;
+		pinctrl-3 = <&P8_24_gpio_pd_pin>;
+	};
+
+	/* P8_25 (ZCZ ball U7) emmc */
+	P8_25_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_25_default_pin>;
+		pinctrl-1 = <&P8_25_gpio_pin>;
+		pinctrl-2 = <&P8_25_gpio_pu_pin>;
+		pinctrl-3 = <&P8_25_gpio_pd_pin>;
+	};
+
+	/* P8_26 (ZCZ ball V6) */
+	P8_26_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_26_default_pin>;
+		pinctrl-1 = <&P8_26_gpio_pin>;
+		pinctrl-2 = <&P8_26_gpio_pu_pin>;
+		pinctrl-3 = <&P8_26_gpio_pd_pin>;
+	};
+
+	/* P8_27 (ZCZ ball U5) hdmi */
+	P8_27_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P8_27_default_pin>;
+		pinctrl-1 = <&P8_27_gpio_pin>;
+		pinctrl-2 = <&P8_27_gpio_pu_pin>;
+		pinctrl-3 = <&P8_27_gpio_pd_pin>;
+		pinctrl-4 = <&P8_27_pruout_pin>;
+		pinctrl-5 = <&P8_27_pruin_pin>;
+	};
+
+	/* P8_28 (ZCZ ball V5) hdmi */
+	P8_28_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P8_28_default_pin>;
+		pinctrl-1 = <&P8_28_gpio_pin>;
+		pinctrl-2 = <&P8_28_gpio_pu_pin>;
+		pinctrl-3 = <&P8_28_gpio_pd_pin>;
+		pinctrl-4 = <&P8_28_pruout_pin>;
+		pinctrl-5 = <&P8_28_pruin_pin>;
+	};
+
+	/* P8_29 (ZCZ ball R5) hdmi */
+	P8_29_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P8_29_default_pin>;
+		pinctrl-1 = <&P8_29_gpio_pin>;
+		pinctrl-2 = <&P8_29_gpio_pu_pin>;
+		pinctrl-3 = <&P8_29_gpio_pd_pin>;
+		pinctrl-4 = <&P8_29_pruout_pin>;
+		pinctrl-5 = <&P8_29_pruin_pin>;
+	};
+
+	/* P8_30 (ZCZ ball R6) hdmi */
+	P8_30_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P8_30_default_pin>;
+		pinctrl-1 = <&P8_30_gpio_pin>;
+		pinctrl-2 = <&P8_30_gpio_pu_pin>;
+		pinctrl-3 = <&P8_30_gpio_pd_pin>;
+		pinctrl-4 = <&P8_30_pruout_pin>;
+		pinctrl-5 = <&P8_30_pruin_pin>;
+	};
+
+	/* P8_31 (ZCZ ball V4) hdmi */
+	P8_31_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "eqep";
+		pinctrl-0 = <&P8_31_default_pin>;
+		pinctrl-1 = <&P8_31_gpio_pin>;
+		pinctrl-2 = <&P8_31_gpio_pu_pin>;
+		pinctrl-3 = <&P8_31_gpio_pd_pin>;
+		pinctrl-4 = <&P8_31_uart_pin>;
+		pinctrl-5 = <&P8_31_eqep_pin>;
+	};
+
+	/* P8_32 (ZCZ ball T5) hdmi */
+	P8_32_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep";
+		pinctrl-0 = <&P8_32_default_pin>;
+		pinctrl-1 = <&P8_32_gpio_pin>;
+		pinctrl-2 = <&P8_32_gpio_pu_pin>;
+		pinctrl-3 = <&P8_32_gpio_pd_pin>;
+		pinctrl-4 = <&P8_32_eqep_pin>;
+	};
+
+	/* P8_33 (ZCZ ball V3) hdmi */
+	P8_33_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep";
+		pinctrl-0 = <&P8_33_default_pin>;
+		pinctrl-1 = <&P8_33_gpio_pin>;
+		pinctrl-2 = <&P8_33_gpio_pu_pin>;
+		pinctrl-3 = <&P8_33_gpio_pd_pin>;
+		pinctrl-4 = <&P8_33_eqep_pin>;
+	};
+
+	/* P8_34 (ZCZ ball U4) hdmi */
+	P8_34_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P8_34_default_pin>;
+		pinctrl-1 = <&P8_34_gpio_pin>;
+		pinctrl-2 = <&P8_34_gpio_pu_pin>;
+		pinctrl-3 = <&P8_34_gpio_pd_pin>;
+		pinctrl-4 = <&P8_34_pwm_pin>;
+	};
+
+	/* P8_35 (ZCZ ball V2) hdmi */
+	P8_35_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep";
+		pinctrl-0 = <&P8_35_default_pin>;
+		pinctrl-1 = <&P8_35_gpio_pin>;
+		pinctrl-2 = <&P8_35_gpio_pu_pin>;
+		pinctrl-3 = <&P8_35_gpio_pd_pin>;
+		pinctrl-4 = <&P8_35_eqep_pin>;
+	};
+
+	/* P8_36 (ZCZ ball U3) hdmi */
+	P8_36_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P8_36_default_pin>;
+		pinctrl-1 = <&P8_36_gpio_pin>;
+		pinctrl-2 = <&P8_36_gpio_pu_pin>;
+		pinctrl-3 = <&P8_36_gpio_pd_pin>;
+		pinctrl-4 = <&P8_36_pwm_pin>;
+	};
+
+	/* P8_37 (ZCZ ball U1) hdmi */
+	P8_37_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "pwm";
+		pinctrl-0 = <&P8_37_default_pin>;
+		pinctrl-1 = <&P8_37_gpio_pin>;
+		pinctrl-2 = <&P8_37_gpio_pu_pin>;
+		pinctrl-3 = <&P8_37_gpio_pd_pin>;
+		pinctrl-4 = <&P8_37_uart_pin>;
+		pinctrl-5 = <&P8_37_pwm_pin>;
+	};
+
+	/* P8_38 (ZCZ ball U2) hdmi */
+	P8_38_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "pwm";
+		pinctrl-0 = <&P8_38_default_pin>;
+		pinctrl-1 = <&P8_38_gpio_pin>;
+		pinctrl-2 = <&P8_38_gpio_pu_pin>;
+		pinctrl-3 = <&P8_38_gpio_pd_pin>;
+		pinctrl-4 = <&P8_38_uart_pin>;
+		pinctrl-5 = <&P8_38_pwm_pin>;
+	};
+
+	/* P8_39 (ZCZ ball T3) hdmi */
+	P8_39_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P8_39_default_pin>;
+		pinctrl-1 = <&P8_39_gpio_pin>;
+		pinctrl-2 = <&P8_39_gpio_pu_pin>;
+		pinctrl-3 = <&P8_39_gpio_pd_pin>;
+		pinctrl-4 = <&P8_39_eqep_pin>;
+		pinctrl-5 = <&P8_39_pruout_pin>;
+		pinctrl-6 = <&P8_39_pruin_pin>;
+	};
+
+	/* P8_40 (ZCZ ball T4) hdmi */
+	P8_40_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P8_40_default_pin>;
+		pinctrl-1 = <&P8_40_gpio_pin>;
+		pinctrl-2 = <&P8_40_gpio_pu_pin>;
+		pinctrl-3 = <&P8_40_gpio_pd_pin>;
+		pinctrl-4 = <&P8_40_eqep_pin>;
+		pinctrl-5 = <&P8_40_pruout_pin>;
+		pinctrl-6 = <&P8_40_pruin_pin>;
+	};
+
+	/* P8_41 (ZCZ ball T1) hdmi */
+	P8_41_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P8_41_default_pin>;
+		pinctrl-1 = <&P8_41_gpio_pin>;
+		pinctrl-2 = <&P8_41_gpio_pu_pin>;
+		pinctrl-3 = <&P8_41_gpio_pd_pin>;
+		pinctrl-4 = <&P8_41_eqep_pin>;
+		pinctrl-5 = <&P8_41_pruout_pin>;
+		pinctrl-6 = <&P8_41_pruin_pin>;
+	};
+
+	/* P8_42 (ZCZ ball T2) hdmi */
+	P8_42_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P8_42_default_pin>;
+		pinctrl-1 = <&P8_42_gpio_pin>;
+		pinctrl-2 = <&P8_42_gpio_pu_pin>;
+		pinctrl-3 = <&P8_42_gpio_pd_pin>;
+		pinctrl-4 = <&P8_42_eqep_pin>;
+		pinctrl-5 = <&P8_42_pruout_pin>;
+		pinctrl-6 = <&P8_42_pruin_pin>;
+	};
+
+	/* P8_43 (ZCZ ball R3) hdmi */
+	P8_43_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P8_43_default_pin>;
+		pinctrl-1 = <&P8_43_gpio_pin>;
+		pinctrl-2 = <&P8_43_gpio_pu_pin>;
+		pinctrl-3 = <&P8_43_gpio_pd_pin>;
+		pinctrl-4 = <&P8_43_pwm_pin>;
+		pinctrl-5 = <&P8_43_pruout_pin>;
+		pinctrl-6 = <&P8_43_pruin_pin>;
+	};
+
+	/* P8_44 (ZCZ ball R4) hdmi */
+	P8_44_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P8_44_default_pin>;
+		pinctrl-1 = <&P8_44_gpio_pin>;
+		pinctrl-2 = <&P8_44_gpio_pu_pin>;
+		pinctrl-3 = <&P8_44_gpio_pd_pin>;
+		pinctrl-4 = <&P8_44_pwm_pin>;
+		pinctrl-5 = <&P8_44_pruout_pin>;
+		pinctrl-6 = <&P8_44_pruin_pin>;
+	};
+
+	/* P8_45 (ZCZ ball R1) hdmi */
+	P8_45_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P8_45_default_pin>;
+		pinctrl-1 = <&P8_45_gpio_pin>;
+		pinctrl-2 = <&P8_45_gpio_pu_pin>;
+		pinctrl-3 = <&P8_45_gpio_pd_pin>;
+		pinctrl-4 = <&P8_45_pwm_pin>;
+		pinctrl-5 = <&P8_45_pruout_pin>;
+		pinctrl-6 = <&P8_45_pruin_pin>;
+	};
+
+	/* P8_46 (ZCZ ball R2) hdmi */
+	P8_46_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P8_46_default_pin>;
+		pinctrl-1 = <&P8_46_gpio_pin>;
+		pinctrl-2 = <&P8_46_gpio_pu_pin>;
+		pinctrl-3 = <&P8_46_gpio_pd_pin>;
+		pinctrl-4 = <&P8_46_pwm_pin>;
+		pinctrl-5 = <&P8_46_pruout_pin>;
+		pinctrl-6 = <&P8_46_pruin_pin>;
+	};
+
+	/************************/
+	/* P9 Header */
+	/************************/
+
+	/* P9_01                GND */
+
+	/* P9_02                GND */
+
+	/* P9_03                3V3 */
+
+	/* P9_04                3V3 */
+
+	/* P9_05                VDD_5V */
+
+	/* P9_06                VDD_5V */
+
+	/* P9_07                SYS_5V */
+
+	/* P9_08                SYS_5V */
+
+	/* P9_09                PWR_BUT */
+
+	/* P9_10                RSTn */
+
+	/* P9_11 (ZCZ ball T17) */
+	P9_11_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart";
+		pinctrl-0 = <&P9_11_default_pin>;
+		pinctrl-1 = <&P9_11_gpio_pin>;
+		pinctrl-2 = <&P9_11_gpio_pu_pin>;
+		pinctrl-3 = <&P9_11_gpio_pd_pin>;
+		pinctrl-4 = <&P9_11_uart_pin>;
+	};
+
+	/* P9_12 (ZCZ ball U18) */
+	P9_12_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P9_12_default_pin>;
+		pinctrl-1 = <&P9_12_gpio_pin>;
+		pinctrl-2 = <&P9_12_gpio_pu_pin>;
+		pinctrl-3 = <&P9_12_gpio_pd_pin>;
+	};
+
+	/* P9_13 (ZCZ ball U17) */
+	P9_13_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart";
+		pinctrl-0 = <&P9_13_default_pin>;
+		pinctrl-1 = <&P9_13_gpio_pin>;
+		pinctrl-2 = <&P9_13_gpio_pu_pin>;
+		pinctrl-3 = <&P9_13_gpio_pd_pin>;
+		pinctrl-4 = <&P9_13_uart_pin>;
+	};
+
+	/* P9_14 (ZCZ ball U14) */
+	P9_14_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P9_14_default_pin>;
+		pinctrl-1 = <&P9_14_gpio_pin>;
+		pinctrl-2 = <&P9_14_gpio_pu_pin>;
+		pinctrl-3 = <&P9_14_gpio_pd_pin>;
+		pinctrl-4 = <&P9_14_pwm_pin>;
+	};
+
+	/* P9_15 (ZCZ ball R13) */
+	P9_15_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P9_15_default_pin>;
+		pinctrl-1 = <&P9_15_gpio_pin>;
+		pinctrl-2 = <&P9_15_gpio_pu_pin>;
+		pinctrl-3 = <&P9_15_gpio_pd_pin>;
+		pinctrl-4 = <&P9_15_pwm_pin>;
+	};
+
+	/* P9_16 (ZCZ ball T14) */
+	P9_16_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P9_16_default_pin>;
+		pinctrl-1 = <&P9_16_gpio_pin>;
+		pinctrl-2 = <&P9_16_gpio_pu_pin>;
+		pinctrl-3 = <&P9_16_gpio_pd_pin>;
+		pinctrl-4 = <&P9_16_pwm_pin>;
+	};
+
+	/* P9_17 (ZCZ ball A16) */
+	P9_17_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "i2c", "pwm", "pru_uart";
+		pinctrl-0 = <&P9_17_default_pin>;
+		pinctrl-1 = <&P9_17_gpio_pin>;
+		pinctrl-2 = <&P9_17_gpio_pu_pin>;
+		pinctrl-3 = <&P9_17_gpio_pd_pin>;
+		pinctrl-4 = <&P9_17_spi_cs_pin>;
+		pinctrl-5 = <&P9_17_i2c_pin>;
+		pinctrl-6 = <&P9_17_pwm_pin>;
+		pinctrl-7 = <&P9_17_pru_uart_pin>;
+	};
+
+	/* P9_18 (ZCZ ball B16) */
+	P9_18_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm", "pru_uart";
+		pinctrl-0 = <&P9_18_default_pin>;
+		pinctrl-1 = <&P9_18_gpio_pin>;
+		pinctrl-2 = <&P9_18_gpio_pu_pin>;
+		pinctrl-3 = <&P9_18_gpio_pd_pin>;
+		pinctrl-4 = <&P9_18_spi_pin>;
+		pinctrl-5 = <&P9_18_i2c_pin>;
+		pinctrl-6 = <&P9_18_pwm_pin>;
+		pinctrl-7 = <&P9_18_pru_uart_pin>;
+	};
+
+	/* P9_19 (ZCZ ball D17) i2c */
+	P9_19_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "can", "i2c", "pru_uart", "timer";
+		pinctrl-0 = <&P9_19_default_pin>;
+		pinctrl-1 = <&P9_19_gpio_pin>;
+		pinctrl-2 = <&P9_19_gpio_pu_pin>;
+		pinctrl-3 = <&P9_19_gpio_pd_pin>;
+		pinctrl-4 = <&P9_19_spi_cs_pin>;
+		pinctrl-5 = <&P9_19_can_pin>;
+		pinctrl-6 = <&P9_19_i2c_pin>;
+		pinctrl-7 = <&P9_19_pru_uart_pin>;
+		pinctrl-8 = <&P9_19_timer_pin>;
+	};
+
+	/* P9_20 (ZCZ ball D18) i2c */
+	P9_20_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "can", "i2c", "pru_uart", "timer";
+		pinctrl-0 = <&P9_20_default_pin>;
+		pinctrl-1 = <&P9_20_gpio_pin>;
+		pinctrl-2 = <&P9_20_gpio_pu_pin>;
+		pinctrl-3 = <&P9_20_gpio_pd_pin>;
+		pinctrl-4 = <&P9_20_spi_cs_pin>;
+		pinctrl-5 = <&P9_20_can_pin>;
+		pinctrl-6 = <&P9_20_i2c_pin>;
+		pinctrl-7 = <&P9_20_pru_uart_pin>;
+		pinctrl-8 = <&P9_20_timer_pin>;
+	};
+
+	/* P9_21 (ZCZ ball B17) */
+	P9_21_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm", "pru_uart";
+		pinctrl-0 = <&P9_21_default_pin>;
+		pinctrl-1 = <&P9_21_gpio_pin>;
+		pinctrl-2 = <&P9_21_gpio_pu_pin>;
+		pinctrl-3 = <&P9_21_gpio_pd_pin>;
+		pinctrl-4 = <&P9_21_spi_pin>;
+		pinctrl-5 = <&P9_21_uart_pin>;
+		pinctrl-6 = <&P9_21_i2c_pin>;
+		pinctrl-7 = <&P9_21_pwm_pin>;
+		pinctrl-8 = <&P9_21_pru_uart_pin>;
+	};
+
+	/* P9_22 (ZCZ ball A17) */
+	P9_22_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_sclk", "uart", "i2c", "pwm", "pru_uart";
+		pinctrl-0 = <&P9_22_default_pin>;
+		pinctrl-1 = <&P9_22_gpio_pin>;
+		pinctrl-2 = <&P9_22_gpio_pu_pin>;
+		pinctrl-3 = <&P9_22_gpio_pd_pin>;
+		pinctrl-4 = <&P9_22_spi_sclk_pin>;
+		pinctrl-5 = <&P9_22_uart_pin>;
+		pinctrl-6 = <&P9_22_i2c_pin>;
+		pinctrl-7 = <&P9_22_pwm_pin>;
+		pinctrl-8 = <&P9_22_pru_uart_pin>;
+	};
+
+	/* P9_23 (ZCZ ball V14) */
+	P9_23_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P9_23_default_pin>;
+		pinctrl-1 = <&P9_23_gpio_pin>;
+		pinctrl-2 = <&P9_23_gpio_pu_pin>;
+		pinctrl-3 = <&P9_23_gpio_pd_pin>;
+		pinctrl-4 = <&P9_23_pwm_pin>;
+	};
+
+	/* P9_24 (ZCZ ball D15) */
+	P9_24_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pru_uart", "pruin";
+		pinctrl-0 = <&P9_24_default_pin>;
+		pinctrl-1 = <&P9_24_gpio_pin>;
+		pinctrl-2 = <&P9_24_gpio_pu_pin>;
+		pinctrl-3 = <&P9_24_gpio_pd_pin>;
+		pinctrl-4 = <&P9_24_uart_pin>;
+		pinctrl-5 = <&P9_24_can_pin>;
+		pinctrl-6 = <&P9_24_i2c_pin>;
+		pinctrl-7 = <&P9_24_pru_uart_pin>;
+		pinctrl-8 = <&P9_24_pruin_pin>;
+	};
+
+	/* P9_25 (ZCZ ball A14) audio */
+	P9_25_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P9_25_default_pin>;
+		pinctrl-1 = <&P9_25_gpio_pin>;
+		pinctrl-2 = <&P9_25_gpio_pu_pin>;
+		pinctrl-3 = <&P9_25_gpio_pd_pin>;
+		pinctrl-4 = <&P9_25_eqep_pin>;
+		pinctrl-5 = <&P9_25_pruout_pin>;
+		pinctrl-6 = <&P9_25_pruin_pin>;
+	};
+
+	/* P9_26 (ZCZ ball D16) */
+	P9_26_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pru_uart", "pruin";
+		pinctrl-0 = <&P9_26_default_pin>;
+		pinctrl-1 = <&P9_26_gpio_pin>;
+		pinctrl-2 = <&P9_26_gpio_pu_pin>;
+		pinctrl-3 = <&P9_26_gpio_pd_pin>;
+		pinctrl-4 = <&P9_26_uart_pin>;
+		pinctrl-5 = <&P9_26_can_pin>;
+		pinctrl-6 = <&P9_26_i2c_pin>;
+		pinctrl-7 = <&P9_26_pru_uart_pin>;
+		pinctrl-8 = <&P9_26_pruin_pin>;
+	};
+
+	/* P9_27 (ZCZ ball C13) */
+	P9_27_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P9_27_default_pin>;
+		pinctrl-1 = <&P9_27_gpio_pin>;
+		pinctrl-2 = <&P9_27_gpio_pu_pin>;
+		pinctrl-3 = <&P9_27_gpio_pd_pin>;
+		pinctrl-4 = <&P9_27_eqep_pin>;
+		pinctrl-5 = <&P9_27_pruout_pin>;
+		pinctrl-6 = <&P9_27_pruin_pin>;
+	};
+
+	/* P9_28 (ZCZ ball C12) audio */
+	P9_28_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "pwm", "pwm2", "pruout", "pruin";
+		pinctrl-0 = <&P9_28_default_pin>;
+		pinctrl-1 = <&P9_28_gpio_pin>;
+		pinctrl-2 = <&P9_28_gpio_pu_pin>;
+		pinctrl-3 = <&P9_28_gpio_pd_pin>;
+		pinctrl-4 = <&P9_28_spi_cs_pin>;
+		pinctrl-5 = <&P9_28_pwm_pin>;
+		pinctrl-6 = <&P9_28_pwm2_pin>;
+		pinctrl-7 = <&P9_28_pruout_pin>;
+		pinctrl-8 = <&P9_28_pruin_pin>;
+	};
+
+	/* P9_29 (ZCZ ball B13) audio */
+	P9_29_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P9_29_default_pin>;
+		pinctrl-1 = <&P9_29_gpio_pin>;
+		pinctrl-2 = <&P9_29_gpio_pu_pin>;
+		pinctrl-3 = <&P9_29_gpio_pd_pin>;
+		pinctrl-4 = <&P9_29_spi_pin>;
+		pinctrl-5 = <&P9_29_pwm_pin>;
+		pinctrl-6 = <&P9_29_pruout_pin>;
+		pinctrl-7 = <&P9_29_pruin_pin>;
+	};
+
+	/* P9_30 (ZCZ ball D12) */
+	P9_30_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P9_30_default_pin>;
+		pinctrl-1 = <&P9_30_gpio_pin>;
+		pinctrl-2 = <&P9_30_gpio_pu_pin>;
+		pinctrl-3 = <&P9_30_gpio_pd_pin>;
+		pinctrl-4 = <&P9_30_spi_pin>;
+		pinctrl-5 = <&P9_30_pwm_pin>;
+		pinctrl-6 = <&P9_30_pruout_pin>;
+		pinctrl-7 = <&P9_30_pruin_pin>;
+	};
+
+	/* P9_31 (ZCZ ball A13) audio */
+	P9_31_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_sclk", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P9_31_default_pin>;
+		pinctrl-1 = <&P9_31_gpio_pin>;
+		pinctrl-2 = <&P9_31_gpio_pu_pin>;
+		pinctrl-3 = <&P9_31_gpio_pd_pin>;
+		pinctrl-4 = <&P9_31_spi_sclk_pin>;
+		pinctrl-5 = <&P9_31_pwm_pin>;
+		pinctrl-6 = <&P9_31_pruout_pin>;
+		pinctrl-7 = <&P9_31_pruin_pin>;
+	};
+
+	/* P9_32                VADC */
+
+	/* P9_33 (ZCZ ball C8)  AIN4 */
+
+	/* P9_34                AGND */
+
+	/* P9_35 (ZCZ ball A8)  AIN6 */
+
+	/* P9_36 (ZCZ ball B8)  AIN5 */
+
+	/* P9_37 (ZCZ ball B7)  AIN2 */
+
+	/* P9_38 (ZCZ ball A7)  AIN3 */
+
+	/* P9_39 (ZCZ ball B6)  AIN0 */
+
+	/* P9_40 (ZCZ ball C7)  AIN1 */
+
+	/* P9_41 (ZCZ ball D14) */
+	P9_41_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer", "pruin";
+		pinctrl-0 = <&P9_41_default_pin>;
+		pinctrl-1 = <&P9_41_gpio_pin>;
+		pinctrl-2 = <&P9_41_gpio_pu_pin>;
+		pinctrl-3 = <&P9_41_gpio_pd_pin>;
+		pinctrl-4 = <&P9_41_timer_pin>;
+		pinctrl-5 = <&P9_41_pruin_pin>;
+	};
+
+	/* P9_41.1 */
+	/* P9_91 (ZCZ ball D13) */
+	P9_91_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P9_91_default_pin>;
+		pinctrl-1 = <&P9_91_gpio_pin>;
+		pinctrl-2 = <&P9_91_gpio_pu_pin>;
+		pinctrl-3 = <&P9_91_gpio_pd_pin>;
+		pinctrl-4 = <&P9_91_eqep_pin>;
+		pinctrl-5 = <&P9_91_pruout_pin>;
+		pinctrl-6 = <&P9_91_pruin_pin>;
+	};
+
+	/* P9_42 (ZCZ ball C18) */
+	P9_42_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "spi_sclk", "uart", "pwm", "pru_ecap_pwm";
+		pinctrl-0 = <&P9_42_default_pin>;
+		pinctrl-1 = <&P9_42_gpio_pin>;
+		pinctrl-2 = <&P9_42_gpio_pu_pin>;
+		pinctrl-3 = <&P9_42_gpio_pd_pin>;
+		pinctrl-4 = <&P9_42_spi_cs_pin>;
+		pinctrl-5 = <&P9_42_spi_sclk_pin>;
+		pinctrl-6 = <&P9_42_uart_pin>;
+		pinctrl-7 = <&P9_42_pwm_pin>;
+		pinctrl-8 = <&P9_42_pru_ecap_pwm_pin>;
+	};
+
+	/* P9_42.1 */
+	/* P9_92 (ZCZ ball B12) */
+	P9_92_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P9_92_default_pin>;
+		pinctrl-1 = <&P9_92_gpio_pin>;
+		pinctrl-2 = <&P9_92_gpio_pu_pin>;
+		pinctrl-3 = <&P9_92_gpio_pd_pin>;
+		pinctrl-4 = <&P9_92_eqep_pin>;
+		pinctrl-5 = <&P9_92_pruout_pin>;
+		pinctrl-6 = <&P9_92_pruin_pin>;
+	};
+
+	/* P9_43                GND */
+
+	/* P9_44                GND */
+
+	/* P9_45                GND */
+
+	/* P9_46                GND */
+
+	cape-universal {
+		compatible = "gpio-of-helper";
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <>;
+
+		P8_03 {
+			gpio-name = "P8_03";
+			gpio = <&gpio1 6 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_04 {
+			gpio-name = "P8_04";
+			gpio = <&gpio1 7 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_05 {
+			gpio-name = "P8_05";
+			gpio = <&gpio1 2 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_06 {
+			gpio-name = "P8_06";
+			gpio = <&gpio1 3 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_07 {
+			gpio-name = "P8_07";
+			gpio = <&gpio2 2 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_08 {
+			gpio-name = "P8_08";
+			gpio = <&gpio2 3 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_09 {
+			gpio-name = "P8_09";
+			gpio = <&gpio2 5 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_10 {
+			gpio-name = "P8_10";
+			gpio = <&gpio2 4 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_11 {
+			gpio-name = "P8_11";
+			gpio = <&gpio1 13 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_12 {
+			gpio-name = "P8_12";
+			gpio = <&gpio1 12 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_13 {
+			gpio-name = "P8_13";
+			gpio = <&gpio0 23 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_14 {
+			gpio-name = "P8_14";
+			gpio = <&gpio0 26 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_15 {
+			gpio-name = "P8_15";
+			gpio = <&gpio1 15 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_16 {
+			gpio-name = "P8_16";
+			gpio = <&gpio1 14 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_17 {
+			gpio-name = "P8_17";
+			gpio = <&gpio0 27 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_18 {
+			gpio-name = "P8_18";
+			gpio = <&gpio2 1 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_19 {
+			gpio-name = "P8_19";
+			gpio = <&gpio0 22 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_20 {
+			gpio-name = "P8_20";
+			gpio = <&gpio1 31 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_21 {
+			gpio-name = "P8_21";
+			gpio = <&gpio1 30 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_22 {
+			gpio-name = "P8_22";
+			gpio = <&gpio1 5 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_23 {
+			gpio-name = "P8_23";
+			gpio = <&gpio1 4 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_24 {
+			gpio-name = "P8_24";
+			gpio = <&gpio1 1 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_25 {
+			gpio-name = "P8_25";
+			gpio = <&gpio1 0 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_26 {
+			gpio-name = "P8_26";
+			gpio = <&gpio1 29 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_27 {
+			gpio-name = "P8_27";
+			gpio = <&gpio2 22 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_28 {
+			gpio-name = "P8_28";
+			gpio = <&gpio2 24 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_29 {
+			gpio-name = "P8_29";
+			gpio = <&gpio2 23 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_30 {
+			gpio-name = "P8_30";
+			gpio = <&gpio2 25 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_31 {
+			gpio-name = "P8_31";
+			gpio = <&gpio0 10 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_32 {
+			gpio-name = "P8_32";
+			gpio = <&gpio0 11 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_33 {
+			gpio-name = "P8_33";
+			gpio = <&gpio0 9 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_34 {
+			gpio-name = "P8_34";
+			gpio = <&gpio2 17 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_35 {
+			gpio-name = "P8_35";
+			gpio = <&gpio0 8 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_36 {
+			gpio-name = "P8_36";
+			gpio = <&gpio2 16 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_37 {
+			gpio-name = "P8_37";
+			gpio = <&gpio2 14 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_38 {
+			gpio-name = "P8_38";
+			gpio = <&gpio2 15 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_39 {
+			gpio-name = "P8_39";
+			gpio = <&gpio2 12 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_40 {
+			gpio-name = "P8_40";
+			gpio = <&gpio2 13 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_41 {
+			gpio-name = "P8_41";
+			gpio = <&gpio2 10 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_42 {
+			gpio-name = "P8_42";
+			gpio = <&gpio2 11 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_43 {
+			gpio-name = "P8_43";
+			gpio = <&gpio2 8 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_44 {
+			gpio-name = "P8_44";
+			gpio = <&gpio2 9 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_45 {
+			gpio-name = "P8_45";
+			gpio = <&gpio2 6 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_46 {
+			gpio-name = "P8_46";
+			gpio = <&gpio2 7 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_11 {
+			gpio-name = "P9_11";
+			gpio = <&gpio0 30 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_12 {
+			gpio-name = "P9_12";
+			gpio = <&gpio1 28 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_13 {
+			gpio-name = "P9_13";
+			gpio = <&gpio0 31 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_14 {
+			gpio-name = "P9_14";
+			gpio = <&gpio1 18 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_15 {
+			gpio-name = "P9_15";
+			gpio = <&gpio1 16 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_16 {
+			gpio-name = "P9_16";
+			gpio = <&gpio1 19 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_17 {
+			gpio-name = "P9_17";
+			gpio = <&gpio0 5 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_18 {
+			gpio-name = "P9_18";
+			gpio = <&gpio0 4 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_19 {
+			gpio-name = "P9_19";
+			gpio = <&gpio0 13 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_20 {
+			gpio-name = "P9_20";
+			gpio = <&gpio0 12 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_21 {
+			gpio-name = "P9_21";
+			gpio = <&gpio0 3 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_22 {
+			gpio-name = "P9_22";
+			gpio = <&gpio0 2 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_23 {
+			gpio-name = "P9_23";
+			gpio = <&gpio1 17 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_24 {
+			gpio-name = "P9_24";
+			gpio = <&gpio0 15 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_25 {
+			gpio-name = "P9_25";
+			gpio = <&gpio3 21 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_26 {
+			gpio-name = "P9_26";
+			gpio = <&gpio0 14 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_27 {
+			gpio-name = "P9_27";
+			gpio = <&gpio3 19 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_28 {
+			gpio-name = "P9_28";
+			gpio = <&gpio3 17 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_29 {
+			gpio-name = "P9_29";
+			gpio = <&gpio3 15 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_30 {
+			gpio-name = "P9_30";
+			gpio = <&gpio3 16 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_31 {
+			gpio-name = "P9_31";
+			gpio = <&gpio3 14 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_41 {
+			gpio-name = "P9_41";
+			gpio = <&gpio0 20 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_91 {
+			gpio-name = "P9_91";
+			gpio = <&gpio3 20 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_42 {
+			gpio-name = "P9_42";
+			gpio = <&gpio0 7 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_92 {
+			gpio-name = "P9_92";
+			gpio = <&gpio3 18 0>;
+			input;
+			dir-changeable;
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
--- a/arch/arm/boot/dts/am335x-bone.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-bone.dts	2024-01-28 14:01:31.236353764 -0500
@@ -10,6 +10,11 @@
 / {
 	model = "TI AM335x BeagleBone";
 	compatible = "ti,am335x-bone", "ti,am33xx";
+
+	chosen {
+		base_dtb = "am335x-bone.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
 };
 
 &ldo3_reg {
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-bonegreen-common.dtsi b/arch/arm/boot/dts/am335x-bonegreen-common.dtsi
--- a/arch/arm/boot/dts/am335x-bonegreen-common.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-bonegreen-common.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -22,7 +22,7 @@
 };
 
 &am33xx_pinmux {
-	uart2_pins: uart2_pins {
+	uart2_pins: uart2-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1)	/* spi0_sclk.uart2_rxd */
 			AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1)	/* spi0_d0.uart2_txd */
@@ -34,6 +34,7 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart2_pins>;
 	status = "okay";
+	symlink = "bone/uart/2";
 };
 
 &rtc {
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-bonegreen.dts b/arch/arm/boot/dts/am335x-bonegreen.dts
--- a/arch/arm/boot/dts/am335x-bonegreen.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-bonegreen.dts	2024-01-28 14:01:31.236353764 -0500
@@ -11,4 +11,157 @@
 / {
 	model = "TI AM335x BeagleBone Green";
 	compatible = "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+
+	chosen {
+		base_dtb = "am335x-bonegreen.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
 };
+
+&gpio0 {
+	gpio-line-names =
+		"[mdio_data]",
+		"[mdio_clk]",
+		"P9_22 [spi0_sclk]",
+		"P9_21 [spi0_d0]",
+		"P9_18 [spi0_d1]",
+		"P9_17 [spi0_cs0]",
+		"[mmc0_cd]",
+		"P9_42A [ecappwm0]",
+		"P8_35 [lcd d12]",
+		"P8_33 [lcd d13]",
+		"P8_31 [lcd d14]",
+		"P8_32 [lcd d15]",
+		"P9_20 [i2c2_sda]",
+		"P9_19 [i2c2_scl]",
+		"P9_26 [uart1_rxd]",
+		"P9_24 [uart1_txd]",
+		"[rmii1_txd3]",
+		"[rmii1_txd2]",
+		"[usb0_drvvbus]",
+		"[hdmi cec]",
+		"P9_41B",
+		"[rmii1_txd1]",
+		"P8_19 [ehrpwm2a]",
+		"P8_13 [ehrpwm2b]",
+		"NC",
+		"NC",
+		"P8_14",
+		"P8_17",
+		"[rmii1_txd0]",
+		"[rmii1_refclk]",
+		"P9_11 [uart4_rxd]",
+		"P9_13 [uart4_txd]";
+};
+
+&gpio1 {
+	gpio-line-names =
+		"P8_25 [mmc1_dat0]",
+		"[mmc1_dat1]",
+		"P8_5 [mmc1_dat2]",
+		"P8_6 [mmc1_dat3]",
+		"P8_23 [mmc1_dat4]",
+		"P8_22 [mmc1_dat5]",
+		"P8_3 [mmc1_dat6]",
+		"P8_4 [mmc1_dat7]",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"P8_12",
+		"P8_11",
+		"P8_16",
+		"P8_15",
+		"P9_15A",
+		"P9_23",
+		"P9_14 [ehrpwm1a]",
+		"P9_16 [ehrpwm1b]",
+		"[emmc rst]",
+		"[usr0 led]",
+		"[usr1 led]",
+		"[usr2 led]",
+		"[usr3 led]",
+		"[hdmi irq]",
+		"[usb vbus oc]",
+		"[hdmi audio]",
+		"P9_12",
+		"P8_26",
+		"P8_21 [emmc]",
+		"P8_20 [emmc]";
+};
+
+&gpio2 {
+	gpio-line-names =
+		"P9_15B",
+		"P8_18",
+		"P8_7",
+		"P8_8",
+		"P8_10",
+		"P8_9",
+		"P8_45",
+		"P8_46",
+		"P8_43",
+		"P8_44",
+		"P8_41",
+		"P8_42",
+		"P8_39",
+		"P8_40",
+		"P8_37",
+		"P8_38",
+		"P8_36",
+		"P8_34",
+		"[rmii1_rxd3]",
+		"[rmii1_rxd2]",
+		"[rmii1_rxd1]",
+		"[rmii1_rxd0]",
+		"P8_27",
+		"P8_29",
+		"P8_28",
+		"P8_30",
+		"[mmc0_dat3]",
+		"[mmc0_dat2]",
+		"[mmc0_dat1]",
+		"[mmc0_dat0]",
+		"[mmc0_clk]",
+		"[mmc0_cmd]";
+};
+
+&gpio3 {
+	gpio-line-names =
+		"[mii col]",
+		"[mii crs]",
+		"[mii rx err]",
+		"[mii tx en]",
+		"[mii rx dv]",
+		"[i2c0 sda]",
+		"[i2c0 scl]",
+		"[jtag emu0]",
+		"[jtag emu1]",
+		"[mii tx clk]",
+		"[mii rx clk]",
+		"NC",
+		"NC",
+		"[usb vbus en]",
+		"P9_31 [spi1_sclk]",
+		"P9_29 [spi1_d0]",
+		"P9_30 [spi1_d1]",
+		"P9_28 [spi1_cs0]",
+		"P9_42B [ecappwm0]",
+		"P9_27",
+		"P9_41A",
+		"P9_25",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC",
+		"NC";
+};
+
+&baseboard_eeprom {
+	vcc-supply = <&ldo4_reg>;
+};
\ No newline at end of file
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-bonegreen-gateway.dts b/arch/arm/boot/dts/am335x-bonegreen-gateway.dts
--- a/arch/arm/boot/dts/am335x-bonegreen-gateway.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-bonegreen-gateway.dts	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+#include "am335x-bonegreen-common.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	model = "SeeedStudio BeagleBone Green Gateway";
+	compatible = "ti,am335x-bone-green-gateway", "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+
+	aliases {
+		rtc0 = &extrtc;
+		rtc1 = &rtc;
+	};
+
+	chosen {
+		base_dtb = "am335x-bonegreen-gateway.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+		wl1835_bt = "S3-texas-300000";
+	};
+
+	wlan_en_reg: fixedregulator@2 {
+		compatible = "regulator-fixed";
+		regulator-name = "wlan-en-regulator";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		startup-delay-us= <70000>;
+
+		/* WL_EN */
+		gpio = <&gpio3 9 0>;
+		enable-active-high;
+	};
+
+	leds {
+		pinctrl-names = "default";
+		//pinctrl-0 = <&user_leds_s0>;
+		pinctrl-0 = <&user_leds_s0 &bt_pins>;
+
+		compatible = "gpio-leds";
+
+		led2 {
+			label = "beaglebone:green:usr0";
+			gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+
+		led3 {
+			label = "beaglebone:green:usr1";
+			gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led4 {
+			label = "beaglebone:green:usr2";
+			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "cpu0";
+			default-state = "off";
+		};
+
+		led5 {
+			label = "beaglebone:green:usr3";
+			gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc1";
+			default-state = "off";
+		};
+
+		led6 {
+			label = "beaglebone:green:usr4";
+			gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "netdev";
+			default-state = "off";
+		};
+
+		wl18xx_bt_en: led7 {
+			label = "wl18xx_bt_en";
+			gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+};
+
+&cpu0_opp_table {
+	/*
+	 * Octavo Systems:
+	 * The EFUSE_SMA register is not programmed for any of the AM335x wafers
+	 * we get and we are not programming them during our production test.
+	 * Therefore, from a DEVICE_ID revision point of view, the silicon looks
+	 * like it is Revision 2.1.  However, from an EFUSE_SMA point of view for
+	 * the HW OPP table, the silicon looks like it is Revision 1.0 (ie the
+	 * EFUSE_SMA register reads as all zeros).
+	 */
+	oppnitro-1000000000 {
+		opp-supported-hw = <0x06 0x0100>;
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usbhost_pins>;
+
+	user_leds_s0: user-leds-s0-pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gpmc_a5.gpio1_21 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_a6.gpio1_22 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gpmc_a7.gpio1_23 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_a8.gpio1_24 */
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* WL_Active_LED / USR4 */
+		>;
+	};
+
+	bt_pins: bt-pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gmii1_txd0.gpio0_28 - BT_EN */
+		>;
+	};
+
+	mmc3_pins: mmc3-pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */
+			AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */
+			AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */
+			AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */
+			AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */
+			AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */
+		>;
+	};
+
+	uart2_grove_pins: pinmux_uart2_grove_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x90c, PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6)
+			AM33XX_IOPAD(0x910, PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6)
+		>;
+	};
+
+	uart3_pins: uart3-pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1)	/* gmii1_rxd3.uart3_rxd */
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1)	/* gmii1_rxd2.uart3_txd */
+			AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT, MUX_MODE3)		/* mdio_data.uart3_ctsn */
+			AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLDOWN, MUX_MODE3)	/* mdio_clk.uart3_rtsn */
+		>;
+	};
+
+	usbhost_pins: pinmux_usbhost_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gmii1_txd1.gpio0[21] */
+		>;
+	};
+
+	wl18xx_pins: wl18xx-pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gmii1_txclk.gpio3_9 WL_EN */
+			AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)	/* rmii1_refclk.gpio0_29 WL_IRQ */
+			AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gmii1_rxclk.gpio3_10 LS_BUF_EN */
+		>;
+	};
+};
+
+&mac_sw {
+	/delete-property/pinctrl-names;
+	/delete-property/pinctrl-0;
+	/delete-property/pinctrl-1;
+	status = "disabled";
+};
+
+&mmc3 {
+	dmas = <&edma_xbar 12 0 1
+		&edma_xbar 13 0 2>;
+	dma-names = "tx", "rx";
+	status = "okay";
+	vmmc-supply = <&wlan_en_reg>;
+	bus-width = <4>;
+	non-removable;
+	cap-power-off-card;
+	keep-power-in-suspend;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc3_pins &wl18xx_pins>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1835";
+		reg = <2>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <29 IRQ_TYPE_EDGE_RISING>;
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_grove_pins>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+	//pinctrl-0 = <&uart3_pins &bt_pins>;
+	status = "okay";
+
+	//bluetooth {
+	//	compatible = "ti,wl1835-st";
+	//	enable-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
+	//};
+};
+
+&i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	extrtc: rtc@68 {
+		compatible = "dallas,ds1340";
+		reg = <0x68>;
+	};
+};
+
+// (K16) gmii1_txd1.gpio0[21]
+&gpio0 {
+	usb-reset-hog {
+		gpio-hog;
+		gpios = <21 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "usb_reset";
+	};
+};
+
+&gpio3 {
+	ls-buf-en-hog {
+		gpio-hog;
+		gpios = <10 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "LS_BUF_EN";
+	};
+};
+
+&usb1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	hub@1 {
+		compatible = "usb424,9512";
+		reg = <1>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethernet: ethernet@1 {
+			compatible = "usb424,ec00";
+			reg = <1>;
+		};
+	};
+};
+
+&baseboard_eeprom {
+	vcc-supply = <&ldo4_reg>;
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-bonegreen-wireless-common-univ.dtsi b/arch/arm/boot/dts/am335x-bonegreen-wireless-common-univ.dtsi
--- a/arch/arm/boot/dts/am335x-bonegreen-wireless-common-univ.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-bonegreen-wireless-common-univ.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,2197 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+#include <dt-bindings/board/am335x-bone-pins.h>
+
+&am33xx_pinmux {
+
+/* macro: BONE_PIN( <pin>, <mode_name>, <register_value_macro(s)> */
+#define BONE_PIN(XX,ZZ,QQ) \
+	XX##_##ZZ##_pin: pinmux_##XX##_##ZZ##_pin { pinctrl-single,pins = < QQ >; };
+
+	/************************/
+	/* P8 Header */
+	/************************/
+
+	/* P8_01                GND */
+
+	/* P8_02                GND */
+
+
+	/* P8_03 (ZCZ ball R9) gpmc_ad6 (emmc) */
+	BONE_PIN(P8_03, default, P8_03(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_03, gpio, P8_03(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_03, gpio_pu, P8_03(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_03, gpio_pd, P8_03(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_04 (ZCZ ball T9) gpmc_ad7 (emmc) */
+	BONE_PIN(P8_04, default, P8_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_04, gpio, P8_04(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_04, gpio_pu, P8_04(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_04, gpio_pd, P8_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_05 (ZCZ ball R8) gpmc_ad2 (emmc) */
+	BONE_PIN(P8_05, default, P8_05(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_05, gpio, P8_05(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_05, gpio_pu, P8_05(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_05, gpio_pd, P8_05(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_06 (ZCZ ball T8) gpmc_ad3 (emmc) */
+	BONE_PIN(P8_06, default, P8_06(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_06, gpio, P8_06(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_06, gpio_pu, P8_06(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_06, gpio_pd, P8_06(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_07 (ZCZ ball R7) gpmc_advn_ale (gpio2_2) */
+	BONE_PIN(P8_07, default, P8_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_07, gpio, P8_07(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_07, gpio_pu, P8_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_07, gpio_pd, P8_07(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_07, timer, P8_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_08 (ZCZ ball T7) gpmc_oen_ren (gpio2_3) */
+	BONE_PIN(P8_08, default, P8_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_08, gpio, P8_08(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_08, gpio_pu, P8_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_08, gpio_pd, P8_08(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_08, timer, P8_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_09 (ZCZ ball T6) gpmc_be0n_cle (gpio2_5) */
+	BONE_PIN(P8_09, default, P8_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_09, gpio, P8_09(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_09, gpio_pu, P8_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_09, gpio_pd, P8_09(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_09, timer, P8_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_10 (ZCZ ball U6) gpmc_wen (gpio2_4) */
+	BONE_PIN(P8_10, default, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_10, gpio, P8_10(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_10, gpio_pu, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_10, gpio_pd, P8_10(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_10, timer, P8_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_11 (ZCZ ball R12) gpmc_ad13 (gpio1_13) */
+	BONE_PIN(P8_11, default, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_11, gpio, P8_11(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_11, gpio_pu, P8_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_11, gpio_pd, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_11, eqep, P8_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P8_11, pruout, P8_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P8_12 (ZCZ ball T12) gpmc_ad12 (gpio1_12) */
+	BONE_PIN(P8_12, default, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_12, gpio, P8_12(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_12, gpio_pu, P8_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_12, gpio_pd, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_12, eqep, P8_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P8_12, pruout, P8_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P8_13 (ZCZ ball T10) gpmc_ad9 (gpio0_23) */
+	BONE_PIN(P8_13, default, P8_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_13, gpio, P8_13(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_13, gpio_pu, P8_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_13, gpio_pd, P8_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_13, pwm, P8_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4))
+
+	/* P8_14 (ZCZ ball T11) wl1835: wl_en */
+
+	/* P8_15 (ZCZ ball U13) gpmc_ad15 (gpio1_15) */
+	BONE_PIN(P8_15, default, P8_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_15, gpio, P8_15(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_15, gpio_pu, P8_15(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_15, gpio_pd, P8_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_15, eqep, P8_15(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P8_15, pru_ecap_pwm, P8_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_15, pruin, P8_15(PIN_INPUT | MUX_MODE6))
+
+	/* P8_16 (ZCZ ball V13) gpmc_ad14 (gpio1_14) */
+	BONE_PIN(P8_16, default, P8_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_16, gpio, P8_16(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_16, gpio_pu, P8_16(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_16, gpio_pd, P8_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_16, eqep, P8_16(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P8_16, pruin, P8_16(PIN_INPUT | MUX_MODE6))
+
+	/* P8_17 (ZCZ ball U12) wl1835: wl_irq */
+
+	/* P8_18 (ZCZ ball V12) gpmc_clk (gpio2_1) */
+	BONE_PIN(P8_18, default, P8_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_18, gpio, P8_18(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_18, gpio_pu, P8_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_18, gpio_pd, P8_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_19 (ZCZ ball U10) gpmc_ad8 (gpio0_22) */
+	BONE_PIN(P8_19, default, P8_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_19, gpio, P8_19(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_19, gpio_pu, P8_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_19, gpio_pd, P8_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_19, pwm, P8_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4))
+
+	/* P8_20 (ZCZ ball V9) gpmc_csn2 (emmc) */
+	BONE_PIN(P8_20, default, P8_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_20, gpio, P8_20(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_20, gpio_pu, P8_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_20, gpio_pd, P8_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_20, pruout, P8_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_20, pruin, P8_20(PIN_INPUT | MUX_MODE6))
+
+	/* P8_21 (ZCZ ball U9) gpmc_csn1 (emmc) */
+	BONE_PIN(P8_21, default, P8_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_21, gpio, P8_21(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_21, gpio_pu, P8_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_21, gpio_pd, P8_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_21, pruout, P8_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_21, pruin, P8_21(PIN_INPUT | MUX_MODE6))
+
+	/* P8_22 (ZCZ ball V8) gpmc_ad5 (emmc) */
+	BONE_PIN(P8_22, default, P8_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_22, gpio, P8_22(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_22, gpio_pu, P8_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_22, gpio_pd, P8_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_23 (ZCZ ball U8) gpmc_ad4 (emmc) */
+	BONE_PIN(P8_23, default, P8_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_23, gpio, P8_23(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_23, gpio_pu, P8_23(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_23, gpio_pd, P8_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_24 (ZCZ ball V7) gpmc_ad1 (emmc) */
+	BONE_PIN(P8_24, default, P8_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_24, gpio, P8_24(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_24, gpio_pu, P8_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_24, gpio_pd, P8_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_25 (ZCZ ball U7) gpmc_ad0 (emmc) */
+	BONE_PIN(P8_25, default, P8_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_25, gpio, P8_25(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_25, gpio_pu, P8_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_25, gpio_pd, P8_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P8_26 (ZCZ ball V6) gpio-hog wl1835 */
+
+	/* P8_27 (ZCZ ball U5) lcd_vsync (hdmi) */
+	BONE_PIN(P8_27, default, P8_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_27, gpio, P8_27(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_27, gpio_pu, P8_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_27, gpio_pd, P8_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_27, pruout, P8_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_27, pruin, P8_27(PIN_INPUT | MUX_MODE6))
+
+	/* P8_28 (ZCZ ball V5) lcd_pclk (hdmi) */
+	BONE_PIN(P8_28, default, P8_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_28, gpio, P8_28(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_28, gpio_pu, P8_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_28, gpio_pd, P8_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_28, pruout, P8_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_28, pruin, P8_28(PIN_INPUT | MUX_MODE6))
+
+	/* P8_29 (ZCZ ball R5) lcd_hsync (hdmi) */
+	BONE_PIN(P8_29, default, P8_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_29, gpio, P8_29(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_29, gpio_pu, P8_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_29, gpio_pd, P8_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_29, pruout, P8_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_29, pruin, P8_29(PIN_INPUT | MUX_MODE6))
+
+	/* P8_30 (ZCZ ball R6) lcd_ac_bias_en (hdmi) */
+	BONE_PIN(P8_30, default, P8_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_30, gpio, P8_30(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_30, gpio_pu, P8_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_30, gpio_pd, P8_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_30, pruout, P8_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_30, pruin, P8_30(PIN_INPUT | MUX_MODE6))
+
+	/* P8_31 (ZCZ ball V4) lcd_data14 (hdmi) */
+	BONE_PIN(P8_31, default, P8_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_31, gpio, P8_31(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_31, gpio_pu, P8_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_31, gpio_pd, P8_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_31, eqep, P8_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P8_31, uart, P8_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P8_32 (ZCZ ball T5) lcd_data15 (hdmi) */
+	BONE_PIN(P8_32, default, P8_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_32, gpio, P8_32(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_32, gpio_pu, P8_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_32, gpio_pd, P8_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_32, eqep, P8_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_33 (ZCZ ball V3) lcd_data13 (hdmi) */
+	BONE_PIN(P8_33, default, P8_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_33, gpio, P8_33(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_33, gpio_pu, P8_33(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_33, gpio_pd, P8_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_33, eqep, P8_33(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_34 (ZCZ ball U4) lcd_data11 (hdmi) */
+	BONE_PIN(P8_34, default, P8_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_34, gpio, P8_34(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_34, gpio_pu, P8_34(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_34, gpio_pd, P8_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_34, pwm, P8_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2))
+
+	/* P8_35 (ZCZ ball V2) lcd_data12 (hdmi) */
+	BONE_PIN(P8_35, default, P8_35(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_35, gpio, P8_35(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_35, gpio_pu, P8_35(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_35, gpio_pd, P8_35(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_35, eqep, P8_35(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+
+	/* P8_36 (ZCZ ball U3) lcd_data10 (hdmi) */
+	BONE_PIN(P8_36, default, P8_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_36, gpio, P8_36(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_36, gpio_pu, P8_36(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_36, gpio_pd, P8_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_36, pwm, P8_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2))
+
+	/* P8_37 (ZCZ ball U1) lcd_data8 (hdmi) */
+	BONE_PIN(P8_37, default, P8_37(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_37, gpio, P8_37(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_37, gpio_pu, P8_37(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_37, gpio_pd, P8_37(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_37, pwm, P8_37(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P8_37, uart, P8_37(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P8_38 (ZCZ ball U2) lcd_data9 (hdmi) */
+	BONE_PIN(P8_38, default, P8_38(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_38, gpio, P8_38(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_38, gpio_pu, P8_38(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_38, gpio_pd, P8_38(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_38, pwm, P8_38(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P8_38, uart, P8_38(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P8_39 (ZCZ ball T3) lcd_data6 (hdmi) */
+	BONE_PIN(P8_39, default, P8_39(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_39, gpio, P8_39(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_39, gpio_pu, P8_39(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_39, gpio_pd, P8_39(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_39, eqep, P8_39(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_39, pruout, P8_39(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_39, pruin, P8_39(PIN_INPUT | MUX_MODE6))
+
+	/* P8_40 (ZCZ ball T4) lcd_data7 (hdmi) */
+	BONE_PIN(P8_40, default, P8_40(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_40, gpio, P8_40(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_40, gpio_pu, P8_40(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_40, gpio_pd, P8_40(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_40, eqep, P8_40(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_40, pruout, P8_40(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_40, pruin, P8_40(PIN_INPUT | MUX_MODE6))
+
+	/* P8_41 (ZCZ ball T1) lcd_data4 (hdmi) */
+	BONE_PIN(P8_41, default, P8_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_41, gpio, P8_41(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_41, gpio_pu, P8_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_41, gpio_pd, P8_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_41, eqep, P8_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_41, pruout, P8_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_41, pruin, P8_41(PIN_INPUT | MUX_MODE6))
+
+	/* P8_42 (ZCZ ball T2) lcd_data5 (hdmi) */
+	BONE_PIN(P8_42, default, P8_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_42, gpio, P8_42(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_42, gpio_pu, P8_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_42, gpio_pd, P8_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_42, eqep, P8_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_42, pruout, P8_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_42, pruin, P8_42(PIN_INPUT | MUX_MODE6))
+
+	/* P8_43 (ZCZ ball R3) lcd_data2 (hdmi) */
+	BONE_PIN(P8_43, default, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_43, gpio, P8_43(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_43, gpio_pu, P8_43(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_43, gpio_pd, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_43, pwm, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_43, pruout, P8_43(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_43, pruin, P8_43(PIN_INPUT | MUX_MODE6))
+
+	/* P8_44 (ZCZ ball R4) lcd_data3 (hdmi) */
+	BONE_PIN(P8_44, default, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_44, gpio, P8_44(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_44, gpio_pu, P8_44(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_44, gpio_pd, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_44, pwm, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_44, pruout, P8_44(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_44, pruin, P8_44(PIN_INPUT | MUX_MODE6))
+
+	/* P8_45 (ZCZ ball R1) lcd_data0 (hdmi) */
+	BONE_PIN(P8_45, default, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_45, gpio, P8_45(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_45, gpio_pu, P8_45(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_45, gpio_pd, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_45, pwm, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_45, pruout, P8_45(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_45, pruin, P8_45(PIN_INPUT | MUX_MODE6))
+
+	/* P8_46 (ZCZ ball R2) lcd_data1 (hdmi) */
+	BONE_PIN(P8_46, default, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_46, gpio, P8_46(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_46, gpio_pu, P8_46(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_46, gpio_pd, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P8_46, pwm, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P8_46, pruout, P8_46(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P8_46, pruin, P8_46(PIN_INPUT | MUX_MODE6))
+
+	/************************/
+	/* P9 Header */
+	/************************/
+
+	/* P9_01                GND */
+
+	/* P9_02                GND */
+
+	/* P9_03                3V3 */
+
+	/* P9_04                3V3 */
+
+	/* P9_05                VDD_5V */
+
+	/* P9_06                VDD_5V */
+
+	/* P9_07                SYS_5V */
+
+	/* P9_08                SYS_5V */
+
+	/* P9_09                PWR_BUT */
+
+	/* P9_10                RSTn */
+
+	/* P9_11 (ZCZ ball T17) gpmc_wait0 (gpio0_30) */
+	BONE_PIN(P9_11, default, P9_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_11, gpio, P9_11(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_11, gpio_pu, P9_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_11, gpio_pd, P9_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_11, uart, P9_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6))
+
+	/* P9_12 (ZCZ ball U18) gpmc_be1n (gpio1_28) */
+	BONE_PIN(P9_12, default, P9_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_12, gpio, P9_12(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_12, gpio_pu, P9_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_12, gpio_pd, P9_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P9_13 (ZCZ ball U17) gpmc_wpn (gpio0_31) */
+	BONE_PIN(P9_13, default, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_13, gpio, P9_13(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_13, gpio_pu, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_13, gpio_pd, P9_13(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_13, uart, P9_13(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6))
+
+	/* P9_14 (ZCZ ball U14) gpmc_a2 (gpio1_18) */
+	BONE_PIN(P9_14, default, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_14, gpio, P9_14(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_14, gpio_pu, P9_14(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_14, gpio_pd, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_14, pwm, P9_14(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P9_15 (ZCZ ball R13) gpmc_a0 (gpio1_16) */
+	BONE_PIN(P9_15, default, P9_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_15, gpio, P9_15(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_15, gpio_pu, P9_15(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_15, gpio_pd, P9_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_15, pwm, P9_15(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P9_16 (ZCZ ball T14) gpmc_a3 (gpio1_19) */
+	BONE_PIN(P9_16, default, P9_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_16, gpio, P9_16(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_16, gpio_pu, P9_16(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_16, gpio_pd, P9_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_16, pwm, P9_16(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P9_17 (ZCZ ball A16) spi0_cs0 (gpio0_5) */
+	BONE_PIN(P9_17, default, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_17, gpio, P9_17(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_17, gpio_pu, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_17, gpio_pd, P9_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_17, spi_cs, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P9_17, i2c, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P9_17, pwm, P9_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_17, pru_uart, P9_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P9_18 (ZCZ ball B16) spi0_d1 (gpio0_4) */
+	BONE_PIN(P9_18, default, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_18, gpio, P9_18(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_18, gpio_pu, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_18, gpio_pd, P9_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_18, spi, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P9_18, i2c, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P9_18, pwm, P9_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_18, pru_uart, P9_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P9_19 (ZCZ ball D17) uart1_rtsn (i2c2_scl) */
+	BONE_PIN(P9_19, default, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_19, gpio, P9_19(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_19, gpio_pu, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_19, gpio_pd, P9_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_19, timer, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_19, can, P9_19(PIN_INPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P9_19, i2c, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_19, spi_cs, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P9_19, pru_uart, P9_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+
+	/* P9_20 (ZCZ ball D18) uart1_ctsn (i2c2_sda) */
+	BONE_PIN(P9_20, default, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_20, gpio, P9_20(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_20, gpio_pu, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_20, gpio_pd, P9_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_20, timer, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_20, can, P9_20(PIN_OUTPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P9_20, i2c, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_20, spi_cs, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P9_20, pru_uart, P9_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+
+	/* P9_21 (ZCZ ball B17) spi0_d0 (gpio0_3) */
+	BONE_PIN(P9_21, default, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_21, gpio, P9_21(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_21, gpio_pu, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_21, gpio_pd, P9_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_21, spi, P9_21(PIN_INPUT_PULLUP | MUX_MODE0))
+	BONE_PIN(P9_21, uart, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_21, i2c, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P9_21, pwm, P9_21(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_21, pru_uart, P9_21(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P9_22 (ZCZ ball A17) spi0_sclk (gpio0_2) */
+	BONE_PIN(P9_22, default, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_22, gpio, P9_22(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_22, gpio_pu, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_22, gpio_pd, P9_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_22, spi_sclk, P9_22(PIN_INPUT_PULLUP | MUX_MODE0))
+	BONE_PIN(P9_22, uart, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_22, i2c, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P9_22, pwm, P9_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_22, pru_uart, P9_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P9_23 (ZCZ ball V14) gpmc_a1 (gpio1_17) */
+	BONE_PIN(P9_23, default, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_23, gpio, P9_23(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_23, gpio_pu, P9_23(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_23, gpio_pd, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_23, pwm, P9_23(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P9_24 (ZCZ ball D15) uart1_txd (gpio0_15) */
+	BONE_PIN(P9_24, default, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_24, gpio, P9_24(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_24, gpio_pu, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_24, gpio_pd, P9_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_24, uart, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P9_24, can, P9_24(PIN_INPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P9_24, i2c, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_24, pru_uart, P9_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_24, pruin, P9_24(PIN_INPUT | MUX_MODE6))
+
+	/* P9_25 (ZCZ ball A14) mcasp0_ahclkx (audio) */
+	BONE_PIN(P9_25, default, P9_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_25, gpio, P9_25(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_25, gpio_pu, P9_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_25, gpio_pd, P9_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_25, eqep, P9_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_25, pruout, P9_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_25, pruin, P9_25(PIN_INPUT | MUX_MODE6))
+
+	/* P9_26 (ZCZ ball D16) uart1_rxd (gpio0_14) */
+	BONE_PIN(P9_26, default, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_26, gpio, P9_26(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_26, gpio_pu, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_26, gpio_pd, P9_26(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_26, uart, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P9_26, can, P9_26(PIN_OUTPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P9_26, i2c, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_26, pru_uart, P9_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_26, pruin, P9_26(PIN_INPUT | MUX_MODE6))
+
+	/* P9_27 (ZCZ ball C13) mcasp0_fsr (gpio3_19) */
+	BONE_PIN(P9_27, default, P9_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_27, gpio, P9_27(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_27, gpio_pu, P9_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_27, gpio_pd, P9_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_27, eqep, P9_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_27, pruout, P9_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_27, pruin, P9_27(PIN_INPUT | MUX_MODE6))
+
+	/* P9_28 (ZCZ ball C12) mcasp0_ahclkr (audio) */
+	BONE_PIN(P9_28, default, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_28, gpio, P9_28(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_28, gpio_pu, P9_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_28, gpio_pd, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_28, pwm, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_28, spi_cs, P9_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_28, pwm2, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P9_28, pruout, P9_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_28, pruin, P9_28(PIN_INPUT | MUX_MODE6))
+
+	/* P9_29 (ZCZ ball B13) mcasp0_fsx (audio) */
+	BONE_PIN(P9_29, default, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_29, gpio, P9_29(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_29, gpio_pu, P9_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_29, gpio_pd, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_29, pwm, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_29, spi, P9_29(PIN_INPUT_PULLUP | MUX_MODE3))
+	BONE_PIN(P9_29, pruout, P9_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_29, pruin, P9_29(PIN_INPUT | MUX_MODE6))
+
+	/* P9_30 (ZCZ ball D12) gpio-hog wl1835 */
+
+	/* P9_31 (ZCZ ball A13) mcasp0_aclkx (audio) */
+	BONE_PIN(P9_31, default, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_31, gpio, P9_31(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_31, gpio_pu, P9_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_31, gpio_pd, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_31, pwm, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_31, spi_sclk, P9_31(PIN_INPUT_PULLUP | MUX_MODE3))
+	BONE_PIN(P9_31, pruout, P9_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_31, pruin, P9_31(PIN_INPUT | MUX_MODE6))
+
+	/* P9_32                VADC */
+
+	/* P9_33 (ZCZ ball C8)  AIN4 */
+
+	/* P9_34                AGND */
+
+	/* P9_35 (ZCZ ball A8)  AIN6 */
+
+	/* P9_36 (ZCZ ball B8)  AIN5 */
+
+	/* P9_37 (ZCZ ball B7)  AIN2 */
+
+	/* P9_38 (ZCZ ball A7)  AIN3 */
+
+	/* P9_39 (ZCZ ball B6)  AIN0 */
+
+	/* P9_40 (ZCZ ball C7)  AIN1 */
+
+	/* P9_41 (ZCZ ball D14) xdma_event_intr1 (gpio0_20) */
+	BONE_PIN(P9_41, default, P9_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_41, gpio, P9_41(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_41, gpio_pu, P9_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_41, gpio_pd, P9_41(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_41, timer, P9_41(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P9_41, pruin, P9_41(PIN_INPUT | MUX_MODE5))
+
+	/* P9_41.1 */
+	/* P9_91 (ZCZ ball D13) mcasp0_axr1 (gpio3_20) */
+	BONE_PIN(P9_91, default, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_91, gpio, P9_91(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_91, gpio_pu, P9_91(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_91, gpio_pd, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_91, eqep, P9_91(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_91, pruout, P9_91(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_91, pruin, P9_91(PIN_INPUT | MUX_MODE6))
+
+	/* P9_42 (ZCZ ball C18) eCAP0_in_PWM0_out (gpio0_7) */
+	BONE_PIN(P9_42, default, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_42, gpio, P9_42(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_42, gpio_pu, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_42, gpio_pd, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_42, pwm, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P9_42, uart, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_42, spi_cs, P9_42(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P9_42, pru_ecap_pwm, P9_42(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P9_42, spi_sclk, P9_42(PIN_INPUT_PULLUP | MUX_MODE4))
+
+	/* P9_42.1 */
+	/* P9_92 (ZCZ ball B12) mcasp0_aclkr (gpio3_18) */
+	BONE_PIN(P9_92, default, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_92, gpio, P9_92(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_92, gpio_pu, P9_92(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_92, gpio_pd, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P9_92, eqep, P9_92(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P9_92, pruout, P9_92(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P9_92, pruin, P9_92(PIN_INPUT | MUX_MODE6))
+
+	/* P9_43                GND */
+
+	/* P9_44                GND */
+
+	/* P9_45                GND */
+
+	/* P9_46                GND */
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+
+	clock-frequency = <100000>;
+	symlink = "bone/i2c/1";
+};
+
+&i2c2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+
+	clock-frequency = <100000>;
+	symlink = "bone/i2c/2";
+};
+
+&uart1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/uart/1";
+};
+
+&uart2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/uart/2";
+};
+
+&uart3 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/uart/3";
+};
+
+&uart4 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/uart/4";
+};
+
+&uart5 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/uart/5";
+};
+
+&dcan0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/can/0";
+};
+
+&dcan1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/can/1";
+};
+
+&eqep0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/eqep/0";
+};
+
+&eqep1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/eqep/1";
+};
+
+&eqep2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+	symlink = "bone/eqep/2";
+};
+
+&epwmss0 {
+	status = "okay";
+};
+
+&epwmss1 {
+	status = "okay";
+};
+
+&epwmss2 {
+	status = "okay";
+};
+
+&ehrpwm0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&ehrpwm1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&ehrpwm2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&ecap0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&ecap1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&ecap2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&spi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+
+	channel@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/0.0";
+
+		reg = <0>;
+		spi-max-frequency = <16000000>;
+		spi-cpha;
+	};
+
+	channel@1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/0.1";
+
+		reg = <1>;
+		spi-max-frequency = <16000000>;
+	};
+};
+
+&spi1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+
+	channel@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/1.0";
+
+		reg = <0>;
+		spi-max-frequency = <16000000>;
+		spi-cpha;
+	};
+
+	channel@1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/1.1";
+
+		reg = <1>;
+		spi-max-frequency = <16000000>;
+	};
+};
+
+/**********************************************************************/
+/* Pin Multiplex Helpers                                              */
+/*                                                                    */
+/* These provide userspace runtime pin configuration for the          */
+/* BeagleBone cape expansion headers                                  */
+/**********************************************************************/
+
+&ocp {
+	/************************/
+	/* P8 Header */
+	/************************/
+
+	/* P8_01                GND */
+
+	/* P8_02                GND */
+
+
+	/* P8_03 (ZCZ ball R9) emmc */
+	P8_03_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_03_default_pin>;
+		pinctrl-1 = <&P8_03_gpio_pin>;
+		pinctrl-2 = <&P8_03_gpio_pu_pin>;
+		pinctrl-3 = <&P8_03_gpio_pd_pin>;
+	};
+
+	/* P8_04 (ZCZ ball T9) emmc */
+	P8_04_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_04_default_pin>;
+		pinctrl-1 = <&P8_04_gpio_pin>;
+		pinctrl-2 = <&P8_04_gpio_pu_pin>;
+		pinctrl-3 = <&P8_04_gpio_pd_pin>;
+	};
+
+	/* P8_05 (ZCZ ball R8) emmc */
+	P8_05_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_05_default_pin>;
+		pinctrl-1 = <&P8_05_gpio_pin>;
+		pinctrl-2 = <&P8_05_gpio_pu_pin>;
+		pinctrl-3 = <&P8_05_gpio_pd_pin>;
+	};
+
+	/* P8_06 (ZCZ ball T8) emmc */
+	P8_06_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_06_default_pin>;
+		pinctrl-1 = <&P8_06_gpio_pin>;
+		pinctrl-2 = <&P8_06_gpio_pu_pin>;
+		pinctrl-3 = <&P8_06_gpio_pd_pin>;
+	};
+
+	/* P8_07 (ZCZ ball R7) */
+	P8_07_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer";
+		pinctrl-0 = <&P8_07_default_pin>;
+		pinctrl-1 = <&P8_07_gpio_pin>;
+		pinctrl-2 = <&P8_07_gpio_pu_pin>;
+		pinctrl-3 = <&P8_07_gpio_pd_pin>;
+		pinctrl-4 = <&P8_07_timer_pin>;
+	};
+
+	/* P8_08 (ZCZ ball T7) */
+	P8_08_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer";
+		pinctrl-0 = <&P8_08_default_pin>;
+		pinctrl-1 = <&P8_08_gpio_pin>;
+		pinctrl-2 = <&P8_08_gpio_pu_pin>;
+		pinctrl-3 = <&P8_08_gpio_pd_pin>;
+		pinctrl-4 = <&P8_08_timer_pin>;
+	};
+
+	/* P8_09 (ZCZ ball T6) */
+	P8_09_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer";
+		pinctrl-0 = <&P8_09_default_pin>;
+		pinctrl-1 = <&P8_09_gpio_pin>;
+		pinctrl-2 = <&P8_09_gpio_pu_pin>;
+		pinctrl-3 = <&P8_09_gpio_pd_pin>;
+		pinctrl-4 = <&P8_09_timer_pin>;
+	};
+
+	/* P8_10 (ZCZ ball U6) */
+	P8_10_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer";
+		pinctrl-0 = <&P8_10_default_pin>;
+		pinctrl-1 = <&P8_10_gpio_pin>;
+		pinctrl-2 = <&P8_10_gpio_pu_pin>;
+		pinctrl-3 = <&P8_10_gpio_pd_pin>;
+		pinctrl-4 = <&P8_10_timer_pin>;
+	};
+
+	/* P8_11 (ZCZ ball R12) */
+	P8_11_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout";
+		pinctrl-0 = <&P8_11_default_pin>;
+		pinctrl-1 = <&P8_11_gpio_pin>;
+		pinctrl-2 = <&P8_11_gpio_pu_pin>;
+		pinctrl-3 = <&P8_11_gpio_pd_pin>;
+		pinctrl-4 = <&P8_11_eqep_pin>;
+		pinctrl-5 = <&P8_11_pruout_pin>;
+	};
+
+	/* P8_12 (ZCZ ball T12) */
+	P8_12_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout";
+		pinctrl-0 = <&P8_12_default_pin>;
+		pinctrl-1 = <&P8_12_gpio_pin>;
+		pinctrl-2 = <&P8_12_gpio_pu_pin>;
+		pinctrl-3 = <&P8_12_gpio_pd_pin>;
+		pinctrl-4 = <&P8_12_eqep_pin>;
+		pinctrl-5 = <&P8_12_pruout_pin>;
+	};
+
+	/* P8_13 (ZCZ ball T10) */
+	P8_13_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P8_13_default_pin>;
+		pinctrl-1 = <&P8_13_gpio_pin>;
+		pinctrl-2 = <&P8_13_gpio_pu_pin>;
+		pinctrl-3 = <&P8_13_gpio_pd_pin>;
+		pinctrl-4 = <&P8_13_pwm_pin>;
+	};
+
+	/* P8_14 (ZCZ ball T11) wl1835: wl_en */
+
+	/* P8_15 (ZCZ ball U13) */
+	P8_15_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pru_ecap_pwm", "pruin";
+		pinctrl-0 = <&P8_15_default_pin>;
+		pinctrl-1 = <&P8_15_gpio_pin>;
+		pinctrl-2 = <&P8_15_gpio_pu_pin>;
+		pinctrl-3 = <&P8_15_gpio_pd_pin>;
+		pinctrl-4 = <&P8_15_eqep_pin>;
+		pinctrl-5 = <&P8_15_pru_ecap_pwm_pin>;
+		pinctrl-6 = <&P8_15_pruin_pin>;
+	};
+
+	/* P8_16 (ZCZ ball V13) */
+	P8_16_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruin";
+		pinctrl-0 = <&P8_16_default_pin>;
+		pinctrl-1 = <&P8_16_gpio_pin>;
+		pinctrl-2 = <&P8_16_gpio_pu_pin>;
+		pinctrl-3 = <&P8_16_gpio_pd_pin>;
+		pinctrl-4 = <&P8_16_eqep_pin>;
+		pinctrl-5 = <&P8_16_pruin_pin>;
+	};
+
+	/* P8_17 (ZCZ ball U12) wl1835: wl_irq */
+
+	/* P8_18 (ZCZ ball V12) */
+	P8_18_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_18_default_pin>;
+		pinctrl-1 = <&P8_18_gpio_pin>;
+		pinctrl-2 = <&P8_18_gpio_pu_pin>;
+		pinctrl-3 = <&P8_18_gpio_pd_pin>;
+	};
+
+	/* P8_19 (ZCZ ball U10) */
+	P8_19_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P8_19_default_pin>;
+		pinctrl-1 = <&P8_19_gpio_pin>;
+		pinctrl-2 = <&P8_19_gpio_pu_pin>;
+		pinctrl-3 = <&P8_19_gpio_pd_pin>;
+		pinctrl-4 = <&P8_19_pwm_pin>;
+	};
+
+	/* P8_20 (ZCZ ball V9) emmc */
+	P8_20_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P8_20_default_pin>;
+		pinctrl-1 = <&P8_20_gpio_pin>;
+		pinctrl-2 = <&P8_20_gpio_pu_pin>;
+		pinctrl-3 = <&P8_20_gpio_pd_pin>;
+		pinctrl-4 = <&P8_20_pruout_pin>;
+		pinctrl-5 = <&P8_20_pruin_pin>;
+	};
+
+	/* P8_21 (ZCZ ball U9) emmc */
+	P8_21_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P8_21_default_pin>;
+		pinctrl-1 = <&P8_21_gpio_pin>;
+		pinctrl-2 = <&P8_21_gpio_pu_pin>;
+		pinctrl-3 = <&P8_21_gpio_pd_pin>;
+		pinctrl-4 = <&P8_21_pruout_pin>;
+		pinctrl-5 = <&P8_21_pruin_pin>;
+	};
+
+	/* P8_22 (ZCZ ball V8) emmc */
+	P8_22_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_22_default_pin>;
+		pinctrl-1 = <&P8_22_gpio_pin>;
+		pinctrl-2 = <&P8_22_gpio_pu_pin>;
+		pinctrl-3 = <&P8_22_gpio_pd_pin>;
+	};
+
+	/* P8_23 (ZCZ ball U8) emmc */
+	P8_23_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_23_default_pin>;
+		pinctrl-1 = <&P8_23_gpio_pin>;
+		pinctrl-2 = <&P8_23_gpio_pu_pin>;
+		pinctrl-3 = <&P8_23_gpio_pd_pin>;
+	};
+
+	/* P8_24 (ZCZ ball V7) emmc */
+	P8_24_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_24_default_pin>;
+		pinctrl-1 = <&P8_24_gpio_pin>;
+		pinctrl-2 = <&P8_24_gpio_pu_pin>;
+		pinctrl-3 = <&P8_24_gpio_pd_pin>;
+	};
+
+	/* P8_25 (ZCZ ball U7) emmc */
+	P8_25_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P8_25_default_pin>;
+		pinctrl-1 = <&P8_25_gpio_pin>;
+		pinctrl-2 = <&P8_25_gpio_pu_pin>;
+		pinctrl-3 = <&P8_25_gpio_pd_pin>;
+	};
+
+	/* P8_26 (ZCZ ball V6) gpio-hog wl1835 */
+
+	/* P8_27 (ZCZ ball U5) hdmi */
+	P8_27_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P8_27_default_pin>;
+		pinctrl-1 = <&P8_27_gpio_pin>;
+		pinctrl-2 = <&P8_27_gpio_pu_pin>;
+		pinctrl-3 = <&P8_27_gpio_pd_pin>;
+		pinctrl-4 = <&P8_27_pruout_pin>;
+		pinctrl-5 = <&P8_27_pruin_pin>;
+	};
+
+	/* P8_28 (ZCZ ball V5) hdmi */
+	P8_28_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P8_28_default_pin>;
+		pinctrl-1 = <&P8_28_gpio_pin>;
+		pinctrl-2 = <&P8_28_gpio_pu_pin>;
+		pinctrl-3 = <&P8_28_gpio_pd_pin>;
+		pinctrl-4 = <&P8_28_pruout_pin>;
+		pinctrl-5 = <&P8_28_pruin_pin>;
+	};
+
+	/* P8_29 (ZCZ ball R5) hdmi */
+	P8_29_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P8_29_default_pin>;
+		pinctrl-1 = <&P8_29_gpio_pin>;
+		pinctrl-2 = <&P8_29_gpio_pu_pin>;
+		pinctrl-3 = <&P8_29_gpio_pd_pin>;
+		pinctrl-4 = <&P8_29_pruout_pin>;
+		pinctrl-5 = <&P8_29_pruin_pin>;
+	};
+
+	/* P8_30 (ZCZ ball R6) hdmi */
+	P8_30_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P8_30_default_pin>;
+		pinctrl-1 = <&P8_30_gpio_pin>;
+		pinctrl-2 = <&P8_30_gpio_pu_pin>;
+		pinctrl-3 = <&P8_30_gpio_pd_pin>;
+		pinctrl-4 = <&P8_30_pruout_pin>;
+		pinctrl-5 = <&P8_30_pruin_pin>;
+	};
+
+	/* P8_31 (ZCZ ball V4) hdmi */
+	P8_31_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "eqep";
+		pinctrl-0 = <&P8_31_default_pin>;
+		pinctrl-1 = <&P8_31_gpio_pin>;
+		pinctrl-2 = <&P8_31_gpio_pu_pin>;
+		pinctrl-3 = <&P8_31_gpio_pd_pin>;
+		pinctrl-4 = <&P8_31_uart_pin>;
+		pinctrl-5 = <&P8_31_eqep_pin>;
+	};
+
+	/* P8_32 (ZCZ ball T5) hdmi */
+	P8_32_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep";
+		pinctrl-0 = <&P8_32_default_pin>;
+		pinctrl-1 = <&P8_32_gpio_pin>;
+		pinctrl-2 = <&P8_32_gpio_pu_pin>;
+		pinctrl-3 = <&P8_32_gpio_pd_pin>;
+		pinctrl-4 = <&P8_32_eqep_pin>;
+	};
+
+	/* P8_33 (ZCZ ball V3) hdmi */
+	P8_33_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep";
+		pinctrl-0 = <&P8_33_default_pin>;
+		pinctrl-1 = <&P8_33_gpio_pin>;
+		pinctrl-2 = <&P8_33_gpio_pu_pin>;
+		pinctrl-3 = <&P8_33_gpio_pd_pin>;
+		pinctrl-4 = <&P8_33_eqep_pin>;
+	};
+
+	/* P8_34 (ZCZ ball U4) hdmi */
+	P8_34_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P8_34_default_pin>;
+		pinctrl-1 = <&P8_34_gpio_pin>;
+		pinctrl-2 = <&P8_34_gpio_pu_pin>;
+		pinctrl-3 = <&P8_34_gpio_pd_pin>;
+		pinctrl-4 = <&P8_34_pwm_pin>;
+	};
+
+	/* P8_35 (ZCZ ball V2) hdmi */
+	P8_35_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep";
+		pinctrl-0 = <&P8_35_default_pin>;
+		pinctrl-1 = <&P8_35_gpio_pin>;
+		pinctrl-2 = <&P8_35_gpio_pu_pin>;
+		pinctrl-3 = <&P8_35_gpio_pd_pin>;
+		pinctrl-4 = <&P8_35_eqep_pin>;
+	};
+
+	/* P8_36 (ZCZ ball U3) hdmi */
+	P8_36_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P8_36_default_pin>;
+		pinctrl-1 = <&P8_36_gpio_pin>;
+		pinctrl-2 = <&P8_36_gpio_pu_pin>;
+		pinctrl-3 = <&P8_36_gpio_pd_pin>;
+		pinctrl-4 = <&P8_36_pwm_pin>;
+	};
+
+	/* P8_37 (ZCZ ball U1) hdmi */
+	P8_37_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "pwm";
+		pinctrl-0 = <&P8_37_default_pin>;
+		pinctrl-1 = <&P8_37_gpio_pin>;
+		pinctrl-2 = <&P8_37_gpio_pu_pin>;
+		pinctrl-3 = <&P8_37_gpio_pd_pin>;
+		pinctrl-4 = <&P8_37_uart_pin>;
+		pinctrl-5 = <&P8_37_pwm_pin>;
+	};
+
+	/* P8_38 (ZCZ ball U2) hdmi */
+	P8_38_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "pwm";
+		pinctrl-0 = <&P8_38_default_pin>;
+		pinctrl-1 = <&P8_38_gpio_pin>;
+		pinctrl-2 = <&P8_38_gpio_pu_pin>;
+		pinctrl-3 = <&P8_38_gpio_pd_pin>;
+		pinctrl-4 = <&P8_38_uart_pin>;
+		pinctrl-5 = <&P8_38_pwm_pin>;
+	};
+
+	/* P8_39 (ZCZ ball T3) hdmi */
+	P8_39_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P8_39_default_pin>;
+		pinctrl-1 = <&P8_39_gpio_pin>;
+		pinctrl-2 = <&P8_39_gpio_pu_pin>;
+		pinctrl-3 = <&P8_39_gpio_pd_pin>;
+		pinctrl-4 = <&P8_39_eqep_pin>;
+		pinctrl-5 = <&P8_39_pruout_pin>;
+		pinctrl-6 = <&P8_39_pruin_pin>;
+	};
+
+	/* P8_40 (ZCZ ball T4) hdmi */
+	P8_40_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P8_40_default_pin>;
+		pinctrl-1 = <&P8_40_gpio_pin>;
+		pinctrl-2 = <&P8_40_gpio_pu_pin>;
+		pinctrl-3 = <&P8_40_gpio_pd_pin>;
+		pinctrl-4 = <&P8_40_eqep_pin>;
+		pinctrl-5 = <&P8_40_pruout_pin>;
+		pinctrl-6 = <&P8_40_pruin_pin>;
+	};
+
+	/* P8_41 (ZCZ ball T1) hdmi */
+	P8_41_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P8_41_default_pin>;
+		pinctrl-1 = <&P8_41_gpio_pin>;
+		pinctrl-2 = <&P8_41_gpio_pu_pin>;
+		pinctrl-3 = <&P8_41_gpio_pd_pin>;
+		pinctrl-4 = <&P8_41_eqep_pin>;
+		pinctrl-5 = <&P8_41_pruout_pin>;
+		pinctrl-6 = <&P8_41_pruin_pin>;
+	};
+
+	/* P8_42 (ZCZ ball T2) hdmi */
+	P8_42_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P8_42_default_pin>;
+		pinctrl-1 = <&P8_42_gpio_pin>;
+		pinctrl-2 = <&P8_42_gpio_pu_pin>;
+		pinctrl-3 = <&P8_42_gpio_pd_pin>;
+		pinctrl-4 = <&P8_42_eqep_pin>;
+		pinctrl-5 = <&P8_42_pruout_pin>;
+		pinctrl-6 = <&P8_42_pruin_pin>;
+	};
+
+	/* P8_43 (ZCZ ball R3) hdmi */
+	P8_43_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P8_43_default_pin>;
+		pinctrl-1 = <&P8_43_gpio_pin>;
+		pinctrl-2 = <&P8_43_gpio_pu_pin>;
+		pinctrl-3 = <&P8_43_gpio_pd_pin>;
+		pinctrl-4 = <&P8_43_pwm_pin>;
+		pinctrl-5 = <&P8_43_pruout_pin>;
+		pinctrl-6 = <&P8_43_pruin_pin>;
+	};
+
+	/* P8_44 (ZCZ ball R4) hdmi */
+	P8_44_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P8_44_default_pin>;
+		pinctrl-1 = <&P8_44_gpio_pin>;
+		pinctrl-2 = <&P8_44_gpio_pu_pin>;
+		pinctrl-3 = <&P8_44_gpio_pd_pin>;
+		pinctrl-4 = <&P8_44_pwm_pin>;
+		pinctrl-5 = <&P8_44_pruout_pin>;
+		pinctrl-6 = <&P8_44_pruin_pin>;
+	};
+
+	/* P8_45 (ZCZ ball R1) hdmi */
+	P8_45_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P8_45_default_pin>;
+		pinctrl-1 = <&P8_45_gpio_pin>;
+		pinctrl-2 = <&P8_45_gpio_pu_pin>;
+		pinctrl-3 = <&P8_45_gpio_pd_pin>;
+		pinctrl-4 = <&P8_45_pwm_pin>;
+		pinctrl-5 = <&P8_45_pruout_pin>;
+		pinctrl-6 = <&P8_45_pruin_pin>;
+	};
+
+	/* P8_46 (ZCZ ball R2) hdmi */
+	P8_46_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P8_46_default_pin>;
+		pinctrl-1 = <&P8_46_gpio_pin>;
+		pinctrl-2 = <&P8_46_gpio_pu_pin>;
+		pinctrl-3 = <&P8_46_gpio_pd_pin>;
+		pinctrl-4 = <&P8_46_pwm_pin>;
+		pinctrl-5 = <&P8_46_pruout_pin>;
+		pinctrl-6 = <&P8_46_pruin_pin>;
+	};
+
+	/************************/
+	/* P9 Header */
+	/************************/
+
+	/* P9_01                GND */
+
+	/* P9_02                GND */
+
+	/* P9_03                3V3 */
+
+	/* P9_04                3V3 */
+
+	/* P9_05                VDD_5V */
+
+	/* P9_06                VDD_5V */
+
+	/* P9_07                SYS_5V */
+
+	/* P9_08                SYS_5V */
+
+	/* P9_09                PWR_BUT */
+
+	/* P9_10                RSTn */
+
+	/* P9_11 (ZCZ ball T17) */
+	P9_11_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart";
+		pinctrl-0 = <&P9_11_default_pin>;
+		pinctrl-1 = <&P9_11_gpio_pin>;
+		pinctrl-2 = <&P9_11_gpio_pu_pin>;
+		pinctrl-3 = <&P9_11_gpio_pd_pin>;
+		pinctrl-4 = <&P9_11_uart_pin>;
+	};
+
+	/* P9_12 (ZCZ ball U18) */
+	P9_12_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P9_12_default_pin>;
+		pinctrl-1 = <&P9_12_gpio_pin>;
+		pinctrl-2 = <&P9_12_gpio_pu_pin>;
+		pinctrl-3 = <&P9_12_gpio_pd_pin>;
+	};
+
+	/* P9_13 (ZCZ ball U17) */
+	P9_13_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart";
+		pinctrl-0 = <&P9_13_default_pin>;
+		pinctrl-1 = <&P9_13_gpio_pin>;
+		pinctrl-2 = <&P9_13_gpio_pu_pin>;
+		pinctrl-3 = <&P9_13_gpio_pd_pin>;
+		pinctrl-4 = <&P9_13_uart_pin>;
+	};
+
+	/* P9_14 (ZCZ ball U14) */
+	P9_14_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P9_14_default_pin>;
+		pinctrl-1 = <&P9_14_gpio_pin>;
+		pinctrl-2 = <&P9_14_gpio_pu_pin>;
+		pinctrl-3 = <&P9_14_gpio_pd_pin>;
+		pinctrl-4 = <&P9_14_pwm_pin>;
+	};
+
+	/* P9_15 (ZCZ ball R13) */
+	P9_15_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P9_15_default_pin>;
+		pinctrl-1 = <&P9_15_gpio_pin>;
+		pinctrl-2 = <&P9_15_gpio_pu_pin>;
+		pinctrl-3 = <&P9_15_gpio_pd_pin>;
+		pinctrl-4 = <&P9_15_pwm_pin>;
+	};
+
+	/* P9_16 (ZCZ ball T14) */
+	P9_16_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P9_16_default_pin>;
+		pinctrl-1 = <&P9_16_gpio_pin>;
+		pinctrl-2 = <&P9_16_gpio_pu_pin>;
+		pinctrl-3 = <&P9_16_gpio_pd_pin>;
+		pinctrl-4 = <&P9_16_pwm_pin>;
+	};
+
+	/* P9_17 (ZCZ ball A16) */
+	P9_17_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "i2c", "pwm", "pru_uart";
+		pinctrl-0 = <&P9_17_default_pin>;
+		pinctrl-1 = <&P9_17_gpio_pin>;
+		pinctrl-2 = <&P9_17_gpio_pu_pin>;
+		pinctrl-3 = <&P9_17_gpio_pd_pin>;
+		pinctrl-4 = <&P9_17_spi_cs_pin>;
+		pinctrl-5 = <&P9_17_i2c_pin>;
+		pinctrl-6 = <&P9_17_pwm_pin>;
+		pinctrl-7 = <&P9_17_pru_uart_pin>;
+	};
+
+	/* P9_18 (ZCZ ball B16) */
+	P9_18_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm", "pru_uart";
+		pinctrl-0 = <&P9_18_default_pin>;
+		pinctrl-1 = <&P9_18_gpio_pin>;
+		pinctrl-2 = <&P9_18_gpio_pu_pin>;
+		pinctrl-3 = <&P9_18_gpio_pd_pin>;
+		pinctrl-4 = <&P9_18_spi_pin>;
+		pinctrl-5 = <&P9_18_i2c_pin>;
+		pinctrl-6 = <&P9_18_pwm_pin>;
+		pinctrl-7 = <&P9_18_pru_uart_pin>;
+	};
+
+	/* P9_19 (ZCZ ball D17) i2c */
+	P9_19_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "can", "i2c", "pru_uart", "timer";
+		pinctrl-0 = <&P9_19_default_pin>;
+		pinctrl-1 = <&P9_19_gpio_pin>;
+		pinctrl-2 = <&P9_19_gpio_pu_pin>;
+		pinctrl-3 = <&P9_19_gpio_pd_pin>;
+		pinctrl-4 = <&P9_19_spi_cs_pin>;
+		pinctrl-5 = <&P9_19_can_pin>;
+		pinctrl-6 = <&P9_19_i2c_pin>;
+		pinctrl-7 = <&P9_19_pru_uart_pin>;
+		pinctrl-8 = <&P9_19_timer_pin>;
+	};
+
+	/* P9_20 (ZCZ ball D18) i2c */
+	P9_20_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "can", "i2c", "pru_uart", "timer";
+		pinctrl-0 = <&P9_20_default_pin>;
+		pinctrl-1 = <&P9_20_gpio_pin>;
+		pinctrl-2 = <&P9_20_gpio_pu_pin>;
+		pinctrl-3 = <&P9_20_gpio_pd_pin>;
+		pinctrl-4 = <&P9_20_spi_cs_pin>;
+		pinctrl-5 = <&P9_20_can_pin>;
+		pinctrl-6 = <&P9_20_i2c_pin>;
+		pinctrl-7 = <&P9_20_pru_uart_pin>;
+		pinctrl-8 = <&P9_20_timer_pin>;
+	};
+
+	/* P9_21 (ZCZ ball B17) */
+	P9_21_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm", "pru_uart";
+		pinctrl-0 = <&P9_21_default_pin>;
+		pinctrl-1 = <&P9_21_gpio_pin>;
+		pinctrl-2 = <&P9_21_gpio_pu_pin>;
+		pinctrl-3 = <&P9_21_gpio_pd_pin>;
+		pinctrl-4 = <&P9_21_spi_pin>;
+		pinctrl-5 = <&P9_21_uart_pin>;
+		pinctrl-6 = <&P9_21_i2c_pin>;
+		pinctrl-7 = <&P9_21_pwm_pin>;
+		pinctrl-8 = <&P9_21_pru_uart_pin>;
+	};
+
+	/* P9_22 (ZCZ ball A17) */
+	P9_22_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_sclk", "uart", "i2c", "pwm", "pru_uart";
+		pinctrl-0 = <&P9_22_default_pin>;
+		pinctrl-1 = <&P9_22_gpio_pin>;
+		pinctrl-2 = <&P9_22_gpio_pu_pin>;
+		pinctrl-3 = <&P9_22_gpio_pd_pin>;
+		pinctrl-4 = <&P9_22_spi_sclk_pin>;
+		pinctrl-5 = <&P9_22_uart_pin>;
+		pinctrl-6 = <&P9_22_i2c_pin>;
+		pinctrl-7 = <&P9_22_pwm_pin>;
+		pinctrl-8 = <&P9_22_pru_uart_pin>;
+	};
+
+	/* P9_23 (ZCZ ball V14) */
+	P9_23_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P9_23_default_pin>;
+		pinctrl-1 = <&P9_23_gpio_pin>;
+		pinctrl-2 = <&P9_23_gpio_pu_pin>;
+		pinctrl-3 = <&P9_23_gpio_pd_pin>;
+		pinctrl-4 = <&P9_23_pwm_pin>;
+	};
+
+	/* P9_24 (ZCZ ball D15) */
+	P9_24_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pru_uart", "pruin";
+		pinctrl-0 = <&P9_24_default_pin>;
+		pinctrl-1 = <&P9_24_gpio_pin>;
+		pinctrl-2 = <&P9_24_gpio_pu_pin>;
+		pinctrl-3 = <&P9_24_gpio_pd_pin>;
+		pinctrl-4 = <&P9_24_uart_pin>;
+		pinctrl-5 = <&P9_24_can_pin>;
+		pinctrl-6 = <&P9_24_i2c_pin>;
+		pinctrl-7 = <&P9_24_pru_uart_pin>;
+		pinctrl-8 = <&P9_24_pruin_pin>;
+	};
+
+	/* P9_25 (ZCZ ball A14) audio */
+	P9_25_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P9_25_default_pin>;
+		pinctrl-1 = <&P9_25_gpio_pin>;
+		pinctrl-2 = <&P9_25_gpio_pu_pin>;
+		pinctrl-3 = <&P9_25_gpio_pd_pin>;
+		pinctrl-4 = <&P9_25_eqep_pin>;
+		pinctrl-5 = <&P9_25_pruout_pin>;
+		pinctrl-6 = <&P9_25_pruin_pin>;
+	};
+
+	/* P9_26 (ZCZ ball D16) */
+	P9_26_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pru_uart", "pruin";
+		pinctrl-0 = <&P9_26_default_pin>;
+		pinctrl-1 = <&P9_26_gpio_pin>;
+		pinctrl-2 = <&P9_26_gpio_pu_pin>;
+		pinctrl-3 = <&P9_26_gpio_pd_pin>;
+		pinctrl-4 = <&P9_26_uart_pin>;
+		pinctrl-5 = <&P9_26_can_pin>;
+		pinctrl-6 = <&P9_26_i2c_pin>;
+		pinctrl-7 = <&P9_26_pru_uart_pin>;
+		pinctrl-8 = <&P9_26_pruin_pin>;
+	};
+
+	/* P9_27 (ZCZ ball C13) */
+	P9_27_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P9_27_default_pin>;
+		pinctrl-1 = <&P9_27_gpio_pin>;
+		pinctrl-2 = <&P9_27_gpio_pu_pin>;
+		pinctrl-3 = <&P9_27_gpio_pd_pin>;
+		pinctrl-4 = <&P9_27_eqep_pin>;
+		pinctrl-5 = <&P9_27_pruout_pin>;
+		pinctrl-6 = <&P9_27_pruin_pin>;
+	};
+
+	/* P9_28 (ZCZ ball C12) audio */
+	P9_28_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "pwm", "pwm2", "pruout", "pruin";
+		pinctrl-0 = <&P9_28_default_pin>;
+		pinctrl-1 = <&P9_28_gpio_pin>;
+		pinctrl-2 = <&P9_28_gpio_pu_pin>;
+		pinctrl-3 = <&P9_28_gpio_pd_pin>;
+		pinctrl-4 = <&P9_28_spi_cs_pin>;
+		pinctrl-5 = <&P9_28_pwm_pin>;
+		pinctrl-6 = <&P9_28_pwm2_pin>;
+		pinctrl-7 = <&P9_28_pruout_pin>;
+		pinctrl-8 = <&P9_28_pruin_pin>;
+	};
+
+	/* P9_29 (ZCZ ball B13) audio */
+	P9_29_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P9_29_default_pin>;
+		pinctrl-1 = <&P9_29_gpio_pin>;
+		pinctrl-2 = <&P9_29_gpio_pu_pin>;
+		pinctrl-3 = <&P9_29_gpio_pd_pin>;
+		pinctrl-4 = <&P9_29_spi_pin>;
+		pinctrl-5 = <&P9_29_pwm_pin>;
+		pinctrl-6 = <&P9_29_pruout_pin>;
+		pinctrl-7 = <&P9_29_pruin_pin>;
+	};
+
+	/* P9_30 (ZCZ ball D12) gpio-hog wl1835 */
+
+	/* P9_31 (ZCZ ball A13) audio */
+	P9_31_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_sclk", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P9_31_default_pin>;
+		pinctrl-1 = <&P9_31_gpio_pin>;
+		pinctrl-2 = <&P9_31_gpio_pu_pin>;
+		pinctrl-3 = <&P9_31_gpio_pd_pin>;
+		pinctrl-4 = <&P9_31_spi_sclk_pin>;
+		pinctrl-5 = <&P9_31_pwm_pin>;
+		pinctrl-6 = <&P9_31_pruout_pin>;
+		pinctrl-7 = <&P9_31_pruin_pin>;
+	};
+
+	/* P9_32                VADC */
+
+	/* P9_33 (ZCZ ball C8)  AIN4 */
+
+	/* P9_34                AGND */
+
+	/* P9_35 (ZCZ ball A8)  AIN6 */
+
+	/* P9_36 (ZCZ ball B8)  AIN5 */
+
+	/* P9_37 (ZCZ ball B7)  AIN2 */
+
+	/* P9_38 (ZCZ ball A7)  AIN3 */
+
+	/* P9_39 (ZCZ ball B6)  AIN0 */
+
+	/* P9_40 (ZCZ ball C7)  AIN1 */
+
+	/* P9_41 (ZCZ ball D14) */
+	P9_41_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "timer", "pruin";
+		pinctrl-0 = <&P9_41_default_pin>;
+		pinctrl-1 = <&P9_41_gpio_pin>;
+		pinctrl-2 = <&P9_41_gpio_pu_pin>;
+		pinctrl-3 = <&P9_41_gpio_pd_pin>;
+		pinctrl-4 = <&P9_41_timer_pin>;
+		pinctrl-5 = <&P9_41_pruin_pin>;
+	};
+
+	/* P9_41.1 */
+	/* P9_91 (ZCZ ball D13) */
+	P9_91_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P9_91_default_pin>;
+		pinctrl-1 = <&P9_91_gpio_pin>;
+		pinctrl-2 = <&P9_91_gpio_pu_pin>;
+		pinctrl-3 = <&P9_91_gpio_pd_pin>;
+		pinctrl-4 = <&P9_91_eqep_pin>;
+		pinctrl-5 = <&P9_91_pruout_pin>;
+		pinctrl-6 = <&P9_91_pruin_pin>;
+	};
+
+	/* P9_42 (ZCZ ball C18) */
+	P9_42_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "spi_sclk", "uart", "pwm", "pru_ecap_pwm";
+		pinctrl-0 = <&P9_42_default_pin>;
+		pinctrl-1 = <&P9_42_gpio_pin>;
+		pinctrl-2 = <&P9_42_gpio_pu_pin>;
+		pinctrl-3 = <&P9_42_gpio_pd_pin>;
+		pinctrl-4 = <&P9_42_spi_cs_pin>;
+		pinctrl-5 = <&P9_42_spi_sclk_pin>;
+		pinctrl-6 = <&P9_42_uart_pin>;
+		pinctrl-7 = <&P9_42_pwm_pin>;
+		pinctrl-8 = <&P9_42_pru_ecap_pwm_pin>;
+	};
+
+	/* P9_42.1 */
+	/* P9_92 (ZCZ ball B12) */
+	P9_92_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P9_92_default_pin>;
+		pinctrl-1 = <&P9_92_gpio_pin>;
+		pinctrl-2 = <&P9_92_gpio_pu_pin>;
+		pinctrl-3 = <&P9_92_gpio_pd_pin>;
+		pinctrl-4 = <&P9_92_eqep_pin>;
+		pinctrl-5 = <&P9_92_pruout_pin>;
+		pinctrl-6 = <&P9_92_pruin_pin>;
+	};
+
+	/* P9_43                GND */
+
+	/* P9_44                GND */
+
+	/* P9_45                GND */
+
+	/* P9_46                GND */
+
+	cape-universal {
+		compatible = "gpio-of-helper";
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <>;
+
+		P8_03 {
+			gpio-name = "P8_03";
+			gpio = <&gpio1 6 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_04 {
+			gpio-name = "P8_04";
+			gpio = <&gpio1 7 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_05 {
+			gpio-name = "P8_05";
+			gpio = <&gpio1 2 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_06 {
+			gpio-name = "P8_06";
+			gpio = <&gpio1 3 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_07 {
+			gpio-name = "P8_07";
+			gpio = <&gpio2 2 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_08 {
+			gpio-name = "P8_08";
+			gpio = <&gpio2 3 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_09 {
+			gpio-name = "P8_09";
+			gpio = <&gpio2 5 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_10 {
+			gpio-name = "P8_10";
+			gpio = <&gpio2 4 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_11 {
+			gpio-name = "P8_11";
+			gpio = <&gpio1 13 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_12 {
+			gpio-name = "P8_12";
+			gpio = <&gpio1 12 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_13 {
+			gpio-name = "P8_13";
+			gpio = <&gpio0 23 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_15 {
+			gpio-name = "P8_15";
+			gpio = <&gpio1 15 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_16 {
+			gpio-name = "P8_16";
+			gpio = <&gpio1 14 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_18 {
+			gpio-name = "P8_18";
+			gpio = <&gpio2 1 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_19 {
+			gpio-name = "P8_19";
+			gpio = <&gpio0 22 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_20 {
+			gpio-name = "P8_20";
+			gpio = <&gpio1 31 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_21 {
+			gpio-name = "P8_21";
+			gpio = <&gpio1 30 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_22 {
+			gpio-name = "P8_22";
+			gpio = <&gpio1 5 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_23 {
+			gpio-name = "P8_23";
+			gpio = <&gpio1 4 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_24 {
+			gpio-name = "P8_24";
+			gpio = <&gpio1 1 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_25 {
+			gpio-name = "P8_25";
+			gpio = <&gpio1 0 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_27 {
+			gpio-name = "P8_27";
+			gpio = <&gpio2 22 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_28 {
+			gpio-name = "P8_28";
+			gpio = <&gpio2 24 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_29 {
+			gpio-name = "P8_29";
+			gpio = <&gpio2 23 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_30 {
+			gpio-name = "P8_30";
+			gpio = <&gpio2 25 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_31 {
+			gpio-name = "P8_31";
+			gpio = <&gpio0 10 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_32 {
+			gpio-name = "P8_32";
+			gpio = <&gpio0 11 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_33 {
+			gpio-name = "P8_33";
+			gpio = <&gpio0 9 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_34 {
+			gpio-name = "P8_34";
+			gpio = <&gpio2 17 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_35 {
+			gpio-name = "P8_35";
+			gpio = <&gpio0 8 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_36 {
+			gpio-name = "P8_36";
+			gpio = <&gpio2 16 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_37 {
+			gpio-name = "P8_37";
+			gpio = <&gpio2 14 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_38 {
+			gpio-name = "P8_38";
+			gpio = <&gpio2 15 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_39 {
+			gpio-name = "P8_39";
+			gpio = <&gpio2 12 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_40 {
+			gpio-name = "P8_40";
+			gpio = <&gpio2 13 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_41 {
+			gpio-name = "P8_41";
+			gpio = <&gpio2 10 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_42 {
+			gpio-name = "P8_42";
+			gpio = <&gpio2 11 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_43 {
+			gpio-name = "P8_43";
+			gpio = <&gpio2 8 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_44 {
+			gpio-name = "P8_44";
+			gpio = <&gpio2 9 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_45 {
+			gpio-name = "P8_45";
+			gpio = <&gpio2 6 0>;
+			input;
+			dir-changeable;
+		};
+
+		P8_46 {
+			gpio-name = "P8_46";
+			gpio = <&gpio2 7 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_11 {
+			gpio-name = "P9_11";
+			gpio = <&gpio0 30 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_12 {
+			gpio-name = "P9_12";
+			gpio = <&gpio1 28 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_13 {
+			gpio-name = "P9_13";
+			gpio = <&gpio0 31 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_14 {
+			gpio-name = "P9_14";
+			gpio = <&gpio1 18 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_15 {
+			gpio-name = "P9_15";
+			gpio = <&gpio1 16 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_16 {
+			gpio-name = "P9_16";
+			gpio = <&gpio1 19 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_17 {
+			gpio-name = "P9_17";
+			gpio = <&gpio0 5 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_18 {
+			gpio-name = "P9_18";
+			gpio = <&gpio0 4 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_19 {
+			gpio-name = "P9_19";
+			gpio = <&gpio0 13 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_20 {
+			gpio-name = "P9_20";
+			gpio = <&gpio0 12 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_21 {
+			gpio-name = "P9_21";
+			gpio = <&gpio0 3 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_22 {
+			gpio-name = "P9_22";
+			gpio = <&gpio0 2 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_23 {
+			gpio-name = "P9_23";
+			gpio = <&gpio1 17 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_24 {
+			gpio-name = "P9_24";
+			gpio = <&gpio0 15 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_25 {
+			gpio-name = "P9_25";
+			gpio = <&gpio3 21 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_26 {
+			gpio-name = "P9_26";
+			gpio = <&gpio0 14 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_27 {
+			gpio-name = "P9_27";
+			gpio = <&gpio3 19 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_28 {
+			gpio-name = "P9_28";
+			gpio = <&gpio3 17 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_29 {
+			gpio-name = "P9_29";
+			gpio = <&gpio3 15 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_31 {
+			gpio-name = "P9_31";
+			gpio = <&gpio3 14 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_41 {
+			gpio-name = "P9_41";
+			gpio = <&gpio0 20 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_91 {
+			gpio-name = "P9_91";
+			gpio = <&gpio3 20 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_42 {
+			gpio-name = "P9_42";
+			gpio = <&gpio0 7 0>;
+			input;
+			dir-changeable;
+		};
+
+		P9_92 {
+			gpio-name = "P9_92";
+			gpio = <&gpio3 18 0>;
+			input;
+			dir-changeable;
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-bonegreen-wireless.dts b/arch/arm/boot/dts/am335x-bonegreen-wireless.dts
--- a/arch/arm/boot/dts/am335x-bonegreen-wireless.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-bonegreen-wireless.dts	2024-01-28 14:01:31.236353764 -0500
@@ -13,6 +13,12 @@
 	model = "TI AM335x BeagleBone Green Wireless";
 	compatible = "ti,am335x-bone-green-wireless", "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
 
+	chosen {
+		base_dtb = "am335x-bonegreen-wireless.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+		wl1835_bt = "S3-texas-300000";
+	};
+
 	wlan_en_reg: fixedregulator@2 {
 		compatible = "regulator-fixed";
 		regulator-name = "wlan-en-regulator";
@@ -24,16 +30,67 @@
 		gpio = <&gpio0 26 0>;
 		enable-active-high;
 	};
+
+	leds {
+		pinctrl-names = "default";
+		//pinctrl-0 = <&user_leds_s0>;
+		pinctrl-0 = <&user_leds_s0 &bt_pins>;
+
+		compatible = "gpio-leds";
+
+		led2 {
+			label = "beaglebone:green:usr0";
+			gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+
+		led3 {
+			label = "beaglebone:green:usr1";
+			gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led4 {
+			label = "beaglebone:green:usr2";
+			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "cpu0";
+			default-state = "off";
+		};
+
+		led5 {
+			label = "beaglebone:green:usr3";
+			gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc1";
+			default-state = "off";
+		};
+
+		wl18xx_bt_en: led7 {
+			label = "wl18xx_bt_en";
+			gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
 };
 
 &am33xx_pinmux {
-	bt_pins: pinmux_bt_pins {
+	user_leds_s0: user-leds-s0-pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gpmc_a5.gpio1_21 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_a6.gpio1_22 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gpmc_a7.gpio1_23 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_a8.gpio1_24 */
+		>;
+	};
+
+	bt_pins: bt-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_ad12.gpio1_28 BT_EN */
 		>;
 	};
 
-	mmc3_pins: pinmux_mmc3_pins {
+	mmc3_pins: mmc3-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLUP, MUX_MODE3)	/* gpmc_ad12.mmc2_dat0 */
 			AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLUP, MUX_MODE3)	/* gpmc_ad13.mmc2_dat1 */
@@ -44,7 +101,7 @@
 		>;
 	};
 
-	uart3_pins: pinmux_uart3_pins {
+	uart3_pins: uart3-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1)	/* gmii1_rxd3.uart3_rxd */
 			AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1)	/* gmii1_rxd2.uart3_txd */
@@ -53,7 +110,7 @@
 		>;
 	};
 
-	wl18xx_pins: pinmux_wl18xx_pins {
+	wl18xx_pins: wl18xx-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gpmc_ad10.gpio0_26 WL_EN */
 			AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT_PULLDOWN, MUX_MODE7)	/* gpmc_ad11.gpio0_27 WL_IRQ */
@@ -63,6 +120,9 @@
 };
 
 &mac_sw {
+	/delete-property/pinctrl-names;
+	/delete-property/pinctrl-0;
+	/delete-property/pinctrl-1;
 	status = "disabled";
 };
 
@@ -91,13 +151,14 @@
 
 &uart3 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&uart3_pins &bt_pins>;
+	pinctrl-0 = <&uart3_pins>;
+	//pinctrl-0 = <&uart3_pins &bt_pins>;
 	status = "okay";
 
-	bluetooth {
-		compatible = "ti,wl1835-st";
-		enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
-	};
+	//bluetooth {
+	//	compatible = "ti,wl1835-st";
+	//	enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+	//};
 };
 
 &gpio1 {
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-bonegreen-wireless-uboot-univ.dts b/arch/arm/boot/dts/am335x-bonegreen-wireless-uboot-univ.dts
--- a/arch/arm/boot/dts/am335x-bonegreen-wireless-uboot-univ.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-bonegreen-wireless-uboot-univ.dts	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-bone-common.dtsi"
+#include "am335x-bonegreen-wireless-common-univ.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	model = "TI AM335x BeagleBone Green Wireless";
+	compatible = "ti,am335x-bone-green-wireless", "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+
+	chosen {
+		base_dtb = "am335x-bonegreen-wireless-uboot-univ.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
+};
+
+&ldo3_reg {
+	regulator-min-microvolt = <1800000>;
+	regulator-max-microvolt = <1800000>;
+	regulator-always-on;
+};
+
+&mmc1 {
+	vmmc-supply = <&vmmcsd_fixed>;
+};
+
+&gpio1 {
+	ls-buf-en-hog {
+		gpio-hog;
+		gpios = <29 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "LS_BUF_EN";
+	};
+};
+
+/* BT_AUD_OUT from wl1835 has to be pulled low when WL_EN is activated.*/
+/* in case it isn't, wilink8 ends up in one of the test modes that     */
+/* intruces various issues (elp wkaeup timeouts etc.)                  */
+/* On the BBGW this pin is routed through the level shifter (U21) that */
+/* introduces a pullup on the line and wilink8 ends up in a bad state. */
+/* use a gpio hog to force this pin low. An alternative may be adding  */
+/* an external pulldown on U21 pin 4.                                  */
+
+&gpio3 {
+	bt-aud-in-hog {
+		gpio-hog;
+		gpios = <16 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "MCASP0_AHCLKR";
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
--- a/arch/arm/boot/dts/am335x-evmsk.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-evmsk.dts	2024-01-28 14:01:31.236353764 -0500
@@ -29,6 +29,11 @@
 		reg = <0x80000000 0x10000000>; /* 256 MB */
 	};
 
+	aliases {
+		serial0 = &uart0;
+		serial1 = &pruss_uart;
+	};
+
 	chosen {
 		stdout-path = &uart0;
 	};
@@ -441,6 +446,22 @@
 			AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT_PULLUP, MUX_MODE7) /* gpmc_csn0.gpio1_29 */
 		>;
 	};
+
+	pruss_uart_pins: pruss_uart_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLDOWN, MUX_MODE4) /* spi0_sclk.pr1_uart0_cts_n */
+			AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT_PULLDOWN, MUX_MODE4) /* spi0_d0.pr1_uart0_rts_n */
+			AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE4) /* spi0_d1.pr1_uart0_rxd */
+			AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_OUTPUT_PULLUP, MUX_MODE4) /* spi0_cs9.pr1_uart0_txd */
+		>;
+	};
+};
+
+&pruss_uart {
+	interrupts = <6 2 2>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pruss_uart_pins>;
+	status = "okay";
 };
 
 &uart0 {
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-osd3358-sm-red.dts b/arch/arm/boot/dts/am335x-osd3358-sm-red.dts
--- a/arch/arm/boot/dts/am335x-osd3358-sm-red.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-osd3358-sm-red.dts	2024-01-28 14:01:31.236353764 -0500
@@ -10,13 +10,16 @@
 
 #include "am33xx.dtsi"
 #include "am335x-osd335x-common.dtsi"
-#include <dt-bindings/interrupt-controller/irq.h>
-
-#include <dt-bindings/display/tda998x.h>
+#include "am335x-boneblack-hdmi.dtsi"
 
 / {
 	model = "Octavo Systems OSD3358-SM-RED";
 	compatible = "oct,osd3358-sm-refdesign", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+
+	chosen {
+		base_dtb = "am335x-osd3358-sm-red.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
 };
 
 &ldo3_reg {
@@ -33,48 +36,7 @@
 	status = "okay";
 };
 
-&lcdc {
-	status = "okay";
-
-	/* If you want to get 24 bit RGB and 16 BGR mode instead of
-	 * current 16 bit RGB and 24 BGR modes, set the propety
-	 * below to "crossed" and uncomment the video-ports -property
-	 * in tda19988 node.
-	 * AM335x errata for wiring:
-	 * https://www.ti.com/lit/er/sprz360i/sprz360i.pdf
-	 */
-
-	blue-and-red-wiring = "straight";
-
-	port {
-		lcdc_0: endpoint {
-			remote-endpoint = <&hdmi_0>;
-		};
-	};
-};
-
 &i2c0 {
-	tda19988: hdmi-encoder@70 {
-		compatible = "nxp,tda998x";
-		reg = <0x70>;
-
-		pinctrl-names = "default", "off";
-		pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
-		pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
-
-		/* Convert 24bit BGR to RGB, e.g. cross red and blue wiring */
-		/* video-ports = <0x234501>; */
-
-		#sound-dai-cells = <0>;
-		audio-ports = <	TDA998x_I2S	0x03>;
-
-		port {
-			hdmi_0: endpoint {
-				remote-endpoint = <&lcdc_0>;
-			};
-		};
-	};
-
 	mpu9250: imu@68 {
 		compatible = "invensense,mpu6050";
 		reg = <0x68>;
@@ -101,51 +63,7 @@
 	};
 };
 
-&mcasp0 {
-	#sound-dai-cells = <0>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&mcasp0_pins>;
-	status = "okay";
-	op-mode = <0>;	/* MCASP_IIS_MODE */
-	tdm-slots = <2>;
-	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
-			0 0 1 0
-		>;
-	tx-num-evt = <32>;
-	rx-num-evt = <32>;
-};
-
 / {
-	clk_mcasp0_fixed: clk-mcasp0-fixed {
-		#clock-cells = <0>;
-		compatible = "fixed-clock";
-		clock-frequency = <24576000>;
-	};
-
-	clk_mcasp0: clk-mcasp0 {
-		#clock-cells = <0>;
-		compatible = "gpio-gate-clock";
-		clocks = <&clk_mcasp0_fixed>;
-		enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
-	};
-
-	sound {
-		compatible = "simple-audio-card";
-		simple-audio-card,name = "TI BeagleBone Black";
-		simple-audio-card,format = "i2s";
-		simple-audio-card,bitclock-master = <&dailink0_master>;
-		simple-audio-card,frame-master = <&dailink0_master>;
-
-		dailink0_master: simple-audio-card,cpu {
-			sound-dai = <&mcasp0>;
-			clocks = <&clk_mcasp0>;
-		};
-
-		simple-audio-card,codec {
-			sound-dai = <&tda19988>;
-		};
-	};
-
 	chosen {
 		stdout-path = &uart0;
 	};
@@ -194,70 +112,25 @@
 };
 
 &am33xx_pinmux {
-	pinctrl-names = "default";
-	pinctrl-0 = <&clkout2_pin>;
-
-	nxp_hdmi_bonelt_pins: nxp-hdmi-bonelt-pins {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
-		>;
-	};
-
-	nxp_hdmi_bonelt_off_pins: nxp-hdmi-bonelt-off-pins {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE3)
-		>;
-	};
-
-	mcasp0_pins: mcasp0-pins {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLUP, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
-			AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT_PULLUP, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a11.GPIO1_27 */
-		>;
-	};
-
-	flash_enable: flash-enable {
+	flash_enable: flash-enable-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* rmii1_ref_clk.gpio0_29 */
 		>;
 	};
 
-	imu_interrupt: imu-interrupt {
+	imu_interrupt: imu-interrupt-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MII1_RX_ER, PIN_INPUT_PULLDOWN, MUX_MODE7)	/* mii1_rx_er.gpio3_2 */
 		>;
 	};
 
-	ethernet_interrupt: ethernet-interrupt{
+	ethernet_interrupt: ethernet-interrupt-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLDOWN, MUX_MODE7)	/* mii1_col.gpio3_0 */
 		>;
 	};
 
-	user_leds_s0: user-leds-s0 {
+	user_leds_s0: user-leds-s0-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gpmc_a5.gpio1_21 */
 			AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_a6.gpio1_22 */
@@ -280,13 +153,7 @@
 		>;
 	};
 
-	clkout2_pin: pinmux-clkout2-pin {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE3)	/* xdma_event_intr1.clkout2 */
-		>;
-	};
-
-	cpsw_default: cpsw-default {
+	cpsw_default: cpsw-default-pins {
 		pinctrl-single,pins = <
 			/* Slave 1 */
 			AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
@@ -304,7 +171,7 @@
 		>;
 	};
 
-	cpsw_sleep: cpsw-sleep {
+	cpsw_sleep: cpsw-sleep-pins {
 		pinctrl-single,pins = <
 			/* Slave 1 reset value */
 			AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
@@ -322,7 +189,7 @@
 		>;
 	};
 
-	davinci_mdio_default: davinci-mdio-default {
+	davinci_mdio_default: davinci-mdio-default-pins {
 		pinctrl-single,pins = <
 			/* MDIO */
 			AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLUP | SLEWCTRL_FAST, MUX_MODE0)
@@ -330,7 +197,7 @@
 		>;
 	};
 
-	davinci_mdio_sleep: davinci-mdio-sleep {
+	davinci_mdio_sleep: davinci-mdio-sleep-pins {
 		pinctrl-single,pins = <
 			/* MDIO reset value */
 			AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT_PULLDOWN, MUX_MODE7)
@@ -372,6 +239,7 @@
 	pinctrl-0 = <&uart0_pins>;
 
 	status = "okay";
+	symlink = "bone/uart/0";
 };
 
 &usb0 {
@@ -389,6 +257,7 @@
 	pinctrl-0 = <&i2c2_pins>;
 	status = "okay";
 	clock-frequency = <100000>;
+	symlink = "bone/i2c/2";
 };
 
 &cpsw_port1 {
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-osd335x-common.dtsi b/arch/arm/boot/dts/am335x-osd335x-common.dtsi
--- a/arch/arm/boot/dts/am335x-osd335x-common.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-osd335x-common.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -29,6 +29,7 @@
 	* EFUSE_SMA register reads as all zeros).
 	*/
 	oppnitro-1000000000 {
+		/* OPP Nitro */
 		opp-supported-hw = <0x06 0x0100>;
 	};
 };
@@ -48,6 +49,7 @@
 
 	status = "okay";
 	clock-frequency = <400000>;
+	symlink = "bone/i2c/0";
 
 	tps: tps@24 {
 		reg = <0x24>;
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-pocketbeagle.dts b/arch/arm/boot/dts/am335x-pocketbeagle.dts
--- a/arch/arm/boot/dts/am335x-pocketbeagle.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-pocketbeagle.dts	2024-01-28 14:01:31.236353764 -0500
@@ -8,6 +8,8 @@
 
 #include "am33xx.dtsi"
 #include "am335x-osd335x-common.dtsi"
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/board/am335x-bone-pins.h>
 
 / {
 	model = "TI AM335x PocketBeagle";
@@ -15,6 +17,8 @@
 
 	chosen {
 		stdout-path = &uart0;
+		base_dtb = "am335x-pocketbeagle.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
 	};
 
 	leds {
@@ -23,29 +27,37 @@
 
 		compatible = "gpio-leds";
 
-		usr0 {
+		led-usr0 {
 			label = "beaglebone:green:usr0";
+			color = <LED_COLOR_ID_BLUE>;
+			function = LED_FUNCTION_HEARTBEAT;
 			gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "heartbeat";
 			default-state = "off";
 		};
 
-		usr1 {
+		led-usr1 {
 			label = "beaglebone:green:usr1";
+			color = <LED_COLOR_ID_BLUE>;
+			function = LED_FUNCTION_DISK_ACTIVITY;
 			gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "mmc0";
 			default-state = "off";
 		};
 
-		usr2 {
+		led-usr2 {
 			label = "beaglebone:green:usr2";
+			color = <LED_COLOR_ID_BLUE>;
+			function = LED_FUNCTION_CPU;
 			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "cpu0";
 			default-state = "off";
 		};
 
-		usr3 {
+		led-usr3 {
 			label = "beaglebone:green:usr3";
+			color = <LED_COLOR_ID_BLUE>;
+			function = LED_FUNCTION_INDICATOR;
 			gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
 			default-state = "off";
 		};
@@ -112,7 +124,7 @@
 		"P2.24",
 		"P2.33",
 		"P2.22",
-		"P2.18",
+		"P2.18 [PRU0.15i]",
 		"NC",
 		"NC",
 		"P2.01 [PWM1A]",
@@ -204,150 +216,24 @@
 };
 
 &am33xx_pinmux {
-
-	compatible = "pinconf-single";
-	pinctrl-names = "default";
-
-	pinctrl-0 =   < &P2_03_gpio &P1_34_gpio &P2_19_gpio &P2_24_gpio
-			&P2_33_gpio &P2_22_gpio &P2_18_gpio &P2_10_gpio
-			&P2_06_gpio &P2_04_gpio &P2_02_gpio &P2_08_gpio
-			&P2_17_gpio >;
-
-	/* P2_03 (ZCZ ball T10) gpio0_23 0x824 PIN 9 */
-	P2_03_gpio: pinmux_P2_03_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_INPUT_PULLUP, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x10  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x10  0x00  0x10  0x18>;
-	};
-
-	/* P1_34 (ZCZ ball T11) gpio0_26 0x828 PIN 10 */
-	P1_34_gpio: pinmux_P1_34_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_INPUT_PULLUP, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x10  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x10  0x00  0x10  0x18>;
-	};
-
-	/* P2_19 (ZCZ ball U12) gpio0_27 0x82c PIN 11 */
-	P2_19_gpio: pinmux_P2_19_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT_PULLUP, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x10  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x10  0x00  0x10  0x18>;
-	};
-
-	/* P2_24 (ZCZ ball T12) gpio1_12 0x830 PIN 12 */
-	P2_24_gpio: pinmux_P2_24_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLUP, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x10  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x10  0x00  0x10  0x18>;
-	};
-
-	/* P2_33 (ZCZ ball R12) gpio1_13 0x834 PIN 13 */
-	P2_33_gpio: pinmux_P2_33_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLUP, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x10  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x10  0x00  0x10  0x18>;
-	};
-
-	/* P2_22 (ZCZ ball V13) gpio1_14 0x838 PIN 14 */
-	P2_22_gpio: pinmux_P2_22_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT_PULLUP, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x10  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x10  0x00  0x10  0x18>;
-	};
-
-	/* P2_18 (ZCZ ball U13) gpio1_15 0x83c PIN 15 */
-	P2_18_gpio: pinmux_P2_18_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLUP, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x10  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x10  0x00  0x10  0x18>;
-	};
-
-	/* P2_10 (ZCZ ball R14) gpio1_20 0x850 PIN 20 */
-	P2_10_gpio: pinmux_P2_10_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_A4, PIN_INPUT_PULLUP, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x10  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x10  0x00  0x10  0x18>;
-	};
-
-	/* P2_06 (ZCZ ball U16) gpio1_25 0x864 PIN 25 */
-	P2_06_gpio: pinmux_P2_06_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_INPUT_PULLUP, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x10  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x10  0x00  0x10  0x18>;
-	};
-
-	/* P2_04 (ZCZ ball T16) gpio1_26 0x868 PIN 26 */
-	P2_04_gpio: pinmux_P2_04_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT_PULLUP, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x10  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x10  0x00  0x10  0x18>;
-	};
-
-	/* P2_02 (ZCZ ball V17) gpio1_27 0x86c PIN 27 */
-	P2_02_gpio: pinmux_P2_02_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_INPUT_PULLUP, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x10  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x10  0x00  0x10  0x18>;
-	};
-
-	/* P2_08 (ZCZ ball U18) gpio1_28 0x878 PIN 30 */
-	P2_08_gpio: pinmux_P2_08_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT_PULLDOWN, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x00  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x00  0x00  0x10  0x18>;
-	};
-
-	/* P2_17 (ZCZ ball V12) gpio2_1 0x88c PIN 35 */
-	P2_17_gpio: pinmux_P2_17_gpio {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_CLK, PIN_INPUT_PULLUP, MUX_MODE7)
-		>;
-		pinctrl-single,bias-pullup   =   < 0x10  0x10  0x00  0x18>;
-		pinctrl-single,bias-pulldown   = < 0x10  0x00  0x10  0x18>;
-	};
-
-	i2c2_pins: pinmux-i2c2-pins {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLUP, MUX_MODE3)	/* (D17) uart1_rtsn.I2C2_SCL */
-			AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3)	/* (D18) uart1_ctsn.I2C2_SDA */
-		>;
-	};
-
-	ehrpwm0_pins: pinmux-ehrpwm0-pins {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE1)	/* (A13) mcasp0_aclkx.ehrpwm0A */
-		>;
-	};
-
-	ehrpwm1_pins: pinmux-ehrpwm1-pins {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT_PULLDOWN, MUX_MODE6)	/* (U14) gpmc_a2.ehrpwm1A */
-		>;
-	};
+//	i2c2_pins: pinmux-i2c2-pins {
+//		pinctrl-single,pins = <
+//			AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_INPUT_PULLUP, MUX_MODE3)	/* (D17) uart1_rtsn.I2C2_SCL */
+//			AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT_PULLUP, MUX_MODE3)	/* (D18) uart1_ctsn.I2C2_SDA */
+//		>;
+//	};
+
+//	ehrpwm0_pins: pinmux-ehrpwm0-pins {
+//		pinctrl-single,pins = <
+//			AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE1)	/* (A13) mcasp0_aclkx.ehrpwm0A */
+//		>;
+//	};
+
+//	ehrpwm1_pins: pinmux-ehrpwm1-pins {
+//		pinctrl-single,pins = <
+//			AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT_PULLDOWN, MUX_MODE6)	/* (U14) gpmc_a2.ehrpwm1A */
+//		>;
+//	};
 
 	mmc0_pins: pinmux-mmc0-pins {
 		pinctrl-single,pins = <
@@ -361,23 +247,23 @@
 		>;
 	};
 
-	spi0_pins: pinmux-spi0-pins {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE0)
-			AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE0)
-		>;
-	};
-
-	spi1_pins: pinmux-spi1-pins {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, PIN_INPUT_PULLUP, MUX_MODE4)	/* (C18) eCAP0_in_PWM0_out.spi1_sclk */
-			AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLUP, MUX_MODE4)	/* (E18) uart0_ctsn.spi1_d0 */
-			AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLUP, MUX_MODE4)	/* (E17) uart0_rtsn.spi1_d1 */
-			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_INPUT_PULLUP, MUX_MODE4)	/* (A15) xdma_event_intr0.spi1_cs1 */
-		>;
-	};
+//	spi0_pins: pinmux-spi0-pins {
+//		pinctrl-single,pins = <
+//			AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT_PULLUP, MUX_MODE0)	/* (A17) spi0_sclk.spi0_sclk */
+//			AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT_PULLUP, MUX_MODE0)	/* (B17) spi0_d0.spi0_d0 */
+//			AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT_PULLUP, MUX_MODE0)	/* (B16) spi0_d1.spi0_d1 */
+//			AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT_PULLUP, MUX_MODE0)	/* (A16) spi0_cs0.spi0_cs0 */
+//		>;
+//	};
+
+//	spi1_pins: pinmux-spi1-pins {
+//		pinctrl-single,pins = <
+//			AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, PIN_INPUT_PULLUP, MUX_MODE4)	/* (C18) eCAP0_in_PWM0_out.spi1_sclk */
+//			AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT_PULLUP, MUX_MODE4)	/* (E18) uart0_ctsn.spi1_d0 */
+//			AM33XX_PADCONF(AM335X_PIN_UART0_RTSN, PIN_INPUT_PULLUP, MUX_MODE4)	/* (E17) uart0_rtsn.spi1_d1 */
+//			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_INPUT_PULLUP, MUX_MODE4)	/* (A15) xdma_event_intr0.spi1_cs1 */
+//		>;
+//	};
 
 	usr_leds_pins: pinmux-usr-leds-pins {
 		pinctrl-single,pins = <
@@ -395,12 +281,463 @@
 		>;
 	};
 
-	uart4_pins: pinmux-uart4-pins {
-		pinctrl-single,pins = <
-			AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE6)	/* (T17) gpmc_wait0.uart4_rxd */
-			AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT_PULLDOWN, MUX_MODE6)	/* (U17) gpmc_wpn.uart4_txd */
-		>;
-	};
+//	uart4_pins: pinmux-uart4-pins {
+//		pinctrl-single,pins = <
+//			AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT_PULLUP, MUX_MODE6)	/* (T17) gpmc_wait0.uart4_rxd */
+//			AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT_PULLDOWN, MUX_MODE6)	/* (U17) gpmc_wpn.uart4_txd */
+//		>;
+//	};
+
+
+/* macro: BONE_PIN( <pin>, <mode_name>, <register_value_macro(s)> */
+#define BONE_PIN(XX,ZZ,QQ) \
+	XX##_##ZZ##_pin: pinmux_##XX##_##ZZ##_pin { pinctrl-single,pins = < QQ >; };
+
+	/************************/
+	/* P1 Header */
+	/************************/
+
+	/* P1_01                VIN-AC */
+
+	/* P1_02 (ZCZ ball R5) lcd_hsync (gpio2_23) */
+	BONE_PIN(P1_02, default, P1_02(PIN_INPUT | MUX_MODE7))
+	BONE_PIN(P1_02, gpio, P1_02(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_02, gpio_pu, P1_02(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_02, gpio_pd, P1_02(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_02, pruout, P1_02(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P1_02, pruin, P1_02(PIN_INPUT | MUX_MODE6))
+
+	/* P1_03 (ZCZ ball F15)  usb1_vbus_out */
+
+	/* P1_04 (ZCZ ball R6) lcd_ac_bias_en (gpio2_25) */
+	BONE_PIN(P1_04, default, P1_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_04, gpio, P1_04(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_04, gpio_pu, P1_04(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_04, gpio_pd, P1_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_04, pruout, P1_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P1_04, pruin, P1_04(PIN_INPUT | MUX_MODE6))
+
+	/* P1_05 (ZCZ ball T18)  usb1_vbus_in */
+
+	/* P1_06 (ZCZ ball A16) spi0_cs0 (spi0_cs0) */
+	BONE_PIN(P1_06, default, P1_06(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P1_06, gpio, P1_06(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_06, gpio_pu, P1_06(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_06, gpio_pd, P1_06(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_06, spi_cs, P1_06(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P1_06, i2c, P1_06(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P1_06, pwm, P1_06(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P1_06, pru_uart, P1_06(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P1_07                VIN-USB */
+
+	/* P1_08 (ZCZ ball A17) spi0_sclk (spi0_sclk) */
+	BONE_PIN(P1_08, default, P1_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P1_08, gpio, P1_08(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_08, gpio_pu, P1_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_08, gpio_pd, P1_08(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_08, spi_sclk, P1_08(PIN_INPUT_PULLUP | MUX_MODE0))
+	BONE_PIN(P1_08, uart, P1_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P1_08, i2c, P1_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P1_08, pwm, P1_08(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P1_08, pru_uart, P1_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P1_09 (ZCZ ball R18)  USB1-DN */
+
+	/* P1_10 (ZCZ ball B17) spi0_d0 (spi0_d0) */
+	BONE_PIN(P1_10, default, P1_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P1_10, gpio, P1_10(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_10, gpio_pu, P1_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_10, gpio_pd, P1_10(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_10, spi, P1_10(PIN_INPUT_PULLUP | MUX_MODE0))
+	BONE_PIN(P1_10, uart, P1_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P1_10, i2c, P1_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P1_10, pwm, P1_10(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P1_10, pru_uart, P1_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P1_11 (ZCZ ball R17)  USB1-DP */
+
+	/* P1_12 (ZCZ ball B16) spi0_d1 (spi0_d1) */
+	BONE_PIN(P1_12, default, P1_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P1_12, gpio, P1_12(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_12, gpio_pu, P1_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_12, gpio_pd, P1_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_12, spi, P1_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P1_12, i2c, P1_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P1_12, pwm, P1_12(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P1_12, pru_uart, P1_12(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+
+	/* P1_13 (ZCZ ball P17)  USB1-ID */
+
+	/* P1_14                VOUT-3.3V */
+
+	/* P1_15                GND */
+
+	/* P1_16                GND */
+
+	/* P1_17 (ZCZ ball A9)  VREFN */
+
+	/* P1_18 (ZCZ ball B9)  VREFP */
+
+	/* P1_19 (ZCZ ball B6)  AIN0 */
+
+	/* P1_20 (ZCZ ball D14) xdma_event_intr1 (gpio0_20) */
+	BONE_PIN(P1_20, default, P1_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_20, gpio, P1_20(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_20, gpio_pu, P1_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_20, gpio_pd, P1_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_20, pruin, P1_20(PIN_INPUT | MUX_MODE5))
+
+	/* P1_21 (ZCZ ball C7)  AIN1 */
+
+	/* P1_22                GND */
+
+	/* P1_23 (ZCZ ball B7)  AIN2 */
+
+	/* P1_24                VOUT-5V */
+
+	/* P1_25 (ZCZ ball A7)  AIN3 */
+
+	/* P1_26 (ZCZ ball D18) uart1_ctsn (i2c2_sda) */
+	BONE_PIN(P1_26, default, P1_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P1_26, gpio, P1_26(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_26, gpio_pu, P1_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_26, gpio_pd, P1_26(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_26, can, P1_26(PIN_OUTPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P1_26, i2c, P1_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P1_26, spi_cs, P1_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P1_26, pru_uart, P1_26(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+
+	/* P1_27 (ZCZ ball C8)  AIN4 */
+
+	/* P1_28 (ZCZ ball D17) uart1_rtsn (i2c2_scl) */
+	BONE_PIN(P1_28, default, P1_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P1_28, gpio, P1_28(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_28, gpio_pu, P1_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_28, gpio_pd, P1_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_28, can, P1_28(PIN_INPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P1_28, i2c, P1_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P1_28, spi_cs, P1_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P1_28, pru_uart, P1_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+
+	/* P1_29 (ZCZ ball A14) mcasp0_ahclkx (pru0_in7) */
+	BONE_PIN(P1_29, default, P1_29(PIN_INPUT | MUX_MODE6))
+	BONE_PIN(P1_29, gpio, P1_29(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_29, gpio_pu, P1_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_29, gpio_pd, P1_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_29, eqep, P1_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P1_29, pruout, P1_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P1_29, pruin, P1_29(PIN_INPUT | MUX_MODE6))
+
+	/* P1_30 (ZCZ ball E16) uart0_txd (uart0_txd) */
+	BONE_PIN(P1_30, default, P1_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P1_30, gpio, P1_30(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_30, gpio_pu, P1_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_30, gpio_pd, P1_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_30, uart, P1_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P1_30, spi_cs, P1_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P1_30, can, P1_30(PIN_INPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P1_30, i2c, P1_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P1_30, pruout, P1_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P1_30, pruin, P1_30(PIN_INPUT | MUX_MODE6))
+
+	/* P1_31 (ZCZ ball B12) mcasp0_aclkr (pru0_in4) */
+	BONE_PIN(P1_31, default, P1_31(PIN_INPUT | MUX_MODE6))
+	BONE_PIN(P1_31, gpio, P1_31(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_31, gpio_pu, P1_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_31, gpio_pd, P1_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_31, eqep, P1_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P1_31, pruout, P1_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P1_31, pruin, P1_31(PIN_INPUT | MUX_MODE6))
+
+	/* P1_32 (ZCZ ball E15) uart0_rxd (uart0_rxd) */
+	BONE_PIN(P1_32, default, P1_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P1_32, gpio, P1_32(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_32, gpio_pu, P1_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_32, gpio_pd, P1_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_32, uart, P1_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P1_32, spi_cs, P1_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P1_32, can, P1_32(PIN_OUTPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P1_32, i2c, P1_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P1_32, pruout, P1_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P1_32, pruin, P1_32(PIN_INPUT | MUX_MODE6))
+
+	/* P1_33 (ZCZ ball B13) mcasp0_fsx (pru0_in1) */
+	BONE_PIN(P1_33, default, P1_33(PIN_INPUT | MUX_MODE6))
+	BONE_PIN(P1_33, gpio, P1_33(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_33, gpio_pu, P1_33(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_33, gpio_pd, P1_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_33, pwm, P1_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P1_33, spi, P1_33(PIN_INPUT_PULLUP | MUX_MODE3))
+	BONE_PIN(P1_33, pruout, P1_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P1_33, pruin, P1_33(PIN_INPUT | MUX_MODE6))
+
+	/* P1_34 (ZCZ ball T11) gpmc_ad10 (gpio0_26) */
+	BONE_PIN(P1_34, default, P1_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_34, gpio, P1_34(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_34, gpio_pu, P1_34(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_34, gpio_pd, P1_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_34, pwm, P1_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4))
+
+	/* P1_35 (ZCZ ball V5) lcd_pclk (pru1_in10) */
+	BONE_PIN(P1_35, default, P1_35(PIN_INPUT | MUX_MODE6))
+	BONE_PIN(P1_35, gpio, P1_35(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_35, gpio_pu, P1_35(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_35, gpio_pd, P1_35(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_35, pruout, P1_35(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P1_35, pruin, P1_35(PIN_INPUT | MUX_MODE6))
+
+	/* P1_36 (ZCZ ball A13) mcasp0_aclkx (ehrpwm0a) */
+	BONE_PIN(P1_36, default, P1_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P1_36, gpio, P1_36(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_36, gpio_pu, P1_36(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_36, gpio_pd, P1_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P1_36, pwm, P1_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P1_36, spi_sclk, P1_36(PIN_INPUT_PULLUP | MUX_MODE3))
+	BONE_PIN(P1_36, pruout, P1_36(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P1_36, pruin, P1_36(PIN_INPUT | MUX_MODE6))
+
+
+	/************************/
+	/* P2 Header */
+	/************************/
+
+	/* P2_01 (ZCZ ball U14) gpmc_a2 (ehrpwm1a) */
+	BONE_PIN(P2_01, default, P2_01(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+	BONE_PIN(P2_01, gpio, P2_01(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_01, gpio_pu, P2_01(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_01, gpio_pd, P2_01(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_01, pwm, P2_01(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P2_02 (ZCZ ball V17) gpmc_a11 (gpio1_27) */
+	BONE_PIN(P2_02, default, P2_02(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_02, gpio, P2_02(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_02, gpio_pu, P2_02(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_02, gpio_pd, P2_02(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P2_03 (ZCZ ball T10) gpmc_ad9 (gpio0_23) */
+	BONE_PIN(P2_03, default, P2_03(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_03, gpio, P2_03(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_03, gpio_pu, P2_03(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_03, gpio_pd, P2_03(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_03, pwm, P2_03(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4))
+
+	/* P2_04 (ZCZ ball T16) gpmc_a10 (gpio1_26) */
+	BONE_PIN(P2_04, default, P2_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_04, gpio, P2_04(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_04, gpio_pu, P2_04(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_04, gpio_pd, P2_04(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P2_05 (ZCZ ball T17) gpmc_wait0 (uart4_rxd) */
+	BONE_PIN(P2_05, default, P2_05(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6))
+	BONE_PIN(P2_05, gpio, P2_05(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_05, gpio_pu, P2_05(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_05, gpio_pd, P2_05(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_05, uart, P2_05(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6))
+
+	/* P2_06 (ZCZ ball U16) gpmc_a9 (gpio1_25) */
+	BONE_PIN(P2_06, default, P2_06(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_06, gpio, P2_06(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_06, gpio_pu, P2_06(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_06, gpio_pd, P2_06(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P2_07 (ZCZ ball U17) gpmc_wpn (uart4_txd) */
+	BONE_PIN(P2_07, default, P2_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6))
+	BONE_PIN(P2_07, gpio, P2_07(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_07, gpio_pu, P2_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_07, gpio_pd, P2_07(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_07, uart, P2_07(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6))
+
+	/* P2_08 (ZCZ ball U18) gpmc_be1n (gpio1_28) */
+	BONE_PIN(P2_08, default, P2_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_08, gpio, P2_08(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_08, gpio_pu, P2_08(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_08, gpio_pd, P2_08(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P2_09 (ZCZ ball D15) uart1_txd (i2c1_scl) */
+	BONE_PIN(P2_09, default, P2_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P2_09, gpio, P2_09(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_09, gpio_pu, P2_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_09, gpio_pd, P2_09(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_09, uart, P2_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P2_09, can, P2_09(PIN_INPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P2_09, i2c, P2_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P2_09, pru_uart, P2_09(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P2_09, pruin, P2_09(PIN_INPUT | MUX_MODE6))
+
+	/* P2_10 (ZCZ ball R14) gpmc_a4 (gpio1_20) */
+	BONE_PIN(P2_10, default, P2_10(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_10, gpio, P2_10(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_10, gpio_pu, P2_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_10, gpio_pd, P2_10(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_10, eqep, P2_10(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6))
+
+	/* P2_11 (ZCZ ball D16) uart1_rxd (i2c1_sda) */
+	BONE_PIN(P2_11, default, P2_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P2_11, gpio, P2_11(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_11, gpio_pu, P2_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_11, gpio_pd, P2_11(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_11, uart, P2_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P2_11, can, P2_11(PIN_OUTPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P2_11, i2c, P2_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P2_11, pru_uart, P2_11(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P2_11, pruin, P2_11(PIN_INPUT | MUX_MODE6))
+
+	/* P2_12                POWER_BUTTON */
+
+	/* P2_13                VOUT-5V */
+
+	/* P2_14                BAT-VIN */
+
+	/* P2_15                GND */
+
+	/* P2_16                BAT-TEMP */
+
+	/* P2_17 (ZCZ ball V12) gpmc_clk (gpio2_1) */
+	BONE_PIN(P2_17, default, P2_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_17, gpio, P2_17(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_17, gpio_pu, P2_17(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_17, gpio_pd, P2_17(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P2_18 (ZCZ ball U13) gpmc_ad15 (gpio1_15) */
+	BONE_PIN(P2_18, default, P2_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_18, gpio, P2_18(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_18, gpio_pu, P2_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_18, gpio_pd, P2_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_18, eqep, P2_18(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P2_18, pru_ecap_pwm, P2_18(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P2_18, pruin, P2_18(PIN_INPUT | MUX_MODE6))
+
+	/* P2_19 (ZCZ ball U12) gpmc_ad11 (gpio0_27) */
+	BONE_PIN(P2_19, default, P2_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_19, gpio, P2_19(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_19, gpio_pu, P2_19(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_19, gpio_pd, P2_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_19, pwm, P2_19(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE4))
+
+	/* P2_20 (ZCZ ball T13) gpmc_csn3 (gpio2_0) */
+	BONE_PIN(P2_20, default, P2_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_20, gpio, P2_20(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_20, gpio_pu, P2_20(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_20, gpio_pd, P2_20(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+
+	/* P2_21                GND */
+
+	/* P2_22 (ZCZ ball V13) gpmc_ad14 (gpio1_14) */
+	BONE_PIN(P2_22, default, P2_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_22, gpio, P2_22(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_22, gpio_pu, P2_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_22, gpio_pd, P2_22(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_22, eqep, P2_22(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P2_22, pruin, P2_22(PIN_INPUT | MUX_MODE6))
+
+	/* P2_23                VOUT-3.3V */
+
+	/* P2_24 (ZCZ ball T12) gpmc_ad12 (gpio1_12) */
+	BONE_PIN(P2_24, default, P2_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_24, gpio, P2_24(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_24, gpio_pu, P2_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_24, gpio_pd, P2_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_24, eqep, P2_24(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P2_24, pruout, P2_24(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P2_25 (ZCZ ball E17) uart0_rtsn (spi1_d1) */
+	BONE_PIN(P2_25, default, P2_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P2_25, gpio, P2_25(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_25, gpio_pu, P2_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_25, gpio_pd, P2_25(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_25, uart, P2_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P2_25, can, P2_25(PIN_INPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P2_25, i2c, P2_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P2_25, spi, P2_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P2_25, spi_cs, P2_25(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE5))
+
+	/* P2_26                RESET# */
+
+	/* P2_27 (ZCZ ball E18) uart0_ctsn (spi1_d0) */
+	BONE_PIN(P2_27, default, P2_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P2_27, gpio, P2_27(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_27, gpio_pu, P2_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_27, gpio_pd, P2_27(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_27, uart, P2_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P2_27, can, P2_27(PIN_OUTPUT_PULLUP | MUX_MODE2))
+	BONE_PIN(P2_27, i2c, P2_27(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P2_27, spi, P2_27(PIN_INPUT_PULLUP | MUX_MODE4))
+
+	/* P2_28 (ZCZ ball D13) mcasp0_axr1 (pru0_in6) */
+	BONE_PIN(P2_28, default, P2_28(PIN_INPUT | MUX_MODE6))
+	BONE_PIN(P2_28, gpio, P2_28(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_28, gpio_pu, P2_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_28, gpio_pd, P2_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_28, eqep, P2_28(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P2_28, pruout, P2_28(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P2_28, pruin, P2_28(PIN_INPUT | MUX_MODE6))
+
+	/* P2_29 (ZCZ ball C18) eCAP0_in_PWM0_out (spi1_sclk) */
+	BONE_PIN(P2_29, default, P2_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P2_29, gpio, P2_29(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_29, gpio_pu, P2_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_29, gpio_pd, P2_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_29, pwm, P2_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE0))
+	BONE_PIN(P2_29, uart, P2_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P2_29, spi_cs, P2_29(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE2))
+	BONE_PIN(P2_29, pru_ecap_pwm, P2_29(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P2_29, spi_sclk, P2_29(PIN_INPUT_PULLUP | MUX_MODE4))
+
+	/* P2_30 (ZCZ ball C12) mcasp0_ahclkr (pru0_in3) */
+	BONE_PIN(P2_30, default, P2_30(PIN_INPUT | MUX_MODE6))
+	BONE_PIN(P2_30, gpio, P2_30(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_30, gpio_pu, P2_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_30, gpio_pd, P2_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_30, pwm, P2_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P2_30, spi_cs, P2_30(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P2_30, pruout, P2_30(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P2_30, pruin, P2_30(PIN_INPUT | MUX_MODE6))
+
+	/* P2_31 (ZCZ ball A15) xdma_event_intr0 (spi1_cs1) */
+	BONE_PIN(P2_31, default, P2_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P2_31, gpio, P2_31(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_31, gpio_pu, P2_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_31, gpio_pd, P2_31(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_31, spi_cs, P2_31(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P2_31, pruin, P2_31(PIN_INPUT | MUX_MODE5))
+
+	/* P2_32 (ZCZ ball D12) mcasp0_axr0 (pru0_in2) */
+	BONE_PIN(P2_32, default, P2_32(PIN_INPUT | MUX_MODE6))
+	BONE_PIN(P2_32, gpio, P2_32(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_32, gpio_pu, P2_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_32, gpio_pd, P2_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_32, pwm, P2_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P2_32, spi, P2_32(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE3))
+	BONE_PIN(P2_32, pruout, P2_32(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P2_32, pruin, P2_32(PIN_INPUT | MUX_MODE6))
+
+	/* P2_33 (ZCZ ball R12) gpmc_ad13 (gpio1_13) */
+	BONE_PIN(P2_33, default, P2_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_33, gpio, P2_33(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_33, gpio_pu, P2_33(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_33, gpio_pd, P2_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_33, eqep, P2_33(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE4))
+	BONE_PIN(P2_33, pruout, P2_33(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE6))
+
+	/* P2_34 (ZCZ ball C13) mcasp0_fsr (pru0_in5) */
+	BONE_PIN(P2_34, default, P2_34(PIN_INPUT | MUX_MODE6))
+	BONE_PIN(P2_34, gpio, P2_34(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_34, gpio_pu, P2_34(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_34, gpio_pd, P2_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_34, eqep, P2_34(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE1))
+	BONE_PIN(P2_34, pruout, P2_34(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P2_34, pruin, P2_34(PIN_INPUT | MUX_MODE6))
+
+	/* P2_35 (ZCZ ball U5) lcd_vsync (gpio2_22) */
+	BONE_PIN(P2_35, default, P2_35(PIN_INPUT | MUX_MODE7))
+	BONE_PIN(P2_35, gpio, P2_35(PIN_OUTPUT | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_35, gpio_pu, P2_35(PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_35, gpio_pd, P2_35(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE7))
+	BONE_PIN(P2_35, pruout, P2_35(PIN_OUTPUT_PULLDOWN | INPUT_EN | MUX_MODE5))
+	BONE_PIN(P2_35, pruin, P2_35(PIN_INPUT | MUX_MODE6))
+
+	/* P2_36 (ZCZ ball C9)  AIN7 */
 };
 
 &epwmss0 {
@@ -410,7 +747,8 @@
 &ehrpwm0 {
 	status = "okay";
 	pinctrl-names = "default";
-	pinctrl-0 = <&ehrpwm0_pins>;
+	//pinctrl-0 = <&ehrpwm0_pins>;
+	pinctrl-0 = <>;
 };
 
 &epwmss1 {
@@ -420,7 +758,18 @@
 &ehrpwm1 {
 	status = "okay";
 	pinctrl-names = "default";
-	pinctrl-0 = <&ehrpwm1_pins>;
+	//pinctrl-0 = <&ehrpwm1_pins>;
+	pinctrl-0 = <>;
+};
+
+&epwmss2 {
+	status = "okay";
+};
+
+&ehrpwm2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
 };
 
 &i2c0 {
@@ -430,9 +779,18 @@
 	};
 };
 
+&i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+
+	status = "okay";
+	clock-frequency = <400000>;
+};
+
 &i2c2 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&i2c2_pins>;
+//	pinctrl-0 = <&i2c2_pins>;
+	pinctrl-0 = <>;
 
 	status = "okay";
 	clock-frequency = <400000>;
@@ -463,14 +821,30 @@
 
 &uart0 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&uart0_pins>;
+	//pinctrl-0 = <&uart0_pins>;
+	pinctrl-0 = <>;
+
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+
+	status = "okay";
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
 
 	status = "okay";
 };
 
 &uart4 {
 	pinctrl-names = "default";
-	pinctrl-0 = <&uart4_pins>;
+	//pinctrl-0 = <&uart4_pins>;
+	pinctrl-0 = <>;
 
 	status = "okay";
 };
@@ -482,3 +856,1048 @@
 &usb1 {
 	dr_mode = "host";
 };
+
+&spi0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	channel@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/0.0";
+		reg = <0>;
+		spi-max-frequency = <24000000>;
+	};
+
+	channel@1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/0.1";
+		reg = <1>;
+		spi-max-frequency = <24000000>;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	channel@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/1.0";
+		reg = <0>;
+		spi-max-frequency = <24000000>;
+	};
+
+	channel@1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/1.1";
+		reg = <1>;
+		spi-max-frequency = <24000000>;
+	};
+};
+
+&dcan0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&dcan1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <>;
+};
+
+&ocp {
+	/************************/
+	/* P1 Header */
+	/************************/
+
+	/* P1_01                VIN-AC */
+
+	/* P1_02 (ZCZ ball R5) gpio */
+	P1_02_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P1_02_default_pin>;
+		pinctrl-1 = <&P1_02_gpio_pin>;
+		pinctrl-2 = <&P1_02_gpio_pu_pin>;
+		pinctrl-3 = <&P1_02_gpio_pd_pin>;
+		pinctrl-4 = <&P1_02_pruout_pin>;
+		pinctrl-5 = <&P1_02_pruin_pin>;
+	};
+
+	/* P1_03 (ZCZ ball F15)  usb1_vbus_out */
+
+	/* P1_04 (ZCZ ball R6) */
+	P1_04_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P1_04_default_pin>;
+		pinctrl-1 = <&P1_04_gpio_pin>;
+		pinctrl-2 = <&P1_04_gpio_pu_pin>;
+		pinctrl-3 = <&P1_04_gpio_pd_pin>;
+		pinctrl-4 = <&P1_04_pruout_pin>;
+		pinctrl-5 = <&P1_04_pruin_pin>;
+	};
+
+	/* P1_05 (ZCZ ball T18)  usb1_vbus_in */
+
+	/* P1_06 (ZCZ ball A16) spi_cs */
+	P1_06_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "i2c", "pwm", "pru_uart";
+		pinctrl-0 = <&P1_06_default_pin>;
+		pinctrl-1 = <&P1_06_gpio_pin>;
+		pinctrl-2 = <&P1_06_gpio_pu_pin>;
+		pinctrl-3 = <&P1_06_gpio_pd_pin>;
+		pinctrl-4 = <&P1_06_spi_cs_pin>;
+		pinctrl-5 = <&P1_06_i2c_pin>;
+		pinctrl-6 = <&P1_06_pwm_pin>;
+		pinctrl-7 = <&P1_06_pru_uart_pin>;
+	};
+
+	/* P1_07                VIN-USB */
+
+	/* P1_08 (ZCZ ball A17) spi_sclk */
+	P1_08_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_sclk", "uart", "i2c", "pwm", "pru_uart";
+		pinctrl-0 = <&P1_08_default_pin>;
+		pinctrl-1 = <&P1_08_gpio_pin>;
+		pinctrl-2 = <&P1_08_gpio_pu_pin>;
+		pinctrl-3 = <&P1_08_gpio_pd_pin>;
+		pinctrl-4 = <&P1_08_spi_sclk_pin>;
+		pinctrl-5 = <&P1_08_uart_pin>;
+		pinctrl-6 = <&P1_08_i2c_pin>;
+		pinctrl-7 = <&P1_08_pwm_pin>;
+		pinctrl-8 = <&P1_08_pru_uart_pin>;
+	};
+
+	/* P1_09 (ZCZ ball R18)  USB1-DN */
+
+	/* P1_10 (ZCZ ball B17) spi */
+	P1_10_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "i2c", "pwm", "pru_uart";
+		pinctrl-0 = <&P1_10_default_pin>;
+		pinctrl-1 = <&P1_10_gpio_pin>;
+		pinctrl-2 = <&P1_10_gpio_pu_pin>;
+		pinctrl-3 = <&P1_10_gpio_pd_pin>;
+		pinctrl-4 = <&P1_10_spi_pin>;
+		pinctrl-5 = <&P1_10_uart_pin>;
+		pinctrl-6 = <&P1_10_i2c_pin>;
+		pinctrl-7 = <&P1_10_pwm_pin>;
+		pinctrl-8 = <&P1_10_pru_uart_pin>;
+	};
+
+	/* P1_11 (ZCZ ball R17)  USB1-DP */
+
+	/* P1_12 (ZCZ ball B16) spi */
+	P1_12_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "i2c", "pwm", "pru_uart";
+		pinctrl-0 = <&P1_12_default_pin>;
+		pinctrl-1 = <&P1_12_gpio_pin>;
+		pinctrl-2 = <&P1_12_gpio_pu_pin>;
+		pinctrl-3 = <&P1_12_gpio_pd_pin>;
+		pinctrl-4 = <&P1_12_spi_pin>;
+		pinctrl-5 = <&P1_12_i2c_pin>;
+		pinctrl-6 = <&P1_12_pwm_pin>;
+		pinctrl-7 = <&P1_12_pru_uart_pin>;
+	};
+
+	/* P1_13 (ZCZ ball P17)  USB1-ID */
+
+	/* P1_14                VOUT-3.3V */
+
+	/* P1_15                GND */
+
+	/* P1_16                GND */
+
+	/* P1_17 (ZCZ ball A9)  VREFN */
+
+	/* P1_18 (ZCZ ball B9)  VREFP */
+
+	/* P1_19 (ZCZ ball B6)  AIN0 */
+
+	/* P1_20 (ZCZ ball D14) */
+	P1_20_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruin";
+		pinctrl-0 = <&P1_20_default_pin>;
+		pinctrl-1 = <&P1_20_gpio_pin>;
+		pinctrl-2 = <&P1_20_gpio_pu_pin>;
+		pinctrl-3 = <&P1_20_gpio_pd_pin>;
+		pinctrl-4 = <&P1_20_pruin_pin>;
+	};
+
+	/* P1_21 (ZCZ ball C7)  AIN1 */
+
+	/* P1_22                GND */
+
+	/* P1_23 (ZCZ ball B7)  AIN2 */
+
+	/* P1_24                VOUT-5V */
+
+	/* P1_25 (ZCZ ball A7)  AIN3 */
+
+	/* P1_26 (ZCZ ball D18) i2c */
+	P1_26_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "can", "i2c", "pru_uart";
+		pinctrl-0 = <&P1_26_default_pin>;
+		pinctrl-1 = <&P1_26_gpio_pin>;
+		pinctrl-2 = <&P1_26_gpio_pu_pin>;
+		pinctrl-3 = <&P1_26_gpio_pd_pin>;
+		pinctrl-4 = <&P1_26_spi_cs_pin>;
+		pinctrl-5 = <&P1_26_can_pin>;
+		pinctrl-6 = <&P1_26_i2c_pin>;
+		pinctrl-7 = <&P1_26_pru_uart_pin>;
+	};
+
+	/* P1_27 (ZCZ ball C8)  AIN4 */
+
+	/* P1_28 (ZCZ ball D17) i2c */
+	P1_28_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "can", "i2c", "pru_uart";
+		pinctrl-0 = <&P1_28_default_pin>;
+		pinctrl-1 = <&P1_28_gpio_pin>;
+		pinctrl-2 = <&P1_28_gpio_pu_pin>;
+		pinctrl-3 = <&P1_28_gpio_pd_pin>;
+		pinctrl-4 = <&P1_28_spi_cs_pin>;
+		pinctrl-5 = <&P1_28_can_pin>;
+		pinctrl-6 = <&P1_28_i2c_pin>;
+		pinctrl-7 = <&P1_28_pru_uart_pin>;
+	};
+
+	/* P1_29 (ZCZ ball A14) pruin */
+	P1_29_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P1_29_default_pin>;
+		pinctrl-1 = <&P1_29_gpio_pin>;
+		pinctrl-2 = <&P1_29_gpio_pu_pin>;
+		pinctrl-3 = <&P1_29_gpio_pd_pin>;
+		pinctrl-4 = <&P1_29_eqep_pin>;
+		pinctrl-5 = <&P1_29_pruout_pin>;
+		pinctrl-6 = <&P1_29_pruin_pin>;
+	};
+
+	/* P1_30 (ZCZ ball E16) uart */
+	P1_30_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "uart", "can", "i2c", "pruout", "pruin";
+		pinctrl-0 = <&P1_30_default_pin>;
+		pinctrl-1 = <&P1_30_gpio_pin>;
+		pinctrl-2 = <&P1_30_gpio_pu_pin>;
+		pinctrl-3 = <&P1_30_gpio_pd_pin>;
+		pinctrl-4 = <&P1_30_spi_cs_pin>;
+		pinctrl-5 = <&P1_30_uart_pin>;
+		pinctrl-6 = <&P1_30_can_pin>;
+		pinctrl-7 = <&P1_30_i2c_pin>;
+		pinctrl-8 = <&P1_30_pruout_pin>;
+		pinctrl-9 = <&P1_30_pruin_pin>;
+	};
+
+	/* P1_31 (ZCZ ball B12) pruin */
+	P1_31_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P1_31_default_pin>;
+		pinctrl-1 = <&P1_31_gpio_pin>;
+		pinctrl-2 = <&P1_31_gpio_pu_pin>;
+		pinctrl-3 = <&P1_31_gpio_pd_pin>;
+		pinctrl-4 = <&P1_31_eqep_pin>;
+		pinctrl-5 = <&P1_31_pruout_pin>;
+		pinctrl-6 = <&P1_31_pruin_pin>;
+	};
+
+	/* P1_32 (ZCZ ball E15) uart */
+	P1_32_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "uart", "can", "i2c", "pruout", "pruin";
+		pinctrl-0 = <&P1_32_default_pin>;
+		pinctrl-1 = <&P1_32_gpio_pin>;
+		pinctrl-2 = <&P1_32_gpio_pu_pin>;
+		pinctrl-3 = <&P1_32_gpio_pd_pin>;
+		pinctrl-4 = <&P1_32_spi_cs_pin>;
+		pinctrl-5 = <&P1_32_uart_pin>;
+		pinctrl-6 = <&P1_32_can_pin>;
+		pinctrl-7 = <&P1_32_i2c_pin>;
+		pinctrl-8 = <&P1_32_pruout_pin>;
+		pinctrl-9 = <&P1_32_pruin_pin>;
+	};
+
+	/* P1_33 (ZCZ ball B13) pruin */
+	P1_33_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P1_33_default_pin>;
+		pinctrl-1 = <&P1_33_gpio_pin>;
+		pinctrl-2 = <&P1_33_gpio_pu_pin>;
+		pinctrl-3 = <&P1_33_gpio_pd_pin>;
+		pinctrl-4 = <&P1_33_spi_pin>;
+		pinctrl-5 = <&P1_33_pwm_pin>;
+		pinctrl-6 = <&P1_33_pruout_pin>;
+		pinctrl-7 = <&P1_33_pruin_pin>;
+	};
+
+	/* P1_34 (ZCZ ball T11) */
+	P1_34_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P1_34_default_pin>;
+		pinctrl-1 = <&P1_34_gpio_pin>;
+		pinctrl-2 = <&P1_34_gpio_pu_pin>;
+		pinctrl-3 = <&P1_34_gpio_pd_pin>;
+		pinctrl-4 = <&P1_34_pwm_pin>;
+	};
+
+	/* P1_35 (ZCZ ball V5) pruin */
+	P1_35_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P1_35_default_pin>;
+		pinctrl-1 = <&P1_35_gpio_pin>;
+		pinctrl-2 = <&P1_35_gpio_pu_pin>;
+		pinctrl-3 = <&P1_35_gpio_pd_pin>;
+		pinctrl-4 = <&P1_35_pruout_pin>;
+		pinctrl-5 = <&P1_35_pruin_pin>;
+	};
+
+	/* P1_36 (ZCZ ball A13) pwm */
+	P1_36_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_sclk", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P1_36_default_pin>;
+		pinctrl-1 = <&P1_36_gpio_pin>;
+		pinctrl-2 = <&P1_36_gpio_pu_pin>;
+		pinctrl-3 = <&P1_36_gpio_pd_pin>;
+		pinctrl-4 = <&P1_36_spi_sclk_pin>;
+		pinctrl-5 = <&P1_36_pwm_pin>;
+		pinctrl-6 = <&P1_36_pruout_pin>;
+		pinctrl-7 = <&P1_36_pruin_pin>;
+	};
+
+
+	/************************/
+	/* P2 Header */
+	/************************/
+
+	/* P2_01 (ZCZ ball U14) pwm */
+	P2_01_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P2_01_default_pin>;
+		pinctrl-1 = <&P2_01_gpio_pin>;
+		pinctrl-2 = <&P2_01_gpio_pu_pin>;
+		pinctrl-3 = <&P2_01_gpio_pd_pin>;
+		pinctrl-4 = <&P2_01_pwm_pin>;
+	};
+
+	/* P2_02 (ZCZ ball V17) */
+	P2_02_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P2_02_default_pin>;
+		pinctrl-1 = <&P2_02_gpio_pin>;
+		pinctrl-2 = <&P2_02_gpio_pu_pin>;
+		pinctrl-3 = <&P2_02_gpio_pd_pin>;
+	};
+
+	/* P2_03 (ZCZ ball T10) */
+	P2_03_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P2_03_default_pin>;
+		pinctrl-1 = <&P2_03_gpio_pin>;
+		pinctrl-2 = <&P2_03_gpio_pu_pin>;
+		pinctrl-3 = <&P2_03_gpio_pd_pin>;
+		pinctrl-4 = <&P2_03_pwm_pin>;
+	};
+
+	/* P2_04 (ZCZ ball T16) */
+	P2_04_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P2_04_default_pin>;
+		pinctrl-1 = <&P2_04_gpio_pin>;
+		pinctrl-2 = <&P2_04_gpio_pu_pin>;
+		pinctrl-3 = <&P2_04_gpio_pd_pin>;
+	};
+
+	/* P2_05 (ZCZ ball T17) uart */
+	P2_05_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart";
+		pinctrl-0 = <&P2_05_default_pin>;
+		pinctrl-1 = <&P2_05_gpio_pin>;
+		pinctrl-2 = <&P2_05_gpio_pu_pin>;
+		pinctrl-3 = <&P2_05_gpio_pd_pin>;
+		pinctrl-4 = <&P2_05_uart_pin>;
+	};
+
+	/* P2_06 (ZCZ ball U16) */
+	P2_06_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P2_06_default_pin>;
+		pinctrl-1 = <&P2_06_gpio_pin>;
+		pinctrl-2 = <&P2_06_gpio_pu_pin>;
+		pinctrl-3 = <&P2_06_gpio_pd_pin>;
+	};
+
+	/* P2_07 (ZCZ ball U17) uart */
+	P2_07_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart";
+		pinctrl-0 = <&P2_07_default_pin>;
+		pinctrl-1 = <&P2_07_gpio_pin>;
+		pinctrl-2 = <&P2_07_gpio_pu_pin>;
+		pinctrl-3 = <&P2_07_gpio_pd_pin>;
+		pinctrl-4 = <&P2_07_uart_pin>;
+	};
+
+	/* P2_08 (ZCZ ball U18) */
+	P2_08_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P2_08_default_pin>;
+		pinctrl-1 = <&P2_08_gpio_pin>;
+		pinctrl-2 = <&P2_08_gpio_pu_pin>;
+		pinctrl-3 = <&P2_08_gpio_pd_pin>;
+	};
+
+	/* P2_09 (ZCZ ball D15) i2c */
+	P2_09_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pru_uart", "pruin";
+		pinctrl-0 = <&P2_09_default_pin>;
+		pinctrl-1 = <&P2_09_gpio_pin>;
+		pinctrl-2 = <&P2_09_gpio_pu_pin>;
+		pinctrl-3 = <&P2_09_gpio_pd_pin>;
+		pinctrl-4 = <&P2_09_uart_pin>;
+		pinctrl-5 = <&P2_09_can_pin>;
+		pinctrl-6 = <&P2_09_i2c_pin>;
+		pinctrl-7 = <&P2_09_pru_uart_pin>;
+		pinctrl-8 = <&P2_09_pruin_pin>;
+	};
+
+	/* P2_10 (ZCZ ball R14) */
+	P2_10_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep";
+		pinctrl-0 = <&P2_10_default_pin>;
+		pinctrl-1 = <&P2_10_gpio_pin>;
+		pinctrl-2 = <&P2_10_gpio_pu_pin>;
+		pinctrl-3 = <&P2_10_gpio_pd_pin>;
+		pinctrl-4 = <&P2_10_eqep_pin>;
+	};
+
+	/* P2_11 (ZCZ ball D16) i2c */
+	P2_11_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "uart", "can", "i2c", "pru_uart", "pruin";
+		pinctrl-0 = <&P2_11_default_pin>;
+		pinctrl-1 = <&P2_11_gpio_pin>;
+		pinctrl-2 = <&P2_11_gpio_pu_pin>;
+		pinctrl-3 = <&P2_11_gpio_pd_pin>;
+		pinctrl-4 = <&P2_11_uart_pin>;
+		pinctrl-5 = <&P2_11_can_pin>;
+		pinctrl-6 = <&P2_11_i2c_pin>;
+		pinctrl-7 = <&P2_11_pru_uart_pin>;
+		pinctrl-8 = <&P2_11_pruin_pin>;
+	};
+
+	/* P2_12                POWER_BUTTON */
+
+	/* P2_13                VOUT-5V */
+
+	/* P2_14                BAT-VIN */
+
+	/* P2_15                GND */
+
+	/* P2_16                BAT-TEMP */
+
+	/* P2_17 (ZCZ ball V12) */
+	P2_17_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P2_17_default_pin>;
+		pinctrl-1 = <&P2_17_gpio_pin>;
+		pinctrl-2 = <&P2_17_gpio_pu_pin>;
+		pinctrl-3 = <&P2_17_gpio_pd_pin>;
+	};
+
+	/* P2_18 (ZCZ ball U13) */
+	P2_18_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pru_ecap_pwm", "pruin";
+		pinctrl-0 = <&P2_18_default_pin>;
+		pinctrl-1 = <&P2_18_gpio_pin>;
+		pinctrl-2 = <&P2_18_gpio_pu_pin>;
+		pinctrl-3 = <&P2_18_gpio_pd_pin>;
+		pinctrl-4 = <&P2_18_eqep_pin>;
+		pinctrl-5 = <&P2_18_pru_ecap_pwm_pin>;
+		pinctrl-6 = <&P2_18_pruin_pin>;
+	};
+
+	/* P2_19 (ZCZ ball U12) */
+	P2_19_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pwm";
+		pinctrl-0 = <&P2_19_default_pin>;
+		pinctrl-1 = <&P2_19_gpio_pin>;
+		pinctrl-2 = <&P2_19_gpio_pu_pin>;
+		pinctrl-3 = <&P2_19_gpio_pd_pin>;
+		pinctrl-4 = <&P2_19_pwm_pin>;
+	};
+
+	/* P2_20 (ZCZ ball T13) */
+	P2_20_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd";
+		pinctrl-0 = <&P2_20_default_pin>;
+		pinctrl-1 = <&P2_20_gpio_pin>;
+		pinctrl-2 = <&P2_20_gpio_pu_pin>;
+		pinctrl-3 = <&P2_20_gpio_pd_pin>;
+	};
+
+	/* P2_21                GND */
+
+	/* P2_22 (ZCZ ball V13) */
+	P2_22_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruin";
+		pinctrl-0 = <&P2_22_default_pin>;
+		pinctrl-1 = <&P2_22_gpio_pin>;
+		pinctrl-2 = <&P2_22_gpio_pu_pin>;
+		pinctrl-3 = <&P2_22_gpio_pd_pin>;
+		pinctrl-4 = <&P2_22_eqep_pin>;
+		pinctrl-5 = <&P2_22_pruin_pin>;
+	};
+
+	/* P2_23                VOUT-3.3V */
+
+	/* P2_24 (ZCZ ball T12) */
+	P2_24_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout";
+		pinctrl-0 = <&P2_24_default_pin>;
+		pinctrl-1 = <&P2_24_gpio_pin>;
+		pinctrl-2 = <&P2_24_gpio_pu_pin>;
+		pinctrl-3 = <&P2_24_gpio_pd_pin>;
+		pinctrl-4 = <&P2_24_eqep_pin>;
+		pinctrl-5 = <&P2_24_pruout_pin>;
+	};
+
+	/* P2_25 (ZCZ ball E17) spi */
+	P2_25_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "spi_cs", "uart", "can", "i2c";
+		pinctrl-0 = <&P2_25_default_pin>;
+		pinctrl-1 = <&P2_25_gpio_pin>;
+		pinctrl-2 = <&P2_25_gpio_pu_pin>;
+		pinctrl-3 = <&P2_25_gpio_pd_pin>;
+		pinctrl-4 = <&P2_25_spi_pin>;
+		pinctrl-5 = <&P2_25_spi_cs_pin>;
+		pinctrl-6 = <&P2_25_uart_pin>;
+		pinctrl-7 = <&P2_25_can_pin>;
+		pinctrl-8 = <&P2_25_i2c_pin>;
+	};
+
+	/* P2_26                RESET# */
+
+	/* P2_27 (ZCZ ball E18) spi */
+	P2_27_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "uart", "can", "i2c";
+		pinctrl-0 = <&P2_27_default_pin>;
+		pinctrl-1 = <&P2_27_gpio_pin>;
+		pinctrl-2 = <&P2_27_gpio_pu_pin>;
+		pinctrl-3 = <&P2_27_gpio_pd_pin>;
+		pinctrl-4 = <&P2_27_spi_pin>;
+		pinctrl-5 = <&P2_27_uart_pin>;
+		pinctrl-6 = <&P2_27_can_pin>;
+		pinctrl-7 = <&P2_27_i2c_pin>;
+	};
+
+	/* P2_28 (ZCZ ball D13) pruin */
+	P2_28_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P2_28_default_pin>;
+		pinctrl-1 = <&P2_28_gpio_pin>;
+		pinctrl-2 = <&P2_28_gpio_pu_pin>;
+		pinctrl-3 = <&P2_28_gpio_pd_pin>;
+		pinctrl-4 = <&P2_28_eqep_pin>;
+		pinctrl-5 = <&P2_28_pruout_pin>;
+		pinctrl-6 = <&P2_28_pruin_pin>;
+	};
+
+	/* P2_29 (ZCZ ball C18) spi_sclk */
+	P2_29_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "spi_sclk", "uart", "pwm", "pru_ecap_pwm";
+		pinctrl-0 = <&P2_29_default_pin>;
+		pinctrl-1 = <&P2_29_gpio_pin>;
+		pinctrl-2 = <&P2_29_gpio_pu_pin>;
+		pinctrl-3 = <&P2_29_gpio_pd_pin>;
+		pinctrl-4 = <&P2_29_spi_cs_pin>;
+		pinctrl-5 = <&P2_29_spi_sclk_pin>;
+		pinctrl-6 = <&P2_29_uart_pin>;
+		pinctrl-7 = <&P2_29_pwm_pin>;
+		pinctrl-8 = <&P2_29_pru_ecap_pwm_pin>;
+	};
+
+	/* P2_30 (ZCZ ball C12) pruin */
+	P2_30_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P2_30_default_pin>;
+		pinctrl-1 = <&P2_30_gpio_pin>;
+		pinctrl-2 = <&P2_30_gpio_pu_pin>;
+		pinctrl-3 = <&P2_30_gpio_pd_pin>;
+		pinctrl-4 = <&P2_30_spi_cs_pin>;
+		pinctrl-5 = <&P2_30_pwm_pin>;
+		pinctrl-6 = <&P2_30_pruout_pin>;
+		pinctrl-7 = <&P2_30_pruin_pin>;
+	};
+
+	/* P2_31 (ZCZ ball A15) spi_cs */
+	P2_31_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi_cs", "pruin";
+		pinctrl-0 = <&P2_31_default_pin>;
+		pinctrl-1 = <&P2_31_gpio_pin>;
+		pinctrl-2 = <&P2_31_gpio_pu_pin>;
+		pinctrl-3 = <&P2_31_gpio_pd_pin>;
+		pinctrl-4 = <&P2_31_spi_cs_pin>;
+		pinctrl-5 = <&P2_31_pruin_pin>;
+	};
+
+	/* P2_32 (ZCZ ball D12) pruin */
+	P2_32_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "spi", "pwm", "pruout", "pruin";
+		pinctrl-0 = <&P2_32_default_pin>;
+		pinctrl-1 = <&P2_32_gpio_pin>;
+		pinctrl-2 = <&P2_32_gpio_pu_pin>;
+		pinctrl-3 = <&P2_32_gpio_pd_pin>;
+		pinctrl-4 = <&P2_32_spi_pin>;
+		pinctrl-5 = <&P2_32_pwm_pin>;
+		pinctrl-6 = <&P2_32_pruout_pin>;
+		pinctrl-7 = <&P2_32_pruin_pin>;
+	};
+
+	/* P2_33 (ZCZ ball R12) */
+	P2_33_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout";
+		pinctrl-0 = <&P2_33_default_pin>;
+		pinctrl-1 = <&P2_33_gpio_pin>;
+		pinctrl-2 = <&P2_33_gpio_pu_pin>;
+		pinctrl-3 = <&P2_33_gpio_pd_pin>;
+		pinctrl-4 = <&P2_33_eqep_pin>;
+		pinctrl-5 = <&P2_33_pruout_pin>;
+	};
+
+	/* P2_34 (ZCZ ball C13) pruin */
+	P2_34_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "eqep", "pruout", "pruin";
+		pinctrl-0 = <&P2_34_default_pin>;
+		pinctrl-1 = <&P2_34_gpio_pin>;
+		pinctrl-2 = <&P2_34_gpio_pu_pin>;
+		pinctrl-3 = <&P2_34_gpio_pd_pin>;
+		pinctrl-4 = <&P2_34_eqep_pin>;
+		pinctrl-5 = <&P2_34_pruout_pin>;
+		pinctrl-6 = <&P2_34_pruin_pin>;
+	};
+
+	/* P2_35 (ZCZ ball U5) gpio */
+	P2_35_pinmux {
+		compatible = "bone-pinmux-helper";
+		status = "okay";
+		pinctrl-names = "default", "gpio", "gpio_pu", "gpio_pd", "pruout", "pruin";
+		pinctrl-0 = <&P2_35_default_pin>;
+		pinctrl-1 = <&P2_35_gpio_pin>;
+		pinctrl-2 = <&P2_35_gpio_pu_pin>;
+		pinctrl-3 = <&P2_35_gpio_pd_pin>;
+		pinctrl-4 = <&P2_35_pruout_pin>;
+		pinctrl-5 = <&P2_35_pruin_pin>;
+	};
+
+	/* P2_36 (ZCZ ball C9)  AIN7 */
+
+	cape-universal {
+		compatible = "gpio-of-helper";
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <>;
+
+		P1_02 {
+			gpio-name = "P1_02";
+			gpio = <&gpio2 23 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_04 {
+			gpio-name = "P1_04";
+			gpio = <&gpio2 25 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_06 {
+			gpio-name = "P1_06";
+			gpio = <&gpio0 5 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_08 {
+			gpio-name = "P1_08";
+			gpio = <&gpio0 2 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_10 {
+			gpio-name = "P1_10";
+			gpio = <&gpio0 3 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_12 {
+			gpio-name = "P1_12";
+			gpio = <&gpio0 4 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_20 {
+			gpio-name = "P1_20";
+			gpio = <&gpio0 20 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_26 {
+			gpio-name = "P1_26";
+			gpio = <&gpio0 12 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_28 {
+			gpio-name = "P1_28";
+			gpio = <&gpio0 13 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_29 {
+			gpio-name = "P1_29";
+			gpio = <&gpio3 21 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_30 {
+			gpio-name = "P1_30";
+			gpio = <&gpio1 11 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_31 {
+			gpio-name = "P1_31";
+			gpio = <&gpio3 18 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_32 {
+			gpio-name = "P1_32";
+			gpio = <&gpio1 10 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_33 {
+			gpio-name = "P1_33";
+			gpio = <&gpio3 15 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_34 {
+			gpio-name = "P1_34";
+			gpio = <&gpio0 26 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_35 {
+			gpio-name = "P1_35";
+			gpio = <&gpio2 24 0>;
+			input;
+			dir-changeable;
+		};
+
+		P1_36 {
+			gpio-name = "P1_36";
+			gpio = <&gpio3 14 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_01 {
+			gpio-name = "P2_01";
+			gpio = <&gpio1 18 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_02 {
+			gpio-name = "P2_02";
+			gpio = <&gpio1 27 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_03 {
+			gpio-name = "P2_03";
+			gpio = <&gpio0 23 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_04 {
+			gpio-name = "P2_04";
+			gpio = <&gpio1 26 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_05 {
+			gpio-name = "P2_05";
+			gpio = <&gpio0 30 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_06 {
+			gpio-name = "P2_06";
+			gpio = <&gpio1 25 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_07 {
+			gpio-name = "P2_07";
+			gpio = <&gpio0 31 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_08 {
+			gpio-name = "P2_08";
+			gpio = <&gpio1 28 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_09 {
+			gpio-name = "P2_09";
+			gpio = <&gpio0 15 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_10 {
+			gpio-name = "P2_10";
+			gpio = <&gpio1 20 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_11 {
+			gpio-name = "P2_11";
+			gpio = <&gpio0 14 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_17 {
+			gpio-name = "P2_17";
+			gpio = <&gpio2 1 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_18 {
+			gpio-name = "P2_18";
+			gpio = <&gpio1 15 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_19 {
+			gpio-name = "P2_19";
+			gpio = <&gpio0 27 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_20 {
+			gpio-name = "P2_20";
+			gpio = <&gpio2 0 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_22 {
+			gpio-name = "P2_22";
+			gpio = <&gpio1 14 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_24 {
+			gpio-name = "P2_24";
+			gpio = <&gpio1 12 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_25 {
+			gpio-name = "P2_25";
+			gpio = <&gpio1 9 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_27 {
+			gpio-name = "P2_27";
+			gpio = <&gpio1 8 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_28 {
+			gpio-name = "P2_28";
+			gpio = <&gpio3 20 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_29 {
+			gpio-name = "P2_29";
+			gpio = <&gpio0 7 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_30 {
+			gpio-name = "P2_30";
+			gpio = <&gpio3 17 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_31 {
+			gpio-name = "P2_31";
+			gpio = <&gpio0 19 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_32 {
+			gpio-name = "P2_32";
+			gpio = <&gpio3 16 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_33 {
+			gpio-name = "P2_33";
+			gpio = <&gpio1 13 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_34 {
+			gpio-name = "P2_34";
+			gpio = <&gpio3 19 0>;
+			input;
+			dir-changeable;
+		};
+
+		P2_35 {
+			gpio-name = "P2_35";
+			gpio = <&gpio2 22 0>;
+			input;
+			dir-changeable;
+		};
+
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/AM335X-PRU-UIO-00A0.dtso b/arch/arm/boot/dts/AM335X-PRU-UIO-00A0.dtso
--- a/arch/arm/boot/dts/AM335X-PRU-UIO-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/AM335X-PRU-UIO-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		AM335X-PRU-UIO-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+
+&pruss_tm {
+	status = "okay";
+};
+
+&pruss {
+	compatible = "ti,pruss-v2";
+	ti,pintc-offset = <0x20000>;
+	interrupt-parent = <&intc>;
+	interrupts = <20 21 22 23 24 25 26 27>;
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-sancloud-bbe-common.dtsi b/arch/arm/boot/dts/am335x-sancloud-bbe-common.dtsi
--- a/arch/arm/boot/dts/am335x-sancloud-bbe-common.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-sancloud-bbe-common.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -4,7 +4,7 @@
  */
 
 &am33xx_pinmux {
-	cpsw_default: cpsw_default {
+	cpsw_default: cpsw-default-pins {
 		pinctrl-single,pins = <
 			/* Slave 1 */
 			AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE2)	/* mii1_txen.rgmii1_tctl */
@@ -22,7 +22,7 @@
 		>;
 	};
 
-	cpsw_sleep: cpsw_sleep {
+	cpsw_sleep: cpsw-sleep-pins {
 		pinctrl-single,pins = <
 			/* Slave 1 reset value */
 			AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLDOWN, MUX_MODE7)
@@ -40,7 +40,7 @@
 		>;
 	};
 
-	usb_hub_ctrl: usb_hub_ctrl {
+	usb_hub_ctrl: usb-hub-ctrl-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7)     /* rmii1_refclk.gpio0_29 */
 		>;
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-sancloud-bbe.dts b/arch/arm/boot/dts/am335x-sancloud-bbe.dts
--- a/arch/arm/boot/dts/am335x-sancloud-bbe.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-sancloud-bbe.dts	2024-01-28 14:01:31.236353764 -0500
@@ -14,16 +14,21 @@
 / {
 	model = "SanCloud BeagleBone Enhanced";
 	compatible = "sancloud,am335x-boneenhanced", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+
+	chosen {
+		base_dtb = "am335x-sancloud-bbe.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
 };
 
 &am33xx_pinmux {
-	mpu6050_pins: pinmux_mpu6050_pins {
+	mpu6050_pins: mpu6050-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_UART0_CTSN, PIN_INPUT, MUX_MODE7)    /* uart0_ctsn.gpio1_8 */
 		>;
 	};
 
-	lps3331ap_pins: pinmux_lps3331ap_pins {
+	lps3331ap_pins: lps3331ap-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_GPMC_A10, PIN_INPUT, MUX_MODE7)     /* gpmc_a10.gpio1_26 */
 		>;
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-sancloud-bbe-extended-wifi.dts b/arch/arm/boot/dts/am335x-sancloud-bbe-extended-wifi.dts
--- a/arch/arm/boot/dts/am335x-sancloud-bbe-extended-wifi.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-sancloud-bbe-extended-wifi.dts	2024-01-28 14:01:31.236353764 -0500
@@ -18,6 +18,11 @@
 		     "ti,am335x-bone",
 		     "ti,am33xx";
 
+	chosen {
+		base_dtb = "am335x-sancloud-bbe-extended-wifi.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
+
 	wlan_en_reg: fixedregulator@2 {
 		compatible = "regulator-fixed";
 		regulator-name = "wlan-en-regulator";
@@ -28,7 +33,7 @@
 };
 
 &am33xx_pinmux {
-	mmc3_pins: pinmux_mmc3_pins {
+	mmc3_pins: mmc3-pins {
 		pinctrl-single,pins = <
 			/* gpmc_a9.gpio1_25: RADIO_EN */
 			AM33XX_PADCONF(AM335X_PIN_GPMC_A9, PIN_OUTPUT_PULLUP, MUX_MODE7)
@@ -53,14 +58,14 @@
 		>;
 	};
 
-	bluetooth_pins: pinmux_bluetooth_pins {
+	bluetooth_pins: bluetooth-pins {
 		pinctrl-single,pins = <
 			/* event_intr0.gpio0_19 */
 			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_INPUT_PULLUP, MUX_MODE7)
 		>;
 	};
 
-	uart1_pins: pinmux_uart1_pins {
+	uart1_pins: uart1-pins {
 		pinctrl-single,pins = <
 			/* uart1_rxd */
 			AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE0)
diff -Naur --no-dereference a/arch/arm/boot/dts/am335x-sancloud-bbe-lite.dts b/arch/arm/boot/dts/am335x-sancloud-bbe-lite.dts
--- a/arch/arm/boot/dts/am335x-sancloud-bbe-lite.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am335x-sancloud-bbe-lite.dts	2024-01-28 14:01:31.236353764 -0500
@@ -16,10 +16,15 @@
 		     "ti,am335x-bone-black",
 		     "ti,am335x-bone",
 		     "ti,am33xx";
+
+	chosen {
+		base_dtb = "am335x-sancloud-bbe-lite.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
 };
 
 &am33xx_pinmux {
-	bb_spi0_pins: pinmux_bb_spi0_pins {
+	bb_spi0_pins: bb-spi0-pins {
 		pinctrl-single,pins = <
 			AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE0)
 			AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT, MUX_MODE0)
@@ -42,6 +47,7 @@
 		#size-cells = <0>;
 
 		compatible = "micron,spi-authenta";
+		symlink = "bone/spi/0.0";
 
 		reg = <0>;
 		spi-max-frequency = <16000000>;
diff -Naur --no-dereference a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
--- a/arch/arm/boot/dts/am33xx.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am33xx.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -81,6 +81,7 @@
 		 * single SoC.
 		 */
 		opp50-300000000 {
+			/* OPP50 */
 			opp-hz = /bits/ 64 <300000000>;
 			opp-microvolt = <950000 931000 969000>;
 			opp-supported-hw = <0x06 0x0010>;
@@ -88,6 +89,7 @@
 		};
 
 		opp100-275000000 {
+			/* OPP100-1 */
 			opp-hz = /bits/ 64 <275000000>;
 			opp-microvolt = <1100000 1078000 1122000>;
 			opp-supported-hw = <0x01 0x00FF>;
@@ -95,6 +97,7 @@
 		};
 
 		opp100-300000000 {
+			/* OPP100-2 */
 			opp-hz = /bits/ 64 <300000000>;
 			opp-microvolt = <1100000 1078000 1122000>;
 			opp-supported-hw = <0x06 0x0020>;
@@ -102,42 +105,49 @@
 		};
 
 		opp100-500000000 {
+			/* OPP100-3 */
 			opp-hz = /bits/ 64 <500000000>;
 			opp-microvolt = <1100000 1078000 1122000>;
 			opp-supported-hw = <0x01 0xFFFF>;
 		};
 
 		opp100-600000000 {
+			/* OPP100-4 */
 			opp-hz = /bits/ 64 <600000000>;
 			opp-microvolt = <1100000 1078000 1122000>;
 			opp-supported-hw = <0x06 0x0040>;
 		};
 
 		opp120-600000000 {
+			/* OPP120-1 */
 			opp-hz = /bits/ 64 <600000000>;
 			opp-microvolt = <1200000 1176000 1224000>;
 			opp-supported-hw = <0x01 0xFFFF>;
 		};
 
 		opp120-720000000 {
+			/* OPP120-2 */
 			opp-hz = /bits/ 64 <720000000>;
 			opp-microvolt = <1200000 1176000 1224000>;
 			opp-supported-hw = <0x06 0x0080>;
 		};
 
 		oppturbo-720000000 {
+			/* OPP Turbo-1 */
 			opp-hz = /bits/ 64 <720000000>;
 			opp-microvolt = <1260000 1234800 1285200>;
 			opp-supported-hw = <0x01 0xFFFF>;
 		};
 
 		oppturbo-800000000 {
+			/* OPP Turbo-2 */
 			opp-hz = /bits/ 64 <800000000>;
 			opp-microvolt = <1260000 1234800 1285200>;
 			opp-supported-hw = <0x06 0x0100>;
 		};
 
 		oppnitro-1000000000 {
+			/* OPP Nitro */
 			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <1325000 1298500 1351500>;
 			opp-supported-hw = <0x04 0x0200>;
@@ -349,6 +359,7 @@
 					<SYSC_IDLE_NO>,
 					<SYSC_IDLE_SMART>,
 					<SYSC_IDLE_SMART_WKUP>;
+			ti,sysc-delay-us = <2>;
 			clocks = <&l3s_clkctrl AM3_L3S_USB_OTG_HS_CLKCTRL 0>;
 			clock-names = "fck";
 			#address-cells = <1>;
@@ -629,10 +640,11 @@
 			#size-cells = <1>;
 			ranges = <0 0x56000000 0x1000000>;
 
-			/*
-			 * Closed source PowerVR driver, no child device
-			 * binding or driver in mainline
-			 */
+			gpu: gpu@0 {
+				compatible = "ti,am3352-sgx530", "img,sgx530";
+				reg = <0x0 0x10000>;
+				interrupts = <37>;
+			};
 		};
 	};
 };
diff -Naur --no-dereference a/arch/arm/boot/dts/am33xx-l4.dtsi b/arch/arm/boot/dts/am33xx-l4.dtsi
--- a/arch/arm/boot/dts/am33xx-l4.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am33xx-l4.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -302,7 +302,7 @@
 				am33xx_pinmux: pinmux@800 {
 					compatible = "pinctrl-single";
 					reg = <0x800 0x238>;
-					#pinctrl-cells = <2>;
+					#pinctrl-cells = <1>;
 					pinctrl-single,register-width = <32>;
 					pinctrl-single,function-mask = <0x7f>;
 				};
@@ -455,8 +455,8 @@
 			rtc: rtc@0 {
 				compatible = "ti,am3352-rtc", "ti,da830-rtc";
 				reg = <0x0 0x1000>;
-				interrupts = <75
-					      76>;
+				interrupts = <75>,
+					     <76>;
 			};
 		};
 
@@ -739,7 +739,7 @@
 				 * c0_tx_pend
 				 * c0_misc_pend
 				 */
-				interrupts = <40 41 42 43>;
+				interrupts = <40>, <41>, <42>, <43>;
 				ranges = <0 0 0x8000>;
 				syscon = <&scm_conf>;
 				status = "disabled";
@@ -779,7 +779,7 @@
 				syscon = <&scm_conf>;
 				status = "disabled";
 
-				interrupts = <40 41 42 43>;
+				interrupts = <40>, <41>, <42>, <43>;
 				interrupt-names = "rx_thresh", "rx", "tx", "misc";
 
 				ethernet-ports {
@@ -854,7 +854,7 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0x0 0x300000 0x80000>;
-			status = "disabled";
+			status = "okay";
 
 			pruss: pruss@0 {
 				compatible = "ti,am3356-pruss";
@@ -891,6 +891,14 @@
 					};
 				};
 
+				pruss_uart: serial@28000 {
+					compatible = "ti,pruss-uart";
+					reg = <0x28000 0x38>;
+					clocks = <&dpll_per_m2_ck>;
+					interrupt-parent = <&pruss_intc>;
+					status = "disabled";
+				};
+
 				pruss_mii_rt: mii-rt@32000 {
 					compatible = "ti,pruss-mii", "syscon";
 					reg = <0x32000 0x58>;
@@ -899,7 +907,7 @@
 				pruss_intc: interrupt-controller@20000 {
 					compatible = "ti,pruss-intc";
 					reg = <0x20000 0x2000>;
-					interrupts = <20 21 22 23 24 25 26 27>;
+					interrupts = <20>, <21>, <22>, <23>, <24>, <25>, <26>, <27>;
 					interrupt-names = "host_intr0", "host_intr1",
 							  "host_intr2", "host_intr3",
 							  "host_intr4", "host_intr5",
diff -Naur --no-dereference a/arch/arm/boot/dts/am4372.dtsi b/arch/arm/boot/dts/am4372.dtsi
--- a/arch/arm/boot/dts/am4372.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am4372.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -714,6 +714,12 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 0x56000000 0x1000000>;
+
+			gpu: gpu@0 {
+				compatible = "ti,am4376-sgx530", "img,sgx530";
+				reg = <0x0 0x10000>;
+				interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+			};
 		};
 	};
 };
diff -Naur --no-dereference a/arch/arm/boot/dts/am571x-idk-touchscreen.dtso b/arch/arm/boot/dts/am571x-idk-touchscreen.dtso
--- a/arch/arm/boot/dts/am571x-idk-touchscreen.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am571x-idk-touchscreen.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019-2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&i2c1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	touchscreen: edt-ft5506@38 {
+		compatible = "edt,edt-ft5506", "edt,edt-ft5x06";
+
+		reg = <0x38>;
+
+		interrupt-parent = <&gpio5>;
+		interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
+
+		/* GPIO line is inverted before going to touch panel */
+		reset-gpios = <&gpio6 15 GPIO_ACTIVE_LOW>;
+
+		touchscreen-size-x = <1920>;
+		touchscreen-size-y = <1200>;
+
+		wakeup-source;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am5729-beagleboneai.dts b/arch/arm/boot/dts/am5729-beagleboneai.dts
--- a/arch/arm/boot/dts/am5729-beagleboneai.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am5729-beagleboneai.dts	2024-01-28 14:01:31.236353764 -0500
@@ -22,10 +22,19 @@
 		rtc0 = &tps659038_rtc;
 		rtc1 = &rtc;
 		display0 = &hdmi_conn;
+		mmc0 = &mmc1;
+		mmc1 = &mmc2;
+		mmc2 = &mmc4;
+		i2c0 = &i2c1;
+		i2c1 = &i2c5;
+		i2c2 = &i2c4;
+		i2c3 = &i2c3;
 	};
 
 	chosen {
 		stdout-path = &uart1;
+		base_dtb = "am5729-beagleboneai.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
 	};
 
 	memory@0 {
@@ -103,6 +112,8 @@
 
 	leds {
 		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins_default>;
 
 		led0 {
 			label = "beaglebone:green:usr0";
@@ -186,10 +197,14 @@
 	emmc_pwrseq: emmc_pwrseq {
 		compatible = "mmc-pwrseq-emmc";
 		reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&emmc_pwrseq_pins_default>;
 	};
 
 	brcmf_pwrseq: brcmf_pwrseq {
 		compatible = "mmc-pwrseq-simple";
+		pinctrl-names = "default";
+		pinctrl-0 = <&brcmf_pwrseq_pins_default>;
 		reset-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>,	/* BT-REG-ON */
 				<&gpio3 18 GPIO_ACTIVE_LOW>;	/* WL-REG-ON */
 	};
@@ -197,13 +212,85 @@
 	extcon_usb1: extcon_usb1 {
 		compatible = "linux,extcon-usb-gpio";
 		ti,enable-id-detection;
-		id-gpio = <&gpio3 13 GPIO_ACTIVE_HIGH>;
+		id-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&extcon_usb1_pins_default>;
+	};
+};
+
+&dra7_pmx_core {
+	extcon_usb1_pins_default: extcon_usb1_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3518, PIN_INPUT | MUX_MODE14) /* AG2: vin1a_d9.gpio3_13  - USR0 */
+		>;
+	};
+
+	led_pins_default: led_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3528, PIN_OUTPUT | MUX_MODE14) /* AF6: vin1a_d13.gpio3_17  - USR0 */
+			DRA7XX_CORE_IOPAD(0x36c0, PIN_OUTPUT | MUX_MODE14) /* J11: mcasp1_axr3.gpio5_5 - USR1 */
+			DRA7XX_CORE_IOPAD(0x3520, PIN_OUTPUT | MUX_MODE14) /* AG5: vin1a_d12.gpio3_15  - USR2 */
+			DRA7XX_CORE_IOPAD(0x351c, PIN_OUTPUT | MUX_MODE14) /* AG3: vin1a_d10.gpio3_14  - USR3 */
+			DRA7XX_CORE_IOPAD(0x3500, PIN_OUTPUT | MUX_MODE14) /* AH6: vin1a_d3.gpio3_7    - USR4 */
+		>;
+	};
+
+	emmc_pwrseq_pins_default: emmc_pwrseq_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x36c8, PIN_OUTPUT_PULLUP | MUX_MODE14) /* F13: mcasp1_axr5.gpio5_7 - eMMC_RSTn */
+		>;
+	};
+
+	brcmf_pwrseq_pins_default: brcmf_pwrseq_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x352c, PIN_OUTPUT_PULLUP | MUX_MODE14) /* AF3: vin1a_d14.gpio3_18 - WL_REG_ON */
+			DRA7XX_CORE_IOPAD(0x353c, PIN_OUTPUT_PULLUP | MUX_MODE14) /* AE5: vin1a_d18.gpio3_22 - BT_REG_ON */
+		>;
+	};
+
+	wifibt_extra_pins_default: wifibt_extra_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3540, PIN_INPUT | MUX_MODE14) /* AE1: vin1a_d19.gpio3_23 - WL_HOST_WAKE */
+			DRA7XX_CORE_IOPAD(0x3450, PIN_INPUT | MUX_MODE8) /* P6: vin1a_d20.uart6_rxd - UART6_RXD */
+			DRA7XX_CORE_IOPAD(0x3454, PIN_INPUT | MUX_MODE8) /* R9: vin1a_d21.uart6_txd - UART6_TXD */
+			DRA7XX_CORE_IOPAD(0x3458, PIN_INPUT | MUX_MODE8) /* R5: vin1a_d22.uart6_ctsn - UART6_CTSN */
+			DRA7XX_CORE_IOPAD(0x345c, PIN_INPUT | MUX_MODE8) /* P5: vin1a_d23.uart6_rtsn - UART6_RTSN */
+			DRA7XX_CORE_IOPAD(0x3534, PIN_INPUT_PULLDOWN | MUX_MODE14) /* AF1: vin1a_d16.gpio3_20 - BT_HOST_WAKE */
+			DRA7XX_CORE_IOPAD(0x3538, PIN_OUTPUT_PULLDOWN | MUX_MODE14) /* AE3: vin1a_d6.gpio3_21 - BT_WAKE */
+		>;
+	};
+
+	adc_pins_default: adc_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3550, PIN_OUTPUT | MUX_MODE14) /* AD3: vin1a_d23.gpio3_27 - VDD_ADC_SEL */
+			DRA7XX_CORE_IOPAD(0x34DC, PIN_INPUT_PULLUP | MUX_MODE14) /* AG8: vin1a_clk0.gpio2_30 - INT_ADC */
+		>;
+	};
+
+	pmic_pins_default: pmic_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3690, PIN_INPUT_PULLUP | MUX_MODE14) /* F21: gpio6_16.gpio6_16 - PMIC_INT */
+		>;
+	};
+
+	hdmi_pins_default: hdmi_pins_default {
+		pinctrl-single,pins = <
+			DRA7XX_CORE_IOPAD(0x3808, PIN_INPUT | MUX_MODE1) /* C25: i2c2_sda.hdmi1_ddc_scl - HDMI_DDC_SCL */
+			DRA7XX_CORE_IOPAD(0x380C, PIN_INPUT | MUX_MODE1) /* F17: i2c2_scl.hdmi1_ddc_sda - HDMI_DDC_SDA */
+			DRA7XX_CORE_IOPAD(0x37BC, PIN_INPUT | MUX_MODE6) /* B20: spi1_cs3.hdmi1_cec - HDMI_DDC_CEC */
+#if 0
+			DRA7XX_CORE_IOPAD(0x37B8, PIN_INPUT | MUX_MODE6) /* B21: spi1_cs2.hdmi1_hpd - HDMI_DDC_HPD */
+#else
+			DRA7XX_CORE_IOPAD(0x37B8, PIN_INPUT | MUX_MODE14) /* B21: spi1_cs2.gpio7_12 - HDMI_DDC_HPD */
+#endif
+		>;
 	};
 };
 
 &i2c1 {
 	status = "okay";
 	clock-frequency = <400000>;
+	symlink = "bone/i2c/0";
 
 	tps659038: tps659038@58 {
 		compatible = "ti,tps659038";
@@ -211,6 +298,9 @@
 		interrupt-parent = <&gpio6>;
 		interrupts = <16 IRQ_TYPE_LEVEL_LOW>;
 
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_pins_default>;
+
 		#interrupt-cells = <2>;
 		interrupt-controller;
 
@@ -424,6 +514,9 @@
 		st,adc-freq = <1>; /* 3.25 MHz ADC clock speed */
 		st,sample-time = <4>; /* ADC converstion time: 80 clocks */
 
+		pinctrl-names = "default";
+		pinctrl-0 = <&adc_pins_default>;
+
 		stmpe_adc {
 			compatible = "st,stmpe-adc";
 			st,norequest-mask = <0x00>; /* mask any channels to be used by touchscreen */
@@ -462,6 +555,11 @@
 			#pwm-cells = <2>;
 		};
 	};
+
+	eeprom: eeprom@50 {
+		compatible = "atmel,24c32";
+		reg = <0x50>;
+	};
 };
 
 &mcspi3 {
@@ -486,6 +584,7 @@
 
 &uart1 {
 	status = "okay";
+	symlink = "bone/uart/0";
 };
 
 &davinci_mdio_sw {
@@ -550,7 +649,11 @@
 	ti,needs-special-reset;
 	dmas = <&sdma_xbar 47>, <&sdma_xbar 48>;
 	dma-names = "tx", "rx";
-
+	pinctrl-names = "default", "hs", "ddr_1_8v", "hs200_1_8v";
+	pinctrl-0 = <&mmc2_pins_default>;
+	pinctrl-1 = <&mmc2_pins_hs>;
+	pinctrl-2 = <&mmc2_pins_ddr_rev20>;
+	pinctrl-3 = <&mmc2_pins_hs200>;
 };
 
 &mmc4 {
@@ -563,6 +666,10 @@
 	/* DDR50: DDR up to 50 MHz (1.8 V signaling). */
 	status = "okay";
 
+	pinctrl-names = "default", "hs";
+	pinctrl-0 = <&mmc4_pins_default &wifibt_extra_pins_default>;
+	pinctrl-1 = <&mmc4_pins_hs &wifibt_extra_pins_default>;
+
 	ti,needs-special-reset;
 	vmmc-supply = <&vdd_3v3>;
 	cap-power-off-card;
@@ -614,6 +721,10 @@
 	dr_mode = "host";
 };
 
+&bb2d {
+	status = "okay";
+};
+
 &dss {
 	status = "okay";
 	vdda_video-supply = <&vdd_1v8_pll>;
@@ -622,6 +733,8 @@
 &hdmi {
 	status = "okay";
 	vdda-supply = <&vdd_1v8_phy_ldo4>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&hdmi_pins_default>;
 
 	port {
 		hdmi_out: endpoint {
@@ -675,12 +788,7 @@
 &i2c4 {
 	status = "okay";
 	clock-frequency = <100000>;
-};
-
-&cpu0_opp_table {
-	opp_slow-500000000 {
-		opp-shared;
-	};
+	symlink = "bone/i2c/2";
 };
 
 &ipu2 {
diff -Naur --no-dereference a/arch/arm/boot/dts/am572x-idk-touchscreen.dtso b/arch/arm/boot/dts/am572x-idk-touchscreen.dtso
--- a/arch/arm/boot/dts/am572x-idk-touchscreen.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am572x-idk-touchscreen.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019-2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&i2c1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	touchscreen: edt-ft5506@38 {
+		compatible = "edt,edt-ft5506", "edt,edt-ft5x06";
+
+		reg = <0x38>;
+
+		interrupt-parent = <&gpio3>;
+		interrupts = <14 IRQ_TYPE_EDGE_FALLING>;
+
+		/* GPIO line is inverted before going to touch panel */
+		reset-gpios = <&gpio6 15 GPIO_ACTIVE_LOW>;
+
+		touchscreen-size-x = <1920>;
+		touchscreen-size-y = <1200>;
+
+		wakeup-source;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts
--- a/arch/arm/boot/dts/am57xx-beagle-x15.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts	2024-01-28 14:01:31.236353764 -0500
@@ -8,6 +8,11 @@
 / {
 	/* NOTE: This describes the "original" pre-production A2 revision */
 	model = "TI AM5728 BeagleBoard-X15";
+
+	chosen {
+		base_dtb = "am57xx-beagle-x15.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
 };
 
 &tpd12s015 {
diff -Naur --no-dereference a/arch/arm/boot/dts/am57xx-beagle-x15-revb1.dts b/arch/arm/boot/dts/am57xx-beagle-x15-revb1.dts
--- a/arch/arm/boot/dts/am57xx-beagle-x15-revb1.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am57xx-beagle-x15-revb1.dts	2024-01-28 14:01:31.236353764 -0500
@@ -7,6 +7,11 @@
 
 / {
 	model = "TI AM5728 BeagleBoard-X15 rev B1";
+
+	chosen {
+		base_dtb = "am57xx-beagle-x15-revb1.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
 };
 
 &tpd12s015 {
diff -Naur --no-dereference a/arch/arm/boot/dts/am57xx-beagle-x15-revc.dts b/arch/arm/boot/dts/am57xx-beagle-x15-revc.dts
--- a/arch/arm/boot/dts/am57xx-beagle-x15-revc.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/am57xx-beagle-x15-revc.dts	2024-01-28 14:01:31.236353764 -0500
@@ -7,6 +7,11 @@
 
 / {
 	model = "TI AM5728 BeagleBoard-X15 rev C";
+
+	chosen {
+		base_dtb = "am57xx-beagle-x15-revc.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
 };
 
 &tpd12s015 {
diff -Naur --no-dereference a/arch/arm/boot/dts/am57xx-evm.dtso b/arch/arm/boot/dts/am57xx-evm.dtso
--- a/arch/arm/boot/dts/am57xx-evm.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am57xx-evm.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT overlay for AM57xx GP EVM boards
+ *
+ * Copyright (C) 2020-2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+&{/} {
+	compatible = "ti,am5728-evm", "ti,am572x-beagle-x15", "ti,am5728", "ti,dra742", "ti,dra74", "ti,dra7";
+	model = "TI AM5728 EVM";
+
+	aliases {
+		display0 = "/display";
+		display1 = "/connector"; // Fixme: &lcd0 and &hdmi0 could be
+					 // resolved here correcly based on
+					 // information in the base dtb symbol
+					 // table with a fix in dtc
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		button-user1 {
+			gpios = <&gpio2 23 GPIO_ACTIVE_LOW>;
+			label = "USER1";
+			linux,code = <BTN_1>;
+		};
+
+		button-user2 {
+			gpios = <&gpio2 25 GPIO_ACTIVE_LOW>;
+			label = "USER2";
+			linux,code = <BTN_2>;
+		};
+
+		button-user3 {
+			gpios = <&gpio2 28 GPIO_ACTIVE_LOW>;
+			label = "USER3";
+			linux,code = <BTN_3>;
+		};
+
+		button-user4 {
+			gpios = <&gpio2 24 GPIO_ACTIVE_LOW>;
+			label = "USER4";
+			linux,code = <BTN_4>;
+		};
+
+		button-user5 {
+			gpios = <&gpio2 20 GPIO_ACTIVE_LOW>;
+			label = "USER5";
+			linux,code = <BTN_5>;
+		};
+	};
+
+	lcd0: display {
+		compatible = "osddisplays,osd070t1718-19ts", "panel-dpi";
+		backlight = <&lcd_bl>;
+		enable-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
+		label = "lcd";
+
+		port {
+			lcd_in: endpoint {
+				remote-endpoint = <&dpi_out>;
+			};
+		};
+	};
+
+	lcd_bl: backlight {
+		compatible = "pwm-backlight";
+		brightness-levels = <0 243 245 247 249 251 252 253 255>;
+		default-brightness-level = <8>;
+		pwms = <&ehrpwm1 0 50000 0>;
+	};
+};
+
+&ehrpwm1 {
+	status = "okay";
+};
+
+&epwmss1 {
+	status = "okay";
+};
+
+&i2c5 {
+	status = "okay";
+	clock-frequency = <400000>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	touchscreen@5c {
+		compatible = "pixcir,pixcir_tangoc";
+		attb-gpio = <&gpio2 4 GPIO_ACTIVE_HIGH>;
+		interrupt-parent = <&gpio2>;
+		interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+		reg = <0x5c>;
+		reset-gpio = <&gpio2 6 GPIO_ACTIVE_HIGH>;
+		touchscreen-size-x = <1024>;
+		touchscreen-size-y = <600>;
+	};
+};
+
+&uart8 {
+	status = "okay";
+};
+
+&dss {
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+
+			dpi_out: endpoint {
+				data-lines = <24>;
+				remote-endpoint = <&lcd_in>;
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am57xx-idk-lcd-osd101t2045.dtso b/arch/arm/boot/dts/am57xx-idk-lcd-osd101t2045.dtso
--- a/arch/arm/boot/dts/am57xx-idk-lcd-osd101t2045.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am57xx-idk-lcd-osd101t2045.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019-2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	aliases {
+		display0 = "/display";
+		display1 = "/connector";
+	};
+
+	lcd_bl: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&ecap0 0 50000 1>;
+		brightness-levels = <0 51 53 56 62 75 101 152 255>;
+		default-brightness-level = <8>;
+	};
+};
+
+&dsi_bridge {
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	lcd: display {
+		compatible = "osddisplays,osd101t2045-53ts";
+		reg = <0>;
+
+		label = "lcd";
+
+		backlight = <&lcd_bl>;
+
+		port {
+			lcd_in: endpoint {
+				remote-endpoint = <&dsi_out>;
+			};
+		};
+	};
+};
+
+&dsi_bridge_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@1 {
+		reg = <1>;
+		dsi_out: endpoint {
+			remote-endpoint = <&lcd_in>;
+		};
+	};
+};
+
+&epwmss0 {
+	status = "okay";
+};
+
+&ecap0 {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/am57xx-idk-lcd-osd101t2587.dtso b/arch/arm/boot/dts/am57xx-idk-lcd-osd101t2587.dtso
--- a/arch/arm/boot/dts/am57xx-idk-lcd-osd101t2587.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/am57xx-idk-lcd-osd101t2587.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019-2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&{/} {
+	aliases {
+		display0 = "/display";
+		display1 = "/connector";
+	};
+
+	lcd_bl: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&ecap0 0 50000 1>;
+		brightness-levels = <0 51 53 56 62 75 101 152 255>;
+		default-brightness-level = <8>;
+	};
+};
+
+&dsi_bridge {
+	status = "okay";
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	lcd: display {
+		compatible = "osddisplays,osd101t2587-53ts";
+		reg = <0>;
+
+		label = "lcd";
+
+		backlight = <&lcd_bl>;
+
+		port {
+			lcd_in: endpoint {
+				remote-endpoint = <&dsi_out>;
+			};
+		};
+	};
+};
+
+&dsi_bridge_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@1 {
+		reg = <1>;
+		dsi_out: endpoint {
+			remote-endpoint = <&lcd_in>;
+		};
+	};
+};
+
+&epwmss0 {
+	status = "okay";
+};
+
+&ecap0 {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-ADC-00A0.dtso b/arch/arm/boot/dts/BB-ADC-00A0.dtso
--- a/arch/arm/boot/dts/BB-ADC-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-ADC-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-ADC-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+&tscadc {
+	status = "okay";
+	adc {
+		// Configure one or more (up to 8) steps for the adc to execute:
+
+
+		// For each step, the channel to sample.
+		//	range: 0 .. 7
+		ti,adc-channels = <0 1 2 3 4 5 6 7>;
+		//
+		// BeagleBone Black (and most other variants):
+		//	ch 0	P9.39
+		//	ch 1	P9.40
+		//	ch 2	P9.37
+		//	ch 3	P9.38
+		//	ch 4	P9.33
+		//	ch 5	P9.36
+		//	ch 6	P9.35
+		//	ch 7	measures 0.5 * VDD_3V3B with 2.4 kΩ source impedance
+		//
+		// PocketBeagle:
+		//	ch 0	P1.19
+		//	ch 1	P1.21
+		//	ch 2	P1.23
+		//	ch 3	P1.25
+		//	ch 4	P1.27
+		//	ch 5	P2.35 via 10k/10k voltage divider
+		//	ch 6	P1.02 via 10k/10k voltage divider
+		//	ch 7	P2.36 via pmic mux
+		//
+		// The divider used on PocketBeagle channels 5 and 6 makes the effective voltage V_eff and
+		// source impedance Z_eff seen by the adc on these channels depend on the voltage V_src and
+		// impedance Z_src of the source connected to the corresponding pin as follows:
+		//
+		//	V_eff = V_src / (2 + Z_src / (10 kΩ))
+		//	Z_eff = 5 kΩ * (1 + Z_src / (Z_src + 20 kΩ))
+		//		≈ 5 kΩ + Z_src / 4    for small values of Z_src (up to 2 kΩ or so)
+
+
+		// For each step, number of adc clock cycles to wait between setting up muxes and sampling.
+		//	range: 0 .. 262143
+		//	optional, default is 152 (XXX but why?!)
+		ti,chan-step-opendelay = <152 152 152 152 152 152 152 152>;
+		//`
+		// XXX is there any purpose to set this nonzero other than to fine-tune the sample rate?
+
+
+		// For each step, how many times it should sample to average.
+		//	range: 1 .. 16, must be power of two (i.e. 1, 2, 4, 8, or 16)
+		//	optional, default is 16
+		ti,chan-step-avg = <16 16 16 16 16 16 16 16>;
+		//
+		// If you're using periodic sampling (using the iio block device rather than sysfs) then
+		// you should consider setting this to 1 and if desired reduce the samplerate in userspace
+		// instead since averaging isn't a particularly good low-pass filter.
+		//
+		// If you're using sysfs to occasionally read a value, then the default value of 16 will
+		// still get you the most accurate readings.
+
+
+		// For each step, number of adc clock cycles to sample minus two.
+		//	range: 0 .. 255   (resulting in sampling time of 2 .. 257 cycles)
+		//	optional, default is 0
+		ti,chan-step-sampledelay = <0 0 0 0 0 0 0 0>;
+		//
+		// If this is set too low, accuracy will deteriorate when the thing you're measuring has a
+		// high source impedance.  The maximum source impedance recommended (by erratum 1.0.32) is:
+		//	(2 + sampledelay) * 2.873 kΩ - 0.2 kΩ
+		// which means that the default should be fine for source impedance up to 5.5 kΩ.
+		//
+		// (This seems to ensure the sampling time is at least 21 times the RC constant, based on
+		// the 5.5 pF nominal capacitance specified in the datasheet.)
+
+
+		// After sampling, conversion time is 13 adc clock cycles.
+		//
+		// The adc clock frequency is 3 MHz, therefore the total time per step in microseconds is:
+		//	( opendelay + avg * ( 2 + sampledelay + 13 ) ) / 3
+		//
+		// If all steps use the same timings then the sample rate will be:
+		//	3 MHz / ( opendelay + avg * ( 2 + sampledelay + 13 ) ) / number_of_steps
+		//
+		// The highest samplerate obtainable (avg=1, opendelay=0, sampledelay=0) is therefore:
+		//	200 kHz / number_of_steps
+		//	= 25 kHz    when using all 8 steps.
+		//
+		// Using avg=16 reduces that to:
+		//	12.5 kHz / number_of_steps
+		//	= 1.5625 kHz    when using all 8 steps.
+		//
+		// Using the default values (avg=16, opendelay=152, sampledelay=0) reduces that to:
+		//	7.653 kHz / number_of_steps
+		//	= 0.9566 kHz    when using all 8 steps.
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-BBBW-WL1835-00A0.dtso b/arch/arm/boot/dts/BB-BBBW-WL1835-00A0.dtso
--- a/arch/arm/boot/dts/BB-BBBW-WL1835-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-BBBW-WL1835-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-BBBW-WL1835-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+&{/} {
+	model = "TI AM335x BeagleBone Black Wireless";
+	compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+
+	wlan_en_reg: fixedregulator@2 {
+		compatible = "regulator-fixed";
+		regulator-name = "wlan-en-regulator";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		startup-delay-us= <70000>;
+
+		/* WL_EN */
+		gpio = <&gpio3 9 0>;
+		enable-active-high;
+	};
+};
+
+&am33xx_pinmux {
+	bt_pins: pinmux_bt_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gmii1_txd0.gpio0_28 - BT_EN */
+		>;
+	};
+
+	mmc3_pins: pinmux_mmc3_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */
+			AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */
+			AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */
+			AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */
+			AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */
+			AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1)	/* gmii1_rxd3.uart3_rxd */
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1)	/* gmii1_rxd2.uart3_txd */
+			AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT, MUX_MODE3)		/* mdio_data.uart3_ctsn */
+			AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLDOWN, MUX_MODE3)	/* mdio_clk.uart3_rtsn */
+		>;
+	};
+
+	wl18xx_pins: pinmux_wl18xx_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gmii1_txclk.gpio3_9 WL_EN */
+			AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)	/* rmii1_refclk.gpio0_29 WL_IRQ */
+			AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gmii1_rxclk.gpio3_10 LS_BUF_EN */
+		>;
+	};
+};
+
+&mac_sw {
+	/delete-property/pinctrl-names;
+	/delete-property/pinctrl-0;
+	/delete-property/pinctrl-1;
+	status = "disabled";
+};
+
+&mmc3 {
+	dmas = <&edma_xbar 12 0 1
+		&edma_xbar 13 0 2>;
+	dma-names = "tx", "rx";
+	status = "okay";
+	vmmc-supply = <&wlan_en_reg>;
+	bus-width = <4>;
+	non-removable;
+	cap-power-off-card;
+	keep-power-in-suspend;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc3_pins &wl18xx_pins>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1835";
+		reg = <2>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <29 IRQ_TYPE_EDGE_RISING>;
+	};
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins &bt_pins>;
+	status = "okay";
+
+	bluetooth {
+		compatible = "ti,wl1835-st";
+		enable-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&gpio3 {
+	ls-buf-en-hog {
+		gpio-hog;
+		gpios = <10 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "LS_BUF_EN";
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-BBGG-WL1835-00A0.dtso b/arch/arm/boot/dts/BB-BBGG-WL1835-00A0.dtso
--- a/arch/arm/boot/dts/BB-BBGG-WL1835-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-BBGG-WL1835-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-BBGG-WL1835-00A0.kernel = __TIMESTAMP__;
+		wl1835_bt = "S3-texas-300000";
+	};
+};
+
+&{/} {
+	model = "SeeedStudio BeagleBone Green Gateway";
+	compatible = "ti,am335x-bone-green-gateway", "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+
+	aliases {
+		rtc0 = &extrtc;
+		rtc1 = "/ocp/rtc@44e3e000";
+	};
+
+	wlan_en_reg: fixedregulator@2 {
+		compatible = "regulator-fixed";
+		regulator-name = "wlan-en-regulator";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		startup-delay-us= <70000>;
+
+		/* WL_EN */
+		gpio = <&gpio3 9 0>;
+		enable-active-high;
+	};
+
+	leds {
+		pinctrl-names = "default";
+		//pinctrl-0 = <&user_leds_s0>;
+		pinctrl-0 = <&user_leds_s0 &bt_pins>;
+
+		compatible = "gpio-leds";
+
+		led2 {
+			label = "beaglebone:green:usr0";
+			gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+
+		led3 {
+			label = "beaglebone:green:usr1";
+			gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led4 {
+			label = "beaglebone:green:usr2";
+			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "cpu0";
+			default-state = "off";
+		};
+
+		led5 {
+			label = "beaglebone:green:usr3";
+			gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc1";
+			default-state = "off";
+		};
+
+		led6 {
+			label = "beaglebone:green:usr4";
+			gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "netdev";
+			default-state = "off";
+		};
+
+		wl18xx_bt_en: led7 {
+			label = "wl18xx_bt_en";
+			gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+};
+
+&am33xx_pinmux {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usbhost_pins>;
+
+	user_leds_s0: user_leds_s0 {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gpmc_a5.gpio1_21 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_a6.gpio1_22 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gpmc_a7.gpio1_23 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_a8.gpio1_24 */
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD0, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* WL_Active_LED / USR4 */
+		>;
+	};
+
+	bt_pins: pinmux_bt_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_TXD0, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gmii1_txd0.gpio0_28 - BT_EN */
+		>;
+	};
+
+	mmc3_pins: pinmux_mmc3_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD1, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (L15) gmii1_rxd1.mmc2_clk */
+			AM33XX_PADCONF(AM335X_PIN_MII1_TX_EN, PIN_INPUT_PULLUP, MUX_MODE6 ) /* (J16) gmii1_txen.mmc2_cmd */
+			AM33XX_PADCONF(AM335X_PIN_MII1_RX_DV, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J17) gmii1_rxdv.mmc2_dat0 */
+			AM33XX_PADCONF(AM335X_PIN_MII1_TXD3, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (J18) gmii1_txd3.mmc2_dat1 */
+			AM33XX_PADCONF(AM335X_PIN_MII1_TXD2, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (K15) gmii1_txd2.mmc2_dat2 */
+			AM33XX_PADCONF(AM335X_PIN_MII1_COL, PIN_INPUT_PULLUP, MUX_MODE5 ) /* (H16) gmii1_col.mmc2_dat3 */
+		>;
+	};
+
+	uart2_grove_pins: pinmux_uart2_grove_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x90c, PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6)
+			AM33XX_IOPAD(0x910, PIN_OUTPUT_PULLUP | INPUT_EN | MUX_MODE6)
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1)	/* gmii1_rxd3.uart3_rxd */
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1)	/* gmii1_rxd2.uart3_txd */
+			AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT, MUX_MODE3)		/* mdio_data.uart3_ctsn */
+			AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLDOWN, MUX_MODE3)	/* mdio_clk.uart3_rtsn */
+		>;
+	};
+
+	usbhost_pins: pinmux_usbhost_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_TXD1, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gmii1_txd1.gpio0[21] */
+		>;
+	};
+
+	wl18xx_pins: pinmux_wl18xx_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_TX_CLK, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gmii1_txclk.gpio3_9 WL_EN */
+			AM33XX_PADCONF(AM335X_PIN_RMII1_REF_CLK, PIN_INPUT_PULLDOWN, MUX_MODE7)	/* rmii1_refclk.gpio0_29 WL_IRQ */
+			AM33XX_PADCONF(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gmii1_rxclk.gpio3_10 LS_BUF_EN */
+		>;
+	};
+};
+
+&mac_sw {
+	/delete-property/pinctrl-names;
+	/delete-property/pinctrl-0;
+	/delete-property/pinctrl-1;
+	status = "disabled";
+};
+
+&mmc3 {
+	dmas = <&edma_xbar 12 0 1
+		&edma_xbar 13 0 2>;
+	dma-names = "tx", "rx";
+	status = "okay";
+	vmmc-supply = <&wlan_en_reg>;
+	bus-width = <4>;
+	non-removable;
+	cap-power-off-card;
+	keep-power-in-suspend;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc3_pins &wl18xx_pins>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1835";
+		reg = <2>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <29 IRQ_TYPE_EDGE_RISING>;
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart2_grove_pins>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+	//pinctrl-0 = <&uart3_pins &bt_pins>;
+	status = "okay";
+
+	//bluetooth {
+	//	compatible = "ti,wl1835-st";
+	//	enable-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
+	//};
+};
+
+&i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	extrtc: rtc@68 {
+		compatible = "dallas,ds1340";
+		reg = <0x68>;
+	};
+};
+
+// (K16) gmii1_txd1.gpio0[21]
+&gpio0 {
+	usb-reset-hog {
+		gpio-hog;
+		gpios = <21 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "usb_reset";
+	};
+};
+
+&gpio3 {
+	ls-buf-en-hog {
+		gpio-hog;
+		gpios = <10 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "LS_BUF_EN";
+	};
+};
+
+&usb1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	hub@1 {
+		compatible = "usb424,9512";
+		reg = <1>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		ethernet: ethernet@1 {
+			compatible = "usb424,ec00";
+			reg = <1>;
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-BBGW-WL1835-00A0.dtso b/arch/arm/boot/dts/BB-BBGW-WL1835-00A0.dtso
--- a/arch/arm/boot/dts/BB-BBGW-WL1835-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-BBGW-WL1835-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-BBGW-WL1835-00A0.kernel = __TIMESTAMP__;
+		wl1835_bt = "S3-texas-300000";
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_12_pinmux { status = "disabled"; };	/* gpmc_ad12.gpio1_28 BT_EN */
+	P8_12_pinmux { status = "disabled"; };	/* gpmc_ad12.mmc2_dat0 */
+	P8_11_pinmux { status = "disabled"; };	/* gpmc_ad13.mmc2_dat1 */
+	P8_16_pinmux { status = "disabled"; };	/* gpmc_ad14.mmc2_dat2 */
+	P8_15_pinmux { status = "disabled"; };	/* gpmc_ad15.mmc2_dat3 */
+
+	P8_18_pinmux { status = "disabled"; };	/* gpmc_clk.mmc2_clk */
+
+	//Audio...
+	P9_28_pinmux { status = "disabled"; };
+	P9_29_pinmux { status = "disabled"; };
+	P9_31_pinmux { status = "disabled"; };
+
+	/* wl1835 */
+	P8_14_pinmux { status = "disabled"; };	/* wl1835: wl_en */
+	P8_17_pinmux { status = "disabled"; };	/* wl1835: wl_irq */
+	P8_26_pinmux { status = "disabled"; };	/* wl1835: LS_BUF_EN */
+	P9_30_pinmux { status = "disabled"; };	/* wl1835: MCASP0_AHCLKR */
+};
+
+&{/} {
+	model = "TI AM335x BeagleBone Green Wireless";
+	compatible = "ti,am335x-bone-green-wireless", "ti,am335x-bone-green", "ti,am335x-bone", "ti,am33xx";
+
+	wlan_en_reg: fixedregulator@2 {
+		compatible = "regulator-fixed";
+		regulator-name = "wlan-en-regulator";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		startup-delay-us= <70000>;
+
+		/* WL_EN */
+		gpio = <&gpio0 26 0>;
+		enable-active-high;
+	};
+
+	leds {
+		pinctrl-names = "default";
+		//pinctrl-0 = <&user_leds_s0>;
+		pinctrl-0 = <&user_leds_s0 &bt_pins>;
+
+		compatible = "gpio-leds";
+
+		led2 {
+			label = "beaglebone:green:usr0";
+			gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+
+		led3 {
+			label = "beaglebone:green:usr1";
+			gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc0";
+			default-state = "off";
+		};
+
+		led4 {
+			label = "beaglebone:green:usr2";
+			gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "cpu0";
+			default-state = "off";
+		};
+
+		led5 {
+			label = "beaglebone:green:usr3";
+			gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "mmc1";
+			default-state = "off";
+		};
+
+		wl18xx_bt_en: led7 {
+			label = "wl18xx_bt_en";
+			gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+};
+
+&am33xx_pinmux {
+	user_leds_s0: user_leds_s0 {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A5, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gpmc_a5.gpio1_21 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A6, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_a6.gpio1_22 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A7, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gpmc_a7.gpio1_23 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A8, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_a8.gpio1_24 */
+		>;
+	};
+
+	bt_pins: pinmux_bt_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_ad12.gpio1_28 BT_EN */
+		>;
+	};
+
+	mmc3_pins: pinmux_mmc3_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_INPUT_PULLUP, MUX_MODE3)	/* gpmc_ad12.mmc2_dat0 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_INPUT_PULLUP, MUX_MODE3)	/* gpmc_ad13.mmc2_dat1 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_INPUT_PULLUP, MUX_MODE3)	/* gpmc_ad14.mmc2_dat2 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_INPUT_PULLUP, MUX_MODE3)	/* gpmc_ad15.mmc2_dat3 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_CSN3, PIN_INPUT_PULLUP, MUX_MODE3)	/* gpmc_csn3.mmc2_cmd */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_CLK, PIN_INPUT_PULLUP, MUX_MODE3)	/* gpmc_clk.mmc2_clk */
+		>;
+	};
+
+	uart3_pins: pinmux_uart3_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD3, PIN_INPUT_PULLUP, MUX_MODE1)	/* gmii1_rxd3.uart3_rxd */
+			AM33XX_PADCONF(AM335X_PIN_MII1_RXD2, PIN_OUTPUT_PULLDOWN, MUX_MODE1)	/* gmii1_rxd2.uart3_txd */
+			AM33XX_PADCONF(AM335X_PIN_MDIO, PIN_INPUT, MUX_MODE3)		/* mdio_data.uart3_ctsn */
+			AM33XX_PADCONF(AM335X_PIN_MDC, PIN_OUTPUT_PULLDOWN, MUX_MODE3)	/* mdio_clk.uart3_rtsn */
+		>;
+	};
+
+	wl18xx_pins: pinmux_wl18xx_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* gpmc_ad10.gpio0_26 WL_EN */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_INPUT_PULLDOWN, MUX_MODE7)	/* gpmc_ad11.gpio0_27 WL_IRQ */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_csn0.gpio1_29 LS_BUF_EN */
+		>;
+	};
+};
+
+&mac_sw {
+	/delete-property/pinctrl-names;
+	/delete-property/pinctrl-0;
+	/delete-property/pinctrl-1;
+	status = "disabled";
+};
+
+&mmc3 {
+	dmas = <&edma_xbar 12 0 1
+		&edma_xbar 13 0 2>;
+	dma-names = "tx", "rx";
+	status = "okay";
+	vmmc-supply = <&wlan_en_reg>;
+	bus-width = <4>;
+	non-removable;
+	cap-power-off-card;
+	keep-power-in-suspend;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mmc3_pins &wl18xx_pins>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1835";
+		reg = <2>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <27 IRQ_TYPE_EDGE_RISING>;
+	};
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_pins>;
+	//pinctrl-0 = <&uart3_pins &bt_pins>;
+	status = "okay";
+
+	//bluetooth {
+	//	compatible = "ti,wl1835-st";
+	//	enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+	//};
+};
+
+&gpio1 {
+	ls-buf-en-hog {
+		gpio-hog;
+		gpios = <29 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "LS_BUF_EN";
+	};
+};
+
+/* BT_AUD_OUT from wl1835 has to be pulled low when WL_EN is activated.*/
+/* in case it isn't, wilink8 ends up in one of the test modes that     */
+/* intruces various issues (elp wkaeup timeouts etc.)                  */
+/* On the BBGW this pin is routed through the level shifter (U21) that */
+/* introduces a pullup on the line and wilink8 ends up in a bad state. */
+/* use a gpio hog to force this pin low. An alternative may be adding  */
+/* an external pulldown on U21 pin 4.                                  */
+
+&gpio3 {
+	bt-aud-in-hog {
+		gpio-hog;
+		gpios = <16 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "MCASP0_AHCLKR";
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-BONE-4D5R-01-00A1.dtso b/arch/arm/boot/dts/BB-BONE-4D5R-01-00A1.dtso
--- a/arch/arm/boot/dts/BB-BONE-4D5R-01-00A1.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-BONE-4D5R-01-00A1.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-BONE-4D5R-01-00A1.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P8_45_pinmux { status = "disabled"; };	/* lcd: lcd_data0 */
+	P8_46_pinmux { status = "disabled"; };	/* lcd: lcd_data1 */
+	P8_43_pinmux { status = "disabled"; };	/* lcd: lcd_data2 */
+	P8_44_pinmux { status = "disabled"; };	/* lcd: lcd_data3 */
+	P8_41_pinmux { status = "disabled"; };	/* lcd: lcd_data4 */
+	P8_42_pinmux { status = "disabled"; };	/* lcd: lcd_data5 */
+	P8_39_pinmux { status = "disabled"; };	/* lcd: lcd_data6 */
+	P8_40_pinmux { status = "disabled"; };	/* lcd: lcd_data7 */
+	P8_37_pinmux { status = "disabled"; };	/* lcd: lcd_data8 */
+	P8_38_pinmux { status = "disabled"; };	/* lcd: lcd_data9 */
+	P8_36_pinmux { status = "disabled"; };	/* lcd: lcd_data10 */
+	P8_34_pinmux { status = "disabled"; };	/* lcd: lcd_data11 */
+	P8_35_pinmux { status = "disabled"; };	/* lcd: lcd_data12 */
+	P8_33_pinmux { status = "disabled"; };	/* lcd: lcd_data13 */
+	P8_31_pinmux { status = "disabled"; };	/* lcd: lcd_data14 */
+	P8_32_pinmux { status = "disabled"; };	/* lcd: lcd_data15 */
+
+	P8_27_pinmux { status = "disabled"; };	/* lcd: lcd_vsync */
+	P8_29_pinmux { status = "disabled"; };	/* lcd: lcd_hsync */
+	P8_28_pinmux { status = "disabled"; };	/* lcd: lcd_pclk */
+	P8_30_pinmux { status = "disabled"; };	/* lcd: lcd_ac_bias_en */
+
+	P9_27_pinmux { status = "disabled"; };	/* lcd: gpio3_19 DISPEN */
+
+	P9_14_pinmux { status = "disabled"; };	/* pwm: ehrpwm1a PWM_BL */
+
+	P9_18_pinmux { status = "disabled"; };	/* i2c1_sda */
+	P9_17_pinmux { status = "disabled"; };	/* i2c1_scl */
+	P9_26_pinmux { status = "disabled"; };	/* touch interrupt on gpio0_14 */
+};
+
+&am33xx_pinmux {
+	bb_lcd_pwm_backlight_pins: pinmux_bb_lcd_pwm_backlight_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT, MUX_MODE6) /* gpmc_a2.ehrpwm1a, OMAP_MUX_MODE6 | AM33XX_PIN_OUTPUT */
+		>;
+	};
+
+	bb_lcd_lcd_pins: pinmux_bb_lcd_lcd_pins {
+		pinctrl-single,pins = <
+			/*LCD enable */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_OUTPUT, MUX_MODE7) /* mcasp0_fsr.gpio3_19, OUTPUT | MODE7  LCD DISEN */
+
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+
+			AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0)
+		>;
+	};
+
+	bb_i2c1_pins: pinmux_bb_i2c1_pins {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | SLEWCTRL_SLOW | MUX_MODE2) /* spi0_d1.i2c1_sda */
+			AM33XX_IOPAD(0x95C, PIN_INPUT_PULLUP | SLEWCTRL_SLOW | MUX_MODE2) /* spi0_cs0.i2c1_scl */
+		>;
+	};
+
+	ar1021_pins: pinmux_ar1021_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE7)
+		>;
+	};
+};
+
+&epwmss1 {
+	status = "okay";
+};
+
+&ehrpwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_lcd_pwm_backlight_pins>;
+	status = "okay";
+};
+
+&lcdc {
+	status = "okay";
+
+	blue-and-red-wiring = "straight";
+
+	//FIXME - LCD doesn't init...
+	//port {
+	//	lcdc_0: endpoint@0 {
+	//		remote-endpoint = <&panel_0>;
+	//	};
+	//};
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_i2c1_pins>;
+
+	clock-frequency = <100000>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	ar1021: ar1021@4d {
+		status = "okay";
+		compatible = "microchip,ar1021-i2c";
+		reg = <0x4d>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&ar1021_pins>;
+		interrupt-parent = <&gpio0>;
+		interrupts = <14 IRQ_TYPE_LEVEL_HIGH>;
+
+		touchscreen-offset-x=<250>;
+		touchscreen-offset-y=<300>;
+
+		touchscreen-inverted-y;
+	};
+};
+
+&{/} {
+	backlight: backlight {
+		status = "okay";
+		compatible = "pwm-backlight";
+		pwms = <&ehrpwm1 0 500000 0>;
+		brightness-levels = <
+			0  1  2  3  4  5  6  7  8  9
+			10 11 12 13 14 15 16 17 18 19
+			20 21 22 23 24 25 26 27 28 29
+			30 31 32 33 34 35 36 37 38 39
+			40 41 42 43 44 45 46 47 48 49
+			50 51 52 53 54 55 56 57 58 59
+			60 61 62 63 64 65 66 67 68 69
+			70 71 72 73 74 75 76 77 78 79
+			80 81 82 83 84 85 86 87 88 89
+			90 91 92 93 94 95 96 97 98 99
+			100
+		>;
+		default-brightness-level = <100>;
+	};
+
+	panel {
+		status = "okay";
+		compatible = "ti,tilcdc,panel";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bb_lcd_lcd_pins>;
+		backlight = <&backlight>;
+		enable-gpios = <&gpio3 19 0>;
+
+		//FIXME - LCD doesn't init...
+		//port {
+		//	panel_0: endpoint@0 {
+		//		remote-endpoint = <&lcdc_0>;
+		//	};
+		//};
+
+		panel-info {
+			ac-bias           = <255>;
+			ac-bias-intrpt    = <0>;
+			dma-burst-sz      = <16>;
+			bpp               = <16>;
+			fdd               = <0x80>;
+			sync-edge         = <0>;
+			sync-ctrl         = <1>;
+			raster-order      = <0>;
+			fifo-th           = <0>;
+		};
+
+		display-timings {
+			native-mode = <&timing0>;
+			/* Settings for ThreeFive S9700RTWV35TR / LCD7 cape: */
+			timing0: 800x480 {
+				clock-frequency = <30000000>;
+				hactive = <800>;
+				vactive = <480>;
+				hfront-porch = <40>;
+				hback-porch = <40>;
+				hsync-len = <48>;
+				vback-porch = <30>;
+				vfront-porch = <13>;
+				vsync-len = <3>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-BONE-eMMC1-01-00A0.dtso b/arch/arm/boot/dts/BB-BONE-eMMC1-01-00A0.dtso
--- a/arch/arm/boot/dts/BB-BONE-eMMC1-01-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-BONE-eMMC1-01-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-BONE-eMMC1-01-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P8_21_pinmux { status = "disabled"; };	/* mmc1_clk */
+	P8_20_pinmux { status = "disabled"; };	/* mmc1_cmd */
+	P8_25_pinmux { status = "disabled"; };	/* mmc1_dat0 */
+	P8_24_pinmux { status = "disabled"; };	/* mmc1_dat1 */
+	P8_05_pinmux { status = "disabled"; };	/* mmc1_dat2 */
+	P8_06_pinmux { status = "disabled"; };	/* mmc1_dat3 */
+	P8_23_pinmux { status = "disabled"; };	/* mmc1_dat4 */
+	P8_22_pinmux { status = "disabled"; };	/* mmc1_dat5 */
+	P8_03_pinmux { status = "disabled"; };	/* mmc1_dat6 */
+	P8_04_pinmux { status = "disabled"; };	/* mmc1_dat7 */
+};
+
+&am33xx_pinmux {
+	emmc_pins: pinmux_emmc_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_CSN1, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn1.mmc1_clk */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_CSN2, PIN_INPUT_PULLUP, MUX_MODE2) /* gpmc_csn2.mmc1_cmd */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD0, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD1, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD2, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD3, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD4, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD5, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD6, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD7, PIN_INPUT_PULLUP, MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */
+		>;
+	};
+};
+
+&mmc2 {
+	vmmc-supply = <&vmmcsd_fixed>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_pins>;
+	bus-width = <8>;
+	status = "okay";
+	non-removable;
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-BONE-LCD4-01-00A1.dtso b/arch/arm/boot/dts/BB-BONE-LCD4-01-00A1.dtso
--- a/arch/arm/boot/dts/BB-BONE-LCD4-01-00A1.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-BONE-LCD4-01-00A1.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-BONE-LCD4-01-00A1.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_12_pinmux { status = "disabled"; };	/* P9_12: gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
+
+	P9_14_pinmux { status = "disabled"; };	/* P9_14: gpmc_a2.ehrpwm1a */
+
+	P9_27_pinmux { status = "disabled"; };	/* P9_27: mcasp0_fsr.gpio3_19 */
+
+	P8_45_pinmux { status = "disabled"; };	/* P8_45: lcd_data0.lcd_data0 */
+	P8_46_pinmux { status = "disabled"; };	/* P8_46: lcd_data1.lcd_data1 */
+	P8_43_pinmux { status = "disabled"; };	/* P8_43: lcd_data2.lcd_data2 */
+	P8_44_pinmux { status = "disabled"; };	/* P8_44: lcd_data3.lcd_data3 */
+	P8_41_pinmux { status = "disabled"; };	/* P8_41: lcd_data4.lcd_data4 */
+	P8_42_pinmux { status = "disabled"; };	/* P8_42: lcd_data5.lcd_data5 */
+	P8_39_pinmux { status = "disabled"; };	/* P8_39: lcd_data6.lcd_data6 */
+	P8_40_pinmux { status = "disabled"; };	/* P8_40: lcd_data7.lcd_data7 */
+	P8_37_pinmux { status = "disabled"; };	/* P8_37: lcd_data8.lcd_data8 */
+	P8_38_pinmux { status = "disabled"; };	/* P8_38: lcd_data9.lcd_data9 */
+	P8_36_pinmux { status = "disabled"; };	/* P8_36: lcd_data10.lcd_data10 */
+	P8_34_pinmux { status = "disabled"; };	/* P8_34: lcd_data11.lcd_data11 */
+	P8_35_pinmux { status = "disabled"; };	/* P8_35: lcd_data12.lcd_data12 */
+	P8_33_pinmux { status = "disabled"; };	/* P8_33: lcd_data13.lcd_data13 */
+	P8_31_pinmux { status = "disabled"; };	/* P8_31: lcd_data14.lcd_data14 */
+	P8_32_pinmux { status = "disabled"; };	/* P8_32: lcd_data15.lcd_data15 */
+
+	P8_27_pinmux { status = "disabled"; };	/* P8_27: lcd_vsync.lcd_vsync */
+	P8_29_pinmux { status = "disabled"; };	/* P8_29: lcd_hsync.lcd_hsync */
+	P8_28_pinmux { status = "disabled"; };	/* P8_28: lcd_pclk.lcd_pclk */
+	P8_30_pinmux { status = "disabled"; };	/* P8_30: lcd_ac_bias_en.lcd_ac_bias_en */
+
+	P9_15_pinmux { status = "disabled"; };	/* P9_15: gpmc_a0.gpio1_16 */
+	P9_23_pinmux { status = "disabled"; };	/* P9_23: gpmc_a1.gpio1_17 */
+	P9_16_pinmux { status = "disabled"; };	/* P9_16: gpmc_a3.gpio1_19 */
+	P9_30_pinmux { status = "disabled"; };	/* P9_30: mcasp0_axr0.gpio3_16 */
+	P9_24_pinmux { status = "disabled"; };	/* P9_24: uart1_txd.gpio0_15 */
+};
+
+&am33xx_pinmux {
+	bb_lcd_led_pins: pinmux_bb_lcd_led_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT, MUX_MODE7)	/* P9_12: gpmc_ben1.gpio1_28, INPUT | PULLDIS | MODE7 */
+		>;
+	};
+
+	bb_lcd_pwm_backlight_pins: pinmux_bb_lcd_pwm_backlight_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT_PULLDOWN, MUX_MODE6)	/* P9_14: gpmc_a2.ehrpwm1a */
+		>;
+	};
+
+	bb_lcd_lcd_pins: pinmux_bb_lcd_lcd_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* P9_27: mcasp0_fsr.gpio3_19 */
+
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+
+			AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0)
+		>;
+	};
+
+	bb_lcd_keymap_pins: pinmux_bb_lcd_keymap_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A0, PIN_INPUT, MUX_MODE7)	/* P9_15: gpmc_a0.gpio1_16 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A1, PIN_INPUT, MUX_MODE7)	/* P9_23: gpmc_a1.gpio1_17 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_INPUT, MUX_MODE7)	/* P9_16: gpmc_a3.gpio1_19 */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_INPUT, MUX_MODE7)	/* P9_30: mcasp0_axr0.gpio3_16 */
+			AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_INPUT, MUX_MODE7)	/* P9_24: uart1_txd.gpio0_15 */
+		>;
+	};
+};
+
+&epwmss1 {
+	status = "okay";
+};
+
+&ehrpwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_lcd_pwm_backlight_pins>;
+	status = "okay";
+};
+
+&lcdc {
+	status = "okay";
+
+	blue-and-red-wiring = "straight";
+
+	//FIXME - LCD doesn't init...
+	//port {
+	//	lcdc_0: endpoint@0 {
+	//		remote-endpoint = <&panel_0>;
+	//	};
+	//};
+};
+
+&tscadc {
+	status = "okay";
+	tsc {
+		ti,wires = <4>;
+		ti,x-plate-resistance = <200>;
+		ti,coordinate-readouts = <5>;
+		ti,wire-config = <0x00 0x11 0x22 0x33>;
+		ti,charge-delay = <0x400>;
+	};
+
+	adc {
+		ti,adc-channels = <4 5 6 7>;
+	};
+};
+
+&{/} {
+	backlight: backlight {
+		status = "okay";
+		compatible = "pwm-backlight";
+		pwms = <&ehrpwm1 0 500000 0>;
+		brightness-levels = <
+			0  1  2  3  4  5  6  7  8  9
+			10 11 12 13 14 15 16 17 18 19
+			20 21 22 23 24 25 26 27 28 29
+			30 31 32 33 34 35 36 37 38 39
+			40 41 42 43 44 45 46 47 48 49
+			50 51 52 53 54 55 56 57 58 59
+			60 61 62 63 64 65 66 67 68 69
+			70 71 72 73 74 75 76 77 78 79
+			80 81 82 83 84 85 86 87 88 89
+			90 91 92 93 94 95 96 97 98 99
+			100
+		>;
+		default-brightness-level = <100>;
+	};
+
+	panel {
+		status = "okay";
+		compatible = "ti,tilcdc,panel";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bb_lcd_lcd_pins>;
+		backlight = <&backlight>;
+
+		//FIXME - LCD doesn't init...
+		//port {
+		//	panel_0: endpoint@0 {
+		//		remote-endpoint = <&lcdc_0>;
+		//	};
+		//};
+
+		panel-info {
+			ac-bias           = <255>;
+			ac-bias-intrpt    = <0>;
+			dma-burst-sz      = <16>;
+			bpp               = <16>;
+			fdd               = <0x80>;
+			sync-edge         = <0>;
+			sync-ctrl         = <1>;
+			raster-order      = <0>;
+			fifo-th           = <0>;
+		};
+		display-timings {
+			native-mode = <&timing0>;
+			/* www.newhavendisplay.com/app_notes/OTA5180A.pdf */
+			timing0: 480x272 {
+				clock-frequency = <9200000>;
+				hactive = <480>;
+				vactive = <272>;
+				hfront-porch = <8>;
+				hback-porch = <47>;
+				hsync-len = <41>;
+				vback-porch = <2>;
+				vfront-porch = <3>;
+				vsync-len = <10>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <1>;
+				pixelclk-active = <0>;
+			};
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bb_lcd_led_pins>;
+
+		led-ld0 {
+			label = "lcd:green:usr0";
+			gpios = <&gpio1 28 0>;
+			linux,default-trigger = "heartbeat";
+			default-state = "off";
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bb_lcd_keymap_pins>;
+
+		button-1 {
+			debounce_interval = <50>;
+			linux,code = <105>;
+			label = "left";
+			gpios = <&gpio1 16 0x1>;
+			gpio-key,wakeup;
+			autorepeat;
+		};
+		button-2 {
+			debounce_interval = <50>;
+			linux,code = <106>;
+			label = "right";
+			gpios = <&gpio1 17 0x1>;
+			gpio-key,wakeup;
+			autorepeat;
+		};
+		button-3 {
+			debounce_interval = <50>;
+			linux,code = <103>;
+			label = "up";
+			gpios = <&gpio1 19 0x1>;
+			gpio-key,wakeup;
+			autorepeat;
+		};
+		button-4 {
+			debounce_interval = <50>;
+			linux,code = <108>;
+			label = "down";
+			gpios = <&gpio3 16 0x1>;
+			gpio-key,wakeup;
+			autorepeat;
+		};
+		button-5 {
+			debounce_interval = <50>;
+			linux,code = <28>;
+			label = "enter";
+			gpios = <&gpio0 15 0x1>;
+			gpio-key,wakeup;
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-BONE-NH7C-01-A0.dtso b/arch/arm/boot/dts/BB-BONE-NH7C-01-A0.dtso
--- a/arch/arm/boot/dts/BB-BONE-NH7C-01-A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-BONE-NH7C-01-A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-BONE-NH7C-01-A0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P8_45_pinmux { status = "disabled"; };	/* lcd: lcd_data0 */
+	P8_46_pinmux { status = "disabled"; };	/* lcd: lcd_data1 */
+	P8_43_pinmux { status = "disabled"; };	/* lcd: lcd_data2 */
+	P8_44_pinmux { status = "disabled"; };	/* lcd: lcd_data3 */
+	P8_41_pinmux { status = "disabled"; };	/* lcd: lcd_data4 */
+	P8_42_pinmux { status = "disabled"; };	/* lcd: lcd_data5 */
+	P8_39_pinmux { status = "disabled"; };	/* lcd: lcd_data6 */
+	P8_40_pinmux { status = "disabled"; };	/* lcd: lcd_data7 */
+	P8_37_pinmux { status = "disabled"; };	/* lcd: lcd_data8 */
+	P8_38_pinmux { status = "disabled"; };	/* lcd: lcd_data9 */
+	P8_36_pinmux { status = "disabled"; };	/* lcd: lcd_data10 */
+	P8_34_pinmux { status = "disabled"; };	/* lcd: lcd_data11 */
+	P8_35_pinmux { status = "disabled"; };	/* lcd: lcd_data12 */
+	P8_33_pinmux { status = "disabled"; };	/* lcd: lcd_data13 */
+	P8_31_pinmux { status = "disabled"; };	/* lcd: lcd_data14 */
+	P8_32_pinmux { status = "disabled"; };	/* lcd: lcd_data15 */
+
+	P8_15_pinmux { status = "disabled"; };	/* gpmc_ad15.lcd_data16 */
+	P8_16_pinmux { status = "disabled"; };	/* gpmc_ad14.lcd_data17 */
+	P8_11_pinmux { status = "disabled"; };	/* gpmc_ad13.lcd_data18 */
+	P8_12_pinmux { status = "disabled"; };	/* gpmc_ad12.lcd_data19 */
+	P8_17_pinmux { status = "disabled"; };	/* gpmc_ad11.lcd_data20 */
+	P8_14_pinmux { status = "disabled"; };	/* gpmc_ad10.lcd_data21 */
+	P8_13_pinmux { status = "disabled"; };	/* gpmc_ad9.lcd_data22 */
+	P8_19_pinmux { status = "disabled"; };	/* gpmc_ad8.lcd_data23 */
+
+	P8_27_pinmux { status = "disabled"; };	/* lcd: lcd_vsync */
+	P8_29_pinmux { status = "disabled"; };	/* lcd: lcd_hsync */
+	P8_28_pinmux { status = "disabled"; };	/* lcd: lcd_pclk */
+	P8_30_pinmux { status = "disabled"; };	/* lcd: lcd_ac_bias_en */
+
+	P8_18_pinmux { status = "disabled"; };	/* lcd: enable */
+
+	P9_14_pinmux { status = "disabled"; };	/* pwm: ehrpwm1a */
+
+	P9_27_pinmux { status = "disabled"; };	/* ft5336: gpio3_15 */
+};
+
+&am33xx_pinmux {
+	bb_lcd_pwm_backlight_pins: pinmux_bb_lcd_pwm_backlight_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A2, PIN_OUTPUT_PULLDOWN, MUX_MODE6)	/* P9_14: gpmc_a2.ehrpwm1a */
+		>;
+	};
+
+	bb_lcd_lcd_pins: pinmux_bb_lcd_lcd_pins {
+		pinctrl-single,pins = <
+			/*LCD enable */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_CLK, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpmc_clk_mux0.gpio2_1 */
+
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD15, PIN_OUTPUT, MUX_MODE1)	/* P8_15: gpmc_ad15.lcd_data16 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD14, PIN_OUTPUT, MUX_MODE1)	/* P8_16: gpmc_ad14.lcd_data17 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD13, PIN_OUTPUT, MUX_MODE1)	/* P8_11: gpmc_ad13.lcd_data18 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD12, PIN_OUTPUT, MUX_MODE1)	/* P8_12: gpmc_ad12.lcd_data19 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD11, PIN_OUTPUT, MUX_MODE1)	/* P8_17: gpmc_ad11.lcd_data20 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD10, PIN_OUTPUT, MUX_MODE1)	/* P8_14: gpmc_ad10.lcd_data21 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD9, PIN_OUTPUT, MUX_MODE1)	/* P8_13: gpmc_ad9.lcd_data22 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_AD8, PIN_OUTPUT, MUX_MODE1)	/* P8_19: gpmc_ad8.lcd_data23 */
+
+			AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0)
+		>;
+	};
+
+	edt_ft5x06_pins: pinmux_edt_ft5x06_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_INPUT_PULLDOWN, MUX_MODE7)	/* mcasp0_fsr.gpio3_19 */
+		>;
+	};
+};
+
+&epwmss1 {
+	status = "okay";
+};
+
+&ehrpwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_lcd_pwm_backlight_pins>;
+	status = "okay";
+};
+
+&lcdc {
+	status = "okay";
+
+	blue-and-red-wiring = "crossed";
+
+	//FIXME - LCD doesn't init...
+	//port {
+	//	lcdc_0: endpoint@0 {
+	//		remote-endpoint = <&panel_0>;
+	//	};
+	//};
+};
+
+&i2c2 {
+	status = "okay";
+
+	clock-frequency = <100000>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	edt-ft5x06@38 {
+		status = "okay";
+		compatible = "edt,edt-ft5406";
+		reg = <0x38>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&edt_ft5x06_pins>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <19 0>;
+		//reset-gpios = <&gpio3 14 GPIO_ACTIVE_LOW>;
+
+		touchscreen-size-x = <800>;
+		touchscreen-size-y = <480>;
+		//touchscreen-swapped-x-y;
+	};
+};
+
+&{/} {
+	backlight: backlight {
+		status = "okay";
+		compatible = "pwm-backlight";
+		pwms = <&ehrpwm1 0 500000 0>;
+		brightness-levels = <
+			0  1  2  3  4  5  6  7  8  9
+			10 11 12 13 14 15 16 17 18 19
+			20 21 22 23 24 25 26 27 28 29
+			30 31 32 33 34 35 36 37 38 39
+			40 41 42 43 44 45 46 47 48 49
+			50 51 52 53 54 55 56 57 58 59
+			60 61 62 63 64 65 66 67 68 69
+			70 71 72 73 74 75 76 77 78 79
+			80 81 82 83 84 85 86 87 88 89
+			90 91 92 93 94 95 96 97 98 99
+			100
+		>;
+		default-brightness-level = <100>;
+	};
+
+	/* NHD-7.0-800480EF-ATXL# */
+	panel {
+		status = "okay";
+		compatible = "ti,tilcdc,panel";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bb_lcd_lcd_pins>;
+		backlight = <&backlight>;
+		enable-gpios = <&gpio2 1 0>;
+
+		//FIXME - LCD doesn't init...
+		//port {
+		//	panel_0: endpoint@0 {
+		//		remote-endpoint = <&lcdc_0>;
+		//	};
+		//};
+
+		panel-info {
+			ac-bias           = <255>;
+			ac-bias-intrpt    = <0>;
+			dma-burst-sz      = <16>;
+			bpp               = <32>;
+			fdd               = <0x80>;
+			tft-alt-mode      = <0>;
+			stn-565-mode      = <0>;
+			mono-8bit-mode    = <0>;
+			sync-edge         = <0>;
+			sync-ctrl         = <0>;
+			raster-order      = <0>;
+			fifo-th           = <0>;
+		};
+
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: 800x480 {
+				clock-frequency = <45000000>;
+				hactive = <800>;
+				vactive = <480>;
+				hfront-porch = <40>;
+				hback-porch = <40>;
+				hsync-len = <48>;
+				vback-porch = <29>;
+				vfront-porch = <13>;
+				vsync-len = <3>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-CAPE-DISP-CT4-00A0.dtso b/arch/arm/boot/dts/BB-CAPE-DISP-CT4-00A0.dtso
--- a/arch/arm/boot/dts/BB-CAPE-DISP-CT4-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-CAPE-DISP-CT4-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-CAPE-DISP-CT4-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P8_45_pinmux { status = "disabled"; };	/* lcd: lcd_data0 */
+	P8_46_pinmux { status = "disabled"; };	/* lcd: lcd_data1 */
+	P8_43_pinmux { status = "disabled"; };	/* lcd: lcd_data2 */
+	P8_44_pinmux { status = "disabled"; };	/* lcd: lcd_data3 */
+	P8_41_pinmux { status = "disabled"; };	/* lcd: lcd_data4 */
+	P8_42_pinmux { status = "disabled"; };	/* lcd: lcd_data5 */
+	P8_39_pinmux { status = "disabled"; };	/* lcd: lcd_data6 */
+	P8_40_pinmux { status = "disabled"; };	/* lcd: lcd_data7 */
+	P8_37_pinmux { status = "disabled"; };	/* lcd: lcd_data8 */
+	P8_38_pinmux { status = "disabled"; };	/* lcd: lcd_data9 */
+	P8_36_pinmux { status = "disabled"; };	/* lcd: lcd_data10 */
+	P8_34_pinmux { status = "disabled"; };	/* lcd: lcd_data11 */
+	P8_35_pinmux { status = "disabled"; };	/* lcd: lcd_data12 */
+	P8_33_pinmux { status = "disabled"; };	/* lcd: lcd_data13 */
+	P8_31_pinmux { status = "disabled"; };	/* lcd: lcd_data14 */
+	P8_32_pinmux { status = "disabled"; };	/* lcd: lcd_data15 */
+
+	P8_27_pinmux { status = "disabled"; };	/* lcd: lcd_vsync */
+	P8_29_pinmux { status = "disabled"; };	/* lcd: lcd_hsync */
+	P8_28_pinmux { status = "disabled"; };	/* lcd: lcd_pclk */
+	P8_30_pinmux { status = "disabled"; };	/* lcd: lcd_ac_bias_en */
+
+	P9_28_pinmux { status = "disabled"; };	/* pwm: eCAP2_in_PWM2_out */
+
+	P9_29_pinmux { status = "disabled"; };	/* ft5336: gpio3_15 */
+	P9_31_pinmux { status = "disabled"; };	/* ft5336: gpio3_14 */
+};
+
+&am33xx_pinmux {
+	bb_lcd_pwm_backlight_pins: pinmux_bb_lcd_pwm_backlight_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN,  MUX_MODE4) /* mcasp0_ahclkr.eCAP2_in_PWM2_out */
+		>;
+	};
+
+	bb_lcd_lcd_pins: pinmux_bb_lcd_lcd_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+
+			AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT, MUX_MODE0)
+		>;
+	};
+
+	edt_ft5336_ts_pins: pinmux_edt_ft5336_ts_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT_PULLDOWN, MUX_MODE7)	/* mcasp0_fsx.gpio3_15 */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT_PULLDOWN, MUX_MODE7)	/* mcasp0_aclkx.gpio3_14 */
+		>;
+	};
+};
+
+&epwmss2 {
+	status = "okay";
+};
+
+&ecap2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_lcd_pwm_backlight_pins>;
+	status = "okay";
+};
+
+&lcdc {
+	status = "okay";
+
+	blue-and-red-wiring = "straight";
+
+	//FIXME - LCD doesn't init...
+	//port {
+	//	lcdc_0: endpoint@0 {
+	//		remote-endpoint = <&panel_0>;
+	//	};
+	//};
+};
+
+&i2c2 {
+	status = "okay";
+
+	/* this is the configuration part */
+	clock-frequency = <100000>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	edt-ft5336@38 {
+		status = "okay";
+		compatible = "edt,edt-ft5336", "edt,edt-ft5306", "edt,edt-ft5x06";
+		reg = <0x38>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&edt_ft5336_ts_pins>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <15 0>;
+		reset-gpios = <&gpio3 14 GPIO_ACTIVE_LOW>;
+
+		touchscreen-size-x = <272>;
+		touchscreen-size-y = <480>;
+		touchscreen-swapped-x-y;
+	};
+};
+
+&{/} {
+	backlight: backlight {
+		status = "okay";
+		compatible = "pwm-backlight";
+		pwms = <&ecap2 0 500000 0>;
+		brightness-levels = <
+			0  1  2  3  4  5  6  7  8  9
+			10 11 12 13 14 15 16 17 18 19
+			20 21 22 23 24 25 26 27 28 29
+			30 31 32 33 34 35 36 37 38 39
+			40 41 42 43 44 45 46 47 48 49
+			50 51 52 53 54 55 56 57 58 59
+			60 61 62 63 64 65 66 67 68 69
+			70 71 72 73 74 75 76 77 78 79
+			80 81 82 83 84 85 86 87 88 89
+			90 91 92 93 94 95 96 97 98 99
+			100
+		>;
+		default-brightness-level = <50>;
+	};
+
+	panel {
+		status = "okay";
+		compatible = "ti,tilcdc,panel";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bb_lcd_lcd_pins>;
+		backlight = <&backlight>;
+
+		//FIXME - LCD doesn't init...
+		//port {
+		//	panel_0: endpoint@0 {
+		//		remote-endpoint = <&lcdc_0>;
+		//	};
+		//};
+
+		panel-info {
+			ac-bias           = <255>;
+			ac-bias-intrpt    = <0>;
+			dma-burst-sz      = <16>;
+			bpp               = <16>;
+			fdd               = <0x80>;
+			tft-alt-mode      = <0>;
+			stn-565-mode      = <0>;
+			mono-8bit-mode    = <0>;
+			sync-edge         = <0>;
+			sync-ctrl         = <1>;
+			raster-order      = <0>;
+			fifo-th           = <0>;
+		};
+		/* ILI6480 */
+		display-timings {
+			native-mode = <&timing0>;
+			timing0: 480x272 {
+				clock-frequency = <9000000>;
+				hactive = <480>;
+				vactive = <272>;
+				hfront-porch = <5>;
+				hback-porch = <40>;
+				hsync-len = <1>;
+				vback-porch = <8>;
+				vfront-porch = <8>;
+				vsync-len = <1>;
+				hsync-active = <0>;
+				vsync-active = <0>;
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-HDMI-TDA998x-00A0.dtso b/arch/arm/boot/dts/BB-HDMI-TDA998x-00A0.dtso
--- a/arch/arm/boot/dts/BB-HDMI-TDA998x-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-HDMI-TDA998x-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/display/tda998x.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-HDMI-TDA998x-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_25_pinmux { status = "disabled"; };	/* mcasp0_ahclkx */
+	P9_28_pinmux { status = "disabled"; };	/* mcasp0_axr2 */
+	P9_29_pinmux { status = "disabled"; };	/* mcasp0_fsx */
+	P9_31_pinmux { status = "disabled"; };	/* mcasp0_aclkx */
+	P8_45_pinmux { status = "disabled"; };	/* lcd_data0 */
+	P8_46_pinmux { status = "disabled"; };	/* lcd_data1 */
+	P8_43_pinmux { status = "disabled"; };	/* lcd_data2 */
+	P8_44_pinmux { status = "disabled"; };	/* lcd_data3 */
+	P8_41_pinmux { status = "disabled"; };	/* lcd_data4 */
+	P8_42_pinmux { status = "disabled"; };	/* lcd_data5 */
+	P8_39_pinmux { status = "disabled"; };	/* lcd_data6 */
+	P8_40_pinmux { status = "disabled"; };	/* lcd_data7 */
+	P8_37_pinmux { status = "disabled"; };	/* lcd_data8 */
+	P8_38_pinmux { status = "disabled"; };	/* lcd_data9 */
+	P8_36_pinmux { status = "disabled"; };	/* lcd_data10 */
+	P8_34_pinmux { status = "disabled"; };	/* lcd_data11 */
+	P8_35_pinmux { status = "disabled"; };	/* lcd_data12 */
+	P8_33_pinmux { status = "disabled"; };	/* lcd_data13 */
+	P8_31_pinmux { status = "disabled"; };	/* lcd_data14 */
+	P8_32_pinmux { status = "disabled"; };	/* lcd_data15 */
+	P8_27_pinmux { status = "disabled"; };	/* lcd_vsync */
+	P8_29_pinmux { status = "disabled"; };	/* lcd_hsync */
+	P8_28_pinmux { status = "disabled"; };	/* lcd_pclk */
+	P8_30_pinmux { status = "disabled"; };	/* lcd_ac_bias_en */
+};
+
+&am33xx_pinmux {
+	nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLUP, MUX_MODE7)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+		>;
+	};
+
+	nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE7)
+		>;
+	};
+
+	mcasp0_pins: mcasp0_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT_PULLUP, MUX_MODE0) /* mcasp0_ahcklx.mcasp0_ahclkx */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_OUTPUT_PULLDOWN, MUX_MODE2) /* mcasp0_ahclkr.mcasp0_axr2*/
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_OUTPUT_PULLUP, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A11, PIN_OUTPUT_PULLDOWN, MUX_MODE7) /* gpmc_a11.GPIO1_27 */
+		>;
+	};
+};
+
+&lcdc {
+	status = "okay";
+
+	/* If you want to get 24 bit RGB and 16 BGR mode instead of
+	 * current 16 bit RGB and 24 BGR modes, set the propety
+	 * below to "crossed" and uncomment the video-ports -property
+	 * in tda19988 node.
+	 */
+	blue-and-red-wiring = "straight";
+
+	port {
+		lcdc_0: endpoint@0 {
+			remote-endpoint = <&hdmi_0>;
+		};
+	};
+};
+
+&i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	tda19988: tda19988@70 {
+		compatible = "nxp,tda998x";
+		reg = <0x70>;
+		nxp,calib-gpios = <&gpio1 25 0>;
+		interrupts-extended = <&gpio1 25 IRQ_TYPE_LEVEL_LOW>;
+
+		pinctrl-names = "default", "off";
+		pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+		pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
+		/* Convert 24bit BGR to RGB, e.g. cross red and blue wiring */
+		/* video-ports = <0x234501>; */
+
+		#sound-dai-cells = <0>;
+		audio-ports = <	TDA998x_I2S	0x03>;
+
+		ports {
+			port@0 {
+				hdmi_0: endpoint@0 {
+					remote-endpoint = <&lcdc_0>;
+				};
+			};
+		};
+	};
+};
+
+&mcasp0 {
+	#sound-dai-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcasp0_pins>;
+	status = "okay";
+	op-mode = <0>;	/* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+	serial-dir = <	/* 0: INACTIVE, 1: TX, 2: RX */
+			0 0 1 0
+		>;
+	tx-num-evt = <32>;
+	rx-num-evt = <32>;
+};
+
+&{/} {
+	clk_mcasp0_fixed: clk_mcasp0_fixed {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <24576000>;
+	};
+
+	clk_mcasp0: clk_mcasp0 {
+		#clock-cells = <0>;
+		compatible = "gpio-gate-clock";
+		clocks = <&clk_mcasp0_fixed>;
+		enable-gpios = <&gpio1 27 0>; /* BeagleBone Black Clk enable on GPIO1_27 */
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "TI BeagleBone Black";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&dailink0_master>;
+		simple-audio-card,frame-master = <&dailink0_master>;
+
+		dailink0_master: simple-audio-card,cpu {
+			sound-dai = <&mcasp0>;
+			clocks = <&clk_mcasp0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&tda19988>;
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-I2C1-MCP7940X-00A0.dtso b/arch/arm/boot/dts/BB-I2C1-MCP7940X-00A0.dtso
--- a/arch/arm/boot/dts/BB-I2C1-MCP7940X-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-I2C1-MCP7940X-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2015 Robert Nelson <robertcnelson@gmail.com>
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-I2C1-MCP7940X-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_17_pinmux { status = "disabled"; };	/* spi0_d1.i2c1_sda */
+	P9_18_pinmux { status = "disabled"; };	/* spi0_cs0.i2c1_scl */
+	P8_26_pinmux { status = "disabled"; };	/* rtc: gpio1_29 */
+};
+
+&{/} {
+	aliases {
+		rtc0 = &extrtc;
+		/* find /sys/firmware/devicetree/ | grep rtc@ */
+		rtc1 = "/ocp/interconnect@44c00000/segment@200000/target-module@3e000/rtc@0";
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bb_gpio1_29_pins>;
+
+		rtc_mfp@1 {
+			label = "rtc_mfp";
+			gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>;
+			linux,code = <143>; /* System Wake Up */
+			gpio-key,wakeup;
+		};
+	};
+};
+
+&am33xx_pinmux {
+	bb_gpio1_29_pins: pinmux_bb_gpio1_29_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_CSN0, PIN_INPUT, MUX_MODE7) /* gpmc_csn0.gpio1_29 */
+		>;
+	};
+
+	bb_i2c1_pins: pinmux_bb_i2c1_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_SPI0_D1, SLEWCTRL_SLOW | PIN_INPUT_PULLUP, MUX_MODE2)		/* spi0_d1.i2c1_sda */
+			AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, SLEWCTRL_SLOW | PIN_INPUT_PULLUP, MUX_MODE2)	/* spi0_cs0.i2c1_scl */
+		>;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_i2c1_pins>;
+
+	clock-frequency = <100000>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	extrtc: mcp7940x@68 {
+		status = "okay";
+		compatible = "microchip,mcp7940x";
+		reg = <0x68>;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-I2C1-RTC-DS3231.dtso b/arch/arm/boot/dts/BB-I2C1-RTC-DS3231.dtso
--- a/arch/arm/boot/dts/BB-I2C1-RTC-DS3231.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-I2C1-RTC-DS3231.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 Sam Cohen <samc1213@gmail.com>
+ *
+ * Based on BB-I2C2-RTC-DS3231.dts:
+ * Copyright (C) 2019 Tomas Arturo Herrera Castro <taherrera@uc.cl>
+ *
+ * DTS file for DS3231 Real Time Clock, running on the I2C1 interface. Also see
+ * BB-I2C2-RTC-DS3231.dts to run this RTC on I2C2.
+ *
+ * Tested on BeagleBone Black Wireless
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-I2C1-RTC-DS3231.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_17_pinmux { status = "disabled"; };	/* spi0_d1.i2c1_sda */
+	P9_18_pinmux { status = "disabled"; };	/* spi0_cs0.i2c1_scl */
+};
+
+&{/} {
+	aliases {
+		rtc0 = &extrtc;
+		/* find /sys/firmware/devicetree/ | grep rtc@ */
+		rtc1 = "/ocp/interconnect@44c00000/segment@200000/target-module@3e000/rtc@0";
+	};
+};
+
+&am33xx_pinmux {
+	bb_i2c1_pins: pinmux_bb_i2c1_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_SPI0_D1, SLEWCTRL_SLOW | PIN_INPUT_PULLUP, MUX_MODE2)		/* spi0_d1.i2c1_sda */
+			AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, SLEWCTRL_SLOW | PIN_INPUT_PULLUP, MUX_MODE2)	/* spi0_cs0.i2c1_scl */
+		>;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_i2c1_pins>;
+
+	clock-frequency = <100000>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	extrtc: ds3231@68 {
+		status = "okay";
+		compatible = "maxim,ds3231";
+		reg = <0x68>;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-I2C1-RTC-PCF8563.dtso b/arch/arm/boot/dts/BB-I2C1-RTC-PCF8563.dtso
--- a/arch/arm/boot/dts/BB-I2C1-RTC-PCF8563.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-I2C1-RTC-PCF8563.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2018 Robert Nelson <robertcnelson@gmail.com>
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-I2C1-RTC-PCF8563.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_17_pinmux { status = "disabled"; };	/* spi0_d1.i2c1_sda */
+	P9_18_pinmux { status = "disabled"; };	/* spi0_cs0.i2c1_scl */
+};
+
+&{/} {
+	aliases {
+		rtc0 = &extrtc;
+		/* find /sys/firmware/devicetree/ | grep rtc@ */
+		rtc1 = "/ocp/interconnect@44c00000/segment@200000/target-module@3e000/rtc@0";
+	};
+};
+
+&am33xx_pinmux {
+	bb_i2c1_pins: pinmux_bb_i2c1_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_SPI0_D1, SLEWCTRL_SLOW | PIN_INPUT_PULLUP, MUX_MODE2)		/* spi0_d1.i2c1_sda */
+			AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, SLEWCTRL_SLOW | PIN_INPUT_PULLUP, MUX_MODE2)	/* spi0_cs0.i2c1_scl */
+		>;
+	};
+};
+
+&i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_i2c1_pins>;
+
+	clock-frequency = <100000>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	extrtc: pcf8563@51 {
+		status = "okay";
+		compatible = "nxp,pcf8563";
+		reg = <0x51>;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-I2C2-BME680.dtso b/arch/arm/boot/dts/BB-I2C2-BME680.dtso
--- a/arch/arm/boot/dts/BB-I2C2-BME680.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-I2C2-BME680.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2022 Robert Nelson <robertcnelson@gmail.com>
+ */
+
+/dts-v1/;
+/plugin/;
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-I2C2-BME680.kernel = __TIMESTAMP__;
+	};
+};
+
+&i2c2 {
+	status = "okay";
+
+	clock-frequency = <100000>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	bme680@76 {
+		status = "okay";
+		compatible = "bosch,bme680";
+		reg = <0x76>;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-I2C2-MPU6050.dtso b/arch/arm/boot/dts/BB-I2C2-MPU6050.dtso
--- a/arch/arm/boot/dts/BB-I2C2-MPU6050.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-I2C2-MPU6050.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2022 Robert Nelson <robertcnelson@gmail.com>
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-I2C2-MPU6050.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_12_pinmux { status = "disabled"; };
+};
+
+&am33xx_pinmux {
+	mpu6050_pins: pinmux_mpu6050_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT, MUX_MODE7) /* gpio1_28 */
+		>;
+	};
+};
+
+&i2c2 {
+	status = "okay";
+
+	clock-frequency = <400000>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	imu@68 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&mpu6050_pins>;
+		compatible = "invensense,mpu6050";
+		reg = <0x68>;
+		interrupt-parent = <&gpio1>;
+		interrupts = <28 IRQ_TYPE_EDGE_RISING>;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-LCD-ADAFRUIT-24-SPI1-00A0.dtso b/arch/arm/boot/dts/BB-LCD-ADAFRUIT-24-SPI1-00A0.dtso
--- a/arch/arm/boot/dts/BB-LCD-ADAFRUIT-24-SPI1-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-LCD-ADAFRUIT-24-SPI1-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,180 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Copyright (C) 2018 Drew Fustini <drew@beagleboard.org>
+ * Copyright (C) 2019 Mark A. Yoder <mark.a.yoder@beagleboard.org>
+ *
+ * Adafruit 2.4" TFT LCD on SPI1 bus using tinydrm ili9341 driver
+ *
+ * DOCUMENTATION:
+ * --------------
+ * This file was copied from src/arm/BB-SPIDEV1-00A0.dts and modified
+ * by Drew Fustini based on an exmample from David Lechner.
+ * Later modified by Mark A. Yoder for the 2.4" LCD.
+ *
+ * This is the Adafruit 2.4" TFT LCD:
+ * https://www.adafruit.com/product/2478
+ *
+ * It should be connected to BeagleBone SPI1 bus:
+ *
+ *   P9.16 <--> lite (pwm) [OPTIONAL]
+ *   P9.23 <--> lite (gpio) [OPTIONAL]
+ *   P9.25 <--> reset
+ *   P9.27 <--> dc
+ *   P9.28 <--> tft_cs
+ *   P9.29 <--> miso
+ *   P9.30 <--> mosi
+ *   P9.31 <--> clk
+ *
+ * This overlay will load the mainline tinydrm ili9341 driver by David Lechner:
+ * https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/tiny/ili9341.c
+ *
+ * Tested with 4.19.59-ti-r26 kernel on Debian 10.1 image
+ *
+ * Run libdrm modetest for colorbar test based on instructions from:
+ * https://github.com/notro/tinydrm/wiki/Development#modetest
+ *
+ * modetest -M "ili9341" -c #this will display connector id
+ * modetest -M "ili9341" -s 28:128x160 #connector id and resolution
+ * # you should now see a color bar on the LCD
+ *
+ * Mailing list post with more information:
+ * https://groups.google.com/d/msg/beagleboard/GuMQIP_XCW0/b3lxbx_8AwAJ
+ *
+ * Discussion with notro on how to test tinydrm driver:
+ * https://github.com/notro/tinydrm/issues/1#issuecomment-367279037
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-LCD-ADAFRUIT-24-SPI1-00A0 = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_25_pinmux { status = "disabled"; };	/* lcd reset */
+	P9_16_pinmux { status = "disabled"; };  /* lcd pwm backlight (OPTIONAL) */
+	P9_27_pinmux { status = "disabled"; };	/* lcd dc */
+	P9_28_pinmux { status = "disabled"; };	/* spi1_cs0 */
+	P9_29_pinmux { status = "disabled"; };	/* spi1_d0 */
+	P9_30_pinmux { status = "disabled"; };	/* spi1_d1 */
+	P9_31_pinmux { status = "disabled"; };	/* spi1_sclk */
+};
+
+&am33xx_pinmux {
+	/* default state has all gpios released and mode set to uart1 */
+	/* See page 1446 of am35xx TRM */
+	bb_spi1_pins: pinmux_bb_spi1_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT, MUX_MODE3)	/* mcasp0_aclkx.spi1_sclk */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT, MUX_MODE3)	/* mcasp0_fsx.spi1_d0 */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_INPUT, MUX_MODE3)	/* mcasp0_axr0.spi1_d1 */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_INPUT, MUX_MODE3)	/* mcasp0_ahclkr.spi1_cs0 */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpio, dc */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKX, PIN_OUTPUT_PULLUP, MUX_MODE7)	/* gpio, reset */
+		>;
+	};
+
+	backlight_pwm_pins: pinmux_backlight_pwm_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_A3, PIN_OUTPUT, MUX_MODE6) /* gpmc_a2.ehrpwm1b */
+		>;
+	};  /* gpmc_a2.ehrpwm1b */
+};
+
+&epwmss1 {
+	status = "okay";
+};
+
+&ehrpwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&backlight_pwm_pins>;
+	status = "okay";
+};
+
+&spi1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_spi1_pins>;
+
+	channel@0{
+		status = "disabled";
+		reg = <0>;
+	};
+
+	display@0{
+		status = "okay";
+		compatible = "adafruit,yx240qv29", "ilitek,ili9341";
+		reg = <0>;
+		spi-max-frequency = <32000000>;
+		dc-gpios    = <&gpio3 19 0>;   // lcd dc    P9.27 gpio3[19]
+		reset-gpios = <&gpio3 21 0>;   // lcd reset P9.25 gpio3[21]
+		// backlight is optional
+		// choose either pwm or gpio control
+		//backlight = <&backlight_gpio>; // lcd lite  P9.23 gpio1[17]
+		backlight = <&backlight_pwm>;    // lcd lite  P9.16 gpmc_a2.ehrpwm1b
+		// refer to https://elinux.org/Beagleboard:Cape_Expansion_Headers
+		// rotation is optional
+		rotation = <270>;
+	};
+};
+
+&{/} {
+	bl_reg: backlight-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "backlight";
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	/* backlight is optional */
+	backlight_gpio: backlight_gpio {
+		compatible = "gpio-backlight";
+		gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
+		// connect lcd lite pin to P9.23 which is gpio1[17]
+		// refer to https://elinux.org/Beagleboard:Cape_Expansion_Headers
+	};
+
+	/*
+	 * Turn the PWM backlight on by setting bl_power to 0:
+	 * echo 0 > /sys/class/backlight/backlight_pwm/bl_power
+	 */
+	backlight_pwm: backlight_pwm {
+		// P9.16 <--> lite (pwm-backlight EHRPWM1B)
+		status = "okay";
+		compatible = "pwm-backlight";
+		pwms = <&ehrpwm1 1 500000 0>;	// First digit: 0 for A side of pwm, 1 for B side
+										// 500000 is the PWM period in ns
+										// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/pwm/pwm.txt
+		brightness-levels = <
+			0  1  2  3  4  5  6  7  8  9
+			10 11 12 13 14 15 16 17 18 19
+			20 21 22 23 24 25 26 27 28 29
+			30 31 32 33 34 35 36 37 38 39
+			40 41 42 43 44 45 46 47 48 49
+			50 51 52 53 54 55 56 57 58 59
+			60 61 62 63 64 65 66 67 68 69
+			70 71 72 73 74 75 76 77 78 79
+			80 81 82 83 84 85 86 87 88 89
+			90 91 92 93 94 95 96 97 98 99
+			100
+		>;
+		default-brightness-level = <100>;
+		power-supply = <&bl_reg>;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-NHDMI-TDA998x-00A0.dtso b/arch/arm/boot/dts/BB-NHDMI-TDA998x-00A0.dtso
--- a/arch/arm/boot/dts/BB-NHDMI-TDA998x-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-NHDMI-TDA998x-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/display/tda998x.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-NHDMI-TDA998x-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P8_45_pinmux { status = "disabled"; };	/* lcd_data0 */
+	P8_46_pinmux { status = "disabled"; };	/* lcd_data1 */
+	P8_43_pinmux { status = "disabled"; };	/* lcd_data2 */
+	P8_44_pinmux { status = "disabled"; };	/* lcd_data3 */
+	P8_41_pinmux { status = "disabled"; };	/* lcd_data4 */
+	P8_42_pinmux { status = "disabled"; };	/* lcd_data5 */
+	P8_39_pinmux { status = "disabled"; };	/* lcd_data6 */
+	P8_40_pinmux { status = "disabled"; };	/* lcd_data7 */
+	P8_37_pinmux { status = "disabled"; };	/* lcd_data8 */
+	P8_38_pinmux { status = "disabled"; };	/* lcd_data9 */
+	P8_36_pinmux { status = "disabled"; };	/* lcd_data10 */
+	P8_34_pinmux { status = "disabled"; };	/* lcd_data11 */
+	P8_35_pinmux { status = "disabled"; };	/* lcd_data12 */
+	P8_33_pinmux { status = "disabled"; };	/* lcd_data13 */
+	P8_31_pinmux { status = "disabled"; };	/* lcd_data14 */
+	P8_32_pinmux { status = "disabled"; };	/* lcd_data15 */
+	P8_27_pinmux { status = "disabled"; };	/* lcd_vsync */
+	P8_29_pinmux { status = "disabled"; };	/* lcd_hsync */
+	P8_28_pinmux { status = "disabled"; };	/* lcd_pclk */
+	P8_30_pinmux { status = "disabled"; };	/* lcd_ac_bias_en */
+};
+
+&am33xx_pinmux {
+	nxp_hdmi_bonelt_pins: nxp_hdmi_bonelt_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLUP, MUX_MODE7)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA0, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA1, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA2, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA3, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA4, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA5, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA6, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA7, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA10, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA11, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA12, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA13, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA14, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_DATA15, PIN_OUTPUT, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_VSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_HSYNC, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_PCLK, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+			AM33XX_PADCONF(AM335X_PIN_LCD_AC_BIAS_EN, PIN_OUTPUT_PULLDOWN, MUX_MODE0)
+		>;
+	};
+
+	nxp_hdmi_bonelt_off_pins: nxp_hdmi_bonelt_off_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR0, PIN_OUTPUT_PULLDOWN, MUX_MODE7)
+		>;
+	};
+};
+
+&lcdc {
+	status = "okay";
+
+	/* If you want to get 24 bit RGB and 16 BGR mode instead of
+	 * current 16 bit RGB and 24 BGR modes, set the propety
+	 * below to "crossed" and uncomment the video-ports -property
+	 * in tda19988 node.
+	 */
+	blue-and-red-wiring = "straight";
+
+	port {
+		lcdc_0: endpoint@0 {
+			remote-endpoint = <&hdmi_0>;
+		};
+	};
+};
+
+&i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	tda19988: tda19988@70 {
+		compatible = "nxp,tda998x";
+		reg = <0x70>;
+		nxp,calib-gpios = <&gpio1 25 0>;
+		interrupts-extended = <&gpio1 25 IRQ_TYPE_LEVEL_LOW>;
+
+		pinctrl-names = "default", "off";
+		pinctrl-0 = <&nxp_hdmi_bonelt_pins>;
+		pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>;
+
+		/* Convert 24bit BGR to RGB, e.g. cross red and blue wiring */
+		/* video-ports = <0x234501>; */
+
+		ports {
+			port@0 {
+				hdmi_0: endpoint@0 {
+					remote-endpoint = <&lcdc_0>;
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BBORG_COMMS-00A2.dtso b/arch/arm/boot/dts/BBORG_COMMS-00A2.dtso
--- a/arch/arm/boot/dts/BBORG_COMMS-00A2.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BBORG_COMMS-00A2.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012,2019 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2015 Robert Nelson <robertcnelson@gmail.com>
+ * Copyright (C) 2015 Sebastian Jegerås
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BBORG_COMMS-00A2.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_24_pinmux { status = "disabled"; };	/* P9_24: uart1_txd.d_can1_rx */
+	P9_26_pinmux { status = "disabled"; };	/* P9_26: uart1_rxd.d_can1_tx */
+	P9_13_pinmux { status = "disabled"; };	/* P9_13: gpmc_wpn.uart4_txd_mux2 */
+	P9_11_pinmux { status = "disabled"; };	/* P9_11: gpmc_wait0.uart4_rxd_mux2 */
+};
+
+&bone_can_1 {
+	status = "okay";
+};
+
+&bone_uart_4 {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BBORG_FAN-A000.dtso b/arch/arm/boot/dts/BBORG_FAN-A000.dtso
--- a/arch/arm/boot/dts/BBORG_FAN-A000.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BBORG_FAN-A000.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020 Robert Nelson <robercnelson@gmail.com>
+ */
+
+/dts-v1/;
+/plugin/;
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BBORG_FAN-A000.kernel = __TIMESTAMP__;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BBORG_RELAY-00A2.dtso b/arch/arm/boot/dts/BBORG_RELAY-00A2.dtso
--- a/arch/arm/boot/dts/BBORG_RELAY-00A2.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BBORG_RELAY-00A2.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2015 Robert Nelson <robertcnelson@gmail.com>
+ * Copyright (C) 2019 Amilcar Lucas <amilcar.lucas@iav.de>
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BBORG_RELAY-00A2.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_41_pinmux { status = "disabled"; };	/* P9_41: gpmc_a0.gpio0_20 */
+	P9_42_pinmux { status = "disabled"; };	/* P9_42: gpmc_a1.gpio0_07 */
+	P9_30_pinmux { status = "disabled"; };	/* P9_30: gpmc_be1n.gpio3_16 */
+	P9_27_pinmux { status = "disabled"; };	/* P9_27: mcasp0_fsr.gpio3_19 */
+};
+
+&am33xx_pinmux {
+	bb_gpio_relay_pins: pinmux_bb_gpio_relay_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_XDMA_EVENT_INTR1, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* P9_41: Relay1 */
+			AM33XX_PADCONF(AM335X_PIN_ECAP0_IN_PWM0_OUT, PIN_OUTPUT_PULLDOWN, MUX_MODE7)	/* P9_42: Relay2 */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_OUTPUT_PULLDOWN, MUX_MODE7)		/* P9_30: Relay3 */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_FSR, PIN_OUTPUT_PULLDOWN, MUX_MODE7)		/* P9_27: Relay4 */
+		>;
+	};
+};
+
+&{/} {
+	leds {
+		pinctrl-names = "default";
+		pinctrl-0 = <&bb_gpio_relay_pins>;
+
+		compatible = "gpio-leds";
+
+		jp@1 {
+			label = "relay-jp1";
+			gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+			default-state = "keep";
+		};
+
+		jp@2 {
+			label = "relay-jp2";
+			gpios = <&gpio0 07 GPIO_ACTIVE_HIGH>;
+			default-state = "keep";
+		};
+
+		jp@3 {
+			label = "relay-jp3";
+			gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>;
+			default-state = "keep";
+		};
+
+		jp@4 {
+			label = "relay-jp4";
+			gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
+			default-state = "keep";
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-SPIDEV0-00A0.dtso b/arch/arm/boot/dts/BB-SPIDEV0-00A0.dtso
--- a/arch/arm/boot/dts/BB-SPIDEV0-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-SPIDEV0-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Virtual cape for SPI0 on connector pins P9.22 P9.21 P9.18 P9.17
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-SPIDEV0-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_17_pinmux { status = "disabled"; };	/* P9_17 (A16) spi0_cs0.spi0_cs0 */
+	P9_18_pinmux { status = "disabled"; };	/* P9_18 (B16) spi0_d1.spi0_d1 */
+	P9_21_pinmux { status = "disabled"; };	/* P9_21 (B17) spi0_d0.spi0_d0 */
+	P9_22_pinmux { status = "disabled"; };	/* P9_22 (A17) spi0_sclk.spi0_sclk */
+};
+
+&am33xx_pinmux {
+	bb_spi0_pins: pinmux_bb_spi0_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE0)	/* P9_22 (A17) spi0_sclk.spi0_sclk */
+			AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_INPUT, MUX_MODE0)	/* P9_21 (B17) spi0_d0.spi0_d0 */
+			AM33XX_PADCONF(AM335X_PIN_SPI0_D1, PIN_INPUT, MUX_MODE0)	/* P9_18 (B16) spi0_d1.spi0_d1 */
+			AM33XX_PADCONF(AM335X_PIN_SPI0_CS0, PIN_INPUT, MUX_MODE0)	/* P9_17 (A16) spi0_cs0.spi0_cs0 */
+		>;
+	};
+};
+
+&spi0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_spi0_pins>;
+
+	/*
+	 * Select the D0 pin as output and D1 as
+	 * input. The default is D0 as input and
+	 * D1 as output.
+	 */
+	//ti,pindir-d0-out-d1-in;
+
+	channel@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/0.0";
+
+		reg = <0>;
+		spi-max-frequency = <16000000>;
+		spi-cpha;
+	};
+
+	channel@1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/0.1";
+
+		reg = <1>;
+		spi-max-frequency = <16000000>;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-SPIDEV1-00A0.dtso b/arch/arm/boot/dts/BB-SPIDEV1-00A0.dtso
--- a/arch/arm/boot/dts/BB-SPIDEV1-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-SPIDEV1-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Virtual cape for SPI1 on connector pins P9.29 P9.31 P9.30 P9.28
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-SPIDEV1-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_28_pinmux { status = "disabled"; };	/* P9_28 (C12) mcasp0_ahclkr.spi1_cs0 */
+	P9_30_pinmux { status = "disabled"; };	/* P9_30 (D12) mcasp0_axr0.spi1_d1 */
+	P9_29_pinmux { status = "disabled"; };	/* P9_29 (B13) mcasp0_fsx.spi1_d0 */
+	P9_31_pinmux { status = "disabled"; };	/* P9_31 (A13) mcasp0_aclkx.spi1_sclk */
+};
+
+&am33xx_pinmux {
+	bb_spi1_pins: pinmux_bb_spi1_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT, MUX_MODE3)	/* P9_31 (A13) mcasp0_aclkx.spi1_sclk */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_FSX, PIN_INPUT, MUX_MODE3)	/* P9_29 (B13) mcasp0_fsx.spi1_d0 */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_AXR0, PIN_INPUT, MUX_MODE3)	/* P9_30 (D12) mcasp0_axr0.spi1_d1 */
+			AM33XX_PADCONF(AM335X_PIN_MCASP0_AHCLKR, PIN_INPUT, MUX_MODE3)	/* P9_28 (C12) mcasp0_ahclkr.spi1_cs0 */
+		>;
+	};
+};
+
+&spi1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_spi1_pins>;
+
+	/*
+	 * Select the D0 pin as output and D1 as
+	 * input. The default is D0 as input and
+	 * D1 as output.
+	 */
+	//ti,pindir-d0-out-d1-in;
+
+	channel@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/1.0";
+
+		reg = <0>;
+		spi-max-frequency = <16000000>;
+		spi-cpha;
+	};
+
+	channel@1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "rohm,dh2228fv";
+		symlink = "bone/spi/1.1";
+
+		reg = <1>;
+		spi-max-frequency = <16000000>;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-UART1-00A0.dtso b/arch/arm/boot/dts/BB-UART1-00A0.dtso
--- a/arch/arm/boot/dts/BB-UART1-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-UART1-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Virtual cape for UART1 on connector pins P9.24 P9.26
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-UART1-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_24_pinmux { status = "disabled"; };	/* uart1_txd */
+	P9_26_pinmux { status = "disabled"; };	/* uart1_rxd */
+};
+
+&am33xx_pinmux {
+	bb_uart1_pins: pinmux_bb_uart1_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_UART1_TXD, PIN_OUTPUT, MUX_MODE0)	/* P9_24 uart1_txd.uart1_txd */
+			AM33XX_PADCONF(AM335X_PIN_UART1_RXD, PIN_INPUT, MUX_MODE0)	/* P9_26 uart1_rxd.uart1_rxd */
+			//AM33XX_PADCONF(AM335X_PIN_UART1_RTSN, PIN_OUTPUT, MUX_MODE0)	/* P9_19 uart1_rtsn.uart1_rtsn */
+			//AM33XX_PADCONF(AM335X_PIN_UART1_CTSN, PIN_INPUT, MUX_MODE0)	/* P9_20 uart1_ctsn.uart1_ctsn */
+		>;
+	};
+};
+
+&uart1 {
+	/* sudo agetty 115200 ttyS1 */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_uart1_pins>;
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-UART2-00A0.dtso b/arch/arm/boot/dts/BB-UART2-00A0.dtso
--- a/arch/arm/boot/dts/BB-UART2-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-UART2-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Virtual cape for UART2 on connector pins P9.21 P9.22
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-UART2-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_21_pinmux { status = "disabled"; };	/* P9_21: spi0_d0.uart2_txd */
+	P9_22_pinmux { status = "disabled"; };	/* P9_22: spi0_sclk.uart2_rxd */
+};
+
+&am33xx_pinmux {
+	bb_uart2_pins: pinmux_bb_uart2_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_SPI0_D0, PIN_OUTPUT, MUX_MODE1)	/* P9_21 spi0_d0.uart2_txd */
+			AM33XX_PADCONF(AM335X_PIN_SPI0_SCLK, PIN_INPUT, MUX_MODE1)	/* P9_22 spi0_sclk.uart2_rxd */
+			//AM33XX_PADCONF(AM335X_PIN_LCD_DATA9, PIN_OUTPUT, MUX_MODE6)	/* P8_38 lcd_data9.uart2_rtsn */
+			//AM33XX_PADCONF(AM335X_PIN_LCD_DATA8, PIN_INPUT, MUX_MODE6)	/* P8_37 lcd_data8.uart2_ctsn */
+		>;
+	};
+};
+
+&uart2 {
+	/* sudo agetty 115200 ttyS2 */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_uart2_pins>;
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-UART4-00A0.dtso b/arch/arm/boot/dts/BB-UART4-00A0.dtso
--- a/arch/arm/boot/dts/BB-UART4-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-UART4-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2013 CircuitCo
+ * Virtual cape for UART4 on connector pins P9.13 P9.11
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-UART4-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_13_pinmux { status = "disabled"; };	/* P9_13: uart4_txd */
+	P9_11_pinmux { status = "disabled"; };	/* P9_11: uart4_rxd */
+};
+
+&am33xx_pinmux {
+	bb_uart4_pins: pinmux_bb_uart4_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_WPN, PIN_OUTPUT, MUX_MODE6)	/* P9_13 gpmc_wpn.uart4_txd_mux2 */
+			AM33XX_PADCONF(AM335X_PIN_GPMC_WAIT0, PIN_INPUT, MUX_MODE6)	/* P9_13 gpmc_wait0.uart4_rxd_mux2 */
+		>;
+	};
+};
+
+&uart4 {
+	/* sudo agetty 115200 ttyS4 */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&bb_uart4_pins>;
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BB-W1-P9.12-00A0.dtso b/arch/arm/boot/dts/BB-W1-P9.12-00A0.dtso
--- a/arch/arm/boot/dts/BB-W1-P9.12-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BB-W1-P9.12-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2015 Robert Nelson <robertcnelson@gmail.com>
+ * Virtual cape for onewire on connector pin P9.12
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BB-W1-P9.12-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P9_12_pinmux { status = "disabled"; };	/* P9_12 (U18) gpmc_be1n.gpio1_28 */
+};
+
+&am33xx_pinmux {
+	bb_dallas_w1_pins: pinmux_bb_dallas_w1_pins {
+		pinctrl-single,pins = <
+			AM33XX_PADCONF(AM335X_PIN_GPMC_BEN1, PIN_INPUT_PULLUP, MUX_MODE7)	/* P9_12 (U18) gpmc_be1n.gpio1_28 */
+		>;
+	};
+};
+
+&{/} {
+	onewire {
+		status = "okay";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bb_dallas_w1_pins>;
+
+		compatible = "w1-gpio";
+		gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+	};
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/BONE-ADC.dtso b/arch/arm/boot/dts/BONE-ADC.dtso
--- a/arch/arm/boot/dts/BONE-ADC.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/BONE-ADC.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020 Deepak Khatri <deepaklorkhatri7@gmail.com>
+ * See Cape Interface Spec page for more info on Bone Buses
+ * https://elinux.org/Beagleboard:BeagleBone_cape_interface_spec
+ *
+ * Virtual cape for Bone ADC
+ */
+
+/dts-v1/;
+/plugin/;
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		BONE-ADC.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * See these files for the phandles (&bone_*) and other bone bus nodes
+ * am335x-bbb-bone-buses.dtsi
+ */
+&bone_adc {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi b/arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi
--- a/arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/dra74x-mmc-iodelay.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -30,7 +30,7 @@
  */
 
 &dra7_pmx_core {
-	mmc1_pins_default: mmc1_pins_default {
+	mmc1_pins_default: mmc1-default-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */
 			DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */
@@ -41,7 +41,7 @@
 		>;
 	};
 
-	mmc1_pins_sdr12: mmc1_pins_sdr12 {
+	mmc1_pins_sdr12: mmc1-sdr12-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc1_clk.clk */
 			DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0)	/* mmc1_cmd.cmd */
@@ -52,7 +52,7 @@
 		>;
 	};
 
-	mmc1_pins_hs: mmc1_pins_hs {
+	mmc1_pins_hs: mmc1-hs-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE11 | MUX_MODE0) /* mmc1_clk.clk */
 			DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE11 | MUX_MODE0) /* mmc1_cmd.cmd */
@@ -63,7 +63,7 @@
 		>;
 	};
 
-	mmc1_pins_sdr25: mmc1_pins_sdr25 {
+	mmc1_pins_sdr25: mmc1-sdr25-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE11 | MUX_MODE0)	/* mmc1_clk.clk */
 			DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE11 | MUX_MODE0)	/* mmc1_cmd.cmd */
@@ -74,7 +74,7 @@
 		>;
 	};
 
-	mmc1_pins_sdr50: mmc1_pins_sdr50 {
+	mmc1_pins_sdr50: mmc1-sdr50-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE10 | MUX_MODE0)	/* mmc1_clk.clk */
 			DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_VIRTUAL_MODE10 | MUX_MODE0)	/* mmc1_cmd.cmd */
@@ -85,7 +85,7 @@
 		>;
 	};
 
-	mmc1_pins_ddr50: mmc1_pins_ddr50 {
+	mmc1_pins_ddr50: mmc1-ddr50-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)	/* mmc1_clk.clk */
 			DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)	/* mmc1_cmd.cmd */
@@ -96,7 +96,7 @@
 		>;
 	};
 
-	mmc1_pins_sdr104: mmc1_pins_sdr104 {
+	mmc1_pins_sdr104: mmc1-sdr104-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)	/* mmc1_clk.clk */
 			DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)	/* mmc1_cmd.cmd */
@@ -107,7 +107,7 @@
 		>;
 	};
 
-	mmc2_pins_default: mmc2_pins_default {
+	mmc2_pins_default: mmc2-default-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */
 			DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
@@ -122,7 +122,7 @@
 		>;
 	};
 
-	mmc2_pins_hs: mmc2_pins_hs {
+	mmc2_pins_hs: mmc2-hs-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */
 			DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
@@ -137,7 +137,7 @@
 		>;
 	};
 
-	mmc2_pins_ddr_3_3v_rev11: mmc2_pins_ddr_3_3v_rev11 {
+	mmc2_pins_ddr_3_3v_rev11: mmc2-ddr-3-3v-rev11-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_a23.mmc2_clk */
 			DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
@@ -152,7 +152,7 @@
 		>;
 	};
 
-	mmc2_pins_ddr_1_8v_rev11: mmc2_pins_ddr_1_8v_rev11 {
+	mmc2_pins_ddr_1_8v_rev11: mmc2-ddr-1-8v-rev11-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_a23.mmc2_clk */
 			DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
@@ -167,7 +167,7 @@
 		>;
 	};
 
-	mmc2_pins_ddr_rev20: mmc2_pins_ddr_rev20 {
+	mmc2_pins_ddr_rev20: mmc2-ddr-rev20-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */
 			DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
@@ -182,7 +182,7 @@
 		>;
 	};
 
-	mmc2_pins_hs200: mmc2_pins_hs200 {
+	mmc2_pins_hs200: mmc2-hs200-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_a23.mmc2_clk */
 			DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
@@ -197,7 +197,7 @@
 		>;
 	};
 
-	mmc4_pins_default: mmc4_pins_default {
+	mmc4_pins_default: mmc4-default-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x37e8, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_ctsn.mmc4_clk */
 			DRA7XX_CORE_IOPAD(0x37ec, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_rtsn.mmc4_cmd */
@@ -208,7 +208,7 @@
 		>;
 	};
 
-	mmc4_pins_hs: mmc4_pins_hs {
+	mmc4_pins_hs: mmc4-hs-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x37e8, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_ctsn.mmc4_clk */
 			DRA7XX_CORE_IOPAD(0x37ec, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_rtsn.mmc4_cmd */
@@ -219,7 +219,7 @@
 		>;
 	};
 
-	mmc3_pins_default: mmc3_pins_default {
+	mmc3_pins_default: mmc3-default-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
 			DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
@@ -230,7 +230,7 @@
 		>;
 	};
 
-	mmc3_pins_hs: mmc3_pins_hs {
+	mmc3_pins_hs: mmc3-hs-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
 			DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
@@ -241,7 +241,7 @@
 		>;
 	};
 
-	mmc3_pins_sdr12: mmc3_pins_sdr12 {
+	mmc3_pins_sdr12: mmc3-sdr12-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
 			DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
@@ -252,7 +252,7 @@
 		>;
 	};
 
-	mmc3_pins_sdr25: mmc3_pins_sdr25 {
+	mmc3_pins_sdr25: mmc3-sdr25-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
 			DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
@@ -263,7 +263,7 @@
 		>;
 	};
 
-	mmc3_pins_sdr50: mmc3_pins_sdr50 {
+	mmc3_pins_sdr50: mmc3-sdr50-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x377c, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_clk.mmc3_clk */
 			DRA7XX_CORE_IOPAD(0x3780, (PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE0)) /* mmc3_cmd.mmc3_cmd */
@@ -274,7 +274,7 @@
 		>;
 	};
 
-	mmc4_pins_sdr12: mmc4_pins_sdr12 {
+	mmc4_pins_sdr12: mmc4-sdr12-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x37e8, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_ctsn.mmc4_clk */
 			DRA7XX_CORE_IOPAD(0x37ec, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_rtsn.mmc4_cmd */
@@ -285,7 +285,7 @@
 		>;
 	};
 
-	mmc4_pins_sdr25: mmc4_pins_sdr25 {
+	mmc4_pins_sdr25: mmc4-sdr25-pins {
 		pinctrl-single,pins = <
 			DRA7XX_CORE_IOPAD(0x37e8, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_ctsn.mmc4_clk */
 			DRA7XX_CORE_IOPAD(0x37ec, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE3) /* uart1_rtsn.mmc4_cmd */
diff -Naur --no-dereference a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
--- a/arch/arm/boot/dts/dra7.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/dra7.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -102,6 +102,7 @@
 		syscon = <&scm_wkup>;
 
 		opp_nom-1000000000 {
+			/* OPP NOM */
 			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <1060000 850000 1150000>,
 					<1060000 850000 1150000>;
@@ -110,6 +111,7 @@
 		};
 
 		opp_od-1176000000 {
+			/* OPP OD */
 			opp-hz = /bits/ 64 <1176000000>;
 			opp-microvolt = <1160000 885000 1160000>,
 					<1160000 885000 1160000>;
@@ -118,6 +120,7 @@
 		};
 
 		opp_high@1500000000 {
+			/* OPP High */
 			opp-hz = /bits/ 64 <1500000000>;
 			opp-microvolt = <1210000 950000 1250000>,
 					<1210000 950000 1250000>;
@@ -144,7 +147,7 @@
 
 		l3-noc@44000000 {
 			compatible = "ti,dra7-l3-noc";
-			reg = <0x44000000 0x1000>,
+			reg = <0x44000000 0x1000000>,
 			      <0x45000000 0x1000>;
 			interrupts-extended = <&crossbar_mpu GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
 					      <&wakeupgen GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
@@ -847,12 +850,19 @@
 					<SYSC_IDLE_SMART>;
 			ti,sysc-sidle = <SYSC_IDLE_FORCE>,
 					<SYSC_IDLE_NO>,
-					<SYSC_IDLE_SMART>;
+					<SYSC_IDLE_SMART>,
+					<SYSC_IDLE_SMART_WKUP>;
 			clocks = <&gpu_clkctrl DRA7_GPU_CLKCTRL 0>;
 			clock-names = "fck";
 			#address-cells = <1>;
 			#size-cells = <1>;
 			ranges = <0 0x56000000 0x2000000>;
+
+			gpu: gpu@0 {
+				compatible = "ti,dra7-sgx544", "img,sgx544";
+				reg = <0x0 0x10000>;
+				interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+			};
 		};
 
 		crossbar_mpu: crossbar@4a002a48 {
diff -Naur --no-dereference a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
--- a/arch/arm/boot/dts/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/Makefile	2024-01-28 14:01:31.236353764 -0500
@@ -1,11 +1,15 @@
 # SPDX-License-Identifier: GPL-2.0
+
+ifeq ($(CONFIG_OF_OVERLAY),y)
+DTC_FLAGS += -@
+endif
+
 dtb-$(CONFIG_ARCH_ALPINE) += \
 	alpine-db.dtb
 dtb-$(CONFIG_MACH_ARTPEC6) += \
 	artpec6-devboard.dtb
 dtb-$(CONFIG_MACH_ASM9260) += \
 	alphascale-asm9260-devkit.dtb
-# Keep at91 dtb files sorted alphabetically for each SoC
 dtb-$(CONFIG_SOC_AT91RM9200) += \
 	at91rm9200ek.dtb \
 	mpa1600.dtb
@@ -933,6 +937,40 @@
 	am335x-base0033.dtb \
 	am335x-bone.dtb \
 	am335x-boneblack.dtb \
+	am335x-boneblack-uboot.dtb \
+	PB-MIKROBUS-1.dtbo \
+	PB-MIKROBUS-0.dtbo \
+	M-BB-BBGG-00A0.dtbo \
+	M-BB-BBG-00A0.dtbo \
+	BONE-ADC.dtbo \
+	BBORG_RELAY-00A2.dtbo \
+	BBORG_FAN-A000.dtbo \
+	BBORG_COMMS-00A2.dtbo \
+	BB-W1-P9.12-00A0.dtbo \
+	BB-UART4-00A0.dtbo \
+	BB-UART2-00A0.dtbo \
+	BB-UART1-00A0.dtbo \
+	BB-SPIDEV1-00A0.dtbo \
+	BB-SPIDEV0-00A0.dtbo \
+	BB-NHDMI-TDA998x-00A0.dtbo \
+	BB-LCD-ADAFRUIT-24-SPI1-00A0.dtbo \
+	BB-I2C2-MPU6050.dtbo \
+	BB-I2C2-BME680.dtbo \
+	BB-I2C1-RTC-PCF8563.dtbo \
+	BB-I2C1-RTC-DS3231.dtbo \
+	BB-I2C1-MCP7940X-00A0.dtbo \
+	BB-HDMI-TDA998x-00A0.dtbo \
+	BB-CAPE-DISP-CT4-00A0.dtbo \
+	BB-BONE-eMMC1-01-00A0.dtbo \
+	BB-BONE-NH7C-01-A0.dtbo \
+	BB-BONE-LCD4-01-00A1.dtbo \
+	BB-BONE-4D5R-01-00A1.dtbo \
+	BB-BBGW-WL1835-00A0.dtbo \
+	BB-BBGG-WL1835-00A0.dtbo \
+	BB-BBBW-WL1835-00A0.dtbo \
+	BB-ADC-00A0.dtbo \
+	AM335X-PRU-UIO-00A0.dtbo \
+	am335x-boneblack-pps.dtb \
 	am335x-boneblack-wireless.dtb \
 	am335x-boneblue.dtb \
 	am335x-bonegreen.dtb \
@@ -988,16 +1026,24 @@
 	omap5-igep0050.dtb \
 	omap5-sbc-t54.dtb \
 	omap5-uevm.dtb
+am57xx-evm-dtbs := am57xx-beagle-x15.dtb am57xx-evm.dtbo
+am57xx-evm-reva3-dtbs := am57xx-beagle-x15-revc.dtb am57xx-evm.dtbo
 dtb-$(CONFIG_SOC_DRA7XX) += \
 	am57xx-beagle-x15.dtb \
 	am57xx-beagle-x15-revb1.dtb \
 	am57xx-beagle-x15-revc.dtb \
+	am57xx-evm.dtb \
+	am57xx-evm-reva3.dtb \
 	am5729-beagleboneai.dtb \
 	am57xx-cl-som-am57x.dtb \
 	am57xx-sbc-am57x.dtb \
 	am572x-idk.dtb \
+	am572x-idk-touchscreen.dtbo \
 	am571x-idk.dtb \
+	am571x-idk-touchscreen.dtbo \
 	am574x-idk.dtb \
+	am57xx-idk-lcd-osd101t2045.dtbo \
+	am57xx-idk-lcd-osd101t2587.dtbo \
 	dra7-evm.dtb \
 	dra72-evm.dtb \
 	dra72-evm-revc.dtb \
diff -Naur --no-dereference a/arch/arm/boot/dts/M-BB-BBG-00A0.dtso b/arch/arm/boot/dts/M-BB-BBG-00A0.dtso
--- a/arch/arm/boot/dts/M-BB-BBG-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/M-BB-BBG-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		M-BB-BBG-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+&{/} {
+	model = "TI AM335x BeagleBone Green";
+	compatible = "ti,am335x-bone-green", "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/M-BB-BBGG-00A0.dtso b/arch/arm/boot/dts/M-BB-BBGG-00A0.dtso
--- a/arch/arm/boot/dts/M-BB-BBGG-00A0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/M-BB-BBGG-00A0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		M-BB-BBGG-00A0.kernel = __TIMESTAMP__;
+	};
+};
+
+&{/} {
+	model = "SeeedStudio BeagleBone Green Gateway";
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/omap34xx.dtsi b/arch/arm/boot/dts/omap34xx.dtsi
--- a/arch/arm/boot/dts/omap34xx.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/omap34xx.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -164,12 +164,18 @@
 			clock-names = "fck", "ick";
 			#address-cells = <1>;
 			#size-cells = <1>;
-			ranges = <0 0x50000000 0x4000>;
+			ranges = <0 0x50000000 0x10000>;
 
 			/*
 			 * Closed source PowerVR driver, no child device
 			 * binding or driver in mainline
 			 */
+
+			sgx: gpu@0 {
+				compatible = "ti,omap3530-sgx530", "img,sgx530";
+				reg = <0x0 0x10000>; /* 64kB */
+				interrupts = <21>;
+			};
 		};
 	};
 
diff -Naur --no-dereference a/arch/arm/boot/dts/omap36xx.dtsi b/arch/arm/boot/dts/omap36xx.dtsi
--- a/arch/arm/boot/dts/omap36xx.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/omap36xx.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -31,6 +31,7 @@
 		syscon = <&scm_conf>;
 
 		opp50-300000000 {
+			/* OPP50 */
 			opp-hz = /bits/ 64 <300000000>;
 			/*
 			 * we currently only select the max voltage from table
@@ -49,6 +50,7 @@
 		};
 
 		opp100-600000000 {
+			/* OPP100 */
 			opp-hz = /bits/ 64 <600000000>;
 			opp-microvolt = <1200000 1200000 1200000>,
 					 <1200000 1200000 1200000>;
@@ -56,6 +58,7 @@
 		};
 
 		opp130-800000000 {
+			/* OPP130 */
 			opp-hz = /bits/ 64 <800000000>;
 			opp-microvolt = <1325000 1325000 1325000>,
 					 <1325000 1325000 1325000>;
@@ -63,6 +66,7 @@
 		};
 
 		opp1g-1000000000 {
+			/* OPP1G */
 			opp-hz = /bits/ 64 <1000000000>;
 			opp-microvolt = <1375000 1375000 1375000>,
 					 <1375000 1375000 1375000>;
diff -Naur --no-dereference a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
--- a/arch/arm/boot/dts/omap3-beagle.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/omap3-beagle.dts	2024-01-28 14:01:31.236353764 -0500
@@ -28,18 +28,18 @@
 
 	leds {
 		compatible = "gpio-leds";
-		pmu_stat {
+		led-pmu-stat {
 			label = "beagleboard::pmu_stat";
 			gpios = <&twl_gpio 19 GPIO_ACTIVE_HIGH>; /* LEDB */
 		};
 
-		heartbeat {
+		led-heartbeat {
 			label = "beagleboard::usr0";
 			gpios = <&gpio5 22 GPIO_ACTIVE_HIGH>; /* 150 -> D6 LED */
 			linux,default-trigger = "heartbeat";
 		};
 
-		mmc {
+		led-mmc {
 			label = "beagleboard::usr1";
 			gpios = <&gpio5 21 GPIO_ACTIVE_HIGH>; /* 149 -> D7 LED */
 			linux,default-trigger = "mmc0";
@@ -57,7 +57,7 @@
 	};
 
 	/* HS USB Host PHY on PORT 2 */
-	hsusb2_phy: hsusb2_phy {
+	hsusb2_phy: hsusb2-phy-pins {
 		compatible = "usb-nop-xceiv";
 		reset-gpios = <&gpio5 19 GPIO_ACTIVE_LOW>;	/* gpio_147 */
 		vcc-supply = <&hsusb2_power>;
@@ -170,7 +170,7 @@
 };
 
 &omap3_pmx_wkup {
-	gpio1_pins: pinmux_gpio1_pins {
+	gpio1_pins: gpio1-pins {
 		pinctrl-single,pins = <
 			OMAP3_WKUP_IOPAD(0x2a14, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE4) /* sys_boot5.gpio_7 */
 		>;
@@ -183,7 +183,7 @@
 			&hsusb2_pins
 	>;
 
-	hsusb2_pins: pinmux_hsusb2_pins {
+	hsusb2_pins: hsusb2-pins {
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x21d4, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi1_cs3.hsusb2_data2 */
 			OMAP3_CORE1_IOPAD(0x21d6, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi2_clk.hsusb2_data7 */
@@ -194,20 +194,20 @@
 		>;
 	};
 
-	uart3_pins: pinmux_uart3_pins {
+	uart3_pins: uart3-pins {
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */
 			OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */
 		>;
 	};
 
-	tfp410_pins: pinmux_tfp410_pins {
+	tfp410_pins: tfp410-pins {
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x21c6, PIN_OUTPUT | MUX_MODE4)	/* hdq_sio.gpio_170 */
 		>;
 	};
 
-	dss_dpi_pins: pinmux_dss_dpi_pins {
+	dss_dpi_pins: dss-dpi-pins {
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0)   /* dss_pclk.dss_pclk */
 			OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0)   /* dss_hsync.dss_hsync */
@@ -247,7 +247,7 @@
 			&hsusb2_2_pins
 	>;
 
-	hsusb2_2_pins: pinmux_hsusb2_2_pins {
+	hsusb2_2_pins: hsusb2-2-pins {
 		pinctrl-single,pins = <
 			OMAP3430_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3)		/* etk_d10.hsusb2_clk */
 			OMAP3430_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3)		/* etk_d11.hsusb2_stp */
diff -Naur --no-dereference a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/omap3-beagle-xm.dts
--- a/arch/arm/boot/dts/omap3-beagle-xm.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/omap3-beagle-xm.dts	2024-01-28 14:01:31.236353764 -0500
@@ -8,7 +8,7 @@
 
 / {
 	model = "TI OMAP3 BeagleBoard xM";
-	compatible = "ti,omap3-beagle-xm", "ti,omap3630", "ti,omap36xx", "ti,omap3";
+	compatible = "ti,omap3-beagle-xm", "ti,omap3630", "ti,omap3";
 
 	cpus {
 		cpu@0 {
@@ -90,7 +90,7 @@
 	};
 
 	/* HS USB Host PHY on PORT 2 */
-	hsusb2_phy: hsusb2_phy {
+	hsusb2_phy: hsusb2-phy-pins {
 		compatible = "usb-nop-xceiv";
 		reset-gpios = <&gpio5 19 GPIO_ACTIVE_LOW>; /* gpio_147 */
 		vcc-supply = <&hsusb2_power>;
@@ -183,13 +183,13 @@
 };
 
 &omap3_pmx_wkup {
-	gpio1_pins: pinmux_gpio1_pins {
+	gpio1_pins: gpio1-pins {
 		pinctrl-single,pins = <
 			OMAP3_WKUP_IOPAD(0x2a0e, PIN_INPUT | PIN_OFF_WAKEUPENABLE | MUX_MODE4) /* sys_boot2.gpio_4 */
 		>;
 	};
 
-	dss_dpi_pins2: pinmux_dss_dpi_pins1 {
+	dss_dpi_pins2: dss-dpi1-pins {
 		pinctrl-single,pins = <
 			OMAP3_WKUP_IOPAD(0x2a0a, PIN_OUTPUT | MUX_MODE3)   /* sys_boot0.dss_data18 */
 			OMAP3_WKUP_IOPAD(0x2a0c, PIN_OUTPUT | MUX_MODE3)   /* sys_boot1.dss_data19 */
@@ -207,14 +207,14 @@
 			&hsusb2_pins
 	>;
 
-	uart3_pins: pinmux_uart3_pins {
+	uart3_pins: uart3-pins {
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0)	/* uart3_rx_irrx.uart3_rx_irrx */
 			OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0)	/* uart3_tx_irtx.uart3_tx_irtx OUTPUT | MODE0 */
 		>;
 	};
 
-	hsusb2_pins: pinmux_hsusb2_pins {
+	hsusb2_pins: hsusb2-pins {
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x21d4, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi1_cs3.hsusb2_data2 */
 			OMAP3_CORE1_IOPAD(0x21d6, PIN_INPUT_PULLDOWN | MUX_MODE3)	/* mcspi2_clk.hsusb2_data7 */
@@ -225,7 +225,7 @@
 		>;
 	};
 
-	dss_dpi_pins1: pinmux_dss_dpi_pins2 {
+	dss_dpi_pins1: dss-dpi2-pins {
 		pinctrl-single,pins = <
 			OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0)   /* dss_pclk.dss_pclk */
 			OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0)   /* dss_hsync.dss_hsync */
@@ -261,7 +261,7 @@
 			&hsusb2_2_pins
 	>;
 
-	hsusb2_2_pins: pinmux_hsusb2_2_pins {
+	hsusb2_2_pins: hsusb2-2-pins {
 		pinctrl-single,pins = <
 			OMAP3630_CORE2_IOPAD(0x25f0, PIN_OUTPUT | MUX_MODE3)		/* etk_d10.hsusb2_clk */
 			OMAP3630_CORE2_IOPAD(0x25f2, PIN_OUTPUT | MUX_MODE3)		/* etk_d11.hsusb2_stp */
diff -Naur --no-dereference a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
--- a/arch/arm/boot/dts/omap4.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/omap4.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -505,6 +505,12 @@
 			 * Closed source PowerVR driver, no child device
 			 * binding or driver in mainline
 			 */
+
+			gpu@0 {
+				compatible = "ti,omap4430-sgx540", "img,sgx540";
+				reg = <0x0 0x2000000>; /* 32MB */
+				interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			};
 		};
 
 		/*
diff -Naur --no-dereference a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi
--- a/arch/arm/boot/dts/omap4-panda-common.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/omap4-panda-common.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -49,13 +49,13 @@
 			&led_wkgpio_pins
 		>;
 
-		heartbeat {
+		led-heartbeat {
 			label = "pandaboard::status1";
 			gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "heartbeat";
 		};
 
-		mmc {
+		led-mmc {
 			label = "pandaboard::status2";
 			gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
 			linux,default-trigger = "mmc0";
@@ -237,14 +237,14 @@
 			&hsusbb1_pins
 	>;
 
-	twl6040_pins: twl6040-pins {
+	twl6040_pins: pinmux_twl6040_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x120, PIN_OUTPUT | MUX_MODE3)	/* hdq_sio.gpio_127 */
 			OMAP4_IOPAD(0x1a0, PIN_INPUT | MUX_MODE0)	/* sys_nirq2.sys_nirq2 */
 		>;
 	};
 
-	mcbsp1_pins: mcbsp1-pins {
+	mcbsp1_pins: pinmux_mcbsp1_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x0fe, PIN_INPUT | MUX_MODE0)		/* abe_mcbsp1_clkx.abe_mcbsp1_clkx */
 			OMAP4_IOPAD(0x100, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* abe_mcbsp1_dr.abe_mcbsp1_dr */
@@ -253,7 +253,7 @@
 		>;
 	};
 
-	dss_dpi_pins: dss-dpi-pins {
+	dss_dpi_pins: pinmux_dss_dpi_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x162, PIN_OUTPUT | MUX_MODE5)	/* dispc2_data23 */
 			OMAP4_IOPAD(0x164, PIN_OUTPUT | MUX_MODE5) 	/* dispc2_data22 */
@@ -288,13 +288,13 @@
 		>;
 	};
 
-	tfp410_pins: tfp410-pins {
+	tfp410_pins: pinmux_tfp410_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x184, PIN_OUTPUT | MUX_MODE3)	/* gpio_0 */
 		>;
 	};
 
-	dss_hdmi_pins: dss-hdmi-pins {
+	dss_hdmi_pins: pinmux_dss_hdmi_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x09a, PIN_INPUT | MUX_MODE0)		/* hdmi_cec.hdmi_cec */
 			OMAP4_IOPAD(0x09c, PIN_INPUT_PULLUP | MUX_MODE0)	/* hdmi_scl.hdmi_scl */
@@ -302,7 +302,7 @@
 		>;
 	};
 
-	tpd12s015_pins: tpd12s015-pins {
+	tpd12s015_pins: pinmux_tpd12s015_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x062, PIN_OUTPUT | MUX_MODE3)		/* gpmc_a17.gpio_41 */
 			OMAP4_IOPAD(0x088, PIN_OUTPUT | MUX_MODE3)		/* gpmc_nbe1.gpio_60 */
@@ -310,7 +310,7 @@
 		>;
 	};
 
-	hsusbb1_pins: hsusbb1-pins {
+	hsusbb1_pins: pinmux_hsusbb1_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x0c2, PIN_INPUT_PULLDOWN | MUX_MODE4)	/* usbb1_ulpitll_clk.usbb1_ulpiphy_clk */
 			OMAP4_IOPAD(0x0c4, PIN_OUTPUT | MUX_MODE4)		/* usbb1_ulpitll_stp.usbb1_ulpiphy_stp */
@@ -327,28 +327,28 @@
 		>;
 	};
 
-	i2c1_pins: i2c1-pins {
+	i2c1_pins: pinmux_i2c1_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x122, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c1_scl */
 			OMAP4_IOPAD(0x124, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c1_sda */
 		>;
 	};
 
-	i2c2_pins: i2c2-pins {
+	i2c2_pins: pinmux_i2c2_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x126, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c2_scl */
 			OMAP4_IOPAD(0x128, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c2_sda */
 		>;
 	};
 
-	i2c3_pins: i2c3-pins {
+	i2c3_pins: pinmux_i2c3_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x12a, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c3_scl */
 			OMAP4_IOPAD(0x12c, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c3_sda */
 		>;
 	};
 
-	i2c4_pins: i2c4-pins {
+	i2c4_pins: pinmux_i2c4_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x12e, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c4_scl */
 			OMAP4_IOPAD(0x130, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c4_sda */
@@ -359,7 +359,7 @@
 	 * wl12xx GPIO outputs for WLAN_EN, BT_EN, FM_EN, BT_WAKEUP
 	 * REVISIT: Are the pull-ups needed for GPIO 48 and 49?
 	 */
-	wl12xx_gpio: wl12xx-gpio-pins {
+	wl12xx_gpio: pinmux_wl12xx_gpio {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x066, PIN_OUTPUT | MUX_MODE3)		/* gpmc_a19.gpio_43 */
 			OMAP4_IOPAD(0x06c, PIN_OUTPUT | MUX_MODE3)		/* gpmc_a22.gpio_46 */
@@ -369,7 +369,7 @@
 	};
 
 	/* wl12xx GPIO inputs and SDIO pins */
-	wl12xx_pins: wl12xx-pins {
+	wl12xx_pins: pinmux_wl12xx_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x078, PIN_INPUT | MUX_MODE3)		/* gpmc_ncs2.gpio_52 */
 			OMAP4_IOPAD(0x07a, PIN_INPUT | MUX_MODE3)		/* gpmc_ncs3.gpio_53 */
@@ -382,7 +382,7 @@
 		>;
 	};
 
-	button_pins: button-pins {
+	button_pins: pinmux_button_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x114, PIN_INPUT_PULLUP | MUX_MODE3)	/* gpio_121 */
 		>;
@@ -390,7 +390,7 @@
 };
 
 &omap4_pmx_wkup {
-	led_wkgpio_pins: leds-wkpins-pins {
+	led_wkgpio_pins: pinmux_leds_wkpins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x05a, PIN_OUTPUT | MUX_MODE3)	/* gpio_wk7 */
 			OMAP4_IOPAD(0x05c, PIN_OUTPUT | MUX_MODE3)	/* gpio_wk8 */
diff -Naur --no-dereference a/arch/arm/boot/dts/omap4-panda-es.dts b/arch/arm/boot/dts/omap4-panda-es.dts
--- a/arch/arm/boot/dts/omap4-panda-es.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/omap4-panda-es.dts	2024-01-28 14:01:31.236353764 -0500
@@ -38,26 +38,26 @@
 };
 
 &omap4_pmx_core {
-	led_gpio_pins: gpio-led-pmx-pins {
+	led_gpio_pins: gpio_led_pmx {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x0f6, PIN_OUTPUT | MUX_MODE3)	/* gpio_110 */
 		>;
 	};
 
-	button_pins: button-pins {
+	button_pins: pinmux_button_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x0fc, PIN_INPUT_PULLUP | MUX_MODE3) /* gpio_113 */
 		>;
 	};
 
-	bt_pins: bt-pins {
+	bt_pins: pinmux_bt_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x06c, PIN_OUTPUT | MUX_MODE3)		/* gpmc_a22.gpio_46 - BTEN */
 			OMAP4_IOPAD(0x072, PIN_OUTPUT_PULLUP | MUX_MODE3)	/* gpmc_a25.gpio_49 - BTWAKEUP */
 		>;
 	};
 
-	uart2_pins: uart2-pins {
+	uart2_pins: pinmux_uart2_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x118, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart2_cts.uart2_cts - HCI */
 			OMAP4_IOPAD(0x11a, PIN_OUTPUT | MUX_MODE0)		/* uart2_rts.uart2_rts */
diff -Naur --no-dereference a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts
--- a/arch/arm/boot/dts/omap4-sdp.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/omap4-sdp.dts	2024-01-28 14:01:31.236353764 -0500
@@ -214,7 +214,7 @@
 			&tpd12s015_pins
 	>;
 
-	uart2_pins: uart2-pins {
+	uart2_pins: pinmux_uart2_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x118, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart2_cts.uart2_cts */
 			OMAP4_IOPAD(0x11a, PIN_OUTPUT | MUX_MODE0)		/* uart2_rts.uart2_rts */
@@ -223,7 +223,7 @@
 		>;
 	};
 
-	uart3_pins: uart3-pins {
+	uart3_pins: pinmux_uart3_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x140, PIN_INPUT_PULLUP | MUX_MODE0)	/* uart3_cts_rctx.uart3_cts_rctx */
 			OMAP4_IOPAD(0x142, PIN_OUTPUT | MUX_MODE0)		/* uart3_rts_sd.uart3_rts_sd */
@@ -232,21 +232,21 @@
 		>;
 	};
 
-	uart4_pins: uart4-pins {
+	uart4_pins: pinmux_uart4_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x15c, PIN_INPUT | MUX_MODE0)		/* uart4_rx.uart4_rx */
 			OMAP4_IOPAD(0x15e, PIN_OUTPUT | MUX_MODE0)		/* uart4_tx.uart4_tx */
 		>;
 	};
 
-	twl6040_pins: twl6040-pins {
+	twl6040_pins: pinmux_twl6040_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x120, PIN_OUTPUT | MUX_MODE3)		/* hdq_sio.gpio_127 */
 			OMAP4_IOPAD(0x1a0, PIN_INPUT | MUX_MODE0)		/* sys_nirq2.sys_nirq2 */
 		>;
 	};
 
-	dmic_pins: dmic-pins {
+	dmic_pins: pinmux_dmic_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x110, PIN_OUTPUT | MUX_MODE0)		/* abe_dmic_clk1.abe_dmic_clk1 */
 			OMAP4_IOPAD(0x112, PIN_INPUT | MUX_MODE0)		/* abe_dmic_din1.abe_dmic_din1 */
@@ -255,7 +255,7 @@
 		>;
 	};
 
-	mcbsp1_pins: mcbsp1-pins {
+	mcbsp1_pins: pinmux_mcbsp1_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x0fe, PIN_INPUT | MUX_MODE0)		/* abe_mcbsp1_clkx.abe_mcbsp1_clkx */
 			OMAP4_IOPAD(0x100, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* abe_mcbsp1_dr.abe_mcbsp1_dr */
@@ -264,7 +264,7 @@
 		>;
 	};
 
-	mcbsp2_pins: mcbsp2-pins {
+	mcbsp2_pins: pinmux_mcbsp2_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x0f6, PIN_INPUT | MUX_MODE0)		/* abe_mcbsp2_clkx.abe_mcbsp2_clkx */
 			OMAP4_IOPAD(0x0f8, PIN_INPUT_PULLDOWN | MUX_MODE0)	/* abe_mcbsp2_dr.abe_mcbsp2_dr */
@@ -273,7 +273,7 @@
 		>;
 	};
 
-	mcspi1_pins: mcspi1-pins {
+	mcspi1_pins: pinmux_mcspi1_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x132, PIN_INPUT | MUX_MODE0)		/*  mcspi1_clk.mcspi1_clk */
 			OMAP4_IOPAD(0x134, PIN_INPUT | MUX_MODE0)		/*  mcspi1_somi.mcspi1_somi */
@@ -282,7 +282,7 @@
 		>;
 	};
 
-	dss_hdmi_pins: dss-hdmi-pins {
+	dss_hdmi_pins: pinmux_dss_hdmi_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x09a, PIN_INPUT | MUX_MODE0)		/* hdmi_cec.hdmi_cec */
 			OMAP4_IOPAD(0x09c, PIN_INPUT_PULLUP | MUX_MODE0)	/* hdmi_scl.hdmi_scl */
@@ -290,7 +290,7 @@
 		>;
 	};
 
-	tpd12s015_pins: tpd12s015-pins {
+	tpd12s015_pins: pinmux_tpd12s015_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x062, PIN_OUTPUT | MUX_MODE3)		/* gpmc_a17.gpio_41 */
 			OMAP4_IOPAD(0x088, PIN_OUTPUT | MUX_MODE3)		/* gpmc_nbe1.gpio_60 */
@@ -298,28 +298,28 @@
 		>;
 	};
 
-	i2c1_pins: i2c1-pins {
+	i2c1_pins: pinmux_i2c1_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x122, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c1_scl */
 			OMAP4_IOPAD(0x124, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c1_sda */
 		>;
 	};
 
-	i2c2_pins: i2c2-pins {
+	i2c2_pins: pinmux_i2c2_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x126, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c2_scl */
 			OMAP4_IOPAD(0x128, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c2_sda */
 		>;
 	};
 
-	i2c3_pins: i2c3-pins {
+	i2c3_pins: pinmux_i2c3_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x12a, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c3_scl */
 			OMAP4_IOPAD(0x12c, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c3_sda */
 		>;
 	};
 
-	i2c4_pins: i2c4-pins {
+	i2c4_pins: pinmux_i2c4_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x12e, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c4_scl */
 			OMAP4_IOPAD(0x130, PIN_INPUT_PULLUP | MUX_MODE0)	/* i2c4_sda */
@@ -327,14 +327,14 @@
 	};
 
 	/* wl12xx GPIO output for WLAN_EN */
-	wl12xx_gpio: wl12xx-gpio-pins {
+	wl12xx_gpio: pinmux_wl12xx_gpio {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x07c, PIN_OUTPUT | MUX_MODE3)		/* gpmc_nwp.gpio_54 */
 		>;
 	};
 
 	/* wl12xx GPIO inputs and SDIO pins */
-	wl12xx_pins: wl12xx-pins {
+	wl12xx_pins: pinmux_wl12xx_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x07a, PIN_INPUT | MUX_MODE3)		/* gpmc_ncs3.gpio_53 */
 			OMAP4_IOPAD(0x148, PIN_INPUT_PULLUP | MUX_MODE0)	/* sdmmc5_clk.sdmmc5_clk */
@@ -347,13 +347,13 @@
 	};
 
 	/* gpio_48 for ENET_ENABLE */
-	enet_enable_gpio: enet-enable-gpio-pins {
+	enet_enable_gpio: pinmux_enet_enable_gpio {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x070, PIN_OUTPUT_PULLDOWN | MUX_MODE3)	/* gpmc_a24.gpio_48 */
 		>;
 	};
 
-	ks8851_pins: ks8851-pins {
+	ks8851_pins: pinmux_ks8851_pins {
 		pinctrl-single,pins = <
 			/* ENET_INT */
 			OMAP4_IOPAD(0x054, PIN_INPUT_PULLUP | MUX_MODE3)	/* gpmc_ad10.gpio_34 */
diff -Naur --no-dereference a/arch/arm/boot/dts/PB-MIKROBUS-0.dtso b/arch/arm/boot/dts/PB-MIKROBUS-0.dtso
--- a/arch/arm/boot/dts/PB-MIKROBUS-0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/PB-MIKROBUS-0.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2020 Vaishnav M A, BeagleBoard.org Foundation.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		PB-MIKROBUS-0.kernel = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P2_01_pinmux { status = "disabled"; };
+	P2_03_pinmux { status = "disabled"; };
+	P2_05_pinmux { status = "disabled"; };
+	P2_07_pinmux { status = "disabled"; };
+	P2_09_pinmux { status = "disabled"; };
+	P2_11_pinmux { status = "disabled"; };
+	P1_12_pinmux { status = "disabled"; };
+	P1_10_pinmux { status = "disabled"; };
+	P1_08_pinmux { status = "disabled"; };
+	P1_06_pinmux { status = "disabled"; };
+	P1_04_pinmux { status = "disabled"; };
+	P1_02_pinmux { status = "disabled"; };
+};
+
+&{/} {
+	aliases {
+		mikrobus0 = "/mikrobus-0";
+	};
+
+	mikrobus-0 {
+		compatible = "linux,mikrobus";
+		status = "okay";
+		pinctrl-names = "default", "pwm_default", "pwm_gpio",
+				"uart_default", "uart_gpio", "i2c_default",
+				"i2c_gpio", "spi_default", "spi_gpio";
+		pinctrl-0 = <
+			&P2_03_gpio_input_pin
+			&P1_04_gpio_pin
+			&P1_02_gpio_pin
+		>;
+		pinctrl-1 = <&P2_01_pwm_pin>;
+		pinctrl-2 = <&P2_01_gpio_pin>;
+		pinctrl-3 = <
+			&P2_05_uart_pin
+			&P2_07_uart_pin
+		>;
+		pinctrl-4 = <
+			&P2_05_gpio_pin
+			&P2_07_gpio_pin
+		>;
+		pinctrl-5 = <
+			&P2_09_i2c_pin
+			&P2_11_i2c_pin
+		>;
+		pinctrl-6 = <
+			&P2_09_gpio_pin
+			&P2_11_gpio_pin
+		>;
+		pinctrl-7 = <
+			&P1_12_spi_pin
+			&P1_10_spi_pin
+			&P1_08_spi_sclk_pin
+			&P1_06_spi_cs_pin
+		>;
+		pinctrl-8 = <
+			&P1_12_gpio_pin
+			&P1_10_gpio_pin
+			&P1_08_gpio_pin
+			&P1_06_gpio_pin
+		>;
+		i2c-adapter = <&i2c1>;
+		spi-master = <0>;
+		spi-cs = <0 1>;
+		uart = <&uart4>;
+		pwms = <&ehrpwm1 0 500000 0>;
+		mikrobus-gpios = <&gpio1 18 0> , <&gpio0 23 0>,
+				 <&gpio0 30 0> , <&gpio0 31 0>,
+				 <&gpio0 15 0> , <&gpio0 14 0>,
+				 <&gpio0 4 0>  , <&gpio0 3 0>,
+				 <&gpio0 2 0>  , <&gpio0 5 0>,
+				 <&gpio2 25 0> , <&gpio2 3 0>;
+	};
+};
+
+&spi0 {
+	status = "okay";
+	channel@0{ status = "disabled"; };
+};
+
+&uart4 {
+	status = "okay";
+	force-empty-serdev-controller;
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/PB-MIKROBUS-1.dtso b/arch/arm/boot/dts/PB-MIKROBUS-1.dtso
--- a/arch/arm/boot/dts/PB-MIKROBUS-1.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/boot/dts/PB-MIKROBUS-1.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright 2020 Vaishnav M A, BeagleBoard.org Foundation.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/am33xx.h>
+
+/*
+ * Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
+ */
+&{/chosen} {
+	overlays {
+		PB-MIKROBUS-1 = __TIMESTAMP__;
+	};
+};
+
+/*
+ * Free up the pins used by the cape from the pinmux helpers.
+ */
+&ocp {
+	P1_36_pinmux { status = "disabled"; };
+	P1_34_pinmux { status = "disabled"; };
+	P1_32_pinmux { status = "disabled"; };
+	P1_30_pinmux { status = "disabled"; };
+	P1_28_pinmux { status = "disabled"; };
+	P1_26_pinmux { status = "disabled"; };
+	P2_25_pinmux { status = "disabled"; };
+	P2_27_pinmux { status = "disabled"; };
+	P2_29_pinmux { status = "disabled"; };
+	P2_31_pinmux { status = "disabled"; };
+	P2_33_pinmux { status = "disabled"; };
+	P2_35_pinmux { status = "disabled"; };
+};
+
+&{/} {
+	aliases {
+		mikrobus1 = "/mikrobus-1";
+	};
+
+	mikrobus-1 {
+		compatible = "linux,mikrobus";
+		status = "okay";
+		pinctrl-names = "default", "pwm_default", "pwm_gpio",
+				"uart_default", "uart_gpio", "i2c_default",
+				"i2c_gpio", "spi_default", "spi_gpio";
+		pinctrl-0 = <
+			&P1_34_gpio_input_pin
+			&P2_33_gpio_pin
+			&P2_35_gpio_pin
+		>;
+		pinctrl-1 = <&P1_36_pwm_pin>;
+		pinctrl-2 = <&P1_36_gpio_pin>;
+		pinctrl-3 = <
+			&P1_32_uart_pin
+			&P1_30_uart_pin
+		>;
+		pinctrl-4 = <
+			&P1_32_gpio_pin
+			&P1_30_gpio_pin
+		>;
+		pinctrl-5 = <
+			&P1_26_i2c_pin
+			&P1_28_i2c_pin
+		>;
+		pinctrl-6 = <
+			&P1_26_gpio_pin
+			&P1_28_gpio_pin
+		>;
+		pinctrl-7 = <
+			&P2_25_spi_pin
+			&P2_27_spi_pin
+			&P2_29_spi_sclk_pin
+			&P2_31_spi_cs_pin
+		>;
+		pinctrl-8 = <
+			&P2_25_gpio_pin
+			&P2_27_gpio_pin
+			&P2_29_gpio_pin
+			&P2_31_gpio_pin
+		>;
+		i2c-adapter = <&i2c2>;
+		spi-master = <1>;
+		spi-cs = <1 2>;
+		uart = <&uart0>;
+		pwms = <&ehrpwm0 0 500000 0>;
+		mikrobus-gpios = <&gpio3 14 0> , <&gpio0 26 0>,
+				 <&gpio1 10 0> , <&gpio1 11 0>,
+				 <&gpio0 13 0> , <&gpio0 12 0>,
+				 <&gpio1 9 0>  , <&gpio1 8 0>,
+				 <&gpio0 7 0>  , <&gpio0 19 0>,
+				 <&gpio1 13 0> , <&gpio2 22 0>;
+	};
+};
+
+&spi1 {
+	status = "okay";
+	channel@0{ status = "disabled"; };
+	channel@1{ status = "disabled"; };
+};
+
+&uart0 {
+	status = "okay";
+	force-empty-serdev-controller;
+};
diff -Naur --no-dereference a/arch/arm/boot/dts/twl6030_omap4.dtsi b/arch/arm/boot/dts/twl6030_omap4.dtsi
--- a/arch/arm/boot/dts/twl6030_omap4.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/boot/dts/twl6030_omap4.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -19,7 +19,7 @@
 };
 
 &omap4_pmx_wkup {
-	twl6030_wkup_pins: twl6030-wkup-pins {
+	twl6030_wkup_pins: pinmux_twl6030_wkup_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x054, PIN_OUTPUT | MUX_MODE2)		/* fref_clk0_out.sys_drm_msecure */
 		>;
@@ -27,7 +27,7 @@
 };
 
 &omap4_pmx_core {
-	twl6030_pins: twl6030-pins {
+	twl6030_pins: pinmux_twl6030_pins {
 		pinctrl-single,pins = <
 			OMAP4_IOPAD(0x19e, WAKEUP_EN | PIN_INPUT_PULLUP | MUX_MODE0)	/* sys_nirq1.sys_nirq1 */
 		>;
diff -Naur --no-dereference a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
--- a/arch/arm/configs/multi_v7_defconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm/configs/multi_v7_defconfig	2024-01-28 14:01:31.236353764 -0500
@@ -1,10 +1,13 @@
 CONFIG_SYSVIPC=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
 CONFIG_CGROUPS=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_EMBEDDED=y
 CONFIG_PERF_EVENTS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 CONFIG_ARCH_VIRT=y
 CONFIG_ARCH_AIROHA=y
 CONFIG_ARCH_ACTIONS=y
@@ -236,19 +239,21 @@
 CONFIG_QCOM_FASTRPC=m
 CONFIG_APDS9802ALS=y
 CONFIG_ISL29003=y
+CONFIG_SRAM_DMA_HEAP=y
 CONFIG_PCI_ENDPOINT_TEST=m
 CONFIG_EEPROM_AT24=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=y
 CONFIG_ATA=y
-CONFIG_SATA_AHCI=y
-CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_AHCI_PLATFORM=m
 CONFIG_AHCI_BRCM=y
 CONFIG_AHCI_DM816=y
 CONFIG_AHCI_ST=y
 CONFIG_AHCI_IMX=y
 CONFIG_AHCI_SUNXI=y
 CONFIG_AHCI_TEGRA=y
+CONFIG_AHCI_DWC=m
 CONFIG_SATA_HIGHBANK=y
 CONFIG_SATA_MV=y
 CONFIG_SATA_RCAR=y
@@ -325,10 +330,13 @@
 CONFIG_MOUSE_CYAPA=m
 CONFIG_MOUSE_ELAN_I2C=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_EDT_FT5X06=y
 CONFIG_TOUCHSCREEN_ADC=m
 CONFIG_TOUCHSCREEN_ATMEL_MXT=m
 CONFIG_TOUCHSCREEN_ELAN=m
 CONFIG_TOUCHSCREEN_MMS114=m
+CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
+CONFIG_TOUCHSCREEN_PIXCIR=m
 CONFIG_TOUCHSCREEN_WM97XX=m
 CONFIG_TOUCHSCREEN_ST1232=m
 CONFIG_TOUCHSCREEN_STMPE=y
@@ -357,6 +365,7 @@
 CONFIG_SERIAL_8250_OMAP=y
 CONFIG_SERIAL_8250_MT6577=y
 CONFIG_SERIAL_8250_UNIPHIER=y
+CONFIG_SERIAL_8250_PRUSS=m
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
@@ -531,6 +540,9 @@
 CONFIG_SENSORS_RASPBERRYPI_HWMON=m
 CONFIG_SENSORS_INA2XX=m
 CONFIG_CPU_THERMAL=y
+CONFIG_TI_THERMAL=y
+CONFIG_THERMAL_EMULATION=y
+CONFIG_DRA752_THERMAL=y
 CONFIG_DEVFREQ_THERMAL=y
 CONFIG_IMX_THERMAL=y
 CONFIG_ROCKCHIP_THERMAL=y
@@ -552,6 +564,7 @@
 CONFIG_SAMA5D4_WATCHDOG=y
 CONFIG_S3C2410_WATCHDOG=m
 CONFIG_DW_WATCHDOG=y
+CONFIG_OMAP_WATCHDOG=m
 CONFIG_DAVINCI_WATCHDOG=m
 CONFIG_ORION_WATCHDOG=y
 CONFIG_RN5T618_WATCHDOG=y
@@ -598,6 +611,7 @@
 CONFIG_MFD_RN5T618=y
 CONFIG_MFD_SEC_CORE=y
 CONFIG_MFD_STMPE=y
+CONFIG_MFD_TI_AM335X_TSCADC=m
 CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65090=y
 CONFIG_MFD_TPS65217=y
@@ -660,6 +674,7 @@
 CONFIG_MEDIA_SUPPORT=m
 CONFIG_MEDIA_USB_SUPPORT=y
 CONFIG_USB_VIDEO_CLASS=m
+CONFIG_VIDEO_TI_VPE=m
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_V4L_MEM2MEM_DRIVERS=y
 CONFIG_VIDEO_ASPEED=m
@@ -712,6 +727,9 @@
 CONFIG_DRM_ATMEL_HLCDC=m
 CONFIG_DRM_RCAR_DU=m
 CONFIG_DRM_SUN4I=m
+CONFIG_DRM_OMAP=m
+CONFIG_OMAP5_DSS_HDMI=y
+CONFIG_DRM_TILCDC=m
 CONFIG_DRM_MSM=m
 CONFIG_DRM_FSL_DCU=m
 CONFIG_DRM_TEGRA=y
@@ -720,6 +738,7 @@
 CONFIG_DRM_PANEL_LVDS=m
 CONFIG_DRM_PANEL_SIMPLE=y
 CONFIG_DRM_PANEL_EDP=y
+CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS=y
 CONFIG_DRM_PANEL_SAMSUNG_LD9040=m
 CONFIG_DRM_PANEL_ORISETECH_OTM8009A=m
 CONFIG_DRM_PANEL_RAYDIUM_RM68200=m
@@ -735,6 +754,8 @@
 CONFIG_DRM_SIMPLE_BRIDGE=m
 CONFIG_DRM_TOSHIBA_TC358764=m
 CONFIG_DRM_TOSHIBA_TC358768=m
+CONFIG_DRM_TI_TFP410=m
+CONFIG_DRM_TI_TPD12S015=m
 CONFIG_DRM_I2C_ADV7511=m
 CONFIG_DRM_I2C_ADV7511_AUDIO=y
 CONFIG_DRM_STI=m
@@ -763,6 +784,7 @@
 CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
 CONFIG_SOUND=m
 CONFIG_SND=m
+CONFIG_SND_SOC_OMAP_HDMI=m
 CONFIG_SND_HDA_TEGRA=m
 CONFIG_SND_HDA_INPUT_BEEP=y
 CONFIG_SND_HDA_PATCH_LOADER=y
@@ -821,6 +843,7 @@
 CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=m
 CONFIG_SND_SOC_SGTL5000=m
 CONFIG_SND_SOC_STI_SAS=m
+CONFIG_SND_SOC_TLV320AIC3X_I2C=m
 CONFIG_SND_SOC_WM8978=m
 CONFIG_SND_AUDIO_GRAPH_CARD=m
 CONFIG_USB=y
@@ -851,7 +874,8 @@
 CONFIG_USB_INVENTRA_DMA=y
 CONFIG_USB_TI_CPPI41_DMA=y
 CONFIG_USB_TUSB_OMAP_DMA=y
-CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3=m
+CONFIG_USB_DWC3_DUAL_ROLE=y
 CONFIG_USB_DWC2=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_UDC=y
@@ -868,6 +892,14 @@
 CONFIG_USB_ISP1301=y
 CONFIG_USB_MXS_PHY=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
+CONFIG_USB_G_NCM=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=32
+CONFIG_USB_ZERO=m
 CONFIG_USB_RENESAS_USBHS_UDC=m
 CONFIG_USB_ASPEED_VHUB=m
 CONFIG_USB_CONFIGFS=m
@@ -890,6 +922,7 @@
 CONFIG_USB_CONFIGFS_F_UVC=y
 CONFIG_USB_CONFIGFS_F_PRINTER=y
 CONFIG_USB_ETH=m
+CONFIG_USB_CDC_COMPOSITE=m
 CONFIG_TYPEC=m
 CONFIG_TYPEC_STUSB160X=m
 CONFIG_MMC=y
@@ -965,7 +998,7 @@
 CONFIG_RTC_DRV_TWL4030=y
 CONFIG_RTC_DRV_PALMAS=y
 CONFIG_RTC_DRV_TPS6586X=y
-CONFIG_RTC_DRV_TPS65910=y
+CONFIG_RTC_DRV_TPS65910=m
 CONFIG_RTC_DRV_S35390A=m
 CONFIG_RTC_DRV_RX8581=m
 CONFIG_RTC_DRV_EM3027=y
@@ -973,6 +1006,7 @@
 CONFIG_RTC_DRV_DA9063=m
 CONFIG_RTC_DRV_EFI=m
 CONFIG_RTC_DRV_DIGICOLOR=m
+CONFIG_RTC_DRV_OMAP=m
 CONFIG_RTC_DRV_S3C=m
 CONFIG_RTC_DRV_SA1100=m
 CONFIG_RTC_DRV_SH=m
@@ -1012,6 +1046,10 @@
 CONFIG_DW_DMAC=y
 CONFIG_RCAR_DMAC=y
 CONFIG_RENESAS_USB_DMAC=m
+CONFIG_DMABUF_HEAPS=y
+CONFIG_DMABUF_HEAPS_SYSTEM=y
+CONFIG_DMABUF_HEAPS_CMA=y
+CONFIG_DMABUF_HEAPS_CARVEOUT=y
 CONFIG_VIRTIO_PCI=y
 CONFIG_VIRTIO_MMIO=y
 CONFIG_STAGING=y
@@ -1056,6 +1094,9 @@
 CONFIG_QCOM_SYSMON=m
 CONFIG_QCOM_WCNSS_PIL=m
 CONFIG_ST_REMOTEPROC=m
+CONFIG_OMAP_REMOTEPROC=m
+CONFIG_RPMSG_CHAR=m
+CONFIG_RPMSG_CTRL=m
 CONFIG_RPMSG_QCOM_SMD=y
 CONFIG_RPMSG_VIRTIO=m
 CONFIG_ASPEED_LPC_CTRL=m
@@ -1102,9 +1143,16 @@
 CONFIG_ARCH_TEGRA_3x_SOC=y
 CONFIG_ARCH_TEGRA_114_SOC=y
 CONFIG_ARCH_TEGRA_124_SOC=y
+CONFIG_SOC_TI=y
+CONFIG_TI_PRUSS=m
+CONFIG_PM_DEBUG=y
+CONFIG_PM_ADVANCED_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_DPM_WATCHDOG=y
 CONFIG_ARM_EXYNOS_BUS_DEVFREQ=m
 CONFIG_ARM_TEGRA_DEVFREQ=m
 CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP=m
+CONFIG_EXTCON_PALMAS=m
 CONFIG_EXTCON_MAX14577=m
 CONFIG_EXTCON_MAX77693=m
 CONFIG_EXTCON_MAX8997=m
@@ -1127,6 +1175,7 @@
 CONFIG_STM32_ADC=m
 CONFIG_STM32_DFSDM_ADC=m
 CONFIG_STMPE_ADC=m
+CONFIG_TI_AM335X_ADC=m
 CONFIG_VF610_ADC=m
 CONFIG_XILINX_XADC=y
 CONFIG_IIO_CROS_EC_SENSORS_CORE=m
@@ -1147,6 +1196,8 @@
 CONFIG_PWM_BCM2835=y
 CONFIG_PWM_BRCMSTB=m
 CONFIG_PWM_FSL_FTM=m
+CONFIG_PWM_TIECAP=m
+CONFIG_PWM_TIEHRPWM=m
 CONFIG_PWM_MESON=m
 CONFIG_PWM_RCAR=m
 CONFIG_PWM_RENESAS_TPU=y
@@ -1248,6 +1299,10 @@
 CONFIG_CRYPTO_DEV_STM32_CRC=m
 CONFIG_CRYPTO_DEV_STM32_HASH=m
 CONFIG_CRYPTO_DEV_STM32_CRYP=m
+CONFIG_CRYPTO_DEV_OMAP=m
+CONFIG_CRYPTO_DEV_OMAP_SHAM=m
+CONFIG_CRYPTO_DEV_OMAP_AES=m
+CONFIG_CRYPTO_DEV_OMAP_DES=m
 CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
diff -Naur --no-dereference a/arch/arm/configs/rcn-ee_defconfig b/arch/arm/configs/rcn-ee_defconfig
--- a/arch/arm/configs/rcn-ee_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm/configs/rcn-ee_defconfig	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,2864 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_LZ4=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BPF_JIT=y
+CONFIG_BPF_LSM=y
+CONFIG_PREEMPT=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_PSI=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_IKHEADERS=m
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_MEMCG=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_RDMA=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_CGROUP_BPF=y
+CONFIG_CGROUP_MISC=y
+CONFIG_NAMESPACES=y
+CONFIG_USER_NS=y
+CONFIG_CHECKPOINT_RESTORE=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_SYSFS_SYSCALL is not set
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_SOC_OMAP5=y
+CONFIG_SOC_AM33XX=y
+CONFIG_SOC_DRA7XX=y
+CONFIG_SOC_HAS_OMAP2_SDRC=y
+CONFIG_OMAP5_ERRATA_801819=y
+CONFIG_ARM_THUMBEE=y
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_PL310_ERRATA_727915=y
+CONFIG_PL310_ERRATA_753970=y
+CONFIG_ARM_ERRATA_430973=y
+CONFIG_ARM_ERRATA_773022=y
+CONFIG_ARM_ERRATA_814220=y
+CONFIG_SMP=y
+# CONFIG_ARM_CPU_TOPOLOGY is not set
+CONFIG_MCPM=y
+CONFIG_NR_CPUS=2
+CONFIG_ARM_PSCI=y
+CONFIG_HZ_250=y
+CONFIG_PARAVIRT=y
+# CONFIG_ATAGS is not set
+CONFIG_KEXEC=y
+CONFIG_CRASH_DUMP=y
+CONFIG_EFI=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
+CONFIG_CPUFREQ_DT=m
+# CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_ARM_PSCI_CPUIDLE=y
+CONFIG_KERNEL_MODE_NEON=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_ADVANCED_DEBUG=y
+CONFIG_APM_EMULATION=y
+CONFIG_ENERGY_MODEL=y
+CONFIG_KPROBES=y
+CONFIG_JUMP_LABEL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_COMPRESS_XZ=y
+CONFIG_BLK_DEV_ZONED=y
+CONFIG_BLK_DEV_THROTTLING=y
+CONFIG_BLK_WBT=y
+CONFIG_BLK_CGROUP_IOCOST=y
+CONFIG_BLK_SED_OPAL=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_KARMA_PARTITION=y
+CONFIG_MQ_IOSCHED_KYBER=m
+CONFIG_IOSCHED_BFQ=m
+CONFIG_BFQ_GROUP_IOSCHED=y
+CONFIG_BINFMT_MISC=m
+CONFIG_ZSWAP=y
+CONFIG_Z3FOLD=m
+CONFIG_SLAB_FREELIST_RANDOM=y
+CONFIG_SLAB_FREELIST_HARDENED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_KSM=y
+CONFIG_USERFAULTFD=y
+CONFIG_LRU_GEN=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=m
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=m
+CONFIG_TLS=m
+CONFIG_TLS_DEVICE=y
+CONFIG_XFRM_USER=m
+CONFIG_XFRM_INTERFACE=m
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=m
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_XDP_SOCKETS=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_FIB_TRIE_STATS=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_BROADCAST=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_NET_IPVTI=m
+CONFIG_NET_FOU_IP_TUNNELS=y
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_ESP_OFFLOAD=m
+CONFIG_INET_IPCOMP=m
+CONFIG_INET_DIAG=m
+CONFIG_INET_UDP_DIAG=m
+CONFIG_INET_RAW_DIAG=m
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_HSTCP=m
+CONFIG_TCP_CONG_HYBLA=m
+CONFIG_TCP_CONG_NV=m
+CONFIG_TCP_CONG_SCALABLE=m
+CONFIG_TCP_CONG_LP=m
+CONFIG_TCP_CONG_VENO=m
+CONFIG_TCP_CONG_YEAH=m
+CONFIG_TCP_CONG_ILLINOIS=m
+CONFIG_TCP_CONG_DCTCP=m
+CONFIG_TCP_CONG_CDG=m
+CONFIG_TCP_CONG_BBR=m
+CONFIG_TCP_MD5SIG=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=m
+CONFIG_INET6_ESP=m
+CONFIG_INET6_ESP_OFFLOAD=m
+CONFIG_INET6_IPCOMP=m
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_ILA=m
+CONFIG_IPV6_VTI=m
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_SIT_6RD=y
+CONFIG_IPV6_GRE=m
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_IPV6_SEG6_LWTUNNEL=y
+CONFIG_IPV6_SEG6_HMAC=y
+CONFIG_NETLABEL=y
+CONFIG_MPTCP=y
+CONFIG_NETWORK_PHY_TIMESTAMPING=y
+CONFIG_NETFILTER=y
+CONFIG_BRIDGE_NETFILTER=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CONNTRACK_AMANDA=m
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+CONFIG_NF_CONNTRACK_NETBIOS_NS=m
+CONFIG_NF_CONNTRACK_SNMP=m
+CONFIG_NF_CONNTRACK_PPTP=m
+CONFIG_NF_CONNTRACK_SANE=m
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+CONFIG_NF_CT_NETLINK_TIMEOUT=m
+CONFIG_NF_CT_NETLINK_HELPER=m
+CONFIG_NETFILTER_NETLINK_GLUE_CT=y
+CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=y
+CONFIG_NF_TABLES_NETDEV=y
+CONFIG_NFT_NUMGEN=m
+CONFIG_NFT_CT=m
+CONFIG_NFT_FLOW_OFFLOAD=m
+CONFIG_NFT_CONNLIMIT=m
+CONFIG_NFT_LOG=m
+CONFIG_NFT_LIMIT=m
+CONFIG_NFT_MASQ=m
+CONFIG_NFT_REDIR=m
+CONFIG_NFT_NAT=m
+CONFIG_NFT_TUNNEL=m
+CONFIG_NFT_OBJREF=m
+CONFIG_NFT_QUEUE=m
+CONFIG_NFT_QUOTA=m
+CONFIG_NFT_REJECT=m
+CONFIG_NFT_COMPAT=m
+CONFIG_NFT_HASH=m
+CONFIG_NFT_FIB_INET=m
+CONFIG_NFT_XFRM=m
+CONFIG_NFT_SOCKET=m
+CONFIG_NFT_OSF=m
+CONFIG_NFT_TPROXY=m
+CONFIG_NFT_SYNPROXY=m
+CONFIG_NFT_DUP_NETDEV=m
+CONFIG_NFT_FWD_NETDEV=m
+CONFIG_NFT_FIB_NETDEV=m
+CONFIG_NF_FLOW_TABLE_INET=m
+CONFIG_NF_FLOW_TABLE=m
+CONFIG_NETFILTER_XT_SET=m
+CONFIG_NETFILTER_XT_TARGET_AUDIT=m
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HMARK=m
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+CONFIG_NETFILTER_XT_TARGET_LED=m
+CONFIG_NETFILTER_XT_TARGET_LOG=m
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_SECMARK=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m
+CONFIG_NETFILTER_XT_MATCH_BPF=m
+CONFIG_NETFILTER_XT_MATCH_CGROUP=m
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=m
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m
+CONFIG_NETFILTER_XT_MATCH_DSCP=m
+CONFIG_NETFILTER_XT_MATCH_ESP=m
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_IPCOMP=m
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+CONFIG_NETFILTER_XT_MATCH_IPVS=m
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+CONFIG_NETFILTER_XT_MATCH_NFACCT=m
+CONFIG_NETFILTER_XT_MATCH_OSF=m
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+CONFIG_IP_SET=m
+CONFIG_IP_SET_BITMAP_IP=m
+CONFIG_IP_SET_BITMAP_IPMAC=m
+CONFIG_IP_SET_BITMAP_PORT=m
+CONFIG_IP_SET_HASH_IP=m
+CONFIG_IP_SET_HASH_IPMARK=m
+CONFIG_IP_SET_HASH_IPPORT=m
+CONFIG_IP_SET_HASH_IPPORTIP=m
+CONFIG_IP_SET_HASH_IPPORTNET=m
+CONFIG_IP_SET_HASH_IPMAC=m
+CONFIG_IP_SET_HASH_MAC=m
+CONFIG_IP_SET_HASH_NETPORTNET=m
+CONFIG_IP_SET_HASH_NET=m
+CONFIG_IP_SET_HASH_NETNET=m
+CONFIG_IP_SET_HASH_NETPORT=m
+CONFIG_IP_SET_HASH_NETIFACE=m
+CONFIG_IP_SET_LIST_SET=m
+CONFIG_IP_VS=m
+CONFIG_IP_VS_IPV6=y
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_PROTO_ESP=y
+CONFIG_IP_VS_PROTO_AH=y
+CONFIG_IP_VS_PROTO_SCTP=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_WRR=m
+CONFIG_IP_VS_LC=m
+CONFIG_IP_VS_WLC=m
+CONFIG_IP_VS_FO=m
+CONFIG_IP_VS_OVF=m
+CONFIG_IP_VS_LBLC=m
+CONFIG_IP_VS_LBLCR=m
+CONFIG_IP_VS_DH=m
+CONFIG_IP_VS_SH=m
+CONFIG_IP_VS_MH=m
+CONFIG_IP_VS_SED=m
+CONFIG_IP_VS_NQ=m
+CONFIG_IP_VS_FTP=m
+CONFIG_IP_VS_PE_SIP=m
+CONFIG_NFT_DUP_IPV4=m
+CONFIG_NFT_FIB_IPV4=m
+CONFIG_NF_TABLES_ARP=y
+CONFIG_NF_LOG_ARP=m
+CONFIG_NF_LOG_IPV4=m
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_RPFILTER=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_SYNPROXY=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_SECURITY=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+CONFIG_NFT_DUP_IPV6=m
+CONFIG_NFT_FIB_IPV6=m
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+CONFIG_IP6_NF_MATCH_RPFILTER=m
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_MATCH_SRH=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+CONFIG_IP6_NF_TARGET_SYNPROXY=m
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+CONFIG_IP6_NF_SECURITY=m
+CONFIG_IP6_NF_NAT=m
+CONFIG_IP6_NF_TARGET_MASQUERADE=m
+CONFIG_IP6_NF_TARGET_NPT=m
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_NFT_BRIDGE_META=m
+CONFIG_NFT_BRIDGE_REJECT=m
+CONFIG_NF_CONNTRACK_BRIDGE=m
+CONFIG_BRIDGE_NF_EBTABLES=m
+CONFIG_BRIDGE_EBT_BROUTE=m
+CONFIG_BRIDGE_EBT_T_FILTER=m
+CONFIG_BRIDGE_EBT_T_NAT=m
+CONFIG_BRIDGE_EBT_802_3=m
+CONFIG_BRIDGE_EBT_AMONG=m
+CONFIG_BRIDGE_EBT_ARP=m
+CONFIG_BRIDGE_EBT_IP=m
+CONFIG_BRIDGE_EBT_IP6=m
+CONFIG_BRIDGE_EBT_LIMIT=m
+CONFIG_BRIDGE_EBT_MARK=m
+CONFIG_BRIDGE_EBT_PKTTYPE=m
+CONFIG_BRIDGE_EBT_STP=m
+CONFIG_BRIDGE_EBT_VLAN=m
+CONFIG_BRIDGE_EBT_ARPREPLY=m
+CONFIG_BRIDGE_EBT_DNAT=m
+CONFIG_BRIDGE_EBT_MARK_T=m
+CONFIG_BRIDGE_EBT_REDIRECT=m
+CONFIG_BRIDGE_EBT_SNAT=m
+CONFIG_BRIDGE_EBT_LOG=m
+CONFIG_BRIDGE_EBT_NFLOG=m
+CONFIG_IP_DCCP=m
+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1=y
+CONFIG_SCTP_COOKIE_HMAC_MD5=y
+CONFIG_RDS=m
+CONFIG_RDS_TCP=m
+CONFIG_TIPC=m
+CONFIG_ATM=m
+CONFIG_ATM_CLIP=m
+CONFIG_ATM_LANE=m
+CONFIG_ATM_MPOA=m
+CONFIG_ATM_BR2684=m
+CONFIG_L2TP=m
+CONFIG_L2TP_DEBUGFS=m
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=m
+CONFIG_L2TP_ETH=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=m
+CONFIG_VLAN_8021Q_GVRP=y
+CONFIG_VLAN_8021Q_MVRP=y
+CONFIG_LLC2=m
+CONFIG_ATALK=m
+CONFIG_PHONET=m
+CONFIG_6LOWPAN=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m
+CONFIG_6LOWPAN_GHC_UDP=m
+CONFIG_6LOWPAN_GHC_ICMPV6=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m
+CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m
+CONFIG_IEEE802154=m
+CONFIG_IEEE802154_6LOWPAN=m
+CONFIG_MAC802154=m
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_CBQ=m
+CONFIG_NET_SCH_HTB=m
+CONFIG_NET_SCH_HFSC=m
+CONFIG_NET_SCH_ATM=m
+CONFIG_NET_SCH_PRIO=m
+CONFIG_NET_SCH_MULTIQ=m
+CONFIG_NET_SCH_RED=m
+CONFIG_NET_SCH_SFB=m
+CONFIG_NET_SCH_SFQ=m
+CONFIG_NET_SCH_TEQL=m
+CONFIG_NET_SCH_TBF=m
+CONFIG_NET_SCH_CBS=m
+CONFIG_NET_SCH_ETF=m
+CONFIG_NET_SCH_TAPRIO=m
+CONFIG_NET_SCH_GRED=m
+CONFIG_NET_SCH_DSMARK=m
+CONFIG_NET_SCH_NETEM=m
+CONFIG_NET_SCH_DRR=m
+CONFIG_NET_SCH_MQPRIO=m
+CONFIG_NET_SCH_SKBPRIO=m
+CONFIG_NET_SCH_CHOKE=m
+CONFIG_NET_SCH_QFQ=m
+CONFIG_NET_SCH_CODEL=m
+CONFIG_NET_SCH_FQ_CODEL=y
+CONFIG_NET_SCH_CAKE=m
+CONFIG_NET_SCH_FQ=m
+CONFIG_NET_SCH_HHF=m
+CONFIG_NET_SCH_PIE=m
+CONFIG_NET_SCH_FQ_PIE=m
+CONFIG_NET_SCH_INGRESS=m
+CONFIG_NET_SCH_PLUG=m
+CONFIG_NET_SCH_ETS=m
+CONFIG_NET_SCH_DEFAULT=y
+CONFIG_DEFAULT_FQ_CODEL=y
+CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_PERF=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_CLS_CGROUP=y
+CONFIG_NET_CLS_BPF=m
+CONFIG_NET_CLS_FLOWER=m
+CONFIG_NET_CLS_MATCHALL=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
+CONFIG_NET_EMATCH_CANID=m
+CONFIG_NET_EMATCH_IPSET=m
+CONFIG_NET_EMATCH_IPT=m
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
+CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
+CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_SAMPLE=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
+CONFIG_NET_ACT_MPLS=m
+CONFIG_NET_ACT_VLAN=m
+CONFIG_NET_ACT_BPF=m
+CONFIG_NET_ACT_CONNMARK=m
+CONFIG_NET_ACT_CTINFO=m
+CONFIG_NET_ACT_SKBMOD=m
+CONFIG_NET_ACT_IFE=m
+CONFIG_NET_ACT_TUNNEL_KEY=m
+CONFIG_NET_ACT_CT=m
+CONFIG_NET_ACT_GATE=m
+CONFIG_NET_IFE_SKBMARK=m
+CONFIG_NET_IFE_SKBPRIO=m
+CONFIG_NET_IFE_SKBTCINDEX=m
+CONFIG_DCB=y
+CONFIG_BATMAN_ADV=m
+CONFIG_BATMAN_ADV_NC=y
+CONFIG_OPENVSWITCH=m
+CONFIG_VSOCKETS=m
+CONFIG_VIRTIO_VSOCKETS=m
+CONFIG_NETLINK_DIAG=m
+CONFIG_NET_MPLS_GSO=y
+CONFIG_MPLS_ROUTING=m
+CONFIG_MPLS_IPTUNNEL=m
+CONFIG_HSR=m
+CONFIG_NET_SWITCHDEV=y
+CONFIG_QRTR=m
+CONFIG_QRTR_SMD=m
+CONFIG_QRTR_TUN=m
+CONFIG_NET_NCSI=y
+CONFIG_CGROUP_NET_PRIO=y
+CONFIG_BPF_STREAM_PARSER=y
+CONFIG_NET_PKTGEN=m
+CONFIG_NET_DROP_MONITOR=m
+CONFIG_HAMRADIO=y
+CONFIG_AX25=m
+CONFIG_NETROM=m
+CONFIG_ROSE=m
+CONFIG_MKISS=m
+CONFIG_6PACK=m
+CONFIG_BPQETHER=m
+CONFIG_BAYCOM_SER_FDX=m
+CONFIG_BAYCOM_SER_HDX=m
+CONFIG_YAM=m
+CONFIG_CAN=m
+CONFIG_CAN_J1939=m
+CONFIG_CAN_ISOTP=m
+CONFIG_BT=m
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_HS=y
+CONFIG_BT_6LOWPAN=m
+CONFIG_BT_LEDS=y
+CONFIG_BT_MSFTEXT=y
+CONFIG_BT_HCIBTUSB=m
+CONFIG_BT_HCIBTUSB_MTK=y
+CONFIG_BT_HCIBTSDIO=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_NOKIA=m
+CONFIG_BT_HCIUART_ATH3K=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIUART_INTEL=y
+CONFIG_BT_HCIUART_BCM=y
+CONFIG_BT_HCIUART_RTL=y
+CONFIG_BT_HCIUART_QCA=y
+CONFIG_BT_HCIUART_AG6XX=y
+CONFIG_BT_HCIUART_MRVL=y
+CONFIG_BT_MRVL=m
+CONFIG_BT_MRVL_SDIO=m
+CONFIG_BT_ATH3K=m
+CONFIG_BT_MTKUART=m
+CONFIG_AF_RXRPC_IPV6=y
+CONFIG_RXKAD=y
+CONFIG_AF_KCM=m
+CONFIG_CFG80211=m
+# CONFIG_CFG80211_DEFAULT_PS is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_MESH=y
+CONFIG_RFKILL=y
+CONFIG_RFKILL_INPUT=y
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+CONFIG_NFC=m
+CONFIG_NFC_DIGITAL=m
+CONFIG_NFC_NCI=m
+CONFIG_NFC_NCI_SPI=m
+CONFIG_NFC_NCI_UART=m
+CONFIG_NFC_TRF7970A=m
+CONFIG_NFC_SIM=m
+CONFIG_NFC_PORT100=m
+CONFIG_NFC_PN533_USB=m
+CONFIG_NFC_PN533_I2C=m
+CONFIG_NFC_ST_NCI_I2C=m
+CONFIG_NFC_ST_NCI_SPI=m
+CONFIG_NFC_NXP_NCI=m
+CONFIG_NFC_NXP_NCI_I2C=m
+CONFIG_NFC_ST95HF=m
+CONFIG_PAGE_POOL_STATS=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_EXTRA_FIRMWARE="regulatory.db regulatory.db.p7s am335x-pm-firmware.elf am335x-bone-scale-data.bin am335x-evm-scale-data.bin am43x-evm-scale-data.bin"
+CONFIG_EXTRA_FIRMWARE_DIR="firmware"
+CONFIG_OMAP_OCP2SCP=y
+CONFIG_CONNECTOR=y
+CONFIG_DMI_SYSFS=y
+CONFIG_TRUSTED_FOUNDATIONS=y
+CONFIG_EFI_BOOTLOADER_CONTROL=m
+CONFIG_EFI_CAPSULE_LOADER=m
+CONFIG_RESET_ATTACK_MITIGATION=y
+CONFIG_GNSS=m
+CONFIG_GNSS_MTK_SERIAL=m
+CONFIG_GNSS_SIRF_SERIAL=m
+CONFIG_GNSS_UBX_SERIAL=m
+CONFIG_MTD=y
+CONFIG_MTD_AR7_PARTS=m
+CONFIG_MTD_OF_PARTS=m
+CONFIG_MTD_BLOCK=m
+CONFIG_MTD_BLOCK_RO=m
+CONFIG_RFD_FTL=m
+CONFIG_SSFDC=m
+CONFIG_MTD_OOPS=m
+CONFIG_MTD_SWAP=m
+CONFIG_MTD_PHYSMAP=m
+CONFIG_MTD_PLATRAM=m
+CONFIG_MTD_DATAFLASH=m
+CONFIG_MTD_SST25L=m
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+CONFIG_MTD_ONENAND_2X_PROGRAM=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_MTD_NAND_OMAP2=m
+CONFIG_MTD_NAND_NANDSIM=m
+CONFIG_MTD_NAND_ECC_SW_BCH=y
+CONFIG_MTD_LPDDR=m
+CONFIG_MTD_SPI_NOR=m
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_BLOCK=y
+CONFIG_OF_OVERLAY=y
+CONFIG_BLK_DEV_NULL_BLK=m
+CONFIG_ZRAM=m
+CONFIG_ZRAM_WRITEBACK=y
+CONFIG_ZRAM_MEMORY_TRACKING=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_DRBD=m
+CONFIG_BLK_DEV_NBD=m
+CONFIG_BLK_DEV_RAM=m
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_ATA_OVER_ETH=m
+CONFIG_VIRTIO_BLK=m
+CONFIG_BLK_DEV_RBD=m
+CONFIG_AD525X_DPOT=m
+CONFIG_AD525X_DPOT_I2C=m
+CONFIG_AD525X_DPOT_SPI=m
+CONFIG_ICS932S401=m
+CONFIG_APDS9802ALS=m
+CONFIG_ISL29003=m
+CONFIG_ISL29020=m
+CONFIG_SENSORS_TSL2550=m
+CONFIG_SENSORS_BH1770=m
+CONFIG_SENSORS_APDS990X=m
+CONFIG_HMC6352=m
+CONFIG_DS1682=m
+CONFIG_SRAM=y
+CONFIG_SRAM_DMA_HEAP=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_EEPROM_LEGACY=m
+CONFIG_EEPROM_MAX6875=m
+CONFIG_EEPROM_93XX46=m
+CONFIG_EEPROM_EE1004=m
+CONFIG_TI_ST=m
+CONFIG_RAID_ATTRS=m
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_SG=m
+CONFIG_CHR_DEV_SCH=m
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SAS_ATA=y
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_ATA=y
+CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
+CONFIG_MD_CLUSTER=m
+CONFIG_BCACHE=m
+CONFIG_BLK_DEV_DM=m
+CONFIG_DM_UNSTRIPED=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_THIN_PROVISIONING=m
+CONFIG_DM_CACHE=m
+CONFIG_DM_WRITECACHE=m
+CONFIG_DM_ERA=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_LOG_USERSPACE=m
+CONFIG_DM_ZERO=m
+CONFIG_DM_MULTIPATH=m
+CONFIG_DM_MULTIPATH_QL=m
+CONFIG_DM_MULTIPATH_ST=m
+CONFIG_DM_DELAY=m
+CONFIG_DM_UEVENT=y
+CONFIG_DM_FLAKEY=m
+CONFIG_DM_VERITY=m
+CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG=y
+CONFIG_DM_SWITCH=m
+CONFIG_DM_LOG_WRITES=m
+CONFIG_DM_INTEGRITY=m
+CONFIG_DM_ZONED=m
+CONFIG_TARGET_CORE=m
+CONFIG_TCM_IBLOCK=m
+CONFIG_TCM_FILEIO=m
+CONFIG_TCM_PSCSI=m
+CONFIG_TCM_USER2=m
+CONFIG_LOOPBACK_TARGET=m
+CONFIG_ISCSI_TARGET=m
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=m
+CONFIG_DUMMY=m
+CONFIG_WIREGUARD=m
+CONFIG_EQUALIZER=m
+CONFIG_IFB=m
+CONFIG_NET_TEAM=m
+CONFIG_NET_TEAM_MODE_BROADCAST=m
+CONFIG_NET_TEAM_MODE_ROUNDROBIN=m
+CONFIG_NET_TEAM_MODE_RANDOM=m
+CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m
+CONFIG_NET_TEAM_MODE_LOADBALANCE=m
+CONFIG_MACVLAN=m
+CONFIG_MACVTAP=m
+CONFIG_IPVLAN=m
+CONFIG_IPVTAP=m
+CONFIG_VXLAN=m
+CONFIG_GENEVE=m
+CONFIG_GTP=m
+CONFIG_MACSEC=m
+CONFIG_NETCONSOLE=m
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_VIRTIO_NET=m
+CONFIG_NLMON=m
+CONFIG_NET_VRF=m
+CONFIG_ATM_DUMMY=m
+# CONFIG_NET_VENDOR_ALACRITECH is not set
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_VENDOR_AQUANTIA is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CADENCE is not set
+# CONFIG_NET_VENDOR_CAVIUM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_CORTINA is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_GOOGLE is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_HUAWEI is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+CONFIG_KS8851=m
+CONFIG_ENC28J60=y
+CONFIG_ENCX24J600=y
+# CONFIG_NET_VENDOR_NI is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_PENSANDO is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SOLARFLARE is not set
+CONFIG_SMC91X=m
+CONFIG_SMC911X=m
+CONFIG_SMSC911X=m
+# CONFIG_NET_VENDOR_SOCIONEXT is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
+CONFIG_TI_CPSW_PHY_SEL=y
+CONFIG_TI_CPSW=y
+CONFIG_TI_CPSW_SWITCHDEV=y
+CONFIG_TI_CPTS=y
+# CONFIG_NET_VENDOR_VIA is not set
+CONFIG_WIZNET_W5100=y
+CONFIG_WIZNET_W5100_SPI=y
+# CONFIG_NET_VENDOR_XILINX is not set
+CONFIG_LED_TRIGGER_PHY=y
+CONFIG_MICREL_PHY=y
+CONFIG_MICROCHIP_PHY=y
+CONFIG_MICROSEMI_PHY=m
+CONFIG_AT803X_PHY=y
+CONFIG_DP83867_PHY=y
+CONFIG_DP83869_PHY=m
+CONFIG_VITESSE_PHY=y
+CONFIG_CAN_VCAN=m
+CONFIG_CAN_VXCAN=m
+CONFIG_CAN_SLCAN=m
+CONFIG_CAN_C_CAN=m
+CONFIG_CAN_C_CAN_PLATFORM=m
+CONFIG_CAN_HI311X=m
+CONFIG_CAN_MCP251X=m
+CONFIG_CAN_MCP251XFD=m
+CONFIG_CAN_8DEV_USB=m
+CONFIG_CAN_EMS_USB=m
+CONFIG_CAN_ESD_USB=m
+CONFIG_CAN_GS_USB=m
+CONFIG_CAN_KVASER_USB=m
+CONFIG_CAN_MCBA_USB=m
+CONFIG_CAN_PEAK_USB=m
+CONFIG_CAN_UCAN=m
+CONFIG_MDIO_BCM_UNIMAC=m
+CONFIG_MDIO_GPIO=y
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOATM=m
+CONFIG_PPPOE=m
+CONFIG_PPTP=m
+CONFIG_PPPOL2TP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_RTL8152=m
+CONFIG_USB_LAN78XX=m
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_AX88179_178A=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_HUAWEI_CDC_NCM=m
+CONFIG_USB_NET_CDC_MBIM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SR9700=m
+CONFIG_USB_NET_SR9800=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_NET_CX82310_ETH=m
+CONFIG_USB_NET_KALMIA=m
+CONFIG_USB_NET_QMI_WWAN=m
+CONFIG_USB_HSO=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_CDC_PHONET=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_USB_VL600=m
+CONFIG_USB_NET_CH9200=m
+CONFIG_USB_NET_AQC111=m
+CONFIG_ATH9K=m
+CONFIG_ATH9K_CHANNEL_CONTEXT=y
+CONFIG_ATH9K_HTC=m
+CONFIG_CARL9170=m
+CONFIG_ATH6KL=m
+CONFIG_ATH6KL_SDIO=m
+CONFIG_ATH6KL_USB=m
+CONFIG_AR5523=m
+CONFIG_ATH10K=m
+CONFIG_ATH10K_SDIO=m
+CONFIG_ATH10K_USB=m
+CONFIG_ATH11K=m
+CONFIG_ATH11K_AHB=m
+CONFIG_AT76C50X_USB=m
+CONFIG_BRCMFMAC=m
+# CONFIG_WLAN_VENDOR_CISCO is not set
+CONFIG_P54_COMMON=m
+CONFIG_P54_USB=m
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_MESH=y
+CONFIG_LIBERTAS_THINFIRM=m
+CONFIG_LIBERTAS_THINFIRM_USB=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_USB=m
+CONFIG_MT7601U=m
+CONFIG_MT76x0U=m
+CONFIG_MT76x2U=m
+CONFIG_MT7663U=m
+CONFIG_MT7663S=m
+CONFIG_MT7921S=m
+CONFIG_MT7921U=m
+CONFIG_WILC1000_SDIO=m
+CONFIG_WILC1000_SPI=m
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT3573=y
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RT2800USB_RT55XX=y
+CONFIG_RTL8187=m
+CONFIG_RTL8192CU=m
+# CONFIG_RTLWIFI_DEBUG is not set
+CONFIG_RTL8XXXU=m
+CONFIG_RTW88=m
+CONFIG_RTW89=m
+CONFIG_RSI_91X=m
+# CONFIG_RSI_SDIO is not set
+CONFIG_WL1251=m
+CONFIG_WL1251_SPI=m
+CONFIG_WL1251_SDIO=m
+CONFIG_WL12XX=m
+CONFIG_WL18XX=m
+CONFIG_WLCORE_SPI=m
+CONFIG_WLCORE_SDIO=m
+CONFIG_ZD1211RW=m
+CONFIG_MAC80211_HWSIM=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_IEEE802154_AT86RF230=m
+CONFIG_IEEE802154_MRF24J40=m
+CONFIG_IEEE802154_CC2520=m
+CONFIG_IEEE802154_ATUSB=m
+CONFIG_IEEE802154_WPANUSB=m
+CONFIG_IEEE802154_ADF7242=m
+CONFIG_IEEE802154_CA8210=m
+CONFIG_IEEE802154_MCR20A=m
+CONFIG_IEEE802154_HWSIM=m
+CONFIG_INPUT_SPARSEKMAP=m
+CONFIG_INPUT_JOYDEV=m
+CONFIG_INPUT_EVDEV=m
+CONFIG_KEYBOARD_ADP5588=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_QT2160=m
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_TCA8418=m
+CONFIG_KEYBOARD_LM8323=m
+CONFIG_KEYBOARD_MAX7359=m
+CONFIG_KEYBOARD_STOWAWAY=m
+# CONFIG_MOUSE_PS2 is not set
+CONFIG_MOUSE_APPLETOUCH=m
+CONFIG_MOUSE_ELAN_I2C=m
+CONFIG_MOUSE_SYNAPTICS_I2C=m
+CONFIG_MOUSE_SYNAPTICS_USB=m
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_JOYSTICK_IFORCE=m
+CONFIG_JOYSTICK_IFORCE_USB=m
+CONFIG_JOYSTICK_IFORCE_232=m
+CONFIG_JOYSTICK_WARRIOR=m
+CONFIG_JOYSTICK_MAGELLAN=m
+CONFIG_JOYSTICK_SPACEORB=m
+CONFIG_JOYSTICK_SPACEBALL=m
+CONFIG_JOYSTICK_STINGER=m
+CONFIG_JOYSTICK_TWIDJOY=m
+CONFIG_JOYSTICK_ZHENHUA=m
+CONFIG_JOYSTICK_AS5011=m
+CONFIG_JOYSTICK_XPAD=m
+CONFIG_JOYSTICK_XPAD_FF=y
+CONFIG_JOYSTICK_XPAD_LEDS=y
+CONFIG_JOYSTICK_PSXPAD_SPI=y
+CONFIG_JOYSTICK_PSXPAD_SPI_FF=y
+CONFIG_JOYSTICK_PXRC=m
+CONFIG_JOYSTICK_FSIA6B=m
+CONFIG_INPUT_TABLET=y
+CONFIG_TABLET_USB_ACECAD=m
+CONFIG_TABLET_USB_AIPTEK=m
+CONFIG_TABLET_USB_HANWANG=m
+CONFIG_TABLET_USB_KBTAB=m
+CONFIG_TABLET_USB_PEGASUS=m
+CONFIG_TABLET_SERIAL_WACOM4=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_AD7877=m
+CONFIG_TOUCHSCREEN_AD7879=m
+CONFIG_TOUCHSCREEN_AD7879_I2C=m
+CONFIG_TOUCHSCREEN_AR1021_I2C=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
+CONFIG_TOUCHSCREEN_DYNAPRO=m
+CONFIG_TOUCHSCREEN_HAMPSHIRE=m
+CONFIG_TOUCHSCREEN_EETI=m
+CONFIG_TOUCHSCREEN_FUJITSU=m
+CONFIG_TOUCHSCREEN_GOODIX=m
+CONFIG_TOUCHSCREEN_GUNZE=m
+CONFIG_TOUCHSCREEN_ELAN=m
+CONFIG_TOUCHSCREEN_ELO=m
+CONFIG_TOUCHSCREEN_WACOM_W8001=m
+CONFIG_TOUCHSCREEN_MCS5000=m
+CONFIG_TOUCHSCREEN_MTOUCH=m
+CONFIG_TOUCHSCREEN_INEXIO=m
+CONFIG_TOUCHSCREEN_MK712=m
+CONFIG_TOUCHSCREEN_PENMOUNT=m
+CONFIG_TOUCHSCREEN_EDT_FT5X06=y
+CONFIG_TOUCHSCREEN_TOUCHRIGHT=m
+CONFIG_TOUCHSCREEN_TOUCHWIN=m
+CONFIG_TOUCHSCREEN_TI_AM335X_TSC=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+CONFIG_TOUCHSCREEN_TOUCHIT213=m
+CONFIG_TOUCHSCREEN_TSC2005=m
+CONFIG_TOUCHSCREEN_TSC2007=m
+CONFIG_TOUCHSCREEN_SILEAD=y
+CONFIG_TOUCHSCREEN_STMPE=y
+CONFIG_TOUCHSCREEN_TPS6507X=m
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AD714X=m
+CONFIG_INPUT_MMA8450=m
+CONFIG_INPUT_GPIO_DECODER=m
+CONFIG_INPUT_ATI_REMOTE2=m
+CONFIG_INPUT_KEYSPAN_REMOTE=m
+CONFIG_INPUT_POWERMATE=m
+CONFIG_INPUT_YEALINK=m
+CONFIG_INPUT_CM109=m
+CONFIG_INPUT_TPS65218_PWRBUTTON=y
+CONFIG_INPUT_TPS65219_PWRBUTTON=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_PALMAS_PWRBUTTON=y
+CONFIG_RMI4_F34=y
+CONFIG_RMI4_F3A=y
+CONFIG_RMI4_F55=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set
+# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_SERIAL_8250_DMA is not set
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_RUNTIME_UARTS=6
+CONFIG_SERIAL_8250_OMAP=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_MAX3100=m
+CONFIG_SERIAL_MAX310X=m
+CONFIG_N_GSM=m
+CONFIG_RPMSG_TTY=m
+CONFIG_SERIAL_DEV_BUS=y
+CONFIG_TTY_PRINTK=m
+CONFIG_VIRTIO_CONSOLE=m
+CONFIG_HW_RANDOM_VIRTIO=m
+CONFIG_TCG_TIS_I2C_ATMEL=y
+CONFIG_TCG_TIS_I2C_INFINEON=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=m
+CONFIG_I2C_MUX_GPIO=y
+CONFIG_I2C_MUX_PCA954x=m
+CONFIG_I2C_MUX_PINCTRL=y
+CONFIG_I2C_ATR=m
+CONFIG_I2C_GPIO=y
+CONFIG_I2C_DIOLAN_U2C=m
+CONFIG_I2C_ROBOTFUZZ_OSIF=m
+CONFIG_I2C_TAOS_EVM=m
+CONFIG_I2C_TINY_USB=m
+CONFIG_I2C_SLAVE=y
+CONFIG_I2C_SLAVE_EEPROM=y
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_OMAP24XX=y
+CONFIG_SPI_TI_QSPI=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_SLAVE=y
+CONFIG_SPI_SLAVE_TIME=m
+CONFIG_SPI_SLAVE_SYSTEM_CONTROL=m
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_PPS_CLIENT_GPIO=m
+CONFIG_PINCTRL_MCP23S08=m
+CONFIG_PINCTRL_PALMAS=y
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_GPIO_SYSCON=y
+CONFIG_GPIO_ADNP=m
+CONFIG_GPIO_MAX7300=m
+CONFIG_GPIO_MAX732X=m
+CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_PCA953X_IRQ=y
+CONFIG_GPIO_PCF857X=m
+CONFIG_GPIO_TPIC2810=m
+CONFIG_GPIO_PALMAS=y
+CONFIG_GPIO_STMPE=y
+CONFIG_GPIO_TPS65218=y
+CONFIG_GPIO_74X164=m
+CONFIG_GPIO_MAX3191X=m
+CONFIG_GPIO_MAX7301=m
+CONFIG_GPIO_MC33880=m
+CONFIG_GPIO_PISOSR=m
+CONFIG_GPIO_XRA1403=m
+CONFIG_GPIO_AGGREGATOR=m
+CONFIG_W1=y
+CONFIG_W1_MASTER_DS2490=m
+CONFIG_W1_MASTER_DS2482=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_THERM=m
+CONFIG_W1_SLAVE_SMEM=m
+CONFIG_W1_SLAVE_DS2405=m
+CONFIG_W1_SLAVE_DS2408=m
+CONFIG_W1_SLAVE_DS2413=m
+CONFIG_W1_SLAVE_DS2406=m
+CONFIG_W1_SLAVE_DS2423=m
+CONFIG_W1_SLAVE_DS2805=m
+CONFIG_W1_SLAVE_DS2430=m
+CONFIG_W1_SLAVE_DS2431=m
+CONFIG_W1_SLAVE_DS2433=m
+CONFIG_W1_SLAVE_DS2433_CRC=y
+CONFIG_W1_SLAVE_DS2438=m
+CONFIG_W1_SLAVE_DS250X=m
+CONFIG_W1_SLAVE_DS2780=m
+CONFIG_W1_SLAVE_DS2781=m
+CONFIG_W1_SLAVE_DS28E04=m
+CONFIG_W1_SLAVE_DS28E17=m
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
+CONFIG_POWER_RESET_GPIO_RESTART=y
+CONFIG_POWER_RESET_RESTART=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_RESET_SYSCON_POWEROFF=y
+CONFIG_SYSCON_REBOOT_MODE=m
+CONFIG_GENERIC_ADC_BATTERY=m
+CONFIG_BATTERY_DS2760=m
+CONFIG_CHARGER_GPIO=m
+CONFIG_CHARGER_BQ2415X=m
+CONFIG_SENSORS_AD7314=m
+CONFIG_SENSORS_AD7414=m
+CONFIG_SENSORS_AD7418=m
+CONFIG_SENSORS_ADM1025=m
+CONFIG_SENSORS_ADM1026=m
+CONFIG_SENSORS_ADM1029=m
+CONFIG_SENSORS_ADM1031=m
+CONFIG_SENSORS_ADM1177=m
+CONFIG_SENSORS_ADM9240=m
+CONFIG_SENSORS_ADT7310=m
+CONFIG_SENSORS_ADT7410=m
+CONFIG_SENSORS_ADT7411=m
+CONFIG_SENSORS_ADT7462=m
+CONFIG_SENSORS_ADT7470=m
+CONFIG_SENSORS_ADT7475=m
+CONFIG_SENSORS_AHT10=m
+CONFIG_SENSORS_AQUACOMPUTER_D5NEXT=m
+CONFIG_SENSORS_AS370=m
+CONFIG_SENSORS_ASC7621=m
+CONFIG_SENSORS_AXI_FAN_CONTROL=m
+CONFIG_SENSORS_ATXP1=m
+CONFIG_SENSORS_CORSAIR_CPRO=m
+CONFIG_SENSORS_CORSAIR_PSU=m
+CONFIG_SENSORS_DRIVETEMP=m
+CONFIG_SENSORS_DS620=m
+CONFIG_SENSORS_DS1621=m
+CONFIG_SENSORS_F71805F=m
+CONFIG_SENSORS_F71882FG=m
+CONFIG_SENSORS_F75375S=m
+CONFIG_SENSORS_FTSTEUTATES=m
+CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
+CONFIG_SENSORS_G760A=m
+CONFIG_SENSORS_G762=m
+CONFIG_SENSORS_GPIO_FAN=y
+CONFIG_SENSORS_HIH6130=m
+CONFIG_SENSORS_IIO_HWMON=m
+CONFIG_SENSORS_IT87=m
+CONFIG_SENSORS_JC42=m
+CONFIG_SENSORS_POWR1220=m
+CONFIG_SENSORS_LINEAGE=m
+CONFIG_SENSORS_LTC2945=m
+CONFIG_SENSORS_LTC2947_I2C=m
+CONFIG_SENSORS_LTC2947_SPI=m
+CONFIG_SENSORS_LTC2990=m
+CONFIG_SENSORS_LTC2992=m
+CONFIG_SENSORS_LTC4151=m
+CONFIG_SENSORS_LTC4215=m
+CONFIG_SENSORS_LTC4222=m
+CONFIG_SENSORS_LTC4245=m
+CONFIG_SENSORS_LTC4260=m
+CONFIG_SENSORS_LTC4261=m
+CONFIG_SENSORS_MAX1111=m
+CONFIG_SENSORS_MAX127=m
+CONFIG_SENSORS_MAX16065=m
+CONFIG_SENSORS_MAX1619=m
+CONFIG_SENSORS_MAX1668=m
+CONFIG_SENSORS_MAX197=m
+CONFIG_SENSORS_MAX31722=m
+CONFIG_SENSORS_MAX31730=m
+CONFIG_SENSORS_MAX31760=m
+CONFIG_SENSORS_MAX6620=m
+CONFIG_SENSORS_MAX6621=m
+CONFIG_SENSORS_MAX6639=m
+CONFIG_SENSORS_MAX6650=m
+CONFIG_SENSORS_MAX6697=m
+CONFIG_SENSORS_MAX31790=m
+CONFIG_SENSORS_MCP3021=m
+CONFIG_SENSORS_TC654=m
+CONFIG_SENSORS_TPS23861=m
+CONFIG_SENSORS_MR75203=m
+CONFIG_SENSORS_ADCXX=m
+CONFIG_SENSORS_LM63=m
+CONFIG_SENSORS_LM70=m
+CONFIG_SENSORS_LM73=m
+CONFIG_SENSORS_LM75=m
+CONFIG_SENSORS_LM77=m
+CONFIG_SENSORS_LM78=m
+CONFIG_SENSORS_LM80=m
+CONFIG_SENSORS_LM83=m
+CONFIG_SENSORS_LM85=m
+CONFIG_SENSORS_LM87=m
+CONFIG_SENSORS_LM90=m
+CONFIG_SENSORS_LM92=m
+CONFIG_SENSORS_LM93=m
+CONFIG_SENSORS_LM95234=m
+CONFIG_SENSORS_LM95241=m
+CONFIG_SENSORS_LM95245=m
+CONFIG_SENSORS_PC87360=m
+CONFIG_SENSORS_PC87427=m
+CONFIG_SENSORS_NTC_THERMISTOR=m
+CONFIG_SENSORS_NCT6683=m
+CONFIG_SENSORS_NCT6775_I2C=m
+CONFIG_SENSORS_NCT7802=m
+CONFIG_SENSORS_NCT7904=m
+CONFIG_SENSORS_NPCM7XX=m
+CONFIG_SENSORS_NZXT_KRAKEN2=m
+CONFIG_SENSORS_NZXT_SMART2=m
+CONFIG_SENSORS_OCC_P8_I2C=m
+CONFIG_SENSORS_PCF8591=m
+CONFIG_PMBUS=m
+CONFIG_SENSORS_ADM1266=m
+CONFIG_SENSORS_ADM1275=m
+CONFIG_SENSORS_IBM_CFFPS=m
+CONFIG_SENSORS_INSPUR_IPSPS=m
+CONFIG_SENSORS_IR35221=m
+CONFIG_SENSORS_IR38064=m
+CONFIG_SENSORS_IRPS5401=m
+CONFIG_SENSORS_ISL68137=m
+CONFIG_SENSORS_LM25066=m
+CONFIG_SENSORS_LTC2978=m
+CONFIG_SENSORS_LTC2978_REGULATOR=y
+CONFIG_SENSORS_LTC3815=m
+CONFIG_SENSORS_MAX16064=m
+CONFIG_SENSORS_MAX16601=m
+CONFIG_SENSORS_MAX20730=m
+CONFIG_SENSORS_MAX20751=m
+CONFIG_SENSORS_MAX31785=m
+CONFIG_SENSORS_MAX34440=m
+CONFIG_SENSORS_MAX8688=m
+CONFIG_SENSORS_MP2975=m
+CONFIG_SENSORS_PXE1610=m
+CONFIG_SENSORS_TPS40422=m
+CONFIG_SENSORS_TPS53679=m
+CONFIG_SENSORS_UCD9000=m
+CONFIG_SENSORS_UCD9200=m
+CONFIG_SENSORS_XDPE122=m
+CONFIG_SENSORS_ZL6100=m
+CONFIG_SENSORS_PWM_FAN=m
+CONFIG_SENSORS_SBTSI=m
+CONFIG_SENSORS_SBRMI=m
+CONFIG_SENSORS_SHT15=m
+CONFIG_SENSORS_SHT21=m
+CONFIG_SENSORS_SHT3x=m
+CONFIG_SENSORS_SHT4x=m
+CONFIG_SENSORS_SHTC1=m
+CONFIG_SENSORS_DME1737=m
+CONFIG_SENSORS_EMC1403=m
+CONFIG_SENSORS_EMC2103=m
+CONFIG_SENSORS_EMC2305=m
+CONFIG_SENSORS_EMC6W201=m
+CONFIG_SENSORS_SMSC47M1=m
+CONFIG_SENSORS_SMSC47M192=m
+CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_SCH5627=m
+CONFIG_SENSORS_SCH5636=m
+CONFIG_SENSORS_STTS751=m
+CONFIG_SENSORS_SMM665=m
+CONFIG_SENSORS_ADC128D818=m
+CONFIG_SENSORS_ADS7828=m
+CONFIG_SENSORS_ADS7871=m
+CONFIG_SENSORS_AMC6821=m
+CONFIG_SENSORS_INA209=m
+CONFIG_SENSORS_INA2XX=m
+CONFIG_SENSORS_INA238=m
+CONFIG_SENSORS_INA3221=m
+CONFIG_SENSORS_TC74=m
+CONFIG_SENSORS_THMC50=m
+CONFIG_SENSORS_TMP102=m
+CONFIG_SENSORS_TMP103=m
+CONFIG_SENSORS_TMP108=m
+CONFIG_SENSORS_TMP401=m
+CONFIG_SENSORS_TMP421=m
+CONFIG_SENSORS_TMP464=m
+CONFIG_SENSORS_TMP513=m
+CONFIG_SENSORS_VT1211=m
+CONFIG_SENSORS_W83773G=m
+CONFIG_SENSORS_W83781D=m
+CONFIG_SENSORS_W83791D=m
+CONFIG_SENSORS_W83792D=m
+CONFIG_SENSORS_W83793=m
+CONFIG_SENSORS_W83795=m
+CONFIG_SENSORS_W83795_FANCTRL=y
+CONFIG_SENSORS_W83L785TS=m
+CONFIG_SENSORS_W83L786NG=m
+CONFIG_SENSORS_W83627HF=m
+CONFIG_SENSORS_W83627EHF=m
+CONFIG_THERMAL_STATISTICS=y
+CONFIG_THERMAL_GOV_FAIR_SHARE=y
+CONFIG_THERMAL_GOV_BANG_BANG=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
+CONFIG_THERMAL_EMULATION=y
+CONFIG_TI_THERMAL=y
+CONFIG_OMAP5_THERMAL=y
+CONFIG_DRA752_THERMAL=y
+CONFIG_GENERIC_ADC_THERMAL=m
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_WATCHDOG_PRETIMEOUT_GOV=y
+CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=m
+CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP=y
+CONFIG_SOFT_WATCHDOG=y
+CONFIG_OMAP_WATCHDOG=y
+CONFIG_MFD_STMPE=y
+CONFIG_MFD_TI_AM335X_TSCADC=y
+CONFIG_MFD_PALMAS=y
+CONFIG_MFD_TPS65217=y
+CONFIG_MFD_TPS65218=y
+CONFIG_MFD_TPS65219=y
+CONFIG_MFD_TPS6594_I2C=y
+CONFIG_MFD_TPS6594_SPI=y
+CONFIG_MFD_WL1273_CORE=m
+CONFIG_REGULATOR_USERSPACE_CONSUMER=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_PALMAS=y
+CONFIG_REGULATOR_PBIAS=y
+CONFIG_REGULATOR_PWM=y
+CONFIG_REGULATOR_TI_ABB=y
+CONFIG_REGULATOR_TPS65217=y
+CONFIG_REGULATOR_TPS65218=y
+CONFIG_REGULATOR_TPS65219=y
+CONFIG_RC_CORE=m
+CONFIG_LIRC=y
+CONFIG_RC_DECODERS=y
+CONFIG_IR_IMON_DECODER=m
+CONFIG_IR_JVC_DECODER=m
+CONFIG_IR_MCE_KBD_DECODER=m
+CONFIG_IR_NEC_DECODER=m
+CONFIG_IR_RC5_DECODER=m
+CONFIG_IR_RC6_DECODER=m
+CONFIG_IR_SANYO_DECODER=m
+CONFIG_IR_SHARP_DECODER=m
+CONFIG_IR_SONY_DECODER=m
+CONFIG_IR_XMP_DECODER=m
+CONFIG_RC_DEVICES=y
+CONFIG_IR_GPIO_CIR=m
+CONFIG_IR_IGORPLUGUSB=m
+CONFIG_IR_IGUANA=m
+CONFIG_IR_IMON=m
+CONFIG_IR_IMON_RAW=m
+CONFIG_IR_MCEUSB=m
+CONFIG_IR_REDRAT3=m
+CONFIG_IR_STREAMZAP=m
+CONFIG_IR_TTUSBIR=m
+CONFIG_RC_ATI_REMOTE=m
+CONFIG_RC_LOOPBACK=m
+CONFIG_USB_PULSE8_CEC=m
+CONFIG_USB_RAINSHADOW_CEC=m
+CONFIG_MEDIA_SUPPORT=m
+CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_DTCS033=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+CONFIG_USB_GSPCA_JL2005BCD=m
+CONFIG_USB_GSPCA_KINECT=m
+CONFIG_USB_GSPCA_KONICA=m
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+CONFIG_USB_GSPCA_NW80X=m
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SE401=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA1528=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+CONFIG_USB_GSPCA_SQ930X=m
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STK1135=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TOPRO=m
+CONFIG_USB_GSPCA_TOUPTEK=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+CONFIG_USB_GSPCA_VICAM=m
+CONFIG_USB_GSPCA_XIRLINK_CIT=m
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_PWC=m
+CONFIG_USB_S2255=m
+CONFIG_VIDEO_USBTV=m
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_VIDEO_GO7007=m
+CONFIG_VIDEO_GO7007_USB=m
+CONFIG_VIDEO_GO7007_USB_S2250_BOARD=m
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_STK1160_COMMON=m
+CONFIG_VIDEO_AU0828=m
+CONFIG_VIDEO_AU0828_RC=y
+CONFIG_VIDEO_CX231XX=m
+CONFIG_VIDEO_CX231XX_ALSA=m
+CONFIG_VIDEO_CX231XX_DVB=m
+CONFIG_DVB_AS102=m
+CONFIG_DVB_B2C2_FLEXCOP_USB=m
+CONFIG_DVB_USB_V2=m
+CONFIG_DVB_USB_AF9015=m
+CONFIG_DVB_USB_AF9035=m
+CONFIG_DVB_USB_ANYSEE=m
+CONFIG_DVB_USB_AU6610=m
+CONFIG_DVB_USB_AZ6007=m
+CONFIG_DVB_USB_CE6230=m
+CONFIG_DVB_USB_DVBSKY=m
+CONFIG_DVB_USB_EC168=m
+CONFIG_DVB_USB_GL861=m
+CONFIG_DVB_USB_LME2510=m
+CONFIG_DVB_USB_MXL111SF=m
+CONFIG_DVB_USB_RTL28XXU=m
+CONFIG_DVB_USB_ZD1301=m
+CONFIG_DVB_USB=m
+CONFIG_DVB_USB_A800=m
+CONFIG_DVB_USB_AF9005=m
+CONFIG_DVB_USB_AF9005_REMOTE=m
+CONFIG_DVB_USB_AZ6027=m
+CONFIG_DVB_USB_CINERGY_T2=m
+CONFIG_DVB_USB_CXUSB=m
+CONFIG_DVB_USB_DIB0700=m
+CONFIG_DVB_USB_DIBUSB_MB=m
+CONFIG_DVB_USB_DIBUSB_MB_FAULTY=y
+CONFIG_DVB_USB_DIBUSB_MC=m
+CONFIG_DVB_USB_DIGITV=m
+CONFIG_DVB_USB_DTT200U=m
+CONFIG_DVB_USB_DTV5100=m
+CONFIG_DVB_USB_DW2102=m
+CONFIG_DVB_USB_GP8PSK=m
+CONFIG_DVB_USB_M920X=m
+CONFIG_DVB_USB_NOVA_T_USB2=m
+CONFIG_DVB_USB_OPERA1=m
+CONFIG_DVB_USB_PCTV452E=m
+CONFIG_DVB_USB_TECHNISAT_USB2=m
+CONFIG_DVB_USB_TTUSB2=m
+CONFIG_DVB_USB_UMT_010=m
+CONFIG_DVB_USB_VP702X=m
+CONFIG_DVB_USB_VP7045=m
+CONFIG_SMS_USB_DRV=m
+CONFIG_VIDEO_EM28XX=m
+CONFIG_VIDEO_EM28XX_V4L2=m
+CONFIG_VIDEO_EM28XX_ALSA=m
+CONFIG_VIDEO_EM28XX_DVB=m
+CONFIG_USB_AIRSPY=m
+CONFIG_USB_HACKRF=m
+CONFIG_USB_MSI2500=m
+CONFIG_RADIO_SHARK=m
+CONFIG_RADIO_SHARK2=m
+CONFIG_RADIO_SI4713=m
+CONFIG_USB_KEENE=m
+CONFIG_USB_MA901=m
+CONFIG_USB_MR800=m
+CONFIG_USB_RAREMONO=m
+CONFIG_RADIO_SI470X=m
+CONFIG_USB_SI470X=m
+CONFIG_I2C_SI4713=m
+CONFIG_RADIO_WL128X=m
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_MUX=m
+CONFIG_VIDEO_TI_VPE=m
+CONFIG_SMS_SDIO_DRV=m
+CONFIG_VIDEO_IMX219=m
+CONFIG_VIDEO_IMX290=m
+CONFIG_VIDEO_MT9P031=m
+CONFIG_VIDEO_NOON010PC30=m
+CONFIG_VIDEO_OV5640=m
+CONFIG_VIDEO_OV5645=m
+CONFIG_VIDEO_OV5647=m
+CONFIG_VIDEO_OV7251=m
+CONFIG_VIDEO_OV7670=m
+CONFIG_VIDEO_SR030PC30=m
+CONFIG_VIDEO_CS3308=m
+CONFIG_VIDEO_CS5345=m
+CONFIG_VIDEO_TDA7432=m
+CONFIG_VIDEO_TDA9840=m
+CONFIG_VIDEO_TEA6415C=m
+CONFIG_VIDEO_TEA6420=m
+CONFIG_VIDEO_TLV320AIC23B=m
+CONFIG_VIDEO_TVAUDIO=m
+CONFIG_VIDEO_VP27SMPX=m
+CONFIG_VIDEO_WM8739=m
+CONFIG_VIDEO_SAA6588=m
+CONFIG_VIDEO_BT819=m
+CONFIG_VIDEO_BT856=m
+CONFIG_VIDEO_KS0127=m
+CONFIG_VIDEO_SAA7110=m
+CONFIG_VIDEO_VPX3220=m
+CONFIG_VIDEO_SAA717X=m
+CONFIG_VIDEO_ADV7170=m
+CONFIG_VIDEO_ADV7175=m
+CONFIG_VIDEO_SAA7127=m
+CONFIG_VIDEO_SAA7185=m
+CONFIG_VIDEO_UPD64031A=m
+CONFIG_VIDEO_UPD64083=m
+CONFIG_VIDEO_SAA6752HS=m
+CONFIG_VIDEO_M52790=m
+CONFIG_CXD2880_SPI_DRV=m
+CONFIG_MEDIA_TUNER_M88RS6000T=m
+CONFIG_MEDIA_TUNER_MT2131=m
+CONFIG_MEDIA_TUNER_MXL301RF=m
+CONFIG_MEDIA_TUNER_QM1D1B0004=m
+CONFIG_DVB_MXL5XX=m
+CONFIG_DVB_STV0910=m
+CONFIG_DVB_STV6111=m
+CONFIG_DVB_CX24110=m
+CONFIG_DVB_CX24117=m
+CONFIG_DVB_MB86A16=m
+CONFIG_DVB_TDA8083=m
+CONFIG_DVB_TDA8261=m
+CONFIG_DVB_TUA6100=m
+CONFIG_DVB_VES1X93=m
+CONFIG_DVB_ZL10036=m
+CONFIG_DVB_CX22700=m
+CONFIG_DVB_DIB9000=m
+CONFIG_DVB_L64781=m
+CONFIG_DVB_S5H1432=m
+CONFIG_DVB_SP887X=m
+CONFIG_DVB_STV0367=m
+CONFIG_DVB_TDA10021=m
+CONFIG_DVB_VES1820=m
+CONFIG_DVB_OR51132=m
+CONFIG_DVB_OR51211=m
+CONFIG_DVB_MN88443X=m
+CONFIG_DVB_ASCOT2E=m
+CONFIG_DVB_HELENE=m
+CONFIG_DVB_HORUS3A=m
+CONFIG_DVB_ISL6405=m
+CONFIG_DVB_LGS8GL5=m
+CONFIG_DVB_LNBH25=m
+CONFIG_DVB_LNBH29=m
+CONFIG_DVB_TDA665x=m
+CONFIG_DVB_CXD2099=m
+CONFIG_DVB_DUMMY_FE=m
+CONFIG_DRM=y
+CONFIG_DRM_LOAD_EDID_FIRMWARE=y
+CONFIG_DRM_DP_AUX_CHARDEV=y
+CONFIG_DRM_I2C_NXP_TDA998X=y
+CONFIG_DRM_VGEM=m
+CONFIG_DRM_UDL=m
+CONFIG_DRM_OMAP=y
+CONFIG_OMAP5_DSS_HDMI=y
+CONFIG_DRM_TILCDC=y
+CONFIG_DRM_PANEL_SIMPLE=y
+CONFIG_DRM_PANEL_LG_LB035Q02=m
+CONFIG_DRM_PANEL_NEC_NL8048HL11=m
+CONFIG_DRM_PANEL_ORISETECH_OTM8009A=y
+CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS=y
+CONFIG_DRM_PANEL_SHARP_LS037V7DW01=m
+CONFIG_DRM_PANEL_SONY_ACX565AKM=m
+CONFIG_DRM_PANEL_TPO_TD028TTEC1=m
+CONFIG_DRM_PANEL_TPO_TD043MTEA1=m
+CONFIG_DRM_DISPLAY_CONNECTOR=y
+CONFIG_DRM_ITE_IT66121=m
+CONFIG_DRM_LVDS_CODEC=y
+CONFIG_DRM_SII902X=y
+CONFIG_DRM_SIMPLE_BRIDGE=m
+CONFIG_DRM_TOSHIBA_TC358767=y
+CONFIG_DRM_TOSHIBA_TC358768=y
+CONFIG_DRM_TI_TFP410=y
+CONFIG_DRM_TI_TPD12S015=y
+CONFIG_DRM_I2C_ADV7511=y
+CONFIG_DRM_I2C_ADV7511_AUDIO=y
+CONFIG_DRM_ETNAVIV=y
+CONFIG_DRM_GM12U320=m
+CONFIG_TINYDRM_HX8357D=m
+CONFIG_TINYDRM_ILI9225=m
+CONFIG_TINYDRM_ILI9341=m
+CONFIG_TINYDRM_ILI9486=m
+CONFIG_TINYDRM_MI0283QT=m
+CONFIG_TINYDRM_REPAPER=m
+CONFIG_TINYDRM_ST7586=m
+CONFIG_TINYDRM_ST7735R=m
+CONFIG_DRM_TIDSS=y
+CONFIG_DRM_LEGACY=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_SMSCUFX=m
+CONFIG_FB_UDL=m
+CONFIG_FB_SIMPLE=y
+CONFIG_FB_SSD1307=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_PWM=y
+CONFIG_BACKLIGHT_GPIO=y
+CONFIG_BACKLIGHT_LED=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_SOUND=m
+CONFIG_SND=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_DUMMY=m
+CONFIG_SND_ALOOP=m
+CONFIG_SND_VIRMIDI=m
+CONFIG_SND_MTPAV=m
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_HDA_PREALLOC_SIZE=2048
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_UA101=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_USB_6FIRE=m
+CONFIG_SND_USB_HIFACE=m
+CONFIG_SND_BCD2000=m
+CONFIG_SND_USB_POD=m
+CONFIG_SND_USB_PODHD=m
+CONFIG_SND_USB_TONEPORT=m
+CONFIG_SND_USB_VARIAX=m
+CONFIG_SND_SOC=m
+CONFIG_SND_SOC_DAVINCI_MCASP=m
+CONFIG_SND_SOC_OMAP_DMIC=m
+CONFIG_SND_SOC_OMAP_MCBSP=m
+CONFIG_SND_SOC_OMAP_MCPDM=m
+CONFIG_SND_SOC_OMAP_HDMI=m
+CONFIG_SND_SOC_ADAU1701=m
+CONFIG_SND_SOC_ADAU7002=m
+CONFIG_SND_SOC_AK4554=m
+CONFIG_SND_SOC_CS42L51_I2C=m
+CONFIG_SND_SOC_CS4265=m
+CONFIG_SND_SOC_CS4271_I2C=m
+CONFIG_SND_SOC_DMIC=m
+CONFIG_SND_SOC_ES8328_I2C=m
+CONFIG_SND_SOC_ES8328_SPI=m
+CONFIG_SND_SOC_MAX98357A=m
+CONFIG_SND_SOC_PCM3168A_I2C=m
+CONFIG_SND_SOC_PCM5102A=m
+CONFIG_SND_SOC_PCM512x_I2C=m
+CONFIG_SND_SOC_SGTL5000=m
+CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m
+CONFIG_SND_SOC_SPDIF=m
+CONFIG_SND_SOC_TLV320AIC23_I2C=m
+CONFIG_SND_SOC_TLV320AIC31XX=m
+CONFIG_SND_SOC_TS3A227E=m
+CONFIG_SND_SOC_WM8753=m
+CONFIG_SND_SOC_WM8804_I2C=m
+CONFIG_SND_SOC_WM8903=m
+CONFIG_SND_SOC_WM8904=m
+CONFIG_SND_SOC_WM8960=m
+CONFIG_SND_SOC_TPA6130A2=m
+CONFIG_SND_SIMPLE_CARD=m
+CONFIG_SND_AUDIO_GRAPH_CARD=m
+CONFIG_HID_BATTERY_STRENGTH=y
+CONFIG_HIDRAW=y
+CONFIG_UHID=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_ACCUTOUCH=m
+CONFIG_HID_ACRUX=m
+CONFIG_HID_ACRUX_FF=y
+CONFIG_HID_APPLE=m
+CONFIG_HID_ASUS=m
+CONFIG_HID_AUREAL=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BETOP_FF=m
+CONFIG_HID_BIGBEN_FF=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CORSAIR=m
+CONFIG_HID_COUGAR=m
+CONFIG_HID_MACALLY=m
+CONFIG_HID_PRODIKEYS=m
+CONFIG_HID_CMEDIA=m
+CONFIG_HID_CP2112=m
+CONFIG_HID_CREATIVE_SB0540=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DRAGONRISE=m
+CONFIG_DRAGONRISE_FF=y
+CONFIG_HID_EMS_FF=m
+CONFIG_HID_ELAN=m
+CONFIG_HID_ELECOM=m
+CONFIG_HID_ELO=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_FT260=m
+CONFIG_HID_GEMBIRD=m
+CONFIG_HID_GFRM=m
+CONFIG_HID_GLORIOUS=m
+CONFIG_HID_HOLTEK=m
+CONFIG_HOLTEK_FF=y
+CONFIG_HID_VIVALDI=m
+CONFIG_HID_GT683R=m
+CONFIG_HID_KEYTOUCH=m
+CONFIG_HID_KYE=m
+CONFIG_HID_UCLOGIC=m
+CONFIG_HID_WALTOP=m
+CONFIG_HID_VIEWSONIC=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_ICADE=m
+CONFIG_HID_ITE=m
+CONFIG_HID_JABRA=m
+CONFIG_HID_TWINHAN=m
+CONFIG_HID_KENSINGTON=m
+CONFIG_HID_LCPOWER=m
+CONFIG_HID_LENOVO=m
+CONFIG_HID_LOGITECH=y
+CONFIG_HID_LOGITECH_DJ=y
+CONFIG_LOGITECH_FF=y
+CONFIG_LOGIRUMBLEPAD2_FF=y
+CONFIG_LOGIG940_FF=y
+CONFIG_HID_MAGICMOUSE=m
+CONFIG_HID_MALTRON=m
+CONFIG_HID_MAYFLASH=m
+CONFIG_HID_REDRAGON=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_MULTITOUCH=m
+CONFIG_HID_NINTENDO=m
+CONFIG_NINTENDO_FF=y
+CONFIG_HID_NTI=m
+CONFIG_HID_NTRIG=m
+CONFIG_HID_ORTEK=m
+CONFIG_HID_PANTHERLORD=m
+CONFIG_PANTHERLORD_FF=y
+CONFIG_HID_PENMOUNT=m
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_PICOLCD=m
+CONFIG_HID_PICOLCD_FB=y
+CONFIG_HID_PICOLCD_BACKLIGHT=y
+CONFIG_HID_PICOLCD_LEDS=y
+CONFIG_HID_PICOLCD_CIR=y
+CONFIG_HID_PLANTRONICS=m
+CONFIG_HID_PLAYSTATION=m
+CONFIG_PLAYSTATION_FF=y
+CONFIG_HID_PRIMAX=m
+CONFIG_HID_RETRODE=m
+CONFIG_HID_ROCCAT=m
+CONFIG_HID_SAITEK=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SEMITEK=m
+CONFIG_HID_SONY=m
+CONFIG_SONY_FF=y
+CONFIG_HID_SPEEDLINK=m
+CONFIG_HID_STEAM=m
+CONFIG_HID_STEELSERIES=m
+CONFIG_HID_SUNPLUS=m
+CONFIG_HID_RMI=m
+CONFIG_HID_GREENASIA=m
+CONFIG_GREENASIA_FF=y
+CONFIG_HID_SMARTJOYPLUS=m
+CONFIG_SMARTJOYPLUS_FF=y
+CONFIG_HID_TIVO=m
+CONFIG_HID_TOPSEED=m
+CONFIG_HID_THINGM=m
+CONFIG_HID_THRUSTMASTER=m
+CONFIG_THRUSTMASTER_FF=y
+CONFIG_HID_UDRAW_PS3=m
+CONFIG_HID_U2FZERO=m
+CONFIG_HID_WACOM=m
+CONFIG_HID_WIIMOTE=m
+CONFIG_HID_XINMO=m
+CONFIG_HID_ZEROPLUS=m
+CONFIG_ZEROPLUS_FF=y
+CONFIG_HID_ZYDACRON=m
+CONFIG_HID_SENSOR_HUB=m
+CONFIG_HID_SENSOR_CUSTOM_SENSOR=m
+CONFIG_HID_ALPS=m
+CONFIG_HID_MCP2221=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB_LED_TRIG=y
+CONFIG_USB_ULPI_BUS=m
+CONFIG_USB_CONN_GPIO=m
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_OTG=y
+CONFIG_USB_LEDS_TRIGGER_USBPORT=m
+CONFIG_USB_MON=m
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_PRINTER=m
+CONFIG_USB_TMC=m
+CONFIG_USB_STORAGE=m
+CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_STORAGE_ENE_UB6250=m
+CONFIG_USB_UAS=m
+CONFIG_USB_MDC800=m
+CONFIG_USB_MICROTEK=m
+CONFIG_USBIP_CORE=m
+CONFIG_USBIP_VHCI_HCD=m
+CONFIG_USBIP_VHCI_HC_PORTS=15
+CONFIG_USBIP_VHCI_NR_HCS=8
+CONFIG_USBIP_HOST=m
+CONFIG_USBIP_VUDC=m
+CONFIG_USB_MUSB_HDRC=y
+CONFIG_USB_MUSB_DSPS=y
+CONFIG_MUSB_PIO_ONLY=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=m
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_F81232=m
+CONFIG_USB_SERIAL_F8153X=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_METRO=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MXUPORT=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_XSENS_MT=m
+CONFIG_USB_SERIAL_WISHBONE=m
+CONFIG_USB_SERIAL_SSU100=m
+CONFIG_USB_SERIAL_QT2=m
+CONFIG_USB_SERIAL_UPD78F0730=m
+CONFIG_USB_SERIAL_XR=m
+CONFIG_USB_SERIAL_DEBUG=m
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+CONFIG_USB_ADUTUX=m
+CONFIG_USB_SEVSEG=m
+CONFIG_USB_LEGOTOWER=m
+CONFIG_USB_LCD=m
+CONFIG_USB_CYPRESS_CY7C63=m
+CONFIG_USB_CYTHERM=m
+CONFIG_USB_IDMOUSE=m
+CONFIG_USB_FTDI_ELAN=m
+CONFIG_USB_APPLEDISPLAY=m
+CONFIG_APPLE_MFI_FASTCHARGE=m
+CONFIG_USB_SISUSBVGA=m
+CONFIG_USB_LD=m
+CONFIG_USB_TRANCEVIBRATOR=m
+CONFIG_USB_IOWARRIOR=m
+CONFIG_USB_TEST=m
+CONFIG_USB_EHSET_TEST_FIXTURE=m
+CONFIG_USB_ISIGHTFW=m
+CONFIG_USB_YUREX=m
+CONFIG_USB_HSIC_USB3503=m
+CONFIG_USB_CHAOSKEY=m
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_AM335X_PHY_USB=y
+CONFIG_USB_GPIO_VBUS=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_DUMMY_HCD=m
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_PHONET=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_UAC1=y
+CONFIG_USB_CONFIGFS_F_UAC2=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_UVC=y
+CONFIG_USB_CONFIGFS_F_PRINTER=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_AUDIO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FUNCTIONFS=m
+CONFIG_USB_FUNCTIONFS_ETH=y
+CONFIG_USB_FUNCTIONFS_RNDIS=y
+CONFIG_USB_FUNCTIONFS_GENERIC=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_NOKIA=m
+CONFIG_USB_G_ACM_MS=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_HID=m
+CONFIG_USB_G_DBGP=m
+CONFIG_USB_G_WEBCAM=m
+CONFIG_TYPEC=y
+CONFIG_TYPEC_HD3SS3220=y
+CONFIG_MMC=y
+CONFIG_PWRSEQ_SD8787=m
+CONFIG_MMC_BLOCK_MINORS=256
+CONFIG_SDIO_UART=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SPI=m
+CONFIG_MMC_VUB300=m
+CONFIG_MMC_USHC=m
+CONFIG_MMC_SDHCI_OMAP=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_CLASS_MULTICOLOR=m
+CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_LP3944=m
+CONFIG_LEDS_LP55XX_COMMON=m
+CONFIG_LEDS_LP5523=m
+CONFIG_LEDS_PCA955X=m
+CONFIG_LEDS_PCA963X=m
+CONFIG_LEDS_DAC124S085=m
+CONFIG_LEDS_PWM=m
+CONFIG_LEDS_REGULATOR=m
+CONFIG_LEDS_BD2802=m
+CONFIG_LEDS_LT3593=m
+CONFIG_LEDS_TCA6507=m
+CONFIG_LEDS_SYSCON=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_DISK=y
+CONFIG_LEDS_TRIGGER_MTD=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_ACTIVITY=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_TRANSIENT=m
+CONFIG_LEDS_TRIGGER_CAMERA=m
+CONFIG_LEDS_TRIGGER_PANIC=y
+CONFIG_LEDS_TRIGGER_NETDEV=y
+CONFIG_LEDS_TRIGGER_PATTERN=m
+CONFIG_LEDS_TRIGGER_AUDIO=m
+CONFIG_ACCESSIBILITY=y
+CONFIG_A11Y_BRAILLE_CONSOLE=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_ABB5ZES3=y
+CONFIG_RTC_DRV_ABEOZ9=y
+CONFIG_RTC_DRV_ABX80X=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
+CONFIG_RTC_DRV_DS1374_WDT=y
+CONFIG_RTC_DRV_DS1672=y
+CONFIG_RTC_DRV_HYM8563=y
+CONFIG_RTC_DRV_MAX6900=y
+CONFIG_RTC_DRV_RS5C372=y
+CONFIG_RTC_DRV_ISL1208=y
+CONFIG_RTC_DRV_ISL12022=y
+CONFIG_RTC_DRV_ISL12026=y
+CONFIG_RTC_DRV_X1205=y
+CONFIG_RTC_DRV_PCF8523=y
+CONFIG_RTC_DRV_PCF85063=y
+CONFIG_RTC_DRV_PCF85363=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_RTC_DRV_PCF8583=y
+CONFIG_RTC_DRV_M41T80=y
+CONFIG_RTC_DRV_M41T80_WDT=y
+CONFIG_RTC_DRV_BQ32K=y
+CONFIG_RTC_DRV_PALMAS=y
+CONFIG_RTC_DRV_S35390A=y
+CONFIG_RTC_DRV_FM3130=y
+CONFIG_RTC_DRV_RX8010=y
+CONFIG_RTC_DRV_RX8581=y
+CONFIG_RTC_DRV_RX8025=y
+CONFIG_RTC_DRV_EM3027=y
+CONFIG_RTC_DRV_RV8803=y
+CONFIG_RTC_DRV_M41T93=y
+CONFIG_RTC_DRV_M41T94=y
+CONFIG_RTC_DRV_DS1302=y
+CONFIG_RTC_DRV_DS1305=y
+CONFIG_RTC_DRV_DS1343=y
+CONFIG_RTC_DRV_DS1347=y
+CONFIG_RTC_DRV_DS1390=y
+CONFIG_RTC_DRV_MAX6916=y
+CONFIG_RTC_DRV_R9701=y
+CONFIG_RTC_DRV_RX4581=y
+CONFIG_RTC_DRV_RS5C348=y
+CONFIG_RTC_DRV_MAX6902=y
+CONFIG_RTC_DRV_PCF2123=y
+CONFIG_RTC_DRV_MCP795=y
+CONFIG_RTC_DRV_DS3232=y
+CONFIG_RTC_DRV_PCF2127=y
+CONFIG_RTC_DRV_RV3029C2=y
+CONFIG_RTC_DRV_RX6110=y
+CONFIG_RTC_DRV_DS1286=m
+CONFIG_RTC_DRV_DS1511=m
+CONFIG_RTC_DRV_DS1553=m
+CONFIG_RTC_DRV_DS1685_FAMILY=m
+CONFIG_RTC_DRV_DS1742=m
+CONFIG_RTC_DRV_DS2404=m
+CONFIG_RTC_DRV_EFI=y
+CONFIG_RTC_DRV_STK17TA8=m
+CONFIG_RTC_DRV_M48T86=m
+CONFIG_RTC_DRV_M48T35=m
+CONFIG_RTC_DRV_M48T59=m
+CONFIG_RTC_DRV_MSM6242=m
+CONFIG_RTC_DRV_BQ4802=m
+CONFIG_RTC_DRV_RP5C01=m
+CONFIG_RTC_DRV_V3020=m
+CONFIG_RTC_DRV_OMAP=y
+CONFIG_RTC_DRV_HID_SENSOR_TIME=m
+CONFIG_DMADEVICES=y
+CONFIG_TI_CPPI41=y
+CONFIG_ASYNC_TX_DMA=y
+CONFIG_DMABUF_HEAPS=y
+CONFIG_DMABUF_HEAPS_SYSTEM=y
+CONFIG_DMABUF_HEAPS_CMA=y
+CONFIG_DMABUF_HEAPS_CARVEOUT=y
+CONFIG_AUXDISPLAY=y
+CONFIG_HD44780=m
+CONFIG_IMG_ASCII_LCD=m
+CONFIG_HT16K33=m
+CONFIG_LCD2S=m
+CONFIG_UIO=m
+CONFIG_UIO_PDRV_GENIRQ=m
+CONFIG_UIO_PRUSS=m
+CONFIG_VIRT_DRIVERS=y
+CONFIG_VIRTIO_BALLOON=m
+CONFIG_VIRTIO_INPUT=m
+CONFIG_VIRTIO_MMIO=m
+CONFIG_GREYBUS=m
+CONFIG_GREYBUS_ES2=m
+CONFIG_STAGING=y
+CONFIG_RTLLIB=m
+CONFIG_RTL8723BS=m
+CONFIG_R8712U=m
+CONFIG_R8188EU=m
+CONFIG_ADIS16203=m
+CONFIG_ADIS16240=m
+CONFIG_AD7816=m
+CONFIG_ADT7316=m
+CONFIG_ADT7316_I2C=m
+CONFIG_AD9832=m
+CONFIG_AD9834=m
+CONFIG_AD5933=m
+CONFIG_ADE7854=m
+CONFIG_AD2S1210=m
+CONFIG_FB_TFT=m
+CONFIG_FB_TFT_AGM1264K_FL=m
+CONFIG_FB_TFT_BD663474=m
+CONFIG_FB_TFT_HX8340BN=m
+CONFIG_FB_TFT_HX8347D=m
+CONFIG_FB_TFT_HX8353D=m
+CONFIG_FB_TFT_HX8357D=m
+CONFIG_FB_TFT_ILI9163=m
+CONFIG_FB_TFT_ILI9320=m
+CONFIG_FB_TFT_ILI9325=m
+CONFIG_FB_TFT_ILI9340=m
+CONFIG_FB_TFT_ILI9341=m
+CONFIG_FB_TFT_ILI9481=m
+CONFIG_FB_TFT_ILI9486=m
+CONFIG_FB_TFT_PCD8544=m
+CONFIG_FB_TFT_RA8875=m
+CONFIG_FB_TFT_S6D02A1=m
+CONFIG_FB_TFT_S6D1121=m
+CONFIG_FB_TFT_SH1106=m
+CONFIG_FB_TFT_SSD1289=m
+CONFIG_FB_TFT_SSD1305=m
+CONFIG_FB_TFT_SSD1306=m
+CONFIG_FB_TFT_SSD1331=m
+CONFIG_FB_TFT_SSD1351=m
+CONFIG_FB_TFT_ST7735R=m
+CONFIG_FB_TFT_ST7789V=m
+CONFIG_FB_TFT_TINYLCD=m
+CONFIG_FB_TFT_TLS8204=m
+CONFIG_FB_TFT_UC1611=m
+CONFIG_FB_TFT_UC1701=m
+CONFIG_FB_TFT_UPD161704=m
+CONFIG_GREYBUS_AUDIO=m
+CONFIG_GREYBUS_BOOTROM=m
+CONFIG_GREYBUS_FIRMWARE=m
+CONFIG_GREYBUS_HID=m
+CONFIG_GREYBUS_LIGHT=m
+CONFIG_GREYBUS_LOG=m
+CONFIG_GREYBUS_LOOPBACK=m
+CONFIG_GREYBUS_POWER=m
+CONFIG_GREYBUS_RAW=m
+CONFIG_GREYBUS_VIBRATOR=m
+CONFIG_GREYBUS_BRIDGED_PHY=m
+CONFIG_GREYBUS_GPIO=m
+CONFIG_GREYBUS_I2C=m
+CONFIG_GREYBUS_PWM=m
+CONFIG_GREYBUS_SDIO=m
+CONFIG_GREYBUS_SPI=m
+CONFIG_GREYBUS_UART=m
+CONFIG_GREYBUS_USB=m
+CONFIG_COMMON_CLK_PALMAS=y
+CONFIG_COMMON_CLK_TI_ADPLL=y
+CONFIG_HWSPINLOCK=y
+CONFIG_HWSPINLOCK_OMAP=y
+CONFIG_OMAP2PLUS_MBOX=y
+CONFIG_OMAP_IOMMU=y
+CONFIG_REMOTEPROC=y
+CONFIG_REMOTEPROC_CDEV=y
+CONFIG_OMAP_REMOTEPROC=m
+CONFIG_WKUP_M3_RPROC=y
+CONFIG_RPMSG_CHAR=m
+CONFIG_RPMSG_CTRL=m
+CONFIG_RPMSG_VIRTIO=m
+CONFIG_RPMSG_PRU=m
+CONFIG_SOC_TI=y
+CONFIG_AMX3_PM=m
+CONFIG_WKUP_M3_IPC=m
+CONFIG_TI_PRUSS=m
+CONFIG_PM_DEVFREQ=y
+CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
+CONFIG_DEVFREQ_GOV_PERFORMANCE=y
+CONFIG_DEVFREQ_GOV_POWERSAVE=y
+CONFIG_DEVFREQ_GOV_USERSPACE=y
+CONFIG_DEVFREQ_GOV_PASSIVE=y
+CONFIG_PM_DEVFREQ_EVENT=y
+CONFIG_EXTCON_GPIO=y
+CONFIG_EXTCON_PALMAS=y
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_TI_EMIF=y
+CONFIG_TI_EMIF_SRAM=y
+CONFIG_IIO=y
+CONFIG_IIO_SW_DEVICE=m
+CONFIG_IIO_SW_TRIGGER=m
+CONFIG_ADIS16201=m
+CONFIG_ADIS16209=m
+CONFIG_ADXL313_I2C=m
+CONFIG_ADXL313_SPI=m
+CONFIG_ADXL345_I2C=m
+CONFIG_ADXL345_SPI=m
+CONFIG_ADXL355_I2C=m
+CONFIG_ADXL355_SPI=m
+CONFIG_ADXL367_SPI=m
+CONFIG_ADXL367_I2C=m
+CONFIG_ADXL372_SPI=m
+CONFIG_ADXL372_I2C=m
+CONFIG_BMA180=m
+CONFIG_BMA220=m
+CONFIG_BMA400=m
+CONFIG_BMC150_ACCEL=m
+CONFIG_BMI088_ACCEL=m
+CONFIG_DA280=m
+CONFIG_DA311=m
+CONFIG_DMARD06=m
+CONFIG_DMARD09=m
+CONFIG_DMARD10=m
+CONFIG_FXLS8962AF_I2C=m
+CONFIG_FXLS8962AF_SPI=m
+CONFIG_HID_SENSOR_ACCEL_3D=m
+CONFIG_KXSD9=m
+CONFIG_KXCJK1013=m
+CONFIG_MC3230=m
+CONFIG_MMA7455_I2C=m
+CONFIG_MMA7455_SPI=m
+CONFIG_MMA7660=m
+CONFIG_MMA8452=m
+CONFIG_MMA9551=m
+CONFIG_MMA9553=m
+CONFIG_MSA311=m
+CONFIG_MXC4005=m
+CONFIG_MXC6255=m
+CONFIG_SCA3000=m
+CONFIG_SCA3300=m
+CONFIG_STK8312=m
+CONFIG_STK8BA50=m
+CONFIG_AD7091R5=m
+CONFIG_AD7124=m
+CONFIG_AD7192=m
+CONFIG_AD7266=m
+CONFIG_AD7280=m
+CONFIG_AD7291=m
+CONFIG_AD7292=m
+CONFIG_AD7298=m
+CONFIG_AD7476=m
+CONFIG_AD7606_IFACE_PARALLEL=m
+CONFIG_AD7606_IFACE_SPI=m
+CONFIG_AD7766=m
+CONFIG_AD7768_1=m
+CONFIG_AD7780=m
+CONFIG_AD7791=m
+CONFIG_AD7793=m
+CONFIG_AD7887=m
+CONFIG_AD7923=m
+CONFIG_AD7949=m
+CONFIG_AD799X=m
+CONFIG_AD9467=m
+CONFIG_ADI_AXI_ADC=m
+CONFIG_CC10001_ADC=m
+CONFIG_ENVELOPE_DETECTOR=m
+CONFIG_HI8435=m
+CONFIG_HX711=m
+CONFIG_INA2XX_ADC=m
+CONFIG_LTC2471=m
+CONFIG_LTC2485=m
+CONFIG_LTC2496=m
+CONFIG_LTC2497=m
+CONFIG_MAX1027=m
+CONFIG_MAX11100=m
+CONFIG_MAX1118=m
+CONFIG_MAX11205=m
+CONFIG_MAX1241=m
+CONFIG_MAX1363=m
+CONFIG_MAX9611=m
+CONFIG_MCP320X=m
+CONFIG_MCP3422=m
+CONFIG_MCP3911=m
+CONFIG_NAU7802=m
+CONFIG_PALMAS_GPADC=m
+CONFIG_RICHTEK_RTQ6056=m
+CONFIG_SD_ADC_MODULATOR=m
+CONFIG_STMPE_ADC=m
+CONFIG_TI_ADC081C=m
+CONFIG_TI_ADC0832=m
+CONFIG_TI_ADC084S021=m
+CONFIG_TI_ADC12138=m
+CONFIG_TI_ADC108S102=m
+CONFIG_TI_ADC128S052=m
+CONFIG_TI_ADC161S626=m
+CONFIG_TI_ADS1015=m
+CONFIG_TI_ADS7950=m
+CONFIG_TI_ADS8344=m
+CONFIG_TI_ADS8688=m
+CONFIG_TI_ADS124S08=m
+CONFIG_TI_ADS131E08=m
+CONFIG_TI_AM335X_ADC=y
+CONFIG_TI_TLC4541=m
+CONFIG_TI_TSC2046=m
+CONFIG_AD74413R=m
+CONFIG_IIO_RESCALE=m
+CONFIG_AD8366=m
+CONFIG_ADA4250=m
+CONFIG_HMC425=m
+CONFIG_AD7150=m
+CONFIG_AD7746=m
+CONFIG_ATLAS_PH_SENSOR=m
+CONFIG_ATLAS_EZO_SENSOR=m
+CONFIG_BME680=m
+CONFIG_CCS811=m
+CONFIG_IAQCORE=m
+CONFIG_PMS7003=m
+CONFIG_SCD30_CORE=m
+CONFIG_SCD30_I2C=m
+CONFIG_SCD30_SERIAL=m
+CONFIG_SCD4X=m
+CONFIG_SENSIRION_SGP30=m
+CONFIG_SENSIRION_SGP40=m
+CONFIG_SPS30_I2C=m
+CONFIG_SPS30_SERIAL=m
+CONFIG_SENSEAIR_SUNRISE_CO2=m
+CONFIG_VZ89X=m
+CONFIG_AD3552R=m
+CONFIG_AD5064=m
+CONFIG_AD5360=m
+CONFIG_AD5380=m
+CONFIG_AD5421=m
+CONFIG_AD5446=m
+CONFIG_AD5449=m
+CONFIG_AD5592R=m
+CONFIG_AD5593R=m
+CONFIG_AD5504=m
+CONFIG_AD5624R_SPI=m
+CONFIG_LTC2688=m
+CONFIG_AD5686_SPI=m
+CONFIG_AD5696_I2C=m
+CONFIG_AD5755=m
+CONFIG_AD5758=m
+CONFIG_AD5761=m
+CONFIG_AD5764=m
+CONFIG_AD5766=m
+CONFIG_AD5770R=m
+CONFIG_AD5791=m
+CONFIG_AD7293=m
+CONFIG_AD7303=m
+CONFIG_AD8801=m
+CONFIG_DPOT_DAC=m
+CONFIG_DS4424=m
+CONFIG_LTC1660=m
+CONFIG_LTC2632=m
+CONFIG_M62332=m
+CONFIG_MAX517=m
+CONFIG_MAX5821=m
+CONFIG_MCP4725=m
+CONFIG_MCP4922=m
+CONFIG_TI_DAC082S085=m
+CONFIG_TI_DAC5571=m
+CONFIG_TI_DAC7311=m
+CONFIG_TI_DAC7612=m
+CONFIG_AD9523=m
+CONFIG_ADF4350=m
+CONFIG_ADF4371=m
+CONFIG_ADMV1013=m
+CONFIG_ADMV4420=m
+CONFIG_ADRF6780=m
+CONFIG_ADIS16080=m
+CONFIG_ADIS16130=m
+CONFIG_ADIS16136=m
+CONFIG_ADIS16260=m
+CONFIG_ADXRS290=m
+CONFIG_ADXRS450=m
+CONFIG_BMG160=m
+CONFIG_FXAS21002C=m
+CONFIG_HID_SENSOR_GYRO_3D=m
+CONFIG_MPU3050_I2C=m
+CONFIG_IIO_ST_GYRO_3AXIS=m
+CONFIG_ITG3200=m
+CONFIG_AFE4403=m
+CONFIG_AFE4404=m
+CONFIG_MAX30100=m
+CONFIG_MAX30102=m
+CONFIG_AM2315=m
+CONFIG_DHT11=m
+CONFIG_HDC100X=m
+CONFIG_HDC2010=m
+CONFIG_HID_SENSOR_HUMIDITY=m
+CONFIG_HTS221=m
+CONFIG_HTU21=m
+CONFIG_SI7005=m
+CONFIG_SI7020=m
+CONFIG_ADIS16400=m
+CONFIG_ADIS16460=m
+CONFIG_ADIS16475=m
+CONFIG_ADIS16480=m
+CONFIG_BMI160_I2C=m
+CONFIG_BMI160_SPI=m
+CONFIG_BOSCH_BNO055_SERIAL=m
+CONFIG_BOSCH_BNO055_I2C=m
+CONFIG_FXOS8700_I2C=m
+CONFIG_FXOS8700_SPI=m
+CONFIG_KMX61=m
+CONFIG_INV_ICM42600_I2C=m
+CONFIG_INV_ICM42600_SPI=m
+CONFIG_INV_MPU6050_I2C=m
+CONFIG_INV_MPU6050_SPI=m
+CONFIG_IIO_ST_LSM6DSX=m
+CONFIG_IIO_ST_LSM9DS0=m
+CONFIG_ADJD_S311=m
+CONFIG_ADUX1020=m
+CONFIG_AL3010=m
+CONFIG_AL3320A=m
+CONFIG_APDS9300=m
+CONFIG_APDS9960=m
+CONFIG_AS73211=m
+CONFIG_BH1750=m
+CONFIG_BH1780=m
+CONFIG_CM32181=m
+CONFIG_CM3232=m
+CONFIG_CM3323=m
+CONFIG_CM3605=m
+CONFIG_CM36651=m
+CONFIG_GP2AP002=m
+CONFIG_GP2AP020A00F=m
+CONFIG_SENSORS_ISL29018=m
+CONFIG_SENSORS_ISL29028=m
+CONFIG_ISL29125=m
+CONFIG_HID_SENSOR_ALS=m
+CONFIG_HID_SENSOR_PROX=m
+CONFIG_JSA1212=m
+CONFIG_RPR0521=m
+CONFIG_LTR501=m
+CONFIG_LTRF216A=m
+CONFIG_LV0104CS=m
+CONFIG_MAX44000=m
+CONFIG_MAX44009=m
+CONFIG_NOA1305=m
+CONFIG_OPT3001=m
+CONFIG_PA12203001=m
+CONFIG_SI1133=m
+CONFIG_SI1145=m
+CONFIG_STK3310=m
+CONFIG_ST_UVIS25=m
+CONFIG_TCS3414=m
+CONFIG_TCS3472=m
+CONFIG_SENSORS_TSL2563=m
+CONFIG_TSL2583=m
+CONFIG_TSL2591=m
+CONFIG_TSL2772=m
+CONFIG_TSL4531=m
+CONFIG_US5182D=m
+CONFIG_VCNL4000=m
+CONFIG_VCNL4035=m
+CONFIG_VEML6030=m
+CONFIG_VEML6070=m
+CONFIG_VL6180=m
+CONFIG_ZOPT2201=m
+CONFIG_AK8974=m
+CONFIG_AK09911=m
+CONFIG_BMC150_MAGN_I2C=m
+CONFIG_BMC150_MAGN_SPI=m
+CONFIG_MAG3110=m
+CONFIG_HID_SENSOR_MAGNETOMETER_3D=m
+CONFIG_MMC35240=m
+CONFIG_SENSORS_HMC5843_I2C=m
+CONFIG_SENSORS_HMC5843_SPI=m
+CONFIG_SENSORS_RM3100_I2C=m
+CONFIG_SENSORS_RM3100_SPI=m
+CONFIG_YAMAHA_YAS530=m
+CONFIG_IIO_MUX=m
+CONFIG_HID_SENSOR_INCLINOMETER_3D=m
+CONFIG_HID_SENSOR_DEVICE_ROTATION=m
+CONFIG_IIO_HRTIMER_TRIGGER=m
+CONFIG_IIO_INTERRUPT_TRIGGER=m
+CONFIG_IIO_TIGHTLOOP_TRIGGER=m
+CONFIG_IIO_SYSFS_TRIGGER=m
+CONFIG_HID_SENSOR_CUSTOM_INTEL_HINGE=m
+CONFIG_AD5110=m
+CONFIG_AD5272=m
+CONFIG_DS1803=m
+CONFIG_MAX5432=m
+CONFIG_MAX5481=m
+CONFIG_MAX5487=m
+CONFIG_MCP4018=m
+CONFIG_MCP4131=m
+CONFIG_MCP4531=m
+CONFIG_MCP41010=m
+CONFIG_TPL0102=m
+CONFIG_LMP91000=m
+CONFIG_ABP060MG=m
+CONFIG_BMP280=m
+CONFIG_DLHL60D=m
+CONFIG_DPS310=m
+CONFIG_HID_SENSOR_PRESS=m
+CONFIG_HP03=m
+CONFIG_ICP10100=m
+CONFIG_MPL115_I2C=m
+CONFIG_MPL115_SPI=m
+CONFIG_MPL3115=m
+CONFIG_MS5611=m
+CONFIG_MS5611_I2C=m
+CONFIG_MS5611_SPI=m
+CONFIG_MS5637=m
+CONFIG_IIO_ST_PRESS=m
+CONFIG_T5403=m
+CONFIG_HP206C=m
+CONFIG_ZPA2326=m
+CONFIG_AS3935=m
+CONFIG_ISL29501=m
+CONFIG_LIDAR_LITE_V2=m
+CONFIG_MB1232=m
+CONFIG_PING=m
+CONFIG_RFD77402=m
+CONFIG_SRF04=m
+CONFIG_SX9310=m
+CONFIG_SX9324=m
+CONFIG_SX9360=m
+CONFIG_SX9500=m
+CONFIG_SRF08=m
+CONFIG_VCNL3020=m
+CONFIG_VL53L0X_I2C=m
+CONFIG_AD2S90=m
+CONFIG_AD2S1200=m
+CONFIG_LTC2983=m
+CONFIG_MAXIM_THERMOCOUPLE=m
+CONFIG_HID_SENSOR_TEMP=m
+CONFIG_MLX90614=m
+CONFIG_MLX90632=m
+CONFIG_TMP006=m
+CONFIG_TMP007=m
+CONFIG_TMP117=m
+CONFIG_TSYS01=m
+CONFIG_TSYS02D=m
+CONFIG_MAX31856=m
+CONFIG_MAX31865=m
+CONFIG_PWM=y
+CONFIG_PWM_OMAP_DMTIMER=y
+CONFIG_PWM_PCA9685=y
+CONFIG_PWM_STMPE=y
+CONFIG_PWM_TIECAP=y
+CONFIG_PWM_TIEHRPWM=y
+CONFIG_RESET_TI_SYSCON=y
+CONFIG_PHY_CAN_TRANSCEIVER=m
+CONFIG_OMAP_USB2=y
+CONFIG_TI_PIPE3=y
+CONFIG_RAS=y
+CONFIG_FPGA=m
+CONFIG_ALTERA_PR_IP_CORE=m
+CONFIG_ALTERA_PR_IP_CORE_PLAT=m
+CONFIG_FPGA_MGR_ALTERA_PS_SPI=m
+CONFIG_FPGA_MGR_XILINX_SPI=m
+CONFIG_FPGA_MGR_ICE40_SPI=m
+CONFIG_FPGA_MGR_MACHXO2_SPI=m
+CONFIG_FPGA_BRIDGE=m
+CONFIG_ALTERA_FREEZE_BRIDGE=m
+CONFIG_XILINX_PR_DECOUPLER=m
+CONFIG_FPGA_REGION=m
+CONFIG_OF_FPGA_REGION=m
+CONFIG_MUX_ADG792A=m
+CONFIG_MUX_ADGS1408=m
+CONFIG_MUX_GPIO=m
+CONFIG_MUX_MMIO=m
+CONFIG_COUNTER=m
+CONFIG_INTERRUPT_CNT=m
+CONFIG_TI_EQEP=m
+CONFIG_TI_ECAP_CAPTURE=m
+CONFIG_VALIDATE_FS_PARSER=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_JFS_FS=m
+CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
+CONFIG_GFS2_FS=m
+CONFIG_GFS2_FS_LOCKING_DLM=y
+CONFIG_BTRFS_FS=y
+CONFIG_BTRFS_FS_POSIX_ACL=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_COMPRESSION=y
+CONFIG_ZONEFS_FS=m
+CONFIG_FS_ENCRYPTION=y
+CONFIG_FS_VERITY=y
+CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y
+CONFIG_FANOTIFY=y
+CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_AUTOFS4_FS=y
+CONFIG_FUSE_FS=y
+CONFIG_CUSE=m
+CONFIG_VIRTIO_FS=m
+CONFIG_OVERLAY_FS=y
+CONFIG_FSCACHE=y
+CONFIG_FSCACHE_STATS=y
+CONFIG_CACHEFILES=y
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+CONFIG_FAT_DEFAULT_UTF8=y
+CONFIG_EXFAT_FS=m
+CONFIG_NTFS_FS=m
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ECRYPT_FS=m
+CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RUBIN=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_SQUASHFS=m
+CONFIG_SQUASHFS_FILE_DIRECT=y
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SQUASHFS_XATTR=y
+CONFIG_SQUASHFS_LZ4=y
+CONFIG_SQUASHFS_LZO=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_ZSTD=y
+CONFIG_ROMFS_FS=m
+CONFIG_ROMFS_BACKED_BY_BOTH=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NFS_SWAP=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3_ACL=y
+CONFIG_NFSD_V4=y
+CONFIG_NFSD_BLOCKLAYOUT=y
+CONFIG_NFSD_V4_SECURITY_LABEL=y
+CONFIG_SUNRPC_DEBUG=y
+CONFIG_CEPH_FS=m
+CONFIG_CEPH_FSCACHE=y
+CONFIG_CEPH_FS_POSIX_ACL=y
+CONFIG_CIFS=m
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_CIFS_FSCACHE=y
+CONFIG_SMB_SERVER=m
+CONFIG_CODA_FS=m
+CONFIG_AFS_FS=m
+CONFIG_AFS_FSCACHE=y
+CONFIG_9P_FS=m
+CONFIG_9P_FSCACHE=y
+CONFIG_9P_FS_POSIX_ACL=y
+CONFIG_9P_FS_SECURITY=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
+CONFIG_DLM=m
+CONFIG_DLM_DEBUG=y
+CONFIG_UNICODE=y
+CONFIG_KEY_DH_OPERATIONS=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_NETWORK_XFRM=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_FORTIFY_SOURCE=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_TOMOYO=y
+CONFIG_SECURITY_APPARMOR=y
+CONFIG_SECURITY_YAMA=y
+CONFIG_SECURITY_LANDLOCK=y
+CONFIG_INTEGRITY_SIGNATURE=y
+CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
+CONFIG_IMA=y
+CONFIG_IMA_SIG_TEMPLATE=y
+CONFIG_IMA_DEFAULT_HASH_SHA256=y
+CONFIG_IMA_APPRAISE=y
+CONFIG_IMA_ARCH_POLICY=y
+CONFIG_EVM=y
+CONFIG_DEFAULT_SECURITY_APPARMOR=y
+CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y
+CONFIG_CRYPTO_USER=m
+CONFIG_CRYPTO_PCRYPT=m
+CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_ECRDSA=m
+CONFIG_CRYPTO_CURVE25519=m
+CONFIG_CRYPTO_AES_TI=m
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
+CONFIG_CRYPTO_DRBG_HASH=y
+CONFIG_CRYPTO_DRBG_CTR=y
+CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
+# CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set
+CONFIG_CRYPTO_GHASH_ARM_CE=m
+CONFIG_CRYPTO_NHPOLY1305_NEON=m
+CONFIG_CRYPTO_BLAKE2B_NEON=m
+CONFIG_CRYPTO_SHA1_ARM_NEON=m
+CONFIG_CRYPTO_SHA1_ARM_CE=m
+CONFIG_CRYPTO_SHA2_ARM_CE=m
+CONFIG_CRYPTO_SHA512_ARM=m
+CONFIG_CRYPTO_AES_ARM=m
+CONFIG_CRYPTO_AES_ARM_BS=m
+CONFIG_CRYPTO_AES_ARM_CE=m
+CONFIG_CRYPTO_CRC32_ARM_CE=m
+CONFIG_CRYPTO_CRCT10DIF_ARM_CE=m
+CONFIG_CRYPTO_DEV_OMAP=y
+CONFIG_CRYPTO_DEV_OMAP_SHAM=y
+CONFIG_CRYPTO_DEV_OMAP_AES=y
+CONFIG_CRYPTO_DEV_OMAP_DES=y
+CONFIG_CRYPTO_DEV_ATMEL_ECC=y
+CONFIG_CRYPTO_DEV_ATMEL_SHA204A=y
+CONFIG_CRYPTO_DEV_VIRTIO=m
+CONFIG_PKCS8_PRIVATE_KEY_PARSER=m
+# CONFIG_RAID6_PQ_BENCHMARK is not set
+CONFIG_CORDIC=m
+CONFIG_CRC4=m
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_IA64 is not set
+# CONFIG_XZ_DEC_SPARC is not set
+CONFIG_CMA_SIZE_MBYTES=48
+CONFIG_IRQ_POLL=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_TER16x32=y
+CONFIG_PRINTK_TIME=y
+CONFIG_BOOT_PRINTK_DELAY=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x01b6
+CONFIG_PAGE_EXTENSION=y
+CONFIG_PAGE_POISONING=y
+CONFIG_DEBUG_WX=y
+CONFIG_SCHED_STACK_END_CHECK=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_SOFTLOCKUP_DETECTOR=y
+CONFIG_SCHEDSTATS=y
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_BUG_ON_DATA_CORRUPTION=y
+# CONFIG_RCU_TRACE is not set
+CONFIG_STACK_TRACER=y
+CONFIG_FTRACE_SYSCALLS=y
+CONFIG_TRACER_SNAPSHOT=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_HIST_TRIGGERS=y
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_NOTIFIER_ERROR_INJECTION=m
+# CONFIG_RUNTIME_TESTING_MENU is not set
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dts
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Device Tree fragment for LS1028A QDS board, serdes 13bb
- *
- * Copyright 2019-2021 NXP
- *
- * Requires a LS1028A QDS board with lane B rework.
- * Requires a SCH-30841 card with lane A of connector rewired to PHY lane C.
- * Set-up is a SCH-30842 card in slot 1 and SCH-30841 in slot 2.
- */
-
-/dts-v1/;
-/plugin/;
-
-&mdio_slot1 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	slot1_sgmii: ethernet-phy@2 {
-		/* AQR112 */
-		reg = <0x2>;
-		compatible = "ethernet-phy-ieee802.3-c45";
-	};
-};
-
-&enetc_port0 {
-	phy-handle = <&slot1_sgmii>;
-	phy-mode = "usxgmii";
-	managed = "in-band-status";
-	status = "okay";
-};
-
-&mdio_slot2 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	/* 4 ports on AQR412 */
-	slot2_qxgmii0: ethernet-phy@0 {
-		reg = <0x0>;
-		compatible = "ethernet-phy-ieee802.3-c45";
-	};
-
-	slot2_qxgmii1: ethernet-phy@1 {
-		reg = <0x1>;
-		compatible = "ethernet-phy-ieee802.3-c45";
-	};
-
-	slot2_qxgmii2: ethernet-phy@2 {
-		reg = <0x2>;
-		compatible = "ethernet-phy-ieee802.3-c45";
-	};
-
-	slot2_qxgmii3: ethernet-phy@3 {
-		reg = <0x3>;
-		compatible = "ethernet-phy-ieee802.3-c45";
-	};
-};
-
-&mscc_felix_ports {
-	port@0 {
-		status = "okay";
-		phy-handle = <&slot2_qxgmii0>;
-		phy-mode = "usxgmii";
-		managed = "in-band-status";
-	};
-
-	port@1 {
-		status = "okay";
-		phy-handle = <&slot2_qxgmii1>;
-		phy-mode = "usxgmii";
-		managed = "in-band-status";
-	};
-
-	port@2 {
-		status = "okay";
-		phy-handle = <&slot2_qxgmii2>;
-		phy-mode = "usxgmii";
-		managed = "in-band-status";
-	};
-
-	port@3 {
-		status = "okay";
-		phy-handle = <&slot2_qxgmii3>;
-		phy-mode = "usxgmii";
-		managed = "in-band-status";
-	};
-};
-
-&mscc_felix {
-	status = "okay";
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dtso b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dtso
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree fragment for LS1028A QDS board, serdes 13bb
+ *
+ * Copyright 2019-2021 NXP
+ *
+ * Requires a LS1028A QDS board with lane B rework.
+ * Requires a SCH-30841 card with lane A of connector rewired to PHY lane C.
+ * Set-up is a SCH-30842 card in slot 1 and SCH-30841 in slot 2.
+ */
+
+/dts-v1/;
+/plugin/;
+
+&mdio_slot1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	slot1_sgmii: ethernet-phy@2 {
+		/* AQR112 */
+		reg = <0x2>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
+};
+
+&enetc_port0 {
+	phy-handle = <&slot1_sgmii>;
+	phy-mode = "usxgmii";
+	managed = "in-band-status";
+	status = "okay";
+};
+
+&mdio_slot2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* 4 ports on AQR412 */
+	slot2_qxgmii0: ethernet-phy@0 {
+		reg = <0x0>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
+
+	slot2_qxgmii1: ethernet-phy@1 {
+		reg = <0x1>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
+
+	slot2_qxgmii2: ethernet-phy@2 {
+		reg = <0x2>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
+
+	slot2_qxgmii3: ethernet-phy@3 {
+		reg = <0x3>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
+};
+
+&mscc_felix_ports {
+	port@0 {
+		status = "okay";
+		phy-handle = <&slot2_qxgmii0>;
+		phy-mode = "usxgmii";
+		managed = "in-band-status";
+	};
+
+	port@1 {
+		status = "okay";
+		phy-handle = <&slot2_qxgmii1>;
+		phy-mode = "usxgmii";
+		managed = "in-band-status";
+	};
+
+	port@2 {
+		status = "okay";
+		phy-handle = <&slot2_qxgmii2>;
+		phy-mode = "usxgmii";
+		managed = "in-band-status";
+	};
+
+	port@3 {
+		status = "okay";
+		phy-handle = <&slot2_qxgmii3>;
+		phy-mode = "usxgmii";
+		managed = "in-band-status";
+	};
+};
+
+&mscc_felix {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dts
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,85 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Device Tree fragment for LS1028A QDS board, serdes 69xx
- *
- * Copyright 2019-2021 NXP
- *
- * Requires a LS1028A QDS board with lane B rework.
- * Requires a SCH-30842 card in slot 1 and a SCH-28021 card in slot 2.
- */
-
-/dts-v1/;
-/plugin/;
-
-&mdio_slot1 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	slot1_sgmii: ethernet-phy@2 {
-		/* AQR112 */
-		reg = <0x2>;
-		compatible = "ethernet-phy-ieee802.3-c45";
-	};
-};
-
-&enetc_port0 {
-	phy-handle = <&slot1_sgmii>;
-	phy-mode = "2500base-x";
-	status = "okay";
-};
-
-&mdio_slot2 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	/* 4 ports on VSC8514 */
-	slot2_qsgmii0: ethernet-phy@8 {
-		reg = <0x8>;
-	};
-
-	slot2_qsgmii1: ethernet-phy@9 {
-		reg = <0x9>;
-	};
-
-	slot2_qsgmii2: ethernet-phy@a {
-		reg = <0xa>;
-	};
-
-	slot2_qsgmii3: ethernet-phy@b {
-		reg = <0xb>;
-	};
-};
-
-&mscc_felix_ports {
-	port@0 {
-		status = "okay";
-		phy-handle = <&slot2_qsgmii0>;
-		phy-mode = "qsgmii";
-		managed = "in-band-status";
-	};
-
-	port@1 {
-		status = "okay";
-		phy-handle = <&slot2_qsgmii1>;
-		phy-mode = "qsgmii";
-		managed = "in-band-status";
-	};
-
-	port@2 {
-		status = "okay";
-		phy-handle = <&slot2_qsgmii2>;
-		phy-mode = "qsgmii";
-		managed = "in-band-status";
-	};
-
-	port@3 {
-		status = "okay";
-		phy-handle = <&slot2_qsgmii3>;
-		phy-mode = "qsgmii";
-		managed = "in-band-status";
-	};
-};
-
-&mscc_felix {
-	status = "okay";
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dtso b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dtso
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree fragment for LS1028A QDS board, serdes 69xx
+ *
+ * Copyright 2019-2021 NXP
+ *
+ * Requires a LS1028A QDS board with lane B rework.
+ * Requires a SCH-30842 card in slot 1 and a SCH-28021 card in slot 2.
+ */
+
+/dts-v1/;
+/plugin/;
+
+&mdio_slot1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	slot1_sgmii: ethernet-phy@2 {
+		/* AQR112 */
+		reg = <0x2>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
+};
+
+&enetc_port0 {
+	phy-handle = <&slot1_sgmii>;
+	phy-mode = "2500base-x";
+	status = "okay";
+};
+
+&mdio_slot2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* 4 ports on VSC8514 */
+	slot2_qsgmii0: ethernet-phy@8 {
+		reg = <0x8>;
+	};
+
+	slot2_qsgmii1: ethernet-phy@9 {
+		reg = <0x9>;
+	};
+
+	slot2_qsgmii2: ethernet-phy@a {
+		reg = <0xa>;
+	};
+
+	slot2_qsgmii3: ethernet-phy@b {
+		reg = <0xb>;
+	};
+};
+
+&mscc_felix_ports {
+	port@0 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii0>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
+	};
+
+	port@1 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii1>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
+	};
+
+	port@2 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii2>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
+	};
+
+	port@3 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii3>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
+	};
+};
+
+&mscc_felix {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dts
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Device Tree fragment for LS1028A QDS board, serdes 7777
- *
- * Copyright 2019-2021 NXP
- *
- * Requires a LS1028A QDS board without lane B rework.
- * Requires a SCH-30841 card without lane A/C rewire and with a FW with muxing
- * disabled, plugged in slot 1.
- */
-
-/dts-v1/;
-/plugin/;
-
-&mdio_slot1 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	/* 4 ports on AQR412 */
-	slot1_sxgmii0: ethernet-phy@0 {
-		reg = <0x0>;
-		compatible = "ethernet-phy-ieee802.3-c45";
-	};
-
-	slot1_sxgmii1: ethernet-phy@1 {
-		reg = <0x1>;
-		compatible = "ethernet-phy-ieee802.3-c45";
-	};
-
-	slot1_sxgmii2: ethernet-phy@2 {
-		reg = <0x2>;
-		compatible = "ethernet-phy-ieee802.3-c45";
-	};
-
-	slot1_sxgmii3: ethernet-phy@3 {
-		reg = <0x3>;
-		compatible = "ethernet-phy-ieee802.3-c45";
-	};
-};
-
-&mscc_felix_ports {
-	port@0 {
-		status = "okay";
-		phy-handle = <&slot1_sxgmii0>;
-		phy-mode = "2500base-x";
-	};
-
-	port@1 {
-		status = "okay";
-		phy-handle = <&slot1_sxgmii1>;
-		phy-mode = "2500base-x";
-	};
-
-	port@2 {
-		status = "okay";
-		phy-handle = <&slot1_sxgmii2>;
-		phy-mode = "2500base-x";
-	};
-
-	port@3 {
-		status = "okay";
-		phy-handle = <&slot1_sxgmii3>;
-		phy-mode = "2500base-x";
-	};
-};
-
-&mscc_felix {
-	status = "okay";
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dtso b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dtso
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree fragment for LS1028A QDS board, serdes 7777
+ *
+ * Copyright 2019-2021 NXP
+ *
+ * Requires a LS1028A QDS board without lane B rework.
+ * Requires a SCH-30841 card without lane A/C rewire and with a FW with muxing
+ * disabled, plugged in slot 1.
+ */
+
+/dts-v1/;
+/plugin/;
+
+&mdio_slot1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* 4 ports on AQR412 */
+	slot1_sxgmii0: ethernet-phy@0 {
+		reg = <0x0>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
+
+	slot1_sxgmii1: ethernet-phy@1 {
+		reg = <0x1>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
+
+	slot1_sxgmii2: ethernet-phy@2 {
+		reg = <0x2>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
+
+	slot1_sxgmii3: ethernet-phy@3 {
+		reg = <0x3>;
+		compatible = "ethernet-phy-ieee802.3-c45";
+	};
+};
+
+&mscc_felix_ports {
+	port@0 {
+		status = "okay";
+		phy-handle = <&slot1_sxgmii0>;
+		phy-mode = "2500base-x";
+	};
+
+	port@1 {
+		status = "okay";
+		phy-handle = <&slot1_sxgmii1>;
+		phy-mode = "2500base-x";
+	};
+
+	port@2 {
+		status = "okay";
+		phy-handle = <&slot1_sxgmii2>;
+		phy-mode = "2500base-x";
+	};
+
+	port@3 {
+		status = "okay";
+		phy-handle = <&slot1_sxgmii3>;
+		phy-mode = "2500base-x";
+	};
+};
+
+&mscc_felix {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dts
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,85 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Device Tree fragment for LS1028A QDS board, serdes 85bb
- *
- * Copyright 2019-2021 NXP
- *
- * Requires a LS1028A QDS board with lane B rework.
- * Requires a SCH-24801 card in slot 1 and a SCH-28021 card in slot 2.
- */
-
-/dts-v1/;
-/plugin/;
-
-&mdio_slot1 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	slot1_sgmii: ethernet-phy@1c {
-		/* 1st port on VSC8234 */
-		reg = <0x1c>;
-	};
-};
-
-&enetc_port0 {
-	phy-handle = <&slot1_sgmii>;
-	phy-mode = "sgmii";
-	managed = "in-band-status";
-	status = "okay";
-};
-
-&mdio_slot2 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	/* 4 ports on VSC8514 */
-	slot2_qsgmii0: ethernet-phy@8 {
-		reg = <0x8>;
-	};
-
-	slot2_qsgmii1: ethernet-phy@9 {
-		reg = <0x9>;
-	};
-
-	slot2_qsgmii2: ethernet-phy@a {
-		reg = <0xa>;
-	};
-
-	slot2_qsgmii3: ethernet-phy@b {
-		reg = <0xb>;
-	};
-};
-
-&mscc_felix_ports {
-	port@0 {
-		status = "okay";
-		phy-handle = <&slot2_qsgmii0>;
-		phy-mode = "qsgmii";
-		managed = "in-band-status";
-	};
-
-	port@1 {
-		status = "okay";
-		phy-handle = <&slot2_qsgmii1>;
-		phy-mode = "qsgmii";
-		managed = "in-band-status";
-	};
-
-	port@2 {
-		status = "okay";
-		phy-handle = <&slot2_qsgmii2>;
-		phy-mode = "qsgmii";
-		managed = "in-band-status";
-	};
-
-	port@3 {
-		status = "okay";
-		phy-handle = <&slot2_qsgmii3>;
-		phy-mode = "qsgmii";
-		managed = "in-band-status";
-	};
-};
-
-&mscc_felix {
-	status = "okay";
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dtso b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dtso
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree fragment for LS1028A QDS board, serdes 85bb
+ *
+ * Copyright 2019-2021 NXP
+ *
+ * Requires a LS1028A QDS board with lane B rework.
+ * Requires a SCH-24801 card in slot 1 and a SCH-28021 card in slot 2.
+ */
+
+/dts-v1/;
+/plugin/;
+
+&mdio_slot1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	slot1_sgmii: ethernet-phy@1c {
+		/* 1st port on VSC8234 */
+		reg = <0x1c>;
+	};
+};
+
+&enetc_port0 {
+	phy-handle = <&slot1_sgmii>;
+	phy-mode = "sgmii";
+	managed = "in-band-status";
+	status = "okay";
+};
+
+&mdio_slot2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* 4 ports on VSC8514 */
+	slot2_qsgmii0: ethernet-phy@8 {
+		reg = <0x8>;
+	};
+
+	slot2_qsgmii1: ethernet-phy@9 {
+		reg = <0x9>;
+	};
+
+	slot2_qsgmii2: ethernet-phy@a {
+		reg = <0xa>;
+	};
+
+	slot2_qsgmii3: ethernet-phy@b {
+		reg = <0xb>;
+	};
+};
+
+&mscc_felix_ports {
+	port@0 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii0>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
+	};
+
+	port@1 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii1>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
+	};
+
+	port@2 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii2>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
+	};
+
+	port@3 {
+		status = "okay";
+		phy-handle = <&slot2_qsgmii3>;
+		phy-mode = "qsgmii";
+		managed = "in-band-status";
+	};
+};
+
+&mscc_felix {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dts
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Device Tree fragment for LS1028A QDS board, serdes 85xx
- *
- * Copyright 2019-2021 NXP
- *
- * Requires a LS1028A QDS board without lane B rework.
- * Requires a SCH-24801 card in slot 1.
- */
-
-/dts-v1/;
-/plugin/;
-
-&mdio_slot1 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	/* VSC8234 */
-	slot1_sgmii0: ethernet-phy@1c {
-		reg = <0x1c>;
-	};
-
-	slot1_sgmii1: ethernet-phy@1d {
-		reg = <0x1d>;
-	};
-
-	slot1_sgmii2: ethernet-phy@1e {
-		reg = <0x1e>;
-	};
-
-	slot1_sgmii3: ethernet-phy@1f {
-		reg = <0x1f>;
-	};
-};
-
-&enetc_port0 {
-	phy-handle = <&slot1_sgmii0>;
-	phy-mode = "sgmii";
-	managed = "in-band-status";
-	status = "okay";
-};
-
-&mscc_felix_ports {
-	port@1 {
-		status = "okay";
-		phy-handle = <&slot1_sgmii1>;
-		phy-mode = "sgmii";
-		managed = "in-band-status";
-	};
-
-	port@2 {
-		status = "okay";
-		phy-handle = <&slot1_sgmii2>;
-		phy-mode = "sgmii";
-		managed = "in-band-status";
-	};
-};
-
-&mscc_felix {
-	status = "okay";
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dtso b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dtso
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree fragment for LS1028A QDS board, serdes 85xx
+ *
+ * Copyright 2019-2021 NXP
+ *
+ * Requires a LS1028A QDS board without lane B rework.
+ * Requires a SCH-24801 card in slot 1.
+ */
+
+/dts-v1/;
+/plugin/;
+
+&mdio_slot1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* VSC8234 */
+	slot1_sgmii0: ethernet-phy@1c {
+		reg = <0x1c>;
+	};
+
+	slot1_sgmii1: ethernet-phy@1d {
+		reg = <0x1d>;
+	};
+
+	slot1_sgmii2: ethernet-phy@1e {
+		reg = <0x1e>;
+	};
+
+	slot1_sgmii3: ethernet-phy@1f {
+		reg = <0x1f>;
+	};
+};
+
+&enetc_port0 {
+	phy-handle = <&slot1_sgmii0>;
+	phy-mode = "sgmii";
+	managed = "in-band-status";
+	status = "okay";
+};
+
+&mscc_felix_ports {
+	port@1 {
+		status = "okay";
+		phy-handle = <&slot1_sgmii1>;
+		phy-mode = "sgmii";
+		managed = "in-band-status";
+	};
+
+	port@2 {
+		status = "okay";
+		phy-handle = <&slot1_sgmii2>;
+		phy-mode = "sgmii";
+		managed = "in-band-status";
+	};
+};
+
+&mscc_felix {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dts
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Device Tree fragment for LS1028A QDS board, serdes 85xx
- *
- * Copyright 2019-2021 NXP
- *
- * Requires a LS1028A QDS board without lane B rework.
- * Requires a SCH-24801 card in slot 1.
- */
-
-/dts-v1/;
-/plugin/;
-
-&mdio_slot1 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	/* VSC8234 */
-	slot1_sgmii0: ethernet-phy@1c {
-		reg = <0x1c>;
-	};
-
-	slot1_sgmii1: ethernet-phy@1d {
-		reg = <0x1d>;
-	};
-
-	slot1_sgmii2: ethernet-phy@1e {
-		reg = <0x1e>;
-	};
-
-	slot1_sgmii3: ethernet-phy@1f {
-		reg = <0x1f>;
-	};
-};
-
-&mscc_felix_ports {
-	port@0 {
-		status = "okay";
-		phy-handle = <&slot1_sgmii0>;
-		phy-mode = "sgmii";
-		managed = "in-band-status";
-	};
-
-	port@1 {
-		status = "okay";
-		phy-handle = <&slot1_sgmii1>;
-		phy-mode = "sgmii";
-		managed = "in-band-status";
-	};
-
-	port@2 {
-		status = "okay";
-		phy-handle = <&slot1_sgmii2>;
-		phy-mode = "sgmii";
-		managed = "in-band-status";
-	};
-
-	port@3 {
-		status = "okay";
-		phy-handle = <&slot1_sgmii3>;
-		phy-mode = "sgmii";
-		managed = "in-band-status";
-	};
-};
-
-&mscc_felix {
-	status = "okay";
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dtso b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dtso
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree fragment for LS1028A QDS board, serdes 85xx
+ *
+ * Copyright 2019-2021 NXP
+ *
+ * Requires a LS1028A QDS board without lane B rework.
+ * Requires a SCH-24801 card in slot 1.
+ */
+
+/dts-v1/;
+/plugin/;
+
+&mdio_slot1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* VSC8234 */
+	slot1_sgmii0: ethernet-phy@1c {
+		reg = <0x1c>;
+	};
+
+	slot1_sgmii1: ethernet-phy@1d {
+		reg = <0x1d>;
+	};
+
+	slot1_sgmii2: ethernet-phy@1e {
+		reg = <0x1e>;
+	};
+
+	slot1_sgmii3: ethernet-phy@1f {
+		reg = <0x1f>;
+	};
+};
+
+&mscc_felix_ports {
+	port@0 {
+		status = "okay";
+		phy-handle = <&slot1_sgmii0>;
+		phy-mode = "sgmii";
+		managed = "in-band-status";
+	};
+
+	port@1 {
+		status = "okay";
+		phy-handle = <&slot1_sgmii1>;
+		phy-mode = "sgmii";
+		managed = "in-band-status";
+	};
+
+	port@2 {
+		status = "okay";
+		phy-handle = <&slot1_sgmii2>;
+		phy-mode = "sgmii";
+		managed = "in-band-status";
+	};
+
+	port@3 {
+		status = "okay";
+		phy-handle = <&slot1_sgmii3>;
+		phy-mode = "sgmii";
+		managed = "in-band-status";
+	};
+};
+
+&mscc_felix {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dts
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,93 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Copyright 2022 Gateworks Corporation
- */
-
-#include <dt-bindings/gpio/gpio.h>
-
-#include "imx8mm-pinfunc.h"
-
-/dts-v1/;
-/plugin/;
-
-&{/} {
-	compatible = "gw,imx8mm-gw72xx-0x", "fsl,imx8mm";
-
-	reg_cam: regulator-cam {
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_reg_cam>;
-		compatible = "regulator-fixed";
-		regulator-name = "reg_cam";
-		gpio = <&gpio1 1 GPIO_ACTIVE_HIGH>;
-		enable-active-high;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-	};
-
-	cam24m: cam24m {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <24000000>;
-		clock-output-names = "cam24m";
-	};
-};
-
-&csi {
-	status = "okay";
-};
-
-&i2c3 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	imx219: sensor@10 {
-		compatible = "sony,imx219";
-		reg = <0x10>;
-		clocks = <&cam24m>;
-		VDIG-supply = <&reg_cam>;
-
-		port {
-			/* MIPI CSI-2 bus endpoint */
-			imx219_to_mipi_csi2: endpoint {
-				remote-endpoint = <&imx8mm_mipi_csi_in>;
-				clock-lanes = <0>;
-				data-lanes = <1 2>;
-				link-frequencies = /bits/ 64 <456000000>;
-			};
-		};
-	};
-};
-
-&mipi_csi {
-	status = "okay";
-
-	ports {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		port@0 {
-			reg = <0>;
-
-			imx8mm_mipi_csi_in: endpoint {
-				remote-endpoint = <&imx219_to_mipi_csi2>;
-				data-lanes = <1 2>;
-			};
-		};
-
-		port@1 {
-			reg = <1>;
-
-			imx8mm_mipi_csi_out: endpoint {
-				remote-endpoint = <&csi_in>;
-			};
-		};
-	};
-};
-
-&iomuxc {
-	pinctrl_reg_cam: regcamgrp {
-		fsl,pins = <
-			MX8MM_IOMUXC_GPIO1_IO01_GPIO1_IO1	0x41
-		>;
-	};
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dtso
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2022 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "imx8mm-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	compatible = "gw,imx8mm-gw72xx-0x", "fsl,imx8mm";
+
+	reg_cam: regulator-cam {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_reg_cam>;
+		compatible = "regulator-fixed";
+		regulator-name = "reg_cam";
+		gpio = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	cam24m: cam24m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "cam24m";
+	};
+};
+
+&csi {
+	status = "okay";
+};
+
+&i2c3 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	imx219: sensor@10 {
+		compatible = "sony,imx219";
+		reg = <0x10>;
+		clocks = <&cam24m>;
+		VDIG-supply = <&reg_cam>;
+
+		port {
+			/* MIPI CSI-2 bus endpoint */
+			imx219_to_mipi_csi2: endpoint {
+				remote-endpoint = <&imx8mm_mipi_csi_in>;
+				clock-lanes = <0>;
+				data-lanes = <1 2>;
+				link-frequencies = /bits/ 64 <456000000>;
+			};
+		};
+	};
+};
+
+&mipi_csi {
+	status = "okay";
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+
+			imx8mm_mipi_csi_in: endpoint {
+				remote-endpoint = <&imx219_to_mipi_csi2>;
+				data-lanes = <1 2>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+
+			imx8mm_mipi_csi_out: endpoint {
+				remote-endpoint = <&csi_in>;
+			};
+		};
+	};
+};
+
+&iomuxc {
+	pinctrl_reg_cam: regcamgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_GPIO1_IO01_GPIO1_IO1	0x41
+		>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dts
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Copyright 2022 Gateworks Corporation
- *
- * GW72xx RS232 with RTS/CTS hardware flow control:
- *  - GPIO4_0 rs485_en needs to be driven low (in-active)
- *  - UART4_TX becomes RTS
- *  - UART4_RX becomes CTS
- */
-
-#include <dt-bindings/gpio/gpio.h>
-
-#include "imx8mm-pinfunc.h"
-
-/dts-v1/;
-/plugin/;
-
-&{/} {
-	compatible = "gw,imx8mm-gw72xx-0x";
-};
-
-&gpio4 {
-	rs485_en {
-		gpio-hog;
-		gpios = <0 GPIO_ACTIVE_HIGH>;
-		output-low;
-		line-name = "rs485_en";
-	};
-};
-
-&uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2>;
-	rts-gpios = <&gpio5 29 GPIO_ACTIVE_LOW>;
-	cts-gpios = <&gpio5 28 GPIO_ACTIVE_LOW>;
-	status = "okay";
-};
-
-&uart4 {
-	status = "disabled";
-};
-
-&iomuxc {
-	pinctrl_uart2: uart2grp {
-		fsl,pins = <
-			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
-			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
-			MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29	0x140
-			MX8MM_IOMUXC_UART4_RXD_GPIO5_IO28	0x140
-		>;
-	};
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dtso
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2022 Gateworks Corporation
+ *
+ * GW72xx RS232 with RTS/CTS hardware flow control:
+ *  - GPIO4_0 rs485_en needs to be driven low (in-active)
+ *  - UART4_TX becomes RTS
+ *  - UART4_RX becomes CTS
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "imx8mm-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	compatible = "gw,imx8mm-gw72xx-0x";
+};
+
+&gpio4 {
+	rs485_en {
+		gpio-hog;
+		gpios = <0 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "rs485_en";
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	rts-gpios = <&gpio5 29 GPIO_ACTIVE_LOW>;
+	cts-gpios = <&gpio5 28 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&uart4 {
+	status = "disabled";
+};
+
+&iomuxc {
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
+			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
+			MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29	0x140
+			MX8MM_IOMUXC_UART4_RXD_GPIO5_IO28	0x140
+		>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dts
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Copyright 2022 Gateworks Corporation
- *
- * GW72xx RS422 (RS485 full duplex):
- *  - GPIO1_0 rs485_term selects on-chip termination
- *  - GPIO4_0 rs485_en needs to be driven high (active)
- *  - GPIO4_2 rs485_hd needs to be driven low (in-active)
- *  - UART4_TX is DE for RS485 transmitter
- *  - RS485_EN needs to be pulled high
- *  - RS485_HALF needs to be low
- */
-
-#include <dt-bindings/gpio/gpio.h>
-
-#include "imx8mm-pinfunc.h"
-
-/dts-v1/;
-/plugin/;
-
-&{/} {
-	compatible = "gw,imx8mm-gw72xx-0x";
-};
-
-&gpio4 {
-	rs485_en {
-		gpio-hog;
-		gpios = <0 GPIO_ACTIVE_HIGH>;
-		output-high;
-		line-name = "rs485_en";
-	};
-
-	rs485_hd {
-		gpio-hog;
-		gpios = <2 GPIO_ACTIVE_HIGH>;
-		output-low;
-		line-name = "rs485_hd";
-	};
-};
-
-&uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2>;
-	rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
-	linux,rs485-enabled-at-boot-time;
-	status = "okay";
-};
-
-&uart4 {
-	status = "disabled";
-};
-
-&iomuxc {
-	pinctrl_uart2: uart2grp {
-		fsl,pins = <
-			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
-			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
-			MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29	0x140
-		>;
-	};
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dtso
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2022 Gateworks Corporation
+ *
+ * GW72xx RS422 (RS485 full duplex):
+ *  - GPIO1_0 rs485_term selects on-chip termination
+ *  - GPIO4_0 rs485_en needs to be driven high (active)
+ *  - GPIO4_2 rs485_hd needs to be driven low (in-active)
+ *  - UART4_TX is DE for RS485 transmitter
+ *  - RS485_EN needs to be pulled high
+ *  - RS485_HALF needs to be low
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "imx8mm-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	compatible = "gw,imx8mm-gw72xx-0x";
+};
+
+&gpio4 {
+	rs485_en {
+		gpio-hog;
+		gpios = <0 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "rs485_en";
+	};
+
+	rs485_hd {
+		gpio-hog;
+		gpios = <2 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "rs485_hd";
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+	linux,rs485-enabled-at-boot-time;
+	status = "okay";
+};
+
+&uart4 {
+	status = "disabled";
+};
+
+&iomuxc {
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
+			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
+			MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29	0x140
+		>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dts
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Copyright 2022 Gateworks Corporation
- *
- * GW72xx RS485 HD:
- *  - GPIO1_0 rs485_term selects on-chip termination
- *  - GPIO4_0 rs485_en needs to be driven high (active)
- *  - GPIO4_2 rs485_hd needs to be driven high (active)
- *  - UART4_TX is DE for RS485 transmitter
- *  - RS485_EN needs to be pulled high
- *  - RS485_HALF needs to be pulled high
- */
-
-#include <dt-bindings/gpio/gpio.h>
-
-#include "imx8mm-pinfunc.h"
-
-/dts-v1/;
-/plugin/;
-
-&{/} {
-	compatible = "gw,imx8mm-gw72xx-0x";
-};
-
-&gpio4 {
-	rs485_en {
-		gpio-hog;
-		gpios = <0 GPIO_ACTIVE_HIGH>;
-		output-high;
-		line-name = "rs485_en";
-	};
-
-	rs485_hd {
-		gpio-hog;
-		gpios = <2 GPIO_ACTIVE_HIGH>;
-		output-high;
-		line-name = "rs485_hd";
-	};
-};
-
-&uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2>;
-	rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
-	linux,rs485-enabled-at-boot-time;
-	status = "okay";
-};
-
-&uart4 {
-	status = "disabled";
-};
-
-&iomuxc {
-	pinctrl_uart2: uart2grp {
-		fsl,pins = <
-			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
-			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
-			MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29	0x140
-		>;
-	};
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dtso
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2022 Gateworks Corporation
+ *
+ * GW72xx RS485 HD:
+ *  - GPIO1_0 rs485_term selects on-chip termination
+ *  - GPIO4_0 rs485_en needs to be driven high (active)
+ *  - GPIO4_2 rs485_hd needs to be driven high (active)
+ *  - UART4_TX is DE for RS485 transmitter
+ *  - RS485_EN needs to be pulled high
+ *  - RS485_HALF needs to be pulled high
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "imx8mm-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	compatible = "gw,imx8mm-gw72xx-0x";
+};
+
+&gpio4 {
+	rs485_en {
+		gpio-hog;
+		gpios = <0 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "rs485_en";
+	};
+
+	rs485_hd {
+		gpio-hog;
+		gpios = <2 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "rs485_hd";
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+	linux,rs485-enabled-at-boot-time;
+	status = "okay";
+};
+
+&uart4 {
+	status = "disabled";
+};
+
+&iomuxc {
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
+			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
+			MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29	0x140
+		>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dts
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,93 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Copyright 2022 Gateworks Corporation
- */
-
-#include <dt-bindings/gpio/gpio.h>
-
-#include "imx8mm-pinfunc.h"
-
-/dts-v1/;
-/plugin/;
-
-&{/} {
-	compatible = "gw,imx8mm-gw73xx-0x", "fsl,imx8mm";
-
-	reg_cam: regulator-cam {
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_reg_cam>;
-		compatible = "regulator-fixed";
-		regulator-name = "reg_cam";
-		gpio = <&gpio1 1 GPIO_ACTIVE_HIGH>;
-		enable-active-high;
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-	};
-
-	cam24m: cam24m {
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <24000000>;
-		clock-output-names = "cam24m";
-	};
-};
-
-&csi {
-	status = "okay";
-};
-
-&i2c3 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	imx219: sensor@10 {
-		compatible = "sony,imx219";
-		reg = <0x10>;
-		clocks = <&cam24m>;
-		VDIG-supply = <&reg_cam>;
-
-		port {
-			/* MIPI CSI-2 bus endpoint */
-			imx219_to_mipi_csi2: endpoint {
-				remote-endpoint = <&imx8mm_mipi_csi_in>;
-				clock-lanes = <0>;
-				data-lanes = <1 2>;
-				link-frequencies = /bits/ 64 <456000000>;
-			};
-		};
-	};
-};
-
-&mipi_csi {
-	status = "okay";
-
-	ports {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		port@0 {
-			reg = <0>;
-
-			imx8mm_mipi_csi_in: endpoint {
-				remote-endpoint = <&imx219_to_mipi_csi2>;
-				data-lanes = <1 2>;
-			};
-		};
-
-		port@1 {
-			reg = <1>;
-
-			imx8mm_mipi_csi_out: endpoint {
-				remote-endpoint = <&csi_in>;
-			};
-		};
-	};
-};
-
-&iomuxc {
-	pinctrl_reg_cam: regcamgrp {
-		fsl,pins = <
-			MX8MM_IOMUXC_GPIO1_IO01_GPIO1_IO1	0x41
-		>;
-	};
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dtso
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2022 Gateworks Corporation
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "imx8mm-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	compatible = "gw,imx8mm-gw73xx-0x", "fsl,imx8mm";
+
+	reg_cam: regulator-cam {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_reg_cam>;
+		compatible = "regulator-fixed";
+		regulator-name = "reg_cam";
+		gpio = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+	};
+
+	cam24m: cam24m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+		clock-output-names = "cam24m";
+	};
+};
+
+&csi {
+	status = "okay";
+};
+
+&i2c3 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	imx219: sensor@10 {
+		compatible = "sony,imx219";
+		reg = <0x10>;
+		clocks = <&cam24m>;
+		VDIG-supply = <&reg_cam>;
+
+		port {
+			/* MIPI CSI-2 bus endpoint */
+			imx219_to_mipi_csi2: endpoint {
+				remote-endpoint = <&imx8mm_mipi_csi_in>;
+				clock-lanes = <0>;
+				data-lanes = <1 2>;
+				link-frequencies = /bits/ 64 <456000000>;
+			};
+		};
+	};
+};
+
+&mipi_csi {
+	status = "okay";
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+
+			imx8mm_mipi_csi_in: endpoint {
+				remote-endpoint = <&imx219_to_mipi_csi2>;
+				data-lanes = <1 2>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+
+			imx8mm_mipi_csi_out: endpoint {
+				remote-endpoint = <&csi_in>;
+			};
+		};
+	};
+};
+
+&iomuxc {
+	pinctrl_reg_cam: regcamgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_GPIO1_IO01_GPIO1_IO1	0x41
+		>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dts
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Copyright 2022 Gateworks Corporation
- *
- * GW73xx RS232 with RTS/CTS hardware flow control:
- *  - GPIO4_0 rs485_en needs to be driven low (in-active)
- *  - UART4_TX becomes RTS
- *  - UART4_RX becomes CTS
- */
-
-#include <dt-bindings/gpio/gpio.h>
-
-#include "imx8mm-pinfunc.h"
-
-/dts-v1/;
-/plugin/;
-
-&{/} {
-	compatible = "gw,imx8mm-gw73xx-0x";
-};
-
-&gpio4 {
-	rs485_en {
-		gpio-hog;
-		gpios = <0 GPIO_ACTIVE_HIGH>;
-		output-low;
-		line-name = "rs485_en";
-	};
-};
-
-&uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2>;
-	rts-gpios = <&gpio5 29 GPIO_ACTIVE_LOW>;
-	cts-gpios = <&gpio5 28 GPIO_ACTIVE_LOW>;
-	status = "okay";
-};
-
-&uart4 {
-	status = "disabled";
-};
-
-&iomuxc {
-	pinctrl_uart2: uart2grp {
-		fsl,pins = <
-			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
-			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
-			MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29	0x140
-			MX8MM_IOMUXC_UART4_RXD_GPIO5_IO28	0x140
-		>;
-	};
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2022 Gateworks Corporation
+ *
+ * GW73xx RS232 with RTS/CTS hardware flow control:
+ *  - GPIO4_0 rs485_en needs to be driven low (in-active)
+ *  - UART4_TX becomes RTS
+ *  - UART4_RX becomes CTS
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "imx8mm-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	compatible = "gw,imx8mm-gw73xx-0x";
+};
+
+&gpio4 {
+	rs485_en {
+		gpio-hog;
+		gpios = <0 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "rs485_en";
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	rts-gpios = <&gpio5 29 GPIO_ACTIVE_LOW>;
+	cts-gpios = <&gpio5 28 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&uart4 {
+	status = "disabled";
+};
+
+&iomuxc {
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
+			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
+			MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29	0x140
+			MX8MM_IOMUXC_UART4_RXD_GPIO5_IO28	0x140
+		>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dts
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Copyright 2021 Gateworks Corporation
- *
- * GW73xx RS422 (RS485 full duplex):
- *  - GPIO1_0 rs485_term selects on-chip termination
- *  - GPIO4_0 rs485_en needs to be driven high (active)
- *  - GPIO4_2 rs485_hd needs to be driven low (in-active)
- *  - UART4_TX is DE for RS485 transmitter
- *  - RS485_EN needs to be pulled high
- *  - RS485_HALF needs to be low
- */
-
-#include <dt-bindings/gpio/gpio.h>
-
-#include "imx8mm-pinfunc.h"
-
-/dts-v1/;
-/plugin/;
-
-&{/} {
-	compatible = "gw,imx8mm-gw73xx-0x";
-};
-
-&gpio4 {
-	rs485_en {
-		gpio-hog;
-		gpios = <0 GPIO_ACTIVE_HIGH>;
-		output-high;
-		line-name = "rs485_en";
-	};
-
-	rs485_hd {
-		gpio-hog;
-		gpios = <2 GPIO_ACTIVE_HIGH>;
-		output-low;
-		line-name = "rs485_hd";
-	};
-};
-
-&uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2>;
-	rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
-	linux,rs485-enabled-at-boot-time;
-	status = "okay";
-};
-
-&uart4 {
-	status = "disabled";
-};
-
-&iomuxc {
-	pinctrl_uart2: uart2grp {
-		fsl,pins = <
-			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
-			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
-			MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29	0x140
-		>;
-	};
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2021 Gateworks Corporation
+ *
+ * GW73xx RS422 (RS485 full duplex):
+ *  - GPIO1_0 rs485_term selects on-chip termination
+ *  - GPIO4_0 rs485_en needs to be driven high (active)
+ *  - GPIO4_2 rs485_hd needs to be driven low (in-active)
+ *  - UART4_TX is DE for RS485 transmitter
+ *  - RS485_EN needs to be pulled high
+ *  - RS485_HALF needs to be low
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "imx8mm-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	compatible = "gw,imx8mm-gw73xx-0x";
+};
+
+&gpio4 {
+	rs485_en {
+		gpio-hog;
+		gpios = <0 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "rs485_en";
+	};
+
+	rs485_hd {
+		gpio-hog;
+		gpios = <2 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "rs485_hd";
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+	linux,rs485-enabled-at-boot-time;
+	status = "okay";
+};
+
+&uart4 {
+	status = "disabled";
+};
+
+&iomuxc {
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
+			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
+			MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29	0x140
+		>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dts
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Copyright 2021 Gateworks Corporation
- *
- * GW73xx RS485 HD:
- *  - GPIO1_0 rs485_term selects on-chip termination
- *  - GPIO4_0 rs485_en needs to be driven high (active)
- *  - GPIO4_2 rs485_hd needs to be driven high (active)
- *  - UART4_TX is DE for RS485 transmitter
- *  - RS485_EN needs to be pulled high
- *  - RS485_HALF needs to be pulled high
- */
-
-#include <dt-bindings/gpio/gpio.h>
-
-#include "imx8mm-pinfunc.h"
-
-/dts-v1/;
-/plugin/;
-
-&{/} {
-	compatible = "gw,imx8mm-gw73xx-0x";
-};
-
-&gpio4 {
-	rs485_en {
-		gpio-hog;
-		gpios = <0 GPIO_ACTIVE_HIGH>;
-		output-high;
-		line-name = "rs485_en";
-	};
-
-	rs485_hd {
-		gpio-hog;
-		gpios = <2 GPIO_ACTIVE_HIGH>;
-		output-high;
-		line-name = "rs485_hd";
-	};
-};
-
-&uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2>;
-	rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
-	linux,rs485-enabled-at-boot-time;
-	status = "okay";
-};
-
-&uart4 {
-	status = "disabled";
-};
-
-&iomuxc {
-	pinctrl_uart2: uart2grp {
-		fsl,pins = <
-			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
-			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
-			MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29	0x140
-		>;
-	};
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2021 Gateworks Corporation
+ *
+ * GW73xx RS485 HD:
+ *  - GPIO1_0 rs485_term selects on-chip termination
+ *  - GPIO4_0 rs485_en needs to be driven high (active)
+ *  - GPIO4_2 rs485_hd needs to be driven high (active)
+ *  - UART4_TX is DE for RS485 transmitter
+ *  - RS485_EN needs to be pulled high
+ *  - RS485_HALF needs to be pulled high
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+#include "imx8mm-pinfunc.h"
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	compatible = "gw,imx8mm-gw73xx-0x";
+};
+
+&gpio4 {
+	rs485_en {
+		gpio-hog;
+		gpios = <0 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "rs485_en";
+	};
+
+	rs485_hd {
+		gpio-hog;
+		gpios = <2 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "rs485_hd";
+	};
+};
+
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	rts-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
+	linux,rs485-enabled-at-boot-time;
+	status = "okay";
+};
+
+&uart4 {
+	status = "disabled";
+};
+
+&iomuxc {
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX     0x140
+			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX     0x140
+			MX8MM_IOMUXC_UART4_TXD_GPIO5_IO29	0x140
+		>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dts b/arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dts
--- a/arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Device Tree overlay for the AA104XD12 panel connected to LVDS1 on a Draak or
- * Ebisu board
- *
- * Copyright 2021 Ideas on Board Oy
- */
-
-/dts-v1/;
-/plugin/;
-
-&{/} {
-#include "panel-aa104xd12.dtsi"
-};
-
-&{/panel} {
-	backlight = <&backlight>;
-
-	port {
-		panel_in: endpoint {
-			remote-endpoint = <&lvds1_out>;
-		};
-	};
-};
-
-&lvds1 {
-	status = "okay";
-
-	ports {
-		port@1 {
-			lvds1_out: endpoint {
-				remote-endpoint = <&panel_in>;
-			};
-		};
-	};
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dtso b/arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dtso
--- a/arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree overlay for the AA104XD12 panel connected to LVDS1 on a Draak or
+ * Ebisu board
+ *
+ * Copyright 2021 Ideas on Board Oy
+ */
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+#include "panel-aa104xd12.dtsi"
+};
+
+&{/panel} {
+	backlight = <&backlight>;
+
+	port {
+		panel_in: endpoint {
+			remote-endpoint = <&lvds1_out>;
+		};
+	};
+};
+
+&lvds1 {
+	status = "okay";
+
+	ports {
+		port@1 {
+			lvds1_out: endpoint {
+				remote-endpoint = <&panel_in>;
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dts b/arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dts
--- a/arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
-/*
- * Device Tree overlay for the AA104XD12 panel connected to LVDS0 on a
- * Salvator-X or Salvator-XS board
- *
- * Copyright 2021 Ideas on Board Oy
- */
-
-/dts-v1/;
-/plugin/;
-
-&{/} {
-#include "panel-aa104xd12.dtsi"
-};
-
-&{/panel} {
-	backlight = <&backlight>;
-
-	port {
-		panel_in: endpoint {
-			remote-endpoint = <&lvds0_out>;
-		};
-	};
-};
-
-&lvds0 {
-	status = "okay";
-
-	ports {
-		port@1 {
-			lvds0_out: endpoint {
-				remote-endpoint = <&panel_in>;
-			};
-		};
-	};
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dtso b/arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dtso
--- a/arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree overlay for the AA104XD12 panel connected to LVDS0 on a
+ * Salvator-X or Salvator-XS board
+ *
+ * Copyright 2021 Ideas on Board Oy
+ */
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+#include "panel-aa104xd12.dtsi"
+};
+
+&{/panel} {
+	backlight = <&backlight>;
+
+	port {
+		panel_in: endpoint {
+			remote-endpoint = <&lvds0_out>;
+		};
+	};
+};
+
+&lvds0 {
+	status = "okay";
+
+	ports {
+		port@1 {
+			lvds0_out: endpoint {
+				remote-endpoint = <&panel_in>;
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-ov5640.dtso
--- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-ov5640.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-ov5640.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ALINX AN5641 & Digilent PCam 5C - OV5640 camera module
+ * Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_ov5640_fixed: ov5640-xclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <12000000>;
+	};
+};
+
+&main_gpio0 {
+	p11-hog {
+		/* P11 - CSI2_CAMERA_GPIO1 */
+		gpio-hog;
+		gpios = <11 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "CSI2_CAMERA_GPIO1";
+	};
+};
+
+&wkup_i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	ov5640: camera@3c {
+		compatible = "ovti,ov5640";
+		reg = <0x3c>;
+
+		clocks = <&clk_ov5640_fixed>;
+		clock-names = "xclk";
+
+		port {
+			csi2_cam0: endpoint {
+				remote-endpoint = <&csi2rx0_in_sensor>;
+				clock-lanes = <0>;
+				data-lanes = <1 2>;
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
+
+&dphy0 {
+	status = "okay";
+};
+
+&ti_csi2rx0 {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-tevi-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-tevi-ov5640.dtso
--- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-tevi-ov5640.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay-csi2-tevi-ov5640.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Technexion TEVI-OV5640-*-RPI - OV5640 camera module
+ * Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_ov5640_fixed: ov5640-xclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+	};
+};
+
+&main_gpio0 {
+	p11-hog {
+		/* P11 - CSI2_CAMERA_GPIO1 */
+		gpio-hog;
+		gpios = <11 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "CSI2_CAMERA_GPIO1";
+	};
+};
+
+&wkup_i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	ov5640: camera@3c {
+		compatible = "ovti,ov5640";
+		reg = <0x3c>;
+
+		clocks = <&clk_ov5640_fixed>;
+		clock-names = "xclk";
+
+		port {
+			csi2_cam0: endpoint {
+				remote-endpoint = <&csi2rx0_in_sensor>;
+				clock-lanes = <0>;
+				data-lanes = <1 2>;
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
+
+&dphy0 {
+	status = "okay";
+};
+
+&ti_csi2rx0 {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts
--- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay.dts	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,1122 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * https://beagleplay.org/
+ *
+ * Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2022-2023 Robert Nelson, BeagleBoard.org Foundation
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "k3-am625.dtsi"
+
+/ {
+	compatible = "beagle,am625-beagleplay", "ti,am625";
+	model = "BeagleBoard.org BeaglePlay";
+
+	aliases {
+		ethernet0 = &cpsw_port1;
+		ethernet1 = &cpsw_port2;
+		gpio0 = &main_gpio0;
+		gpio1 = &main_gpio1;
+		gpio2 = &mcu_gpio0;
+		i2c0 = &main_i2c0;
+		i2c1 = &main_i2c1;
+		i2c2 = &main_i2c2;
+		i2c3 = &main_i2c3;
+		i2c4 = &wkup_i2c0;
+		i2c5 = &mcu_i2c0;
+		mdio-gpio0 = &mdio0;
+		mikrobus0 = &mikrobus0;
+		mmc0 = &sdhci0;
+		mmc1 = &sdhci1;
+		mmc2 = &sdhci2;
+		rtc0 = &rtc;
+		rtc1 = &wkup_rtc0;
+		serial0 = &main_uart5;
+		serial1 = &main_uart6;
+		serial2 = &main_uart0;
+		usb0 = &usb0;
+		usb1 = &usb1;
+	};
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+		base_dtb = "k3-am625-beagleplay.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
+
+	memory@80000000 {
+		bootph-pre-ram;
+		device_type = "memory";
+		/* 2G RAM */
+		reg = <0x00000000 0x80000000 0x00000000 0x80000000>;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		ramoops: ramoops@9ca00000 {
+			compatible = "ramoops";
+			reg = <0x00 0x9c700000 0x00 0x00100000>;
+			record-size = <0x8000>;
+			console-size = <0x8000>;
+			ftrace-size = <0x00>;
+			pmsg-size = <0x8000>;
+		};
+
+		/* global cma region */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x00 0x8000000>;
+			linux,cma-default;
+		};
+
+		mcu_m4fss_dma_memory_region: m4f-dma-memory@9cb00000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9cb00000 0x00 0x100000>;
+			no-map;
+		};
+
+		mcu_m4fss_memory_region: m4f-memory@9cc00000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9cc00000 0x00 0xe00000>;
+			no-map;
+		};
+
+		secure_tfa_ddr: tfa@9e780000 {
+			reg = <0x00 0x9e780000 0x00 0x80000>;
+			no-map;
+		};
+
+		secure_ddr: optee@9e800000 {
+			reg = <0x00 0x9e800000 0x00 0x01800000>;
+			no-map;
+		};
+
+		wkup_r5fss0_core0_dma_memory_region: r5f-dma-memory@9db00000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9db00000 0x00 0xc00000>;
+			no-map;
+		};
+	};
+
+	vsys_5v0: regulator-1 {
+		bootph-all;
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_5v0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vdd_3v3: regulator-2 {
+		/* output of TLV62595DMQR-U12 */
+		bootph-all;
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vsys_5v0>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	wlan_en: regulator-3 {
+		/* OUTPUT of SN74AVC2T244DQMR */
+		compatible = "regulator-fixed";
+		regulator-name = "wlan_en";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		enable-active-high;
+		/* regulator-always-on; */
+		regulator-off-in-suspend;
+		vin-supply = <&vdd_3v3>;
+		gpio = <&main_gpio0 38 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_en_pins_default>;
+	};
+
+	vdd_3v3_sd: regulator-4 {
+		/* output of TPS22918DBVR-U21 */
+		bootph-all;
+		pinctrl-names = "default";
+		pinctrl-0 = <&vdd_3v3_sd_pins_default>;
+
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_3v3_sd";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		enable-active-high;
+		regulator-always-on;
+		vin-supply = <&vdd_3v3>;
+		gpio = <&main_gpio1 19 GPIO_ACTIVE_HIGH>;
+	};
+
+	vdd_sd_dv: regulator-5 {
+		bootph-all;
+		compatible = "regulator-gpio";
+		regulator-name = "sd_hs200_switch";
+		pinctrl-names = "default";
+		pinctrl-0 = <&vdd_sd_dv_pins_default>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		vin-supply = <&ldo1_reg>;
+		gpios = <&main_gpio1 49 GPIO_ACTIVE_HIGH>;
+		states = <1800000 0x0>,
+			 <3300000 0x1>;
+	};
+
+	leds {
+		bootph-all;
+		compatible = "gpio-leds";
+
+		led-0 {
+			bootph-all;
+			label = "beaglebone:green:usr0";
+			gpios = <&main_gpio0 3 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			function = LED_FUNCTION_HEARTBEAT;
+			default-state = "off";
+		};
+
+		led-1 {
+			bootph-all;
+			label = "beaglebone:green:usr1";
+			gpios = <&main_gpio0 4 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "disk-activity";
+			function = LED_FUNCTION_DISK_ACTIVITY;
+			default-state = "keep";
+		};
+
+		led-2 {
+			bootph-all;
+			label = "beaglebone:green:usr2";
+			gpios = <&main_gpio0 5 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "cpu";
+			function = LED_FUNCTION_CPU;
+		};
+
+		led-3 {
+			bootph-all;
+			label = "beaglebone:green:usr3";
+			gpios = <&main_gpio0 6 GPIO_ACTIVE_HIGH>;
+			function = LED_FUNCTION_LAN;
+		};
+
+		led-4 {
+			bootph-all;
+			label = "beaglebone:green:usr4";
+			gpios = <&main_gpio0 9 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "phy0tx";
+			function = LED_FUNCTION_WLAN;
+		};
+	};
+
+	gpio_keys: gpio-keys {
+		compatible = "gpio-keys";
+		autorepeat;
+		pinctrl-names = "default";
+		pinctrl-0 = <&usr_button_pins_default>;
+
+		usr: button-usr {
+			label = "User Key";
+			linux,code = <BTN_0>;
+			gpios = <&main_gpio0 18 GPIO_ACTIVE_LOW>;
+		};
+
+	};
+
+	hdmi0: connector {
+		compatible = "hdmi-connector";
+		label = "hdmi";
+		type = "a";
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&it66121hdmitx_out>;
+			};
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "it66121 HDMI";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&hdmi_dailink_master>;
+		simple-audio-card,frame-master = <&hdmi_dailink_master>;
+		simple-audio-card,mclk-fs = <2182>;
+
+		hdmi_dailink_master: simple-audio-card,cpu {
+			sound-dai = <&mcasp1>;
+			system-clock-frequency = <24000000>;
+			system-clock-direction-out;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&it66121hdmitx>;
+		};
+	};
+
+	/* Workaround for errata i2329 - just use mdio bitbang */
+	mdio0: mdio {
+		compatible = "virtual,mdio-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&mdio0_pins_default>;
+		gpios = <&main_gpio0 86 GPIO_ACTIVE_HIGH>, /* MDC */
+			<&main_gpio0 85 GPIO_ACTIVE_HIGH>; /* MDIO */
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpsw3g_phy0: ethernet-phy@0 {
+			reg = <0>;
+		};
+
+		cpsw3g_phy1: ethernet-phy@1 {
+			reg = <1>;
+			reset-gpios = <&main_gpio1 5 GPIO_ACTIVE_LOW>;
+			reset-assert-us = <25>;
+			reset-deassert-us = <60000>; /* T2 */
+		};
+	};
+
+	mikrobus0: linux-mikrobus {
+		symlink = "play/mikrobus";
+		compatible = "linux,mikrobus";
+		pinctrl-names = "default", "pwm_default", "pwm_gpio",
+				"uart_default", "uart_gpio", "i2c_default",
+				"i2c_gpio", "spi_default", "spi_gpio";
+		pinctrl-0 = <&mikrobus_gpio_pins_default>;
+		pinctrl-1 = <&mikrobus_pwm_pins_default>;
+		pinctrl-2 = <&mikrobus_pwm_pins_gpio>;
+		pinctrl-3 = <&mikrobus_uart_pins_default>;
+		pinctrl-4 = <&mikrobus_uart_pins_gpio>;
+		pinctrl-5 = <&mikrobus_i2c_pins_default>;
+		pinctrl-6 = <&mikrobus_i2c_pins_gpio>;
+		pinctrl-7 = <&mikrobus_spi_pins_default>;
+		pinctrl-8 = <&mikrobus_spi_pins_gpio>;
+		i2c-adapter = <&main_i2c3>;
+		spi-master = <1>;
+		spi-cs = <0 1>;
+		uart = <&main_uart5>;
+		mikrobus-gpios = <&main_gpio1 11 GPIO_ACTIVE_HIGH>, <&main_gpio1 9 GPIO_ACTIVE_HIGH>,
+		<&main_gpio1 24 GPIO_ACTIVE_HIGH>, <&main_gpio1 25 GPIO_ACTIVE_HIGH>,
+		<&main_gpio1 22 GPIO_ACTIVE_HIGH>, <&main_gpio1 23 GPIO_ACTIVE_HIGH>,
+		<&main_gpio1 7 GPIO_ACTIVE_HIGH>, <&main_gpio1 8 GPIO_ACTIVE_HIGH>,
+		<&main_gpio1 14 GPIO_ACTIVE_HIGH>, <&main_gpio1 13 GPIO_ACTIVE_HIGH>,
+		<&main_gpio1 12 GPIO_ACTIVE_HIGH>, <&main_gpio1 10 GPIO_ACTIVE_HIGH>;
+	};
+};
+
+&main_pmx0 {
+	hdmi_pins_default: hdmi-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0100, PIN_OUTPUT, 0) /* (AC25) VOUT0_VSYNC */
+			AM62X_IOPAD(0x00f8, PIN_OUTPUT, 0) /* (AB24) VOUT0_HSYNC */
+			AM62X_IOPAD(0x0104, PIN_OUTPUT, 0) /* (AC24) VOUT0_PCLK */
+			AM62X_IOPAD(0x00fc, PIN_OUTPUT, 0) /* (Y20) VOUT0_DE */
+			AM62X_IOPAD(0x00b8, PIN_OUTPUT, 0) /* (U22) VOUT0_DATA0 */
+			AM62X_IOPAD(0x00bc, PIN_OUTPUT, 0) /* (V24) VOUT0_DATA1 */
+			AM62X_IOPAD(0x00c0, PIN_OUTPUT, 0) /* (W25) VOUT0_DATA2 */
+			AM62X_IOPAD(0x00c4, PIN_OUTPUT, 0) /* (W24) VOUT0_DATA3 */
+			AM62X_IOPAD(0x00c8, PIN_OUTPUT, 0) /* (Y25) VOUT0_DATA4 */
+			AM62X_IOPAD(0x00cc, PIN_OUTPUT, 0) /* (Y24) VOUT0_DATA5 */
+			AM62X_IOPAD(0x00d0, PIN_OUTPUT, 0) /* (Y23) VOUT0_DATA6 */
+			AM62X_IOPAD(0x00d4, PIN_OUTPUT, 0) /* (AA25) VOUT0_DATA7 */
+			AM62X_IOPAD(0x00d8, PIN_OUTPUT, 0) /* (V21) VOUT0_DATA8 */
+			AM62X_IOPAD(0x00dc, PIN_OUTPUT, 0) /* (W21) VOUT0_DATA9 */
+			AM62X_IOPAD(0x00e0, PIN_OUTPUT, 0) /* (V20) VOUT0_DATA10 */
+			AM62X_IOPAD(0x00e4, PIN_OUTPUT, 0) /* (AA23) VOUT0_DATA11 */
+			AM62X_IOPAD(0x00e8, PIN_OUTPUT, 0) /* (AB25) VOUT0_DATA12 */
+			AM62X_IOPAD(0x00ec, PIN_OUTPUT, 0) /* (AA24) VOUT0_DATA13 */
+			AM62X_IOPAD(0x00f0, PIN_OUTPUT, 0) /* (Y22) VOUT0_DATA14 */
+			AM62X_IOPAD(0x00f4, PIN_OUTPUT, 0) /* (AA21) VOUT0_DATA15 */
+			AM62X_IOPAD(0x005c, PIN_OUTPUT, 1) /* (R24) GPMC0_AD8.VOUT0_DATA16 */
+			AM62X_IOPAD(0x0060, PIN_OUTPUT, 1) /* (R25) GPMC0_AD9.VOUT0_DATA17 */
+			AM62X_IOPAD(0x0064, PIN_OUTPUT, 1) /* (T25) GPMC0_AD10.VOUT0_DATA18 */
+			AM62X_IOPAD(0x0068, PIN_OUTPUT, 1) /* (R21) GPMC0_AD11.VOUT0_DATA19 */
+			AM62X_IOPAD(0x006c, PIN_OUTPUT, 1) /* (T22) GPMC0_AD12.VOUT0_DATA20 */
+			AM62X_IOPAD(0x0070, PIN_OUTPUT, 1) /* (T24) GPMC0_AD13.VOUT0_DATA21 */
+			AM62X_IOPAD(0x0074, PIN_OUTPUT, 1) /* (U25) GPMC0_AD14.VOUT0_DATA22 */
+			AM62X_IOPAD(0x0078, PIN_OUTPUT, 1) /* (U24) GPMC0_AD15.VOUT0_DATA23 */
+		>;
+	};
+
+	hdmi_gpio_pins_default: hdmi-gpio-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0094, PIN_INPUT_PULLUP | PIN_DEBOUNCE_CONF6, 7) /* (N20) GPMC0_BE1n.GPIO0_36 */
+			AM62X_IOPAD(0x0054, PIN_OUTPUT_PULLUP, 7) /* (P21) GPMC0_AD6.GPIO0_21 */
+		>;
+	};
+
+	gpio0_pins_default: gpio0-default-pins {
+		bootph-all;
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0004, PIN_INPUT, 7) /* (G25) OSPI0_LBCLKO.GPIO0_1 */
+			AM62X_IOPAD(0x0008, PIN_INPUT, 7) /* (J24) OSPI0_DQS.GPIO0_2 */
+			AM62X_IOPAD(0x000c, PIN_INPUT, 7) /* (E25) OSPI0_D0.GPIO0_3 */
+			AM62X_IOPAD(0x0010, PIN_INPUT, 7) /* (G24) OSPI0_D1.GPIO0_4 */
+			AM62X_IOPAD(0x0014, PIN_INPUT, 7) /* (F25) OSPI0_D2.GPIO0_5 */
+			AM62X_IOPAD(0x0018, PIN_INPUT, 7) /* (F24) OSPI0_D3.GPIO0_6 */
+			AM62X_IOPAD(0x0024, PIN_INPUT, 7) /* (H25) OSPI0_D6.GPIO0_9 */
+			AM62X_IOPAD(0x0028, PIN_INPUT, 7) /* (J22) OSPI0_D7.GPIO0_10 */
+			AM62X_IOPAD(0x002c, PIN_INPUT, 7) /* (F23) OSPI0_CSn0.GPIO0_11 */
+			AM62X_IOPAD(0x0030, PIN_INPUT, 7) /* (G21) OSPI0_CSn1.GPIO0_12 */
+			AM62X_IOPAD(0x0034, PIN_INPUT, 7) /* (H21) OSPI0_CSn2.GPIO0_13 */
+			AM62X_IOPAD(0x0038, PIN_INPUT, 7) /* (E24) OSPI0_CSn3.GPIO0_14 */
+			AM62X_IOPAD(0x00a4, PIN_INPUT, 7) /* (M22) GPMC0_DIR.GPIO0_40 */
+			AM62X_IOPAD(0x00ac, PIN_INPUT, 7) /* (L21) GPMC0_CSn1.GPIO0_42 */
+		>;
+	};
+
+	vdd_sd_dv_pins_default: vdd-sd-default-pins {
+		bootph-all;
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0244, PIN_OUTPUT, 7) /* (C17) MMC1_SDWP.GPIO1_49 */
+		>;
+	};
+
+	usr_button_pins_default: usr-button-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0048, PIN_INPUT, 7) /* (N25) GPMC0_AD3.GPIO0_18 */
+		>;
+	};
+
+	grove_pins_default: grove-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01e8, PIN_INPUT_PULLUP, 0) /* (B17) I2C1_SCL */
+			AM62X_IOPAD(0x01ec, PIN_INPUT_PULLUP, 0) /* (A17) I2C1_SDA */
+		>;
+	};
+
+	local_i2c_pins_default: local-i2c-default-pins {
+		bootph-all;
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01e0, PIN_INPUT_PULLUP, 0) /* (B16) I2C0_SCL */
+			AM62X_IOPAD(0x01e4, PIN_INPUT_PULLUP, 0) /* (A16) I2C0_SDA */
+		>;
+	};
+
+	i2c2_1v8_pins_default: i2c2-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x00b0, PIN_INPUT_PULLUP, 1) /* (K22) GPMC0_CSn2.I2C2_SCL */
+			AM62X_IOPAD(0x00b4, PIN_INPUT_PULLUP, 1) /* (K24) GPMC0_CSn3.I2C2_SDA */
+		>;
+	};
+
+	mcasp_hdmi_pins_default: mcasp-hdmi-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0090, PIN_INPUT, 2) /* (M24) GPMC0_BE0n_CLE.MCASP1_ACLKX */
+			AM62X_IOPAD(0x0098, PIN_INPUT, 2) /* (U23) GPMC0_WAIT0.MCASP1_AFSX */
+			AM62X_IOPAD(0x008c, PIN_OUTPUT, 2) /* (L25) GPMC0_WEn.MCASP1_AXR0 */
+			AM62X_IOPAD(0x0088, PIN_INPUT, 2) /* (L24) GPMC0_OEn_REn.MCASP1_AXR1 */
+			AM62X_IOPAD(0x0084, PIN_INPUT, 2) /* (L23) GPMC0_ADVn_ALE.MCASP1_AXR2 */
+			AM62X_IOPAD(0x007c, PIN_INPUT, 2) /* (P25) GPMC0_CLK.MCASP1_AXR3 */
+		>;
+	};
+
+	mdio0_pins_default: mdio0-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0160, PIN_OUTPUT, 7) /* (AD24) MDIO0_MDC.GPIO0_86 */
+			AM62X_IOPAD(0x015c, PIN_INPUT, 7) /* (AB22) MDIO0_MDIO.GPIO0_85 */
+		>;
+	};
+
+	rgmii1_pins_default: rgmii1-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x014c, PIN_INPUT, 0) /* (AB17) RGMII1_RD0 */
+			AM62X_IOPAD(0x0150, PIN_INPUT, 0) /* (AC17) RGMII1_RD1 */
+			AM62X_IOPAD(0x0154, PIN_INPUT, 0) /* (AB16) RGMII1_RD2 */
+			AM62X_IOPAD(0x0158, PIN_INPUT, 0) /* (AA15) RGMII1_RD3 */
+			AM62X_IOPAD(0x0148, PIN_INPUT, 0) /* (AD17) RGMII1_RXC */
+			AM62X_IOPAD(0x0144, PIN_INPUT, 0) /* (AE17) RGMII1_RX_CTL */
+			AM62X_IOPAD(0x0134, PIN_OUTPUT, 0) /* (AE20) RGMII1_TD0 */
+			AM62X_IOPAD(0x0138, PIN_OUTPUT, 0) /* (AD20) RGMII1_TD1 */
+			AM62X_IOPAD(0x013c, PIN_OUTPUT, 0) /* (AE18) RGMII1_TD2 */
+			AM62X_IOPAD(0x0140, PIN_OUTPUT, 0) /* (AD18) RGMII1_TD3 */
+			AM62X_IOPAD(0x0130, PIN_OUTPUT, 0) /* (AE19) RGMII1_TXC */
+			AM62X_IOPAD(0x012c, PIN_OUTPUT, 0) /* (AD19) RGMII1_TX_CTL */
+		>;
+	};
+
+	emmc_pins_default: emmc-default-pins {
+		bootph-all;
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0220, PIN_INPUT, 0) /* (Y3) MMC0_CMD */
+			AM62X_IOPAD(0x0218, PIN_INPUT, 0) /* (AB1) MMC0_CLK */
+			AM62X_IOPAD(0x0214, PIN_INPUT, 0) /* (AA2) MMC0_DAT0 */
+			AM62X_IOPAD(0x0210, PIN_INPUT, 0) /* (AA1) MMC0_DAT1 */
+			AM62X_IOPAD(0x020c, PIN_INPUT, 0) /* (AA3) MMC0_DAT2 */
+			AM62X_IOPAD(0x0208, PIN_INPUT, 0) /* (Y4) MMC0_DAT3 */
+			AM62X_IOPAD(0x0204, PIN_INPUT, 0) /* (AB2) MMC0_DAT4 */
+			AM62X_IOPAD(0x0200, PIN_INPUT, 0) /* (AC1) MMC0_DAT5 */
+			AM62X_IOPAD(0x01fc, PIN_INPUT, 0) /* (AD2) MMC0_DAT6 */
+			AM62X_IOPAD(0x01f8, PIN_INPUT, 0) /* (AC2) MMC0_DAT7 */
+		>;
+	};
+
+	vdd_3v3_sd_pins_default: vdd-3v3-sd-default-pins {
+		bootph-all;
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01c4, PIN_INPUT, 7) /* (B14) SPI0_D1_GPIO1_19 */
+		>;
+	};
+
+	sd_pins_default: sd-default-pins {
+		bootph-all;
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x023c, PIN_INPUT, 0) /* (A21) MMC1_CMD */
+			AM62X_IOPAD(0x0234, PIN_INPUT, 0) /* (B22) MMC1_CLK */
+			AM62X_IOPAD(0x0230, PIN_INPUT, 0) /* (A22) MMC1_DAT0 */
+			AM62X_IOPAD(0x022c, PIN_INPUT, 0) /* (B21) MMC1_DAT1 */
+			AM62X_IOPAD(0x0228, PIN_INPUT, 0) /* (C21) MMC1_DAT2 */
+			AM62X_IOPAD(0x0224, PIN_INPUT, 0) /* (D22) MMC1_DAT3 */
+			AM62X_IOPAD(0x0240, PIN_INPUT, 7) /* (D17) MMC1_SDCD.GPIO1_48 */
+		>;
+	};
+
+	wifi_pins_default: wifi-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0120, PIN_INPUT, 0) /* (C24) MMC2_CMD */
+			AM62X_IOPAD(0x0118, PIN_INPUT, 0) /* (D25) MMC2_CLK */
+			AM62X_IOPAD(0x0114, PIN_INPUT, 0) /* (B24) MMC2_DAT0 */
+			AM62X_IOPAD(0x0110, PIN_INPUT, 0) /* (C25) MMC2_DAT1 */
+			AM62X_IOPAD(0x010c, PIN_INPUT, 0) /* (E23) MMC2_DAT2 */
+			AM62X_IOPAD(0x0108, PIN_INPUT, 0) /* (D24) MMC2_DAT3 */
+			AM62X_IOPAD(0x0124, PIN_INPUT, 0) /* (A23) MMC2_SDCD */
+			AM62X_IOPAD(0x11c, PIN_INPUT, 0) /* (#N/A) MMC2_CLKB */
+		>;
+	};
+
+	wifi_en_pins_default: wifi-en-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x009c, PIN_OUTPUT, 7) /* (V25) GPMC0_WAIT1.GPIO0_38 */
+		>;
+	};
+
+	wifi_wlirq_pins_default: wifi-wlirq-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x00a8, PIN_INPUT, 7) /* (M21) GPMC0_CSn0.GPIO0_41 */
+		>;
+	};
+
+	oldi_pins_default: oldi-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0260, PIN_OUTPUT, 0) /* (AA5) OLDI0_A0N */
+			AM62X_IOPAD(0x025c, PIN_OUTPUT, 0) /* (Y6) OLDI0_A0P */
+			AM62X_IOPAD(0x0268, PIN_OUTPUT, 0) /* (AD3) OLDI0_A1N */
+			AM62X_IOPAD(0x0264, PIN_OUTPUT, 0) /* (AB4) OLDI0_A1P */
+			AM62X_IOPAD(0x0270, PIN_OUTPUT, 0) /* (Y8) OLDI0_A2N */
+			AM62X_IOPAD(0x026c, PIN_OUTPUT, 0) /* (AA8) OLDI0_A2P */
+			AM62X_IOPAD(0x0278, PIN_OUTPUT, 0) /* (AB6) OLDI0_A3N */
+			AM62X_IOPAD(0x0274, PIN_OUTPUT, 0) /* (AA7) OLDI0_A3P */
+			AM62X_IOPAD(0x0280, PIN_OUTPUT, 0) /* (AC6) OLDI0_A4N */
+			AM62X_IOPAD(0x027c, PIN_OUTPUT, 0) /* (AC5) OLDI0_A4P */
+			AM62X_IOPAD(0x0288, PIN_OUTPUT, 0) /* (AE5) OLDI0_A5N */
+			AM62X_IOPAD(0x0284, PIN_OUTPUT, 0) /* (AD6) OLDI0_A5P */
+			AM62X_IOPAD(0x0290, PIN_OUTPUT, 0) /* (AE6) OLDI0_A6N */
+			AM62X_IOPAD(0x028c, PIN_OUTPUT, 0) /* (AD7) OLDI0_A6P */
+			AM62X_IOPAD(0x0298, PIN_OUTPUT, 0) /* (AD8) OLDI0_A7N */
+			AM62X_IOPAD(0x0294, PIN_OUTPUT, 0) /* (AE7) OLDI0_A7P */
+			AM62X_IOPAD(0x02a0, PIN_OUTPUT, 0) /* (AD4) OLDI0_CLK0N */
+			AM62X_IOPAD(0x029c, PIN_OUTPUT, 0) /* (AE3) OLDI0_CLK0P */
+			AM62X_IOPAD(0x02a8, PIN_OUTPUT, 0) /* (AE4) OLDI0_CLK1N */
+			AM62X_IOPAD(0x02a4, PIN_OUTPUT, 0) /* (AD5) OLDI0_CLK1P */
+		>;
+	};
+
+	spe_pins_default: spe-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0168, PIN_INPUT, 1) /* (AE21) RGMII2_TXC.RMII2_CRS_DV */
+			AM62X_IOPAD(0x0180, PIN_INPUT, 1) /* (AD23) RGMII2_RXC.RMII2_REF_CLK */
+			AM62X_IOPAD(0x0184, PIN_INPUT, 1) /* (AE23) RGMII2_RD0.RMII2_RXD0 */
+			AM62X_IOPAD(0x0188, PIN_INPUT, 1) /* (AB20) RGMII2_RD1.RMII2_RXD1 */
+			AM62X_IOPAD(0x017c, PIN_INPUT, 1) /* (AD22) RGMII2_RX_CTL.RMII2_RX_ER */
+			AM62X_IOPAD(0x016c, PIN_INPUT, 1) /* (Y18) RGMII2_TD0.RMII2_TXD0 */
+			AM62X_IOPAD(0x0170, PIN_INPUT, 1) /* (AA18) RGMII2_TD1.RMII2_TXD1 */
+			AM62X_IOPAD(0x0164, PIN_INPUT, 1) /* (AA19) RGMII2_TX_CTL.RMII2_TX_EN */
+			AM62X_IOPAD(0x018c, PIN_OUTPUT, 7) /* (AC21) RGMII2_RD2.GPIO1_5 */
+			AM62X_IOPAD(0x0190, PIN_INPUT, 7) /* (AE22) RGMII2_RD3.GPIO1_6 */
+			AM62X_IOPAD(0x01f0, PIN_OUTPUT, 5) /* (A18) EXT_REFCLK1.CLKOUT0 */
+		>;
+	};
+
+	mikrobus_i2c_pins_default: mikrobus-i2c-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01d0, PIN_INPUT_PULLUP, 2) /* (A15) UART0_CTSn.I2C3_SCL */
+			AM62X_IOPAD(0x01d4, PIN_INPUT_PULLUP, 2) /* (B15) UART0_RTSn.I2C3_SDA */
+		>;
+	};
+
+	mikrobus_i2c_pins_gpio: mikrobus-i2c-pins-gpio {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01d0, PIN_INPUT, 7) /* (A15) UART0_CTSn.GPIO1_22 */
+			AM62X_IOPAD(0x01d4, PIN_INPUT, 7) /* (B15) UART0_RTSn.GPIO1_23 */
+		>;
+	};
+
+	mikrobus_uart_pins_default: mikrobus-uart-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01d8, PIN_INPUT, 1) /* (C15) MCAN0_TX.UART5_RXD */
+			AM62X_IOPAD(0x01dc, PIN_OUTPUT, 1) /* (E15) MCAN0_RX.UART5_TXD */
+		>;
+	};
+
+	mikrobus_uart_pins_gpio: mikrobus-uart-pins-gpio {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01d8, PIN_INPUT, 7) /* (C15) MCAN0_TX.GPIO1_24 */
+			AM62X_IOPAD(0x01dc, PIN_INPUT, 7) /* (E15) MCAN0_RX.GPIO1_25 */
+		>;
+	};
+
+	mikrobus_spi_pins_default: mikrobus-spi-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01b0, PIN_INPUT, 1) /* (A20) MCASP0_ACLKR.SPI2_CLK */
+			AM62X_IOPAD(0x01ac, PIN_INPUT, 1) /* (E19) MCASP0_AFSR.SPI2_CS0 */
+			AM62X_IOPAD(0x0194, PIN_INPUT, 1) /* (B19) MCASP0_AXR3.SPI2_D0 */
+			AM62X_IOPAD(0x0198, PIN_INPUT, 1) /* (A19) MCASP0_AXR2.SPI2_D1 */
+		>;
+	};
+
+	mikrobus_spi_pins_gpio: mikrobus-spi-pins-gpio {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0194, PIN_INPUT, 7) /* (B19) MCASP0_AXR3.GPIO1_7 */
+			AM62X_IOPAD(0x0198, PIN_INPUT, 7) /* (A19) MCASP0_AXR2.GPIO1_8 */
+			AM62X_IOPAD(0x01ac, PIN_INPUT, 7) /* (E19) MCASP0_AFSR.GPIO1_13 */
+			AM62X_IOPAD(0x01b0, PIN_INPUT, 7) /* (A20) MCASP0_ACLKR.GPIO1_14 */
+		>;
+	};
+
+	mikrobus_gpio_pins_default: mikrobus-gpio-default-pins {
+		bootph-all;
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x019c, PIN_INPUT, 7) /* (B18) MCASP0_AXR1.GPIO1_9 */
+			AM62X_IOPAD(0x01a0, PIN_INPUT, 7) /* (E18) MCASP0_AXR0.GPIO1_10 */
+			AM62X_IOPAD(0x01a8, PIN_INPUT, 7) /* (D20) MCASP0_AFSX.GPIO1_12 */
+		>;
+	};
+
+	main_uart0_pins_default: main-uart0-default-pins {
+		bootph-all;
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01c8, PIN_INPUT, 0) /* (D14) UART0_RXD */
+			AM62X_IOPAD(0x01cc, PIN_OUTPUT, 0) /* (E14) UART0_TXD */
+		>;
+	};
+
+	mikrobus_pwm_pins_default: mikrobus-pwm-pins-default {
+		bootph-all;
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01a4, PIN_INPUT, 2) /* (B20) MCASP0_ACLKX.ECAP2_IN_APWM_OUT */
+		>;
+	};
+
+	mikrobus_pwm_pins_gpio: mikrobus-pwm-pins-gpio {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01a4, PIN_INPUT, 7) /* (B20) MCASP0_ACLKX.GPIO1_11 */
+		>;
+	};
+
+	touchscreen_pins_default: touchscreen-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01b4, PIN_OUTPUT, 7) /* (A13) SPI0_CS0.GPIO1_15 */
+			AM62X_IOPAD(0x00a0, PIN_INPUT, 7) /* (K25) GPMC0_WPn.GPIO0_39 */
+		>;
+	};
+
+	backlight_pins_default: bl-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0000, PIN_OUTPUT, 7) /* (H24) OSPI0_CLK.GPIO0_0 */
+			AM62X_IOPAD(0x01b8, PIN_OUTPUT, 2) /* (C13) SPI0_CS1.EHRPWM0_B */
+		>;
+	};
+
+	wifi_debug_uart_pins_default: wifi-debug-uart-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x001c, PIN_INPUT, 3) /* (J23) OSPI0_D4.UART6_RXD */
+			AM62X_IOPAD(0x0020, PIN_OUTPUT, 3) /* (J25) OSPI0_D5.UART6_TXD */
+		>;
+	};
+
+	usb1_pins_default: usb1-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0258, PIN_INPUT, 0) /* (F18) USB1_DRVVBUS */
+		>;
+	};
+
+	pmic_irq_pins_default: pmic-irq-default-pins {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01f4, PIN_INPUT_PULLUP, 0) /* (D16) EXTINTn */
+		>;
+	};
+};
+
+&mcu_pmx0 {
+	i2c_qwiic_pins_default: i2c-qwiic-default-pins {
+		pinctrl-single,pins = <
+			AM62X_MCU_IOPAD(0x0044, PIN_INPUT, 0) /* (A8) MCU_I2C0_SCL */
+			AM62X_MCU_IOPAD(0x0048, PIN_INPUT, 0) /* (D10) MCU_I2C0_SDA */
+		>;
+	};
+
+	gbe_pmx_obsclk: gbe-pmx-obsclk-default-pins {
+		pinctrl-single,pins = <
+			AM62X_MCU_IOPAD(0x0004, PIN_OUTPUT, 1) /* (B8) MCU_SPI0_CS1.MCU_OBSCLK0 */
+		>;
+	};
+
+	i2c_csi_pins_default: i2c-csi-default-pins {
+		pinctrl-single,pins = <
+			AM62X_MCU_IOPAD(0x004c, PIN_INPUT_PULLUP, 0) /* (B9) WKUP_I2C0_SCL */
+			AM62X_MCU_IOPAD(0x0050, PIN_INPUT_PULLUP, 0) /* (A9) WKUP_I2C0_SDA */
+		>;
+	};
+
+	wifi_32k_clk: mcu-clk-out-default-pins {
+		pinctrl-single,pins = <
+			AM62X_MCU_IOPAD(0x0084, PIN_OUTPUT, 0) /* (A12) WKUP_CLKOUT0 */
+		>;
+	};
+};
+
+&a53_opp_table {
+	/* Requires VDD_CORE to be at 0.85V */
+	opp-1400000000 {
+		opp-hz = /bits/ 64 <1400000000>;
+		opp-supported-hw = <0x01 0x0004>;
+	};
+};
+
+&wkup_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c_csi_pins_default>;
+	clock-frequency = <400000>;
+	/* Enable with overlay for camera sensor */
+	symlink = "play/csi/i2c";
+};
+
+&mcu_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c_qwiic_pins_default>;
+	clock-frequency = <100000>;
+	status = "okay";
+	symlink = "play/qwiic/i2c";
+};
+
+&mcu_m4fss {
+	mboxes = <&mailbox0_cluster0 &mbox_m4_0>;
+	memory-region = <&mcu_m4fss_dma_memory_region>,
+			<&mcu_m4fss_memory_region>;
+};
+
+&wkup_r5fss0 {
+	/* Runs dedicated Device Management firmware */
+	status = "reserved";
+};
+
+&mailbox0_cluster0 {
+	mbox_m4_0: mbox-m4-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+};
+
+&usbss0 {
+	ti,vbus-divider;
+	status = "okay";
+};
+
+&usb0 {
+	dr_mode = "peripheral";
+};
+
+&usbss1 {
+	ti,vbus-divider;
+	status = "okay";
+};
+
+&usb1 {
+	dr_mode = "host";
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb1_pins_default>;
+};
+
+&cpsw3g {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii1_pins_default>, <&spe_pins_default>,
+		    <&gbe_pmx_obsclk>;
+	assigned-clocks = <&k3_clks 157 70>, <&k3_clks 157 20>;
+	assigned-clock-parents = <&k3_clks 157 72>, <&k3_clks 157 22>;
+};
+
+&cpsw_port1 {
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&cpsw3g_phy0>;
+};
+
+&cpsw_port2 {
+	phy-mode = "rmii";
+	phy-handle = <&cpsw3g_phy1>;
+};
+
+&cpsw3g_mdio {
+	/* Workaround for errata i2329 - Use mdio bitbang */
+	status = "disabled";
+};
+
+&main_gpio0 {
+	bootph-all;
+	pinctrl-names = "default";
+	pinctrl-0 = <&gpio0_pins_default>;
+	gpio-line-names = "BL_EN_3V3", "SPE_PO_EN", "RTC_INT",	/* 0-2 */
+		"USR0", "USR1", "USR2", "USR3", "", "", "USR4",	/* 3-9 */
+		"EEPROM_WP",					/* 10 */
+		"CSI2_CAMERA_GPIO1", "CSI2_CAMERA_GPIO2",	/* 11-12 */
+		"CC1352P7_BOOT", "CC1352P7_RSTN", "", "", "",	/* 13-17 */
+		"USR_BUTTON", "", "", "", "", "", "", "", "",	/* 18-26 */
+		"", "", "", "", "", "", "", "", "", "HDMI_INT",	/* 27-36 */
+		"", "VDD_WLAN_EN", "", "", "WL_IRQ", "GBE_INTN",/* 37-42 */
+		"", "", "", "", "", "", "", "", "", "", "", "",	/* 43-54 */
+		"", "", "", "", "", "", "", "", "", "", "", "", /* 55-66 */
+		"", "", "", "", "", "", "", "", "", "", "", "", /* 67-78 */
+		"", "", "", "", "", "",				/* 79-84 */
+		"BITBANG_MDIO_DATA", "BITBANG_MDIO_CLK",	/* 85-86 */
+		"", "", "", "", "";				/* 87-91 */
+};
+
+&main_gpio1 {
+	bootph-all;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mikrobus_gpio_pins_default>;
+	gpio-line-names = "", "", "", "", "",			/* 0-4 */
+		"SPE_RSTN", "SPE_INTN", "MIKROBUS_GPIO1_7",	/* 5-7 */
+		"MIKROBUS_GPIO1_8", "MIKROBUS_GPIO1_9",		/* 8-9 */
+		"MIKROBUS_GPIO1_10", "MIKROBUS_GPIO1_11",	/* 10-11 */
+		"MIKROBUS_GPIO1_12", "MIKROBUS_W1_GPIO0",	/* 12-13 */
+		"MIKROBUS_GPIO1_14",				/* 14 */
+		"", "", "", "", "VDD_3V3_SD", "", "",		/* 15-21 */
+		"MIKROBUS_GPIO1_22", "MIKROBUS_GPIO1_23",	/* 22-23 */
+		"MIKROBUS_GPIO1_24", "MIKROBUS_GPIO1_25",	/* 24-25 */
+		"", "", "", "", "", "", "", "", "", "", "", "",	/* 26-37 */
+		"", "", "", "", "", "", "", "", "", "",		/* 38-47 */
+		"SD_CD", "SD_VOLT_SEL", "", "";			/* 48-51 */
+};
+
+&mcu_gpio0 {
+	gpio-line-names = "", "", "", "",			/* 0-3 */
+		"", "", "", "",					/* 4-7 */
+		"", "", "", "",					/* 8-11 */
+		"", "", "", "",					/* 12-15 */
+		"", "QWIIC_I2C0_SCL", "QWIIC_I2C0_SDA", "",	/* 16-19 */
+		"", "", "", "";					/* 20-23 */
+};
+
+&main_i2c0 {
+	bootph-all;
+	pinctrl-names = "default";
+	pinctrl-0 = <&local_i2c_pins_default>;
+	clock-frequency = <400000>;
+	status = "okay";
+
+	eeprom@50 {
+		compatible = "atmel,24c32";
+		reg = <0x50>;
+	};
+
+	rtc: rtc@68 {
+		compatible = "ti,bq32000";
+		reg = <0x68>;
+		interrupt-parent = <&main_gpio0>;
+		interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+	};
+
+	tps65219: pmic@30 {
+		bootph-all;
+		compatible = "ti,tps65219";
+		reg = <0x30>;
+		buck1-supply = <&vsys_5v0>;
+		buck2-supply = <&vsys_5v0>;
+		buck3-supply = <&vsys_5v0>;
+		ldo1-supply = <&vdd_3v3>;
+		ldo2-supply = <&buck2_reg>;
+		ldo3-supply = <&vdd_3v3>;
+		ldo4-supply = <&vdd_3v3>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_irq_pins_default>;
+		interrupt-parent = <&gic500>;
+		interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+
+		system-power-controller;
+		ti,power-button;
+
+		regulators {
+			buck1_reg: buck1 {
+				regulator-name = "VDD_CORE";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck2_reg: buck2 {
+				regulator-name = "VDD_1V8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck3_reg: buck3 {
+				regulator-name = "VDD_1V2";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo1_reg: ldo1 {
+				/*
+				 * Regulator is left as is unused, vdd_sd
+				 * is controlled via GPIO with bypass config
+				 * as per the NVM configuration
+				 */
+				regulator-name = "VDD_SD_3V3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-allow-bypass;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo2_reg: ldo2 {
+				regulator-name = "VDDA_0V85";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo3_reg: ldo3 {
+				regulator-name = "VDDA_1V8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo4_reg: ldo4 {
+				regulator-name = "VDD_2V5";
+				regulator-min-microvolt = <2500000>;
+				regulator-max-microvolt = <2500000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&main_i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&grove_pins_default>;
+	clock-frequency = <100000>;
+	status = "okay";
+	symlink = "play/grove/i2c";
+};
+
+&main_i2c2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&i2c2_1v8_pins_default>;
+	clock-frequency = <100000>;
+	status = "okay";
+
+	it66121hdmitx: hdmitx@4c {
+		compatible = "ite,it66121";
+		reg = <0x4c>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&hdmi_gpio_pins_default>;
+		vcn33-supply = <&vdd_3v3>;
+		vcn18-supply = <&buck2_reg>;
+		vrf12-supply = <&buck3_reg>;
+		reset-gpios = <&main_gpio0 21 GPIO_ACTIVE_LOW>;
+		interrupt-parent = <&main_gpio0>;
+		interrupts = <36 IRQ_TYPE_EDGE_FALLING>;
+		#sound-dai-cells = <0>;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				it66121hdmitx_in: endpoint {
+					bus-width = <24>;
+					remote-endpoint = <&dpi1_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				it66121hdmitx_out: endpoint {
+					remote-endpoint = <&hdmi_connector_in>;
+				};
+			};
+		};
+	};
+};
+
+&main_i2c3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mikrobus_i2c_pins_default>;
+	clock-frequency = <400000>;
+	status = "okay";
+	symlink = "play/mikrobus/i2c";
+};
+
+&main_spi2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mikrobus_spi_pins_default>;
+	status = "okay";
+	symlink = "play/mikrobus/spi";
+};
+
+&mcasp0 {
+	status = "disabled";
+};
+
+&mcasp2 {
+	status = "disabled";
+};
+
+&sdhci0 {
+	bootph-all;
+	pinctrl-names = "default";
+	pinctrl-0 = <&emmc_pins_default>;
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
+	status = "okay";
+};
+
+&sdhci1 {
+	/* SD/MMC */
+	bootph-all;
+	pinctrl-names = "default";
+	pinctrl-0 = <&sd_pins_default>;
+
+	vmmc-supply = <&vdd_3v3_sd>;
+	vqmmc-supply = <&vdd_sd_dv>;
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
+	cd-gpios = <&main_gpio1 48 GPIO_ACTIVE_LOW>;
+	cd-debounce-delay-ms = <100>;
+	ti,fails-without-test-cd;
+	status = "okay";
+};
+
+&sdhci2 {
+	vmmc-supply = <&wlan_en>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&wifi_pins_default>, <&wifi_32k_clk>;
+	bus-width = <4>;
+	non-removable;
+	ti,fails-without-test-cd;
+	cap-power-off-card;
+	keep-power-in-suspend;
+	ti,driver-strength-ohm = <50>;
+	assigned-clocks = <&k3_clks 157 158>;
+	assigned-clock-parents = <&k3_clks 157 160>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1807";
+		reg = <2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wifi_wlirq_pins_default>;
+		interrupt-parent = <&main_gpio0>;
+		interrupts = <41 IRQ_TYPE_EDGE_FALLING>;
+	};
+};
+
+&main_uart0 {
+	bootph-all;
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_uart0_pins_default>;
+	status = "okay";
+};
+
+&main_uart1 {
+	/* Main UART1 is used by TIFS firmware */
+	status = "reserved";
+};
+
+&main_uart5 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mikrobus_uart_pins_default>;
+	status = "okay";
+	symlink = "play/mikrobus/uart";
+};
+
+&main_uart6 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&wifi_debug_uart_pins_default>;
+	status = "okay";
+	symlink = "play/cc1352/uart";
+
+	mcu {
+		status = "okay";
+		compatible = "ti,cc1352p7";
+		reset-gpios = <&main_gpio0 72 GPIO_ACTIVE_LOW>;
+		vdds-supply = <&vdd_3v3>;
+	};
+};
+
+&dss {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&hdmi_pins_default>;
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* VP2: DPI Output */
+	port@1 {
+		reg = <1>;
+
+		dpi1_out: endpoint {
+			remote-endpoint = <&it66121hdmitx_in>;
+		};
+	};
+};
+
+&mcasp1 {
+	status = "okay";
+	#sound-dai-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcasp_hdmi_pins_default>;
+
+	op-mode = <0>;          /* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+	serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+	       1 0 0 0
+	       0 0 0 0
+	       0 0 0 0
+	       0 0 0 0
+	>;
+	tx-num-evt = <32>;
+	rx-num-evt = <32>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-beagleplay-lincolntech-lcd185-panel.dtso b/arch/arm64/boot/dts/ti/k3-am625-beagleplay-lincolntech-lcd185-panel.dtso
--- a/arch/arm64/boot/dts/ti/k3-am625-beagleplay-lincolntech-lcd185-panel.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-beagleplay-lincolntech-lcd185-panel.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * Lincoln tech Solutions OLDI panel (LCD185-101CT) and touch DT overlay for AM625-BeaglePlay
+ *
+ * AM625-BeaglePlay: https://www.beagleboard.org/boards/beagleplay
+ * Panel datasheet: https://lincolntechsolutions.com/wp-content/uploads/2023/04/LCD185-101CTL1ARNTT_DS_R1.3.pdf
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&{/} {
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&backlight_pins_default>;
+		brightness-levels = <0 4 8 16 32 64 128 255>;
+		default-brightness-level = <6>;
+		enable-gpios = <&main_gpio0 0 GPIO_ACTIVE_HIGH>;
+		pwms = <&epwm0 1 20000 0>;
+	};
+
+	lcd {
+		compatible = "lincolntech,lcd185-101ct";
+		backlight = <&backlight>;
+		/*
+		* Note that the OLDI TX 0 transmits the odd set of pixels
+		* while the OLDI TX 1 transmits the even set. This is a
+		* fixed configuration in the IP integration and is not
+		* changeable. The properties, "dual-lvds-odd-pixels" and
+		* "dual-lvds-even-pixels" have been used to merely
+		* identify if a Dual Link configuration is required.
+		* But swapping them will cause an error in the dss driver.
+		*/
+		port@0 {
+			dual-lvds-odd-pixels;
+			lcd_in0: endpoint {
+				remote-endpoint = <&oldi_out0>;
+			};
+		};
+		port@1 {
+			dual-lvds-even-pixels;
+			lcd_in1: endpoint {
+				remote-endpoint = <&oldi_out1>;
+			};
+		};
+	};
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* VP1: LVDS Output (OLDI TX 0) */
+	port@0 {
+		reg = <0>;
+		oldi_out0: endpoint {
+			remote-endpoint = <&lcd_in0>;
+		};
+	};
+
+	/* VP1: LVDS Output (OLDI TX 1) */
+	port@2 {
+		reg = <2>;
+		oldi_out1: endpoint {
+			remote-endpoint = <&lcd_in1>;
+		};
+	};
+};
+
+&main_i2c2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	eeprom@57 {
+		compatible = "atmel,24c256";
+		reg = <0x57>;
+	};
+
+	touchscreen@5d {
+		compatible = "goodix,gt928";
+		reg = <0x5d>;
+		pinctrl-names = "default";
+	        pinctrl-0 = <&touchscreen_pins_default>;
+		interrupt-parent = <&main_gpio0>;
+		interrupts = <39 IRQ_TYPE_EDGE_FALLING>;
+		irq-gpios = <&main_gpio0 39 GPIO_ACTIVE_LOW>;
+		reset-gpios = <&main_gpio1 15 GPIO_ACTIVE_HIGH>;
+		touchscreen-size-x = <1920>;
+		touchscreen-size-y = <1200>;
+	};
+};
+
+&epwm0 {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625.dtsi b/arch/arm64/boot/dts/ti/k3-am625.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am625.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -48,6 +48,8 @@
 			d-cache-line-size = <64>;
 			d-cache-sets = <128>;
 			next-level-cache = <&L2_0>;
+			operating-points-v2 = <&a53_opp_table>;
+			clocks = <&k3_clks 135 0>;
 		};
 
 		cpu1: cpu@1 {
@@ -62,6 +64,8 @@
 			d-cache-line-size = <64>;
 			d-cache-sets = <128>;
 			next-level-cache = <&L2_0>;
+			operating-points-v2 = <&a53_opp_table>;
+			clocks = <&k3_clks 136 0>;
 		};
 
 		cpu2: cpu@2 {
@@ -76,6 +80,8 @@
 			d-cache-line-size = <64>;
 			d-cache-sets = <128>;
 			next-level-cache = <&L2_0>;
+			operating-points-v2 = <&a53_opp_table>;
+			clocks = <&k3_clks 137 0>;
 		};
 
 		cpu3: cpu@3 {
@@ -90,11 +96,57 @@
 			d-cache-line-size = <64>;
 			d-cache-sets = <128>;
 			next-level-cache = <&L2_0>;
+			operating-points-v2 = <&a53_opp_table>;
+			clocks = <&k3_clks 138 0>;
+		};
+	};
+
+	a53_opp_table: opp-table {
+		compatible = "operating-points-v2-ti-cpu";
+		opp-shared;
+		syscon = <&wkup_conf>;
+
+		opp-200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+			opp-supported-hw = <0x01 0x0007>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-400000000 {
+			opp-hz = /bits/ 64 <400000000>;
+			opp-supported-hw = <0x01 0x0007>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-supported-hw = <0x01 0x0007>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-supported-hw = <0x01 0x0007>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-supported-hw = <0x01 0x0006>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-1250000000 {
+			opp-hz = /bits/ 64 <1250000000>;
+			opp-supported-hw = <0x01 0x0004>;
+			clock-latency-ns = <6000000>;
+			opp-suspend;
 		};
 	};
 
 	L2_0: l2-cache0 {
 		compatible = "cache";
+		cache-unified;
 		cache-level = <2>;
 		cache-size = <0x80000>;
 		cache-line-size = <64>;
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-sk-dmtimer-pwm.dtso b/arch/arm64/boot/dts/ti/k3-am625-sk-dmtimer-pwm.dtso
--- a/arch/arm64/boot/dts/ti/k3-am625-sk-dmtimer-pwm.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-sk-dmtimer-pwm.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay to enable brightness control for Heartbeat LED
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/leds/common.h>
+#include "k3-pinctrl.h"
+
+&{/} {
+	leds {
+		compatible = "pwm-leds";
+		pinctrl-names;
+		pinctrl-0;
+
+		led-0 {
+			pwms = <&main_pwm7 0 7812500 0>;
+			max-brightness = <255>;
+		};
+	};
+
+	main_pwm7: dmtimer-main-pwm-7 {
+		pinctrl-0 = <&usr_led_pins_default>;
+		pinctrl-names = "default";
+		compatible = "ti,omap-dmtimer-pwm";
+		#pwm-cells = <3>;
+		ti,timers = <&main_timer7>;
+	};
+};
+
+&main_pmx0 {
+	usr_led_pins_default: usr-led-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x244, PIN_OUTPUT, 2) /* (C17) MMC1_SDWP.TIMER_IO7 */
+		>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-sk.dts b/arch/arm64/boot/dts/ti/k3-am625-sk.dts
--- a/arch/arm64/boot/dts/ti/k3-am625-sk.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-sk.dts	2024-01-28 14:01:31.236353764 -0500
@@ -7,28 +7,19 @@
 
 /dts-v1/;
 
-#include <dt-bindings/leds/common.h>
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/net/ti-dp83867.h>
-#include "k3-am625.dtsi"
+#include "k3-am62x-sk-common.dtsi"
 
 / {
 	compatible = "ti,am625-sk", "ti,am625";
 	model = "Texas Instruments AM625 SK";
 
-	aliases {
-		serial2 = &main_uart0;
-		mmc0 = &sdhci0;
-		mmc1 = &sdhci1;
-		mmc2 = &sdhci2;
-		spi0 = &ospi0;
-		ethernet0 = &cpsw_port1;
-		ethernet1 = &cpsw_port2;
-	};
-
-	chosen {
-		stdout-path = "serial2:115200n8";
-		bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000";
+	opp-table {
+		/* Add 1.4GHz OPP for am625-sk board. Requires VDD_CORE to be at 0.85V */
+		opp-1400000000 {
+			opp-hz = /bits/ 64 <1400000000>;
+			opp-supported-hw = <0x01 0x0004>;
+			clock-latency-ns = <6000000>;
+		};
 	};
 
 	memory@80000000 {
@@ -38,41 +29,9 @@
 
 	};
 
-	reserved-memory {
-		#address-cells = <2>;
-		#size-cells = <2>;
-		ranges;
-
-		ramoops@9ca00000 {
-			compatible = "ramoops";
-			reg = <0x00 0x9ca00000 0x00 0x00100000>;
-			record-size = <0x8000>;
-			console-size = <0x8000>;
-			ftrace-size = <0x00>;
-			pmsg-size = <0x8000>;
-		};
-
-		secure_tfa_ddr: tfa@9e780000 {
-			reg = <0x00 0x9e780000 0x00 0x80000>;
-			alignment = <0x1000>;
-			no-map;
-		};
-
-		secure_ddr: optee@9e800000 {
-			reg = <0x00 0x9e800000 0x00 0x01800000>; /* for OP-TEE */
-			alignment = <0x1000>;
-			no-map;
-		};
-
-		wkup_r5fss0_core0_dma_memory_region: r5f-dma-memory@9db00000 {
-			compatible = "shared-dma-pool";
-			reg = <0x00 0x9db00000 0x00 0xc00000>;
-			no-map;
-		};
-	};
-
 	vmain_pd: regulator-0 {
 		/* TPS65988 PD CONTROLLER OUTPUT */
+		bootph-all;
 		compatible = "regulator-fixed";
 		regulator-name = "vmain_pd";
 		regulator-min-microvolt = <5000000>;
@@ -83,6 +42,7 @@
 
 	vcc_5v0: regulator-1 {
 		/* Output of LM34936 */
+		bootph-all;
 		compatible = "regulator-fixed";
 		regulator-name = "vcc_5v0";
 		regulator-min-microvolt = <5000000>;
@@ -94,6 +54,7 @@
 
 	vcc_3v3_sys: regulator-2 {
 		/* output of LM61460-Q1 */
+		bootph-all;
 		compatible = "regulator-fixed";
 		regulator-name = "vcc_3v3_sys";
 		regulator-min-microvolt = <3300000>;
@@ -105,6 +66,7 @@
 
 	vdd_mmc1: regulator-3 {
 		/* TPS22918DBVR */
+		bootph-all;
 		compatible = "regulator-fixed";
 		regulator-name = "vdd_mmc1";
 		regulator-min-microvolt = <3300000>;
@@ -117,6 +79,7 @@
 
 	vdd_sd_dv: regulator-4 {
 		/* Output of TLV71033 */
+		bootph-all;
 		compatible = "regulator-gpio";
 		regulator-name = "tlv71033";
 		pinctrl-names = "default";
@@ -130,107 +93,51 @@
 			 <3300000 0x1>;
 	};
 
-	leds {
-		compatible = "gpio-leds";
-		pinctrl-names = "default";
-		pinctrl-0 = <&usr_led_pins_default>;
-
-		led-0 {
-			label = "am62-sk:green:heartbeat";
-			gpios = <&main_gpio1 49 GPIO_ACTIVE_HIGH>;
-			linux,default-trigger = "heartbeat";
-			function = LED_FUNCTION_HEARTBEAT;
-			default-state = "off";
-		};
-	};
-};
-
-&main_pmx0 {
-	main_uart0_pins_default: main-uart0-pins-default {
-		pinctrl-single,pins = <
-			AM62X_IOPAD(0x1c8, PIN_INPUT, 0) /* (D14) UART0_RXD */
-			AM62X_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14) UART0_TXD */
-		>;
-	};
-
-	main_i2c0_pins_default: main-i2c0-pins-default {
-		pinctrl-single,pins = <
-			AM62X_IOPAD(0x1e0, PIN_INPUT_PULLUP, 0) /* (B16) I2C0_SCL */
-			AM62X_IOPAD(0x1e4, PIN_INPUT_PULLUP, 0) /* (A16) I2C0_SDA */
-		>;
-	};
-
-	main_i2c1_pins_default: main-i2c1-pins-default {
-		pinctrl-single,pins = <
-			AM62X_IOPAD(0x1e8, PIN_INPUT_PULLUP, 0) /* (B17) I2C1_SCL */
-			AM62X_IOPAD(0x1ec, PIN_INPUT_PULLUP, 0) /* (A17) I2C1_SDA */
-		>;
-	};
-
-	main_i2c2_pins_default: main-i2c2-pins-default {
-		pinctrl-single,pins = <
-			AM62X_IOPAD(0x0b0, PIN_INPUT_PULLUP, 1) /* (K22) GPMC0_CSn2.I2C2_SCL */
-			AM62X_IOPAD(0x0b4, PIN_INPUT_PULLUP, 1) /* (K24) GPMC0_CSn3.I2C2_SDA */
-		>;
-	};
-
-	main_mmc0_pins_default: main-mmc0-pins-default {
-		pinctrl-single,pins = <
-			AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (Y3) MMC0_CMD */
-			AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (AB1) MMC0_CLK */
-			AM62X_IOPAD(0x214, PIN_INPUT, 0) /* (AA2) MMC0_DAT0 */
-			AM62X_IOPAD(0x210, PIN_INPUT, 0) /* (AA1) MMC0_DAT1 */
-			AM62X_IOPAD(0x20c, PIN_INPUT, 0) /* (AA3) MMC0_DAT2 */
-			AM62X_IOPAD(0x208, PIN_INPUT, 0) /* (Y4) MMC0_DAT3 */
-			AM62X_IOPAD(0x204, PIN_INPUT, 0) /* (AB2) MMC0_DAT4 */
-			AM62X_IOPAD(0x200, PIN_INPUT, 0) /* (AC1) MMC0_DAT5 */
-			AM62X_IOPAD(0x1fc, PIN_INPUT, 0) /* (AD2) MMC0_DAT6 */
-			AM62X_IOPAD(0x1f8, PIN_INPUT, 0) /* (AC2) MMC0_DAT7 */
-		>;
-	};
-
-	main_mmc1_pins_default: main-mmc1-pins-default {
-		pinctrl-single,pins = <
-			AM62X_IOPAD(0x23c, PIN_INPUT, 0) /* (A21) MMC1_CMD */
-			AM62X_IOPAD(0x234, PIN_INPUT, 0) /* (B22) MMC1_CLK */
-			AM62X_IOPAD(0x230, PIN_INPUT, 0) /* (A22) MMC1_DAT0 */
-			AM62X_IOPAD(0x22c, PIN_INPUT, 0) /* (B21) MMC1_DAT1 */
-			AM62X_IOPAD(0x228, PIN_INPUT, 0) /* (C21) MMC1_DAT2 */
-			AM62X_IOPAD(0x224, PIN_INPUT, 0) /* (D22) MMC1_DAT3 */
-			AM62X_IOPAD(0x240, PIN_INPUT, 0) /* (D17) MMC1_SDCD */
-		>;
+	vcc_1v8: regulator-5 {
+		/* output of TPS6282518DMQ */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_1v8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&vcc_3v3_sys>;
+		regulator-always-on;
+		regulator-boot-on;
 	};
 
-	usr_led_pins_default: usr-led-pins-default {
-		pinctrl-single,pins = <
-			AM62X_IOPAD(0x244, PIN_OUTPUT, 7) /* (C17) MMC1_SDWP.GPIO1_49 */
-		>;
+	wlan_lten: regulator-6 {
+		compatible = "regulator-fixed";
+		regulator-name = "wlan_lten";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vcc_3v3_sys>;
+		gpios = <&exp1 11 GPIO_ACTIVE_LOW>;
 	};
 
-	main_mdio1_pins_default: main-mdio1-pins-default {
-		pinctrl-single,pins = <
-			AM62X_IOPAD(0x160, PIN_OUTPUT, 0) /* (AD24) MDIO0_MDC */
-			AM62X_IOPAD(0x15c, PIN_INPUT, 0) /* (AB22) MDIO0_MDIO */
-		>;
+	wlan_en: regulator-7 {
+		compatible = "regulator-fixed";
+		regulator-name = "wlan_en";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		vin-supply = <&wlan_lten>;
+		enable-active-high;
+		gpios = <&main_gpio0 71 GPIO_ACTIVE_HIGH>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wlan_en_pins_default>;
 	};
 
-	main_rgmii1_pins_default: main-rgmii1-pins-default {
-		pinctrl-single,pins = <
-			AM62X_IOPAD(0x14c, PIN_INPUT, 0) /* (AB17) RGMII1_RD0 */
-			AM62X_IOPAD(0x150, PIN_INPUT, 0) /* (AC17) RGMII1_RD1 */
-			AM62X_IOPAD(0x154, PIN_INPUT, 0) /* (AB16) RGMII1_RD2 */
-			AM62X_IOPAD(0x158, PIN_INPUT, 0) /* (AA15) RGMII1_RD3 */
-			AM62X_IOPAD(0x148, PIN_INPUT, 0) /* (AD17) RGMII1_RXC */
-			AM62X_IOPAD(0x144, PIN_INPUT, 0) /* (AE17) RGMII1_RX_CTL */
-			AM62X_IOPAD(0x134, PIN_OUTPUT, 0) /* (AE20) RGMII1_TD0 */
-			AM62X_IOPAD(0x138, PIN_OUTPUT, 0) /* (AD20) RGMII1_TD1 */
-			AM62X_IOPAD(0x13c, PIN_OUTPUT, 0) /* (AE18) RGMII1_TD2 */
-			AM62X_IOPAD(0x140, PIN_OUTPUT, 0) /* (AD18) RGMII1_TD3 */
-			AM62X_IOPAD(0x130, PIN_OUTPUT, 0) /* (AE19) RGMII1_TXC */
-			AM62X_IOPAD(0x12c, PIN_OUTPUT, 0) /* (AD19) RGMII1_TX_CTL */
-		>;
+	vdd_core: regulator-8 {
+		/* output of TPS62826DMQ */
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_core";
+		regulator-min-microvolt = <850000>;
+		regulator-max-microvolt = <850000>;
+		vin-supply = <&vcc_3v3_sys>;
+		regulator-always-on;
+		regulator-boot-on;
 	};
+};
 
+&main_pmx0 {
 	main_rgmii2_pins_default: main-rgmii2-pins-default {
 		pinctrl-single,pins = <
 			AM62X_IOPAD(0x184, PIN_INPUT, 0) /* (AE23) RGMII2_RD0 */
@@ -275,67 +182,35 @@
 			AM62X_IOPAD(0x01d4, PIN_INPUT, 7) /* (B15) UART0_RTSn.GPIO1_23 */
 		>;
 	};
-};
-
-&wkup_uart0 {
-	/* WKUP UART0 is used by DM firmware */
-	status = "reserved";
-};
-
-&mcu_uart0 {
-	status = "disabled";
-};
 
-&main_uart0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&main_uart0_pins_default>;
-};
-
-&main_uart1 {
-	/* Main UART1 is used by TIFS firmware */
-	status = "reserved";
-};
-
-&main_uart2 {
-	status = "disabled";
-};
-
-&main_uart3 {
-	status = "disabled";
-};
-
-&main_uart4 {
-	status = "disabled";
-};
-
-&main_uart5 {
-	status = "disabled";
-};
-
-&main_uart6 {
-	status = "disabled";
-};
-
-&mcu_i2c0 {
-	status = "disabled";
-};
+	wlan_en_pins_default: wlan-en-pins-default {
+		pinctrl-single,pins = <
+				AM62X_IOPAD(0x124, PIN_OUTPUT, 7) /* (A23) MMC2_SDCD.GPIO0_71 */
+		>;
+	};
 
-&wkup_i2c0 {
-	status = "disabled";
-};
+	main_mmc2_pins_default: main-mmc2-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x120, PIN_INPUT, 0) /* (C24) MMC2_CMD */
+			AM62X_IOPAD(0x118, PIN_INPUT, 0) /* (D25) MMC2_CLK */
+			AM62X_IOPAD(0x114, PIN_INPUT, 0) /* (B24) MMC2_DAT0 */
+			AM62X_IOPAD(0x110, PIN_INPUT, 0) /* (C25) MMC2_DAT1 */
+			AM62X_IOPAD(0x10c, PIN_INPUT, 0) /* (E23) MMC2_DAT2 */
+			AM62X_IOPAD(0x108, PIN_INPUT, 0) /* (D24) MMC2_DAT3 */
+			AM62X_IOPAD(0x11c, PIN_INPUT, 0) /* (#N/A) MMC2_CLKB */
+		>;
+	};
 
-&main_i2c0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&main_i2c0_pins_default>;
-	clock-frequency = <400000>;
+	main_wlirq_pins_default: main-wlirq-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x128, PIN_INPUT, 7) /* (B23) MMC2_SDWP.GPIO0_72 */
+		>;
+	};
 };
 
 &main_i2c1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&main_i2c1_pins_default>;
-	clock-frequency = <400000>;
-
 	exp1: gpio@22 {
+		bootph-all;
 		compatible = "ti,tca6424";
 		reg = <0x22>;
 		gpio-controller;
@@ -348,7 +223,7 @@
 				   "UART1_FET_BUF_EN", "WL_LT_EN",
 				   "GPIO_HDMI_RSTn", "CSI_GPIO1",
 				   "CSI_GPIO2", "PRU_3V3_EN",
-				   "HDMI_INTn", "TEST_GPIO2",
+				   "HDMI_INTn", "PD_I2C_IRQ",
 				   "MCASP1_FET_EN", "MCASP1_BUF_BT_EN",
 				   "MCASP1_FET_SEL", "UART1_FET_SEL",
 				   "TSINT#", "IO_EXP_TEST_LED";
@@ -363,41 +238,46 @@
 	};
 };
 
-&main_i2c2 {
-	status = "disabled";
-};
-
-&main_i2c3 {
-	status = "disabled";
-};
-
-&sdhci0 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&main_mmc0_pins_default>;
-	ti,driver-strength-ohm = <50>;
-	disable-wp;
-};
-
 &sdhci1 {
-	/* SD/MMC */
 	vmmc-supply = <&vdd_mmc1>;
 	vqmmc-supply = <&vdd_sd_dv>;
+};
+
+&sdhci2 {
+	status = "okay";
+	vmmc-supply = <&wlan_en>;
 	pinctrl-names = "default";
-	pinctrl-0 = <&main_mmc1_pins_default>;
+	pinctrl-0 = <&main_mmc2_pins_default>;
+	bus-width = <4>;
+	non-removable;
+	ti,fails-without-test-cd;
+	cap-power-off-card;
+	keep-power-in-suspend;
 	ti,driver-strength-ohm = <50>;
-	disable-wp;
+	assigned-clocks = <&k3_clks 157 158>;
+	assigned-clock-parents = <&k3_clks 157 160>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+	wlcore: wlcore@2 {
+		compatible = "ti,wl1837";
+		reg = <2>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&main_wlirq_pins_default>;
+		interrupt-parent = <&main_gpio0>;
+		interrupts = <72 IRQ_TYPE_EDGE_RISING>;
+	};
 };
 
 &cpsw3g {
 	pinctrl-names = "default";
-	pinctrl-0 = <&main_mdio1_pins_default
-		     &main_rgmii1_pins_default
+	pinctrl-0 = <&main_rgmii1_pins_default
 		     &main_rgmii2_pins_default>;
-};
 
-&cpsw_port1 {
-	phy-mode = "rgmii-rxid";
-	phy-handle = <&cpsw3g_phy0>;
+	cpts@3d000 {
+		/* MAP HW3_TS_PUSH to GENF1 */
+		ti,pps = <2 1>;
+	};
 };
 
 &cpsw_port2 {
@@ -406,13 +286,6 @@
 };
 
 &cpsw3g_mdio {
-	cpsw3g_phy0: ethernet-phy@0 {
-		reg = <0>;
-		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
-		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
-		ti,min-output-impedance;
-	};
-
 	cpsw3g_phy1: ethernet-phy@1 {
 		reg = <1>;
 		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
@@ -429,6 +302,8 @@
 };
 
 &ospi0 {
+	bootph-all;
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&ospi0_pins_default>;
 
@@ -445,6 +320,7 @@
 		cdns,read-delay = <4>;
 
 		partitions {
+			bootph-all;
 			compatible = "fixed-partitions";
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -480,6 +356,7 @@
 			};
 
 			partition@3fc0000 {
+				bootph-pre-ram;
 				label = "ospi.phypattern";
 				reg = <0x3fc0000 0x40000>;
 			};
@@ -487,30 +364,22 @@
 	};
 };
 
-&ecap0 {
-	status = "disabled";
-};
-
-&ecap1 {
-	status = "disabled";
-};
-
-&ecap2 {
-	status = "disabled";
-};
-
-&main_mcan0 {
-	status = "disabled";
+&tlv320aic3106 {
+	DVDD-supply = <&vcc_1v8>;
 };
 
-&epwm0 {
-	status = "disabled";
-};
+#define K3_TS_OFFSET(pa, val)	(0x4+(pa)*4) (0x10000 | val)
 
-&epwm1 {
-	status = "disabled";
-};
+&timesync_router {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpsw_cpts>;
 
-&epwm2 {
-	status = "disabled";
+	/* Use Time Sync Router to map GENF1 input to HW3_TS_PUSH output */
+	cpsw_cpts: cpsw-cpts {
+		pinctrl-single,pins = <
+			/* pps [cpsw cpts genf1] in17 -> out12 [cpsw cpts hw3_push] */
+			K3_TS_OFFSET(12, 17)
+			>;
+	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-sk-ecap-capture.dtso b/arch/arm64/boot/dts/ti/k3-am625-sk-ecap-capture.dtso
--- a/arch/arm64/boot/dts/ti/k3-am625-sk-ecap-capture.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-sk-ecap-capture.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay for enabling ECAP capture mode on AM625-SK board.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+	main_ecap2_capture_pins_default: main-ecap2-capture-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01a4, PIN_INPUT, 2) /* (B20) MCASP0_ACLKX.ECAP2_IN_APWM_OUT */
+		>;
+	};
+};
+
+&ecap2 {
+	compatible = "ti,am62-ecap-capture";
+	interrupt-parent = <&gic500>;
+	interrupts = <GIC_SPI 115 IRQ_TYPE_EDGE_RISING>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_ecap2_capture_pins_default>;
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-sk-lincolntech-lcd185-panel.dtso b/arch/arm64/boot/dts/ti/k3-am625-sk-lincolntech-lcd185-panel.dtso
--- a/arch/arm64/boot/dts/ti/k3-am625-sk-lincolntech-lcd185-panel.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-sk-lincolntech-lcd185-panel.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * Lincoln tech Solutions OLDI panel (LCD185-101CT) and touch DT overlay for AM625-SK
+ *
+ * AM625-SKEVM: https://www.ti.com/tool/SK-AM62
+ * Panel datasheet: https://lincolntechsolutions.com/wp-content/uploads/2023/04/LCD185-101CTL1ARNTT_DS_R1.3.pdf
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&{/} {
+	display {
+		compatible = "lincolntech,lcd185-101ct";
+		/*
+		* Note that the OLDI TX 0 transmits the odd set of pixels
+		* while the OLDI TX 1 transmits the even set. This is a
+		* fixed configuration in the IP integration and is not
+		* changeable. The properties, "dual-lvds-odd-pixels" and
+		* "dual-lvds-even-pixels" have been used to merely
+		* identify if a Dual Link configuration is required.
+		* But swapping them will cause an error in the dss driver.
+		*/
+		port@0 {
+			dual-lvds-odd-pixels;
+			lcd_in0: endpoint {
+				remote-endpoint = <&oldi_out0>;
+			};
+		};
+		port@1 {
+			dual-lvds-even-pixels;
+			lcd_in1: endpoint {
+				remote-endpoint = <&oldi_out1>;
+			};
+		};
+	};
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* VP1: LVDS Output (OLDI TX 0) */
+	port@0 {
+		reg = <0>;
+		oldi_out0: endpoint {
+			remote-endpoint = <&lcd_in0>;
+		};
+	};
+
+	/* VP1: LVDS Output (OLDI TX 1) */
+	port@2 {
+		reg = <2>;
+		oldi_out1: endpoint {
+			remote-endpoint = <&lcd_in1>;
+		};
+	};
+};
+
+&main_i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	eeprom@57 {
+		compatible = "atmel,24c256";
+		reg = <0x57>;
+	};
+
+	touchscreen@5d {
+		compatible = "goodix,gt928";
+		reg = <0x5d>;
+		interrupt-parent = <&exp1>;
+		interrupts = <22 IRQ_TYPE_EDGE_FALLING>;
+		irq-gpios = <&exp1 22 GPIO_ACTIVE_LOW>;
+		touchscreen-size-x = <1920>;
+		touchscreen-size-y = <1200>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-sk-mcspi-loopback.dtso b/arch/arm64/boot/dts/ti/k3-am625-sk-mcspi-loopback.dtso
--- a/arch/arm64/boot/dts/ti/k3-am625-sk-mcspi-loopback.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-sk-mcspi-loopback.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,55 @@
+
+
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for using McSPI on the RPi header on AM625-SK board.
+ *
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+	main_spi0_pins_default: main-spi0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01bc, PIN_INPUT, 0) /* (A14) SPI0_CLK */
+			AM62X_IOPAD(0x01c0, PIN_INPUT, 0) /* (B13) SPI0_D0 */
+			AM62X_IOPAD(0x01c4, PIN_INPUT, 0) /* (B14) SPI0_D1 */
+			AM62X_IOPAD(0x01b4, PIN_INPUT, 0) /* (A13) SPI0_CS0 */
+		>;
+	};
+};
+
+&main_i2c1 {
+	gpio@22 {
+		en_rpi_3v3 {
+			gpio-hog;
+			gpios = <5 GPIO_ACTIVE_HIGH>;
+			output-high;
+			line-name = "EXP_PS_3V3_EN";
+		};
+	};
+};
+
+&main_spi0 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-0 = <&main_spi0_pins_default>;
+	pinctrl-names = "default";
+	spidev@0 {
+		/*
+		 * Using spidev compatible is warned loudly,
+		 * thus use another equivalent compatible id
+		 * from spidev.
+		 */
+		compatible = "rohm,dh2228fv";
+		spi-max-frequency = <24000000>;
+		reg = <0>;
+	};
+};
+
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-sk-microtips-mf101hie-panel.dtso b/arch/arm64/boot/dts/ti/k3-am625-sk-microtips-mf101hie-panel.dtso
--- a/arch/arm64/boot/dts/ti/k3-am625-sk-microtips-mf101hie-panel.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-sk-microtips-mf101hie-panel.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * Microtips integrated OLDI panel (MF-101HIEBCAF0) and touch DT overlay for AM625 - SK
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	display {
+		compatible = "microtips,mf-101hiebcaf0";
+		/*
+		* Note that the OLDI TX 0 transmits the odd set of pixels
+		* while the OLDI TX 1 transmits the even set. This is a
+		* fixed configuration in the IP integration and is not
+		* changeable. The properties, "dual-lvds-odd-pixels" and
+		* "dual-lvds-even-pixels" have been used to merely
+		* identify if a Dual Link configuration is required.
+		* Swapping them will not make any difference.
+		*/
+		port@0 {
+			dual-lvds-odd-pixels;
+			lcd_in0: endpoint {
+				remote-endpoint = <&oldi_out0>;
+			};
+		};
+		port@1 {
+			dual-lvds-even-pixels;
+			lcd_in1: endpoint {
+				remote-endpoint = <&oldi_out1>;
+			};
+		};
+	};
+};
+
+&main_pmx0 {
+	main_oldi0_pins_default: main-oldi0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0260, PIN_OUTPUT, 0) /* (AA5) OLDI0_A0N */
+			AM62X_IOPAD(0x025c, PIN_OUTPUT, 0) /* (Y6) OLDI0_A0P */
+			AM62X_IOPAD(0x0268, PIN_OUTPUT, 0) /* (AD3) OLDI0_A1N */
+			AM62X_IOPAD(0x0264, PIN_OUTPUT, 0) /* (AB4) OLDI0_A1P */
+			AM62X_IOPAD(0x0270, PIN_OUTPUT, 0) /* (Y8) OLDI0_A2N */
+			AM62X_IOPAD(0x026c, PIN_OUTPUT, 0) /* (AA8) OLDI0_A2P */
+			AM62X_IOPAD(0x0278, PIN_OUTPUT, 0) /* (AB6) OLDI0_A3N */
+			AM62X_IOPAD(0x0274, PIN_OUTPUT, 0) /* (AA7) OLDI0_A3P */
+			AM62X_IOPAD(0x0280, PIN_OUTPUT, 0) /* (AC6) OLDI0_A4N */
+			AM62X_IOPAD(0x027c, PIN_OUTPUT, 0) /* (AC5) OLDI0_A4P */
+			AM62X_IOPAD(0x0288, PIN_OUTPUT, 0) /* (AE5) OLDI0_A5N */
+			AM62X_IOPAD(0x0284, PIN_OUTPUT, 0) /* (AD6) OLDI0_A5P */
+			AM62X_IOPAD(0x0290, PIN_OUTPUT, 0) /* (AE6) OLDI0_A6N */
+			AM62X_IOPAD(0x028c, PIN_OUTPUT, 0) /* (AD7) OLDI0_A6P */
+			AM62X_IOPAD(0x0298, PIN_OUTPUT, 0) /* (AD8) OLDI0_A7N */
+			AM62X_IOPAD(0x0294, PIN_OUTPUT, 0) /* (AE7) OLDI0_A7P */
+			AM62X_IOPAD(0x02a0, PIN_OUTPUT, 0) /* (AD4) OLDI0_CLK0N */
+			AM62X_IOPAD(0x029c, PIN_OUTPUT, 0) /* (AE3) OLDI0_CLK0P */
+			AM62X_IOPAD(0x02a8, PIN_OUTPUT, 0) /* (AE4) OLDI0_CLK1N */
+			AM62X_IOPAD(0x02a4, PIN_OUTPUT, 0) /* (AD5) OLDI0_CLK1P */
+		>;
+	};
+};
+
+&dss {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_oldi0_pins_default &main_dss0_pins_default>;
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* VP1: LVDS Output (OLDI TX 0) */
+	port@0 {
+		reg = <0>;
+		oldi_out0: endpoint {
+			remote-endpoint = <&lcd_in0>;
+		};
+	};
+
+	/* VP1: LVDS Output (OLDI TX 1) */
+	port@2 {
+		reg = <2>;
+		oldi_out1: endpoint {
+			remote-endpoint = <&lcd_in1>;
+		};
+	};
+};
+
+&main_i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	touchscreen@41 {
+		compatible = "ilitek,ili251x";
+		reg = <0x41>;
+		interrupt-parent = <&exp1>;
+		interrupts = <22 IRQ_TYPE_EDGE_FALLING>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-sk-microtips-mf103hie-lcd2.dtso b/arch/arm64/boot/dts/ti/k3-am625-sk-microtips-mf103hie-lcd2.dtso
--- a/arch/arm64/boot/dts/ti/k3-am625-sk-microtips-mf103hie-lcd2.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-sk-microtips-mf103hie-lcd2.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * Microtips integrated OLDI panel (MF-103HIEB0GA0) (SK-LCD2) DT overlay for AM625-SK and AM62-LP SK
+ *
+ * AM625-SKEVM: https://www.ti.com/tool/SK-AM62
+ * AM62-LP SKEVM: https://www.ti.com/tool/SK-AM62-LP
+ * Panel datasheet: https://simplespec.microtipsusa.com/uploads/spec/datasheetFile/2660/13-103HIEB0GA0-S_V1.0_20211206.pdf
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&{/} {
+	display {
+		compatible = "microtips,mf-103hieb0ga0";
+		/*
+		* Note that the OLDI TX 0 transmits the odd set of pixels
+		* while the OLDI TX 1 transmits the even set. This is a
+		* fixed configuration in the IP integration and is not
+		* changeable. The properties, "dual-lvds-odd-pixels" and
+		* "dual-lvds-even-pixels" have been used to merely
+		* identify if a Dual Link configuration is required.
+		* But swapping them will cause an error in the dss driver.
+		*/
+		port@0 {
+			dual-lvds-odd-pixels;
+			lcd_in0: endpoint {
+				remote-endpoint = <&oldi_out0>;
+			};
+		};
+		port@1 {
+			dual-lvds-even-pixels;
+			lcd_in1: endpoint {
+				remote-endpoint = <&oldi_out1>;
+			};
+		};
+	};
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* VP1: LVDS Output (OLDI TX 0) */
+	port@0 {
+		reg = <0>;
+		oldi_out0: endpoint {
+			remote-endpoint = <&lcd_in0>;
+		};
+	};
+
+	/* VP1: LVDS Output (OLDI TX 1) */
+	port@2 {
+		reg = <2>;
+		oldi_out1: endpoint {
+			remote-endpoint = <&lcd_in1>;
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-sk-pwm.dtso b/arch/arm64/boot/dts/ti/k3-am625-sk-pwm.dtso
--- a/arch/arm64/boot/dts/ti/k3-am625-sk-pwm.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-sk-pwm.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for enabling PWM output on RPi header on AM625-SK board.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+	main_epwm0_pins_default: main-epwm0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01ac, PIN_OUTPUT, 6) /* (E19) MCASP0_AFSR.EHRPWM0_A */
+		>;
+	};
+	main_epwm1_pins_default: main-epwm1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01a0, PIN_OUTPUT, 6) /* (E18) MCASP0_AXR0.EHRPWM1_B */
+		>;
+	};
+	main_ecap1_pins_default: main-ecap1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01a4, PIN_OUTPUT, 2) /* (B20) MCASP0_ACLKX.ECAP2_IN_APWM_OUT */
+		>;
+	};
+};
+
+&main_i2c1 {
+	gpio@22 {
+		fet_sel {
+			gpio-hog;
+			gpios = <21 GPIO_ACTIVE_HIGH>;
+			output-low;
+			line-name = "UART1_FET_SEL";
+		};
+	};
+};
+
+&epwm0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_epwm0_pins_default>;
+	status = "okay";
+};
+
+&epwm1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_epwm1_pins_default>;
+	status = "okay";
+};
+
+&ecap2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_ecap1_pins_default>;
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am625-sk-rpi-hdr-ehrpwm.dtso b/arch/arm64/boot/dts/ti/k3-am625-sk-rpi-hdr-ehrpwm.dtso
--- a/arch/arm64/boot/dts/ti/k3-am625-sk-rpi-hdr-ehrpwm.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am625-sk-rpi-hdr-ehrpwm.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for enabling RPi header with GPIOs and eHRPWMs for AM625-SK
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+	rpi_header_gpio0_pins_default: rpi-header-gpio0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0038, PIN_INPUT, 7) /* (E24) OSPI0_CSn3.GPIO0_14 */
+			AM62X_IOPAD(0x0088, PIN_INPUT, 7) /* (L24) GPMC0_OEn_REn.GPIO0_33 */
+			AM62X_IOPAD(0x0094, PIN_INPUT, 7) /* (N20) GPMC0_BE1n.GPIO0_36 */
+			AM62X_IOPAD(0x009c, PIN_INPUT, 7) /* (V25) GPMC0_WAIT1.GPIO0_38 */
+			AM62X_IOPAD(0x00a0, PIN_INPUT, 7) /* (K25) GPMC0_WPn.GPIO0_39 */
+			AM62X_IOPAD(0x00a4, PIN_INPUT, 7) /* (M22) GPMC0_DIR.GPIO0_40 */
+			AM62X_IOPAD(0x00a8, PIN_INPUT, 7) /* (M21) GPMC0_CSn0.GPIO0_41 */
+			AM62X_IOPAD(0x00ac, PIN_INPUT, 7) /* (L21) GPMC0_CSn1.GPIO0_42 */
+		>;
+	};
+
+	rpi_header_gpio1_pins_default: rpi-header-gpio1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01d0, PIN_INPUT, 7) /* (A15) UART0_CTSn.GPIO1_22 */
+		>;
+	};
+
+	rpi_header_ehrpwm0_pins_default: rpi-header-ehrpwm0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01ac, PIN_OUTPUT, 6) /* (E19) MCASP0_AFSR.EHRPWM0_A */
+			AM62X_IOPAD(0x01b0, PIN_OUTPUT, 6) /* (A20) MCASP0_ACLKR.EHRPWM0_B */
+		>;
+	};
+
+	rpi_header_ehrpwm1_pins_default: rpi-header-ehrpwm1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x019c, PIN_OUTPUT, 6) /* (B18) MCASP0_AXR1.EHRPWM1_A */
+			AM62X_IOPAD(0x01a0, PIN_OUTPUT, 6) /* (E18) MCASP0_AXR0.EHRPWM1_B */
+		>;
+	};
+};
+
+&main_i2c1 {
+	gpio@22 {
+		p05-hog {
+			/* P05 - EXP_PS_3V3_EN */
+			gpio-hog;
+			gpios = <5 GPIO_ACTIVE_HIGH>;
+			output-high;
+			line-name = "EXP_PS_3V3_EN";
+		};
+
+		p06-hog {
+			/* P06 - EXP_PS_5V0_EN */
+			gpio-hog;
+			gpios = <6 GPIO_ACTIVE_HIGH>;
+			output-high;
+			line-name = "EXP_PS_5V0_EN";
+		};
+
+		p25-hog {
+			/* P25 - UART1_FET_SEL */
+			gpio-hog;
+			gpios = <21 GPIO_ACTIVE_HIGH>;
+			output-low;
+			line-name = "UART1_FET_SEL";
+		};
+	};
+};
+
+&mcasp0 {
+	status = "disabled";
+};
+
+&epwm0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm0_pins_default>;
+};
+
+&epwm1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm1_pins_default>;
+};
+
+
+&main_gpio0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio0_pins_default>;
+};
+
+&main_gpio1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio1_pins_default>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a7.dtsi b/arch/arm64/boot/dts/ti/k3-am62a7.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62a7.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62a7.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -48,6 +48,8 @@
 			d-cache-line-size = <64>;
 			d-cache-sets = <128>;
 			next-level-cache = <&L2_0>;
+			operating-points-v2 = <&a53_opp_table>;
+			clocks = <&k3_clks 135 0>;
 		};
 
 		cpu1: cpu@1 {
@@ -62,6 +64,8 @@
 			d-cache-line-size = <64>;
 			d-cache-sets = <128>;
 			next-level-cache = <&L2_0>;
+			operating-points-v2 = <&a53_opp_table>;
+			clocks = <&k3_clks 136 0>;
 		};
 
 		cpu2: cpu@2 {
@@ -76,6 +80,8 @@
 			d-cache-line-size = <64>;
 			d-cache-sets = <128>;
 			next-level-cache = <&L2_0>;
+			operating-points-v2 = <&a53_opp_table>;
+			clocks = <&k3_clks 137 0>;
 		};
 
 		cpu3: cpu@3 {
@@ -90,11 +96,57 @@
 			d-cache-line-size = <64>;
 			d-cache-sets = <128>;
 			next-level-cache = <&L2_0>;
+			operating-points-v2 = <&a53_opp_table>;
+			clocks = <&k3_clks 138 0>;
+		};
+	};
+
+	a53_opp_table: opp-table {
+		compatible = "operating-points-v2-ti-cpu";
+		opp-shared;
+		syscon = <&wkup_conf>;
+
+		opp-200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+			opp-supported-hw = <0x01 0x0007>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-400000000 {
+			opp-hz = /bits/ 64 <400000000>;
+			opp-supported-hw = <0x01 0x0007>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-supported-hw = <0x01 0x0007>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-supported-hw = <0x01 0x0007>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-supported-hw = <0x01 0x0006>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-1250000000 {
+			opp-hz = /bits/ 64 <1250000000>;
+			opp-supported-hw = <0x01 0x0004>;
+			clock-latency-ns = <6000000>;
+			opp-suspend;
 		};
 	};
 
 	L2_0: l2-cache0 {
 		compatible = "cache";
+		cache-unified;
 		cache-level = <2>;
 		cache-size = <0x80000>;
 		cache-line-size = <64>;
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts	2024-01-28 14:01:31.236353764 -0500
@@ -9,6 +9,7 @@
 
 #include <dt-bindings/leds/common.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
 #include "k3-am62a7.dtsi"
 
 / {
@@ -16,8 +17,13 @@
 	model = "Texas Instruments AM62A7 SK";
 
 	aliases {
+		serial0 = &mcu_uart0;
+		serial1 = &wkup_uart0;
 		serial2 = &main_uart0;
+		mmc0 = &sdhci0;
 		mmc1 = &sdhci1;
+		ethernet0 = &cpsw_port1;
+		spi0 = &ospi0;
 	};
 
 	chosen {
@@ -31,11 +37,24 @@
 		      <0x00000008 0x80000000 0x00000000 0x80000000>;
 	};
 
+	dma_buf_phys {
+		compatible = "ti,dma-buf-phys";
+	};
+
 	reserved-memory {
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
 
+		/* global cma region */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x00 0x24000000>;
+			alloc-ranges = <0x00 0xc0000000 0x00 0x24000000>;
+			linux,cma-default;
+		};
+
 		secure_tfa_ddr: tfa@9e780000 {
 			reg = <0x00 0x9e780000 0x00 0x80000>;
 			alignment = <0x1000>;
@@ -48,11 +67,63 @@
 			no-map;
 		};
 
+		wkup_r5fss0_core0_dma_memory_region: r5f-dma-memory@9c800000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9c800000 0x00 0x100000>;
+			no-map;
+		};
+
 		wkup_r5fss0_core0_memory_region: r5f-dma-memory@9c900000 {
 			compatible = "shared-dma-pool";
 			reg = <0x00 0x9c900000 0x00 0x01e00000>;
 			no-map;
 		};
+
+		mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@9b800000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9b800000 0x00 0x100000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core0_memory_region: r5f-dma-memory@9b900000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9b900000 0x00 0x0f00000>;
+			no-map;
+		};
+
+		c7x_0_dma_memory_region: c7x-dma-memory@99800000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x99800000 0x00 0x100000>;
+			no-map;
+		};
+
+		c7x_0_memory_region: c7x-memory@99900000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x99900000 0x00 0x01efffff>;
+			no-map;
+		};
+
+		edgeai_rtos_ipc_memory_region: edgeai-rtos-ipc-memory-region {
+			reg = <0x00 0xa0000000 0x00 0x01000000>;
+			no-map;
+		};
+
+		edgeai_memory_region: edgeai-dma-memory@a1000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa1000000 0x00 0x02000000>;
+			no-map;
+		};
+
+		edgeai_shared_region: edgeai_shared-memories {
+			compatible = "dma-heap-carveout";
+			reg = <0x00 0xa3000000 0x00 0x0b000000>;
+		};
+
+		edgeai_core_heaps: edgeai-core-heap-memory@ae000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xae000000 0x00 0x12000000>;
+			no-map;
+		};
 	};
 
 	vmain_pd: regulator-0 {
@@ -76,10 +147,10 @@
 		regulator-boot-on;
 	};
 
-	vcc_3v3_sys: regulator-2 {
+	vcc_3v3_main: regulator-2 {
 		/* output of LM5141-Q1 */
 		compatible = "regulator-fixed";
-		regulator-name = "vcc_3v3_sys";
+		regulator-name = "vcc_3v3_main";
 		regulator-min-microvolt = <3300000>;
 		regulator-max-microvolt = <3300000>;
 		vin-supply = <&vmain_pd>;
@@ -98,6 +169,31 @@
 		gpio = <&exp1 3 GPIO_ACTIVE_HIGH>;
 	};
 
+	vcc_3v3_sys: regulator-4 {
+		/* output of TPS222965DSGT */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_3v3_sys";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vcc_3v3_main>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vddshv_sdio: regulator-5 {
+		compatible = "regulator-gpio";
+		regulator-name = "vddshv_sdio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&vddshv_sdio_pins_default>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		vin-supply = <&ldo1>;
+		gpios = <&main_gpio0 31 GPIO_ACTIVE_HIGH>;
+		states = <1800000 0x0>,
+			 <3300000 0x1>;
+	};
+
 	leds {
 		compatible = "gpio-leds";
 		pinctrl-names = "default";
@@ -111,6 +207,52 @@
 			default-state = "off";
 		};
 	};
+
+	tlv320_mclk: clk-0 {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <12288000>;
+	};
+
+	codec_audio: sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "AM62Ax-SKEVM";
+		simple-audio-card,widgets =
+			"Headphone",	"Headphone Jack",
+			"Line",		"Line In",
+			"Microphone",	"Microphone Jack";
+		simple-audio-card,routing =
+			"Headphone Jack",	"HPLOUT",
+			"Headphone Jack",	"HPROUT",
+			"LINE1L",		"Line In",
+			"LINE1R",		"Line In",
+			"MIC3R",		"Microphone Jack",
+			"Microphone Jack",	"Mic Bias";
+		simple-audio-card,format = "dsp_b";
+		simple-audio-card,bitclock-master = <&sound_master>;
+		simple-audio-card,frame-master = <&sound_master>;
+		simple-audio-card,bitclock-inversion;
+
+		simple-audio-card,cpu {
+			sound-dai = <&mcasp1>;
+		};
+
+		sound_master: simple-audio-card,codec {
+			sound-dai = <&tlv320aic3106>;
+			clocks = <&tlv320_mclk>;
+		};
+	};
+
+	hdmi: connector {
+		compatible = "hdmi-connector";
+		label = "hdmi";
+		type = "a";
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&sii9022_out>;
+			};
+		};
+	};
 };
 
 &main_pmx0 {
@@ -159,6 +301,137 @@
 			AM62AX_IOPAD(0x244, PIN_OUTPUT, 7) /* (D18) MMC1_SDWP.GPIO1_49 */
 		>;
 	};
+
+	main_usb1_pins_default: main-usb1-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x0258, PIN_OUTPUT, 0) /* (F18) USB1_DRVVBUS */
+		>;
+	};
+
+	main_mdio1_pins_default: main-mdio1-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x160, PIN_OUTPUT, 0) /* (V12) MDIO0_MDC */
+			AM62AX_IOPAD(0x15c, PIN_INPUT, 0) /* (V13) MDIO0_MDIO */
+		>;
+	};
+
+	main_rgmii1_pins_default: main-rgmii1-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x14c, PIN_INPUT, 0) /* (AB16) RGMII1_RD0 */
+			AM62AX_IOPAD(0x150, PIN_INPUT, 0) /* (V15) RGMII1_RD1 */
+			AM62AX_IOPAD(0x154, PIN_INPUT, 0) /* (W15) RGMII1_RD2 */
+			AM62AX_IOPAD(0x158, PIN_INPUT, 0) /* (V14) RGMII1_RD3 */
+			AM62AX_IOPAD(0x148, PIN_INPUT, 0) /* (AA16) RGMII1_RXC */
+			AM62AX_IOPAD(0x144, PIN_INPUT, 0) /* (AA15) RGMII1_RX_CTL */
+			AM62AX_IOPAD(0x134, PIN_INPUT, 0) /* (Y17) RGMII1_TD0 */
+			AM62AX_IOPAD(0x138, PIN_INPUT, 0) /* (V16) RGMII1_TD1 */
+			AM62AX_IOPAD(0x13c, PIN_INPUT, 0) /* (Y16) RGMII1_TD2 */
+			AM62AX_IOPAD(0x140, PIN_INPUT, 0) /* (AA17) RGMII1_TD3 */
+			AM62AX_IOPAD(0x130, PIN_INPUT, 0) /* (AB17) RGMII1_TXC */
+			AM62AX_IOPAD(0x12c, PIN_INPUT, 0) /* (W16) RGMII1_TX_CTL */
+		>;
+	};
+
+	main_mcasp1_pins_default: main-mcasp1-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x090, PIN_INPUT, 2) /* (L19) GPMC0_BE0n_CLE.MCASP1_ACLKX */
+			AM62AX_IOPAD(0x098, PIN_INPUT, 2) /* (R18) GPMC0_WAIT0.MCASP1_AFSX */
+			AM62AX_IOPAD(0x08c, PIN_OUTPUT, 2) /* (K19) GPMC0_WEn.MCASP1_AXR0 */
+			AM62AX_IOPAD(0x084, PIN_INPUT, 2) /* (L18) GPMC0_ADVn_ALE.MCASP1_AXR2 */
+		>;
+	};
+
+	main_gpio1_ioexp_intr_pins_default: main-gpio1-ioexp-intr-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x01d4, PIN_INPUT, 7) /* (C15) UART0_RTSn.GPIO1_23 */
+
+		>;
+	};
+
+	main_dss0_pins_default: main-dss0-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x100, PIN_OUTPUT, 0) /* (V17) VOUT0_VSYNC */
+			AM62AX_IOPAD(0x0f8, PIN_OUTPUT, 0) /* (T18) VOUT0_HSYNC */
+			AM62AX_IOPAD(0x104, PIN_OUTPUT, 0) /* (AA22) VOUT0_PCLK */
+			AM62AX_IOPAD(0x0fc, PIN_OUTPUT, 0) /* (U17) VOUT0_DE */
+			AM62AX_IOPAD(0x0b8, PIN_OUTPUT, 0) /* (U22) VOUT0_DATA0 */
+			AM62AX_IOPAD(0x0bc, PIN_OUTPUT, 0) /* (U21) VOUT0_DATA1 */
+			AM62AX_IOPAD(0x0c0, PIN_OUTPUT, 0) /* (U20) VOUT0_DATA2 */
+			AM62AX_IOPAD(0x0c4, PIN_OUTPUT, 0) /* (U19) VOUT0_DATA3 */
+			AM62AX_IOPAD(0x0c8, PIN_OUTPUT, 0) /* (T19) VOUT0_DATA4 */
+			AM62AX_IOPAD(0x0cc, PIN_OUTPUT, 0) /* (U18) VOUT0_DATA5 */
+			AM62AX_IOPAD(0x0d0, PIN_OUTPUT, 0) /* (V22) VOUT0_DATA6 */
+			AM62AX_IOPAD(0x0d4, PIN_OUTPUT, 0) /* (V21) VOUT0_DATA7 */
+			AM62AX_IOPAD(0x0d8, PIN_OUTPUT, 0) /* (V19) VOUT0_DATA8 */
+			AM62AX_IOPAD(0x0dc, PIN_OUTPUT, 0) /* (V18) VOUT0_DATA9 */
+			AM62AX_IOPAD(0x0e0, PIN_OUTPUT, 0) /* (W22) VOUT0_DATA10 */
+			AM62AX_IOPAD(0x0e4, PIN_OUTPUT, 0) /* (W21) VOUT0_DATA11 */
+			AM62AX_IOPAD(0x0e8, PIN_OUTPUT, 0) /* (W20) VOUT0_DATA12 */
+			AM62AX_IOPAD(0x0ec, PIN_OUTPUT, 0) /* (W19) VOUT0_DATA13 */
+			AM62AX_IOPAD(0x0f0, PIN_OUTPUT, 0) /* (Y21) VOUT0_DATA14 */
+			AM62AX_IOPAD(0x0f4, PIN_OUTPUT, 0) /* (Y22) VOUT0_DATA15 */
+			AM62AX_IOPAD(0x05c, PIN_OUTPUT, 1) /* (P22) GPMC0_AD8.VOUT0_DATA16 */
+			AM62AX_IOPAD(0x060, PIN_OUTPUT, 1) /* (R19) GPMC0_AD9.VOUT0_DATA17 */
+			AM62AX_IOPAD(0x064, PIN_OUTPUT, 1) /* (R20) GPMC0_AD10.VOUT0_DATA18 */
+			AM62AX_IOPAD(0x068, PIN_OUTPUT, 1) /* (R22) GPMC0_AD11.VOUT0_DATA19 */
+			AM62AX_IOPAD(0x06c, PIN_OUTPUT, 1) /* (T22) GPMC0_AD12.VOUT0_DATA20 */
+			AM62AX_IOPAD(0x070, PIN_OUTPUT, 1) /* (R21) GPMC0_AD13.VOUT0_DATA21 */
+			AM62AX_IOPAD(0x074, PIN_OUTPUT, 1) /* (T20) GPMC0_AD14.VOUT0_DATA22 */
+			AM62AX_IOPAD(0x078, PIN_OUTPUT, 1) /* (T21) GPMC0_AD15.VOUT0_DATA23 */
+		>;
+	};
+
+	main_mmc0_pins_default: main-mmc0-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x220, PIN_INPUT, 0) /* (Y3) MMC0_CMD */
+			AM62AX_IOPAD(0x218, PIN_INPUT, 0) /* (AB1) MMC0_CLKLB */
+			AM62AX_IOPAD(0x21c, PIN_INPUT, 0) /* (AB1) MMC0_CLK */
+			AM62AX_IOPAD(0x214, PIN_INPUT, 0) /* (AA2) MMC0_DAT0 */
+			AM62AX_IOPAD(0x210, PIN_INPUT_PULLUP, 0) /* (AA1) MMC0_DAT1 */
+			AM62AX_IOPAD(0x20c, PIN_INPUT_PULLUP, 0) /* (AA3) MMC0_DAT2 */
+			AM62AX_IOPAD(0x208, PIN_INPUT_PULLUP, 0) /* (Y4) MMC0_DAT3 */
+			AM62AX_IOPAD(0x204, PIN_INPUT_PULLUP, 0) /* (AB2) MMC0_DAT4 */
+			AM62AX_IOPAD(0x200, PIN_INPUT_PULLUP, 0) /* (AC1) MMC0_DAT5 */
+			AM62AX_IOPAD(0x1fc, PIN_INPUT_PULLUP, 0) /* (AD2) MMC0_DAT6 */
+			AM62AX_IOPAD(0x1f8, PIN_INPUT_PULLUP, 0) /* (AC2) MMC0_DAT7 */
+		>;
+	};
+
+	vddshv_sdio_pins_default: vddshv-sdio-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x07c, PIN_OUTPUT, 7) /* (M19) GPMC0_CLK.GPIO0_31 */
+		>;
+	};
+
+	ospi0_pins_default: ospi0-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x000, PIN_OUTPUT, 0) /* (H24) OSPI0_CLK */
+			AM62AX_IOPAD(0x02c, PIN_OUTPUT, 0) /* (F23) OSPI0_CSn0 */
+			AM62AX_IOPAD(0x00c, PIN_INPUT, 0) /* (E25) OSPI0_D0 */
+			AM62AX_IOPAD(0x010, PIN_INPUT, 0) /* (G24) OSPI0_D1 */
+			AM62AX_IOPAD(0x014, PIN_INPUT, 0) /* (F25) OSPI0_D2 */
+			AM62AX_IOPAD(0x018, PIN_INPUT, 0) /* (F24) OSPI0_D3 */
+			AM62AX_IOPAD(0x01c, PIN_INPUT, 0) /* (J23) OSPI0_D4 */
+			AM62AX_IOPAD(0x020, PIN_INPUT, 0) /* (J25) OSPI0_D5 */
+			AM62AX_IOPAD(0x024, PIN_INPUT, 0) /* (H25) OSPI0_D6 */
+			AM62AX_IOPAD(0x028, PIN_INPUT, 0) /* (J22) OSPI0_D7 */
+			AM62AX_IOPAD(0x008, PIN_INPUT, 0) /* (J24) OSPI0_DQS */
+		>;
+	};
+};
+
+&mcu_pmx0 {
+	status = "okay";
+
+	pmic_irq_pins_default: pmic-irq-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_MCU_IOPAD(0x000, PIN_INPUT, 7) /* (E11) MCU_GPIO0_0 */
+		>;
+	};
+};
+
+&mcu_gpio0 {
+	status = "okay";
 };
 
 &main_i2c0 {
@@ -166,6 +439,105 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c0_pins_default>;
 	clock-frequency = <400000>;
+
+	typec_pd0: usb-power-controller@3f {
+		compatible = "ti,tps6598x";
+		reg = <0x3f>;
+
+		connector {
+			compatible = "usb-c-connector";
+			label = "USB-C";
+			self-powered;
+			data-role = "dual";
+			power-role = "sink";
+			port {
+				usb_con_hs: endpoint {
+					remote-endpoint = <&usb0_hs_ep>;
+				};
+			};
+		};
+	};
+
+	tps659312: pmic@48 {
+		compatible = "ti,tps6593-q1";
+		reg = <0x48>;
+		ti,primary-pmic;
+		system-power-controller;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_irq_pins_default>;
+		interrupt-parent = <&mcu_gpio0>;
+		interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+
+		buck123-supply = <&vcc_3v3_sys>;
+		buck4-supply = <&vcc_3v3_sys>;
+		buck5-supply = <&vcc_3v3_sys>;
+		ldo1-supply = <&vcc_3v3_sys>;
+		ldo2-supply = <&vcc_3v3_sys>;
+		ldo3-supply = <&buck5>;
+		ldo4-supply = <&vcc_3v3_sys>;
+
+		regulators {
+			buck123: buck123 {
+				regulator-name = "vcc_core";
+				regulator-min-microvolt = <715000>;
+				regulator-max-microvolt = <895000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck4: buck4 {
+				regulator-name = "vcc_1v1";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck5: buck5 {
+				regulator-name = "vcc_1v8_sys";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo1: ldo1 {
+				regulator-name = "vddshv5_sdio";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo2: ldo2 {
+				regulator-name = "vpp_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo3: ldo3 {
+				regulator-name = "vcc_0v85";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo4: ldo4 {
+				regulator-name = "vdda_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
 };
 
 &main_i2c1 {
@@ -180,6 +552,11 @@
 		gpio-controller;
 		#gpio-cells = <2>;
 
+		interrupt-parent = <&main_gpio1>;
+		interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
 		gpio-line-names = "GPIO_CPSW2_RST", "GPIO_CPSW1_RST",
 				   "BT_EN_SOC", "MMC1_SD_EN",
 				   "VPP_EN", "EXP_PS_3V3_En",
@@ -192,13 +569,90 @@
 				   "MCASP1_FET_EN", "MCASP1_BUF_BT_EN",
 				   "MCASP1_FET_SEL", "UART1_FET_SEL",
 				   "PD_I2C_IRQ", "IO_EXP_TEST_LED";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&main_gpio1_ioexp_intr_pins_default>;
+	};
+
+	exp2: gpio@23 {
+		compatible = "ti,tca6424";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		gpio-line-names = "", "",
+				  "", "",
+				  "", "",
+				  "", "",
+				  "WL_LT_EN", "CSI_RSTz",
+				  "", "",
+				  "", "",
+				  "", "",
+				  "SPI0_FET_SEL", "SPI0_FET_OE",
+				  "RGMII2_BRD_CONN_DET", "CSI_SEL2",
+				  "CSI_EN", "AUTO_100M_1000M_CONFIG",
+				  "CSI_VLDO_SEL", "SoC_WLAN_SDIO_RST";
+	};
+
+	tlv320aic3106: audio-codec@1b {
+		#sound-dai-cells = <0>;
+		compatible = "ti,tlv320aic3106";
+		reg = <0x1b>;
+		ai3x-micbias-vg = <1>;	/* 2.0V */
+		ai3x-ocmv = <1>;	/* 1.5V */
+
+		/* Regulators */
+		AVDD-supply = <&vcc_3v3_sys>;
+		IOVDD-supply = <&vcc_3v3_sys>;
+		DRVDD-supply = <&vcc_3v3_sys>;
+	};
+
+	sii9022: sii9022@3b {
+		#sound-dai-cells = <0>;
+		compatible = "sil,sii9022";
+		reg = <0x3b>;
+
+		interrupt-parent = <&exp1>;
+		interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
+
+		sil,i2s-data-lanes = < 0 >;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				sii9022_in: endpoint {
+					remote-endpoint = <&dpi1_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				sii9022_out: endpoint {
+					remote-endpoint = <&hdmi_connector_in>;
+				};
+			};
+		};
 	};
+
+};
+
+&main_i2c2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c2_pins_default>;
+	clock-frequency = <400000>;
 };
 
 &sdhci1 {
 	/* SD/MMC */
 	status = "okay";
 	vmmc-supply = <&vdd_mmc1>;
+	vqmmc-supply = <&vddshv_sdio>;
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_mmc1_pins_default>;
 	ti,driver-strength-ohm = <50>;
@@ -221,4 +675,240 @@
 	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart0_pins_default>;
+	interrupts-extended = <&gic500 GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>,
+			<&main_pmx0 0x1c8>; /* (D14) UART0_RXD PADCONFIG114 */
+	interrupt-names = "irq", "wakeup";
+};
+
+&usbss0 {
+	status = "okay";
+	ti,vbus-divider;
+};
+
+&usb0 {
+	usb-role-switch;
+
+	port {
+		usb0_hs_ep: endpoint {
+			remote-endpoint = <&usb_con_hs>;
+		};
+	};
+};
+
+&usbss1 {
+	status = "okay";
+};
+
+&usb1 {
+	dr_mode = "host";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_usb1_pins_default>;
+};
+
+&cpsw3g {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_rgmii1_pins_default>;
+
+	cpts@3d000 {
+		/* MAP HW3_TS_PUSH to GENF1 */
+		ti,pps = <2 1>;
+	};
+};
+
+&cpsw_port1 {
+	status = "okay";
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&cpsw3g_phy0>;
+};
+
+&cpsw_port2 {
+	status = "disabled";
+};
+
+&cpsw3g_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mdio1_pins_default>;
+
+	cpsw3g_phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+};
+
+&mcasp1 {
+	status = "okay";
+	#sound-dai-cells = <0>;
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcasp1_pins_default>;
+
+	op-mode = <0>;          /* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+
+	serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+	       1 0 2 0
+	       0 0 0 0
+	       0 0 0 0
+	       0 0 0 0
+	>;
+	tx-num-evt = <32>;
+	rx-num-evt = <32>;
+};
+
+&ti_csi2rx0 {
+	status = "okay";
+};
+
+&dphy0 {
+	status = "okay";
+};
+
+&dss {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_dss0_pins_default>;
+};
+
+&dss_ports {
+	/* VP2: DPI Output */
+	port@0 {
+		reg = <0>;
+
+		dpi1_out: endpoint {
+			remote-endpoint = <&sii9022_in>;
+		};
+	};
+};
+
+&fss {
+	status = "okay";
+};
+
+&ospi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ospi0_pins_default>;
+
+	flash@0{
+		compatible = "spi-nand";
+		reg = <0x0>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+		spi-max-frequency = <25000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <2>;
+		cdns,phy-mode;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi_nand.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi_nand.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi_nand.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi_nand.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi_nand.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@2000000 {
+				label = "ospi_nand.rootfs";
+				reg = <0x2000000 0x5fc0000>;
+			};
+
+			partition@7fc0000 {
+				label = "ospi_nand.phypattern";
+				reg = <0x7fc0000 0x40000>;
+			};
+		};
+	};
+};
+
+&mailbox0_cluster0 {
+	ti,mbox-num-fifos = <2>;
+	mbox_r5_0: mbox-r5-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+};
+
+&mailbox0_cluster1 {
+	ti,mbox-num-fifos = <2>;
+	mbox_c7x_0: mbox-c7x-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+};
+
+&mailbox0_cluster2 {
+	ti,mbox-num-fifos = <2>;
+	mbox_mcu_r5_0: mbox-mcu_r5-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+};
+
+&c7x_0 {
+	mboxes = <&mailbox0_cluster1 &mbox_c7x_0>;
+	memory-region = <&c7x_0_dma_memory_region>,
+			<&c7x_0_memory_region>;
+};
+
+&wkup_r5fss0_core0 {
+	mboxes = <&mailbox0_cluster0 &mbox_r5_0>;
+	memory-region = <&wkup_r5fss0_core0_dma_memory_region>,
+		<&wkup_r5fss0_core0_memory_region>;
+};
+
+&mcu_r5fss0_core0 {
+	mboxes = <&mailbox0_cluster2 &mbox_mcu_r5_0>;
+	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
+			<&mcu_r5fss0_core0_memory_region>;
+};
+
+#define K3_TS_OFFSET(pa, val)	(0x4+(pa)*4) (0x10000 | val)
+
+&timesync_router {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpsw_cpts>;
+
+	/* Use Time Sync Router to map GENF1 input to HW3_TS_PUSH output */
+	cpsw_cpts: cpsw-cpts {
+		pinctrl-single,pins = <
+			/* pps [cpsw cpts genf1] in17 -> out12 [cpsw cpts hw3_push] */
+			K3_TS_OFFSET(12, 17)
+			>;
+	};
+};
+
+&sdhci0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mmc0_pins_default>;
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a7-sk-e3-max-opp.dtso b/arch/arm64/boot/dts/ti/k3-am62a7-sk-e3-max-opp.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk-e3-max-opp.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk-e3-max-opp.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay to run AM62A7-SK Rev E3 board at maximum performance
+ * Requires VDD_CORE to be at 0.85V
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	opp-table {
+		/*
+		 * Add 1.4GHz and disable lower OPPs for max A53 performance
+		 * Only for AM62A7-SK Rev E3 board
+		 * Requires VDD_CORE to be at 0.85V
+		 */
+		opp-200000000 {
+			status = "disabled";
+		};
+
+		opp-400000000 {
+			status = "disabled";
+		};
+
+		opp-600000000 {
+			status = "disabled";
+		};
+
+		opp-800000000 {
+			status = "disabled";
+		};
+
+		opp-1000000000 {
+			status = "disabled";
+		};
+
+		opp-1250000000 {
+			status = "disabled";
+		};
+
+		opp-1400000000 {
+			opp-hz = /bits/ 64 <1400000000>;
+			opp-supported-hw = <0x01 0x0004>;
+			clock-latency-ns = <6000000>;
+		};
+	};
+};
+
+&c7x_0 {
+	/*
+	 * Override C7x frequency to 1 GHz for max performance
+	 * Only for AM62A7-SK Rev E3 board
+	 * Requires VDD_CORE to be at 0.85V
+	 */
+	clocks = <&k3_clks 208 0>;
+	assigned-clocks = <&k3_clks 208 0>;
+	assigned-clock-rates = <1000000000>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a7-sk-ethernet-dc01.dtso b/arch/arm64/boot/dts/ti/k3-am62a7-sk-ethernet-dc01.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk-ethernet-dc01.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk-ethernet-dc01.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for second CPSW3G port in RGMII mode using SK-ETHERNET-DC01
+ * Add-On Daughtercard with AM62A7-SK.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
+#include "k3-pinctrl.h"
+
+&{/} {
+	aliases {
+		ethernet1 = "/bus@f0000/ethernet@8000000/ethernet-ports/port@2";
+	};
+};
+
+&cpsw3g {
+	pinctrl-0 = <&main_rgmii1_pins_default>, <&main_rgmii2_pins_default>;
+};
+
+&cpsw_port2 {
+	status = "okay";
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&cpsw3g_phy1>;
+};
+
+&cpsw3g_mdio {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	cpsw3g_phy1: ethernet-phy@1 {
+		reg = <1>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+};
+
+&main_pmx0 {
+	main_rgmii2_pins_default: main-rgmii2-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x0184, PIN_INPUT, 0) /* (AA21) RGMII2_RD0 */
+			AM62AX_IOPAD(0x0188, PIN_INPUT, 0) /* (Y20) RGMII2_RD1 */
+			AM62AX_IOPAD(0x018c, PIN_INPUT, 0) /* (AB21) RGMII2_RD2 */
+			AM62AX_IOPAD(0x0190, PIN_INPUT, 0) /* (AB20) RGMII2_RD3 */
+			AM62AX_IOPAD(0x0180, PIN_INPUT, 0) /* (AA20) RGMII2_RXC */
+			AM62AX_IOPAD(0x017c, PIN_INPUT, 0) /* (W18) RGMII2_RX_CTL */
+			AM62AX_IOPAD(0x016c, PIN_INPUT, 0) /* (AA19) RGMII2_TD0 */
+			AM62AX_IOPAD(0x0170, PIN_INPUT, 0) /* (Y18) RGMII2_TD1 */
+			AM62AX_IOPAD(0x0174, PIN_INPUT, 0) /* (AA18) RGMII2_TD2 */
+			AM62AX_IOPAD(0x0178, PIN_INPUT, 0) /* (W17) RGMII2_TD3 */
+			AM62AX_IOPAD(0x0168, PIN_INPUT, 0) /* (AB19) RGMII2_TXC */
+			AM62AX_IOPAD(0x0164, PIN_INPUT, 0) /* (Y19) RGMII2_TX_CTL */
+		>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a7-sk-fusion.dtso b/arch/arm64/boot/dts/ti/k3-am62a7-sk-fusion.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk-fusion.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk-fusion.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay for Fusion (FPD-Link III) board on SK-AM62A
+ * https://svtronics.com/portfolio/evm577pfusion-v1-0-fusion/
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_fusion_25M_fixed: fixed-clock-25M {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+&exp2 {
+	p19-hog {
+		/* P19 - CSI_SEL2 */
+		gpio-hog;
+		gpios = <19 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "CSI_SEL2";
+	};
+};
+
+&main_i2c2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	i2c-switch@71 {
+		compatible = "nxp,pca9543";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x71>;
+
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			deser@3d {
+				compatible = "ti,ds90ub960-q1";
+				reg = <0x3d>;
+
+				clock-names = "refclk";
+				clocks = <&clk_fusion_25M_fixed>;
+
+				i2c-alias-pool = <0x4a 0x4b 0x4c 0x4d 0x4e 0x4f>;
+
+				ds90ub960_0_ports: ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* CSI-2 TX */
+					port@4 {
+						reg = <4>;
+						ds90ub960_0_csi_out: endpoint {
+							data-lanes = <1 2 3 4>;
+							clock-lanes = <0>;
+							link-frequencies = /bits/ 64 <800000000>;
+							remote-endpoint = <&csi2_phy0>;
+						};
+					};
+				};
+
+				ds90ub960_0_links: links {
+					#address-cells = <1>;
+					#size-cells = <0>;
+				};
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2_phy0: endpoint {
+		remote-endpoint = <&ds90ub960_0_csi_out>;
+		data-lanes = <1 2 3 4>;
+		clock-lanes = <0>;
+		link-frequencies = /bits/ 64 <800000000>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a7-sk-rpi-hdr-ehrpwm.dtso b/arch/arm64/boot/dts/ti/k3-am62a7-sk-rpi-hdr-ehrpwm.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk-rpi-hdr-ehrpwm.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk-rpi-hdr-ehrpwm.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for enabling RPi header with GPIOs and eHRPWMs on AM62A-SK
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+	rpi_header_gpio0_pins_default: rpi-header-gpio0-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x0038, PIN_INPUT, 7) /* (G20) OSPI0_CSn3.GPIO0_14 */
+			AM62AX_IOPAD(0x0088, PIN_INPUT, 7) /* (L17) GPMC0_OEn_REn.GPIO0_33 */
+			AM62AX_IOPAD(0x0094, PIN_INPUT, 7) /* (M18) GPMC0_BE1n.GPIO0_36 */
+			AM62AX_IOPAD(0x009c, PIN_INPUT, 7) /* (R17) GPMC0_WAIT1.GPIO0_38 */
+			AM62AX_IOPAD(0x00a0, PIN_INPUT, 7) /* (K17) GPMC0_WPn.GPIO0_39 */
+			AM62AX_IOPAD(0x00a4, PIN_INPUT, 7) /* (K18) GPMC0_DIR.GPIO0_40 */
+			AM62AX_IOPAD(0x00a8, PIN_INPUT, 7) /* (M19) GPMC0_CSn0.GPIO0_41 */
+			AM62AX_IOPAD(0x00ac, PIN_INPUT, 7) /* (M21) GPMC0_CSn1.GPIO0_42 */
+		>;
+	};
+
+	rpi_header_gpio1_pins_default: rpi-header-gpio1-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x01d0, PIN_INPUT, 7) /* (F14) UART0_CTSn.GPIO1_22 */
+		>;
+	};
+
+	rpi_header_ehrpwm0_pins_default: rpi-header-ehrpwm0-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x01ac, PIN_OUTPUT, 6) /* (B21) MCASP0_AFSR.EHRPWM0_A */
+			AM62AX_IOPAD(0x01b0, PIN_OUTPUT, 6) /* (A21) MCASP0_ACLKR.EHRPWM0_B */
+		>;
+	};
+
+	rpi_header_ehrpwm1_pins_default: rpi-header-ehrpwm1-pins-default {
+		pinctrl-single,pins = <
+			AM62AX_IOPAD(0x019c, PIN_OUTPUT, 6) /* (B18) MCASP0_AXR1.EHRPWM1_A */
+			AM62AX_IOPAD(0x01a0, PIN_OUTPUT, 6) /* (B20) MCASP0_AXR0.EHRPWM1_B */
+		>;
+	};
+};
+
+&main_i2c1 {
+	gpio@22 {
+		p05-hog {
+			/* P05 - EXP_PS_3V3_EN */
+			gpio-hog;
+			gpios = <5 GPIO_ACTIVE_HIGH>;
+			output-high;
+			line-name = "EXP_PS_3V3_EN";
+		};
+
+		p06-hog {
+			/* P06 - EXP_PS_5V0_EN */
+			gpio-hog;
+			gpios = <6 GPIO_ACTIVE_HIGH>;
+			output-high;
+			line-name = "EXP_PS_5V0_EN";
+		};
+
+		p25-hog {
+			/* P25 - UART1_FET_SEL */
+			gpio-hog;
+			gpios = <21 GPIO_ACTIVE_HIGH>;
+			output-low;
+			line-name = "UART1_FET_SEL";
+		};
+	};
+};
+
+&mcasp0 {
+	status = "disabled";
+};
+
+&epwm0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm0_pins_default>;
+};
+
+&epwm1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm1_pins_default>;
+};
+
+
+&main_gpio0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio0_pins_default>;
+};
+
+&main_gpio1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio1_pins_default>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a7-sk-ub954-evm.dtso b/arch/arm64/boot/dts/ti/k3-am62a7-sk-ub954-evm.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk-ub954-evm.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk-ub954-evm.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay for DS90UB954-Q1EVM FPDLink-III deserializer board on SK-AM62A
+ * https://www.ti.com/tool/DS90UB954-Q1EVM
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_fusion_25M_fixed: fixed-clock-25M {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+&exp2 {
+	p19-hog {
+		/* P19 - CSI_SEL2 */
+		gpio-hog;
+		gpios = <19 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "CSI_SEL2";
+	};
+};
+
+&main_i2c2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	i2c-switch@71 {
+		compatible = "nxp,pca9543";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x71>;
+
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			deser@3d {
+				compatible = "ti,ds90ub954-q1";
+				reg = <0x3d>;
+
+				clock-names = "refclk";
+				clocks = <&clk_fusion_25M_fixed>;
+
+				i2c-alias-pool = <0x4a 0x4b 0x4c 0x4d 0x4e 0x4f>;
+
+				ds90ub960_0_ports: ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* CSI-2 TX */
+					port@2 {
+						reg = <2>;
+						ds90ub960_0_csi_out: endpoint {
+							data-lanes = <1 2 3 4>;
+							clock-lanes = <0>;
+							link-frequencies = /bits/ 64 <800000000>;
+							remote-endpoint = <&csi2_phy0>;
+						};
+					};
+				};
+
+				ds90ub960_0_links: links {
+					#address-cells = <1>;
+					#size-cells = <0>;
+				};
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2_phy0: endpoint {
+		remote-endpoint = <&ds90ub960_0_csi_out>;
+		data-lanes = <1 2 3 4>;
+		clock-lanes = <0>;
+		link-frequencies = /bits/ 64 <800000000>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a.dtsi b/arch/arm64/boot/dts/ti/k3-am62a.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62a.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62a.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -8,9 +8,10 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/pinctrl/k3.h>
 #include <dt-bindings/soc/ti,sci_pm_domain.h>
 
+#include "k3-pinctrl.h"
+
 / {
 	model = "Texas Instruments K3 AM62A SoC";
 	compatible = "ti,am62a7";
@@ -60,6 +61,8 @@
 			 <0x00 0x08000000 0x00 0x08000000 0x00 0x00200000>, /* Main CPSW */
 			 <0x00 0x0e000000 0x00 0x0e000000 0x00 0x01d20000>, /* Second peripheral window */
 			 <0x00 0x0fd00000 0x00 0x0fd00000 0x00 0x00020000>, /* GPU */
+			 <0x00 0x0fd20000 0x00 0x0fd20000 0x00 0x00000100>, /* JPEGENC0_CORE */
+			 <0x00 0x0fd20200 0x00 0x0fd20200 0x00 0x00000200>, /* JPEGENC0_CORE_MMU */
 			 <0x00 0x20000000 0x00 0x20000000 0x00 0x0a008000>, /* Third peripheral window */
 			 <0x00 0x30040000 0x00 0x30040000 0x00 0x00080000>, /* PRUSS-M */
 			 <0x00 0x30101000 0x00 0x30101000 0x00 0x00010100>, /* CSI window */
@@ -114,9 +117,15 @@
 				 <0x00 0x78100000 0x00 0x78100000 0x00 0x00008000>; /* DM R5 BTCM*/
 		};
 	};
+
+	#include "k3-am62a-thermal.dtsi"
 };
 
 /* Now include the peripherals for each bus segments */
 #include "k3-am62a-main.dtsi"
 #include "k3-am62a-mcu.dtsi"
 #include "k3-am62a-wakeup.dtsi"
+
+&dmsc {
+	ti,partial-io-wakeup-sources = <&mcu_mcan0>, <&mcu_mcan1>, <&mcu_uart0>, <&wkup_uart0>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62a-main.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -48,6 +48,36 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0x00 0x00 0x00100000 0x20000>;
+
+		phy_gmii_sel: phy@4044 {
+			compatible = "ti,am654-phy-gmii-sel";
+			reg = <0x4044 0x8>;
+			#phy-cells = <1>;
+		};
+
+		epwm_tbclk: clock-controller@4130 {
+			compatible = "ti,am62-epwm-tbclk";
+			reg = <0x4130 0x4>;
+			#clock-cells = <1>;
+		};
+
+		audio_refclk0: clock@82e0 {
+			compatible = "ti,am62-audio-refclk";
+			reg = <0x82e0 0x4>;
+			clocks = <&k3_clks 157 0>;
+			assigned-clocks = <&k3_clks 157 0>;
+			assigned-clock-parents = <&k3_clks 157 8>;
+			#clock-cells = <0>;
+		};
+
+		audio_refclk1: clock@82e4 {
+			compatible = "ti,am62-audio-refclk";
+			reg = <0x82e4 0x4>;
+			clocks = <&k3_clks 157 10>;
+			assigned-clocks = <&k3_clks 157 10>;
+			assigned-clock-parents = <&k3_clks 157 18>;
+			#clock-cells = <0>;
+		};
 	};
 
 	dmss: bus@48000000 {
@@ -69,6 +99,105 @@
 			interrupt-names = "rx_012";
 			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
 		};
+
+		inta_main_dmss: interrupt-controller@48000000 {
+			compatible = "ti,sci-inta";
+			reg = <0x00 0x48000000 0x00 0x100000>;
+			#interrupt-cells = <0>;
+			interrupt-controller;
+			interrupt-parent = <&gic500>;
+			msi-controller;
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <28>;
+			ti,interrupt-ranges = <6 70 34>;
+			ti,unmapped-event-sources = <&main_bcdma>, <&main_pktdma>;
+		};
+
+		main_bcdma: dma-controller@485c0100 {
+			compatible = "ti,am64-dmss-bcdma";
+			reg = <0x00 0x485c0100 0x00 0x100>,
+			      <0x00 0x4c000000 0x00 0x20000>,
+			      <0x00 0x4a820000 0x00 0x20000>,
+			      <0x00 0x4aa40000 0x00 0x20000>,
+			      <0x00 0x4bc00000 0x00 0x100000>;
+			reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt";
+			msi-parent = <&inta_main_dmss>;
+			#dma-cells = <3>;
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <26>;
+			ti,sci-rm-range-bchan = <0x20>; /* BLOCK_COPY_CHAN */
+			ti,sci-rm-range-rchan = <0x21>; /* SPLIT_TR_RX_CHAN */
+			ti,sci-rm-range-tchan = <0x22>; /* SPLIT_TR_TX_CHAN */
+		};
+
+		main_pktdma: dma-controller@485c0000 {
+			compatible = "ti,am64-dmss-pktdma";
+			reg = <0x00 0x485c0000 0x00 0x100>,
+			      <0x00 0x4a800000 0x00 0x20000>,
+			      <0x00 0x4aa00000 0x00 0x40000>,
+			      <0x00 0x4b800000 0x00 0x400000>;
+			reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt";
+			msi-parent = <&inta_main_dmss>;
+			#dma-cells = <2>;
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <30>;
+			ti,sci-rm-range-tchan = <0x23>, /* UNMAPPED_TX_CHAN */
+						<0x24>, /* CPSW_TX_CHAN */
+						<0x25>, /* SAUL_TX_0_CHAN */
+						<0x26>; /* SAUL_TX_1_CHAN */
+			ti,sci-rm-range-tflow = <0x10>, /* RING_UNMAPPED_TX_CHAN */
+						<0x11>, /* RING_CPSW_TX_CHAN */
+						<0x12>, /* RING_SAUL_TX_0_CHAN */
+						<0x13>; /* RING_SAUL_TX_1_CHAN */
+			ti,sci-rm-range-rchan = <0x29>, /* UNMAPPED_RX_CHAN */
+						<0x2b>, /* CPSW_RX_CHAN */
+						<0x2d>, /* SAUL_RX_0_CHAN */
+						<0x2f>, /* SAUL_RX_1_CHAN */
+						<0x31>, /* SAUL_RX_2_CHAN */
+						<0x33>; /* SAUL_RX_3_CHAN */
+			ti,sci-rm-range-rflow = <0x2a>, /* FLOW_UNMAPPED_RX_CHAN */
+						<0x2c>, /* FLOW_CPSW_RX_CHAN */
+						<0x2e>, /* FLOW_SAUL_RX_0/1_CHAN */
+						<0x32>; /* FLOW_SAUL_RX_2/3_CHAN */
+		};
+	};
+
+	dmss_csi: bus@4e000000 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		dma-ranges;
+		ranges = <0x00 0x4e000000 0x00 0x4e000000 0x00 0x300000>;
+
+		ti,sci-dev-id = <198>;
+
+		inta_main_dmss_csi: interrupt-controller@4e0a0000 {
+			compatible = "ti,sci-inta";
+			reg = <0x00 0x4e0a0000 0x00 0x8000>;
+			#interrupt-cells = <0>;
+			interrupt-controller;
+			interrupt-parent = <&gic500>;
+			msi-controller;
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <200>;
+			ti,interrupt-ranges = <0 237 8>;
+			ti,unmapped-event-sources = <&main_bcdma_csi>;
+			power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+		};
+
+		main_bcdma_csi: dma-controller@4e230000 {
+			compatible = "ti,am62a-dmss-bcdma-csirx";
+			reg = <0x00 0x4e230000 0x00 0x100>,
+			      <0x00 0x4e180000 0x00 0x8000>,
+			      <0x00 0x4e100000 0x00 0x10000>;
+			reg-names = "gcfg", "rchanrt", "ringrt";
+			msi-parent = <&inta_main_dmss_csi>;
+			#dma-cells = <3>;
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <199>;
+			ti,sci-rm-range-rchan = <0x21>;
+			power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+		};
 	};
 
 	dmsc: system-controller@44043000 {
@@ -96,12 +225,123 @@
 		};
 	};
 
+	crypto: crypto@40900000 {
+		compatible = "ti,am62-sa3ul";
+		reg = <0x00 0x40900000 0x00 0x1200>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x00 0x40900000 0x00 0x40900000 0x00 0x30000>;
+
+		dmas = <&main_pktdma 0xf501 0>, <&main_pktdma 0x7506 0>,
+		       <&main_pktdma 0x7507 0>;
+		dma-names = "tx", "rx1", "rx2";
+	};
+
 	main_pmx0: pinctrl@f4000 {
-		compatible = "pinctrl-single";
-		reg = <0x00 0xf4000 0x00 0x2ac>;
+		compatible = "ti,am6-padconf";
+		reg = <0x00 0xf4000 0x00 0x25c>;
 		#pinctrl-cells = <1>;
 		pinctrl-single,register-width = <32>;
 		pinctrl-single,function-mask = <0xffffffff>;
+		interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+	};
+
+	main_timer0: timer@2400000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2400000 0x00 0x400>;
+		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 36 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 36 2>;
+		assigned-clock-parents = <&k3_clks 36 3>;
+		power-domains = <&k3_pds 36 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer1: timer@2410000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2410000 0x00 0x400>;
+		interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 37 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 37 2>;
+		assigned-clock-parents = <&k3_clks 37 3>;
+		power-domains = <&k3_pds 37 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer2: timer@2420000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2420000 0x00 0x400>;
+		interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 38 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 38 2>;
+		assigned-clock-parents = <&k3_clks 38 3>;
+		power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer3: timer@2430000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2430000 0x00 0x400>;
+		interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 39 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 39 2>;
+		assigned-clock-parents = <&k3_clks 39 3>;
+		power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer4: timer@2440000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2440000 0x00 0x400>;
+		interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 40 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 40 2>;
+		assigned-clock-parents = <&k3_clks 40 3>;
+		power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer5: timer@2450000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2450000 0x00 0x400>;
+		interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 41 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 41 2>;
+		assigned-clock-parents = <&k3_clks 41 3>;
+		power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer6: timer@2460000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2460000 0x00 0x400>;
+		interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 42 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 42 2>;
+		assigned-clock-parents = <&k3_clks 42 3>;
+		power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer7: timer@2470000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2470000 0x00 0x400>;
+		interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 43 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 43 2>;
+		assigned-clock-parents = <&k3_clks 43 3>;
+		power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
 	};
 
 	main_uart0: serial@2800000 {
@@ -222,6 +462,39 @@
 		status = "disabled";
 	};
 
+	main_spi0: spi@20100000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x20100000 0x00 0x400>;
+		interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 141 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 141 0>;
+		status = "disabled";
+	};
+
+	main_spi1: spi@20110000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x20110000 0x00 0x400>;
+		interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 142 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 142 0>;
+		status = "disabled";
+	};
+
+	main_spi2: spi@20120000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x20120000 0x00 0x400>;
+		interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 143 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 143 0>;
+		status = "disabled";
+	};
+
 	main_gpio_intr: interrupt-controller@a00000 {
 		compatible = "ti,sci-intr";
 		reg = <0x00 0x00a00000 0x00 0x800>;
@@ -245,7 +518,7 @@
 			     <193>, <194>, <195>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		ti,ngpio = <87>;
+		ti,ngpio = <92>;
 		ti,davinci-gpio-unbanked = <0>;
 		power-domains = <&k3_pds 77 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 77 0>;
@@ -263,7 +536,7 @@
 			     <183>, <184>, <185>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
-		ti,ngpio = <88>;
+		ti,ngpio = <52>;
 		ti,davinci-gpio-unbanked = <0>;
 		power-domains = <&k3_pds 78 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 78 0>;
@@ -271,6 +544,25 @@
 		status = "disabled";
 	};
 
+	sdhci0: mmc@fa10000 {
+		compatible = "ti,am62-sdhci";
+		reg = <0x00 0xfa10000 0x00 0x260>, <0x00 0xfa18000 0x00 0x134>;
+		interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 57 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 57 5>, <&k3_clks 57 6>;
+		clock-names = "clk_ahb", "clk_xin";
+		assigned-clocks = <&k3_clks 57 6>;
+		assigned-clock-parents = <&k3_clks 57 8>;
+		mmc-hs200-1_8v;
+		ti,trm-icp = <0x2>;
+		bus-width = <8>;
+		ti,clkbuf-sel = <0x7>;
+		ti,otap-del-sel-legacy = <0x0>;
+		ti,otap-del-sel-mmc-hs = <0x0>;
+		ti,otap-del-sel-hs200 = <0x6>;
+		status = "disabled";
+	};
+
 	sdhci1: mmc@fa00000 {
 		compatible = "ti,am62-sdhci";
 		reg = <0x00 0xfa00000 0x00 0x260>, <0x00 0xfa08000 0x00 0x134>;
@@ -279,7 +571,7 @@
 		clocks = <&k3_clks 58 5>, <&k3_clks 58 6>;
 		clock-names = "clk_ahb", "clk_xin";
 		ti,trm-icp = <0x2>;
-		ti,otap-del-sel-legacy = <0x0>;
+		ti,otap-del-sel-legacy = <0x8>;
 		ti,otap-del-sel-sd-hs = <0x0>;
 		ti,otap-del-sel-sdr12 = <0xf>;
 		ti,otap-del-sel-sdr25 = <0xf>;
@@ -292,7 +584,504 @@
 		ti,itap-del-sel-sdr25 = <0x0>;
 		ti,clkbuf-sel = <0x7>;
 		bus-width = <4>;
-		no-1-8-v;
 		status = "disabled";
 	};
+
+	usbss0: dwc3-usb@f900000 {
+		compatible = "ti,am62-usb";
+		reg = <0x00 0x0f900000 0x00 0x800>;
+		clocks = <&k3_clks 161 3>;
+		clock-names = "ref";
+		ti,syscon-phy-pll-refclk = <&usb0_phy_ctrl 0x0>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		power-domains = <&k3_pds 178 TI_SCI_PD_EXCLUSIVE>;
+		ranges;
+		status = "disabled";
+
+		usb0: usb@31000000 {
+			compatible = "snps,dwc3";
+			reg =<0x00 0x31000000 0x00 0x50000>;
+			interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
+				     <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>; /* irq.0 */
+			interrupt-names = "host", "peripheral";
+			maximum-speed = "high-speed";
+			dr_mode = "otg";
+		};
+	};
+
+	usbss1: dwc3-usb@f910000 {
+		compatible = "ti,am62-usb";
+		reg = <0x00 0x0f910000 0x00 0x800>;
+		clocks = <&k3_clks 162 3>;
+		clock-names = "ref";
+		ti,syscon-phy-pll-refclk = <&usb1_phy_ctrl 0x0>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		power-domains = <&k3_pds 179 TI_SCI_PD_EXCLUSIVE>;
+		ranges;
+		status = "disabled";
+
+		usb1: usb@31100000 {
+			compatible = "snps,dwc3";
+			reg =<0x00 0x31100000 0x00 0x50000>;
+			interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
+				     <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>; /* irq.0 */
+			interrupt-names = "host", "peripheral";
+			maximum-speed = "high-speed";
+			dr_mode = "otg";
+		};
+	};
+
+	fss: bus@fc00000 {
+		compatible = "simple-bus";
+		reg = <0x00 0x0fc00000 0x00 0x70000>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		status = "disabled";
+
+		ospi0: spi@fc40000 {
+			compatible = "ti,am654-ospi", "cdns,qspi-nor";
+			reg = <0x00 0x0fc40000 0x00 0x100>,
+			      <0x05 0x00000000 0x01 0x00000000>;
+			interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
+			cdns,fifo-depth = <256>;
+			cdns,fifo-width = <4>;
+			cdns,trigger-address = <0x0>;
+			clocks = <&k3_clks 75 7>;
+			assigned-clocks = <&k3_clks 75 7>;
+			assigned-clock-parents = <&k3_clks 75 8>;
+			assigned-clock-rates = <166666666>;
+			power-domains = <&k3_pds 75 TI_SCI_PD_EXCLUSIVE>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	cpsw3g: ethernet@8000000 {
+		compatible = "ti,am642-cpsw-nuss";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		reg = <0x0 0x8000000 0x0 0x200000>;
+		reg-names = "cpsw_nuss";
+		ranges = <0x0 0x0 0x0 0x8000000 0x0 0x200000>;
+		clocks = <&k3_clks 13 0>;
+		assigned-clocks = <&k3_clks 13 3>;
+		assigned-clock-parents = <&k3_clks 13 11>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 13 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+
+		dmas = <&main_pktdma 0xc600 15>,
+		       <&main_pktdma 0xc601 15>,
+		       <&main_pktdma 0xc602 15>,
+		       <&main_pktdma 0xc603 15>,
+		       <&main_pktdma 0xc604 15>,
+		       <&main_pktdma 0xc605 15>,
+		       <&main_pktdma 0xc606 15>,
+		       <&main_pktdma 0xc607 15>,
+		       <&main_pktdma 0x4600 15>;
+		dma-names = "tx0", "tx1", "tx2", "tx3", "tx4", "tx5", "tx6",
+			    "tx7", "rx";
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			cpsw_port1: port@1 {
+				reg = <1>;
+				ti,mac-only;
+				label = "port1";
+				phys = <&phy_gmii_sel 1>;
+				mac-address = [00 00 00 00 00 00];
+				ti,syscon-efuse = <&wkup_conf 0x200>;
+			};
+
+			cpsw_port2: port@2 {
+				reg = <2>;
+				ti,mac-only;
+				label = "port2";
+				phys = <&phy_gmii_sel 2>;
+				mac-address = [00 00 00 00 00 00];
+			};
+		};
+
+		cpsw3g_mdio: mdio@f00 {
+			compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+			reg = <0x0 0xf00 0x0 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&k3_clks 13 0>;
+			clock-names = "fck";
+			bus_freq = <1000000>;
+		};
+
+		cpts@3d000 {
+			compatible = "ti,j721e-cpts";
+			reg = <0x0 0x3d000 0x0 0x400>;
+			clocks = <&k3_clks 13 3>;
+			clock-names = "cpts";
+			interrupts-extended = <&gic500 GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "cpts";
+			ti,cpts-ext-ts-inputs = <4>;
+			ti,cpts-periodic-outputs = <2>;
+		};
+	};
+
+	timesync_router: pinctrl@a40000 {
+		compatible = "pinctrl-single";
+		reg = <0x0 0xa40000 0x0 0x800>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0x000107ff>;
+		status = "disabled";
+	};
+
+	hwspinlock: spinlock@2a000000 {
+		compatible = "ti,am64-hwspinlock";
+		reg = <0x00 0x2a000000 0x00 0x1000>;
+		#hwlock-cells = <1>;
+	};
+
+	mailbox0_cluster0: mailbox@29000000 {
+		compatible = "ti,am64-mailbox";
+		reg = <0x00 0x29000000 0x00 0x200>;
+		interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+		#mbox-cells = <1>;
+		ti,mbox-num-users = <4>;
+		ti,mbox-num-fifos = <16>;
+	};
+
+	mailbox0_cluster1: mailbox@29010000 {
+		compatible = "ti,am64-mailbox";
+		reg = <0x00 0x29010000 0x00 0x200>;
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+		#mbox-cells = <1>;
+		ti,mbox-num-users = <4>;
+		ti,mbox-num-fifos = <16>;
+	};
+
+	mailbox0_cluster2: mailbox@29020000 {
+		compatible = "ti,am64-mailbox";
+		reg = <0x00 0x29020000 0x00 0x200>;
+		interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+		#mbox-cells = <1>;
+		ti,mbox-num-users = <4>;
+		ti,mbox-num-fifos = <16>;
+	};
+
+	mailbox0_cluster3: mailbox@29030000 {
+		compatible = "ti,am64-mailbox";
+		reg = <0x00 0x29030000 0x00 0x200>;
+		interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+		#mbox-cells = <1>;
+		ti,mbox-num-users = <4>;
+		ti,mbox-num-fifos = <16>;
+	};
+
+	main_mcan0: can@20701000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x20701000 0x00 0x200>,
+		      <0x00 0x20708000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 98 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 98 6>, <&k3_clks 98 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	epwm0: pwm@23000000 {
+		compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23000000 0x00 0x100>;
+		power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&epwm_tbclk 0>, <&k3_clks 86 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	epwm1: pwm@23010000 {
+		compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23010000 0x00 0x100>;
+		power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&epwm_tbclk 1>, <&k3_clks 87 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	epwm2: pwm@23020000 {
+		compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23020000 0x00 0x100>;
+		power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&epwm_tbclk 2>, <&k3_clks 88 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	ecap0: pwm@23100000 {
+		compatible = "ti,am3352-ecap";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23100000 0x00 0x100>;
+		power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 51 0>;
+		clock-names = "fck";
+		status = "disabled";
+	};
+
+	ecap1: pwm@23110000 {
+		compatible = "ti,am3352-ecap";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23110000 0x00 0x100>;
+		power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 52 0>;
+		clock-names = "fck";
+		status = "disabled";
+	};
+
+	ecap2: pwm@23120000 {
+		compatible = "ti,am3352-ecap";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23120000 0x00 0x100>;
+		power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 53 0>;
+		clock-names = "fck";
+		status = "disabled";
+	};
+
+	eqep0: counter@23200000 {
+		compatible = "ti,am3352-eqep";
+		reg = <0x00 0x23200000 0x00 0x100>;
+		power-domains = <&k3_pds 59 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 59 0>;
+		clock-names = "fck";
+		interrupts = <GIC_SPI 116 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
+	};
+
+	eqep1: counter@23210000 {
+		compatible = "ti,am3352-eqep";
+		reg = <0x00 0x23210000 0x00 0x100>;
+		power-domains = <&k3_pds 60 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 60 0>;
+		clock-names = "fck";
+		interrupts = <GIC_SPI 117 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
+	};
+
+	eqep2: counter@23220000 {
+		compatible = "ti,am3352-eqep";
+		reg = <0x00 0x23220000 0x00 0x100>;
+		power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 62 0>;
+		clock-names = "fck";
+		interrupts = <GIC_SPI 118 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
+	};
+
+	mcasp0: audio-controller@2b00000 {
+		compatible = "ti,am33xx-mcasp-audio";
+		reg = <0x00 0x02b00000 0x00 0x2000>,
+		      <0x00 0x02b08000 0x00 0x400>;
+		reg-names = "mpu", "dat";
+		interrupts = <GIC_SPI 236 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "tx", "rx";
+
+		dmas = <&main_bcdma 0 0xc500 0>, <&main_bcdma 0 0x4500 0>;
+		dma-names = "tx", "rx";
+
+		clocks = <&k3_clks 190 0>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 190 0>;
+		assigned-clock-parents = <&k3_clks 190 2>;
+		power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	mcasp1: audio-controller@2b10000 {
+		compatible = "ti,am33xx-mcasp-audio";
+		reg = <0x00 0x02b10000 0x00 0x2000>,
+		      <0x00 0x02b18000 0x00 0x400>;
+		reg-names = "mpu", "dat";
+		interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "tx", "rx";
+
+		dmas = <&main_bcdma 0 0xc501 0>, <&main_bcdma 0 0x4501 0>;
+		dma-names = "tx", "rx";
+
+		clocks = <&k3_clks 191 0>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 191 0>;
+		assigned-clock-parents = <&k3_clks 191 2>;
+		power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	mcasp2: audio-controller@2b20000 {
+		compatible = "ti,am33xx-mcasp-audio";
+		reg = <0x00 0x02b20000 0x00 0x2000>,
+		      <0x00 0x02b28000 0x00 0x400>;
+		reg-names = "mpu", "dat";
+		interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "tx", "rx";
+
+		dmas = <&main_bcdma 0 0xc502 0>, <&main_bcdma 0 0x4502 0>;
+		dma-names = "tx", "rx";
+
+		clocks = <&k3_clks 192 0>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 192 0>;
+		assigned-clock-parents = <&k3_clks 192 2>;
+		power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	ti_csi2rx0: ticsi2rx@30102000 {
+		compatible = "ti,j721e-csi2rx";
+		dmas = <&main_bcdma_csi 0 0x5000 0>, <&main_bcdma_csi 0 0x5001 0>,
+			<&main_bcdma_csi 0 0x5002 0>, <&main_bcdma_csi 0 0x5003 0>,
+			<&main_bcdma_csi 0 0x5004 0>, <&main_bcdma_csi 0 0x5005 0>;
+		dma-names = "rx0", "rx1", "rx2", "rx3", "rx4", "rx5";
+		reg = <0x00 0x30102000 0x00 0x1000>;
+		power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		status = "disabled";
+
+		cdns_csi2rx0: csi-bridge@30101000 {
+			compatible = "cdns,csi2rx";
+			reg = <0x00 0x30101000 0x00 0x1000>;
+			clocks = <&k3_clks 182 0>, <&k3_clks 182 3>, <&k3_clks 182 0>,
+				<&k3_clks 182 0>, <&k3_clks 182 4>, <&k3_clks 182 4>;
+			clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+				"pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+			phys = <&dphy0>;
+			phy-names = "dphy";
+			power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				csi0_port0: port@0 {
+					reg = <0>;
+					status = "disabled";
+				};
+
+				csi0_port1: port@1 {
+					reg = <1>;
+					status = "disabled";
+				};
+
+				csi0_port2: port@2 {
+					reg = <2>;
+					status = "disabled";
+				};
+
+				csi0_port3: port@3 {
+					reg = <3>;
+					status = "disabled";
+				};
+
+				csi0_port4: port@4 {
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
+	dphy0: phy@30110000 {
+		compatible = "cdns,dphy-rx";
+		reg = <0x00 0x30110000 0x00 0x1100>;
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 185 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	dss: dss@30200000 {
+		compatible = "ti,am62a7-dss";
+		reg = <0x00 0x30200000 0x00 0x1000>, /* common */
+		      <0x00 0x30202000 0x00 0x1000>, /* vidl1 */
+		      <0x00 0x30206000 0x00 0x1000>, /* vid */
+		      <0x00 0x30207000 0x00 0x1000>, /* ovr1 */
+		      <0x00 0x30208000 0x00 0x1000>, /* ovr2 */
+		      <0x00 0x3020a000 0x00 0x1000>, /* vp1: OLDI: Tied OFF */
+		      <0x00 0x3020b000 0x00 0x1000>, /* vp2: Used as DPI Out */
+		      <0x00 0x30201000 0x00 0x1000>; /* common1 */
+		reg-names = "common", "vidl1", "vid",
+			    "ovr1", "ovr2", "vp1", "vp2", "common1";
+		power-domains = <&k3_pds 186 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 186 6>,
+			 <&k3_clks 186 0>,
+			 <&k3_clks 186 2>;
+		clock-names = "fck", "vp1", "vp2";
+		interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+
+		dss_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	vpu: video-codec@30210000 {
+		compatible = "cnm,cm521c-vpu";
+		reg = <0x00 0x30210000 0x00 0x10000>;
+		clocks = <&k3_clks 204 2>;
+		clock-names = "vcodec";
+		power-domains = <&k3_pds 204 TI_SCI_PD_EXCLUSIVE>;
+		sram=<&oc_sram>;
+		sram-size=<0xf800>;
+		operating-points-v2 = <&vpu_opp_table>;
+		vpu_opp_table: opp-table {
+			compatible = "operating-points-v2";
+			opp-20000000 {
+				opp-hz = /bits/ 64 <20000000>;
+			};
+
+			opp-100000000 {
+				opp-hz = /bits/ 64 <100000000>;
+			};
+
+			opp-200000000 {
+				opp-hz = /bits/ 64 <200000000>;
+			};
+
+			opp-400000000 {
+				opp-hz = /bits/ 64 <400000000>;
+			};
+		};
+	};
+
+	e5010: e5010@fd20000 {
+		compatible = "img,e5010-jpeg-enc";
+		reg = <0x00 0xfd20000 0x00 0x100>,
+		      <0x00 0xfd20200 0x00 0x200>;
+		reg-names = "regjasper", "regmmu";
+		clocks = <&k3_clks 201 0>;
+		clock-names = "core_clk";
+		power-domains = <&k3_pds 201 TI_SCI_PD_EXCLUSIVE>;
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	c7x_0: dsp@7e000000 {
+		compatible = "ti,am62a-c7xv-dsp";
+		reg = <0x00 0x7e000000 0x00 0x00100000>;
+		reg-names = "l2sram";
+		ti,sci = <&dmsc>;
+		ti,sci-dev-id = <208>;
+		ti,sci-proc-ids = <0x04 0xff>;
+		resets = <&k3_reset 208 1>;
+		firmware-name = "am62a-c71_0-fw";
+	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62a-mcu.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -6,6 +6,18 @@
  */
 
 &cbass_mcu {
+	mcu_ram: sram@79100000 {
+		compatible = "mmio-sram";
+		reg = <0x00 0x79100000 0x00 0x80000>;
+		ranges = <0x00 0x00 0x79100000 0x80000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		mcu_sram1@0 {
+			reg = <0x0 0x80000>;
+		};
+	};
+
 	mcu_pmx0: pinctrl@4084000 {
 		compatible = "pinctrl-single";
 		reg = <0x00 0x04084000 0x00 0x88>;
@@ -15,6 +27,51 @@
 		status = "disabled";
 	};
 
+	/*
+	 * The MCU domain timer interrupts are routed only to the ESM module,
+	 * and not currently available for Linux. The MCU domain timers are
+	 * of limited use without interrupts, and likely reserved by the ESM.
+	 */
+	mcu_timer0: timer@4800000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x4800000 0x00 0x400>;
+		clocks = <&k3_clks 35 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		status = "reserved";
+	};
+
+	mcu_timer1: timer@4810000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x4810000 0x00 0x400>;
+		clocks = <&k3_clks 48 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 48 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		status = "reserved";
+	};
+
+	mcu_timer2: timer@4820000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x4820000 0x00 0x400>;
+		clocks = <&k3_clks 49 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 49 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		status = "reserved";
+	};
+
+	mcu_timer3: timer@4830000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x4830000 0x00 0x400>;
+		clocks = <&k3_clks 50 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 50 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		status = "reserved";
+	};
+
 	mcu_uart0: serial@4a00000 {
 		compatible = "ti,am64-uart", "ti,am654-uart";
 		reg = <0x00 0x04a00000 0x00 0x100>;
@@ -36,4 +93,106 @@
 		clock-names = "fck";
 		status = "disabled";
 	};
+
+	mcu_spi0: spi@4b00000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x04b00000 0x00 0x400>;
+		interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 147 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 147 0>;
+		status = "disabled";
+	};
+
+	mcu_spi1: spi@4b10000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x04b10000 0x00 0x400>;
+		interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 148 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 148 0>;
+		status = "disabled";
+	};
+
+	mcu_gpio_intr: interrupt-controller@4210000 {
+		compatible = "ti,sci-intr";
+		reg = <0x00 0x04210000 0x00 0x200>;
+		ti,intr-trigger-type = <1>;
+		interrupt-controller;
+		interrupt-parent = <&gic500>;
+		#interrupt-cells = <1>;
+		ti,sci = <&dmsc>;
+		ti,sci-dev-id = <5>;
+		ti,interrupt-ranges = <0 104 4>;
+	};
+
+	mcu_gpio0: gpio@4201000 {
+		compatible = "ti,am64-gpio", "ti,keystone-gpio";
+		reg = <0x00 0x04201000 0x00 0x100>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&mcu_gpio_intr>;
+		interrupts = <30>, <31>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		ti,ngpio = <24>;
+		ti,davinci-gpio-unbanked = <0>;
+		power-domains = <&k3_pds 79 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 79 0>;
+		clock-names = "gpio";
+		status = "disabled";
+	};
+
+	mcu_r5fss0: r5fss@79000000 {
+		compatible = "ti,am62-r5fss";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x79000000 0x00 0x79000000 0x8000>,
+			 <0x79020000 0x00 0x79020000 0x8000>;
+		power-domains = <&k3_pds 7 TI_SCI_PD_EXCLUSIVE>;
+		mcu_r5fss0_core0: r5f@79000000 {
+			compatible = "ti,am62-r5f";
+			reg = <0x79000000 0x00008000>,
+				<0x79020000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <9>;
+			ti,sci-proc-ids = <0x03 0xff>;
+			resets = <&k3_reset 9 1>;
+			firmware-name = "am62a-mcu-r5f0_0-fw";
+			ti,atcm-enable = <0>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <0>;
+			sram = <&mcu_ram>;
+			wakeup-source;
+		};
+	};
+
+	mcu_mcan0: can@4e08000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x4e08000 0x00 0x200>,
+		      <0x00 0x4e00000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 188 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 188 6>, <&k3_clks 188 1>;
+		clock-names = "hclk", "cclk";
+		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		wakeup-source;
+		status = "disabled";
+	};
+
+	mcu_mcan1: can@4e18000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x4e18000 0x00 0x200>,
+		      <0x00 0x4e10000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 189 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 189 6>, <&k3_clks 189 1>;
+		clock-names = "hclk", "cclk";
+		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		wakeup-source;
+		status = "disabled";
+	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-thermal.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62a-thermal.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62a-thermal.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/thermal/thermal.h>
+
+thermal_zones: thermal-zones {
+	main0_thermal: main0-thermal {
+		polling-delay-passive = <250>;	/* milliSeconds */
+		polling-delay = <500>;		/* milliSeconds */
+		thermal-sensors = <&wkup_vtm0 0>;
+
+		trips {
+			main0_crit: main0-crit {
+				temperature = <125000>;	/* milliCelsius */
+				hysteresis = <2000>;	/* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+
+	main1_thermal: main1-thermal {
+		polling-delay-passive = <250>;	/* milliSeconds */
+		polling-delay = <500>;		/* milliSeconds */
+		thermal-sensors = <&wkup_vtm0 1>;
+
+		trips {
+			main1_crit: main1-crit {
+				temperature = <125000>;	/* milliCelsius */
+				hysteresis = <2000>;	/* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+
+	main2_thermal: main2-thermal {
+	       polling-delay-passive = <250>;	/* milliSeconds */
+	       polling-delay = <500>;		/* milliSeconds */
+	       thermal-sensors = <&wkup_vtm0 2>;
+
+		trips {
+			main2_crit: main2-crit {
+				temperature = <125000>;	/* milliCelsius */
+				hysteresis = <2000>;	/* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -17,6 +17,16 @@
 			compatible = "ti,am654-chipid";
 			reg = <0x14 0x4>;
 		};
+
+		usb0_phy_ctrl: syscon@4008 {
+			compatible = "syscon";
+			reg = <0x4008 0x4>;
+		};
+
+		usb1_phy_ctrl: syscon@4018 {
+			compatible = "syscon";
+			reg = <0x4018 0x4>;
+		};
 	};
 
 	wkup_uart0: serial@2b300000 {
@@ -31,7 +41,7 @@
 
 	wkup_i2c0: i2c@2b200000 {
 		compatible = "ti,am64-i2c", "ti,omap4-i2c";
-		reg = <0x00 0x02b200000 0x00 0x100>;
+		reg = <0x00 0x2b200000 0x00 0x100>;
 		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
@@ -49,6 +59,36 @@
 		clock-names = "vbus", "osc32k";
 		power-domains = <&k3_pds 117 TI_SCI_PD_EXCLUSIVE>;
 		wakeup-source;
-		status = "disabled";
+	};
+
+	wkup_r5fss0: r5fss@78000000 {
+		compatible = "ti,am62-r5fss";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x78000000 0x00 0x78000000 0x8000>,
+			 <0x78100000 0x00 0x78100000 0x8000>;
+		power-domains = <&k3_pds 119 TI_SCI_PD_EXCLUSIVE>;
+		wkup_r5fss0_core0: r5f@78000000 {
+			compatible = "ti,am62-r5f";
+			reg = <0x78000000 0x00008000>,
+				<0x78100000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <121>;
+			ti,sci-proc-ids = <0x01 0xff>;
+			resets = <&k3_reset 121 1>;
+			firmware-name = "am62-wkup-r5f0_0-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+	};
+
+	wkup_vtm0: temperature-sensor@b00000 {
+		compatible = "ti,j7200-vtm";
+		reg = <0x00 0xb00000 0x00 0x400>,
+		      <0x00 0xb01000 0x00 0x400>;
+		power-domains = <&k3_pds 95 TI_SCI_PD_EXCLUSIVE>;
+		#thermal-sensor-cells = <1>;
 	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62.dtsi b/arch/arm64/boot/dts/ti/k3-am62.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -8,9 +8,10 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/pinctrl/k3.h>
 #include <dt-bindings/soc/ti,sci_pm_domain.h>
 
+#include "k3-pinctrl.h"
+
 / {
 	model = "Texas Instruments K3 AM625 SoC";
 	compatible = "ti,am625";
@@ -46,6 +47,7 @@
 	};
 
 	cbass_main: bus@f0000 {
+		bootph-all;
 		compatible = "simple-bus";
 		#address-cells = <2>;
 		#size-cells = <2>;
@@ -64,6 +66,7 @@
 			 <0x00 0x30040000 0x00 0x30040000 0x00 0x00080000>, /* PRUSS-M */
 			 <0x00 0x30101000 0x00 0x30101000 0x00 0x00010100>, /* CSI window */
 			 <0x00 0x30200000 0x00 0x30200000 0x00 0x00010000>, /* DSS */
+			 <0x00 0x30300000 0x00 0x30300000 0x00 0x00001000>, /* MCRC */
 			 <0x00 0x31000000 0x00 0x31000000 0x00 0x00050000>, /* USB0 DWC3 Core window */
 			 <0x00 0x31100000 0x00 0x31100000 0x00 0x00050000>, /* USB1 DWC3 Core window */
 			 <0x00 0x40900000 0x00 0x40900000 0x00 0x00030000>, /* SA3UL */
@@ -75,32 +78,48 @@
 			 <0x00 0x70000000 0x00 0x70000000 0x00 0x00010000>, /* OCSRAM */
 			 <0x01 0x00000000 0x01 0x00000000 0x00 0x00310000>, /* A53 PERIPHBASE */
 			 <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, /* FSS0 DAT3 */
+			 <0x00 0x3b000000 0x00 0x3b000000 0x00 0x00000400>, /* GPMC0_CFG */
+			 <0x00 0x50000000 0x00 0x50000000 0x00 0x08000000>, /* GPMC0 DATA */
 
 			 /* MCU Domain Range */
 			 <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>,
 
 			 /* Wakeup Domain Range */
+			 <0x00 0x00b00000 0x00 0x00b00000 0x00 0x00002400>, /* VTM */
 			 <0x00 0x2b000000 0x00 0x2b000000 0x00 0x00300400>,
-			 <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>;
+			 <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>,
+			 <0x00 0x78000000 0x00 0x78000000 0x00 0x00008000>, /* DM R5 ATCM*/
+			 <0x00 0x78100000 0x00 0x78100000 0x00 0x00008000>; /* DM R5 BTCM*/
 
 		cbass_mcu: bus@4000000 {
+			bootph-all;
 			compatible = "simple-bus";
 			#address-cells = <2>;
 			#size-cells = <2>;
 			ranges = <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>; /* Peripheral window */
 		};
 
-		cbass_wakeup: bus@2b000000 {
+		cbass_wakeup: bus@b00000 {
+			bootph-all;
 			compatible = "simple-bus";
 			#address-cells = <2>;
 			#size-cells = <2>;
-			ranges = <0x00 0x2b000000 0x00 0x2b000000 0x00 0x00300400>, /* Peripheral Window */
-				 <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>;
+			ranges = <0x00 0x00b00000 0x00 0x00b00000 0x00 0x00002400>, /* VTM */
+				 <0x00 0x2b000000 0x00 0x2b000000 0x00 0x00300400>, /* Peripheral Window */
+				 <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>,
+				 <0x00 0x78000000 0x00 0x78000000 0x00 0x00008000>, /* DM R5 ATCM*/
+				 <0x00 0x78100000 0x00 0x78100000 0x00 0x00008000>; /* DM R5 BTCM*/
 		};
 	};
+
+	#include "k3-am62-thermal.dtsi"
 };
 
 /* Now include the peripherals for each bus segments */
 #include "k3-am62-main.dtsi"
 #include "k3-am62-mcu.dtsi"
 #include "k3-am62-wakeup.dtsi"
+
+&dmsc {
+	ti,partial-io-wakeup-sources = <&mcu_mcan0>, <&mcu_mcan1>, <&mcu_uart0>, <&wkup_uart0>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts b/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts
--- a/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62-lp-sk.dts	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AM62x LP SK: https://www.ti.com/tool/SK-AM62-LP
+ *
+ * Copyright (C) 2021-2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+
+#include "k3-am62x-sk-common.dtsi"
+
+/ {
+	compatible = "ti,am62-lp-sk", "ti,am625";
+	model = "Texas Instruments AM62x LP SK";
+
+	vmain_pd: regulator-0 {
+		/* TPS65988 PD CONTROLLER OUTPUT */
+		compatible = "regulator-fixed";
+		regulator-name = "vmain_pd";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vcc_5v0: regulator-1 {
+		/* Output of TPS630702RNMR */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_5v0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&vmain_pd>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vcc_3v3_sys: regulator-2 {
+		/* output of LM61460-Q1 */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_3v3_sys";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vmain_pd>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vdd_mmc1: regulator-3 {
+		/* TPS22918DBVR */
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_mmc1";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		enable-active-high;
+		vin-supply = <&vcc_3v3_sys>;
+		gpio = <&exp1 3 GPIO_ACTIVE_HIGH>;
+	};
+
+	vddshv_sdio: regulator-4 {
+		compatible = "regulator-gpio";
+		regulator-name = "vddshv_sdio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&vddshv_sdio_pins_default>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		vin-supply = <&ldo1_reg>;
+		gpios = <&main_gpio0 31 GPIO_ACTIVE_HIGH>;
+		states = <1800000 0x0>,
+			 <3300000 0x1>;
+	};
+};
+
+&main_pmx0 {
+	vddshv_sdio_pins_default: vddshv-sdio-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x07c, PIN_OUTPUT, 7) /* (M19) GPMC0_CLK.GPIO0_31 */
+		>;
+	};
+
+	main_gpio1_ioexp_intr_pins_default: main-gpio1-ioexp-intr-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01d4, PIN_INPUT, 7) /* (C13) UART0_RTSn.GPIO1_23 */
+		>;
+	};
+
+	pmic_irq_pins_default: pmic-irq-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01f4, PIN_INPUT, 0) /* (B16) EXTINTn */
+		>;
+	};
+};
+
+&main_i2c1 {
+	exp1: gpio@22 {
+		compatible = "ti,tca6424";
+		reg = <0x22>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names = "GPIO_CPSW2_RST", "GPIO_CPSW1_RST",
+				   "PRU_DETECT", "MMC1_SD_EN",
+				   "VPP_LDO_EN", "EXP_PS_3V3_En",
+				   "EXP_PS_5V0_En", "EXP_HAT_DETECT",
+				   "GPIO_AUD_RSTn", "GPIO_eMMC_RSTn",
+				   "UART1_FET_BUF_EN", "BT_UART_WAKE_SOC",
+				   "GPIO_HDMI_RSTn", "CSI_GPIO0",
+				   "CSI_GPIO1", "GPIO_OLDI_INT",
+				   "HDMI_INTn", "TEST_GPIO2",
+				   "MCASP1_FET_EN", "MCASP1_BUF_BT_EN",
+				   "MCASP1_FET_SEL", "UART1_FET_SEL",
+				   "", "IO_EXP_TEST_LED";
+
+		interrupt-parent = <&main_gpio1>;
+		interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&main_gpio1_ioexp_intr_pins_default>;
+	};
+
+	exp2: gpio@23 {
+		compatible = "ti,tca6424";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names = "", "",
+				   "", "",
+				   "", "",
+				   "", "",
+				   "WL_LT_EN", "CSI_RSTz",
+				   "", "",
+				   "", "",
+				   "", "",
+				   "SPI0_FET_SEL", "SPI0_FET_OE",
+				   "GPIO_OLDI_RSTn", "PRU_3V3_EN",
+				   "", "",
+				   "CSI_VLDO_SEL", "SOC_WLAN_SDIO_RST";
+	};
+};
+
+&sdhci1 {
+	vmmc-supply = <&vdd_mmc1>;
+	vqmmc-supply = <&vddshv_sdio>;
+};
+
+&cpsw_port2 {
+	status = "disabled";
+};
+
+&main_i2c0 {
+	tps65219: pmic@30 {
+		compatible = "ti,tps65219";
+		reg = <0x30>;
+		buck1-supply = <&vcc_3v3_sys>;
+		buck2-supply = <&vcc_3v3_sys>;
+		buck3-supply = <&vcc_3v3_sys>;
+		ldo1-supply = <&vcc_3v3_sys>;
+		ldo2-supply = <&buck2_reg>;
+		ldo3-supply = <&vcc_3v3_sys>;
+		ldo4-supply = <&vcc_3v3_sys>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_irq_pins_default>;
+
+		interrupt-parent = <&gic500>;
+		interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>;
+
+		regulators {
+			buck1_reg: buck1 {
+				regulator-name = "VDD_CORE";
+				regulator-min-microvolt = <750000>;
+				regulator-max-microvolt = <750000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck2_reg: buck2 {
+				regulator-name = "VCC1V8_SYS";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buck3_reg: buck3 {
+				regulator-name = "VDD_LPDDR4";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo1_reg: ldo1 {
+				regulator-name = "VDDSHV_SDIO";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+			};
+
+			ldo2_reg: ldo2 {
+				regulator-name = "VDDAR_CORE";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo3_reg: ldo3 {
+				regulator-name = "VDDA_1V8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldo4_reg: ldo4 {
+				regulator-name = "VDD_1V2";
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <1200000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&tlv320aic3106 {
+	DVDD-supply = <&buck2_reg>;
+};
+
+&ospi0 {
+	flash@0 {
+		compatible = "spi-nand";
+		reg = <0x0>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+		spi-max-frequency = <25000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <2>;
+		cdns,phy-mode;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi_nand.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi_nand.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi_nand.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi_nand.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi_nand.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@2000000 {
+				label = "ospi_nand.rootfs";
+				reg = <0x2000000 0x5fc0000>;
+			};
+
+			partition@7fc0000 {
+				label = "ospi_nand.phypattern";
+				reg = <0x7fc0000 0x40000>;
+			};
+		};
+	};
+};
+
+/*
+ * All SoC variants with the AMC package have no PRU.
+ * Attempting to access the PRU on these devices will
+ * result in a crash at kernel bootup.
+ *
+ * For now, we do not have any code that can figure out
+ * the absence of the PRU by reading any SoC registers,
+ * so for now disable the PRU here in the board DTS file.
+ */
+&pruss {
+        status = "disabled";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-lp-sk-lincolntech-lcd185-panel.dtso b/arch/arm64/boot/dts/ti/k3-am62-lp-sk-lincolntech-lcd185-panel.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62-lp-sk-lincolntech-lcd185-panel.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62-lp-sk-lincolntech-lcd185-panel.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * Lincoln tech Solutions OLDI panel (LCD185-101CT) and touch DT overlay for AM62-LP-SK
+ *
+ * AM62-LP SKEVM: https://www.ti.com/tool/SK-AM62-LP
+ * Panel datasheet: https://lincolntechsolutions.com/wp-content/uploads/2023/04/LCD185-101CTL1ARNTT_DS_R1.3.pdf
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&{/} {
+	display {
+		compatible = "lincolntech,lcd185-101ct";
+		/*
+		* Note that the OLDI TX 0 transmits the odd set of pixels
+		* while the OLDI TX 1 transmits the even set. This is a
+		* fixed configuration in the IP integration and is not
+		* changeable. The properties, "dual-lvds-odd-pixels" and
+		* "dual-lvds-even-pixels" have been used to merely
+		* identify if a Dual Link configuration is required.
+		* But swapping them will cause an error in the dss driver.
+		*/
+		port@0 {
+			dual-lvds-odd-pixels;
+			lcd_in0: endpoint {
+				remote-endpoint = <&oldi_out0>;
+			};
+		};
+		port@1 {
+			dual-lvds-even-pixels;
+			lcd_in1: endpoint {
+				remote-endpoint = <&oldi_out1>;
+			};
+		};
+	};
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* VP1: LVDS Output (OLDI TX 0) */
+	port@0 {
+		reg = <0>;
+		oldi_out0: endpoint {
+			remote-endpoint = <&lcd_in0>;
+		};
+	};
+
+	/* VP1: LVDS Output (OLDI TX 1) */
+	port@2 {
+		reg = <2>;
+		oldi_out1: endpoint {
+			remote-endpoint = <&lcd_in1>;
+		};
+	};
+};
+
+&main_i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	eeprom@57 {
+		compatible = "atmel,24c256";
+		reg = <0x57>;
+	};
+
+	touchscreen@5d {
+		compatible = "goodix,gt928";
+		reg = <0x5d>;
+		interrupt-parent = <&exp1>;
+		interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
+		irq-gpios = <&exp1 15 GPIO_ACTIVE_LOW>;
+		reset-gpios = <&exp2 18 GPIO_ACTIVE_LOW>;
+		touchscreen-size-x = <1920>;
+		touchscreen-size-y = <1200>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-lp-sk-microtips-mf101hie-panel.dtso b/arch/arm64/boot/dts/ti/k3-am62-lp-sk-microtips-mf101hie-panel.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62-lp-sk-microtips-mf101hie-panel.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62-lp-sk-microtips-mf101hie-panel.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * Microtips integrated OLDI panel (MF-101HIEBCAF0) and touch DT overlay for AM62 LP-SK
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	display {
+		compatible = "microtips,mf-101hiebcaf0";
+		/*
+		* Note that the OLDI TX 0 transmits the odd set of pixels
+		* while the OLDI TX 1 transmits the even set. This is a
+		* fixed configuration in the IP integration and is not
+		* changeable. The properties, "dual-lvds-odd-pixels" and
+		* "dual-lvds-even-pixels" have been used to merely
+		* identify if a Dual Link configuration is required.
+		* Swapping them will not make any difference.
+		*/
+		port@0 {
+			dual-lvds-odd-pixels;
+			lcd_in0: endpoint {
+				remote-endpoint = <&oldi_out0>;
+			};
+		};
+		port@1 {
+			dual-lvds-even-pixels;
+			lcd_in1: endpoint {
+				remote-endpoint = <&oldi_out1>;
+			};
+		};
+	};
+};
+
+&main_pmx0 {
+	main_oldi0_pins_default: main-oldi0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0260, PIN_OUTPUT, 0) /* (AA5) OLDI0_A0N */
+			AM62X_IOPAD(0x025c, PIN_OUTPUT, 0) /* (Y6) OLDI0_A0P */
+			AM62X_IOPAD(0x0268, PIN_OUTPUT, 0) /* (AD3) OLDI0_A1N */
+			AM62X_IOPAD(0x0264, PIN_OUTPUT, 0) /* (AB4) OLDI0_A1P */
+			AM62X_IOPAD(0x0270, PIN_OUTPUT, 0) /* (Y8) OLDI0_A2N */
+			AM62X_IOPAD(0x026c, PIN_OUTPUT, 0) /* (AA8) OLDI0_A2P */
+			AM62X_IOPAD(0x0278, PIN_OUTPUT, 0) /* (AB6) OLDI0_A3N */
+			AM62X_IOPAD(0x0274, PIN_OUTPUT, 0) /* (AA7) OLDI0_A3P */
+			AM62X_IOPAD(0x0280, PIN_OUTPUT, 0) /* (AC6) OLDI0_A4N */
+			AM62X_IOPAD(0x027c, PIN_OUTPUT, 0) /* (AC5) OLDI0_A4P */
+			AM62X_IOPAD(0x0288, PIN_OUTPUT, 0) /* (AE5) OLDI0_A5N */
+			AM62X_IOPAD(0x0284, PIN_OUTPUT, 0) /* (AD6) OLDI0_A5P */
+			AM62X_IOPAD(0x0290, PIN_OUTPUT, 0) /* (AE6) OLDI0_A6N */
+			AM62X_IOPAD(0x028c, PIN_OUTPUT, 0) /* (AD7) OLDI0_A6P */
+			AM62X_IOPAD(0x0298, PIN_OUTPUT, 0) /* (AD8) OLDI0_A7N */
+			AM62X_IOPAD(0x0294, PIN_OUTPUT, 0) /* (AE7) OLDI0_A7P */
+			AM62X_IOPAD(0x02a0, PIN_OUTPUT, 0) /* (AD4) OLDI0_CLK0N */
+			AM62X_IOPAD(0x029c, PIN_OUTPUT, 0) /* (AE3) OLDI0_CLK0P */
+			AM62X_IOPAD(0x02a8, PIN_OUTPUT, 0) /* (AE4) OLDI0_CLK1N */
+			AM62X_IOPAD(0x02a4, PIN_OUTPUT, 0) /* (AD5) OLDI0_CLK1P */
+		>;
+	};
+};
+
+&dss {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_oldi0_pins_default &main_dss0_pins_default>;
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* VP1: LVDS Output (OLDI TX 0) */
+	port@0 {
+		reg = <0>;
+		oldi_out0: endpoint {
+			remote-endpoint = <&lcd_in0>;
+		};
+	};
+
+	/* VP1: LVDS Output (OLDI TX 1) */
+	port@2 {
+		reg = <2>;
+		oldi_out1: endpoint {
+			remote-endpoint = <&lcd_in1>;
+		};
+	};
+};
+
+&main_i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	touchscreen@41 {
+		compatible = "ilitek,ili251x";
+		reg = <0x41>;
+		interrupt-parent = <&exp1>;
+		interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
+		reset-gpios = <&exp2 18 GPIO_ACTIVE_LOW>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-lp-sk-nand.dtso b/arch/arm64/boot/dts/ti/k3-am62-lp-sk-nand.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62-lp-sk-nand.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62-lp-sk-nand.dtso	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "k3-pinctrl.h"
+
+&mcasp1 {
+	status = "disabled";
+};
+
+&main_pmx0 {
+	gpmc0_pins_default: gpmc0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x003c, PIN_INPUT, 0) /* (M25) GPMC0_AD0 */
+			AM62X_IOPAD(0x0040, PIN_INPUT, 0) /* (N23) GPMC0_AD1 */
+			AM62X_IOPAD(0x0044, PIN_INPUT, 0) /* (N24) GPMC0_AD2 */
+			AM62X_IOPAD(0x0048, PIN_INPUT, 0) /* (N25) GPMC0_AD3 */
+			AM62X_IOPAD(0x004c, PIN_INPUT, 0) /* (P24) GPMC0_AD4 */
+			AM62X_IOPAD(0x0050, PIN_INPUT, 0) /* (P22) GPMC0_AD5 */
+			AM62X_IOPAD(0x0054, PIN_INPUT, 0) /* (P21) GPMC0_AD6 */
+			AM62X_IOPAD(0x0058, PIN_INPUT, 0) /* (R23) GPMC0_AD7 */
+			AM62X_IOPAD(0x0084, PIN_OUTPUT, 0) /* (L23) GPMC0_ADVn_ALE */
+			AM62X_IOPAD(0x0088, PIN_OUTPUT, 0) /* (L24) GPMC0_OEn_REn */
+			AM62X_IOPAD(0x008c, PIN_OUTPUT, 0) /* (L25) GPMC0_WEn */
+			AM62X_IOPAD(0x0090, PIN_OUTPUT, 0) /* (M24) GPMC0_BE0n_CLE */
+			AM62X_IOPAD(0x00a8, PIN_OUTPUT, 0) /* (M21) GPMC0_CSn0 */
+			AM62X_IOPAD(0x0098, PIN_INPUT, 0) /* (U23) GPMC0_WAIT0 */
+		>;
+	};
+};
+
+&gpmc0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&gpmc0_pins_default>;
+	ranges = <0 0 0x00 0x51000000 0x01000000>; /* CS0 space. Min partition = 16MB */
+	#address-cells = <2>;
+	#size-cells = <1>;
+
+	nand0_0: nand@0,0 {
+		compatible = "ti,am64-nand";
+		reg = <0 0 64>;         /* device IO registers */
+		interrupt-parent = <&gpmc0>;
+		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+			     <1 IRQ_TYPE_NONE>; /* termcount */
+		rb-gpios = <&gpmc0 0 GPIO_ACTIVE_HIGH>; /* gpmc_wait0 */
+		ti,nand-xfer-type = "prefetch-polled";
+		ti,nand-ecc-opt = "bch8";       /* BCH8: Bootrom limitation */
+		ti,elm-id = <&elm0>;
+		nand-bus-width = <8>;
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <40>;
+		gpmc,cs-wr-off-ns = <40>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <25>;
+		gpmc,adv-wr-off-ns = <25>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <20>;
+		gpmc,oe-on-ns = <3>;
+		gpmc,oe-off-ns = <30>;
+		gpmc,access-ns = <30>;
+		gpmc,rd-cycle-ns = <40>;
+		gpmc,wr-cycle-ns = <40>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "NAND.tiboot3";
+				reg = <0x00000000 0x00200000>;  /* 2M */
+			};
+			partition@200000 {
+				label = "NAND.tispl";
+				reg = <0x00200000 0x00200000>;  /* 2M */
+			};
+			partition@400000 {
+				label = "NAND.tiboot3.backup";  /* 2M */
+				reg = <0x00400000 0x00200000>;  /* BootROM looks at 4M */
+			};
+			partition@600000 {
+				label = "NAND.u-boot";
+				reg = <0x00600000 0x00400000>;  /* 4M */
+			};
+			partition@a00000 {
+				label = "NAND.u-boot-env";
+				reg = <0x00a00000 0x00040000>;  /* 256K */
+			};
+			partition@a40000 {
+				label = "NAND.u-boot-env.backup";
+				reg = <0x00a40000 0x00040000>;  /* 256K */
+			};
+			partition@a80000 {
+				label = "NAND.file-system";
+				reg = <0x00a80000 0x3f580000>;
+			};
+		};
+	};
+};
+
+&elm0{
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -56,13 +56,37 @@
 		};
 
 		epwm_tbclk: clock@4130 {
-			compatible = "ti,am62-epwm-tbclk", "syscon";
+			compatible = "ti,am62-epwm-tbclk";
 			reg = <0x4130 0x4>;
 			#clock-cells = <1>;
 		};
+
+		dss_oldi_io_ctrl: dss-oldi-io-ctrl@8600 {
+			compatible = "syscon";
+			reg = <0x8600 0x200>;
+		};
+
+		audio_refclk0: clock@82e0 {
+			compatible = "ti,am62-audio-refclk";
+			reg = <0x82e0 0x4>;
+			clocks = <&k3_clks 157 0>;
+			assigned-clocks = <&k3_clks 157 0>;
+			assigned-clock-parents = <&k3_clks 157 8>;
+			#clock-cells = <0>;
+		};
+
+		audio_refclk1: clock@82e4 {
+			compatible = "ti,am62-audio-refclk";
+			reg = <0x82e4 0x4>;
+			clocks = <&k3_clks 157 10>;
+			assigned-clocks = <&k3_clks 157 10>;
+			assigned-clock-parents = <&k3_clks 157 18>;
+			#clock-cells = <0>;
+		};
 	};
 
 	dmss: bus@48000000 {
+		bootph-all;
 		compatible = "simple-mfd";
 		#address-cells = <2>;
 		#size-cells = <2>;
@@ -72,6 +96,7 @@
 		ti,sci-dev-id = <25>;
 
 		secure_proxy_main: mailbox@4d000000 {
+			bootph-all;
 			compatible = "ti,am654-secure-proxy";
 			#mbox-cells = <1>;
 			reg-names = "target_data", "rt", "scfg";
@@ -156,16 +181,19 @@
 		reg = <0x00 0x44043000 0x00 0xfe0>;
 
 		k3_pds: power-controller {
+			bootph-all;
 			compatible = "ti,sci-pm-domain";
 			#power-domain-cells = <2>;
 		};
 
 		k3_clks: clock-controller {
+			bootph-all;
 			compatible = "ti,k2g-sci-clk";
 			#clock-cells = <2>;
 		};
 
 		k3_reset: reset-controller {
+			bootph-all;
 			compatible = "ti,sci-reset";
 			#reset-cells = <2>;
 		};
@@ -174,7 +202,6 @@
 	crypto: crypto@40900000 {
 		compatible = "ti,am62-sa3ul";
 		reg = <0x00 0x40900000 0x00 0x1200>;
-		power-domains = <&k3_pds 70 TI_SCI_PD_SHARED>;
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges = <0x00 0x40900000 0x00 0x40900000 0x00 0x30000>;
@@ -184,12 +211,141 @@
 		dma-names = "tx", "rx1", "rx2";
 	};
 
+	mcrc: mcrc@30300000 {
+		compatible = "ti,mcrc";
+		reg = <0x00 0x30300000 0x00 0x1000>;
+		clocks = <&k3_clks 116 0>;
+		power-domains = <&k3_pds 116 TI_SCI_PD_EXCLUSIVE>;
+	};
+
+	secure_proxy_sa3: mailbox@43600000 {
+		compatible = "ti,am654-secure-proxy";
+		#mbox-cells = <1>;
+		reg-names = "target_data", "rt", "scfg";
+		reg = <0x00 0x43600000 0x00 0x10000>,
+		      <0x00 0x44880000 0x00 0x20000>,
+		      <0x00 0x44860000 0x00 0x20000>;
+		/*
+		 * Marked Disabled:
+		 * Node is incomplete as it is meant for bootloaders and
+		 * firmware on non-MPU processors
+		 */
+		status = "disabled";
+	};
+
 	main_pmx0: pinctrl@f4000 {
-		compatible = "pinctrl-single";
+		bootph-all;
+		compatible = "ti,am6-padconf";
 		reg = <0x00 0xf4000 0x00 0x2ac>;
 		#pinctrl-cells = <1>;
 		pinctrl-single,register-width = <32>;
 		pinctrl-single,function-mask = <0xffffffff>;
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+	};
+
+	main_timer0: timer@2400000 {
+		bootph-all;
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2400000 0x00 0x400>;
+		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 36 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 36 2>;
+		assigned-clock-parents = <&k3_clks 36 3>;
+		power-domains = <&k3_pds 36 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer1: timer@2410000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2410000 0x00 0x400>;
+		interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 37 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 37 2>;
+		assigned-clock-parents = <&k3_clks 37 3>;
+		power-domains = <&k3_pds 37 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer2: timer@2420000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2420000 0x00 0x400>;
+		interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 38 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 38 2>;
+		assigned-clock-parents = <&k3_clks 38 3>;
+		power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer3: timer@2430000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2430000 0x00 0x400>;
+		interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 39 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 39 2>;
+		assigned-clock-parents = <&k3_clks 39 3>;
+		power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer4: timer@2440000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2440000 0x00 0x400>;
+		interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 40 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 40 2>;
+		assigned-clock-parents = <&k3_clks 40 3>;
+		power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer5: timer@2450000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2450000 0x00 0x400>;
+		interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 41 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 41 2>;
+		assigned-clock-parents = <&k3_clks 41 3>;
+		power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer6: timer@2460000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2460000 0x00 0x400>;
+		interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 42 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 42 2>;
+		assigned-clock-parents = <&k3_clks 42 3>;
+		power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer7: timer@2470000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2470000 0x00 0x400>;
+		interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 43 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 43 2>;
+		assigned-clock-parents = <&k3_clks 43 3>;
+		power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_esm: esm@420000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x00 0x420000 0x00 0x1000>;
+		ti,esm-pins = <160>, <161>, <162>, <163>, <177>, <178>;
 	};
 
 	main_uart0: serial@2800000 {
@@ -199,6 +355,7 @@
 		power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 146 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart1: serial@2810000 {
@@ -208,6 +365,7 @@
 		power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 152 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart2: serial@2820000 {
@@ -217,6 +375,7 @@
 		power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 153 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart3: serial@2830000 {
@@ -226,6 +385,7 @@
 		power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 154 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart4: serial@2840000 {
@@ -235,6 +395,7 @@
 		power-domains = <&k3_pds 155 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 155 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart5: serial@2850000 {
@@ -244,6 +405,7 @@
 		power-domains = <&k3_pds 156 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 156 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart6: serial@2860000 {
@@ -253,6 +415,7 @@
 		power-domains = <&k3_pds 158 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 158 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_i2c0: i2c@20000000 {
@@ -264,6 +427,7 @@
 		power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 102 2>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	main_i2c1: i2c@20010000 {
@@ -275,6 +439,7 @@
 		power-domains = <&k3_pds 103 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 103 2>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	main_i2c2: i2c@20020000 {
@@ -286,6 +451,7 @@
 		power-domains = <&k3_pds 104 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 104 2>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	main_i2c3: i2c@20030000 {
@@ -297,6 +463,7 @@
 		power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 105 2>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	main_spi0: spi@20100000 {
@@ -394,8 +561,11 @@
 		ti,clkbuf-sel = <0x7>;
 		ti,otap-del-sel-legacy = <0x0>;
 		ti,otap-del-sel-mmc-hs = <0x0>;
-		ti,otap-del-sel-ddr52 = <0x9>;
-		ti,otap-del-sel-hs200 = <0x6>;
+		ti,otap-del-sel-ddr52 = <0x5>;
+		ti,otap-del-sel-hs200 = <0x5>;
+		ti,itap-del-sel-legacy = <0xa>;
+		ti,itap-del-sel-mmc-hs = <0x1>;
+		status = "disabled";
 	};
 
 	sdhci1: mmc@fa00000 {
@@ -406,19 +576,20 @@
 		clocks = <&k3_clks 58 5>, <&k3_clks 58 6>;
 		clock-names = "clk_ahb", "clk_xin";
 		ti,trm-icp = <0x2>;
-		ti,otap-del-sel-legacy = <0x0>;
+		ti,otap-del-sel-legacy = <0x8>;
 		ti,otap-del-sel-sd-hs = <0x0>;
-		ti,otap-del-sel-sdr12 = <0xf>;
-		ti,otap-del-sel-sdr25 = <0xf>;
-		ti,otap-del-sel-sdr50 = <0xc>;
-		ti,otap-del-sel-sdr104 = <0x6>;
-		ti,otap-del-sel-ddr50 = <0x9>;
-		ti,itap-del-sel-legacy = <0x0>;
-		ti,itap-del-sel-sd-hs = <0x0>;
-		ti,itap-del-sel-sdr12 = <0x0>;
-		ti,itap-del-sel-sdr25 = <0x0>;
+		ti,otap-del-sel-sdr12 = <0x0>;
+		ti,otap-del-sel-sdr25 = <0x0>;
+		ti,otap-del-sel-sdr50 = <0x8>;
+		ti,otap-del-sel-sdr104 = <0x7>;
+		ti,otap-del-sel-ddr50 = <0x4>;
+		ti,itap-del-sel-legacy = <0xa>;
+		ti,itap-del-sel-sd-hs = <0x1>;
+		ti,itap-del-sel-sdr12 = <0xa>;
+		ti,itap-del-sel-sdr25 = <0x1>;
 		ti,clkbuf-sel = <0x7>;
 		bus-width = <4>;
+		status = "disabled";
 	};
 
 	sdhci2: mmc@fa20000 {
@@ -429,23 +600,79 @@
 		clocks = <&k3_clks 184 5>, <&k3_clks 184 6>;
 		clock-names = "clk_ahb", "clk_xin";
 		ti,trm-icp = <0x2>;
-		ti,otap-del-sel-legacy = <0x0>;
+		ti,otap-del-sel-legacy = <0x8>;
 		ti,otap-del-sel-sd-hs = <0x0>;
-		ti,otap-del-sel-sdr12 = <0xf>;
-		ti,otap-del-sel-sdr25 = <0xf>;
-		ti,otap-del-sel-sdr50 = <0xc>;
-		ti,otap-del-sel-sdr104 = <0x6>;
-		ti,otap-del-sel-ddr50 = <0x9>;
-		ti,itap-del-sel-legacy = <0x0>;
-		ti,itap-del-sel-sd-hs = <0x0>;
-		ti,itap-del-sel-sdr12 = <0x0>;
-		ti,itap-del-sel-sdr25 = <0x0>;
+		ti,otap-del-sel-sdr12 = <0x0>;
+		ti,otap-del-sel-sdr25 = <0x0>;
+		ti,otap-del-sel-sdr50 = <0x8>;
+		ti,otap-del-sel-sdr104 = <0x7>;
+		ti,otap-del-sel-ddr50 = <0x8>;
+		ti,itap-del-sel-legacy = <0xa>;
+		ti,itap-del-sel-sd-hs = <0xa>;
+		ti,itap-del-sel-sdr12 = <0xa>;
+		ti,itap-del-sel-sdr25 = <0x1>;
 		ti,clkbuf-sel = <0x7>;
+		status = "disabled";
+	};
+
+	gpu: gpu@fd00000 {
+		compatible = "ti,am62-pvr", "img,pvr-axe116m";
+		reg = <0x00 0x0fd00000 0x00 0x20000>;
+		interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 187 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 187 0>;
+	};
+
+	usbss0: dwc3-usb@f900000 {
+		compatible = "ti,am62-usb";
+		reg = <0x00 0x0f900000 0x00 0x800>;
+		clocks = <&k3_clks 161 3>;
+		clock-names = "ref";
+		ti,syscon-phy-pll-refclk = <&usb0_phy_ctrl 0x0>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		power-domains = <&k3_pds 178 TI_SCI_PD_EXCLUSIVE>;
+		ranges;
+		status = "disabled";
+
+		usb0: usb@31000000 {
+			compatible = "snps,dwc3";
+			reg =<0x00 0x31000000 0x00 0x50000>;
+			interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
+				     <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>; /* irq.0 */
+			interrupt-names = "host", "peripheral";
+			maximum-speed = "high-speed";
+			dr_mode = "otg";
+		};
+	};
+
+	usbss1: dwc3-usb@f910000 {
+		compatible = "ti,am62-usb";
+		reg = <0x00 0x0f910000 0x00 0x800>;
+		clocks = <&k3_clks 162 3>;
+		clock-names = "ref";
+		ti,syscon-phy-pll-refclk = <&usb1_phy_ctrl 0x0>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		power-domains = <&k3_pds 179 TI_SCI_PD_EXCLUSIVE>;
+		ranges;
+		status = "disabled";
+
+		usb1: usb@31100000 {
+			compatible = "snps,dwc3";
+			reg =<0x00 0x31100000 0x00 0x50000>;
+			interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
+				     <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>; /* irq.0 */
+			interrupt-names = "host", "peripheral";
+			maximum-speed = "high-speed";
+			dr_mode = "otg";
+		};
 	};
 
 	fss: bus@fc00000 {
-		compatible = "simple-bus";
+		compatible = "simple-pm-bus";
 		reg = <0x00 0x0fc00000 0x00 0x70000>;
+		power-domains = <&k3_pds 74 TI_SCI_PD_EXCLUSIVE>;
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
@@ -465,6 +692,7 @@
 			power-domains = <&k3_pds 75 TI_SCI_PD_EXCLUSIVE>;
 			#address-cells = <1>;
 			#size-cells = <0>;
+			status = "disabled";
 		};
 	};
 
@@ -523,6 +751,7 @@
 			clocks = <&k3_clks 13 0>;
 			clock-names = "fck";
 			bus_freq = <1000000>;
+			status = "disabled";
 		};
 
 		cpts@3d000 {
@@ -537,6 +766,41 @@
 		};
 	};
 
+	dss: dss@30200000 {
+		compatible = "ti,am625-dss";
+		reg = <0x00 0x30200000 0x00 0x1000>, /* common */
+		      <0x00 0x30202000 0x00 0x1000>, /* vidl1 */
+		      <0x00 0x30206000 0x00 0x1000>, /* vid */
+		      <0x00 0x30207000 0x00 0x1000>, /* ovr1 */
+		      <0x00 0x30208000 0x00 0x1000>, /* ovr2 */
+		      <0x00 0x3020a000 0x00 0x1000>, /* vp1: Used for OLDI */
+		      <0x00 0x3020b000 0x00 0x1000>, /* vp2: Used as DPI Out */
+		      <0x00 0x30201000 0x00 0x1000>; /* common1 */
+		reg-names = "common", "vidl1", "vid",
+			    "ovr1", "ovr2", "vp1", "vp2", "common1";
+		ti,am65x-oldi-io-ctrl = <&dss_oldi_io_ctrl>;
+		power-domains = <&k3_pds 186 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 186 6>,
+			 <&k3_clks 186 0>,
+			 <&k3_clks 186 2>;
+		clock-names = "fck", "vp1", "vp2";
+		interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+
+		dss_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	timesync_router: pinctrl@a40000 {
+		compatible = "pinctrl-single";
+		reg = <0x0 0xa40000 0x0 0x800>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0x000107ff>;
+		status = "disabled";
+	};
+
 	hwspinlock: spinlock@2a000000 {
 		compatible = "ti,am64-hwspinlock";
 		reg = <0x00 0x2a000000 0x00 0x1000>;
@@ -560,6 +824,7 @@
 		power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 51 0>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	ecap1: pwm@23110000 {
@@ -569,6 +834,7 @@
 		power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 52 0>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	ecap2: pwm@23120000 {
@@ -578,6 +844,37 @@
 		power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 53 0>;
 		clock-names = "fck";
+		status = "disabled";
+	};
+
+	eqep0: counter@23200000 {
+		compatible = "ti,am3352-eqep";
+		reg = <0x00 0x23200000 0x00 0x100>;
+		power-domains = <&k3_pds 59 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 59 0>;
+		clock-names = "fck";
+		interrupts = <GIC_SPI 116 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
+	};
+
+	eqep1: counter@23210000 {
+		compatible = "ti,am3352-eqep";
+		reg = <0x00 0x23210000 0x00 0x100>;
+		power-domains = <&k3_pds 60 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 60 0>;
+		clock-names = "fck";
+		interrupts = <GIC_SPI 117 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
+	};
+
+	eqep2: counter@23220000 {
+		compatible = "ti,am3352-eqep";
+		reg = <0x00 0x23220000 0x00 0x100>;
+		power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 62 0>;
+		clock-names = "fck";
+		interrupts = <GIC_SPI 118 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
 	};
 
 	main_mcan0: can@20701000 {
@@ -592,6 +889,52 @@
 			     <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_rti0: watchdog@e000000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x0e000000 0x00 0x100>;
+		clocks = <&k3_clks 125 0>;
+		power-domains = <&k3_pds 125 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 125 0>;
+		assigned-clock-parents = <&k3_clks 125 2>;
+	};
+
+	main_rti1: watchdog@e010000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x0e010000 0x00 0x100>;
+		clocks = <&k3_clks 126 0>;
+		power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 126 0>;
+		assigned-clock-parents = <&k3_clks 126 2>;
+	};
+
+	main_rti2: watchdog@e020000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x0e020000 0x00 0x100>;
+		clocks = <&k3_clks 127 0>;
+		power-domains = <&k3_pds 127 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 127 0>;
+		assigned-clock-parents = <&k3_clks 127 2>;
+	};
+
+	main_rti3: watchdog@e030000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x0e030000 0x00 0x100>;
+		clocks = <&k3_clks 128 0>;
+		power-domains = <&k3_pds 128 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 128 0>;
+		assigned-clock-parents = <&k3_clks 128 2>;
+	};
+
+	main_rti15: watchdog@e0f0000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x0e0f0000 0x00 0x100>;
+		clocks = <&k3_clks 130 0>;
+		power-domains = <&k3_pds 130 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 130 0>;
+		assigned-clock-parents = <&k3_clks 130 2>;
 	};
 
 	epwm0: pwm@23000000 {
@@ -601,6 +944,7 @@
 		power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&epwm_tbclk 0>, <&k3_clks 86 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	epwm1: pwm@23010000 {
@@ -610,6 +954,7 @@
 		power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&epwm_tbclk 1>, <&k3_clks 87 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	epwm2: pwm@23020000 {
@@ -619,5 +964,258 @@
 		power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&epwm_tbclk 2>, <&k3_clks 88 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	mcasp0: audio-controller@2b00000 {
+		compatible = "ti,am33xx-mcasp-audio";
+		reg = <0x00 0x02b00000 0x00 0x2000>,
+		      <0x00 0x02b08000 0x00 0x400>;
+		reg-names = "mpu", "dat";
+		interrupts = <GIC_SPI 236 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "tx", "rx";
+
+		dmas = <&main_bcdma 0 0xc500 0>, <&main_bcdma 0 0x4500 0>;
+		dma-names = "tx", "rx";
+
+		clocks = <&k3_clks 190 0>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 190 0>;
+		assigned-clock-parents = <&k3_clks 190 2>;
+		power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	mcasp1: audio-controller@2b10000 {
+		compatible = "ti,am33xx-mcasp-audio";
+		reg = <0x00 0x02b10000 0x00 0x2000>,
+		      <0x00 0x02b18000 0x00 0x400>;
+		reg-names = "mpu", "dat";
+		interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "tx", "rx";
+
+		dmas = <&main_bcdma 0 0xc501 0>, <&main_bcdma 0 0x4501 0>;
+		dma-names = "tx", "rx";
+
+		clocks = <&k3_clks 191 0>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 191 0>;
+		assigned-clock-parents = <&k3_clks 191 2>;
+		power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	mcasp2: audio-controller@2b20000 {
+		compatible = "ti,am33xx-mcasp-audio";
+		reg = <0x00 0x02b20000 0x00 0x2000>,
+		      <0x00 0x02b28000 0x00 0x400>;
+		reg-names = "mpu", "dat";
+		interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "tx", "rx";
+
+		dmas = <&main_bcdma 0 0xc502 0>, <&main_bcdma 0 0x4502 0>;
+		dma-names = "tx", "rx";
+
+		clocks = <&k3_clks 192 0>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 192 0>;
+		assigned-clock-parents = <&k3_clks 192 2>;
+		power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	ti_csi2rx0: ticsi2rx@30102000 {
+		compatible = "ti,j721e-csi2rx";
+		dmas = <&main_bcdma 0 0x4700 0>, <&main_bcdma 0 0x4701 0>, <&main_bcdma 0 0x4702 0>,
+			<&main_bcdma 0 0x4703 0>;
+		dma-names = "rx0", "rx1", "rx2", "rx3";
+		reg = <0x00 0x30102000 0x00 0x1000>;
+		power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		status = "disabled";
+
+		cdns_csi2rx0: csi-bridge@30101000 {
+			compatible = "cdns,csi2rx";
+			reg = <0x00 0x30101000 0x00 0x1000>;
+			clocks = <&k3_clks 182 0>, <&k3_clks 182 3>, <&k3_clks 182 0>,
+				<&k3_clks 182 0>, <&k3_clks 182 4>, <&k3_clks 182 4>;
+			clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+				"pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+			phys = <&dphy0>;
+			phy-names = "dphy";
+			power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				csi0_port0: port@0 {
+					reg = <0>;
+					status = "disabled";
+				};
+
+				csi0_port1: port@1 {
+					reg = <1>;
+					status = "disabled";
+				};
+
+				csi0_port2: port@2 {
+					reg = <2>;
+					status = "disabled";
+				};
+
+				csi0_port3: port@3 {
+					reg = <3>;
+					status = "disabled";
+				};
+
+				csi0_port4: port@4 {
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
+	dphy0: phy@30110000 {
+		compatible = "cdns,dphy-rx";
+		reg = <0x00 0x30110000 0x00 0x1100>;
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 185 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	gpmc0: memory-controller@3b000000 {
+		status = "disabled";
+		compatible = "ti,am64-gpmc";
+		power-domains = <&k3_pds 80 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 80 0>;
+		clock-names = "fck";
+		reg = <0x00 0x03b000000 0x00 0x400>,
+		      <0x00 0x050000000 0x00 0x8000000>;
+		reg-names = "cfg", "data";
+		interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+		gpmc,num-cs = <3>;
+		gpmc,num-waitpins = <2>;
+		#address-cells = <2>;
+		#size-cells = <1>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	elm0: ecc@25010000 {
+		status = "disabled";
+		compatible = "ti,am3352-elm";
+		reg = <0x00 0x25010000 0x00 0x2000>;
+		interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 54 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 54 0>;
+		clock-names = "fck";
+	};
+
+	ecap2: pwm@23120000 {
+		compatible = "ti,am3352-ecap";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23120000 0x00 0x100>;
+		power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 53 0>;
+		clock-names = "fck";
+	};
+
+	pruss: pruss@30040000 {
+		compatible = "ti,am625-pruss";
+		reg = <0x00 0x30040000 0x00 0x80000>;
+		power-domains = <&k3_pds 81 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x0 0x00 0x30040000 0x80000>;
+
+		pruss_mem: memories@0 {
+			reg = <0x0 0x2000>,
+			      <0x2000 0x2000>,
+			      <0x10000 0x10000>;
+			reg-names = "dram0", "dram1", "shrdram2";
+		};
+
+		pruss_cfg: cfg@26000 {
+			compatible = "ti,pruss-cfg", "syscon";
+			reg = <0x26000 0x200>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0x26000 0x2000>;
+
+			clocks {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				pruss_coreclk_mux: coreclk-mux@3c {
+					reg = <0x3c>;
+					#clock-cells = <0>;
+					clocks = <&k3_clks 81 0>,  /* pruss_core_clk */
+						 <&k3_clks 81 20>; /* pruss_iclk */
+					assigned-clocks = <&pruss_coreclk_mux>;
+					assigned-clock-parents = <&k3_clks 81 20>;
+				};
+
+				pruss_iepclk_mux: iepclk-mux@30 {
+					reg = <0x30>;
+					#clock-cells = <0>;
+					clocks = <&k3_clks 81 3>,	/* pruss_iep_clk */
+						 <&pruss_coreclk_mux>;	/* pruss_coreclk_mux */
+					assigned-clocks = <&pruss_iepclk_mux>;
+					assigned-clock-parents = <&pruss_coreclk_mux>;
+				};
+			};
+		};
+
+		pruss_intc: interrupt-controller@20000 {
+			compatible = "ti,pruss-intc";
+			reg = <0x20000 0x2000>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "host_intr0", "host_intr1",
+					  "host_intr2", "host_intr3",
+					  "host_intr4", "host_intr5",
+					  "host_intr6", "host_intr7";
+		};
+
+		pru0: pru@34000 {
+			compatible = "ti,am625-pru";
+			reg = <0x34000 0x3000>,
+			      <0x22000 0x100>,
+			      <0x22400 0x100>;
+			reg-names = "iram", "control", "debug";
+			firmware-name = "am62x-pru0-fw";
+			interrupt-parent = <&pruss_intc>;
+			interrupts = <16 2 2>;
+			interrupt-names = "vring";
+		};
+
+		pru1: pru@38000 {
+			compatible = "ti,am625-pru";
+			reg = <0x38000 0x3000>,
+			      <0x24000 0x100>,
+			      <0x24400 0x100>;
+			reg-names = "iram", "control", "debug";
+			firmware-name = "am62x-pru1-fw";
+			interrupt-parent = <&pruss_intc>;
+			interrupts = <18 3 3>;
+			interrupt-names = "vring";
+		};
 	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -7,6 +7,7 @@
 
 &cbass_mcu {
 	mcu_pmx0: pinctrl@4084000 {
+		bootph-all;
 		compatible = "pinctrl-single";
 		reg = <0x00 0x04084000 0x00 0x88>;
 		#pinctrl-cells = <1>;
@@ -14,6 +15,57 @@
 		pinctrl-single,function-mask = <0xffffffff>;
 	};
 
+	/*
+	 * The MCU domain timer interrupts are routed only to the ESM module,
+	 * and not currently available for Linux. The MCU domain timers are
+	 * of limited use without interrupts, and likely reserved by the ESM.
+	 */
+	mcu_timer0: timer@4800000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x4800000 0x00 0x400>;
+		clocks = <&k3_clks 35 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		status = "reserved";
+	};
+
+	mcu_timer1: timer@4810000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x4810000 0x00 0x400>;
+		clocks = <&k3_clks 48 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 48 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		status = "reserved";
+	};
+
+	mcu_timer2: timer@4820000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x4820000 0x00 0x400>;
+		clocks = <&k3_clks 49 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 49 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		status = "reserved";
+	};
+
+	mcu_timer3: timer@4830000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x4830000 0x00 0x400>;
+		clocks = <&k3_clks 50 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 50 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		status = "reserved";
+	};
+
+	mcu_esm: esm@4100000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x00 0x4100000 0x00 0x1000>;
+		ti,esm-pins = <0>, <1>, <2>, <85>;
+	};
+
 	mcu_uart0: serial@4a00000 {
 		compatible = "ti,am64-uart", "ti,am654-uart";
 		reg = <0x00 0x04a00000 0x00 0x100>;
@@ -21,6 +73,7 @@
 		power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 149 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	mcu_i2c0: i2c@4900000 {
@@ -32,6 +85,7 @@
 		power-domains = <&k3_pds 106 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 106 2>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	mcu_spi0: spi@4b00000 {
@@ -83,4 +137,54 @@
 		clocks = <&k3_clks 79 0>;
 		clock-names = "gpio";
 	};
+
+	mcu_rti0: watchdog@4880000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x04880000 0x00 0x100>;
+		clocks = <&k3_clks 131 0>;
+		power-domains = <&k3_pds 131 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 131 0>;
+		assigned-clock-parents = <&k3_clks 131 2>;
+		/* Tightly coupled to M4F */
+		status = "reserved";
+	};
+
+	mcu_m4fss: m4fss@5000000 {
+		compatible = "ti,am64-m4fss";
+		reg = <0x00 0x5000000 0x00 0x30000>,
+		<0x00 0x5040000 0x00 0x10000>;
+		reg-names = "iram", "dram";
+		ti,sci = <&dmsc>;
+		ti,sci-dev-id = <9>;
+		ti,sci-proc-ids = <0x18 0xff>;
+		resets = <&k3_reset 9 1>;
+		firmware-name = "am62-mcu-m4f0_0-fw";
+		wakeup-source;
+	};
+
+	mcu_mcan0: can@4e08000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x4e08000 0x00 0x200>,
+		      <0x00 0x4e00000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 188 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 188 6>, <&k3_clks 188 1>;
+		clock-names = "hclk", "cclk";
+		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		wakeup-source;
+		status = "disabled";
+	};
+
+	mcu_mcan1: can@4e18000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x4e18000 0x00 0x200>,
+		      <0x00 0x4e10000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 189 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 189 6>, <&k3_clks 189 1>;
+		clock-names = "hclk", "cclk";
+		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		wakeup-source;
+		status = "disabled";
+	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p5.dtsi b/arch/arm64/boot/dts/ti/k3-am62p5.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62p5.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p5.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for the AM62P5 SoC family (quad core)
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * TRM: https://www.ti.com/lit/pdf/spruj83
+ */
+
+/dts-v1/;
+
+#include "k3-am62p.dtsi"
+
+/ {
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0: cluster0 {
+				core0 {
+					cpu = <&cpu0>;
+				};
+
+				core1 {
+					cpu = <&cpu1>;
+				};
+
+				core2 {
+					cpu = <&cpu2>;
+				};
+
+				core3 {
+					cpu = <&cpu3>;
+				};
+			};
+		};
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a53";
+			reg = <0x000>;
+			device_type = "cpu";
+			enable-method = "psci";
+			i-cache-size = <0x8000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <128>;
+			next-level-cache = <&l2_0>;
+			operating-points-v2 = <&a53_opp_table>;
+			clocks = <&k3_clks 135 0>;
+		};
+
+		cpu1: cpu@1 {
+			compatible = "arm,cortex-a53";
+			reg = <0x001>;
+			device_type = "cpu";
+			enable-method = "psci";
+			i-cache-size = <0x8000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <128>;
+			next-level-cache = <&l2_0>;
+			operating-points-v2 = <&a53_opp_table>;
+			clocks = <&k3_clks 136 0>;
+		};
+
+		cpu2: cpu@2 {
+			compatible = "arm,cortex-a53";
+			reg = <0x002>;
+			device_type = "cpu";
+			enable-method = "psci";
+			i-cache-size = <0x8000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <128>;
+			next-level-cache = <&l2_0>;
+			operating-points-v2 = <&a53_opp_table>;
+			clocks = <&k3_clks 137 0>;
+		};
+
+		cpu3: cpu@3 {
+			compatible = "arm,cortex-a53";
+			reg = <0x003>;
+			device_type = "cpu";
+			enable-method = "psci";
+			i-cache-size = <0x8000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <128>;
+			next-level-cache = <&l2_0>;
+			operating-points-v2 = <&a53_opp_table>;
+			clocks = <&k3_clks 138 0>;
+		};
+	};
+
+	a53_opp_table: opp-table {
+		compatible = "operating-points-v2-ti-cpu";
+		opp-shared;
+		syscon = <&wkup_conf>;
+
+		opp-200000000 {
+			opp-hz = /bits/ 64 <200000000>;
+			opp-supported-hw = <0x01 0x0007>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-400000000 {
+			opp-hz = /bits/ 64 <400000000>;
+			opp-supported-hw = <0x01 0x0007>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-supported-hw = <0x01 0x0007>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-supported-hw = <0x01 0x0007>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+			opp-supported-hw = <0x01 0x0006>;
+			clock-latency-ns = <6000000>;
+		};
+
+		opp-1250000000 {
+			opp-hz = /bits/ 64 <1250000000>;
+			opp-supported-hw = <0x01 0x0004>;
+			clock-latency-ns = <6000000>;
+			opp-suspend;
+		};
+	};
+
+	l2_0: l2-cache0 {
+		compatible = "cache";
+		cache-unified;
+		cache-level = <2>;
+		cache-size = <0x80000>;
+		cache-line-size = <64>;
+		cache-sets = <512>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p5-sk-dsi-rpi-7inch-panel.dtso b/arch/arm64/boot/dts/ti/k3-am62p5-sk-dsi-rpi-7inch-panel.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk-dsi-rpi-7inch-panel.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk-dsi-rpi-7inch-panel.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for RPi 7inch touchscreen panel interfaced with DSI on
+ * AM62P5-SK EVM.
+ *
+ * RPi DSI Panel: https://www.raspberrypi.com/products/raspberry-pi-touch-display/
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	panel0 {
+		compatible = "raspberrypi,7inch-dsi", "simple-panel";
+		backlight = <&display_reg>;
+		power-supply = <&display_reg>;
+		port {
+			panel_in: endpoint {
+				remote-endpoint = <&panel_bridge_out>;
+			};
+		};
+	};
+
+	bridge_reg: bridge-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "bridge-reg";
+		gpio = <&display_reg 0 0>;
+		vin-supply = <&display_reg>;
+		enable-active-high;
+	};
+};
+
+&dphy_tx0 {
+	status = "okay";
+};
+
+&main_i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	display_reg: regulator@45 {
+		compatible = "raspberrypi,7inch-touchscreen-panel-regulator";
+		reg = <0x45>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
+
+&dss1 {
+	status = "okay";
+};
+
+&dss1_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* DSS1-VP1: DSI Output */
+	port@1 {
+		reg = <1>;
+
+		dss1_dpi1_out: endpoint {
+			remote-endpoint = <&dsi0_in>;
+		};
+	};
+};
+
+&dsi0 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+			dsi0_out: endpoint {
+				remote-endpoint = <&panel_bridge_in>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+			dsi0_in: endpoint {
+				remote-endpoint = <&dss1_dpi1_out>;
+			};
+		};
+	};
+
+	bridge@0 {
+		status = "okay";
+		compatible = "toshiba,tc358762";
+		reg = <0>;
+		vddc-supply = <&bridge_reg>;
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				panel_bridge_in: endpoint {
+					remote-endpoint = <&dsi0_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				panel_bridge_out: endpoint {
+					remote-endpoint = <&panel_in>;
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p5-sk-dss-shared-mode.dtso b/arch/arm64/boot/dts/ti/k3-am62p5-sk-dss-shared-mode.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk-dss-shared-mode.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk-dss-shared-mode.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT overlay to enable display sharing mode for AM62P DSS0
+ * This is compatible with AM62P Device Manager firmware labelled as
+ * "dss_display_share.wkup-r5f0_0.release.strip.out"
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+&dss0 {
+	ti,dss-shared-mode;
+	ti,dss-shared-mode-vp = "vp1";
+	ti,dss-shared-mode-vp-owned = <0>;
+	ti,dss-shared-mode-common = "common1";
+	ti,dss-shared-mode-planes = "vid";
+	ti,dss-shared-mode-plane-zorder = <0>;
+	interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk.dts	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,844 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for the AM62P5-SK
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * Schematics: https://www.ti.com/lit/zip/sprr487
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
+#include "k3-am62p5.dtsi"
+
+/ {
+	compatible = "ti,am62p5-sk", "ti,am62p5";
+	model = "Texas Instruments AM62P5 SK";
+
+	aliases {
+		serial0 = &wkup_uart0;
+		serial2 = &main_uart0;
+		serial3 = &main_uart1;
+		mmc0 = &sdhci0;
+		mmc1 = &sdhci1;
+		mmc2 = &sdhci2;
+		spi0 = &ospi0;
+		ethernet0 = &cpsw_port1;
+		ethernet1 = &cpsw_port2;
+		usb0 = &usb0;
+		usb1 = &usb1;
+	};
+
+	chosen {
+		stdout-path = &main_uart0;
+	};
+
+	memory@80000000 {
+		/* 8G RAM */
+		reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
+		      <0x00000008 0x80000000 0x00000001 0x80000000>;
+		device_type = "memory";
+		bootph-pre-ram;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x00 0x24000000>;
+			linux,cma-default;
+		};
+
+		rtos_ipc_memory_region: rtos-ipc-memory@9b500000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9b500000 0x00 0x00300000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core0_dma_memory_region: mcu-r5fss-dma-memory-region@9b800000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9b800000 0x00 0x00100000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core0_memory_region: mcu-r5fss-memory-region@9b900000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9b900000 0x00 0x00f00000>;
+			no-map;
+		};
+
+		wkup_r5fss0_core0_dma_memory_region: r5f-dma-memory@9c800000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9c800000 0x00 0x00100000>;
+			no-map;
+		};
+
+		wkup_r5fss0_core0_memory_region: r5f-memory@9c900000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9c900000 0x00 0x01e00000>;
+			no-map;
+		};
+
+		secure_tfa_ddr: tfa@9e780000 {
+			reg = <0x00 0x9e780000 0x00 0x80000>;
+			no-map;
+		};
+
+		secure_ddr: optee@9e800000 {
+			reg = <0x00 0x9e800000 0x00 0x01800000>; /* for OP-TEE */
+			no-map;
+		};
+	};
+
+	vmain_pd: regulator-0 {
+		/* TPS65988 PD CONTROLLER OUTPUT */
+		compatible = "regulator-fixed";
+		regulator-name = "vmain_pd";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+		bootph-all;
+	};
+
+	vcc_5v0: regulator-1 {
+		/* Output of TPS630702RNMR */
+		compatible = "regulator-fixed";
+		regulator-name = "vcc_5v0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&vmain_pd>;
+		regulator-always-on;
+		regulator-boot-on;
+		bootph-all;
+	};
+
+	vdd_mmc1: regulator-2 {
+		/* TPS22918DBVR */
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_mmc1";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		enable-active-high;
+		gpio = <&exp1 3 GPIO_ACTIVE_HIGH>;
+		bootph-all;
+	};
+
+	vddshv_sdio: regulator-3 {
+		compatible = "regulator-gpio";
+		regulator-name = "vddshv_sdio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&vddshv_sdio_pins_default>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		gpios = <&main_gpio0 31 GPIO_ACTIVE_HIGH>;
+		states = <1800000 0x0>,
+			 <3300000 0x1>;
+		bootph-all;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&usr_led_pins_default>;
+
+		led-0 {
+			label = "am62-sk:green:heartbeat";
+			gpios = <&main_gpio1 49 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			function = LED_FUNCTION_HEARTBEAT;
+			default-state = "off";
+		};
+	};
+
+	opp-table {
+		/* Add 1.4GHz OPP for am62p5-sk board. Requires VDD_CORE at 0v85 */
+		opp-1400000000 {
+			opp-hz = /bits/ 64 <1400000000>;
+			opp-supported-hw = <0x01 0x0004>;
+			clock-latency-ns = <6000000>;
+		};
+	};
+
+	tlv320_mclk: clk-0 {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <12288000>;
+	};
+
+	codec_audio: sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "AM62x-SKEVM";
+		simple-audio-card,widgets =
+			"Headphone",	"Headphone Jack",
+			"Line",		"Line In",
+			"Microphone",	"Microphone Jack";
+		simple-audio-card,routing =
+			"Headphone Jack",	"HPLOUT",
+			"Headphone Jack",	"HPROUT",
+			"LINE1L",		"Line In",
+			"LINE1R",		"Line In",
+			"MIC3R",		"Microphone Jack",
+			"Microphone Jack",	"Mic Bias";
+		simple-audio-card,format = "dsp_b";
+		simple-audio-card,bitclock-master = <&sound_master>;
+		simple-audio-card,frame-master = <&sound_master>;
+		simple-audio-card,bitclock-inversion;
+
+		simple-audio-card,cpu {
+			sound-dai = <&mcasp1>;
+		};
+
+		sound_master: simple-audio-card,codec {
+			sound-dai = <&tlv320aic3106>;
+			clocks = <&tlv320_mclk>;
+		};
+	};
+
+	hdmi0: connector-hdmi {
+		compatible = "hdmi-connector";
+		label = "hdmi";
+		type = "a";
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&sii9022_out>;
+			};
+		};
+	};
+};
+
+&main_gpio0 {
+	bootph-all;
+};
+
+&main_gpio1 {
+	bootph-all;
+};
+
+&main_pmx0 {
+	bootph-all;
+
+	main_i2c0_pins_default: main-i2c0-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x01e0, PIN_INPUT_PULLUP, 0) /* (B25) I2C0_SCL */
+			AM62PX_IOPAD(0x01e4, PIN_INPUT_PULLUP, 0) /* (A24) I2C0_SDA */
+		>;
+	};
+
+	main_i2c1_pins_default: main-i2c1-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x01e8, PIN_INPUT_PULLUP, 0) /* (C24) I2C1_SCL */
+			AM62PX_IOPAD(0x01ec, PIN_INPUT_PULLUP, 0) /* (B24) I2C1_SDA */
+		>;
+		bootph-all;
+	};
+
+	main_i2c2_pins_default: main-i2c2-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x00b0, PIN_INPUT_PULLUP, 1) /* (T22) GPMC0_CSn2.I2C2_SCL */
+			AM62PX_IOPAD(0x00b4, PIN_INPUT_PULLUP, 1) /* (U25) GPMC0_CSn3.I2C2_SDA */
+		>;
+	};
+
+	main_gpio1_ioexp_intr_pins_default: main-gpio1-ioexp-intr-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x01d4, PIN_INPUT, 7) /* (C22) UART0_RTSn.GPIO1_23 */
+		>;
+	};
+
+	main_mcasp1_pins_default: main-mcasp1-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0090, PIN_INPUT, 2) /* (U24) GPMC0_BE0n_CLE.MCASP1_ACLKX */
+			AM62PX_IOPAD(0x0098, PIN_INPUT, 2) /* (AA24) GPMC0_WAIT0.MCASP1_AFSX */
+			AM62PX_IOPAD(0x008c, PIN_OUTPUT, 2) /* (T25) GPMC0_WEn.MCASP1_AXR0 */
+			AM62PX_IOPAD(0x0084, PIN_INPUT, 2) /* (R25) GPMC0_ADVn_ALE.MCASP1_AXR2 */
+		>;
+	};
+
+	main_mdio1_pins_default: main-mdio1-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0160, PIN_OUTPUT, 0) /* (F17) MDIO0_MDC */
+			AM62PX_IOPAD(0x015c, PIN_INPUT, 0) /* (F16) MDIO0_MDIO */
+		>;
+	};
+
+	main_mmc1_pins_default: main-mmc1-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x023c, PIN_INPUT, 0) /* (H20) MMC1_CMD */
+			AM62PX_IOPAD(0x0234, PIN_OUTPUT, 0) /* (J24) MMC1_CLK */
+			AM62PX_IOPAD(0x0230, PIN_INPUT, 0) /* (H21) MMC1_DAT0 */
+			AM62PX_IOPAD(0x022c, PIN_INPUT_PULLUP, 0) /* (H23) MMC1_DAT1 */
+			AM62PX_IOPAD(0x0228, PIN_INPUT_PULLUP, 0) /* (H22) MMC1_DAT2 */
+			AM62PX_IOPAD(0x0224, PIN_INPUT_PULLUP, 0) /* (H25) MMC1_DAT3 */
+			AM62PX_IOPAD(0x0240, PIN_INPUT, 0) /* (D23) MMC1_SDCD */
+		>;
+		bootph-all;
+	};
+
+	main_mmc2_pins_default: main-mmc2-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0120, PIN_INPUT, 0) /* (K24) MMC2_CMD */
+			AM62PX_IOPAD(0x0118, PIN_OUTPUT, 0) /* (K21) MMC2_CLK */
+			AM62PX_IOPAD(0x011C, PIN_INPUT, 0) /* () MMC2_CLKLB */
+			AM62PX_IOPAD(0x0114, PIN_INPUT, 0) /* (K23) MMC2_DAT0 */
+			AM62PX_IOPAD(0x0110, PIN_INPUT_PULLUP, 0) /* (K22) MMC2_DAT1 */
+			AM62PX_IOPAD(0x010c, PIN_INPUT_PULLUP, 0) /* (L20) MMC2_DAT2 */
+			AM62PX_IOPAD(0x0108, PIN_INPUT_PULLUP, 0) /* (L21) MMC2_DAT3 */
+		>;
+		bootph-all;
+	};
+
+	main_rgmii1_pins_default: main-rgmii1-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x014c, PIN_INPUT, 0) /* (B15) RGMII1_RD0 */
+			AM62PX_IOPAD(0x0150, PIN_INPUT, 0) /* (B16) RGMII1_RD1 */
+			AM62PX_IOPAD(0x0154, PIN_INPUT, 0) /* (A14) RGMII1_RD2 */
+			AM62PX_IOPAD(0x0158, PIN_INPUT, 0) /* (B14) RGMII1_RD3 */
+			AM62PX_IOPAD(0x0148, PIN_INPUT, 0) /* (A16) RGMII1_RXC */
+			AM62PX_IOPAD(0x0144, PIN_INPUT, 0) /* (A15) RGMII1_RX_CTL */
+			AM62PX_IOPAD(0x0134, PIN_INPUT, 0) /* (A18) RGMII1_TD0 */
+			AM62PX_IOPAD(0x0138, PIN_INPUT, 0) /* (C17) RGMII1_TD1 */
+			AM62PX_IOPAD(0x013c, PIN_INPUT, 0) /* (A17) RGMII1_TD2 */
+			AM62PX_IOPAD(0x0140, PIN_INPUT, 0) /* (C16) RGMII1_TD3 */
+			AM62PX_IOPAD(0x0130, PIN_INPUT, 0) /* (B17) RGMII1_TXC */
+			AM62PX_IOPAD(0x012c, PIN_INPUT, 0) /* (B18) RGMII1_TX_CTL */
+		>;
+		bootph-all;
+	};
+
+	main_rgmii2_pins_default: main-rgmii2-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0184, PIN_INPUT, 0) /* (E19) RGMII2_RD0 */
+			AM62PX_IOPAD(0x0188, PIN_INPUT, 0) /* (E16) RGMII2_RD1 */
+			AM62PX_IOPAD(0x018c, PIN_INPUT, 0) /* (E17) RGMII2_RD2 */
+			AM62PX_IOPAD(0x0190, PIN_INPUT, 0) /* (C19) RGMII2_RD3 */
+			AM62PX_IOPAD(0x0180, PIN_INPUT, 0) /* (D19) RGMII2_RXC */
+			AM62PX_IOPAD(0x017c, PIN_INPUT, 0) /* (F19) RGMII2_RX_CTL */
+			AM62PX_IOPAD(0x016c, PIN_INPUT, 0) /* (B19) RGMII2_TD0 */
+			AM62PX_IOPAD(0x0170, PIN_INPUT, 0) /* (A21) RGMII2_TD1 */
+			AM62PX_IOPAD(0x0174, PIN_INPUT, 0) /* (D17) RGMII2_TD2 */
+			AM62PX_IOPAD(0x0178, PIN_INPUT, 0) /* (A19) RGMII2_TD3 */
+			AM62PX_IOPAD(0x0168, PIN_INPUT, 0) /* (D16) RGMII2_TXC */
+			AM62PX_IOPAD(0x0164, PIN_INPUT, 0) /* (A20) RGMII2_TX_CTL */
+		>;
+		bootph-all;
+	};
+
+	main_uart0_pins_default: main-uart0-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x1c8, PIN_INPUT, 0)	/* (A22) UART0_RXD */
+			AM62PX_IOPAD(0x1cc, PIN_OUTPUT, 0)	/* (B22) UART0_TXD */
+		>;
+		bootph-all;
+	};
+
+	main_uart1_pins_default: main-uart1-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0194, PIN_INPUT, 2) /* (D25) MCASP0_AXR3.UART1_CTSn */
+			AM62PX_IOPAD(0x0198, PIN_OUTPUT, 2) /* (E25) MCASP0_AXR2.UART1_RTSn */
+			AM62PX_IOPAD(0x01ac, PIN_INPUT, 2) /* (G23) MCASP0_AFSR.UART1_RXD */
+			AM62PX_IOPAD(0x01b0, PIN_OUTPUT, 2) /* (G20) MCASP0_ACLKR.UART1_TXD */
+		>;
+		bootph-all;
+	};
+
+	main_usb1_pins_default: main-usb1-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0258, PIN_INPUT, 0) /* (G21) USB1_DRVVBUS */
+		>;
+	};
+
+	main_wlirq_pins_default: main-wlirq-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0128, PIN_INPUT, 7) /* (K25) MMC2_SDWP.GPIO0_72 */
+		>;
+	};
+
+	ospi0_pins_default: ospi0-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0000, PIN_OUTPUT, 0) /* (P23) OSPI0_CLK */
+			AM62PX_IOPAD(0x002c, PIN_OUTPUT, 0) /* (M25) OSPI0_CSn0 */
+			AM62PX_IOPAD(0x000c, PIN_INPUT, 0) /* (L25) OSPI0_D0 */
+			AM62PX_IOPAD(0x0010, PIN_INPUT, 0) /* (N24) OSPI0_D1 */
+			AM62PX_IOPAD(0x0014, PIN_INPUT, 0) /* (N25) OSPI0_D2 */
+			AM62PX_IOPAD(0x0018, PIN_INPUT, 0) /* (M24) OSPI0_D3 */
+			AM62PX_IOPAD(0x001c, PIN_INPUT, 0) /* (N21) OSPI0_D4 */
+			AM62PX_IOPAD(0x0020, PIN_INPUT, 0) /* (N22) OSPI0_D5 */
+			AM62PX_IOPAD(0x0024, PIN_INPUT, 0) /* (P21) OSPI0_D6 */
+			AM62PX_IOPAD(0x0028, PIN_INPUT, 0) /* (N20) OSPI0_D7 */
+			AM62PX_IOPAD(0x0008, PIN_INPUT, 0) /* (P22) OSPI0_DQS */
+		>;
+		bootph-all;
+	};
+
+	usr_led_pins_default: usr-led-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0244, PIN_INPUT, 7) /* (D24) MMC1_SDWP.GPIO1_49 */
+		>;
+	};
+
+	vddshv_sdio_pins_default: vddshvr-sdio-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x007c, PIN_INPUT, 7) /* (Y25) GPMC0_CLK.GPIO0_31 */
+		>;
+		bootph-all;
+	};
+
+	wlan_en_pins_default: wlan-en-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0124, PIN_INPUT, 7) /* (J25) MMC2_SDCD.GPIO0_71 */
+		>;
+	};
+
+	main_dpi_pins_default: main-dpi-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0100, PIN_OUTPUT, 0) /* (W20) VOUT0_VSYNC */
+			AM62PX_IOPAD(0x00f8, PIN_OUTPUT, 0) /* (AC20) VOUT0_HSYNC */
+			AM62PX_IOPAD(0x0104, PIN_OUTPUT, 0) /* (Y21) VOUT0_PCLK */
+			AM62PX_IOPAD(0x00fc, PIN_OUTPUT, 0) /* (W21) VOUT0_DE */
+			AM62PX_IOPAD(0x00b8, PIN_OUTPUT, 0) /* (AE24) VOUT0_DATA0 */
+			AM62PX_IOPAD(0x00bc, PIN_OUTPUT, 0) /* (W23) VOUT0_DATA1 */
+			AM62PX_IOPAD(0x00c0, PIN_OUTPUT, 0) /* (AA23) VOUT0_DATA2 */
+			AM62PX_IOPAD(0x00c4, PIN_OUTPUT, 0) /* (Y23) VOUT0_DATA3 */
+			AM62PX_IOPAD(0x00c8, PIN_OUTPUT, 0) /* (AB23) VOUT0_DATA4 */
+			AM62PX_IOPAD(0x00cc, PIN_OUTPUT, 0) /* (AD23) VOUT0_DATA5 */
+			AM62PX_IOPAD(0x00d0, PIN_OUTPUT, 0) /* (AC23) VOUT0_DATA6 */
+			AM62PX_IOPAD(0x00d4, PIN_OUTPUT, 0) /* (AE23) VOUT0_DATA7 */
+			AM62PX_IOPAD(0x00d8, PIN_OUTPUT, 0) /* (AE22) VOUT0_DATA8 */
+			AM62PX_IOPAD(0x00dc, PIN_OUTPUT, 0) /* (AC22) VOUT0_DATA9 */
+			AM62PX_IOPAD(0x00e0, PIN_OUTPUT, 0) /* (W22) VOUT0_DATA10 */
+			AM62PX_IOPAD(0x00e4, PIN_OUTPUT, 0) /* (AE21) VOUT0_DATA11 */
+			AM62PX_IOPAD(0x00e8, PIN_OUTPUT, 0) /* (AD21) VOUT0_DATA12 */
+			AM62PX_IOPAD(0x00ec, PIN_OUTPUT, 0) /* (AC21) VOUT0_DATA13 */
+			AM62PX_IOPAD(0x00f0, PIN_OUTPUT, 0) /* (AA20) VOUT0_DATA14 */
+			AM62PX_IOPAD(0x00f4, PIN_OUTPUT, 0) /* (Y20) VOUT0_DATA15 */
+			AM62PX_IOPAD(0x005c, PIN_OUTPUT, 1) /* (AC25) GPMC0_AD8.VOUT0_DATA16 */
+			AM62PX_IOPAD(0x0060, PIN_OUTPUT, 1) /* (AB25) GPMC0_AD9.VOUT0_DATA17 */
+			AM62PX_IOPAD(0x0064, PIN_OUTPUT, 1) /* (AA25) GPMC0_AD10.VOUT0_DATA18 */
+			AM62PX_IOPAD(0x0068, PIN_OUTPUT, 1) /* (W24) GPMC0_AD11.VOUT0_DATA19 */
+			AM62PX_IOPAD(0x006c, PIN_OUTPUT, 1) /* (Y24) GPMC0_AD12.VOUT0_DATA20 */
+			AM62PX_IOPAD(0x0070, PIN_OUTPUT, 1) /* (AD25) GPMC0_AD13.VOUT0_DATA21 */
+			AM62PX_IOPAD(0x0074, PIN_OUTPUT, 1) /* (AB24) GPMC0_AD14.VOUT0_DATA22 */
+			AM62PX_IOPAD(0x0078, PIN_OUTPUT, 1) /* (AC24) GPMC0_AD15.VOUT0_DATA23 */
+			AM62PX_IOPAD(0x009c, PIN_OUTPUT, 1) /* (AD24) GPMC0_WAIT1.VOUT0_EXTPCLKIN */
+		>;
+	};
+};
+
+&main_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c0_pins_default>;
+	clock-frequency = <400000>;
+};
+
+&main_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c0_pins_default>;
+	clock-frequency = <400000>;
+
+	typec_pd0: tps6598x@3f {
+		compatible = "ti,tps6598x";
+		reg = <0x3f>;
+
+		connector {
+			compatible = "usb-c-connector";
+			label = "USB-C";
+			self-powered;
+			data-role = "dual";
+			power-role = "sink";
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				port@0 {
+					reg = <0>;
+					usb_con_hs: endpoint {
+						remote-endpoint = <&usb0_hs_ep>;
+					};
+				};
+			};
+		};
+	};
+};
+
+&main_i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c1_pins_default>;
+	clock-frequency = <100000>;
+	bootph-all;
+
+	tlv320aic3106: audio-codec@1b {
+		#sound-dai-cells = <0>;
+		compatible = "ti,tlv320aic3106";
+		reg = <0x1b>;
+		ai3x-micbias-vg = <1>;  /* 2.0V */
+	};
+
+	exp1: gpio@22 {
+		compatible = "ti,tca6424";
+		reg = <0x22>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names = "OLDI_INT#", "x8_NAND_DETECT",
+				   "UART1_FET_SEL", "MMC1_SD_EN",
+				   "VPP_EN", "EXP_PS_3V3_EN",
+				   "UART1_FET_BUF_EN", "EXP_HAT_DETECT",
+				   "DSI_GPIO0", "DSI_GPIO1",
+				   "OLDI_EDID", "BT_UART_WAKE_SOC_3V3",
+				   "USB_TYPEA_OC_INDICATION", "CSI_GPIO0",
+				   "CSI_GPIO1", "WLAN_ALERTn",
+				   "HDMI_INTn", "TEST_GPIO2",
+				   "MCASP1_FET_EN", "MCASP1_BUF_BT_EN",
+				   "MCASP1_FET_SEL", "DSI_EDID",
+				   "PD_I2C_IRQ", "IO_EXP_TEST_LED";
+
+		interrupt-parent = <&main_gpio1>;
+		interrupts = <23 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&main_gpio1_ioexp_intr_pins_default>;
+		bootph-all;
+	};
+
+	exp2: gpio@23 {
+		compatible = "ti,tca6424";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names = "BT_EN_SOC", "EXP_PS_5V0_EN",
+				   "", "",
+				   "", "",
+				   "", "",
+				   "WL_LT_EN", "",
+				   "TP3", "TP6",
+				   "TP4", "TP7",
+				   "TP5", "TP8",
+				   "SoC_I2C2_MCAN_SEL", "GPIO_HDMI_RSTn",
+				   "GPIO_CPSW2_RST", "GPIO_CPSW1_RST",
+				   "GPIO_OLDI_RSTn", "GPIO_AUD_RSTn",
+				   "GPIO_eMMC_RSTn", "SoC_WLAN_SDIO_RST";
+	};
+
+	sii9022: bridge-hdmi@3b {
+		compatible = "sil,sii9022";
+		reg = <0x3b>;
+		interrupt-parent = <&exp1>;
+		interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
+		#sound-dai-cells = <0>;
+		sil,i2s-data-lanes = < 0 >;
+
+		hdmi_tx_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/*
+			 * HDMI can be serviced with 3 potential VPs -
+			 * (DSS0 VP1 / DSS1 VP0 / DSS1 VP1).
+			 * For now, we will service it with DSS0 VP1.
+			 */
+			port@0 {
+				reg = <0>;
+				sii9022_in: endpoint {
+					remote-endpoint = <&dss0_dpi1_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				sii9022_out: endpoint {
+					remote-endpoint = <&hdmi_connector_in>;
+				};
+			};
+		};
+	};
+};
+
+&main_i2c2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c2_pins_default>;
+	clock-frequency = <400000>;
+};
+
+&sdhci0 {
+	status = "okay";
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
+	bootph-all;
+};
+
+&sdhci1 {
+	/* SD/MMC */
+	status = "okay";
+	vmmc-supply = <&vdd_mmc1>;
+	vqmmc-supply = <&vddshv_sdio>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mmc1_pins_default>;
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
+	bootph-all;
+};
+
+&cpsw3g {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_rgmii1_pins_default>,
+		    <&main_rgmii2_pins_default>;
+};
+
+&cpsw_port1 {
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&cpsw3g_phy0>;
+};
+
+&cpsw_port2 {
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&cpsw3g_phy1>;
+};
+
+&cpsw3g_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mdio1_pins_default>;
+
+	cpsw3g_phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+
+	cpsw3g_phy1: ethernet-phy@1 {
+		reg = <1>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+};
+
+&usbss0 {
+	status = "okay";
+	ti,vbus-divider;
+};
+
+&usbss1 {
+	status = "okay";
+	ti,vbus-divider;
+};
+
+&usb0 {
+	usb-role-switch;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@0 {
+		reg = <0>;
+		usb0_hs_ep: endpoint {
+			remote-endpoint = <&usb_con_hs>;
+		};
+	};
+};
+
+&usb1 {
+	dr_mode = "host";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_usb1_pins_default>;
+};
+
+&mcasp1 {
+	status = "okay";
+	#sound-dai-cells = <0>;
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcasp1_pins_default>;
+
+	op-mode = <0>;          /* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+
+	serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+	       1 0 2 0
+	       0 0 0 0
+	       0 0 0 0
+	       0 0 0 0
+	>;
+	tx-num-evt = <32>;
+	rx-num-evt = <32>;
+};
+
+&fss {
+	bootph-all;
+};
+
+&ospi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&ospi0_pins_default>;
+	bootph-all;
+
+	flash@0{
+		compatible = "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+		spi-max-frequency = <25000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <4>;
+		bootph-all;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			bootph-all;
+
+			partition@0 {
+				label = "ospi.tiboot3";
+				reg = <0x00 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "ospi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fc0000 {
+				label = "ospi.phypattern";
+				reg = <0x3fc0000 0x40000>;
+				bootph-all;
+			};
+		};
+	};
+};
+
+&mailbox0_cluster0 {
+	mbox_r5_0: mbox-r5-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+};
+
+&mailbox0_cluster1 {
+	mbox_mcu_r5_0: mbox-mcu-r5-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+};
+&wkup_r5fss0_core0 {
+	mboxes = <&mailbox0_cluster0 &mbox_r5_0>;
+	memory-region = <&wkup_r5fss0_core0_dma_memory_region>,
+			<&wkup_r5fss0_core0_memory_region>;
+};
+
+&mcu_r5fss0_core0 {
+	mboxes = <&mailbox0_cluster1 &mbox_mcu_r5_0>;
+	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
+			<&mcu_r5fss0_core0_memory_region>;
+};
+
+&main_uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_uart0_pins_default>;
+	interrupts-extended = <&gic500 GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>,
+			<&main_pmx0 0x1c8>; /* (D14) UART0_RXD PADCONFIG114 */
+	interrupt-names = "irq", "wakeup";
+	status = "okay";
+	bootph-all;
+};
+
+&main_uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_uart1_pins_default>;
+	/* Main UART1 is used by TIFS firmware */
+	status = "reserved";
+	bootph-all;
+};
+
+&mcu_pmx0 {
+	bootph-all;
+
+	wkup_uart0_pins_default: wkup-uart0-default-pins {
+		pinctrl-single,pins = <
+			AM62PX_MCU_IOPAD(0x02c, PIN_INPUT, 0)	/* (C7) WKUP_UART0_CTSn */
+			AM62PX_MCU_IOPAD(0x030, PIN_OUTPUT, 0)	/* (C6) WKUP_UART0_RTSn */
+			AM62PX_MCU_IOPAD(0x024, PIN_INPUT, 0)	/* (D8) WKUP_UART0_RXD */
+			AM62PX_MCU_IOPAD(0x028, PIN_OUTPUT, 0)	/* (D7) WKUP_UART0_TXD */
+		>;
+		bootph-all;
+	};
+};
+
+&wkup_uart0 {
+	/* WKUP UART0 is used by DM firmware */
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_uart0_pins_default>;
+	status = "reserved";
+	bootph-all;
+};
+
+&dss0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_dpi_pins_default>;
+};
+
+&dss0_ports {
+	/* DSS0-VP2: DPI/HDMI Output */
+	port@1 {
+		reg = <1>;
+		dss0_dpi1_out: endpoint {
+			remote-endpoint = <&sii9022_in>;
+		};
+	};
+};
+
+&ti_csi2rx0 {
+	status = "okay";
+};
+
+&dphy0 {
+	status = "okay";
+};
+
+/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */
+&mcu_gpio0 {
+	status = "reserved";
+};
+
+&mcu_gpio_intr {
+	status = "reserved";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p5-sk-eqep.dtso b/arch/arm64/boot/dts/ti/k3-am62p5-sk-eqep.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk-eqep.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk-eqep.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay for enabling EQEP on AM62P-SK
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+	main_eqep0_pins_default: main-eqep0-pins-default {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0194, PIN_INPUT, 8) /* (D25) MCASP0_AXR3.EQEP0_A */
+			AM62PX_IOPAD(0x0198, PIN_INPUT, 8) /* (E25) MCASP0_AXR2.EQEP0_B */
+			AM62PX_IOPAD(0x01a0, PIN_INPUT, 8) /* (F23) MCASP0_AXR0.EQEP0_I */
+			AM62PX_IOPAD(0x019c, PIN_INPUT, 8) /* (E24) MCASP0_AXR1.EQEP0_S */
+		>;
+	};
+};
+
+&main_i2c1 {
+	gpio@22 {
+		p02-hog {
+			/* P02 - UART1_FET_SEL */
+			gpio-hog;
+			gpios = <2 GPIO_ACTIVE_HIGH>;
+			output-low;
+			line-name = "UART1_FET_SEL";
+		};
+	};
+};
+
+&eqep0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_eqep0_pins_default>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p5-sk-mcan.dtso b/arch/arm64/boot/dts/ti/k3-am62p5-sk-mcan.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk-mcan.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk-mcan.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT overlay for enabling MCAN for AM62P-SK
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&{/} {
+	transceiver1: can-phy0 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	transceiver2: can-phy1 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	transceiver3: can-phy2 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	transceiver4: can-phy3 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+};
+
+&main_pmx0 {
+	main_mcan0_pins_default: main-mcan0-pins-default {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x01dc, PIN_INPUT, 0) /* (F20) MCAN0_RX */
+			AM62PX_IOPAD(0x01d8, PIN_OUTPUT, 0) /* (B23) MCAN0_TX */
+		>;
+	};
+
+	main_mcan1_pins_default: main-mcan1-pins-default {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x00b4, PIN_INPUT, 5) /* (U25) GPMC0_CSn3.MCAN1_RX */
+			AM62PX_IOPAD(0x00b0, PIN_OUTPUT, 5) /* (T22) GPMC0_CSn2.MCAN1_TX */
+		>;
+	};
+};
+
+&mcu_pmx0 {
+	mcu_mcan0_pins_default: mcu-mcan0-pins-default {
+		pinctrl-single,pins = <
+			AM62PX_MCU_IOPAD(0x0038, PIN_INPUT, 0) /* (D6) MCU_MCAN0_RX */
+			AM62PX_MCU_IOPAD(0x0034, PIN_OUTPUT, 0) /* (E8) MCU_MCAN0_TX */
+		>;
+	};
+
+	mcu_mcan1_pins_default: mcu-mcan1-pins-default {
+		pinctrl-single,pins = <
+			AM62PX_MCU_IOPAD(0x0040, PIN_INPUT, 0) /* (E7) MCU_MCAN1_RX */
+			AM62PX_MCU_IOPAD(0x003c, PIN_OUTPUT, 0) /* (F8) MCU_MCAN1_TX */
+		>;
+	};
+};
+
+&main_i2c2{
+	/*
+	* main_i2c2 is using (U25) and (T22)
+	* so disable to use main_mcan1
+	*/
+	status = "disabled";
+};
+
+&main_i2c1 {
+	/*
+	* Unset GPIO SoC_I2C2_MCAN_SEL to
+	* route MCAN1 signals to MCAN1 HDR
+	*/
+	gpio@23 {
+		p20-hog {
+		/* P20 - SoC_I2C2_MCAN_SEL */
+		gpio-hog;
+		gpios = <16 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "SoC_I2C2_MCAN_SEL";
+		};
+	};
+};
+
+&main_mcan0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcan0_pins_default>;
+	phys = <&transceiver1>;
+};
+
+&main_mcan1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcan1_pins_default>;
+	phys = <&transceiver2>;
+};
+
+&mcu_mcan0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mcan0_pins_default>;
+	phys = <&transceiver3>;
+};
+
+&mcu_mcan1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mcan1_pins_default>;
+	phys = <&transceiver4>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p5-sk-microtips-mf101hie-panel.dtso b/arch/arm64/boot/dts/ti/k3-am62p5-sk-microtips-mf101hie-panel.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk-microtips-mf101hie-panel.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk-microtips-mf101hie-panel.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * Microtips integrated OLDI panel (MF-101HIEBCAF0) and touch DT overlay for AM62P5-SK
+ *
+ * Panel datasheet: https://simplespec.microtipsusa.com/uploads/spec/datasheetFile/2588/13-101HIEBCAF0-S_V1.1_20221104.pdf
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&{/} {
+	display {
+		compatible = "microtips,mf-101hiebcaf0";
+		/*
+		* Note that the OLDI TX 0 transmits the odd set of pixels
+		* while the OLDI TX 1 transmits the even set. This is a
+		* fixed configuration in the IP integration and is not
+		* changeable. The properties, "dual-lvds-odd-pixels" and
+		* "dual-lvds-even-pixels" have been used to merely
+		* identify if a Dual Link configuration is required.
+		* Swapping them will not make any difference.
+		*/
+		port@0 {
+			dual-lvds-odd-pixels;
+			lcd_in0: endpoint {
+				remote-endpoint = <&oldi_out0>;
+			};
+		};
+		port@1 {
+			dual-lvds-even-pixels;
+			lcd_in1: endpoint {
+				remote-endpoint = <&oldi_out1>;
+			};
+		};
+	};
+};
+
+&dss0 {
+	status = "okay";
+};
+
+&dss0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* VP1: LVDS Output (OLDI TX 0) */
+	port@0 {
+		reg = <0>;
+		oldi_out0: endpoint {
+			remote-endpoint = <&lcd_in0>;
+		};
+	};
+
+	/* VP1: LVDS Output (OLDI TX 1) */
+	port@2 {
+		reg = <2>;
+		oldi_out1: endpoint {
+			remote-endpoint = <&lcd_in1>;
+		};
+	};
+};
+
+&main_i2c0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	touchscreen@41 {
+		compatible = "ilitek,ili251x";
+		reg = <0x41>;
+		interrupt-parent = <&exp1>;
+		interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+		reset-gpios = <&exp2 20 GPIO_ACTIVE_LOW>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p5-sk-microtips-mf103hie-lcd2.dtso b/arch/arm64/boot/dts/ti/k3-am62p5-sk-microtips-mf103hie-lcd2.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk-microtips-mf103hie-lcd2.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk-microtips-mf103hie-lcd2.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * Microtips integrated OLDI panel (MF-103HIEB0GA0) (SK-LCD2) DT overlay for AM62PS5-SK
+ *
+ * Panel datasheet: https://simplespec.microtipsusa.com/uploads/spec/datasheetFile/2660/13-103HIEB0GA0-S_V1.0_20211206.pdf
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&{/} {
+	display {
+		compatible = "microtips,mf-103hieb0ga0";
+		/*
+		* Note that the OLDI TX 0 transmits the odd set of pixels
+		* while the OLDI TX 1 transmits the even set. This is a
+		* fixed configuration in the IP integration and is not
+		* changeable. The properties, "dual-lvds-odd-pixels" and
+		* "dual-lvds-even-pixels" have been used to merely
+		* identify if a Dual Link configuration is required.
+		* But swapping them will cause an error in the dss driver.
+		*/
+		port@0 {
+			dual-lvds-odd-pixels;
+			lcd_in0: endpoint {
+				remote-endpoint = <&oldi_out0>;
+			};
+		};
+		port@1 {
+			dual-lvds-even-pixels;
+			lcd_in1: endpoint {
+				remote-endpoint = <&oldi_out1>;
+			};
+		};
+	};
+};
+
+&dss0 {
+	status = "okay";
+};
+
+&dss0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* VP1: LVDS Output (OLDI TX 0) */
+	port@0 {
+		reg = <0>;
+		oldi_out0: endpoint {
+			remote-endpoint = <&lcd_in0>;
+		};
+	};
+
+	/* VP1: LVDS Output (OLDI TX 1) */
+	port@2 {
+		reg = <2>;
+		oldi_out1: endpoint {
+			remote-endpoint = <&lcd_in1>;
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p5-sk-rpi-hdr-ehrpwm.dtso b/arch/arm64/boot/dts/ti/k3-am62p5-sk-rpi-hdr-ehrpwm.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62p5-sk-rpi-hdr-ehrpwm.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p5-sk-rpi-hdr-ehrpwm.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for enabling RPi header with GPIOs and eHRPWMs on AM62P-SK
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+	rpi_header_gpio0_pins_default: rpi-header-gpio0-pins-default {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x0038, PIN_INPUT, 7) /* (L23) OSPI0_CSn3.GPIO0_14 */
+			AM62PX_IOPAD(0x0088, PIN_INPUT, 7) /* (R24) GPMC0_OEn_REn.GPIO0_33 */
+			AM62PX_IOPAD(0x0094, PIN_INPUT, 7) /* (T24) GPMC0_BE1n.GPIO0_36 */
+			AM62PX_IOPAD(0x009c, PIN_INPUT, 7) /* (AD24) GPMC0_WAIT1.GPIO0_38 */
+			AM62PX_IOPAD(0x00a0, PIN_INPUT, 7) /* (P24) GPMC0_WPn.GPIO0_39 */
+			AM62PX_IOPAD(0x00a4, PIN_INPUT, 7) /* (P25) GPMC0_DIR.GPIO0_40 */
+			AM62PX_IOPAD(0x00a8, PIN_INPUT, 7) /* (T23) GPMC0_CSn0.GPIO0_41 */
+			AM62PX_IOPAD(0x00ac, PIN_INPUT, 7) /* (U23) GPMC0_CSn1.GPIO0_42 */
+		>;
+	};
+
+	rpi_header_gpio1_pins_default: rpi-header-gpio1-pins-default {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x01d0, PIN_INPUT, 7) /* (A23) UART0_CTSn.GPIO1_22 */
+		>;
+	};
+
+	rpi_header_ehrpwm0_pins_default: rpi-header-ehrpwm0-pins-default {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x01ac, PIN_OUTPUT, 6) /* (G23) MCASP0_AFSR.EHRPWM0_A */
+			AM62PX_IOPAD(0x01b0, PIN_OUTPUT, 6) /* (G20) MCASP0_ACLKR.EHRPWM0_B */
+		>;
+	};
+
+	rpi_header_ehrpwm1_pins_default: rpi-header-ehrpwm1-pins-default {
+		pinctrl-single,pins = <
+			AM62PX_IOPAD(0x019c, PIN_OUTPUT, 6) /* (E24) MCASP0_AXR1.EHRPWM1_A */
+			AM62PX_IOPAD(0x01a0, PIN_OUTPUT, 6) /* (F23) MCASP0_AXR0.EHRPWM1_B */
+		>;
+	};
+};
+
+&main_i2c1 {
+	gpio@22 {
+		p02-hog {
+			/* P02 - UART1_FET_SEL */
+			gpio-hog;
+			gpios = <2 GPIO_ACTIVE_HIGH>;
+			output-low;
+			line-name = "UART1_FET_SEL";
+		};
+
+		p05-hog {
+			/* P05 - EXP_PS_3V3_EN */
+			gpio-hog;
+			gpios = <5 GPIO_ACTIVE_HIGH>;
+			output-high;
+			line-name = "EXP_PS_3V3_EN";
+		};
+	};
+
+	gpio@23 {
+		p01-hog {
+			/* P01 - EXP_PS_5V0_EN */
+			gpio-hog;
+			gpios = <1 GPIO_ACTIVE_HIGH>;
+			output-high;
+			line-name = "EXP_PS_5V0_EN";
+		};
+	};
+};
+
+&mcasp0 {
+	status = "disabled";
+};
+
+&epwm0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm0_pins_default>;
+};
+
+&epwm1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm1_pins_default>;
+};
+
+
+&main_gpio0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio0_pins_default>;
+};
+
+&main_gpio1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio1_pins_default>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p.dtsi b/arch/arm64/boot/dts/ti/k3-am62p.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62p.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for AM62P SoC Family
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+#include "k3-pinctrl.h"
+
+/ {
+	model = "Texas Instruments K3 AM62P5 SoC";
+	compatible = "ti,am62p5";
+	interrupt-parent = <&gic500>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	firmware {
+		optee {
+			compatible = "linaro,optee-tz";
+			method = "smc";
+		};
+
+		psci: psci {
+			compatible = "arm,psci-1.0";
+			method = "smc";
+		};
+	};
+
+	a53_timer0: timer-cl0-cpu0 {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, /* cntpsirq */
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, /* cntpnsirq */
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, /* cntvirq */
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; /* cnthpirq */
+	};
+
+	pmu: pmu {
+		compatible = "arm,cortex-a53-pmu";
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	cbass_main: bus@f0000 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		bootph-all;
+
+		ranges = <0x00 0x000f0000 0x00 0x000f0000 0x00 0x00030000>, /* Main MMRs */
+			 <0x00 0x00420000 0x00 0x00420000 0x00 0x00001000>, /* ESM0 */
+			 <0x00 0x00600000 0x00 0x00600000 0x00 0x00001100>, /* GPIO */
+			 <0x00 0x00703000 0x00 0x00703000 0x00 0x00000200>, /* USB0 debug trace */
+			 <0x00 0x0070c000 0x00 0x0070c000 0x00 0x00000200>, /* USB1 debug trace */
+			 <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* Timesync router */
+			 <0x00 0x01000000 0x00 0x01000000 0x00 0x01b28400>, /* First peripheral window */
+			 <0x00 0x08000000 0x00 0x08000000 0x00 0x00200000>, /* Main CPSW */
+			 <0x00 0x0e000000 0x00 0x0e000000 0x00 0x01d20000>, /* Second peripheral window */
+			 <0x00 0x0fd80000 0x00 0x0fd80000 0x00 0x00080000>, /* GPU */
+			 <0x00 0x20000000 0x00 0x20000000 0x00 0x0a008000>, /* Third peripheral window */
+			 <0x00 0x30040000 0x00 0x30040000 0x00 0x00080000>, /* PRUSS-M */
+			 <0x00 0x30101000 0x00 0x30101000 0x00 0x00010100>, /* CSI window */
+			 <0x00 0x301C0000 0x00 0x301C0000 0x00 0x00001000>, /* DPHY-TX */
+			 <0x00 0x30200000 0x00 0x30200000 0x00 0x00010000>, /* DSS */
+			 <0x00 0x30210000 0x00 0x30210000 0x00 0x00010000>, /* VPU */
+			 <0x00 0x30220000 0x00 0x30220000 0x00 0x00010000>, /* DSS1 */
+			 <0x00 0x30270000 0x00 0x30270000 0x00 0x00010000>, /* DSI Wrapper */
+			 <0x00 0x30500000 0x00 0x30500000 0x00 0x00100000>, /* DSI Config */
+			 <0x00 0x31000000 0x00 0x31000000 0x00 0x00050000>, /* USB0 DWC3 Core window */
+			 <0x00 0x31100000 0x00 0x31100000 0x00 0x00050000>, /* USB1 DWC3 Core window */
+			 <0x00 0x40900000 0x00 0x40900000 0x00 0x00030000>, /* SA3UL */
+			 <0x00 0x43600000 0x00 0x43600000 0x00 0x00010000>, /* SA3 sproxy data */
+			 <0x00 0x44043000 0x00 0x44043000 0x00 0x00000fe0>, /* TI SCI DEBUG */
+			 <0x00 0x44860000 0x00 0x44860000 0x00 0x00040000>, /* SA3 sproxy config */
+			 <0x00 0x48000000 0x00 0x48000000 0x00 0x06408000>, /* DMSS */
+			 <0x00 0x60000000 0x00 0x60000000 0x00 0x08000000>, /* FSS0 DAT1 */
+			 <0x00 0x70000000 0x00 0x70000000 0x00 0x00010000>, /* OCSRAM */
+			 <0x01 0x00000000 0x01 0x00000000 0x00 0x00310000>, /* A53 PERIPHBASE */
+			 <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, /* FSS0 DAT3 */
+
+			 /* MCU Domain Range */
+			 <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>,
+			 <0x00 0x79000000 0x00 0x79000000 0x00 0x00008000>,
+			 <0x00 0x79020000 0x00 0x79020000 0x00 0x00008000>,
+			 <0x00 0x79100000 0x00 0x79100000 0x00 0x00040000>,
+			 <0x00 0x79140000 0x00 0x79140000 0x00 0x00040000>,
+
+			 /* Wakeup Domain Range */
+			 <0x00 0x00b00000 0x00 0x00b00000 0x00 0x00002400>,
+			 <0x00 0x2b000000 0x00 0x2b000000 0x00 0x00300400>,
+			 <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>,
+			 <0x00 0x78000000 0x00 0x78000000 0x00 0x00008000>,
+			 <0x00 0x78100000 0x00 0x78100000 0x00 0x00008000>;
+
+		cbass_mcu: bus@4000000 {
+			compatible = "simple-bus";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>, /* Peripheral window */
+				 <0x00 0x79000000 0x00 0x79000000 0x00 0x00008000>, /* MCU R5 ATCM */
+				 <0x00 0x79020000 0x00 0x79020000 0x00 0x00008000>, /* MCU R5 BTCM */
+				 <0x00 0x79100000 0x00 0x79100000 0x00 0x00040000>, /* MCU IRAM0 */
+				 <0x00 0x79140000 0x00 0x79140000 0x00 0x00040000>; /* MCU IRAM1 */
+			bootph-all;
+		};
+
+		cbass_wakeup: bus@b00000 {
+			compatible = "simple-bus";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x00 0x00b00000 0x00 0x00b00000 0x00 0x00002400>, /* VTM */
+				 <0x00 0x2b000000 0x00 0x2b000000 0x00 0x00300400>, /* Peripheral Window */
+				 <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>, /* WKUP CTRL MMR */
+				 <0x00 0x78000000 0x00 0x78000000 0x00 0x00008000>, /* DM R5 ATCM*/
+				 <0x00 0x78100000 0x00 0x78100000 0x00 0x00008000>; /* DM R5 BTCM*/
+			bootph-all;
+		};
+	};
+
+	#include "k3-am62p-thermal.dtsi"
+};
+
+/* Now include peripherals for each bus segment */
+#include "k3-am62p-main.dtsi"
+#include "k3-am62p-mcu.dtsi"
+#include "k3-am62p-wakeup.dtsi"
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p-main.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,1239 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for the AM62P main domain peripherals
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+&cbass_main {
+	oc_sram: sram@70000000 {
+		compatible = "mmio-sram";
+		reg = <0x00 0x70000000 0x00 0x10000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x00 0x00 0x70000000 0x10000>;
+	};
+
+	gic500: interrupt-controller@1800000 {
+		compatible = "arm,gic-v3";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x00 0x01800000 0x00 0x10000>,	/* GICD */
+		      <0x00 0x01880000 0x00 0xc0000>,	/* GICR */
+		      <0x01 0x00000000 0x00 0x2000>,    /* GICC */
+		      <0x01 0x00010000 0x00 0x1000>,    /* GICH */
+		      <0x01 0x00020000 0x00 0x2000>;    /* GICV */
+		/*
+		 * vcpumntirq:
+		 * virtual CPU interface maintenance interrupt
+		 */
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+		gic_its: msi-controller@1820000 {
+			compatible = "arm,gic-v3-its";
+			reg = <0x00 0x01820000 0x00 0x10000>;
+			socionext,synquacer-pre-its = <0x1000000 0x400000>;
+			msi-controller;
+			#msi-cells = <1>;
+		};
+	};
+
+	main_conf: bus@100000 {
+		compatible = "simple-bus";
+		reg = <0x00 0x00100000 0x00 0x20000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x00 0x00 0x00100000 0x20000>;
+
+		phy_gmii_sel: phy@4044 {
+			compatible = "ti,am654-phy-gmii-sel";
+			reg = <0x4044 0x8>;
+			#phy-cells = <1>;
+		};
+
+		epwm_tbclk: clock-controller@4130 {
+			compatible = "ti,am62-epwm-tbclk";
+			reg = <0x4130 0x4>;
+			#clock-cells = <1>;
+		};
+
+		dss_oldi_io_ctrl: dss-oldi-io-ctrl@8600 {
+			compatible = "syscon";
+			reg = <0x8600 0x200>;
+		};
+	};
+
+	dmss: bus@48000000 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		dma-ranges;
+		ranges = <0x00 0x48000000 0x00 0x48000000 0x00 0x06400000>;
+		bootph-all;
+
+		ti,sci-dev-id = <25>;
+
+		secure_proxy_main: mailbox@4d000000 {
+			compatible = "ti,am654-secure-proxy";
+			#mbox-cells = <1>;
+			reg-names = "target_data", "rt", "scfg";
+			reg = <0x00 0x4d000000 0x00 0x80000>,
+			      <0x00 0x4a600000 0x00 0x80000>,
+			      <0x00 0x4a400000 0x00 0x80000>;
+			interrupt-names = "rx_012";
+			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+			bootph-all;
+		};
+
+		inta_main_dmss: interrupt-controller@48000000 {
+			compatible = "ti,sci-inta";
+			reg = <0x00 0x48000000 0x00 0x100000>;
+			#interrupt-cells = <0>;
+			interrupt-controller;
+			interrupt-parent = <&gic500>;
+			msi-controller;
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <28>;
+			ti,interrupt-ranges = <5 69 35>;
+			ti,unmapped-event-sources = <&main_bcdma>, <&main_pktdma>;
+		};
+
+		main_bcdma: dma-controller@485c0100 {
+			compatible = "ti,am64-dmss-bcdma";
+			reg = <0x00 0x485c0100 0x00 0x100>,
+			      <0x00 0x4c000000 0x00 0x20000>,
+			      <0x00 0x4a820000 0x00 0x20000>,
+			      <0x00 0x4aa40000 0x00 0x20000>,
+			      <0x00 0x4bc00000 0x00 0x100000>;
+			reg-names = "gcfg", "bchanrt", "rchanrt", "tchanrt", "ringrt";
+			msi-parent = <&inta_main_dmss>;
+			#dma-cells = <3>;
+
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <26>;
+			ti,sci-rm-range-bchan = <0x20>; /* BLOCK_COPY_CHAN */
+			ti,sci-rm-range-rchan = <0x21>; /* SPLIT_TR_RX_CHAN */
+			ti,sci-rm-range-tchan = <0x22>; /* SPLIT_TR_TX_CHAN */
+			bootph-all;
+		};
+
+		main_pktdma: dma-controller@485c0000 {
+			compatible = "ti,am64-dmss-pktdma";
+			reg = <0x00 0x485c0000 0x00 0x100>,
+			      <0x00 0x4a800000 0x00 0x20000>,
+			      <0x00 0x4aa00000 0x00 0x40000>,
+			      <0x00 0x4b800000 0x00 0x400000>;
+			reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt";
+			msi-parent = <&inta_main_dmss>;
+			#dma-cells = <2>;
+			bootph-all;
+
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <30>;
+			ti,sci-rm-range-tchan = <0x23>, /* UNMAPPED_TX_CHAN */
+						<0x24>, /* CPSW_TX_CHAN */
+						<0x25>, /* SAUL_TX_0_CHAN */
+						<0x26>; /* SAUL_TX_1_CHAN */
+			ti,sci-rm-range-tflow = <0x10>, /* RING_UNMAPPED_TX_CHAN */
+						<0x11>, /* RING_CPSW_TX_CHAN */
+						<0x12>, /* RING_SAUL_TX_0_CHAN */
+						<0x13>; /* RING_SAUL_TX_1_CHAN */
+			ti,sci-rm-range-rchan = <0x29>, /* UNMAPPED_RX_CHAN */
+						<0x2b>, /* CPSW_RX_CHAN */
+						<0x2d>, /* SAUL_RX_0_CHAN */
+						<0x2f>, /* SAUL_RX_1_CHAN */
+						<0x31>, /* SAUL_RX_2_CHAN */
+						<0x33>; /* SAUL_RX_3_CHAN */
+			ti,sci-rm-range-rflow = <0x2a>, /* FLOW_UNMAPPED_RX_CHAN */
+						<0x2c>, /* FLOW_CPSW_RX_CHAN */
+						<0x2e>, /* FLOW_SAUL_RX_0/1_CHAN */
+						<0x32>; /* FLOW_SAUL_RX_2/3_CHAN */
+		};
+	};
+
+	dmss_csi: bus@4e000000 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		dma-ranges;
+		ranges = <0x00 0x4e000000 0x00 0x4e000000 0x00 0x408000>;
+
+		ti,sci-dev-id = <198>;
+
+		inta_main_dmss_csi: interrupt-controller@4e400000 {
+			compatible = "ti,sci-inta";
+			reg = <0x00 0x4e400000 0x00 0x8000>;
+			#interrupt-cells = <0>;
+			interrupt-controller;
+			interrupt-parent = <&gic500>;
+			msi-controller;
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <200>;
+			ti,interrupt-ranges = <0 237 8>;
+			ti,unmapped-event-sources = <&main_bcdma_csi>;
+			power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+		};
+
+		main_bcdma_csi: dma-controller@4e230000 {
+			compatible = "ti,am62a-dmss-bcdma-csirx";
+			reg = <0x00 0x4e230000 0x00 0x100>,
+			      <0x00 0x4e180000 0x00 0x8000>,
+			      <0x00 0x4e100000 0x00 0x10000>;
+			reg-names = "gcfg", "rchanrt", "ringrt";
+			msi-parent = <&inta_main_dmss_csi>;
+			#dma-cells = <3>;
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <199>;
+			ti,sci-rm-range-rchan = <0x21>;
+			power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+		};
+	};
+
+	dmsc: system-controller@44043000 {
+		compatible = "ti,k2g-sci";
+		ti,host-id = <12>;
+		mbox-names = "rx", "tx";
+		mboxes = <&secure_proxy_main 12>,
+			 <&secure_proxy_main 13>;
+		reg-names = "debug_messages";
+		reg = <0x00 0x44043000 0x00 0xfe0>;
+		bootph-all;
+
+		k3_pds: power-controller {
+			compatible = "ti,sci-pm-domain";
+			#power-domain-cells = <2>;
+			bootph-all;
+		};
+
+		k3_clks: clock-controller {
+			compatible = "ti,k2g-sci-clk";
+			#clock-cells = <2>;
+			bootph-all;
+		};
+
+		k3_reset: reset-controller {
+			compatible = "ti,sci-reset";
+			#reset-cells = <2>;
+			bootph-all;
+		};
+	};
+
+	crypto: crypto@40900000 {
+		compatible = "ti,am62-sa3ul";
+		reg = <0x00 0x40900000 0x00 0x1200>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x00 0x40900000 0x00 0x40900000 0x00 0x30000>;
+
+		dmas = <&main_pktdma 0xf501 0>, <&main_pktdma 0x7506 0>,
+		       <&main_pktdma 0x7507 0>;
+		dma-names = "tx", "rx1", "rx2";
+	};
+
+	secure_proxy_sa3: mailbox@43600000 {
+		compatible = "ti,am654-secure-proxy";
+		#mbox-cells = <1>;
+		reg-names = "target_data", "rt", "scfg";
+		reg = <0x00 0x43600000 0x00 0x10000>,
+		      <0x00 0x44880000 0x00 0x20000>,
+		      <0x00 0x44860000 0x00 0x20000>;
+		/*
+		 * Marked Disabled:
+		 * Node is incomplete as it is meant for bootloaders and
+		 * firmware on non-MPU processors
+		 */
+		status = "disabled";
+		bootph-all;
+	};
+
+	main_pmx0: pinctrl@f4000 {
+		compatible = "ti,am6-padconf";
+		reg = <0x00 0xf4000 0x00 0x2ac>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+		interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		bootph-all;
+	};
+
+	main_esm: esm@420000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x00 0x420000 0x00 0x1000>;
+		ti,esm-pins = <160>, <161>, <162>, <163>, <177>, <178>;
+		bootph-pre-ram;
+	};
+
+	main_timer0: timer@2400000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2400000 0x00 0x400>;
+		interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 36 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 36 2>;
+		assigned-clock-parents = <&k3_clks 36 3>;
+		power-domains = <&k3_pds 36 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		bootph-all;
+	};
+
+	main_timer1: timer@2410000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2410000 0x00 0x400>;
+		interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 37 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 37 2>;
+		assigned-clock-parents = <&k3_clks 37 3>;
+		power-domains = <&k3_pds 37 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer2: timer@2420000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2420000 0x00 0x400>;
+		interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 38 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 38 2>;
+		assigned-clock-parents = <&k3_clks 38 3>;
+		power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer3: timer@2430000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2430000 0x00 0x400>;
+		interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 39 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 39 2>;
+		assigned-clock-parents = <&k3_clks 39 3>;
+		power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer4: timer@2440000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2440000 0x00 0x400>;
+		interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 40 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 40 2>;
+		assigned-clock-parents = <&k3_clks 40 3>;
+		power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer5: timer@2450000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2450000 0x00 0x400>;
+		interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 41 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 41 2>;
+		assigned-clock-parents = <&k3_clks 41 3>;
+		power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer6: timer@2460000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2460000 0x00 0x400>;
+		interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 42 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 42 2>;
+		assigned-clock-parents = <&k3_clks 42 3>;
+		power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_timer7: timer@2470000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x2470000 0x00 0x400>;
+		interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 43 2>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 43 2>;
+		assigned-clock-parents = <&k3_clks 43 3>;
+		power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+	};
+
+	main_uart0: serial@2800000 {
+		compatible = "ti,am64-uart", "ti,am654-uart";
+		reg = <0x00 0x02800000 0x00 0x100>;
+		interrupts = <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 146 0>;
+		clock-names = "fclk";
+		status = "disabled";
+	};
+
+	main_uart1: serial@2810000 {
+		compatible = "ti,am64-uart", "ti,am654-uart";
+		reg = <0x00 0x02810000 0x00 0x100>;
+		interrupts = <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 152 0>;
+		clock-names = "fclk";
+		status = "disabled";
+	};
+
+	main_uart2: serial@2820000 {
+		compatible = "ti,am64-uart", "ti,am654-uart";
+		reg = <0x00 0x02820000 0x00 0x100>;
+		interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 153 0>;
+		clock-names = "fclk";
+		status = "disabled";
+	};
+
+	main_uart3: serial@2830000 {
+		compatible = "ti,am64-uart", "ti,am654-uart";
+		reg = <0x00 0x02830000 0x00 0x100>;
+		interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 154 0>;
+		clock-names = "fclk";
+		status = "disabled";
+	};
+
+	main_uart4: serial@2840000 {
+		compatible = "ti,am64-uart", "ti,am654-uart";
+		reg = <0x00 0x02840000 0x00 0x100>;
+		interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 155 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 155 0>;
+		clock-names = "fclk";
+		status = "disabled";
+	};
+
+	main_uart5: serial@2850000 {
+		compatible = "ti,am64-uart", "ti,am654-uart";
+		reg = <0x00 0x02850000 0x00 0x100>;
+		interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 156 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 156 0>;
+		clock-names = "fclk";
+		status = "disabled";
+	};
+
+	main_uart6: serial@2860000 {
+		compatible = "ti,am64-uart", "ti,am654-uart";
+		reg = <0x00 0x02860000 0x00 0x100>;
+		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 158 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 158 0>;
+		clock-names = "fclk";
+		status = "disabled";
+	};
+
+	main_i2c0: i2c@20000000 {
+		compatible = "ti,am64-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x20000000 0x00 0x100>;
+		interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 102 2>;
+		clock-names = "fck";
+		status = "disabled";
+	};
+
+	main_i2c1: i2c@20010000 {
+		compatible = "ti,am64-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x20010000 0x00 0x100>;
+		interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 103 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 103 2>;
+		clock-names = "fck";
+		status = "disabled";
+	};
+
+	main_i2c2: i2c@20020000 {
+		compatible = "ti,am64-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x20020000 0x00 0x100>;
+		interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 104 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 104 2>;
+		clock-names = "fck";
+		status = "disabled";
+	};
+
+	main_i2c3: i2c@20030000 {
+		compatible = "ti,am64-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x20030000 0x00 0x100>;
+		interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 105 2>;
+		clock-names = "fck";
+		status = "disabled";
+	};
+
+	vpu: video-codec@30210000 {
+		compatible = "cnm,cm521c-vpu";
+		reg = <0x00 0x30210000 0x00 0x10000>;
+		interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 204 2>;
+		clock-names = "vcodec";
+		power-domains = <&k3_pds 204 TI_SCI_PD_EXCLUSIVE>;
+		sram = <&oc_sram>;
+		sram-size = <0xf800>;
+		operating-points-v2 = <&vpu_opp_table>;
+		vpu_opp_table: opp-table {
+			compatible = "operating-points-v2";
+			opp-20000000 {
+				opp-hz = /bits/ 64 <20000000>;
+			};
+
+			opp-100000000 {
+				opp-hz = /bits/ 64 <100000000>;
+			};
+
+			opp-200000000 {
+				opp-hz = /bits/ 64 <200000000>;
+			};
+
+			opp-400000000 {
+				opp-hz = /bits/ 64 <400000000>;
+			};
+
+			opp-500000000 {
+				opp-hz = /bits/ 64 <500000000>;
+			};
+		};
+	};
+
+	main_spi0: spi@20100000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x20100000 0x00 0x400>;
+		interrupts = <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 141 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 141 0>;
+		status = "disabled";
+	};
+
+	main_spi1: spi@20110000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x20110000 0x00 0x400>;
+		interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 142 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 142 0>;
+		status = "disabled";
+	};
+
+	main_spi2: spi@20120000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x20120000 0x00 0x400>;
+		interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 143 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 143 0>;
+		status = "disabled";
+	};
+
+	main_gpio_intr: interrupt-controller@a00000 {
+		compatible = "ti,sci-intr";
+		reg = <0x00 0x00a00000 0x00 0x800>;
+		ti,intr-trigger-type = <1>;
+		interrupt-controller;
+		interrupt-parent = <&gic500>;
+		#interrupt-cells = <1>;
+		ti,sci = <&dmsc>;
+		ti,sci-dev-id = <3>;
+		ti,interrupt-ranges = <0 32 16>;
+	};
+
+	main_gpio0: gpio@600000 {
+		compatible = "ti,am64-gpio", "ti,keystone-gpio";
+		reg = <0x00 0x00600000 0x00 0x100>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&main_gpio_intr>;
+		interrupts = <190>, <191>, <192>,
+			     <193>, <194>, <195>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		ti,ngpio = <92>;
+		ti,davinci-gpio-unbanked = <0>;
+		power-domains = <&k3_pds 77 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 77 0>;
+		clock-names = "gpio";
+	};
+
+	main_gpio1: gpio@601000 {
+		compatible = "ti,am64-gpio", "ti,keystone-gpio";
+		reg = <0x00 0x00601000 0x00 0x100>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&main_gpio_intr>;
+		interrupts = <180>, <181>, <182>,
+			     <183>, <184>, <185>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		ti,ngpio = <52>;
+		ti,davinci-gpio-unbanked = <0>;
+		power-domains = <&k3_pds 78 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 78 0>;
+		clock-names = "gpio";
+	};
+
+	sdhci0: mmc@fa10000 {
+		compatible = "ti,am64-sdhci-8bit";
+		reg = <0x00 0x0fa10000 0x00 0x1000>, <0x00 0x0fa18000 0x00 0x400>;
+		interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 57 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 57 1>, <&k3_clks 57 2>;
+		clock-names = "clk_ahb", "clk_xin";
+		assigned-clocks = <&k3_clks 57 2>;
+		assigned-clock-parents = <&k3_clks 57 4>;
+		bus-width = <8>;
+		mmc-ddr-1_8v;
+		mmc-hs200-1_8v;
+		mmc-hs400-1_8v;
+		ti,clkbuf-sel = <0x7>;
+		ti,strobe-sel = <0x77>;
+		ti,trm-icp = <0x8>;
+		ti,otap-del-sel-legacy = <0x1>;
+		ti,otap-del-sel-mmc-hs = <0x1>;
+		ti,otap-del-sel-ddr52 = <0x6>;
+		ti,otap-del-sel-hs200 = <0x6>;
+		ti,otap-del-sel-hs400 = <0x6>;
+		ti,itap-del-sel-legacy = <0x10>;
+		ti,itap-del-sel-mmc-hs = <0xa>;
+		ti,itap-del-sel-ddr52 = <0x3>;
+		status = "disabled";
+	};
+
+	sdhci1: mmc@fa00000 {
+		compatible = "ti,am62-sdhci";
+		reg = <0x00 0x0fa00000 0x00 0x1000>, <0x00 0x0fa08000 0x00 0x400>;
+		interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 58 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 58 5>, <&k3_clks 58 6>;
+		clock-names = "clk_ahb", "clk_xin";
+		bus-width = <4>;
+		ti,clkbuf-sel = <0x7>;
+		ti,trm-icp = <0x8>;
+		ti,otap-del-sel-legacy = <0x0>;
+		ti,otap-del-sel-sd-hs = <0x0>;
+		ti,otap-del-sel-sdr12 = <0xf>;
+		ti,otap-del-sel-sdr25 = <0xf>;
+		ti,otap-del-sel-sdr50 = <0xc>;
+		ti,otap-del-sel-ddr50 = <0x9>;
+		ti,otap-del-sel-sdr104 = <0x6>;
+		ti,itap-del-sel-legacy = <0x0>;
+		ti,itap-del-sel-sd-hs = <0x0>;
+		ti,itap-del-sel-sdr12 = <0x0>;
+		ti,itap-del-sel-sdr25 = <0x0>;
+		status = "disabled";
+	};
+
+	sdhci2: mmc@fa20000 {
+		compatible = "ti,am62-sdhci";
+		reg = <0x00 0x0fa20000 0x00 0x1000>, <0x00 0x0fa28000 0x00 0x400>;
+		interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 184 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 184 5>, <&k3_clks 184 6>;
+		clock-names = "clk_ahb", "clk_xin";
+		bus-width = <4>;
+		ti,clkbuf-sel = <0x7>;
+		ti,trm-icp = <0x8>;
+		ti,otap-del-sel-legacy = <0x0>;
+		ti,otap-del-sel-sd-hs = <0x0>;
+		ti,otap-del-sel-sdr12 = <0xf>;
+		ti,otap-del-sel-sdr25 = <0xf>;
+		ti,otap-del-sel-sdr50 = <0xc>;
+		ti,otap-del-sel-ddr50 = <0x9>;
+		ti,otap-del-sel-sdr104 = <0x6>;
+		ti,itap-del-sel-legacy = <0x0>;
+		ti,itap-del-sel-sd-hs = <0x0>;
+		ti,itap-del-sel-sdr12 = <0x0>;
+		ti,itap-del-sel-sdr25 = <0x0>;
+		status = "disabled";
+	};
+
+	usbss0: dwc3-usb@f900000 {
+		compatible = "ti,am62-usb";
+		reg = <0x00 0x0f900000 0x00 0x800>;
+		clocks = <&k3_clks 161 3>;
+		clock-names = "ref";
+		ti,syscon-phy-pll-refclk = <&wkup_conf 0x4008>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		power-domains = <&k3_pds 178 TI_SCI_PD_EXCLUSIVE>;
+		ranges;
+		status = "disabled";
+
+		usb0: usb@31000000 {
+			compatible = "snps,dwc3";
+			reg = <0x00 0x31000000 0x00 0x50000>;
+			interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
+			<GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>; /* irq.0 */
+			interrupt-names = "host", "peripheral";
+			maximum-speed = "high-speed";
+			dr_mode = "otg";
+		};
+	};
+
+	usbss1: dwc3-usb@f910000 {
+		compatible = "ti,am62-usb";
+		reg = <0x00 0x0f910000 0x00 0x800>;
+		clocks = <&k3_clks 162 3>;
+		clock-names = "ref";
+		ti,syscon-phy-pll-refclk = <&wkup_conf 0x4018>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		power-domains = <&k3_pds 179 TI_SCI_PD_EXCLUSIVE>;
+		ranges;
+		status = "disabled";
+
+		usb1: usb@31100000 {
+			compatible = "snps,dwc3";
+			reg = <0x00 0x31100000 0x00 0x50000>;
+			interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>, /* irq.0 */
+			<GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>; /* irq.0 */
+			interrupt-names = "host", "peripheral";
+			maximum-speed = "high-speed";
+			dr_mode = "otg";
+		};
+	};
+
+	fss: bus@fc00000 {
+		compatible = "simple-bus";
+		reg = <0x00 0x0fc00000 0x00 0x70000>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		ospi0: spi@fc40000 {
+			compatible = "ti,am654-ospi", "cdns,qspi-nor";
+			reg = <0x00 0x0fc40000 0x00 0x100>,
+			      <0x05 0x00000000 0x01 0x00000000>;
+			interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
+			cdns,fifo-depth = <256>;
+			cdns,fifo-width = <4>;
+			cdns,trigger-address = <0x0>;
+			clocks = <&k3_clks 75 7>;
+			assigned-clocks = <&k3_clks 75 7>;
+			assigned-clock-parents = <&k3_clks 75 8>;
+			assigned-clock-rates = <166666666>;
+			power-domains = <&k3_pds 75 TI_SCI_PD_EXCLUSIVE>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+	};
+
+	cpsw3g: ethernet@8000000 {
+		compatible = "ti,am642-cpsw-nuss";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		reg = <0x00 0x08000000 0x00 0x200000>;
+		reg-names = "cpsw_nuss";
+		ranges = <0x00 0x00 0x00 0x08000000 0x00 0x200000>;
+		clocks = <&k3_clks 13 0>;
+		assigned-clocks = <&k3_clks 13 3>;
+		assigned-clock-parents = <&k3_clks 13 11>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 13 TI_SCI_PD_EXCLUSIVE>;
+
+		dmas = <&main_pktdma 0xc600 15>,
+		       <&main_pktdma 0xc601 15>,
+		       <&main_pktdma 0xc602 15>,
+		       <&main_pktdma 0xc603 15>,
+		       <&main_pktdma 0xc604 15>,
+		       <&main_pktdma 0xc605 15>,
+		       <&main_pktdma 0xc606 15>,
+		       <&main_pktdma 0xc607 15>,
+		       <&main_pktdma 0x4600 15>;
+		dma-names = "tx0", "tx1", "tx2", "tx3", "tx4", "tx5", "tx6",
+			    "tx7", "rx";
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			cpsw_port1: port@1 {
+				reg = <1>;
+				ti,mac-only;
+				label = "port1";
+				phys = <&phy_gmii_sel 1>;
+				mac-address = [00 00 00 00 00 00];
+			};
+
+			cpsw_port2: port@2 {
+				reg = <2>;
+				ti,mac-only;
+				label = "port2";
+				phys = <&phy_gmii_sel 2>;
+				mac-address = [00 00 00 00 00 00];
+			};
+		};
+
+		cpsw3g_mdio: mdio@f00 {
+			compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+			reg = <0x00 0xf00 0x00 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&k3_clks 13 0>;
+			clock-names = "fck";
+			bus_freq = <1000000>;
+			status = "disabled";
+		};
+
+		cpts@3d000 {
+			compatible = "ti,j721e-cpts";
+			reg = <0x00 0x3d000 0x00 0x400>;
+			clocks = <&k3_clks 13 3>;
+			clock-names = "cpts";
+			interrupts-extended = <&gic500 GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "cpts";
+			ti,cpts-ext-ts-inputs = <4>;
+			ti,cpts-periodic-outputs = <2>;
+		};
+	};
+
+	hwspinlock: spinlock@2a000000 {
+		compatible = "ti,am64-hwspinlock";
+		reg = <0x00 0x2a000000 0x00 0x1000>;
+		#hwlock-cells = <1>;
+	};
+
+	mailbox0_cluster0: mailbox@29000000 {
+		compatible = "ti,am64-mailbox";
+		reg = <0x00 0x29000000 0x00 0x200>;
+		interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+		#mbox-cells = <1>;
+		ti,mbox-num-users = <4>;
+		ti,mbox-num-fifos = <16>;
+	};
+
+	mailbox0_cluster1: mailbox@29010000 {
+		compatible = "ti,am64-mailbox";
+		reg = <0x00 0x29010000 0x00 0x200>;
+		interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+		#mbox-cells = <1>;
+		ti,mbox-num-users = <4>;
+		ti,mbox-num-fifos = <16>;
+	};
+
+	mailbox0_cluster2: mailbox@29020000 {
+		compatible = "ti,am64-mailbox";
+		reg = <0x00 0x29020000 0x00 0x200>;
+		interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+		#mbox-cells = <1>;
+		ti,mbox-num-users = <4>;
+		ti,mbox-num-fifos = <16>;
+	};
+
+	mailbox0_cluster3: mailbox@29030000 {
+		compatible = "ti,am64-mailbox";
+		reg = <0x00 0x29030000 0x00 0x200>;
+		interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+		#mbox-cells = <1>;
+		ti,mbox-num-users = <4>;
+		ti,mbox-num-fifos = <16>;
+	};
+
+	ecap0: pwm@23100000 {
+		compatible = "ti,am3352-ecap";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23100000 0x00 0x100>;
+		power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 51 0>;
+		clock-names = "fck";
+		status = "disabled";
+	};
+
+	ecap1: pwm@23110000 {
+		compatible = "ti,am3352-ecap";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23110000 0x00 0x100>;
+		power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 52 0>;
+		clock-names = "fck";
+		status = "disabled";
+	};
+
+	ecap2: pwm@23120000 {
+		compatible = "ti,am3352-ecap";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23120000 0x00 0x100>;
+		power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 53 0>;
+		clock-names = "fck";
+		status = "disabled";
+	};
+
+	eqep0: counter@23200000 {
+		compatible = "ti,am3352-eqep";
+		reg = <0x00 0x23200000 0x00 0x100>;
+		power-domains = <&k3_pds 59 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 59 0>;
+		clock-names = "fck";
+		interrupts = <GIC_SPI 116 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
+	};
+
+	eqep1: counter@23210000 {
+		compatible = "ti,am3352-eqep";
+		reg = <0x00 0x23210000 0x00 0x100>;
+		power-domains = <&k3_pds 60 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 60 0>;
+		clock-names = "fck";
+		interrupts = <GIC_SPI 117 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
+	};
+
+	eqep2: counter@23220000 {
+		compatible = "ti,am3352-eqep";
+		reg = <0x00 0x23220000 0x00 0x100>;
+		power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 62 0>;
+		clock-names = "fck";
+		interrupts = <GIC_SPI 118 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
+	};
+
+	main_mcan0: can@20701000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x20701000 0x00 0x200>,
+		      <0x00 0x20708000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 98 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 98 6>, <&k3_clks 98 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan1: can@20711000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x20711000 0x00 0x200>,
+		      <0x00 0x20718000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 99 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 99 6>, <&k3_clks 99 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_rti0: watchdog@e000000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x0e000000 0x00 0x100>;
+		clocks = <&k3_clks 125 0>;
+		power-domains = <&k3_pds 125 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 125 0>;
+		assigned-clock-parents = <&k3_clks 125 2>;
+	};
+
+	main_rti1: watchdog@e010000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x0e010000 0x00 0x100>;
+		clocks = <&k3_clks 126 0>;
+		power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 126 0>;
+		assigned-clock-parents = <&k3_clks 126 2>;
+	};
+
+	main_rti2: watchdog@e020000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x0e020000 0x00 0x100>;
+		clocks = <&k3_clks 127 0>;
+		power-domains = <&k3_pds 127 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 127 0>;
+		assigned-clock-parents = <&k3_clks 127 2>;
+	};
+
+	main_rti3: watchdog@e030000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x0e030000 0x00 0x100>;
+		clocks = <&k3_clks 128 0>;
+		power-domains = <&k3_pds 128 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 128 0>;
+		assigned-clock-parents = <&k3_clks 128 2>;
+	};
+
+	main_rti15: watchdog@e0f0000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x0e0f0000 0x00 0x100>;
+		clocks = <&k3_clks 130 0>;
+		power-domains = <&k3_pds 130 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 130 0>;
+		assigned-clock-parents = <&k3_clks 130 2>;
+	};
+
+	epwm0: pwm@23000000 {
+		compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23000000 0x00 0x100>;
+		power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&epwm_tbclk 0>, <&k3_clks 86 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	epwm1: pwm@23010000 {
+		compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23010000 0x00 0x100>;
+		power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&epwm_tbclk 1>, <&k3_clks 87 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	epwm2: pwm@23020000 {
+		compatible = "ti,am64-epwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x23020000 0x00 0x100>;
+		power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&epwm_tbclk 2>, <&k3_clks 88 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	mcasp0: audio-controller@2b00000 {
+		compatible = "ti,am33xx-mcasp-audio";
+		reg = <0x00 0x02b00000 0x00 0x2000>,
+		      <0x00 0x02b08000 0x00 0x400>;
+		reg-names = "mpu", "dat";
+		interrupts = <GIC_SPI 236 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "tx", "rx";
+
+		dmas = <&main_bcdma 0 0xc500 0>, <&main_bcdma 0 0x4500 0>;
+		dma-names = "tx", "rx";
+
+		clocks = <&k3_clks 190 0>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 190 0>;
+		assigned-clock-parents = <&k3_clks 190 2>;
+		power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	mcasp1: audio-controller@2b10000 {
+		compatible = "ti,am33xx-mcasp-audio";
+		reg = <0x00 0x02b10000 0x00 0x2000>,
+		      <0x00 0x02b18000 0x00 0x400>;
+		reg-names = "mpu", "dat";
+		interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 237 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "tx", "rx";
+
+		dmas = <&main_bcdma 0 0xc501 0>, <&main_bcdma 0 0x4501 0>;
+		dma-names = "tx", "rx";
+
+		clocks = <&k3_clks 191 0>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 191 0>;
+		assigned-clock-parents = <&k3_clks 191 2>;
+		power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	mcasp2: audio-controller@2b20000 {
+		compatible = "ti,am33xx-mcasp-audio";
+		reg = <0x00 0x02b20000 0x00 0x2000>,
+		      <0x00 0x02b28000 0x00 0x400>;
+		reg-names = "mpu", "dat";
+		interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "tx", "rx";
+
+		dmas = <&main_bcdma 0 0xc502 0>, <&main_bcdma 0 0x4502 0>;
+		dma-names = "tx", "rx";
+
+		clocks = <&k3_clks 192 0>;
+		clock-names = "fck";
+		assigned-clocks = <&k3_clks 192 0>;
+		assigned-clock-parents = <&k3_clks 192 2>;
+		power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	dss0: dss@30200000 {
+		compatible = "ti,am62p51-dss";
+		reg = <0x00 0x30200000 0x00 0x1000>, /* common */
+		      <0x00 0x30202000 0x00 0x1000>, /* vidl1 */
+		      <0x00 0x30206000 0x00 0x1000>, /* vid */
+		      <0x00 0x30207000 0x00 0x1000>, /* ovr1 */
+		      <0x00 0x30208000 0x00 0x1000>, /* ovr2 */
+		      <0x00 0x3020a000 0x00 0x1000>, /* vp1: Used for OLDI */
+		      <0x00 0x3020b000 0x00 0x1000>, /* vp2: Used as DPI Out */
+		      <0x00 0x30201000 0x00 0x1000>; /* common1 */
+		reg-names = "common", "vidl1", "vid",
+			    "ovr1", "ovr2", "vp1", "vp2", "common1";
+		ti,am65x-oldi-io-ctrl = <&dss_oldi_io_ctrl>;
+		power-domains = <&k3_pds 186 TI_SCI_PD_EXCLUSIVE>,	/* DSS0 */
+				<&k3_pds 243 TI_SCI_PD_EXCLUSIVE>,	/* OLDI0 */
+				<&k3_pds 244 TI_SCI_PD_EXCLUSIVE>;	/* OLDI1 */
+		clocks = <&k3_clks 186 6>,
+			 <&k3_clks 186 0>,
+			 <&k3_clks 186 2>;
+		clock-names = "fck", "vp1", "vp2";
+		interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+
+		dss0_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	gpu: gpu@fd80000 {
+		compatible = "ti,am62p-pvr", "img,pvr-bxs64";
+		reg = <0x00 0x0fd80000 0x00 0x80000>;
+		interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 237 TI_SCI_PD_EXCLUSIVE>,
+				<&k3_pds 242 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 237 3>;
+		assigned-clock-rates = <800000000>;
+		power-domain-names = "firmware", "dust";
+		clocks = <&k3_clks 237 3>;
+		clock-names = "core";
+	};
+
+	ti_csi2rx0: ticsi2rx@30102000 {
+		compatible = "ti,j721e-csi2rx";
+		dmas = <&main_bcdma_csi 0 0x5000 0>, <&main_bcdma_csi 0 0x5001 0>,
+			<&main_bcdma_csi 0 0x5002 0>, <&main_bcdma_csi 0 0x5003 0>,
+			<&main_bcdma_csi 0 0x5004 0>, <&main_bcdma_csi 0 0x5005 0>;
+		dma-names = "rx0", "rx1", "rx2", "rx3", "rx4", "rx5";
+		reg = <0x00 0x30102000 0x00 0x1000>;
+		power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		status = "disabled";
+
+		cdns_csi2rx0: csi-bridge@30101000 {
+			compatible = "cdns,csi2rx";
+			reg = <0x00 0x30101000 0x00 0x1000>;
+			clocks = <&k3_clks 182 0>, <&k3_clks 182 3>, <&k3_clks 182 0>,
+				<&k3_clks 182 0>, <&k3_clks 182 4>, <&k3_clks 182 4>;
+			clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+				"pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+			phys = <&dphy0>;
+			phy-names = "dphy";
+			power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				csi0_port0: port@0 {
+					reg = <0>;
+					status = "disabled";
+				};
+
+				csi0_port1: port@1 {
+					reg = <1>;
+					status = "disabled";
+				};
+
+				csi0_port2: port@2 {
+					reg = <2>;
+					status = "disabled";
+				};
+
+				csi0_port3: port@3 {
+					reg = <3>;
+					status = "disabled";
+				};
+
+				csi0_port4: port@4 {
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
+	dphy0: phy@30110000 {
+		compatible = "cdns,dphy-rx";
+		reg = <0x00 0x30110000 0x00 0x1100>;
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 185 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	dss1: dss@30220000 {
+		compatible = "ti,am62p52-dss";
+		reg = <0x00 0x30220000 0x00 0x1000>, /* common */
+		      <0x00 0x30222000 0x00 0x1000>, /* vidl1 */
+		      <0x00 0x30226000 0x00 0x1000>, /* vid */
+		      <0x00 0x30227000 0x00 0x1000>, /* ovr1 */
+		      <0x00 0x30228000 0x00 0x1000>, /* ovr2 */
+		      <0x00 0x3022a000 0x00 0x1000>, /* vp1: Used for OLDI */
+		      <0x00 0x3022b000 0x00 0x1000>; /* vp2: Used as DPI Out */
+		reg-names = "common", "vidl1", "vid",
+			    "ovr1", "ovr2", "vp1", "vp2";
+		ti,am65x-oldi-io-ctrl = <&dss_oldi_io_ctrl>;
+		power-domains = <&k3_pds 232 TI_SCI_PD_EXCLUSIVE>,	/* DSS0 */
+				<&k3_pds 244 TI_SCI_PD_EXCLUSIVE>;	/* OLDI1 */
+		clocks = <&k3_clks 232 8>,
+			 <&k3_clks 232 0>,
+			 <&k3_clks 232 4>;
+		clock-names = "fck", "vp1", "vp2";
+		interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+		status = "disabled";
+
+		dss1_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	dphy_tx0: phy@301c0000 {
+		compatible = "ti,j721e-dphy";
+		reg = <0x0 0x301c0000 0x0 0x1000>;
+		clocks = <&k3_clks 238 16>, <&k3_clks 238 1>;
+		clock-names = "psm", "pll_ref";
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 238 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 238 1>;
+		assigned-clock-parents = <&k3_clks 238 2>;
+		assigned-clock-rates = <25000000>;
+		status = "disabled";
+	};
+
+	dsi0: dsi@30500000 {
+		compatible = "ti,j721e-dsi";
+		reg = <0x0 0x30500000 0x0 0x100000>, <0x0 0x30270000 0x0 0x100>;
+		clocks = <&k3_clks 231 2>, <&k3_clks 231 5>;
+		clock-names = "dsi_p_clk", "dsi_sys_clk";
+		power-domains = <&k3_pds 231 TI_SCI_PD_EXCLUSIVE>;
+		interrupt-parent = <&gic500>;
+		interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+		phys = <&dphy_tx0>;
+		phy-names = "dphy";
+		status = "disabled";
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p-mcu.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for the AM62P MCU domain peripherals
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+&cbass_mcu {
+	mcu_ram: sram@79100000 {
+		compatible = "mmio-sram";
+		reg = <0x00 0x79100000 0x00 0x80000>;
+		ranges = <0x00 0x00 0x79100000 0x80000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		mcu_sram1@0 {
+			reg = <0x0 0x80000>;
+		};
+	};
+
+	mcu_pmx0: pinctrl@4084000 {
+		compatible = "pinctrl-single";
+		reg = <0x00 0x04084000 0x00 0x88>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+		bootph-all;
+	};
+
+	mcu_esm: esm@4100000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x00 0x4100000 0x00 0x1000>;
+		ti,esm-pins = <0>, <1>, <2>, <85>;
+		status = "reserved";
+		bootph-pre-ram;
+	};
+
+	/*
+	 * The MCU domain timer interrupts are routed only to the ESM module,
+	 * and not currently available for Linux. The MCU domain timers are
+	 * of limited use without interrupts, and likely reserved by the ESM.
+	 */
+	mcu_timer0: timer@4800000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x4800000 0x00 0x400>;
+		clocks = <&k3_clks 35 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		status = "reserved";
+	};
+
+	mcu_timer1: timer@4810000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x4810000 0x00 0x400>;
+		clocks = <&k3_clks 48 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 48 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		status = "reserved";
+	};
+
+	mcu_timer2: timer@4820000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x4820000 0x00 0x400>;
+		clocks = <&k3_clks 49 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 49 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		status = "reserved";
+	};
+
+	mcu_timer3: timer@4830000 {
+		compatible = "ti,am654-timer";
+		reg = <0x00 0x4830000 0x00 0x400>;
+		clocks = <&k3_clks 50 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 50 TI_SCI_PD_EXCLUSIVE>;
+		ti,timer-pwm;
+		status = "reserved";
+	};
+
+	mcu_uart0: serial@4a00000 {
+		compatible = "ti,am64-uart", "ti,am654-uart";
+		reg = <0x00 0x04a00000 0x00 0x100>;
+		interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 149 0>;
+		clock-names = "fclk";
+		status = "disabled";
+	};
+
+	mcu_i2c0: i2c@4900000 {
+		compatible = "ti,am64-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x04900000 0x00 0x100>;
+		interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 106 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 106 2>;
+		clock-names = "fck";
+		status = "disabled";
+	};
+
+	mcu_spi0: spi@4b00000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x04b00000 0x00 0x400>;
+		interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 147 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 147 0>;
+		status = "disabled";
+	};
+
+	mcu_spi1: spi@4b10000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x04b10000 0x00 0x400>;
+		interrupts = <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 148 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 148 0>;
+		status = "disabled";
+	};
+
+	mcu_gpio_intr: interrupt-controller@4210000 {
+		compatible = "ti,sci-intr";
+		reg = <0x00 0x04210000 0x00 0x200>;
+		ti,intr-trigger-type = <1>;
+		interrupt-controller;
+		interrupt-parent = <&gic500>;
+		#interrupt-cells = <1>;
+		ti,sci = <&dmsc>;
+		ti,sci-dev-id = <5>;
+		ti,interrupt-ranges = <0 104 4>;
+	};
+
+	mcu_gpio0: gpio@4201000 {
+		compatible = "ti,am64-gpio", "ti,keystone-gpio";
+		reg = <0x00 0x4201000 0x00 0x100>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&mcu_gpio_intr>;
+		interrupts = <30>, <31>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		ti,ngpio = <24>;
+		ti,davinci-gpio-unbanked = <0>;
+		power-domains = <&k3_pds 79 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 79 0>;
+		clock-names = "gpio";
+	};
+
+	mcu_rti0: watchdog@4880000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x04880000 0x00 0x100>;
+		clocks = <&k3_clks 131 0>;
+		power-domains = <&k3_pds 131 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 131 0>;
+		assigned-clock-parents = <&k3_clks 131 2>;
+		/* Tightly coupled to M4F */
+		status = "reserved";
+	};
+
+	mcu_mcan0: can@4e08000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x4e08000 0x00 0x200>,
+		      <0x00 0x4e00000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 188 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 188 6>, <&k3_clks 188 1>;
+		clock-names = "hclk", "cclk";
+		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		status = "disabled";
+	};
+
+	mcu_mcan1: can@4e18000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x4e18000 0x00 0x200>,
+		      <0x00 0x4e10000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 189 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 189 6>, <&k3_clks 189 1>;
+		clock-names = "hclk", "cclk";
+		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		status = "disabled";
+	};
+
+	mcu_r5fss0: r5fss@79000000 {
+		compatible = "ti,am62-r5fss";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x79000000 0x00 0x79000000 0x8000>,
+			 <0x79020000 0x00 0x79020000 0x8000>;
+		power-domains = <&k3_pds 7 TI_SCI_PD_EXCLUSIVE>;
+		mcu_r5fss0_core0: r5f@79000000 {
+			compatible = "ti,am62-r5f";
+			reg = <0x79000000 0x00008000>,
+			      <0x79020000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <9>;
+			ti,sci-proc-ids = <0x03 0xff>;
+			resets = <&k3_reset 9 1>;
+			firmware-name = "am62p-mcu-r5f0_0-fw";
+			ti,atcm-enable = <0>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <0>;
+			sram = <&mcu_ram>;
+			wakeup-source;
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p-thermal.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/thermal/thermal.h>
+
+thermal_zones: thermal-zones {
+	main0_thermal: main0-thermal {
+		polling-delay-passive = <250>;	/* milliSeconds */
+		polling-delay = <500>;		/* milliSeconds */
+		thermal-sensors = <&wkup_vtm0 0>;
+
+		trips {
+			main0_crit: main0-crit {
+				temperature = <125000>;	/* milliCelsius */
+				hysteresis = <2000>;	/* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+
+	main1_thermal: main1-thermal {
+		polling-delay-passive = <250>;	/* milliSeconds */
+		polling-delay = <500>;		/* milliSeconds */
+		thermal-sensors = <&wkup_vtm0 1>;
+
+		trips {
+			main1_crit: main1-crit {
+				temperature = <125000>;	/* milliCelsius */
+				hysteresis = <2000>;	/* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+
+	main2_thermal: main2-thermal {
+	       polling-delay-passive = <250>;	/* milliSeconds */
+	       polling-delay = <500>;		/* milliSeconds */
+	       thermal-sensors = <&wkup_vtm0 2>;
+
+		trips {
+			main2_crit: main2-crit {
+				temperature = <125000>;	/* milliCelsius */
+				hysteresis = <2000>;	/* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62p-wakeup.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for the AM62P wakeup domain peripherals
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+&cbass_wakeup {
+	wkup_conf: bus@43000000 {
+		compatible = "syscon", "simple-mfd";
+		reg = <0x00 0x43000000 0x00 0x20000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x00 0x00 0x43000000 0x20000>;
+		bootph-all;
+
+		chipid: chipid@14 {
+			compatible = "ti,am654-chipid";
+			reg = <0x14 0x4>;
+			bootph-all;
+		};
+	};
+
+	wkup_uart0: serial@2b300000 {
+		compatible = "ti,am64-uart", "ti,am654-uart";
+		reg = <0x00 0x2b300000 0x00 0x100>;
+		interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 114 0>;
+		clock-names = "fclk";
+		status = "disabled";
+	};
+
+	wkup_i2c0: i2c@2b200000 {
+		compatible = "ti,am64-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x2b200000 0x00 0x100>;
+		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 107 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 107 4>;
+		clock-names = "fck";
+		status = "disabled";
+	};
+
+	wkup_rtc0: rtc@2b1f0000 {
+		compatible = "ti,am62-rtc";
+		reg = <0x00 0x2b1f0000 0x00 0x100>;
+		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 117 6> , <&k3_clks 117 0>;
+		clock-names = "vbus", "osc32k";
+		power-domains = <&k3_pds 117 TI_SCI_PD_EXCLUSIVE>;
+		wakeup-source;
+	};
+
+	wkup_rti0: watchdog@2b000000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2b000000 0x00 0x100>;
+		clocks = <&k3_clks 132 0>;
+		power-domains = <&k3_pds 132 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 132 0>;
+		assigned-clock-parents = <&k3_clks 132 2>;
+		/* Used by DM firmware */
+		status = "reserved";
+	};
+
+	wkup_vtm0: temperature-sensor@b00000 {
+		compatible = "ti,j7200-vtm";
+		reg = <0x00 0xb00000 0x00 0x400>,
+		      <0x00 0xb01000 0x00 0x400>;
+		power-domains = <&k3_pds 95 TI_SCI_PD_EXCLUSIVE>;
+		#thermal-sensor-cells = <1>;
+	};
+
+	wkup_r5fss0: r5fss@78000000 {
+		compatible = "ti,am62-r5fss";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x78000000 0x00 0x78000000 0x8000>,
+			 <0x78100000 0x00 0x78100000 0x8000>;
+		power-domains = <&k3_pds 119 TI_SCI_PD_EXCLUSIVE>;
+
+		wkup_r5fss0_core0: r5f@78000000 {
+			compatible = "ti,am62-r5f";
+			reg = <0x78000000 0x00008000>,
+			      <0x78100000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <121>;
+			ti,sci-proc-ids = <0x01 0xff>;
+			resets = <&k3_reset 121 1>;
+			firmware-name = "am62-wkup-r5f0_0-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62-thermal.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/thermal/thermal.h>
+
+thermal_zones: thermal-zones {
+	main0_thermal: main0-thermal {
+		polling-delay-passive = <250>;	/* milliSeconds */
+		polling-delay = <500>;		/* milliSeconds */
+		thermal-sensors = <&wkup_vtm0 0>;
+
+		trips {
+			main0_crit: main0-crit {
+				temperature = <105000>;	/* milliCelsius */
+				hysteresis = <2000>;	/* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+
+	main1_thermal: main1-thermal {
+		polling-delay-passive = <250>;	/* milliSeconds */
+		polling-delay = <500>;		/* milliSeconds */
+		thermal-sensors = <&wkup_vtm0 1>;
+
+		trips {
+			main1_crit: main1-crit {
+				temperature = <105000>;	/* milliCelsius */
+				hysteresis = <2000>;	/* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi	2024-01-28 14:01:31.236353764 -0500
@@ -7,6 +7,7 @@
 
 &cbass_wakeup {
 	wkup_conf: syscon@43000000 {
+		bootph-all;
 		compatible = "syscon", "simple-mfd";
 		reg = <0x00 0x43000000 0x00 0x20000>;
 		#address-cells = <1>;
@@ -14,9 +15,20 @@
 		ranges = <0x0 0x00 0x43000000 0x20000>;
 
 		chipid: chipid@14 {
+			bootph-all;
 			compatible = "ti,am654-chipid";
 			reg = <0x14 0x4>;
 		};
+
+		usb0_phy_ctrl: syscon@4008 {
+			compatible = "syscon";
+			reg = <0x4008 0x4>;
+		};
+
+		usb1_phy_ctrl: syscon@4018 {
+			compatible = "syscon";
+			reg = <0x4018 0x4>;
+		};
 	};
 
 	wkup_uart0: serial@2b300000 {
@@ -26,16 +38,71 @@
 		power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 114 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	wkup_i2c0: i2c@2b200000 {
 		compatible = "ti,am64-i2c", "ti,omap4-i2c";
-		reg = <0x00 0x02b200000 0x00 0x100>;
+		reg = <0x00 0x2b200000 0x00 0x100>;
 		interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 		power-domains = <&k3_pds 107 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 107 4>;
 		clock-names = "fck";
+		status = "disabled";
+	};
+
+	wkup_rtc0: rtc@2b1f0000 {
+		compatible = "ti,am62-rtc";
+		reg = <0x00 0x2b1f0000 0x00 0x100>;
+		interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 117 6> , <&k3_clks 117 0>;
+		clock-names = "vbus", "osc32k";
+		power-domains = <&k3_pds 117 TI_SCI_PD_EXCLUSIVE>;
+		wakeup-source;
+	};
+
+	wkup_rti0: watchdog@2b000000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2b000000 0x00 0x100>;
+		clocks = <&k3_clks 132 0>;
+		power-domains = <&k3_pds 132 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 132 0>;
+		assigned-clock-parents = <&k3_clks 132 2>;
+		/* Used by DM firmware */
+		status = "reserved";
+	};
+
+	wkup_r5fss0: r5fss@78000000 {
+		compatible = "ti,am62-r5fss";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x78000000 0x00 0x78000000 0x8000>,
+				 <0x78100000 0x00 0x78100000 0x8000>;
+		power-domains = <&k3_pds 119 TI_SCI_PD_EXCLUSIVE>;
+
+		wkup_r5fss0_core0: r5f@78000000 {
+			compatible = "ti,am62-r5f";
+			reg = <0x78000000 0x00008000>,
+			      <0x78100000 0x00008000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&dmsc>;
+			ti,sci-dev-id = <121>;
+			ti,sci-proc-ids = <0x01 0xff>;
+			resets = <&k3_reset 121 1>;
+			firmware-name = "ti-sysfw/ti-fs-stub-firmware-am62x-gp-signed.bin";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+	};
+
+	wkup_vtm0: temperature-sensor@b00000 {
+		compatible = "ti,j7200-vtm";
+		reg = <0x00 0xb00000 0x00 0x400>,
+		      <0x00 0xb01000 0x00 0x400>;
+		power-domains = <&k3_pds 95 TI_SCI_PD_EXCLUSIVE>;
+		#thermal-sensor-cells = <1>;
 	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-common.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,599 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Common dtsi for AM62x SK and derivatives
+ *
+ * Copyright (C) 2021-2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
+#include "k3-am625.dtsi"
+
+/ {
+	aliases {
+		serial0 = &mcu_uart0;
+		serial1 = &wkup_uart0;
+		serial2 = &main_uart0;
+		mmc0 = &sdhci0;
+		mmc1 = &sdhci1;
+		mmc2 = &sdhci2;
+		spi0 = &ospi0;
+		ethernet0 = &cpsw_port1;
+		ethernet1 = &cpsw_port2;
+		usb0 = &usb0;
+		usb1 = &usb1;
+	};
+
+	chosen {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		stdout-path = "serial2:115200n8";
+		bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000";
+
+		framebuffer0: framebuffer@0 {
+			compatible = "simple-framebuffer";
+			power-domains = <&k3_pds 186 TI_SCI_PD_EXCLUSIVE>;
+			clocks = <&k3_clks 186 6>,
+				 <&k3_clks 186 0>,
+				 <&k3_clks 186 2>;
+			display = <&dss>;
+			reg = <0x00 0xff700000 0x00 0x008ca000>;
+			width = <1920>;
+			height = <1200>;
+			stride = <(1920 * 4)>;
+			format = "x8r8g8b8";
+		};
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		/* 2G RAM */
+		reg = <0x00000000 0x80000000 0x00000000 0x80000000>;
+
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		ramoops@9c700000 {
+			compatible = "ramoops";
+			reg = <0x00 0x9c700000 0x00 0x00100000>;
+			record-size = <0x8000>;
+			console-size = <0x8000>;
+			ftrace-size = <0x00>;
+			pmsg-size = <0x8000>;
+		};
+
+		/* global cma region */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x00 0x8000000>;
+			linux,cma-default;
+		};
+
+		rtos_ipc_memory_region: ipc-memories@9c800000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9c800000 0x00 0x00300000>;
+			no-map;
+		};
+
+		mcu_m4fss_dma_memory_region: m4f-dma-memory@9cb00000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9cb00000 0x00 0x100000>;
+			no-map;
+		};
+
+		mcu_m4fss_memory_region: m4f-memory@9cc00000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9cc00000 0x00 0xe00000>;
+			no-map;
+		};
+
+		wkup_r5fss0_core0_dma_memory_region: r5f-dma-memory@9da00000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9da00000 0x00 0x00100000>;
+			no-map;
+		};
+
+		wkup_r5fss0_core0_memory_region: r5f-memory@9db00000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0x9db00000 0x00 0x00c00000>;
+			no-map;
+		};
+
+		secure_tfa_ddr: tfa@9e780000 {
+			reg = <0x00 0x9e780000 0x00 0x80000>;
+			alignment = <0x1000>;
+			no-map;
+		};
+
+		secure_ddr: optee@9e800000 {
+			reg = <0x00 0x9e800000 0x00 0x01800000>; /* for OP-TEE */
+			alignment = <0x1000>;
+			no-map;
+		};
+
+		framebuffer: framebuffer@ff700000 {
+			reg = <0x00 0xff700000 0x00 0x008ca000>;
+			no-map;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&usr_led_pins_default>;
+
+		led-0 {
+			label = "am62-sk:green:heartbeat";
+			gpios = <&main_gpio1 49 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+			function = LED_FUNCTION_HEARTBEAT;
+			default-state = "off";
+		};
+	};
+
+	tlv320_mclk: clk-0 {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <12288000>;
+	};
+
+	codec_audio: sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "AM62x-SKEVM";
+		simple-audio-card,widgets =
+			"Headphone",	"Headphone Jack",
+			"Line",		"Line In",
+			"Microphone",	"Microphone Jack";
+		simple-audio-card,routing =
+			"Headphone Jack",	"HPLOUT",
+			"Headphone Jack",	"HPROUT",
+			"LINE1L",		"Line In",
+			"LINE1R",		"Line In",
+			"MIC3R",		"Microphone Jack",
+			"Microphone Jack",	"Mic Bias";
+		simple-audio-card,format = "dsp_b";
+		simple-audio-card,bitclock-master = <&sound_master>;
+		simple-audio-card,frame-master = <&sound_master>;
+		simple-audio-card,bitclock-inversion;
+
+		simple-audio-card,cpu {
+			sound-dai = <&mcasp1>;
+		};
+
+		sound_master: simple-audio-card,codec {
+			sound-dai = <&tlv320aic3106>;
+			clocks = <&tlv320_mclk>;
+		};
+	};
+
+	hdmi: connector {
+		compatible = "hdmi-connector";
+		label = "hdmi";
+		type = "a";
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&sii9022_out>;
+			};
+		};
+	};
+};
+
+&main_pmx0 {
+	/* First pad number is ALW package and second is AMC package */
+	main_uart0_pins_default: main-uart0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x1c8, PIN_INPUT, 0) /* (D14/A13) UART0_RXD */
+			AM62X_IOPAD(0x1cc, PIN_OUTPUT, 0) /* (E14/E11) UART0_TXD */
+		>;
+	};
+
+	main_i2c0_pins_default: main-i2c0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x1e0, PIN_INPUT_PULLUP, 0) /* (B16/E12) I2C0_SCL */
+			AM62X_IOPAD(0x1e4, PIN_INPUT_PULLUP, 0) /* (A16/D14) I2C0_SDA */
+		>;
+	};
+
+	main_i2c1_pins_default: main-i2c1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x1e8, PIN_INPUT_PULLUP, 0) /* (B17/A17) I2C1_SCL */
+			AM62X_IOPAD(0x1ec, PIN_INPUT_PULLUP, 0) /* (A17/A16) I2C1_SDA */
+		>;
+	};
+
+	main_i2c2_pins_default: main-i2c2-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0b0, PIN_INPUT_PULLUP, 1) /* (K22/H18) GPMC0_CSn2.I2C2_SCL */
+			AM62X_IOPAD(0x0b4, PIN_INPUT_PULLUP, 1) /* (K24/H19) GPMC0_CSn3.I2C2_SDA */
+		>;
+	};
+
+	main_mmc0_pins_default: main-mmc0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x220, PIN_INPUT, 0) /* (Y3/V3) MMC0_CMD */
+			AM62X_IOPAD(0x218, PIN_INPUT, 0) /* (AB1/Y1) MMC0_CLK */
+			AM62X_IOPAD(0x214, PIN_INPUT, 0) /* (AA2/V2) MMC0_DAT0 */
+			AM62X_IOPAD(0x210, PIN_INPUT, 0) /* (AA1/V1) MMC0_DAT1 */
+			AM62X_IOPAD(0x20c, PIN_INPUT, 0) /* (AA3/W2) MMC0_DAT2 */
+			AM62X_IOPAD(0x208, PIN_INPUT, 0) /* (Y4/W1) MMC0_DAT3 */
+			AM62X_IOPAD(0x204, PIN_INPUT, 0) /* (AB2/Y2) MMC0_DAT4 */
+			AM62X_IOPAD(0x200, PIN_INPUT, 0) /* (AC1/W3) MMC0_DAT5 */
+			AM62X_IOPAD(0x1fc, PIN_INPUT, 0) /* (AD2/W4) MMC0_DAT6 */
+			AM62X_IOPAD(0x1f8, PIN_INPUT, 0) /* (AC2/V4) MMC0_DAT7 */
+		>;
+	};
+
+	main_mmc1_pins_default: main-mmc1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x23c, PIN_INPUT, 0) /* (A21/C18) MMC1_CMD */
+			AM62X_IOPAD(0x234, PIN_INPUT, 0) /* (B22/A20) MMC1_CLK */
+			AM62X_IOPAD(0x230, PIN_INPUT, 0) /* (A22/A19) MMC1_DAT0 */
+			AM62X_IOPAD(0x22c, PIN_INPUT, 0) /* (B21/B19) MMC1_DAT1 */
+			AM62X_IOPAD(0x228, PIN_INPUT, 0) /* (C21/B20) MMC1_DAT2 */
+			AM62X_IOPAD(0x224, PIN_INPUT, 0) /* (D22/C19) MMC1_DAT3 */
+			AM62X_IOPAD(0x240, PIN_INPUT, 0) /* (D17/C15) MMC1_SDCD */
+		>;
+	};
+
+	usr_led_pins_default: usr-led-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x244, PIN_OUTPUT, 7) /* (C17/B15) MMC1_SDWP.GPIO1_49 */
+		>;
+	};
+
+	main_mdio1_pins_default: main-mdio1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x160, PIN_OUTPUT, 0) /* (AD24/V17) MDIO0_MDC */
+			AM62X_IOPAD(0x15c, PIN_INPUT, 0) /* (AB22/U16) MDIO0_MDIO */
+		>;
+	};
+
+	main_rgmii1_pins_default: main-rgmii1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x14c, PIN_INPUT, 0) /* (AB17/W15) RGMII1_RD0 */
+			AM62X_IOPAD(0x150, PIN_INPUT, 0) /* (AC17/Y16) RGMII1_RD1 */
+			AM62X_IOPAD(0x154, PIN_INPUT, 0) /* (AB16/AA17) RGMII1_RD2 */
+			AM62X_IOPAD(0x158, PIN_INPUT, 0) /* (AA15/Y15) RGMII1_RD3 */
+			AM62X_IOPAD(0x148, PIN_INPUT, 0) /* (AD17/AA16) RGMII1_RXC */
+			AM62X_IOPAD(0x144, PIN_INPUT, 0) /* (AE17/W14) RGMII1_RX_CTL */
+			AM62X_IOPAD(0x134, PIN_OUTPUT, 0) /* (AE20/U14) RGMII1_TD0 */
+			AM62X_IOPAD(0x138, PIN_OUTPUT, 0) /* (AD20/AA19) RGMII1_TD1 */
+			AM62X_IOPAD(0x13c, PIN_OUTPUT, 0) /* (AE18/Y17) RGMII1_TD2 */
+			AM62X_IOPAD(0x140, PIN_OUTPUT, 0) /* (AD18/AA18) RGMII1_TD3 */
+			AM62X_IOPAD(0x130, PIN_OUTPUT, 0) /* (AE19/W16) RGMII1_TXC */
+			AM62X_IOPAD(0x12c, PIN_OUTPUT, 0) /* (AD19/V15) RGMII1_TX_CTL */
+		>;
+	};
+
+	ospi0_pins_default: ospi0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x000, PIN_OUTPUT, 0) /* (H24) OSPI0_CLK */
+			AM62X_IOPAD(0x02c, PIN_OUTPUT, 0) /* (F23) OSPI0_CSn0 */
+			AM62X_IOPAD(0x00c, PIN_INPUT, 0) /* (E25) OSPI0_D0 */
+			AM62X_IOPAD(0x010, PIN_INPUT, 0) /* (G24) OSPI0_D1 */
+			AM62X_IOPAD(0x014, PIN_INPUT, 0) /* (F25) OSPI0_D2 */
+			AM62X_IOPAD(0x018, PIN_INPUT, 0) /* (F24) OSPI0_D3 */
+			AM62X_IOPAD(0x01c, PIN_INPUT, 0) /* (J23) OSPI0_D4 */
+			AM62X_IOPAD(0x020, PIN_INPUT, 0) /* (J25) OSPI0_D5 */
+			AM62X_IOPAD(0x024, PIN_INPUT, 0) /* (H25) OSPI0_D6 */
+			AM62X_IOPAD(0x028, PIN_INPUT, 0) /* (J22) OSPI0_D7 */
+			AM62X_IOPAD(0x008, PIN_INPUT, 0) /* (J24) OSPI0_DQS */
+		>;
+	};
+
+	main_usb1_pins_default: main-usb1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0258, PIN_OUTPUT, 0) /* (F18/E16) USB1_DRVVBUS */
+		>;
+	};
+
+	main_mcasp1_pins_default: main-mcasp1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x090, PIN_INPUT, 2) /* (M24) GPMC0_BE0N_CLE.MCASP1_ACLKX */
+			AM62X_IOPAD(0x098, PIN_INPUT, 2) /* (U23) GPMC0_WAIT0.MCASP1_AFSX */
+			AM62X_IOPAD(0x08c, PIN_OUTPUT, 2) /* (L25) GPMC0_WEN.MCASP1_AXR0 */
+			AM62X_IOPAD(0x084, PIN_INPUT, 2) /* (L23) GPMC0_ADVN_ALE.MCASP1_AXR2 */
+		>;
+	};
+
+	main_dss0_pins_default: main-dss0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0100, PIN_OUTPUT, 0) /* (AC25) VOUT0_VSYNC */
+			AM62X_IOPAD(0x00f8, PIN_OUTPUT, 0) /* (AB24) VOUT0_HSYNC */
+			AM62X_IOPAD(0x0104, PIN_OUTPUT, 0) /* (AC24) VOUT0_PCLK */
+			AM62X_IOPAD(0x00fc, PIN_OUTPUT, 0) /* (Y20) VOUT0_DE */
+			AM62X_IOPAD(0x00b8, PIN_OUTPUT, 0) /* (U22) VOUT0_DATA0 */
+			AM62X_IOPAD(0x00bc, PIN_OUTPUT, 0) /* (V24) VOUT0_DATA1 */
+			AM62X_IOPAD(0x00c0, PIN_OUTPUT, 0) /* (W25) VOUT0_DATA2 */
+			AM62X_IOPAD(0x00c4, PIN_OUTPUT, 0) /* (W24) VOUT0_DATA3 */
+			AM62X_IOPAD(0x00c8, PIN_OUTPUT, 0) /* (Y25) VOUT0_DATA4 */
+			AM62X_IOPAD(0x00cc, PIN_OUTPUT, 0) /* (Y24) VOUT0_DATA5 */
+			AM62X_IOPAD(0x00d0, PIN_OUTPUT, 0) /* (Y23) VOUT0_DATA6 */
+			AM62X_IOPAD(0x00d4, PIN_OUTPUT, 0) /* (AA25) VOUT0_DATA7 */
+			AM62X_IOPAD(0x00d8, PIN_OUTPUT, 0) /* (V21) VOUT0_DATA8 */
+			AM62X_IOPAD(0x00dc, PIN_OUTPUT, 0) /* (W21) VOUT0_DATA9 */
+			AM62X_IOPAD(0x00e0, PIN_OUTPUT, 0) /* (V20) VOUT0_DATA10 */
+			AM62X_IOPAD(0x00e4, PIN_OUTPUT, 0) /* (AA23) VOUT0_DATA11 */
+			AM62X_IOPAD(0x00e8, PIN_OUTPUT, 0) /* (AB25) VOUT0_DATA12 */
+			AM62X_IOPAD(0x00ec, PIN_OUTPUT, 0) /* (AA24) VOUT0_DATA13 */
+			AM62X_IOPAD(0x00f0, PIN_OUTPUT, 0) /* (Y22) VOUT0_DATA14 */
+			AM62X_IOPAD(0x00f4, PIN_OUTPUT, 0) /* (AA21) VOUT0_DATA15 */
+			AM62X_IOPAD(0x005c, PIN_OUTPUT, 1) /* (R24) GPMC0_AD8.VOUT0_DATA16 */
+			AM62X_IOPAD(0x0060, PIN_OUTPUT, 1) /* (R25) GPMC0_AD9.VOUT0_DATA17 */
+			AM62X_IOPAD(0x0064, PIN_OUTPUT, 1) /* (T25) GPMC0_AD10.VOUT0_DATA18 */
+			AM62X_IOPAD(0x0068, PIN_OUTPUT, 1) /* (R21) GPMC0_AD11.VOUT0_DATA19 */
+			AM62X_IOPAD(0x006c, PIN_OUTPUT, 1) /* (T22) GPMC0_AD12.VOUT0_DATA20 */
+			AM62X_IOPAD(0x0070, PIN_OUTPUT, 1) /* (T24) GPMC0_AD13.VOUT0_DATA21 */
+			AM62X_IOPAD(0x0074, PIN_OUTPUT, 1) /* (U25) GPMC0_AD14.VOUT0_DATA22 */
+			AM62X_IOPAD(0x0078, PIN_OUTPUT, 1) /* (U24) GPMC0_AD15.VOUT0_DATA23 */
+		>;
+	};
+};
+
+&wkup_uart0 {
+	/* WKUP UART0 is used by DM firmware */
+	status = "reserved";
+};
+
+&main_uart0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_uart0_pins_default>;
+	interrupts-extended = <&gic500 GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>,
+			       <&main_pmx0 0x1c8>; /* (D14) UART0_RXD PADCONFIG114 */
+	interrupt-names = "irq", "wakeup";
+};
+
+&main_uart1 {
+	/* Main UART1 is used by TIFS firmware */
+	status = "reserved";
+};
+
+&main_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c0_pins_default>;
+	clock-frequency = <400000>;
+
+	typec_pd0: tps6598x@3f {
+		compatible = "ti,tps6598x";
+		reg = <0x3f>;
+
+		connector {
+			compatible = "usb-c-connector";
+			label = "USB-C";
+			self-powered;
+			data-role = "dual";
+			power-role = "sink";
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					usb_con_hs: endpoint {
+						remote-endpoint = <&usb0_hs_ep>;
+					};
+				};
+			};
+		};
+	};
+};
+
+&main_i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c1_pins_default>;
+	clock-frequency = <100000>;
+
+	tlv320aic3106: audio-codec@1b {
+		#sound-dai-cells = <0>;
+		compatible = "ti,tlv320aic3106";
+		reg = <0x1b>;
+		ai3x-micbias-vg = <1>;	/* 2.0V */
+
+		/* Regulators */
+		AVDD-supply = <&vcc_3v3_sys>;
+		IOVDD-supply = <&vcc_3v3_sys>;
+		DRVDD-supply = <&vcc_3v3_sys>;
+	};
+
+	sii9022: sii9022@3b {
+		#sound-dai-cells = <0>;
+		compatible = "sil,sii9022";
+		reg = <0x3b>;
+
+		interrupt-parent = <&exp1>;
+		interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
+
+		sil,i2s-data-lanes = < 0 >;
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+
+				sii9022_in: endpoint {
+					remote-endpoint = <&dpi1_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+
+				sii9022_out: endpoint {
+					remote-endpoint = <&hdmi_connector_in>;
+				};
+			};
+		};
+	};
+};
+
+&main_i2c2 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c2_pins_default>;
+	clock-frequency = <400000>;
+};
+
+&sdhci0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mmc0_pins_default>;
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
+};
+
+&sdhci1 {
+	/* SD/MMC */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mmc1_pins_default>;
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
+};
+
+&cpsw3g {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_rgmii1_pins_default>;
+};
+
+&cpsw_port1 {
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&cpsw3g_phy0>;
+};
+
+&cpsw3g_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mdio1_pins_default>;
+
+	cpsw3g_phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+};
+
+&mailbox0_cluster0 {
+	mbox_m4_0: mbox-m4-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_r5_0: mbox-r5-0 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mcu_m4fss {
+	mboxes = <&mailbox0_cluster0 &mbox_m4_0>;
+	memory-region = <&mcu_m4fss_dma_memory_region>,
+			<&mcu_m4fss_memory_region>;
+};
+
+&wkup_r5fss0_core0 {
+	mboxes = <&mailbox0_cluster0 &mbox_r5_0>;
+	memory-region = <&wkup_r5fss0_core0_dma_memory_region>,
+			<&wkup_r5fss0_core0_memory_region>;
+};
+
+&usbss0 {
+	status = "okay";
+	ti,vbus-divider;
+};
+
+&usbss1 {
+	status = "okay";
+	ti,vbus-divider;
+};
+
+&usb0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	usb-role-switch;
+
+	port@0 {
+		reg = <0>;
+		usb0_hs_ep: endpoint {
+		    remote-endpoint = <&usb_con_hs>;
+	       };
+	};
+};
+
+&usb1 {
+	dr_mode = "host";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_usb1_pins_default>;
+};
+
+&mcasp1 {
+	status = "okay";
+	#sound-dai-cells = <0>;
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcasp1_pins_default>;
+
+	op-mode = <0>;          /* MCASP_IIS_MODE */
+	tdm-slots = <2>;
+
+	serial-dir = <  /* 0: INACTIVE, 1: TX, 2: RX */
+	       1 0 2 0
+	       0 0 0 0
+	       0 0 0 0
+	       0 0 0 0
+	>;
+	tx-num-evt = <32>;
+	rx-num-evt = <32>;
+};
+
+&ospi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&ospi0_pins_default>;
+};
+
+&ti_csi2rx0 {
+	status = "okay";
+};
+
+&dphy0 {
+	status = "okay";
+};
+
+&dss {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_dss0_pins_default>;
+};
+
+&dss_ports {
+	/* VP2: DPI Output */
+	port@1 {
+		reg = <1>;
+
+		dpi1_out: endpoint {
+			remote-endpoint = <&sii9022_in>;
+		};
+	};
+};
+
+/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */
+&mcu_gpio0 {
+	status = "reserved";
+};
+
+&mcu_gpio_intr {
+	status = "reserved";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-imx219.dtso b/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-imx219.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-imx219.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-imx219.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX219 (RPi v2) Camera Module
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_imx219_fixed: imx219-xclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+	};
+};
+
+&main_i2c2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	i2c-switch@71 {
+		compatible = "nxp,pca9543";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x71>;
+
+		/* CAM port */
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			ov5640: camera@10 {
+				compatible = "sony,imx219";
+				reg = <0x10>;
+
+				clocks = <&clk_imx219_fixed>;
+				clock-names = "xclk";
+
+				reset-gpios = <&exp1 13 GPIO_ACTIVE_HIGH>;
+
+				port {
+					csi2_cam0: endpoint {
+						remote-endpoint = <&csi2rx0_in_sensor>;
+						link-frequencies = /bits/ 64 <456000000>;
+						clock-lanes = <0>;
+						data-lanes = <1 2>;
+					};
+				};
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-ov5640.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-ov5640.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-ov5640.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ALINX AN5641 & Digilent PCam 5C - OV5640 camera module
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_ov5640_fixed: ov5640-xclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <12000000>;
+	};
+};
+
+&main_i2c2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	i2c-switch@71 {
+		compatible = "nxp,pca9543";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x71>;
+
+		/* CAM port */
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			ov5640: camera@3c {
+				compatible = "ovti,ov5640";
+				reg = <0x3c>;
+
+				clocks = <&clk_ov5640_fixed>;
+				clock-names = "xclk";
+				powerdown-gpios = <&exp1 13 GPIO_ACTIVE_LOW>;
+
+				port {
+					csi2_cam0: endpoint {
+						remote-endpoint = <&csi2rx0_in_sensor>;
+						clock-lanes = <0>;
+						data-lanes = <1 2>;
+					};
+				};
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-tevi-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-tevi-ov5640.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-tevi-ov5640.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-csi2-tevi-ov5640.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Technexion TEVI-OV5640-*-RPI - OV5640 camera module
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_ov5640_fixed: ov5640-xclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+	};
+};
+
+&main_i2c2 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	i2c-switch@71 {
+		compatible = "nxp,pca9543";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x71>;
+
+		/* CAM port */
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			ov5640: camera@3c {
+				compatible = "ovti,ov5640";
+				reg = <0x3c>;
+
+				clocks = <&clk_ov5640_fixed>;
+				clock-names = "xclk";
+				powerdown-gpios = <&exp1 13 GPIO_ACTIVE_LOW>;
+
+				port {
+					csi2_cam0: endpoint {
+						remote-endpoint = <&csi2rx0_in_sensor>;
+						clock-lanes = <0>;
+						data-lanes = <1 2>;
+					};
+				};
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-sk-eqep.dtso b/arch/arm64/boot/dts/ti/k3-am62x-sk-eqep.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-eqep.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-eqep.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay for enabling EQEP on AM625-SK
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+	main_eqep0_pins_default: main-eqep0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x0194, PIN_INPUT, 8) /* (B19) MCASP0_AXR3.EQEP0_A */
+			AM62X_IOPAD(0x0198, PIN_INPUT, 8) /* (A19) MCASP0_AXR2.EQEP0_B */
+			AM62X_IOPAD(0x01a0, PIN_INPUT, 8) /* (E18) MCASP0_AXR0.EQEP0_I */
+			AM62X_IOPAD(0x019c, PIN_INPUT, 8) /* (B18) MCASP0_AXR1.EQEP0_S */
+		>;
+	};
+};
+
+&main_i2c1 {
+	gpio@22 {
+		p25-hog {
+			/* P25 - UART1_FET_SEL */
+			gpio-hog;
+			gpios = <21 GPIO_ACTIVE_HIGH>;
+			output-low;
+			line-name = "UART1_FET_SEL";
+		};
+	};
+};
+
+&eqep0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_eqep0_pins_default>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-sk-hdmi-audio.dtso b/arch/arm64/boot/dts/ti/k3-am62x-sk-hdmi-audio.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-hdmi-audio.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-hdmi-audio.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * Audio playback via HDMI for AM625-SK and AM62-LP SK.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	hdmi_audio: sound-sii9022 {
+		compatible = "simple-audio-card";
+		simple-audio-card,name = "AM62x-Sil9022-HDMI";
+		simple-audio-card,format = "i2s";
+		simple-audio-card,bitclock-master = <&hdmi_dailink_master>;
+		simple-audio-card,frame-master = <&hdmi_dailink_master>;
+		hdmi_dailink_master: simple-audio-card,cpu {
+			sound-dai = <&mcasp1>;
+			system-clock-direction-out;
+		};
+		simple-audio-card,codec {
+			sound-dai = <&sii9022>;
+		};
+	};
+};
+
+&mcasp1 {
+	auxclk-fs-ratio = <2177>;
+};
+
+&codec_audio {
+	status = "disabled";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-sk-lpm-wkup-sources.dtso b/arch/arm64/boot/dts/ti/k3-am62x-sk-lpm-wkup-sources.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-lpm-wkup-sources.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-lpm-wkup-sources.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,150 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * AM62 family of devices can wakeup from Low Power Modes via
+ * multiple wakeup sources. This overlay enables MAIN GPIO, MCU GPIO,
+ * and MCU MCAN pins.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	gpio_key {
+		compatible = "gpio-keys";
+		autorepeat;
+		pinctrl-names = "default";
+		pinctrl-0 = <&main_gpio1_pins_default>;
+		switch {
+			label = "WKGPIO";
+			linux,code = <KEY_WAKEUP>;
+			interrupts-extended = <&main_gpio1 10 IRQ_TYPE_EDGE_RISING>,
+				<&main_pmx0 0x1a0>;
+			interrupt-names = "irq", "wakeup";
+		};
+	};
+
+	mcu_gpio_key {
+		compatible = "gpio-keys";
+			autorepeat;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wake_mcugpio1_pins_default>;
+		interrupt-parent = <&mcu_gpio0>;
+		interrupts = <16 IRQ_TYPE_EDGE_RISING>;
+		switch {
+			label = "MCUGPIO";
+			linux,code = <143>;
+			gpios = <&mcu_gpio0 16 GPIO_ACTIVE_LOW>;
+			wakeup-source;
+		};
+	};
+};
+
+&main_pmx0 {
+	main_gpio1_pins_default: main-gpio1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x1a0, PIN_INPUT_PULLUP, 7) /* (E18) MCASP0_AXR0.EHRPWM1_B */
+		>;
+	};
+};
+
+&mcu_pmx0 {
+	wake_mcugpio1_pins_default: wake-mcugpio1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_MCU_IOPAD(0x0040, PIN_INPUT, 7) /* (D6) MCU_MCAN1_RX.MCU_GPIO0_16 */
+		>;
+	};
+
+	mcu_mcan0_tx_pins_default: mcu-mcan0-tx-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x034, PIN_OUTPUT, 0) /* (D6) MCU_MCAN0_TX */
+		>;
+	};
+
+	mcu_mcan0_rx_pins_default: mcu-mcan0-rx-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x038, PIN_INPUT, 0) /* (B3) MCU_MCAN0_RX */
+		>;
+	};
+
+	mcu_mcan0_rx_pins_wakeup: mcu-mcan0-rx-pins-wakeup {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x038, PIN_INPUT | WKUP_EN, 0) /* (B3) MCU_MCAN0_RX */
+		>;
+	};
+
+	mcu_mcan1_tx_pins_default: mcu-mcan1-tx-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x03c, PIN_OUTPUT, 0) /* (E5) MCU_MCAN1_TX */
+		>;
+	};
+
+	mcu_mcan1_rx_pins_default: mcu-mcan1-rx-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x040, PIN_INPUT, 0) /* (D4) MCU_MCAN1_RX */
+		>;
+	};
+
+	mcu_mcan1_rx_pins_wakeup: mcu-mcan1-rx-pins-wakeup {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x040, PIN_INPUT | WKUP_EN, 0) /* (D4) MCU_MCAN1_RX */
+		>;
+	};
+
+	mcu_uart0_pins_default: mcu-uart0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_MCU_IOPAD(0x001c, PIN_INPUT, 0) /* MCU_UART0_CTSn */
+			AM62X_MCU_IOPAD(0x0020, PIN_OUTPUT, 0) /* MCU_UART0_RTSn */
+			AM62X_MCU_IOPAD(0x0018, PIN_OUTPUT, 0) /* MCU_UART0_TXD */
+		>;
+	};
+
+	mcu_uart0_rxd_pins_default: mcu-uart0-rxd-pins-default {
+		pinctrl-single,pins = <
+			AM62X_MCU_IOPAD(0x0014, PIN_INPUT, 0) /* MCU_UART0_RXD */
+		>;
+	};
+
+	mcu_uart0_rxd_pins_wakeup: mcu-uart0-rxd-pins-wakeup {
+		pinctrl-single,pins = <
+			AM62X_MCU_IOPAD(0x0014, PIN_INPUT | WKUP_EN, 0) /* MCU_UART0_RXD */
+		>;
+	};
+};
+
+&mcu_gpio0 {
+	status = "okay";
+};
+
+&mcu_gpio_intr {
+	status = "okay";
+};
+
+&mcu_mcan0 {
+	pinctrl-names = "default", "wakeup";
+	pinctrl-0 = <&mcu_mcan0_tx_pins_default>, <&mcu_mcan0_rx_pins_default>;
+	pinctrl-1 = <&mcu_mcan0_tx_pins_default>, <&mcu_mcan0_rx_pins_wakeup>;
+	status = "okay";
+};
+
+&mcu_mcan1 {
+	pinctrl-names = "default", "wakeup";
+	pinctrl-0 = <&mcu_mcan1_tx_pins_default>, <&mcu_mcan1_rx_pins_default>;
+	pinctrl-1 = <&mcu_mcan1_tx_pins_default>, <&mcu_mcan1_rx_pins_wakeup>;
+	status = "okay";
+};
+
+&mcu_uart0 {
+	pinctrl-names = "default", "wakeup";
+	pinctrl-0 = <&mcu_uart0_pins_default>, <&mcu_uart0_rxd_pins_default>;
+	pinctrl-1 = <&mcu_uart0_pins_default>, <&mcu_uart0_rxd_pins_wakeup>;
+	status = "ok";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am62x-sk-mcan.dtso b/arch/arm64/boot/dts/ti/k3-am62x-sk-mcan.dtso
--- a/arch/arm64/boot/dts/ti/k3-am62x-sk-mcan.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am62x-sk-mcan.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT overlay to enable MCAN on AM625-SK, AM62A-SK, AM62 LP-SK
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	transceiver1: can-phy0 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	transceiver2: can-phy1 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	transceiver3: can-phy2 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+};
+
+&main_pmx0 {
+	main_mcan0_pins_default: main-mcan0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_IOPAD(0x01dc, PIN_INPUT, 0) /* (E15) MCAN0_RX */
+			AM62X_IOPAD(0x01d8, PIN_OUTPUT, 0) /* (C15) MCAN0_TX */
+		>;
+	};
+};
+
+&mcu_pmx0 {
+	mcu_mcan0_pins_default: mcu-mcan0-pins-default {
+		pinctrl-single,pins = <
+			AM62X_MCU_IOPAD(0x0038, PIN_INPUT, 0) /* (B3) MCU_MCAN0_RX */
+			AM62X_MCU_IOPAD(0x0034, PIN_OUTPUT, 0) /* (D6) MCU_MCAN0_TX */
+		>;
+	};
+
+	mcu_mcan1_pins_default: mcu-mcan1-pins-default {
+		pinctrl-single,pins = <
+			AM62X_MCU_IOPAD(0x0040, PIN_INPUT, 0) /* (D4) MCU_MCAN1_RX */
+			AM62X_MCU_IOPAD(0x003c, PIN_OUTPUT, 0) /* (E5) MCU_MCAN1_TX */
+		>;
+	};
+};
+
+&main_mcan0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcan0_pins_default>;
+	phys = <&transceiver1>;
+	status = "okay";
+};
+
+&mcu_mcan0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mcan0_pins_default>;
+	phys = <&transceiver2>;
+	status = "okay";
+};
+
+&mcu_mcan1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mcan1_pins_default>;
+	phys = <&transceiver3>;
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am642.dtsi b/arch/arm64/boot/dts/ti/k3-am642.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am642.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am642.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -58,6 +58,7 @@
 	L2_0: l2-cache0 {
 		compatible = "cache";
 		cache-level = <2>;
+		cache-unified;
 		cache-size = <0x40000>;
 		cache-line-size = <64>;
 		cache-sets = <256>;
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am642-evm.dts b/arch/arm64/boot/dts/ti/k3-am642-evm.dts
--- a/arch/arm64/boot/dts/ti/k3-am642-evm.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am642-evm.dts	2024-01-28 14:01:31.240353775 -0500
@@ -21,6 +21,11 @@
 		bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000";
 	};
 
+	aliases {
+		ethernet2 = &icssg1_emac0;
+		ethernet3 = &icssg1_emac1;
+	};
+
 	memory@80000000 {
 		device_type = "memory";
 		/* 2G RAM */
@@ -87,6 +92,18 @@
 			no-map;
 		};
 
+		mcu_m4fss_dma_memory_region: m4f-dma-memory@a4000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa4000000 0x00 0x100000>;
+			no-map;
+		};
+
+		mcu_m4fss_memory_region: m4f-memory@a4100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa4100000 0x00 0xf00000>;
+			no-map;
+		};
+
 		rtos_ipc_memory_region: ipc-memories@a5000000 {
 			reg = <0x00 0xa5000000 0x00 0x00800000>;
 			alignment = <0x1000>;
@@ -167,7 +184,7 @@
 		mux-gpios = <&exp1 12 GPIO_ACTIVE_HIGH>;
 	};
 
-	mdio-mux-1 {
+	mdio_mux_1: mdio-mux-1 {
 		compatible = "mdio-mux-multiplexer";
 		mux-controls = <&mdio_mux>;
 		mdio-parent-bus = <&cpsw3g_mdio>;
@@ -181,6 +198,8 @@
 
 			cpsw3g_phy3: ethernet-phy@3 {
 				reg = <3>;
+				tx-internal-delay-ps = <250>;
+				rx-internal-delay-ps = <2000>;
 			};
 		};
 	};
@@ -198,6 +217,73 @@
 		max-bitrate = <5000000>;
 		standby-gpios = <&exp1 9 GPIO_ACTIVE_HIGH>;
 	};
+
+	icssg1_eth: icssg1-eth {
+		compatible = "ti,am642-icssg-prueth";
+		pinctrl-names = "default";
+		pinctrl-0 = <&icssg1_rgmii1_pins_default>;
+
+		sram = <&oc_sram>;
+		ti,prus = <&pru1_0>, <&rtu1_0>, <&tx_pru1_0>, <&pru1_1>, <&rtu1_1>, <&tx_pru1_1>;
+		firmware-name = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-rtu0-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-txpru0-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-pru1-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-rtu1-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-txpru1-prueth-fw.elf";
+
+		ti,pruss-gp-mux-sel = <2>,	/* MII mode */
+				      <2>,
+				      <2>,
+				      <2>,	/* MII mode */
+				      <2>,
+				      <2>;
+
+		ti,mii-g-rt = <&icssg1_mii_g_rt>;
+		ti,mii-rt = <&icssg1_mii_rt>;
+		ti,pa-stats = <&icssg1_pa_stats>;
+		iep = <&icssg1_iep0>,  <&icssg1_iep1>;
+
+		interrupt-parent = <&icssg1_intc>;
+		interrupts = <24 0 2>, <25 1 3>;
+		interrupt-names = "tx_ts0", "tx_ts1";
+
+		dmas = <&main_pktdma 0xc200 15>, /* egress slice 0 */
+		       <&main_pktdma 0xc201 15>, /* egress slice 0 */
+		       <&main_pktdma 0xc202 15>, /* egress slice 0 */
+		       <&main_pktdma 0xc203 15>, /* egress slice 0 */
+		       <&main_pktdma 0xc204 15>, /* egress slice 1 */
+		       <&main_pktdma 0xc205 15>, /* egress slice 1 */
+		       <&main_pktdma 0xc206 15>, /* egress slice 1 */
+		       <&main_pktdma 0xc207 15>, /* egress slice 1 */
+		       <&main_pktdma 0x4200 15>, /* ingress slice 0 */
+		       <&main_pktdma 0x4201 15>, /* ingress slice 1 */
+		       <&main_pktdma 0x4202 0>, /* mgmnt rsp slice 0 */
+		       <&main_pktdma 0x4203 0>; /* mgmnt rsp slice 1 */
+		dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3",
+			    "tx1-0", "tx1-1", "tx1-2", "tx1-3",
+			    "rx0", "rx1";
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			icssg1_emac0: port@0 {
+				reg = <0>;
+				phy-handle = <&icssg1_phy1>;
+				phy-mode = "rgmii-id";
+				ti,syscon-rgmii-delay = <&main_conf 0x4110>;
+				/* Filled in by bootloader */
+				local-mac-address = [00 00 00 00 00 00];
+			};
+			icssg1_emac1: port@1 {
+				reg = <1>;
+				ti,syscon-rgmii-delay = <&main_conf 0x4114>;
+				/* Filled in by bootloader */
+				local-mac-address = [00 00 00 00 00 00];
+				status = "disabled";
+			};
+		};
+	};
 };
 
 &main_pmx0 {
@@ -322,9 +408,40 @@
 			AM64X_IOPAD(0x0258, PIN_OUTPUT, 0) /* (C17) MCAN1_TX */
 		>;
 	};
+
+	icssg1_mdio1_pins_default: icssg1-mdio1-pins-default {
+		pinctrl-single,pins = <
+			AM64X_IOPAD(0x015c, PIN_OUTPUT, 0) /* (Y6) PRG1_MDIO0_MDC */
+			AM64X_IOPAD(0x0158, PIN_INPUT, 0) /* (AA6) PRG1_MDIO0_MDIO */
+		>;
+	};
+
+	icssg1_rgmii1_pins_default: icssg1-rgmii1-pins-default {
+		pinctrl-single,pins = <
+			AM64X_IOPAD(0x00b8, PIN_INPUT, 2) /* (Y7) PRG1_PRU0_GPO0.PRG1_RGMII1_RD0 */
+			AM64X_IOPAD(0x00bc, PIN_INPUT, 2) /* (U8) PRG1_PRU0_GPO1.PRG1_RGMII1_RD1 */
+			AM64X_IOPAD(0x00c0, PIN_INPUT, 2) /* (W8) PRG1_PRU0_GPO2.PRG1_RGMII1_RD2 */
+			AM64X_IOPAD(0x00c4, PIN_INPUT, 2) /* (V8) PRG1_PRU0_GPO3.PRG1_RGMII1_RD3 */
+			AM64X_IOPAD(0x00d0, PIN_INPUT, 2) /* (AA7) PRG1_PRU0_GPO6.PRG1_RGMII1_RXC */
+			AM64X_IOPAD(0x00c8, PIN_INPUT, 2) /* (Y8) PRG1_PRU0_GPO4.PRG1_RGMII1_RX_CTL */
+			AM64X_IOPAD(0x00e4, PIN_INPUT, 2) /* (AA8) PRG1_PRU0_GPO11.PRG1_RGMII1_TD0 */
+			AM64X_IOPAD(0x00e8, PIN_INPUT, 2) /* (U9) PRG1_PRU0_GPO12.PRG1_RGMII1_TD1 */
+			AM64X_IOPAD(0x00ec, PIN_INPUT, 2) /* (W9) PRG1_PRU0_GPO13.PRG1_RGMII1_TD2 */
+			AM64X_IOPAD(0x00f0, PIN_INPUT, 2) /* (AA9) PRG1_PRU0_GPO14.PRG1_RGMII1_TD3 */
+			AM64X_IOPAD(0x00f8, PIN_INPUT, 2) /* (V9) PRG1_PRU0_GPO16.PRG1_RGMII1_TXC */
+			AM64X_IOPAD(0x00f4, PIN_INPUT, 2) /* (Y9) PRG1_PRU0_GPO15.PRG1_RGMII1_TX_CTL */
+		>;
+	};
+
+	icssg1_iep0_pins_default: icssg1-iep0-pins-default {
+		pinctrl-single,pins = <
+			AM64X_IOPAD(0x0104, PIN_OUTPUT, 2) /* (W7) PRG1_PRU0_GPO19.PRG1_IEP0_EDC_SYNC_OUT0 */
+		>;
+	};
 };
 
 &main_uart0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart0_pins_default>;
 };
@@ -334,35 +451,8 @@
 	status = "reserved";
 };
 
-&main_uart2 {
-	status = "disabled";
-};
-
-&main_uart3 {
-	status = "disabled";
-};
-
-&main_uart4 {
-	status = "disabled";
-};
-
-&main_uart5 {
-	status = "disabled";
-};
-
-&main_uart6 {
-	status = "disabled";
-};
-
-&mcu_uart0 {
-	status = "disabled";
-};
-
-&mcu_uart1 {
-	status = "disabled";
-};
-
 &main_i2c1 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c1_pins_default>;
 	clock-frequency = <400000>;
@@ -400,28 +490,17 @@
 	};
 };
 
-/* mcu_gpio0 is reserved for mcu firmware usage */
+/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */
 &mcu_gpio0 {
 	status = "reserved";
 };
 
-&mcu_i2c0 {
-	status = "disabled";
-};
-
-&mcu_i2c1 {
-	status = "disabled";
-};
-
-&mcu_spi0 {
-	status = "disabled";
-};
-
-&mcu_spi1 {
-	status = "disabled";
+&mcu_gpio_intr {
+	status = "reserved";
 };
 
 &main_spi0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_spi0_pins_default>;
 	ti,pindir-d0-out-d1-in;
@@ -466,9 +545,13 @@
 
 &cpsw3g {
 	pinctrl-names = "default";
-	pinctrl-0 = <&mdio1_pins_default
-		     &rgmii1_pins_default
+	pinctrl-0 = <&rgmii1_pins_default
 		     &rgmii2_pins_default>;
+
+	/* Map HW8_TS_PUSH to GENF1 */
+	cpts@3d000 {
+		ti,pps = <7 1>;
+	};
 };
 
 &cpsw_port1 {
@@ -482,6 +565,10 @@
 };
 
 &cpsw3g_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio1_pins_default>;
+
 	cpsw3g_phy0: ethernet-phy@0 {
 		reg = <0>;
 		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
@@ -509,6 +596,47 @@
 		cdns,tchsh-ns = <60>;
 		cdns,tslch-ns = <60>;
 		cdns,read-delay = <4>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi.tiboot3";
+				reg = <0x0 0x100000>;
+			};
+
+			partition@100000 {
+				label = "ospi.tispl";
+				reg = <0x100000 0x200000>;
+			};
+
+			partition@300000 {
+				label = "ospi.u-boot";
+				reg = <0x300000 0x400000>;
+			};
+
+			partition@700000 {
+				label = "ospi.env";
+				reg = <0x700000 0x40000>;
+			};
+
+			partition@740000 {
+				label = "ospi.env.backup";
+				reg = <0x740000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "ospi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fc0000 {
+				label = "ospi.phypattern";
+				reg = <0x3fc0000 0x40000>;
+			};
+		};
 	};
 };
 
@@ -579,6 +707,12 @@
 			<&main_r5fss1_core1_memory_region>;
 };
 
+&mcu_m4fss {
+	mboxes = <&mailbox0_cluster6 &mbox_m4_0>;
+	memory-region = <&mcu_m4fss_dma_memory_region>,
+			<&mcu_m4fss_memory_region>;
+};
+
 &serdes_ln_ctrl {
 	idle-states = <AM64_SERDES0_LANE0_PCIE0>;
 };
@@ -594,6 +728,7 @@
 };
 
 &pcie0_rc {
+	status = "okay";
 	reset-gpios = <&exp1 5 GPIO_ACTIVE_HIGH>;
 	phys = <&serdes0_pcie_link>;
 	phy-names = "pcie-phy";
@@ -604,83 +739,63 @@
 	phys = <&serdes0_pcie_link>;
 	phy-names = "pcie-phy";
 	num-lanes = <1>;
-	status = "disabled";
 };
 
 &ecap0 {
+	status = "okay";
 	/* PWM is available on Pin 1 of header J12 */
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_ecap0_pins_default>;
 };
 
-&ecap1 {
-	status = "disabled";
-};
-
-&ecap2 {
-	status = "disabled";
-};
-
-&epwm0 {
-	status = "disabled";
-};
-
-&epwm1 {
-	status = "disabled";
-};
-
-&epwm2 {
-	status = "disabled";
-};
-
-&epwm3 {
-	status = "disabled";
-};
-
-&epwm4 {
-	status = "disabled";
-};
-
-&epwm5 {
-	status = "disabled";
-};
-
-&epwm6 {
-	status = "disabled";
-};
-
-&epwm7 {
-	status = "disabled";
-};
-
-&epwm8 {
-	status = "disabled";
-};
-
-&icssg0_mdio {
-	status = "disabled";
-};
-
-&icssg1_mdio {
-	status = "disabled";
-};
-
 &main_mcan0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_mcan0_pins_default>;
 	phys = <&transceiver1>;
 };
 
 &main_mcan1 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_mcan1_pins_default>;
 	phys = <&transceiver2>;
 };
 
-&gpmc0 {
-	status = "disabled";
+&icssg1_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&icssg1_mdio1_pins_default>;
+
+	icssg1_phy1: ethernet-phy@0 {
+		reg = <0xf>;
+		tx-internal-delay-ps = <250>;
+		rx-internal-delay-ps = <2000>;
+	};
 };
 
-&elm0 {
-	status = "disabled";
+#define TS_OFFSET(pa, val)     (0x4+(pa)*4) (0x10000 | val)
+
+&timesync_router {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpsw_cpts_pps>;
+
+	/*
+	 * Use Time Sync Router to map GENF1 input to HW8_TS_PUSH output as well
+	 * as the PRU ICSSG0 SYNC1 output.
+	 */
+	cpsw_cpts_pps: cpsw-cpts-pps {
+		pinctrl-single,pins = <
+			/* pps [cpts genf1] in22 -> out37 [cpts hw8_push] */
+			TS_OFFSET(37, 22)
+			/* pps [cpts genf1] in22 -> out26 [SYNC1_OUT pin] */
+			TS_OFFSET(26, 22)
+			>;
+	};
+};
+
+&icssg1_iep0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&icssg1_iep0_pins_default>;
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am642-evm-icssg1-dualemac.dtso b/arch/arm64/boot/dts/ti/k3-am642-evm-icssg1-dualemac.dtso
--- a/arch/arm64/boot/dts/ti/k3-am642-evm-icssg1-dualemac.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am642-evm-icssg1-dualemac.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT overlay for 2nd ICSSG1 port enabling on AM642 EVM
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&{/} {
+	aliases {
+		ethernet1 = "/icssg1-eth/ethernet-ports/port@0";
+		ethernet2 = "/icssg1-eth/ethernet-ports/port@1";
+	};
+
+	mdio-mux-2 {
+		compatible = "mdio-mux-multiplexer";
+		mux-controls = <&mdio_mux>;
+		mdio-parent-bus = <&icssg1_mdio>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mdio@0 {
+			reg = <0x0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			icssg1_phy2: ethernet-phy@3 {
+				reg = <3>;
+			};
+		};
+	};
+};
+
+&main_pmx0 {
+	icssg1_rgmii2_pins_default: icssg1-rgmii2-pins-default {
+		pinctrl-single,pins = <
+			AM64X_IOPAD(0x0108, PIN_INPUT, 2) /* (W11) PRG1_PRU1_GPO0.RGMII2_RD0 */
+			AM64X_IOPAD(0x010c, PIN_INPUT, 2) /* (V11) PRG1_PRU1_GPO1.RGMII2_RD1 */
+			AM64X_IOPAD(0x0110, PIN_INPUT, 2) /* (AA12) PRG1_PRU1_GPO2.RGMII2_RD2 */
+			AM64X_IOPAD(0x0114, PIN_INPUT, 2) /* (Y12) PRG1_PRU1_GPO3.RGMII2_RD3 */
+			AM64X_IOPAD(0x0120, PIN_INPUT, 2) /* (U11) PRG1_PRU1_GPO6.RGMII2_RXC */
+			AM64X_IOPAD(0x0118, PIN_INPUT, 2) /* (W12) PRG1_PRU1_GPO4.RGMII2_RX_CTL */
+			AM64X_IOPAD(0x0134, PIN_OUTPUT, 2) /* (AA10) PRG1_PRU1_GPO11.RGMII2_TD0 */
+			AM64X_IOPAD(0x0138, PIN_OUTPUT, 2) /* (V10) PRG1_PRU1_GPO12.RGMII2_TD1 */
+			AM64X_IOPAD(0x013c, PIN_OUTPUT, 2) /* (U10) PRG1_PRU1_GPO13.RGMII2_TD2 */
+			AM64X_IOPAD(0x0140, PIN_OUTPUT, 2) /* (AA11) PRG1_PRU1_GPO14.RGMII2_TD3 */
+			AM64X_IOPAD(0x0148, PIN_OUTPUT, 2) /* (Y10) PRG1_PRU1_GPO16.RGMII2_TXC */
+			AM64X_IOPAD(0x0144, PIN_OUTPUT, 2) /* (Y11) PRG1_PRU1_GPO15.RGMII2_TX_CTL */
+		>;
+	};
+};
+
+&cpsw3g {
+	pinctrl-0 = <&rgmii1_pins_default>;
+};
+
+&cpsw_port2 {
+	status = "disabled";
+};
+
+&mdio_mux_1 {
+	status = "disabled";
+};
+
+&icssg1_eth {
+	pinctrl-0 = <&icssg1_rgmii1_pins_default &icssg1_rgmii2_pins_default>;
+};
+
+&icssg1_emac1 {
+	status = "okay";
+	phy-handle = <&icssg1_phy2>;
+	phy-mode = "rgmii-id";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am642-evm-icssg1-dualemac-mii.dtso b/arch/arm64/boot/dts/ti/k3-am642-evm-icssg1-dualemac-mii.dtso
--- a/arch/arm64/boot/dts/ti/k3-am642-evm-icssg1-dualemac-mii.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am642-evm-icssg1-dualemac-mii.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT overlay for 2nd ICSSG1 port enabling on AM642 EVM
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&{/} {
+	aliases {
+		ethernet1 = "/icssg1-eth/ethernet-ports/port@0";
+		ethernet2 = "/icssg1-eth/ethernet-ports/port@1";
+	};
+
+	mdio-mux-2 {
+		compatible = "mdio-mux-multiplexer";
+		mux-controls = <&mdio_mux>;
+		mdio-parent-bus = <&icssg1_mdio>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		mdio@0 {
+			reg = <0x0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			icssg1_phy2: ethernet-phy@3 {
+				reg = <3>;
+			};
+		};
+	};
+};
+
+&main_pmx0 {
+	icssg1_mii1_pins_default: icssg1-mii1-pins-default {
+		pinctrl-single,pins = <
+			AM64X_IOPAD(0x00f8, PIN_INPUT, 1) /* (V9) PRG1_PRU0_GPO16.PR1_MII_MT0_CLK */
+			AM64X_IOPAD(0x00f4, PIN_OUTPUT, 0) /* (Y9) PRG1_PRU0_GPO15.PR1_MII0_TXEN */
+			AM64X_IOPAD(0x00f0, PIN_OUTPUT, 0) /* (AA9) PRG1_PRU0_GPO14.PR1_MII0_TXD3 */
+			AM64X_IOPAD(0x00ec, PIN_OUTPUT, 0) /* (W9) PRG1_PRU0_GPO13.PR1_MII0_TXD2 */
+			AM64X_IOPAD(0x00e8, PIN_OUTPUT, 0) /* (U9) PRG1_PRU0_GPO12.PR1_MII0_TXD1 */
+			AM64X_IOPAD(0x00e4, PIN_OUTPUT, 0) /* (AA8) PRG1_PRU0_GPO11.PR1_MII0_TXD0 */
+			AM64X_IOPAD(0x00c8, PIN_INPUT, 1) /* (Y8) PRG1_PRU0_GPO4.PR1_MII0_RXDV */
+			AM64X_IOPAD(0x00d0, PIN_INPUT, 1) /* (AA7) PRG1_PRU0_GPO6.PR1_MII_MR0_CLK */
+			AM64X_IOPAD(0x00c4, PIN_INPUT, 1) /* (V8) PRG1_PRU0_GPO3.PR1_MII0_RXD3 */
+			AM64X_IOPAD(0x00c0, PIN_INPUT, 1) /* (W8) PRG1_PRU0_GPO2.PR1_MII0_RXD2 */
+			AM64X_IOPAD(0x00cc, PIN_INPUT, 1) /* (V13) PRG1_PRU0_GPO5.PR1_MII0_RXER */
+			AM64X_IOPAD(0x00bc, PIN_INPUT, 1) /* (U8) PRG1_PRU0_GPO1.PR1_MII0_RXD1 */
+			AM64X_IOPAD(0x00b8, PIN_INPUT, 1) /* (Y7) PRG1_PRU0_GPO0.PR1_MII0_RXD0 */
+			AM64X_IOPAD(0x00d8, PIN_INPUT, 1) /* (W13) PRG1_PRU0_GPO8.PR1_MII0_RXLINK */
+		>;
+	};
+
+	icssg1_mii2_pins_default: icssg1-mii-pins-default {
+		pinctrl-single,pins = <
+			AM64X_IOPAD(0x0148, PIN_INPUT, 1) /* (Y10) PRG1_PRU1_GPO16.PR1_MII_MT1_CLK */
+			AM64X_IOPAD(0x0144, PIN_OUTPUT, 0) /* (Y11) PRG1_PRU1_GPO15.PR1_MII1_TXEN */
+			AM64X_IOPAD(0x0140, PIN_OUTPUT, 0) /* (AA11) PRG1_PRU1_GPO14.PR1_MII1_TXD3 */
+			AM64X_IOPAD(0x013c, PIN_OUTPUT, 0) /* (U10) PRG1_PRU1_GPO13.PR1_MII1_TXD2 */
+			AM64X_IOPAD(0x0138, PIN_OUTPUT, 0) /* (V10) PRG1_PRU1_GPO12.PR1_MII1_TXD1 */
+			AM64X_IOPAD(0x0134, PIN_OUTPUT, 0) /* (AA10) PRG1_PRU1_GPO11.PR1_MII1_TXD0 */
+			AM64X_IOPAD(0x0118, PIN_INPUT, 1) /* (W12) PRG1_PRU1_GPO4.PR1_MII1_RXDV */
+			AM64X_IOPAD(0x0120, PIN_INPUT, 1) /* (U11) PRG1_PRU1_GPO6.PR1_MII_MR1_CLK */
+			AM64X_IOPAD(0x0114, PIN_INPUT, 1) /* (Y12) PRG1_PRU1_GPO3.PR1_MII1_RXD3 */
+			AM64X_IOPAD(0x0110, PIN_INPUT, 1) /* (AA12) PRG1_PRU1_GPO2.PR1_MII1_RXD2 */
+			AM64X_IOPAD(0x011c, PIN_INPUT, 1) /* (AA13) PRG1_PRU1_GPO5.PR1_MII1_RXER */
+			AM64X_IOPAD(0x010c, PIN_INPUT, 1) /* (V11) PRG1_PRU1_GPO1.PR1_MII1_RXD1 */
+			AM64X_IOPAD(0x0108, PIN_INPUT, 1) /* (W11) PRG1_PRU1_GPO0.PR1_MII1_RXD0 */
+			AM64X_IOPAD(0x0128, PIN_INPUT, 1) /* (U12) PRG1_PRU1_GPO8.PR1_MII1_RXLINK */
+		>;
+	};
+};
+
+&cpsw3g {
+	pinctrl-0 = <&mdio1_pins_default &rgmii1_pins_default>;
+};
+
+&cpsw_port2 {
+	status = "disabled";
+};
+
+&mdio_mux_1 {
+	status = "disabled";
+};
+
+&icssg1_eth {
+	pinctrl-0 = <&icssg1_mii1_pins_default &icssg1_mii2_pins_default>;
+};
+
+&icssg1_emac0 {
+	phy-mode = "mii";
+};
+
+&icssg1_emac1 {
+	status = "okay";
+	phy-handle = <&icssg1_phy2>;
+	phy-mode = "mii";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am642-evm-nand.dtso b/arch/arm64/boot/dts/ti/k3-am642-evm-nand.dtso
--- a/arch/arm64/boot/dts/ti/k3-am642-evm-nand.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am642-evm-nand.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT overlay for HSE NAND expansion card on AM642 EVM
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+	gpmc0_pins_default: gpmc0-pins-default {
+		pinctrl-single,pins = <
+			AM64X_IOPAD(0x0094, PIN_INPUT, 7) /* (T19) GPMC0_BE1n.GPIO0_36 */
+
+			AM64X_IOPAD(0x003c, PIN_INPUT, 0) /* (T20) GPMC0_AD0 */
+			AM64X_IOPAD(0x0040, PIN_INPUT, 0) /* (U21) GPMC0_AD1 */
+			AM64X_IOPAD(0x0064, PIN_INPUT, 0) /* (R16) GPMC0_AD10 */
+			AM64X_IOPAD(0x0068, PIN_INPUT, 0) /* (W20) GPMC0_AD11 */
+			AM64X_IOPAD(0x006c, PIN_INPUT, 0) /* (W21) GPMC0_AD12 */
+			AM64X_IOPAD(0x0070, PIN_INPUT, 0) /* (V18) GPMC0_AD13 */
+			AM64X_IOPAD(0x0074, PIN_INPUT, 0) /* (Y21) GPMC0_AD14 */
+			AM64X_IOPAD(0x0078, PIN_INPUT, 0) /* (Y20) GPMC0_AD15 */
+			AM64X_IOPAD(0x0044, PIN_INPUT, 0) /* (T18) GPMC0_AD2 */
+			AM64X_IOPAD(0x0048, PIN_INPUT, 0) /* (U20) GPMC0_AD3 */
+			AM64X_IOPAD(0x004c, PIN_INPUT, 0) /* (U18) GPMC0_AD4 */
+			AM64X_IOPAD(0x0050, PIN_INPUT, 0) /* (U19) GPMC0_AD5 */
+			AM64X_IOPAD(0x0054, PIN_INPUT, 0) /* (V20) GPMC0_AD6 */
+			AM64X_IOPAD(0x0058, PIN_INPUT, 0) /* (V21) GPMC0_AD7 */
+			AM64X_IOPAD(0x005c, PIN_INPUT, 0) /* (V19) GPMC0_AD8 */
+			AM64X_IOPAD(0x0060, PIN_INPUT, 0) /* (T17) GPMC0_AD9 */
+			AM64X_IOPAD(0x0098, PIN_INPUT_PULLUP, 0) /* (W19) GPMC0_WAIT0 */
+			AM64X_IOPAD(0x009c, PIN_INPUT_PULLUP, 0) /* (Y18) GPMC0_WAIT1 */
+			AM64X_IOPAD(0x00a8, PIN_OUTPUT_PULLUP, 0) /* (R19) GPMC0_CSn0 */
+			AM64X_IOPAD(0x00ac, PIN_OUTPUT_PULLUP, 0) /* (R20) GPMC0_CSn1 */
+			AM64X_IOPAD(0x00b0, PIN_OUTPUT_PULLUP, 0) /* (P19) GPMC0_CSn2 */
+			AM64X_IOPAD(0x00b4, PIN_OUTPUT_PULLUP, 0) /* (R21) GPMC0_CSn3 */
+			AM64X_IOPAD(0x007c, PIN_OUTPUT, 0) /* (R17) GPMC0_CLK */
+			AM64X_IOPAD(0x0084, PIN_OUTPUT, 0) /* (P16) GPMC0_ADVn_ALE */
+			AM64X_IOPAD(0x0088, PIN_OUTPUT, 0) /* (R18) GPMC0_OEn_REn */
+			AM64X_IOPAD(0x008c, PIN_OUTPUT, 0) /* (T21) GPMC0_WEn */
+			AM64X_IOPAD(0x0090, PIN_OUTPUT, 0) /* (P17) GPMC0_BE0n_CLE */
+			AM64X_IOPAD(0x00a0, PIN_OUTPUT_PULLUP, 0) /* (N16) GPMC0_WPn */
+			AM64X_IOPAD(0x00a4, PIN_OUTPUT, 0) /* (N17) GPMC0_DIR */
+		>;
+	};
+};
+
+&main_gpio0 {
+	gpio0-36 {
+		gpio-hog;
+		gpios = <36 0>;
+		input;
+		line-name = "GPMC0_MUX_DIR";
+	};
+};
+
+&elm0 {
+	status = "okay";
+};
+
+&gpmc0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&gpmc0_pins_default>;
+	ranges = <0 0 0x00 0x51000000 0x01000000>; /* CS0 space. Min partition = 16MB */
+	#address-cells = <2>;
+	#size-cells = <1>;
+
+	nand@0,0 {
+		compatible = "ti,am64-nand";
+		reg = <0 0 64>;		/* device IO registers */
+		interrupt-parent = <&gpmc0>;
+		interrupts = <0 IRQ_TYPE_NONE>, /* fifoevent */
+			     <1 IRQ_TYPE_NONE>;	/* termcount */
+		rb-gpios = <&gpmc0 0 GPIO_ACTIVE_HIGH>;	/* gpmc_wait0 */
+		ti,nand-xfer-type = "prefetch-polled";
+		ti,nand-ecc-opt = "bch8";	/* BCH8: Bootrom limitation */
+		ti,elm-id = <&elm0>;
+		nand-bus-width = <8>;
+		gpmc,device-width = <1>;
+		gpmc,sync-clk-ps = <0>;
+		gpmc,cs-on-ns = <0>;
+		gpmc,cs-rd-off-ns = <40>;
+		gpmc,cs-wr-off-ns = <40>;
+		gpmc,adv-on-ns = <0>;
+		gpmc,adv-rd-off-ns = <25>;
+		gpmc,adv-wr-off-ns = <25>;
+		gpmc,we-on-ns = <0>;
+		gpmc,we-off-ns = <20>;
+		gpmc,oe-on-ns = <3>;
+		gpmc,oe-off-ns = <30>;
+		gpmc,access-ns = <30>;
+		gpmc,rd-cycle-ns = <40>;
+		gpmc,wr-cycle-ns = <40>;
+		gpmc,bus-turnaround-ns = <0>;
+		gpmc,cycle2cycle-delay-ns = <0>;
+		gpmc,clk-activation-ns = <0>;
+		gpmc,wr-access-ns = <40>;
+		gpmc,wr-data-mux-bus-ns = <0>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "NAND.tiboot3";
+				reg = <0x00000000 0x00200000>;	/* 2M */
+			};
+			partition@200000 {
+				label = "NAND.tispl";
+				reg = <0x00200000 0x00200000>;	/* 2M */
+			};
+			partition@400000 {
+				label = "NAND.tiboot3.backup";	/* 2M */
+				reg = <0x00400000 0x00200000>;	/* BootROM looks at 4M */
+			};
+			partition@600000 {
+				label = "NAND.u-boot";
+				reg = <0x00600000 0x00400000>;	/* 4M */
+			};
+			partition@a00000 {
+				label = "NAND.u-boot-env";
+				reg = <0x00a00000 0x00040000>;	/* 256K */
+			};
+			partition@a40000 {
+				label = "NAND.u-boot-env.backup";
+				reg = <0x00a40000 0x00040000>;	/* 256K */
+			};
+			partition@a80000 {
+				label = "NAND.file-system";
+				reg = <0x00a80000 0x3f580000>;
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am642-sk.dts b/arch/arm64/boot/dts/ti/k3-am642-sk.dts
--- a/arch/arm64/boot/dts/ti/k3-am642-sk.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am642-sk.dts	2024-01-28 14:01:31.240353775 -0500
@@ -87,6 +87,18 @@
 			no-map;
 		};
 
+		mcu_m4fss_dma_memory_region: m4f-dma-memory@a4000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa4000000 0x00 0x100000>;
+			no-map;
+		};
+
+		mcu_m4fss_memory_region: m4f-memory@a4100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa4100000 0x00 0xf00000>;
+			no-map;
+		};
+
 		rtos_ipc_memory_region: ipc-memories@a5000000 {
 			reg = <0x00 0xa5000000 0x00 0x00800000>;
 			alignment = <0x1000>;
@@ -336,17 +348,19 @@
 			AM64X_IOPAD(0x00bc, PIN_INPUT, 7) /* (U8) GPIO0_46 */
 		>;
 	};
-};
 
-&mcu_uart0 {
-	status = "disabled";
-};
-
-&mcu_uart1 {
-	status = "disabled";
+	main_eqep0_pins_default: main-eqep0-pins-default {
+		pinctrl-single,pins = <
+			AM64X_IOPAD(0x00a0, PIN_INPUT, 3) /* (N16) GPMC0_WPn.EQEP0_A */
+			AM64X_IOPAD(0x00a4, PIN_INPUT, 3) /* (N17) GPMC0_DIR.EQEP0_B */
+			AM64X_IOPAD(0x00ac, PIN_INPUT, 3) /* (R20) GPMC0_CSn1.EQEP0_I */
+			AM64X_IOPAD(0x00a8, PIN_INPUT, 3) /* (R19) GPMC0_CSn0.EQEP0_S */
+		>;
+	};
 };
 
 &main_uart0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart0_pins_default>;
 };
@@ -356,35 +370,8 @@
 	status = "reserved";
 };
 
-&main_uart2 {
-	status = "disabled";
-};
-
-&main_uart3 {
-	status = "disabled";
-};
-
-&main_uart4 {
-	status = "disabled";
-};
-
-&main_uart5 {
-	status = "disabled";
-};
-
-&main_uart6 {
-	status = "disabled";
-};
-
-&mcu_i2c0 {
-	status = "disabled";
-};
-
-&mcu_i2c1 {
-	status = "disabled";
-};
-
 &main_i2c1 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c1_pins_default>;
 	clock-frequency = <400000>;
@@ -409,20 +396,12 @@
 	};
 };
 
-&main_i2c3 {
-	status = "disabled";
-};
-
-&mcu_spi0 {
-	status = "disabled";
-};
-
-&mcu_spi1 {
-	status = "disabled";
+/* mcu_gpio0 and mcu_gpio_intr are reserved for mcu firmware usage */
+&mcu_gpio0 {
+	status = "reserved";
 };
 
-/* mcu_gpio0 is reserved for mcu firmware usage */
-&mcu_gpio0 {
+&mcu_gpio_intr {
 	status = "reserved";
 };
 
@@ -485,9 +464,13 @@
 
 &cpsw3g {
 	pinctrl-names = "default";
-	pinctrl-0 = <&mdio1_pins_default
-		     &rgmii1_pins_default
+	pinctrl-0 = <&rgmii1_pins_default
 		     &rgmii2_pins_default>;
+
+	/* Map HW8_TS_PUSH to GENF1 */
+	cpts@3d000 {
+		ti,pps = <7 1>;
+	};
 };
 
 &cpsw_port1 {
@@ -501,6 +484,10 @@
 };
 
 &cpsw3g_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio1_pins_default>;
+
 	cpsw3g_phy0: ethernet-phy@0 {
 		reg = <0>;
 		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
@@ -533,6 +520,47 @@
 		cdns,tchsh-ns = <60>;
 		cdns,tslch-ns = <60>;
 		cdns,read-delay = <4>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi.tiboot3";
+				reg = <0x0 0x100000>;
+			};
+
+			partition@100000 {
+				label = "ospi.tispl";
+				reg = <0x100000 0x200000>;
+			};
+
+			partition@300000 {
+				label = "ospi.u-boot";
+				reg = <0x300000 0x400000>;
+			};
+
+			partition@700000 {
+				label = "ospi.env";
+				reg = <0x700000 0x40000>;
+			};
+
+			partition@740000 {
+				label = "ospi.env.backup";
+				reg = <0x740000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "ospi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fc0000 {
+				label = "ospi.phypattern";
+				reg = <0x3fc0000 0x40000>;
+			};
+		};
 	};
 };
 
@@ -603,92 +631,44 @@
 			<&main_r5fss1_core1_memory_region>;
 };
 
-&pcie0_rc {
-	status = "disabled";
-};
-
-&pcie0_ep {
-	status = "disabled";
+&mcu_m4fss {
+	mboxes = <&mailbox0_cluster6 &mbox_m4_0>;
+	memory-region = <&mcu_m4fss_dma_memory_region>,
+			<&mcu_m4fss_memory_region>;
 };
 
 &ecap0 {
+	status = "okay";
 	/* PWM is available on Pin 1 of header J3 */
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_ecap0_pins_default>;
 };
 
-&ecap1 {
-	status = "disabled";
-};
-
-&ecap2 {
-	status = "disabled";
-};
-
-&epwm0 {
-	status = "disabled";
-};
-
-&epwm1 {
-	status = "disabled";
-};
-
-&epwm2 {
-	status = "disabled";
+&eqep0 {
+	/* EQEP0_A is available on Pin 18 of header J4 */
+	/* EQEP0_B is available on Pin 22 of header J4 */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_eqep0_pins_default>;
 };
 
-&epwm3 {
-	status = "disabled";
-};
+#define TS_OFFSET(pa, val)     (0x4+(pa)*4) (0x10000 | val)
 
-&epwm4 {
-	/*
-	 * EPWM4_A, EPWM4_B is available on Pin 32 and 33 on J4 (RPi hat)
-	 * But RPi Hat will be used for other use cases, so marking epwm4 as disabled.
-	 */
-	status = "disabled";
-};
+&timesync_router {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&cpsw_cpts_pps>;
 
-&epwm5 {
 	/*
-	 * EPWM5_A, EPWM5_B is available on Pin 29 and 31 on J4 (RPi hat)
-	 * But RPi Hat will be used for other use cases, so marking epwm5 as disabled.
+	 * Use Time Sync Router to map GENF1 input to HW8_TS_PUSH output as well
+	 * as the PRU ICSSG0 SYNC1 output.
 	 */
-	status = "disabled";
-};
-
-&epwm6 {
-	status = "disabled";
-};
-
-&epwm7 {
-	status = "disabled";
-};
-
-&epwm8 {
-	status = "disabled";
-};
-
-&icssg0_mdio {
-	status = "disabled";
-};
-
-&icssg1_mdio {
-	status = "disabled";
-};
-
-&main_mcan0 {
-	status = "disabled";
-};
-
-&main_mcan1 {
-	status = "disabled";
-};
-
-&gpmc0 {
-	status = "disabled";
-};
-
-&elm0 {
-	status = "disabled";
+	cpsw_cpts_pps: cpsw-cpts-pps {
+		pinctrl-single,pins = <
+			/* pps [cpts genf1] in22 -> out37 [cpts hw8_push] */
+			TS_OFFSET(37, 22)
+			/* pps [cpts genf1] in22 -> out26 [SYNC1_OUT pin] */
+			TS_OFFSET(26, 22)
+			>;
+	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am64.dtsi b/arch/arm64/boot/dts/ti/k3-am64.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am64.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am64.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -8,9 +8,10 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/pinctrl/k3.h>
 #include <dt-bindings/soc/ti,sci_pm_domain.h>
 
+#include "k3-pinctrl.h"
+
 / {
 	model = "Texas Instruments K3 AM642 SoC";
 	compatible = "ti,am642";
@@ -69,6 +70,7 @@
 			 <0x00 0x00420000 0x00 0x00420000 0x00 0x00001000>, /* ESM0 */
 			 <0x00 0x00600000 0x00 0x00600000 0x00 0x00001100>, /* GPIO */
 			 <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* Timesync router */
+			 <0x00 0x00b00000 0x00 0x00b00000 0x00 0x00002400>, /* VTM */
 			 <0x00 0x01000000 0x00 0x01000000 0x00 0x02330400>, /* First peripheral window */
 			 <0x00 0x08000000 0x00 0x08000000 0x00 0x00200000>, /* Main CPSW */
 			 <0x00 0x0d000000 0x00 0x0d000000 0x00 0x00800000>, /* PCIE_CORE */
@@ -105,6 +107,8 @@
 			ranges = <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>; /* Peripheral window */
 		};
 	};
+
+	#include "k3-am64-thermal.dtsi"
 };
 
 /* Now include the peripherals for each bus segments */
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -222,7 +222,7 @@
 		};
 
 		epwm_tbclk: clock@4140 {
-			compatible = "ti,am64-epwm-tbclk", "syscon";
+			compatible = "ti,am64-epwm-tbclk";
 			reg = <0x4130 0x4>;
 			#clock-cells = <1>;
 		};
@@ -237,6 +237,7 @@
 		power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 146 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart1: serial@2810000 {
@@ -248,6 +249,7 @@
 		power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 152 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart2: serial@2820000 {
@@ -259,6 +261,7 @@
 		power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 153 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart3: serial@2830000 {
@@ -270,6 +273,7 @@
 		power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 154 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart4: serial@2840000 {
@@ -281,6 +285,7 @@
 		power-domains = <&k3_pds 155 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 155 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart5: serial@2850000 {
@@ -292,6 +297,7 @@
 		power-domains = <&k3_pds 156 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 156 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart6: serial@2860000 {
@@ -303,6 +309,7 @@
 		power-domains = <&k3_pds 158 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 158 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_i2c0: i2c@20000000 {
@@ -314,6 +321,7 @@
 		power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 102 2>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	main_i2c1: i2c@20010000 {
@@ -325,6 +333,7 @@
 		power-domains = <&k3_pds 103 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 103 2>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	main_i2c2: i2c@20020000 {
@@ -336,6 +345,7 @@
 		power-domains = <&k3_pds 104 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 104 2>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	main_i2c3: i2c@20030000 {
@@ -347,6 +357,7 @@
 		power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 105 2>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	main_spi0: spi@20100000 {
@@ -359,6 +370,7 @@
 		clocks = <&k3_clks 141 0>;
 		dmas = <&main_pktdma 0xc300 0>, <&main_pktdma 0x4300 0>;
 		dma-names = "tx0", "rx0";
+		status = "disabled";
 	};
 
 	main_spi1: spi@20110000 {
@@ -369,6 +381,7 @@
 		#size-cells = <0>;
 		power-domains = <&k3_pds 142 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 142 0>;
+		status = "disabled";
 	};
 
 	main_spi2: spi@20120000 {
@@ -379,6 +392,7 @@
 		#size-cells = <0>;
 		power-domains = <&k3_pds 143 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 143 0>;
+		status = "disabled";
 	};
 
 	main_spi3: spi@20130000 {
@@ -389,6 +403,7 @@
 		#size-cells = <0>;
 		power-domains = <&k3_pds 144 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 144 0>;
+		status = "disabled";
 	};
 
 	main_spi4: spi@20140000 {
@@ -399,6 +414,7 @@
 		#size-cells = <0>;
 		power-domains = <&k3_pds 145 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 145 0>;
+		status = "disabled";
 	};
 
 	main_gpio_intr: interrupt-controller@a00000 {
@@ -457,6 +473,9 @@
 		mmc-ddr-1_8v;
 		mmc-hs200-1_8v;
 		ti,trm-icp = <0x2>;
+		ti,itap-del-sel-legacy = <0x10>;
+		ti,itap-del-sel-mmc-hs = <0xA>;
+		ti,itap-del-sel-ddr52 = <0x3>;
 		ti,otap-del-sel-legacy = <0x0>;
 		ti,otap-del-sel-mmc-hs = <0x0>;
 		ti,otap-del-sel-ddr52 = <0x6>;
@@ -471,6 +490,10 @@
 		clocks = <&k3_clks 58 3>, <&k3_clks 58 4>;
 		clock-names = "clk_ahb", "clk_xin";
 		ti,trm-icp = <0x2>;
+		ti,itap-del-sel-legacy = <0x0>;
+		ti,itap-del-sel-sd-hs = <0x0>;
+		ti,itap-del-sel-sdr12 = <0x0>;
+		ti,itap-del-sel-sdr25 = <0x0>;
 		ti,otap-del-sel-legacy = <0x0>;
 		ti,otap-del-sel-sd-hs = <0xf>;
 		ti,otap-del-sel-sdr12 = <0xf>;
@@ -536,6 +559,7 @@
 			clocks = <&k3_clks 13 0>;
 			clock-names = "fck";
 			bus_freq = <1000000>;
+			status = "disabled";
 		};
 
 		cpts@3d000 {
@@ -855,6 +879,20 @@
 		ranges = <0x01000000 0x00 0x68001000  0x00 0x68001000  0x00 0x0010000>,
 			 <0x02000000 0x00 0x68011000  0x00 0x68011000  0x00 0x7fef000>;
 		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x00000010 0x0>;
+		status = "disabled";
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie0_intc 0>, /* INT A */
+				<0 0 0 2 &pcie0_intc 0>, /* INT B */
+				<0 0 0 3 &pcie0_intc 0>, /* INT C */
+				<0 0 0 4 &pcie0_intc 0>; /* INT D */
+
+		pcie0_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 202 IRQ_TYPE_EDGE_RISING>;
+		};
 	};
 
 	pcie0_ep: pcie-ep@f102000 {
@@ -873,6 +911,7 @@
 		clocks = <&k3_clks 114 0>;
 		clock-names = "fck";
 		max-functions = /bits/ 8 <1>;
+		status = "disabled";
 	};
 
 	epwm0: pwm@23000000 {
@@ -882,6 +921,7 @@
 		power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&epwm_tbclk 0>, <&k3_clks 86 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	epwm1: pwm@23010000 {
@@ -891,6 +931,7 @@
 		power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&epwm_tbclk 1>, <&k3_clks 87 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	epwm2: pwm@23020000 {
@@ -900,6 +941,7 @@
 		power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&epwm_tbclk 2>, <&k3_clks 88 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	epwm3: pwm@23030000 {
@@ -909,6 +951,7 @@
 		power-domains = <&k3_pds 89 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&epwm_tbclk 3>, <&k3_clks 89 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	epwm4: pwm@23040000 {
@@ -918,6 +961,7 @@
 		power-domains = <&k3_pds 90 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&epwm_tbclk 4>, <&k3_clks 90 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	epwm5: pwm@23050000 {
@@ -927,6 +971,7 @@
 		power-domains = <&k3_pds 91 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&epwm_tbclk 5>, <&k3_clks 91 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	epwm6: pwm@23060000 {
@@ -936,6 +981,7 @@
 		power-domains = <&k3_pds 92 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&epwm_tbclk 6>, <&k3_clks 92 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	epwm7: pwm@23070000 {
@@ -945,6 +991,7 @@
 		power-domains = <&k3_pds 93 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&epwm_tbclk 7>, <&k3_clks 93 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	epwm8: pwm@23080000 {
@@ -954,6 +1001,7 @@
 		power-domains = <&k3_pds 94 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&epwm_tbclk 8>, <&k3_clks 94 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	ecap0: pwm@23100000 {
@@ -963,6 +1011,7 @@
 		power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 51 0>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	ecap1: pwm@23110000 {
@@ -972,6 +1021,7 @@
 		power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 52 0>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	ecap2: pwm@23120000 {
@@ -981,6 +1031,37 @@
 		power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 53 0>;
 		clock-names = "fck";
+		status = "disabled";
+	};
+
+	eqep0: counter@23200000 {
+		compatible = "ti,am3352-eqep";
+		reg = <0x00 0x23200000 0x00 0x100>;
+		power-domains = <&k3_pds 59 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 59 0>;
+		clock-names = "fck";
+		interrupts = <GIC_SPI 116 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
+	};
+
+	eqep1: counter@23210000 {
+		compatible = "ti,am3352-eqep";
+		reg = <0x00 0x23210000 0x00 0x100>;
+		power-domains = <&k3_pds 60 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 60 0>;
+		clock-names = "fck";
+		interrupts = <GIC_SPI 117 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
+	};
+
+	eqep2: counter@23220000 {
+		compatible = "ti,am3352-eqep";
+		reg = <0x00 0x23220000 0x00 0x100>;
+		power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 62 0>;
+		clock-names = "fck";
+		interrupts = <GIC_SPI 118 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
 	};
 
 	main_rti0: watchdog@e000000 {
@@ -1047,6 +1128,18 @@
 			};
 		};
 
+		icssg0_iep0: iep@2e000 {
+			compatible = "ti,am654-icss-iep";
+			reg = <0x2e000 0x1000>;
+			clocks = <&icssg0_iepclk_mux>;
+		};
+
+		icssg0_iep1: iep@2f000 {
+			compatible = "ti,am654-icss-iep";
+			reg = <0x2f000 0x1000>;
+			clocks = <&icssg0_iepclk_mux>;
+		};
+
 		icssg0_mii_rt: mii-rt@32000 {
 			compatible = "ti,pruss-mii", "syscon";
 			reg = <0x32000 0x100>;
@@ -1057,6 +1150,11 @@
 			reg = <0x33000 0x1000>;
 		};
 
+		icssg0_pa_stats: pa-stats@2c000 {
+			compatible = "ti,pruss-pa-st", "syscon";
+			reg = <0x2c000 0x1000>;
+		};
+
 		icssg0_intc: interrupt-controller@20000 {
 			compatible = "ti,icssg-intc";
 			reg = <0x20000 0x2000>;
@@ -1083,6 +1181,9 @@
 			      <0x22400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am64x-pru0_0-fw";
+			interrupt-parent = <&icssg0_intc>;
+			interrupts = <16 2 2>;
+			interrupt-names = "vring";
 		};
 
 		rtu0_0: rtu@4000 {
@@ -1092,6 +1193,9 @@
 			      <0x23400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am64x-rtu0_0-fw";
+			interrupt-parent = <&icssg0_intc>;
+			interrupts = <20 4 4>;
+			interrupt-names = "vring";
 		};
 
 		tx_pru0_0: txpru@a000 {
@@ -1110,6 +1214,9 @@
 			      <0x24400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am64x-pru0_1-fw";
+			interrupt-parent = <&icssg0_intc>;
+			interrupts = <18 3 3>;
+			interrupt-names = "vring";
 		};
 
 		rtu0_1: rtu@6000 {
@@ -1119,6 +1226,9 @@
 			      <0x23c00 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am64x-rtu0_1-fw";
+			interrupt-parent = <&icssg0_intc>;
+			interrupts = <22 5 5>;
+			interrupt-names = "vring";
 		};
 
 		tx_pru0_1: txpru@c000 {
@@ -1138,6 +1248,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			bus_freq = <1000000>;
+			status = "disabled";
 		};
 	};
 
@@ -1187,6 +1298,18 @@
 			};
 		};
 
+		icssg1_iep0: iep@2e000 {
+			compatible = "ti,am654-icss-iep";
+			reg = <0x2e000 0x1000>;
+			clocks = <&icssg1_iepclk_mux>;
+		};
+
+		icssg1_iep1: iep@2f000 {
+			compatible = "ti,am654-icss-iep";
+			reg = <0x2f000 0x1000>;
+			clocks = <&icssg1_iepclk_mux>;
+		};
+
 		icssg1_mii_rt: mii-rt@32000 {
 			compatible = "ti,pruss-mii", "syscon";
 			reg = <0x32000 0x100>;
@@ -1197,6 +1320,11 @@
 			reg = <0x33000 0x1000>;
 		};
 
+		icssg1_pa_stats: pa-stats@2c000 {
+			compatible = "ti,pruss-pa-st", "syscon";
+			reg = <0x2c000 0x1000>;
+		};
+
 		icssg1_intc: interrupt-controller@20000 {
 			compatible = "ti,icssg-intc";
 			reg = <0x20000 0x2000>;
@@ -1223,6 +1351,9 @@
 			      <0x22400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am64x-pru1_0-fw";
+			interrupt-parent = <&icssg1_intc>;
+			interrupts = <16 2 2>;
+			interrupt-names = "vring";
 		};
 
 		rtu1_0: rtu@4000 {
@@ -1232,6 +1363,9 @@
 			      <0x23400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am64x-rtu1_0-fw";
+			interrupt-parent = <&icssg1_intc>;
+			interrupts = <20 4 4>;
+			interrupt-names = "vring";
 		};
 
 		tx_pru1_0: txpru@a000 {
@@ -1250,6 +1384,9 @@
 			      <0x24400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am64x-pru1_1-fw";
+			interrupt-parent = <&icssg1_intc>;
+			interrupts = <18 3 3>;
+			interrupt-names = "vring";
 		};
 
 		rtu1_1: rtu@6000 {
@@ -1259,6 +1396,9 @@
 			      <0x23c00 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am64x-rtu1_1-fw";
+			interrupt-parent = <&icssg1_intc>;
+			interrupts = <22 5 5>;
+			interrupt-names = "vring";
 		};
 
 		tx_pru1_1: txpru@c000 {
@@ -1278,6 +1418,7 @@
 			clocks = <&k3_clks 82 0>;
 			clock-names = "fck";
 			bus_freq = <1000000>;
+			status = "disabled";
 		};
 	};
 
@@ -1293,6 +1434,7 @@
 			     <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan1: can@20711000 {
@@ -1307,6 +1449,7 @@
 			     <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	crypto: crypto@40900000 {
@@ -1324,7 +1467,6 @@
 			compatible = "inside-secure,safexcel-eip76";
 			reg = <0x00 0x40910000 0x00 0x7d>;
 			interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&k3_clks 133 1>;
 			status = "disabled"; /* Used by OP-TEE */
 		};
 	};
@@ -1334,8 +1476,8 @@
 		power-domains = <&k3_pds 80 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 80 0>;
 		clock-names = "fck";
-		reg = <0x00 0x03b000000 0x00 0x400>,
-		      <0x00 0x050000000 0x00 0x8000000>;
+		reg = <0x00 0x3b000000 0x00 0x400>,
+		      <0x00 0x50000000 0x00 0x8000000>;
 		reg-names = "cfg", "data";
 		interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
 		gpmc,num-cs = <3>;
@@ -1346,6 +1488,7 @@
 		#interrupt-cells = <2>;
 		gpio-controller;
 		#gpio-cells = <2>;
+		status = "disabled";
 	};
 
 	elm0: ecc@25010000 {
@@ -1355,5 +1498,14 @@
 		power-domains = <&k3_pds 54 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 54 0>;
 		clock-names = "fck";
+		status = "disabled";
+	};
+
+	main_vtm0: temperature-sensor@b00000 {
+		compatible = "ti,j7200-vtm";
+		reg = <0x00 0xb00000 0x00 0x400>,
+		      <0x00 0xb01000 0x00 0x400>;
+		power-domains = <&k3_pds 95 TI_SCI_PD_EXCLUSIVE>;
+		#thermal-sensor-cells = <1>;
 	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -14,6 +14,7 @@
 		power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 149 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	mcu_uart1: serial@4a10000 {
@@ -24,6 +25,7 @@
 		power-domains = <&k3_pds 160 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 160 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	mcu_i2c0: i2c@4900000 {
@@ -35,6 +37,7 @@
 		power-domains = <&k3_pds 106 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 106 2>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	mcu_i2c1: i2c@4910000 {
@@ -46,6 +49,7 @@
 		power-domains = <&k3_pds 107 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 107 2>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	mcu_spi0: spi@4b00000 {
@@ -56,6 +60,7 @@
 		#size-cells = <0>;
 		power-domains = <&k3_pds 147 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 147 0>;
+		status = "disabled";
 	};
 
 	mcu_spi1: spi@4b10000 {
@@ -66,6 +71,7 @@
 		#size-cells = <0>;
 		power-domains = <&k3_pds 148 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 148 0>;
+		status = "disabled";
 	};
 
 	mcu_gpio_intr: interrupt-controller@4210000 {
@@ -103,4 +109,16 @@
 		pinctrl-single,register-width = <32>;
 		pinctrl-single,function-mask = <0xffffffff>;
 	};
+
+	mcu_m4fss: m4fss@5000000 {
+		compatible = "ti,am64-m4fss";
+		reg = <0x00 0x5000000 0x00 0x30000>,
+		<0x00 0x5040000 0x00 0x10000>;
+		reg-names = "iram", "dram";
+		ti,sci = <&dmsc>;
+		ti,sci-dev-id = <9>;
+		ti,sci-proc-ids = <0x18 0xff>;
+		resets = <&k3_reset 9 1>;
+		firmware-name = "am64-mcu-m4f0_0-fw";
+	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am64-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-am64-thermal.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am64-thermal.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am64-thermal.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/thermal/thermal.h>
+
+thermal_zones: thermal-zones {
+	main0_thermal: main0-thermal {
+		polling-delay-passive = <250>;	/* milliSeconds */
+		polling-delay = <500>;		/* milliSeconds */
+		thermal-sensors = <&main_vtm0 0>;
+
+		trips {
+			main0_crit: main0-crit {
+				temperature = <105000>;	/* milliCelsius */
+				hysteresis = <2000>;	/* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+
+	main1_thermal: main1-thermal {
+		polling-delay-passive = <250>;	/* milliSeconds */
+		polling-delay = <500>;		/* milliSeconds */
+		thermal-sensors = <&main_vtm0 1>;
+
+		trips {
+			main1_crit: main1-crit {
+				temperature = <105000>;	/* milliCelsius */
+				hysteresis = <2000>;	/* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi b/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -50,6 +50,7 @@
 };
 
 &main_uart0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart0_pins_default>;
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -50,7 +50,3 @@
 	ti,driver-strength-ohm = <50>;
 	disable-wp;
 };
-
-&main_uart0 {
-	status = "disabled";
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts
--- a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts	2024-01-28 14:01:31.240353775 -0500
@@ -13,6 +13,11 @@
 	compatible = "ti,am654-evm", "ti,am654";
 	model = "Texas Instruments AM654 Base Board";
 
+	aliases {
+		ethernet1 = &icssg2_emac0;
+		ethernet2 = &icssg2_emac1;
+	};
+
 	chosen {
 		stdout-path = "serial2:115200n8";
 		bootargs = "earlycon=ns16550a,mmio32,0x02800000";
@@ -117,6 +122,76 @@
 		vin-supply = <&vcc3v3_io>;
 		gpio = <&pca9554 4 GPIO_ACTIVE_HIGH>;
 	};
+
+	/* Dual Ethernet application node on PRU-ICSSG2 */
+	icssg2_eth: icssg2-eth {
+		compatible = "ti,am654-icssg-prueth";
+		pinctrl-names = "default";
+		pinctrl-0 = <&icssg2_rgmii_pins_default>;
+		sram = <&msmc_ram>;
+		ti,prus = <&pru2_0>, <&rtu2_0>, <&tx_pru2_0>,
+			<&pru2_1>, <&rtu2_1>, <&tx_pru2_1>;
+		firmware-name = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-rtu0-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-txpru0-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-pru1-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-rtu1-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-txpru1-prueth-fw.elf";
+
+		ti,pruss-gp-mux-sel = <2>,      /* MII mode */
+				      <2>,
+				      <2>,
+				      <2>,	/* MII mode */
+				      <2>,
+				      <2>;
+
+		ti,mii-g-rt = <&icssg2_mii_g_rt>;
+		ti,mii-rt = <&icssg2_mii_rt>;
+		ti,pa-stats = <&icssg2_pa_stats>;
+		iep = <&icssg2_iep0>,  <&icssg2_iep1>;
+
+		interrupt-parent = <&icssg2_intc>;
+		interrupts = <24 0 2>, <25 1 3>;
+		interrupt-names = "tx_ts0", "tx_ts1";
+
+		dmas = <&main_udmap 0xc300>, /* egress slice 0 */
+		       <&main_udmap 0xc301>, /* egress slice 0 */
+		       <&main_udmap 0xc302>, /* egress slice 0 */
+		       <&main_udmap 0xc303>, /* egress slice 0 */
+		       <&main_udmap 0xc304>, /* egress slice 1 */
+		       <&main_udmap 0xc305>, /* egress slice 1 */
+		       <&main_udmap 0xc306>, /* egress slice 1 */
+		       <&main_udmap 0xc307>, /* egress slice 1 */
+
+		       <&main_udmap 0x4300>, /* ingress slice 0 */
+		       <&main_udmap 0x4301>, /* ingress slice 1 */
+		       <&main_udmap 0x4302>, /* mgmnt rsp slice 0 */
+		       <&main_udmap 0x4303>; /* mgmnt rsp slice 1 */
+		dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3",
+			    "tx1-0", "tx1-1", "tx1-2", "tx1-3",
+			    "rx0", "rx1";
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			icssg2_emac0: port@0 {
+				reg = <0>;
+				phy-handle = <&icssg2_phy0>;
+				phy-mode = "rgmii-id";
+				ti,syscon-rgmii-delay = <&scm_conf 0x4120>;
+				/* Filled in by bootloader */
+				local-mac-address = [00 00 00 00 00 00];
+			};
+			icssg2_emac1: port@1 {
+				reg = <1>;
+				phy-handle = <&icssg2_phy1>;
+				phy-mode = "rgmii-id";
+				ti,syscon-rgmii-delay = <&scm_conf 0x4124>;
+				/* Filled in by bootloader */
+				local-mac-address = [00 00 00 00 00 00];
+			};
+		};
+	};
 };
 
 &wkup_pmx0 {
@@ -242,6 +317,43 @@
 			AM65X_IOPAD(0x02c0, PIN_OUTPUT, 0) /* (AC8) USB1_DRVVBUS */
 		>;
 	};
+
+	icssg2_mdio_pins_default: icssg2-mdio-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x0094, PIN_INPUT, 2) /* (AC19) PRG2_PRU0_GPO7.PRG2_MDIO0_MDIO */
+			AM65X_IOPAD(0x00c8, PIN_OUTPUT, 2) /* (AE15) PRG2_PRU1_GPO7.PRG2_MDIO0_MDC */
+		>;
+	};
+
+	icssg2_rgmii_pins_default: icssg2-rgmii-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x00ac, PIN_INPUT, 2) /* (AH15) PRG2_PRU1_GPO0.PRG2_RGMII2_RD0 */
+			AM65X_IOPAD(0x00b0, PIN_INPUT, 2) /* (AC16) PRG2_PRU1_GPO1.PRG2_RGMII2_RD1 */
+			AM65X_IOPAD(0x00b4, PIN_INPUT, 2) /* (AD17) PRG2_PRU1_GPO2.PRG2_RGMII2_RD2 */
+			AM65X_IOPAD(0x00b8, PIN_INPUT, 2) /* (AH14) PRG2_PRU1_GPO3.PRG2_RGMII2_RD3 */
+			AM65X_IOPAD(0x00cc, PIN_OUTPUT, 2) /* (AD15) PRG2_PRU1_GPO8.PRG2_RGMII2_TD0 */
+			AM65X_IOPAD(0x00d0, PIN_OUTPUT, 2) /* (AF14) PRG2_PRU1_GPO9.PRG2_RGMII2_TD1 */
+			AM65X_IOPAD(0x00d4, PIN_OUTPUT, 2) /* (AC15) PRG2_PRU1_GPO10.PRG2_RGMII2_TD2 */
+			AM65X_IOPAD(0x00d8, PIN_OUTPUT, 2) /* (AD14) PRG2_PRU1_GPO11.PRG2_RGMII2_TD3 */
+			AM65X_IOPAD(0x00dc, PIN_INPUT, 2) /* (AE14) PRG2_PRU1_GPO16.PRG2_RGMII2_TXC */
+			AM65X_IOPAD(0x00c4, PIN_OUTPUT, 2) /* (AC17) PRG2_PRU1_GPO6.PRG2_RGMII2_TX_CTL */
+			AM65X_IOPAD(0x00c0, PIN_INPUT, 2) /* (AG15) PRG2_PRU1_GPO5.PRG2_RGMII2_RXC */
+			AM65X_IOPAD(0x00bc, PIN_INPUT, 2) /* (AG14) PRG2_PRU1_GPO4.PRG2_RGMII2_RX_CTL */
+
+			AM65X_IOPAD(0x0078, PIN_INPUT, 2) /* (AF18) PRG2_PRU0_GPO0.PRG2_RGMII1_RD0 */
+			AM65X_IOPAD(0x007c, PIN_INPUT, 2) /* (AE18) PRG2_PRU0_GPO1.PRG2_RGMII1_RD1 */
+			AM65X_IOPAD(0x0080, PIN_INPUT, 2) /* (AH17) PRG2_PRU0_GPO2.PRG2_RGMII1_RD2 */
+			AM65X_IOPAD(0x0084, PIN_INPUT, 2) /* (AG18) PRG2_PRU0_GPO3.PRG2_RGMII1_RD3 */
+			AM65X_IOPAD(0x0098, PIN_OUTPUT, 2) /* (AH16) PRG2_PRU0_GPO8.PRG2_RGMII1_TD0 */
+			AM65X_IOPAD(0x009c, PIN_OUTPUT, 2) /* (AG16) PRG2_PRU0_GPO9.PRG2_RGMII1_TD1 */
+			AM65X_IOPAD(0x00a0, PIN_OUTPUT, 2) /* (AF16) PRG2_PRU0_GPO10.PRG2_RGMII1_TD2 */
+			AM65X_IOPAD(0x00a4, PIN_OUTPUT, 2) /* (AE16) PRG2_PRU0_GPO11.PRG2_RGMII1_TD3 */
+			AM65X_IOPAD(0x00a8, PIN_INPUT, 2) /* (AD16) PRG2_PRU0_GPO16.PRG2_RGMII1_TXC */
+			AM65X_IOPAD(0x0090, PIN_OUTPUT, 2) /* (AE17) PRG2_PRU0_GPO6.PRG2_RGMII1_TX_CTL */
+			AM65X_IOPAD(0x008c, PIN_INPUT, 2) /* (AF17) PRG2_PRU0_GPO5.PRG2_RGMII1_RXC */
+			AM65X_IOPAD(0x0088, PIN_INPUT, 2) /* (AG17) PRG2_PRU0_GPO4.PRG2_RGMII1_RX_CTL */
+		>;
+	};
 };
 
 &main_pmx1 {
@@ -264,6 +376,13 @@
 			AM65X_IOPAD(0x0010, PIN_INPUT, 0) /* (D21) ECAP0_IN_APWM_OUT */
 		>;
 	};
+
+	/* Select GPIO1_87 for ICSSG2 PHY interrupt */
+	icssg2_phy_irq_pins_default: icssg2-phy-irq-default-pins {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x0014, PIN_INPUT, 7) /* (A22) EXT_REFCLK1.GPIO1_87 */
+		>;
+	};
 };
 
 &wkup_uart0 {
@@ -271,13 +390,20 @@
 	status = "reserved";
 };
 
+&mcu_uart0 {
+	status = "okay";
+	/* Default pinmux */
+};
+
 &main_uart0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart0_pins_default>;
 	power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
 };
 
 &wkup_i2c0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&wkup_i2c0_pins_default>;
 	clock-frequency = <400000>;
@@ -296,7 +422,13 @@
 	};
 };
 
+&mcu_i2c0 {
+	status = "okay";
+	/* Default pinmux */
+};
+
 &main_i2c0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c0_pins_default>;
 	clock-frequency = <400000>;
@@ -310,23 +442,27 @@
 };
 
 &main_i2c1 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c1_pins_default>;
 	clock-frequency = <400000>;
 };
 
 &main_i2c2 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c2_pins_default>;
 	clock-frequency = <400000>;
 };
 
 &ecap0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&ecap0_pins_default>;
 };
 
 &main_spi0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_spi0_pins_default>;
 	#address-cells = <1>;
@@ -398,31 +534,8 @@
 	status = "disabled";
 };
 
-&pcie0_rc {
-	status = "disabled";
-};
-
-&pcie0_ep {
-	status = "disabled";
-};
-
-&pcie1_rc {
-	status = "disabled";
-};
-
-&pcie1_ep {
-	status = "disabled";
-};
-
-&m_can0 {
-	status = "disabled";
-};
-
-&m_can1 {
-	status = "disabled";
-};
-
 &mailbox0_cluster0 {
+	status = "okay";
 	interrupts = <436>;
 
 	mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
@@ -432,6 +545,7 @@
 };
 
 &mailbox0_cluster1 {
+	status = "okay";
 	interrupts = <432>;
 
 	mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
@@ -440,46 +554,6 @@
 	};
 };
 
-&mailbox0_cluster2 {
-	status = "disabled";
-};
-
-&mailbox0_cluster3 {
-	status = "disabled";
-};
-
-&mailbox0_cluster4 {
-	status = "disabled";
-};
-
-&mailbox0_cluster5 {
-	status = "disabled";
-};
-
-&mailbox0_cluster6 {
-	status = "disabled";
-};
-
-&mailbox0_cluster7 {
-	status = "disabled";
-};
-
-&mailbox0_cluster8 {
-	status = "disabled";
-};
-
-&mailbox0_cluster9 {
-	status = "disabled";
-};
-
-&mailbox0_cluster10 {
-	status = "disabled";
-};
-
-&mailbox0_cluster11 {
-	status = "disabled";
-};
-
 &mcu_r5fss0_core0 {
 	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
 			<&mcu_r5fss0_core0_memory_region>;
@@ -507,15 +581,65 @@
 		cdns,tchsh-ns = <60>;
 		cdns,tslch-ns = <60>;
 		cdns,read-delay = <0>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi.env";
+				reg = <0x680000 0x20000>;
+			};
+
+			partition@6a0000 {
+				label = "ospi.env.backup";
+				reg = <0x6a0000 0x20000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi.sysfw";
+				reg = <0x6c0000 0x100000>;
+			};
+
+			partition@800000 {
+				label = "ospi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fe0000 {
+				label = "ospi.phypattern";
+				reg = <0x3fe0000 0x20000>;
+			};
+		};
 	};
 };
 
 &mcu_cpsw {
 	pinctrl-names = "default";
-	pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
+	pinctrl-0 = <&mcu_cpsw_pins_default>;
 };
 
 &davinci_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mdio_pins_default>;
+
 	phy0: ethernet-phy@0 {
 		reg = <0>;
 		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
@@ -528,18 +652,6 @@
 	phy-handle = <&phy0>;
 };
 
-&mcasp0 {
-	status = "disabled";
-};
-
-&mcasp1 {
-	status = "disabled";
-};
-
-&mcasp2 {
-	status = "disabled";
-};
-
 &dss {
 	status = "disabled";
 };
@@ -553,5 +665,23 @@
 };
 
 &icssg2_mdio {
-	status = "disabled";
+	status = "okay";
+	pinctrl-names = "default", "icssg2-phy-irq";
+	pinctrl-0 = <&icssg2_mdio_pins_default>, <&icssg2_phy_irq_pins_default>;
+
+	icssg2_phy0: ethernet-phy@0 {
+		reg = <0>;
+		interrupt-parent = <&main_gpio1>;
+		interrupts = <87 0x2>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+	};
+
+	icssg2_phy1: ethernet-phy@3 {
+		reg = <3>;
+		interrupt-parent = <&main_gpio1>;
+		interrupts = <87 0x2>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am654.dtsi b/arch/arm64/boot/dts/ti/k3-am654.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am654.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am654.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -93,6 +93,7 @@
 	L2_0: l2-cache0 {
 		compatible = "cache";
 		cache-level = <2>;
+		cache-unified;
 		cache-size = <0x80000>;
 		cache-line-size = <64>;
 		cache-sets = <512>;
@@ -102,6 +103,7 @@
 	L2_1: l2-cache1 {
 		compatible = "cache";
 		cache-level = <2>;
+		cache-unified;
 		cache-size = <0x80000>;
 		cache-line-size = <64>;
 		cache-sets = <512>;
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am654-evm-oldi-lcd1evm.dtso b/arch/arm64/boot/dts/ti/k3-am654-evm-oldi-lcd1evm.dtso
--- a/arch/arm64/boot/dts/ti/k3-am654-evm-oldi-lcd1evm.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am654-evm-oldi-lcd1evm.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * OLDI-LCD1EVM Rocktech integrated panel and touch DT overlay for AM654-EVM.
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+&{/} {
+	display0 {
+		compatible = "rocktech,rk101ii01d-ct";
+		backlight = <&lcd_bl>;
+		enable-gpios = <&pca9555 8 GPIO_ACTIVE_HIGH>;
+		port {
+			lcd_in0: endpoint {
+				remote-endpoint = <&oldi_out0>;
+			};
+		};
+	};
+	lcd_bl: backlight {
+		compatible = "pwm-backlight";
+		pwms = <&ecap0 0 50000 PWM_POLARITY_INVERTED>;
+		brightness-levels =
+			<0 32 64 96 128 160 192 224 255>;
+		default-brightness-level = <8>;
+	};
+};
+
+&dss {
+	status = "okay";
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@0 {
+		reg = <0>;
+
+		oldi_out0: endpoint {
+			remote-endpoint = <&lcd_in0>;
+		};
+	};
+};
+
+&main_i2c1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	gt928: touchscreen@14 {
+		status = "okay";
+		compatible = "goodix,gt928";
+		reg = <0x14>;
+
+		interrupt-parent = <&pca9554>;
+		interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+		touchscreen-size-x = <1280>;
+		touchscreen-size-y = <800>;
+
+		reset-gpios = <&pca9555 9 GPIO_ACTIVE_HIGH>;
+		irq-gpios = <&pca9554 3 GPIO_ACTIVE_HIGH>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso
--- a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT overlay for IDK application board on AM654 EVM
+ *
+ * Copyright (C) 2018-2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
+#include "k3-pinctrl.h"
+
+&{/} {
+	aliases {
+		ethernet3 = "/icssg0-eth/ethernet-ports/port@0";
+		ethernet4 = "/icssg0-eth/ethernet-ports/port@1";
+		ethernet5 = "/icssg1-eth/ethernet-ports/port@0";
+		ethernet6 = "/icssg1-eth/ethernet-ports/port@1";
+	};
+
+	transceiver1: can-phy0 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&mcan0_gpio_pins_default>;
+		standby-gpios = <&main_gpio1 47 GPIO_ACTIVE_LOW>;
+	};
+
+        transceiver2: can-phy1 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&mcan1_gpio_pins_default>;
+		standby-gpios = <&main_gpio1 67 GPIO_ACTIVE_LOW>;
+	};
+
+	/* Dual Ethernet application node on PRU-ICSSG0 */
+	icssg0_eth: icssg0-eth {
+		compatible = "ti,am654-icssg-prueth";
+		pinctrl-names = "default";
+		pinctrl-0 = <&icssg0_rgmii_pins_default>;
+		sram = <&msmc_ram>;
+		ti,prus = <&pru0_0>, <&rtu0_0>, <&tx_pru0_0>, <&pru0_1>, <&rtu0_1>, <&tx_pru0_1>;
+		firmware-name = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-rtu0-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-txpru0-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-pru1-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-rtu1-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-txpru1-prueth-fw.elf";
+
+		ti,pruss-gp-mux-sel = <2>,	/* MII mode */
+				      <2>,
+				      <2>,
+				      <2>,	/* MII mode */
+				      <2>,
+				      <2>;
+
+		ti,mii-g-rt = <&icssg0_mii_g_rt>;
+		ti,mii-rt = <&icssg0_mii_rt>;
+		ti,pa-stats = <&icssg0_pa_stats>;
+		iep = <&icssg0_iep0>,  <&icssg0_iep1>;
+
+		interrupt-parent = <&icssg0_intc>;
+		interrupts = <24 0 2>, <25 1 3>;
+		interrupt-names = "tx_ts0", "tx_ts1";
+
+		dmas = <&main_udmap 0xc100>, /* egress slice 0 */
+		       <&main_udmap 0xc101>, /* egress slice 0 */
+		       <&main_udmap 0xc102>, /* egress slice 0 */
+		       <&main_udmap 0xc103>, /* egress slice 0 */
+		       <&main_udmap 0xc104>, /* egress slice 1 */
+		       <&main_udmap 0xc105>, /* egress slice 1 */
+		       <&main_udmap 0xc106>, /* egress slice 1 */
+		       <&main_udmap 0xc107>, /* egress slice 1 */
+
+		       <&main_udmap 0x4100>, /* ingress slice 0 */
+		       <&main_udmap 0x4101>, /* ingress slice 1 */
+		       <&main_udmap 0x4102>, /* mgmnt rsp slice 0 */
+		       <&main_udmap 0x4103>; /* mgmnt rsp slice 1 */
+		dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3",
+			    "tx1-0", "tx1-1", "tx1-2", "tx1-3",
+			    "rx0", "rx1";
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			icssg0_emac0: port@0 {
+				reg = <0>;
+				phy-handle = <&icssg0_phy0>;
+				phy-mode = "rgmii-id";
+				ti,syscon-rgmii-delay = <&scm_conf 0x4100>;
+				/* Filled in by bootloader */
+				local-mac-address = [00 00 00 00 00 00];
+			};
+			icssg0_emac1: port@1 {
+				reg = <1>;
+				phy-handle = <&icssg0_phy1>;
+				phy-mode = "rgmii-id";
+				ti,syscon-rgmii-delay = <&scm_conf 0x4104>;
+				/* Filled in by bootloader */
+				local-mac-address = [00 00 00 00 00 00];
+			};
+		};
+	};
+
+	/* Dual Ethernet application node on PRU-ICSSG1 */
+	icssg1_eth: icssg1-eth {
+		compatible = "ti,am654-icssg-prueth";
+		pinctrl-names = "default";
+		pinctrl-0 = <&icssg1_rgmii_pins_default>;
+		sram = <&msmc_ram>;
+		ti,prus = <&pru1_0>, <&rtu1_0>, <&tx_pru1_0>, <&pru1_1>, <&rtu1_1>, <&tx_pru1_1>;
+		firmware-name = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-rtu0-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-txpru0-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-pru1-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-rtu1-prueth-fw.elf",
+				"ti-pruss/am65x-sr2-txpru1-prueth-fw.elf";
+
+		ti,pruss-gp-mux-sel = <2>,	/* MII mode */
+				      <2>,
+				      <2>,
+				      <2>,	/* MII mode */
+				      <2>,
+				      <2>;
+
+		ti,mii-g-rt = <&icssg1_mii_g_rt>;
+		ti,mii-rt = <&icssg1_mii_rt>;
+		ti,pa-stats = <&icssg1_pa_stats>;
+		iep = <&icssg1_iep0>,  <&icssg1_iep1>;
+
+		interrupt-parent = <&icssg1_intc>;
+		interrupts = <24 0 2>, <25 1 3>;
+
+		interrupt-names = "tx_ts0", "tx_ts1";
+
+		dmas = <&main_udmap 0xc200>, /* egress slice 0 */
+		       <&main_udmap 0xc201>, /* egress slice 0 */
+		       <&main_udmap 0xc202>, /* egress slice 0 */
+		       <&main_udmap 0xc203>, /* egress slice 0 */
+		       <&main_udmap 0xc204>, /* egress slice 1 */
+		       <&main_udmap 0xc205>, /* egress slice 1 */
+		       <&main_udmap 0xc206>, /* egress slice 1 */
+		       <&main_udmap 0xc207>, /* egress slice 1 */
+
+		       <&main_udmap 0x4200>, /* ingress slice 0 */
+		       <&main_udmap 0x4201>, /* ingress slice 1 */
+		       <&main_udmap 0x4202>, /* mgmnt rsp slice 0 */
+		       <&main_udmap 0x4203>; /* mgmnt rsp slice 1 */
+		dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3",
+			    "tx1-0", "tx1-1", "tx1-2", "tx1-3",
+			    "rx0", "rx1";
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			icssg1_emac0: port@0 {
+				reg = <0>;
+				phy-handle = <&icssg1_phy0>;
+				phy-mode = "rgmii-id";
+				ti,syscon-rgmii-delay = <&scm_conf 0x4110>;
+				/* Filled in by bootloader */
+				local-mac-address = [00 00 00 00 00 00];
+			};
+			icssg1_emac1: port@1 {
+				reg = <1>;
+				phy-handle = <&icssg1_phy1>;
+				phy-mode = "rgmii-id";
+				ti,syscon-rgmii-delay = <&scm_conf 0x4114>;
+				/* Filled in by bootloader */
+				local-mac-address = [00 00 00 00 00 00];
+			};
+		};
+	};
+};
+
+&main_pmx0 {
+	mcan0_gpio_pins_default: mcan0-gpio-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x023c, PIN_INPUT, 7) /* (V25) PRG0_PRU0_GPIO18:GPIO1_47 */
+		>;
+	};
+
+	mcan1_gpio_pins_default: mcan1-gpio-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x028c, PIN_INPUT, 7) /* (Y26) PRG0_PRU1_GPIO18.GPIO1_67 */
+		>;
+	};
+
+	icssg0_mdio_pins_default: icssg0-mdio-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x0294, PIN_INPUT, 0) /* (AE26) PRG0_MDIO0_MDIO */
+			AM65X_IOPAD(0x0298, PIN_OUTPUT, 0) /* (AE28) PRG0_MDIO0_MDC */
+		>;
+	};
+
+	icssg0_rgmii_pins_default: icssg0-rgmii-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x0244, PIN_INPUT, 2) /* (AB28) PRG0_PRU1_GPO0.PRG0_RGMII2_RD0 */
+			AM65X_IOPAD(0x0248, PIN_INPUT, 2) /* (AC28) PRG0_PRU1_GPO1.PRG0_RGMII2_RD1 */
+			AM65X_IOPAD(0x024c, PIN_INPUT, 2) /* (AC27) PRG0_PRU1_GPO2.PRG0_RGMII2_RD2 */
+			AM65X_IOPAD(0x0250, PIN_INPUT, 2) /* (AB26) PRG0_PRU1_GPO3.PRG0_RGMII2_RD3 */
+			AM65X_IOPAD(0x0274, PIN_OUTPUT, 2) /* (AC25) PRG0_PRU1_GPO12.PRG0_RGMII2_TD0 */
+			AM65X_IOPAD(0x0278, PIN_OUTPUT, 2) /* (AD25) PRG0_PRU1_GPO13.PRG0_RGMII2_TD1 */
+			AM65X_IOPAD(0x027c, PIN_OUTPUT, 2) /* (AD24) PRG0_PRU1_GPO14.PRG0_RGMII2_TD2 */
+			AM65X_IOPAD(0x0280, PIN_OUTPUT, 2) /* (AE27) PRG0_PRU1_GPO15.PRG0_RGMII2_TD3 */
+			AM65X_IOPAD(0x0284, PIN_INPUT, 2) /* (AC24) PRG0_PRU1_GPO16.PRG0_RGMII2_TXC */
+			AM65X_IOPAD(0x0270, PIN_OUTPUT, 2) /* (AB24) PRG0_PRU1_GPO11.PRG0_RGMII2_TX_CTL */
+			AM65X_IOPAD(0x025c, PIN_INPUT, 2) /* (AB27) PRG0_PRU1_GPO6.PRG0_RGMII2_RXC */
+			AM65X_IOPAD(0x0254, PIN_INPUT, 2) /* (AA25) PRG0_PRU1_GPO4.PRG0_RGMII2_RX_CTL */
+
+			AM65X_IOPAD(0x01f4, PIN_INPUT, 2) /* (V24) PRG0_PRU0_GPO0.PRG0_RGMII1_RD0 */
+			AM65X_IOPAD(0x01f8, PIN_INPUT, 2) /* (W25) PRG0_PRU0_GPO1.PRG0_RGMII1_RD1 */
+			AM65X_IOPAD(0x01fc, PIN_INPUT, 2) /* (W24) PRG0_PRU0_GPO2.PRG0_RGMII1_RD2 */
+			AM65X_IOPAD(0x0200, PIN_INPUT, 2) /* (AA27) PRG0_PRU0_GPO3.PRG0_RGMII1_RD3 */
+			AM65X_IOPAD(0x0224, PIN_OUTPUT, 2) /* (AD27) PRG0_PRU0_GPO12.PRG0_RGMII1_TD0 */
+			AM65X_IOPAD(0x0228, PIN_OUTPUT, 2) /* (AC26) PRG0_PRU0_GPO13.PRG0_RGMII1_TD1 */
+			AM65X_IOPAD(0x022c, PIN_OUTPUT, 2) /* (AD26) PRG0_PRU0_GPO14.PRG0_RGMII1_TD2 */
+			AM65X_IOPAD(0x0230, PIN_OUTPUT, 2) /* (AA24) PRG0_PRU0_GPO15.PRG0_RGMII1_TD3 */
+			AM65X_IOPAD(0x0234, PIN_INPUT, 2) /* (AD28) PRG0_PRU0_GPO16.PRG0_RGMII1_TXC */
+			AM65X_IOPAD(0x0220, PIN_OUTPUT, 2) /* (AB25) PRG0_PRU0_GPO11.PRG0_RGMII1_TX_CTL */
+			AM65X_IOPAD(0x020c, PIN_INPUT, 2) /* (Y25) PRG0_PRU0_GPO6.PRG0_RGMII1_RXC */
+			AM65X_IOPAD(0x0204, PIN_INPUT, 2) /* (Y24) PRG0_PRU0_GPO4.PRG0_RGMII1_RX_CTL */
+		>;
+	};
+
+	icssg0_iep0_pins_default: icssg0-iep0-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x0240, PIN_INPUT, 2) /* (U24) PRG0_PRU0_GPO19.PRG0_IEP0_EDC_SYNC_OUT0 */
+		>;
+	};
+
+	icssg1_mdio_pins_default: icssg1-mdio-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x0180, PIN_INPUT, 0) /* (AD18) PRG1_MDIO0_MDIO */
+			AM65X_IOPAD(0x0184, PIN_OUTPUT, 0) /* (AH18) PRG1_MDIO0_MDC */
+		>;
+	};
+
+	icssg1_rgmii_pins_default: icssg1-rgmii-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x0130, PIN_INPUT, 2) /* (AH24) PRG1_PRU1_GPO0.PRG1_RGMII2_RD0 */
+			AM65X_IOPAD(0x0134, PIN_INPUT, 2) /* (AH23) PRG1_PRU1_GPO1.PRG1_RGMII2_RD1 */
+			AM65X_IOPAD(0x0138, PIN_INPUT, 2) /* (AG21) PRG1_PRU1_GPO2.PRG1_RGMII2_RD2 */
+			AM65X_IOPAD(0x013c, PIN_INPUT, 2) /* (AH22) PRG1_PRU1_GPO3.PRG1_RGMII2_RD3 */
+			AM65X_IOPAD(0x0160, PIN_OUTPUT, 2) /* (AE20) PRG1_PRU1_GPO12.PRG1_RGMII2_TD0 */
+			AM65X_IOPAD(0x0164, PIN_OUTPUT, 2) /* (AF19) PRG1_PRU1_GPO13.PRG1_RGMII2_TD1 */
+			AM65X_IOPAD(0x0168, PIN_OUTPUT, 2) /* (AH19) PRG1_PRU1_GPO14.PRG1_RGMII2_TD2 */
+			AM65X_IOPAD(0x016c, PIN_OUTPUT, 2) /* (AG19) PRG1_PRU1_GPO15.PRG1_RGMII2_TD3 */
+			AM65X_IOPAD(0x0170, PIN_INPUT, 2) /* (AE19) PRG1_PRU1_GPO16.PRG1_RGMII2_TXC */
+			AM65X_IOPAD(0x015c, PIN_OUTPUT, 2) /* (AC20) PRG1_PRU1_GPO11.PRG1_RGMII2_TX_CTL */
+			AM65X_IOPAD(0x0148, PIN_INPUT, 2) /* (AG22) PRG1_PRU1_GPO6.PRG1_RGMII2_RXC */
+			AM65X_IOPAD(0x0140, PIN_INPUT, 2) /* (AE21) PRG1_PRU1_GPO4.PRG1_RGMII2_RX_CTL */
+
+			AM65X_IOPAD(0x00e0, PIN_INPUT, 2) /* (AE22) PRG1_PRU0_GPO0.PRG1_RGMII1_RD0 */
+			AM65X_IOPAD(0x00e4, PIN_INPUT, 2) /* (AG24) PRG1_PRU0_GPO1.PRG1_RGMII1_RD1 */
+			AM65X_IOPAD(0x00e8, PIN_INPUT, 2) /* (AF23) PRG1_PRU0_GPO2.PRG1_RGMII1_RD2 */
+			AM65X_IOPAD(0x00ec, PIN_INPUT, 2) /* (AD21) PRG1_PRU0_GPO3.PRG1_RGMII1_RD3 */
+			AM65X_IOPAD(0x0110, PIN_OUTPUT, 2) /* (AH20) PRG1_PRU0_GPO12.PRG1_RGMII1_TD0 */
+			AM65X_IOPAD(0x0114, PIN_OUTPUT, 2) /* (AH21) PRG1_PRU0_GPO13.PRG1_RGMII1_TD1 */
+			AM65X_IOPAD(0x0118, PIN_OUTPUT, 2) /* (AG20) PRG1_PRU0_GPO14.PRG1_RGMII1_TD2 */
+			AM65X_IOPAD(0x011c, PIN_OUTPUT, 2) /* (AD19) PRG1_PRU0_GPO15.PRG1_RGMII1_TD3 */
+			AM65X_IOPAD(0x0120, PIN_INPUT, 2) /* (AD20) PRG1_PRU0_GPO16.PRG1_RGMII1_TXC */
+			AM65X_IOPAD(0x010c, PIN_OUTPUT, 2) /* (AF21) PRG1_PRU0_GPO11.PRG1_RGMII1_TX_CTL */
+			AM65X_IOPAD(0x00f8, PIN_INPUT, 2) /* (AF22) PRG1_PRU0_GPO6.PRG1_RGMII1_RXC */
+			AM65X_IOPAD(0x00f0, PIN_INPUT, 2) /* (AG23) PRG1_PRU0_GPO4.PRG1_RGMII1_RX_CTL */
+		>;
+	};
+
+	icssg1_iep0_pins_default: icssg1-iep0-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x012c, PIN_INPUT, 2) /* (AG26) PRG1_PRU0_GPO19.PRG1_IEP0_EDC_SYNC_OUT0 */
+		>;
+	};
+};
+
+&wkup_pmx0 {
+	mcu_mcan0_pins_default: mcu-mcan0-pins-default {
+		pinctrl-single,pins = <
+			AM65X_WKUP_IOPAD(0x00ac, PIN_INPUT_PULLUP, 0) /* (W2) MCU_MCAN0_RX */
+			AM65X_WKUP_IOPAD(0x00a8, PIN_OUTPUT_PULLUP, 0) /* (W1) MCU_MCAN0_TX */
+		>;
+	};
+
+	mcu_mcan1_pins_default: mcu-mcan1-pins-default {
+		pinctrl-single,pins = <
+			AM65X_WKUP_IOPAD(0x00c4, PIN_INPUT_PULLUP, 1) /* (AD3) WKUP_GPIO0_5.MCU_MCAN1_RX */
+			AM65X_WKUP_IOPAD(0x00c0, PIN_OUTPUT_PULLUP, 1) /* (AC3) WKUP_GPIO0_4.MCU_MCAN1_TX */
+		>;
+	};
+};
+
+&m_can0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mcan0_pins_default>;
+	phys = <&transceiver1>;
+};
+
+&m_can1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mcan1_pins_default>;
+	phys = <&transceiver2>;
+};
+
+&icssg0_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&icssg0_mdio_pins_default>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	icssg0_phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+	};
+
+	icssg0_phy1: ethernet-phy@3 {
+		reg = <3>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+	};
+};
+
+&icssg0_iep0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&icssg0_iep0_pins_default>;
+};
+
+&icssg1_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&icssg1_mdio_pins_default>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	icssg1_phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+	};
+
+	icssg1_phy1: ethernet-phy@3 {
+		reg = <3>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+	};
+};
+
+&icssg1_iep0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&icssg1_iep0_pins_default>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am654-pcie-usb2.dtso b/arch/arm64/boot/dts/ti/k3-am654-pcie-usb2.dtso
--- a/arch/arm64/boot/dts/ti/k3-am654-pcie-usb2.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am654-pcie-usb2.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT overlay for SERDES personality card: 2lane PCIe + USB2.0 Host on AM654 EVM
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/phy/phy-am654-serdes.h>
+#include "k3-pinctrl.h"
+
+&serdes0 {
+	assigned-clocks = <&k3_clks 153 4>,
+			  <&serdes0 AM654_SERDES_CMU_REFCLK>,
+			  <&serdes0 AM654_SERDES_RO_REFCLK>;
+	assigned-clock-parents = <&k3_clks 153 8>,
+				 <&k3_clks 153 4>,
+				 <&k3_clks 153 4>;
+	status = "okay";
+};
+
+&serdes1 {
+	assigned-clocks = <&serdes1 AM654_SERDES_CMU_REFCLK>;
+	assigned-clock-parents = <&serdes0 AM654_SERDES_RO_REFCLK>;
+	status = "okay";
+};
+
+&pcie0_rc {
+	num-lanes = <2>;
+	phys = <&serdes0 PHY_TYPE_PCIE 1>, <&serdes1 PHY_TYPE_PCIE 1>;
+	phy-names = "pcie-phy0", "pcie-phy1";
+	reset-gpios = <&pca9555 5 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&pcie0_ep {
+	num-lanes = <2>;
+	phys = <&serdes0 PHY_TYPE_PCIE 1>, <&serdes1 PHY_TYPE_PCIE 1>;
+	phy-names = "pcie-phy0", "pcie-phy1";
+};
+
+&main_pmx0 {
+       usb0_pins_default: usb0-pins-default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x02bc, PIN_OUTPUT, 0) /* (AD9) USB0_DRVVBUS */
+		>;
+	};
+};
+
+&dwc3_0 {
+	status = "okay";
+};
+
+&usb0_phy {
+	status = "okay";
+};
+
+&usb0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb0_pins_default>;
+	dr_mode = "host";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am654-pcie-usb3.dtso b/arch/arm64/boot/dts/ti/k3-am654-pcie-usb3.dtso
--- a/arch/arm64/boot/dts/ti/k3-am654-pcie-usb3.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am654-pcie-usb3.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT overlay for SERDES personality card: 1lane PCIe + USB3.0 DRD on AM654 EVM
+ *
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/phy/phy-am654-serdes.h>
+
+#include "k3-pinctrl.h"
+
+&serdes1 {
+	status = "okay";
+};
+
+&pcie1_rc {
+	num-lanes = <1>;
+	phys = <&serdes1 PHY_TYPE_PCIE 0>;
+	phy-names = "pcie-phy0";
+	reset-gpios = <&pca9555 5 GPIO_ACTIVE_HIGH>;
+	status = "okay";
+};
+
+&pcie1_ep {
+	num-lanes = <1>;
+	phys = <&serdes1 PHY_TYPE_PCIE 0>;
+	phy-names = "pcie-phy0";
+};
+
+&main_pmx0 {
+	usb0_pins_default: usb0_pins_default {
+		pinctrl-single,pins = <
+			AM65X_IOPAD(0x02bc, PIN_OUTPUT, 0) /* (AD9) USB0_DRVVBUS */
+		>;
+	};
+};
+
+&serdes0 {
+	status = "okay";
+	assigned-clocks = <&k3_clks 153 4>, <&serdes0 AM654_SERDES_CMU_REFCLK>;
+	assigned-clock-parents = <&k3_clks 153 7>, <&k3_clks 153 4>;
+};
+
+&dwc3_0 {
+	status = "okay";
+	assigned-clock-parents = <&k3_clks 151 4>,      /* set REF_CLK to 20MHz i.e. PER0_PLL/48 */
+	<&k3_clks 151 8>;      /* set PIPE3_TXB_CLK to WIZ8B2M4VSB */
+	phys = <&serdes0 PHY_TYPE_USB3 0>;
+	phy-names = "usb3-phy";
+};
+
+&usb0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb0_pins_default>;
+	dr_mode = "host";
+	maximum-speed = "super-speed";
+	snps,dis-u1-entry-quirk;
+	snps,dis-u2-entry-quirk;
+};
+
+&usb0_phy {
+	status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am65.dtsi b/arch/arm64/boot/dts/ti/k3-am65.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am65.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am65.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -8,9 +8,10 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/pinctrl/k3.h>
 #include <dt-bindings/soc/ti,sci_pm_domain.h>
 
+#include "k3-pinctrl.h"
+
 / {
 	model = "Texas Instruments K3 AM654 SoC";
 	compatible = "ti,am654";
@@ -70,6 +71,7 @@
 		ranges = <0x00 0x00100000 0x00 0x00100000 0x00 0x00020000>, /* ctrl mmr */
 			 <0x00 0x00600000 0x00 0x00600000 0x00 0x00001100>, /* GPIO */
 			 <0x00 0x00900000 0x00 0x00900000 0x00 0x00012000>, /* serdes */
+			 <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* timesync router */
 			 <0x00 0x01000000 0x00 0x01000000 0x00 0x0af02400>, /* Most peripherals */
 			 <0x00 0x30800000 0x00 0x30800000 0x00 0x0bc00000>, /* MAIN NAVSS */
 			 <0x00 0x70000000 0x00 0x70000000 0x00 0x00200000>, /* MSMC SRAM */
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -360,15 +360,13 @@
 };
 
 &main_uart1 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart1_pins_default>;
 };
 
-&main_uart2 {
-	status = "disabled";
-};
-
 &mcu_uart0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&arduino_uart_pins_default>;
 };
@@ -413,12 +411,14 @@
 };
 
 &wkup_i2c0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&wkup_i2c0_pins_default>;
 	clock-frequency = <400000>;
 };
 
 &mcu_i2c0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcu_i2c0_pins_default>;
 	clock-frequency = <400000>;
@@ -478,6 +478,7 @@
 };
 
 &main_i2c0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c0_pins_default>;
 	clock-frequency = <400000>;
@@ -495,18 +496,21 @@
 };
 
 &main_i2c1 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c1_pins_default>;
 	clock-frequency = <400000>;
 };
 
 &main_i2c2 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c2_pins_default>;
 	clock-frequency = <400000>;
 };
 
 &main_i2c3 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c3_pins_default>;
 	clock-frequency = <400000>;
@@ -546,6 +550,7 @@
 };
 
 &ecap0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&ecap0_pins_default>;
 };
@@ -570,6 +575,7 @@
 };
 
 &mcu_spi0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcu_spi0_pins_default>;
 
@@ -603,6 +609,52 @@
 		cdns,tchsh-ns = <60>;
 		cdns,tslch-ns = <60>;
 		cdns,read-delay = <2>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			seboot@0 {
+				label = "seboot";
+				reg = <0x0 0x180000>; /* 1.5M */
+			};
+
+			tispl@180000 {
+				label = "tispl";
+				reg = <0x180000 0x200000>; /* 2M */
+			};
+
+			u-boot@380000 {
+				label = "u-boot";
+				reg = <0x380000 0x300000>; /* 3M */
+			};
+
+			env@680000 {
+				label = "env";
+				reg = <0x680000 0x20000>; /* 128K */
+			};
+
+			env-backup@6a0000 {
+				label = "env.backup";
+				reg = <0x6a0000 0x20000>; /* 128K */
+			};
+
+			otpcmd@6c0000 {
+				label = "otpcmd";
+				reg = <0x6c0000 0x10000>; /* 64K */
+			};
+
+			unused@6d0000 {
+				label = "unused";
+				reg = <0x6d0000 0x7b0000>; /* 7872K */
+			};
+
+			seboot-backup@e80000 {
+				label = "seboot.backup";
+				reg = <0xe80000 0x180000>; /* 1.5M */
+			};
+		};
 	};
 };
 
@@ -626,15 +678,8 @@
 	};
 };
 
-&pcie0_rc {
-	status = "disabled";
-};
-
-&pcie0_ep {
-	status = "disabled";
-};
-
 &pcie1_rc {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&minipcie_pins_default>;
 
@@ -644,19 +689,8 @@
 	reset-gpios = <&wkup_gpio0 27 GPIO_ACTIVE_HIGH>;
 };
 
-&m_can0 {
-	status = "disabled";
-};
-
-&m_can1 {
-	status = "disabled";
-};
-
-&pcie1_ep {
-	status = "disabled";
-};
-
 &mailbox0_cluster0 {
+	status = "okay";
 	interrupts = <436>;
 
 	mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
@@ -666,6 +700,7 @@
 };
 
 &mailbox0_cluster1 {
+	status = "okay";
 	interrupts = <432>;
 
 	mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
@@ -674,46 +709,6 @@
 	};
 };
 
-&mailbox0_cluster2 {
-	status = "disabled";
-};
-
-&mailbox0_cluster3 {
-	status = "disabled";
-};
-
-&mailbox0_cluster4 {
-	status = "disabled";
-};
-
-&mailbox0_cluster5 {
-	status = "disabled";
-};
-
-&mailbox0_cluster6 {
-	status = "disabled";
-};
-
-&mailbox0_cluster7 {
-	status = "disabled";
-};
-
-&mailbox0_cluster8 {
-	status = "disabled";
-};
-
-&mailbox0_cluster9 {
-	status = "disabled";
-};
-
-&mailbox0_cluster10 {
-	status = "disabled";
-};
-
-&mailbox0_cluster11 {
-	status = "disabled";
-};
-
 &mcu_r5fss0_core0 {
 	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
 			<&mcu_r5fss0_core0_memory_region>;
@@ -725,27 +720,3 @@
 			<&mcu_r5fss0_core1_memory_region>;
 	mboxes = <&mailbox0_cluster1 &mbox_mcu_r5fss0_core1>;
 };
-
-&icssg0_mdio {
-	status = "disabled";
-};
-
-&icssg1_mdio {
-	status = "disabled";
-};
-
-&icssg2_mdio {
-	status = "disabled";
-};
-
-&mcasp0 {
-	status = "disabled";
-};
-
-&mcasp1 {
-	status = "disabled";
-};
-
-&mcasp2 {
-	status = "disabled";
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -91,6 +91,7 @@
 		clock-frequency = <48000000>;
 		current-speed = <115200>;
 		power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_uart1: serial@2810000 {
@@ -99,6 +100,7 @@
 		interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
 		clock-frequency = <48000000>;
 		power-domains = <&k3_pds 147 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_uart2: serial@2820000 {
@@ -107,6 +109,7 @@
 		interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>;
 		clock-frequency = <48000000>;
 		power-domains = <&k3_pds 148 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	crypto: crypto@4e00000 {
@@ -125,7 +128,6 @@
 			compatible = "inside-secure,safexcel-eip76";
 			reg = <0x0 0x4e10000 0x0 0x7d>;
 			interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&k3_clks 136 1>;
 			status = "disabled"; /* Used by OP-TEE */
 		};
 	};
@@ -155,6 +157,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 110 1>;
 		power-domains = <&k3_pds 110 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c1: i2c@2010000 {
@@ -166,6 +169,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 111 1>;
 		power-domains = <&k3_pds 111 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c2: i2c@2020000 {
@@ -177,6 +181,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 112 1>;
 		power-domains = <&k3_pds 112 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c3: i2c@2030000 {
@@ -188,6 +193,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 113 1>;
 		power-domains = <&k3_pds 113 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	ecap0: pwm@3100000 {
@@ -197,6 +203,7 @@
 		power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 39 0>;
 		clock-names = "fck";
+		status = "disabled";
 	};
 
 	main_spi0: spi@2100000 {
@@ -209,6 +216,7 @@
 		#size-cells = <0>;
 		dmas = <&main_udmap 0xc500>, <&main_udmap 0x4500>;
 		dma-names = "tx0", "rx0";
+		status = "disabled";
 	};
 
 	main_spi1: spi@2110000 {
@@ -221,6 +229,7 @@
 		#size-cells = <0>;
 		assigned-clocks = <&k3_clks 137 1>;
 		assigned-clock-rates = <48000000>;
+		status = "disabled";
 	};
 
 	main_spi2: spi@2120000 {
@@ -231,6 +240,7 @@
 		power-domains = <&k3_pds 139 TI_SCI_PD_EXCLUSIVE>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		status = "disabled";
 	};
 
 	main_spi3: spi@2130000 {
@@ -241,6 +251,7 @@
 		power-domains = <&k3_pds 140 TI_SCI_PD_EXCLUSIVE>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		status = "disabled";
 	};
 
 	main_spi4: spi@2140000 {
@@ -251,6 +262,7 @@
 		power-domains = <&k3_pds 141 TI_SCI_PD_EXCLUSIVE>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		status = "disabled";
 	};
 
 	sdhci0: mmc@4f80000 {
@@ -341,11 +353,11 @@
 
 		dss_oldi_io_ctrl: dss-oldi-io-ctrl@41e0 {
 			compatible = "syscon";
-			reg = <0x0000041e0 0x14>;
+			reg = <0x000041e0 0x14>;
 		};
 
 		ehrpwm_tbclk: clock@4140 {
-			compatible = "ti,am654-ehrpwm-tbclk", "syscon";
+			compatible = "ti,am654-ehrpwm-tbclk";
 			reg = <0x4140 0x18>;
 			#clock-cells = <1>;
 		};
@@ -500,6 +512,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&intr_main_navss>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster1: mailbox@31f81000 {
@@ -509,6 +522,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&intr_main_navss>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster2: mailbox@31f82000 {
@@ -518,6 +532,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&intr_main_navss>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster3: mailbox@31f83000 {
@@ -527,6 +542,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&intr_main_navss>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster4: mailbox@31f84000 {
@@ -536,6 +552,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&intr_main_navss>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster5: mailbox@31f85000 {
@@ -545,6 +562,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&intr_main_navss>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster6: mailbox@31f86000 {
@@ -554,6 +572,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&intr_main_navss>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster7: mailbox@31f87000 {
@@ -563,6 +582,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&intr_main_navss>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster8: mailbox@31f88000 {
@@ -572,6 +592,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&intr_main_navss>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster9: mailbox@31f89000 {
@@ -581,6 +602,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&intr_main_navss>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster10: mailbox@31f8a000 {
@@ -590,6 +612,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&intr_main_navss>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster11: mailbox@31f8b000 {
@@ -599,6 +622,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&intr_main_navss>;
+			status = "disabled";
 		};
 
 		ringacc: ringacc@3c000000 {
@@ -706,6 +730,20 @@
 		interrupts = <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>;
 		msi-map = <0x0 &gic_its 0x0 0x10000>;
 		device_type = "pci";
+		status = "disabled";
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie0_intc 0>, /* INT A */
+				<0 0 0 2 &pcie0_intc 0>, /* INT B */
+				<0 0 0 3 &pcie0_intc 0>, /* INT C */
+				<0 0 0 4 &pcie0_intc 0>; /* INT D */
+
+		pcie0_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>;
+		};
 	};
 
 	pcie0_ep: pcie-ep@5500000 {
@@ -719,6 +757,7 @@
 		max-link-speed = <2>;
 		dma-coherent;
 		interrupts = <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
 	};
 
 	pcie1_rc: pcie@5600000 {
@@ -739,6 +778,20 @@
 		interrupts = <GIC_SPI 355 IRQ_TYPE_EDGE_RISING>;
 		msi-map = <0x0 &gic_its 0x10000 0x10000>;
 		device_type = "pci";
+		status = "disabled";
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie1_intc 0>, /* INT A */
+				<0 0 0 2 &pcie1_intc 0>, /* INT B */
+				<0 0 0 3 &pcie1_intc 0>, /* INT C */
+				<0 0 0 4 &pcie1_intc 0>; /* INT D */
+
+		pcie1_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 343 IRQ_TYPE_EDGE_RISING>;
+		};
 	};
 
 	pcie1_ep: pcie-ep@5600000 {
@@ -752,6 +805,7 @@
 		max-link-speed = <2>;
 		dma-coherent;
 		interrupts = <GIC_SPI 355 IRQ_TYPE_EDGE_RISING>;
+		status = "disabled";
 	};
 
 	mcasp0: mcasp@2b00000 {
@@ -769,6 +823,7 @@
 		clocks = <&k3_clks 104 0>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 104 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp1: mcasp@2b10000 {
@@ -786,6 +841,7 @@
 		clocks = <&k3_clks 105 0>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp2: mcasp@2b20000 {
@@ -803,6 +859,7 @@
 		clocks = <&k3_clks 106 0>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 106 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	cal: cal@6f03000 {
@@ -835,9 +892,10 @@
 			<0x0 0x04a07000 0x0 0x1000>, /* ovr1 */
 			<0x0 0x04a08000 0x0 0x1000>, /* ovr2 */
 			<0x0 0x04a0a000 0x0 0x1000>, /* vp1 */
-			<0x0 0x04a0b000 0x0 0x1000>; /* vp2 */
+			<0x0 0x04a0b000 0x0 0x1000>, /* vp2 */
+			<0x0 0x04a01000 0x0 0x1000>; /* common1 */
 		reg-names = "common", "vidl1", "vid",
-			"ovr1", "ovr2", "vp1", "vp2";
+			"ovr1", "ovr2", "vp1", "vp2", "common1";
 
 		ti,am65x-oldi-io-ctrl = <&dss_oldi_io_ctrl>;
 
@@ -856,7 +914,7 @@
 		assigned-clocks = <&k3_clks 67 2>;
 		assigned-clock-parents = <&k3_clks 67 5>;
 
-		interrupts = <GIC_SPI 166 IRQ_TYPE_EDGE_RISING>;
+		interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
 
 		dma-coherent;
 
@@ -866,6 +924,13 @@
 		};
 	};
 
+	gpu: gpu@7000000 {
+		compatible = "ti,am654-sgx544", "img,sgx544";
+		reg = <0x0 0x7000000 0x0 0x10000>;
+		interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 65 TI_SCI_PD_EXCLUSIVE>;
+	};
+
 	ehrpwm0: pwm@3000000 {
 		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
 		#pwm-cells = <3>;
@@ -873,6 +938,7 @@
 		power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&ehrpwm_tbclk 0>, <&k3_clks 40 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	ehrpwm1: pwm@3010000 {
@@ -882,6 +948,7 @@
 		power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&ehrpwm_tbclk 1>, <&k3_clks 41 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	ehrpwm2: pwm@3020000 {
@@ -891,6 +958,7 @@
 		power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&ehrpwm_tbclk 2>, <&k3_clks 42 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	ehrpwm3: pwm@3030000 {
@@ -900,6 +968,7 @@
 		power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&ehrpwm_tbclk 3>, <&k3_clks 43 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	ehrpwm4: pwm@3040000 {
@@ -909,6 +978,7 @@
 		power-domains = <&k3_pds 44 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&ehrpwm_tbclk 4>, <&k3_clks 44 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	ehrpwm5: pwm@3050000 {
@@ -918,6 +988,18 @@
 		power-domains = <&k3_pds 45 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&ehrpwm_tbclk 5>, <&k3_clks 45 0>;
 		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	timesync_router: pinctrl@a40000 {
+		compatible = "pinctrl-single";
+		reg = <0x0 0xa40000 0x0 0x800>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0x800007ff>;
+		status = "disabled";
 	};
 
 	icssg0: icssg@b000000 {
@@ -967,6 +1049,18 @@
 			};
 		};
 
+		icssg0_iep0: iep@2e000 {
+			compatible = "ti,am654-icss-iep";
+			reg = <0x2e000 0x1000>;
+			clocks = <&icssg0_iepclk_mux>;
+		};
+
+		icssg0_iep1: iep@2f000 {
+			compatible = "ti,am654-icss-iep";
+			reg = <0x2f000 0x1000>;
+			clocks = <&icssg0_iepclk_mux>;
+		};
+
 		icssg0_mii_rt: mii-rt@32000 {
 			compatible = "ti,pruss-mii", "syscon";
 			reg = <0x32000 0x100>;
@@ -977,6 +1071,11 @@
 			reg = <0x33000 0x1000>;
 		};
 
+		icssg0_pa_stats: pa-stats@2c000 {
+			compatible = "ti,pruss-pa-st", "syscon";
+			reg = <0x2c000 0x1000>;
+		};
+
 		icssg0_intc: interrupt-controller@20000 {
 			compatible = "ti,icssg-intc";
 			reg = <0x20000 0x2000>;
@@ -1003,6 +1102,9 @@
 			      <0x22400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am65x-pru0_0-fw";
+			interrupt-parent = <&icssg0_intc>;
+			interrupts = <16 2 2>;
+			interrupt-names = "vring";
 		};
 
 		rtu0_0: rtu@4000 {
@@ -1012,6 +1114,9 @@
 			      <0x23400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am65x-rtu0_0-fw";
+			interrupt-parent = <&icssg0_intc>;
+			interrupts = <20 4 4>;
+			interrupt-names = "vring";
 		};
 
 		tx_pru0_0: txpru@a000 {
@@ -1030,6 +1135,9 @@
 			      <0x24400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am65x-pru0_1-fw";
+			interrupt-parent = <&icssg0_intc>;
+			interrupts = <18 3 3>;
+			interrupt-names = "vring";
 		};
 
 		rtu0_1: rtu@6000 {
@@ -1039,6 +1147,9 @@
 			      <0x23c00 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am65x-rtu0_1-fw";
+			interrupt-parent = <&icssg0_intc>;
+			interrupts = <22 5 5>;
+			interrupt-names = "vring";
 		};
 
 		tx_pru0_1: txpru@c000 {
@@ -1058,6 +1169,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			bus_freq = <1000000>;
+			status = "disabled";
 		};
 	};
 
@@ -1108,6 +1220,18 @@
 			};
 		};
 
+		icssg1_iep0: iep@2e000 {
+			compatible = "ti,am654-icss-iep";
+			reg = <0x2e000 0x1000>;
+			clocks = <&icssg1_iepclk_mux>;
+		};
+
+		icssg1_iep1: iep@2f000 {
+			compatible = "ti,am654-icss-iep";
+			reg = <0x2f000 0x1000>;
+			clocks = <&icssg1_iepclk_mux>;
+		};
+
 		icssg1_mii_rt: mii-rt@32000 {
 			compatible = "ti,pruss-mii", "syscon";
 			reg = <0x32000 0x100>;
@@ -1118,6 +1242,11 @@
 			reg = <0x33000 0x1000>;
 		};
 
+		icssg1_pa_stats: pa-stats@2c000 {
+			compatible = "ti,pruss-pa-st", "syscon";
+			reg = <0x2c000 0x1000>;
+		};
+
 		icssg1_intc: interrupt-controller@20000 {
 			compatible = "ti,icssg-intc";
 			reg = <0x20000 0x2000>;
@@ -1144,6 +1273,9 @@
 			      <0x22400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am65x-pru1_0-fw";
+			interrupt-parent = <&icssg1_intc>;
+			interrupts = <16 2 2>;
+			interrupt-names = "vring";
 		};
 
 		rtu1_0: rtu@4000 {
@@ -1153,6 +1285,9 @@
 			      <0x23400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am65x-rtu1_0-fw";
+			interrupt-parent = <&icssg1_intc>;
+			interrupts = <20 4 4>;
+			interrupt-names = "vring";
 		};
 
 		tx_pru1_0: txpru@a000 {
@@ -1171,6 +1306,9 @@
 			      <0x24400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am65x-pru1_1-fw";
+			interrupt-parent = <&icssg1_intc>;
+			interrupts = <18 3 3>;
+			interrupt-names = "vring";
 		};
 
 		rtu1_1: rtu@6000 {
@@ -1180,6 +1318,9 @@
 			      <0x23c00 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am65x-rtu1_1-fw";
+			interrupt-parent = <&icssg1_intc>;
+			interrupts = <22 5 5>;
+			interrupt-names = "vring";
 		};
 
 		tx_pru1_1: txpru@c000 {
@@ -1199,6 +1340,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			bus_freq = <1000000>;
+			status = "disabled";
 		};
 	};
 
@@ -1249,6 +1391,18 @@
 			};
 		};
 
+		icssg2_iep0: iep@2e000 {
+			compatible = "ti,am654-icss-iep";
+			reg = <0x2e000 0x1000>;
+			clocks = <&icssg2_iepclk_mux>;
+		};
+
+		icssg2_iep1: iep@2f000 {
+			compatible = "ti,am654-icss-iep";
+			reg = <0x2f000 0x1000>;
+			clocks = <&icssg2_iepclk_mux>;
+		};
+
 		icssg2_mii_rt: mii-rt@32000 {
 			compatible = "ti,pruss-mii", "syscon";
 			reg = <0x32000 0x100>;
@@ -1259,6 +1413,11 @@
 			reg = <0x33000 0x1000>;
 		};
 
+		icssg2_pa_stats: pa-stats@2c000 {
+			compatible = "ti,pruss-pa-st", "syscon";
+			reg = <0x2c000 0x1000>;
+		};
+
 		icssg2_intc: interrupt-controller@20000 {
 			compatible = "ti,icssg-intc";
 			reg = <0x20000 0x2000>;
@@ -1285,6 +1444,9 @@
 			      <0x22400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am65x-pru2_0-fw";
+			interrupt-parent = <&icssg2_intc>;
+			interrupts = <16 2 2>;
+			interrupt-names = "vring";
 		};
 
 		rtu2_0: rtu@4000 {
@@ -1294,6 +1456,9 @@
 			      <0x23400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am65x-rtu2_0-fw";
+			interrupt-parent = <&icssg2_intc>;
+			interrupts = <20 4 4>;
+			interrupt-names = "vring";
 		};
 
 		tx_pru2_0: txpru@a000 {
@@ -1312,6 +1477,9 @@
 			      <0x24400 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am65x-pru2_1-fw";
+			interrupt-parent = <&icssg2_intc>;
+			interrupts = <18 3 3>;
+			interrupt-names = "vring";
 		};
 
 		rtu2_1: rtu@6000 {
@@ -1321,6 +1489,9 @@
 			      <0x23c00 0x100>;
 			reg-names = "iram", "control", "debug";
 			firmware-name = "am65x-rtu2_1-fw";
+			interrupt-parent = <&icssg2_intc>;
+			interrupts = <22 5 5>;
+			interrupt-names = "vring";
 		};
 
 		tx_pru2_1: txpru@c000 {
@@ -1340,6 +1511,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			bus_freq = <1000000>;
+			status = "disabled";
 		};
 	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -22,11 +22,12 @@
 
 	mcu_uart0: serial@40a00000 {
 		compatible = "ti,am654-uart";
-			reg = <0x00 0x40a00000 0x00 0x100>;
-			interrupts = <GIC_SPI 565 IRQ_TYPE_LEVEL_HIGH>;
-			clock-frequency = <96000000>;
-			current-speed = <115200>;
-			power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
+		reg = <0x00 0x40a00000 0x00 0x100>;
+		interrupts = <GIC_SPI 565 IRQ_TYPE_LEVEL_HIGH>;
+		clock-frequency = <96000000>;
+		current-speed = <115200>;
+		power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcu_ram: sram@41c00000 {
@@ -46,6 +47,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 114 1>;
 		power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcu_spi0: spi@40300000 {
@@ -56,6 +58,7 @@
 		power-domains = <&k3_pds 142 TI_SCI_PD_EXCLUSIVE>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		status = "disabled";
 	};
 
 	mcu_spi1: spi@40310000 {
@@ -66,6 +69,7 @@
 		power-domains = <&k3_pds 143 TI_SCI_PD_EXCLUSIVE>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		status = "disabled";
 	};
 
 	mcu_spi2: spi@40320000 {
@@ -76,6 +80,7 @@
 		power-domains = <&k3_pds 144 TI_SCI_PD_EXCLUSIVE>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		status = "disabled";
 	};
 
 	tscadc0: tscadc@40200000 {
@@ -172,6 +177,7 @@
 			     <GIC_SPI 545 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	m_can1: mcan@40568000 {
@@ -187,6 +193,7 @@
 			     <GIC_SPI 548 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	fss: fss@47000000 {
@@ -273,6 +280,7 @@
 			clocks = <&k3_clks 5 10>;
 			clock-names = "fck";
 			bus_freq = <1000000>;
+			status = "disabled";
 		};
 
 		cpts@3d000 {
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -54,6 +54,7 @@
 		clock-frequency = <48000000>;
 		current-speed = <115200>;
 		power-domains = <&k3_pds 150 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	wkup_i2c0: i2c@42120000 {
@@ -65,6 +66,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 115 1>;
 		power-domains = <&k3_pds 115 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	intr_wkup_gpio: interrupt-controller@42200000 {
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-base-board.dts	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,724 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * Base Board: https://www.ti.com/lit/zip/SPRR463
+ */
+
+/dts-v1/;
+
+#include "k3-am68-sk-som.dtsi"
+#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/phy/phy-cadence.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/mux/ti-serdes.h>
+
+/ {
+	compatible = "ti,am68-sk", "ti,j721s2";
+	model = "Texas Instruments AM68 SK";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	aliases {
+		serial2 = &main_uart8;
+		mmc1 = &main_sdhci1;
+		can0 = &mcu_mcan0;
+		can1 = &mcu_mcan1;
+		can2 = &main_mcan6;
+		can3 = &main_mcan7;
+	};
+
+	vusb_main: regulator-vusb-main5v0 {
+		/* USB MAIN INPUT 5V DC */
+		compatible = "regulator-fixed";
+		regulator-name = "vusb-main5v0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_3v3: regulator-vsys3v3 {
+		/* Output of LM5141 */
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vusb_main>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vdd_mmc1: regulator-sd {
+		/* Output of TPS22918 */
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_mmc1";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		enable-active-high;
+		vin-supply = <&vsys_3v3>;
+		gpio = <&exp1 8 GPIO_ACTIVE_HIGH>;
+	};
+
+	vdd_sd_dv: regulator-tlv71033 {
+		/* Output of TLV71033 */
+		compatible = "regulator-gpio";
+		regulator-name = "tlv71033";
+		pinctrl-names = "default";
+		pinctrl-0 = <&vdd_sd_dv_pins_default>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		vin-supply = <&vsys_3v3>;
+		gpios = <&main_gpio0 49 GPIO_ACTIVE_HIGH>;
+		states = <1800000 0x0>,
+			 <3300000 0x1>;
+	};
+
+	vsys_io_1v8: regulator-vsys-io-1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_io_1v8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_io_1v2: regulator-vsys-io-1v2 {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_io_1v2";
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	edp0_refclk: clock-edp0-refclk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <19200000>;
+	};
+
+	transceiver1: can-phy0 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	transceiver2: can-phy1 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	transceiver3: can-phy2 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	transceiver4: can-phy3 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	dp0_pwr_3v3: fixedregulator-dp0-pwr {
+		compatible = "regulator-fixed";
+		regulator-name = "dp0-pwr";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		pinctrl-names = "default";
+		gpio = <&exp2 2 GPIO_ACTIVE_HIGH>;     /*P0 - DP0_3V3 _EN */
+		enable-active-high;
+		regulator-always-on;
+	};
+
+
+	hdmi-connector {
+		compatible = "hdmi-connector";
+		label = "hdmi";
+		type = "a";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&hdmi_hpd_pins_default>;
+
+		ddc-i2c-bus = <&mcu_i2c1>;
+		digital;
+
+		/* HDMI_HPD */
+		hpd-gpios = <&main_gpio0 0 GPIO_ACTIVE_HIGH>;
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&tfp410_out>;
+			};
+		};
+	};
+
+	dvi-bridge {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "ti,tfp410";
+
+		/* HDMI_PDn */
+		powerdown-gpios = <&exp2 0 GPIO_ACTIVE_LOW>;
+
+		port@0 {
+			reg = <0>;
+
+			tfp410_in: endpoint {
+				remote-endpoint = <&dpi_out0>;
+				pclk-sample = <1>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+
+			tfp410_out: endpoint {
+				remote-endpoint = <&hdmi_connector_in>;
+			};
+		};
+	};
+};
+
+&main_pmx0 {
+	main_uart8_pins_default: main-uart8-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0d0, PIN_INPUT, 11) /* (AF26) SPI0_CS1.UART8_RXD */
+			J721S2_IOPAD(0x0d4, PIN_OUTPUT, 11) /* (AH27) SPI0_CLK.UART8_TXD */
+		>;
+	};
+
+	main_i2c0_pins_default: main-i2c0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0e0, PIN_INPUT, 0) /* (AH25) I2C0_SCL */
+			J721S2_IOPAD(0x0e4, PIN_INPUT, 0) /* (AE24) I2C0_SDA */
+		>;
+	};
+
+	main_i2c1_pins_default: main-i2c1-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0ac, PIN_INPUT, 13) /* (AC25) MCASP0_AXR15.I2C1_SCL */
+			J721S2_IOPAD(0x0b0, PIN_INPUT, 13) /* (AD26) MCASP1_AXR3.I2C1_SDA */
+		>;
+	};
+
+	main_mmc1_pins_default: main-mmc1-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x104, PIN_INPUT, 0) /* (P23) MMC1_CLK */
+			J721S2_IOPAD(0x108, PIN_INPUT, 0) /* (N24) MMC1_CMD */
+			J721S2_IOPAD(0x0fc, PIN_INPUT, 0) /* (M23) MMC1_DAT0 */
+			J721S2_IOPAD(0x0f8, PIN_INPUT, 0) /* (P24) MMC1_DAT1 */
+			J721S2_IOPAD(0x0f4, PIN_INPUT, 0) /* (R24) MMC1_DAT2 */
+			J721S2_IOPAD(0x0f0, PIN_INPUT, 0) /* (R22) MMC1_DAT3 */
+			J721S2_IOPAD(0x0e8, PIN_INPUT, 8) /* (AE25) TIMER_IO0.MMC1_SDCD */
+		>;
+	};
+
+	vdd_sd_dv_pins_default: vdd-sd-dv-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0c4, PIN_INPUT, 7) /* (AB26) ECAP0_IN_APWM_OUT.GPIO0_49 */
+		>;
+	};
+
+	main_usbss0_pins_default: main-usbss0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0ec, PIN_OUTPUT, 6) /* (AG25) TIMER_IO1.USB0_DRVVBUS */
+		>;
+	};
+
+	main_mcan6_pins_default: main-mcan6-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x098, PIN_INPUT, 0) /* (V25) MCASP0_AXR10.MCAN6_RX */
+			J721S2_IOPAD(0x094, PIN_INPUT, 0) /* (AA25) MCASP0_AXR9.MCAN6_TX */
+		>;
+	};
+
+	main_mcan7_pins_default: main-mcan7-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0a0, PIN_INPUT, 0) /* (AB25) MCASP0_AXR12.MCAN7_RX */
+			J721S2_IOPAD(0x09c, PIN_INPUT, 0) /* (T24) MCASP0_AXR11.MCAN7_TX */
+		>;
+	};
+
+	dss_vout0_pins_default: dss-vout0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x074, PIN_OUTPUT, 2) /* (R28) MCAN2_TX.VOUT0_DATA0 */
+			J721S2_IOPAD(0x070, PIN_OUTPUT, 2) /* (R27) MCAN1_RX.VOUT0_DATA1 */
+			J721S2_IOPAD(0x04c, PIN_OUTPUT, 2) /* (V27) MCASP1_AXR1.VOUT0_DATA10 */
+			J721S2_IOPAD(0x048, PIN_OUTPUT, 2) /* (AB27) MCASP0_AXR2.VOUT0_DATA11 */
+			J721S2_IOPAD(0x044, PIN_OUTPUT, 2) /* (Y26) MCASP0_AXR1.VOUT0_DATA12 */
+			J721S2_IOPAD(0x040, PIN_OUTPUT, 2) /* (AC28) MCASP0_AXR0.VOUT0_DATA13 */
+			J721S2_IOPAD(0x03c, PIN_OUTPUT, 2) /* (U27) MCASP0_AFSX.VOUT0_DATA14 */
+			J721S2_IOPAD(0x038, PIN_OUTPUT, 2) /* (AB28) MCASP0_ACLKX.VOUT0_DATA15 */
+			J721S2_IOPAD(0x0c8, PIN_OUTPUT, 2) /* (AD28) EXT_REFCLK1.VOUT0_DATA16 */
+			J721S2_IOPAD(0x030, PIN_OUTPUT, 2) /* (T26) GPIO0_12.VOUT0_DATA17 */
+			J721S2_IOPAD(0x02c, PIN_OUTPUT, 2) /* (V23) GPIO0_11.VOUT0_DATA18 */
+			J721S2_IOPAD(0x028, PIN_OUTPUT, 2) /* (AB24) MCAN16_RX.VOUT0_DATA19 */
+			J721S2_IOPAD(0x07c, PIN_OUTPUT, 2) /* (T27) MCASP0_AXR3.VOUT0_DATA2 */
+			J721S2_IOPAD(0x024, PIN_OUTPUT, 2) /* (Y28) MCAN16_TX.VOUT0_DATA20 */
+			J721S2_IOPAD(0x020, PIN_OUTPUT, 2) /* (AA23) MCAN15_RX.VOUT0_DATA21 */
+			J721S2_IOPAD(0x01c, PIN_OUTPUT, 2) /* (Y24) MCAN15_TX.VOUT0_DATA22 */
+			J721S2_IOPAD(0x018, PIN_OUTPUT, 2) /* (W23) MCAN14_RX.VOUT0_DATA23 */
+			J721S2_IOPAD(0x068, PIN_OUTPUT, 2) /* (U28) MCAN0_RX.VOUT0_DATA3 */
+			J721S2_IOPAD(0x064, PIN_OUTPUT, 2) /* (W28) MCAN0_TX.VOUT0_DATA4 */
+			J721S2_IOPAD(0x060, PIN_OUTPUT, 2) /* (AC27) MCASP2_AXR1.VOUT0_DATA5 */
+			J721S2_IOPAD(0x05c, PIN_OUTPUT, 2) /* (AA26) MCASP2_AXR0.VOUT0_DATA6 */
+			J721S2_IOPAD(0x058, PIN_OUTPUT, 2) /* (AA27) MCASP2_AFSX.VOUT0_DATA7 */
+			J721S2_IOPAD(0x054, PIN_OUTPUT, 2) /* (Y27) MCASP2_ACLKX.VOUT0_DATA8 */
+			J721S2_IOPAD(0x050, PIN_OUTPUT, 2) /* (W27) MCASP1_AXR2.VOUT0_DATA9 */
+			J721S2_IOPAD(0x084, PIN_OUTPUT, 2) /* (AA28) MCASP0_AXR5.VOUT0_DE */
+			J721S2_IOPAD(0x080, PIN_OUTPUT, 2) /* (U26) MCASP0_AXR4.VOUT0_HSYNC */
+			J721S2_IOPAD(0x078, PIN_OUTPUT, 2) /* (Y25) MCAN2_RX.VOUT0_PCLK */
+			J721S2_IOPAD(0x088, PIN_OUTPUT, 2) /* (AD27) MCASP0_AXR6.VOUT0_VP0_VSYNC */
+		>;
+	};
+
+	hdmi_hpd_pins_default: hdmi-hpd-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x000, PIN_INPUT, 7) /* (AG24) EXTINTN.GPIO0_0  */
+		>;
+	};
+
+	main_i2c4_pins_default: main-i2c4-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x010, PIN_INPUT_PULLUP, 8) /* (AF28) MCAN13_RX.I2C4_SDA */
+			J721S2_IOPAD(0x014, PIN_INPUT_PULLUP, 8) /* (AD25) MCAN14_TX.I2C4_SCL */
+		>;
+	};
+
+	rpi_header_gpio0_pins_default: rpi-header-gpio0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0a8, PIN_INPUT, 7) /* (U24)  MCASP0_AXR14.GPIO0_42 */
+			J721S2_IOPAD(0x090, PIN_INPUT, 7) /* (W24) MCASP0_AXR8.GPIO0_36 */
+			J721S2_IOPAD(0x0bc, PIN_INPUT, 7) /* (V28) MCASP1_AFSX.GPIO0_47 */
+			J721S2_IOPAD(0x06c, PIN_INPUT, 7) /* (V26) MCAN1_TX.GPIO0_27 */
+			J721S2_IOPAD(0x004, PIN_INPUT, 7) /* (W25) MCAN12_TX.GPIO0_1 */
+			J721S2_IOPAD(0x008, PIN_INPUT, 7) /* (AC24) MCAN12_RX.GPIO0_2 */
+			J721S2_IOPAD(0x0b8, PIN_INPUT, 7) /* (AA24) MCASP1_ACLKX.GPIO0_46 */
+			J721S2_IOPAD(0x00c, PIN_INPUT, 7) /* (AE28) MCAN13_TX.GPIO0_3 */
+			J721S2_IOPAD(0x034, PIN_INPUT, 7) /* (AD24) PMIC_WAKE0.GPIO0_13 */
+			J721S2_IOPAD(0x0a4, PIN_INPUT, 7) /* (T23) MCASP0_AXR13.GPIO0_41 */
+			J721S2_IOPAD(0x0c0, PIN_INPUT, 7) /* (T28) MCASP1_AXR0.GPIO0_48 */
+			J721S2_IOPAD(0x0b4, PIN_INPUT, 7) /* (U25) MCASP1_AXR4.GPIO0_45 */
+			J721S2_IOPAD(0x0cc, PIN_INPUT, 7) /* (AE27) SPI0_CS0.GPIO0_51 */
+			J721S2_IOPAD(0x08c, PIN_INPUT, 7) /* (T25) MCASP0_AXR7.GPIO0_35 */
+		>;
+	};
+};
+
+&wkup_pmx2 {
+	mcu_cpsw_pins_default: mcu-cpsw-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x02c, PIN_INPUT, 0) /* (B22) MCU_RGMII1_RD0 */
+			J721S2_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (B21) MCU_RGMII1_RD1 */
+			J721S2_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (C22) MCU_RGMII1_RD2 */
+			J721S2_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D23) MCU_RGMII1_RD3 */
+			J721S2_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (D22) MCU_RGMII1_RXC */
+			J721S2_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (E23) MCU_RGMII1_RX_CTL */
+			J721S2_WKUP_IOPAD(0x014, PIN_OUTPUT, 0) /* (F23) MCU_RGMII1_TD0 */
+			J721S2_WKUP_IOPAD(0x010, PIN_OUTPUT, 0) /* (G22) MCU_RGMII1_TD1 */
+			J721S2_WKUP_IOPAD(0x00c, PIN_OUTPUT, 0) /* (E21) MCU_RGMII1_TD2 */
+			J721S2_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E22) MCU_RGMII1_TD3 */
+			J721S2_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (F21) MCU_RGMII1_TXC */
+			J721S2_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (F22) MCU_RGMII1_TX_CTL */
+		>;
+	};
+
+	mcu_mdio_pins_default: mcu-mdio-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A21) MCU_MDIO0_MDC */
+			J721S2_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (A22) MCU_MDIO0_MDIO */
+		>;
+	};
+
+	mcu_mcan0_pins_default: mcu-mcan0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x054, PIN_INPUT, 0) /* (E28) MCU_MCAN0_RX */
+			J721S2_WKUP_IOPAD(0x050, PIN_OUTPUT, 0) /* (E27) MCU_MCAN0_TX */
+		>;
+	};
+
+	mcu_mcan1_pins_default: mcu-mcan1-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x06C, PIN_INPUT, 0) /* (F26) WKUP_GPIO0_5.MCU_MCAN1_RX */
+			J721S2_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /* (C23) WKUP_GPIO0_4.MCU_MCAN1_TX*/
+		>;
+	};
+
+	mcu_i2c1_pins_default: mcu-i2c1-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x078, PIN_INPUT, 0) /* (F24) WKUP_GPIO0_8.MCU_I2C1_SCL */
+			J721S2_WKUP_IOPAD(0x07c, PIN_INPUT, 0) /* (H26) WKUP_GPIO0_9.MCU_I2C1_SDA */
+		>;
+	};
+
+	mcu_rpi_header_gpio0_pins0_default: mcu-rpi-header-gpio0-pins0-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x118, PIN_INPUT, 7) /* (G25) WKUP_GPIO0_66 */
+			J721S2_WKUP_IOPAD(0x05C, PIN_INPUT, 7) /* (E24) MCU_SPI1_D0.WKUP_GPIO0_1 */
+			J721S2_WKUP_IOPAD(0x060, PIN_INPUT, 7) /* (C28) MCU_SPI1_D1.WKUP_GPIO0_2 */
+			J721S2_WKUP_IOPAD(0x058, PIN_INPUT, 7) /* (D26) MCU_SPI1_CLK.WKUP_GPIO0_0 */
+			J721S2_WKUP_IOPAD(0x094, PIN_INPUT, 7) /* (D25) MCU_SPI1_CS2.WKUP_GPIO0_15*/
+			J721S2_WKUP_IOPAD(0x0B8, PIN_INPUT, 7) /* (G27) WKUP_GPIO0_56 */
+			J721S2_WKUP_IOPAD(0x114, PIN_INPUT, 7) /* (J26) WKUP_GPIO0_57 */
+			J721S2_WKUP_IOPAD(0x11C, PIN_INPUT, 7) /* (J27) WKUP_GPIO0_67 */
+			J721S2_WKUP_IOPAD(0x064, PIN_INPUT, 7) /* (C27) MCU_SPI1_CS0.WKUP_GPIO0_3 */
+		>;
+	};
+};
+
+&wkup_pmx3 {
+	mcu_rpi_header_gpio0_pins1_default: mcu-rpi-header-gpio0-pins1-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x000, PIN_INPUT, 7) /* (K26) WKUP_GPIO0_49 */
+		>;
+	};
+};
+
+&main_gpio0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio0_pins_default>;
+};
+
+&main_gpio2 {
+	status = "disabled";
+};
+
+&main_gpio4 {
+	status = "disabled";
+};
+
+&main_gpio6 {
+	status = "disabled";
+};
+
+&wkup_gpio0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_rpi_header_gpio0_pins0_default>, <&mcu_rpi_header_gpio0_pins1_default>;
+};
+
+&wkup_gpio1 {
+	status = "disabled";
+};
+
+&wkup_uart0 {
+	status = "reserved";
+};
+
+&main_uart8 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_uart8_pins_default>;
+	/* Shared with TFA on this platform */
+	power-domains = <&k3_pds 357 TI_SCI_PD_SHARED>;
+};
+
+&main_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c0_pins_default>;
+	clock-frequency = <400000>;
+
+	exp1: gpio@21 {
+		compatible = "ti,tca6416";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names = " ", " ", " ", " ", " ",
+				  "BOARDID_EEPROM_WP", "CAN_STB", " ",
+				  "GPIO_uSD_PWR_EN", " ", "IO_EXP_PCIe1_M.2_RTSz",
+				  "IO_EXP_MCU_RGMII_RST#", " ", " ", " ", " ";
+	};
+};
+
+&main_i2c1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c1_pins_default>;
+	clock-frequency = <400000>;
+
+	exp3: gpio@20 {
+		compatible = "ti,tca6408";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names = "CSI_VIO_SEL", "CSI_SEL_FPC_EXPn",
+				"IO_EXP_CSI2_EXP_RSTz","CSI0_B_GPIO1",
+				"CSI1_B_GPIO1";
+	};
+};
+
+&mcu_i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_i2c1_pins_default>;
+	/* i2c1 is used for DVI DDC, so we need to use 100kHz */
+	clock-frequency = <100000>;
+
+	exp2: gpio@20 {
+		compatible = "ti,tca6408";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names = "HDMI_PDn","HDMI_LS_OE",
+				"DP0_3V3_EN","eDP_ENABLE";
+	};
+
+	dsi_edp_bridge: dsi-edp-bridge@2c {
+		compatible = "ti,sn65dsi86";
+		reg = <0x2c>;
+
+		clock-names = "refclk";
+		clocks = <&edp0_refclk>;
+
+		enable-gpios = <&exp2 3 GPIO_ACTIVE_HIGH>;
+
+		vpll-supply = <&vsys_io_1v8>;
+		vccio-supply = <&vsys_io_1v8>;
+		vcca-supply = <&vsys_io_1v2>;
+		vcc-supply = <&vsys_io_1v2>;
+
+		aux-bus {
+			panel {
+				compatible = "ti,panel-edp";
+				power-supply = <&dp0_pwr_3v3>;
+
+				port {
+					dp0_panel_in: endpoint {
+						remote-endpoint = <&dp0_out>;
+					};
+				};
+			};
+		};
+
+		dsi_edp_bridge_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				dp0_in: endpoint {
+					remote-endpoint = <&dsi0_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				dp0_out: endpoint {
+					remote-endpoint = <&dp0_panel_in>;
+				};
+			};
+		};
+	};
+};
+
+&main_i2c4 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c4_pins_default>;
+	clock-frequency = <400000>;
+};
+
+&main_sdhci0 {
+	/* Unused */
+	status = "disabled";
+};
+
+&main_sdhci1 {
+	/* SD card */
+	pinctrl-0 = <&main_mmc1_pins_default>;
+	pinctrl-names = "default";
+	disable-wp;
+	vmmc-supply = <&vdd_mmc1>;
+	vqmmc-supply = <&vdd_sd_dv>;
+};
+
+&mcu_cpsw {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
+};
+
+&davinci_mdio {
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+};
+
+&cpsw_port1 {
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&phy0>;
+};
+
+&serdes_ln_ctrl {
+	idle-states = <J721S2_SERDES0_LANE0_PCIE1_LANE0>, <J721S2_SERDES0_LANE1_PCIE1_LANE1>,
+		      <J721S2_SERDES0_LANE2_USB_SWAP>, <J721S2_SERDES0_LANE3_USB>;
+};
+
+&serdes_refclk {
+	clock-frequency = <100000000>;
+};
+
+&torrent_phy_dp {
+	status = "disabled";
+};
+
+&serdes0 {
+	status = "okay";
+
+	serdes0_pcie_link: phy@0 {
+		reg = <0>;
+		cdns,num-lanes = <2>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_PCIE>;
+		resets = <&serdes_wiz0 1>, <&serdes_wiz0 2>;
+	};
+
+	serdes0_usb_link: phy@2 {
+		status = "okay";
+		reg = <2>;
+		cdns,num-lanes = <1>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_USB3>;
+		resets = <&serdes_wiz0 3>;
+	};
+};
+
+&usb_serdes_mux {
+	idle-states = <0>; /* USB0 to SERDES lane 2 */
+};
+
+&usbss0 {
+	status = "okay";
+	pinctrl-0 = <&main_usbss0_pins_default>;
+	pinctrl-names = "default";
+	ti,vbus-divider;
+};
+
+&usb0 {
+	dr_mode = "host";
+	maximum-speed = "super-speed";
+	phys = <&serdes0_usb_link>;
+	phy-names = "cdns3,usb3-phy";
+};
+
+&pcie1_rc {
+	status = "okay";
+	reset-gpios = <&exp1 10 GPIO_ACTIVE_HIGH>;
+	phys = <&serdes0_pcie_link>;
+	phy-names = "pcie-phy";
+	num-lanes = <2>;
+};
+
+&dss {
+
+	status = "okay";
+
+	pinctrl-names = "default";
+	pinctrl-0 = <&dss_vout0_pins_default>;
+
+	/*
+	 * These clock assignments are chosen to enable the following outputs:
+	 *
+	 * VP1 - DPI0
+	 */
+	assigned-clocks = <&k3_clks 158 5>;
+	assigned-clock-parents = <&k3_clks 158 7>;
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@2 {
+		reg = <2>;
+		dpi0_out: endpoint {
+			remote-endpoint = <&dsi0_in>;
+		};
+	};
+
+	/* HDMI */
+	port@1 {
+		reg = <1>;
+
+		dpi_out0: endpoint {
+			remote-endpoint = <&tfp410_in>;
+		};
+	};
+};
+
+&ti_csi2rx0 {
+	status = "okay";
+	/* MIPI-CSI Connector */
+};
+
+&ti_csi2rx1 {
+	status = "okay";
+	/* MIPI-CSI Connector */
+};
+
+&dphy_rx0 {
+	status = "okay";
+};
+
+&dphy_rx1 {
+	status = "okay";
+};
+
+&dphy_tx0 {
+	status = "okay";
+};
+
+&dsi0 {
+	status = "okay";
+};
+
+&dsi0_ports {
+
+	port@0 {
+		reg = <0>;
+		dsi0_out: endpoint {
+			remote-endpoint = <&dp0_in>;
+		};
+	};
+
+	port@1 {
+		reg = <1>;
+		dsi0_in: endpoint {
+			remote-endpoint = <&dpi0_out>;
+		};
+	};
+};
+
+&mcu_mcan0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mcan0_pins_default>;
+	phys = <&transceiver1>;
+};
+
+&mcu_mcan1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mcan1_pins_default>;
+	phys = <&transceiver2>;
+};
+
+&main_mcan6 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcan6_pins_default>;
+	phys = <&transceiver3>;
+};
+
+&main_mcan7 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcan7_pins_default>;
+	phys = <&transceiver4>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am68-sk-bb-csi2-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-am68-sk-bb-csi2-ov5640.dtso
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-bb-csi2-ov5640.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-bb-csi2-ov5640.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * LI OV5640 MIPI Camera module.
+ *
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&wkup_pmx2 {
+	csi2_exp_refclk_pins_default: csi2-exp-refclk-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x084, PIN_OUTPUT, 6) /* (F25) WKUP_GPIO0_11.MCU_CLKOUT0 */
+		>;
+	};
+};
+
+&k3_clks {
+	/* Confiure AUDIO_EXT_REFCLK2 pin as output */
+	pinctrl-names = "default";
+	pinctrl-0 = <&csi2_exp_refclk_pins_default>;
+};
+
+&main_i2c1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	i2c-switch@70 {
+		compatible = "nxp,pca9543";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x70>;
+
+		/* CAM0 I2C */
+		ti_cam0_i2c: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			ov5640: camera@3c {
+				compatible = "ovti,ov5640";
+				reg = <0x3c>;
+
+				powerdown-gpios = <&exp3 2 GPIO_ACTIVE_LOW>;
+
+				/* MCU_CLKOUT0 WKUP_GPIO0_11 (F25) */
+				clocks = <&k3_clks 157 221>;
+				clock-names = "xclk";
+
+				/* HSDIV4_16FFT_MCU_2_HSDIVOUT0_CLK10 -> REFCLK2 */
+				assigned-clocks = <&k3_clks 157 221>;
+				assigned-clock-parents = <&k3_clks 157 223>;
+				assigned-clock-rates = <25000000>;
+
+				port {
+					csi2_cam0: endpoint {
+						remote-endpoint = <&csi2rx0_in_sensor>;
+						clock-lanes = <0>;
+						data-lanes = <1 2>;
+					};
+				};
+			};
+		};
+
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am68-sk-bb-rpi-cam-imx219.dtso b/arch/arm64/boot/dts/ti/k3-am68-sk-bb-rpi-cam-imx219.dtso
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-bb-rpi-cam-imx219.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-bb-rpi-cam-imx219.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for RPi Camera V2.1 (Sony IMX219) interfaced with CSI2 on AM68-SK board.
+ * https://datasheets.raspberrypi.org/camera/camera-v2-schematic.pdf
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&{/} {
+	clk_imx219_fixed: imx219-xclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+	};
+};
+
+&exp3 {
+	p01-hog {
+		/* CSI_MUX_SEL_2 */
+		gpio-hog;
+		gpios = <1 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "CSI_MUX_SEL_2";
+	};
+};
+
+&main_i2c1 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	i2c-switch@70 {
+		compatible = "nxp,pca9543";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x70>;
+
+		i2c-alias-pool = /bits/ 16 <0x10 0x11>;
+
+		/* CAM0 I2C */
+		cam0_i2c: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			imx219_0: imx219_0@10 {
+				compatible = "sony,imx219";
+				reg = <0x10>;
+
+				clocks = <&clk_imx219_fixed>;
+				clock-names = "xclk";
+
+				reset-gpios = <&exp3 3 GPIO_ACTIVE_HIGH>;
+
+				port {
+					csi2_cam0: endpoint {
+						remote-endpoint = <&csi2rx0_in_sensor>;
+						link-frequencies = /bits/ 64 <456000000>;
+						clock-lanes = <0>;
+						data-lanes = <1 2>;
+					};
+				};
+			};
+		};
+
+		/* CAM1 I2C */
+		cam1_i2c: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			imx219_1: imx219_1@10 {
+				compatible = "sony,imx219";
+				reg = <0x10>;
+
+				clocks = <&clk_imx219_fixed>;
+				clock-names = "xclk";
+
+				reset-gpios = <&exp3 4 GPIO_ACTIVE_HIGH>;
+
+				port {
+					csi2_cam1: endpoint {
+						remote-endpoint = <&csi2rx1_in_sensor>;
+						link-frequencies = /bits/ 64 <456000000>;
+						clock-lanes = <0>;
+						data-lanes = <1 2>;
+					};
+				};
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
+
+&csi1_port0 {
+	status = "okay";
+	csi2rx1_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam1>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am68-sk-fpdlink-fusion.dtso b/arch/arm64/boot/dts/ti/k3-am68-sk-fpdlink-fusion.dtso
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-fpdlink-fusion.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-fpdlink-fusion.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay for Fusion (FPD-Link III) board on AM68 SK
+ * https://svtronics.com/portfolio/evm577pfusion-v1-0-fusion/
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	clk_fusion_25M_fixed: fixed-clock-25M {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+&main_i2c1 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	i2c-switch@70 {
+		compatible = "nxp,pca9543";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x70>;
+
+		cam0_i2c: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			deser@3d {
+				compatible = "ti,ds90ub960-q1";
+				reg = <0x3d>;
+				clocks = <&clk_fusion_25M_fixed>;
+				clock-names = "refclk";
+				i2c-alias-pool = <0x4a 0x4b 0x4c 0x4d 0x4e 0x4f>;
+
+				ds90ub960_0_ports: ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* CSI-2 TX*/
+					port@4 {
+						reg = <4>;
+						ds90ub960_0_csi_out: endpoint {
+							clock-lanes = <0>;
+							data-lanes = <1 2 3 4>;
+							link-frequencies = /bits/ 64 <800000000>;
+							remote-endpoint = <&csi2_phy0>;
+						};
+					};
+				};
+
+				ds90ub960_0_links: links {
+					#address-cells = <1>;
+					#size-cells = <0>;
+				};
+			};
+
+			deser@36 {
+				compatible = "ti,ds90ub960-q1";
+				reg       = <0x36>;
+				clocks = <&clk_fusion_25M_fixed>;
+				clock-names = "refclk";
+				i2c-alias-pool = <0x5a 0x5b 0x5c 0x5d 0x5e 0x5f>;
+
+				ds90ub960_1_ports: ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* CSI-2 TX*/
+					port@4 {
+						reg = <4>;
+						ds90ub960_1_csi_out: endpoint {
+							clock-lanes = <0>;
+							data-lanes = <1 2 3 4>;
+							link-frequencies = /bits/ 64 <800000000>;
+							remote-endpoint = <&csi2_phy1>;
+						};
+					};
+				};
+
+				ds90ub960_1_links: links {
+					#address-cells = <1>;
+					#size-cells = <0>;
+				};
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2_phy0: endpoint {
+		remote-endpoint = <&ds90ub960_0_csi_out>;
+		clock-lanes = <0>;
+		data-lanes = <1 2 3 4>;
+		link-frequencies = /bits/ 64 <800000000>;
+	};
+};
+
+&csi1_port0 {
+	status = "okay";
+
+	csi2_phy1: endpoint {
+		remote-endpoint = <&ds90ub960_1_csi_out>;
+		clock-lanes = <0>;
+		data-lanes = <1 2 3 4>;
+		link-frequencies = /bits/ 64 <800000000>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am68-sk-rpi-hdr-ehrpwm.dtso b/arch/arm64/boot/dts/ti/k3-am68-sk-rpi-hdr-ehrpwm.dtso
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-rpi-hdr-ehrpwm.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-rpi-hdr-ehrpwm.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for enabling EHRPWMs on RPi expansion header on AM68 SK board.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+	rpi_header_gpio0_pins_default: rpi-header-gpio0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0a8, PIN_INPUT, 7) /* (U24)  MCASP0_AXR14.GPIO0_42 */
+			J721S2_IOPAD(0x090, PIN_INPUT, 7) /* (W24) MCASP0_AXR8.GPIO0_36 */
+			J721S2_IOPAD(0x0bc, PIN_INPUT, 7) /* (V28)  MCASP1_AFSX.GPIO0_47 */
+			J721S2_IOPAD(0x06c, PIN_INPUT, 7) /* (V26)  MCAN1_TX.GPIO0_27 */
+			J721S2_IOPAD(0x004, PIN_INPUT, 7) /* (W25)  MCAN12_TX.GPIO0_1 */
+			J721S2_IOPAD(0x008, PIN_INPUT, 7) /* (AC24) MCAN12_RX.GPI0_2 */
+			J721S2_IOPAD(0x0b8, PIN_INPUT, 7) /* (AA24) MCASP1_ACLKX.GPIO0_46 */
+			J721S2_IOPAD(0x00c, PIN_INPUT, 7) /* (AE28) MCAN13_TX.GPIO0_3 */
+			J721S2_IOPAD(0x034, PIN_INPUT, 7) /* (AD24) PMIC_WAKE0.GPIO0_13 */
+			J721S2_IOPAD(0x0c0, PIN_INPUT, 7) /* (T28)  MCASP1_AXR0.GPIO0_48 */
+			J721S2_IOPAD(0x0b4, PIN_INPUT, 7) /* (U25)  MCASP1_AXR4.GPIO0_45 */
+		>;
+	};
+
+	rpi_header_ehrpwm0_pins_default: rpi-header-ehrpwm0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0cc, PIN_INPUT, 5) /* (AE27) SPI0_CS0.GPIO0_51.EHRPWM0_A */
+		>;
+	};
+
+	rpi_header_ehrpwm3_pins_default: rpi-header-ehrpwm3-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x08c, PIN_INPUT, 9) /* (T25)  RGMII1_TD0.GPIO0_35.EHRPWM3_A */
+		>;
+	};
+
+	rpi_header_ehrpwm4_pins_default: rpi-header-ehrpwm4-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0a4, PIN_INPUT, 9) /* (T23)  RGMII1_RD2.GPIO0_41.EHRPWM4_A */
+		>;
+	};
+};
+
+&main_ehrpwm0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm0_pins_default>;
+	status = "okay";
+};
+
+&main_ehrpwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm3_pins_default>;
+	status = "okay";
+};
+
+&main_ehrpwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm4_pins_default>;
+	status = "okay";
+};
+
+&main_gpio0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio0_pins_default>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am68-sk-som-ddr-mem-carveout.dtso b/arch/arm64/boot/dts/ti/k3-am68-sk-som-ddr-mem-carveout.dtso
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-som-ddr-mem-carveout.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-som-ddr-mem-carveout.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for DDR careveout memory nodes for R5F and C71x DSPs.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	dma_buf_phys {
+		compatible = "ti,dma-buf-phys";
+	};
+};
+
+&reserved_memory {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa0000000 0x00 0x100000>;
+		no-map;
+	};
+
+	mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa0100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa1000000 0x00 0x100000>;
+		no-map;
+	};
+
+	mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa1100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa2000000 0x00 0x100000>;
+		no-map;
+	};
+
+	main_r5fss0_core0_memory_region: r5f-memory@a2100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa2100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa3000000 0x00 0x100000>;
+		no-map;
+	};
+
+	main_r5fss0_core1_memory_region: r5f-memory@a3100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa3100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa4000000 0x00 0x100000>;
+		no-map;
+	};
+
+	main_r5fss1_core0_memory_region: r5f-memory@a4100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa4100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa5000000 0x00 0x100000>;
+		no-map;
+	};
+
+	main_r5fss1_core1_memory_region: r5f-memory@a5100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa5100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	c71_0_dma_memory_region: c71-dma-memory@a6000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa6000000 0x00 0x100000>;
+		no-map;
+	};
+
+	c71_0_memory_region: c71-memory@a6100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa6100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	c71_1_dma_memory_region: c71-dma-memory@a7000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa7000000 0x00 0x100000>;
+		no-map;
+	};
+
+	c71_1_memory_region: c71-memory@a7100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa7100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	rtos_ipc_memory_region: ipc-memories@a8000000 {
+		reg = <0x00 0xa8000000 0x00 0x01c00000>;
+		alignment = <0x1000>;
+		no-map;
+	};
+};
+
+&mailbox0_cluster0 {
+	interrupts = <436>;
+
+	mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster1 {
+	interrupts = <432>;
+
+	mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster2 {
+	interrupts = <428>;
+
+	mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster3 {
+	status = "disabled";
+};
+
+&mailbox0_cluster4 {
+	interrupts = <420>;
+
+	mbox_c71_0: mbox-c71-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_c71_1: mbox-c71-1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster5 {
+	status = "disabled";
+};
+
+&mailbox0_cluster6 {
+	status = "disabled";
+};
+
+&mailbox0_cluster7 {
+	status = "disabled";
+};
+
+&mailbox0_cluster8 {
+	status = "disabled";
+};
+
+&mailbox0_cluster9 {
+	status = "disabled";
+};
+
+&mailbox0_cluster10 {
+	status = "disabled";
+};
+
+&mailbox0_cluster11 {
+	status = "disabled";
+};
+
+&mailbox1_cluster0 {
+	status = "disabled";
+};
+
+&mailbox1_cluster1 {
+	status = "disabled";
+};
+
+&mailbox1_cluster2 {
+	status = "disabled";
+};
+
+&mailbox1_cluster3 {
+	status = "disabled";
+};
+
+&mailbox1_cluster4 {
+	status = "disabled";
+};
+
+&mailbox1_cluster5 {
+	status = "disabled";
+};
+
+&mailbox1_cluster6 {
+	status = "disabled";
+};
+
+&mailbox1_cluster7 {
+	status = "disabled";
+};
+
+&mailbox1_cluster8 {
+	status = "disabled";
+};
+
+&mailbox1_cluster9 {
+	status = "disabled";
+};
+
+&mailbox1_cluster10 {
+	status = "disabled";
+};
+
+&mailbox1_cluster11 {
+	status = "disabled";
+};
+
+&mcu_r5fss0_core0 {
+	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
+	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
+			<&mcu_r5fss0_core0_memory_region>;
+};
+
+&mcu_r5fss0_core1 {
+	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>;
+	memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
+			<&mcu_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss0_core0 {
+	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>;
+	memory-region = <&main_r5fss0_core0_dma_memory_region>,
+			<&main_r5fss0_core0_memory_region>;
+};
+
+&main_r5fss0_core1 {
+	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>;
+	memory-region = <&main_r5fss0_core1_dma_memory_region>,
+			<&main_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss1_core0 {
+	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>;
+	memory-region = <&main_r5fss1_core0_dma_memory_region>,
+			<&main_r5fss1_core0_memory_region>;
+};
+
+&main_r5fss1_core1 {
+	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>;
+	memory-region = <&main_r5fss1_core1_dma_memory_region>,
+			<&main_r5fss1_core1_memory_region>;
+};
+
+&c71_0 {
+	mboxes = <&mailbox0_cluster4 &mbox_c71_0>;
+	memory-region = <&c71_0_dma_memory_region>,
+			<&c71_0_memory_region>;
+};
+
+&c71_1 {
+	mboxes = <&mailbox0_cluster4 &mbox_c71_1>;
+	memory-region = <&c71_1_dma_memory_region>,
+			<&c71_1_memory_region>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi
--- a/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am68-sk-som.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+
+#include "k3-j721s2.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+	memory@80000000 {
+		device_type = "memory";
+		/* 16 GB RAM */
+		reg = <0x00 0x80000000 0x00 0x80000000>,
+		      <0x08 0x80000000 0x03 0x80000000>;
+	};
+
+	reserved_memory: reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		secure_ddr: optee@9e800000 {
+			reg = <0x00 0x9e800000 0x00 0x01800000>;
+			no-map;
+		};
+
+		 /* global cma region */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x00 0x38000000>;
+			linux,cma-default;
+		};
+	};
+};
+
+&wkup_pmx0 {
+	mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (D19) MCU_OSPI0_CLK */
+			J721S2_WKUP_IOPAD(0x02c, PIN_OUTPUT, 0) /* (F15) MCU_OSPI0_CSn0 */
+			J721S2_WKUP_IOPAD(0x00c, PIN_INPUT, 0) /* (C19) MCU_OSPI0_D0 */
+			J721S2_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (F16) MCU_OSPI0_D1 */
+			J721S2_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (G15) MCU_OSPI0_D2 */
+			J721S2_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (F18) MCU_OSPI0_D3 */
+			J721S2_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (E19) MCU_OSPI0_D4 */
+			J721S2_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (G19) MCU_OSPI0_D5 */
+			J721S2_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (F19) MCU_OSPI0_D6 */
+			J721S2_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (F20) MCU_OSPI0_D7 */
+			J721S2_WKUP_IOPAD(0x008, PIN_INPUT, 0) /* (E18) MCU_OSPI0_DQS */
+			J721S2_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (E20) MCU_OSPI0_LBCLKO */
+		>;
+	};
+};
+
+&wkup_pmx2 {
+	wkup_i2c0_pins_default: wkup-i2c0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x098, PIN_INPUT, 0) /* (H24) WKUP_I2C0_SCL */
+			J721S2_WKUP_IOPAD(0x09c, PIN_INPUT, 0) /* (H27) WKUP_I2C0_SDA */
+		>;
+	};
+};
+
+&wkup_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_i2c0_pins_default>;
+	clock-frequency = <400000>;
+
+	eeprom@51 {
+		/* AT24C512C-MAHM-T */
+	compatible = "atmel,24c512";
+		reg = <0x51>;
+	};
+};
+
+&ospi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_fss0_ospi0_pins_default>;
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+		spi-max-frequency = <25000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <4>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "ospi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fc0000 {
+				label = "ospi.phypattern";
+				reg = <0x3fc0000 0x40000>;
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am69-sk-csi2-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-am69-sk-csi2-ov5640.dtso
--- a/arch/arm64/boot/dts/ti/k3-am69-sk-csi2-ov5640.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am69-sk-csi2-ov5640.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for OV5640 Camera module on MIPI CSI connector for AM69 SK board.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&wkup_pmx2 {
+	csi2_exp_refclk_pins_default: csi2-exp-refclk-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x084, PIN_OUTPUT, 6) /* (M38) WKUP_GPIO0_11.MCU_CLKOUT0 */
+		>;
+	};
+};
+
+&k3_clks {
+	pinctrl-names = "default";
+	pinctrl-0 = <&csi2_exp_refclk_pins_default>;
+};
+
+&exp2 {
+	p01-hog{
+		/* P01 - CSI_MUX_SEL_2 */
+		gpio-hog;
+		gpios = <1 GPIO_ACTIVE_LOW>;
+		output-high;
+		line-name = "CSI_MUX_SEL_2";
+	};
+};
+
+&pca9543 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	i2c-alias-pool = /bits/ 16 <0x3c 0x3d>;
+
+	/* CAM0 I2C */
+	i2c@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0>;
+
+		camera@3c {
+			compatible = "ovti,ov5640";
+			reg = <0x3c>;
+
+			/* MCU_CLKOUT0 WKUP_GPIO0_11 (M38) */
+			clocks = <&k3_clks 157 174>;
+			clock-names = "xclk";
+			powerdown-gpios = <&exp2 2 GPIO_ACTIVE_LOW>;
+
+			/* HSDIV4_16FFT_MCU_2_HSDIVOUT0_CLK10 -> REFCLK2 */
+			assigned-clocks = <&k3_clks 157 174>;
+			assigned-clock-parents = <&k3_clks 157 176>;
+			assigned-clock-rates = <25000000>;
+
+			port {
+				csi2_cam0: endpoint {
+					remote-endpoint = <&csi2rx0_in_sensor>;
+					clock-lanes = <0>;
+					data-lanes = <1 2>;
+				};
+			};
+		};
+	};
+
+	/* CAM1 I2C */
+	i2c@1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <1>;
+
+		camera@3c {
+			compatible = "ovti,ov5640";
+			reg = <0x3c>;
+
+			/* MCU_CLKOUT0 WKUP_GPIO0_11 (M38) */
+			clocks = <&k3_clks 157 174>;
+			clock-names = "xclk";
+			powerdown-gpios = <&exp2 2 GPIO_ACTIVE_LOW>;
+
+			/* HSDIV4_16FFT_MCU_2_HSDIVOUT0_CLK10 -> REFCLK2 */
+			assigned-clocks = <&k3_clks 157 174>;
+			assigned-clock-parents = <&k3_clks 157 176>;
+			assigned-clock-rates = <25000000>;
+
+			port {
+				csi2_cam1: endpoint {
+					remote-endpoint = <&csi2rx2_in_sensor>;
+					clock-lanes = <0>;
+					data-lanes = <1 2>;
+				};
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
+
+&csi2_port0 {
+	status = "okay";
+
+	csi2rx2_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam1>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
+
+&ti_csi2rx0 {
+        status = "okay";
+};
+
+&ti_csi2rx2 {
+        status = "okay";
+};
+
+&dphy_rx0 {
+        status = "okay";
+};
+
+&dphy_rx2 {
+        status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am69-sk-csi2-rpi-cam-imx219.dtso b/arch/arm64/boot/dts/ti/k3-am69-sk-csi2-rpi-cam-imx219.dtso
--- a/arch/arm64/boot/dts/ti/k3-am69-sk-csi2-rpi-cam-imx219.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am69-sk-csi2-rpi-cam-imx219.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,126 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay for RPi Camera V2.1 (Sony IMX219) interfaced with CSI2 on AM69-SK board.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * Schematics: https://datasheets.raspberrypi.com/camera/camera-v2-schematics.pdf
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_imx219_fixed: imx219-xclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+	};
+};
+
+&exp2 {
+	p01-hog{
+		/* P01 - CSI_MUX_SEL_2 */
+		gpio-hog;
+		gpios = <1 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "CSI_MUX_SEL_2";
+	};
+};
+
+&pca9543 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	i2c-alias-pool = /bits/ 16 <0x10 0x11>;
+
+	/* CAM0 I2C */
+	i2c@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0>;
+
+		imx219_0: sensor@10 {
+			compatible = "sony,imx219";
+			reg = <0x10>;
+
+			clocks = <&clk_imx219_fixed>;
+			clock-names = "xclk";
+
+			reset-gpios = <&exp2 3 GPIO_ACTIVE_HIGH>;
+
+			port {
+				csi2_cam0: endpoint {
+					remote-endpoint = <&csi2rx0_in_sensor>;
+					link-frequencies = /bits/ 64 <456000000>;
+					clock-lanes = <0>;
+					data-lanes = <1 2>;
+				};
+			};
+		};
+	};
+
+	/* CAM1 I2C */
+	i2c@1 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <1>;
+
+		imx219_1: sensor@10 {
+			compatible = "sony,imx219";
+			reg = <0x10>;
+
+			clocks = <&clk_imx219_fixed>;
+			clock-names = "xclk";
+
+			reset-gpios = <&exp2 4 GPIO_ACTIVE_HIGH>;
+
+			port {
+				csi2_cam1: endpoint {
+					remote-endpoint = <&csi2rx1_in_sensor>;
+					link-frequencies = /bits/ 64 <456000000>;
+					clock-lanes = <0>;
+					data-lanes = <1 2>;
+				};
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
+
+&csi1_port0 {
+	status = "okay";
+	csi2rx1_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam1>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
+
+&ti_csi2rx0 {
+        status = "okay";
+};
+
+&ti_csi2rx1 {
+        status = "okay";
+};
+
+&dphy_rx0 {
+        status = "okay";
+};
+
+&dphy_rx1 {
+        status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am69-sk-ddr-mem-carveout.dtso b/arch/arm64/boot/dts/ti/k3-am69-sk-ddr-mem-carveout.dtso
--- a/arch/arm64/boot/dts/ti/k3-am69-sk-ddr-mem-carveout.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am69-sk-ddr-mem-carveout.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,421 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for DDR careveout memory nodes for R5F and C71x DSPs.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	dma-buf-phys {
+		compatible = "ti,dma-buf-phys";
+	};
+};
+
+&reserved_memory {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa0000000 0x00 0x100000>;
+		no-map;
+	};
+
+	mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa0100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa1000000 0x00 0x100000>;
+		no-map;
+	};
+
+	mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa1100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa2000000 0x00 0x100000>;
+		no-map;
+	};
+
+	main_r5fss0_core0_memory_region: r5f-memory@a2100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa2100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa3000000 0x00 0x100000>;
+		no-map;
+	};
+
+	main_r5fss0_core1_memory_region: r5f-memory@a3100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa3100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa4000000 0x00 0x100000>;
+		no-map;
+	};
+
+	main_r5fss1_core0_memory_region: r5f-memory@a4100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa4100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa5000000 0x00 0x100000>;
+		no-map;
+	};
+
+	main_r5fss1_core1_memory_region: r5f-memory@a5100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa5100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	main_r5fss2_core0_dma_memory_region: r5f-dma-memory@a6000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa6000000 0x00 0x100000>;
+		no-map;
+	};
+
+	main_r5fss2_core0_memory_region: r5f-memory@a6100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa6100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	main_r5fss2_core1_dma_memory_region: r5f-dma-memory@a7000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa7000000 0x00 0x100000>;
+		no-map;
+	};
+
+	main_r5fss2_core1_memory_region: r5f-memory@a7100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa7100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	c71_0_dma_memory_region: c71-dma-memory@a8000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa8000000 0x00 0x100000>;
+		no-map;
+	};
+
+	c71_0_memory_region: c71-memory@a8100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa8100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	c71_1_dma_memory_region: c71-dma-memory@a9000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa9000000 0x00 0x100000>;
+		no-map;
+	};
+
+	c71_1_memory_region: c71-memory@a9100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa9100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	c71_2_dma_memory_region: c71-dma-memory@aa000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xaa000000 0x00 0x100000>;
+		no-map;
+	};
+
+	c71_2_memory_region: c71-memory@aa100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xaa100000 0x00 0xf00000>;
+		no-map;
+	};
+
+	c71_3_dma_memory_region: c71-dma-memory@ab000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xab000000 0x00 0x100000>;
+		no-map;
+	};
+
+	c71_3_memory_region: c71-memory@ab100000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xab100000 0x00 0xf00000>;
+		no-map;
+	};
+};
+
+&mailbox0_cluster0 {
+	status = "okay";
+	interrupts = <436>;
+	interrupt-parent = <&main_navss_intr>;
+
+	mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster1 {
+	status = "okay";
+	interrupts = <432>;
+	interrupt-parent = <&main_navss_intr>;
+
+	mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster2 {
+	status = "okay";
+	interrupts = <428>;
+	interrupt-parent = <&main_navss_intr>;
+
+	mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster3 {
+	status = "okay";
+	interrupts = <424>;
+	interrupt-parent = <&main_navss_intr>;
+
+	mbox_main_r5fss2_core0: mbox-main-r5fss2-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_main_r5fss2_core1: mbox-main-r5fss2-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster4 {
+	status = "okay";
+	interrupts = <420>;
+	interrupt-parent = <&main_navss_intr>;
+
+	mbox_c71_0: mbox-c71-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_c71_1: mbox-c71-1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster5 {
+	status = "okay";
+	interrupts = <416>;
+	interrupt-parent = <&main_navss_intr>;
+
+	mbox_c71_2: mbox-c71-2 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_c71_3: mbox-c71-3 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster6 {
+	status = "disabled";
+};
+
+&mailbox0_cluster7 {
+	status = "disabled";
+};
+
+&mailbox0_cluster8 {
+	status = "disabled";
+};
+
+&mailbox0_cluster9 {
+	status = "disabled";
+};
+
+&mailbox0_cluster10 {
+	status = "disabled";
+};
+
+&mailbox0_cluster11 {
+	status = "disabled";
+};
+
+&mailbox1_cluster0 {
+	status = "disabled";
+};
+
+&mailbox1_cluster1 {
+	status = "disabled";
+};
+
+&mailbox1_cluster2 {
+	status = "disabled";
+};
+
+&mailbox1_cluster3 {
+	status = "disabled";
+};
+
+&mailbox1_cluster4 {
+	status = "disabled";
+};
+
+&mailbox1_cluster5 {
+	status = "disabled";
+};
+
+&mailbox1_cluster6 {
+	status = "disabled";
+};
+
+&mailbox1_cluster7 {
+	status = "disabled";
+};
+
+&mailbox1_cluster8 {
+	status = "disabled";
+};
+
+&mailbox1_cluster9 {
+	status = "disabled";
+};
+
+&mailbox1_cluster10 {
+	status = "disabled";
+};
+
+&mailbox1_cluster11 {
+	status = "disabled";
+};
+
+&mcu_r5fss0_core0 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
+	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
+			<&mcu_r5fss0_core0_memory_region>;
+};
+
+&mcu_r5fss0_core1 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>;
+	memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
+			<&mcu_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss0_core0 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>;
+	memory-region = <&main_r5fss0_core0_dma_memory_region>,
+			<&main_r5fss0_core0_memory_region>;
+};
+
+&main_r5fss0_core1 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>;
+	memory-region = <&main_r5fss0_core1_dma_memory_region>,
+			<&main_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss1_core0 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>;
+	memory-region = <&main_r5fss1_core0_dma_memory_region>,
+			<&main_r5fss1_core0_memory_region>;
+};
+
+&main_r5fss1_core1 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>;
+	memory-region = <&main_r5fss1_core1_dma_memory_region>,
+			<&main_r5fss1_core1_memory_region>;
+};
+
+&main_r5fss2_core0 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster3 &mbox_main_r5fss2_core0>;
+	memory-region = <&main_r5fss2_core0_dma_memory_region>,
+			<&main_r5fss2_core0_memory_region>;
+};
+
+&main_r5fss2_core1 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster3 &mbox_main_r5fss2_core1>;
+	memory-region = <&main_r5fss2_core1_dma_memory_region>,
+			<&main_r5fss2_core1_memory_region>;
+};
+
+&c71_0 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster4 &mbox_c71_0>;
+	memory-region = <&c71_0_dma_memory_region>,
+			<&c71_0_memory_region>;
+};
+
+&c71_1 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster4 &mbox_c71_1>;
+	memory-region = <&c71_1_dma_memory_region>,
+			<&c71_1_memory_region>;
+};
+
+&c71_2 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster5 &mbox_c71_2>;
+	memory-region = <&c71_2_dma_memory_region>,
+			<&c71_2_memory_region>;
+};
+
+&c71_3 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster5 &mbox_c71_3>;
+	memory-region = <&c71_3_dma_memory_region>,
+			<&c71_3_memory_region>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am69-sk.dts b/arch/arm64/boot/dts/ti/k3-am69-sk.dts
--- a/arch/arm64/boot/dts/ti/k3-am69-sk.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am69-sk.dts	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,850 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022-2023 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * Design Files: https://www.ti.com/lit/zip/SPRR466
+ * TRM: https://www.ti.com/lit/zip/spruj52
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-j784s4.dtsi"
+
+/ {
+	compatible = "ti,am69-sk", "ti,j784s4";
+	model = "Texas Instruments AM69 SK";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	aliases {
+		serial2 = &main_uart8;
+		mmc0 = &main_sdhci0;
+		mmc1 = &main_sdhci1;
+		i2c0 = &main_i2c0;
+		i2c1 = &main_i2c1;
+		ethernet0 = &mcu_cpsw_port1;
+		can0 = &mcu_mcan0;
+		can1 = &mcu_mcan1;
+		can2 = &main_mcan6;
+		can3 = &main_mcan7;
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		/* 32G RAM */
+		reg = <0x00 0x80000000 0x00 0x80000000>,
+		      <0x08 0x80000000 0x07 0x80000000>;
+	};
+
+	reserved_memory: reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* global cma region */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x00 0x70000000>;
+			linux,cma-default;
+		};
+
+		secure_ddr: optee@9e800000 {
+			reg = <0x00 0x9e800000 0x00 0x01800000>;
+			no-map;
+		};
+	};
+
+	vusb_main: regulator-vusb-main5v0 {
+		/* USB MAIN INPUT 5V DC */
+		compatible = "regulator-fixed";
+		regulator-name = "vusb-main5v0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_5v0: regulator-vsys5v0 {
+		/* Output of LM61460 */
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_5v0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&vusb_main>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_3v3: regulator-vsys3v3 {
+		/* Output of LM5143 */
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&vusb_main>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vdd_mmc1: regulator-sd {
+		/* Output of TPS22918 */
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_mmc1";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		enable-active-high;
+		vin-supply = <&vsys_3v3>;
+		gpio = <&exp1 2 GPIO_ACTIVE_HIGH>;
+	};
+
+	vdd_sd_dv: regulator-tlv71033 {
+		/* Output of TLV71033 */
+		compatible = "regulator-gpio";
+		regulator-name = "tlv71033";
+		pinctrl-names = "default";
+		pinctrl-0 = <&vdd_sd_dv_pins_default>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		vin-supply = <&vsys_5v0>;
+		gpios = <&main_gpio0 49 GPIO_ACTIVE_HIGH>;
+		states = <1800000 0x0>,
+			 <3300000 0x1>;
+	};
+
+	transceiver1: can-phy0 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	transceiver2: can-phy1 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	transceiver3: can-phy2 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	transceiver4: can-phy3 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+
+	dp0_pwr_3v3: regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "dp0-pwr";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&dp_pwr_en_pins_default>;
+		gpio = <&main_gpio0 4 0>;	/* DP0_3V3 _EN */
+		enable-active-high;
+	};
+
+	dp0: connector {
+		compatible = "dp-connector";
+		label = "DP0";
+		type = "full-size";
+		dp-pwr-supply = <&dp0_pwr_3v3>;
+
+		port {
+			dp0_connector_in: endpoint {
+				remote-endpoint = <&dp0_out>;
+			};
+		};
+	};
+
+	hdmi-connector {
+		compatible = "hdmi-connector";
+		label = "hdmi";
+		type = "a";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&hdmi_hpd_pins_default>;
+
+		ddc-i2c-bus = <&mcu_i2c1>;
+		digital;
+
+		/* HDMI_HPD */
+		hpd-gpios = <&main_gpio0 0 GPIO_ACTIVE_HIGH>;
+
+		port {
+			hdmi_connector_in: endpoint {
+				remote-endpoint = <&tfp410_out>;
+			};
+		};
+	};
+
+	dvi-bridge {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "ti,tfp410";
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&hdmi_pdn_pins_default>;
+
+		/* HDMI_PDn */
+		powerdown-gpios = <&wkup_gpio0 14 GPIO_ACTIVE_LOW>;
+
+		port@0 {
+			reg = <0>;
+
+			tfp410_in: endpoint {
+				remote-endpoint = <&dpi1_out0>;
+				pclk-sample = <1>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+
+			tfp410_out: endpoint {
+				remote-endpoint = <&hdmi_connector_in>;
+			};
+		};
+	};
+};
+
+&main_pmx0 {
+	main_uart8_pins_default: main-uart8-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0d0, PIN_INPUT, 11) /* (AP38) SPI0_CS1.UART8_RXD */
+			J784S4_IOPAD(0x0d4, PIN_OUTPUT, 11) /* (AN38) SPI0_CLK.UART8_TXD */
+		>;
+	};
+
+	main_i2c0_pins_default: main-i2c0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0e0, PIN_INPUT_PULLUP, 0) /* (AN36) I2C0_SCL */
+			J784S4_IOPAD(0x0e4, PIN_INPUT_PULLUP, 0) /* (AP37) I2C0_SDA */
+		>;
+	};
+
+	main_i2c1_pins_default: main-i2c1-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0ac, PIN_INPUT_PULLUP, 13) /* (AE34) MCASP0_AXR15.I2C1_SCL */
+			J784S4_IOPAD(0x0b0, PIN_INPUT_PULLUP, 13) /* (AL33) MCASP1_AXR3.I2C1_SDA */
+		>;
+	};
+
+	main_mmc1_pins_default: main-mmc1-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x104, PIN_INPUT, 0) /* (AB38) MMC1_CLK */
+			J784S4_IOPAD(0x108, PIN_INPUT, 0) /* (AB36) MMC1_CMD */
+			J784S4_IOPAD(0x100, PIN_INPUT, 0) /* (No Pin) MMC1_CLKLB */
+			J784S4_IOPAD(0x0fc, PIN_INPUT, 0) /* (AA33) MMC1_DAT0 */
+			J784S4_IOPAD(0x0f8, PIN_INPUT, 0) /* (AB34) MMC1_DAT1 */
+			J784S4_IOPAD(0x0f4, PIN_INPUT, 0) /* (AA32) MMC1_DAT2 */
+			J784S4_IOPAD(0x0f0, PIN_INPUT, 0) /* (AC38) MMC1_DAT3 */
+			J784S4_IOPAD(0x0e8, PIN_INPUT, 8) /* (AR38) TIMER_IO0.MMC1_SDCD */
+		>;
+	};
+
+	vdd_sd_dv_pins_default: vdd-sd-dv-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0C4, PIN_INPUT, 7) /* (AD36) ECAP0_IN_APWM_OUT.GPIO0_49 */
+		>;
+	};
+
+	main_usbss0_pins_default: main-usbss0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0ec, PIN_OUTPUT, 6) /* (AN37) TIMER_IO1.USB0_DRVVBUS */
+		>;
+	};
+
+	main_mcan6_pins_default: main-mcan6-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x098, PIN_INPUT, 0) /* (AH36) MCAN6_RX */
+			J784S4_IOPAD(0x094, PIN_OUTPUT, 0) /* (AG35) MCAN6_TX */
+		>;
+	};
+
+	main_mcan7_pins_default: main-mcan7-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0A0, PIN_INPUT, 0) /* (AD34) MCAN7_RX */
+			J784S4_IOPAD(0x09C, PIN_OUTPUT, 0) /* (AF35) MCAN7_TX */
+		>;
+	};
+
+	dp0_pins_default: dp0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x014, PIN_INPUT, 13) /* (AG33) MCAN14_TX.DP0_HPD */
+		>;
+	};
+
+	dp_pwr_en_pins_default: dp-pwr-en-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x010, PIN_INPUT, 7) /* (AH33) MCAN13_RX.GPIO0_4 */
+		>;
+	};
+
+	dss_vout0_pins_default: dss-vout0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x074, PIN_OUTPUT, 2) /* (AC33) MCAN2_TX.VOUT0_DATA0 */
+			J784S4_IOPAD(0x070, PIN_OUTPUT, 2) /* (AH38) MCAN1_RX.VOUT0_DATA1 */
+			J784S4_IOPAD(0x07c, PIN_OUTPUT, 2) /* (AJ38) MCASP0_AXR3.VOUT0_DATA2 */
+			J784S4_IOPAD(0x068, PIN_OUTPUT, 2) /* (AE38) MCAN0_RX.VOUT0_DATA3 */
+			J784S4_IOPAD(0x064, PIN_OUTPUT, 2) /* (AF38) MCAN0_TX.VOUT0_DATA4 */
+			J784S4_IOPAD(0x060, PIN_OUTPUT, 2) /* (AE36) MCASP2_AXR1.VOUT0_DATA5 */
+			J784S4_IOPAD(0x05c, PIN_OUTPUT, 2) /* (AC36) MCASP2_AXR0.VOUT0_DATA6 */
+			J784S4_IOPAD(0x058, PIN_OUTPUT, 2) /* (AE37) MCASP2_AFSX.VOUT0_DATA7 */
+			J784S4_IOPAD(0x054, PIN_OUTPUT, 2) /* (AD37) MCASP2_ACLKX.VOUT0_DATA8 */
+			J784S4_IOPAD(0x050, PIN_OUTPUT, 2) /* (AC37) MCASP1_AXR2.VOUT0_DATA9 */
+			J784S4_IOPAD(0x04c, PIN_OUTPUT, 2) /* (AC32) MCASP1_AXR1.VOUT0_DATA10 */
+			J784S4_IOPAD(0x048, PIN_OUTPUT, 2) /* (AK33) MCASP0_AXR2.VOUT0_DATA11 */
+			J784S4_IOPAD(0x044, PIN_OUTPUT, 2) /* (AG37) MCASP0_AXR1.VOUT0_DATA12 */
+			J784S4_IOPAD(0x040, PIN_OUTPUT, 2) /* (AF37) MCASP0_AXR0.VOUT0_DATA13 */
+			J784S4_IOPAD(0x03c, PIN_OUTPUT, 2) /* (AK38) MCASP0_AFSX.VOUT0_DATA14 */
+			J784S4_IOPAD(0x038, PIN_OUTPUT, 2) /* (AK35) MCASP0_ACLKX.VOUT0_DATA15 */
+			J784S4_IOPAD(0x0c8, PIN_OUTPUT, 2) /* (AJ32) EXT_REFCLK1.VOUT0_DATA16 */
+			J784S4_IOPAD(0x030, PIN_OUTPUT, 2) /* (AK37) GPIO0_12.VOUT0_DATA17 */
+			J784S4_IOPAD(0x02c, PIN_OUTPUT, 2) /* (AL32) GPIO0_11.VOUT0_DATA18 */
+			J784S4_IOPAD(0x028, PIN_OUTPUT, 2) /* (AE33) MCAN16_RX.VOUT0_DATA19 */
+			J784S4_IOPAD(0x024, PIN_OUTPUT, 2) /* (AH34) MCAN16_TX.VOUT0_DATA20 */
+			J784S4_IOPAD(0x020, PIN_OUTPUT, 2) /* (AJ35) MCAN15_RX.VOUT0_DATA21 */
+			J784S4_IOPAD(0x01c, PIN_OUTPUT, 2) /* (AG34) MCAN15_TX.VOUT0_DATA22 */
+			J784S4_IOPAD(0x018, PIN_OUTPUT, 2) /* (AK36) MCAN14_RX.VOUT0_DATA23 */
+			J784S4_IOPAD(0x084, PIN_OUTPUT, 2) /* (AG38) MCASP0_AXR5.VOUT0_DE */
+			J784S4_IOPAD(0x080, PIN_OUTPUT, 2) /* (AK34) MCASP0_AXR4.VOUT0_HSYNC */
+			J784S4_IOPAD(0x078, PIN_OUTPUT, 2) /* (AH37) MCAN2_RX.VOUT0_PCLK */
+			J784S4_IOPAD(0x088, PIN_OUTPUT, 2) /* (AF36) MCASP0_AXR6.VOUT0_VSYNC */
+		>;
+	};
+
+	hdmi_hpd_pins_default: hdmi-hpd-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x000, PIN_INPUT, 7) /* (AN35) EXTINTN.GPIO0_0 */
+		>;
+	};
+
+	rpi_header_gpio0_pins_default: rpi-header-gpio0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0BC, PIN_INPUT, 7) /* (AD33) MCASP1_AFSX.GPIO0_47 */
+			J784S4_IOPAD(0x06C, PIN_INPUT, 7) /* (AJ37) MCASP4_AFSX.GPIO0_27 */
+			J784S4_IOPAD(0x0B4, PIN_INPUT, 7) /* (AL34) MCASP1_AXR4.GPIO0_45 */
+			J784S4_IOPAD(0x0C0, PIN_INPUT, 7) /* (AD38) MCASP1_AXR0.GPIO0_48 */
+			J784S4_IOPAD(0x00C, PIN_INPUT, 7) /* (AF33) MCAN13_TX.GPIO0_3 */
+			J784S4_IOPAD(0x0B8, PIN_INPUT, 7) /* (AC34) MCASP1_ACLKX.GPIO0_46 */
+			J784S4_IOPAD(0x090, PIN_INPUT, 7) /* (AC35) MCASP0_AXR8.GPIO0_36 */
+			J784S4_IOPAD(0x0A8, PIN_INPUT, 7) /* (AF34) MCASP0_AXR14.GPIO0_42 */
+			J784S4_IOPAD(0x0A4, PIN_INPUT, 7) /* (AJ36) MCASP0_AXR13.GPIO0_41 */
+			J784S4_IOPAD(0x034, PIN_INPUT, 7) /* (AJ34) PMIC_WAKE0n.GPIO0_13 */
+			J784S4_IOPAD(0x0CC, PIN_INPUT, 7) /* (AM37) SPI0_CS0.GPIO0_51 */
+			J784S4_IOPAD(0x08C, PIN_INPUT, 7) /* (AE35) MCASP0_AXR7.GPIO0_35 */
+			J784S4_IOPAD(0x008, PIN_INPUT, 7) /* (AJ33) MCAN12_RX.GPIO0_2 */
+			J784S4_IOPAD(0x004, PIN_INPUT, 7) /* (AG36) MCAN12_TX.GPIO0_1 */
+		>;
+	};
+};
+
+&wkup_pmx0 {
+	mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (E32) MCU_OSPI0_CLK */
+			J784S4_WKUP_IOPAD(0x02c, PIN_OUTPUT, 0) /* (A32) MCU_OSPI0_CSn0 */
+			J784S4_WKUP_IOPAD(0x00c, PIN_INPUT, 0) /* (B33) MCU_OSPI0_D0 */
+			J784S4_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (B32) MCU_OSPI0_D1 */
+			J784S4_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (C33) MCU_OSPI0_D2 */
+			J784S4_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (C35) MCU_OSPI0_D3 */
+			J784S4_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (D33) MCU_OSPI0_D4 */
+			J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D34) MCU_OSPI0_D5 */
+			J784S4_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (E34) MCU_OSPI0_D6 */
+			J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (E33) MCU_OSPI0_D7 */
+			J784S4_WKUP_IOPAD(0x008, PIN_INPUT, 0) /* (C34) MCU_OSPI0_DQS */
+		>;
+	};
+};
+
+&wkup_pmx2 {
+	mcu_cpsw_pins_default: mcu-cpsw-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x02c, PIN_INPUT, 0) /* (A35) MCU_RGMII1_RD0 */
+			J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (B36) MCU_RGMII1_RD1 */
+			J784S4_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (C36) MCU_RGMII1_RD2 */
+			J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D36) MCU_RGMII1_RD3 */
+			J784S4_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (B37) MCU_RGMII1_RXC */
+			J784S4_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (C37) MCU_RGMII1_RX_CTL */
+			J784S4_WKUP_IOPAD(0x014, PIN_OUTPUT, 0) /* (D37) MCU_RGMII1_TD0 */
+			J784S4_WKUP_IOPAD(0x010, PIN_OUTPUT, 0) /* (D38) MCU_RGMII1_TD1 */
+			J784S4_WKUP_IOPAD(0x00c, PIN_OUTPUT, 0) /* (E37) MCU_RGMII1_TD2 */
+			J784S4_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E38) MCU_RGMII1_TD3 */
+			J784S4_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (E36) MCU_RGMII1_TXC */
+			J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (C38) MCU_RGMII1_TX_CTL */
+		>;
+	};
+
+	mcu_mdio_pins_default: mcu-mdio-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A36) MCU_MDIO0_MDC */
+			J784S4_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (B35) MCU_MDIO0_MDIO */
+		>;
+	};
+
+	mcu_i2c0_pins_default: mcu-i2c0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x0a0, PIN_INPUT_PULLUP, 0) /* (M35) MCU_I2C0_SCL */
+			J784S4_WKUP_IOPAD(0x0a4, PIN_INPUT_PULLUP, 0) /* (G34) MCU_I2C0_SDA */
+		>;
+	};
+
+	mcu_i2c1_pins_default: mcu-i2c1-pins-default {
+		pinctrl-single,pins = <
+			/* (L35) WKUP_GPIO0_8.MCU_I2C1_SCL */
+			J784S4_WKUP_IOPAD(0x078, PIN_INPUT_PULLUP, 0)
+			/* (L34) WKUP_GPIO0_9.MCU_I2C1_SDA */
+			J784S4_WKUP_IOPAD(0x07c, PIN_INPUT_PULLUP, 0)
+		>;
+	};
+
+	hdmi_pdn_pins_default: hdmi-pdn-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x090, PIN_INPUT, 7) /* (H37) WKUP_GPIO0_14 */
+		>;
+	};
+
+	mcu_mcan0_pins_default: mcu-mcan0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x054, PIN_INPUT, 0) /* (F38) MCU_MCAN0_RX */
+			J784S4_WKUP_IOPAD(0x050, PIN_OUTPUT, 0) /* (K33) MCU_MCAN0_TX */
+		>;
+	};
+
+	mcu_mcan1_pins_default: mcu-mcan1-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x06c, PIN_INPUT, 0) /* (K36) WKUP_GPIO0_5.MCU_MCAN1_RX */
+			J784S4_WKUP_IOPAD(0x068, PIN_OUTPUT, 0)/* (H35) WKUP_GPIO0_4.MCU_MCAN1_TX */
+		>;
+	};
+
+	mcu_rpi_hdr1_gpio0_pins_default: mcu-rpi-hdr1-gpio0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x118, PIN_INPUT, 7) /* (N34) WKUP_GPIO0_66 */
+			J784S4_WKUP_IOPAD(0x05c, PIN_INPUT, 7) /* (J34) WKUP_GPIO0_1 */
+			J784S4_WKUP_IOPAD(0x060, PIN_INPUT, 7) /* (J35) WKUP_GPIO0_2 */
+			J784S4_WKUP_IOPAD(0x058, PIN_INPUT, 7) /* (H38) WKUP_GPIO0_0 */
+			J784S4_WKUP_IOPAD(0x0b8, PIN_INPUT, 7) /* (M37) WKUP_GPIO0_56 */
+			J784S4_WKUP_IOPAD(0x114, PIN_INPUT, 7) /* (M36) WKUP_GPIO0_57 */
+			J784S4_WKUP_IOPAD(0x094, PIN_INPUT, 7) /* (K37) WKUP_GPIO0_15 */
+			J784S4_WKUP_IOPAD(0x064, PIN_INPUT, 7) /* (J36) WKUP_GPIO0_3 */
+			J784S4_WKUP_IOPAD(0x11c, PIN_INPUT, 7) /* (M34) WKUP_GPIO0_67 */
+		>;
+	};
+};
+
+&wkup_pmx3 {
+	mcu_rpi_hdr2_gpio0_pins_default: mcu-rpi-hdr2-gpio0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x0, PIN_INPUT, 7) /* (M33) WKUP_GPIO0_49 */
+		>;
+	};
+};
+
+&main_uart8 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_uart8_pins_default>;
+};
+
+&main_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c0_pins_default>;
+	clock-frequency = <400000>;
+
+	exp1: gpio@21 {
+		compatible = "ti,tca6416";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names	= "BOARDID_EEPROM_WP", "CAN_STB", "GPIO_uSD_PWR_EN",
+				"IO_EXP_MCU_RGMII_RST#", "IO_EXP_PCIe0_4L_PERST#",
+				"IO_EXP_PCIe1_M.2_RTSz", "IO_EXP_PCIe3_M.2_RTSz",
+				"PM_INA_BUS_EN", "ENET1_EXP_PWRDN", "EXP1_ENET_RSTz",
+				"ENET1_I2CMUX_SEL", "PCIe0_CLKREQ#", "PCIe1_M.2_CLKREQ#",
+				"PCIe3_M2_CLKREQ#", "PCIe0_PRSNT2#_1", "PCIe0_PRSNT2#_2";
+	};
+};
+
+&main_i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c1_pins_default>;
+	clock-frequency = <400000>;
+
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	exp2: gpio@21 {
+		compatible = "ti,tca6408";
+		reg = <0x21>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names = "CSI_VIO_SEL", "CSI_MUX_SEL_2", "CSI2_RSTz",
+				"IO_EXP_CAM0_GPIO1", "IO_EXP_CAM1_GPIO1";
+	};
+
+	pca9543: i2c-mux@70 {
+		compatible = "nxp,pca9543";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x70>;
+	};
+};
+
+&mcu_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_i2c0_pins_default>;
+	clock-frequency = <400000>;
+};
+
+&mcu_i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_i2c1_pins_default>;
+	clock-frequency = <100000>;
+};
+
+&ospi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_fss0_ospi0_pins_default>;
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+		spi-max-frequency = <25000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <4>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "ospi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fc0000 {
+				label = "ospi.phypattern";
+				reg = <0x3fc0000 0x40000>;
+			};
+		};
+	};
+};
+
+&fss {
+	status = "okay";
+};
+
+&main_sdhci0 {
+	/* eMMC */
+	status = "okay";
+	non-removable;
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
+	no-mmc-hs400;
+};
+
+&main_sdhci1 {
+	/* SD card */
+	status = "okay";
+	pinctrl-0 = <&main_mmc1_pins_default>;
+	pinctrl-names = "default";
+	disable-wp;
+	vmmc-supply = <&vdd_mmc1>;
+	vqmmc-supply = <&vdd_sd_dv>;
+};
+
+&wkup_gpio0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_rpi_hdr1_gpio0_pins_default>, <&mcu_rpi_hdr2_gpio0_pins_default>;
+};
+
+&wkup_gpio_intr {
+	status = "okay";
+};
+
+&main_gpio0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio0_pins_default>;
+};
+
+&mcu_cpsw {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_cpsw_pins_default>, <&mcu_mdio_pins_default>;
+};
+
+&davinci_mdio {
+	mcu_phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+};
+
+&mcu_cpsw_port1 {
+	status = "okay";
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&mcu_phy0>;
+};
+
+&serdes_wiz4 {
+	status = "okay";
+};
+
+&serdes4 {
+	status = "okay";
+	serdes4_dp_link: phy@0 {
+		reg = <0>;
+		cdns,num-lanes = <4>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_DP>;
+		resets = <&serdes_wiz4 1>, <&serdes_wiz4 2>,
+			 <&serdes_wiz4 3>, <&serdes_wiz4 4>;
+	};
+};
+
+&dss {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&dss_vout0_pins_default>;
+	assigned-clocks = <&k3_clks 218 2>,
+			  <&k3_clks 218 5>;
+	assigned-clock-parents = <&k3_clks 218 3>,
+				 <&k3_clks 218 7>;
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* DP */
+	port@0 {
+		reg = <0>;
+		dpi0_out: endpoint {
+			remote-endpoint = <&dp0_in>;
+		};
+	};
+
+	/* HDMI */
+	port@1 {
+		reg = <1>;
+		dpi1_out0: endpoint {
+			remote-endpoint = <&tfp410_in>;
+		};
+	};
+};
+
+&mhdp {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&dp0_pins_default>;
+	phys = <&serdes4_dp_link>;
+	phy-names = "dpphy";
+};
+
+&dp0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@0 {
+		reg = <0>;
+		dp0_in: endpoint {
+			remote-endpoint = <&dpi0_out>;
+		};
+	};
+
+	port@4 {
+		reg = <4>;
+		dp0_out: endpoint {
+			remote-endpoint = <&dp0_connector_in>;
+		};
+	};
+};
+
+&serdes_refclk {
+	clock-frequency = <100000000>;
+};
+
+&serdes_ln_ctrl {
+	idle-states = <J784S4_SERDES0_LANE0_PCIE1_LANE0>, <J784S4_SERDES0_LANE1_PCIE1_LANE1>,
+		      <J784S4_SERDES0_LANE2_PCIE3_LANE0>, <J784S4_SERDES0_LANE3_USB>,
+			<J784S4_SERDES1_LANE0_PCIE0_LANE0>, <J784S4_SERDES1_LANE1_PCIE0_LANE1>,
+			<J784S4_SERDES1_LANE2_PCIE0_LANE2>, <J784S4_SERDES1_LANE3_PCIE0_LANE3>;
+};
+
+&serdes_wiz0 {
+	status = "okay";
+};
+
+&serdes0 {
+	status = "okay";
+	serdes0_pcie_link: phy@0 {
+		reg = <0>;
+		cdns,num-lanes = <3>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_PCIE>;
+		resets = <&serdes_wiz0 1>, <&serdes_wiz0 2>, <&serdes_wiz0 3>;
+	};
+	serdes0_usb_link: phy@3 {
+		reg = <3>;
+		cdns,num-lanes = <1>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_USB3>;
+		resets = <&serdes_wiz0 4>;
+	};
+};
+
+&serdes1 {
+	status = "okay";
+	serdes1_pcie_link: phy@0 {
+		reg = <0>;
+		cdns,num-lanes = <4>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_PCIE>;
+		resets = <&serdes_wiz1 1>, <&serdes_wiz1 2>, <&serdes_wiz1 3>, <&serdes_wiz1 4>;
+	};
+};
+
+&serdes_wiz1 {
+	status = "okay";
+};
+
+&pcie0_rc {
+	status = "okay";
+	reset-gpios = <&exp1 4 GPIO_ACTIVE_HIGH>;
+	phys = <&serdes1_pcie_link>;
+	phy-names = "pcie-phy";
+};
+
+&pcie0_ep {
+	status = "disabled";
+	phys = <&serdes1_pcie_link>;
+	phy-names = "pcie-phy";
+};
+
+&pcie1_rc {
+	status = "okay";
+	reset-gpios = <&exp1 5 GPIO_ACTIVE_HIGH>;
+	phys = <&serdes0_pcie_link>;
+	phy-names = "pcie-phy";
+	num-lanes = <2>;
+};
+
+&pcie1_ep {
+	status = "disabled";
+	phys = <&serdes0_pcie_link>;
+	phy-names = "pcie-phy";
+	num-lanes = <2>;
+};
+
+&pcie3_rc {
+	status = "okay";
+	reset-gpios = <&exp1 6 GPIO_ACTIVE_HIGH>;
+	phys = <&serdes0_pcie_link>;
+	phy-names = "pcie-phy";
+	num-lanes = <1>;
+};
+
+&pcie3_ep {
+	status = "disabled";
+	phys = <&serdes0_pcie_link>;
+	phy-names = "pcie-phy";
+	num-lanes = <1>;
+};
+
+&usb_serdes_mux {
+	idle-states = <0>; /* USB0 to SERDES0 */
+};
+
+&usbss0 {
+	status = "okay";
+	pinctrl-0 = <&main_usbss0_pins_default>;
+	pinctrl-names = "default";
+	ti,vbus-divider;
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+	maximum-speed = "super-speed";
+	phys = <&serdes0_usb_link>;
+	phy-names = "cdns3,usb3-phy";
+};
+
+&mcu_mcan0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mcan0_pins_default>;
+	phys = <&transceiver1>;
+};
+
+&mcu_mcan1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mcan1_pins_default>;
+	phys = <&transceiver2>;
+};
+
+&main_mcan6 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcan6_pins_default>;
+	phys = <&transceiver3>;
+};
+
+&main_mcan7 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcan7_pins_default>;
+	phys = <&transceiver4>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am69-sk-fpdlink-fusion.dtso b/arch/arm64/boot/dts/ti/k3-am69-sk-fpdlink-fusion.dtso
--- a/arch/arm64/boot/dts/ti/k3-am69-sk-fpdlink-fusion.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am69-sk-fpdlink-fusion.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay for Fusion (FPD-Link III) board on AM69 SK
+ * https://svtronics.com/portfolio/evm577pfusion-v1-0-fusion/
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	clk_fusion_25M_fixed: fixed-clock-25M {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+&pca9543 {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+	cam0_i2c: i2c@0 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0>;
+
+		deser@3d {
+			compatible = "ti,ds90ub960-q1";
+			reg = <0x3d>;
+			clocks = <&clk_fusion_25M_fixed>;
+			clock-names = "refclk";
+			i2c-alias-pool = <0x4a 0x4b 0x4c 0x4d 0x4e 0x4f>;
+
+			ds90ub960_0_ports: ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				/* CSI-2 TX*/
+				port@4 {
+					reg = <4>;
+					ds90ub960_0_csi_out: endpoint {
+						clock-lanes = <0>;
+						data-lanes = <1 2 3 4>;
+						link-frequencies = /bits/ 64 <800000000>;
+						remote-endpoint = <&csi2_phy0>;
+					};
+				};
+			};
+
+			ds90ub960_0_links: links {
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+		};
+
+		deser@36 {
+			compatible = "ti,ds90ub960-q1";
+			reg       = <0x36>;
+			clocks = <&clk_fusion_25M_fixed>;
+			clock-names = "refclk";
+			i2c-alias-pool = <0x5a 0x5b 0x5c 0x5d 0x5e 0x5f>;
+
+			ds90ub960_1_ports: ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				/* CSI-2 TX*/
+				port@4 {
+					reg = <4>;
+					ds90ub960_1_csi_out: endpoint {
+						clock-lanes = <0>;
+						data-lanes = <1 2 3 4>;
+						link-frequencies = /bits/ 64 <800000000>;
+						remote-endpoint = <&csi2_phy1>;
+					};
+				};
+			};
+
+			ds90ub960_1_links: links {
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+		};
+	};
+};
+
+&cdns_csi2rx0 {
+	ports {
+		port@0 {
+			status = "okay";
+
+			csi2_phy0: endpoint {
+				remote-endpoint = <&ds90ub960_0_csi_out>;
+				clock-lanes = <0>;
+				data-lanes = <1 2 3 4>;
+				link-frequencies = /bits/ 64 <800000000>;
+			};
+		};
+};	};
+
+&cdns_csi2rx1 {
+	ports {
+		port@0 {
+			status = "okay";
+
+			csi2_phy1: endpoint {
+				remote-endpoint = <&ds90ub960_1_csi_out>;
+				clock-lanes = <0>;
+				data-lanes = <1 2 3 4>;
+				link-frequencies = /bits/ 64 <800000000>;
+			};
+		};
+	};
+};
+
+&ti_csi2rx0 {
+        status = "okay";
+};
+
+&ti_csi2rx1 {
+        status = "okay";
+};
+
+&dphy_rx0 {
+        status = "okay";
+};
+
+&dphy_rx1 {
+        status = "okay";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-am69-sk-rpi-hdr-ehrpwm.dtso b/arch/arm64/boot/dts/ti/k3-am69-sk-rpi-hdr-ehrpwm.dtso
--- a/arch/arm64/boot/dts/ti/k3-am69-sk-rpi-hdr-ehrpwm.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-am69-sk-rpi-hdr-ehrpwm.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for enabling EHRPWMs on RPi expansion header on AM69 SK board.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+	rpi_header_gpio0_pins_default: rpi-header-gpio0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0bc, PIN_INPUT, 7) /* (AD33) MCASP1_AFSX.GPIO0_47 */
+			J784S4_IOPAD(0x06c, PIN_INPUT, 7) /* (AJ37) MCASP4_AFSX.GPIO0_27 */
+			J784S4_IOPAD(0x0b4, PIN_INPUT, 7) /* (AL34) MCASP1_AXR4.GPIO0_45 */
+			J784S4_IOPAD(0x0c0, PIN_INPUT, 7) /* (AD38) MCASP1_AXR0.GPIO0_48 */
+			J784S4_IOPAD(0x00c, PIN_INPUT, 7) /* (AF33) MCAN13_TX.GPIO0_3 */
+			J784S4_IOPAD(0x0b8, PIN_INPUT, 7) /* (AC34) MCASP1_ACLKX.GPIO0_46 */
+			J784S4_IOPAD(0x090, PIN_INPUT, 7) /* (AC35) MCASP0_AXR8.GPIO0_36 */
+			J784S4_IOPAD(0x0a8, PIN_INPUT, 7) /* (AF34) MCASP0_AXR14.GPIO0_42 */
+			J784S4_IOPAD(0x034, PIN_INPUT, 7) /* (AJ34) PMIC_WAKE0n.GPIO0_13 */
+			J784S4_IOPAD(0x008, PIN_INPUT, 7) /* (AJ33) MCAN12_RX.GPIO0_2 */
+			J784S4_IOPAD(0x004, PIN_INPUT, 7) /* (AG36) MCAN12_TX.GPIO0_1 */
+		>;
+	};
+
+	rpi_header_ehrpwm0_pins_default: rpi-header-ehrpwm0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0cc, PIN_INPUT, 5) /* (AM37) SPI0_CS0.EHRPWM0_A */
+		>;
+	};
+
+	rpi_header_ehrpwm3_pins_default: rpi-header-ehrpwm3-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x08c, PIN_INPUT, 9) /* (AE35) MCASP0_AXR7.EHRPWM3_A */
+		>;
+	};
+
+	rpi_header_ehrpwm4_pins_default: rpi-header-ehrpwm4-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0a4, PIN_INPUT, 9) /* (AJ36) MCASP0_AXR13.EHRPWM4_A */
+		>;
+	};
+};
+
+&main_ehrpwm0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm0_pins_default>;
+	status = "okay";
+};
+
+&main_ehrpwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm3_pins_default>;
+	status = "okay";
+};
+
+&main_ehrpwm4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm4_pins_default>;
+	status = "okay";
+};
+
+&main_gpio0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio0_pins_default>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-0.dtso b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-0.dtso
--- a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-0.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX390 FPD-Link 3 Camera Module
+ * https://www.d3engineering.co/product/designcore-d3rcm-imx390-953-rugged-camera-module/
+ *
+ * Copyright (c) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&ds90ub960_0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* FPDLink RX 0 */
+	port@0 {
+		reg = <0>;
+
+		ub960_fpd3_1_in: endpoint {
+			remote-endpoint = <&ub953_1_out>;
+		};
+	};
+};
+
+&ds90ub960_0_links {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	link@0 {
+		reg = <0>;
+		i2c-alias = <0x44>;
+
+		ti,rx-mode = <3>;
+
+		serializer: serializer {
+			compatible = "ti,ds90ub953-q1";
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					ub953_1_in: endpoint {
+						data-lanes = <1 2 3 4>;
+						remote-endpoint = <&sensor_1_out>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					ub953_1_out: endpoint {
+						remote-endpoint = <&ub960_fpd3_1_in>;
+					};
+				};
+			};
+
+			i2c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sensor@1a {
+					compatible = "sony,imx390";
+					reg = <0x1a>;
+
+					clocks = <&serializer>;
+					clock-names = "inck";
+					assigned-clocks = <&serializer>;
+					assigned-clock-rates = <27000000>;
+
+					xclr-gpios = <&serializer 1 GPIO_ACTIVE_LOW>;
+					error0-gpios = <&serializer 2 GPIO_ACTIVE_HIGH>;
+					error1-gpios = <&serializer 3 GPIO_ACTIVE_HIGH>;
+					comready-gpios = <&serializer 0 GPIO_ACTIVE_HIGH>;
+
+					port {
+						sensor_1_out: endpoint {
+							remote-endpoint = <&ub953_1_in>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-1.dtso b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-1.dtso
--- a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-1.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-1.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX390 FPD-Link 3 Camera Module
+ * https://www.d3engineering.co/product/designcore-d3rcm-imx390-953-rugged-camera-module/
+ *
+ * Copyright (c) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&ds90ub960_0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* FPDLink RX 1 */
+	port@1 {
+		reg = <1>;
+
+		ub960_fpd3_1_in: endpoint {
+			remote-endpoint = <&ub953_1_out>;
+		};
+	};
+};
+
+&ds90ub960_0_links {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	link@1 {
+		reg = <1>;
+		i2c-alias = <0x45>;
+
+		ti,rx-mode = <3>;
+
+		serializer: serializer {
+			compatible = "ti,ds90ub953-q1";
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					ub953_1_in: endpoint {
+						data-lanes = <1 2 3 4>;
+						remote-endpoint = <&sensor_1_out>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					ub953_1_out: endpoint {
+						remote-endpoint = <&ub960_fpd3_1_in>;
+					};
+				};
+			};
+
+			i2c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sensor@1a {
+					compatible = "sony,imx390";
+					reg = <0x1a>;
+
+					clocks = <&serializer>;
+					clock-names = "inck";
+					assigned-clocks = <&serializer>;
+					assigned-clock-rates = <27000000>;
+
+					xclr-gpios = <&serializer 1 GPIO_ACTIVE_LOW>;
+					error0-gpios = <&serializer 2 GPIO_ACTIVE_HIGH>;
+					error1-gpios = <&serializer 3 GPIO_ACTIVE_HIGH>;
+					comready-gpios = <&serializer 0 GPIO_ACTIVE_HIGH>;
+
+					port {
+						sensor_1_out: endpoint {
+							remote-endpoint = <&ub953_1_in>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-2.dtso b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-2.dtso
--- a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-2.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-2.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX390 FPD-Link 3 Camera Module
+ * https://www.d3engineering.co/product/designcore-d3rcm-imx390-953-rugged-camera-module/
+ *
+ * Copyright (c) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&ds90ub960_0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* FPDLink RX 2 */
+	port@2 {
+		reg = <2>;
+
+		ub960_fpd3_1_in: endpoint {
+			remote-endpoint = <&ub953_1_out>;
+		};
+	};
+};
+
+&ds90ub960_0_links {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	link@2 {
+		reg = <2>;
+		i2c-alias = <0x46>;
+
+		ti,rx-mode = <3>;
+
+		serializer: serializer {
+			compatible = "ti,ds90ub953-q1";
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					ub953_1_in: endpoint {
+						data-lanes = <1 2 3 4>;
+						remote-endpoint = <&sensor_1_out>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					ub953_1_out: endpoint {
+						remote-endpoint = <&ub960_fpd3_1_in>;
+					};
+				};
+			};
+
+			i2c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sensor@1a {
+					compatible = "sony,imx390";
+					reg = <0x1a>;
+
+					clocks = <&serializer>;
+					clock-names = "inck";
+					assigned-clocks = <&serializer>;
+					assigned-clock-rates = <27000000>;
+
+					xclr-gpios = <&serializer 1 GPIO_ACTIVE_LOW>;
+					error0-gpios = <&serializer 2 GPIO_ACTIVE_HIGH>;
+					error1-gpios = <&serializer 3 GPIO_ACTIVE_HIGH>;
+					comready-gpios = <&serializer 0 GPIO_ACTIVE_HIGH>;
+
+					port {
+						sensor_1_out: endpoint {
+							remote-endpoint = <&ub953_1_in>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-3.dtso b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-3.dtso
--- a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-3.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-0-3.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX390 FPD-Link 3 Camera Module
+ * https://www.d3engineering.co/product/designcore-d3rcm-imx390-953-rugged-camera-module/
+ *
+ * Copyright (c) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&ds90ub960_0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* FPDLink RX 3 */
+	port@3 {
+		reg = <3>;
+
+		ub960_fpd3_1_in: endpoint {
+			remote-endpoint = <&ub953_1_out>;
+		};
+	};
+};
+
+&ds90ub960_0_links {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	link@3 {
+		reg = <3>;
+		i2c-alias = <0x47>;
+
+		ti,rx-mode = <3>;
+
+		serializer: serializer {
+			compatible = "ti,ds90ub953-q1";
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					ub953_1_in: endpoint {
+						data-lanes = <1 2 3 4>;
+						remote-endpoint = <&sensor_1_out>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					ub953_1_out: endpoint {
+						remote-endpoint = <&ub960_fpd3_1_in>;
+					};
+				};
+			};
+
+			i2c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sensor@1a {
+					compatible = "sony,imx390";
+					reg = <0x1a>;
+
+					clocks = <&serializer>;
+					clock-names = "inck";
+					assigned-clocks = <&serializer>;
+					assigned-clock-rates = <27000000>;
+
+					xclr-gpios = <&serializer 1 GPIO_ACTIVE_LOW>;
+					error0-gpios = <&serializer 2 GPIO_ACTIVE_HIGH>;
+					error1-gpios = <&serializer 3 GPIO_ACTIVE_HIGH>;
+					comready-gpios = <&serializer 0 GPIO_ACTIVE_HIGH>;
+
+					port {
+						sensor_1_out: endpoint {
+							remote-endpoint = <&ub953_1_in>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-0.dtso b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-0.dtso
--- a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-0.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX390 FPD-Link 3 Camera Module
+ * https://www.d3engineering.co/product/designcore-d3rcm-imx390-953-rugged-camera-module/
+ *
+ * Copyright (c) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&ds90ub960_1_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* FPDLink RX 0 */
+	port@0 {
+		reg = <0>;
+
+		ub960_fpd3_1_in: endpoint {
+			remote-endpoint = <&ub953_1_out>;
+		};
+	};
+};
+
+&ds90ub960_1_links {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	link@0 {
+		reg = <0>;
+		i2c-alias = <0x54>;
+
+		ti,rx-mode = <3>;
+
+		serializer: serializer {
+			compatible = "ti,ds90ub953-q1";
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					ub953_1_in: endpoint {
+						data-lanes = <1 2 3 4>;
+						remote-endpoint = <&sensor_1_out>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					ub953_1_out: endpoint {
+						remote-endpoint = <&ub960_fpd3_1_in>;
+					};
+				};
+			};
+
+			i2c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sensor@1a {
+					compatible = "sony,imx390";
+					reg = <0x1a>;
+
+					clocks = <&serializer>;
+					clock-names = "inck";
+					assigned-clocks = <&serializer>;
+					assigned-clock-rates = <27000000>;
+
+					xclr-gpios = <&serializer 1 GPIO_ACTIVE_LOW>;
+					error0-gpios = <&serializer 2 GPIO_ACTIVE_HIGH>;
+					error1-gpios = <&serializer 3 GPIO_ACTIVE_HIGH>;
+					comready-gpios = <&serializer 0 GPIO_ACTIVE_HIGH>;
+
+					port {
+						sensor_1_out: endpoint {
+							remote-endpoint = <&ub953_1_in>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-1.dtso b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-1.dtso
--- a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-1.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-1.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX390 FPD-Link 3 Camera Module
+ * https://www.d3engineering.co/product/designcore-d3rcm-imx390-953-rugged-camera-module/
+ *
+ * Copyright (c) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&ds90ub960_1_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* FPDLink RX 1 */
+	port@1 {
+		reg = <1>;
+
+		ub960_fpd3_1_in: endpoint {
+			remote-endpoint = <&ub953_1_out>;
+		};
+	};
+};
+
+&ds90ub960_1_links {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	link@1 {
+		reg = <1>;
+		i2c-alias = <0x55>;
+
+		ti,rx-mode = <3>;
+
+		serializer: serializer {
+			compatible = "ti,ds90ub953-q1";
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					ub953_1_in: endpoint {
+						data-lanes = <1 2 3 4>;
+						remote-endpoint = <&sensor_1_out>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					ub953_1_out: endpoint {
+						remote-endpoint = <&ub960_fpd3_1_in>;
+					};
+				};
+			};
+
+			i2c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sensor@1a {
+					compatible = "sony,imx390";
+					reg = <0x1a>;
+
+					clocks = <&serializer>;
+					clock-names = "inck";
+					assigned-clocks = <&serializer>;
+					assigned-clock-rates = <27000000>;
+
+					xclr-gpios = <&serializer 1 GPIO_ACTIVE_LOW>;
+					error0-gpios = <&serializer 2 GPIO_ACTIVE_HIGH>;
+					error1-gpios = <&serializer 3 GPIO_ACTIVE_HIGH>;
+					comready-gpios = <&serializer 0 GPIO_ACTIVE_HIGH>;
+
+					port {
+						sensor_1_out: endpoint {
+							remote-endpoint = <&ub953_1_in>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-2.dtso b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-2.dtso
--- a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-2.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-2.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX390 FPD-Link 3 Camera Module
+ * https://www.d3engineering.co/product/designcore-d3rcm-imx390-953-rugged-camera-module/
+ *
+ * Copyright (c) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&ds90ub960_1_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* FPDLink RX 2 */
+	port@2 {
+		reg = <2>;
+
+		ub960_fpd3_1_in: endpoint {
+			remote-endpoint = <&ub953_1_out>;
+		};
+	};
+};
+
+&ds90ub960_1_links {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	link@2 {
+		reg = <2>;
+		i2c-alias = <0x56>;
+
+		ti,rx-mode = <3>;
+
+		serializer: serializer {
+			compatible = "ti,ds90ub953-q1";
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					ub953_1_in: endpoint {
+						data-lanes = <1 2 3 4>;
+						remote-endpoint = <&sensor_1_out>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					ub953_1_out: endpoint {
+						remote-endpoint = <&ub960_fpd3_1_in>;
+					};
+				};
+			};
+
+			i2c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sensor@1a {
+					compatible = "sony,imx390";
+					reg = <0x1a>;
+
+					clocks = <&serializer>;
+					clock-names = "inck";
+					assigned-clocks = <&serializer>;
+					assigned-clock-rates = <27000000>;
+
+					xclr-gpios = <&serializer 1 GPIO_ACTIVE_LOW>;
+					error0-gpios = <&serializer 2 GPIO_ACTIVE_HIGH>;
+					error1-gpios = <&serializer 3 GPIO_ACTIVE_HIGH>;
+					comready-gpios = <&serializer 0 GPIO_ACTIVE_HIGH>;
+
+					port {
+						sensor_1_out: endpoint {
+							remote-endpoint = <&ub953_1_in>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-3.dtso b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-3.dtso
--- a/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-3.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-fpdlink-imx390-rcm-1-3.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX390 FPD-Link 3 Camera Module
+ * https://www.d3engineering.co/product/designcore-d3rcm-imx390-953-rugged-camera-module/
+ *
+ * Copyright (c) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&ds90ub960_1_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* FPDLink RX 3 */
+	port@3 {
+		reg = <3>;
+
+		ub960_fpd3_1_in: endpoint {
+			remote-endpoint = <&ub953_1_out>;
+		};
+	};
+};
+
+&ds90ub960_1_links {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	link@3 {
+		reg = <3>;
+		i2c-alias = <0x57>;
+
+		ti,rx-mode = <3>;
+
+		serializer: serializer {
+			compatible = "ti,ds90ub953-q1";
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					ub953_1_in: endpoint {
+						data-lanes = <1 2 3 4>;
+						remote-endpoint = <&sensor_1_out>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					ub953_1_out: endpoint {
+						remote-endpoint = <&ub960_fpd3_1_in>;
+					};
+				};
+			};
+
+			i2c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sensor@1a {
+					compatible = "sony,imx390";
+					reg = <0x1a>;
+
+					clocks = <&serializer>;
+					clock-names = "inck";
+					assigned-clocks = <&serializer>;
+					assigned-clock-rates = <27000000>;
+
+					xclr-gpios = <&serializer 1 GPIO_ACTIVE_LOW>;
+					error0-gpios = <&serializer 2 GPIO_ACTIVE_HIGH>;
+					error1-gpios = <&serializer 3 GPIO_ACTIVE_HIGH>;
+					comready-gpios = <&serializer 0 GPIO_ACTIVE_HIGH>;
+
+					port {
+						sensor_1_out: endpoint {
+							remote-endpoint = <&ub953_1_in>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-0.dtso b/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-0.dtso
--- a/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-0.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX390 FPD-Link 3 Camera Module
+ * Copyright (c) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&ds90ub960_0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* FPDLink RX 0 */
+	port@0 {
+		reg = <0>;
+
+		ub960_fpd3_1_in: endpoint {
+			remote-endpoint = <&ub953_1_out>;
+		};
+	};
+};
+
+&ds90ub960_0_links {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	link@0 {
+		reg = <0>;
+		i2c-alias = <0x44>;
+
+		ti,rx-mode = <3>;
+
+		serializer: serializer {
+			compatible = "ti,ds90ub953-q1";
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					ub953_1_in: endpoint {
+						data-lanes = <1 2>;
+						/*clock-noncontinuous;*/
+						remote-endpoint = <&sensor_1_out>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					ub953_1_out: endpoint {
+						remote-endpoint = <&ub960_fpd3_1_in>;
+					};
+				};
+			};
+
+			i2c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sensor@60 {
+					compatible = "ovti,ov2312";
+					reg = <0x60>;
+
+					clocks = <&serializer>;
+					clock-names = "xvclk";
+					assigned-clocks = <&serializer>;
+					assigned-clock-rates = <24000000>;
+
+					reset-gpios = <&serializer 2 GPIO_ACTIVE_HIGH>;
+
+					port {
+						sensor_1_out: endpoint {
+							remote-endpoint = <&ub953_1_in>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-1.dtso b/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-1.dtso
--- a/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-1.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-1.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX390 FPD-Link 3 Camera Module
+ * Copyright (c) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&ds90ub960_0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* FPDLink RX 1 */
+	port@1 {
+		reg = <1>;
+
+		ub960_fpd3_1_in: endpoint {
+			remote-endpoint = <&ub953_1_out>;
+		};
+	};
+};
+
+&ds90ub960_0_links {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	link@1 {
+		reg = <1>;
+		i2c-alias = <0x45>;
+
+		ti,rx-mode = <3>;
+
+		serializer: serializer {
+			compatible = "ti,ds90ub953-q1";
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					ub953_1_in: endpoint {
+						data-lanes = <1 2>;
+						/*clock-noncontinuous;*/
+						remote-endpoint = <&sensor_1_out>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					ub953_1_out: endpoint {
+						remote-endpoint = <&ub960_fpd3_1_in>;
+					};
+				};
+			};
+
+			i2c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sensor@60 {
+					compatible = "ovti,ov2312";
+					reg = <0x60>;
+
+					clocks = <&serializer>;
+					clock-names = "xvclk";
+					assigned-clocks = <&serializer>;
+					assigned-clock-rates = <24000000>;
+
+					reset-gpios = <&serializer 2 GPIO_ACTIVE_HIGH>;
+
+					port {
+						sensor_1_out: endpoint {
+							remote-endpoint = <&ub953_1_in>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-2.dtso b/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-2.dtso
--- a/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-2.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-2.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX390 FPD-Link 3 Camera Module
+ * Copyright (c) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&ds90ub960_0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* FPDLink RX 2 */
+	port@2 {
+		reg = <2>;
+
+		ub960_fpd3_1_in: endpoint {
+			remote-endpoint = <&ub953_1_out>;
+		};
+	};
+};
+
+&ds90ub960_0_links {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	link@2 {
+		reg = <2>;
+		i2c-alias = <0x46>;
+
+		ti,rx-mode = <3>;
+
+		serializer: serializer {
+			compatible = "ti,ds90ub953-q1";
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					ub953_1_in: endpoint {
+						data-lanes = <1 2>;
+						/*clock-noncontinuous;*/
+						remote-endpoint = <&sensor_1_out>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					ub953_1_out: endpoint {
+						remote-endpoint = <&ub960_fpd3_1_in>;
+					};
+				};
+			};
+
+			i2c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sensor@60 {
+					compatible = "ovti,ov2312";
+					reg = <0x60>;
+
+					clocks = <&serializer>;
+					clock-names = "xvclk";
+					assigned-clocks = <&serializer>;
+					assigned-clock-rates = <24000000>;
+
+					reset-gpios = <&serializer 2 GPIO_ACTIVE_HIGH>;
+
+					port {
+						sensor_1_out: endpoint {
+							remote-endpoint = <&ub953_1_in>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-3.dtso b/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-3.dtso
--- a/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-3.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-fpdlink-ov2312-0-3.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMX390 FPD-Link 3 Camera Module
+ * Copyright (c) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&ds90ub960_0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	/* FPDLink RX 3 */
+	port@3 {
+		reg = <3>;
+
+		ub960_fpd3_1_in: endpoint {
+			remote-endpoint = <&ub953_1_out>;
+		};
+	};
+};
+
+&ds90ub960_0_links {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	link@3 {
+		reg = <3>;
+		i2c-alias = <0x47>;
+
+		ti,rx-mode = <3>;
+
+		serializer: serializer {
+			compatible = "ti,ds90ub953-q1";
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			#clock-cells = <0>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				port@0 {
+					reg = <0>;
+					ub953_1_in: endpoint {
+						data-lanes = <1 2>;
+						/*clock-noncontinuous;*/
+						remote-endpoint = <&sensor_1_out>;
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+
+					ub953_1_out: endpoint {
+						remote-endpoint = <&ub960_fpd3_1_in>;
+					};
+				};
+			};
+
+			i2c {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sensor@60 {
+					compatible = "ovti,ov2312";
+					reg = <0x60>;
+
+					clocks = <&serializer>;
+					clock-names = "xvclk";
+					assigned-clocks = <&serializer>;
+					assigned-clock-rates = <24000000>;
+
+					reset-gpios = <&serializer 2 GPIO_ACTIVE_HIGH>;
+
+					port {
+						sensor_1_out: endpoint {
+							remote-endpoint = <&ub953_1_in>;
+						};
+					};
+				};
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
--- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts	2024-01-28 14:01:31.240353775 -0500
@@ -80,6 +80,26 @@
 	};
 };
 
+&wkup_pmx0{
+	mcu_uart0_pins_default: mcu-uart0-pins-default {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0xf8, PIN_INPUT, 0) /* (E20) WKUP_GPIO0_14.MCU_UART0_CTSn */
+			J721E_WKUP_IOPAD(0xfc, PIN_OUTPUT, 0) /* (E21) WKUP_GPIO0_15.MCU_UART0_RTSn */
+			J721E_WKUP_IOPAD(0xf4, PIN_INPUT, 0) /* (D20) WKUP_GPIO0_13.MCU_UART0_RXD */
+			J721E_WKUP_IOPAD(0xf0, PIN_OUTPUT, 0) /* (D19) WKUP_GPIO0_12.MCU_UART0_TXD */
+		>;
+	};
+
+	wkup_uart0_pins_default: wkup-uart0-pins-default {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0xd8, PIN_INPUT, 0) /* (C14) WKUP_GPIO0_6.WKUP_UART0_CTSn */
+			J721E_WKUP_IOPAD(0xdc, PIN_OUTPUT, 0) /* (C18) WKUP_GPIO0_7.WKUP_UART0_RTSn */
+			J721E_WKUP_IOPAD(0xb0, PIN_INPUT, 0) /* (B14) WKUP_UART0_RXD */
+			J721E_WKUP_IOPAD(0xb4, PIN_OUTPUT, 0) /* (A14) WKUP_UART0_TXD */
+		>;
+	};
+};
+
 &wkup_pmx2 {
 	mcu_cpsw_pins_default: mcu-cpsw-pins-default {
 		pinctrl-single,pins = <
@@ -98,6 +118,12 @@
 		>;
 	};
 
+	wkup_gpio_pins_default: wkup-gpio-pins-default {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0x70, PIN_INPUT, 7) /* (C14) WKUP_GPIO0_6 */
+		>;
+	};
+
 	mcu_mdio_pins_default: mcu-mdio1-pins-default {
 		pinctrl-single,pins = <
 			J721E_WKUP_IOPAD(0x0034, PIN_OUTPUT, 0) /* (L1) MCU_MDIO0_MDC */
@@ -152,53 +178,33 @@
 &wkup_uart0 {
 	/* Wakeup UART is used by System firmware */
 	status = "reserved";
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_uart0_pins_default>;
+};
+
+&mcu_uart0 {
+	status = "okay";
+	/* Default pinmux */
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_uart0_pins_default>;
 };
 
 &main_uart0 {
+	status = "okay";
 	/* Shared with ATF on this platform */
 	power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
 };
 
+&main_uart1 {
+	status = "okay";
+	/* Default pinmux */
+};
+
 &main_uart2 {
 	/* MAIN UART 2 is used by R5F firmware */
 	status = "reserved";
 };
 
-&main_uart3 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
-&main_uart4 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
-&main_uart5 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
-&main_uart6 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
-&main_uart7 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
-&main_uart8 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
-&main_uart9 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
 &main_gpio2 {
 	status = "disabled";
 };
@@ -211,6 +217,11 @@
 	status = "disabled";
 };
 
+&wkup_gpio0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_gpio_pins_default>;
+};
+
 &wkup_gpio1 {
 	status = "disabled";
 };
@@ -218,6 +229,11 @@
 &mcu_cpsw {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
+
+	cpts@3d000 {
+		/* Map HW4_TS_PUSH to GENF1 */
+		ti,pps = <3 1>;
+	};
 };
 
 &davinci_mdio {
@@ -234,6 +250,7 @@
 };
 
 &main_i2c0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c0_pins_default>;
 	clock-frequency = <400000>;
@@ -261,6 +278,7 @@
  * The i2c1 of the CPB (as it is labeled) is not connected to j7200.
  */
 &main_i2c1 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c1_pins_default>;
 	clock-frequency = <400000>;
@@ -355,3 +373,19 @@
 	num-lanes = <2>;
 	status = "disabled";
 };
+
+#define K3_TS_OFFSET(pa, val)  (0x4+(pa)*4) (0x10000 | val)
+
+&timesync_router {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_cpsw_cpts>;
+
+	/* Use Time Sync Router to map GENF1 input to HW4_TS_PUSH output */
+	mcu_cpsw_cpts: mcu-cpsw-cpts {
+		pinctrl-single,pins = <
+			/* pps [mcu cpsw cpts genf1] in17 -> out25 [mcu cpsw cpts hw4_push] */
+			K3_TS_OFFSET(25, 17)
+			>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200.dtsi b/arch/arm64/boot/dts/ti/k3-j7200.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j7200.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j7200.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -7,9 +7,10 @@
 
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/pinctrl/k3.h>
 #include <dt-bindings/soc/ti,sci_pm_domain.h>
 
+#include "k3-pinctrl.h"
+
 / {
 	model = "Texas Instruments K3 J7200 SoC";
 	compatible = "ti,j7200";
@@ -64,6 +65,10 @@
 			d-cache-line-size = <64>;
 			d-cache-sets = <256>;
 			next-level-cache = <&L2_0>;
+			clocks = <&k3_clks 202 2>;
+			clock-names = "cpu";
+			operating-points-v2 = <&cpu0_opp_table>;
+			#cooling-cells = <2>; /* min followed by max */
 		};
 
 		cpu1: cpu@1 {
@@ -78,12 +83,37 @@
 			d-cache-line-size = <64>;
 			d-cache-sets = <256>;
 			next-level-cache = <&L2_0>;
+			clocks = <&k3_clks 203 0>;
+			clock-names = "cpu";
+			operating-points-v2 = <&cpu0_opp_table>;
+			#cooling-cells = <2>; /* min followed by max */
+		};
+	};
+
+	cpu0_opp_table: opp-table {
+		compatible = "operating-points-v2";
+
+		opp4-2000000000 {
+			opp-hz = /bits/ 64 <2000000000>;
+		};
+
+		opp3-1500000000 {
+			opp-hz = /bits/ 64 <1500000000>;
+		};
+
+		opp2-1000000000 {
+			opp-hz = /bits/ 64 <1000000000>;
+		};
+
+		opp1-750000000 {
+			opp-hz = /bits/ 64 <750000000>;
 		};
 	};
 
 	L2_0: l2-cache0 {
 		compatible = "cache";
 		cache-level = <2>;
+		cache-unified;
 		cache-size = <0x100000>;
 		cache-line-size = <64>;
 		cache-sets = <1024>;
@@ -168,6 +198,8 @@
 				 <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; /* FSS OSPI1 data region 3 */
 		};
 	};
+
+	#include "k3-j7200-thermal.dtsi"
 };
 
 /* Now include the peripherals for each bus segments */
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200-evm-mcspi-loopback.dtso b/arch/arm64/boot/dts/ti/k3-j7200-evm-mcspi-loopback.dtso
--- a/arch/arm64/boot/dts/ti/k3-j7200-evm-mcspi-loopback.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j7200-evm-mcspi-loopback.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MCSPI internal master-slave loopback example overlay for J7200.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * J7200 has MCSPI4 connected as master to MCU_MCSPI2 by default and not
+ * pinned out to external pads, This overlay enables spidev on these
+ * interfaces for userspace testing.
+ */
+
+/dts-v1/;
+/plugin/;
+
+&main_spi4 {
+	status = "okay";
+	#address-cells = <0>;
+	#size-cells = <0>;
+	spi-slave;
+	dmas = <&main_udmap 0xc610>, <&main_udmap 0x4610>;
+	dma-names = "tx0", "rx0";
+
+	slave {
+		/*
+		 * Using spidev compatible is warned loudly,
+		 * thus use another equivalent compatible id
+		 * from spidev.
+		 */
+		compatible = "rohm,dh2228fv";
+		spi-max-frequency = <24000000>;
+	};
+};
+
+&mcu_spi2 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	spidev@0 {
+		/*
+		 * Using spidev compatible is warned loudly,
+		 * thus use another equivalent compatible id
+		 * from spidev.
+		 */
+		compatible = "rohm,dh2228fv";
+		spi-max-frequency = <24000000>;
+		reg = <0>;
+	};
+};
\ No newline at end of file
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200-evm-quad-port-eth-exp.dtso b/arch/arm64/boot/dts/ti/k3-j7200-evm-quad-port-eth-exp.dtso
--- a/arch/arm64/boot/dts/ti/k3-j7200-evm-quad-port-eth-exp.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j7200-evm-quad-port-eth-exp.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for CPSW5G in QSGMII mode using J7 Quad Port ETH EXP Add-On Ethernet Card with
+ * J7200 board.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/mux/ti-serdes.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	aliases {
+		ethernet1 = "/bus@100000/ethernet@c000000/ethernet-ports/port@1";
+		ethernet2 = "/bus@100000/ethernet@c000000/ethernet-ports/port@2";
+		ethernet3 = "/bus@100000/ethernet@c000000/ethernet-ports/port@3";
+		ethernet4 = "/bus@100000/ethernet@c000000/ethernet-ports/port@4";
+	};
+};
+
+&cpsw0 {
+	status = "okay";
+};
+
+&cpsw0_port1 {
+	status = "okay";
+	phy-handle = <&cpsw5g_phy0>;
+	phy-mode = "qsgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 1>;
+};
+
+&cpsw0_port2 {
+	status = "okay";
+	phy-handle = <&cpsw5g_phy1>;
+	phy-mode = "qsgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 2>;
+};
+
+&cpsw0_port3 {
+	status = "okay";
+	phy-handle = <&cpsw5g_phy2>;
+	phy-mode = "qsgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 3>;
+};
+
+&cpsw0_port4 {
+	status = "okay";
+	phy-handle = <&cpsw5g_phy3>;
+	phy-mode = "qsgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 4>;
+};
+
+&cpsw5g_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio0_pins_default>;
+	reset-gpios = <&exp2 17 GPIO_ACTIVE_LOW>;
+	reset-post-delay-us = <120000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	cpsw5g_phy0: ethernet-phy@16 {
+		reg = <16>;
+	};
+	cpsw5g_phy1: ethernet-phy@17 {
+		reg = <17>;
+	};
+	cpsw5g_phy2: ethernet-phy@18 {
+		reg = <18>;
+	};
+	cpsw5g_phy3: ethernet-phy@19 {
+		reg = <19>;
+	};
+};
+
+&exp2 {
+	qsgmii-line-hog {
+		gpio-hog;
+		gpios = <16 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "qsgmii-pwrdn-line";
+	};
+};
+
+&main_pmx0 {
+	mdio0_pins_default: mdio0-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x00a8, PIN_OUTPUT, 5) /* (W19) UART8_TXD.MDIO0_MDC */
+			J721E_IOPAD(0x00a4, PIN_INPUT, 5) /* (W14) UART8_RXD.MDIO0_MDIO */
+		>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200-evm-virt-mac-client.dtso b/arch/arm64/boot/dts/ti/k3-j7200-evm-virt-mac-client.dtso
--- a/arch/arm64/boot/dts/ti/k3-j7200-evm-virt-mac-client.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j7200-evm-virt-mac-client.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for enabling CPSW Virt MAC Client driver in linux to interface with EthFw via the
+ * Linux MAC Only port as well as the Switch Ports of the CPSW5G CPSW instance.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+&{/} {
+	cpsw5g_virt_mac: main-r5fss-cpsw5g-virt-mac0 {
+		compatible = "ti,j721e-cpsw-virt-mac";
+		dma-coherent;
+		ti,psil-base = <0x4a00>;
+		ti,remote-name = "mpu_1_0_ethswitch-device-0";
+
+		dmas = <&main_udmap 0xca00>,
+		       <&main_udmap 0xca01>,
+		       <&main_udmap 0xca02>,
+		       <&main_udmap 0xca03>,
+		       <&main_udmap 0xca04>,
+		       <&main_udmap 0xca05>,
+		       <&main_udmap 0xca06>,
+		       <&main_udmap 0xca07>,
+		       <&main_udmap 0x4a00>;
+		dma-names = "tx0", "tx1", "tx2", "tx3",
+			    "tx4", "tx5", "tx6", "tx7",
+			    "rx";
+
+		virt-emac-port {
+			ti,label = "virt-port";
+			/* local-mac-address = [0 0 0 0 0 0]; */
+		};
+	};
+
+	cpsw5g_virt_maconly: main-r5fss-cpsw5g-virt-mac1 {
+		compatible = "ti,j721e-cpsw-virt-mac";
+		dma-coherent;
+		ti,psil-base = <0x4a00>;
+		ti,remote-name = "mpu_1_0_ethmac-device-1";
+
+		dmas = <&main_udmap 0xca00>,
+		       <&main_udmap 0xca01>,
+		       <&main_udmap 0xca02>,
+		       <&main_udmap 0xca03>,
+		       <&main_udmap 0xca04>,
+		       <&main_udmap 0xca05>,
+		       <&main_udmap 0xca06>,
+		       <&main_udmap 0xca07>,
+		       <&main_udmap 0x4a00>;
+		dma-names = "tx0", "tx1", "tx2", "tx3",
+			    "tx4", "tx5", "tx6", "tx7",
+			    "rx";
+
+		virt-emac-port {
+			ti,label = "virt-port";
+			/* local-mac-address = [0 0 0 0 0 0]; */
+		};
+	};
+};
+
+/* uart2 is assigned to cpsw9g eth-switch fw running on remote CPU core */
+&main_uart2 {
+	status = "reserved";
+};
+
+/* Reserve shared memory for inter-core network communication */
+&reserved_memory {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	main_r5fss0_core0_shared_memory_queue_region:r5f-virtual-eth-queues@a5000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa5000000 0x00 0x200000>;
+		no-map;
+	};
+
+	main_r5fss0_core0_shared_memory_bufpool_region:r5f-virtual-eth-buffers@a5200000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xa5200000 0x00 0x1e00000>;
+		no-map;
+	};
+};
+
+&main_r5fss0_core0 {
+	memory-region = <&main_r5fss0_core0_dma_memory_region>,
+			<&main_r5fss0_core0_memory_region>,
+			<&main_r5fss0_core0_shared_memory_queue_region>,
+			<&main_r5fss0_core0_shared_memory_bufpool_region>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -39,6 +39,13 @@
 					<0x4088 0x3>, <0x408c 0x3>; /* SERDES0 lane2/3 select */
 		};
 
+		cpsw0_phy_gmii_sel: phy@4044 {
+			compatible = "ti,j7200-cpsw5g-phy-gmii-sel";
+			ti,qsgmii-main-ports = <1>;
+			reg = <0x4044 0x10>;
+			#phy-cells = <1>;
+		};
+
 		usb_serdes_mux: mux-controller@4000 {
 			compatible = "mmio-mux";
 			#mux-control-cells = <1>;
@@ -142,6 +149,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster1: mailbox@31f81000 {
@@ -151,6 +159,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster2: mailbox@31f82000 {
@@ -160,6 +169,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster3: mailbox@31f83000 {
@@ -169,6 +179,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster4: mailbox@31f84000 {
@@ -178,6 +189,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster5: mailbox@31f85000 {
@@ -187,6 +199,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster6: mailbox@31f86000 {
@@ -196,6 +209,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster7: mailbox@31f87000 {
@@ -205,6 +219,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster8: mailbox@31f88000 {
@@ -214,6 +229,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster9: mailbox@31f89000 {
@@ -223,6 +239,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster10: mailbox@31f8a000 {
@@ -232,6 +249,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster11: mailbox@31f8b000 {
@@ -241,6 +259,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		main_ringacc: ringacc@3c000000 {
@@ -292,6 +311,87 @@
 		};
 	};
 
+	cpsw0: ethernet@c000000 {
+		compatible = "ti,j7200-cpswxg-nuss";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		reg = <0x00 0xc000000 0x00 0x200000>;
+		reg-names = "cpsw_nuss";
+		ranges = <0x00 0x00 0x00 0xc000000 0x00 0x200000>;
+		clocks = <&k3_clks 19 33>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 19 TI_SCI_PD_EXCLUSIVE>;
+
+		dmas = <&main_udmap 0xca00>,
+		       <&main_udmap 0xca01>,
+		       <&main_udmap 0xca02>,
+		       <&main_udmap 0xca03>,
+		       <&main_udmap 0xca04>,
+		       <&main_udmap 0xca05>,
+		       <&main_udmap 0xca06>,
+		       <&main_udmap 0xca07>,
+		       <&main_udmap 0x4a00>;
+		dma-names = "tx0", "tx1", "tx2", "tx3",
+			    "tx4", "tx5", "tx6", "tx7",
+			    "rx";
+
+		status = "disabled";
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cpsw0_port1: port@1 {
+				reg = <1>;
+				ti,mac-only;
+				label = "port1";
+				status = "disabled";
+			};
+
+			cpsw0_port2: port@2 {
+				reg = <2>;
+				ti,mac-only;
+				label = "port2";
+				status = "disabled";
+			};
+
+			cpsw0_port3: port@3 {
+				reg = <3>;
+				ti,mac-only;
+				label = "port3";
+				status = "disabled";
+			};
+
+			cpsw0_port4: port@4 {
+				reg = <4>;
+				ti,mac-only;
+				label = "port4";
+				status = "disabled";
+			};
+		};
+
+		cpsw5g_mdio: mdio@f00 {
+			compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+			reg = <0x00 0xf00 0x00 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&k3_clks 19 33>;
+			clock-names = "fck";
+			bus_freq = <1000000>;
+			status = "disabled";
+		};
+
+		cpts@3d000 {
+			compatible = "ti,j721e-cpts";
+			reg = <0x00 0x3d000 0x00 0x400>;
+			clocks = <&k3_clks 19 16>;
+			clock-names = "cpts";
+			interrupts-extended = <&gic500 GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "cpts";
+			ti,cpts-ext-ts-inputs = <4>;
+			ti,cpts-periodic-outputs = <2>;
+		};
+	};
+
 	main_pmx0: pinctrl@11c000 {
 		compatible = "pinctrl-single";
 		/* Proxy 0 addressing */
@@ -319,6 +419,7 @@
 		power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 146 2>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart1: serial@2810000 {
@@ -330,6 +431,7 @@
 		power-domains = <&k3_pds 278 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 278 2>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart2: serial@2820000 {
@@ -341,6 +443,7 @@
 		power-domains = <&k3_pds 279 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 279 2>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart3: serial@2830000 {
@@ -352,6 +455,7 @@
 		power-domains = <&k3_pds 280 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 280 2>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart4: serial@2840000 {
@@ -363,6 +467,7 @@
 		power-domains = <&k3_pds 281 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 281 2>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart5: serial@2850000 {
@@ -374,6 +479,7 @@
 		power-domains = <&k3_pds 282 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 282 2>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart6: serial@2860000 {
@@ -385,6 +491,7 @@
 		power-domains = <&k3_pds 283 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 283 2>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart7: serial@2870000 {
@@ -396,6 +503,7 @@
 		power-domains = <&k3_pds 284 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 284 2>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart8: serial@2880000 {
@@ -407,6 +515,7 @@
 		power-domains = <&k3_pds 285 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 285 2>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart9: serial@2890000 {
@@ -418,6 +527,7 @@
 		power-domains = <&k3_pds 286 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 286 2>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_i2c0: i2c@2000000 {
@@ -429,6 +539,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 187 1>;
 		power-domains = <&k3_pds 187 TI_SCI_PD_SHARED>;
+		status = "disabled";
 	};
 
 	main_i2c1: i2c@2010000 {
@@ -440,6 +551,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 188 1>;
 		power-domains = <&k3_pds 188 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c2: i2c@2020000 {
@@ -451,6 +563,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 189 1>;
 		power-domains = <&k3_pds 189 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c3: i2c@2030000 {
@@ -462,6 +575,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 190 1>;
 		power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c4: i2c@2040000 {
@@ -473,6 +587,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 191 1>;
 		power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c5: i2c@2050000 {
@@ -484,6 +599,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 192 1>;
 		power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c6: i2c@2060000 {
@@ -495,6 +611,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 193 1>;
 		power-domains = <&k3_pds 193 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_sdhci0: mmc@4f80000 {
@@ -627,6 +744,20 @@
 		ranges = <0x01000000 0x0 0x18001000  0x00 0x18001000  0x0 0x0010000>,
 			 <0x02000000 0x0 0x18011000  0x00 0x18011000  0x0 0x7fef000>;
 		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie1_intc 0>, /* INT A */
+				<0 0 0 2 &pcie1_intc 0>, /* INT B */
+				<0 0 0 3 &pcie1_intc 0>, /* INT C */
+				<0 0 0 4 &pcie1_intc 0>; /* INT D */
+
+		pcie1_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			#address-cells = <0>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 324 IRQ_TYPE_EDGE_RISING>;
+		};
 	};
 
 	pcie1_ep: pcie-ep@2910000 {
@@ -748,6 +879,94 @@
 		clock-names = "gpio";
 	};
 
+	main_spi0: spi@2100000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02100000 0x00 0x400>;
+		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 266 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 266 1>;
+		status = "disabled";
+	};
+
+	main_spi1: spi@2110000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02110000 0x00 0x400>;
+		interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 267 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 267 1>;
+		status = "disabled";
+	};
+
+	main_spi2: spi@2120000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02120000 0x00 0x400>;
+		interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 268 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 268 1>;
+		status = "disabled";
+	};
+
+	main_spi3: spi@2130000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02130000 0x00 0x400>;
+		interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 269 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 269 1>;
+		status = "disabled";
+	};
+
+	main_spi4: spi@2140000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02140000 0x00 0x400>;
+		interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 270 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 270 1>;
+		status = "disabled";
+	};
+
+	main_spi5: spi@2150000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02150000 0x00 0x400>;
+		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 271 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 271 1>;
+		status = "disabled";
+	};
+
+	main_spi6: spi@2160000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02160000 0x00 0x400>;
+		interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 272 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 272 1>;
+		status = "disabled";
+	};
+
+	main_spi7: spi@2170000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02170000 0x00 0x400>;
+		interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 273 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 273 1>;
+		status = "disabled";
+	};
+
 	watchdog0: watchdog@2200000 {
 		compatible = "ti,j7-rti-wdt";
 		reg = <0x0 0x2200000 0x0 0x100>;
@@ -768,7 +987,7 @@
 
 	main_r5fss0: r5fss@5c00000 {
 		compatible = "ti,j7200-r5fss";
-		ti,cluster-mode = <1>;
+		ti,cluster-mode = <0>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0x5c00000 0x00 0x5c00000 0x20000>,
@@ -805,4 +1024,15 @@
 			ti,loczrama = <1>;
 		};
 	};
+
+	timesync_router: pinctrl@a40000 {
+		compatible = "pinctrl-single";
+		reg = <0x0 0xa40000 0x0 0x800>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0x000107ff>;
+		status = "disabled";
+	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -106,6 +106,7 @@
 		power-domains = <&k3_pds 287 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 287 2>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	mcu_uart0: serial@40a00000 {
@@ -117,6 +118,7 @@
 		power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 149 2>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	wkup_gpio_intr: interrupt-controller@42200000 {
@@ -276,6 +278,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 194 1>;
 		power-domains = <&k3_pds 194 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcu_i2c1: i2c@40b10000 {
@@ -287,6 +290,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 195 1>;
 		power-domains = <&k3_pds 195 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	wkup_i2c0: i2c@42120000 {
@@ -298,6 +302,40 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 197 1>;
 		power-domains = <&k3_pds 197 TI_SCI_PD_SHARED>;
+		status = "disabled";
+	};
+
+	mcu_spi0: spi@40300000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x040300000 0x00 0x400>;
+		interrupts = <GIC_SPI 848 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 274 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 274 0>;
+		status = "disabled";
+	};
+
+	mcu_spi1: spi@40310000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x040310000 0x00 0x400>;
+		interrupts = <GIC_SPI 849 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 275 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 275 0>;
+		status = "disabled";
+	};
+
+	mcu_spi2: spi@40320000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x040320000 0x00 0x400>;
+		interrupts = <GIC_SPI 850 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 276 0>;
+		status = "disabled";
 	};
 
 	fss: syscon@47000000 {
@@ -365,7 +403,7 @@
 
 	mcu_r5fss0: r5fss@41000000 {
 		compatible = "ti,j7200-r5fss";
-		ti,cluster-mode = <1>;
+		ti,cluster-mode = <0>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0x41000000 0x00 0x41000000 0x20000>,
@@ -421,4 +459,20 @@
 			status = "disabled"; /* Used by OP-TEE */
 		};
 	};
+
+	wkup_vtm0: temperature-sensor@42040000 {
+		compatible = "ti,j7200-vtm";
+		reg = <0x00 0x42040000 0x00 0x350>,
+		      <0x00 0x42050000 0x00 0x350>,
+		      <0x00 0x43000300 0x00 0x10>;
+		power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
+		#thermal-sensor-cells = <1>;
+	};
+
+	mcu_esm: esm@40800000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x00 0x40800000 0x00 0x1000>;
+		ti,esm-pins = <95>;
+		bootph-pre-ram;
+	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -118,6 +118,25 @@
 	};
 };
 
+&wkup_pmx2 {
+	/* wkup_pmx2 starts at 0x68 */
+	wkup_i2c0_pins_default: wkup-i2c0-pins-default {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0x98, PIN_INPUT_PULLUP, 0) /* (F20) WKUP_I2C0_SCL */
+			J721E_WKUP_IOPAD(0x9c, PIN_INPUT_PULLUP, 0) /* (H21) WKUP_I2C0_SDA */
+		>;
+	};
+};
+
+&wkup_pmx3 {
+	/* wkup_pmx3 starts at 0x174 */
+	pmic_irq_pins_default: pmic-irq-pins-default {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0x1c, PIN_INPUT, 7) /* (E18) WKUP_GPIO0_84 */
+		>;
+	};
+};
+
 &main_pmx0 {
 	main_i2c0_pins_default: main-i2c0-pins-default {
 		pinctrl-single,pins = <
@@ -140,10 +159,42 @@
 	flash@0,0 {
 		compatible = "cypress,hyperflash", "cfi-flash";
 		reg = <0x00 0x00 0x4000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "hbmc.tiboot3";
+				reg = <0x0 0x100000>;
+			};
+
+			partition@100000 {
+				label = "hbmc.tispl";
+				reg = <0x100000 0x200000>;
+			};
+
+			partition@300000 {
+				label = "hbmc.u-boot";
+				reg = <0x300000 0x400000>;
+			};
+
+			partition@700000 {
+				label = "hbmc.env";
+				reg = <0x700000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "hbmc.rootfs";
+				reg = <0x800000 0x3800000>;
+			};
+		};
 	};
 };
 
 &mailbox0_cluster0 {
+	status = "okay";
 	interrupts = <436>;
 
 	mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
@@ -158,6 +209,7 @@
 };
 
 &mailbox0_cluster1 {
+	status = "okay";
 	interrupts = <432>;
 
 	mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
@@ -171,46 +223,6 @@
 	};
 };
 
-&mailbox0_cluster2 {
-	status = "disabled";
-};
-
-&mailbox0_cluster3 {
-	status = "disabled";
-};
-
-&mailbox0_cluster4 {
-	status = "disabled";
-};
-
-&mailbox0_cluster5 {
-	status = "disabled";
-};
-
-&mailbox0_cluster6 {
-	status = "disabled";
-};
-
-&mailbox0_cluster7 {
-	status = "disabled";
-};
-
-&mailbox0_cluster8 {
-	status = "disabled";
-};
-
-&mailbox0_cluster9 {
-	status = "disabled";
-};
-
-&mailbox0_cluster10 {
-	status = "disabled";
-};
-
-&mailbox0_cluster11 {
-	status = "disabled";
-};
-
 &mcu_r5fss0_core0 {
 	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
 	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
@@ -267,5 +279,202 @@
 		cdns,tchsh-ns = <60>;
 		cdns,tslch-ns = <60>;
 		cdns,read-delay = <4>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi.tiboot3";
+				reg = <0x0 0x100000>;
+			};
+
+			partition@100000 {
+				label = "ospi.tispl";
+				reg = <0x100000 0x200000>;
+			};
+
+			partition@300000 {
+				label = "ospi.u-boot";
+				reg = <0x300000 0x400000>;
+			};
+
+			partition@700000 {
+				label = "ospi.env";
+				reg = <0x700000 0x40000>;
+			};
+
+			partition@740000 {
+				label = "ospi.env.backup";
+				reg = <0x740000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "ospi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fc0000 {
+				label = "ospi.phypattern";
+				reg = <0x3fc0000 0x40000>;
+			};
+		};
+	};
+};
+
+&wkup_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_i2c0_pins_default>;
+	clock-frequency = <400000>;
+
+	tps659414: pmic@48 {
+		compatible = "ti,tps6594-q1";
+		reg = <0x48>;
+		ti,primary-pmic;
+		system-power-controller;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_irq_pins_default>;
+		interrupt-parent = <&wkup_gpio0>;
+		interrupts = <84 IRQ_TYPE_EDGE_FALLING>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		buck1-supply = <&vsys_3v3>;
+		buck2-supply = <&vsys_3v3>;
+		buck3-supply = <&vsys_3v3>;
+		buck4-supply = <&vsys_3v3>;
+		buck5-supply = <&vsys_3v3>;
+		ldo1-supply = <&vsys_3v3>;
+		ldo2-supply = <&vsys_3v3>;
+		ldo3-supply = <&vsys_3v3>;
+		ldo4-supply = <&vsys_3v3>;
+
+		regulators {
+			bucka1: buck1 {
+				regulator-name = "vda_mcu_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			bucka2: buck2 {
+				regulator-name = "vdd_mcuio_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			bucka3: buck3 {
+				regulator-name = "vdd_mcu_0v85";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			bucka4: buck4 {
+				regulator-name = "vdd_ddr_1v1";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			bucka5: buck5 {
+				regulator-name = "vdd_phyio_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa1: ldo1 {
+				regulator-name = "vdd1_lpddr4_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa2: ldo2 {
+				regulator-name = "vda_dll_0v8";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa3: ldo3 {
+				regulator-name = "vdd_wk_0v8";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa4: ldo4 {
+				regulator-name = "vda_pll_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+
+	lp876441: pmic@4c {
+		compatible = "ti,lp8764-q1";
+		reg = <0x4c>;
+		system-power-controller;
+		interrupt-parent = <&wkup_gpio0>;
+		interrupts = <84 IRQ_TYPE_EDGE_FALLING>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		buck1-supply = <&vsys_3v3>;
+		buck2-supply = <&vsys_3v3>;
+		buck3-supply = <&vsys_3v3>;
+		buck4-supply = <&vsys_3v3>;
+
+		regulators: regulators {
+			buckb1: buck1 {
+				regulator-name = "vdd_cpu_avs";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <900000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buckb2: buck2 {
+				regulator-name = "vdd_ram_0v85";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buckb3: buck3 {
+				regulator-name = "vdd_core_0v85";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buckb4: buck4 {
+				regulator-name = "vdd_io_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
 	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j7200-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-thermal.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j7200-thermal.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j7200-thermal.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/thermal/thermal.h>
+
+thermal_zones: thermal-zones {
+	mcu_thermal: mcu-thermal {
+		polling-delay-passive = <250>; /* milliseconds */
+		polling-delay = <500>; /* milliseconds */
+		thermal-sensors = <&wkup_vtm0 0>;
+
+		trips {
+			wkup_crit: wkup-crit {
+				temperature = <125000>; /* milliCelsius */
+				hysteresis = <2000>; /* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+
+	mpu_thermal: mpu-thermal {
+		polling-delay-passive = <250>; /* milliseconds */
+		polling-delay = <500>; /* milliseconds */
+		thermal-sensors = <&wkup_vtm0 1>;
+
+		trips {
+			mpu_crit: mpu-crit {
+				temperature = <125000>; /* milliCelsius */
+				hysteresis = <2000>; /* milliCelsius */
+				type = "critical";
+			};
+
+			mpu_alert0: mpu_alert {
+				temperature = <75000>; /* millicelsius */
+				hysteresis = <5000>; /* millicelsius */
+				type = "passive";
+			};
+		};
+
+		cpu_cooling_maps: cooling-maps {
+			map0 {
+				trip = <&mpu_alert0>;
+				cooling-device =
+				<&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+			};
+		};
+	};
+
+	main_thermal: main-thermal {
+		polling-delay-passive = <250>; /* milliseconds */
+		polling-delay = <500>; /* milliseconds */
+		thermal-sensors = <&wkup_vtm0 2>;
+
+		trips {
+			c7x_crit: c7x-crit {
+				temperature = <125000>; /* milliCelsius */
+				hysteresis = <2000>; /* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64-dsi-rpi-7inch-panel.dtso b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64-dsi-rpi-7inch-panel.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64-dsi-rpi-7inch-panel.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64-dsi-rpi-7inch-panel.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for RPi 7inch touchscreen panel interfaced with DSI on
+ * J721E based BeagleBone AI-64 (BBAI-64) platform.
+ *
+ * BBAI-64: https://www.beagleboard.org/boards/beaglebone-ai-64
+ * RPi DSI Panel: https://www.raspberrypi.com/products/raspberry-pi-touch-display/
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	bridge_reg: bridge-regulator {
+		compatible = "regulator-fixed";
+		regulator-name = "bridge-reg";
+		gpio = <&display_reg 0 0>;
+		vin-supply = <&display_reg>;
+		enable-active-high;
+	};
+
+	panel0 {
+		compatible = "raspberrypi,7inch-dsi", "simple-panel";
+		backlight = <&display_reg>;
+		power-supply = <&display_reg>;
+		port {
+			panel_in: endpoint {
+				remote-endpoint = <&panel_bridge_out>;
+			};
+		};
+	};
+};
+
+&main_pmx0 {
+	dsi_main_i2c4_pins: dsi-main-i2c4-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0xa8, PIN_INPUT_PULLUP, 2) /* (AD19) PRG1_MDIO0_MDIO.I2C4_SCL */
+			J721E_IOPAD(0xac, PIN_INPUT_PULLUP, 2) /* (AD18) PRG1_MDIO0_MDC.I2C4_SDA */
+		>;
+	};
+};
+
+&main_i2c4 {
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&dsi_main_i2c4_pins>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	display_reg: regulator@45 {
+		compatible = "raspberrypi,7inch-touchscreen-panel-regulator";
+		reg = <0x45>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	touch-controller@38 {
+		compatible = "edt,edt-ft5406";
+		reg = <0x38>;
+
+		touchscreen-size-x = < 800 >;
+		touchscreen-size-y = < 480 >;
+
+		vcc-supply = <&display_reg>;
+		reset-gpio = <&display_reg 1 1>;
+
+		touchscreen-inverted-x;
+		touchscreen-inverted-y;
+	};
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@2 {
+		reg = <2>;
+
+		dpi2_out: endpoint {
+			remote-endpoint = <&dsi0_in>;
+		};
+	};
+};
+
+&dphy2 {
+	status = "okay";
+};
+
+&dsi0 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	ports {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		port@0 {
+			reg = <0>;
+			dsi0_out: endpoint {
+				remote-endpoint = <&panel_bridge_in>;
+			};
+		};
+
+		port@1 {
+			reg = <1>;
+			dsi0_in: endpoint {
+				remote-endpoint = <&dpi2_out>;
+			};
+		};
+	};
+
+	bridge@0 {
+		compatible = "toshiba,tc358762";
+		reg = <0>;
+		vddc-supply = <&bridge_reg>;
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				panel_bridge_in: endpoint {
+					remote-endpoint = <&dsi0_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				panel_bridge_out: endpoint {
+					remote-endpoint = <&panel_in>;
+				};
+			};
+		};
+	};
+
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts
--- a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,1051 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * https://beagleboard.org/ai-64
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2022 Jason Kridner, BeagleBoard.org Foundation
+ * Copyright (C) 2022 Robert Nelson, BeagleBoard.org Foundation
+ */
+
+/dts-v1/;
+
+#include "k3-j721e.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/phy/phy-cadence.h>
+
+/ {
+	compatible = "beagle,j721e-beagleboneai64", "ti,j721e";
+	model = "BeagleBoard.org BeagleBone AI-64";
+
+	aliases {
+		serial2 = &main_uart0;
+		mmc0 = &main_sdhci0;
+		mmc1 = &main_sdhci1;
+		i2c0 = &wkup_i2c0;
+		i2c1 = &main_i2c6;
+		i2c2 = &main_i2c2;
+		i2c3 = &main_i2c4;
+	};
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+		base_dtb = "k3-j721e-beagleboneai64.dts";
+		base_dtb_timestamp = __TIMESTAMP__;
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		/* 4G RAM */
+		reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
+		      <0x00000008 0x80000000 0x00000000 0x80000000>;
+	};
+
+	reserved_memory: reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		secure_ddr: optee@9e800000 {
+			reg = <0x00 0x9e800000 0x00 0x01800000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa0000000 0x00 0x100000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa0100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa1000000 0x00 0x100000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa1100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa2000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss0_core0_memory_region: r5f-memory@a2100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa2100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa3000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss0_core1_memory_region: r5f-memory@a3100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa3100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa4000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss1_core0_memory_region: r5f-memory@a4100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa4100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa5000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss1_core1_memory_region: r5f-memory@a5100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa5100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		c66_1_dma_memory_region: c66-dma-memory@a6000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa6000000 0x00 0x100000>;
+			no-map;
+		};
+
+		c66_0_memory_region: c66-memory@a6100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa6100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		c66_0_dma_memory_region: c66-dma-memory@a7000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa7000000 0x00 0x100000>;
+			no-map;
+		};
+
+		c66_1_memory_region: c66-memory@a7100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa7100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		c71_0_dma_memory_region: c71-dma-memory@a8000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa8000000 0x00 0x100000>;
+			no-map;
+		};
+
+		c71_0_memory_region: c71-memory@a8100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa8100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		rtos_ipc_memory_region: ipc-memories@aa000000 {
+			reg = <0x00 0xaa000000 0x00 0x01c00000>;
+			alignment = <0x1000>;
+			no-map;
+		};
+	};
+
+	gpio_keys: gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&sw_pwr_pins_default>;
+
+		button-1 {
+			label = "BOOT";
+			linux,code = <BTN_0>;
+			gpios = <&wkup_gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+
+		button-2 {
+			label = "POWER";
+			linux,code = <KEY_POWER>;
+			gpios = <&wkup_gpio0 4 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins_default>;
+
+		led-0 {
+			label = "beaglebone:green:usr0";
+			gpios = <&main_gpio0 96 GPIO_ACTIVE_HIGH>;
+			function = LED_FUNCTION_HEARTBEAT;
+			linux,default-trigger = "heartbeat";
+		};
+
+		led-1 {
+			label = "beaglebone:green:usr1";
+			gpios = <&main_gpio0 95 GPIO_ACTIVE_HIGH>;
+			function = LED_FUNCTION_DISK_ACTIVITY;
+			linux,default-trigger = "mmc0";
+		};
+
+		led-2 {
+			label = "beaglebone:green:usr2";
+			gpios = <&main_gpio0 97 GPIO_ACTIVE_HIGH>;
+			function = LED_FUNCTION_CPU;
+			linux,default-trigger = "cpu";
+		};
+
+		led-3 {
+			label = "beaglebone:green:usr3";
+			gpios = <&main_gpio0 110 GPIO_ACTIVE_HIGH>;
+			function = LED_FUNCTION_DISK_ACTIVITY;
+			linux,default-trigger = "mmc1";
+		};
+
+		led-4 {
+			label = "beaglebone:green:usr4";
+			gpios = <&main_gpio0 109 GPIO_ACTIVE_HIGH>;
+			function = LED_FUNCTION_WLAN;
+			linux,default-trigger = "phy0tx";
+			default-state = "off";
+		};
+	};
+
+	evm_12v0: regulator-0 {
+		/* main supply */
+		compatible = "regulator-fixed";
+		regulator-name = "evm_12v0";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_3v3: regulator-1 {
+		/* Output of LMS140 */
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&evm_12v0>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_5v0: regulator-2 {
+		/* Output of LM5140 */
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_5v0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&evm_12v0>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vdd_mmc1: regulator-3 {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pwr_en_pins_default>;
+		regulator-name = "vdd_mmc1";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		enable-active-high;
+		vin-supply = <&vsys_3v3>;
+		gpio = <&main_gpio0 82 GPIO_ACTIVE_HIGH>;
+	};
+
+	vdd_sd_dv_alt: regulator-4 {
+		compatible = "regulator-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&vdd_sd_dv_alt_pins_default>;
+		regulator-name = "tlv71033";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		vin-supply = <&vsys_5v0>;
+		gpios = <&main_gpio0 117 GPIO_ACTIVE_HIGH>;
+		states = <1800000 0x0>,
+			 <3300000 0x1>;
+	};
+
+	dp_pwr_3v3: regulator-5 {
+		compatible = "regulator-fixed";
+		pinctrl-names = "default";
+		pinctrl-0 = <&dp0_3v3_en_pins_default>;
+		regulator-name = "dp-pwr";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&main_gpio0 49 GPIO_ACTIVE_HIGH>; /* DP0_PWR_SW_EN */
+		enable-active-high;
+	};
+
+	dp0: connector {
+		compatible = "dp-connector";
+		label = "DP0";
+		type = "full-size";
+		dp-pwr-supply = <&dp_pwr_3v3>;
+
+		port {
+			dp_connector_in: endpoint {
+				remote-endpoint = <&dp0_out>;
+			};
+		};
+	};
+};
+
+&main_pmx0 {
+	led_pins_default: led-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x184, PIN_INPUT, 7) /* (T23) RGMII5_RD0.GPIO0_96 */
+			J721E_IOPAD(0x180, PIN_INPUT, 7) /* (R23) RGMII5_RD1.GPIO0_95 */
+			J721E_IOPAD(0x188, PIN_INPUT, 7) /* (Y28) RGMII6_TX_CTL.GPIO0_97 */
+			J721E_IOPAD(0x1bc, PIN_INPUT, 7) /* (V24) MDIO0_MDC.GPIO0_110 */
+			J721E_IOPAD(0x1b8, PIN_INPUT, 7) /* (V26) MDIO0_MDIO.GPIO0_109 */
+		>;
+	};
+
+	main_mmc1_pins_default: main-mmc1-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x254, PIN_INPUT, 0) /* (R29) MMC1_CMD */
+			J721E_IOPAD(0x250, PIN_INPUT, 0) /* (P25) MMC1_CLK */
+			J721E_IOPAD(0x2ac, PIN_INPUT, 0) /* (P25) MMC1_CLKLB */
+			J721E_IOPAD(0x24c, PIN_INPUT, 0) /* (R24) MMC1_DAT0 */
+			J721E_IOPAD(0x248, PIN_INPUT, 0) /* (P24) MMC1_DAT1 */
+			J721E_IOPAD(0x244, PIN_INPUT, 0) /* (R25) MMC1_DAT2 */
+			J721E_IOPAD(0x240, PIN_INPUT, 0) /* (R26) MMC1_DAT3 */
+			J721E_IOPAD(0x258, PIN_INPUT, 0) /* (P23) MMC1_SDCD */
+		>;
+	};
+
+	main_uart0_pins_default: main-uart0-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x1e8, PIN_INPUT, 0) /* (AB2) UART0_RXD */
+			J721E_IOPAD(0x1ec, PIN_OUTPUT, 0) /* (AB3) UART0_TXD */
+		>;
+	};
+
+	sd_pwr_en_pins_default: sd-pwr-en-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x14c, PIN_INPUT, 7) /* (AA29) PRG0_PRU1_GPO19.GPIO0_82 */
+		>;
+	};
+
+	vdd_sd_dv_alt_pins_default: vdd-sd-dv-alt-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x1d8, PIN_INPUT, 7) /* (W4) SPI1_CS1.GPIO0_117 */
+		>;
+	};
+
+	main_usbss0_pins_default: main-usbss0-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x210, PIN_INPUT, 7) /* (W3) MCAN1_RX.GPIO1_3 - USBC_DIR */
+		>;
+	};
+
+	main_usbss1_pins_default: main-usbss1-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x290, INPUT_DISABLE, 1) /* (U6) USB0_DRVVBUS.USB1_DRVVBUS */
+		>;
+	};
+
+	dp0_3v3_en_pins_default:dp0-3v3-en-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0xc8, PIN_INPUT, 7) /* (AE26) PRG0_PRU0_GPO6.GPIO0_49 */
+		>;
+	};
+
+	dp0_pins_default: dp0-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x1c4, PIN_INPUT, 5) /* (Y4) SPI0_CS1.DP0_HPD */
+		>;
+	};
+
+	main_i2c0_pins_default: main-i2c0-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x220, PIN_INPUT_PULLUP, 0) /* (AC5) I2C0_SCL */
+			J721E_IOPAD(0x224, PIN_INPUT_PULLUP, 0) /* (AA5) I2C0_SDA */
+		>;
+	};
+
+	main_i2c1_pins_default: main-i2c1-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x228, PIN_INPUT_PULLUP, 0) /* (Y6) I2C1_SCL */
+			J721E_IOPAD(0x22c, PIN_INPUT_PULLUP, 0) /* (AA6) I2C1_SDA */
+		>;
+	};
+
+	main_i2c2_pins_default: main-i2c2-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x208, PIN_INPUT_PULLUP, 4) /* (W5) MCAN0_RX.I2C2_SCL */
+			J721E_IOPAD(0x20c, PIN_INPUT_PULLUP, 4) /* (W6) MCAN0_TX.I2C2_SDA */
+			J721E_IOPAD(0x138, PIN_INPUT, 7) /* (AE25) PRG0_PRU1_GPO14.GPIO0_77 */
+			J721E_IOPAD(0x13c, PIN_INPUT, 7) /* (AF29) PRG0_PRU1_GPO15.GPIO0_78 */
+		>;
+	};
+
+	main_i2c3_pins_default: main-i2c3-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x270, PIN_INPUT_PULLUP, 4) /* (T26) MMC2_CLK.I2C3_SCL */
+			J721E_IOPAD(0x274, PIN_INPUT_PULLUP, 4) /* (T25) MMC2_CMD.I2C3_SDA */
+		>;
+	};
+
+	main_i2c4_pins_default: main-i2c4-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x1e0, PIN_INPUT_PULLUP, 2) /* (Y5) SPI1_D0.I2C4_SCL */
+			J721E_IOPAD(0x1dc, PIN_INPUT_PULLUP, 2) /* (Y1) SPI1_CLK.I2C4_SDA */
+			J721E_IOPAD(0x30, PIN_INPUT, 7) /* (AF24) PRG1_PRU0_GPO11.GPIO0_12 */
+			J721E_IOPAD(0x34, PIN_INPUT, 7) /* (AJ24) PRG1_PRU0_GPO12.GPIO0_13 */
+		>;
+	};
+
+	main_i2c5_pins_default: main-i2c5-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x150, PIN_INPUT_PULLUP, 2) /* (Y26) PRG0_MDIO0_MDIO.I2C5_SCL */
+			J721E_IOPAD(0x154, PIN_INPUT_PULLUP, 2) /* (AA27) PRG0_MDIO0_MDC.I2C5_SDA */
+		>;
+	};
+
+	main_i2c6_pins_default: main-i2c6-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x1d0, PIN_INPUT_PULLUP, 2) /* (AA3) SPI0_D1.I2C6_SCL */
+			J721E_IOPAD(0x1e4, PIN_INPUT_PULLUP, 2) /* (Y2) SPI1_D1.I2C6_SDA */
+			J721E_IOPAD(0x74, PIN_INPUT, 7) /* (AC21) PRG1_PRU1_GPO7.GPIO0_28 */
+			J721E_IOPAD(0xa4, PIN_INPUT, 7) /* (AH22) PRG1_PRU1_GPO19.GPIO0_40 */
+		>;
+	};
+
+	csi0_gpio_pins_default: csi0-gpio-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x19c, PIN_INPUT_PULLDOWN, 7) /* (W27) RGMII6_TD0.GPIO0_102 */
+			J721E_IOPAD(0x1a0, PIN_INPUT_PULLDOWN, 7) /* (W29) RGMII6_TXC.GPIO0_103 */
+		>;
+	};
+
+	csi1_gpio_pins_default: csi1-gpio-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x198, PIN_INPUT_PULLDOWN, 7) /* (V25) RGMII6_TD1.GPIO0_101 */
+			J721E_IOPAD(0x1b0, PIN_INPUT_PULLDOWN, 7) /* (W24) RGMII6_RD1.GPIO0_107 */
+		>;
+	};
+
+	pcie1_rst_pins_default: pcie1-rst-default-pins {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x5c, PIN_INPUT, 7) /* (AG23) PRG1_PRU1_GPO1.GPIO0_22 */
+		>;
+	};
+};
+
+&wkup_pmx0 {
+	eeprom_wp_pins_default: eeprom-wp-default-pins {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0xc4, PIN_OUTPUT_PULLUP, 7) /* (G24) WKUP_GPIO0_5 */
+		>;
+	};
+
+	mcu_adc0_pins_default: mcu-adc0-default-pins {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0x130, PIN_INPUT, 0) /* (K25) MCU_ADC0_AIN0 */
+			J721E_WKUP_IOPAD(0x134, PIN_INPUT, 0) /* (K26) MCU_ADC0_AIN1 */
+			J721E_WKUP_IOPAD(0x138, PIN_INPUT, 0) /* (K28) MCU_ADC0_AIN2 */
+			J721E_WKUP_IOPAD(0x13c, PIN_INPUT, 0) /* (L28) MCU_ADC0_AIN3 */
+			J721E_WKUP_IOPAD(0x140, PIN_INPUT, 0) /* (K24) MCU_ADC0_AIN4 */
+			J721E_WKUP_IOPAD(0x144, PIN_INPUT, 0) /* (K27) MCU_ADC0_AIN5 */
+			J721E_WKUP_IOPAD(0x148, PIN_INPUT, 0) /* (K29) MCU_ADC0_AIN6 */
+		>;
+	};
+
+	mcu_adc1_pins_default: mcu-adc1-default-pins {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0x150, PIN_INPUT, 0) /* (N23) MCU_ADC1_AIN0 */
+		>;
+	};
+
+	mikro_bus_pins_default: mikro-bus-default-pins {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0x108, PIN_INPUT, 7) /* SDAPULLEN (E26) PMIC_POWER_EN0.WKUP_GPIO0_66 */
+			J721E_WKUP_IOPAD(0xd4, PIN_INPUT, 7) /* SDA (G26) WKUP_GPIO0_9.MCU_I2C1_SDA */
+			J721E_WKUP_IOPAD(0xf4, PIN_INPUT, 7) /* SDA (D25) MCU_I3C0_SDA.WKUP_GPIO0_61 */
+			J721E_WKUP_IOPAD(0xd0, PIN_INPUT, 7) /* SCL (G27) WKUP_GPIO0_8.MCU_I2C1_SCL */
+			J721E_WKUP_IOPAD(0xf0, PIN_INPUT, 7) /* SCL (D26) MCU_I3C0_SCL.WKUP_GPIO0_60 */
+
+			J721E_WKUP_IOPAD(0xb8, PIN_INPUT, 7) /* MOSI (F28) WKUP_GPIO0_2.MCU_SPI1_D1 */
+			J721E_WKUP_IOPAD(0xb4, PIN_INPUT, 7) /* MISO (F25) WKUP_GPIO0_1.MCU_SPI1_D0 */
+			J721E_WKUP_IOPAD(0xb0, PIN_INPUT, 7) /* CLK (F26) WKUP_GPIO0_0.MCU_SPI1_CLK */
+			J721E_WKUP_IOPAD(0xbc, PIN_INPUT, 7) /* CS (F27) WKUP_GPIO0_3.MCU_SPI1_CS0 */
+
+			J721E_WKUP_IOPAD(0x44, PIN_INPUT, 7) /* RX (G22) MCU_OSPI1_D1.WKUP_GPIO0_33 */
+			J721E_WKUP_IOPAD(0x48, PIN_INPUT, 7) /* TX (D23) MCU_OSPI1_D2.WKUP_GPIO0_34 */
+
+			J721E_WKUP_IOPAD(0x4c, PIN_INPUT, 7) /* INT (C23) MCU_OSPI1_D3.WKUP_GPIO0_35 */
+			J721E_WKUP_IOPAD(0x54, PIN_INPUT, 7) /* RST (E22) MCU_OSPI1_CSn1.WKUP_GPIO0_37 */
+			J721E_WKUP_IOPAD(0xdc, PIN_INPUT, 7) /* PWM (H27) WKUP_GPIO0_11 */
+			J721E_WKUP_IOPAD(0xac, PIN_INPUT, 7) /* AN (C29) MCU_MCAN0_RX.WKUP_GPIO0_59 */
+		>;
+	};
+
+	mcu_cpsw_pins_default: mcu-cpsw-default-pins {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0x84, PIN_INPUT, 0) /* (B24) MCU_RGMII1_RD0 */
+			J721E_WKUP_IOPAD(0x80, PIN_INPUT, 0) /* (A24) MCU_RGMII1_RD1 */
+			J721E_WKUP_IOPAD(0x7c, PIN_INPUT, 0) /* (D24) MCU_RGMII1_RD2 */
+			J721E_WKUP_IOPAD(0x78, PIN_INPUT, 0) /* (A25) MCU_RGMII1_RD3 */
+			J721E_WKUP_IOPAD(0x74, PIN_INPUT, 0) /* (C24) MCU_RGMII1_RXC */
+			J721E_WKUP_IOPAD(0x5c, PIN_INPUT, 0) /* (C25) MCU_RGMII1_RX_CTL */
+			J721E_WKUP_IOPAD(0x6c, PIN_OUTPUT, 0) /* (B25) MCU_RGMII1_TD0 */
+			J721E_WKUP_IOPAD(0x68, PIN_OUTPUT, 0) /* (A26) MCU_RGMII1_TD1 */
+			J721E_WKUP_IOPAD(0x64, PIN_OUTPUT, 0) /* (A27) MCU_RGMII1_TD2 */
+			J721E_WKUP_IOPAD(0x60, PIN_OUTPUT, 0) /* (A28) MCU_RGMII1_TD3 */
+			J721E_WKUP_IOPAD(0x70, PIN_OUTPUT, 0) /* (B26) MCU_RGMII1_TXC */
+			J721E_WKUP_IOPAD(0x58, PIN_OUTPUT, 0) /* (B27) MCU_RGMII1_TX_CTL */
+		>;
+	};
+
+	mcu_mdio_pins_default: mcu-mdio1-default-pins {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0x8c, PIN_OUTPUT, 0) /* (F23) MCU_MDIO0_MDC */
+			J721E_WKUP_IOPAD(0x88, PIN_INPUT, 0) /* (E23) MCU_MDIO0_MDIO */
+		>;
+	};
+
+	sw_pwr_pins_default: sw-pwr-default-pins {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0xc0, PIN_INPUT, 7) /* (G25) WKUP_GPIO0_4 */
+		>;
+	};
+
+	wkup_i2c0_pins_default: wkup-i2c0-default-pins {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0xf8, PIN_INPUT_PULLUP, 0) /* (J25) WKUP_I2C0_SCL */
+			J721E_WKUP_IOPAD(0xfc, PIN_INPUT_PULLUP, 0) /* (H24) WKUP_I2C0_SDA */
+		>;
+	};
+
+	wkup_uart0_pins_default: wkup-uart0-default-pins {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0xa0, PIN_INPUT, 0) /* (J29) WKUP_UART0_RXD */
+			J721E_WKUP_IOPAD(0xa4, PIN_OUTPUT, 0) /* (J28) WKUP_UART0_TXD */
+		>;
+	};
+
+	mcu_usbss1_pins_default: mcu-usbss1-default-pins {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0x3c, PIN_OUTPUT_PULLUP, 5) /* (A23) MCU_OSPI1_LBCLKO.WKUP_GPIO0_30 */
+		>;
+	};
+};
+
+&wkup_uart0 {
+	/* Wakeup UART is used by TIFS firmware. */
+	status = "reserved";
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_uart0_pins_default>;
+};
+
+&main_uart0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_uart0_pins_default>;
+	/* Shared with ATF on this platform */
+	power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
+};
+
+&main_sdhci0 {
+	/* eMMC */
+	status = "okay";
+	non-removable;
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
+};
+
+&main_sdhci1 {
+	/* SD Card */
+	status = "okay";
+	vmmc-supply = <&vdd_mmc1>;
+	vqmmc-supply = <&vdd_sd_dv_alt>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mmc1_pins_default>;
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
+};
+
+&main_sdhci2 {
+	/* Unused */
+	status = "disabled";
+};
+
+&ospi0 {
+	/* Unused */
+	status = "disabled";
+};
+
+&ospi1 {
+	/* Unused */
+	status = "disabled";
+};
+
+&main_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c0_pins_default>;
+	clock-frequency = <400000>;
+};
+
+&main_i2c1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c1_pins_default>;
+	clock-frequency = <400000>;
+};
+
+&main_i2c2 {
+	/* BBB Header: P9.19 and P9.20 */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c2_pins_default>;
+	clock-frequency = <100000>;
+};
+
+&main_i2c3 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c3_pins_default>;
+	clock-frequency = <400000>;
+};
+
+&main_i2c4 {
+	/* BBB Header: P9.24 and P9.26 */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c4_pins_default>;
+	clock-frequency = <100000>;
+};
+
+&main_i2c5 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c5_pins_default>;
+	clock-frequency = <400000>;
+};
+
+&main_i2c6 {
+	/* BBB Header: P9.17 and P9.18 */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c6_pins_default>;
+	clock-frequency = <100000>;
+	status = "okay";
+};
+
+&wkup_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_i2c0_pins_default>;
+	clock-frequency = <400000>;
+
+	eeprom@50 {
+		compatible = "atmel,24c04";
+		reg = <0x50>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&eeprom_wp_pins_default>;
+	};
+};
+
+&main_gpio2 {
+	/* Unused */
+	status = "disabled";
+};
+
+&main_gpio3 {
+	/* Unused */
+	status = "disabled";
+};
+
+&main_gpio4 {
+	/* Unused */
+	status = "disabled";
+};
+
+&main_gpio5 {
+	/* Unused */
+	status = "disabled";
+};
+
+&main_gpio6 {
+	/* Unused */
+	status = "disabled";
+};
+
+&main_gpio7 {
+	/* Unused */
+	status = "disabled";
+};
+
+&wkup_gpio0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_adc0_pins_default>, <&mcu_adc1_pins_default>,
+		    <&mikro_bus_pins_default>;
+};
+
+&wkup_gpio1 {
+	/* Unused */
+	status = "disabled";
+};
+
+&main_gpio0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&csi1_gpio_pins_default>, <&csi0_gpio_pins_default>;
+};
+
+&usb_serdes_mux {
+	idle-states = <1>, <1>; /* USB0 to SERDES3, USB1 to SERDES2 */
+};
+
+&serdes_ln_ctrl {
+	idle-states = <J721E_SERDES0_LANE0_IP4_UNUSED>, <J721E_SERDES0_LANE1_IP4_UNUSED>,
+		      <J721E_SERDES1_LANE0_PCIE1_LANE0>, <J721E_SERDES1_LANE1_PCIE1_LANE1>,
+		      <J721E_SERDES2_LANE0_IP1_UNUSED>, <J721E_SERDES2_LANE1_USB3_1>,
+		      <J721E_SERDES3_LANE0_USB3_0_SWAP>, <J721E_SERDES3_LANE1_USB3_0>,
+		      <J721E_SERDES4_LANE0_EDP_LANE0>, <J721E_SERDES4_LANE1_EDP_LANE1>,
+		      <J721E_SERDES4_LANE2_EDP_LANE2>, <J721E_SERDES4_LANE3_EDP_LANE3>;
+};
+
+&serdes_wiz3 {
+	typec-dir-gpios = <&main_gpio1 3 GPIO_ACTIVE_LOW>;
+	typec-dir-debounce-ms = <700>;	/* TUSB321, tCCB_DEFAULT 133 ms */
+};
+
+&serdes3 {
+	serdes3_usb_link: phy@0 {
+		reg = <0>;
+		cdns,num-lanes = <2>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_USB3>;
+		resets = <&serdes_wiz3 1>, <&serdes_wiz3 2>;
+	};
+};
+
+&serdes4 {
+	torrent_phy_dp: phy@0 {
+		reg = <0>;
+		resets = <&serdes_wiz4 1>;
+		cdns,phy-type = <PHY_TYPE_DP>;
+		cdns,num-lanes = <4>;
+		cdns,max-bit-rate = <5400>;
+		#phy-cells = <0>;
+	};
+};
+
+&mhdp {
+	phys = <&torrent_phy_dp>;
+	phy-names = "dpphy";
+	pinctrl-names = "default";
+	pinctrl-0 = <&dp0_pins_default>;
+};
+
+&usbss0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_usbss0_pins_default>;
+	ti,vbus-divider;
+};
+
+&usb0 {
+	dr_mode = "peripheral";
+	maximum-speed = "super-speed";
+	phys = <&serdes3_usb_link>;
+	phy-names = "cdns3,usb3-phy";
+};
+
+&serdes2 {
+	serdes2_usb_link: phy@1 {
+		reg = <1>;
+		cdns,num-lanes = <1>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_USB3>;
+		resets = <&serdes_wiz2 2>;
+	};
+};
+
+&usbss1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_usbss1_pins_default>, <&mcu_usbss1_pins_default>;
+	ti,vbus-divider;
+};
+
+&usb1 {
+	dr_mode = "host";
+	maximum-speed = "super-speed";
+	phys = <&serdes2_usb_link>;
+	phy-names = "cdns3,usb3-phy";
+};
+
+&tscadc0 {
+	status = "okay";
+	/* BBB Header: P9.39, P9.40, P9.37, P9.38, P9.33, P9.36, P9.35 */
+	adc {
+		ti,adc-channels = <0 1 2 3 4 5 6>;
+	};
+};
+
+&tscadc1 {
+	status = "okay";
+	/* MCU mikroBUS Header J10.1 - MCU_ADC1_AIN0 */
+	adc {
+		ti,adc-channels = <0>;
+	};
+};
+
+&mcu_cpsw {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_cpsw_pins_default>;
+};
+
+&davinci_mdio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mdio_pins_default>;
+
+	phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+	};
+};
+
+&cpsw_port1 {
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&phy0>;
+};
+
+&dss {
+	/*
+	 * These clock assignments are chosen to enable the following outputs:
+	 *
+	 * VP0 - DisplayPort SST
+	 * VP1 - DPI0
+	 * VP2 - DSI
+	 * VP3 - DPI1
+	 */
+
+	assigned-clocks = <&k3_clks 152 1>,	/* VP 1 pixel clock */
+			  <&k3_clks 152 4>,	/* VP 2 pixel clock */
+			  <&k3_clks 152 9>,	/* VP 3 pixel clock */
+			  <&k3_clks 152 13>;	/* VP 4 pixel clock */
+	assigned-clock-parents = <&k3_clks 152 2>,	/* PLL16_HSDIV0 */
+				 <&k3_clks 152 6>,	/* PLL19_HSDIV0 */
+				 <&k3_clks 152 11>,	/* PLL18_HSDIV0 */
+				 <&k3_clks 152 18>;	/* PLL23_HSDIV0 */
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@0 {
+		reg = <0>;
+
+		dpi0_out: endpoint {
+			remote-endpoint = <&dp0_in>;
+		};
+	};
+};
+
+&dp0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@0 {
+		reg = <0>;
+		dp0_in: endpoint {
+			remote-endpoint = <&dpi0_out>;
+		};
+	};
+
+	port@4 {
+		reg = <4>;
+		dp0_out: endpoint {
+			remote-endpoint = <&dp_connector_in>;
+		};
+	};
+};
+
+&serdes0 {
+	serdes0_pcie_link: phy@0 {
+		reg = <0>;
+		cdns,num-lanes = <1>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_PCIE>;
+		resets = <&serdes_wiz0 1>;
+	};
+};
+
+&serdes1 {
+	serdes1_pcie_link: phy@0 {
+		reg = <0>;
+		cdns,num-lanes = <2>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_PCIE>;
+		resets = <&serdes_wiz1 1>, <&serdes_wiz1 2>;
+	};
+};
+
+&pcie1_rc {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pcie1_rst_pins_default>;
+	phys = <&serdes1_pcie_link>;
+	phy-names = "pcie-phy";
+	num-lanes = <2>;
+	max-link-speed = <3>;
+	reset-gpios = <&main_gpio0 22 GPIO_ACTIVE_HIGH>;
+};
+
+&ufs_wrapper {
+	status = "disabled";
+};
+
+&mailbox0_cluster0 {
+	status = "okay";
+	interrupts = <436>;
+
+	mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster1 {
+	status = "okay";
+	interrupts = <432>;
+
+	mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster2 {
+	status = "okay";
+	interrupts = <428>;
+
+	mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster3 {
+	status = "okay";
+	interrupts = <424>;
+
+	mbox_c66_0: mbox-c66-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_c66_1: mbox-c66-1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster4 {
+	status = "okay";
+	interrupts = <420>;
+
+	mbox_c71_0: mbox-c71-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+};
+
+&mcu_r5fss0_core0 {
+	mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>;
+	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
+			<&mcu_r5fss0_core0_memory_region>;
+};
+
+&mcu_r5fss0_core1 {
+	mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>;
+	memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
+			<&mcu_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss0_core0 {
+	mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>;
+	memory-region = <&main_r5fss0_core0_dma_memory_region>,
+			<&main_r5fss0_core0_memory_region>;
+};
+
+&main_r5fss0_core1 {
+	mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>;
+	memory-region = <&main_r5fss0_core1_dma_memory_region>,
+			<&main_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss1_core0 {
+	mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core0>;
+	memory-region = <&main_r5fss1_core0_dma_memory_region>,
+			<&main_r5fss1_core0_memory_region>;
+};
+
+&main_r5fss1_core1 {
+	mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core1>;
+	memory-region = <&main_r5fss1_core1_dma_memory_region>,
+			<&main_r5fss1_core1_memory_region>;
+};
+
+&c66_0 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster3>, <&mbox_c66_0>;
+	memory-region = <&c66_0_dma_memory_region>,
+			<&c66_0_memory_region>;
+};
+
+&c66_1 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster3>, <&mbox_c66_1>;
+	memory-region = <&c66_1_dma_memory_region>,
+			<&c66_1_memory_region>;
+};
+
+&c71_0 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster4>, <&mbox_c71_0>;
+	memory-region = <&c71_0_dma_memory_region>,
+			<&c71_0_memory_region>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts
--- a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts	2024-01-28 14:01:31.240353775 -0500
@@ -96,7 +96,7 @@
 			 <3300000 0x1>;
 	};
 
-	sound0: sound@0 {
+	sound0: sound-0 {
 		compatible = "ti,j721e-cpb-audio";
 		model = "j721e-cpb";
 
@@ -363,45 +363,64 @@
 			J721E_WKUP_IOPAD(0xb8, PIN_INPUT, 7) /* (F28) WKUP_GPIO0_2 */
 		>;
 	};
+
+	wkup_gpio_pins_default: wkup-gpio-pins-default {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0xd0, PIN_INPUT, 7) /* (C14) WKUP_GPIO0_8 */
+		>;
+	};
+
+	mcu_uart0_pins_default: mcu-uart0-pins-default {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0xe8, PIN_INPUT, 0) /* (H29) WKUP_GPIO0_14.MCU_UART0_CTSn */
+			J721E_WKUP_IOPAD(0xec, PIN_OUTPUT, 0) /* (J27) WKUP_GPIO0_15.MCU_UART0_RTSn */
+			J721E_WKUP_IOPAD(0xe4, PIN_INPUT, 0) /* (H28) WKUP_GPIO0_13.MCU_UART0_RXD */
+			J721E_WKUP_IOPAD(0xe0, PIN_OUTPUT, 0) /* (G29) WKUP_GPIO0_12.MCU_UART0_TXD */
+		>;
+	};
+
+	wkup_uart0_pins_default: wkup-uart0-pins-default {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0xc8, PIN_INPUT, 0) /* (F29) WKUP_GPIO0_6.WKUP_UART0_CTSn */
+			J721E_WKUP_IOPAD(0xcc, PIN_OUTPUT, 0) /* (G28) WKUP_GPIO0_7.WKUP_UART0_RTSn */
+			J721E_WKUP_IOPAD(0xa0, PIN_INPUT, 0) /* (J29) WKUP_UART0_RXD */
+			J721E_WKUP_IOPAD(0xa4, PIN_OUTPUT, 0) /* (J28) WKUP_UART0_TXD */
+		>;
+	};
 };
 
 &wkup_uart0 {
 	/* Wakeup UART is used by System firmware */
 	status = "reserved";
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_uart0_pins_default>;
 };
 
-&main_uart0 {
-	power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
-};
-
-&main_uart3 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
-&main_uart5 {
-	/* UART not brought out */
-	status = "disabled";
+&mcu_uart0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_uart0_pins_default>;
 };
 
-&main_uart6 {
-	/* UART not brought out */
-	status = "disabled";
+&main_uart0 {
+	status = "okay";
+	/* Shared with ATF on this platform */
+	power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
 };
 
-&main_uart7 {
-	/* UART not brought out */
-	status = "disabled";
+&main_uart1 {
+	status = "okay";
+	/* Default pinmux */
 };
 
-&main_uart8 {
-	/* UART not brought out */
-	status = "disabled";
+&main_uart2 {
+	status = "okay";
+	/* Default pinmux */
 };
 
-&main_uart9 {
-	/* UART not brought out */
-	status = "disabled";
+&main_uart4 {
+	status = "okay";
+	/* Default pinmux */
 };
 
 &main_gpio2 {
@@ -428,6 +447,11 @@
 	status = "disabled";
 };
 
+&wkup_gpio0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_gpio_pins_default>;
+};
+
 &wkup_gpio1 {
 	status = "disabled";
 };
@@ -521,6 +545,52 @@
 		cdns,tchsh-ns = <60>;
 		cdns,tslch-ns = <60>;
 		cdns,read-delay = <2>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "qspi.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "qspi.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "qspi.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "qspi.env";
+				reg = <0x680000 0x20000>;
+			};
+
+			partition@6a0000 {
+				label = "qspi.env.backup";
+				reg = <0x6a0000 0x20000>;
+			};
+
+			partition@6c0000 {
+				label = "qspi.sysfw";
+				reg = <0x6c0000 0x100000>;
+			};
+
+			partition@800000 {
+				label = "qspi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fe0000 {
+				label = "qspi.phypattern";
+				reg = <0x3fe0000 0x20000>;
+			};
+		};
 	};
 };
 
@@ -537,6 +607,7 @@
 };
 
 &main_i2c0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c0_pins_default>;
 	clock-frequency = <400000>;
@@ -573,6 +644,7 @@
 };
 
 &main_i2c1 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c1_pins_default>;
 	clock-frequency = <400000>;
@@ -598,6 +670,7 @@
 };
 
 &main_i2c3 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c3_pins_default>;
 	clock-frequency = <400000>;
@@ -636,6 +709,7 @@
 };
 
 &main_i2c6 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c6_pins_default>;
 	clock-frequency = <400000>;
@@ -651,6 +725,11 @@
 &mcu_cpsw {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
+
+	cpts@3d000 {
+		/* Map HW4_TS_PUSH to GENF1 */
+		ti,pps = <3 1>;
+	};
 };
 
 &davinci_mdio {
@@ -713,47 +792,8 @@
 	};
 };
 
-&mcasp0 {
-	status = "disabled";
-};
-
-&mcasp1 {
-	status = "disabled";
-};
-
-&mcasp2 {
-	status = "disabled";
-};
-
-&mcasp3 {
-	status = "disabled";
-};
-
-&mcasp4 {
-	status = "disabled";
-};
-
-&mcasp5 {
-	status = "disabled";
-};
-
-&mcasp6 {
-	status = "disabled";
-};
-
-&mcasp7 {
-	status = "disabled";
-};
-
-&mcasp8 {
-	status = "disabled";
-};
-
-&mcasp9 {
-	status = "disabled";
-};
-
 &mcasp10 {
+	status = "okay";
 	#sound-dai-cells = <0>;
 
 	pinctrl-names = "default";
@@ -771,10 +811,6 @@
 	rx-num-evt = <0>;
 };
 
-&mcasp11 {
-	status = "disabled";
-};
-
 &cmn_refclk1 {
 	clock-frequency = <100000000>;
 };
@@ -854,7 +890,7 @@
 		resets = <&serdes_wiz4 1>;
 		cdns,phy-type = <PHY_TYPE_DP>;
 		cdns,num-lanes = <4>;
-		cdns,max-bit-rate = <5400>;
+		cdns,max-bit-rate = <2700>;
 		#phy-cells = <0>;
 	};
 };
@@ -867,6 +903,7 @@
 };
 
 &pcie0_rc {
+	status = "okay";
 	reset-gpios = <&exp1 6 GPIO_ACTIVE_HIGH>;
 	phys = <&serdes0_pcie_link>;
 	phy-names = "pcie-phy";
@@ -874,6 +911,7 @@
 };
 
 &pcie1_rc {
+	status = "okay";
 	reset-gpios = <&exp1 2 GPIO_ACTIVE_HIGH>;
 	phys = <&serdes1_pcie_link>;
 	phy-names = "pcie-phy";
@@ -881,117 +919,71 @@
 };
 
 &pcie2_rc {
+	status = "okay";
 	reset-gpios = <&exp2 20 GPIO_ACTIVE_HIGH>;
 	phys = <&serdes2_pcie_link>;
 	phy-names = "pcie-phy";
 	num-lanes = <2>;
 };
 
-&pcie0_ep {
-	phys = <&serdes0_pcie_link>;
-	phy-names = "pcie-phy";
-	num-lanes = <1>;
-	status = "disabled";
-};
-
-&pcie1_ep {
-	phys = <&serdes1_pcie_link>;
-	phy-names = "pcie-phy";
-	num-lanes = <2>;
-	status = "disabled";
-};
-
-&pcie2_ep {
-	phys = <&serdes2_pcie_link>;
-	phy-names = "pcie-phy";
-	num-lanes = <2>;
-	status = "disabled";
-};
-
-&pcie3_rc {
-	status = "disabled";
-};
-
-&pcie3_ep {
-	status = "disabled";
-};
-
-&icssg0_mdio {
-	status = "disabled";
-};
-
-&icssg1_mdio {
-	status = "disabled";
-};
-
 &mcu_mcan0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcu_mcan0_pins_default>;
 	phys = <&transceiver1>;
 };
 
 &mcu_mcan1 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcu_mcan1_pins_default>;
 	phys = <&transceiver2>;
 };
 
 &main_mcan0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_mcan0_pins_default>;
 	phys = <&transceiver3>;
 };
 
-&main_mcan1 {
-	status = "disabled";
-};
-
 &main_mcan2 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_mcan2_pins_default>;
 	phys = <&transceiver4>;
 };
 
-&main_mcan3 {
-	status = "disabled";
+&ti_csi2rx0 {
+	status = "okay";
+	/* MIPI-CSI Connector */
 };
 
-&main_mcan4 {
-	status = "disabled";
+&ti_csi2rx1 {
+	status = "okay";
+	/* MIPI-CSI Connector */
 };
 
-&main_mcan5 {
-	status = "disabled";
+&dphy0 {
+	status = "okay";
 };
 
-&main_mcan6 {
-	status = "disabled";
+&dphy1 {
+	status = "okay";
 };
 
-&main_mcan7 {
-	status = "disabled";
-};
+#define K3_TS_OFFSET(pa, val)	(0x4+(pa)*4) (0x10000 | val)
 
-&main_mcan8 {
-	status = "disabled";
-};
-
-&main_mcan9 {
-	status = "disabled";
-};
-
-&main_mcan10 {
-	status = "disabled";
-};
-
-&main_mcan11 {
-	status = "disabled";
-};
-
-&main_mcan12 {
-	status = "disabled";
-};
+&timesync_router {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_cpsw_cpts>;
 
-&main_mcan13 {
-	status = "disabled";
+	/* Use Time Sync Router to map GENF1 input to HW4_TS_PUSH output */
+	mcu_cpsw_cpts: mcu-cpsw-cpts {
+		pinctrl-single,pins = <
+			/* pps [mcu cpsw cpts genf1] in17 -> out25 [mcu cpsw cpts hw4_push] */
+			K3_TS_OFFSET(25, 17)
+			>;
+	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e.dtsi b/arch/arm64/boot/dts/ti/k3-j721e.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j721e.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -7,9 +7,10 @@
 
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/pinctrl/k3.h>
 #include <dt-bindings/soc/ti,sci_pm_domain.h>
 
+#include "k3-pinctrl.h"
+
 / {
 	model = "Texas Instruments K3 J721E SoC";
 	compatible = "ti,j721e";
@@ -86,6 +87,7 @@
 	L2_0: l2-cache0 {
 		compatible = "cache";
 		cache-level = <2>;
+		cache-unified;
 		cache-size = <0x100000>;
 		cache-line-size = <64>;
 		cache-sets = <1024>;
@@ -134,6 +136,7 @@
 			 <0x00 0x06000000 0x00 0x06000000 0x00 0x00400000>, /* USBSS0 */
 			 <0x00 0x06400000 0x00 0x06400000 0x00 0x00400000>, /* USBSS1 */
 			 <0x00 0x01000000 0x00 0x01000000 0x00 0x0af02400>, /* Most peripherals */
+			 <0x00 0x0c000000 0x00 0x0c000000 0x00 0x0d000000>, /* CPSW9G */
 			 <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>, /* MAIN NAVSS */
 			 <0x00 0x0d000000 0x00 0x0d000000 0x00 0x01800000>, /* PCIe Core*/
 			 <0x00 0x0e000000 0x00 0x0e000000 0x00 0x01800000>, /* PCIe Core*/
@@ -181,6 +184,8 @@
 				 <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; /* FSS OSPI1 data region 3*/
 		};
 	};
+
+	#include "k3-j721e-thermal.dtsi"
 };
 
 /* Now include the peripherals for each bus segments */
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-evm-csi2-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-j721e-evm-csi2-ov5640.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721e-evm-csi2-ov5640.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-evm-csi2-ov5640.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * LI OV5640 MIPI Camera module on MIPI CSI connector.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_ov5640_fixed: ov5640-xclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+&main_i2c6 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	ov5640: camera@3c {
+		compatible = "ovti,ov5640";
+		reg = <0x3c>;
+		clocks = <&clk_ov5640_fixed>;
+		clock-names = "xclk";
+		powerdown-gpios = <&exp5 0 GPIO_ACTIVE_LOW>;
+
+		port {
+			csi2_cam0: endpoint {
+				remote-endpoint = <&csi2rx0_in_sensor>;
+				clock-lanes = <0>;
+				data-lanes = <1 2>;
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-evm-fusion.dtso b/arch/arm64/boot/dts/ti/k3-j721e-evm-fusion.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721e-evm-fusion.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-evm-fusion.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay for Fusion (FPD-Link III) board on J721E EVM
+ * https://svtronics.com/portfolio/evm577pfusion-v1-0-fusion/
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_fusion_25M_fixed: fixed-clock-25M {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+
+&main_i2c6 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	deser@3d {
+		compatible = "ti,ds90ub960-q1";
+		reg = <0x3d>;
+		clocks = <&clk_fusion_25M_fixed>;
+		clock-names = "refclk";
+		i2c-alias-pool = <0x4a 0x4b 0x4c 0x4d 0x4e 0x4f>;
+
+		ds90ub960_0_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* CSI-2 TX */
+			port@4 {
+				reg = <4>;
+				ds90ub960_0_csi_out: endpoint {
+					clock-lanes = <0>;
+					data-lanes = <1 2 3 4>;
+					link-frequencies = /bits/ 64 <800000000>;
+					remote-endpoint = <&csi2_phy0>;
+				};
+			};
+		};
+
+		ds90ub960_0_links: links {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	deser@36 {
+		compatible = "ti,ds90ub960-q1";
+		reg = <0x36>;
+		clocks = <&clk_fusion_25M_fixed>;
+		clock-names = "refclk";
+		i2c-alias-pool = <0x5a 0x5b 0x5c 0x5d 0x5e 0x5f>;
+
+		ds90ub960_1_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* CSI-2 TX */
+			port@4 {
+				reg = <4>;
+				ds90ub960_1_csi_out: endpoint {
+					clock-lanes = <0>;
+					data-lanes = <1 2 3 4>;
+					link-frequencies = /bits/ 64 <800000000>;
+					remote-endpoint = <&csi2_phy1>;
+				};
+			};
+		};
+
+		ds90ub960_1_links: links {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2_phy0: endpoint {
+		remote-endpoint = <&ds90ub960_0_csi_out>;
+		clock-lanes = <0>;
+		data-lanes = <1 2 3 4>;
+		link-frequencies = /bits/ 64 <800000000>;
+	};
+};
+
+&csi1_port0 {
+	status = "okay";
+
+	csi2_phy1: endpoint {
+		remote-endpoint = <&ds90ub960_1_csi_out>;
+		clock-lanes = <0>;
+		data-lanes = <1 2 3 4>;
+		link-frequencies = /bits/ 64 <800000000>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-evm-gesi-exp-board.dtso b/arch/arm64/boot/dts/ti/k3-j721e-evm-gesi-exp-board.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721e-evm-gesi-exp-board.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-evm-gesi-exp-board.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for CPSW9G in RGMII mode using J7 GESI EXP BRD board with
+ * J721E board.
+ *
+ * GESI Board Product Link: https://www.ti.com/tool/J7EXPCXEVM
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	aliases {
+		ethernet1 = "/bus@100000/ethernet@c000000/ethernet-ports/port@1";
+		ethernet2 = "/bus@100000/ethernet@c000000/ethernet-ports/port@2";
+		ethernet3 = "/bus@100000/ethernet@c000000/ethernet-ports/port@3";
+		ethernet4 = "/bus@100000/ethernet@c000000/ethernet-ports/port@4";
+	};
+};
+
+&cpsw0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii1_pins_default
+		     &rgmii2_pins_default
+		     &rgmii3_pins_default
+		     &rgmii4_pins_default>;
+};
+
+&cpsw0_port1 {
+	status = "okay";
+	phy-handle = <&cpsw9g_phy12>;
+	phy-mode = "rgmii-rxid";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 1>;
+};
+
+&cpsw0_port2 {
+	status = "okay";
+	phy-handle = <&cpsw9g_phy15>;
+	phy-mode = "rgmii-rxid";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 2>;
+};
+
+&cpsw0_port3 {
+	status = "okay";
+	phy-handle = <&cpsw9g_phy0>;
+	phy-mode = "rgmii-rxid";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 3>;
+};
+
+&cpsw0_port4 {
+	status = "okay";
+	phy-handle = <&cpsw9g_phy3>;
+	phy-mode = "rgmii-rxid";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 4>;
+};
+
+&cpsw9g_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio0_pins_default>;
+	bus_freq = <1000000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	cpsw9g_phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+	cpsw9g_phy3: ethernet-phy@3 {
+		reg = <3>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+	cpsw9g_phy12: ethernet-phy@12 {
+		reg = <12>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+	cpsw9g_phy15: ethernet-phy@15 {
+		reg = <15>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+};
+
+&exp1 {
+	p15-hog {
+		/* P15 - EXP_MUX2 */
+		gpio-hog;
+		gpios = <13 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "EXP_MUX2";
+	};
+
+	p16-hog {
+		/* P16 - EXP_MUX3 */
+		gpio-hog;
+		gpios = <14 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "EXP_MUX3";
+	};
+};
+
+&main_pmx0 {
+	mdio0_pins_default: mdio0-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x1bc, PIN_OUTPUT, 0) /* (V24) MDIO0_MDC */
+			J721E_IOPAD(0x1b8, PIN_INPUT, 0) /* (V26) MDIO0_MDIO */
+		>;
+	};
+
+	rgmii1_pins_default: rgmii1-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x4, PIN_INPUT, 4) /* (AC23) PRG1_PRU0_GPO0.RGMII1_RD0 */
+			J721E_IOPAD(0x8, PIN_INPUT, 4) /* (AG22) PRG1_PRU0_GPO1.RGMII1_RD1 */
+			J721E_IOPAD(0xc, PIN_INPUT, 4) /* (AF22) PRG1_PRU0_GPO2.RGMII1_RD2 */
+			J721E_IOPAD(0x10, PIN_INPUT, 4) /* (AJ23) PRG1_PRU0_GPO3.RGMII1_RD3 */
+			J721E_IOPAD(0x1c, PIN_INPUT, 4) /* (AD22) PRG1_PRU0_GPO6.RGMII1_RXC */
+			J721E_IOPAD(0x14, PIN_INPUT, 4) /* (AH23) PRG1_PRU0_GPO4.RGMII1_RX_CTL */
+			J721E_IOPAD(0x30, PIN_OUTPUT, 4) /* (AF24) PRG1_PRU0_GPO11.RGMII1_TD0 */
+			J721E_IOPAD(0x34, PIN_OUTPUT, 4) /* (AJ24) PRG1_PRU0_GPO12.RGMII1_TD1 */
+			J721E_IOPAD(0x38, PIN_OUTPUT, 4) /* (AG24) PRG1_PRU0_GPO13.RGMII1_TD2 */
+			J721E_IOPAD(0x3c, PIN_OUTPUT, 4) /* (AD24) PRG1_PRU0_GPO14.RGMII1_TD3 */
+			J721E_IOPAD(0x44, PIN_OUTPUT, 4) /* (AE24) PRG1_PRU0_GPO16.RGMII1_TXC */
+			J721E_IOPAD(0x40, PIN_OUTPUT, 4) /* (AC24) PRG1_PRU0_GPO15.RGMII1_TX_CTL */
+		>;
+	};
+
+	rgmii2_pins_default: rgmii2-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x58, PIN_INPUT, 4) /* (AE22) PRG1_PRU1_GPO0.RGMII2_RD0 */
+			J721E_IOPAD(0x5c, PIN_INPUT, 4) /* (AG23) PRG1_PRU1_GPO1.RGMII2_RD1 */
+			J721E_IOPAD(0x60, PIN_INPUT, 4) /* (AF23) PRG1_PRU1_GPO2.RGMII2_RD2 */
+			J721E_IOPAD(0x64, PIN_INPUT, 4) /* (AD23) PRG1_PRU1_GPO3.RGMII2_RD3 */
+			J721E_IOPAD(0x70, PIN_INPUT, 4) /* (AE23) PRG1_PRU1_GPO6.RGMII2_RXC */
+			J721E_IOPAD(0x68, PIN_INPUT, 4) /* (AH24) PRG1_PRU1_GPO4.RGMII2_RX_CTL */
+			J721E_IOPAD(0x84, PIN_OUTPUT, 4) /* (AJ25) PRG1_PRU1_GPO11.RGMII2_TD0 */
+			J721E_IOPAD(0x88, PIN_OUTPUT, 4) /* (AH25) PRG1_PRU1_GPO12.RGMII2_TD1 */
+			J721E_IOPAD(0x8c, PIN_OUTPUT, 4) /* (AG25) PRG1_PRU1_GPO13.RGMII2_TD2 */
+			J721E_IOPAD(0x90, PIN_OUTPUT, 4) /* (AH26) PRG1_PRU1_GPO14.RGMII2_TD3 */
+			J721E_IOPAD(0x98, PIN_OUTPUT, 4) /* (AJ26) PRG1_PRU1_GPO16.RGMII2_TXC */
+			J721E_IOPAD(0x94, PIN_OUTPUT, 4) /* (AJ27) PRG1_PRU1_GPO15.RGMII2_TX_CTL */
+		>;
+	};
+
+	rgmii3_pins_default: rgmii3-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0xb0, PIN_INPUT, 4) /* (AF28) PRG0_PRU0_GPO0.RGMII3_RD0 */
+			J721E_IOPAD(0xb4, PIN_INPUT, 4) /* (AE28) PRG0_PRU0_GPO1.RGMII3_RD1 */
+			J721E_IOPAD(0xb8, PIN_INPUT, 4) /* (AE27) PRG0_PRU0_GPO2.RGMII3_RD2 */
+			J721E_IOPAD(0xbc, PIN_INPUT, 4) /* (AD26) PRG0_PRU0_GPO3.RGMII3_RD3 */
+			J721E_IOPAD(0xc8, PIN_INPUT, 4) /* (AE26) PRG0_PRU0_GPO6.RGMII3_RXC */
+			J721E_IOPAD(0xc0, PIN_INPUT, 4) /* (AD25) PRG0_PRU0_GPO4.RGMII3_RX_CTL */
+			J721E_IOPAD(0xdc, PIN_OUTPUT, 4) /* (AJ28) PRG0_PRU0_GPO11.RGMII3_TD0 */
+			J721E_IOPAD(0xe0, PIN_OUTPUT, 4) /* (AH27) PRG0_PRU0_GPO12.RGMII3_TD1 */
+			J721E_IOPAD(0xe4, PIN_OUTPUT, 4) /* (AH29) PRG0_PRU0_GPO13.RGMII3_TD2 */
+			J721E_IOPAD(0xe8, PIN_OUTPUT, 4) /* (AG28) PRG0_PRU0_GPO14.RGMII3_TD3 */
+			J721E_IOPAD(0xf0, PIN_OUTPUT, 4) /* (AH28) PRG0_PRU0_GPO16.RGMII3_TXC */
+			J721E_IOPAD(0xec, PIN_OUTPUT, 4) /* (AG27) PRG0_PRU0_GPO15.RGMII3_TX_CTL */
+		>;
+	};
+
+	rgmii4_pins_default: rgmii4-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x100, PIN_INPUT, 4) /* (AE29) PRG0_PRU1_GPO0.RGMII4_RD0 */
+			J721E_IOPAD(0x104, PIN_INPUT, 4) /* (AD28) PRG0_PRU1_GPO1.RGMII4_RD1 */
+			J721E_IOPAD(0x108, PIN_INPUT, 4) /* (AD27) PRG0_PRU1_GPO2.RGMII4_RD2 */
+			J721E_IOPAD(0x10c, PIN_INPUT, 4) /* (AC25) PRG0_PRU1_GPO3.RGMII4_RD3 */
+			J721E_IOPAD(0x118, PIN_INPUT, 4) /* (AC26) PRG0_PRU1_GPO6.RGMII4_RXC */
+			J721E_IOPAD(0x110, PIN_INPUT, 4) /* (AD29) PRG0_PRU1_GPO4.RGMII4_RX_CTL */
+			J721E_IOPAD(0x12c, PIN_OUTPUT, 4) /* (AG26) PRG0_PRU1_GPO11.RGMII4_TD0 */
+			J721E_IOPAD(0x130, PIN_OUTPUT, 4) /* (AF27) PRG0_PRU1_GPO12.RGMII4_TD1 */
+			J721E_IOPAD(0x134, PIN_OUTPUT, 4) /* (AF26) PRG0_PRU1_GPO13.RGMII4_TD2 */
+			J721E_IOPAD(0x138, PIN_OUTPUT, 4) /* (AE25) PRG0_PRU1_GPO14.RGMII4_TD3 */
+			J721E_IOPAD(0x140, PIN_OUTPUT, 4) /* (AG29) PRG0_PRU1_GPO16.RGMII4_TXC */
+			J721E_IOPAD(0x13c, PIN_OUTPUT, 4) /* (AF29) PRG0_PRU1_GPO15.RGMII4_TX_CTL */
+		>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-evm-quad-port-eth-exp.dtso b/arch/arm64/boot/dts/ti/k3-j721e-evm-quad-port-eth-exp.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721e-evm-quad-port-eth-exp.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-evm-quad-port-eth-exp.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for CPSW9G in QSGMII mode using J7 Quad Port ETH EXP Add-On Ethernet Card with
+ * J721E board.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/mux/ti-serdes.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/phy/phy-cadence.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	aliases {
+		ethernet1 = "/bus@100000/ethernet@c000000/ethernet-ports/port@1";
+		ethernet2 = "/bus@100000/ethernet@c000000/ethernet-ports/port@2";
+		ethernet3 = "/bus@100000/ethernet@c000000/ethernet-ports/port@3";
+		ethernet4 = "/bus@100000/ethernet@c000000/ethernet-ports/port@4";
+	};
+};
+
+&cpsw0 {
+	status = "okay";
+};
+
+&cpsw0_port1 {
+	status = "okay";
+	phy-handle = <&cpsw9g_phy0>;
+	phy-mode = "qsgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 1>;
+};
+
+&cpsw0_port2 {
+	status = "okay";
+	phy-handle = <&cpsw9g_phy1>;
+	phy-mode = "qsgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 2>;
+};
+
+&cpsw0_port3 {
+	status = "okay";
+	phy-handle = <&cpsw9g_phy2>;
+	phy-mode = "qsgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 3>;
+};
+
+&cpsw0_port4 {
+	status = "okay";
+	phy-handle = <&cpsw9g_phy3>;
+	phy-mode = "qsgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 4>;
+};
+
+&cpsw9g_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio0_pins_default>;
+	reset-gpios = <&exp2 17 GPIO_ACTIVE_LOW>;
+	reset-post-delay-us = <120000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	cpsw9g_phy0: ethernet-phy@17 {
+		reg = <17>;
+	};
+	cpsw9g_phy1: ethernet-phy@16 {
+		reg = <16>;
+	};
+	cpsw9g_phy2: ethernet-phy@18 {
+		reg = <18>;
+	};
+	cpsw9g_phy3: ethernet-phy@19 {
+		reg = <19>;
+	};
+};
+
+&exp2 {
+	qsgmii-line-hog {
+		gpio-hog;
+		gpios = <16 GPIO_ACTIVE_HIGH>;
+		output-low;
+		line-name = "qsgmii-pwrdn-line";
+	};
+};
+
+&main_pmx0 {
+	mdio0_pins_default: mdio0-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x1bc, PIN_OUTPUT, 0) /* (V24) MDIO0_MDC */
+			J721E_IOPAD(0x1b8, PIN_INPUT, 0) /* (V26) MDIO0_MDIO */
+		>;
+	};
+};
+
+&serdes_ln_ctrl {
+	idle-states = <J721E_SERDES0_LANE0_PCIE0_LANE0>, <J721E_SERDES0_LANE1_QSGMII_LANE2>,
+		      <J721E_SERDES1_LANE0_PCIE1_LANE0>, <J721E_SERDES1_LANE1_PCIE1_LANE1>,
+		      <J721E_SERDES2_LANE0_PCIE2_LANE0>, <J721E_SERDES2_LANE1_PCIE2_LANE1>,
+		      <J721E_SERDES3_LANE0_USB3_0_SWAP>, <J721E_SERDES3_LANE1_USB3_0>,
+		      <J721E_SERDES4_LANE0_EDP_LANE0>, <J721E_SERDES4_LANE1_EDP_LANE1>,
+		      <J721E_SERDES4_LANE2_EDP_LANE2>, <J721E_SERDES4_LANE3_EDP_LANE3>;
+};
+
+&serdes_wiz0 {
+	status = "okay";
+};
+
+&serdes0 {
+	status = "okay";
+
+	assigned-clocks = <&serdes0 CDNS_SIERRA_PLL_CMNLC>, <&serdes0 CDNS_SIERRA_PLL_CMNLC1>;
+	assigned-clock-parents = <&wiz0_pll1_refclk>, <&wiz0_pll1_refclk>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	serdes0_qsgmii_link: phy@1 {
+		reg = <1>;
+		cdns,num-lanes = <1>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_QSGMII>;
+		resets = <&serdes_wiz0 2>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-evm-virt-mac-client.dtso b/arch/arm64/boot/dts/ti/k3-j721e-evm-virt-mac-client.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721e-evm-virt-mac-client.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-evm-virt-mac-client.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for enabling CPSW Virt MAC Client driver in linux to interface with EthFw via the
+ * Linux MAC Only port as well as the Switch Ports of the CPSW9G CPSW instance.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/mux/ti-serdes.h>
+
+&{/} {
+	cpsw9g_virt_mac: main-r5fss-cpsw9g-virt-mac0 {
+		compatible = "ti,j721e-cpsw-virt-mac";
+		dma-coherent;
+		ti,psil-base = <0x4a00>;
+		ti,remote-name = "mpu_1_0_ethswitch-device-0";
+
+		dmas = <&main_udmap 0xca00>,
+		       <&main_udmap 0xca01>,
+		       <&main_udmap 0xca02>,
+		       <&main_udmap 0xca03>,
+		       <&main_udmap 0xca04>,
+		       <&main_udmap 0xca05>,
+		       <&main_udmap 0xca06>,
+		       <&main_udmap 0xca07>,
+		       <&main_udmap 0x4a00>;
+		dma-names = "tx0", "tx1", "tx2", "tx3",
+			    "tx4", "tx5", "tx6", "tx7",
+			    "rx";
+
+		virt-emac-port {
+			ti,label = "virt-port";
+			/* local-mac-address = [0 0 0 0 0 0]; */
+		};
+	};
+
+	cpsw9g_virt_maconly: main-r5fss-cpsw9g-virt-mac1 {
+		compatible = "ti,j721e-cpsw-virt-mac";
+		dma-coherent;
+		ti,psil-base = <0x4a00>;
+		ti,remote-name = "mpu_1_0_ethmac-device-1";
+
+		dmas = <&main_udmap 0xca00>,
+		       <&main_udmap 0xca01>,
+		       <&main_udmap 0xca02>,
+		       <&main_udmap 0xca03>,
+		       <&main_udmap 0xca04>,
+		       <&main_udmap 0xca05>,
+		       <&main_udmap 0xca06>,
+		       <&main_udmap 0xca07>,
+		       <&main_udmap 0x4a00>;
+		dma-names = "tx0", "tx1", "tx2", "tx3",
+			    "tx4", "tx5", "tx6", "tx7",
+			    "rx";
+
+		virt-emac-port {
+			ti,label = "virt-port";
+			/* local-mac-address = [0 0 0 0 0 0]; */
+		};
+	};
+};
+
+/* uart2 is assigned to cpsw9g eth-switch fw running on remote CPU core */
+&main_uart2 {
+	status = "reserved";
+};
+
+/* Reserve shared memory for inter-core network communication */
+&reserved_memory {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	main_r5fss0_core0_shared_memory_queue_region:r5f-virtual-eth-queues@ac000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xac000000 0x00 0x200000>;
+		no-map;
+	};
+
+	main_r5fss0_core0_shared_memory_bufpool_region:r5f-virtual-eth-buffers@ac200000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xac200000 0x00 0x1e00000>;
+		no-map;
+	};
+};
+
+&main_r5fss0_core0 {
+	memory-region = <&main_r5fss0_core0_dma_memory_region>,
+			<&main_r5fss0_core0_memory_region>,
+			<&main_r5fss0_core0_shared_memory_queue_region>,
+			<&main_r5fss0_core0_shared_memory_bufpool_region>;
+};
+
+&serdes_ln_ctrl {
+	idle-states = <J721E_SERDES0_LANE0_PCIE0_LANE0>, <J721E_SERDES0_LANE1_QSGMII_LANE2>,
+		      <J721E_SERDES1_LANE0_PCIE1_LANE0>, <J721E_SERDES1_LANE1_PCIE1_LANE1>,
+		      <J721E_SERDES2_LANE0_PCIE2_LANE0>, <J721E_SERDES2_LANE1_PCIE2_LANE1>,
+		      <J721E_SERDES3_LANE0_USB3_0_SWAP>, <J721E_SERDES3_LANE1_USB3_0>,
+		      <J721E_SERDES4_LANE0_EDP_LANE0>, <J721E_SERDES4_LANE1_EDP_LANE1>,
+		      <J721E_SERDES4_LANE2_EDP_LANE2>, <J721E_SERDES4_LANE3_EDP_LANE3>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -7,6 +7,7 @@
 #include <dt-bindings/phy/phy.h>
 #include <dt-bindings/phy/phy-ti.h>
 #include <dt-bindings/mux/mux.h>
+
 #include <dt-bindings/mux/ti-serdes.h>
 
 / {
@@ -61,12 +62,85 @@
 				      <J721E_SERDES4_LANE2_EDP_LANE2>, <J721E_SERDES4_LANE3_EDP_LANE3>;
 		};
 
+		cpsw0_phy_gmii_sel: phy@4044 {
+			compatible = "ti,j721e-cpsw9g-phy-gmii-sel";
+			ti,qsgmii-main-ports = <2>, <2>;
+			reg = <0x4044 0x20>;
+			#phy-cells = <1>;
+		};
+
 		usb_serdes_mux: mux-controller@4000 {
 			compatible = "mmio-mux";
 			#mux-control-cells = <1>;
 			mux-reg-masks = <0x4000 0x8000000>, /* USB0 to SERDES0/3 mux */
 					<0x4010 0x8000000>; /* USB1 to SERDES1/2 mux */
-	    };
+		};
+
+		ehrpwm_tbclk: clock-controller@4140 {
+			compatible = "ti,am654-ehrpwm-tbclk", "syscon";
+			reg = <0x4140 0x18>;
+			#clock-cells = <1>;
+		};
+	};
+
+	main_ehrpwm0: pwm@3000000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3000000 0x00 0x100>;
+		power-domains = <&k3_pds 83 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 0>, <&k3_clks 83 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	main_ehrpwm1: pwm@3010000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3010000 0x00 0x100>;
+		power-domains = <&k3_pds 84 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 1>, <&k3_clks 84 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	main_ehrpwm2: pwm@3020000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3020000 0x00 0x100>;
+		power-domains = <&k3_pds 85 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 2>, <&k3_clks 85 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	main_ehrpwm3: pwm@3030000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3030000 0x00 0x100>;
+		power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 3>, <&k3_clks 86 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	main_ehrpwm4: pwm@3040000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3040000 0x00 0x100>;
+		power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 4>, <&k3_clks 87 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	main_ehrpwm5: pwm@3050000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3050000 0x00 0x100>;
+		power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 5>, <&k3_clks 88 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
 	};
 
 	gic500: interrupt-controller@1800000 {
@@ -176,6 +250,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster1: mailbox@31f81000 {
@@ -185,6 +260,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster2: mailbox@31f82000 {
@@ -194,6 +270,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster3: mailbox@31f83000 {
@@ -203,6 +280,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster4: mailbox@31f84000 {
@@ -212,6 +290,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster5: mailbox@31f85000 {
@@ -221,6 +300,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster6: mailbox@31f86000 {
@@ -230,6 +310,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster7: mailbox@31f87000 {
@@ -239,6 +320,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster8: mailbox@31f88000 {
@@ -248,6 +330,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster9: mailbox@31f89000 {
@@ -257,6 +340,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster10: mailbox@31f8a000 {
@@ -266,6 +350,7 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		mailbox0_cluster11: mailbox@31f8b000 {
@@ -275,14 +360,15 @@
 			ti,mbox-num-users = <4>;
 			ti,mbox-num-fifos = <16>;
 			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
 		};
 
 		main_ringacc: ringacc@3c000000 {
 			compatible = "ti,am654-navss-ringacc";
-			reg =	<0x0 0x3c000000 0x0 0x400000>,
-				<0x0 0x38000000 0x0 0x400000>,
-				<0x0 0x31120000 0x0 0x100>,
-				<0x0 0x33000000 0x0 0x40000>;
+			reg = <0x0 0x3c000000 0x0 0x400000>,
+			      <0x0 0x38000000 0x0 0x400000>,
+			      <0x0 0x31120000 0x0 0x100>,
+			      <0x0 0x33000000 0x0 0x40000>;
 			reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target";
 			ti,num-rings = <1024>;
 			ti,sci-rm-range-gp-rings = <0x1>; /* GP ring range */
@@ -293,9 +379,9 @@
 
 		main_udmap: dma-controller@31150000 {
 			compatible = "ti,j721e-navss-main-udmap";
-			reg =	<0x0 0x31150000 0x0 0x100>,
-				<0x0 0x34000000 0x0 0x100000>,
-				<0x0 0x35000000 0x0 0x100000>;
+			reg = <0x0 0x31150000 0x0 0x100>,
+			      <0x0 0x34000000 0x0 0x100000>,
+			      <0x0 0x35000000 0x0 0x100000>;
 			reg-names = "gcfg", "rchanrt", "tchanrt";
 			msi-parent = <&main_udmass_inta>;
 			#dma-cells = <1>;
@@ -326,6 +412,115 @@
 		};
 	};
 
+	cpsw0: ethernet@c000000 {
+		compatible = "ti,j721e-cpswxg-nuss";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		reg = <0x0 0xc000000 0x0 0x200000>;
+		reg-names = "cpsw_nuss";
+		ranges = <0x0 0x0 0x0 0x0c000000 0x0 0x200000>;
+		clocks = <&k3_clks 19 89>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 19 TI_SCI_PD_EXCLUSIVE>;
+
+		dmas = <&main_udmap 0xca00>,
+		       <&main_udmap 0xca01>,
+		       <&main_udmap 0xca02>,
+		       <&main_udmap 0xca03>,
+		       <&main_udmap 0xca04>,
+		       <&main_udmap 0xca05>,
+		       <&main_udmap 0xca06>,
+		       <&main_udmap 0xca07>,
+		       <&main_udmap 0x4a00>;
+		dma-names = "tx0", "tx1", "tx2", "tx3",
+			    "tx4", "tx5", "tx6", "tx7",
+			    "rx";
+
+		status = "disabled";
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			cpsw0_port1: port@1 {
+				reg = <1>;
+				ti,mac-only;
+				label = "port1";
+				status = "disabled";
+			};
+
+			cpsw0_port2: port@2 {
+				reg = <2>;
+				ti,mac-only;
+				label = "port2";
+				status = "disabled";
+			};
+
+			cpsw0_port3: port@3 {
+				reg = <3>;
+				ti,mac-only;
+				label = "port3";
+				status = "disabled";
+			};
+
+			cpsw0_port4: port@4 {
+				reg = <4>;
+				ti,mac-only;
+				label = "port4";
+				status = "disabled";
+			};
+
+			cpsw0_port5: port@5 {
+				reg = <5>;
+				ti,mac-only;
+				label = "port5";
+				status = "disabled";
+			};
+
+			cpsw0_port6: port@6 {
+				reg = <6>;
+				ti,mac-only;
+				label = "port6";
+				status = "disabled";
+			};
+
+			cpsw0_port7: port@7 {
+				reg = <7>;
+				ti,mac-only;
+				label = "port7";
+				status = "disabled";
+			};
+
+			cpsw0_port8: port@8 {
+				reg = <8>;
+				ti,mac-only;
+				label = "port8";
+				status = "disabled";
+			};
+		};
+
+		cpsw9g_mdio: mdio@f00 {
+			compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+			reg = <0x0 0xf00 0x0 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&k3_clks 19 89>;
+			clock-names = "fck";
+			bus_freq = <1000000>;
+			status = "disabled";
+		};
+
+		cpts@3d000 {
+			compatible = "ti,j721e-cpts";
+			reg = <0x0 0x3d000 0x0 0x400>;
+			clocks = <&k3_clks 19 16>;
+			clock-names = "cpts";
+			interrupts-extended = <&gic500 GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "cpts";
+			ti,cpts-ext-ts-inputs = <4>;
+			ti,cpts-periodic-outputs = <2>;
+		};
+	};
+
 	main_crypto: crypto@4e00000 {
 		compatible = "ti,j721e-sa2ul";
 		reg = <0x0 0x4e00000 0x0 0x1200>;
@@ -342,7 +537,6 @@
 			compatible = "inside-secure,safexcel-eip76";
 			reg = <0x0 0x4e10000 0x0 0x7d>;
 			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&k3_clks 264 2>;
 		};
 	};
 
@@ -449,7 +643,7 @@
 			assigned-clock-parents = <&k3_clks 293 13>;
 		};
 
-		wiz1_cmn_refclk_dig_div: cmn-refclk-dig-div{
+		wiz1_cmn_refclk_dig_div: cmn-refclk-dig-div {
 			clocks = <&wiz1_refclk_dig>;
 			#clock-cells = <0>;
 		};
@@ -621,26 +815,20 @@
 		ranges = <0x01000000 0x0 0x10001000 0x0 0x10001000 0x0 0x0010000>,
 			 <0x02000000 0x0 0x10011000 0x0 0x10011000 0x0 0x7fef000>;
 		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
-	};
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie0_intc 0>, /* INT A */
+				<0 0 0 2 &pcie0_intc 0>, /* INT B */
+				<0 0 0 3 &pcie0_intc 0>, /* INT C */
+				<0 0 0 4 &pcie0_intc 0>; /* INT D */
+		status = "disabled";
 
-	pcie0_ep: pcie-ep@2900000 {
-		compatible = "ti,j721e-pcie-ep";
-		reg = <0x00 0x02900000 0x00 0x1000>,
-		      <0x00 0x02907000 0x00 0x400>,
-		      <0x00 0x0d000000 0x00 0x00800000>,
-		      <0x00 0x10000000 0x00 0x08000000>;
-		reg-names = "intd_cfg", "user_cfg", "reg", "mem";
-		interrupt-names = "link_state";
-		interrupts = <GIC_SPI 318 IRQ_TYPE_EDGE_RISING>;
-		ti,syscon-pcie-ctrl = <&scm_conf 0x4070>;
-		max-link-speed = <3>;
-		num-lanes = <2>;
-		power-domains = <&k3_pds 239 TI_SCI_PD_EXCLUSIVE>;
-		clocks = <&k3_clks 239 1>;
-		clock-names = "fck";
-		max-functions = /bits/ 8 <6>;
-		max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>;
-		dma-coherent;
+		pcie0_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 312 IRQ_TYPE_EDGE_RISING>;
+		};
 	};
 
 	pcie1_rc: pcie@2910000 {
@@ -669,26 +857,20 @@
 		ranges = <0x01000000 0x0 0x18001000 0x0 0x18001000 0x0 0x0010000>,
 			 <0x02000000 0x0 0x18011000 0x0 0x18011000 0x0 0x7fef000>;
 		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
-	};
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie1_intc 0>, /* INT A */
+				<0 0 0 2 &pcie1_intc 0>, /* INT B */
+				<0 0 0 3 &pcie1_intc 0>, /* INT C */
+				<0 0 0 4 &pcie1_intc 0>; /* INT D */
+		status = "disabled";
 
-	pcie1_ep: pcie-ep@2910000 {
-		compatible = "ti,j721e-pcie-ep";
-		reg = <0x00 0x02910000 0x00 0x1000>,
-		      <0x00 0x02917000 0x00 0x400>,
-		      <0x00 0x0d800000 0x00 0x00800000>,
-		      <0x00 0x18000000 0x00 0x08000000>;
-		reg-names = "intd_cfg", "user_cfg", "reg", "mem";
-		interrupt-names = "link_state";
-		interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
-		ti,syscon-pcie-ctrl = <&scm_conf 0x4074>;
-		max-link-speed = <3>;
-		num-lanes = <2>;
-		power-domains = <&k3_pds 240 TI_SCI_PD_EXCLUSIVE>;
-		clocks = <&k3_clks 240 1>;
-		clock-names = "fck";
-		max-functions = /bits/ 8 <6>;
-		max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>;
-		dma-coherent;
+		pcie1_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 324 IRQ_TYPE_EDGE_RISING>;
+		};
 	};
 
 	pcie2_rc: pcie@2920000 {
@@ -717,26 +899,20 @@
 		ranges = <0x01000000 0x0 0x00001000 0x44 0x00001000 0x0 0x0010000>,
 			 <0x02000000 0x0 0x00011000 0x44 0x00011000 0x0 0x7fef000>;
 		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
-	};
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie2_intc 0>, /* INT A */
+				<0 0 0 2 &pcie2_intc 0>, /* INT B */
+				<0 0 0 3 &pcie2_intc 0>, /* INT C */
+				<0 0 0 4 &pcie2_intc 0>; /* INT D */
+		status = "disabled";
 
-	pcie2_ep: pcie-ep@2920000 {
-		compatible = "ti,j721e-pcie-ep";
-		reg = <0x00 0x02920000 0x00 0x1000>,
-		      <0x00 0x02927000 0x00 0x400>,
-		      <0x00 0x0e000000 0x00 0x00800000>,
-		      <0x44 0x00000000 0x00 0x08000000>;
-		reg-names = "intd_cfg", "user_cfg", "reg", "mem";
-		interrupt-names = "link_state";
-		interrupts = <GIC_SPI 342 IRQ_TYPE_EDGE_RISING>;
-		ti,syscon-pcie-ctrl = <&scm_conf 0x4078>;
-		max-link-speed = <3>;
-		num-lanes = <2>;
-		power-domains = <&k3_pds 241 TI_SCI_PD_EXCLUSIVE>;
-		clocks = <&k3_clks 241 1>;
-		clock-names = "fck";
-		max-functions = /bits/ 8 <6>;
-		max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>;
-		dma-coherent;
+		pcie2_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 336 IRQ_TYPE_EDGE_RISING>;
+		};
 	};
 
 	pcie3_rc: pcie@2930000 {
@@ -765,28 +941,20 @@
 		ranges = <0x01000000 0x0 0x00001000 0x44 0x10001000 0x0 0x0010000>,
 			 <0x02000000 0x0 0x00011000 0x44 0x10011000 0x0 0x7fef000>;
 		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
-	};
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie3_intc 0>, /* INT A */
+				<0 0 0 2 &pcie3_intc 0>, /* INT B */
+				<0 0 0 3 &pcie3_intc 0>, /* INT C */
+				<0 0 0 4 &pcie3_intc 0>; /* INT D */
+		status = "disabled";
 
-	pcie3_ep: pcie-ep@2930000 {
-		compatible = "ti,j721e-pcie-ep";
-		reg = <0x00 0x02930000 0x00 0x1000>,
-		      <0x00 0x02937000 0x00 0x400>,
-		      <0x00 0x0e800000 0x00 0x00800000>,
-		      <0x44 0x10000000 0x00 0x08000000>;
-		reg-names = "intd_cfg", "user_cfg", "reg", "mem";
-		interrupt-names = "link_state";
-		interrupts = <GIC_SPI 354 IRQ_TYPE_EDGE_RISING>;
-		ti,syscon-pcie-ctrl = <&scm_conf 0x407c>;
-		max-link-speed = <3>;
-		num-lanes = <2>;
-		power-domains = <&k3_pds 242 TI_SCI_PD_EXCLUSIVE>;
-		clocks = <&k3_clks 242 1>;
-		clock-names = "fck";
-		max-functions = /bits/ 8 <6>;
-		max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>;
-		dma-coherent;
-		#address-cells = <2>;
-		#size-cells = <2>;
+		pcie3_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 348 IRQ_TYPE_EDGE_RISING>;
+		};
 	};
 
 	serdes_wiz4: wiz@5050000 {
@@ -839,6 +1007,7 @@
 		power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 146 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart1: serial@2810000 {
@@ -850,6 +1019,7 @@
 		power-domains = <&k3_pds 278 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 278 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart2: serial@2820000 {
@@ -861,6 +1031,7 @@
 		power-domains = <&k3_pds 279 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 279 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart3: serial@2830000 {
@@ -872,6 +1043,7 @@
 		power-domains = <&k3_pds 280 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 280 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart4: serial@2840000 {
@@ -883,6 +1055,7 @@
 		power-domains = <&k3_pds 281 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 281 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart5: serial@2850000 {
@@ -894,6 +1067,7 @@
 		power-domains = <&k3_pds 282 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 282 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart6: serial@2860000 {
@@ -905,6 +1079,7 @@
 		power-domains = <&k3_pds 283 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 283 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart7: serial@2870000 {
@@ -916,6 +1091,7 @@
 		power-domains = <&k3_pds 284 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 284 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart8: serial@2880000 {
@@ -927,6 +1103,7 @@
 		power-domains = <&k3_pds 285 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 285 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_uart9: serial@2890000 {
@@ -938,6 +1115,7 @@
 		power-domains = <&k3_pds 286 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 286 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	main_gpio0: gpio@600000 {
@@ -955,6 +1133,7 @@
 		power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 105 0>;
 		clock-names = "gpio";
+		status = "disabled";
 	};
 
 	main_gpio1: gpio@601000 {
@@ -971,6 +1150,7 @@
 		power-domains = <&k3_pds 106 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 106 0>;
 		clock-names = "gpio";
+		status = "disabled";
 	};
 
 	main_gpio2: gpio@610000 {
@@ -988,6 +1168,7 @@
 		power-domains = <&k3_pds 107 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 107 0>;
 		clock-names = "gpio";
+		status = "disabled";
 	};
 
 	main_gpio3: gpio@611000 {
@@ -1021,6 +1202,7 @@
 		power-domains = <&k3_pds 109 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 109 0>;
 		clock-names = "gpio";
+		status = "disabled";
 	};
 
 	main_gpio5: gpio@621000 {
@@ -1037,6 +1219,7 @@
 		power-domains = <&k3_pds 110 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 110 0>;
 		clock-names = "gpio";
+		status = "disabled";
 	};
 
 	main_gpio6: gpio@630000 {
@@ -1054,6 +1237,7 @@
 		power-domains = <&k3_pds 111 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 111 0>;
 		clock-names = "gpio";
+		status = "disabled";
 	};
 
 	main_gpio7: gpio@631000 {
@@ -1070,6 +1254,7 @@
 		power-domains = <&k3_pds 112 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 112 0>;
 		clock-names = "gpio";
+		status = "disabled";
 	};
 
 	main_sdhci0: mmc@4f80000 {
@@ -1084,8 +1269,8 @@
 		bus-width = <8>;
 		mmc-hs200-1_8v;
 		mmc-ddr-1_8v;
-		ti,otap-del-sel-legacy = <0xf>;
-		ti,otap-del-sel-mmc-hs = <0xf>;
+		ti,otap-del-sel-legacy = <0x0>;
+		ti,otap-del-sel-mmc-hs = <0x0>;
 		ti,otap-del-sel-ddr52 = <0x5>;
 		ti,otap-del-sel-hs200 = <0x6>;
 		ti,otap-del-sel-hs400 = <0x0>;
@@ -1094,6 +1279,7 @@
 		ti,itap-del-sel-ddr52 = <0x3>;
 		ti,trm-icp = <0x8>;
 		dma-coherent;
+		status = "disabled";
 	};
 
 	main_sdhci1: mmc@4fb0000 {
@@ -1106,11 +1292,12 @@
 		assigned-clocks = <&k3_clks 92 0>;
 		assigned-clock-parents = <&k3_clks 92 1>;
 		ti,otap-del-sel-legacy = <0x0>;
-		ti,otap-del-sel-sd-hs = <0xf>;
+		ti,otap-del-sel-sd-hs = <0x0>;
 		ti,otap-del-sel-sdr12 = <0xf>;
 		ti,otap-del-sel-sdr25 = <0xf>;
 		ti,otap-del-sel-sdr50 = <0xc>;
 		ti,otap-del-sel-ddr50 = <0xc>;
+		ti,otap-del-sel-sdr104 = <0x5>;
 		ti,itap-del-sel-legacy = <0x0>;
 		ti,itap-del-sel-sd-hs = <0x0>;
 		ti,itap-del-sel-sdr12 = <0x0>;
@@ -1120,6 +1307,7 @@
 		ti,clkbuf-sel = <0x7>;
 		dma-coherent;
 		sdhci-caps-mask = <0x2 0x0>;
+		status = "disabled";
 	};
 
 	main_sdhci2: mmc@4f98000 {
@@ -1132,11 +1320,12 @@
 		assigned-clocks = <&k3_clks 93 0>;
 		assigned-clock-parents = <&k3_clks 93 1>;
 		ti,otap-del-sel-legacy = <0x0>;
-		ti,otap-del-sel-sd-hs = <0xf>;
+		ti,otap-del-sel-sd-hs = <0x0>;
 		ti,otap-del-sel-sdr12 = <0xf>;
 		ti,otap-del-sel-sdr25 = <0xf>;
 		ti,otap-del-sel-sdr50 = <0xc>;
 		ti,otap-del-sel-ddr50 = <0xc>;
+		ti,otap-del-sel-sdr104 = <0x5>;
 		ti,itap-del-sel-legacy = <0x0>;
 		ti,itap-del-sel-sd-hs = <0x0>;
 		ti,itap-del-sel-sdr12 = <0x0>;
@@ -1146,6 +1335,7 @@
 		ti,clkbuf-sel = <0x7>;
 		dma-coherent;
 		sdhci-caps-mask = <0x2 0x0>;
+		status = "disabled";
 	};
 
 	usbss0: cdns-usb@4104000 {
@@ -1217,6 +1407,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 187 0>;
 		power-domains = <&k3_pds 187 TI_SCI_PD_SHARED>;
+		status = "disabled";
 	};
 
 	main_i2c1: i2c@2010000 {
@@ -1228,6 +1419,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 188 0>;
 		power-domains = <&k3_pds 188 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c2: i2c@2020000 {
@@ -1239,6 +1431,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 189 0>;
 		power-domains = <&k3_pds 189 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c3: i2c@2030000 {
@@ -1250,6 +1443,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 190 0>;
 		power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c4: i2c@2040000 {
@@ -1261,6 +1455,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 191 0>;
 		power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c5: i2c@2050000 {
@@ -1272,6 +1467,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 192 0>;
 		power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c6: i2c@2060000 {
@@ -1283,6 +1479,24 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 193 0>;
 		power-domains = <&k3_pds 193 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	vxe384: video-encoder@4200000 {
+		compatible = "img,vxe384";
+		reg = <0x00 0x04200000>,
+		    <0x00 0x100000>;
+		power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>;
+		interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	d5520: video-decoder@4300000 {
+	       /* IMG D5520 driver configuration */
+	       compatible = "img,d5500-vxd";
+	       reg = <0x00 0x04300000>,
+		   <0x00 0x100000>;
+	       power-domains = <&k3_pds 144 TI_SCI_PD_EXCLUSIVE>;
+	       interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
 	};
 
 	ufs_wrapper: ufs-wrapper@4e80000 {
@@ -1338,6 +1552,24 @@
 		};
 	};
 
+	dsi0: dsi@48000000 {
+		compatible = "ti,j721e-dsi";
+		reg = <0x0 0x04800000 0x0 0x100000>, <0x0 0x04710000 0x0 0x100>;
+		clocks = <&k3_clks 150 1>, <&k3_clks 150 5>;
+		clock-names = "dsi_p_clk", "dsi_sys_clk";
+		power-domains = <&k3_pds 150 TI_SCI_PD_EXCLUSIVE>;
+		interrupt-parent = <&gic500>;
+		interrupts = <GIC_SPI 600 IRQ_TYPE_LEVEL_HIGH>;
+		phys = <&dphy2>;
+		phy-names = "dphy";
+		status = "disabled";
+
+		dsi0_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
 	dss: dss@4a00000 {
 		compatible = "ti,j721e-dss";
 		reg =
@@ -1369,11 +1601,11 @@
 			"vp1", "vp2", "vp3", "vp4",
 			"wb";
 
-		clocks =	<&k3_clks 152 0>,
-				<&k3_clks 152 1>,
-				<&k3_clks 152 4>,
-				<&k3_clks 152 9>,
-				<&k3_clks 152 13>;
+		clocks = <&k3_clks 152 0>,
+			 <&k3_clks 152 1>,
+			 <&k3_clks 152 4>,
+			 <&k3_clks 152 9>,
+			 <&k3_clks 152 13>;
 		clock-names = "fck", "vp1", "vp2", "vp3", "vp4";
 
 		power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>;
@@ -1406,6 +1638,7 @@
 		clocks = <&k3_clks 174 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 174 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp1: mcasp@2b10000 {
@@ -1423,6 +1656,7 @@
 		clocks = <&k3_clks 175 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 175 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp2: mcasp@2b20000 {
@@ -1440,6 +1674,7 @@
 		clocks = <&k3_clks 176 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 176 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp3: mcasp@2b30000 {
@@ -1457,6 +1692,7 @@
 		clocks = <&k3_clks 177 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 177 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp4: mcasp@2b40000 {
@@ -1474,6 +1710,7 @@
 		clocks = <&k3_clks 178 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 178 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp5: mcasp@2b50000 {
@@ -1491,6 +1728,7 @@
 		clocks = <&k3_clks 179 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 179 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp6: mcasp@2b60000 {
@@ -1508,6 +1746,7 @@
 		clocks = <&k3_clks 180 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 180 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp7: mcasp@2b70000 {
@@ -1525,6 +1764,7 @@
 		clocks = <&k3_clks 181 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 181 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp8: mcasp@2b80000 {
@@ -1542,6 +1782,7 @@
 		clocks = <&k3_clks 182 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp9: mcasp@2b90000 {
@@ -1559,6 +1800,7 @@
 		clocks = <&k3_clks 183 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 183 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp10: mcasp@2ba0000 {
@@ -1576,6 +1818,7 @@
 		clocks = <&k3_clks 184 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 184 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcasp11: mcasp@2bb0000 {
@@ -1593,6 +1836,7 @@
 		clocks = <&k3_clks 185 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 185 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	watchdog0: watchdog@2200000 {
@@ -1615,7 +1859,7 @@
 
 	main_r5fss0: r5fss@5c00000 {
 		compatible = "ti,j721e-r5fss";
-		ti,cluster-mode = <1>;
+		ti,cluster-mode = <0>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0x5c00000 0x00 0x5c00000 0x20000>,
@@ -1655,7 +1899,7 @@
 
 	main_r5fss1: r5fss@5e00000 {
 		compatible = "ti,j721e-r5fss";
-		ti,cluster-mode = <1>;
+		ti,cluster-mode = <0>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0x5e00000 0x00 0x5e00000 0x20000>,
@@ -1704,6 +1948,7 @@
 		ti,sci-proc-ids = <0x03 0xff>;
 		resets = <&k3_reset 142 1>;
 		firmware-name = "j7-c66_0-fw";
+		status = "disabled";
 	};
 
 	c66_1: dsp@4d81800000 {
@@ -1717,6 +1962,7 @@
 		ti,sci-proc-ids = <0x04 0xff>;
 		resets = <&k3_reset 143 1>;
 		firmware-name = "j7-c66_1-fw";
+		status = "disabled";
 	};
 
 	c71_0: dsp@64800000 {
@@ -1731,6 +1977,17 @@
 		firmware-name = "j7-c71_0-fw";
 	};
 
+	timesync_router: pinctrl@a40000 {
+		compatible = "pinctrl-single";
+		reg = <0x0 0xa40000 0x0 0x800>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0x000107ff>;
+		status = "disabled";
+	};
+
 	icssg0: icssg@b000000 {
 		compatible = "ti,j721e-icssg";
 		reg = <0x00 0xb000000 0x00 0x80000>;
@@ -1869,6 +2126,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			bus_freq = <1000000>;
+			status = "disabled";
 		};
 	};
 
@@ -2010,9 +2268,18 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			bus_freq = <1000000>;
+			status = "disabled";
 		};
 	};
 
+	gpu: gpu@4e20000000 {
+		compatible = "ti,j721e-pvr", "img,pvr-ge8430";
+		reg = <0x4e 0x20000000 0x00 0x80000>;
+		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 125 0>;
+	};
+
 	main_mcan0: can@2701000 {
 		compatible = "bosch,m_can";
 		reg = <0x00 0x02701000 0x00 0x200>,
@@ -2025,6 +2292,7 @@
 			     <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan1: can@2711000 {
@@ -2039,6 +2307,7 @@
 			     <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan2: can@2721000 {
@@ -2053,6 +2322,7 @@
 			     <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan3: can@2731000 {
@@ -2067,6 +2337,7 @@
 			     <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan4: can@2741000 {
@@ -2081,6 +2352,7 @@
 			     <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan5: can@2751000 {
@@ -2095,6 +2367,7 @@
 			     <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan6: can@2761000 {
@@ -2109,6 +2382,7 @@
 			     <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan7: can@2771000 {
@@ -2123,6 +2397,7 @@
 			     <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan8: can@2781000 {
@@ -2137,6 +2412,7 @@
 			     <GIC_SPI 577 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan9: can@2791000 {
@@ -2151,6 +2427,7 @@
 			     <GIC_SPI 580 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan10: can@27a1000 {
@@ -2165,6 +2442,7 @@
 			     <GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan11: can@27b1000 {
@@ -2179,6 +2457,7 @@
 			     <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan12: can@27c1000 {
@@ -2193,6 +2472,7 @@
 			     <GIC_SPI 589 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan13: can@27d1000 {
@@ -2207,5 +2487,241 @@
 			     <GIC_SPI 592 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_spi0: spi@2100000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02100000 0x00 0x400>;
+		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 266 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 266 1>;
+		status = "disabled";
+	};
+
+	main_spi1: spi@2110000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02110000 0x00 0x400>;
+		interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 267 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 267 1>;
+		status = "disabled";
+	};
+
+	main_spi2: spi@2120000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02120000 0x00 0x400>;
+		interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 268 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 268 1>;
+		status = "disabled";
+	};
+
+	main_spi3: spi@2130000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02130000 0x00 0x400>;
+		interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 269 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 269 1>;
+		status = "disabled";
+	};
+
+	main_spi4: spi@2140000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02140000 0x00 0x400>;
+		interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 270 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 270 1>;
+		status = "disabled";
+	};
+
+	main_spi5: spi@2150000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02150000 0x00 0x400>;
+		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 271 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 271 1>;
+		status = "disabled";
+	};
+
+	main_spi6: spi@2160000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02160000 0x00 0x400>;
+		interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 272 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 272 1>;
+		status = "disabled";
+	};
+
+	main_spi7: spi@2170000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02170000 0x00 0x400>;
+		interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 273 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 273 1>;
+		status = "disabled";
+	};
+
+	ti_csi2rx0: ticsi2rx@4500000 {
+		status = "disabled";
+		compatible = "ti,j721e-csi2rx";
+		dmas = <&main_udmap 0x4940>, <&main_udmap 0x4941>, <&main_udmap 0x4942>,
+			<&main_udmap 0x4943>, <&main_udmap 0x4944>, <&main_udmap 0x4945>,
+			<&main_udmap 0x4946>, <&main_udmap 0x4947>, <&main_udmap 0x4948>,
+			<&main_udmap 0x4949>, <&main_udmap 0x494a>, <&main_udmap 0x494b>,
+			<&main_udmap 0x494c>, <&main_udmap 0x494d>, <&main_udmap 0x494e>,
+			<&main_udmap 0x494f>;
+		dma-names = "rx0", "rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
+			    "rx8", "rx9", "rx10", "rx11", "rx12", "rx13", "rx14", "rx15";
+		reg = <0x0 0x4500000 0x0 0x1000>;
+		power-domains = <&k3_pds 26 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cdns_csi2rx0: csi-bridge@4504000 {
+			compatible = "cdns,csi2rx";
+			reg = <0x0 0x4504000 0x0 0x1000>;
+			clocks = <&k3_clks 26 2>, <&k3_clks 26 0>, <&k3_clks 26 2>,
+				<&k3_clks 26 2>, <&k3_clks 26 3>, <&k3_clks 26 3>;
+			clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+				"pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+			phys = <&dphy0>;
+			phy-names = "dphy";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				csi0_port0: port@0 {
+					reg = <0>;
+					status = "disabled";
+				};
+
+				csi0_port1: port@1 {
+					reg = <1>;
+					status = "disabled";
+				};
+
+				csi0_port2: port@2 {
+					reg = <2>;
+					status = "disabled";
+				};
+
+				csi0_port3: port@3 {
+					reg = <3>;
+					status = "disabled";
+				};
+
+				csi0_port4: port@4 {
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
+	ti_csi2rx1: ticsi2rx@4510000 {
+		status = "disabled";
+		compatible = "ti,j721e-csi2rx";
+		dmas = <&main_udmap 0x4960>, <&main_udmap 0x4961>, <&main_udmap 0x4962>,
+			<&main_udmap 0x4963>, <&main_udmap 0x4964>, <&main_udmap 0x4965>,
+			<&main_udmap 0x4966>, <&main_udmap 0x4967>, <&main_udmap 0x4968>,
+			<&main_udmap 0x4969>, <&main_udmap 0x496a>, <&main_udmap 0x496b>,
+			<&main_udmap 0x496c>, <&main_udmap 0x496d>, <&main_udmap 0x496e>,
+			<&main_udmap 0x496f>;
+		dma-names = "rx0", "rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7",
+			    "rx8", "rx9", "rx10", "rx11", "rx12", "rx13", "rx14", "rx15";
+		reg = <0x0 0x4510000 0x0 0x1000>;
+		power-domains = <&k3_pds 27 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cdns_csi2rx1: csi-bridge@4514000 {
+			compatible = "cdns,csi2rx";
+			reg = <0x0 0x4514000 0x0 0x1000>;
+			clocks = <&k3_clks 27 2>, <&k3_clks 27 0>, <&k3_clks 27 2>,
+				<&k3_clks 27 2>, <&k3_clks 27 3>, <&k3_clks 27 3>;
+			clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+				"pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+			phys = <&dphy1>;
+			phy-names = "dphy";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				csi1_port0: port@0 {
+					reg = <0>;
+					status = "disabled";
+				};
+
+				csi1_port1: port@1 {
+					reg = <1>;
+					status = "disabled";
+				};
+
+				csi1_port2: port@2 {
+					reg = <2>;
+					status = "disabled";
+				};
+
+				csi1_port3: port@3 {
+					reg = <3>;
+					status = "disabled";
+				};
+
+				csi1_port4: port@4 {
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
+	dphy0: phy@4580000 {
+		status = "disabled";
+		compatible = "cdns,dphy-rx";
+		reg = <0x0 0x4580000 0x0 0x1100>;
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 147 TI_SCI_PD_EXCLUSIVE>;
+	};
+
+	dphy1: phy@4590000 {
+		status = "disabled";
+		compatible = "cdns,dphy-rx";
+		reg = <0x0 0x4590000 0x0 0x1100>;
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 148 TI_SCI_PD_EXCLUSIVE>;
+	};
+
+	dphy2: phy@4480000 {
+		compatible = "ti,j721e-dphy";
+		reg = <0x0 0x04480000 0x0 0x1000>;
+		clocks = <&k3_clks 296 1>, <&k3_clks 296 3>;
+		clock-names = "psm", "pll_ref";
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 296 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 296 3>;
+		assigned-clock-parents = <&k3_clks 296 4>;
+		assigned-clock-rates = <19200000>;
+		status = "disabled";
 	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -79,6 +79,7 @@
 		power-domains = <&k3_pds 287 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 287 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	mcu_uart0: serial@40a00000 {
@@ -90,6 +91,7 @@
 		power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
 		clocks = <&k3_clks 149 0>;
 		clock-names = "fclk";
+		status = "disabled";
 	};
 
 	wkup_gpio_intr: interrupt-controller@42200000 {
@@ -145,6 +147,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 194 0>;
 		power-domains = <&k3_pds 194 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcu_i2c1: i2c@40b10000 {
@@ -156,6 +159,7 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 195 0>;
 		power-domains = <&k3_pds 195 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	wkup_i2c0: i2c@42120000 {
@@ -167,15 +171,36 @@
 		clock-names = "fck";
 		clocks = <&k3_clks 197 0>;
 		power-domains = <&k3_pds 197 TI_SCI_PD_SHARED>;
+		status = "disabled";
 	};
 
 	fss: fss@47000000 {
-		compatible = "simple-bus";
+		compatible = "ti,j721e-system-controller", "syscon", "simple-mfd";
 		reg = <0x0 0x47000000 0x0 0x100>;
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
 
+		hbmc_mux: mux-controller@47000004 {
+			compatible = "mmio-mux";
+			#mux-control-cells = <1>;
+			mux-reg-masks = <0x4 0x2>; /* HBMC select */
+		};
+
+		hbmc: hyperbus@47034000 {
+			compatible = "ti,am654-hbmc";
+			reg = <0x00 0x47034000 0x00 0x100>,
+				<0x05 0x00000000 0x01 0x0000000>;
+			power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>;
+			clocks = <&k3_clks 102 0>;
+			assigned-clocks = <&k3_clks 102 5>;
+			assigned-clock-rates = <333333333>;
+			#address-cells = <2>;
+			#size-cells = <1>;
+			mux-controls = <&hbmc_mux 0>;
+			status = "disabled";
+		};
+
 		ospi0: spi@47040000 {
 			compatible = "ti,am654-ospi", "cdns,qspi-nor";
 			reg = <0x0 0x47040000 0x0 0x100>,
@@ -353,7 +378,7 @@
 
 	mcu_r5fss0: r5fss@41000000 {
 		compatible = "ti,j721e-r5fss";
-		ti,cluster-mode = <1>;
+		ti,cluster-mode = <0>;
 		#address-cells = <1>;
 		#size-cells = <1>;
 		ranges = <0x41000000 0x00 0x41000000 0x20000>,
@@ -403,6 +428,7 @@
 			     <GIC_SPI 833 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	mcu_mcan1: can@40568000 {
@@ -417,5 +443,48 @@
 			     <GIC_SPI 836 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	mcu_spi0: spi@40300000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x040300000 0x00 0x400>;
+		interrupts = <GIC_SPI 848 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 274 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 274 0>;
+		status = "disabled";
+	};
+
+	mcu_spi1: spi@40310000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x040310000 0x00 0x400>;
+		interrupts = <GIC_SPI 849 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 275 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 275 0>;
+		status = "disabled";
+	};
+
+	mcu_spi2: spi@40320000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x040320000 0x00 0x400>;
+		interrupts = <GIC_SPI 850 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 276 0>;
+		status = "disabled";
+	};
+
+	wkup_vtm0: temperature-sensor@42040000 {
+		compatible = "ti,j721e-vtm";
+		reg = <0x00 0x42040000 0x00 0x350>,
+			<0x00 0x42050000 0x00 0x350>,
+			<0x00 0x43000300 0x00 0x10>;
+		power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
+		#thermal-sensor-cells = <1>;
 	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-ov5640.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-ov5640.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-ov5640.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * LI OV5640 MIPI Camera module on MIPI CSI connector.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&{/} {
+	clk_ov5640_fixed: ov5640-xclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+&main_pmx0 {
+	csi2_exp_pins_default: csi2-exp-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x140, PIN_OUTPUT, 7) /* (AG29) PRG0_PRU1_GPO16.GPIO0_79 */
+		>;
+	};
+};
+
+&main_i2c3 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	i2c-switch@70 {
+		compatible = "nxp,pca9543";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x70>;
+
+		ti_cam0_i2c: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			ov5640: camera@3c {
+				compatible = "ovti,ov5640";
+				reg = <0x3c>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&csi2_exp_pins_default>;
+				powerdown-gpios = <&main_gpio0 79 GPIO_ACTIVE_LOW>;
+				clocks = <&clk_ov5640_fixed>;
+				clock-names = "xclk";
+
+				port {
+					csi2_cam0: endpoint {
+						remote-endpoint = <&csi2rx0_in_sensor>;
+						clock-lanes = <0>;
+						data-lanes = <1 2>;
+					};
+				};
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-rpi-imx219.dtso b/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-rpi-imx219.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-rpi-imx219.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-sk-csi2-rpi-imx219.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RPi Camera V2.1 (Sony IMX219) Camera module on RPI camera connector.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-pinctrl.h"
+
+&{/} {
+	clk_imx219_fixed: imx219-xclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+	};
+};
+
+&main_pmx0 {
+	main_rpi_cam0_reset_pins_default: main-rpi-cam0-reset-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x1D4, PIN_OUTPUT, 7) /* (Y3) SPI1_CS0 */
+		>;
+	};
+
+	main_rpi_cam1_reset_pins_default: main-rpi-cam1-reset-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x1E0, PIN_OUTPUT, 7) /* (Y5) SPI1_D0 */
+		>;
+	};
+
+	main_csi_mux_sel2_pins_default: main-csi-mux-sel2-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x164, PIN_OUTPUT, 7) /* (V29) RGMII5_TD2 */
+		>;
+	};
+};
+
+&main_gpio0 {
+	csi-mux-hog {
+		/* CSI_MUX_SEL_2 */
+		gpio-hog;
+		gpios = <88 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "CSI_MUX_SEL_2";
+	};
+};
+
+&main_i2c3 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	i2c-switch@70 {
+		compatible = "nxp,pca9543";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x70>;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&main_csi_mux_sel2_pins_default>;
+
+		i2c-alias-pool = /bits/ 16 <0x10 0x11>;
+
+		/* CAM0 I2C */
+		cam0_i2c: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			imx219_0: imx219_0@10 {
+				compatible = "sony,imx219";
+				reg = <0x10>;
+				clocks = <&clk_imx219_fixed>;
+				clock-names = "xclk";
+				pinctrl-names = "default";
+				pinctrl-0 = <&main_rpi_cam0_reset_pins_default>;
+				reset-gpios = <&main_gpio0 116 GPIO_ACTIVE_HIGH>;
+
+				port {
+					csi2_cam0: endpoint {
+						remote-endpoint = <&csi2rx0_in_sensor>;
+						link-frequencies = /bits/ 64 <456000000>;
+						clock-lanes = <0>;
+						data-lanes = <1 2>;
+					};
+				};
+			};
+		};
+
+		/* CAM1 I2C */
+		cam1_i2c: i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>;
+
+			imx219_1: imx219_1@10 {
+				compatible = "sony,imx219";
+				reg = <0x10>;
+				clocks = <&clk_imx219_fixed>;
+				clock-names = "xclk";
+				pinctrl-names = "default";
+				pinctrl-0 = <&main_rpi_cam1_reset_pins_default>;
+				reset-gpios = <&main_gpio0 119 GPIO_ACTIVE_HIGH>;
+
+				port {
+					csi2_cam1: endpoint {
+						remote-endpoint = <&csi2rx1_in_sensor>;
+						link-frequencies = /bits/ 64 <456000000>;
+						clock-lanes = <0>;
+						data-lanes = <1 2>;
+					};
+				};
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
+
+&csi1_port0 {
+	status = "okay";
+
+	csi2rx1_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam1>;
+		bus-type = <4>; /* CSI2 DPHY. */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
--- a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts	2024-01-28 14:01:31.240353775 -0500
@@ -16,9 +16,17 @@
 	compatible = "ti,j721e-sk", "ti,j721e";
 	model = "Texas Instruments J721E SK";
 
+	aliases {
+		serial0 = &wkup_uart0;
+		serial1 = &mcu_uart0;
+		serial2 = &main_uart0;
+		serial3 = &main_uart1;
+		ethernet0 = &cpsw_port1;
+		mmc1 = &main_sdhci1;
+	};
+
 	chosen {
 		stdout-path = "serial2:115200n8";
-		bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000";
 	};
 
 	memory@80000000 {
@@ -33,6 +41,14 @@
 		#size-cells = <2>;
 		ranges;
 
+		 /* global cma region */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x00 0x20000000>;
+			linux,cma-default;
+		};
+
 		secure_ddr: optee@9e800000 {
 			reg = <0x00 0x9e800000 0x00 0x01800000>;
 			alignment = <0x1000>;
@@ -400,6 +416,47 @@
 			J721E_IOPAD(0x124, PIN_INPUT, 7) /* (Y24) PRG0_PRU1_GPO9.GPIO0_72 */
 		>;
 	};
+
+	main_i2c5_pins_default: main-i2c5-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x150, PIN_INPUT_PULLUP, 2) /* (Y26) PRG0_MDIO0_MDIO.I2C5_SCL */
+			J721E_IOPAD(0x154, PIN_INPUT_PULLUP, 2) /* (AA27) PRG0_MDIO0_MDC.I2C5_SDA */
+		>;
+	};
+
+	rpi_header_gpio0_pins_default: rpi-header-gpio0-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x01C, PIN_INPUT, 7) /* (AD22) PRG1_PRU0_GPO6.GPIO0_7 */
+			J721E_IOPAD(0x120, PIN_INPUT, 7) /* (AA28) PRG0_PRU1_GPO8.GPIO0_71 */
+			J721E_IOPAD(0x14C, PIN_INPUT, 7) /* (AA29) PRG0_PRU1_GPO19.GPIO0_82 */
+			J721E_IOPAD(0x02C, PIN_INPUT, 7) /* (AD21) PRG1_PRU0_GPO10.GPIO0_11 */
+			J721E_IOPAD(0x198, PIN_INPUT, 7) /* (V25) RGMII6_TD1.GPIO0_101 */
+			J721E_IOPAD(0x1B0, PIN_INPUT, 7) /* (W24) RGMII6_RD1.GPIO0_107 */
+			J721E_IOPAD(0x1A0, PIN_INPUT, 7) /* (W29) RGMII6_TXC.GPIO0_103 */
+			J721E_IOPAD(0x008, PIN_INPUT, 7) /* (AG22) PRG1_PRU0_GPO1.GPIO0_2 */
+			J721E_IOPAD(0x1D0, PIN_INPUT, 7) /* (AA3) SPI0_D1.GPIO0_115 */
+			J721E_IOPAD(0x11C, PIN_INPUT, 7) /* (AA24) PRG0_PRU1_GPO7.GPIO0_70 */
+			J721E_IOPAD(0x148, PIN_INPUT, 7) /* (AA26) PRG0_PRU1_GPO18.GPIO0_81 */
+			J721E_IOPAD(0x004, PIN_INPUT, 7) /* (AC23) PRG1_PRU0_GPO0.GPIO0_1 */
+			J721E_IOPAD(0x014, PIN_INPUT, 7) /* (AH23) PRG1_PRU0_GPO4.GPIO0_5 */
+			J721E_IOPAD(0x020, PIN_INPUT, 7) /* (AE20) PRG1_PRU0_GPO7.GPIO0_8 */
+			J721E_IOPAD(0x19C, PIN_INPUT, 7) /* (W27) RGMII6_TD0.GPIO0_102 */
+			J721E_IOPAD(0x1B4, PIN_INPUT, 7) /* (W25) RGMII6_RD0.GPIO0_108 */
+			J721E_IOPAD(0x188, PIN_INPUT, 7) /* (Y28) RGMII6_TX_CTL.GPIO0_97 */
+			J721E_IOPAD(0x00C, PIN_INPUT, 7) /* (AF22) PRG1_PRU0_GPO2.GPIO0_3 */
+			J721E_IOPAD(0x010, PIN_INPUT, 7) /* (AJ23) PRG1_PRU0_GPO3.GPIO0_4 */
+			J721E_IOPAD(0x178, PIN_INPUT, 7) /* (U27) RGMII5_RD3.GPIO0_93 */
+			J721E_IOPAD(0x17C, PIN_INPUT, 7) /* (U24) RGMII5_RD2.GPIO0_94 */
+			J721E_IOPAD(0x190, PIN_INPUT, 7) /* (W23) RGMII6_TD3.GPIO0_99 */
+			J721E_IOPAD(0x18C, PIN_INPUT, 7) /* (V23) RGMII6_RX_CTL.GPIO0_98 */
+		>;
+	};
+
+	rpi_header_gpio1_pins_default: rpi-header-gpio1-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x234, PIN_INPUT, 7) /* (U3) EXT_REFCLK1.GPIO1_12 */
+		>;
+	};
 };
 
 &wkup_pmx0 {
@@ -475,46 +532,22 @@
 	status = "reserved";
 };
 
+&mcu_uart0 {
+	status = "okay";
+	/* Default pinmux */
+};
+
 &main_uart0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart0_pins_default>;
 	/* Shared with ATF on this platform */
 	power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
 };
 
-&main_uart2 {
-	/* Brought out on RPi header */
-	status = "disabled";
-};
-
-&main_uart3 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
-&main_uart5 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
-&main_uart6 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
-&main_uart7 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
-&main_uart8 {
-	/* UART not brought out */
-	status = "disabled";
-};
-
-&main_uart9 {
-	/* Brought out on M.2 E Key */
-	status = "disabled";
+&main_uart1 {
+	status = "okay";
+	/* Default pinmux */
 };
 
 &main_sdhci0 {
@@ -524,6 +557,7 @@
 
 &main_sdhci1 {
 	/* SD Card */
+	status = "okay";
 	vmmc-supply = <&vdd_mmc1>;
 	vqmmc-supply = <&vdd_sd_dv_alt>;
 	pinctrl-names = "default";
@@ -538,6 +572,7 @@
 };
 
 &ospi0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcu_fss0_ospi0_pins_default>;
 
@@ -552,6 +587,52 @@
 		cdns,tchsh-ns = <60>;
 		cdns,tslch-ns = <60>;
 		cdns,read-delay = <4>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi.sysfw";
+				reg = <0x6c0000 0x100000>;
+			};
+
+			partition@7c0000 {
+				label = "ospi.env.backup";
+				reg = <0x7c0000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "ospi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fc0000 {
+				label = "ospi.phypattern";
+				reg = <0x3fc0000 0x40000>;
+			};
+		};
 	};
 };
 
@@ -561,6 +642,7 @@
 };
 
 &main_i2c0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c0_pins_default>;
 	clock-frequency = <400000>;
@@ -588,18 +670,15 @@
 };
 
 &main_i2c1 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c1_pins_default>;
 	/* i2c1 is used for DVI DDC, so we need to use 100kHz */
 	clock-frequency = <100000>;
 };
 
-&main_i2c2 {
-	/* Unused */
-	status = "disabled";
-};
-
 &main_i2c3 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c3_pins_default>;
 	clock-frequency = <400000>;
@@ -626,19 +705,24 @@
 	};
 };
 
-&main_i2c4 {
-	/* Unused */
-	status = "disabled";
-};
-
 &main_i2c5 {
 	/* Brought out on RPi Header */
-	status = "disabled";
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c5_pins_default>;
+	clock-frequency = <400000>;
 };
 
-&main_i2c6 {
-	/* Unused */
-	status = "disabled";
+&main_gpio0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio0_pins_default>;
+};
+
+&main_gpio1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio1_pins_default>;
 };
 
 &main_gpio2 {
@@ -767,7 +851,7 @@
 
 &mcu_cpsw {
 	pinctrl-names = "default";
-	pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
+	pinctrl-0 = <&mcu_cpsw_pins_default>, <&mcu_mdio_pins_default>;
 };
 
 &davinci_mdio {
@@ -783,6 +867,24 @@
 	phy-handle = <&phy0>;
 };
 
+&ti_csi2rx0 {
+	status = "okay";
+	/* MIPI-CSI Connector */
+};
+
+&ti_csi2rx1 {
+	status = "okay";
+	/* MIPI-CSI Connector */
+};
+
+&dphy0 {
+	status = "okay";
+};
+
+&dphy1 {
+	status = "okay";
+};
+
 &dss {
 	pinctrl-names = "default";
 	pinctrl-0 = <&dss_vout0_pins_default>;
@@ -837,66 +939,6 @@
 	};
 };
 
-&mcasp0 {
-	/* Unused */
-	status = "disabled";
-};
-
-&mcasp1 {
-	/* Unused */
-	status = "disabled";
-};
-
-&mcasp2 {
-	/* Unused */
-	status = "disabled";
-};
-
-&mcasp3 {
-	/* Unused */
-	status = "disabled";
-};
-
-&mcasp4 {
-	/* Unused */
-	status = "disabled";
-};
-
-&mcasp5 {
-	/* Unused */
-	status = "disabled";
-};
-
-&mcasp6 {
-	/* Brought out on RPi header */
-	status = "disabled";
-};
-
-&mcasp7 {
-	/* Unused */
-	status = "disabled";
-};
-
-&mcasp8 {
-	/* Unused */
-	status = "disabled";
-};
-
-&mcasp9 {
-	/* Unused */
-	status = "disabled";
-};
-
-&mcasp10 {
-	/* Unused */
-	status = "disabled";
-};
-
-&mcasp11 {
-	/* Brought out on M.2 E Key */
-	status = "disabled";
-};
-
 &serdes0 {
 	serdes0_pcie_link: phy@0 {
 		reg = <0>;
@@ -918,6 +960,7 @@
 };
 
 &pcie0_rc {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&ekey_reset_pins_default>;
 	reset-gpios = <&main_gpio0 72 GPIO_ACTIVE_HIGH>;
@@ -928,6 +971,7 @@
 };
 
 &pcie1_rc {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&mkey_reset_pins_default>;
 	reset-gpios = <&wkup_gpio0 11 GPIO_ACTIVE_HIGH>;
@@ -937,53 +981,12 @@
 	num-lanes = <2>;
 };
 
-&pcie2_rc {
-	/* Unused */
-	status = "disabled";
-};
-
-&pcie0_ep {
-	status = "disabled";
-	phys = <&serdes0_pcie_link>;
-	phy-names = "pcie-phy";
-	num-lanes = <1>;
-};
-
-&pcie1_ep {
-	status = "disabled";
-	phys = <&serdes1_pcie_link>;
-	phy-names = "pcie-phy";
-	num-lanes = <2>;
-};
-
-&pcie2_ep {
-	/* Unused */
-	status = "disabled";
-};
-
-&pcie3_rc {
-	/* Unused */
-	status = "disabled";
-};
-
-&pcie3_ep {
-	/* Unused */
-	status = "disabled";
-};
-
-&icssg0_mdio {
-	status = "disabled";
-};
-
-&icssg1_mdio {
-	status = "disabled";
-};
-
 &ufs_wrapper {
 	status = "disabled";
 };
 
 &mailbox0_cluster0 {
+	status = "okay";
 	interrupts = <436>;
 
 	mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
@@ -998,6 +1001,7 @@
 };
 
 &mailbox0_cluster1 {
+	status = "okay";
 	interrupts = <432>;
 
 	mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
@@ -1012,6 +1016,7 @@
 };
 
 &mailbox0_cluster2 {
+	status = "okay";
 	interrupts = <428>;
 
 	mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
@@ -1026,6 +1031,7 @@
 };
 
 &mailbox0_cluster3 {
+	status = "okay";
 	interrupts = <424>;
 
 	mbox_c66_0: mbox-c66-0 {
@@ -1040,6 +1046,7 @@
 };
 
 &mailbox0_cluster4 {
+	status = "okay";
 	interrupts = <420>;
 
 	mbox_c71_0: mbox-c71-0 {
@@ -1048,84 +1055,59 @@
 	};
 };
 
-&mailbox0_cluster5 {
-	status = "disabled";
-};
-
-&mailbox0_cluster6 {
-	status = "disabled";
-};
-
-&mailbox0_cluster7 {
-	status = "disabled";
-};
-
-&mailbox0_cluster8 {
-	status = "disabled";
-};
-
-&mailbox0_cluster9 {
-	status = "disabled";
-};
-
-&mailbox0_cluster10 {
-	status = "disabled";
-};
-
-&mailbox0_cluster11 {
-	status = "disabled";
-};
-
 &mcu_r5fss0_core0 {
-	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
+	mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>;
 	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
 			<&mcu_r5fss0_core0_memory_region>;
 };
 
 &mcu_r5fss0_core1 {
-	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>;
+	mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>;
 	memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
 			<&mcu_r5fss0_core1_memory_region>;
 };
 
 &main_r5fss0_core0 {
-	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>;
+	mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>;
 	memory-region = <&main_r5fss0_core0_dma_memory_region>,
 			<&main_r5fss0_core0_memory_region>;
 };
 
 &main_r5fss0_core1 {
-	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>;
+	mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>;
 	memory-region = <&main_r5fss0_core1_dma_memory_region>,
 			<&main_r5fss0_core1_memory_region>;
 };
 
 &main_r5fss1_core0 {
-	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>;
+	mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core0>;
 	memory-region = <&main_r5fss1_core0_dma_memory_region>,
 			<&main_r5fss1_core0_memory_region>;
 };
 
 &main_r5fss1_core1 {
-	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>;
+	mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core1>;
 	memory-region = <&main_r5fss1_core1_dma_memory_region>,
 			<&main_r5fss1_core1_memory_region>;
 };
 
 &c66_0 {
-	mboxes = <&mailbox0_cluster3 &mbox_c66_0>;
+	status = "okay";
+	mboxes = <&mailbox0_cluster3>, <&mbox_c66_0>;
 	memory-region = <&c66_0_dma_memory_region>,
 			<&c66_0_memory_region>;
 };
 
 &c66_1 {
-	mboxes = <&mailbox0_cluster3 &mbox_c66_1>;
+	status = "okay";
+	mboxes = <&mailbox0_cluster3>, <&mbox_c66_1>;
 	memory-region = <&c66_1_dma_memory_region>,
 			<&c66_1_memory_region>;
 };
 
 &c71_0 {
-	mboxes = <&mailbox0_cluster4 &mbox_c71_0>;
+	status = "okay";
+	mboxes = <&mailbox0_cluster4>, <&mbox_c71_0>;
 	memory-region = <&c71_0_dma_memory_region>,
 			<&c71_0_memory_region>;
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-sk-fusion.dtso b/arch/arm64/boot/dts/ti/k3-j721e-sk-fusion.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721e-sk-fusion.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-sk-fusion.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay for Fusion (FPD-Link III) board on J721E SK
+ * https://svtronics.com/portfolio/evm577pfusion-v1-0-fusion/
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_fusion_25M_fixed: fixed-clock-25M {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+
+&main_i2c3 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	i2c-switch@70 {
+		compatible = "nxp,pca9543";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x70>;
+
+		cam0_i2c: i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			deser@3d {
+				compatible = "ti,ds90ub960-q1";
+				reg = <0x3d>;
+				clocks = <&clk_fusion_25M_fixed>;
+				clock-names = "refclk";
+				i2c-alias-pool = <0x4a 0x4b 0x4c 0x4d 0x4e 0x4f>;
+
+				ds90ub960_0_ports: ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* CSI-2 TX */
+					port@4 {
+						reg = <4>;
+						ds90ub960_0_csi_out: endpoint {
+							clock-lanes = <0>;
+							data-lanes = <1 2 3 4>;
+							link-frequencies = /bits/ 64 <800000000>;
+							remote-endpoint = <&csi2_phy0>;
+						};
+					};
+				};
+
+				ds90ub960_0_links: links {
+					#address-cells = <1>;
+					#size-cells = <0>;
+				};
+			};
+
+			deser@36 {
+				compatible = "ti,ds90ub960-q1";
+				reg = <0x36>;
+				clocks = <&clk_fusion_25M_fixed>;
+				clock-names = "refclk";
+				i2c-alias-pool = <0x5a 0x5b 0x5c 0x5d 0x5e 0x5f>;
+
+				ds90ub960_1_ports: ports {
+					#address-cells = <1>;
+					#size-cells = <0>;
+
+					/* CSI-2 TX */
+					port@4 {
+						reg = <4>;
+						ds90ub960_1_csi_out: endpoint {
+							clock-lanes = <0>;
+							data-lanes = <1 2 3 4>;
+							link-frequencies = /bits/ 64 <800000000>;
+							remote-endpoint = <&csi2_phy1>;
+						};
+					};
+				};
+
+				ds90ub960_1_links: links {
+					#address-cells = <1>;
+					#size-cells = <0>;
+				};
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2_phy0: endpoint {
+		remote-endpoint = <&ds90ub960_0_csi_out>;
+		clock-lanes = <0>;
+		data-lanes = <1 2 3 4>;
+		link-frequencies = /bits/ 64 <800000000>;
+	};
+};
+
+&csi1_port0 {
+	status = "okay";
+
+	csi2_phy1: endpoint {
+		remote-endpoint = <&ds90ub960_1_csi_out>;
+		clock-lanes = <0>;
+		data-lanes = <1 2 3 4>;
+		link-frequencies = /bits/ 64 <800000000>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-sk-rpi-hdr-ehrpwm.dtso b/arch/arm64/boot/dts/ti/k3-j721e-sk-rpi-hdr-ehrpwm.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721e-sk-rpi-hdr-ehrpwm.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-sk-rpi-hdr-ehrpwm.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for enabling EHRPWMs on RPi expansion header on J721E SK board.
+ *
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "k3-pinctrl.h"
+
+&main_pmx0 {
+	rpi_header_gpio0_pins_default: rpi-header-gpio0-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x01C, PIN_INPUT, 7) /* (AD22) PRG1_PRU0_GPO6.GPIO0_7 */
+			J721E_IOPAD(0x120, PIN_INPUT, 7) /* (AD28) PRG0_PRU1_GPO8.GPIO0_71 */
+			J721E_IOPAD(0x14C, PIN_INPUT, 7) /* (AD29) PRG0_PRU1_GPO19.GPIO0_82 */
+			J721E_IOPAD(0x02C, PIN_INPUT, 7) /* (AD21) PRG1_PRU0_GPO10.GPIO0_11 */
+			J721E_IOPAD(0x198, PIN_INPUT, 7) /* (V25) RGMII6_TD1.GPIO0_101 */
+			J721E_IOPAD(0x1B0, PIN_INPUT, 7) /* (W24) RGMII6_RD1.GPIO0_107 */
+			J721E_IOPAD(0x1A0, PIN_INPUT, 7) /* (W29) RGMII6_TXC.GPIO0_103 */
+			J721E_IOPAD(0x008, PIN_INPUT, 7) /* (AG22) PRG1_PRU0_GPO1.GPIO0_2 */
+			J721E_IOPAD(0x1D0, PIN_INPUT, 7) /* (AA3) SPI0_D1.GPIO0_115 */
+			J721E_IOPAD(0x11C, PIN_INPUT, 7) /* (AA24) PRG0_PRU1_GPO7.GPIO0_70 */
+			J721E_IOPAD(0x148, PIN_INPUT, 7) /* (AA26) PRG0_PRU1_GPO18.GPIO0_81 */
+			J721E_IOPAD(0x004, PIN_INPUT, 7) /* (AC23) PRG1_PRU0_GPO0.GPIO0_1 */
+			J721E_IOPAD(0x014, PIN_INPUT, 7) /* (AH23) PRG1_PRU0_GPO4.GPIO0_5 */
+			J721E_IOPAD(0x020, PIN_INPUT, 7) /* (AE20) PRG1_PRU0_GPO7.GPIO0_8 */
+			J721E_IOPAD(0x19C, PIN_INPUT, 7) /* (W27) RGMII6_TD0.GPIO0_102 */
+			J721E_IOPAD(0x1B4, PIN_INPUT, 7) /* (W25) RGMII6_RD0.GPIO0_108 */
+			J721E_IOPAD(0x188, PIN_INPUT, 7) /* (Y28) RGMII6_TX_CTL.GPIO0_97 */
+			J721E_IOPAD(0x00C, PIN_INPUT, 7) /* (AF22) PRG1_PRU0_GPO2.GPIO0_3 */
+			J721E_IOPAD(0x010, PIN_INPUT, 7) /* (AJ23) PRG1_PRU0_GPO3.GPIO0_4 */
+		>;
+	};
+
+	rpi_header_ehrpwm2_pins_default: rpi-header-ehrpwm2-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x178, PIN_INPUT, 6) /* (U27) RGMII5_RD3.EHRPWM2_A */
+			J721E_IOPAD(0x17C, PIN_INPUT, 6) /* (U24) RGMII5_RD2.EHRPWM2_B */
+		>;
+	};
+
+	rpi_header_ehrpwm3_pins_default: rpi-header-ehrpwm3-pins-default {
+		pinctrl-single,pins = <
+			J721E_IOPAD(0x18C, PIN_INPUT, 6) /* (V23) RGMII6_RX_CTL.EHRPWM3_A */
+			J721E_IOPAD(0x190, PIN_INPUT, 6) /* (W23) RGMII6_TD3.EHRPWM3_B */
+		>;
+	};
+};
+
+&main_ehrpwm2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm2_pins_default>;
+	status = "okay";
+};
+
+&main_ehrpwm3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_ehrpwm3_pins_default>;
+	status = "okay";
+};
+
+&main_gpio0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&rpi_header_gpio0_pins_default>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -1,6 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2019-2020 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * Product Link: https://www.ti.com/tool/J721EXSOMXEVM
  */
 
 /dts-v1/;
@@ -20,6 +22,14 @@
 		#size-cells = <2>;
 		ranges;
 
+		 /* global cma region */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x00 0x20000000>;
+			linux,cma-default;
+		};
+
 		secure_ddr: optee@9e800000 {
 			reg = <0x00 0x9e800000 0x00 0x01800000>;
 			alignment = <0x1000>;
@@ -150,6 +160,12 @@
 		>;
 	};
 
+	pmic_irq_pins_default: pmic-irq-pins-default {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0xd4, PIN_INPUT, 7) /* (G26) WKUP_GPIO0_9 */
+		>;
+	};
+
 	mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-pins-default {
 		pinctrl-single,pins = <
 			J721E_WKUP_IOPAD(0x0000, PIN_OUTPUT, 0) /* MCU_OSPI0_CLK */
@@ -165,9 +181,29 @@
 			J721E_WKUP_IOPAD(0x002c, PIN_OUTPUT, 0) /* MCU_OSPI0_CSn0 */
 		>;
 	};
+
+	mcu_fss0_hpb0_pins_default: mcu-fss0-hpb0-pins-default {
+		pinctrl-single,pins = <
+			J721E_WKUP_IOPAD(0x0, PIN_OUTPUT, 1)  /* MCU_HYPERBUS0_CK */
+			J721E_WKUP_IOPAD(0x4, PIN_OUTPUT, 1)  /* MCU_HYPERBUS0_CKn */
+			J721E_WKUP_IOPAD(0x2c, PIN_OUTPUT, 1) /* MCU_HYPERBUS0_CSn0 */
+			J721E_WKUP_IOPAD(0x54, PIN_OUTPUT, 3) /* MCU_HYPERBUS0_CSn1 */
+			J721E_WKUP_IOPAD(0x30, PIN_OUTPUT, 1) /* MCU_HYPERBUS0_RESETn */
+			J721E_WKUP_IOPAD(0x8, PIN_INPUT, 1)   /* MCU_HYPERBUS0_RWDS */
+			J721E_WKUP_IOPAD(0xc, PIN_INPUT, 1)   /* MCU_HYPERBUS0_DQ0 */
+			J721E_WKUP_IOPAD(0x10, PIN_INPUT, 1)  /* MCU_HYPERBUS0_DQ1 */
+			J721E_WKUP_IOPAD(0x14, PIN_INPUT, 1)  /* MCU_HYPERBUS0_DQ2 */
+			J721E_WKUP_IOPAD(0x18, PIN_INPUT, 1)  /* MCU_HYPERBUS0_DQ3 */
+			J721E_WKUP_IOPAD(0x1c, PIN_INPUT, 1)  /* MCU_HYPERBUS0_DQ4 */
+			J721E_WKUP_IOPAD(0x20, PIN_INPUT, 1)  /* MCU_HYPERBUS0_DQ5 */
+			J721E_WKUP_IOPAD(0x24, PIN_INPUT, 1)  /* MCU_HYPERBUS0_DQ6 */
+			J721E_WKUP_IOPAD(0x28, PIN_INPUT, 1)  /* MCU_HYPERBUS0_DQ7 */
+		>;
+	};
 };
 
 &ospi0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcu_fss0_ospi0_pins_default>;
 
@@ -182,10 +218,109 @@
 		cdns,tchsh-ns = <60>;
 		cdns,tslch-ns = <60>;
 		cdns,read-delay = <0>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi.env";
+				reg = <0x680000 0x20000>;
+			};
+
+			partition@6a0000 {
+				label = "ospi.env.backup";
+				reg = <0x6a0000 0x20000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi.sysfw";
+				reg = <0x6c0000 0x100000>;
+			};
+
+			partition@800000 {
+				label = "ospi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fe0000 {
+				label = "ospi.phypattern";
+				reg = <0x3fe0000 0x20000>;
+			};
+		};
+	};
+};
+
+&hbmc {
+	/* OSPI and HBMC are muxed inside FSS, Bootloader will enable
+	 * appropriate node based on board detection
+	 */
+	status = "disabled";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_fss0_hpb0_pins_default>;
+	ranges = <0x00 0x00 0x05 0x00000000 0x4000000>, /* 64MB Flash on CS0 */
+		 <0x01 0x00 0x05 0x04000000 0x800000>; /* 8MB RAM on CS1 */
+
+	flash@0,0 {
+		compatible = "cypress,hyperflash", "cfi-flash";
+		reg = <0x00 0x00 0x4000000>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "hbmc.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "hbmc.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "hbmc.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "hbmc.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "hbmc.sysfw";
+				reg = <0x6c0000 0x100000>;
+			};
+
+			partition@800000 {
+				label = "hbmc.rootfs";
+				reg = <0x800000 0x3800000>;
+			};
+		};
 	};
 };
 
 &mailbox0_cluster0 {
+	status = "okay";
 	interrupts = <436>;
 
 	mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
@@ -200,6 +335,7 @@
 };
 
 &mailbox0_cluster1 {
+	status = "okay";
 	interrupts = <432>;
 
 	mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
@@ -214,6 +350,7 @@
 };
 
 &mailbox0_cluster2 {
+	status = "okay";
 	interrupts = <428>;
 
 	mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
@@ -228,6 +365,7 @@
 };
 
 &mailbox0_cluster3 {
+	status = "okay";
 	interrupts = <424>;
 
 	mbox_c66_0: mbox-c66-0 {
@@ -242,6 +380,7 @@
 };
 
 &mailbox0_cluster4 {
+	status = "okay";
 	interrupts = <420>;
 
 	mbox_c71_0: mbox-c71-0 {
@@ -250,84 +389,256 @@
 	};
 };
 
-&mailbox0_cluster5 {
-	status = "disabled";
-};
-
-&mailbox0_cluster6 {
-	status = "disabled";
-};
-
-&mailbox0_cluster7 {
-	status = "disabled";
-};
-
-&mailbox0_cluster8 {
-	status = "disabled";
-};
-
-&mailbox0_cluster9 {
-	status = "disabled";
-};
-
-&mailbox0_cluster10 {
-	status = "disabled";
-};
-
-&mailbox0_cluster11 {
-	status = "disabled";
-};
-
 &mcu_r5fss0_core0 {
-	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
+	mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core0>;
 	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
 			<&mcu_r5fss0_core0_memory_region>;
 };
 
 &mcu_r5fss0_core1 {
-	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>;
+	mboxes = <&mailbox0_cluster0>, <&mbox_mcu_r5fss0_core1>;
 	memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
 			<&mcu_r5fss0_core1_memory_region>;
 };
 
 &main_r5fss0_core0 {
-	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>;
+	mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core0>;
 	memory-region = <&main_r5fss0_core0_dma_memory_region>,
 			<&main_r5fss0_core0_memory_region>;
 };
 
 &main_r5fss0_core1 {
-	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>;
+	mboxes = <&mailbox0_cluster1>, <&mbox_main_r5fss0_core1>;
 	memory-region = <&main_r5fss0_core1_dma_memory_region>,
 			<&main_r5fss0_core1_memory_region>;
 };
 
 &main_r5fss1_core0 {
-	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>;
+	mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core0>;
 	memory-region = <&main_r5fss1_core0_dma_memory_region>,
 			<&main_r5fss1_core0_memory_region>;
 };
 
 &main_r5fss1_core1 {
-	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>;
+	mboxes = <&mailbox0_cluster2>, <&mbox_main_r5fss1_core1>;
 	memory-region = <&main_r5fss1_core1_dma_memory_region>,
 			<&main_r5fss1_core1_memory_region>;
 };
 
 &c66_0 {
-	mboxes = <&mailbox0_cluster3 &mbox_c66_0>;
+	status = "okay";
+	mboxes = <&mailbox0_cluster3>, <&mbox_c66_0>;
 	memory-region = <&c66_0_dma_memory_region>,
 			<&c66_0_memory_region>;
 };
 
 &c66_1 {
-	mboxes = <&mailbox0_cluster3 &mbox_c66_1>;
+	status = "okay";
+	mboxes = <&mailbox0_cluster3>, <&mbox_c66_1>;
 	memory-region = <&c66_1_dma_memory_region>,
 			<&c66_1_memory_region>;
 };
 
 &c71_0 {
-	mboxes = <&mailbox0_cluster4 &mbox_c71_0>;
+	status = "okay";
+	mboxes = <&mailbox0_cluster4>, <&mbox_c71_0>;
 	memory-region = <&c71_0_dma_memory_region>,
 			<&c71_0_memory_region>;
 };
+
+&wkup_i2c0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_i2c0_pins_default>;
+	clock-frequency = <400000>;
+	status = "okay";
+
+	tps659413: pmic@48 {
+		compatible = "ti,tps6594-q1";
+		reg = <0x48>;
+		system-power-controller;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_irq_pins_default>;
+		interrupt-parent = <&wkup_gpio0>;
+		interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+		ti,primary-pmic;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		buck12-supply = <&vsys_3v3>;
+		buck3-supply = <&vsys_3v3>;
+		buck4-supply = <&vsys_3v3>;
+		buck5-supply = <&vsys_3v3>;
+		ldo1-supply = <&vsys_3v3>;
+		ldo2-supply = <&vsys_3v3>;
+		ldo3-supply = <&vsys_3v3>;
+		ldo4-supply = <&vsys_3v3>;
+
+		regulators {
+			bucka12: buck12 {
+				regulator-name = "vdd_cpu_avs";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			bucka3: buck3 {
+				regulator-name = "vdd_mcu_0v85";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			bucka4: buck4 {
+				regulator-name = "vdd_ddr_1v1";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			bucka5: buck5 {
+				regulator-name = "vdd_phyio_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa1: ldo1 {
+				regulator-name = "vdd1_lpddr4_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa2: ldo2 {
+				regulator-name = "vdd_mcuio_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa3: ldo3 {
+				regulator-name = "vdda_dll_0v8";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa4: ldo4 {
+				regulator-name = "vda_mcu_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+
+	tps659411: pmic@4c {
+		compatible = "ti,tps6594-q1";
+		reg = <0x4c>;
+		system-power-controller;
+		interrupt-parent = <&wkup_gpio0>;
+		interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		buck1234-supply = <&vsys_3v3>;
+		buck5-supply = <&vsys_3v3>;
+		ldo1-supply = <&vsys_3v3>;
+		ldo2-supply = <&vsys_3v3>;
+		ldo3-supply = <&vsys_3v3>;
+		ldo4-supply = <&vsys_3v3>;
+
+		regulators {
+			buckb1234: buck1234 {
+				regulator-name = "vdd_core_0v8";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buckb5: buck5 {
+				regulator-name = "vdd_ram_0v85";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldob1: ldo1 {
+				regulator-name = "vdd_sd_dv";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldob2: ldo2 {
+				regulator-name = "vdd_usb_3v3";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldob3: ldo3 {
+				regulator-name = "vdd_io_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldob4: ldo4 {
+				regulator-name = "vda_pll_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+
+	tps65917: pmic@58 {
+		reg = <0x58>;
+		compatible = "ti,tps65917";
+		status = "disabled";
+		tps65917-pmic {
+			compatible = "ti,tps65917-pmic";
+
+			ldo1-in-supply = <&vsys_3v3>;
+			ldo2-in-supply = <&vsys_3v3>;
+
+			tps65917_regulators: regulators {
+				ldo1_reg: ldo1 {
+					/* LDO1_OUT --> VDD_SD_DV_REG  */
+					regulator-name = "ldo1";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-allow-bypass;
+				};
+
+				ldo2_reg: ldo2 {
+					/* LDO2_OUT --> VDA_USB_3V3_REG  */
+					regulator-name = "ldo2";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-allow-bypass;
+					regulator-always-on;
+					regulator-boot-on;
+				};
+			};
+		};
+	};
+
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721e-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-thermal.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j721e-thermal.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721e-thermal.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/thermal/thermal.h>
+
+thermal_zones: thermal-zones {
+	wkup_thermal: wkup-thermal {
+		polling-delay-passive = <250>; /* milliseconds */
+		polling-delay = <500>; /* milliseconds */
+		thermal-sensors = <&wkup_vtm0 0>;
+
+		trips {
+			wkup_crit: wkup-crit {
+				temperature = <125000>; /* milliCelsius */
+				hysteresis = <2000>; /* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+
+	mpu_thermal: mpu-thermal {
+		polling-delay-passive = <250>; /* milliseconds */
+		polling-delay = <500>; /* milliseconds */
+		thermal-sensors = <&wkup_vtm0 1>;
+
+		trips {
+			mpu_crit: mpu-crit {
+				temperature = <125000>; /* milliCelsius */
+				hysteresis = <2000>; /* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+
+	c7x_thermal: c7x-thermal {
+		polling-delay-passive = <250>; /* milliseconds */
+		polling-delay = <500>; /* milliseconds */
+		thermal-sensors = <&wkup_vtm0 2>;
+
+		trips {
+			c7x_crit: c7x-crit {
+				temperature = <125000>; /* milliCelsius */
+				hysteresis = <2000>; /* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+
+	gpu_thermal: gpu-thermal {
+		polling-delay-passive = <250>; /* milliseconds */
+		polling-delay = <500>; /* milliseconds */
+		thermal-sensors = <&wkup_vtm0 3>;
+
+		trips {
+			gpu_crit: gpu-crit {
+				temperature = <125000>; /* milliCelsius */
+				hysteresis = <2000>; /* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+
+	r5f_thermal: r5f-thermal {
+		polling-delay-passive = <250>; /* milliseconds */
+		polling-delay = <500>; /* milliseconds */
+		thermal-sensors = <&wkup_vtm0 4>;
+
+		trips {
+			r5f_crit: r5f-crit {
+				temperature = <125000>; /* milliCelsius */
+				hysteresis = <2000>; /* milliCelsius */
+				type = "critical";
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts
--- a/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts	2024-01-28 14:01:31.240353775 -0500
@@ -9,6 +9,9 @@
 
 #include "k3-j721s2-som-p0.dtsi"
 #include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/phy/phy-cadence.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/mux/ti-serdes.h>
 
 / {
 	compatible = "ti,j721s2-evm", "ti,j721s2";
@@ -20,6 +23,7 @@
 	};
 
 	aliases {
+		serial0 = &wkup_uart0;
 		serial1 = &mcu_uart0;
 		serial2 = &main_uart8;
 		mmc0 = &main_sdhci0;
@@ -27,6 +31,8 @@
 		can0 = &main_mcan16;
 		can1 = &mcu_mcan0;
 		can2 = &mcu_mcan1;
+		can3 = &main_mcan3;
+		can4 = &main_mcan5;
 	};
 
 	evm_12v0: fixedregulator-evm12v0 {
@@ -107,6 +113,82 @@
 		standby-gpios = <&wkup_gpio0 2 GPIO_ACTIVE_HIGH>;
 	};
 
+	transceiver3: can-phy3 {
+		compatible = "ti,tcan1043";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+		standby-gpios = <&exp2 7 GPIO_ACTIVE_LOW>;
+		enable-gpios = <&exp2 6 GPIO_ACTIVE_HIGH>;
+		mux-states = <&mux0 1>;
+	};
+
+	transceiver4: can-phy4 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+		standby-gpios = <&exp_som 7 GPIO_ACTIVE_HIGH>;
+		mux-states = <&mux1 1>;
+	};
+
+	dp0_pwr_3v3: fixedregulator-dp0-prw {
+		compatible = "regulator-fixed";
+		regulator-name = "dp0-pwr";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&exp4 0 0>;	/* P0 - DP0_PWR_SW_EN */
+		enable-active-high;
+	};
+
+	dp1_pwr_3v3: regulator-dp1-prw {
+		compatible = "regulator-fixed";
+		regulator-name = "dp1-pwr";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&exp4 1 GPIO_ACTIVE_HIGH>; /* P1 - DP1_PWR_SW_EN */
+		enable-active-high;
+		regulator-always-on;
+	};
+
+	dp0: dp0-connector {
+		compatible = "dp-connector";
+		label = "DP0";
+		type = "full-size";
+		dp-pwr-supply = <&dp0_pwr_3v3>;
+
+		port {
+			dp0_connector_in: endpoint {
+				remote-endpoint = <&dp0_out>;
+			};
+		};
+	};
+};
+
+&main_i2c4 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c4_pins_default>;
+	clock-frequency = <400000>;
+
+	exp4: gpio@20 {
+		compatible = "ti,tca6408";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
+
+&main_i2c5 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c5_pins_default>;
+	clock-frequency = <400000>;
+
+	exp5: gpio@20 {
+		compatible = "ti,tca6408";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
 };
 
 &main_pmx0 {
@@ -144,57 +226,156 @@
 			J721S2_IOPAD(0x020, PIN_INPUT, 7) /* (AA23) MCAN15_RX.GPIO0_8 */
 		>;
 	};
+
+	main_usbss0_pins_default: main-usbss0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0ec, PIN_OUTPUT, 6) /* (AG25) TIMER_IO1.USB0_DRVVBUS */
+		>;
+	};
+
+	main_mcan3_pins_default: main-mcan3-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x080, PIN_INPUT, 0) /* (U26) MCASP0_AXR4.MCAN3_RX */
+			J721S2_IOPAD(0x07c, PIN_OUTPUT, 0) /* (T27) MCASP0_AXR3.MCAN3_TX */
+		>;
+	};
+
+	main_mcan5_pins_default: main-mcan5-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x03c, PIN_INPUT, 0) /* (U27) MCASP0_AFSX.MCAN5_RX */
+			J721S2_IOPAD(0x038, PIN_OUTPUT, 0) /* (AB28) MCASP0_ACLKX.MCAN5_TX */
+		>;
+	};
+
+	main_i2c4_pins_default: main-i2c4-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x014, PIN_INPUT_PULLUP, 8) /* (AD25) I2C4_SCL */
+			J721S2_IOPAD(0x010, PIN_INPUT_PULLUP, 8) /* (AF28) I2C4_SDA */
+		>;
+	};
+
+	main_i2c5_pins_default: main-i2c5-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x01c, PIN_INPUT, 8) /* (Y24) MCAN15_TX.I2C5_SCL */
+			J721S2_IOPAD(0x018, PIN_INPUT, 8) /* (W23) MCAN14_RX.I2C5_SDA */
+		>;
+	};
+
+	dp0_pins_default: dp0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0b8, PIN_INPUT, 3) /* (AA24) MCASP1_ACLKX.DP0_HPD */
+		>;
+	};
 };
 
-&wkup_pmx0 {
+&wkup_pmx1 {
+	mcu_fss0_ospi1_pins_default: mcu-fss0-ospi1-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (A19) MCU_OSPI1_CLK */
+			J721S2_WKUP_IOPAD(0x024, PIN_OUTPUT, 0) /* (D20) MCU_OSPI1_CSn0 */
+			J721S2_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (D21) MCU_OSPI1_D0 */
+			J721S2_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (G20) MCU_OSPI1_D1 */
+			J721S2_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (C20) MCU_OSPI1_D2 */
+			J721S2_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (A20) MCU_OSPI1_D3 */
+			J721S2_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (B19) MCU_OSPI1_DQS */
+			J721S2_WKUP_IOPAD(0x00c, PIN_INPUT, 0) /* (B20) MCU_OSPI1_LBCLKO */
+		>;
+	};
+};
+
+&wkup_pmx2 {
 	mcu_cpsw_pins_default: mcu-cpsw-pins-default {
 		pinctrl-single,pins = <
-			J721S2_WKUP_IOPAD(0x094, PIN_INPUT, 0) /* (B22) MCU_RGMII1_RD0 */
-			J721S2_WKUP_IOPAD(0x090, PIN_INPUT, 0) /* (B21) MCU_RGMII1_RD1 */
-			J721S2_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (C22) MCU_RGMII1_RD2 */
-			J721S2_WKUP_IOPAD(0x088, PIN_INPUT, 0) /* (D23) MCU_RGMII1_RD3 */
-			J721S2_WKUP_IOPAD(0x084, PIN_INPUT, 0) /* (D22) MCU_RGMII1_RXC */
-			J721S2_WKUP_IOPAD(0x06c, PIN_INPUT, 0) /* (E23) MCU_RGMII1_RX_CTL */
-			J721S2_WKUP_IOPAD(0x07c, PIN_OUTPUT, 0) /* (F23) MCU_RGMII1_TD0 */
-			J721S2_WKUP_IOPAD(0x078, PIN_OUTPUT, 0) /* (G22) MCU_RGMII1_TD1 */
-			J721S2_WKUP_IOPAD(0x074, PIN_OUTPUT, 0) /* (E21) MCU_RGMII1_TD2 */
-			J721S2_WKUP_IOPAD(0x070, PIN_OUTPUT, 0) /* (E22) MCU_RGMII1_TD3 */
-			J721S2_WKUP_IOPAD(0x080, PIN_OUTPUT, 0) /* (F21) MCU_RGMII1_TXC */
-			J721S2_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /* (F22) MCU_RGMII1_TX_CTL */
+			J721S2_WKUP_IOPAD(0x02c, PIN_INPUT, 0) /* (B22) MCU_RGMII1_RD0 */
+			J721S2_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (B21) MCU_RGMII1_RD1 */
+			J721S2_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (C22) MCU_RGMII1_RD2 */
+			J721S2_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D23) MCU_RGMII1_RD3 */
+			J721S2_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (D22) MCU_RGMII1_RXC */
+			J721S2_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (E23) MCU_RGMII1_RX_CTL */
+			J721S2_WKUP_IOPAD(0x014, PIN_OUTPUT, 0) /* (F23) MCU_RGMII1_TD0 */
+			J721S2_WKUP_IOPAD(0x010, PIN_OUTPUT, 0) /* (G22) MCU_RGMII1_TD1 */
+			J721S2_WKUP_IOPAD(0x00c, PIN_OUTPUT, 0) /* (E21) MCU_RGMII1_TD2 */
+			J721S2_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E22) MCU_RGMII1_TD3 */
+			J721S2_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (F21) MCU_RGMII1_TXC */
+			J721S2_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (F22) MCU_RGMII1_TX_CTL */
 		>;
 	};
 
 	mcu_mdio_pins_default: mcu-mdio-pins-default {
 		pinctrl-single,pins = <
-			J721S2_WKUP_IOPAD(0x09c, PIN_OUTPUT, 0) /* (A21) MCU_MDIO0_MDC */
-			J721S2_WKUP_IOPAD(0x098, PIN_INPUT, 0) /* (A22) MCU_MDIO0_MDIO */
+			J721S2_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A21) MCU_MDIO0_MDC */
+			J721S2_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (A22) MCU_MDIO0_MDIO */
 		>;
 	};
 
 	mcu_mcan0_pins_default: mcu-mcan0-pins-default {
 		pinctrl-single,pins = <
-			J721S2_WKUP_IOPAD(0x0bc, PIN_INPUT, 0) /* (E28) MCU_MCAN0_RX */
-			J721S2_WKUP_IOPAD(0x0b8, PIN_OUTPUT, 0) /* (E27) MCU_MCAN0_TX */
+			J721S2_WKUP_IOPAD(0x054, PIN_INPUT, 0) /* (E28) MCU_MCAN0_RX */
+			J721S2_WKUP_IOPAD(0x050, PIN_OUTPUT, 0) /* (E27) MCU_MCAN0_TX */
 		>;
 	};
 
 	mcu_mcan1_pins_default: mcu-mcan1-pins-default {
 		pinctrl-single,pins = <
-			J721S2_WKUP_IOPAD(0x0d4, PIN_INPUT, 0) /* (F26) WKUP_GPIO0_5.MCU_MCAN1_RX */
-			J721S2_WKUP_IOPAD(0x0d0, PIN_OUTPUT, 0) /* (C23) WKUP_GPIO0_4.MCU_MCAN1_TX */
+			J721S2_WKUP_IOPAD(0x06c, PIN_INPUT, 0) /* (F26) WKUP_GPIO0_5.MCU_MCAN1_RX */
+			J721S2_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /* (C23) WKUP_GPIO0_4.MCU_MCAN1_TX */
 		>;
 	};
 
 	mcu_mcan0_gpio_pins_default: mcu-mcan0-gpio-pins-default {
 		pinctrl-single,pins = <
-			J721S2_WKUP_IOPAD(0x0c0, PIN_INPUT, 7) /* (D26) WKUP_GPIO0_0 */
-			J721S2_WKUP_IOPAD(0x0a8, PIN_INPUT, 7) /* (B25) MCU_SPI0_D1.WKUP_GPIO0_69 */
+			J721S2_WKUP_IOPAD(0x058, PIN_INPUT, 7) /* (D26) WKUP_GPIO0_0 */
+			J721S2_WKUP_IOPAD(0x040, PIN_INPUT, 7) /* (B25) MCU_SPI0_D1.WKUP_GPIO0_69 */
 		>;
 	};
 
 	mcu_mcan1_gpio_pins_default: mcu-mcan1-gpio-pins-default {
 		pinctrl-single,pins = <
-			J721S2_WKUP_IOPAD(0x0c8, PIN_INPUT, 7) /* (C28) WKUP_GPIO0_2 */
+			J721S2_WKUP_IOPAD(0x060, PIN_INPUT, 7) /* (C28) WKUP_GPIO0_2 */
+		>;
+	};
+
+	mcu_adc0_pins_default: mcu-adc0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x0cc, PIN_INPUT, 0) /* (L25) MCU_ADC0_AIN0 */
+			J721S2_WKUP_IOPAD(0x0d0, PIN_INPUT, 0) /* (K25) MCU_ADC0_AIN1 */
+			J721S2_WKUP_IOPAD(0x0d4, PIN_INPUT, 0) /* (M24) MCU_ADC0_AIN2 */
+			J721S2_WKUP_IOPAD(0x0d8, PIN_INPUT, 0) /* (L24) MCU_ADC0_AIN3 */
+			J721S2_WKUP_IOPAD(0x0dc, PIN_INPUT, 0) /* (L27) MCU_ADC0_AIN4 */
+			J721S2_WKUP_IOPAD(0x0e0, PIN_INPUT, 0) /* (K24) MCU_ADC0_AIN5 */
+			J721S2_WKUP_IOPAD(0x0e4, PIN_INPUT, 0) /* (M27) MCU_ADC0_AIN6 */
+			J721S2_WKUP_IOPAD(0x0e8, PIN_INPUT, 0) /* (M26) MCU_ADC0_AIN7 */
+		>;
+	};
+
+	mcu_adc1_pins_default: mcu-adc1-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x0ec, PIN_INPUT, 0) /* (P25) MCU_ADC1_AIN0 */
+			J721S2_WKUP_IOPAD(0x0f0, PIN_INPUT, 0) /* (R25) MCU_ADC1_AIN1 */
+			J721S2_WKUP_IOPAD(0x0f4, PIN_INPUT, 0) /* (P28) MCU_ADC1_AIN2 */
+			J721S2_WKUP_IOPAD(0x0f8, PIN_INPUT, 0) /* (P27) MCU_ADC1_AIN3 */
+			J721S2_WKUP_IOPAD(0x0fc, PIN_INPUT, 0) /* (N25) MCU_ADC1_AIN4 */
+			J721S2_WKUP_IOPAD(0x100, PIN_INPUT, 0) /* (P26) MCU_ADC1_AIN5 */
+			J721S2_WKUP_IOPAD(0x104, PIN_INPUT, 0) /* (N26) MCU_ADC1_AIN6 */
+			J721S2_WKUP_IOPAD(0x108, PIN_INPUT, 0) /* (N27) MCU_ADC1_AIN7 */
+		>;
+	};
+
+	mcu_uart0_pins_default: mcu-uart0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x090, PIN_INPUT, 0) /* (B24) WKUP_GPIO0_14.MCU_UART0_CTSn */
+			J721S2_WKUP_IOPAD(0x094, PIN_OUTPUT, 0) /* (D25) WKUP_GPIO0_15.MCU_UART0_RTSn */
+			J721S2_WKUP_IOPAD(0x08c, PIN_INPUT, 0) /* (C24) WKUP_GPIO0_13.MCU_UART0_RXD */
+			J721S2_WKUP_IOPAD(0x088, PIN_OUTPUT, 0) /* (C25) WKUP_GPIO0_12.MCU_UART0_TXD */
+		>;
+	};
+
+	wkup_uart0_pins_default: wkup-uart0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x070, PIN_INPUT, 0) /* (E25) WKUP_GPIO0_6.WKUP_UART0_CTSn */
+			J721S2_WKUP_IOPAD(0x074, PIN_OUTPUT, 0) /* (F28) WKUP_GPIO0_7.WKUP_UART0_RTSn */
+			J721S2_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (D28) WKUP_UART0_RXD */
+			J721S2_WKUP_IOPAD(0x04c, PIN_OUTPUT, 0) /* (D27) WKUP_UART0_TXD */
 		>;
 	};
 };
@@ -217,51 +398,24 @@
 
 &wkup_uart0 {
 	status = "reserved";
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_uart0_pins_default>;
 };
 
-&main_uart0 {
-	status = "disabled";
-};
-
-&main_uart1 {
-	status = "disabled";
-};
-
-&main_uart2 {
-	status = "disabled";
-};
-
-&main_uart3 {
-	status = "disabled";
-};
-
-&main_uart4 {
-	status = "disabled";
-};
-
-&main_uart5 {
-	status = "disabled";
-};
-
-&main_uart6 {
-	status = "disabled";
-};
-
-&main_uart7 {
-	status = "disabled";
+&mcu_uart0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_uart0_pins_default>;
 };
 
 &main_uart8 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_uart8_pins_default>;
 	/* Shared with TFA on this platform */
 	power-domains = <&k3_pds 357 TI_SCI_PD_SHARED>;
 };
 
-&main_uart9 {
-	status = "disabled";
-};
-
 &main_i2c0 {
 	clock-frequency = <400000>;
 
@@ -291,30 +445,6 @@
 	};
 };
 
-&main_i2c1 {
-	status = "disabled";
-};
-
-&main_i2c2 {
-	status = "disabled";
-};
-
-&main_i2c3 {
-	status = "disabled";
-};
-
-&main_i2c4 {
-	status = "disabled";
-};
-
-&main_i2c5 {
-	status = "disabled";
-};
-
-&main_i2c6 {
-	status = "disabled";
-};
-
 &main_sdhci0 {
 	/* eMMC */
 	non-removable;
@@ -334,6 +464,11 @@
 &mcu_cpsw {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
+
+	cpts@3d000 {
+		/* Map HW4_TS_PUSH to GENF1 */
+		ti,pps = <3 1>;
+	};
 };
 
 &davinci_mdio {
@@ -350,82 +485,311 @@
 	phy-handle = <&phy0>;
 };
 
+&serdes_ln_ctrl {
+	idle-states = <J721S2_SERDES0_LANE0_PCIE1_LANE0>, <J721S2_SERDES0_LANE1_USB>,
+		      <J721S2_SERDES0_LANE2_EDP_LANE2>, <J721S2_SERDES0_LANE3_EDP_LANE3>;
+};
+
+&serdes_refclk {
+	clock-frequency = <100000000>;
+};
+
+&serdes0 {
+	status = "okay";
+	serdes0_pcie_link: phy@0 {
+		reg = <0>;
+		cdns,num-lanes = <1>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_PCIE>;
+		resets = <&serdes_wiz0 1>;
+	};
+};
+
+&usb_serdes_mux {
+	idle-states = <1>; /* USB0 to SERDES lane 1 */
+};
+
+&edp_serdes_mux {
+	idle-states = <1>; /* EDP0 to SERDES lane 2/3 */
+};
+
+&usbss0 {
+	status = "okay";
+	pinctrl-0 = <&main_usbss0_pins_default>;
+	pinctrl-names = "default";
+	ti,vbus-divider;
+	ti,usb2-only;
+};
+
+&usb0 {
+	dr_mode = "otg";
+	maximum-speed = "high-speed";
+};
+
+&ospi1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_fss0_ospi1_pins_default>;
+
+	ospi1_nor: flash@0{
+		compatible = "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <40000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <2>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "qspi.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "qspi.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "qspi.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "qspi.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "qspi.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "qspi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fc0000 {
+				label = "qspi.phypattern";
+				reg = <0x3fc0000 0x40000>;
+			};
+		};
+	};
+};
+
+&pcie1_rc {
+	status = "okay";
+	reset-gpios = <&exp1 2 GPIO_ACTIVE_HIGH>;
+	phys = <&serdes0_pcie_link>;
+	phy-names = "pcie-phy";
+	num-lanes = <1>;
+};
+
 &mcu_mcan0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcu_mcan0_pins_default>;
 	phys = <&transceiver1>;
 };
 
 &mcu_mcan1 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&mcu_mcan1_pins_default>;
 	phys = <&transceiver2>;
 };
 
-&main_mcan0 {
-	status = "disabled";
+&main_mcan3 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcan3_pins_default>;
+	phys = <&transceiver3>;
 };
 
-&main_mcan1 {
-	status = "disabled";
+&main_mcan5 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcan5_pins_default>;
+	phys = <&transceiver4>;
 };
 
-&main_mcan2 {
-	status = "disabled";
+&tscadc0 {
+	pinctrl-0 = <&mcu_adc0_pins_default>;
+	pinctrl-names = "default";
+	status = "okay";
+	adc {
+		ti,adc-channels = <0 1 2 3 4 5 6 7>;
+	};
 };
 
-&main_mcan3 {
-	status = "disabled";
+&tscadc1 {
+	pinctrl-0 = <&mcu_adc1_pins_default>;
+	pinctrl-names = "default";
+	status = "okay";
+	adc {
+		ti,adc-channels = <0 1 2 3 4 5 6 7>;
+	};
 };
 
-&main_mcan4 {
-	status = "disabled";
+&dss {
+	/*
+	 * These clock assignments are chosen to enable the following outputs:
+	 *
+	 * VP0 - DisplayPort SST
+	 * VP1 - DPI0
+	 * VP2 - DSI
+	 * VP3 - DPI1
+	 */
+	status = "okay";
+	assigned-clocks = <&k3_clks 158 2>,
+			  <&k3_clks 158 5>,
+			  <&k3_clks 158 14>,
+			  <&k3_clks 158 18>;
+	assigned-clock-parents = <&k3_clks 158 3>,
+				 <&k3_clks 158 7>,
+				 <&k3_clks 158 16>,
+				 <&k3_clks 158 22>;
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@0 {
+		reg = <0>;
+		dpi0_out: endpoint {
+			remote-endpoint = <&dp0_in>;
+		};
+	};
+
+	port@2 {
+		reg = <2>;
+		dpi2_out: endpoint {
+			remote-endpoint = <&dsi0_in>;
+		};
+	};
 };
 
-&main_mcan5 {
-	status = "disabled";
+&dsi0_ports {
+	port@0 {
+		reg = <0>;
+		dsi0_out: endpoint {
+			remote-endpoint = <&dp1_in>;
+		};
+	};
+
+	port@1 {
+		reg = <1>;
+		dsi0_in: endpoint {
+			remote-endpoint = <&dpi2_out>;
+		};
+	};
 };
 
-&main_mcan6 {
-	status = "disabled";
+&dsi_edp_bridge_ports {
+	port@0 {
+		reg = <0>;
+		dp1_in: endpoint {
+			remote-endpoint = <&dsi0_out>;
+		};
+	};
+
+	port@1 {
+		reg = <1>;
+		dp1_out: endpoint {
+			remote-endpoint = <&dp1_panel_in>;
+		};
+	};
 };
 
-&main_mcan7 {
-	status = "disabled";
+&dsi_edp_bridge {
+	aux-bus {
+		panel {
+			compatible = "ti,panel-edp";
+			power-supply = <&dp1_pwr_3v3>;
+
+			port {
+				dp1_panel_in: endpoint {
+					remote-endpoint = <&dp1_out>;
+				};
+			};
+		};
+	};
 };
 
-&main_mcan8 {
-	status = "disabled";
+&mhdp {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&dp0_pins_default>;
+	cdns,no-hpd;
 };
 
-&main_mcan9 {
-	status = "disabled";
+&dp0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@0 {
+		reg = <0>;
+		dp0_in: endpoint {
+			remote-endpoint = <&dpi0_out>;
+		};
+	};
+
+	port@4 {
+		reg = <4>;
+		dp0_out: endpoint {
+			remote-endpoint = <&dp0_connector_in>;
+		};
+	};
 };
 
-&main_mcan10 {
-	status = "disabled";
+&ti_csi2rx0 {
+	status = "okay";
+	/* MIPI-CSI Connector */
 };
 
-&main_mcan11 {
-	status = "disabled";
+&ti_csi2rx1 {
+	status = "okay";
+	/* MIPI-CSI Connector */
 };
 
-&main_mcan12 {
-	status = "disabled";
+&dphy_rx0 {
+	status = "okay";
 };
 
-&main_mcan13 {
-	status = "disabled";
+&dphy_rx1 {
+	status = "okay";
 };
 
-&main_mcan14 {
-	status = "disabled";
+&dphy_tx0 {
+	status = "okay";
 };
 
-&main_mcan15 {
-	status = "disabled";
+&dsi0 {
+	status = "okay";
 };
 
-&main_mcan17 {
-	status = "disabled";
+#define K3_TS_OFFSET(pa, val)  (0x4+(pa)*4) (0x10000 | val)
+
+&timesync_router {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_cpsw_cpts>;
+
+	/* Use Time Sync Router to map GENF1 input to HW4_TS_PUSH output */
+	mcu_cpsw_cpts: mcu-cpsw-cpts {
+		pinctrl-single,pins = <
+			/* pps [mcu cpsw cpts genf1] in17 -> out25 [mcu cpsw cpts hw4_push] */
+			K3_TS_OFFSET(25, 17)
+			>;
+	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j721s2.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721s2.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -10,9 +10,10 @@
 
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/pinctrl/k3.h>
 #include <dt-bindings/soc/ti,sci_pm_domain.h>
 
+#include "k3-pinctrl.h"
+
 / {
 
 	model = "Texas Instruments K3 J721S2 SoC";
@@ -69,6 +70,7 @@
 
 	L2_0: l2-cache0 {
 		compatible = "cache";
+		cache-unified;
 		cache-level = <2>;
 		cache-size = <0x100000>;
 		cache-line-size = <64>;
@@ -114,6 +116,7 @@
 		#size-cells = <2>;
 		ranges = <0x00 0x00100000 0x00 0x00100000 0x00 0x00020000>, /* ctrl mmr */
 			 <0x00 0x00600000 0x00 0x00600000 0x00 0x00031100>, /* GPIO */
+			 <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* Time Sync Router */
 			 <0x00 0x01000000 0x00 0x01000000 0x00 0x0d000000>, /* Most peripherals */
 			 <0x00 0x0d800000 0x00 0x0d800000 0x00 0x00800000>, /* PCIe Core*/
 			 <0x00 0x18000000 0x00 0x18000000 0x00 0x08000000>, /* PCIe1 DAT0 */
@@ -161,6 +164,10 @@
 		};
 
 	};
+
+	thermal_zones: thermal-zones {
+		#include "k3-j721s2-thermal.dtsi"
+	};
 };
 
 /* Now include peripherals from each bus segment */
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-evm-csi2-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-j721s2-evm-csi2-ov5640.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721s2-evm-csi2-ov5640.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-evm-csi2-ov5640.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * LI OV5640 MIPI Camera module on MIPI CSI connector.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_ov5640_fixed: ov5640-xclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+&main_i2c5 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	ov5640: camera@3c {
+		compatible = "ovti,ov5640";
+		reg = <0x3c>;
+		clocks = <&clk_ov5640_fixed>;
+		clock-names = "xclk";
+		powerdown-gpios = <&exp5 0 GPIO_ACTIVE_LOW>;
+
+		port {
+			csi2_cam0: endpoint {
+				remote-endpoint = <&csi2rx0_in_sensor>;
+				clock-lanes = <0>;
+				data-lanes = <1 2>;
+			};
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2rx0_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-evm-fusion.dtso b/arch/arm64/boot/dts/ti/k3-j721s2-evm-fusion.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721s2-evm-fusion.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-evm-fusion.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DT Overlay for Fusion (FPD-Link III) board on J721S2 and J784S4 EVM
+ * https://svtronics.com/portfolio/evm577pfusion-v1-0-fusion/
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_fusion_25M_fixed: fixed-clock-25M {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+
+&main_i2c5 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	deser@3d {
+		compatible = "ti,ds90ub960-q1";
+		reg = <0x3d>;
+		clocks = <&clk_fusion_25M_fixed>;
+		clock-names = "refclk";
+		i2c-alias-pool = <0x4a 0x4b 0x4c 0x4d 0x4e 0x4f>;
+
+		ds90ub960_0_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* CSI-2 TX */
+			port@4 {
+				reg = <4>;
+				ds90ub960_0_csi_out: endpoint {
+					clock-lanes = <0>;
+					data-lanes = <1 2 3 4>;
+					link-frequencies = /bits/ 64 <800000000>;
+					remote-endpoint = <&csi2_phy0>;
+				};
+			};
+		};
+
+		ds90ub960_0_links: links {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	deser@36 {
+		compatible = "ti,ds90ub960-q1";
+		reg = <0x36>;
+		clocks = <&clk_fusion_25M_fixed>;
+		clock-names = "refclk";
+		i2c-alias-pool = <0x5a 0x5b 0x5c 0x5d 0x5e 0x5f>;
+
+		ds90ub960_1_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			/* CSI-2 TX */
+			port@4 {
+				reg = <4>;
+				ds90ub960_1_csi_out: endpoint {
+					clock-lanes = <0>;
+					data-lanes = <1 2 3 4>;
+					link-frequencies = /bits/ 64 <800000000>;
+					remote-endpoint = <&csi2_phy1>;
+				};
+			};
+		};
+
+		ds90ub960_1_links: links {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+};
+
+&csi0_port0 {
+	status = "okay";
+
+	csi2_phy0: endpoint {
+		remote-endpoint = <&ds90ub960_0_csi_out>;
+		clock-lanes = <0>;
+		data-lanes = <1 2 3 4>;
+		link-frequencies = /bits/ 64 <800000000>;
+	};
+};
+
+&csi1_port0 {
+	status = "okay";
+
+	csi2_phy1: endpoint {
+		remote-endpoint = <&ds90ub960_1_csi_out>;
+		clock-lanes = <0>;
+		data-lanes = <1 2 3 4>;
+		link-frequencies = /bits/ 64 <800000000>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-evm-gesi-exp-board.dtso b/arch/arm64/boot/dts/ti/k3-j721s2-evm-gesi-exp-board.dtso
--- a/arch/arm64/boot/dts/ti/k3-j721s2-evm-gesi-exp-board.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-evm-gesi-exp-board.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for MAIN CPSW2G using GESI Expansion Board with J7 common processor board.
+ *
+ * GESI Board Product Link: https://www.ti.com/tool/J7EXPCXEVM
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	aliases {
+		ethernet1 = "/bus@100000/ethernet@c200000/ethernet-ports/port@1";
+	};
+};
+
+&main_pmx0 {
+	main_cpsw_mdio_pins_default: main-cpsw-mdio-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0c0, PIN_OUTPUT, 6) /* (T28) MCASP1_AXR0.MDIO0_MDC */
+			J721S2_IOPAD(0x0bc, PIN_INPUT, 6) /* (V28) MCASP1_AFSX.MDIO0_MDIO */
+		>;
+	};
+
+	rgmii1_pins_default: rgmii1-pins-default {
+		pinctrl-single,pins = <
+			J721S2_IOPAD(0x0b8, PIN_INPUT, 6) /* (AA24) MCASP1_ACLKX.RGMII1_RD0 */
+			J721S2_IOPAD(0x0a0, PIN_INPUT, 6) /* (AB25) MCASP0_AXR12.RGMII1_RD1 */
+			J721S2_IOPAD(0x0a4, PIN_INPUT, 6) /* (T23) MCASP0_AXR13.RGMII1_RD2 */
+			J721S2_IOPAD(0x0a8, PIN_INPUT, 6) /* (U24) MCASP0_AXR14.RGMII1_RD3 */
+			J721S2_IOPAD(0x0b0, PIN_INPUT, 6) /* (AD26) MCASP1_AXR3.RGMII1_RXC */
+			J721S2_IOPAD(0x0ac, PIN_INPUT, 6) /* (AC25) MCASP0_AXR15.RGMII1_RX_CTL */
+			J721S2_IOPAD(0x08c, PIN_OUTPUT, 6) /* (T25) MCASP0_AXR7.RGMII1_TD0 */
+			J721S2_IOPAD(0x090, PIN_OUTPUT, 6) /* (W24) MCASP0_AXR8.RGMII1_TD1 */
+			J721S2_IOPAD(0x094, PIN_OUTPUT, 6) /* (AA25) MCASP0_AXR9.RGMII1_TD2 */
+			J721S2_IOPAD(0x098, PIN_OUTPUT, 6) /* (V25) MCASP0_AXR10.RGMII1_TD3 */
+			J721S2_IOPAD(0x0b4, PIN_OUTPUT, 6) /* (U25) MCASP1_AXR4.RGMII1_TXC */
+			J721S2_IOPAD(0x09c, PIN_OUTPUT, 6) /* (T24) MCASP0_AXR11.RGMII1_TX_CTL */
+		>;
+	};
+};
+
+&exp1 {
+	p15 {
+		/* P15 - EXP_MUX2 */
+		gpio-hog;
+		gpios = <13 GPIO_ACTIVE_HIGH>;
+		output-high;
+		line-name = "EXP_MUX2";
+	};
+};
+
+&main_cpsw {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii1_pins_default>;
+};
+
+&main_cpsw_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_cpsw_mdio_pins_default>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	main_cpsw_phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+};
+
+&main_cpsw_port1 {
+	status = "okay";
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&main_cpsw_phy0>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -4,6 +4,18 @@
  *
  * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
  */
+#include <dt-bindings/phy/phy.h>
+
+#include <dt-bindings/phy/phy-cadence.h>
+#include <dt-bindings/phy/phy-ti.h>
+
+/ {
+	serdes_refclk: clock-cmnrefclk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <0>;
+	};
+};
 
 &cbass_main {
 	msmc_ram: sram@70000000 {
@@ -26,6 +38,103 @@
 		};
 	};
 
+	scm_conf: syscon@104000 {
+		compatible = "ti,j721e-system-controller", "syscon", "simple-mfd";
+		reg = <0x00 0x00104000 0x00 0x18000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x00 0x00 0x00104000 0x18000>;
+
+		usb_serdes_mux: mux-controller@0 {
+			compatible = "mmio-mux";
+			reg = <0x0 0x4>;
+			#mux-control-cells = <1>;
+			mux-reg-masks = <0x0 0x8000000>; /* USB0 to SERDES0 lane 1/3 mux */
+		};
+
+		phy_gmii_sel_cpsw: phy@34 {
+			compatible = "ti,am654-phy-gmii-sel";
+			reg = <0x34 0x4>;
+			#phy-cells = <1>;
+		};
+
+		serdes_ln_ctrl: mux-controller@80 {
+			compatible = "mmio-mux";
+			reg = <0x80 0x10>;
+			#mux-control-cells = <1>;
+			mux-reg-masks = <0x80 0x3>, <0x84 0x3>, /* SERDES0 lane0/1 select */
+					<0x88 0x3>, <0x8c 0x3>; /* SERDES0 lane2/3 select */
+		};
+
+		edp_serdes_mux: mux-controller@310 {
+			compatible = "mmio-mux";
+			reg = <0x310 0x4>;
+			#mux-control-cells = <1>;
+			/* EDP0 to SERDES0 lane 0/1 or 2/3 mux */
+			mux-reg-masks = <0x310 0x10000000>;
+		};
+
+		ehrpwm_tbclk: clock-controller@140 {
+			compatible = "ti,am654-ehrpwm-tbclk", "syscon";
+			reg = <0x140 0x18>;
+			#clock-cells = <1>;
+		};
+	};
+
+	main_ehrpwm0: pwm@3000000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3000000 0x00 0x100>;
+		power-domains = <&k3_pds 160 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 0>, <&k3_clks 160 0>;
+		clock-names = "tbclk", "fck";
+	};
+
+	main_ehrpwm1: pwm@3010000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3010000 0x00 0x100>;
+		power-domains = <&k3_pds 161 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 1>, <&k3_clks 161 0>;
+		clock-names = "tbclk", "fck";
+	};
+
+	main_ehrpwm2: pwm@3020000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3020000 0x00 0x100>;
+		power-domains = <&k3_pds 162 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 2>, <&k3_clks 162 0>;
+		clock-names = "tbclk", "fck";
+	};
+
+	main_ehrpwm3: pwm@3030000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3030000 0x00 0x100>;
+		power-domains = <&k3_pds 163 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 3>, <&k3_clks 163 0>;
+		clock-names = "tbclk", "fck";
+	};
+
+	main_ehrpwm4: pwm@3040000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3040000 0x00 0x100>;
+		power-domains = <&k3_pds 164 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 4>, <&k3_clks 164 0>;
+		clock-names = "tbclk", "fck";
+	};
+
+	main_ehrpwm5: pwm@3050000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3050000 0x00 0x100>;
+		power-domains = <&k3_pds 165 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 5>, <&k3_clks 165 0>;
+		clock-names = "tbclk", "fck";
+	};
+
 	gic500: interrupt-controller@1800000 {
 		compatible = "arm,gic-v3";
 		#address-cells = <2>;
@@ -72,6 +181,25 @@
 		pinctrl-single,function-mask = <0xffffffff>;
 	};
 
+	main_crypto: crypto@4e00000 {
+		compatible = "ti,j721e-sa2ul";
+		reg = <0x00 0x04e00000 0x00 0x1200>;
+		power-domains = <&k3_pds 297 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x00 0x04e00000 0x00 0x04e00000 0x00 0x30000>;
+
+		dmas = <&main_udmap 0xca40>, <&main_udmap 0x4a40>,
+		       <&main_udmap 0x4a41>;
+		dma-names = "tx", "rx1", "rx2";
+
+		rng: rng@4e10000 {
+			compatible = "inside-secure,safexcel-eip76";
+			reg = <0x00 0x04e10000 0x00 0x7d>;
+			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+		};
+	};
+
 	main_uart0: serial@2800000 {
 		compatible = "ti,j721e-uart", "ti,am654-uart";
 		reg = <0x00 0x02800000 0x00 0x200>;
@@ -80,6 +208,7 @@
 		clocks = <&k3_clks 146 3>;
 		clock-names = "fclk";
 		power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_uart1: serial@2810000 {
@@ -90,6 +219,7 @@
 		clocks = <&k3_clks 350 3>;
 		clock-names = "fclk";
 		power-domains = <&k3_pds 350 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_uart2: serial@2820000 {
@@ -100,6 +230,7 @@
 		clocks = <&k3_clks 351 3>;
 		clock-names = "fclk";
 		power-domains = <&k3_pds 351 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_uart3: serial@2830000 {
@@ -110,6 +241,7 @@
 		clocks = <&k3_clks 352 3>;
 		clock-names = "fclk";
 		power-domains = <&k3_pds 352 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_uart4: serial@2840000 {
@@ -120,6 +252,7 @@
 		clocks = <&k3_clks 353 3>;
 		clock-names = "fclk";
 		power-domains = <&k3_pds 353 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_uart5: serial@2850000 {
@@ -130,6 +263,7 @@
 		clocks = <&k3_clks 354 3>;
 		clock-names = "fclk";
 		power-domains = <&k3_pds 354 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_uart6: serial@2860000 {
@@ -140,6 +274,7 @@
 		clocks = <&k3_clks 355 3>;
 		clock-names = "fclk";
 		power-domains = <&k3_pds 355 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_uart7: serial@2870000 {
@@ -150,6 +285,7 @@
 		clocks = <&k3_clks 356 3>;
 		clock-names = "fclk";
 		power-domains = <&k3_pds 356 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_uart8: serial@2880000 {
@@ -160,6 +296,7 @@
 		clocks = <&k3_clks 357 3>;
 		clock-names = "fclk";
 		power-domains = <&k3_pds 357 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_uart9: serial@2890000 {
@@ -170,6 +307,15 @@
 		clocks = <&k3_clks 358 3>;
 		clock-names = "fclk";
 		power-domains = <&k3_pds 358 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	gpu: gpu@4e20000000 {
+		compatible = "ti,j721s2-pvr", "img,pvr-bxs64";
+		reg = <0x4e 0x20000000 0x00 0x80000>;
+		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 373 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 130 1>;
 	};
 
 	main_gpio0: gpio@600000 {
@@ -256,6 +402,7 @@
 		clocks = <&k3_clks 215 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 215 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c2: i2c@2020000 {
@@ -267,6 +414,7 @@
 		clocks = <&k3_clks 216 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 216 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c3: i2c@2030000 {
@@ -278,6 +426,7 @@
 		clocks = <&k3_clks 217 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 217 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c4: i2c@2040000 {
@@ -289,6 +438,7 @@
 		clocks = <&k3_clks 218 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 218 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c5: i2c@2050000 {
@@ -300,6 +450,7 @@
 		clocks = <&k3_clks 219 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 219 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	main_i2c6: i2c@2060000 {
@@ -311,6 +462,41 @@
 		clocks = <&k3_clks 220 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 220 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+    vpu: video-codec@4210000 {
+		compatible = "cnm,cm521c-vpu";
+		reg = <0x00 0x4210000 0x00 0x10000>;
+		interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 179 2>;
+		clock-names = "vcodec";
+		power-domains = <&k3_pds 179 TI_SCI_PD_EXCLUSIVE>;
+		sram = <&main_navss_sram>;
+		sram-size = <0x10000>;
+		operating-points-v2 = <&vpu_opp_table>;
+		vpu_opp_table: opp-table {
+			compatible = "operating-points-v2";
+			opp-20000000 {
+				opp-hz = /bits/ 64 <20000000>;
+			};
+
+			opp-100000000 {
+				opp-hz = /bits/ 64 <100000000>;
+			};
+
+			opp-200000000 {
+				opp-hz = /bits/ 64 <200000000>;
+			};
+
+			opp-400000000 {
+				opp-hz = /bits/ 64 <400000000>;
+			};
+
+			opp-600000000 {
+				opp-hz = /bits/ 64 <600000000>;
+			};
+		};
 	};
 
 	main_sdhci0: mmc@4f80000 {
@@ -365,8 +551,6 @@
 		ti,clkbuf-sel = <0x7>;
 		ti,trm-icp = <0x8>;
 		dma-coherent;
-		/* Masking support for SDR104 capability */
-		sdhci-caps-mask = <0x00000003 0x00000000>;
 	};
 
 	main_navss: bus@30000000 {
@@ -378,6 +562,14 @@
 		dma-coherent;
 		dma-ranges;
 
+		main_navss_sram: navss-sram@30000000{
+			compatible = "mmio-sram";
+			reg = <0x00 0x30000000 0x00 0x10000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0x00 0x30000000 0x10000>;
+		};
+
 		main_navss_intr: interrupt-controller@310e0000 {
 			compatible = "ti,sci-intr";
 			reg = <0x00 0x310e0000 0x00 0x4000>;
@@ -402,6 +594,7 @@
 			ti,sci = <&sms>;
 			ti,sci-dev-id = <265>;
 			ti,interrupt-ranges = <0 0 256>;
+			ti,unmapped-event-sources = <&main_bcdma_csi>;
 		};
 
 		secure_proxy_main: mailbox@32c00000 {
@@ -673,6 +866,21 @@
 			ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */
 		};
 
+		main_bcdma_csi: dma-controller@311a0000 {
+			compatible = "ti,j721s2-dmss-bcdma-csi";
+			reg = <0x00 0x311a0000 0x00 0x100>,
+				<0x00 0x35d00000 0x00 0x20000>,
+				<0x00 0x35c00000 0x00 0x10000>,
+				<0x00 0x35e00000 0x00 0x80000>;
+			reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt";
+			msi-parent = <&main_udmass_inta>;
+			#dma-cells = <3>;
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <225>;
+			ti,sci-rm-range-rchan = <0x21>;
+			ti,sci-rm-range-tchan = <0x22>;
+		};
+
 		cpts@310d0000 {
 			compatible = "ti,j721e-cpts";
 			reg = <0x0 0x310d0000 0x0 0x400>;
@@ -686,6 +894,195 @@
 		};
 	};
 
+	main_cpsw: ethernet@c200000 {
+		compatible = "ti,j721e-cpsw-nuss";
+		reg = <0x00 0xc200000 0x00 0x200000>;
+		reg-names = "cpsw_nuss";
+		ranges = <0x0 0x0 0x0 0xc200000 0x0 0x200000>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		dma-coherent;
+		clocks = <&k3_clks 28 28>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 28 TI_SCI_PD_EXCLUSIVE>;
+
+		dmas = <&main_udmap 0xc640>,
+		       <&main_udmap 0xc641>,
+		       <&main_udmap 0xc642>,
+		       <&main_udmap 0xc643>,
+		       <&main_udmap 0xc644>,
+		       <&main_udmap 0xc645>,
+		       <&main_udmap 0xc646>,
+		       <&main_udmap 0xc647>,
+		       <&main_udmap 0x4640>;
+		dma-names = "tx0", "tx1", "tx2", "tx3",
+			    "tx4", "tx5", "tx6", "tx7",
+			    "rx";
+
+		status = "disabled";
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			main_cpsw_port1: port@1 {
+				reg = <1>;
+				ti,mac-only;
+				label = "port1";
+				phys = <&phy_gmii_sel_cpsw 1>;
+				status = "disabled";
+			};
+		};
+
+		main_cpsw_mdio: mdio@f00 {
+			compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+			reg = <0x00 0xf00 0x00 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&k3_clks 28 28>;
+			clock-names = "fck";
+			bus_freq = <1000000>;
+			status = "disabled";
+		};
+
+		cpts@3d000 {
+			compatible = "ti,am65-cpts";
+			reg = <0x00 0x3d000 0x00 0x400>;
+			clocks = <&k3_clks 28 3>;
+			clock-names = "cpts";
+			interrupts-extended = <&gic500 GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "cpts";
+			ti,cpts-ext-ts-inputs = <4>;
+			ti,cpts-periodic-outputs = <2>;
+		};
+	};
+
+	usbss0: cdns-usb@4104000 {
+		compatible = "ti,j721e-usb";
+		reg = <0x00 0x04104000 0x00 0x100>;
+		clocks = <&k3_clks 360 16>, <&k3_clks 360 15>;
+		clock-names = "ref", "lpm";
+		assigned-clocks = <&k3_clks 360 16>; /* USB2_REFCLK */
+		assigned-clock-parents = <&k3_clks 360 17>;
+		power-domains = <&k3_pds 360 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		dma-coherent;
+
+		status = "disabled"; /* Needs pinmux */
+
+		usb0: usb@6000000 {
+			compatible = "cdns,usb3";
+			reg = <0x00 0x06000000 0x00 0x10000>,
+			      <0x00 0x06010000 0x00 0x10000>,
+			      <0x00 0x06020000 0x00 0x10000>;
+			reg-names = "otg", "xhci", "dev";
+			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "host", "peripheral", "otg";
+			maximum-speed = "super-speed";
+			dr_mode = "otg";
+		};
+	};
+
+	serdes_wiz0: wiz@5060000 {
+		compatible = "ti,j721s2-wiz-10g";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		power-domains = <&k3_pds 365 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 365 0>, <&k3_clks 365 3>, <&serdes_refclk>;
+		clock-names = "fck", "core_ref_clk", "ext_ref_clk";
+		num-lanes = <4>;
+		#reset-cells = <1>;
+		#clock-cells = <1>;
+		ranges = <0x5060000 0x0 0x5060000 0x10000>,
+			 <0xa030a00 0x0 0xa030a00 0x40>; /* DPTX PHY */
+
+		assigned-clocks = <&k3_clks 365 3>;
+		assigned-clock-parents = <&k3_clks 365 7>;
+
+		serdes0: serdes@5060000 {
+			/*
+			 * Note: we also map DPTX PHY registers as the Torrent
+			 * needs to manage those.
+			 */
+			compatible = "ti,j721e-serdes-10g";
+			reg = <0x05060000 0x00010000>,
+			      <0xa030a00 0x40>; /* DPTX PHY */
+			reg-names = "torrent_phy", "dptx_phy";
+			resets = <&serdes_wiz0 0>;
+			reset-names = "torrent_reset";
+			clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>,
+				 <&serdes_wiz0 TI_WIZ_PHY_EN_REFCLK>;
+			clock-names = "refclk", "phy_en_refclk";
+			assigned-clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>,
+					  <&serdes_wiz0 TI_WIZ_PLL1_REFCLK>,
+					  <&serdes_wiz0 TI_WIZ_REFCLK_DIG>;
+			assigned-clock-parents = <&k3_clks 365 3>,
+						 <&k3_clks 365 3>,
+						 <&k3_clks 365 3>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			#clock-cells = <1>;
+
+			status = "disabled"; /* Needs lane config */
+
+			torrent_phy_dp: phy@2 {
+				reg = <2>;
+				resets = <&serdes_wiz0 3>;
+				cdns,phy-type = <PHY_TYPE_DP>;
+				cdns,num-lanes = <2>;
+				cdns,max-bit-rate = <5400>;
+				#phy-cells = <0>;
+			};
+		};
+	};
+
+	pcie1_rc: pcie@2910000 {
+		compatible = "ti,j7200-pcie-host", "ti,j721e-pcie-host";
+		reg = <0x00 0x02910000 0x00 0x1000>,
+		      <0x00 0x02917000 0x00 0x400>,
+		      <0x00 0x0d800000 0x00 0x800000>,
+		      <0x00 0x18000000 0x00 0x1000>;
+		reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
+		interrupt-names = "link_state";
+		interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
+		device_type = "pci";
+		ti,syscon-pcie-ctrl = <&scm_conf 0x074>;
+		max-link-speed = <3>;
+		num-lanes = <4>;
+		power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 276 41>;
+		clock-names = "fck";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		bus-range = <0x0 0xff>;
+		vendor-id = <0x104c>;
+		device-id = <0xb013>;
+		msi-map = <0x0 &gic_its 0x0 0x10000>;
+		dma-coherent;
+		ranges = <0x01000000 0x0 0x18001000  0x00 0x18001000  0x0 0x0010000>,
+			 <0x02000000 0x0 0x18011000  0x00 0x18011000  0x0 0x7fef000>;
+		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie1_intc 0>, /* INT A */
+				<0 0 0 2 &pcie1_intc 0>, /* INT B */
+				<0 0 0 3 &pcie1_intc 0>, /* INT C */
+				<0 0 0 4 &pcie1_intc 0>; /* INT D */
+
+		status = "disabled"; /* Needs gpio and serdes info */
+
+		pcie1_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 324 IRQ_TYPE_EDGE_RISING>;
+		};
+	};
+
 	main_mcan0: can@2701000 {
 		compatible = "bosch,m_can";
 		reg = <0x00 0x02701000 0x00 0x200>,
@@ -698,6 +1095,7 @@
 			     <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan1: can@2711000 {
@@ -712,6 +1110,7 @@
 			     <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan2: can@2721000 {
@@ -726,6 +1125,7 @@
 			     <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan3: can@2731000 {
@@ -740,6 +1140,7 @@
 			     <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan4: can@2741000 {
@@ -754,6 +1155,7 @@
 			     <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan5: can@2751000 {
@@ -768,6 +1170,7 @@
 			     <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan6: can@2761000 {
@@ -782,6 +1185,7 @@
 			     <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan7: can@2771000 {
@@ -796,6 +1200,7 @@
 			     <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan8: can@2781000 {
@@ -810,6 +1215,7 @@
 			     <GIC_SPI 577 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan9: can@2791000 {
@@ -824,6 +1230,7 @@
 			     <GIC_SPI 580 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan10: can@27a1000 {
@@ -838,6 +1245,7 @@
 			     <GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan11: can@27b1000 {
@@ -852,6 +1260,7 @@
 			     <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan12: can@27c1000 {
@@ -866,6 +1275,7 @@
 			     <GIC_SPI 589 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan13: can@27d1000 {
@@ -880,6 +1290,7 @@
 			     <GIC_SPI 592 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan14: can@2681000 {
@@ -894,6 +1305,7 @@
 			     <GIC_SPI 595 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan15: can@2691000 {
@@ -908,6 +1320,7 @@
 			     <GIC_SPI 598 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan16: can@26a1000 {
@@ -922,6 +1335,7 @@
 			     <GIC_SPI 785 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	main_mcan17: can@26b1000 {
@@ -936,5 +1350,562 @@
 			     <GIC_SPI 788 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_spi0: spi@2100000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02100000 0x00 0x400>;
+		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 339 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 339 1>;
+		status = "disabled";
+	};
+
+	main_spi1: spi@2110000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02110000 0x00 0x400>;
+		interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 340 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 340 1>;
+		status = "disabled";
+	};
+
+	main_spi2: spi@2120000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02120000 0x00 0x400>;
+		interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 341 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 341 1>;
+		status = "disabled";
+	};
+
+	main_spi3: spi@2130000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02130000 0x00 0x400>;
+		interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 342 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 342 1>;
+		status = "disabled";
+	};
+
+	main_spi4: spi@2140000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02140000 0x00 0x400>;
+		interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 343 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 343 1>;
+		status = "disabled";
+	};
+
+	main_spi5: spi@2150000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02150000 0x00 0x400>;
+		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 344 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 344 1>;
+		status = "disabled";
+	};
+
+	main_spi6: spi@2160000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02160000 0x00 0x400>;
+		interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 345 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 345 1>;
+		status = "disabled";
+	};
+
+	main_spi7: spi@2170000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02170000 0x00 0x400>;
+		interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 346 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 346 1>;
+		status = "disabled";
+	};
+
+	timesync_router: pinctrl@a40000 {
+		compatible = "pinctrl-single";
+		reg = <0x0 0xa40000 0x0 0x800>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0x000107ff>;
+		status = "disabled";
+	};
+
+	mhdp: dp-bridge@a000000 {
+		compatible = "ti,j721e-mhdp8546";
+		/*
+		 * Note: we do not map DPTX PHY area, as that is handled by
+		 * the PHY driver.
+		 */
+		reg = <0x0 0xa000000 0x0 0x30a00>, /* DSS_EDP0_V2A_CORE_VP_REGS_APB */
+		      <0x0 0x4f40000 0x0 0x20>;    /* DSS_EDP0_INTG_CFG_VP */
+		reg-names = "mhdptx", "j721e-intg";
+
+		clocks = <&k3_clks 156 19>;
+
+		phys = <&torrent_phy_dp>;
+		phy-names = "dpphy";
+
+		interrupt-parent = <&gic500>;
+		interrupts = <GIC_SPI 614 IRQ_TYPE_LEVEL_HIGH>;
+
+		power-domains = <&k3_pds 156 TI_SCI_PD_EXCLUSIVE>;
+
+		status = "disabled";
+
+		dp0_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	dphy_tx0: phy@4480000 {
+		compatible = "ti,j721e-dphy";
+		reg = <0x0 0x04480000 0x0 0x1000>;
+		clocks = <&k3_clks 363 8>, <&k3_clks 363 14>;
+		clock-names = "psm", "pll_ref";
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 363 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 363 14>;
+		assigned-clock-parents = <&k3_clks 363 15>;
+		assigned-clock-rates = <19200000>;
+		status = "disabled";
+	};
+
+	dsi0: dsi@4800000 {
+		compatible = "ti,j721e-dsi";
+		reg = <0x0 0x04800000 0x0 0x100000>, <0x0 0x04710000 0x0 0x100>;
+		clocks = <&k3_clks 154 4>, <&k3_clks 154 1>;
+		clock-names = "dsi_p_clk", "dsi_sys_clk";
+		power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
+		interrupt-parent = <&gic500>;
+		interrupts = <GIC_SPI 600 IRQ_TYPE_LEVEL_HIGH>;
+		phys = <&dphy_tx0>;
+		phy-names = "dphy";
+		status = "disabled";
+
+		dsi0_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+			};
+			port@1 {
+				reg = <1>;
+			};
+		};
+	};
+
+	dss: dss@4a00000 {
+		compatible = "ti,j721e-dss";
+		reg = <0x00 0x04a00000 0x00 0x10000>, /* common_m */
+		      <0x00 0x04a10000 0x00 0x10000>, /* common_s0*/
+		      <0x00 0x04b00000 0x00 0x10000>, /* common_s1*/
+		      <0x00 0x04b10000 0x00 0x10000>, /* common_s2*/
+		      <0x00 0x04a20000 0x00 0x10000>, /* vidl1 */
+		      <0x00 0x04a30000 0x00 0x10000>, /* vidl2 */
+		      <0x00 0x04a50000 0x00 0x10000>, /* vid1 */
+		      <0x00 0x04a60000 0x00 0x10000>, /* vid2 */
+		      <0x00 0x04a70000 0x00 0x10000>, /* ovr1 */
+		      <0x00 0x04a90000 0x00 0x10000>, /* ovr2 */
+		      <0x00 0x04ab0000 0x00 0x10000>, /* ovr3 */
+		      <0x00 0x04ad0000 0x00 0x10000>, /* ovr4 */
+		      <0x00 0x04a80000 0x00 0x10000>, /* vp1 */
+		      <0x00 0x04aa0000 0x00 0x10000>, /* vp2 */
+		      <0x00 0x04ac0000 0x00 0x10000>, /* vp3 */
+		      <0x00 0x04ae0000 0x00 0x10000>, /* vp4 */
+		      <0x00 0x04af0000 0x00 0x10000>; /* wb */
+
+		reg-names = "common_m", "common_s0",
+			    "common_s1", "common_s2",
+			    "vidl1", "vidl2","vid1","vid2",
+			    "ovr1", "ovr2", "ovr3", "ovr4",
+			    "vp1", "vp2", "vp3", "vp4",
+			    "wb";
+
+		clocks = <&k3_clks 158 0>,
+			 <&k3_clks 158 2>,
+			 <&k3_clks 158 5>,
+			 <&k3_clks 158 14>,
+			 <&k3_clks 158 18>;
+		clock-names = "fck", "vp1", "vp2", "vp3", "vp4";
+
+		power-domains = <&k3_pds 158 TI_SCI_PD_EXCLUSIVE>;
+
+		interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "common_m",
+				  "common_s0",
+				  "common_s1",
+				  "common_s2";
+
+		status = "disabled";
+
+		dss_ports: ports {
+		};
+	};
+
+	ti_csi2rx0: ticsi2rx@4500000 {
+		status = "disabled";
+		compatible = "ti,j721e-csi2rx";
+		dmas = <&main_bcdma_csi 0 0x4940 0>, <&main_bcdma_csi 0 0x4941 0>,
+		<&main_bcdma_csi 0 0x4942 0>, <&main_bcdma_csi 0 0x4943 0>,
+		<&main_bcdma_csi 0 0x4944 0>, <&main_bcdma_csi 0 0x4945 0>,
+		<&main_bcdma_csi 0 0x4946 0>, <&main_bcdma_csi 0 0x4947 0>;
+		dma-names = "rx0", "rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7";
+		reg = <0x00 0x04500000 0x00 0x1000>;
+		power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cdns_csi2rx0: csi-bridge@4504000 {
+			compatible = "cdns,csi2rx";
+			reg = <0x00 0x04504000 0x00 0x1000>;
+			clocks = <&k3_clks 38 3>, <&k3_clks 38 1>, <&k3_clks 38 3>,
+				<&k3_clks 38 3>, <&k3_clks 38 4>, <&k3_clks 38 4>;
+			clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+				"pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+			phys = <&dphy_rx0>;
+			phy-names = "dphy";
+			power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				csi0_port0: port@0 {
+					reg = <0>;
+					status = "disabled";
+				};
+
+				csi0_port1: port@1 {
+					reg = <1>;
+					status = "disabled";
+				};
+
+				csi0_port2: port@2 {
+					reg = <2>;
+					status = "disabled";
+				};
+
+				csi0_port3: port@3 {
+					reg = <3>;
+					status = "disabled";
+				};
+
+				csi0_port4: port@4 {
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
+	ti_csi2rx1: ticsi2rx@4510000 {
+		status = "disabled";
+		compatible = "ti,j721e-csi2rx";
+		dmas = <&main_bcdma_csi 0 0x4960 0>, <&main_bcdma_csi 0 0x4961 0>,
+		<&main_bcdma_csi 0 0x4962 0>, <&main_bcdma_csi 0 0x4963 0>,
+		<&main_bcdma_csi 0 0x4964 0>, <&main_bcdma_csi 0 0x4965 0>,
+		<&main_bcdma_csi 0 0x4966 0>, <&main_bcdma_csi 0 0x4967 0>;
+		dma-names = "rx0", "rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7";
+		reg = <0x00 0x04510000 0x00 0x1000>;
+		power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cdns_csi2rx1: csi-bridge@4514000 {
+			compatible = "cdns,csi2rx";
+			reg = <0x00 0x04514000 0x00 0x1000>;
+			clocks = <&k3_clks 39 3>, <&k3_clks 39 1>, <&k3_clks 39 3>,
+				<&k3_clks 39 3>, <&k3_clks 39 4>, <&k3_clks 39 4>;
+			clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+				"pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+			phys = <&dphy_rx1>;
+			phy-names = "dphy";
+			power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				csi1_port0: port@0 {
+					reg = <0>;
+					status = "disabled";
+				};
+
+				csi1_port1: port@1 {
+					reg = <1>;
+					status = "disabled";
+				};
+
+				csi1_port2: port@2 {
+					reg = <2>;
+					status = "disabled";
+				};
+
+				csi1_port3: port@3 {
+					reg = <3>;
+					status = "disabled";
+				};
+
+				csi1_port4: port@4 {
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
+	dphy_rx0: phy@4580000 {
+		status = "disabled";
+		compatible = "cdns,dphy-rx";
+		reg = <0x00 0x04580000 0x00 0x1100>;
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>;
+	};
+
+	dphy_rx1: phy@4590000 {
+		status = "disabled";
+		compatible = "cdns,dphy-rx";
+		reg = <0x00 0x04590000 0x00 0x1100>;
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>;
+	};
+
+	main_r5fss0: r5fss@5c00000 {
+		compatible = "ti,j721s2-r5fss";
+		ti,cluster-mode = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x5c00000 0x00 0x5c00000 0x20000>,
+			 <0x5d00000 0x00 0x5d00000 0x20000>;
+		power-domains = <&k3_pds 277 TI_SCI_PD_EXCLUSIVE>;
+
+		main_r5fss0_core0: r5f@5c00000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x5c00000 0x00010000>,
+			      <0x5c10000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <279>;
+			ti,sci-proc-ids = <0x06 0xff>;
+			resets = <&k3_reset 279 1>;
+			firmware-name = "j721s2-main-r5f0_0-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+
+		main_r5fss0_core1: r5f@5d00000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x5d00000 0x00010000>,
+			      <0x5d10000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <280>;
+			ti,sci-proc-ids = <0x07 0xff>;
+			resets = <&k3_reset 280 1>;
+			firmware-name = "j721s2-main-r5f0_1-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+	};
+
+	main_r5fss1: r5fss@5e00000 {
+		compatible = "ti,j721s2-r5fss";
+		ti,cluster-mode = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x5e00000 0x00 0x5e00000 0x20000>,
+			 <0x5f00000 0x00 0x5f00000 0x20000>;
+		power-domains = <&k3_pds 278 TI_SCI_PD_EXCLUSIVE>;
+
+		main_r5fss1_core0: r5f@5e00000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x5e00000 0x00010000>,
+			      <0x5e10000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <281>;
+			ti,sci-proc-ids = <0x08 0xff>;
+			resets = <&k3_reset 281 1>;
+			firmware-name = "j721s2-main-r5f1_0-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+
+		main_r5fss1_core1: r5f@5f00000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x5f00000 0x00010000>,
+			      <0x5f10000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <282>;
+			ti,sci-proc-ids = <0x09 0xff>;
+			resets = <&k3_reset 282 1>;
+			firmware-name = "j721s2-main-r5f1_1-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+	};
+
+	c71_0: dsp@64800000 {
+		compatible = "ti,j721s2-c71-dsp";
+		reg = <0x00 0x64800000 0x00 0x00080000>,
+		      <0x00 0x64e00000 0x00 0x0000c000>;
+		reg-names = "l2sram", "l1dram";
+		ti,sci = <&sms>;
+		ti,sci-dev-id = <8>;
+		ti,sci-proc-ids = <0x30 0xff>;
+		resets = <&k3_reset 8 1>;
+		firmware-name = "j721s2-c71_0-fw";
+	};
+
+	c71_1: dsp@65800000 {
+		compatible = "ti,j721s2-c71-dsp";
+		reg = <0x00 0x65800000 0x00 0x00080000>,
+		      <0x00 0x65e00000 0x00 0x0000c000>;
+		reg-names = "l2sram", "l1dram";
+		ti,sci = <&sms>;
+		ti,sci-dev-id = <11>;
+		ti,sci-proc-ids = <0x31 0xff>;
+		resets = <&k3_reset 11 1>;
+		firmware-name = "j721s2-c71_1-fw";
+	};
+
+	main_esm: esm@700000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x00 0x700000 0x00 0x1000>;
+		ti,esm-pins = <688>, <689>;
+		bootph-pre-ram;
+	};
+
+	watchdog0: watchdog@2200000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2200000 0x00 0x100>;
+		clocks = <&k3_clks 286 1>;
+		power-domains = <&k3_pds 286 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 286 1>;
+		assigned-clock-parents = <&k3_clks 286 5>;
+	};
+
+	watchdog1: watchdog@2210000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2210000 0x00 0x100>;
+		clocks = <&k3_clks 287 1>;
+		power-domains = <&k3_pds 287 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 287 1>;
+		assigned-clock-parents = <&k3_clks 287 5>;
+	};
+
+	/*
+	 * The following RTI instances are coupled with MCU R5Fs, c7x and
+	 * GPU so keeping them reserved as these will be used by their
+	 * respective firmware
+	 */
+	watchdog2: watchdog@22f0000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x22f0000 0x00 0x100>;
+		clocks = <&k3_clks 290 1>;
+		power-domains = <&k3_pds 290 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 290 1>;
+		assigned-clock-parents = <&k3_clks 290 5>;
+		/* reserved for GPU */
+		status = "reserved";
+	};
+
+	watchdog3: watchdog@2300000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2300000 0x00 0x100>;
+		clocks = <&k3_clks 288 1>;
+		power-domains = <&k3_pds 288 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 288 1>;
+		assigned-clock-parents = <&k3_clks 288 5>;
+		/* reserved for C7X_0 */
+		status = "reserved";
+	};
+
+	watchdog4: watchdog@2310000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2310000 0x00 0x100>;
+		clocks = <&k3_clks 289 1>;
+		power-domains = <&k3_pds 289 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 289 1>;
+		assigned-clock-parents = <&k3_clks 289 5>;
+		/* reserved for C7X_1 */
+		status = "reserved";
+	};
+
+	watchdog5: watchdog@23c0000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x23c0000 0x00 0x100>;
+		clocks = <&k3_clks 291 1>;
+		power-domains = <&k3_pds 291 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 291 1>;
+		assigned-clock-parents = <&k3_clks 291 5>;
+		/* reserved for MAIN_R5F0_0 */
+		status = "reserved";
+	};
+
+	watchdog6: watchdog@23d0000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x23d0000 0x00 0x100>;
+		clocks = <&k3_clks 292 1>;
+		power-domains = <&k3_pds 292 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 292 1>;
+		assigned-clock-parents = <&k3_clks 292 5>;
+		/* reserved for MAIN_R5F0_1 */
+		status = "reserved";
+	};
+
+	watchdog7: watchdog@23e0000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x23e0000 0x00 0x100>;
+		clocks = <&k3_clks 293 1>;
+		power-domains = <&k3_pds 293 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 293 1>;
+		assigned-clock-parents = <&k3_clks 293 5>;
+		/* reserved for MAIN_R5F1_0 */
+		status = "reserved";
+	};
+
+	watchdog8: watchdog@23f0000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x23f0000 0x00 0x100>;
+		clocks = <&k3_clks 294 1>;
+		power-domains = <&k3_pds 294 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 294 1>;
+		assigned-clock-parents = <&k3_clks 294 5>;
+		/* reserved for MAIN_R5F1_1 */
+		status = "reserved";
 	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -50,7 +50,34 @@
 	wkup_pmx0: pinctrl@4301c000 {
 		compatible = "pinctrl-single";
 		/* Proxy 0 addressing */
-		reg = <0x00 0x4301c000 0x00 0x178>;
+		reg = <0x00 0x4301c000 0x00 0x034>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
+
+	wkup_pmx1: pinctrl@4301c038 {
+		compatible = "pinctrl-single";
+		/* Proxy 0 addressing */
+		reg = <0x00 0x4301c038 0x00 0x02C>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
+
+	wkup_pmx2: pinctrl@4301c068 {
+		compatible = "pinctrl-single";
+		/* Proxy 0 addressing */
+		reg = <0x00 0x4301c068 0x00 0x120>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
+
+	wkup_pmx3: pinctrl@4301c190 {
+		compatible = "pinctrl-single";
+		/* Proxy 0 addressing */
+		reg = <0x00 0x4301c190 0x00 0x004>;
 		#pinctrl-cells = <1>;
 		pinctrl-single,register-width = <32>;
 		pinctrl-single,function-mask = <0xffffffff>;
@@ -91,6 +118,7 @@
 		clocks = <&k3_clks 359 3>;
 		clock-names = "fclk";
 		power-domains = <&k3_pds 359 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcu_uart0: serial@40a00000 {
@@ -101,6 +129,7 @@
 		clocks = <&k3_clks 149 3>;
 		clock-names = "fclk";
 		power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	wkup_gpio0: gpio@42110000 {
@@ -144,6 +173,7 @@
 		clocks = <&k3_clks 223 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 223 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcu_i2c0: i2c@40b00000 {
@@ -155,6 +185,7 @@
 		clocks = <&k3_clks 221 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 221 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcu_i2c1: i2c@40b10000 {
@@ -166,6 +197,7 @@
 		clocks = <&k3_clks 222 1>;
 		clock-names = "fck";
 		power-domains = <&k3_pds 222 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
 	};
 
 	mcu_mcan0: can@40528000 {
@@ -180,6 +212,7 @@
 			     <GIC_SPI 833 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
 	};
 
 	mcu_mcan1: can@40568000 {
@@ -194,6 +227,40 @@
 			     <GIC_SPI 836 IRQ_TYPE_LEVEL_HIGH>;
 		interrupt-names = "int0", "int1";
 		bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	mcu_spi0: spi@40300000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x040300000 0x00 0x400>;
+		interrupts = <GIC_SPI 848 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 347 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 347 0>;
+		status = "disabled";
+	};
+
+	mcu_spi1: spi@40310000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x040310000 0x00 0x400>;
+		interrupts = <GIC_SPI 849 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 348 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 348 0>;
+		status = "disabled";
+	};
+
+	mcu_spi2: spi@40320000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x040320000 0x00 0x400>;
+		interrupts = <GIC_SPI 850 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 349 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 349 0>;
+		status = "disabled";
 	};
 
 	mcu_navss: bus@28380000{
@@ -299,4 +366,177 @@
 			ti,cpts-periodic-outputs = <2>;
 		};
 	};
+
+	tscadc0: tscadc@40200000 {
+		compatible = "ti,am3359-tscadc";
+		reg = <0x00 0x40200000 0x00 0x1000>;
+		interrupts = <GIC_SPI 860 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 0 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 0 0>;
+		assigned-clocks = <&k3_clks 0 2>;
+		assigned-clock-rates = <60000000>;
+		clock-names = "fck";
+		dmas = <&main_udmap 0x7400>,
+			<&main_udmap 0x7401>;
+		dma-names = "fifo0", "fifo1";
+		status = "disabled";
+
+		adc {
+			#io-channel-cells = <1>;
+			compatible = "ti,am3359-adc";
+		};
+	};
+
+	tscadc1: tscadc@40210000 {
+		compatible = "ti,am3359-tscadc";
+		reg = <0x00 0x40210000 0x00 0x1000>;
+		interrupts = <GIC_SPI 861 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 1 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 1 0>;
+		assigned-clocks = <&k3_clks 1 2>;
+		assigned-clock-rates = <60000000>;
+		clock-names = "fck";
+		dmas = <&main_udmap 0x7402>,
+			<&main_udmap 0x7403>;
+		dma-names = "fifo0", "fifo1";
+		status = "disabled";
+
+		adc {
+			#io-channel-cells = <1>;
+			compatible = "ti,am3359-adc";
+		};
+	};
+
+	fss: bus@47000000 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>,
+			 <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>,
+			 <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>;
+
+		ospi0: spi@47040000 {
+			compatible = "ti,am654-ospi", "cdns,qspi-nor";
+			reg = <0x00 0x47040000 0x00 0x100>,
+			      <0x05 0x00000000 0x01 0x00000000>;
+			interrupts = <GIC_SPI 840 IRQ_TYPE_LEVEL_HIGH>;
+			cdns,fifo-depth = <256>;
+			cdns,fifo-width = <4>;
+			cdns,trigger-address = <0x0>;
+			clocks = <&k3_clks 109 5>;
+			assigned-clocks = <&k3_clks 109 5>;
+			assigned-clock-parents = <&k3_clks 109 7>;
+			assigned-clock-rates = <166666666>;
+			power-domains = <&k3_pds 109 TI_SCI_PD_EXCLUSIVE>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			status = "disabled"; /* Needs pinmux */
+		};
+
+		ospi1: spi@47050000 {
+			compatible = "ti,am654-ospi", "cdns,qspi-nor";
+			reg = <0x00 0x47050000 0x00 0x100>,
+			      <0x07 0x00000000 0x01 0x00000000>;
+			interrupts = <GIC_SPI 841 IRQ_TYPE_LEVEL_HIGH>;
+			cdns,fifo-depth = <256>;
+			cdns,fifo-width = <4>;
+			cdns,trigger-address = <0x0>;
+			clocks = <&k3_clks 110 5>;
+			power-domains = <&k3_pds 110 TI_SCI_PD_EXCLUSIVE>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			status = "disabled"; /* Needs pinmux */
+		};
+	};
+
+	wkup_vtm0: temperature-sensor@42040000 {
+		compatible = "ti,j7200-vtm";
+		reg = <0x0 0x42040000 0x0 0x350>,
+		      <0x0 0x42050000 0x0 0x350>,
+		      <0x0 0x43000300 0x0 0x10>;
+		power-domains = <&k3_pds 154 TI_SCI_PD_SHARED>;
+		#thermal-sensor-cells = <1>;
+	};
+
+	mcu_r5fss0: r5fss@41000000 {
+		compatible = "ti,j721s2-r5fss";
+		ti,cluster-mode = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x41000000 0x00 0x41000000 0x20000>,
+			 <0x41400000 0x00 0x41400000 0x20000>;
+		power-domains = <&k3_pds 283 TI_SCI_PD_EXCLUSIVE>;
+
+		mcu_r5fss0_core0: r5f@41000000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x41000000 0x00010000>,
+			      <0x41010000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <284>;
+			ti,sci-proc-ids = <0x01 0xff>;
+			resets = <&k3_reset 284 1>;
+			firmware-name = "j721s2-mcu-r5f0_0-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+
+		mcu_r5fss0_core1: r5f@41400000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x41400000 0x00010000>,
+			      <0x41410000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <285>;
+			ti,sci-proc-ids = <0x02 0xff>;
+			resets = <&k3_reset 285 1>;
+			firmware-name = "j721s2-mcu-r5f0_1-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+	};
+
+	mcu_esm: esm@40800000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x00 0x40800000 0x00 0x1000>;
+		ti,esm-pins = <95>;
+		bootph-pre-ram;
+	};
+
+	wkup_esm: esm@42080000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x00 0x42080000 0x00 0x1000>;
+		ti,esm-pins = <63>;
+		bootph-pre-ram;
+	};
+
+	/*
+	 * The 2 RTI instances are couple with MCU R5Fs so keeping them
+	 * reserved as these will be used by their respective firmware
+	 */
+	mcu_watchdog0: watchdog@40600000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x40600000 0x00 0x100>;
+		clocks = <&k3_clks 295 1>;
+		power-domains = <&k3_pds 295 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 295 1>;
+		assigned-clock-parents = <&k3_clks 295 5>;
+		/* reserved for MCU_R5F0_0 */
+		status = "reserved";
+	};
+
+	mcu_watchdog1: watchdog@40610000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x40610000 0x00 0x100>;
+		clocks = <&k3_clks 296 1>;
+		power-domains = <&k3_pds 296 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 296 1>;
+		assigned-clock-parents = <&k3_clks 296 5>;
+		/* reserved for MCU_R5F0_1 */
+		status = "reserved";
+	};
 };
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -24,11 +24,133 @@
 		#size-cells = <2>;
 		ranges;
 
+		 /* global cma region */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x00 0x38000000>;
+			linux,cma-default;
+		};
+
 		secure_ddr: optee@9e800000 {
 			reg = <0x00 0x9e800000 0x00 0x01800000>;
 			alignment = <0x1000>;
 			no-map;
 		};
+
+		mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa0000000 0x00 0x100000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa0100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa1000000 0x00 0x100000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa1100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa2000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss0_core0_memory_region: r5f-memory@a2100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa2100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa3000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss0_core1_memory_region: r5f-memory@a3100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa3100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa4000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss1_core0_memory_region: r5f-memory@a4100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa4100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa5000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss1_core1_memory_region: r5f-memory@a5100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa5100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		c71_0_dma_memory_region: c71-dma-memory@a6000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa6000000 0x00 0x100000>;
+			no-map;
+		};
+
+		c71_0_memory_region: c71-memory@a6100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa6100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		c71_1_dma_memory_region: c71-dma-memory@a7000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa7000000 0x00 0x100000>;
+			no-map;
+		};
+
+		c71_1_memory_region: c71-memory@a7100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa7100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		rtos_ipc_memory_region: ipc-memories@a8000000 {
+			reg = <0x00 0xa8000000 0x00 0x01c00000>;
+			alignment = <0x1000>;
+			no-map;
+		};
+	};
+
+	mux0: mux-controller0 {
+		compatible = "gpio-mux";
+		#mux-state-cells = <1>;
+		mux-gpios = <&exp_som 1 GPIO_ACTIVE_HIGH>;
+	};
+
+	mux1: mux-controller1 {
+		compatible = "gpio-mux";
+		#mux-state-cells = <1>;
+		mux-gpios = <&exp_som 2 GPIO_ACTIVE_HIGH>;
 	};
 
 	transceiver0: can-phy0 {
@@ -37,6 +159,58 @@
 		#phy-cells = <0>;
 		max-bitrate = <5000000>;
 	};
+
+	vsys_io_1v8: regulator-vsys-io-1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_io_1v8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_io_1v2: regulator-vsys-io-1v2 {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_io_1v2";
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	edp1_refclk: clock-edp1-refclk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <19200000>;
+	};
+};
+
+&wkup_pmx0 {
+	mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-pins-default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (D19) MCU_OSPI0_CLK */
+			J721S2_WKUP_IOPAD(0x02c, PIN_OUTPUT, 0) /* (F15) MCU_OSPI0_CSn0 */
+			J721S2_WKUP_IOPAD(0x00c, PIN_INPUT, 0) /* (C19) MCU_OSPI0_D0 */
+			J721S2_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (F16) MCU_OSPI0_D1 */
+			J721S2_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (G15) MCU_OSPI0_D2 */
+			J721S2_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (F18) MCU_OSPI0_D3 */
+			J721S2_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (E19) MCU_OSPI0_D4 */
+			J721S2_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (G19) MCU_OSPI0_D5 */
+			J721S2_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (F19) MCU_OSPI0_D6 */
+			J721S2_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (F20) MCU_OSPI0_D7 */
+			J721S2_WKUP_IOPAD(0x008, PIN_INPUT, 0) /* (E18) MCU_OSPI0_DQS */
+			J721S2_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (E20) MCU_OSPI0_LBCLKO */
+		>;
+	};
+};
+
+&wkup_pmx1 {
+	pmic_irq_pins_default: pmic-irq-pins-default {
+		pinctrl-single,pins = <
+			/* (C21) MCU_OSPI1_CSn1.WKUP_GPIO0_39 */
+			J721S2_WKUP_IOPAD(0x028, PIN_INPUT, 7)
+		>;
+	};
 };
 
 &main_pmx0 {
@@ -56,6 +230,7 @@
 };
 
 &main_i2c0 {
+	status = "okay";
 	pinctrl-names = "default";
 	pinctrl-0 = <&main_i2c0_pins_default>;
 	clock-frequency = <400000>;
@@ -73,21 +248,403 @@
 };
 
 &main_mcan16 {
+	status = "okay";
 	pinctrl-0 = <&main_mcan16_pins_default>;
 	pinctrl-names = "default";
 	phys = <&transceiver0>;
 };
 
+&wkup_pmx2 {
+	wkup_i2c0_pins_default: wkup_i2c0_pins_default {
+		pinctrl-single,pins = <
+			J721S2_WKUP_IOPAD(0x98, PIN_INPUT, 0) /* (H24) WKUP_I2C0_SCL */
+			J721S2_WKUP_IOPAD(0x9c, PIN_INPUT, 0) /* (H27) WKUP_I2C0_SDA */
+		>;
+	};
+};
+
+&wkup_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_i2c0_pins_default>;
+	clock-frequency = <400000>;
+
+	tps659411: pmic@48 {
+		compatible = "ti,tps6594-q1";
+		reg = <0x48>;
+		ti,primary-pmic;
+		system-power-controller;
+
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_irq_pins_default>;
+		interrupt-parent = <&wkup_gpio0>;
+		interrupts = <39 IRQ_TYPE_EDGE_FALLING>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		buck1234-supply = <&vsys_3v3>;
+		buck5-supply = <&vsys_3v3>;
+		ldo1-supply = <&vsys_3v3>;
+		ldo2-supply = <&vsys_3v3>;
+		ldo3-supply = <&vsys_3v3>;
+		ldo4-supply = <&vsys_3v3>;
+
+		regulators {
+			bucka1234: buck1234 {
+				regulator-name = "vdd_cpu_avs";
+				regulator-min-microvolt = <600000>;
+				regulator-max-microvolt = <900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			bucka5: buck5 {
+				regulator-name = "vdd_mcu_0v85";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa1: ldo1 {
+				regulator-name = "vdd_mcuwk_0v8";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa2: ldo2 {
+				regulator-name = "vdd_mcu_gpioret_3v3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa3: ldo3 {
+				regulator-name = "vdd_mcuio_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa4: ldo4 {
+				regulator-name = "vda_mcu_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+
+	tps659414: pmic@4c {
+		compatible = "ti,tps6594-q1";
+		reg = <0x4c>;
+		system-power-controller;
+		interrupt-parent = <&wkup_gpio0>;
+		interrupts = <39 IRQ_TYPE_EDGE_FALLING>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		buck1-supply = <&vsys_3v3>;
+		buck2-supply = <&vsys_3v3>;
+		buck3-supply = <&vsys_3v3>;
+		buck4-supply = <&vsys_3v3>;
+		buck5-supply = <&vsys_3v3>;
+		ldo1-supply = <&vsys_3v3>;
+		ldo2-supply = <&vsys_3v3>;
+		ldo3-supply = <&vsys_3v3>;
+		ldo4-supply = <&vsys_3v3>;
+
+		regulators {
+			buckb1: buck1 {
+				regulator-name = "vdd_io_1v8_reg";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+				regulator-boot-on;
+			};
+
+			buckb2: buck2 {
+				regulator-name = "vdd_fpd_1v1";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buckb3: buck3 {
+				regulator-name = "vdd_phy_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buckb4: buck4 {
+				regulator-name = "vdd_ddr_1v1";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			buckb5: buck5 {
+				regulator-name = "vdd_ram_0v85";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldob1: ldo1 {
+				regulator-name = "vdd_wk_0v8";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldob2: ldo2 {
+				regulator-name = "vdd_gpioret_3v3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldob3: ldo3 {
+				regulator-name = "vda_dll_0v8";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldob4: ldo4 {
+				regulator-name = "vda_pll_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+
+	lp876411: pmic@58 {
+		compatible = "ti,lp8764-q1";
+		reg = <0x58>;
+		system-power-controller;
+		interrupt-parent = <&wkup_gpio0>;
+		interrupts = <39 IRQ_TYPE_EDGE_FALLING>;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		buck1234-supply = <&vsys_3v3>;
+
+		regulators {
+			buckc1234: buck1234 {
+				regulator-name = "vdd_core_0v8";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&ospi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_fss0_ospi0_pins_default>;
+
+	ospi0_nor: flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+		spi-max-frequency = <25000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <4>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "ospi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fc0000 {
+				label = "ospi.phypattern";
+				reg = <0x3fc0000 0x40000>;
+			};
+		};
+	};
+
+	ospi0_nand: nand@0 {
+		compatible = "spi-nand";
+		reg = <0x0>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+		spi-max-frequency = <25000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		status = "disabled";
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi_nand.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi_nand.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi_nand.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi_nand.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi_nand.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@2000000 {
+				label = "ospi_nand.rootfs";
+				reg = <0x2000000 0x5fc0000>;
+			};
+
+			partition@7fc0000 {
+				label = "ospi_nand.phypattern";
+				reg = <0x7fc0000 0x40000>;
+			};
+		};
+	};
+};
+
+&main_i2c4 {
+	dsi_edp_bridge: dsi-edp-bridge@2c {
+		compatible = "ti,sn65dsi86";
+		reg = <0x2c>;
+
+		clock-names = "refclk";
+		clocks = <&edp1_refclk>;
+
+		enable-gpios = <&exp_som 5 0>;
+
+		vpll-supply = <&vsys_io_1v8>;
+		vccio-supply = <&vsys_io_1v8>;
+		vcca-supply = <&vsys_io_1v2>;
+		vcc-supply = <&vsys_io_1v2>;
+
+		dsi_edp_bridge_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+			};
+			port@1 {
+				reg = <1>;
+			};
+		};
+	};
+};
+
 &mailbox0_cluster0 {
-	status = "disabled";
+	interrupts = <436>;
+
+	mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
 };
 
 &mailbox0_cluster1 {
-	status = "disabled";
+	interrupts = <432>;
+
+	mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
 };
 
 &mailbox0_cluster2 {
-	status = "disabled";
+	interrupts = <428>;
+
+	mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
 };
 
 &mailbox0_cluster3 {
@@ -95,7 +652,17 @@
 };
 
 &mailbox0_cluster4 {
-	status = "disabled";
+	interrupts = <420>;
+
+	mbox_c71_0: mbox-c71-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_c71_1: mbox-c71-1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
 };
 
 &mailbox0_cluster5 {
@@ -173,3 +740,51 @@
 &mailbox1_cluster11 {
 	status = "disabled";
 };
+
+&mcu_r5fss0_core0 {
+	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
+	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
+			<&mcu_r5fss0_core0_memory_region>;
+};
+
+&mcu_r5fss0_core1 {
+	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>;
+	memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
+			<&mcu_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss0_core0 {
+	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>;
+	memory-region = <&main_r5fss0_core0_dma_memory_region>,
+			<&main_r5fss0_core0_memory_region>;
+};
+
+&main_r5fss0_core1 {
+	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>;
+	memory-region = <&main_r5fss0_core1_dma_memory_region>,
+			<&main_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss1_core0 {
+	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>;
+	memory-region = <&main_r5fss1_core0_dma_memory_region>,
+			<&main_r5fss1_core0_memory_region>;
+};
+
+&main_r5fss1_core1 {
+	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>;
+	memory-region = <&main_r5fss1_core1_dma_memory_region>,
+			<&main_r5fss1_core1_memory_region>;
+};
+
+&c71_0 {
+	mboxes = <&mailbox0_cluster4 &mbox_c71_0>;
+	memory-region = <&c71_0_dma_memory_region>,
+			<&c71_0_memory_region>;
+};
+
+&c71_1 {
+	mboxes = <&mailbox0_cluster4 &mbox_c71_1>;
+	memory-region = <&c71_1_dma_memory_region>,
+			<&c71_1_memory_region>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j721s2-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-thermal.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j721s2-thermal.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-thermal.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/thermal/thermal.h>
+
+wkup0_thermal: wkup0-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 0>;
+
+	trips {
+		wkup0_crit: wkup0-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
+
+wkup1_thermal: wkup1-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 1>;
+
+	trips {
+		wkup1_crit: wkup1-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
+
+main0_thermal: main0-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 2>;
+
+	trips {
+		main0_crit: main0-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
+
+main1_thermal: main1-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 3>;
+
+	trips {
+		main1_crit: main1-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
+
+main2_thermal: main2-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 4>;
+
+	trips {
+		main2_crit: main2-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
+
+main3_thermal: main3-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 5>;
+
+	trips {
+		main3_crit: main3-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
+
+main4_thermal: main4-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 6>;
+
+	trips {
+		main4_crit: main4-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j722s.dtsi b/arch/arm64/boot/dts/ti/k3-j722s.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j722s.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j722s.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for J722S SoC Family
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+#include "k3-am62p5.dtsi"
+
+/ {
+	model = "Texas Instruments K3 J722S SoC";
+	compatible = "ti,j722s";
+
+	cbass_main: bus@f0000 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+
+		ranges = <0x00 0x000f0000 0x00 0x000f0000 0x00 0x00030000>, /* Main MMRs */
+			 <0x00 0x00420000 0x00 0x00420000 0x00 0x00001000>, /* ESM0 */
+			 <0x00 0x00600000 0x00 0x00600000 0x00 0x00001100>, /* GPIO */
+			 <0x00 0x00703000 0x00 0x00703000 0x00 0x00000200>, /* USB0 debug trace */
+			 <0x00 0x0070c000 0x00 0x0070c000 0x00 0x00000200>, /* USB1 debug trace */
+			 <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* Timesync router */
+			 <0x00 0x01000000 0x00 0x01000000 0x00 0x01b28400>, /* First peripheral window */
+			 <0x00 0x08000000 0x00 0x08000000 0x00 0x00200000>, /* Main CPSW */
+			 <0x00 0x0d000000 0x00 0x0d000000 0x00 0x00800000>, /* PCIE_0 */
+			 <0x00 0x0e000000 0x00 0x0e000000 0x00 0x01d20000>, /* Second peripheral window */
+			 <0x00 0x0fd80000 0x00 0x0fd80000 0x00 0x00080000>, /* GPU */
+			 <0x00 0x0fd20000 0x00 0x0fd20000 0x00 0x00000100>, /* JPEGENC0_CORE */
+			 <0x00 0x0fd20200 0x00 0x0fd20200 0x00 0x00000200>, /* JPEGENC0_CORE_MMU */
+			 <0x00 0x20000000 0x00 0x20000000 0x00 0x0a008000>, /* Third peripheral window */
+			 <0x00 0x30040000 0x00 0x30040000 0x00 0x00080000>, /* PRUSS-M */
+			 <0x00 0x301C0000 0x00 0x301C0000 0x00 0x00001000>, /* DPHY-TX */
+			 <0x00 0x30101000 0x00 0x30101000 0x00 0x00080100>, /* CSI window */
+			 <0x00 0x30200000 0x00 0x30200000 0x00 0x00010000>, /* DSS */
+			 <0x00 0x30210000 0x00 0x30210000 0x00 0x00010000>, /* VPU */
+			 <0x00 0x30220000 0x00 0x30220000 0x00 0x00010000>, /* DSS1 */
+			 <0x00 0x30270000 0x00 0x30270000 0x00 0x00010000>, /* DSI-base1 */
+			 <0x00 0x30500000 0x00 0x30500000 0x00 0x00100000>, /* DSI-base2 */
+			 <0x00 0x31000000 0x00 0x31000000 0x00 0x00050000>, /* USB0 DWC3 Core window */
+			 <0x00 0x31200000 0x00 0x31200000 0x00 0x00040000>, /* USB1 DWC3 Core window */
+			 <0x00 0x40900000 0x00 0x40900000 0x00 0x00030000>, /* SA3UL */
+			 <0x00 0x43600000 0x00 0x43600000 0x00 0x00010000>, /* SA3 sproxy data */
+			 <0x00 0x44043000 0x00 0x44043000 0x00 0x00000fe0>, /* TI SCI DEBUG */
+			 <0x00 0x44860000 0x00 0x44860000 0x00 0x00040000>, /* SA3 sproxy config */
+			 <0x00 0x48000000 0x00 0x48000000 0x00 0x06408000>, /* DMSS */
+			 <0x00 0x60000000 0x00 0x60000000 0x00 0x08000000>, /* FSS0 DAT1 */
+			 <0x00 0x68000000 0x00 0x68000000 0x00 0x08000000>, /* PCIe0 DAT0 */
+			 <0x00 0x70000000 0x00 0x70000000 0x00 0x00040000>, /* OCSRAM */
+			 <0x00 0x78400000 0x00 0x78400000 0x00 0x00008000>, /* MAIN R5FSS0 ATCM */
+			 <0x00 0x78500000 0x00 0x78500000 0x00 0x00008000>, /* MAIN R5FSS0 BTCM */
+			 <0x00 0x7e000000 0x00 0x7e000000 0x00 0x00200000>, /* C7X_0 L2SRAM */
+			 <0x00 0x7e200000 0x00 0x7e200000 0x00 0x00200000>, /* C7X_1 L2SRAM */
+			 <0x01 0x00000000 0x01 0x00000000 0x00 0x00310000>, /* A53 PERIPHBASE */
+			 <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, /* FSS0 DAT3 */
+			 <0x06 0x00000000 0x06 0x00000000 0x01 0x00000000>, /* PCIe0 DAT1 */
+
+			 /* MCU Domain Range */
+			 <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>,
+			 <0x00 0x79000000 0x00 0x79000000 0x00 0x00008000>,
+			 <0x00 0x79020000 0x00 0x79020000 0x00 0x00008000>,
+			 <0x00 0x79100000 0x00 0x79100000 0x00 0x00040000>,
+			 <0x00 0x79140000 0x00 0x79140000 0x00 0x00040000>,
+
+			 /* Wakeup Domain Range */
+			 <0x00 0x00b00000 0x00 0x00b00000 0x00 0x00002400>,
+			 <0x00 0x2b000000 0x00 0x2b000000 0x00 0x00300400>,
+			 <0x00 0x43000000 0x00 0x43000000 0x00 0x00020000>,
+			 <0x00 0x78000000 0x00 0x78000000 0x00 0x00008000>,
+			 <0x00 0x78100000 0x00 0x78100000 0x00 0x00008000>;
+	};
+};
+
+/* Main domain overrides */
+
+&inta_main_dmss {
+	ti,interrupt-ranges = <7 71 21>;
+};
+
+&inta_main_dmss_csi {
+	ti,interrupt-ranges = <0 237 8>;
+};
+
+&main_bcdma_csi {
+	compatible = "ti,j722s-dmss-bcdma-csi";
+	reg = <0x00 0x4e230000 0x00 0x100>,
+			<0x00 0x4e180000 0x00 0x20000>,
+			<0x00 0x4e300000 0x00 0x10000>,
+			<0x00 0x4e100000 0x00 0x80000>;
+	reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt";
+	msi-parent = <&inta_main_dmss_csi>;
+	#dma-cells = <3>;
+	ti,sci = <&dmsc>;
+	ti,sci-dev-id = <199>;
+	ti,sci-rm-range-rchan = <0x21>;
+	ti,sci-rm-range-tchan = <0x22>;
+	power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+};
+
+&oc_sram {
+	reg = <0x00 0x70000000 0x00 0x40000>;
+	ranges = <0x00 0x00 0x70000000 0x40000>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts
--- a/arch/arm64/boot/dts/ti/k3-j722s-evm.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j722s-evm.dts	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,524 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree file for the J722S-EVM
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * Schematics: https://www.ti.com/lit/zip/sprr495
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include "k3-j722s.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
+
+/ {
+	compatible = "ti,j722s-evm", "ti,j722s";
+	model = "Texas Instruments J722S EVM";
+
+	aliases {
+		serial0 = &wkup_uart0;
+		serial2 = &main_uart0;
+		mmc0 = &sdhci0;
+		mmc1 = &sdhci1;
+	};
+
+	chosen {
+		stdout-path = &main_uart0;
+	};
+
+	memory@80000000 {
+		/* 8G RAM */
+		reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
+		      <0x00000008 0x80000000 0x00000001 0x80000000>;
+		device_type = "memory";
+		bootph-pre-ram;
+	};
+
+	reserved_memory: reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		secure_tfa_ddr: tfa@9e780000 {
+			reg = <0x00 0x9e780000 0x00 0x80000>;
+			no-map;
+		};
+
+		secure_ddr: optee@9e800000 {
+			reg = <0x00 0x9e800000 0x00 0x01800000>;
+			no-map;
+		};
+
+		wkup_r5fss0_core0_memory_region: r5f-memory@a0100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa0100000 0x00 0xf00000>;
+			no-map;
+		};
+
+	};
+
+	vmain_pd: regulator-0 {
+		/* TPS65988 PD CONTROLLER OUTPUT */
+		compatible = "regulator-fixed";
+		regulator-name = "vmain_pd";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		regulator-always-on;
+		regulator-boot-on;
+		bootph-all;
+	};
+
+	vsys_5v0: regulator-vsys5v0 {
+		/* Output of LM5140 */
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_5v0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&vmain_pd>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vdd_mmc1: regulator-mmc1 {
+		/* TPS22918DBVR */
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_mmc1";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		enable-active-high;
+		gpio = <&exp1 15 GPIO_ACTIVE_HIGH>;
+		bootph-all;
+	};
+
+	vdd_sd_dv: regulator-TLV71033 {
+		compatible = "regulator-gpio";
+		regulator-name = "tlv71033";
+		pinctrl-names = "default";
+		pinctrl-0 = <&vdd_sd_dv_pins_default>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		vin-supply = <&vsys_5v0>;
+		gpios = <&main_gpio0 70 GPIO_ACTIVE_HIGH>;
+		states = <1800000 0x0>,
+			 <3300000 0x1>;
+	};
+
+	vsys_io_1v8: regulator-vsys-io-1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_io_1v8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_io_1v2: regulator-vsys-io-1v2 {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_io_1v2";
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&led_pins_default>;
+
+		led-0 {
+			label = "j722s-evm:red:heartbeat";
+			gpios = <&main_gpio1 49 GPIO_ACTIVE_HIGH>;
+			function = LED_FUNCTION_HEARTBEAT;
+			linux,default-trigger = "heartbeat";
+		};
+
+		led-1 {
+			label = "j722s-evm:green:disk-activity";
+			gpios = <&exp1 16 GPIO_ACTIVE_HIGH>;
+			function = LED_FUNCTION_DISK_ACTIVITY;
+			linux,default-trigger = "mmc1";
+			default-state = "off";
+		};
+	};
+};
+
+&main_pmx0 {
+
+	main_i2c0_pins_default: main-i2c0-default-pins {
+		pinctrl-single,pins = <
+			J722S_IOPAD(0x01e0, PIN_INPUT_PULLUP, 0) /* (D23) I2C0_SCL */
+			J722S_IOPAD(0x01e4, PIN_INPUT_PULLUP, 0) /* (B22) I2C0_SDA */
+		>;
+		bootph-all;
+	};
+
+	main_uart0_pins_default: main-uart0-default-pins {
+		pinctrl-single,pins = <
+			J722S_IOPAD(0x1c8, PIN_INPUT, 0)	/* (A22) UART0_RXD */
+			J722S_IOPAD(0x1cc, PIN_OUTPUT, 0)	/* (B22) UART0_TXD */
+		>;
+		bootph-all;
+	};
+
+	vdd_sd_dv_pins_default: vdd-sd-dv-default-pins {
+		pinctrl-single,pins = <
+			J722S_IOPAD(0x0120, PIN_INPUT, 7) /* (F27) MMC2_CMD.GPIO0_70 */
+		>;
+		bootph-all;
+	};
+
+	main_mmc1_pins_default: main-mmc1-default-pins {
+		pinctrl-single,pins = <
+			J722S_IOPAD(0x023c, PIN_INPUT, 0) /* (H22) MMC1_CMD */
+			J722S_IOPAD(0x0234, PIN_OUTPUT, 0) /* (H24) MMC1_CLK */
+			J722S_IOPAD(0x0230, PIN_INPUT, 0) /* (H23) MMC1_DAT0 */
+			J722S_IOPAD(0x022c, PIN_INPUT_PULLUP, 0) /* (H20) MMC1_DAT1 */
+			J722S_IOPAD(0x0228, PIN_INPUT_PULLUP, 0) /* (J23) MMC1_DAT2 */
+			J722S_IOPAD(0x0224, PIN_INPUT_PULLUP, 0) /* (H25) MMC1_DAT3 */
+			J722S_IOPAD(0x0240, PIN_INPUT, 0) /* (B24) MMC1_SDCD */
+		>;
+		bootph-all;
+	};
+
+	ospi0_pins_default: ospi0-default-pins {
+		pinctrl-single,pins = <
+			J722S_IOPAD(0x0000, PIN_OUTPUT, 0) /* (P23) OSPI0_CLK */
+			J722S_IOPAD(0x002c, PIN_OUTPUT, 0) /* (M25) OSPI0_CSn0 */
+			J722S_IOPAD(0x000c, PIN_INPUT, 0) /* (L25) OSPI0_D0 */
+			J722S_IOPAD(0x0010, PIN_INPUT, 0) /* (N24) OSPI0_D1 */
+			J722S_IOPAD(0x0014, PIN_INPUT, 0) /* (N25) OSPI0_D2 */
+			J722S_IOPAD(0x0018, PIN_INPUT, 0) /* (M24) OSPI0_D3 */
+			J722S_IOPAD(0x001c, PIN_INPUT, 0) /* (N21) OSPI0_D4 */
+			J722S_IOPAD(0x0020, PIN_INPUT, 0) /* (N22) OSPI0_D5 */
+			J722S_IOPAD(0x0024, PIN_INPUT, 0) /* (P21) OSPI0_D6 */
+			J722S_IOPAD(0x0028, PIN_INPUT, 0) /* (N20) OSPI0_D7 */
+			J722S_IOPAD(0x0008, PIN_INPUT, 0) /* (P22) OSPI0_DQS */
+		>;
+		bootph-all;
+	};
+
+	mdio_pins_default: mdio-default-pins {
+		pinctrl-single,pins = <
+			J722S_IOPAD(0x0160, PIN_OUTPUT, 0) /* (AC24) MDIO0_MDC */
+			J722S_IOPAD(0x015c, PIN_INPUT, 0) /* (AD25) MDIO0_MDIO */
+		>;
+	};
+
+	rgmii1_pins_default: rgmii1-default-pins {
+		pinctrl-single,pins = <
+			J722S_IOPAD(0x014c, PIN_INPUT, 0) /* (AC25) RGMII1_RD0 */
+			J722S_IOPAD(0x0150, PIN_INPUT, 0) /* (AD27) RGMII1_RD1 */
+			J722S_IOPAD(0x0154, PIN_INPUT, 0) /* (AE24) RGMII1_RD2 */
+			J722S_IOPAD(0x0158, PIN_INPUT, 0) /* (AE26) RGMII1_RD3 */
+			J722S_IOPAD(0x0148, PIN_INPUT, 0) /* (AE27) RGMII1_RXC */
+			J722S_IOPAD(0x0144, PIN_INPUT, 0) /* (AD23) RGMII1_RX_CTL */
+			J722S_IOPAD(0x0134, PIN_OUTPUT, 0) /* (AF27) RGMII1_TD0 */
+			J722S_IOPAD(0x0138, PIN_OUTPUT, 0) /* (AE23) RGMII1_TD1 */
+			J722S_IOPAD(0x013c, PIN_OUTPUT, 0) /* (AG25) RGMII1_TD2 */
+			J722S_IOPAD(0x0140, PIN_OUTPUT, 0) /* (AF24) RGMII1_TD3 */
+			J722S_IOPAD(0x0130, PIN_OUTPUT, 0) /* (AG26) RGMII1_TXC */
+			J722S_IOPAD(0x012c, PIN_OUTPUT, 0) /* (AF25) RGMII1_TX_CTL */
+		>;
+	};
+
+	led_pins_default: led-default-pins {
+		pinctrl-single,pins = <
+			J722S_IOPAD(0x0244, PIN_INPUT, 7) /* (A24) MMC1_SDWP */
+		>;
+	};
+};
+
+&main_gpio1 {
+	status = "okay";
+};
+
+&main_uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_uart0_pins_default>;
+	status = "okay";
+	bootph-all;
+};
+
+&mcu_pmx0 {
+
+	wkup_uart0_pins_default: wkup-uart0-default-pins {
+		pinctrl-single,pins = <
+			J722S_MCU_IOPAD(0x02c, PIN_INPUT, 0)	/* (C7) WKUP_UART0_CTSn */
+			J722S_MCU_IOPAD(0x030, PIN_OUTPUT, 0)	/* (C6) WKUP_UART0_RTSn */
+			J722S_MCU_IOPAD(0x024, PIN_INPUT, 0)	/* (D8) WKUP_UART0_RXD */
+			J722S_MCU_IOPAD(0x028, PIN_OUTPUT, 0)	/* (D7) WKUP_UART0_TXD */
+		>;
+		bootph-all;
+	};
+
+	wkup_i2c0_pins_default: wkup-i2c0-default-pins {
+		pinctrl-single,pins = <
+			J722S_MCU_IOPAD(0x04c, PIN_INPUT_PULLUP, 0)	/* (C7) WKUP_I2C0_SCL */
+			J722S_MCU_IOPAD(0x050, PIN_INPUT_PULLUP, 0)	/* (C6) WKUP_I2C1_SDA */
+		>;
+		bootph-all;
+	};
+};
+
+&wkup_uart0 {
+	/* WKUP UART0 is used by DM firmware */
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_uart0_pins_default>;
+	status = "reserved";
+	bootph-all;
+};
+
+&wkup_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_i2c0_pins_default>;
+	clock-frequency = <400000>;
+	bootph-all;
+};
+
+&main_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c0_pins_default>;
+	clock-frequency = <400000>;
+	bootph-all;
+
+	exp1: gpio@23 {
+		compatible = "ti,tca6424";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names = "TRC_MUX_SEL", "OSPI/ONAND_MUX_SEL",
+				  "MCASP1_FET_SEL", "CTRL_PM_I2C_OE#",
+				  "CSI_VIO_SEL", "USB2.0_MUX_SEL",
+				  "CSI01_MUX_SEL_2", "CSI23_MUX_SEL_2",
+				  "LMK1_OE1", "LMK1_OE0",
+				  "LMK2_OE0", "LMK2_OE1",
+				  "GPIO_RGMII1_RST#", "GPIO_AUD_RSTn",
+				  "GPIO_eMMC_RSTn", "GPIO_uSD_PWR_EN",
+				  "USER_LED2", "MCAN0_STB",
+				  "PCIe0_1L_RC_RSTz", "PCIe0_1L_PRSNT#",
+				  "ENET1_EXP_SPARE2", "ENET1_EXP_PWRDN",
+				  "PD_I2ENET1_I2CMUX_SELC_IRQ", "ENET1_EXP_RESETZ";
+	};
+};
+
+&sdhci0 {
+	/*eMMC*/
+	status = "okay";
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
+	bootph-all;
+};
+
+&sdhci1 {
+	/* SD/MMC */
+	status = "okay";
+	vmmc-supply = <&vdd_mmc1>;
+	vqmmc-supply = <&vdd_sd_dv>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mmc1_pins_default>;
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
+	no-1-8-v;
+	bootph-all;
+};
+
+&ospi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&ospi0_pins_default>;
+	bootph-all;
+
+	flash@0{
+		compatible = "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+		spi-max-frequency = <25000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <4>;
+		bootph-all;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			bootph-all;
+
+			partition@0 {
+				label = "ospi.tiboot3";
+				reg = <0x00 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "ospi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fc0000 {
+				label = "ospi.phypattern";
+				reg = <0x3fc0000 0x40000>;
+				bootph-all;
+			};
+		};
+	};
+
+	ospi0_nand: nand@0 {
+		compatible = "spi-nand";
+		reg = <0x0>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+		spi-max-frequency = <25000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		status = "disabled";
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi_nand.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi_nand.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi_nand.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi_nand.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi_nand.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@2000000 {
+				label = "ospi_nand.rootfs";
+				reg = <0x2000000 0x5fc0000>;
+			};
+
+			partition@7fc0000 {
+				label = "ospi_nand.phypattern";
+				reg = <0x7fc0000 0x40000>;
+			};
+		};
+	};
+};
+
+&cpsw3g {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&rgmii1_pins_default>;
+};
+
+&cpsw3g_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio_pins_default>;
+
+	cpsw3g_phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+};
+
+&cpsw_port1 {
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&cpsw3g_phy0>;
+};
+
+&cpsw_port2 {
+	status = "disabled";
+};
+
+&mailbox0_cluster0 {
+	status = "okay";
+	mbox_r5_0: mbox-r5-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+};
+
+&mailbox0_cluster1 {
+	status = "okay";
+	mbox_mcu_r5_0: mbox-mcu-r5-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+};
+
+&mailbox0_cluster2 {
+	status = "okay";
+	mbox_c7x_0: mbox-c7x-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+};
+
+&mailbox0_cluster3 {
+	status = "okay";
+	mbox_main_r5_0: mbox-main-r5-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_c7x_1: mbox-c7x-1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mcu_r5fss0 {
+	status = "disabled";
+};
+
+&wkup_r5fss0 {
+	status = "disabled";
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j784s4.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j784s4.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,297 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for J784S4 SoC Family
+ *
+ * TRM (SPRUJ43 JULY 2022) : http://www.ti.com/lit/zip/spruj52
+ *
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+#include "k3-pinctrl.h"
+
+/ {
+	model = "Texas Instruments K3 J784S4 SoC";
+	compatible = "ti,j784s4";
+	interrupt-parent = <&gic500>;
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu-map {
+			cluster0: cluster0 {
+				core0 {
+					cpu = <&cpu0>;
+				};
+
+				core1 {
+					cpu = <&cpu1>;
+				};
+
+				core2 {
+					cpu = <&cpu2>;
+				};
+
+				core3 {
+					cpu = <&cpu3>;
+				};
+			};
+
+			cluster1: cluster1 {
+				core0 {
+					cpu = <&cpu4>;
+				};
+
+				core1 {
+					cpu = <&cpu5>;
+				};
+
+				core2 {
+					cpu = <&cpu6>;
+				};
+
+				core3 {
+					cpu = <&cpu7>;
+				};
+			};
+		};
+
+		cpu0: cpu@0 {
+			compatible = "arm,cortex-a72";
+			reg = <0x000>;
+			device_type = "cpu";
+			enable-method = "psci";
+			i-cache-size = <0xc000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <256>;
+			next-level-cache = <&L2_0>;
+		};
+
+		cpu1: cpu@1 {
+			compatible = "arm,cortex-a72";
+			reg = <0x001>;
+			device_type = "cpu";
+			enable-method = "psci";
+			i-cache-size = <0xc000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <256>;
+			next-level-cache = <&L2_0>;
+		};
+
+		cpu2: cpu@2 {
+			compatible = "arm,cortex-a72";
+			reg = <0x002>;
+			device_type = "cpu";
+			enable-method = "psci";
+			i-cache-size = <0xc000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <256>;
+			next-level-cache = <&L2_0>;
+		};
+
+		cpu3: cpu@3 {
+			compatible = "arm,cortex-a72";
+			reg = <0x003>;
+			device_type = "cpu";
+			enable-method = "psci";
+			i-cache-size = <0xc000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <256>;
+			next-level-cache = <&L2_0>;
+		};
+
+		cpu4: cpu@100 {
+			compatible = "arm,cortex-a72";
+			reg = <0x100>;
+			device_type = "cpu";
+			enable-method = "psci";
+			i-cache-size = <0xc000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <256>;
+			next-level-cache = <&L2_1>;
+		};
+
+		cpu5: cpu@101 {
+			compatible = "arm,cortex-a72";
+			reg = <0x101>;
+			device_type = "cpu";
+			enable-method = "psci";
+			i-cache-size = <0xc000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <256>;
+			next-level-cache = <&L2_1>;
+		};
+
+		cpu6: cpu@102 {
+			compatible = "arm,cortex-a72";
+			reg = <0x102>;
+			device_type = "cpu";
+			enable-method = "psci";
+			i-cache-size = <0xc000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <256>;
+			next-level-cache = <&L2_1>;
+		};
+
+		cpu7: cpu@103 {
+			compatible = "arm,cortex-a72";
+			reg = <0x103>;
+			device_type = "cpu";
+			enable-method = "psci";
+			i-cache-size = <0xc000>;
+			i-cache-line-size = <64>;
+			i-cache-sets = <256>;
+			d-cache-size = <0x8000>;
+			d-cache-line-size = <64>;
+			d-cache-sets = <256>;
+			next-level-cache = <&L2_1>;
+		};
+	};
+
+	L2_0: l2-cache0 {
+		compatible = "cache";
+		cache-level = <2>;
+		cache-unified;
+		cache-size = <0x200000>;
+		cache-line-size = <64>;
+		cache-sets = <1024>;
+		next-level-cache = <&msmc_l3>;
+	};
+
+	L2_1: l2-cache1 {
+		compatible = "cache";
+		cache-level = <2>;
+		cache-unified;
+		cache-size = <0x200000>;
+		cache-line-size = <64>;
+		cache-sets = <1024>;
+		next-level-cache = <&msmc_l3>;
+	};
+
+	msmc_l3: l3-cache0 {
+		compatible = "cache";
+		cache-level = <3>;
+		cache-unified;
+	};
+
+	firmware {
+		optee {
+			compatible = "linaro,optee-tz";
+			method = "smc";
+		};
+
+		psci: psci {
+			compatible = "arm,psci-1.0";
+			method = "smc";
+		};
+	};
+
+	a72_timer0: timer-cl0-cpu0 {
+		compatible = "arm,armv8-timer";
+		interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>, /* cntpsirq */
+			     <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>, /* cntpnsirq */
+			     <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>, /* cntvirq */
+			     <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>; /* cnthpirq */
+	};
+
+	pmu: pmu {
+		compatible = "arm,cortex-a72-pmu";
+		/* Recommendation from GIC500 TRM Table A.3 */
+		interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_HIGH>;
+	};
+
+	cbass_main: bus@100000 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x00 0x00100000 0x00 0x00100000 0x00 0x00020000>, /* ctrl mmr */
+			 <0x00 0x00600000 0x00 0x00600000 0x00 0x00031100>, /* GPIO */
+			 <0x00 0x00a40000 0x00 0x00a40000 0x00 0x00000800>, /* Time Sync Router */
+			 <0x00 0x01000000 0x00 0x01000000 0x00 0x0d000000>, /* Most peripherals */
+			 <0x00 0x0d000000 0x00 0x0d000000 0x00 0x01000000>, /* PCIe1 Core*/
+			 <0x00 0x0e800000 0x00 0x0e800000 0x00 0x01000000>, /* PCIe3 Core*/
+			 <0x00 0x10000000 0x00 0x10000000 0x00 0x08000000>, /* PCIe0 DAT0 */
+			 <0x00 0x18000000 0x00 0x18000000 0x00 0x08000000>, /* PCIe1 DAT0 */
+			 <0x44 0x00000000 0x44 0x00000000 0x00 0x08000000>, /* PCIe2 DAT0 */
+			 <0x44 0x10000000 0x44 0x10000000 0x00 0x08000000>, /* PCIe3 DAT0 */
+			 <0x00 0x64800000 0x00 0x64800000 0x00 0x0070c000>, /* C71_1 */
+			 <0x00 0x65800000 0x00 0x65800000 0x00 0x0070c000>, /* C71_2 */
+			 <0x00 0x66800000 0x00 0x66800000 0x00 0x0070c000>, /* C71_3 */
+			 <0x00 0x67800000 0x00 0x67800000 0x00 0x0070c000>, /* C71_4 */
+			 <0x00 0x6f000000 0x00 0x6f000000 0x00 0x00310000>, /* A72 PERIPHBASE */
+			 <0x00 0x70000000 0x00 0x70000000 0x00 0x00400000>, /* MSMC RAM */
+			 <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>, /* MAIN NAVSS */
+			 <0x41 0x00000000 0x41 0x00000000 0x01 0x00000000>, /* PCIe1 DAT1 */
+			 <0x43 0x00000000 0x43 0x00000000 0x01 0x00000000>, /* PCIe3 DAT1 */
+			 <0x4e 0x20000000 0x4e 0x20000000 0x00 0x00080000>, /* GPU */
+
+			 /* MCUSS_WKUP Range */
+			 <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>,
+			 <0x00 0x40200000 0x00 0x40200000 0x00 0x00998400>,
+			 <0x00 0x40f00000 0x00 0x40f00000 0x00 0x00020000>,
+			 <0x00 0x41000000 0x00 0x41000000 0x00 0x00020000>,
+			 <0x00 0x41400000 0x00 0x41400000 0x00 0x00020000>,
+			 <0x00 0x41c00000 0x00 0x41c00000 0x00 0x00100000>,
+			 <0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>,
+			 <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>,
+			 <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>,
+			 <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>,
+			 <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>,
+			 <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>,
+			 <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>;
+
+		cbass_mcu_wakeup: bus@28380000 {
+			compatible = "simple-bus";
+			#address-cells = <2>;
+			#size-cells = <2>;
+			ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>, /* MCU NAVSS*/
+				 <0x00 0x40200000 0x00 0x40200000 0x00 0x00998400>, /* First peripheral window */
+				 <0x00 0x40f00000 0x00 0x40f00000 0x00 0x00020000>, /* CTRL_MMR0 */
+				 <0x00 0x41000000 0x00 0x41000000 0x00 0x00020000>, /* MCU R5F Core0 */
+				 <0x00 0x41400000 0x00 0x41400000 0x00 0x00020000>, /* MCU R5F Core1 */
+				 <0x00 0x41c00000 0x00 0x41c00000 0x00 0x00100000>, /* MCU SRAM */
+				 <0x00 0x42040000 0x00 0x42040000 0x00 0x03ac2400>, /* WKUP peripheral window */
+				 <0x00 0x45100000 0x00 0x45100000 0x00 0x00c24000>, /* MMRs, remaining NAVSS */
+				 <0x00 0x46000000 0x00 0x46000000 0x00 0x00200000>, /* CPSW */
+				 <0x00 0x47000000 0x00 0x47000000 0x00 0x00068400>, /* OSPI register space */
+				 <0x00 0x50000000 0x00 0x50000000 0x00 0x10000000>, /* FSS OSPI0/1 data region 0 */
+				 <0x05 0x00000000 0x05 0x00000000 0x01 0x00000000>, /* FSS OSPI0 data region 3 */
+				 <0x07 0x00000000 0x07 0x00000000 0x01 0x00000000>; /* FSS OSPI1 data region 3*/
+		};
+	};
+
+	thermal_zones: thermal-zones {
+		#include "k3-j784s4-thermal.dtsi"
+	};
+};
+
+/* Now include peripherals from each bus segment */
+#include "k3-j784s4-main.dtsi"
+#include "k3-j784s4-mcu-wakeup.dtsi"
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4-evm-csi2-ov5640.dtso b/arch/arm64/boot/dts/ti/k3-j784s4-evm-csi2-ov5640.dtso
--- a/arch/arm64/boot/dts/ti/k3-j784s4-evm-csi2-ov5640.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm-csi2-ov5640.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * LI OV5640 MIPI Camera module on MIPI CSI (CSI2-EXP-AUX) connector.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+
+&{/} {
+	clk_ov5640_fixed: ov5640-xclk {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+};
+
+&main_i2c5 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	ov5640: camera@3c {
+		compatible = "ovti,ov5640";
+		reg = <0x3c>;
+		clocks = <&clk_ov5640_fixed>;
+		clock-names = "xclk";
+		powerdown-gpios = <&exp5 0 GPIO_ACTIVE_LOW>;
+
+		port {
+			csi2_cam0: endpoint {
+				remote-endpoint = <&csi2rx2_in_sensor>;
+				clock-lanes = <0>;
+				data-lanes = <1 2>;
+			};
+		};
+	};
+};
+
+&csi2_port0 {
+	status = "okay";
+
+	csi2rx2_in_sensor: endpoint {
+		remote-endpoint = <&csi2_cam0>;
+		bus-type = <4>; /* CSI2 DPHY */
+		clock-lanes = <0>;
+		data-lanes = <1 2>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts
--- a/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm.dts	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,1534 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * EVM Board Schematics: https://www.ti.com/lit/zip/sprr458
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "k3-j784s4.dtsi"
+
+/ {
+	compatible = "ti,j784s4-evm", "ti,j784s4";
+	model = "Texas Instruments J784S4 EVM";
+
+	chosen {
+		stdout-path = "serial2:115200n8";
+	};
+
+	aliases {
+		serial0 = &wkup_uart0;
+		serial1 = &mcu_uart0;
+		serial2 = &main_uart8;
+		mmc0 = &main_sdhci0;
+		mmc1 = &main_sdhci1;
+		i2c0 = &main_i2c0;
+	};
+
+	memory@80000000 {
+		device_type = "memory";
+		/* 32G RAM */
+		reg = <0x00 0x80000000 0x00 0x80000000>,
+		      <0x08 0x80000000 0x07 0x80000000>;
+	};
+
+	reserved_memory: reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		 /* global cma region */
+		linux,cma {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0x00 0x70000000>;
+			linux,cma-default;
+		};
+
+		secure_ddr: optee@9e800000 {
+			reg = <0x00 0x9e800000 0x00 0x01800000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa0000000 0x00 0x100000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa0100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa1000000 0x00 0x100000>;
+			no-map;
+		};
+
+		mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa1100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa2000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss0_core0_memory_region: r5f-memory@a2100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa2100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa3000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss0_core1_memory_region: r5f-memory@a3100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa3100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa4000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss1_core0_memory_region: r5f-memory@a4100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa4100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa5000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss1_core1_memory_region: r5f-memory@a5100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa5100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss2_core0_dma_memory_region: r5f-dma-memory@a6000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa6000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss2_core0_memory_region: r5f-memory@a6100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa6100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		main_r5fss2_core1_dma_memory_region: r5f-dma-memory@a7000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa7000000 0x00 0x100000>;
+			no-map;
+		};
+
+		main_r5fss2_core1_memory_region: r5f-memory@a7100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa7100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		c71_0_dma_memory_region: c71-dma-memory@a8000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa8000000 0x00 0x100000>;
+			no-map;
+		};
+
+		c71_0_memory_region: c71-memory@a8100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa8100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		c71_1_dma_memory_region: c71-dma-memory@a9000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa9000000 0x00 0x100000>;
+			no-map;
+		};
+
+		c71_1_memory_region: c71-memory@a9100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xa9100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		c71_2_dma_memory_region: c71-dma-memory@aa000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xaa000000 0x00 0x100000>;
+			no-map;
+		};
+
+		c71_2_memory_region: c71-memory@aa100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xaa100000 0x00 0xf00000>;
+			no-map;
+		};
+
+		c71_3_dma_memory_region: c71-dma-memory@ab000000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xab000000 0x00 0x100000>;
+			no-map;
+		};
+
+		c71_3_memory_region: c71-memory@ab100000 {
+			compatible = "shared-dma-pool";
+			reg = <0x00 0xab100000 0x00 0xf00000>;
+			no-map;
+		};
+	};
+
+	evm_12v0: regulator-evm12v0 {
+		/* main supply */
+		compatible = "regulator-fixed";
+		regulator-name = "evm_12v0";
+		regulator-min-microvolt = <12000000>;
+		regulator-max-microvolt = <12000000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_3v3: regulator-vsys3v3 {
+		/* Output of LM5140 */
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_3v3";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		vin-supply = <&evm_12v0>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_5v0: regulator-vsys5v0 {
+		/* Output of LM5140 */
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_5v0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		vin-supply = <&evm_12v0>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vdd_mmc1: regulator-sd {
+		/* Output of TPS22918 */
+		compatible = "regulator-fixed";
+		regulator-name = "vdd_mmc1";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		enable-active-high;
+		vin-supply = <&vsys_3v3>;
+		gpio = <&exp2 2 GPIO_ACTIVE_HIGH>;
+	};
+
+	vdd_sd_dv: regulator-TLV71033 {
+		/* Output of TLV71033 */
+		compatible = "regulator-gpio";
+		regulator-name = "tlv71033";
+		pinctrl-names = "default";
+		pinctrl-0 = <&vdd_sd_dv_pins_default>;
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-boot-on;
+		vin-supply = <&vsys_5v0>;
+		gpios = <&main_gpio0 8 GPIO_ACTIVE_HIGH>;
+		states = <1800000 0x0>,
+			 <3300000 0x1>;
+	};
+
+	dp0_pwr_3v3: regulator-dp0-prw {
+		compatible = "regulator-fixed";
+		regulator-name = "dp0-pwr";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&exp4 0 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+	};
+
+	dp0: dp0-connector {
+		compatible = "dp-connector";
+		label = "DP0";
+		type = "full-size";
+		dp-pwr-supply = <&dp0_pwr_3v3>;
+
+		port {
+			dp0_connector_in: endpoint {
+				remote-endpoint = <&dp0_out>;
+			};
+		};
+	};
+
+	vsys_io_1v8: regulator-vsys-io-1v8 {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_io_1v8";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	vsys_io_1v2: regulator-vsys-io-1v2 {
+		compatible = "regulator-fixed";
+		regulator-name = "vsys_io_1v2";
+		regulator-min-microvolt = <1200000>;
+		regulator-max-microvolt = <1200000>;
+		regulator-always-on;
+		regulator-boot-on;
+	};
+
+	edp1_refclk: clock-edp1-refclk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+		clock-frequency = <19200000>;
+	};
+
+	dp1_pwr_3v3: regulator-dp1-prw {
+		compatible = "regulator-fixed";
+		regulator-name = "dp1-pwr";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		gpio = <&exp4 1 GPIO_ACTIVE_HIGH>; /* P1 - DP1_PWR_SW_EN */
+		enable-active-high;
+		regulator-always-on;
+	};
+
+	transceiver1: can-phy0 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&mcu_mcan0_gpio_pins_default>;
+		standby-gpios = <&wkup_gpio0 69 GPIO_ACTIVE_HIGH>;
+	};
+
+	transceiver2: can-phy1 {
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&mcu_mcan1_gpio_pins_default>;
+		standby-gpios = <&wkup_gpio0 2 GPIO_ACTIVE_HIGH>;
+	};
+
+	transceiver3: can-phy2 {
+		/* standby pin has been grounded by default */
+		compatible = "ti,tcan1042";
+		#phy-cells = <0>;
+		max-bitrate = <5000000>;
+	};
+};
+
+&wkup_pmx1 {
+	pmic_irq_pins_default: pmic-irq-pins-default {
+		pinctrl-single,pins = <
+			/* (G33) MCU_OSPI1_CSn1.WKUP_GPIO0_39 */
+			J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 7)
+		>;
+	};
+
+	mcu_fss0_ospi1_pins_default: mcu-fss0-ospi1-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (F32) MCU_OSPI1_CLK */
+			J784S4_WKUP_IOPAD(0x024, PIN_OUTPUT, 0) /* (G32) MCU_OSPI1_CSn0 */
+			J784S4_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (E35) MCU_OSPI1_D0 */
+			J784S4_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (D31) MCU_OSPI1_D1 */
+			J784S4_WKUP_IOPAD(0x01C, PIN_INPUT, 0) /* (G31) MCU_OSPI1_D2 */
+			J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (F33) MCU_OSPI1_D3 */
+			J784S4_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (F31) MCU_OSPI1_DQS */
+			J784S4_WKUP_IOPAD(0x00C, PIN_INPUT, 0) /* (C31) MCU_OSPI1_LBCLKO */
+		>;
+	};
+
+	mcu_fss0_ospi0_pins1_default: mcu-fss0-ospi0-pins1-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x004, PIN_OUTPUT, 6) /* (C32) MCU_OSPI0_ECC_FAIL */
+			J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 6) /* (B34) MCU_OSPI0_RESET_OUT0 */
+		>;
+	};
+};
+
+&wkup_pmx2 {
+	status = "okay";
+	wkup_i2c0_pins_default: wkup_i2c0_pins_default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x098, PIN_INPUT, 0) /* (N33) WKUP_I2C0_SCL */
+			J784S4_WKUP_IOPAD(0x09C, PIN_INPUT, 0) /* (N35) WKUP_I2C0_SDA */
+		>;
+	};
+
+	mcu_uart0_pins_default: mcu-uart0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x090, PIN_INPUT, 0) /* (H37) MCU_UART0_CTSn */
+			J784S4_WKUP_IOPAD(0x094, PIN_OUTPUT, 0) /* (K37) MCU_UART0_RTSn */
+			J784S4_WKUP_IOPAD(0x08C, PIN_INPUT, 0) /* (K38) MCU_UART0_RXD */
+			J784S4_WKUP_IOPAD(0x088, PIN_OUTPUT, 0) /* (J37) MCU_UART0_TXD */
+		>;
+	};
+
+	wkup_uart0_pins_default: wkup-uart0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x070, PIN_INPUT, 0) /* (E25) WKUP_UART0_CTSn */
+			J784S4_WKUP_IOPAD(0x074, PIN_OUTPUT, 0) /* (F28) WKUP_UART0_RTSn */
+			J784S4_WKUP_IOPAD(0x048, PIN_INPUT, 0) /* (K35) WKUP_UART0_RXD */
+			J784S4_WKUP_IOPAD(0x04c, PIN_OUTPUT, 0) /* (K34) WKUP_UART0_TXD */
+		>;
+	};
+	mcu_cpsw_pins_default: mcu-cpsw-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x02c, PIN_INPUT, 0) /* (A35) MCU_RGMII1_RD0 */
+			J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (B36) MCU_RGMII1_RD1 */
+			J784S4_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (C36) MCU_RGMII1_RD2 */
+			J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D36) MCU_RGMII1_RD3 */
+			J784S4_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (B37) MCU_RGMII1_RXC */
+			J784S4_WKUP_IOPAD(0x004, PIN_INPUT, 0) /* (C37) MCU_RGMII1_RX_CTL */
+			J784S4_WKUP_IOPAD(0x014, PIN_OUTPUT, 0) /* (D37) MCU_RGMII1_TD0 */
+			J784S4_WKUP_IOPAD(0x010, PIN_OUTPUT, 0) /* (D38) MCU_RGMII1_TD1 */
+			J784S4_WKUP_IOPAD(0x00c, PIN_OUTPUT, 0) /* (E37) MCU_RGMII1_TD2 */
+			J784S4_WKUP_IOPAD(0x008, PIN_OUTPUT, 0) /* (E38) MCU_RGMII1_TD3 */
+			J784S4_WKUP_IOPAD(0x018, PIN_OUTPUT, 0) /* (E36) MCU_RGMII1_TXC */
+			J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (C38) MCU_RGMII1_TX_CTL */
+		>;
+	};
+
+	mcu_mdio_pins_default: mcu-mdio-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x034, PIN_OUTPUT, 0) /* (A36) MCU_MDIO0_MDC */
+			J784S4_WKUP_IOPAD(0x030, PIN_INPUT, 0) /* (B35) MCU_MDIO0_MDIO */
+		>;
+	};
+
+	mcu_adc0_pins_default: mcu-adc0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x0cc, PIN_INPUT, 0) /* (P36) MCU_ADC0_AIN0 */
+			J784S4_WKUP_IOPAD(0x0d0, PIN_INPUT, 0) /* (V36) MCU_ADC0_AIN1 */
+			J784S4_WKUP_IOPAD(0x0d4, PIN_INPUT, 0) /* (T34) MCU_ADC0_AIN2 */
+			J784S4_WKUP_IOPAD(0x0d8, PIN_INPUT, 0) /* (T36) MCU_ADC0_AIN3 */
+			J784S4_WKUP_IOPAD(0x0dc, PIN_INPUT, 0) /* (P34) MCU_ADC0_AIN4 */
+			J784S4_WKUP_IOPAD(0x0e0, PIN_INPUT, 0) /* (R37) MCU_ADC0_AIN5 */
+			J784S4_WKUP_IOPAD(0x0e4, PIN_INPUT, 0) /* (R33) MCU_ADC0_AIN6 */
+			J784S4_WKUP_IOPAD(0x0e8, PIN_INPUT, 0) /* (V38) MCU_ADC0_AIN7 */
+		>;
+	};
+
+	mcu_adc1_pins_default: mcu-adc1-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x0ec, PIN_INPUT, 0) /* (Y38) MCU_ADC1_AIN0 */
+			J784S4_WKUP_IOPAD(0x0f0, PIN_INPUT, 0) /* (Y34) MCU_ADC1_AIN1 */
+			J784S4_WKUP_IOPAD(0x0f4, PIN_INPUT, 0) /* (V34) MCU_ADC1_AIN2 */
+			J784S4_WKUP_IOPAD(0x0f8, PIN_INPUT, 0) /* (W37) MCU_ADC1_AIN3 */
+			J784S4_WKUP_IOPAD(0x0fc, PIN_INPUT, 0) /* (AA37) MCU_ADC1_AIN4 */
+			J784S4_WKUP_IOPAD(0x100, PIN_INPUT, 0) /* (W33) MCU_ADC1_AIN5 */
+			J784S4_WKUP_IOPAD(0x104, PIN_INPUT, 0) /* (U33) MCU_ADC1_AIN6 */
+			J784S4_WKUP_IOPAD(0x108, PIN_INPUT, 0) /* (Y36) MCU_ADC1_AIN7 */
+		>;
+	};
+
+};
+
+&wkup_gpio0 {
+	status = "okay";
+};
+
+&wkup_gpio_intr {
+	status = "okay";
+};
+
+&wkup_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_i2c0_pins_default>;
+	clock-frequency = <400000>;
+	tps659413: pmic@48 {
+		compatible = "ti,tps6594-q1";
+		reg = <0x48>;
+		system-power-controller;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pmic_irq_pins_default>;
+		interrupt-parent = <&wkup_gpio0>;
+		interrupts = <39 IRQ_TYPE_EDGE_FALLING>;
+		ti,primary-pmic;
+
+		gpio-controller;
+		#gpio-cells = <2>;
+
+		buck12-supply = <&vsys_3v3>;
+		buck3-supply = <&vsys_3v3>;
+		buck4-supply = <&vsys_3v3>;
+		buck5-supply = <&vsys_3v3>;
+		ldo1-supply = <&vsys_3v3>;
+		ldo2-supply = <&vsys_3v3>;
+		ldo3-supply = <&vsys_3v3>;
+		ldo4-supply = <&vsys_3v3>;
+
+		regulators {
+			bucka12: buck12 {
+				regulator-name = "vdd_ddr_1v1";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			bucka3: buck3 {
+				regulator-name = "vdd_ram_0v85";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			bucka4: buck4 {
+				regulator-name = "vdd_io_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			bucka5: buck5 {
+				regulator-name = "vdd_mcu_0v85";
+				regulator-min-microvolt = <850000>;
+				regulator-max-microvolt = <850000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa1: ldo1 {
+				regulator-name = "vdd_mcuio_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa2: ldo2 {
+				regulator-name = "vdd_mcuio_3v3";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa3: ldo3 {
+				regulator-name = "vds_dll_0v8";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoa4: ldo4 {
+				regulator-name = "vda_mcu_1v8";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&main_pmx0 {
+	main_cpsw2g_pins_default: main-cpsw2g-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0b8, PIN_INPUT, 6) /* (AC34) MCASP1_ACLKX.RGMII1_RD0 */
+			J784S4_IOPAD(0x0a0, PIN_INPUT, 6) /* (AD34) MCASP0_AXR12.RGMII1_RD1 */
+			J784S4_IOPAD(0x0a4, PIN_INPUT, 6) /* (AJ36) MCASP0_AXR13.RGMII1_RD2 */
+			J784S4_IOPAD(0x0a8, PIN_INPUT, 6) /* (AF34) MCASP0_AXR14.RGMII1_RD3 */
+			J784S4_IOPAD(0x0b0, PIN_INPUT, 6) /* (AL33) MCASP1_AXR3.RGMII1_RXC */
+			J784S4_IOPAD(0x0ac, PIN_INPUT, 6) /* (AE34) MCASP0_AXR15.RGMII1_RX_CTL */
+			J784S4_IOPAD(0x08c, PIN_INPUT, 6) /* (AE35) MCASP0_AXR7.RGMII1_TD0 */
+			J784S4_IOPAD(0x090, PIN_INPUT, 6) /* (AC35) MCASP0_AXR8.RGMII1_TD1 */
+			J784S4_IOPAD(0x094, PIN_INPUT, 6) /* (AG35) MCASP0_AXR9.RGMII1_TD2 */
+			J784S4_IOPAD(0x098, PIN_INPUT, 6) /* (AH36) MCASP0_AXR10.RGMII1_TD3 */
+			J784S4_IOPAD(0x0b4, PIN_INPUT, 6) /* (AL34) MCASP1_AXR4.RGMII1_TXC */
+			J784S4_IOPAD(0x09c, PIN_INPUT, 6) /* (AF35) MCASP0_AXR11.RGMII1_TX_CTL */
+		>;
+	};
+
+	main_cpsw2g_mdio_pins_default: main-cpsw2g-mdio-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0c0, PIN_INPUT, 6) /* (AD38) MCASP1_AXR0.MDIO0_MDC */
+			J784S4_IOPAD(0x0bc, PIN_INPUT, 6) /* (AD33) MCASP1_AFSX.MDIO0_MDIO */
+		>;
+	};
+
+	main_uart8_pins_default: main-uart8-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x040, PIN_INPUT, 14) /* (AF37) MCASP0_AXR0.UART8_CTSn */
+			J784S4_IOPAD(0x044, PIN_OUTPUT, 14) /* (AG37) MCASP0_AXR1.UART8_RTSn */
+			J784S4_IOPAD(0x0d0, PIN_INPUT, 11) /* (AP38) SPI0_CS1.UART8_RXD */
+			J784S4_IOPAD(0x0d4, PIN_OUTPUT, 11) /* (AN38) SPI0_CLK.UART8_TXD */
+		>;
+	};
+
+	main_i2c0_pins_default: main-i2c0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0e0, PIN_INPUT_PULLUP, 0) /* (AN36) I2C0_SCL */
+			J784S4_IOPAD(0x0e4, PIN_INPUT_PULLUP, 0) /* (AP37) I2C0_SDA */
+		>;
+	};
+
+	main_i2c5_pins_default: main-i2c5-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x01c, PIN_INPUT, 8) /* (AG34) MCAN15_TX.I2C5_SCL */
+			J784S4_IOPAD(0x018, PIN_INPUT, 8) /* (AK36) MCAN14_RX.I2C5_SDA */
+		>;
+	};
+
+	main_mmc1_pins_default: main-mmc1-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x104, PIN_INPUT, 0) /* (AB38) MMC1_CLK */
+			J784S4_IOPAD(0x108, PIN_INPUT, 0) /* (AB36) MMC1_CMD */
+			J784S4_IOPAD(0x100, PIN_INPUT, 0) /* (No Pin) MMC1_CLKLB */
+			J784S4_IOPAD(0x0fc, PIN_INPUT, 0) /* (AA33) MMC1_DAT0 */
+			J784S4_IOPAD(0x0f8, PIN_INPUT, 0) /* (AB34) MMC1_DAT1 */
+			J784S4_IOPAD(0x0f4, PIN_INPUT, 0) /* (AA32) MMC1_DAT2 */
+			J784S4_IOPAD(0x0f0, PIN_INPUT, 0) /* (AC38) MMC1_DAT3 */
+			J784S4_IOPAD(0x0e8, PIN_INPUT, 8) /* (AR38) TIMER_IO0.MMC1_SDCD */
+		>;
+	};
+
+	vdd_sd_dv_pins_default: vdd-sd-dv-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x020, PIN_INPUT, 7) /* (AJ35) MCAN15_RX.GPIO0_8 */
+		>;
+	};
+
+	dp0_pins_default: dp0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0cc, PIN_INPUT, 12) /* (AM37) SPI0_CS0.DP0_HPD */
+		>;
+	};
+
+	main_i2c4_pins_default: main-i2c4-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x014, PIN_INPUT_PULLUP, 8) /* (AG33) MCAN14_TX.I2C4_SCL */
+			J784S4_IOPAD(0x010, PIN_INPUT_PULLUP, 8) /* (AH33) MCAN13_RX.I2C4_SDA */
+		>;
+	};
+
+	main_usbss0_pins_default: main-usbss0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x0ec, PIN_OUTPUT, 6) /* (AN37) TIMER_IO1.USB0_DRVVBUS */
+		>;
+	};
+
+	main_mcan16_pins_default: main-mcan16-default-pins {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x028, PIN_INPUT, 0) /* (AE33) MCAN16_RX */
+			J784S4_IOPAD(0x024, PIN_OUTPUT, 0) /* (AH34) MCAN16_TX */
+		>;
+	};
+};
+
+&wkup_pmx0 {
+	typec_dir_gpio_pins_default: typec-dir-gpio-pins-default {
+		pinctrl-single,pins = <
+			/* (A33) MCU_OSPI0_CSn1.WKUP_GPIO0_28 */
+			J784S4_WKUP_IOPAD(0x030, PIN_INPUT, 7)
+		>;
+	};
+	mcu_fss0_ospi0_pins_default: mcu-fss0-ospi0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x000, PIN_OUTPUT, 0) /* (E32) MCU_OSPI0_CLK */
+			J784S4_WKUP_IOPAD(0x02c, PIN_OUTPUT, 0) /* (A32) MCU_OSPI0_CSn0 */
+			J784S4_WKUP_IOPAD(0x00c, PIN_INPUT, 0) /* (B33) MCU_OSPI0_D0 */
+			J784S4_WKUP_IOPAD(0x010, PIN_INPUT, 0) /* (B32) MCU_OSPI0_D1 */
+			J784S4_WKUP_IOPAD(0x014, PIN_INPUT, 0) /* (C33) MCU_OSPI0_D2 */
+			J784S4_WKUP_IOPAD(0x018, PIN_INPUT, 0) /* (C35) MCU_OSPI0_D3 */
+			J784S4_WKUP_IOPAD(0x01c, PIN_INPUT, 0) /* (D33) MCU_OSPI0_D4 */
+			J784S4_WKUP_IOPAD(0x020, PIN_INPUT, 0) /* (D34) MCU_OSPI0_D5 */
+			J784S4_WKUP_IOPAD(0x024, PIN_INPUT, 0) /* (E34) MCU_OSPI0_D6 */
+			J784S4_WKUP_IOPAD(0x028, PIN_INPUT, 0) /* (E33) MCU_OSPI0_D7 */
+			J784S4_WKUP_IOPAD(0x008, PIN_INPUT, 0) /* (C34) MCU_OSPI0_DQS */
+		>;
+	};
+};
+
+&wkup_pmx2{
+	mcu_mcan0_pins_default: mcu-mcan0-default-pins {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x050, PIN_OUTPUT, 0) /* (K33) MCU_MCAN0_TX */
+			J784S4_WKUP_IOPAD(0x054, PIN_INPUT, 0) /* (F38) MCU_MCAN0_RX */
+		>;
+	};
+
+	mcu_mcan1_pins_default: mcu-mcan1-default-pins {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x068, PIN_OUTPUT, 0) /* (H35) WKUP_GPIO0_4.MCU_MCAN1_TX */
+			J784S4_WKUP_IOPAD(0x06c, PIN_INPUT, 0) /* (K36) WKUP_GPIO0_5.MCU_MCAN1_RX */
+		>;
+	};
+
+	mcu_mcan0_gpio_pins_default: mcu-mcan0-gpio-default-pins {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x040, PIN_INPUT, 7) /* (J38) MCU_SPI0_D1.WKUP_GPIO0_69 */
+		>;
+	};
+
+	mcu_mcan1_gpio_pins_default: mcu-mcan1-gpio-default-pins {
+		pinctrl-single,pins = <
+			J784S4_WKUP_IOPAD(0x060, PIN_INPUT, 7) /* (J35) WKUP_GPIO0_2 */
+		>;
+	};
+};
+
+&main_uart8 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_uart8_pins_default>;
+};
+
+&ufs_wrapper {
+	status = "okay";
+};
+
+&fss {
+	status = "okay";
+};
+
+&ospi0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_fss0_ospi0_pins_default>;
+
+	ospi0_nor: flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+		spi-max-frequency = <25000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <4>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "ospi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fc0000 {
+				label = "ospi.phypattern";
+				reg = <0x3fc0000 0x40000>;
+			};
+		};
+	};
+
+	ospi0_nand: nand@0 {
+		compatible = "spi-nand";
+		reg = <0x0>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+		spi-max-frequency = <25000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <2>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		status = "disabled";
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "ospi_nand.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "ospi_nand.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "ospi_nand.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "ospi_nand.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "ospi_nand.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@2000000 {
+				label = "ospi_nand.rootfs";
+				reg = <0x2000000 0x5fc0000>;
+			};
+
+			partition@7fc0000 {
+				label = "ospi_nand.phypattern";
+				reg = <0x7fc0000 0x40000>;
+			};
+		};
+	};
+};
+
+&ospi1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_fss0_ospi1_pins_default>;
+
+	flash@0{
+		compatible = "jedec,spi-nor";
+		reg = <0x0>;
+		spi-tx-bus-width = <1>;
+		spi-rx-bus-width = <4>;
+		spi-max-frequency = <40000000>;
+		cdns,tshsl-ns = <60>;
+		cdns,tsd2d-ns = <60>;
+		cdns,tchsh-ns = <60>;
+		cdns,tslch-ns = <60>;
+		cdns,read-delay = <2>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "qspi.tiboot3";
+				reg = <0x0 0x80000>;
+			};
+
+			partition@80000 {
+				label = "qspi.tispl";
+				reg = <0x80000 0x200000>;
+			};
+
+			partition@280000 {
+				label = "qspi.u-boot";
+				reg = <0x280000 0x400000>;
+			};
+
+			partition@680000 {
+				label = "qspi.env";
+				reg = <0x680000 0x40000>;
+			};
+
+			partition@6c0000 {
+				label = "qspi.env.backup";
+				reg = <0x6c0000 0x40000>;
+			};
+
+			partition@800000 {
+				label = "qspi.rootfs";
+				reg = <0x800000 0x37c0000>;
+			};
+
+			partition@3fc0000 {
+				label = "qspi.phypattern";
+				reg = <0x3fc0000 0x40000>;
+			};
+		};
+
+	};
+};
+
+&main_i2c0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c0_pins_default>;
+
+	clock-frequency = <400000>;
+
+	exp1: gpio@20 {
+		compatible = "ti,tca6416";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names = "PCIE1_2L_MODE_SEL", "PCIE1_4L_PERSTZ", "PCIE1_2L_RC_RSTZ",
+				  "PCIE1_2L_EP_RST_EN", "PCIE0_4L_MODE_SEL", "PCIE0_4L_PERSTZ",
+				  "PCIE0_4L_RC_RSTZ", "PCIE0_4L_EP_RST_EN", "PCIE1_4L_PRSNT#",
+				  "PCIE0_4L_PRSNT#", "CDCI1_OE1/OE4", "CDCI1_OE2/OE3",
+				  "AUDIO_MUX_SEL", "EXP_MUX2", "EXP_MUX3", "GESI_EXP_PHY_RSTZ";
+	};
+
+	exp2: gpio@22 {
+		compatible = "ti,tca6424";
+		reg = <0x22>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		gpio-line-names = "R_GPIO_RGMII1_RST", "ENET2_I2CMUX_SEL", "GPIO_USD_PWR_EN",
+				  "USBC_PWR_EN", "USBC_MODE_SEL1", "USBC_MODE_SEL0",
+				  "GPIO_LIN_EN", "R_CAN_STB", "CTRL_PM_I2C_OE#",
+				  "ENET2_EXP_PWRDN", "ENET2_EXP_SPARE2", "CDCI2_RSTZ",
+				  "USB2.0_MUX_SEL", "CANUART_MUX_SEL0", "CANUART_MUX2_SEL1",
+				  "CANUART_MUX1_SEL1", "ENET1_EXP_PWRDN", "ENET1_EXP_RESETZ",
+				  "ENET1_I2CMUX_SEL", "ENET1_EXP_SPARE2", "ENET2_EXP_RESETZ",
+				  "USER_INPUT1", "USER_LED1", "USER_LED2";
+	};
+};
+
+&main_sdhci0 {
+	/* eMMC */
+	status = "okay";
+	non-removable;
+	ti,driver-strength-ohm = <50>;
+	disable-wp;
+	no-mmc-hs400;
+};
+
+&main_sdhci1 {
+	/* SD card */
+	status = "okay";
+	pinctrl-0 = <&main_mmc1_pins_default>;
+	pinctrl-names = "default";
+	disable-wp;
+	vmmc-supply = <&vdd_mmc1>;
+	vqmmc-supply = <&vdd_sd_dv>;
+};
+
+&serdes0 {
+	status = "okay";
+	serdes0_pcie_link: phy@0 {
+		reg = <0>;
+		cdns,num-lanes = <2>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_PCIE>;
+		resets = <&serdes_wiz0 1>, <&serdes_wiz0 2>;
+	};
+
+	serdes0_usb_link: phy@3 {
+		reg = <3>;
+		cdns,num-lanes = <1>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_USB3>;
+		resets = <&serdes_wiz0 4>;
+	};
+};
+
+&serdes_wiz0 {
+	status = "okay";
+};
+
+&usb_serdes_mux {
+	idle-states = <0>; /* USB0 to SERDES lane 3 */
+};
+
+&usbss0 {
+	status = "okay";
+	pinctrl-0 = <&main_usbss0_pins_default>;
+	pinctrl-names = "default";
+	ti,vbus-divider;
+};
+
+&usb0 {
+	dr_mode = "otg";
+	maximum-speed = "super-speed";
+	phys = <&serdes0_usb_link>;
+	phy-names = "cdns3,usb3-phy";
+};
+
+&serdes1 {
+	status = "okay";
+	serdes1_pcie_link: phy@0 {
+		reg = <0>;
+		cdns,num-lanes = <2>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_PCIE>;
+		resets = <&serdes_wiz1 1>, <&serdes_wiz1 2>;
+	};
+};
+
+&serdes_wiz1 {
+	status = "okay";
+};
+
+&pcie0_rc {
+	status = "okay";
+	reset-gpios = <&exp1 6 GPIO_ACTIVE_HIGH>;
+	phys = <&serdes1_pcie_link>;
+	phy-names = "pcie-phy";
+};
+
+&pcie0_ep {
+	phys = <&serdes1_pcie_link>;
+	phy-names = "pcie-phy";
+};
+
+&pcie1_rc {
+	status = "okay";
+	num-lanes = <2>;
+	reset-gpios = <&exp1 2 GPIO_ACTIVE_HIGH>;
+	phys = <&serdes0_pcie_link>;
+	phy-names = "pcie-phy";
+};
+
+&pcie1_ep {
+	num-lanes = <2>;
+	phys = <&serdes0_pcie_link>;
+	phy-names = "pcie-phy";
+};
+
+&serdes_ln_ctrl {
+	idle-states = <J784S4_SERDES0_LANE0_PCIE1_LANE0>, <J784S4_SERDES0_LANE1_PCIE1_LANE1>,
+		<J784S4_SERDES0_LANE2_IP3_UNUSED>, <J784S4_SERDES0_LANE3_USB>,
+		<J784S4_SERDES1_LANE0_PCIE0_LANE0>, <J784S4_SERDES1_LANE1_PCIE0_LANE1>,
+		<J784S4_SERDES1_LANE2_PCIE0_LANE2>, <J784S4_SERDES1_LANE3_PCIE0_LANE3>,
+		<J784S4_SERDES2_LANE2_QSGMII_LANE1>, <J784S4_SERDES2_LANE3_QSGMII_LANE2>;
+};
+
+&main_gpio0 {
+	status = "okay";
+};
+
+&mcu_cpsw {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_cpsw_pins_default>;
+
+	cpts@3d000 {
+		/* Map HW4_TS_PUSH to GENF1 */
+		ti,pps = <3 1>;
+	};
+};
+
+&davinci_mdio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mdio_pins_default>;
+
+	mcu_phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+};
+
+&mcu_cpsw_port1 {
+	status = "okay";
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&mcu_phy0>;
+};
+
+&main_cpsw1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_cpsw2g_pins_default>;
+};
+
+&main_cpsw1_mdio {
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_cpsw2g_mdio_pins_default>;
+
+	main_phy0: ethernet-phy@0 {
+		reg = <0>;
+		ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+		ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+		ti,min-output-impedance;
+	};
+};
+
+&main_cpsw1_port1 {
+	status = "okay";
+	phy-mode = "rgmii-rxid";
+	phy-handle = <&main_phy0>;
+};
+
+&serdes_refclk {
+	clock-frequency = <100000000>;
+};
+
+&dss {
+	status = "okay";
+	assigned-clocks = <&k3_clks 218 2>,
+			  <&k3_clks 218 5>,
+			  <&k3_clks 218 14>,
+			  <&k3_clks 218 18>;
+	assigned-clock-parents = <&k3_clks 218 3>,
+				 <&k3_clks 218 7>,
+				 <&k3_clks 218 16>,
+				 <&k3_clks 218 22>;
+};
+
+&serdes_wiz4 {
+	status = "okay";
+};
+
+&serdes4 {
+	status = "okay";
+	serdes4_dp_link: phy@0 {
+		reg = <0>;
+		cdns,num-lanes = <4>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_DP>;
+		cdns,max-bit-rate = <2700>;
+		resets = <&serdes_wiz4 1>, <&serdes_wiz4 2>,
+			 <&serdes_wiz4 3>, <&serdes_wiz4 4>;
+	};
+};
+
+&mhdp {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&dp0_pins_default>;
+	phys = <&serdes4_dp_link>;
+	phy-names = "dpphy";
+};
+
+&dss_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@0 {
+		reg = <0>;
+		dpi0_out: endpoint {
+			remote-endpoint = <&dp0_in>;
+		};
+	};
+
+	port@2 {
+		reg = <2>;
+		dpi2_out: endpoint {
+			remote-endpoint = <&dsi0_in>;
+		};
+	};
+};
+
+&main_i2c4 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c4_pins_default>;
+	clock-frequency = <400000>;
+
+	exp4: gpio@20 {
+		compatible = "ti,tca6408";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	dsi_edp_bridge: dsi-edp-bridge@2c {
+		compatible = "ti,sn65dsi86";
+		reg = <0x2c>;
+
+		clock-names = "refclk";
+		clocks = <&edp1_refclk>;
+
+		enable-gpios = <&exp4 2 GPIO_ACTIVE_HIGH>;
+
+		vpll-supply = <&vsys_io_1v8>;
+		vccio-supply = <&vsys_io_1v8>;
+		vcca-supply = <&vsys_io_1v2>;
+		vcc-supply = <&vsys_io_1v2>;
+
+		dsi_edp_bridge_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				dp1_in: endpoint {
+					remote-endpoint = <&dsi0_out>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				dp1_out: endpoint {
+					remote-endpoint = <&dp1_panel_in>;
+				};
+			};
+		};
+
+		aux-bus {
+			panel {
+				compatible = "ti,panel-edp";
+				power-supply = <&dp1_pwr_3v3>;
+
+				port {
+					dp1_panel_in: endpoint {
+						remote-endpoint = <&dp1_out>;
+					};
+				};
+			};
+		};
+	};
+};
+
+&dsi0_ports {
+	port@0 {
+		reg = <0>;
+		dsi0_out: endpoint {
+			remote-endpoint = <&dp1_in>;
+		};
+	};
+
+	port@1 {
+		reg = <1>;
+		dsi0_in: endpoint {
+			remote-endpoint = <&dpi2_out>;
+		};
+	};
+};
+
+&main_i2c5 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_i2c5_pins_default>;
+	clock-frequency = <400000>;
+
+	exp5: gpio@20 {
+		compatible = "ti,tca6408";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+};
+
+&mailbox0_cluster0 {
+	status = "okay";
+	interrupts = <436>;
+
+	mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster1 {
+	status = "okay";
+	interrupts = <432>;
+
+	mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster2 {
+	status = "okay";
+	interrupts = <428>;
+
+	mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster3 {
+	status = "okay";
+	interrupts = <424>;
+
+	mbox_main_r5fss2_core0: mbox-main-r5fss2-core0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_main_r5fss2_core1: mbox-main-r5fss2-core1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster4 {
+	status = "okay";
+	interrupts = <420>;
+
+	mbox_c71_0: mbox-c71-0 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_c71_1: mbox-c71-1 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mailbox0_cluster5 {
+	status = "okay";
+	interrupts = <416>;
+
+	mbox_c71_2: mbox-c71-2 {
+		ti,mbox-rx = <0 0 0>;
+		ti,mbox-tx = <1 0 0>;
+	};
+
+	mbox_c71_3: mbox-c71-3 {
+		ti,mbox-rx = <2 0 0>;
+		ti,mbox-tx = <3 0 0>;
+	};
+};
+
+&mcu_r5fss0_core0 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
+	memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
+			<&mcu_r5fss0_core0_memory_region>;
+};
+
+&mcu_r5fss0_core1 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>;
+	memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
+			<&mcu_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss0_core0 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>;
+	memory-region = <&main_r5fss0_core0_dma_memory_region>,
+			<&main_r5fss0_core0_memory_region>;
+};
+
+&main_r5fss0_core1 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>;
+	memory-region = <&main_r5fss0_core1_dma_memory_region>,
+			<&main_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss1_core0 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>;
+	memory-region = <&main_r5fss1_core0_dma_memory_region>,
+			<&main_r5fss1_core0_memory_region>;
+};
+
+&main_r5fss1_core1 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>;
+	memory-region = <&main_r5fss1_core1_dma_memory_region>,
+			<&main_r5fss1_core1_memory_region>;
+};
+
+&main_r5fss2_core0 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster3 &mbox_main_r5fss2_core0>;
+	memory-region = <&main_r5fss2_core0_dma_memory_region>,
+			<&main_r5fss2_core0_memory_region>;
+};
+
+&main_r5fss2_core1 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster3 &mbox_main_r5fss2_core1>;
+	memory-region = <&main_r5fss2_core1_dma_memory_region>,
+			<&main_r5fss2_core1_memory_region>;
+};
+
+&c71_0 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster4 &mbox_c71_0>;
+	memory-region = <&c71_0_dma_memory_region>,
+			<&c71_0_memory_region>;
+};
+
+&c71_1 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster4 &mbox_c71_1>;
+	memory-region = <&c71_1_dma_memory_region>,
+			<&c71_1_memory_region>;
+};
+
+&c71_2 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster5 &mbox_c71_2>;
+	memory-region = <&c71_2_dma_memory_region>,
+			<&c71_2_memory_region>;
+};
+
+&c71_3 {
+	status = "okay";
+	mboxes = <&mailbox0_cluster5 &mbox_c71_3>;
+	memory-region = <&c71_3_dma_memory_region>,
+			<&c71_3_memory_region>;
+};
+
+&dp0_ports {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	port@0 {
+		reg = <0>;
+		dp0_in: endpoint {
+			remote-endpoint = <&dpi0_out>;
+		};
+	};
+
+	port@4 {
+		reg = <4>;
+		dp0_out: endpoint {
+			remote-endpoint = <&dp0_connector_in>;
+		};
+	};
+};
+
+&ti_csi2rx0 {
+	status = "okay";
+	/* MIPI-CSI Connector 0 */
+};
+
+&ti_csi2rx1 {
+	status = "okay";
+	/* MIPI-CSI Connector 0 */
+};
+
+&ti_csi2rx2 {
+	status = "okay";
+	/* MIPI-CSI Connector 1 */
+};
+
+&dphy_rx0 {
+	status = "okay";
+};
+
+&dphy_rx1 {
+	status = "okay";
+};
+
+&dphy_rx2 {
+	status = "okay";
+};
+
+&tscadc0 {
+	pinctrl-0 = <&mcu_adc0_pins_default>;
+	pinctrl-names = "default";
+	status = "okay";
+	adc {
+		ti,adc-channels = <0 1 2 3 4 5 6 7>;
+	};
+};
+
+&tscadc1 {
+	pinctrl-0 = <&mcu_adc1_pins_default>;
+	pinctrl-names = "default";
+	status = "okay";
+	adc {
+		ti,adc-channels = <0 1 2 3 4 5 6 7>;
+	};
+};
+
+&dphy_tx0 {
+	status = "okay";
+};
+
+&dsi0 {
+	status = "okay";
+};
+
+#define K3_TS_OFFSET(pa, val)  (0x4+(pa)*4) (0x10000 | val)
+
+&timesync_router {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_cpsw_cpts>;
+
+	/* Use Time Sync Router to map GENF1 input to HW4_TS_PUSH output */
+	mcu_cpsw_cpts: mcu-cpsw-cpts {
+		pinctrl-single,pins = <
+			/* pps [mcu cpsw cpts genf1] in17 -> out25 [mcu cpsw cpts hw4_push] */
+			K3_TS_OFFSET(25, 17)
+			>;
+	};
+};
+
+&wkup_uart0 {
+	status = "reserved";
+	pinctrl-names = "default";
+	pinctrl-0 = <&wkup_uart0_pins_default>;
+};
+
+&mcu_uart0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_uart0_pins_default>;
+};
+
+&mcu_mcan0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mcan0_pins_default>;
+	phys = <&transceiver1>;
+};
+
+&mcu_mcan1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mcu_mcan1_pins_default>;
+	phys = <&transceiver2>;
+};
+
+&main_mcan16 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&main_mcan16_pins_default>;
+	phys = <&transceiver3>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4-evm-quad-port-eth-exp1.dtso b/arch/arm64/boot/dts/ti/k3-j784s4-evm-quad-port-eth-exp1.dtso
--- a/arch/arm64/boot/dts/ti/k3-j784s4-evm-quad-port-eth-exp1.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm-quad-port-eth-exp1.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for CPSW9G in QSGMII mode using J7 Quad Port ETH EXP Add-On Ethernet Card with
+ * J7AHP board. The Add-On Ethernet Card has to be connected to ENET Expansion 1 slot on the
+ * board.
+ *
+ * Product Datasheet: https://www.ti.com/lit/ug/spruj74/spruj74.pdf
+ * Product Link: https://www.ti.com/tool/J721EXENETXPANEVM
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/mux/ti-serdes.h>
+#include <dt-bindings/phy/phy-cadence.h>
+#include <dt-bindings/phy/phy.h>
+
+#include "k3-pinctrl.h"
+
+&{/} {
+	aliases {
+		ethernet1 = "/bus@100000/ethernet@c000000/ethernet-ports/port@5";
+		ethernet2 = "/bus@100000/ethernet@c000000/ethernet-ports/port@6";
+		ethernet3 = "/bus@100000/ethernet@c000000/ethernet-ports/port@7";
+		ethernet4 = "/bus@100000/ethernet@c000000/ethernet-ports/port@8";
+	};
+};
+
+&main_cpsw0 {
+	status = "okay";
+};
+
+&main_cpsw0_port5 {
+	status = "okay";
+	phy-handle = <&cpsw9g_phy1>;
+	phy-mode = "qsgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 5>, <&serdes2_qsgmii_link>;
+	phy-names = "mac", "serdes";
+};
+
+&main_cpsw0_port6 {
+	status = "okay";
+	phy-handle = <&cpsw9g_phy2>;
+	phy-mode = "qsgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 6>, <&serdes2_qsgmii_link>;
+	phy-names = "mac", "serdes";
+};
+
+&main_cpsw0_port7 {
+	status = "okay";
+	phy-handle = <&cpsw9g_phy0>;
+	phy-mode = "qsgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 7>, <&serdes2_qsgmii_link>;
+	phy-names = "mac", "serdes";
+};
+
+&main_cpsw0_port8 {
+	status = "okay";
+	phy-handle = <&cpsw9g_phy3>;
+	phy-mode = "qsgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 8>, <&serdes2_qsgmii_link>;
+	phy-names = "mac", "serdes";
+};
+
+&main_cpsw0_mdio {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&mdio0_pins_default>;
+	bus_freq = <1000000>;
+	reset-gpios = <&exp2 17 GPIO_ACTIVE_LOW>;
+	reset-post-delay-us = <120000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	cpsw9g_phy0: ethernet-phy@16 {
+		reg = <16>;
+	};
+	cpsw9g_phy1: ethernet-phy@17 {
+		reg = <17>;
+	};
+	cpsw9g_phy2: ethernet-phy@18 {
+		reg = <18>;
+	};
+	cpsw9g_phy3: ethernet-phy@19 {
+		reg = <19>;
+	};
+};
+
+&exp2 {
+	/* Power-up ENET1 EXPANDER PHY. */
+	qsgmii-line-hog {
+		gpio-hog;
+		gpios = <16 GPIO_ACTIVE_HIGH>;
+		output-low;
+	};
+	/* Toggle MUX2 for MDIO lines */
+	mux-sel-hog {
+		gpio-hog;
+		gpios = <13 GPIO_ACTIVE_HIGH>, <14 GPIO_ACTIVE_HIGH>, <15 GPIO_ACTIVE_HIGH>;
+		output-high;
+	};
+};
+
+&main_pmx0 {
+	mdio0_pins_default: mdio0-pins-default {
+		pinctrl-single,pins = <
+			J784S4_IOPAD(0x05c, PIN_INPUT, 4) /* (AC36) MCASP2_AXR0.MDIO1_MDIO */
+			J784S4_IOPAD(0x058, PIN_INPUT, 4) /* (AE37) MCASP2_AFSX.MDIO1_MDC */
+		>;
+	};
+};
+
+&serdes_ln_ctrl {
+	idle-states = <J784S4_SERDES0_LANE0_PCIE1_LANE0>, <J784S4_SERDES0_LANE1_PCIE1_LANE1>,
+		      <J784S4_SERDES0_LANE2_IP3_UNUSED>, <J784S4_SERDES0_LANE3_USB>,
+		      <J784S4_SERDES1_LANE0_PCIE0_LANE0>, <J784S4_SERDES1_LANE1_PCIE0_LANE1>,
+		      <J784S4_SERDES1_LANE2_PCIE0_LANE2>, <J784S4_SERDES1_LANE3_PCIE0_LANE3>,
+		      <J784S4_SERDES2_LANE0_QSGMII_LANE5>, <J784S4_SERDES2_LANE1_QSGMII_LANE6>,
+		      <J784S4_SERDES2_LANE2_QSGMII_LANE7>, <J784S4_SERDES2_LANE3_QSGMII_LANE8>;
+};
+
+&serdes_wiz2 {
+	status = "okay";
+};
+
+&serdes2 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	serdes2_qsgmii_link: phy@0 {
+		reg = <2>;
+		cdns,num-lanes = <1>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_QSGMII>;
+		resets = <&serdes_wiz2 3>;
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4-evm-usxgmii-exp1-exp2.dtso b/arch/arm64/boot/dts/ti/k3-j784s4-evm-usxgmii-exp1-exp2.dtso
--- a/arch/arm64/boot/dts/ti/k3-j784s4-evm-usxgmii-exp1-exp2.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm-usxgmii-exp1-exp2.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for CPSW9G in dual port fixed-link USXGMII mode using ENET-1
+ * and ENET-2 Expansion slots of J784S4 EVM.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/mux/ti-serdes.h>
+#include <dt-bindings/phy/phy-cadence.h>
+#include <dt-bindings/phy/phy.h>
+
+&main_cpsw0 {
+	status = "okay";
+	pinctrl-names = "default";
+};
+
+&main_cpsw0_port1 {
+	status = "okay";
+	phy-mode = "usxgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 1>, <&serdes2_usxgmii_link>;
+	phy-names = "mac", "serdes";
+	fixed-link {
+		speed = <5000>;
+		full-duplex;
+	};
+};
+
+&main_cpsw0_port2 {
+	status = "okay";
+	phy-mode = "usxgmii";
+	mac-address = [00 00 00 00 00 00];
+	phys = <&cpsw0_phy_gmii_sel 2>, <&serdes2_usxgmii_link>;
+	phy-names = "mac", "serdes";
+	fixed-link {
+		speed = <5000>;
+		full-duplex;
+	};
+};
+
+&serdes_wiz2 {
+	status = "okay";
+	assigned-clock-parents = <&k3_clks 406 9>;
+};
+
+&serdes2 {
+	status = "okay";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	serdes2_usxgmii_link: phy@2 {
+		reg = <2>;
+		cdns,num-lanes = <2>;
+		#phy-cells = <0>;
+		cdns,phy-type = <PHY_TYPE_USXGMII>;
+		resets = <&serdes_wiz2 3>, <&serdes_wiz2 4>;
+	};
+};
+
+&serdes_ln_ctrl {
+	idle-states = <J784S4_SERDES0_LANE0_PCIE1_LANE0>, <J784S4_SERDES0_LANE1_PCIE1_LANE1>,
+		      <J784S4_SERDES0_LANE2_IP3_UNUSED>, <J784S4_SERDES0_LANE3_USB>,
+		      <J784S4_SERDES1_LANE0_PCIE0_LANE0>, <J784S4_SERDES1_LANE1_PCIE0_LANE1>,
+		      <J784S4_SERDES1_LANE2_PCIE0_LANE2>, <J784S4_SERDES1_LANE3_PCIE0_LANE3>,
+		      <J784S4_SERDES2_LANE0_IP2_UNUSED>, <J784S4_SERDES2_LANE1_IP2_UNUSED>,
+		      <J784S4_SERDES2_LANE2_QSGMII_LANE1>, <J784S4_SERDES2_LANE3_QSGMII_LANE2>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4-evm-virt-mac-client.dtso b/arch/arm64/boot/dts/ti/k3-j784s4-evm-virt-mac-client.dtso
--- a/arch/arm64/boot/dts/ti/k3-j784s4-evm-virt-mac-client.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-evm-virt-mac-client.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0
+/**
+ * DT Overlay for enabling CPSW Virt MAC Client driver in Linux to interface with EthFw via the
+ * Linux MAC Only port as well as the Switch Ports of the CPSW9G CPSW instance.
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/mux/ti-serdes.h>
+#include <dt-bindings/phy/phy-cadence.h>
+
+&{/} {
+	cpsw9g_virt_mac: main-r5fss-cpsw9g-virt-mac0 {
+		compatible = "ti,j721e-cpsw-virt-mac";
+		dma-coherent;
+		ti,psil-base = <0x4a00>;
+		ti,remote-name = "mpu_1_0_ethswitch-device-0";
+
+		dmas = <&main_udmap 0xca00>,
+		       <&main_udmap 0xca01>,
+		       <&main_udmap 0xca02>,
+		       <&main_udmap 0xca03>,
+		       <&main_udmap 0xca04>,
+		       <&main_udmap 0xca05>,
+		       <&main_udmap 0xca06>,
+		       <&main_udmap 0xca07>,
+		       <&main_udmap 0x4a00>;
+		dma-names = "tx0", "tx1", "tx2", "tx3",
+			    "tx4", "tx5", "tx6", "tx7",
+			    "rx";
+
+		virt-emac-port {
+			ti,label = "virt-port";
+			/* local-mac-address = [0 0 0 0 0 0]; */
+		};
+	};
+
+	cpsw9g_virt_maconly: main-r5fss-cpsw9g-virt-mac1 {
+		compatible = "ti,j721e-cpsw-virt-mac";
+		dma-coherent;
+		ti,psil-base = <0x4a00>;
+		ti,remote-name = "mpu_1_0_ethmac-device-1";
+
+		dmas = <&main_udmap 0xca00>,
+		       <&main_udmap 0xca01>,
+		       <&main_udmap 0xca02>,
+		       <&main_udmap 0xca03>,
+		       <&main_udmap 0xca04>,
+		       <&main_udmap 0xca05>,
+		       <&main_udmap 0xca06>,
+		       <&main_udmap 0xca07>,
+		       <&main_udmap 0x4a00>;
+		dma-names = "tx0", "tx1", "tx2", "tx3",
+			    "tx4", "tx5", "tx6", "tx7",
+			    "rx";
+
+		virt-emac-port {
+			ti,label = "virt-port";
+			/* local-mac-address = [0 0 0 0 0 0]; */
+		};
+	};
+};
+
+/* uart2 is assigned to cpsw9g eth-switch fw running on remote CPU core */
+&main_uart2 {
+	status = "reserved";
+};
+
+&serdes_ln_ctrl {
+	idle-states = <J784S4_SERDES0_LANE0_PCIE1_LANE0>, <J784S4_SERDES0_LANE1_PCIE1_LANE1>,
+		      <J784S4_SERDES0_LANE2_IP3_UNUSED>, <J784S4_SERDES0_LANE3_USB>,
+		      <J784S4_SERDES1_LANE0_PCIE0_LANE0>, <J784S4_SERDES1_LANE1_PCIE0_LANE1>,
+		      <J784S4_SERDES1_LANE2_PCIE0_LANE2>, <J784S4_SERDES1_LANE3_PCIE0_LANE3>,
+		      <J784S4_SERDES2_LANE0_IP2_UNUSED>, <J784S4_SERDES2_LANE1_IP2_UNUSED>,
+		      <J784S4_SERDES2_LANE2_QSGMII_LANE1>, <J784S4_SERDES2_LANE3_QSGMII_LANE2>;
+};
+
+&main_udmass_inta {
+	status = "okay";
+};
+
+&main_ringacc {
+	status = "okay";
+};
+
+&main_udmap {
+	status = "okay";
+};
+
+/* Reserve shared memory for inter-core network communication */
+&reserved_memory {
+	#address-cells = <2>;
+	#size-cells = <2>;
+
+	main_r5fss0_core0_shared_memory_queue_region:r5f-virtual-eth-queues@af000000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xaf000000 0x00 0x200000>;
+		no-map;
+	};
+
+	main_r5fss0_core0_shared_memory_bufpool_region:r5f-virtual-eth-buffers@af200000 {
+		compatible = "shared-dma-pool";
+		reg = <0x00 0xaf200000 0x00 0x1e00000>;
+		no-map;
+	};
+};
+
+&main_r5fss0_core0 {
+	memory-region = <&main_r5fss0_core0_dma_memory_region>,
+			<&main_r5fss0_core0_memory_region>,
+			<&main_r5fss0_core0_shared_memory_queue_region>,
+			<&main_r5fss0_core0_shared_memory_bufpool_region>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-main.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,2592 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for J784S4 SoC Family Main Domain peripherals
+ *
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+#include <dt-bindings/mux/mux.h>
+#include <dt-bindings/mux/ti-serdes.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/phy/phy-ti.h>
+
+/ {
+	serdes_refclk: serdes-refclk {
+		#clock-cells = <0>;
+		compatible = "fixed-clock";
+	};
+};
+
+&cbass_main {
+	msmc_ram: sram@70000000 {
+		compatible = "mmio-sram";
+		reg = <0x00 0x70000000 0x00 0x800000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x00 0x00 0x70000000 0x800000>;
+
+		atf-sram@0 {
+			reg = <0x00 0x20000>;
+		};
+
+		tifs-sram@1f0000 {
+			reg = <0x1f0000 0x10000>;
+		};
+
+		l3cache-sram@200000 {
+			reg = <0x200000 0x200000>;
+		};
+	};
+
+	scm_conf: syscon@100000 {
+		compatible = "ti,j721e-system-controller", "syscon", "simple-mfd";
+		reg = <0x00 0x00100000 0x00 0x1c000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x00 0x00 0x00100000 0x1c000>;
+
+		cpsw1_phy_gmii_sel: phy@4034 {
+			compatible = "ti,am654-phy-gmii-sel";
+			reg = <0x4034 0x4>;
+			#phy-cells = <1>;
+		};
+
+		cpsw0_phy_gmii_sel: phy@4044 {
+			compatible = "ti,j784s4-cpsw9g-phy-gmii-sel";
+			ti,qsgmii-main-ports = <7>, <7>;
+			reg = <0x4044 0x20>;
+			#phy-cells = <1>;
+		};
+
+		serdes_ln_ctrl: mux-controller@4080 {
+			compatible = "mmio-mux";
+			reg = <0x00004080 0x30>;
+			#mux-control-cells = <1>;
+			mux-reg-masks = <0x4080 0x3>, <0x4084 0x3>, /* SERDES0 lane0/1 select */
+					<0x4088 0x3>, <0x408c 0x3>, /* SERDES0 lane2/3 select */
+					<0x4090 0x3>, <0x4094 0x3>, /* SERDES1 lane0/1 select */
+					<0x4098 0x3>, <0x409c 0x3>, /* SERDES1 lane2/3 select */
+					<0x40a0 0x3>, <0x40a4 0x3>, /* SERDES2 lane0/1 select */
+					<0x40a8 0x3>, <0x40ac 0x3>; /* SERDES2 lane2/3 select */
+		};
+
+		usb_serdes_mux: mux-controller@4000 {
+			compatible = "mmio-mux";
+			reg = <0x4000 0x4>;
+			#mux-control-cells = <1>;
+			mux-reg-masks = <0x4000 0x8000000>; /* USB0 to SERDES0 lane 3 mux */
+		};
+
+		ehrpwm_tbclk: clock-controller@4140 {
+			compatible = "ti,am654-ehrpwm-tbclk", "syscon";
+			reg = <0x4140 0x18>;
+			#clock-cells = <1>;
+		};
+	};
+
+	main_ehrpwm0: pwm@3000000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3000000 0x00 0x100>;
+		power-domains = <&k3_pds 219 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 0>, <&k3_clks 219 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	main_ehrpwm1: pwm@3010000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3010000 0x00 0x100>;
+		power-domains = <&k3_pds 220 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 1>, <&k3_clks 220 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	main_ehrpwm2: pwm@3020000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3020000 0x00 0x100>;
+		power-domains = <&k3_pds 221 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 2>, <&k3_clks 221 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	main_ehrpwm3: pwm@3030000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3030000 0x00 0x100>;
+		power-domains = <&k3_pds 222 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 3>, <&k3_clks 222 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	main_ehrpwm4: pwm@3040000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3040000 0x00 0x100>;
+		power-domains = <&k3_pds 223 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 4>, <&k3_clks 223 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+	main_ehrpwm5: pwm@3050000 {
+		compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+		#pwm-cells = <3>;
+		reg = <0x00 0x3050000 0x00 0x100>;
+		power-domains = <&k3_pds 224 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&ehrpwm_tbclk 5>, <&k3_clks 224 0>;
+		clock-names = "tbclk", "fck";
+		status = "disabled";
+	};
+
+
+	gic500: interrupt-controller@1800000 {
+		compatible = "arm,gic-v3";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x00 0x01800000 0x00 0x200000>, /* GICD */
+		      <0x00 0x01900000 0x00 0x100000>, /* GICR */
+		      <0x00 0x6f000000 0x00 0x2000>,   /* GICC */
+		      <0x00 0x6f010000 0x00 0x1000>,   /* GICH */
+		      <0x00 0x6f020000 0x00 0x2000>;   /* GICV */
+
+		/* vcpumntirq: virtual CPU interface maintenance interrupt */
+		interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+		gic_its: msi-controller@1820000 {
+			compatible = "arm,gic-v3-its";
+			reg = <0x00 0x01820000 0x00 0x10000>;
+			socionext,synquacer-pre-its = <0x1000000 0x400000>;
+			msi-controller;
+			#msi-cells = <1>;
+		};
+	};
+
+	main_gpio_intr: interrupt-controller@a00000 {
+		compatible = "ti,sci-intr";
+		reg = <0x00 0x00a00000 0x00 0x800>;
+		ti,intr-trigger-type = <1>;
+		interrupt-controller;
+		interrupt-parent = <&gic500>;
+		#interrupt-cells = <1>;
+		ti,sci = <&sms>;
+		ti,sci-dev-id = <10>;
+		ti,interrupt-ranges = <8 392 56>;
+	};
+
+	main_pmx0: pinctrl@11c000 {
+		compatible = "pinctrl-single";
+		/* Proxy 0 addressing */
+		reg = <0x00 0x11c000 0x00 0x120>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
+
+	main_crypto: crypto@4e00000 {
+		compatible = "ti,j721e-sa2ul";
+		reg = <0x00 0x4e00000 0x00 0x1200>;
+		power-domains = <&k3_pds 369 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x00 0x04e00000 0x00 0x04e00000 0x00 0x30000>;
+
+		dmas = <&main_udmap 0xca40>, <&main_udmap 0x4a40>,
+				<&main_udmap 0x4a41>;
+		dma-names = "tx", "rx1", "rx2";
+
+		rng: rng@4e10000 {
+			compatible = "inside-secure,safexcel-eip76";
+			reg = <0x00 0x4e10000 0x00 0x7d>;
+			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+		};
+	};
+
+	main_uart0: serial@2800000 {
+		compatible = "ti,j721e-uart", "ti,am654-uart";
+		reg = <0x00 0x02800000 0x00 0x200>;
+		interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
+		current-speed = <115200>;
+		clocks = <&k3_clks 146 0>;
+		clock-names = "fclk";
+		power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_uart1: serial@2810000 {
+		compatible = "ti,j721e-uart", "ti,am654-uart";
+		reg = <0x00 0x02810000 0x00 0x200>;
+		interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
+		current-speed = <115200>;
+		clocks = <&k3_clks 388 0>;
+		clock-names = "fclk";
+		power-domains = <&k3_pds 388 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_uart2: serial@2820000 {
+		compatible = "ti,j721e-uart", "ti,am654-uart";
+		reg = <0x00 0x02820000 0x00 0x200>;
+		interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>;
+		current-speed = <115200>;
+		clocks = <&k3_clks 389 0>;
+		clock-names = "fclk";
+		power-domains = <&k3_pds 389 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_uart3: serial@2830000 {
+		compatible = "ti,j721e-uart", "ti,am654-uart";
+		reg = <0x00 0x02830000 0x00 0x200>;
+		interrupts = <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>;
+		current-speed = <115200>;
+		clocks = <&k3_clks 390 0>;
+		clock-names = "fclk";
+		power-domains = <&k3_pds 390 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_uart4: serial@2840000 {
+		compatible = "ti,j721e-uart", "ti,am654-uart";
+		reg = <0x00 0x02840000 0x00 0x200>;
+		interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>;
+		current-speed = <115200>;
+		clocks = <&k3_clks 391 0>;
+		clock-names = "fclk";
+		power-domains = <&k3_pds 391 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_uart5: serial@2850000 {
+		compatible = "ti,j721e-uart", "ti,am654-uart";
+		reg = <0x00 0x02850000 0x00 0x200>;
+		interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+		current-speed = <115200>;
+		clocks = <&k3_clks 392 0>;
+		clock-names = "fclk";
+		power-domains = <&k3_pds 392 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_uart6: serial@2860000 {
+		compatible = "ti,j721e-uart", "ti,am654-uart";
+		reg = <0x00 0x02860000 0x00 0x200>;
+		interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>;
+		current-speed = <115200>;
+		clocks = <&k3_clks 393 0>;
+		clock-names = "fclk";
+		power-domains = <&k3_pds 393 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_uart7: serial@2870000 {
+		compatible = "ti,j721e-uart", "ti,am654-uart";
+		reg = <0x00 0x02870000 0x00 0x200>;
+		interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>;
+		current-speed = <115200>;
+		clocks = <&k3_clks 394 0>;
+		clock-names = "fclk";
+		power-domains = <&k3_pds 394 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_uart8: serial@2880000 {
+		compatible = "ti,j721e-uart", "ti,am654-uart";
+		reg = <0x00 0x02880000 0x00 0x200>;
+		interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>;
+		current-speed = <115200>;
+		clocks = <&k3_clks 395 0>;
+		clock-names = "fclk";
+		power-domains = <&k3_pds 395 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_uart9: serial@2890000 {
+		compatible = "ti,j721e-uart", "ti,am654-uart";
+		reg = <0x00 0x02890000 0x00 0x200>;
+		interrupts = <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>;
+		current-speed = <115200>;
+		clocks = <&k3_clks 396 0>;
+		clock-names = "fclk";
+		power-domains = <&k3_pds 396 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	gpu: gpu@4e20000000 {
+		compatible = "ti,j721s2-pvr", "img,pvr-bxs64";
+		reg = <0x4e 0x20000000 0x00 0x80000>;
+		interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 181 1>;
+	};
+
+	main_gpio0: gpio@600000 {
+		compatible = "ti,j721e-gpio", "ti,keystone-gpio";
+		reg = <0x00 0x00600000 0x00 0x100>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&main_gpio_intr>;
+		interrupts = <145>, <146>, <147>, <148>, <149>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		ti,ngpio = <66>;
+		ti,davinci-gpio-unbanked = <0>;
+		power-domains = <&k3_pds 163 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 163 0>;
+		clock-names = "gpio";
+		status = "disabled";
+	};
+
+	main_gpio2: gpio@610000 {
+		compatible = "ti,j721e-gpio", "ti,keystone-gpio";
+		reg = <0x00 0x00610000 0x00 0x100>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&main_gpio_intr>;
+		interrupts = <154>, <155>, <156>, <157>, <158>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		ti,ngpio = <66>;
+		ti,davinci-gpio-unbanked = <0>;
+		power-domains = <&k3_pds 164 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 164 0>;
+		clock-names = "gpio";
+		status = "disabled";
+	};
+
+	main_gpio4: gpio@620000 {
+		compatible = "ti,j721e-gpio", "ti,keystone-gpio";
+		reg = <0x00 0x00620000 0x00 0x100>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&main_gpio_intr>;
+		interrupts = <163>, <164>, <165>, <166>, <167>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		ti,ngpio = <66>;
+		ti,davinci-gpio-unbanked = <0>;
+		power-domains = <&k3_pds 165 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 165 0>;
+		clock-names = "gpio";
+		status = "disabled";
+	};
+
+	main_gpio6: gpio@630000 {
+		compatible = "ti,j721e-gpio", "ti,keystone-gpio";
+		reg = <0x00 0x00630000 0x00 0x100>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&main_gpio_intr>;
+		interrupts = <172>, <173>, <174>, <175>, <176>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		ti,ngpio = <66>;
+		ti,davinci-gpio-unbanked = <0>;
+		power-domains = <&k3_pds 166 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 166 0>;
+		clock-names = "gpio";
+		status = "disabled";
+	};
+
+	usbss0: cdns-usb@4104000 {
+		compatible = "ti,j721e-usb";
+		reg = <0x00 0x4104000 0x00 0x100>;
+		dma-coherent;
+		power-domains = <&k3_pds 398 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 398 21>, <&k3_clks 398 2>;
+		clock-names = "ref", "lpm";
+		assigned-clocks = <&k3_clks 398 21>;    /* USB2_REFCLK */
+		assigned-clock-parents = <&k3_clks 398 22>; /* HFOSC0 */
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		status = "disabled";
+
+		usb0: usb@6000000 {
+			compatible = "cdns,usb3";
+			reg = <0x00 0x6000000 0x00 0x10000>,
+			      <0x00 0x6010000 0x00 0x10000>,
+			      <0x00 0x6020000 0x00 0x10000>;
+			reg-names = "otg", "xhci", "dev";
+			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,  /* irq.0 */
+				     <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>, /* irq.6 */
+				     <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>; /* otgirq.0 */
+			interrupt-names = "host",
+					  "peripheral",
+					  "otg";
+		};
+	};
+
+	main_i2c0: i2c@2000000 {
+		compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x02000000 0x00 0x100>;
+		interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&k3_clks 270 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 270 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_i2c1: i2c@2010000 {
+		compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x02010000 0x00 0x100>;
+		interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&k3_clks 271 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 271 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_i2c2: i2c@2020000 {
+		compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x02020000 0x00 0x100>;
+		interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&k3_clks 272 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 272 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_i2c3: i2c@2030000 {
+		compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x02030000 0x00 0x100>;
+		interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&k3_clks 273 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 273 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_i2c4: i2c@2040000 {
+		compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x02040000 0x00 0x100>;
+		interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&k3_clks 274 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 274 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_i2c5: i2c@2050000 {
+		compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x02050000 0x00 0x100>;
+		interrupts = <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&k3_clks 275 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 275 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	main_i2c6: i2c@2060000 {
+		compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x02060000 0x00 0x100>;
+		interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&k3_clks 276 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 276 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+    vpu0: video-codec@4210000 {
+		compatible = "cnm,cm521c-vpu";
+		reg = <0x00 0x4210000 0x00 0x10000>;
+		interrupts = <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 241 2>;
+		clock-names = "vcodec";
+		power-domains = <&k3_pds 241 TI_SCI_PD_EXCLUSIVE>;
+		sram = <&main_navss_sram>;
+		sram-size = <0x10000>;
+		operating-points-v2 = <&vpu_opp_table_0>;
+		vpu_opp_table_0: opp-table {
+			compatible = "operating-points-v2";
+			opp-20000000 {
+				opp-hz = /bits/ 64 <20000000>;
+			};
+
+			opp-100000000 {
+				opp-hz = /bits/ 64 <100000000>;
+			};
+
+			opp-200000000 {
+				opp-hz = /bits/ 64 <200000000>;
+			};
+
+			opp-400000000 {
+				opp-hz = /bits/ 64 <400000000>;
+			};
+
+			opp-600000000 {
+				opp-hz = /bits/ 64 <600000000>;
+			};
+		};
+	};
+
+    vpu1: video-codec@4220000 {
+		compatible = "cnm,cm521c-vpu";
+		reg = <0x00 0x4220000 0x00 0x10000>;
+		interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&k3_clks 242 2>;
+		clock-names = "vcodec";
+		power-domains = <&k3_pds 242 TI_SCI_PD_EXCLUSIVE>;
+		sram = <&main_navss_sram>;
+		sram-size = <0x10000>;
+		operating-points-v2 = <&vpu_opp_table_1>;
+		vpu_opp_table_1: opp-table {
+			compatible = "operating-points-v2";
+			opp-20000000 {
+				opp-hz = /bits/ 64 <20000000>;
+			};
+
+			opp-100000000 {
+				opp-hz = /bits/ 64 <100000000>;
+			};
+
+			opp-200000000 {
+				opp-hz = /bits/ 64 <200000000>;
+			};
+
+			opp-400000000 {
+				opp-hz = /bits/ 64 <400000000>;
+			};
+
+			opp-500000000 {
+				opp-hz = /bits/ 64 <600000000>;
+			};
+		};
+	};
+
+	main_sdhci0: mmc@4f80000 {
+		compatible = "ti,j721e-sdhci-8bit";
+		reg = <0x00 0x04f80000 0x00 0x1000>,
+		      <0x00 0x04f88000 0x00 0x400>;
+		interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 140 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 140 1>, <&k3_clks 140 2>;
+		clock-names =  "clk_ahb", "clk_xin";
+		assigned-clocks = <&k3_clks 140 2>;
+		assigned-clock-parents = <&k3_clks 140 3>;
+		bus-width = <8>;
+		ti,otap-del-sel-legacy = <0x0>;
+		ti,otap-del-sel-mmc-hs = <0x0>;
+		ti,otap-del-sel-ddr52 = <0x6>;
+		ti,otap-del-sel-hs200 = <0x8>;
+		ti,otap-del-sel-hs400 = <0x5>;
+		ti,itap-del-sel-legacy = <0x10>;
+		ti,itap-del-sel-mmc-hs = <0xa>;
+		ti,strobe-sel = <0x77>;
+		ti,clkbuf-sel = <0x7>;
+		ti,trm-icp = <0x8>;
+		mmc-ddr-1_8v;
+		mmc-hs200-1_8v;
+		mmc-hs400-1_8v;
+		dma-coherent;
+		status = "disabled";
+	};
+
+	main_sdhci1: mmc@4fb0000 {
+		compatible = "ti,j721e-sdhci-4bit";
+		reg = <0x00 0x04fb0000 0x00 0x1000>,
+		      <0x00 0x04fb8000 0x00 0x400>;
+		interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 141 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 141 3>, <&k3_clks 141 4>;
+		clock-names =  "clk_ahb", "clk_xin";
+		assigned-clocks = <&k3_clks 141 4>;
+		assigned-clock-parents = <&k3_clks 141 5>;
+		bus-width = <4>;
+		ti,otap-del-sel-legacy = <0x0>;
+		ti,otap-del-sel-sd-hs = <0x0>;
+		ti,otap-del-sel-sdr12 = <0xf>;
+		ti,otap-del-sel-sdr25 = <0xf>;
+		ti,otap-del-sel-sdr50 = <0xc>;
+		ti,otap-del-sel-sdr104 = <0x5>;
+		ti,otap-del-sel-ddr50 = <0xc>;
+		ti,itap-del-sel-legacy = <0x0>;
+		ti,itap-del-sel-sd-hs = <0x0>;
+		ti,itap-del-sel-sdr12 = <0x0>;
+		ti,itap-del-sel-sdr25 = <0x0>;
+		ti,clkbuf-sel = <0x7>;
+		ti,trm-icp = <0x8>;
+		dma-coherent;
+		status = "disabled";
+	};
+
+	serdes_wiz0: wiz@5060000 {
+		compatible = "ti,j784s4-wiz-10g";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		power-domains = <&k3_pds 404 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 404 2>, <&k3_clks 404 6>, <&serdes_refclk>, <&k3_clks 404 5>;
+		clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
+		assigned-clocks = <&k3_clks 404 6>;
+		assigned-clock-parents = <&k3_clks 404 10>;
+		num-lanes = <4>;
+		#reset-cells = <1>;
+		#clock-cells = <1>;
+		ranges = <0x5060000 0x00 0x5060000 0x10000>;
+
+		status = "disabled";
+
+		serdes0: serdes@5060000 {
+			compatible = "ti,j721e-serdes-10g";
+			reg = <0x05060000 0x010000>;
+			reg-names = "torrent_phy";
+			resets = <&serdes_wiz0 0>;
+			reset-names = "torrent_reset";
+			clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>,
+				 <&serdes_wiz0 TI_WIZ_PHY_EN_REFCLK>;
+			clock-names = "refclk", "phy_en_refclk";
+			assigned-clocks = <&serdes_wiz0 TI_WIZ_PLL0_REFCLK>,
+					  <&serdes_wiz0 TI_WIZ_PLL1_REFCLK>,
+					  <&serdes_wiz0 TI_WIZ_REFCLK_DIG>;
+			assigned-clock-parents = <&k3_clks 404 6>,
+						 <&k3_clks 404 6>,
+						 <&k3_clks 404 6>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			#clock-cells = <1>;
+
+			status = "disabled";
+		};
+	};
+
+	serdes_wiz1: wiz@5070000 {
+		compatible = "ti,j784s4-wiz-10g";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		power-domains = <&k3_pds 405 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 405 2>, <&k3_clks 405 6>, <&serdes_refclk>, <&k3_clks 405 5>;
+		clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
+		assigned-clocks = <&k3_clks 405 6>;
+		assigned-clock-parents = <&k3_clks 405 10>;
+		num-lanes = <4>;
+		#reset-cells = <1>;
+		#clock-cells = <1>;
+		ranges = <0x05070000 0x00 0x05070000 0x10000>;
+
+		status = "disabled";
+
+		serdes1: serdes@5070000 {
+			compatible = "ti,j721e-serdes-10g";
+			reg = <0x05070000 0x010000>;
+			reg-names = "torrent_phy";
+			resets = <&serdes_wiz1 0>;
+			reset-names = "torrent_reset";
+			clocks = <&serdes_wiz1 TI_WIZ_PLL0_REFCLK>,
+				 <&serdes_wiz1 TI_WIZ_PHY_EN_REFCLK>;
+			clock-names = "refclk", "phy_en_refclk";
+			assigned-clocks = <&serdes_wiz1 TI_WIZ_PLL0_REFCLK>,
+					  <&serdes_wiz1 TI_WIZ_PLL1_REFCLK>,
+					  <&serdes_wiz1 TI_WIZ_REFCLK_DIG>;
+			assigned-clock-parents = <&k3_clks 405 6>,
+						 <&k3_clks 405 6>,
+						 <&k3_clks 405 6>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			#clock-cells = <1>;
+
+			status = "disabled";
+		};
+	};
+
+	serdes_wiz2: wiz@5020000 {
+		compatible = "ti,j784s4-wiz-10g";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		power-domains = <&k3_pds 406 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 406 2>, <&k3_clks 406 6>, <&serdes_refclk>, <&k3_clks 406 5>;
+		clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
+		assigned-clocks = <&k3_clks 406 6>;
+		assigned-clock-parents = <&k3_clks 406 10>;
+		num-lanes = <4>;
+		#reset-cells = <1>;
+		#clock-cells = <1>;
+		ranges = <0x05020000 0x00 0x05020000 0x10000>;
+
+		status = "disabled";
+
+		serdes2: serdes@5020000 {
+			compatible = "ti,j721e-serdes-10g";
+			reg = <0x05020000 0x010000>;
+			reg-names = "torrent_phy";
+			resets = <&serdes_wiz2 0>;
+			reset-names = "torrent_reset";
+			clocks = <&serdes_wiz2 TI_WIZ_PLL0_REFCLK>,
+				 <&serdes_wiz2 TI_WIZ_PHY_EN_REFCLK>;
+			clock-names = "refclk", "phy_en_refclk";
+			assigned-clocks = <&serdes_wiz2 TI_WIZ_PLL0_REFCLK>,
+					  <&serdes_wiz2 TI_WIZ_PLL1_REFCLK>,
+					  <&serdes_wiz2 TI_WIZ_REFCLK_DIG>;
+			assigned-clock-parents = <&k3_clks 406 6>,
+						 <&k3_clks 406 6>,
+						 <&k3_clks 406 6>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			#clock-cells = <1>;
+
+			status = "disabled";
+		};
+	};
+
+	serdes_wiz4: wiz@5050000 {
+		compatible = "ti,j784s4-wiz-10g";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		power-domains = <&k3_pds 407 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 407 2>, <&k3_clks 407 6>, <&serdes_refclk>, <&k3_clks 407 5>;
+		clock-names = "fck", "core_ref_clk", "ext_ref_clk", "core_ref1_clk";
+		assigned-clocks = <&k3_clks 407 6>;
+		assigned-clock-parents = <&k3_clks 407 10>;
+		num-lanes = <4>;
+		#reset-cells = <1>;
+		#clock-cells = <1>;
+		ranges = <0x05050000 0x00 0x05050000 0x10000>,
+			 <0xa030a00 0x00 0xa030a00 0x40>; /* DPTX PHY */
+
+		status = "disabled";
+
+		serdes4: serdes@5050000 {
+			/*
+			 * Note: we also map DPTX PHY registers as the Torrent
+			 * needs to manage those.
+			 */
+			compatible = "ti,j721e-serdes-10g";
+			reg = <0x05050000 0x010000>,
+			      <0x0a030a00 0x40>; /* DPTX PHY */
+			reg-names = "torrent_phy";
+			resets = <&serdes_wiz4 0>;
+			reset-names = "torrent_reset";
+			clocks = <&serdes_wiz4 TI_WIZ_PLL0_REFCLK>,
+				 <&serdes_wiz4 TI_WIZ_PHY_EN_REFCLK>;
+			clock-names = "refclk", "phy_en_refclk";
+			assigned-clocks = <&serdes_wiz4 TI_WIZ_PLL0_REFCLK>,
+					  <&serdes_wiz4 TI_WIZ_PLL1_REFCLK>,
+					  <&serdes_wiz4 TI_WIZ_REFCLK_DIG>;
+			assigned-clock-parents = <&k3_clks 407 6>,
+						 <&k3_clks 407 6>,
+						 <&k3_clks 407 6>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			#clock-cells = <1>;
+
+			status = "disabled";
+		};
+	};
+
+	main_navss: bus@30000000 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x00 0x30000000 0x00 0x30000000 0x00 0x0c400000>;
+		ti,sci-dev-id = <280>;
+		dma-coherent;
+		dma-ranges;
+
+		main_navss_sram: navss-sram@30000000{
+			compatible = "mmio-sram";
+			reg = <0x00 0x30000000 0x00 0x10000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0x00 0x30000000 0x10000>;
+		};
+
+		main_navss_intr: interrupt-controller@310e0000 {
+			compatible = "ti,sci-intr";
+			reg = <0x00 0x310e0000 0x00 0x4000>;
+			ti,intr-trigger-type = <4>;
+			interrupt-controller;
+			interrupt-parent = <&gic500>;
+			#interrupt-cells = <1>;
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <283>;
+			ti,interrupt-ranges = <0 64 64>,
+					      <64 448 64>,
+					      <128 672 64>;
+		};
+
+		main_udmass_inta: msi-controller@33d00000 {
+			compatible = "ti,sci-inta";
+			reg = <0x00 0x33d00000 0x00 0x100000>;
+			interrupt-controller;
+			#interrupt-cells = <0>;
+			interrupt-parent = <&main_navss_intr>;
+			msi-controller;
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <321>;
+			ti,interrupt-ranges = <0 0 256>;
+			ti,unmapped-event-sources = <&main_bcdma_csi>;
+		};
+
+		secure_proxy_main: mailbox@32c00000 {
+			compatible = "ti,am654-secure-proxy";
+			#mbox-cells = <1>;
+			reg-names = "target_data", "rt", "scfg";
+			reg = <0x00 0x32c00000 0x00 0x100000>,
+			      <0x00 0x32400000 0x00 0x100000>,
+			      <0x00 0x32800000 0x00 0x100000>;
+			interrupt-names = "rx_011";
+			interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		hwspinlock: hwlock@30e00000 {
+			compatible = "ti,am654-hwspinlock";
+			reg = <0x00 0x30e00000 0x00 0x1000>;
+			#hwlock-cells = <1>;
+		};
+
+		mailbox0_cluster0: mailbox@31f80000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f80000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox0_cluster1: mailbox@31f81000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f81000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox0_cluster2: mailbox@31f82000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f82000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox0_cluster3: mailbox@31f83000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f83000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox0_cluster4: mailbox@31f84000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f84000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox0_cluster5: mailbox@31f85000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f85000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox0_cluster6: mailbox@31f86000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f86000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox0_cluster7: mailbox@31f87000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f87000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox0_cluster8: mailbox@31f88000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f88000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox0_cluster9: mailbox@31f89000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f89000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox0_cluster10: mailbox@31f8a000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f8a000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox0_cluster11: mailbox@31f8b000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f8b000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox1_cluster0: mailbox@31f90000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f90000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox1_cluster1: mailbox@31f91000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f91000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox1_cluster2: mailbox@31f92000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f92000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox1_cluster3: mailbox@31f93000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f93000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox1_cluster4: mailbox@31f94000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f94000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox1_cluster5: mailbox@31f95000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f95000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox1_cluster6: mailbox@31f96000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f96000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox1_cluster7: mailbox@31f97000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f97000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox1_cluster8: mailbox@31f98000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f98000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox1_cluster9: mailbox@31f99000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f99000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox1_cluster10: mailbox@31f9a000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f9a000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		mailbox1_cluster11: mailbox@31f9b000 {
+			compatible = "ti,am654-mailbox";
+			reg = <0x00 0x31f9b000 0x00 0x200>;
+			#mbox-cells = <1>;
+			ti,mbox-num-users = <4>;
+			ti,mbox-num-fifos = <16>;
+			interrupt-parent = <&main_navss_intr>;
+			status = "disabled";
+		};
+
+		main_ringacc: ringacc@3c000000 {
+			compatible = "ti,am654-navss-ringacc";
+			reg = <0x00 0x3c000000 0x00 0x400000>,
+			      <0x00 0x38000000 0x00 0x400000>,
+			      <0x00 0x31120000 0x00 0x100>,
+			      <0x00 0x33000000 0x00 0x40000>;
+			reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target";
+			ti,num-rings = <1024>;
+			ti,sci-rm-range-gp-rings = <0x1>;
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <315>;
+			msi-parent = <&main_udmass_inta>;
+		};
+
+		main_udmap: dma-controller@31150000 {
+			compatible = "ti,j721e-navss-main-udmap";
+			reg = <0x00 0x31150000 0x00 0x100>,
+			      <0x00 0x34000000 0x00 0x80000>,
+			      <0x00 0x35000000 0x00 0x200000>;
+			reg-names = "gcfg", "rchanrt", "tchanrt";
+			msi-parent = <&main_udmass_inta>;
+			#dma-cells = <1>;
+
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <319>;
+			ti,ringacc = <&main_ringacc>;
+
+			ti,sci-rm-range-tchan = <0x0d>, /* TX_CHAN */
+						<0x0f>, /* TX_HCHAN */
+						<0x10>; /* TX_UHCHAN */
+			ti,sci-rm-range-rchan = <0x0a>, /* RX_CHAN */
+						<0x0b>, /* RX_HCHAN */
+						<0x0c>; /* RX_UHCHAN */
+			ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */
+		};
+
+		main_bcdma_csi: dma-controller@311a0000 {
+			compatible = "ti,j721s2-dmss-bcdma-csi";
+			reg = <0x00 0x311a0000 0x00 0x100>,
+				<0x00 0x35d00000 0x00 0x20000>,
+				<0x00 0x35c00000 0x00 0x10000>,
+				<0x00 0x35e00000 0x00 0x80000>;
+			reg-names = "gcfg", "rchanrt", "tchanrt", "ringrt";
+			msi-parent = <&main_udmass_inta>;
+			#dma-cells = <3>;
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <281>;
+			ti,sci-rm-range-rchan = <0x21>;
+			ti,sci-rm-range-tchan = <0x22>;
+		};
+
+		cpts@310d0000 {
+			compatible = "ti,j721e-cpts";
+			reg = <0x00 0x310d0000 0x00 0x400>;
+			reg-names = "cpts";
+			clocks = <&k3_clks 282 0>;
+			clock-names = "cpts";
+			assigned-clocks = <&k3_clks 62 3>; /* CPTS_RFT_CLK */
+			assigned-clock-parents = <&k3_clks 62 5>; /* MAIN_0_HSDIV6_CLK */
+			interrupts-extended = <&main_navss_intr 391>;
+			interrupt-names = "cpts";
+			ti,cpts-periodic-outputs = <6>;
+			ti,cpts-ext-ts-inputs = <8>;
+		};
+	};
+
+	main_cpsw0: ethernet@c000000 {
+		compatible = "ti,j784s4-cpswxg-nuss";
+		reg = <0x00 0xc000000 0x00 0x200000>;
+		reg-names = "cpsw_nuss";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x00 0x00 0x00 0xc000000 0x00 0x200000>;
+		dma-coherent;
+		clocks = <&k3_clks 64 0>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 64 TI_SCI_PD_EXCLUSIVE>;
+
+		dmas = <&main_udmap 0xca00>,
+		       <&main_udmap 0xca01>,
+		       <&main_udmap 0xca02>,
+		       <&main_udmap 0xca03>,
+		       <&main_udmap 0xca04>,
+		       <&main_udmap 0xca05>,
+		       <&main_udmap 0xca06>,
+		       <&main_udmap 0xca07>,
+		       <&main_udmap 0x4a00>;
+		dma-names = "tx0", "tx1", "tx2", "tx3",
+			    "tx4", "tx5", "tx6", "tx7",
+			    "rx";
+
+		status = "disabled";
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			main_cpsw0_port1: port@1 {
+				reg = <1>;
+				label = "port1";
+				ti,mac-only;
+				status = "disabled";
+			};
+
+			main_cpsw0_port2: port@2 {
+				reg = <2>;
+				label = "port2";
+				ti,mac-only;
+				status = "disabled";
+			};
+
+			main_cpsw0_port3: port@3 {
+				reg = <3>;
+				label = "port3";
+				ti,mac-only;
+				status = "disabled";
+			};
+
+			main_cpsw0_port4: port@4 {
+				reg = <4>;
+				label = "port4";
+				ti,mac-only;
+				status = "disabled";
+			};
+
+			main_cpsw0_port5: port@5 {
+				reg = <5>;
+				label = "port5";
+				status = "disabled";
+			};
+
+			main_cpsw0_port6: port@6 {
+				reg = <6>;
+				label = "port6";
+				status = "disabled";
+			};
+
+			main_cpsw0_port7: port@7 {
+				reg = <7>;
+				label = "port7";
+				status = "disabled";
+			};
+
+			main_cpsw0_port8: port@8 {
+				reg = <8>;
+				label = "port8";
+				status = "disabled";
+			};
+		};
+
+		main_cpsw0_mdio: mdio@f00 {
+			compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+			reg = <0x00 0xf00 0x00 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&k3_clks 64 0>;
+			clock-names = "fck";
+			bus_freq = <1000000>;
+			status = "disabled";
+		};
+
+		cpts@3d000 {
+			compatible = "ti,am65-cpts";
+			reg = <0x00 0x3d000 0x00 0x400>;
+			clocks = <&k3_clks 64 3>;
+			clock-names = "cpts";
+			interrupts-extended = <&gic500 GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "cpts";
+			ti,cpts-ext-ts-inputs = <4>;
+			ti,cpts-periodic-outputs = <2>;
+		};
+	};
+
+	main_cpsw1: ethernet@c200000 {
+		compatible = "ti,j721e-cpsw-nuss";
+		reg = <0x00 0xc200000 0x00 0x200000>;
+		reg-names = "cpsw_nuss";
+		ranges = <0x00 0x00 0x00 0xc200000 0x00 0x200000>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		dma-coherent;
+		clocks = <&k3_clks 62 0>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 62 TI_SCI_PD_EXCLUSIVE>;
+
+		dmas = <&main_udmap 0xc640>,
+		       <&main_udmap 0xc641>,
+		       <&main_udmap 0xc642>,
+		       <&main_udmap 0xc643>,
+		       <&main_udmap 0xc644>,
+		       <&main_udmap 0xc645>,
+		       <&main_udmap 0xc646>,
+		       <&main_udmap 0xc647>,
+		       <&main_udmap 0x4640>;
+		dma-names = "tx0", "tx1", "tx2", "tx3",
+			    "tx4", "tx5", "tx6", "tx7",
+			    "rx";
+
+		status = "disabled";
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			main_cpsw1_port1: port@1 {
+				reg = <1>;
+				label = "port1";
+				phys = <&cpsw1_phy_gmii_sel 1>;
+				ti,mac-only;
+				status = "disabled";
+			};
+		};
+
+		main_cpsw1_mdio: mdio@f00 {
+			compatible = "ti,cpsw-mdio", "ti,davinci_mdio";
+			reg = <0x00 0xf00 0x00 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&k3_clks 62 0>;
+			clock-names = "fck";
+			bus_freq = <1000000>;
+		};
+
+		cpts@3d000 {
+			compatible = "ti,am65-cpts";
+			reg = <0x00 0x3d000 0x00 0x400>;
+			clocks = <&k3_clks 62 3>;
+			clock-names = "cpts";
+			interrupts-extended = <&gic500 GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "cpts";
+			ti,cpts-ext-ts-inputs = <4>;
+			ti,cpts-periodic-outputs = <2>;
+		};
+	};
+
+	pcie0_rc: pcie@2900000 {
+		compatible = "ti,j784s4-pcie-host";
+		reg = <0x00 0x02900000 0x00 0x1000>,
+		      <0x00 0x02907000 0x00 0x400>,
+		      <0x00 0x0d000000 0x00 0x00800000>,
+		      <0x00 0x10000000 0x00 0x00001000>;
+		reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
+		interrupt-names = "link_state";
+		interrupts = <GIC_SPI 318 IRQ_TYPE_EDGE_RISING>;
+		device_type = "pci";
+		ti,syscon-pcie-ctrl = <&scm_conf 0x4070>;
+		max-link-speed = <3>;
+		num-lanes = <4>;
+		power-domains = <&k3_pds 332 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 332 0>;
+		clock-names = "fck";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		bus-range = <0x0 0xff>;
+		vendor-id = <0x104c>;
+		device-id = <0xb00d>;
+		msi-map = <0x0 &gic_its 0x0 0x10000>;
+		dma-coherent;
+		ranges = <0x01000000 0x0 0x10001000 0x0 0x10001000 0x0 0x0010000>,
+			 <0x02000000 0x0 0x10011000 0x0 0x10011000 0x0 0x7fef000>;
+		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie0_intc 0>,
+				<0 0 0 2 &pcie0_intc 0>,
+				<0 0 0 3 &pcie0_intc 0>,
+				<0 0 0 4 &pcie0_intc 0>;
+		status = "disabled";
+
+		pcie0_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 312 IRQ_TYPE_EDGE_RISING>;
+		};
+	};
+
+	pcie0_ep: pcie-ep@2900000 {
+		compatible = "ti,j784s4-pcie-ep";
+		reg = <0x00 0x02900000 0x00 0x1000>,
+		      <0x00 0x02907000 0x00 0x400>,
+		      <0x00 0x0d000000 0x00 0x00800000>,
+		      <0x00 0x10000000 0x00 0x08000000>;
+		reg-names = "intd_cfg", "user_cfg", "reg", "mem";
+		interrupt-names = "link_state";
+		interrupts = <GIC_SPI 318 IRQ_TYPE_EDGE_RISING>;
+		ti,syscon-pcie-ctrl = <&scm_conf 0x4070>;
+		max-link-speed = <3>;
+		num-lanes = <4>;
+		power-domains = <&k3_pds 332 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 332 0>;
+		clock-names = "fck";
+		max-functions = /bits/ 8 <6>;
+		max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>;
+		dma-coherent;
+		status = "disabled";
+	};
+
+	pcie1_rc: pcie@2910000 {
+		compatible = "ti,j784s4-pcie-host";
+		reg = <0x00 0x02910000 0x00 0x1000>,
+		      <0x00 0x02917000 0x00 0x400>,
+		      <0x00 0x0d800000 0x00 0x00800000>,
+		      <0x00 0x18000000 0x00 0x00001000>;
+		reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
+		interrupt-names = "link_state";
+		interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
+		device_type = "pci";
+		ti,syscon-pcie-ctrl = <&scm_conf 0x4074>;
+		ti,syscon-pcie-refclk-out = <&scm_conf 0x9008 0x900c 0x18090 0x8074 0x1>;
+		max-link-speed = <3>;
+		num-lanes = <4>;
+		power-domains = <&k3_pds 333 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 333 0>;
+		clock-names = "fck";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		bus-range = <0x0 0xff>;
+		vendor-id = <0x104c>;
+		device-id = <0xb013>;
+		msi-map = <0x0 &gic_its 0x10000 0x10000>;
+		dma-coherent;
+		ranges = <0x01000000 0x0 0x18001000  0x00 0x18001000  0x0 0x0010000>,
+			 <0x02000000 0x0 0x18011000  0x00 0x18011000  0x0 0x7fef000>;
+		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie1_intc 0>,
+				<0 0 0 2 &pcie1_intc 0>,
+				<0 0 0 3 &pcie1_intc 0>,
+				<0 0 0 4 &pcie1_intc 0>;
+		status = "disabled";
+
+		pcie1_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 324 IRQ_TYPE_EDGE_RISING>;
+		};
+	};
+
+	pcie1_ep: pcie-ep@2910000 {
+		compatible = "ti,j784s4-pcie-ep";
+		reg = <0x00 0x02910000 0x00 0x1000>,
+		      <0x00 0x02917000 0x00 0x400>,
+		      <0x00 0x0d800000 0x00 0x00800000>,
+		      <0x00 0x18000000 0x00 0x08000000>;
+		reg-names = "intd_cfg", "user_cfg", "reg", "mem";
+		interrupt-names = "link_state";
+		interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
+		ti,syscon-pcie-ctrl = <&scm_conf 0x4074>;
+		max-link-speed = <3>;
+		num-lanes = <4>;
+		power-domains = <&k3_pds 333 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 333 0>;
+		clock-names = "fck";
+		max-functions = /bits/ 8 <6>;
+		max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>;
+		dma-coherent;
+		status = "disabled";
+	};
+
+	pcie3_rc: pcie@2930000 {
+		compatible = "ti,j784s4-pcie-host";
+		reg = <0x00 0x02930000 0x00 0x1000>,
+			<0x00 0x02937000 0x00 0x400>,
+			<0x00 0x0e800000 0x00 0x00800000>,
+			<0x44 0x10000000 0x00 0x00001000>;
+		reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
+		interrupt-names = "link_state";
+		interrupts = <GIC_SPI 354 IRQ_TYPE_EDGE_RISING>;
+		device_type = "pci";
+		ti,syscon-pcie-ctrl = <&scm_conf 0x407c>;
+		max-link-speed = <3>;
+		num-lanes = <4>;
+		power-domains = <&k3_pds 335 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 335 0>;
+		clock-names = "fck";
+		#address-cells = <3>;
+		#size-cells = <2>;
+		bus-range = <0x0 0xff>;
+		vendor-id = <0x104c>;
+		device-id = <0xb00d>;
+		msi-map = <0x0 &gic_its 0x30000 0x10000>;
+		dma-coherent;
+		ranges = <0x01000000 0x0 0x00001000 0x44 0x10001000 0x0 0x0010000>,
+			<0x02000000 0x0 0x00011000 0x44 0x10011000 0x0 0x7fef000>;
+		dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0 0 0 7>;
+		interrupt-map = <0 0 0 1 &pcie3_intc 0>,
+			<0 0 0 2 &pcie3_intc 0>,
+			<0 0 0 3 &pcie3_intc 0>,
+			<0 0 0 4 &pcie3_intc 0>;
+		status = "disabled";
+
+		pcie3_intc: interrupt-controller {
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupt-parent = <&gic500>;
+			interrupts = <GIC_SPI 348 IRQ_TYPE_EDGE_RISING>;
+		};
+	};
+
+	pcie3_ep: pcie-ep@2930000 {
+		compatible = "ti,j784s4-pcie-ep";
+		reg = <0x00 0x02930000 0x00 0x1000>,
+			<0x00 0x02937000 0x00 0x400>,
+			<0x00 0x0e800000 0x00 0x00800000>,
+			<0x00 0x10000000 0x00 0x08000000>;
+		reg-names = "intd_cfg", "user_cfg", "reg", "mem";
+		interrupt-names = "link_state";
+		interrupts = <GIC_SPI 354 IRQ_TYPE_EDGE_RISING>;
+		ti,syscon-pcie-ctrl = <&scm_conf 0x407c>;
+		max-link-speed = <3>;
+		num-lanes = <4>;
+		power-domains = <&k3_pds 335 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 335 0>;
+		clock-names = "fck";
+		max-functions = /bits/ 8 <6>;
+		max-virtual-functions = /bits/ 8 <4 4 4 4 0 0>;
+		dma-coherent;
+		status = "disabled";
+	};
+
+	main_mcan0: can@2701000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x02701000 0x00 0x200>,
+		      <0x00 0x02708000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 245 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 245 6>, <&k3_clks 245 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan1: can@2711000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x02711000 0x00 0x200>,
+		      <0x00 0x02718000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 246 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 246 6>, <&k3_clks 246 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan2: can@2721000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x02721000 0x00 0x200>,
+		      <0x00 0x02728000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 247 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 247 6>, <&k3_clks 247 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan3: can@2731000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x02731000 0x00 0x200>,
+		      <0x00 0x02738000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 248 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 248 6>, <&k3_clks 248 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan4: can@2741000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x02741000 0x00 0x200>,
+		      <0x00 0x02748000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 249 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 249 6>, <&k3_clks 249 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan5: can@2751000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x02751000 0x00 0x200>,
+		      <0x00 0x02758000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 250 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 250 6>, <&k3_clks 250 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan6: can@2761000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x02761000 0x00 0x200>,
+		      <0x00 0x02768000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 251 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 251 6>, <&k3_clks 251 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan7: can@2771000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x02771000 0x00 0x200>,
+		      <0x00 0x02778000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 252 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 252 6>, <&k3_clks 252 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan8: can@2781000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x02781000 0x00 0x200>,
+		      <0x00 0x02788000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 253 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 253 6>, <&k3_clks 253 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 576 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 577 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan9: can@2791000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x02791000 0x00 0x200>,
+		      <0x00 0x02798000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 254 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 254 6>, <&k3_clks 254 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 579 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 580 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan10: can@27a1000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x027a1000 0x00 0x200>,
+		      <0x00 0x027a8000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 255 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 255 6>, <&k3_clks 255 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan11: can@27b1000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x027b1000 0x00 0x200>,
+		      <0x00 0x027b8000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 256 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 256 6>, <&k3_clks 256 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 585 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan12: can@27c1000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x027c1000 0x00 0x200>,
+		      <0x00 0x027c8000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 257 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 257 6>, <&k3_clks 257 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 588 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 589 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan13: can@27d1000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x027d1000 0x00 0x200>,
+		      <0x00 0x027d8000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 258 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 258 6>, <&k3_clks 258 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 591 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 592 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan14: can@2681000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x02681000 0x00 0x200>,
+		      <0x00 0x02688000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 259 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 259 6>, <&k3_clks 259 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 594 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 595 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan15: can@2691000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x02691000 0x00 0x200>,
+		      <0x00 0x02698000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 260 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 260 6>, <&k3_clks 260 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 597 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 598 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan16: can@26a1000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x026a1000 0x00 0x200>,
+		      <0x00 0x026a8000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 261 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 261 6>, <&k3_clks 261 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 784 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 785 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_mcan17: can@26b1000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x026b1000 0x00 0x200>,
+		      <0x00 0x026b8000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 262 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 262 6>, <&k3_clks 262 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 787 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 788 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	main_spi0: spi@2100000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02100000 0x00 0x400>;
+		interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 376 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 376 1>;
+		status = "disabled";
+	};
+
+	main_spi1: spi@2110000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02110000 0x00 0x400>;
+		interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 377 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 377 1>;
+		status = "disabled";
+	};
+
+	main_spi2: spi@2120000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02120000 0x00 0x400>;
+		interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 378 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 378 1>;
+		status = "disabled";
+	};
+
+	main_spi3: spi@2130000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02130000 0x00 0x400>;
+		interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 379 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 379 1>;
+		status = "disabled";
+	};
+
+	main_spi4: spi@2140000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02140000 0x00 0x400>;
+		interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 380 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 380 1>;
+		status = "disabled";
+	};
+
+	main_spi5: spi@2150000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02150000 0x00 0x400>;
+		interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 381 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 381 1>;
+		status = "disabled";
+	};
+
+	main_spi6: spi@2160000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02160000 0x00 0x400>;
+		interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 382 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 382 1>;
+		status = "disabled";
+	};
+
+	main_spi7: spi@2170000 {
+		compatible = "ti,am654-mcspi","ti,omap4-mcspi";
+		reg = <0x00 0x02170000 0x00 0x400>;
+		interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 383 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 383 1>;
+		status = "disabled";
+	};
+
+	dphy_tx0: phy@4480000 {
+		compatible = "ti,j721e-dphy";
+		reg = <0x0 0x04480000 0x0 0x1000>;
+		clocks = <&k3_clks 402 20>, <&k3_clks 402 3>;
+		clock-names = "psm", "pll_ref";
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 402 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 402 3>;
+		assigned-clock-parents = <&k3_clks 402 4>;
+		assigned-clock-rates = <19200000>;
+		status = "disabled";
+	};
+
+	dsi0: dsi@4800000 {
+		compatible = "ti,j721e-dsi";
+		reg = <0x0 0x04800000 0x0 0x100000>, <0x0 0x04710000 0x0 0x100>;
+		clocks = <&k3_clks 215 2>, <&k3_clks 215 5>;
+		clock-names = "dsi_p_clk", "dsi_sys_clk";
+		power-domains = <&k3_pds 215 TI_SCI_PD_EXCLUSIVE>;
+		interrupt-parent = <&gic500>;
+		interrupts = <GIC_SPI 600 IRQ_TYPE_LEVEL_HIGH>;
+		phys = <&dphy_tx0>;
+		phy-names = "dphy";
+		status = "disabled";
+
+		dsi0_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+			};
+			port@1 {
+				reg = <1>;
+			};
+		};
+	};
+
+	timesync_router: pinctrl@a40000 {
+		compatible = "pinctrl-single";
+		reg = <0x0 0xa40000 0x0 0x800>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0x000107ff>;
+		status = "disabled";
+	};
+
+	mhdp: dp-bridge@a000000 {
+		compatible = "ti,j721e-mhdp8546";
+
+		reg = <0x0 0xa000000 0x0 0x30a00>,
+		      <0x0 0x4f40000 0x0 0x20>;
+		reg-names = "mhdptx", "j721e-intg";
+
+		clocks = <&k3_clks 217 11>;
+
+		interrupt-parent = <&gic500>;
+		interrupts = <GIC_SPI 614 IRQ_TYPE_LEVEL_HIGH>;
+
+		power-domains = <&k3_pds 217 TI_SCI_PD_EXCLUSIVE>;
+
+		status = "disabled";
+
+		dp0_ports: ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+	};
+
+	dss: dss@4a00000 {
+		compatible = "ti,j721e-dss";
+		reg = <0x00 0x04a00000 0x00 0x10000>, /* common_m */
+		      <0x00 0x04a10000 0x00 0x10000>, /* common_s0*/
+		      <0x00 0x04b00000 0x00 0x10000>, /* common_s1*/
+		      <0x00 0x04b10000 0x00 0x10000>, /* common_s2*/
+		      <0x00 0x04a20000 0x00 0x10000>, /* vidl1 */
+		      <0x00 0x04a30000 0x00 0x10000>, /* vidl2 */
+		      <0x00 0x04a50000 0x00 0x10000>, /* vid1 */
+		      <0x00 0x04a60000 0x00 0x10000>, /* vid2 */
+		      <0x00 0x04a70000 0x00 0x10000>, /* ovr1 */
+		      <0x00 0x04a90000 0x00 0x10000>, /* ovr2 */
+		      <0x00 0x04ab0000 0x00 0x10000>, /* ovr3 */
+		      <0x00 0x04ad0000 0x00 0x10000>, /* ovr4 */
+		      <0x00 0x04a80000 0x00 0x10000>, /* vp1 */
+		      <0x00 0x04aa0000 0x00 0x10000>, /* vp1 */
+		      <0x00 0x04ac0000 0x00 0x10000>, /* vp1 */
+		      <0x00 0x04ae0000 0x00 0x10000>, /* vp4 */
+		      <0x00 0x04af0000 0x00 0x10000>; /* wb */
+
+		reg-names = "common_m", "common_s0",
+			    "common_s1", "common_s2",
+			    "vidl1", "vidl2","vid1","vid2",
+			    "ovr1", "ovr2", "ovr3", "ovr4",
+			    "vp1", "vp2", "vp3", "vp4",
+			    "wb";
+
+		clocks = <&k3_clks 218 0>,
+			 <&k3_clks 218 2>,
+			 <&k3_clks 218 5>,
+			 <&k3_clks 218 14>,
+			 <&k3_clks 218 18>;
+		clock-names = "fck", "vp1", "vp2", "vp3", "vp4";
+
+		power-domains = <&k3_pds 218 TI_SCI_PD_EXCLUSIVE>;
+
+		interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "common_m",
+				  "common_s0",
+				  "common_s1",
+				  "common_s2";
+
+		status = "disabled";
+
+		dss_ports: ports {
+		};
+	};
+
+	ti_csi2rx0: ticsi2rx@4500000 {
+		status = "disabled";
+		compatible = "ti,j721e-csi2rx";
+		dmas = <&main_bcdma_csi 0 0x4940 0>, <&main_bcdma_csi 0 0x4941 0>,
+		<&main_bcdma_csi 0 0x4942 0>, <&main_bcdma_csi 0 0x4943 0>,
+		<&main_bcdma_csi 0 0x4944 0>, <&main_bcdma_csi 0 0x4945 0>,
+		<&main_bcdma_csi 0 0x4946 0>, <&main_bcdma_csi 0 0x4947 0>;
+		dma-names = "rx0", "rx1", "rx2", "rx3", "rx4", "rx5", "rx6", "rx7";
+		reg = <0x00 0x04500000 0x00 0x00001000>;
+		power-domains = <&k3_pds 72 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cdns_csi2rx0: csi-bridge@4504000 {
+			compatible = "cdns,csi2rx";
+			reg = <0x00 0x04504000 0x00 0x00001000>;
+			clocks = <&k3_clks 72 2>, <&k3_clks 72 0>, <&k3_clks 72 2>,
+				<&k3_clks 72 2>, <&k3_clks 72 3>, <&k3_clks 72 3>;
+			clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+				"pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+			phys = <&dphy_rx0>;
+			phy-names = "dphy";
+			power-domains = <&k3_pds 72 TI_SCI_PD_EXCLUSIVE>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				csi0_port0: port@0 {
+					reg = <0>;
+					status = "disabled";
+				};
+
+				csi0_port1: port@1 {
+					reg = <1>;
+					status = "disabled";
+				};
+
+				csi0_port2: port@2 {
+					reg = <2>;
+					status = "disabled";
+				};
+
+				csi0_port3: port@3 {
+					reg = <3>;
+					status = "disabled";
+				};
+
+				csi0_port4: port@4 {
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
+	ti_csi2rx1: ticsi2rx@4510000 {
+		status = "disabled";
+		compatible = "ti,j721e-csi2rx";
+		dmas = <&main_bcdma_csi 0 0x4960 0>, <&main_bcdma_csi 0 0x4961 0>,
+		<&main_bcdma_csi 0 0x4962 0>, <&main_bcdma_csi 0 0x4963 0>;
+		dma-names = "rx0", "rx1", "rx2", "rx3";
+		reg = <0x00 0x04510000 0x00 0x00001000>;
+		power-domains = <&k3_pds 73 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cdns_csi2rx1: csi-bridge@4514000 {
+			compatible = "cdns,csi2rx";
+			reg = <0x00 0x04514000 0x00 0x00001000>;
+			clocks = <&k3_clks 73 2>, <&k3_clks 73 0>, <&k3_clks 73 2>,
+				<&k3_clks 73 2>, <&k3_clks 73 3>, <&k3_clks 73 3>;
+			clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+				"pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+			phys = <&dphy_rx1>;
+			phy-names = "dphy";
+			power-domains = <&k3_pds 73 TI_SCI_PD_EXCLUSIVE>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				csi1_port0: port@0 {
+					reg = <0>;
+					status = "disabled";
+				};
+
+				csi1_port1: port@1 {
+					reg = <1>;
+					status = "disabled";
+				};
+
+				csi1_port2: port@2 {
+					reg = <2>;
+					status = "disabled";
+				};
+
+				csi1_port3: port@3 {
+					reg = <3>;
+					status = "disabled";
+				};
+
+				csi1_port4: port@4 {
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
+	ti_csi2rx2: ticsi2rx@4520000 {
+		status = "disabled";
+		compatible = "ti,j721e-csi2rx";
+		dmas = <&main_bcdma_csi 0 0x4980 0>, <&main_bcdma_csi 0 0x4981 0>,
+		<&main_bcdma_csi 0 0x4982 0>, <&main_bcdma_csi 0 0x4983 0>;
+		dma-names = "rx0", "rx1", "rx2", "rx3";
+		reg = <0x00 0x04520000 0x00 0x00001000>;
+		power-domains = <&k3_pds 74 TI_SCI_PD_EXCLUSIVE>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		cdns_csi2rx2: csi-bridge@4524000 {
+			compatible = "cdns,csi2rx";
+			reg = <0x00 0x04524000 0x00 0x00001000>;
+			clocks = <&k3_clks 74 2>, <&k3_clks 74 0>, <&k3_clks 74 2>,
+				<&k3_clks 74 2>, <&k3_clks 74 3>, <&k3_clks 74 3>;
+			clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+				"pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+			phys = <&dphy_rx2>;
+			phy-names = "dphy";
+			power-domains = <&k3_pds 74 TI_SCI_PD_EXCLUSIVE>;
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				csi2_port0: port@0 {
+					reg = <0>;
+					status = "disabled";
+				};
+
+				csi2_port1: port@1 {
+					reg = <1>;
+					status = "disabled";
+				};
+
+				csi2_port2: port@2 {
+					reg = <2>;
+					status = "disabled";
+				};
+
+				csi2_port3: port@3 {
+					reg = <3>;
+					status = "disabled";
+				};
+
+				csi2_port4: port@4 {
+					reg = <4>;
+					status = "disabled";
+				};
+			};
+		};
+	};
+
+	dphy_rx0: phy@4580000 {
+		status = "disabled";
+		compatible = "cdns,dphy-rx";
+		reg = <0x00 0x04580000 0x00 0x00001100>;
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 212 TI_SCI_PD_EXCLUSIVE>;
+	};
+
+	dphy_rx1: phy@4590000 {
+		status = "disabled";
+		compatible = "cdns,dphy-rx";
+		reg = <0x00 0x04590000 0x00 0x00001100>;
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 213 TI_SCI_PD_EXCLUSIVE>;
+	};
+
+	dphy_rx2: phy@45a0000 {
+		status = "disabled";
+		compatible = "cdns,dphy-rx";
+		reg = <0x00 0x045a0000 0x00 0x00001100>;
+		#phy-cells = <0>;
+		power-domains = <&k3_pds 214 TI_SCI_PD_EXCLUSIVE>;
+	};
+
+	ufs_wrapper: ufs-wrapper@4e80000 {
+		compatible = "ti,j721e-ufs";
+		reg = <0x00 0x4e80000 0x00 0x100>;
+		power-domains = <&k3_pds 387 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 387 3>;
+		assigned-clocks = <&k3_clks 387 3>;
+		assigned-clock-parents = <&k3_clks 387 6>;
+		ranges;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		status = "disabled";
+
+		ufs@4e84000 {
+			compatible = "cdns,ufshc-m31-16nm", "jedec,ufs-2.0";
+			reg = <0x00 0x4e84000 0x00 0x10000>;
+			interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+			freq-table-hz = <250000000 250000000>, <19200000 19200000>,
+					<19200000 19200000>;
+			clocks = <&k3_clks 387 1>, <&k3_clks 387 3>, <&k3_clks 387 3>;
+			clock-names = "core_clk", "phy_clk", "ref_clk";
+			dma-coherent;
+		};
+	};
+
+	main_r5fss0: r5fss@5c00000 {
+		compatible = "ti,j721s2-r5fss";
+		ti,cluster-mode = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x5c00000 0x00 0x5c00000 0x20000>,
+			 <0x5d00000 0x00 0x5d00000 0x20000>;
+		power-domains = <&k3_pds 336 TI_SCI_PD_EXCLUSIVE>;
+
+		main_r5fss0_core0: r5f@5c00000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x5c00000 0x00010000>,
+			      <0x5c10000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <339>;
+			ti,sci-proc-ids = <0x06 0xff>;
+			resets = <&k3_reset 339 1>;
+			firmware-name = "j784s4-main-r5f0_0-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+
+		main_r5fss0_core1: r5f@5d00000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x5d00000 0x00010000>,
+			      <0x5d10000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <340>;
+			ti,sci-proc-ids = <0x07 0xff>;
+			resets = <&k3_reset 340 1>;
+			firmware-name = "j784s4-main-r5f0_1-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+	};
+
+	main_r5fss1: r5fss@5e00000 {
+		compatible = "ti,j721s2-r5fss";
+		ti,cluster-mode = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x5e00000 0x00 0x5e00000 0x20000>,
+			 <0x5f00000 0x00 0x5f00000 0x20000>;
+		power-domains = <&k3_pds 337 TI_SCI_PD_EXCLUSIVE>;
+
+		main_r5fss1_core0: r5f@5e00000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x5e00000 0x00010000>,
+			      <0x5e10000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <341>;
+			ti,sci-proc-ids = <0x08 0xff>;
+			resets = <&k3_reset 341 1>;
+			firmware-name = "j784s4-main-r5f1_0-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+
+		main_r5fss1_core1: r5f@5f00000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x5f00000 0x00010000>,
+			      <0x5f10000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <342>;
+			ti,sci-proc-ids = <0x09 0xff>;
+			resets = <&k3_reset 342 1>;
+			firmware-name = "j784s4-main-r5f1_1-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+	};
+
+	main_r5fss2: r5fss@5900000 {
+		compatible = "ti,j721s2-r5fss";
+		ti,cluster-mode = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x5900000 0x00 0x5900000 0x20000>,
+			 <0x5a00000 0x00 0x5a00000 0x20000>;
+		power-domains = <&k3_pds 338 TI_SCI_PD_EXCLUSIVE>;
+
+		main_r5fss2_core0: r5f@5900000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x5900000 0x00010000>,
+			      <0x5910000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <343>;
+			ti,sci-proc-ids = <0x0a 0xff>;
+			resets = <&k3_reset 343 1>;
+			firmware-name = "j784s4-main-r5f2_0-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+
+		main_r5fss2_core1: r5f@5a00000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x5a00000 0x00010000>,
+			      <0x5a10000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <344>;
+			ti,sci-proc-ids = <0x0b 0xff>;
+			resets = <&k3_reset 344 1>;
+			firmware-name = "j784s4-main-r5f2_1-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+	};
+
+	c71_0: dsp@64800000 {
+		compatible = "ti,j721s2-c71-dsp";
+		reg = <0x00 0x64800000 0x00 0x00080000>,
+		      <0x00 0x64e00000 0x00 0x0000c000>;
+		reg-names = "l2sram", "l1dram";
+		ti,sci = <&sms>;
+		ti,sci-dev-id = <30>;
+		ti,sci-proc-ids = <0x30 0xff>;
+		resets = <&k3_reset 30 1>;
+		firmware-name = "j784s4-c71_0-fw";
+	};
+
+	c71_1: dsp@65800000 {
+		compatible = "ti,j721s2-c71-dsp";
+		reg = <0x00 0x65800000 0x00 0x00080000>,
+		      <0x00 0x65e00000 0x00 0x0000c000>;
+		reg-names = "l2sram", "l1dram";
+		ti,sci = <&sms>;
+		ti,sci-dev-id = <33>;
+		ti,sci-proc-ids = <0x31 0xff>;
+		resets = <&k3_reset 33 1>;
+		firmware-name = "j784s4-c71_1-fw";
+	};
+
+	c71_2: dsp@66800000 {
+		compatible = "ti,j721s2-c71-dsp";
+		reg = <0x00 0x66800000 0x00 0x00080000>,
+		      <0x00 0x66e00000 0x00 0x0000c000>;
+		reg-names = "l2sram", "l1dram";
+		ti,sci = <&sms>;
+		ti,sci-dev-id = <37>;
+		ti,sci-proc-ids = <0x32 0xff>;
+		resets = <&k3_reset 37 1>;
+		firmware-name = "j784s4-c71_2-fw";
+	};
+
+	c71_3: dsp@67800000 {
+		compatible = "ti,j721s2-c71-dsp";
+		reg = <0x00 0x67800000 0x00 0x00080000>,
+		      <0x00 0x67e00000 0x00 0x0000c000>;
+		reg-names = "l2sram", "l1dram";
+		ti,sci = <&sms>;
+		ti,sci-dev-id = <40>;
+		ti,sci-proc-ids = <0x33 0xff>;
+		resets = <&k3_reset 40 1>;
+		firmware-name = "j784s4-c71_3-fw";
+	};
+
+	main_esm: esm@700000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x00 0x700000 0x00 0x1000>;
+		ti,esm-pins = <688>, <689>, <690>, <691>, <692>, <693>, <694>,
+			      <695>;
+		bootph-pre-ram;
+	};
+
+	watchdog0: watchdog@2200000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2200000 0x00 0x100>;
+		clocks = <&k3_clks 348 1>;
+		power-domains = <&k3_pds 348 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 348 0>;
+		assigned-clock-parents = <&k3_clks 348 4>;
+	};
+
+	watchdog1: watchdog@2210000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2210000 0x00 0x100>;
+		clocks = <&k3_clks 349 1>;
+		power-domains = <&k3_pds 349 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 349 0>;
+		assigned-clock-parents = <&k3_clks 349 4>;
+	};
+
+	watchdog2: watchdog@2220000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2220000 0x00 0x100>;
+		clocks = <&k3_clks 350 1>;
+		power-domains = <&k3_pds 350 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 350 0>;
+		assigned-clock-parents = <&k3_clks 350 4>;
+	};
+
+	watchdog3: watchdog@2230000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2230000 0x00 0x100>;
+		clocks = <&k3_clks 351 1>;
+		power-domains = <&k3_pds 351 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 351 0>;
+		assigned-clock-parents = <&k3_clks 351 4>;
+	};
+
+	watchdog4: watchdog@2240000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2240000 0x00 0x100>;
+		clocks = <&k3_clks 352 1>;
+		power-domains = <&k3_pds 352 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 352 0>;
+		assigned-clock-parents = <&k3_clks 352 4>;
+	};
+
+	watchdog5: watchdog@2250000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2250000 0x00 0x100>;
+		clocks = <&k3_clks 353 1>;
+		power-domains = <&k3_pds 353 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 353 0>;
+		assigned-clock-parents = <&k3_clks 353 4>;
+	};
+
+	watchdog6: watchdog@2260000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2260000 0x00 0x100>;
+		clocks = <&k3_clks 354 1>;
+		power-domains = <&k3_pds 354 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 354 0>;
+		assigned-clock-parents = <&k3_clks 354 4>;
+	};
+
+	watchdog7: watchdog@2270000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2270000 0x00 0x100>;
+		clocks = <&k3_clks 355 1>;
+		power-domains = <&k3_pds 355 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 355 0>;
+		assigned-clock-parents = <&k3_clks 355 4>;
+	};
+
+	/*
+	 * The following RTI instances are coupled with MCU R5Fs, c7x and
+	 * GPU so keeping them reserved as these will be used by their
+	 * respective firmware
+	 */
+	watchdog8: watchdog@22f0000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x22f0000 0x00 0x100>;
+		clocks = <&k3_clks 360 1>;
+		power-domains = <&k3_pds 360 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 360 0>;
+		assigned-clock-parents = <&k3_clks 360 4>;
+		/* reserved for GPU */
+		status = "reserved";
+	};
+
+	watchdog9: watchdog@2300000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2300000 0x00 0x100>;
+		clocks = <&k3_clks 356 1>;
+		power-domains = <&k3_pds 356 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 356 0>;
+		assigned-clock-parents = <&k3_clks 356 4>;
+		/* reserved for C7X_0 DSP */
+		status = "reserved";
+	};
+
+	watchdog10: watchdog@2310000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2310000 0x00 0x100>;
+		clocks = <&k3_clks 357 1>;
+		power-domains = <&k3_pds 357 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 357 0>;
+		assigned-clock-parents = <&k3_clks 357 4>;
+		/* reserved for C7X_1 DSP */
+		status = "reserved";
+	};
+
+	watchdog11: watchdog@2320000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2320000 0x00 0x100>;
+		clocks = <&k3_clks 358 1>;
+		power-domains = <&k3_pds 358 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 358 0>;
+		assigned-clock-parents = <&k3_clks 358 4>;
+		/* reserved for C7X_2 DSP */
+		status = "reserved";
+	};
+
+	watchdog12: watchdog@2330000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2330000 0x00 0x100>;
+		clocks = <&k3_clks 359 1>;
+		power-domains = <&k3_pds 359 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 359 0>;
+		assigned-clock-parents = <&k3_clks 359 4>;
+		/* reserved for C7X_3 DSP */
+		status = "reserved";
+	};
+
+	watchdog13: watchdog@23c0000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x23c0000 0x00 0x100>;
+		clocks = <&k3_clks 361 1>;
+		power-domains = <&k3_pds 361 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 361 0>;
+		assigned-clock-parents = <&k3_clks 361 4>;
+		/* reserved for MAIN_R5F0_0 */
+		status = "reserved";
+	};
+
+	watchdog14: watchdog@23d0000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x23d0000 0x00 0x100>;
+		clocks = <&k3_clks 362 1>;
+		power-domains = <&k3_pds 362 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 362 0>;
+		assigned-clock-parents = <&k3_clks 362 4>;
+		/* reserved for MAIN_R5F0_1 */
+		status = "reserved";
+	};
+
+	watchdog15: watchdog@23e0000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x23e0000 0x00 0x100>;
+		clocks = <&k3_clks 363 1>;
+		power-domains = <&k3_pds 363 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 363 0>;
+		assigned-clock-parents = <&k3_clks 363 4>;
+		/* reserved for MAIN_R5F1_0 */
+		status = "reserved";
+	};
+
+	watchdog16: watchdog@23f0000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x23f0000 0x00 0x100>;
+		clocks = <&k3_clks 364 1>;
+		power-domains = <&k3_pds 364 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 364 0>;
+		assigned-clock-parents = <&k3_clks 364 4>;
+		/* reserved for MAIN_R5F1_1 */
+		status = "reserved";
+	};
+
+	watchdog17: watchdog@2540000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2540000 0x00 0x100>;
+		clocks = <&k3_clks 365 1>;
+		power-domains = <&k3_pds 365 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 365 0>;
+		assigned-clock-parents = <&k3_clks 366 4>;
+		/* reserved for MAIN_R5F2_0 */
+		status = "reserved";
+	};
+
+	watchdog18: watchdog@2550000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x2550000 0x00 0x100>;
+		clocks = <&k3_clks 366 1>;
+		power-domains = <&k3_pds 366 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 366 0>;
+		assigned-clock-parents = <&k3_clks 366 4>;
+		/* reserved for MAIN_R5F2_1 */
+		status = "reserved";
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-mcu-wakeup.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,542 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for J784S4 SoC Family MCU/WAKEUP Domain peripherals
+ *
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ */
+
+&cbass_mcu_wakeup {
+	sms: system-controller@44083000 {
+		compatible = "ti,k2g-sci";
+		ti,host-id = <12>;
+
+		mbox-names = "rx", "tx";
+
+		mboxes = <&secure_proxy_main 11>,
+			 <&secure_proxy_main 13>;
+
+		reg-names = "debug_messages";
+		reg = <0x00 0x44083000 0x00 0x1000>;
+
+		k3_pds: power-controller {
+			compatible = "ti,sci-pm-domain";
+			#power-domain-cells = <2>;
+		};
+
+		k3_clks: clock-controller {
+			compatible = "ti,k2g-sci-clk";
+			#clock-cells = <2>;
+		};
+
+		k3_reset: reset-controller {
+			compatible = "ti,sci-reset";
+			#reset-cells = <2>;
+		};
+	};
+
+	chipid@43000014 {
+		compatible = "ti,am654-chipid";
+		reg = <0x00 0x43000014 0x00 0x4>;
+	};
+
+	mcu_ram: sram@41c00000 {
+		compatible = "mmio-sram";
+		reg = <0x00 0x41c00000 0x00 0x100000>;
+		ranges = <0x00 0x00 0x41c00000 0x100000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+	};
+
+	wkup_pmx0: pinctrl@4301c000 {
+		compatible = "pinctrl-single";
+		/* Proxy 0 addressing */
+		reg = <0x00 0x4301c000 0x00 0x034>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
+
+	wkup_pmx1: pinctrl@4301c038 {
+		compatible = "pinctrl-single";
+		/* Proxy 0 addressing */
+		reg = <0x00 0x4301c038 0x00 0x02c>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
+
+	wkup_pmx2: pinctrl@4301c068 {
+		compatible = "pinctrl-single";
+		/* Proxy 0 addressing */
+		reg = <0x00 0x4301c068 0x00 0x120>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
+
+	wkup_pmx3: pinctrl@4301c190 {
+		compatible = "pinctrl-single";
+		/* Proxy 0 addressing */
+		reg = <0x00 0x4301c190 0x00 0x004>;
+		#pinctrl-cells = <1>;
+		pinctrl-single,register-width = <32>;
+		pinctrl-single,function-mask = <0xffffffff>;
+	};
+
+	wkup_gpio_intr: interrupt-controller@42200000 {
+		compatible = "ti,sci-intr";
+		reg = <0x00 0x42200000 0x00 0x400>;
+		ti,intr-trigger-type = <1>;
+		interrupt-controller;
+		interrupt-parent = <&gic500>;
+		#interrupt-cells = <1>;
+		ti,sci = <&sms>;
+		ti,sci-dev-id = <177>;
+		ti,interrupt-ranges = <16 960 16>;
+	};
+
+	mcu_conf: syscon@40f00000 {
+		compatible = "ti,j721e-system-controller", "syscon", "simple-mfd";
+		reg = <0x00 0x40f00000 0x00 0x20000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x00 0x00 0x40f00000 0x20000>;
+
+		phy_gmii_sel: phy@4040 {
+			compatible = "ti,am654-phy-gmii-sel";
+			reg = <0x4040 0x4>;
+			#phy-cells = <1>;
+		};
+	};
+
+	wkup_uart0: serial@42300000 {
+		compatible = "ti,j721e-uart", "ti,am654-uart";
+		reg = <0x00 0x42300000 0x00 0x200>;
+		interrupts = <GIC_SPI 897 IRQ_TYPE_LEVEL_HIGH>;
+		current-speed = <115200>;
+		clocks = <&k3_clks 397 0>;
+		clock-names = "fclk";
+		power-domains = <&k3_pds 397 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	mcu_uart0: serial@40a00000 {
+		compatible = "ti,j721e-uart", "ti,am654-uart";
+		reg = <0x00 0x40a00000 0x00 0x200>;
+		interrupts = <GIC_SPI 846 IRQ_TYPE_LEVEL_HIGH>;
+		current-speed = <115200>;
+		clocks = <&k3_clks 149 0>;
+		clock-names = "fclk";
+		power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	wkup_gpio0: gpio@42110000 {
+		compatible = "ti,j721e-gpio", "ti,keystone-gpio";
+		reg = <0x00 0x42110000 0x00 0x100>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&wkup_gpio_intr>;
+		interrupts = <103>, <104>, <105>, <106>, <107>, <108>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		ti,ngpio = <89>;
+		ti,davinci-gpio-unbanked = <0>;
+		power-domains = <&k3_pds 167 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 167 0>;
+		clock-names = "gpio";
+		status = "disabled";
+	};
+
+	wkup_gpio1: gpio@42100000 {
+		compatible = "ti,j721e-gpio", "ti,keystone-gpio";
+		reg = <0x00 0x42100000 0x00 0x100>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&wkup_gpio_intr>;
+		interrupts = <112>, <113>, <114>, <115>, <116>, <117>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		ti,ngpio = <89>;
+		ti,davinci-gpio-unbanked = <0>;
+		power-domains = <&k3_pds 168 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 168 0>;
+		clock-names = "gpio";
+		status = "disabled";
+	};
+
+	wkup_i2c0: i2c@42120000 {
+		compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x42120000 0x00 0x100>;
+		interrupts = <GIC_SPI 896 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&k3_clks 279 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 279 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	mcu_i2c0: i2c@40b00000 {
+		compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x40b00000 0x00 0x100>;
+		interrupts = <GIC_SPI 852 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&k3_clks 277 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 277 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	mcu_i2c1: i2c@40b10000 {
+		compatible = "ti,j721e-i2c", "ti,omap4-i2c";
+		reg = <0x00 0x40b10000 0x00 0x100>;
+		interrupts = <GIC_SPI 853 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&k3_clks 278 2>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 278 TI_SCI_PD_EXCLUSIVE>;
+		status = "disabled";
+	};
+
+	mcu_mcan0: can@40528000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x40528000 0x00 0x200>,
+		      <0x00 0x40500000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 263 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 263 6>, <&k3_clks 263 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 832 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 833 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	mcu_mcan1: can@40568000 {
+		compatible = "bosch,m_can";
+		reg = <0x00 0x40568000 0x00 0x200>,
+		      <0x00 0x40540000 0x00 0x8000>;
+		reg-names = "m_can", "message_ram";
+		power-domains = <&k3_pds 264 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 264 6>, <&k3_clks 264 1>;
+		clock-names = "hclk", "cclk";
+		interrupts = <GIC_SPI 835 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 836 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		bosch,mram-cfg = <0x00 128 64 64 64 64 32 32>;
+		status = "disabled";
+	};
+
+	mcu_spi0: spi@40300000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x040300000 0x00 0x400>;
+		interrupts = <GIC_SPI 848 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 384 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 384 0>;
+		status = "disabled";
+	};
+
+	mcu_spi1: spi@40310000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x040310000 0x00 0x400>;
+		interrupts = <GIC_SPI 849 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 385 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 385 0>;
+		status = "disabled";
+	};
+
+	mcu_spi2: spi@40320000 {
+		compatible = "ti,am654-mcspi", "ti,omap4-mcspi";
+		reg = <0x00 0x040320000 0x00 0x400>;
+		interrupts = <GIC_SPI 850 IRQ_TYPE_LEVEL_HIGH>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		power-domains = <&k3_pds 386 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 386 0>;
+		status = "disabled";
+	};
+
+	mcu_navss: bus@28380000{
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges = <0x00 0x28380000 0x00 0x28380000 0x00 0x03880000>;
+		ti,sci-dev-id = <323>;
+		dma-coherent;
+		dma-ranges;
+
+		mcu_ringacc: ringacc@2b800000 {
+			compatible = "ti,am654-navss-ringacc";
+			reg = <0x00 0x2b800000 0x00 0x400000>,
+			      <0x00 0x2b000000 0x00 0x400000>,
+			      <0x00 0x28590000 0x00 0x100>,
+			      <0x00 0x2a500000 0x00 0x40000>;
+			reg-names = "rt", "fifos", "proxy_gcfg", "proxy_target";
+			ti,num-rings = <286>;
+			ti,sci-rm-range-gp-rings = <0x1>;
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <328>;
+			msi-parent = <&main_udmass_inta>;
+		};
+
+		mcu_udmap: dma-controller@285c0000 {
+			compatible = "ti,j721e-navss-mcu-udmap";
+			reg = <0x00 0x285c0000 0x00 0x100>,
+			      <0x00 0x2a800000 0x00 0x40000>,
+			      <0x00 0x2aa00000 0x00 0x40000>;
+			reg-names = "gcfg", "rchanrt", "tchanrt";
+			msi-parent = <&main_udmass_inta>;
+			#dma-cells = <1>;
+
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <329>;
+			ti,ringacc = <&mcu_ringacc>;
+			ti,sci-rm-range-tchan = <0x0d>, /* TX_CHAN */
+						<0x0f>; /* TX_HCHAN */
+			ti,sci-rm-range-rchan = <0x0a>, /* RX_CHAN */
+						<0x0b>; /* RX_HCHAN */
+			ti,sci-rm-range-rflow = <0x00>; /* GP RFLOW */
+		};
+	};
+
+	mcu_cpsw: ethernet@46000000 {
+		compatible = "ti,j721e-cpsw-nuss";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		reg = <0x00 0x46000000 0x00 0x200000>;
+		reg-names = "cpsw_nuss";
+		ranges = <0x00 0x00 0x00 0x46000000 0x00 0x200000>;
+		dma-coherent;
+		clocks = <&k3_clks 63 0>;
+		clock-names = "fck";
+		power-domains = <&k3_pds 63 TI_SCI_PD_EXCLUSIVE>;
+
+		dmas = <&mcu_udmap 0xf000>,
+		       <&mcu_udmap 0xf001>,
+		       <&mcu_udmap 0xf002>,
+		       <&mcu_udmap 0xf003>,
+		       <&mcu_udmap 0xf004>,
+		       <&mcu_udmap 0xf005>,
+		       <&mcu_udmap 0xf006>,
+		       <&mcu_udmap 0xf007>,
+		       <&mcu_udmap 0x7000>;
+		dma-names = "tx0", "tx1", "tx2", "tx3",
+			    "tx4", "tx5", "tx6", "tx7",
+			    "rx";
+		status = "disabled";
+
+		ethernet-ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			mcu_cpsw_port1: port@1 {
+				reg = <1>;
+				ti,mac-only;
+				label = "port1";
+				ti,syscon-efuse = <&mcu_conf 0x200>;
+				phys = <&phy_gmii_sel 1>;
+			};
+		};
+
+		davinci_mdio: mdio@f00 {
+			compatible = "ti,cpsw-mdio","ti,davinci_mdio";
+			reg = <0x00 0xf00 0x00 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			clocks = <&k3_clks 63 0>;
+			clock-names = "fck";
+			bus_freq = <1000000>;
+		};
+
+		cpts@3d000 {
+			compatible = "ti,am65-cpts";
+			reg = <0x00 0x3d000 0x00 0x400>;
+			clocks = <&k3_clks 63 3>;
+			clock-names = "cpts";
+			assigned-clocks = <&k3_clks 63 3>; /* CPTS_RFT_CLK */
+			assigned-clock-parents = <&k3_clks 63 5>; /* MAIN_0_HSDIV6_CLK */
+			interrupts-extended = <&gic500 GIC_SPI 858 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "cpts";
+			ti,cpts-ext-ts-inputs = <4>;
+			ti,cpts-periodic-outputs = <2>;
+		};
+	};
+
+	fss: bus@47000000 {
+		compatible = "simple-bus";
+		reg = <0x00 0x47000000 0x00 0x100>;
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		ospi0: spi@47040000 {
+			compatible = "ti,am654-ospi", "cdns,qspi-nor";
+			reg = <0x00 0x47040000 0x00 0x100>,
+			      <0x05 0x0000000 0x01 0x0000000>;
+			interrupts = <GIC_SPI 840 IRQ_TYPE_LEVEL_HIGH>;
+			cdns,fifo-depth = <256>;
+			cdns,fifo-width = <4>;
+			cdns,trigger-address = <0x0>;
+			clocks = <&k3_clks 161 7>;
+			assigned-clocks = <&k3_clks 161 7>;
+			assigned-clock-parents = <&k3_clks 161 9>;
+			assigned-clock-rates = <166666666>;
+			power-domains = <&k3_pds 161 TI_SCI_PD_EXCLUSIVE>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		ospi1: spi@47050000 {
+			compatible = "ti,am654-ospi", "cdns,qspi-nor";
+			reg = <0x00 0x47050000 0x00 0x100>,
+			      <0x07 0x0000000 0x01 0x0000000>;
+			interrupts = <GIC_SPI 841 IRQ_TYPE_LEVEL_HIGH>;
+			cdns,fifo-depth = <256>;
+			cdns,fifo-width = <4>;
+			cdns,trigger-address = <0x0>;
+			clocks = <&k3_clks 162 7>;
+			power-domains = <&k3_pds 162 TI_SCI_PD_EXCLUSIVE>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+	};
+
+	wkup_vtm0: temperature-sensor@42040000 {
+		compatible = "ti,j7200-vtm";
+		reg = <0x0 0x42040000 0x0 0x350>,
+		      <0x0 0x42050000 0x0 0x350>,
+		      <0x0 0x43000300 0x0 0x10>;
+		power-domains = <&k3_pds 154 TI_SCI_PD_SHARED>;
+		#thermal-sensor-cells = <1>;
+	};
+
+	tscadc0: tscadc@40200000 {
+		compatible = "ti,am3359-tscadc";
+		reg = <0x00 0x40200000 0x00 0x1000>;
+		interrupts = <GIC_SPI 860 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 0 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 0 0>;
+		assigned-clocks = <&k3_clks 0 2>;
+		assigned-clock-rates = <60000000>;
+		clock-names = "fck";
+		dmas = <&main_udmap 0x7400>,
+			<&main_udmap 0x7401>;
+		dma-names = "fifo0", "fifo1";
+		status = "disabled";
+
+		adc {
+			#io-channel-cells = <1>;
+			compatible = "ti,am3359-adc";
+		};
+	};
+
+	tscadc1: tscadc@40210000 {
+		compatible = "ti,am3359-tscadc";
+		reg = <0x00 0x40210000 0x00 0x1000>;
+		interrupts = <GIC_SPI 861 IRQ_TYPE_LEVEL_HIGH>;
+		power-domains = <&k3_pds 1 TI_SCI_PD_EXCLUSIVE>;
+		clocks = <&k3_clks 1 0>;
+		assigned-clocks = <&k3_clks 1 2>;
+		assigned-clock-rates = <60000000>;
+		clock-names = "fck";
+		dmas = <&main_udmap 0x7402>,
+			<&main_udmap 0x7403>;
+		dma-names = "fifo0", "fifo1";
+		status = "disabled";
+
+		adc {
+			#io-channel-cells = <1>;
+			compatible = "ti,am3359-adc";
+		};
+	};
+
+	mcu_r5fss0: r5fss@41000000 {
+		compatible = "ti,j721s2-r5fss";
+		ti,cluster-mode = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x41000000 0x00 0x41000000 0x20000>,
+			 <0x41400000 0x00 0x41400000 0x20000>;
+		power-domains = <&k3_pds 345 TI_SCI_PD_EXCLUSIVE>;
+
+		mcu_r5fss0_core0: r5f@41000000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x41000000 0x00010000>,
+			      <0x41010000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <346>;
+			ti,sci-proc-ids = <0x01 0xff>;
+			resets = <&k3_reset 346 1>;
+			firmware-name = "j784s4-mcu-r5f0_0-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+
+		mcu_r5fss0_core1: r5f@41400000 {
+			compatible = "ti,j721s2-r5f";
+			reg = <0x41400000 0x00010000>,
+			      <0x41410000 0x00010000>;
+			reg-names = "atcm", "btcm";
+			ti,sci = <&sms>;
+			ti,sci-dev-id = <347>;
+			ti,sci-proc-ids = <0x02 0xff>;
+			resets = <&k3_reset 347 1>;
+			firmware-name = "j784s4-mcu-r5f0_1-fw";
+			ti,atcm-enable = <1>;
+			ti,btcm-enable = <1>;
+			ti,loczrama = <1>;
+		};
+	};
+
+	mcu_esm: esm@40800000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x00 0x40800000 0x00 0x1000>;
+		ti,esm-pins = <95>;
+		bootph-pre-ram;
+	};
+
+	wkup_esm: esm@42080000 {
+		compatible = "ti,j721e-esm";
+		reg = <0x00 0x42080000 0x00 0x1000>;
+		ti,esm-pins = <63>;
+		bootph-pre-ram;
+	};
+
+	/*
+	 * The 2 RTI instances are couple with MCU R5Fs so keeping them
+	 * reserved as these will be used by their respective firmware
+	 */
+	mcu_watchdog0: watchdog@40600000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x40600000 0x00 0x100>;
+		clocks = <&k3_clks 367 1>;
+		power-domains = <&k3_pds 367 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 367 0>;
+		assigned-clock-parents = <&k3_clks 367 4>;
+		/* reserved for MCU_R5F0_0 */
+		status = "reserved";
+	};
+
+	mcu_watchdog1: watchdog@40610000 {
+		compatible = "ti,j7-rti-wdt";
+		reg = <0x00 0x40610000 0x00 0x100>;
+		clocks = <&k3_clks 368 1>;
+		power-domains = <&k3_pds 368 TI_SCI_PD_EXCLUSIVE>;
+		assigned-clocks = <&k3_clks 368 0>;
+		assigned-clock-parents = <&k3_clks 368 4>;
+		/* reserved for MCU_R5F0_1 */
+		status = "reserved";
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi b/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi
--- a/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-j784s4-thermal.dtsi	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <dt-bindings/thermal/thermal.h>
+
+wkup0_thermal: wkup0-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 0>;
+
+	trips {
+		wkup0_crit: wkup0-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
+
+wkup1_thermal: wkup1-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 1>;
+
+	trips {
+		wkup1_crit: wkup1-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
+
+main0_thermal: main0-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 2>;
+
+	trips {
+		main0_crit: main0-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
+
+main1_thermal: main1-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 3>;
+
+	trips {
+		main1_crit: main1-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
+
+main2_thermal: main2-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 4>;
+
+	trips {
+		main2_crit: main2-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
+
+main3_thermal: main3-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 5>;
+
+	trips {
+		main3_crit: main3-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
+
+main4_thermal: main4-thermal {
+	polling-delay-passive = <250>; /* milliseconds */
+	polling-delay = <500>; /* milliseconds */
+	thermal-sensors = <&wkup_vtm0 6>;
+
+	trips {
+		main4_crit: main4-crit {
+			temperature = <125000>; /* milliCelsius */
+			hysteresis = <2000>; /* milliCelsius */
+			type = "critical";
+		};
+	};
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/k3-pinctrl.h b/arch/arm64/boot/dts/ti/k3-pinctrl.h
--- a/arch/arm64/boot/dts/ti/k3-pinctrl.h	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/k3-pinctrl.h	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This header provides constants for pinctrl bindings for TI's K3 SoC
+ * family.
+ *
+ * Copyright (C) 2018-2023 Texas Instruments Incorporated - https://www.ti.com/
+ */
+#ifndef DTS_ARM64_TI_K3_PINCTRL_H
+#define DTS_ARM64_TI_K3_PINCTRL_H
+
+#define PULLUDEN_SHIFT		(16)
+#define PULLTYPESEL_SHIFT	(17)
+#define RXACTIVE_SHIFT		(18)
+#define DEBOUNCE_SHIFT		(11)
+#define WKUP_EN_SHIFT		(29)
+
+#define PULL_DISABLE		(1 << PULLUDEN_SHIFT)
+#define PULL_ENABLE		(0 << PULLUDEN_SHIFT)
+
+#define PULL_UP			(1 << PULLTYPESEL_SHIFT | PULL_ENABLE)
+#define PULL_DOWN		(0 << PULLTYPESEL_SHIFT | PULL_ENABLE)
+
+#define INPUT_EN		(1 << RXACTIVE_SHIFT)
+#define INPUT_DISABLE		(0 << RXACTIVE_SHIFT)
+
+/* Only these macros are expected be used directly in device tree files */
+#define PIN_OUTPUT		(INPUT_DISABLE | PULL_DISABLE)
+#define PIN_OUTPUT_PULLUP	(INPUT_DISABLE | PULL_UP)
+#define PIN_OUTPUT_PULLDOWN	(INPUT_DISABLE | PULL_DOWN)
+#define PIN_INPUT		(INPUT_EN | PULL_DISABLE)
+#define PIN_INPUT_PULLUP	(INPUT_EN | PULL_UP)
+#define PIN_INPUT_PULLDOWN	(INPUT_EN | PULL_DOWN)
+
+#define PIN_DEBOUNCE_DISABLE	(0 << DEBOUNCE_SHIFT)
+#define PIN_DEBOUNCE_CONF1	(1 << DEBOUNCE_SHIFT)
+#define PIN_DEBOUNCE_CONF2	(2 << DEBOUNCE_SHIFT)
+#define PIN_DEBOUNCE_CONF3	(3 << DEBOUNCE_SHIFT)
+#define PIN_DEBOUNCE_CONF4	(4 << DEBOUNCE_SHIFT)
+#define PIN_DEBOUNCE_CONF5	(5 << DEBOUNCE_SHIFT)
+#define PIN_DEBOUNCE_CONF6	(6 << DEBOUNCE_SHIFT)
+
+#define WKUP_EN			(1 << WKUP_EN_SHIFT)
+
+#define AM62AX_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
+#define AM62AX_MCU_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
+
+#define AM62PX_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
+#define AM62PX_MCU_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
+
+#define AM62X_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
+#define AM62X_MCU_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
+
+#define AM64X_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
+#define AM64X_MCU_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
+
+#define AM65X_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
+#define AM65X_WKUP_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
+
+#define J721E_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
+#define J721E_WKUP_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
+
+#define J721S2_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
+#define J721S2_WKUP_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
+
+#define J722S_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
+#define J722S_MCU_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
+
+#define J784S4_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
+#define J784S4_WKUP_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
+
+#endif
diff -Naur --no-dereference a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile
--- a/arch/arm64/boot/dts/ti/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/ti/Makefile	2024-01-28 14:01:31.236353764 -0500
@@ -5,23 +5,166 @@
 #
 # Copyright (C) 2016-2021 Texas Instruments Incorporated - https://www.ti.com/
 #
+# Entries are grouped as per SoC present on the board. Groups are sorted
+# alphabetically.
 
-dtb-$(CONFIG_ARCH_K3) += k3-am654-base-board.dtb
+# Boards with AM62x SoC
+dtb-$(CONFIG_ARCH_K3) += k3-am625-beagleplay.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am625-beagleplay-csi2-ov5640.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am625-beagleplay-csi2-tevi-ov5640.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am625-beagleplay-lincolntech-lcd185-panel.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am625-sk.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am625-sk-lincolntech-lcd185-panel.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am625-sk-microtips-mf101hie-panel.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am625-sk-microtips-mf103hie-lcd2.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am625-sk-dmtimer-pwm.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am625-sk-ecap-capture.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62-lp-sk.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am62-lp-sk-nand.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62-lp-sk-lincolntech-lcd185-panel.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62-lp-sk-microtips-mf101hie-panel.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am625-sk-pwm.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am625-sk-rpi-hdr-ehrpwm.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am625-sk-mcspi-loopback.dtbo
+
+# Boards with AM62Ax SoC
+k3-am62a7-sk-csi2-imx219-dtbs := k3-am62a7-sk.dtb k3-am62x-sk-csi2-imx219.dtbo
+k3-am62a7-sk-fusion-imx390-dtbs := k3-am62a7-sk.dtb \
+				   k3-am62a7-sk-fusion.dtbo \
+				   k3-fpdlink-imx390-rcm-0-0.dtbo
+k3-am62a7-sk-fusion-ov2312-dtbs := k3-am62a7-sk.dtb \
+				   k3-am62a7-sk-fusion.dtbo \
+				   k3-fpdlink-ov2312-0-0.dtbo
+k3-am62a7-sk-ub954-evm-ov2312-dtbs := k3-am62a7-sk.dtb \
+				      k3-am62a7-sk-ub954-evm.dtbo \
+				      k3-fpdlink-ov2312-0-0.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62a7-sk-csi2-imx219.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am62a7-sk-e3-max-opp.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62a7-sk-ethernet-dc01.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62a7-sk-fusion-imx390.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am62a7-sk-fusion-ov2312.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am62a7-sk-rpi-hdr-ehrpwm.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62a7-sk-ub954-evm-ov2312.dtb
+
+# Boards with AM62Px SoC
+dtb-$(CONFIG_ARCH_K3) += k3-am62p5-sk.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am62p5-sk-dsi-rpi-7inch-panel.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62p5-sk-eqep.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62p5-sk-mcan.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62p5-sk-microtips-mf101hie-panel.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62p5-sk-microtips-mf103hie-lcd2.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62p5-sk-dss-shared-mode.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62p5-sk-rpi-hdr-ehrpwm.dtbo
+
+# Boards with AM64x SoC
+dtb-$(CONFIG_ARCH_K3) += k3-am642-evm.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am642-sk.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am642-evm-icssg1-dualemac.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am642-evm-icssg1-dualemac-mii.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am642-evm-nand.dtbo
+
+# Boards with AM65x SoC
 dtb-$(CONFIG_ARCH_K3) += k3-am6528-iot2050-basic.dtb
 dtb-$(CONFIG_ARCH_K3) += k3-am6528-iot2050-basic-pg2.dtb
 dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced.dtb
 dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced-pg2.dtb
-
-dtb-$(CONFIG_ARCH_K3) += k3-j721e-common-proc-board.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am654-base-board.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am654-evm-oldi-lcd1evm.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am654-idk.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am654-pcie-usb3.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am654-pcie-usb2.dtbo
+
+# Boards with J7200 SoC
+k3-j7200-evm-dtbs := k3-j7200-common-proc-board.dtb k3-j7200-evm-quad-port-eth-exp.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j7200-evm.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-j7200-evm-mcspi-loopback.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j7200-evm-virt-mac-client.dtbo
+
+# Boards with J721e SoC
+k3-j721e-evm-dtbs := k3-j721e-common-proc-board.dtb k3-j721e-evm-quad-port-eth-exp.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-beagleboneai64.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-beagleboneai64-dsi-rpi-7inch-panel.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm-csi2-ov5640.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm-fusion.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm-gesi-exp-board.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-evm-virt-mac-client.dtbo
 dtb-$(CONFIG_ARCH_K3) += k3-j721e-sk.dtb
-
-dtb-$(CONFIG_ARCH_K3) += k3-j7200-common-proc-board.dtb
-
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-sk-csi2-ov5640.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-sk-csi2-rpi-imx219.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-sk-fusion.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-sk-rpi-hdr-ehrpwm.dtbo
+
+# Boards with J721s2 SoC
+dtb-$(CONFIG_ARCH_K3) += k3-am68-sk-base-board.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am68-sk-bb-csi2-ov5640.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am68-sk-bb-rpi-cam-imx219.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am68-sk-fpdlink-fusion.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am68-sk-rpi-hdr-ehrpwm.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am68-sk-som-ddr-mem-carveout.dtbo
 dtb-$(CONFIG_ARCH_K3) += k3-j721s2-common-proc-board.dtb
-
-dtb-$(CONFIG_ARCH_K3) += k3-am642-evm.dtb
-dtb-$(CONFIG_ARCH_K3) += k3-am642-sk.dtb
-
-dtb-$(CONFIG_ARCH_K3) += k3-am625-sk.dtb
-
-dtb-$(CONFIG_ARCH_K3) += k3-am62a7-sk.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-csi2-ov5640.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-fusion.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j721s2-evm-gesi-exp-board.dtbo
+
+# Boards with J722s SoC
+dtb-$(CONFIG_ARCH_K3) += k3-j722s-evm.dtb
+
+# Boards with J784s4 SoC
+dtb-$(CONFIG_ARCH_K3) += k3-am69-sk.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-am69-sk-csi2-ov5640.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am69-sk-ddr-mem-carveout.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am69-sk-csi2-rpi-cam-imx219.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am69-sk-fpdlink-fusion.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am69-sk-rpi-hdr-ehrpwm.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j784s4-evm.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-j784s4-evm-csi2-ov5640.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j784s4-evm-quad-port-eth-exp1.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j784s4-evm-usxgmii-exp1-exp2.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-j784s4-evm-virt-mac-client.dtbo
+
+# Common overlays across AM62 family of boards
+dtb-$(CONFIG_ARCH_K3) += k3-am62x-sk-eqep.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62x-sk-csi2-imx219.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62x-sk-csi2-ov5640.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62x-sk-csi2-tevi-ov5640.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62x-sk-hdmi-audio.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62x-sk-lpm-wkup-sources.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-am62x-sk-mcan.dtbo
+
+# FPDLink Sensors
+dtb-$(CONFIG_ARCH_K3) += k3-fpdlink-imx390-rcm-0-0.dtbo \
+			 k3-fpdlink-imx390-rcm-0-1.dtbo \
+			 k3-fpdlink-imx390-rcm-0-2.dtbo \
+			 k3-fpdlink-imx390-rcm-0-3.dtbo \
+			 k3-fpdlink-imx390-rcm-1-0.dtbo \
+			 k3-fpdlink-imx390-rcm-1-1.dtbo \
+			 k3-fpdlink-imx390-rcm-1-2.dtbo \
+			 k3-fpdlink-imx390-rcm-1-3.dtbo
+dtb-$(CONFIG_ARCH_K3) += k3-fpdlink-ov2312-0-0.dtbo \
+			 k3-fpdlink-ov2312-0-1.dtbo \
+			 k3-fpdlink-ov2312-0-2.dtbo \
+			 k3-fpdlink-ov2312-0-3.dtbo
+
+#Enable support for device-tree overlays
+DTC_FLAGS_k3-am62-lp-sk += -@
+DTC_FLAGS_k3-am625-beagleplay += -@
+DTC_FLAGS_k3-am625-sk += -@
+DTC_FLAGS_k3-am625-sk-lpmdemo += -@
+DTC_FLAGS_k3-am62a7-sk += -@
+DTC_FLAGS_k3-am62a7-sk-fusion += -@
+DTC_FLAGS_k3-am62a7-sk-ub954-evm += -@
+DTC_FLAGS_k3-am62p5-sk += -@
+DTC_FLAGS_k3-am654-base-board += -@
+DTC_FLAGS_k3-am68-sk-base-board += -@
+DTC_FLAGS_k3-am69-sk += -@
+DTC_FLAGS_k3-j7200-common-proc-board += -@
+DTC_FLAGS_k3-j721e-beagleboneai64 += -@
+DTC_FLAGS_k3-j721e-common-proc-board += -@
+DTC_FLAGS_k3-j721e-evm-fusion += -@
+DTC_FLAGS_k3-j721e-sk += -@
+DTC_FLAGS_k3-j721e-sk-fusion += -@
+DTC_FLAGS_k3-j721s2-common-proc-board += -@
+DTC_FLAGS_k3-j721s2-evm-fusion += -@
+DTC_FLAGS_k3-j784s4-evm += -@
+DTC_FLAGS_k3-am642-evm += -@
diff -Naur --no-dereference a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dts
--- a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,315 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * dts file for KV260 revA Carrier Card
- *
- * (C) Copyright 2020 - 2021, Xilinx, Inc.
- *
- * SD level shifter:
- * "A" – A01 board un-modified (NXP)
- * "Y" – A01 board modified with legacy interposer (Nexperia)
- * "Z" – A01 board modified with Diode interposer
- *
- * Michal Simek <michal.simek@xilinx.com>
- */
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/net/ti-dp83867.h>
-#include <dt-bindings/phy/phy.h>
-#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
-
-/dts-v1/;
-/plugin/;
-
-&i2c1 { /* I2C_SCK C23/C24 - MIO from SOM */
-	#address-cells = <1>;
-	#size-cells = <0>;
-	pinctrl-names = "default", "gpio";
-	pinctrl-0 = <&pinctrl_i2c1_default>;
-	pinctrl-1 = <&pinctrl_i2c1_gpio>;
-	scl-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
-	sda-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
-
-	/* u14 - 0x40 - ina260 */
-	/* u27 - 0xe0 - STDP4320 DP/HDMI splitter */
-};
-
-&amba {
-	si5332_0: si5332_0 { /* u17 */
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <125000000>;
-	};
-
-	si5332_1: si5332_1 { /* u17 */
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <25000000>;
-	};
-
-	si5332_2: si5332_2 { /* u17 */
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <48000000>;
-	};
-
-	si5332_3: si5332_3 { /* u17 */
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <24000000>;
-	};
-
-	si5332_4: si5332_4 { /* u17 */
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <26000000>;
-	};
-
-	si5332_5: si5332_5 { /* u17 */
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <27000000>;
-	};
-};
-
-/* DP/USB 3.0 and SATA */
-&psgtr {
-	status = "okay";
-	/* pcie, usb3, sata */
-	clocks = <&si5332_5>, <&si5332_4>, <&si5332_0>;
-	clock-names = "ref0", "ref1", "ref2";
-};
-
-&sata {
-	status = "okay";
-	/* SATA OOB timing settings */
-	ceva,p0-cominit-params = /bits/ 8 <0x18 0x40 0x18 0x28>;
-	ceva,p0-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
-	ceva,p0-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
-	ceva,p0-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
-	ceva,p1-cominit-params = /bits/ 8 <0x18 0x40 0x18 0x28>;
-	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
-	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
-	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
-	phy-names = "sata-phy";
-	phys = <&psgtr 3 PHY_TYPE_SATA 1 2>;
-};
-
-&zynqmp_dpsub {
-	status = "disabled";
-	phy-names = "dp-phy0", "dp-phy1";
-	phys = <&psgtr 1 PHY_TYPE_DP 0 0>, <&psgtr 0 PHY_TYPE_DP 1 0>;
-};
-
-&zynqmp_dpdma {
-	status = "okay";
-};
-
-&usb0 {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usb0_default>;
-	phy-names = "usb3-phy";
-	phys = <&psgtr 2 PHY_TYPE_USB3 0 1>;
-	/* missing usb5744 - u43 */
-};
-
-&dwc3_0 {
-	status = "okay";
-	dr_mode = "host";
-	snps,usb3_lpm_capable;
-	maximum-speed = "super-speed";
-};
-
-&sdhci1 { /* on CC with tuned parameters */
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_sdhci1_default>;
-	/*
-	 * SD 3.0 requires level shifter and this property
-	 * should be removed if the board has level shifter and
-	 * need to work in UHS mode
-	 */
-	no-1-8-v;
-	disable-wp;
-	xlnx,mio-bank = <1>;
-};
-
-&gem3 { /* required by spec */
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_gem3_default>;
-	phy-handle = <&phy0>;
-	phy-mode = "rgmii-id";
-
-	mdio: mdio {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		reset-gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
-		reset-delay-us = <2>;
-
-		phy0: ethernet-phy@1 {
-			#phy-cells = <1>;
-			reg = <1>;
-			ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
-			ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>;
-			ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
-			ti,dp83867-rxctrl-strap-quirk;
-		};
-	};
-};
-
-&pinctrl0 { /* required by spec */
-	status = "okay";
-
-	pinctrl_uart1_default: uart1-default {
-		conf {
-			groups = "uart1_9_grp";
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-			drive-strength = <12>;
-		};
-
-		conf-rx {
-			pins = "MIO37";
-			bias-high-impedance;
-		};
-
-		conf-tx {
-			pins = "MIO36";
-			bias-disable;
-		};
-
-		mux {
-			groups = "uart1_9_grp";
-			function = "uart1";
-		};
-	};
-
-	pinctrl_i2c1_default: i2c1-default {
-		conf {
-			groups = "i2c1_6_grp";
-			bias-pull-up;
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-		};
-
-		mux {
-			groups = "i2c1_6_grp";
-			function = "i2c1";
-		};
-	};
-
-	pinctrl_i2c1_gpio: i2c1-gpio {
-		conf {
-			groups = "gpio0_24_grp", "gpio0_25_grp";
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-		};
-
-		mux {
-			groups = "gpio0_24_grp", "gpio0_25_grp";
-			function = "gpio0";
-		};
-	};
-
-	pinctrl_gem3_default: gem3-default {
-		conf {
-			groups = "ethernet3_0_grp";
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-		};
-
-		conf-rx {
-			pins = "MIO70", "MIO72", "MIO74";
-			bias-high-impedance;
-			low-power-disable;
-		};
-
-		conf-bootstrap {
-			pins = "MIO71", "MIO73", "MIO75";
-			bias-disable;
-			low-power-disable;
-		};
-
-		conf-tx {
-			pins = "MIO64", "MIO65", "MIO66",
-				"MIO67", "MIO68", "MIO69";
-			bias-disable;
-			low-power-enable;
-		};
-
-		conf-mdio {
-			groups = "mdio3_0_grp";
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-			bias-disable;
-		};
-
-		mux-mdio {
-			function = "mdio3";
-			groups = "mdio3_0_grp";
-		};
-
-		mux {
-			function = "ethernet3";
-			groups = "ethernet3_0_grp";
-		};
-	};
-
-	pinctrl_usb0_default: usb0-default {
-		conf {
-			groups = "usb0_0_grp";
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-		};
-
-		conf-rx {
-			pins = "MIO52", "MIO53", "MIO55";
-			bias-high-impedance;
-		};
-
-		conf-tx {
-			pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
-			"MIO60", "MIO61", "MIO62", "MIO63";
-			bias-disable;
-		};
-
-		mux {
-			groups = "usb0_0_grp";
-			function = "usb0";
-		};
-	};
-
-	pinctrl_sdhci1_default: sdhci1-default {
-		conf {
-			groups = "sdio1_0_grp";
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-			bias-disable;
-		};
-
-		conf-cd {
-			groups = "sdio1_cd_0_grp";
-			bias-high-impedance;
-			bias-pull-up;
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-		};
-
-		mux-cd {
-			groups = "sdio1_cd_0_grp";
-			function = "sdio1_cd";
-		};
-
-		mux {
-			groups = "sdio1_0_grp";
-			function = "sdio1";
-		};
-	};
-};
-
-&uart1 {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_default>;
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso
--- a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revA.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,315 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dts file for KV260 revA Carrier Card
+ *
+ * (C) Copyright 2020 - 2021, Xilinx, Inc.
+ *
+ * SD level shifter:
+ * "A" – A01 board un-modified (NXP)
+ * "Y" – A01 board modified with legacy interposer (Nexperia)
+ * "Z" – A01 board modified with Diode interposer
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+
+/dts-v1/;
+/plugin/;
+
+&i2c1 { /* I2C_SCK C23/C24 - MIO from SOM */
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
+
+	/* u14 - 0x40 - ina260 */
+	/* u27 - 0xe0 - STDP4320 DP/HDMI splitter */
+};
+
+&amba {
+	si5332_0: si5332_0 { /* u17 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <125000000>;
+	};
+
+	si5332_1: si5332_1 { /* u17 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+
+	si5332_2: si5332_2 { /* u17 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <48000000>;
+	};
+
+	si5332_3: si5332_3 { /* u17 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+	};
+
+	si5332_4: si5332_4 { /* u17 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+	};
+
+	si5332_5: si5332_5 { /* u17 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <27000000>;
+	};
+};
+
+/* DP/USB 3.0 and SATA */
+&psgtr {
+	status = "okay";
+	/* pcie, usb3, sata */
+	clocks = <&si5332_5>, <&si5332_4>, <&si5332_0>;
+	clock-names = "ref0", "ref1", "ref2";
+};
+
+&sata {
+	status = "okay";
+	/* SATA OOB timing settings */
+	ceva,p0-cominit-params = /bits/ 8 <0x18 0x40 0x18 0x28>;
+	ceva,p0-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
+	ceva,p0-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
+	ceva,p0-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	ceva,p1-cominit-params = /bits/ 8 <0x18 0x40 0x18 0x28>;
+	ceva,p1-comwake-params = /bits/ 8 <0x06 0x14 0x08 0x0E>;
+	ceva,p1-burst-params = /bits/ 8 <0x13 0x08 0x4A 0x06>;
+	ceva,p1-retry-params = /bits/ 16 <0x96A4 0x3FFC>;
+	phy-names = "sata-phy";
+	phys = <&psgtr 3 PHY_TYPE_SATA 1 2>;
+};
+
+&zynqmp_dpsub {
+	status = "disabled";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&psgtr 1 PHY_TYPE_DP 0 0>, <&psgtr 0 PHY_TYPE_DP 1 0>;
+};
+
+&zynqmp_dpdma {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb0_default>;
+	phy-names = "usb3-phy";
+	phys = <&psgtr 2 PHY_TYPE_USB3 0 1>;
+	/* missing usb5744 - u43 */
+};
+
+&dwc3_0 {
+	status = "okay";
+	dr_mode = "host";
+	snps,usb3_lpm_capable;
+	maximum-speed = "super-speed";
+};
+
+&sdhci1 { /* on CC with tuned parameters */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci1_default>;
+	/*
+	 * SD 3.0 requires level shifter and this property
+	 * should be removed if the board has level shifter and
+	 * need to work in UHS mode
+	 */
+	no-1-8-v;
+	disable-wp;
+	xlnx,mio-bank = <1>;
+};
+
+&gem3 { /* required by spec */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gem3_default>;
+	phy-handle = <&phy0>;
+	phy-mode = "rgmii-id";
+
+	mdio: mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reset-gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
+		reset-delay-us = <2>;
+
+		phy0: ethernet-phy@1 {
+			#phy-cells = <1>;
+			reg = <1>;
+			ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+			ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>;
+			ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+			ti,dp83867-rxctrl-strap-quirk;
+		};
+	};
+};
+
+&pinctrl0 { /* required by spec */
+	status = "okay";
+
+	pinctrl_uart1_default: uart1-default {
+		conf {
+			groups = "uart1_9_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+
+		conf-rx {
+			pins = "MIO37";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO36";
+			bias-disable;
+		};
+
+		mux {
+			groups = "uart1_9_grp";
+			function = "uart1";
+		};
+	};
+
+	pinctrl_i2c1_default: i2c1-default {
+		conf {
+			groups = "i2c1_6_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux {
+			groups = "i2c1_6_grp";
+			function = "i2c1";
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		conf {
+			groups = "gpio0_24_grp", "gpio0_25_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux {
+			groups = "gpio0_24_grp", "gpio0_25_grp";
+			function = "gpio0";
+		};
+	};
+
+	pinctrl_gem3_default: gem3-default {
+		conf {
+			groups = "ethernet3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO70", "MIO72", "MIO74";
+			bias-high-impedance;
+			low-power-disable;
+		};
+
+		conf-bootstrap {
+			pins = "MIO71", "MIO73", "MIO75";
+			bias-disable;
+			low-power-disable;
+		};
+
+		conf-tx {
+			pins = "MIO64", "MIO65", "MIO66",
+				"MIO67", "MIO68", "MIO69";
+			bias-disable;
+			low-power-enable;
+		};
+
+		conf-mdio {
+			groups = "mdio3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+
+		mux-mdio {
+			function = "mdio3";
+			groups = "mdio3_0_grp";
+		};
+
+		mux {
+			function = "ethernet3";
+			groups = "ethernet3_0_grp";
+		};
+	};
+
+	pinctrl_usb0_default: usb0-default {
+		conf {
+			groups = "usb0_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO52", "MIO53", "MIO55";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
+			"MIO60", "MIO61", "MIO62", "MIO63";
+			bias-disable;
+		};
+
+		mux {
+			groups = "usb0_0_grp";
+			function = "usb0";
+		};
+	};
+
+	pinctrl_sdhci1_default: sdhci1-default {
+		conf {
+			groups = "sdio1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+
+		conf-cd {
+			groups = "sdio1_cd_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-cd {
+			groups = "sdio1_cd_0_grp";
+			function = "sdio1_cd";
+		};
+
+		mux {
+			groups = "sdio1_0_grp";
+			function = "sdio1";
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_default>;
+};
diff -Naur --no-dereference a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dts b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dts
--- a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,298 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * dts file for KV260 revA Carrier Card
- *
- * (C) Copyright 2020 - 2021, Xilinx, Inc.
- *
- * Michal Simek <michal.simek@xilinx.com>
- */
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/net/ti-dp83867.h>
-#include <dt-bindings/phy/phy.h>
-#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
-
-/dts-v1/;
-/plugin/;
-
-&i2c1 { /* I2C_SCK C23/C24 - MIO from SOM */
-	#address-cells = <1>;
-	#size-cells = <0>;
-	pinctrl-names = "default", "gpio";
-	pinctrl-0 = <&pinctrl_i2c1_default>;
-	pinctrl-1 = <&pinctrl_i2c1_gpio>;
-	scl-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
-	sda-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
-
-	/* u14 - 0x40 - ina260 */
-	/* u43 - 0x2d - usb5744 */
-	/* u27 - 0xe0 - STDP4320 DP/HDMI splitter */
-};
-
-&amba {
-	si5332_0: si5332_0 { /* u17 */
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <125000000>;
-	};
-
-	si5332_1: si5332_1 { /* u17 */
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <25000000>;
-	};
-
-	si5332_2: si5332_2 { /* u17 */
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <48000000>;
-	};
-
-	si5332_3: si5332_3 { /* u17 */
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <24000000>;
-	};
-
-	si5332_4: si5332_4 { /* u17 */
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <26000000>;
-	};
-
-	si5332_5: si5332_5 { /* u17 */
-		compatible = "fixed-clock";
-		#clock-cells = <0>;
-		clock-frequency = <27000000>;
-	};
-};
-
-/* DP/USB 3.0 */
-&psgtr {
-	status = "okay";
-	/* pcie, usb3, sata */
-	clocks = <&si5332_5>, <&si5332_4>, <&si5332_0>;
-	clock-names = "ref0", "ref1", "ref2";
-};
-
-&zynqmp_dpsub {
-	status = "disabled";
-	phy-names = "dp-phy0", "dp-phy1";
-	phys = <&psgtr 1 PHY_TYPE_DP 0 0>, <&psgtr 0 PHY_TYPE_DP 1 0>;
-};
-
-&zynqmp_dpdma {
-	status = "okay";
-};
-
-&usb0 {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usb0_default>;
-	phy-names = "usb3-phy";
-	phys = <&psgtr 2 PHY_TYPE_USB3 0 1>;
-};
-
-&dwc3_0 {
-	status = "okay";
-	dr_mode = "host";
-	snps,usb3_lpm_capable;
-	maximum-speed = "super-speed";
-};
-
-&sdhci1 { /* on CC with tuned parameters */
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_sdhci1_default>;
-	/*
-	 * SD 3.0 requires level shifter and this property
-	 * should be removed if the board has level shifter and
-	 * need to work in UHS mode
-	 */
-	no-1-8-v;
-	disable-wp;
-	xlnx,mio-bank = <1>;
-	clk-phase-sd-hs = <126>, <60>;
-	clk-phase-uhs-sdr25 = <120>, <60>;
-	clk-phase-uhs-ddr50 = <126>, <48>;
-};
-
-&gem3 { /* required by spec */
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_gem3_default>;
-	phy-handle = <&phy0>;
-	phy-mode = "rgmii-id";
-
-	mdio: mdio {
-		#address-cells = <1>;
-		#size-cells = <0>;
-		reset-gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
-		reset-delay-us = <2>;
-
-		phy0: ethernet-phy@1 {
-			#phy-cells = <1>;
-			reg = <1>;
-			ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
-			ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>;
-			ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
-			ti,dp83867-rxctrl-strap-quirk;
-		};
-	};
-};
-
-&pinctrl0 { /* required by spec */
-	status = "okay";
-
-	pinctrl_uart1_default: uart1-default {
-		conf {
-			groups = "uart1_9_grp";
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-			drive-strength = <12>;
-		};
-
-		conf-rx {
-			pins = "MIO37";
-			bias-high-impedance;
-		};
-
-		conf-tx {
-			pins = "MIO36";
-			bias-disable;
-		};
-
-		mux {
-			groups = "uart1_9_grp";
-			function = "uart1";
-		};
-	};
-
-	pinctrl_i2c1_default: i2c1-default {
-		conf {
-			groups = "i2c1_6_grp";
-			bias-pull-up;
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-		};
-
-		mux {
-			groups = "i2c1_6_grp";
-			function = "i2c1";
-		};
-	};
-
-	pinctrl_i2c1_gpio: i2c1-gpio {
-		conf {
-			groups = "gpio0_24_grp", "gpio0_25_grp";
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-		};
-
-		mux {
-			groups = "gpio0_24_grp", "gpio0_25_grp";
-			function = "gpio0";
-		};
-	};
-
-	pinctrl_gem3_default: gem3-default {
-		conf {
-			groups = "ethernet3_0_grp";
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-		};
-
-		conf-rx {
-			pins = "MIO70", "MIO72", "MIO74";
-			bias-high-impedance;
-			low-power-disable;
-		};
-
-		conf-bootstrap {
-			pins = "MIO71", "MIO73", "MIO75";
-			bias-disable;
-			low-power-disable;
-		};
-
-		conf-tx {
-			pins = "MIO64", "MIO65", "MIO66",
-				"MIO67", "MIO68", "MIO69";
-			bias-disable;
-			low-power-enable;
-		};
-
-		conf-mdio {
-			groups = "mdio3_0_grp";
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-			bias-disable;
-		};
-
-		mux-mdio {
-			function = "mdio3";
-			groups = "mdio3_0_grp";
-		};
-
-		mux {
-			function = "ethernet3";
-			groups = "ethernet3_0_grp";
-		};
-	};
-
-	pinctrl_usb0_default: usb0-default {
-		conf {
-			groups = "usb0_0_grp";
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-		};
-
-		conf-rx {
-			pins = "MIO52", "MIO53", "MIO55";
-			bias-high-impedance;
-		};
-
-		conf-tx {
-			pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
-			"MIO60", "MIO61", "MIO62", "MIO63";
-			bias-disable;
-		};
-
-		mux {
-			groups = "usb0_0_grp";
-			function = "usb0";
-		};
-	};
-
-	pinctrl_sdhci1_default: sdhci1-default {
-		conf {
-			groups = "sdio1_0_grp";
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-			bias-disable;
-		};
-
-		conf-cd {
-			groups = "sdio1_cd_0_grp";
-			bias-high-impedance;
-			bias-pull-up;
-			slew-rate = <SLEW_RATE_SLOW>;
-			power-source = <IO_STANDARD_LVCMOS18>;
-		};
-
-		mux-cd {
-			groups = "sdio1_cd_0_grp";
-			function = "sdio1_cd";
-		};
-
-		mux {
-			groups = "sdio1_0_grp";
-			function = "sdio1";
-		};
-	};
-};
-
-&uart1 {
-	status = "okay";
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_default>;
-};
diff -Naur --no-dereference a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso
--- a/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-sck-kv-g-revB.dtso	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,298 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * dts file for KV260 revA Carrier Card
+ *
+ * (C) Copyright 2020 - 2021, Xilinx, Inc.
+ *
+ * Michal Simek <michal.simek@xilinx.com>
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/pinctrl/pinctrl-zynqmp.h>
+
+/dts-v1/;
+/plugin/;
+
+&i2c1 { /* I2C_SCK C23/C24 - MIO from SOM */
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default", "gpio";
+	pinctrl-0 = <&pinctrl_i2c1_default>;
+	pinctrl-1 = <&pinctrl_i2c1_gpio>;
+	scl-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
+	sda-gpios = <&gpio 25 GPIO_ACTIVE_HIGH>;
+
+	/* u14 - 0x40 - ina260 */
+	/* u43 - 0x2d - usb5744 */
+	/* u27 - 0xe0 - STDP4320 DP/HDMI splitter */
+};
+
+&amba {
+	si5332_0: si5332_0 { /* u17 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <125000000>;
+	};
+
+	si5332_1: si5332_1 { /* u17 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <25000000>;
+	};
+
+	si5332_2: si5332_2 { /* u17 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <48000000>;
+	};
+
+	si5332_3: si5332_3 { /* u17 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <24000000>;
+	};
+
+	si5332_4: si5332_4 { /* u17 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <26000000>;
+	};
+
+	si5332_5: si5332_5 { /* u17 */
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <27000000>;
+	};
+};
+
+/* DP/USB 3.0 */
+&psgtr {
+	status = "okay";
+	/* pcie, usb3, sata */
+	clocks = <&si5332_5>, <&si5332_4>, <&si5332_0>;
+	clock-names = "ref0", "ref1", "ref2";
+};
+
+&zynqmp_dpsub {
+	status = "disabled";
+	phy-names = "dp-phy0", "dp-phy1";
+	phys = <&psgtr 1 PHY_TYPE_DP 0 0>, <&psgtr 0 PHY_TYPE_DP 1 0>;
+};
+
+&zynqmp_dpdma {
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usb0_default>;
+	phy-names = "usb3-phy";
+	phys = <&psgtr 2 PHY_TYPE_USB3 0 1>;
+};
+
+&dwc3_0 {
+	status = "okay";
+	dr_mode = "host";
+	snps,usb3_lpm_capable;
+	maximum-speed = "super-speed";
+};
+
+&sdhci1 { /* on CC with tuned parameters */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdhci1_default>;
+	/*
+	 * SD 3.0 requires level shifter and this property
+	 * should be removed if the board has level shifter and
+	 * need to work in UHS mode
+	 */
+	no-1-8-v;
+	disable-wp;
+	xlnx,mio-bank = <1>;
+	clk-phase-sd-hs = <126>, <60>;
+	clk-phase-uhs-sdr25 = <120>, <60>;
+	clk-phase-uhs-ddr50 = <126>, <48>;
+};
+
+&gem3 { /* required by spec */
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gem3_default>;
+	phy-handle = <&phy0>;
+	phy-mode = "rgmii-id";
+
+	mdio: mdio {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reset-gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
+		reset-delay-us = <2>;
+
+		phy0: ethernet-phy@1 {
+			#phy-cells = <1>;
+			reg = <1>;
+			ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_25_NS>;
+			ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_75_NS>;
+			ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+			ti,dp83867-rxctrl-strap-quirk;
+		};
+	};
+};
+
+&pinctrl0 { /* required by spec */
+	status = "okay";
+
+	pinctrl_uart1_default: uart1-default {
+		conf {
+			groups = "uart1_9_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+			drive-strength = <12>;
+		};
+
+		conf-rx {
+			pins = "MIO37";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO36";
+			bias-disable;
+		};
+
+		mux {
+			groups = "uart1_9_grp";
+			function = "uart1";
+		};
+	};
+
+	pinctrl_i2c1_default: i2c1-default {
+		conf {
+			groups = "i2c1_6_grp";
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux {
+			groups = "i2c1_6_grp";
+			function = "i2c1";
+		};
+	};
+
+	pinctrl_i2c1_gpio: i2c1-gpio {
+		conf {
+			groups = "gpio0_24_grp", "gpio0_25_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux {
+			groups = "gpio0_24_grp", "gpio0_25_grp";
+			function = "gpio0";
+		};
+	};
+
+	pinctrl_gem3_default: gem3-default {
+		conf {
+			groups = "ethernet3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO70", "MIO72", "MIO74";
+			bias-high-impedance;
+			low-power-disable;
+		};
+
+		conf-bootstrap {
+			pins = "MIO71", "MIO73", "MIO75";
+			bias-disable;
+			low-power-disable;
+		};
+
+		conf-tx {
+			pins = "MIO64", "MIO65", "MIO66",
+				"MIO67", "MIO68", "MIO69";
+			bias-disable;
+			low-power-enable;
+		};
+
+		conf-mdio {
+			groups = "mdio3_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+
+		mux-mdio {
+			function = "mdio3";
+			groups = "mdio3_0_grp";
+		};
+
+		mux {
+			function = "ethernet3";
+			groups = "ethernet3_0_grp";
+		};
+	};
+
+	pinctrl_usb0_default: usb0-default {
+		conf {
+			groups = "usb0_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+		};
+
+		conf-rx {
+			pins = "MIO52", "MIO53", "MIO55";
+			bias-high-impedance;
+		};
+
+		conf-tx {
+			pins = "MIO54", "MIO56", "MIO57", "MIO58", "MIO59",
+			"MIO60", "MIO61", "MIO62", "MIO63";
+			bias-disable;
+		};
+
+		mux {
+			groups = "usb0_0_grp";
+			function = "usb0";
+		};
+	};
+
+	pinctrl_sdhci1_default: sdhci1-default {
+		conf {
+			groups = "sdio1_0_grp";
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+			bias-disable;
+		};
+
+		conf-cd {
+			groups = "sdio1_cd_0_grp";
+			bias-high-impedance;
+			bias-pull-up;
+			slew-rate = <SLEW_RATE_SLOW>;
+			power-source = <IO_STANDARD_LVCMOS18>;
+		};
+
+		mux-cd {
+			groups = "sdio1_cd_0_grp";
+			function = "sdio1_cd";
+		};
+
+		mux {
+			groups = "sdio1_0_grp";
+			function = "sdio1";
+		};
+	};
+};
+
+&uart1 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1_default>;
+};
diff -Naur --no-dereference a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
--- a/arch/arm64/configs/defconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/arch/arm64/configs/defconfig	2024-01-28 14:01:31.240353775 -0500
@@ -17,6 +17,8 @@
 CONFIG_NUMA_BALANCING=y
 CONFIG_MEMCG=y
 CONFIG_BLK_CGROUP=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_RT_GROUP_SCHED=y
 CONFIG_CGROUP_PIDS=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CGROUP_HUGETLB=y
@@ -25,10 +27,12 @@
 CONFIG_CGROUP_CPUACCT=y
 CONFIG_CGROUP_PERF=y
 CONFIG_CGROUP_BPF=y
+CONFIG_NAMESPACES=y
 CONFIG_USER_NS=y
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_ARCH_ACTIONS=y
 CONFIG_ARCH_SUNXI=y
@@ -36,13 +40,12 @@
 CONFIG_ARCH_APPLE=y
 CONFIG_ARCH_BCM=y
 CONFIG_ARCH_BCM2835=y
-CONFIG_ARCH_BCMBCA=y
 CONFIG_ARCH_BCM_IPROC=y
-CONFIG_ARCH_BERLIN=y
+CONFIG_ARCH_BCMBCA=y
 CONFIG_ARCH_BRCMSTB=y
+CONFIG_ARCH_BERLIN=y
 CONFIG_ARCH_EXYNOS=y
 CONFIG_ARCH_K3=y
-CONFIG_ARCH_LAYERSCAPE=y
 CONFIG_ARCH_LG1K=y
 CONFIG_ARCH_HISI=y
 CONFIG_ARCH_KEEMBAY=y
@@ -50,12 +53,13 @@
 CONFIG_ARCH_MESON=y
 CONFIG_ARCH_MVEBU=y
 CONFIG_ARCH_NXP=y
+CONFIG_ARCH_LAYERSCAPE=y
 CONFIG_ARCH_MXC=y
+CONFIG_ARCH_S32=y
 CONFIG_ARCH_NPCM=y
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_RENESAS=y
 CONFIG_ARCH_ROCKCHIP=y
-CONFIG_ARCH_S32=y
 CONFIG_ARCH_SEATTLE=y
 CONFIG_ARCH_INTEL_SOCFPGA=y
 CONFIG_ARCH_SYNQUACER=y
@@ -112,20 +116,10 @@
 CONFIG_ACPI_APEI_EINJ=y
 CONFIG_VIRTUALIZATION=y
 CONFIG_KVM=y
-CONFIG_CRYPTO_SHA1_ARM64_CE=y
-CONFIG_CRYPTO_SHA2_ARM64_CE=y
-CONFIG_CRYPTO_SHA512_ARM64_CE=m
-CONFIG_CRYPTO_SHA3_ARM64=m
-CONFIG_CRYPTO_SM3_ARM64_CE=m
-CONFIG_CRYPTO_GHASH_ARM64_CE=y
-CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=m
-CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
-CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
-CONFIG_CRYPTO_CHACHA20_NEON=m
-CONFIG_CRYPTO_AES_ARM64_BS=m
 CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
+CONFIG_BLK_DEV_THROTTLING=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_MEMORY_HOTPLUG=y
@@ -136,16 +130,21 @@
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XDP_SOCKETS=y
 CONFIG_INET=y
 CONFIG_IP_MULTICAST=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
+CONFIG_INET_ESP=y
 CONFIG_IPV6=m
 CONFIG_NETFILTER=y
 CONFIG_BRIDGE_NETFILTER=m
 CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_TFTP=m
 CONFIG_NETFILTER_XT_MARK=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
 CONFIG_NETFILTER_XT_TARGET_LOG=m
@@ -153,11 +152,16 @@
 CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
 CONFIG_NETFILTER_XT_MATCH_IPVS=m
 CONFIG_IP_VS=m
+CONFIG_IP_VS_PROTO_TCP=y
+CONFIG_IP_VS_PROTO_UDP=y
+CONFIG_IP_VS_RR=m
+CONFIG_IP_VS_NFCT=y
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
 CONFIG_IP_NF_MANGLE=m
 CONFIG_IP6_NF_IPTABLES=m
 CONFIG_IP6_NF_FILTER=m
@@ -178,18 +182,38 @@
 CONFIG_NET_SCH_MQPRIO=m
 CONFIG_NET_SCH_INGRESS=m
 CONFIG_NET_CLS_BASIC=m
+CONFIG_NET_CLS_ROUTE4=m
+CONFIG_NET_CLS_FW=m
+CONFIG_NET_CLS_U32=m
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_RSVP=m
+CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_CLS_FLOW=m
+CONFIG_NET_CLS_CGROUP=m
 CONFIG_NET_CLS_FLOWER=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
+CONFIG_NET_EMATCH_TEXT=m
 CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_POLICE=m
 CONFIG_NET_ACT_GACT=m
+CONFIG_GACT_PROB=y
 CONFIG_NET_ACT_MIRRED=m
+CONFIG_NET_ACT_IPT=m
+CONFIG_NET_ACT_NAT=m
+CONFIG_NET_ACT_PEDIT=m
+CONFIG_NET_ACT_SIMP=m
+CONFIG_NET_ACT_SKBEDIT=m
+CONFIG_NET_ACT_CSUM=m
 CONFIG_NET_ACT_GATE=m
+CONFIG_HSR=m
 CONFIG_QRTR_SMD=m
 CONFIG_QRTR_TUN=m
+CONFIG_CGROUP_NET_PRIO=y
 CONFIG_CAN=m
-CONFIG_CAN_FLEXCAN=m
-CONFIG_CAN_RCAR=m
-CONFIG_CAN_RCAR_CANFD=m
-CONFIG_CAN_MCP251XFD=m
 CONFIG_BT=m
 CONFIG_BT_HIDP=m
 # CONFIG_BT_LE is not set
@@ -206,7 +230,6 @@
 CONFIG_BT_QCOMSMD=m
 CONFIG_CFG80211=m
 CONFIG_MAC80211=m
-CONFIG_MAC80211_LEDS=y
 CONFIG_RFKILL=m
 CONFIG_NET_9P=y
 CONFIG_NET_9P_VIRTIO=y
@@ -233,6 +256,8 @@
 CONFIG_PCIE_ROCKCHIP_HOST=m
 CONFIG_PCIE_BRCMSTB=m
 CONFIG_PCI_IMX6=y
+CONFIG_PCI_KEYSTONE_HOST=y
+CONFIG_PCI_KEYSTONE_EP=y
 CONFIG_PCI_LAYERSCAPE=y
 CONFIG_PCI_HISI=y
 CONFIG_PCIE_QCOM=y
@@ -242,9 +267,12 @@
 CONFIG_PCIE_TEGRA194_HOST=m
 CONFIG_PCIE_VISCONTI_HOST=y
 CONFIG_PCIE_LAYERSCAPE_GEN4=y
+CONFIG_PCI_J721E_HOST=m
+CONFIG_PCI_J721E_EP=m
 CONFIG_PCI_ENDPOINT=y
 CONFIG_PCI_ENDPOINT_CONFIGFS=y
-CONFIG_PCI_EPF_TEST=m
+CONFIG_PCI_EPF_TEST=y
+CONFIG_PCI_EPF_NTB=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_FW_LOADER_USER_HELPER=y
@@ -261,6 +289,8 @@
 CONFIG_GNSS=m
 CONFIG_GNSS_MTK_SERIAL=m
 CONFIG_MTD=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_ADV_OPTIONS=y
@@ -273,11 +303,17 @@
 CONFIG_MTD_SST25L=y
 CONFIG_MTD_RAW_NAND=y
 CONFIG_MTD_NAND_DENALI_DT=y
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_NAND_OMAP_BCH=y
 CONFIG_MTD_NAND_MARVELL=y
 CONFIG_MTD_NAND_BRCMNAND=m
 CONFIG_MTD_NAND_FSL_IFC=y
 CONFIG_MTD_NAND_QCOM=y
+CONFIG_MTD_SPI_NAND=y
 CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_HYPERBUS=m
+CONFIG_HBMC_AM654=m
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=m
 CONFIG_VIRTIO_BLK=y
@@ -285,6 +321,7 @@
 CONFIG_QCOM_COINCELL=m
 CONFIG_QCOM_FASTRPC=m
 CONFIG_SRAM=y
+CONFIG_SRAM_DMA_HEAP=y
 CONFIG_PCI_ENDPOINT_TEST=m
 CONFIG_EEPROM_AT24=m
 CONFIG_EEPROM_AT25=m
@@ -306,16 +343,19 @@
 CONFIG_AHCI_QORIQ=y
 CONFIG_SATA_SIL24=y
 CONFIG_SATA_RCAR=y
-CONFIG_PATA_PLATFORM=y
 CONFIG_PATA_OF_PLATFORM=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_MD=m
 CONFIG_BLK_DEV_DM=m
+CONFIG_DM_THIN_PROVISIONING=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
 CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
 CONFIG_MACVLAN=m
 CONFIG_MACVTAP=m
+CONFIG_IPVLAN=m
+CONFIG_VXLAN=m
 CONFIG_TUN=y
 CONFIG_VETH=m
 CONFIG_VIRTIO_NET=y
@@ -362,8 +402,13 @@
 CONFIG_SNI_AVE=y
 CONFIG_SNI_NETSEC=y
 CONFIG_STMMAC_ETH=m
-CONFIG_DWMAC_TEGRA=m
+CONFIG_TI_CPSW_PROXY_CLIENT=m
 CONFIG_TI_K3_AM65_CPSW_NUSS=y
+CONFIG_TI_K3_AM65_CPSW_SWITCHDEV=y
+CONFIG_TI_K3_AM65_CPTS=y
+CONFIG_TI_AM65_CPSW_TAS=y
+CONFIG_TI_RDEV_ETH_SWITCH_VIRT_EMAC=m
+CONFIG_TI_ICSSG_PRUETH=m
 CONFIG_QCOM_IPA=m
 CONFIG_MESON_GXL_PHY=m
 CONFIG_AQUANTIA_PHY=y
@@ -376,7 +421,16 @@
 CONFIG_REALTEK_PHY=y
 CONFIG_ROCKCHIP_PHY=y
 CONFIG_DP83867_PHY=y
+CONFIG_DP83869_PHY=y
+CONFIG_DP83TD510_PHY=y
 CONFIG_VITESSE_PHY=y
+CONFIG_CAN_FLEXCAN=m
+CONFIG_CAN_M_CAN=m
+CONFIG_CAN_M_CAN_PLATFORM=m
+CONFIG_CAN_RCAR=m
+CONFIG_CAN_RCAR_CANFD=m
+CONFIG_CAN_MCP251XFD=m
+CONFIG_MDIO_GPIO=y
 CONFIG_MDIO_BUS_MUX_MULTIPLEXER=y
 CONFIG_MDIO_BUS_MUX_MMIOREG=y
 CONFIG_USB_PEGASUS=m
@@ -398,6 +452,9 @@
 CONFIG_ATH11K_AHB=m
 CONFIG_ATH11K_PCI=m
 CONFIG_BRCMFMAC=m
+CONFIG_IWLWIFI=m
+CONFIG_IWLDVM=m
+CONFIG_IWLMVM=m
 CONFIG_MWIFIEX=m
 CONFIG_MWIFIEX_SDIO=m
 CONFIG_MWIFIEX_PCIE=m
@@ -412,10 +469,12 @@
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MXT=m
 CONFIG_TOUCHSCREEN_GOODIX=m
+CONFIG_TOUCHSCREEN_ILI210X=m
 CONFIG_TOUCHSCREEN_EDT_FT5X06=m
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_PM8941_PWRKEY=y
 CONFIG_INPUT_PM8XXX_VIBRATOR=m
+CONFIG_INPUT_TPS65219_PWRBUTTON=m
 CONFIG_INPUT_PWM_BEEPER=m
 CONFIG_INPUT_PWM_VIBRA=m
 CONFIG_INPUT_HISI_POWERKEY=y
@@ -424,6 +483,8 @@
 CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=12
+CONFIG_SERIAL_8250_RUNTIME_UARTS=12
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_8250_BCM2835AUX=y
@@ -432,6 +493,7 @@
 CONFIG_SERIAL_8250_OMAP=y
 CONFIG_SERIAL_8250_MT6577=y
 CONFIG_SERIAL_8250_UNIPHIER=y
+CONFIG_SERIAL_8250_PRUSS=m
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
@@ -505,6 +567,7 @@
 CONFIG_SPI_FSL_DSPI=y
 CONFIG_SPI_MESON_SPICC=m
 CONFIG_SPI_MESON_SPIFC=m
+CONFIG_SPI_OMAP24XX=m
 CONFIG_SPI_ORION=y
 CONFIG_SPI_PL022=y
 CONFIG_SPI_ROCKCHIP=y
@@ -519,6 +582,7 @@
 CONFIG_SPI_TEGRA210_QUAD=m
 CONFIG_SPI_TEGRA114=m
 CONFIG_SPI_SPIDEV=m
+CONFIG_SPI_SLAVE=y
 CONFIG_SPMI=y
 CONFIG_PINCTRL_MAX77620=y
 CONFIG_PINCTRL_SINGLE=y
@@ -601,6 +665,7 @@
 CONFIG_THERMAL_EMULATION=y
 CONFIG_IMX_SC_THERMAL=m
 CONFIG_IMX8MM_THERMAL=m
+CONFIG_K3_THERMAL=m
 CONFIG_QORIQ_THERMAL=m
 CONFIG_SUN8I_THERMAL=y
 CONFIG_ROCKCHIP_THERMAL=m
@@ -625,7 +690,9 @@
 CONFIG_ARM_SBSA_WATCHDOG=y
 CONFIG_S3C2410_WATCHDOG=y
 CONFIG_DW_WATCHDOG=y
+CONFIG_K3_RTI_WATCHDOG=m
 CONFIG_SUNXI_WATCHDOG=m
+CONFIG_NPCM7XX_WATCHDOG=y
 CONFIG_IMX2_WDT=y
 CONFIG_IMX_SC_WDT=m
 CONFIG_QCOM_WDT=m
@@ -638,7 +705,6 @@
 CONFIG_PM8916_WATCHDOG=m
 CONFIG_BCM2835_WDT=y
 CONFIG_BCM7038_WDT=m
-CONFIG_NPCM7XX_WATCHDOG=y
 CONFIG_MFD_ALTERA_SYSMGR=y
 CONFIG_MFD_BD9571MWV=y
 CONFIG_MFD_AXP20X_I2C=y
@@ -653,6 +719,9 @@
 CONFIG_MFD_RK808=y
 CONFIG_MFD_SEC_CORE=y
 CONFIG_MFD_SL28CPLD=y
+CONFIG_MFD_TI_AM335X_TSCADC=m
+CONFIG_MFD_TPS65219=y
+CONFIG_MFD_TPS6594_I2C=y
 CONFIG_MFD_ROHM_BD718XX=y
 CONFIG_MFD_WCD934X=m
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -677,9 +746,11 @@
 CONFIG_REGULATOR_QCOM_RPMH=y
 CONFIG_REGULATOR_QCOM_SMD_RPM=y
 CONFIG_REGULATOR_QCOM_SPMI=y
+CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY=m
 CONFIG_REGULATOR_RK808=y
 CONFIG_REGULATOR_S2MPS11=y
 CONFIG_REGULATOR_TPS65132=m
+CONFIG_REGULATOR_TPS65219=y
 CONFIG_REGULATOR_VCTRL=m
 CONFIG_RC_CORE=m
 CONFIG_RC_DECODERS=y
@@ -687,17 +758,17 @@
 CONFIG_IR_MESON=m
 CONFIG_IR_SUNXI=m
 CONFIG_MEDIA_SUPPORT=m
-CONFIG_MEDIA_CAMERA_SUPPORT=y
-CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
-CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
-CONFIG_MEDIA_SDR_SUPPORT=y
-CONFIG_MEDIA_PLATFORM_SUPPORT=y
 # CONFIG_DVB_NET is not set
 CONFIG_MEDIA_USB_SUPPORT=y
 CONFIG_USB_VIDEO_CLASS=m
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_SDR_PLATFORM_DRIVERS=y
 CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_CADENCE_CSI2RX=m
+CONFIG_VIDEO_WAVE_VPU=m
+CONFIG_VIDEO_IMG_VXD_DEC=m
+CONFIG_VIDEO_IMG_VXE_ENC=m
+CONFIG_VIDEO_E5010_JPEG_ENC=m
 CONFIG_VIDEO_QCOM_CAMSS=m
 CONFIG_VIDEO_QCOM_VENUS=m
 CONFIG_VIDEO_RCAR_ISP=m
@@ -711,9 +782,15 @@
 CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
 CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
 CONFIG_VIDEO_SUN6I_CSI=m
+CONFIG_VIDEO_TI_J721E_CSI2RX=m
+CONFIG_VIDEO_HANTRO=m
 CONFIG_VIDEO_IMX219=m
+CONFIG_VIDEO_IMX390=m
+CONFIG_VIDEO_OV2312=m
 CONFIG_VIDEO_OV5640=m
 CONFIG_VIDEO_OV5645=m
+CONFIG_VIDEO_DS90UB953=m
+CONFIG_VIDEO_DS90UB960=m
 CONFIG_DRM=m
 CONFIG_DRM_I2C_NXP_TDA998X=m
 CONFIG_DRM_HDLCD=m
@@ -736,11 +813,7 @@
 CONFIG_ROCKCHIP_LVDS=y
 CONFIG_DRM_RCAR_DU=m
 CONFIG_DRM_RCAR_DW_HDMI=m
-CONFIG_DRM_RCAR_MIPI_DSI=m
 CONFIG_DRM_SUN4I=m
-CONFIG_DRM_SUN6I_DSI=m
-CONFIG_DRM_SUN8I_DW_HDMI=m
-CONFIG_DRM_SUN8I_MIXER=m
 CONFIG_DRM_MSM=m
 CONFIG_DRM_TEGRA=m
 CONFIG_DRM_PANEL_BOE_TV101WUM_NL6=m
@@ -754,14 +827,18 @@
 CONFIG_DRM_LONTIUM_LT8912B=m
 CONFIG_DRM_LONTIUM_LT9611=m
 CONFIG_DRM_LONTIUM_LT9611UXC=m
+CONFIG_DRM_ITE_IT66121=m
 CONFIG_DRM_NWL_MIPI_DSI=m
 CONFIG_DRM_PARADE_PS8640=m
 CONFIG_DRM_SII902X=m
 CONFIG_DRM_SIMPLE_BRIDGE=m
 CONFIG_DRM_THINE_THC63LVD1024=m
+CONFIG_DRM_TOSHIBA_TC358762=m
+CONFIG_DRM_TI_TFP410=m
 CONFIG_DRM_TI_SN65DSI86=m
 CONFIG_DRM_I2C_ADV7511=m
 CONFIG_DRM_I2C_ADV7511_AUDIO=y
+CONFIG_DRM_CDNS_DSI=m
 CONFIG_DRM_CDNS_MHDP8546=m
 CONFIG_DRM_DW_HDMI_AHB_AUDIO=m
 CONFIG_DRM_DW_HDMI_CEC=m
@@ -782,8 +859,11 @@
 CONFIG_FB=y
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_EFI=y
+CONFIG_FB_SIMPLE=y
 CONFIG_BACKLIGHT_PWM=m
 CONFIG_BACKLIGHT_LP855X=m
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION=y
 CONFIG_LOGO=y
 # CONFIG_LOGO_LINUX_MONO is not set
 # CONFIG_LOGO_LINUX_VGA16 is not set
@@ -791,6 +871,7 @@
 CONFIG_SND=y
 CONFIG_SND_HDA_TEGRA=m
 CONFIG_SND_HDA_CODEC_HDMI=m
+CONFIG_SND_USB_AUDIO=m
 CONFIG_SND_SOC=y
 CONFIG_SND_BCM2835_SOC_I2S=m
 CONFIG_SND_SOC_FSL_ASRC=m
@@ -836,18 +917,19 @@
 CONFIG_SND_SOC_TEGRA210_ADX=m
 CONFIG_SND_SOC_TEGRA210_MIXER=m
 CONFIG_SND_SOC_TEGRA_AUDIO_GRAPH_CARD=m
+CONFIG_SND_SOC_J721E_EVM=m
 CONFIG_SND_SOC_AK4613=m
 CONFIG_SND_SOC_ES7134=m
 CONFIG_SND_SOC_ES7241=m
 CONFIG_SND_SOC_GTM601=m
 CONFIG_SND_SOC_MSM8916_WCD_ANALOG=m
 CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=m
-CONFIG_SND_SOC_PCM3168A_I2C=m
 CONFIG_SND_SOC_RT5659=m
 CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m
 CONFIG_SND_SOC_SIMPLE_MUX=m
 CONFIG_SND_SOC_TAS571X=m
 CONFIG_SND_SOC_TLV320AIC32X4_I2C=m
+CONFIG_SND_SOC_TLV320AIC3X_I2C=m
 CONFIG_SND_SOC_WCD9335=m
 CONFIG_SND_SOC_WCD934X=m
 CONFIG_SND_SOC_WM8524=m
@@ -859,8 +941,6 @@
 CONFIG_SND_SOC_NAU8822=m
 CONFIG_SND_SOC_LPASS_WSA_MACRO=m
 CONFIG_SND_SOC_LPASS_VA_MACRO=m
-CONFIG_SND_SOC_LPASS_RX_MACRO=m
-CONFIG_SND_SOC_LPASS_TX_MACRO=m
 CONFIG_SND_SIMPLE_CARD=m
 CONFIG_SND_AUDIO_GRAPH_CARD=m
 CONFIG_SND_AUDIO_GRAPH_CARD2=m
@@ -890,7 +970,7 @@
 CONFIG_USB_MTU3=y
 CONFIG_USB_MUSB_HDRC=y
 CONFIG_USB_MUSB_SUNXI=y
-CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3=m
 CONFIG_USB_DWC2=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_UDC=y
@@ -903,6 +983,7 @@
 CONFIG_USB_HSIC_USB3503=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=32
 CONFIG_USB_RENESAS_USBHS_UDC=m
 CONFIG_USB_RENESAS_USB3=m
 CONFIG_USB_TEGRA_XUDC=m
@@ -917,6 +998,14 @@
 CONFIG_USB_CONFIGFS_EEM=y
 CONFIG_USB_CONFIGFS_MASS_STORAGE=y
 CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_G_NCM=m
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_CDC=y
 CONFIG_TYPEC=m
 CONFIG_TYPEC_TCPM=m
 CONFIG_TYPEC_TCPCI=m
@@ -930,8 +1019,8 @@
 CONFIG_MMC_SDHCI_ACPI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_OF_ARASAN=y
-CONFIG_MMC_SDHCI_OF_DWCMSHC=y
 CONFIG_MMC_SDHCI_OF_ESDHC=y
+CONFIG_MMC_SDHCI_OF_DWCMSHC=y
 CONFIG_MMC_SDHCI_CADENCE=y
 CONFIG_MMC_SDHCI_ESDHC_IMX=y
 CONFIG_MMC_SDHCI_TEGRA=y
@@ -953,10 +1042,13 @@
 CONFIG_MMC_SDHCI_AM654=y
 CONFIG_MMC_OWL=y
 CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFS_BSG=y
 CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_CDNS_PLATFORM=m
 CONFIG_SCSI_UFS_QCOM=m
 CONFIG_SCSI_UFS_HISI=y
 CONFIG_SCSI_UFS_RENESAS=m
+CONFIG_SCSI_UFS_TI_J721E=m
 CONFIG_SCSI_UFS_EXYNOS=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -984,6 +1076,7 @@
 CONFIG_RTC_DRV_PCF85063=m
 CONFIG_RTC_DRV_PCF85363=m
 CONFIG_RTC_DRV_M41T80=m
+CONFIG_RTC_DRV_BQ32K=m
 CONFIG_RTC_DRV_RX8581=m
 CONFIG_RTC_DRV_RV3028=m
 CONFIG_RTC_DRV_RV8803=m
@@ -1003,6 +1096,7 @@
 CONFIG_RTC_DRV_IMX_SC=m
 CONFIG_RTC_DRV_MT6397=m
 CONFIG_RTC_DRV_XGENE=y
+CONFIG_RTC_DRV_TI_K3=m
 CONFIG_DMADEVICES=y
 CONFIG_DMA_BCM2835=y
 CONFIG_DMA_SUN6I=m
@@ -1025,6 +1119,10 @@
 CONFIG_RZ_DMAC=y
 CONFIG_TI_K3_UDMA=y
 CONFIG_TI_K3_UDMA_GLUE_LAYER=y
+CONFIG_DMABUF_HEAPS=y
+CONFIG_DMABUF_HEAPS_SYSTEM=y
+CONFIG_DMABUF_HEAPS_CMA=y
+CONFIG_DMABUF_HEAPS_CARVEOUT=y
 CONFIG_VFIO=y
 CONFIG_VFIO_PCI=y
 CONFIG_VIRTIO_PCI=y
@@ -1034,7 +1132,6 @@
 CONFIG_XEN_GRANT_DEV_ALLOC=y
 CONFIG_STAGING=y
 CONFIG_STAGING_MEDIA=y
-CONFIG_VIDEO_HANTRO=m
 CONFIG_VIDEO_IMX_MEDIA=m
 CONFIG_VIDEO_MAX96712=m
 CONFIG_CHROME_PLATFORMS=y
@@ -1096,6 +1193,7 @@
 CONFIG_ARM_MHU=y
 CONFIG_IMX_MBOX=y
 CONFIG_PLATFORM_MHU=y
+CONFIG_OMAP2PLUS_MBOX=y
 CONFIG_BCM2835_MBOX=y
 CONFIG_QCOM_APCS_IPC=y
 CONFIG_QCOM_IPCC=y
@@ -1106,16 +1204,23 @@
 CONFIG_MTK_IOMMU=y
 CONFIG_QCOM_IOMMU=y
 CONFIG_REMOTEPROC=y
+CONFIG_MTK_SCP=m
 CONFIG_QCOM_Q6V5_ADSP=m
 CONFIG_QCOM_Q6V5_MSS=m
 CONFIG_QCOM_Q6V5_PAS=m
 CONFIG_QCOM_SYSMON=m
 CONFIG_QCOM_WCNSS_PIL=m
+CONFIG_TI_K3_DSP_REMOTEPROC=m
+CONFIG_TI_K3_M4_REMOTEPROC=m
+CONFIG_TI_K3_R5_REMOTEPROC=m
 CONFIG_RPMSG_CHAR=m
 CONFIG_RPMSG_CTRL=m
 CONFIG_RPMSG_QCOM_GLINK_RPM=y
 CONFIG_RPMSG_QCOM_GLINK_SMEM=m
 CONFIG_RPMSG_QCOM_SMD=y
+CONFIG_RPMSG_VIRTIO=m
+CONFIG_RPMSG_PRU=m
+CONFIG_RPMSG_KDRV_ETH_SWITCH=y
 CONFIG_SOUNDWIRE=m
 CONFIG_SOUNDWIRE_QCOM=m
 CONFIG_OWL_PM_DOMAINS=y
@@ -1173,11 +1278,13 @@
 CONFIG_ARCH_TEGRA_194_SOC=y
 CONFIG_ARCH_TEGRA_234_SOC=y
 CONFIG_TI_SCI_PM_DOMAINS=y
+CONFIG_TI_PRUSS=m
 CONFIG_ARM_IMX_BUS_DEVFREQ=m
 CONFIG_ARM_IMX8M_DDRC_DEVFREQ=m
 CONFIG_EXTCON_PTN5150=m
 CONFIG_EXTCON_USB_GPIO=y
 CONFIG_EXTCON_USBC_CROS_EC=y
+CONFIG_OMAP_GPMC=y
 CONFIG_RENESAS_RPCIF=m
 CONFIG_IIO=y
 CONFIG_EXYNOS_ADC=y
@@ -1187,6 +1294,7 @@
 CONFIG_ROCKCHIP_SARADC=m
 CONFIG_RZG2L_ADC=m
 CONFIG_TI_ADS1015=m
+CONFIG_TI_AM335X_ADC=m
 CONFIG_IIO_CROS_EC_SENSORS_CORE=m
 CONFIG_IIO_CROS_EC_SENSORS=m
 CONFIG_IIO_ST_LSM6DSX=m
@@ -1204,6 +1312,7 @@
 CONFIG_PWM_MESON=m
 CONFIG_PWM_MTK_DISP=m
 CONFIG_PWM_MEDIATEK=m
+CONFIG_PWM_OMAP_DMTIMER=m
 CONFIG_PWM_RCAR=m
 CONFIG_PWM_RENESAS_TPU=m
 CONFIG_PWM_ROCKCHIP=y
@@ -1211,6 +1320,8 @@
 CONFIG_PWM_SL28CPLD=m
 CONFIG_PWM_SUN4I=m
 CONFIG_PWM_TEGRA=m
+CONFIG_PWM_TIECAP=m
+CONFIG_PWM_TIEHRPWM=m
 CONFIG_PWM_VISCONTI=m
 CONFIG_SL28CPLD_INTC=y
 CONFIG_QCOM_PDC=y
@@ -1220,9 +1331,12 @@
 CONFIG_RESET_RZG2L_USBPHY_CTRL=y
 CONFIG_RESET_TI_SCI=y
 CONFIG_PHY_XGENE=y
+CONFIG_PHY_CAN_TRANSCEIVER=m
 CONFIG_PHY_SUN4I_USB=y
-CONFIG_PHY_CADENCE_TORRENT=m
-CONFIG_PHY_CADENCE_SIERRA=m
+CONFIG_PHY_CADENCE_TORRENT=y
+CONFIG_PHY_CADENCE_DPHY=m
+CONFIG_PHY_CADENCE_DPHY_RX=m
+CONFIG_PHY_CADENCE_SIERRA=y
 CONFIG_PHY_MIXEL_MIPI_DPHY=m
 CONFIG_PHY_FSL_IMX8M_PCIE=y
 CONFIG_PHY_HI6220_USB=y
@@ -1251,29 +1365,30 @@
 CONFIG_PHY_UNIPHIER_USB2=y
 CONFIG_PHY_UNIPHIER_USB3=y
 CONFIG_PHY_TEGRA_XUSB=y
-CONFIG_PHY_AM654_SERDES=m
-CONFIG_PHY_J721E_WIZ=m
+CONFIG_PHY_AM654_SERDES=y
+CONFIG_PHY_J721E_WIZ=y
+CONFIG_OMAP_USB2=m
 CONFIG_ARM_CCI_PMU=m
 CONFIG_ARM_CCN=m
 CONFIG_ARM_CMN=m
 CONFIG_ARM_SMMU_V3_PMU=m
 CONFIG_ARM_DSU_PMU=m
 CONFIG_FSL_IMX8_DDR_PMU=m
-CONFIG_ARM_SPE_PMU=m
-CONFIG_ARM_DMC620_PMU=m
 CONFIG_QCOM_L2_PMU=y
 CONFIG_QCOM_L3_PMU=y
+CONFIG_ARM_SPE_PMU=m
+CONFIG_ARM_DMC620_PMU=m
 CONFIG_HISI_PMU=y
 CONFIG_NVMEM_IMX_OCOTP=y
 CONFIG_NVMEM_IMX_OCOTP_SCU=y
+CONFIG_NVMEM_LAYERSCAPE_SFP=m
+CONFIG_NVMEM_MESON_EFUSE=m
 CONFIG_NVMEM_MTK_EFUSE=y
 CONFIG_NVMEM_QCOM_QFPROM=y
+CONFIG_NVMEM_RMEM=m
 CONFIG_NVMEM_ROCKCHIP_EFUSE=y
 CONFIG_NVMEM_SUNXI_SID=y
 CONFIG_NVMEM_UNIPHIER_EFUSE=y
-CONFIG_NVMEM_MESON_EFUSE=m
-CONFIG_NVMEM_RMEM=m
-CONFIG_NVMEM_LAYERSCAPE_SFP=m
 CONFIG_FPGA=y
 CONFIG_FPGA_MGR_ALTERA_CVP=m
 CONFIG_FPGA_MGR_STRATIX10_SOC=m
@@ -1283,11 +1398,9 @@
 CONFIG_OF_FPGA_REGION=m
 CONFIG_TEE=y
 CONFIG_OPTEE=y
-CONFIG_MUX_MMIO=y
-CONFIG_SLIMBUS=m
+CONFIG_MUX_GPIO=y
 CONFIG_SLIM_QCOM_CTRL=m
 CONFIG_SLIM_QCOM_NGD_CTRL=m
-CONFIG_INTERCONNECT=y
 CONFIG_INTERCONNECT_IMX=m
 CONFIG_INTERCONNECT_IMX8MM=m
 CONFIG_INTERCONNECT_IMX8MN=m
@@ -1306,9 +1419,13 @@
 CONFIG_INTERCONNECT_QCOM_SM8250=m
 CONFIG_INTERCONNECT_QCOM_SM8350=m
 CONFIG_INTERCONNECT_QCOM_SM8450=m
+CONFIG_COUNTER=m
+CONFIG_TI_EQEP=m
+CONFIG_TI_ECAP_CAPTURE=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
-CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
 CONFIG_BTRFS_FS=m
 CONFIG_BTRFS_FS_POSIX_ACL=y
 CONFIG_FANOTIFY=y
@@ -1321,8 +1438,8 @@
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_HUGETLBFS=y
-CONFIG_CONFIGFS_FS=y
 CONFIG_EFIVAR_FS=y
+CONFIG_UBIFS_FS=y
 CONFIG_SQUASHFS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V4=y
@@ -1333,10 +1450,22 @@
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_SECURITY=y
-CONFIG_CRYPTO_ECHAINIV=y
+CONFIG_CRYPTO_TEST=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_USER_API_HASH=m
 CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_CHACHA20_NEON=m
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
+CONFIG_CRYPTO_SHA512_ARM64_CE=m
+CONFIG_CRYPTO_SHA3_ARM64=m
+CONFIG_CRYPTO_SM3_ARM64_CE=m
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
+CONFIG_CRYPTO_AES_ARM64_BS=m
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_CRCT10DIF_ARM64_CE=m
 CONFIG_CRYPTO_DEV_SUN8I_CE=m
 CONFIG_CRYPTO_DEV_FSL_CAAM=m
 CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=m
@@ -1346,9 +1475,10 @@
 CONFIG_CRYPTO_DEV_HISI_ZIP=m
 CONFIG_CRYPTO_DEV_HISI_HPRE=m
 CONFIG_CRYPTO_DEV_HISI_TRNG=m
+CONFIG_CRYPTO_DEV_SA2UL=m
+CONFIG_CRYPTO_DEV_TI_MCRC64=m
 CONFIG_CMA_SIZE_MBYTES=32
 CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
 CONFIG_DEBUG_INFO_REDUCED=y
 CONFIG_MAGIC_SYSRQ=y
@@ -1356,6 +1486,8 @@
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
 # CONFIG_FTRACE is not set
+CONFIG_SAMPLES=y
+CONFIG_SAMPLE_RPMSG_CLIENT=m
 CONFIG_CORESIGHT=m
 CONFIG_CORESIGHT_LINK_AND_SINK_TMC=m
 CONFIG_CORESIGHT_CATU=m
diff -Naur --no-dereference a/.clang-format b/.clang-format
--- a/.clang-format	2023-12-20 11:00:29.000000000 -0500
+++ b/.clang-format	2024-01-28 14:01:31.232353751 -0500
@@ -190,6 +190,7 @@
   - 'for_each_active_dev_scope'
   - 'for_each_active_drhd_unit'
   - 'for_each_active_iommu'
+  - 'for_each_active_route'
   - 'for_each_aggr_pgid'
   - 'for_each_available_child_of_node'
   - 'for_each_bench'
diff -Naur --no-dereference a/crypto/tcrypt.c b/crypto/tcrypt.c
--- a/crypto/tcrypt.c	2023-12-20 11:00:29.000000000 -0500
+++ b/crypto/tcrypt.c	2024-01-28 14:01:31.240353775 -0500
@@ -2308,6 +2308,11 @@
 				generic_hash_speed_template);
 		if (mode > 300 && mode < 400) break;
 		fallthrough;
+	case 329:
+		test_hash_speed("crc64", sec, generic_hash_speed_template);
+		if (mode > 300 && mode < 400)
+			break;
+		fallthrough;
 	case 399:
 		break;
 
diff -Naur --no-dereference a/Documentation/ABI/testing/sysfs-bus-counter b/Documentation/ABI/testing/sysfs-bus-counter
--- a/Documentation/ABI/testing/sysfs-bus-counter	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/ABI/testing/sysfs-bus-counter	2024-01-28 14:01:31.232353751 -0500
@@ -65,10 +65,14 @@
 What:		/sys/bus/counter/devices/counterX/countY/function_available
 What:		/sys/bus/counter/devices/counterX/countY/prescaler_available
 What:		/sys/bus/counter/devices/counterX/countY/signalZ_action_available
+What:		/sys/bus/counter/devices/counterX/edge_capture_unit_prescaler_available
+What:		/sys/bus/counter/devices/counterX/latch_mode_available
+What:		/sys/bus/counter/devices/counterX/signalY/index_polarity_available
+What:		/sys/bus/counter/devices/counterX/signalY/synchronous_mode_available
 KernelVersion:	5.2
 Contact:	linux-iio@vger.kernel.org
 Description:
-		Discrete set of available values for the respective Count Y
+		Discrete set of available values for the respective component
 		configuration are listed in this file. Values are delimited by
 		newline characters.
 
@@ -153,6 +157,14 @@
 			updates	the respective count. Quadrature encoding
 			determines the direction.
 
+What:		/sys/bus/counter/devices/counterX/countY/latched_count
+KernelVersion:	5.16
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Latched count data of Count Y represented as a string. The value
+		is latched in based on the trigger selected by the
+		counterX/latch_mode attribute.
+
 What:		/sys/bus/counter/devices/counterX/countY/name
 KernelVersion:	5.2
 Contact:	linux-iio@vger.kernel.org
@@ -222,6 +234,7 @@
 What:		/sys/bus/counter/devices/counterX/countY/direction_component_id
 What:		/sys/bus/counter/devices/counterX/countY/enable_component_id
 What:		/sys/bus/counter/devices/counterX/countY/error_noise_component_id
+What:		/sys/bus/counter/devices/counterX/countY/latched_count_component_id
 What:		/sys/bus/counter/devices/counterX/countY/prescaler_component_id
 What:		/sys/bus/counter/devices/counterX/countY/preset_component_id
 What:		/sys/bus/counter/devices/counterX/countY/preset_enable_component_id
@@ -234,6 +247,14 @@
 What:		/sys/bus/counter/devices/counterX/signalY/polarity_component_id
 What:		/sys/bus/counter/devices/counterX/signalY/synchronous_mode_component_id
 What:		/sys/bus/counter/devices/counterX/signalY/frequency_component_id
+What:		/sys/bus/counter/devices/edge_capture_unit_enable_component_id
+What:		/sys/bus/counter/devices/edge_capture_unit_latched_period_component_id
+What:		/sys/bus/counter/devices/edge_capture_unit_max_period_component_id
+What:		/sys/bus/counter/devices/edge_capture_unit_prescaler_component_id
+What:		/sys/bus/counter/devices/latch_mode_component_id
+What:		/sys/bus/counter/devices/unit_timer_enable_component_id
+What:		/sys/bus/counter/devices/unit_timer_period_component_id
+What:		/sys/bus/counter/devices/unit_timer_time_component_id
 KernelVersion:	5.16
 Contact:	linux-iio@vger.kernel.org
 Description:
@@ -249,6 +270,38 @@
 		shorter or equal to configured value are ignored. Value 0 means
 		filter is disabled.
 
+What:		/sys/bus/counter/devices/edge_capture_unit_enable
+KernelVersion:	5.16
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Read/write attribute that starts or stops the Edge Capture Unit.
+		Valid values are boolean.
+
+What:		/sys/bus/counter/devices/edge_capture_unit_latched_period
+KernelVersion:	5.16
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Latched period of the Edge Capture Unit represented as a string.
+		The value is latched in based on the trigger selected by the
+		counterX/latch_mode attribute. Units are nanoseconds.
+
+What:		/sys/bus/counter/devices/edge_capture_unit_max_period
+KernelVersion:	5.16
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Read/write attribute that selects the maximum period that can
+		be measured by the Edge Capture Unit. Units are nanoseconds.
+
+What:		/sys/bus/counter/devices/edge_capture_unit_prescaler
+KernelVersion:	5.16
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Read/write attribute that selects the how the
+		counterX/countY/count value is scaled coming in to the Edge
+		Capture Unit. This acts like a clock divider, e.g. if a value
+		of 4 is selected, the Edge Capture Unit will measure the period
+		between every 4 counts.
+
 What:		/sys/bus/counter/devices/counterX/events_queue_size
 KernelVersion:	5.16
 Contact:	linux-iio@vger.kernel.org
@@ -257,6 +310,22 @@
 		counter_event data structures. The number of elements will be
 		rounded-up to a power of 2.
 
+What:		/sys/bus/counter/devices/counterX/latch_mode
+KernelVersion:	5.16
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Read/write attribute that selects the trigger for latching
+		values. Valid values are device-specific (given by
+		latch_mode_available attribute) and may include:
+
+		"Read count":
+			Reading the countY/count attribute latches values.
+
+		"Unit timeout":
+			Unit timer timeout event latches values.
+
+		The latched values can be read from latched_* attributes.
+
 What:		/sys/bus/counter/devices/counterX/name
 KernelVersion:	5.2
 Contact:	linux-iio@vger.kernel.org
@@ -311,13 +380,13 @@
 		Active level of index input Signal Y; irrelevant in
 		non-synchronous load mode.
 
-What:		/sys/bus/counter/devices/counterX/signalY/index_polarity_available
-What:		/sys/bus/counter/devices/counterX/signalY/synchronous_mode_available
+What:		/sys/bus/counter/devices/counterX/signalY/name
 KernelVersion:	5.2
 Contact:	linux-iio@vger.kernel.org
 Description:
-		Discrete set of available values for the respective Signal Y
-		configuration are listed in this file.
+		Read-only attribute that indicates the device-specific name of
+		Signal Y. If possible, this should match the name of the
+		respective signal as it appears in the device datasheet.
 
 What:		/sys/bus/counter/devices/counterX/signalY/polarity
 KernelVersion:	6.1
@@ -332,14 +401,6 @@
 		negative:
 			Signal low state considered active level (falling edge).
 
-What:		/sys/bus/counter/devices/counterX/signalY/name
-KernelVersion:	5.2
-Contact:	linux-iio@vger.kernel.org
-Description:
-		Read-only attribute that indicates the device-specific name of
-		Signal Y. If possible, this should match the name of the
-		respective signal as it appears in the device datasheet.
-
 What:		/sys/bus/counter/devices/counterX/signalY/signal
 KernelVersion:	5.2
 Contact:	linux-iio@vger.kernel.org
@@ -380,3 +441,24 @@
 Contact:	linux-iio@vger.kernel.org
 Description:
 		Read-only attribute that indicates the signal Y frequency, in Hz.
+
+What:		/sys/bus/counter/devices/unit_timer_enable
+KernelVersion:	5.16
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Read/write attribute that starts or stops the unit timer. Valid
+		values are boolean.
+
+What:		/sys/bus/counter/devices/unit_timer_period
+KernelVersion:	5.16
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Read/write attribute that selects the unit timer timeout in
+		nanoseconds.
+
+What:		/sys/bus/counter/devices/unit_timer_time
+KernelVersion:	5.16
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Read/write attribute that indicates the current time of the
+		unit timer in nanoseconds.
diff -Naur --no-dereference a/Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml b/Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml
--- a/Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/arm/keystone/ti,sci.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -42,12 +42,16 @@
           - const: ti,am654-sci
 
   reg-names:
-    description: |
-      Specifies the debug messages memory mapped region that is optionally
-      made available from TI-SCI controller.
-    const: debug_messages
+    items:
+      - const: debug_messages
+      - const: lpm
+    minItems: 1
 
   reg:
+    items:
+      - description: |
+          Specifies the debug messages memory mapped region that is optionally
+          made available from TI-SCI controller.
     minItems: 1
 
   mbox-names:
@@ -65,6 +69,12 @@
     description: Determines If system reboot can be triggered by SoC reboot
     type: boolean
 
+  ti,partial-io-wakeup-sources:
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    description: |
+      List of phandles to devicetree nodes that can wakeup the SoC from the
+      Partial IO poweroff mode.
+
   ti,host-id:
     $ref: /schemas/types.yaml#/definitions/uint32
     description: |
diff -Naur --no-dereference a/Documentation/devicetree/bindings/arm/ti/k3.yaml b/Documentation/devicetree/bindings/arm/ti/k3.yaml
--- a/Documentation/devicetree/bindings/arm/ti/k3.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/arm/ti/k3.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -25,10 +25,18 @@
               - ti,am62a7-sk
           - const: ti,am62a7
 
+      - description: K3 AM62P5 SoC and Boards
+        items:
+          - enum:
+              - ti,am62p5-sk
+          - const: ti,am62p5
+
       - description: K3 AM625 SoC
         items:
           - enum:
+              - beagle,am625-beagleplay
               - ti,am625-sk
+              - ti,am62-lp-sk
           - const: ti,am625
 
       - description: K3 AM642 SoC
@@ -68,9 +76,23 @@
       - description: K3 J721s2 SoC
         items:
           - enum:
+              - ti,am68-sk
               - ti,j721s2-evm
           - const: ti,j721s2
 
+      - description: K3 J722S SoC and Boards
+        items:
+          - enum:
+              - ti,j722s-evm
+          - const: ti,j722s
+
+      - description: K3 J784s4 SoC
+        items:
+          - enum:
+              - ti,am69-sk
+              - ti,j784s4-evm
+          - const: ti,j784s4
+
 additionalProperties: true
 
 ...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/clock/ti,am62-audio-refclk.yaml b/Documentation/devicetree/bindings/clock/ti,am62-audio-refclk.yaml
--- a/Documentation/devicetree/bindings/clock/ti,am62-audio-refclk.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/clock/ti,am62-audio-refclk.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/ti,am62-audio-refclk.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI Audio Reference Clock
+
+maintainers:
+  - Jai Luthra <j-luthra@ti.com>
+
+properties:
+  compatible:
+    items:
+      - const: ti,am62-audio-refclk
+
+  reg:
+    maxItems: 1
+
+  "#clock-cells":
+    const: 0
+
+  clocks:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - "#clock-cells"
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    audio_refclk0: clock@82e0 {
+        compatible = "ti,am62-audio-refclk";
+        reg = <0x82e0 0x4>;
+        clocks = <&k3_clks 157 0>;
+        assigned-clocks = <&k3_clks 157 0>;
+        assigned-clock-parents = <&k3_clks 157 8>;
+        #clock-cells = <0>;
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml b/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml
--- a/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/clock/ti,am654-ehrpwm-tbclk.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -16,7 +16,6 @@
           - ti,am654-ehrpwm-tbclk
           - ti,am64-epwm-tbclk
           - ti,am62-epwm-tbclk
-      - const: syscon
 
   "#clock-cells":
     const: 1
@@ -33,8 +32,8 @@
 
 examples:
   - |
-    ehrpwm_tbclk: syscon@4140 {
-        compatible = "ti,am654-ehrpwm-tbclk", "syscon";
+    ehrpwm_tbclk: clock@4140 {
+        compatible = "ti,am654-ehrpwm-tbclk";
         reg = <0x4140 0x18>;
         #clock-cells = <1>;
     };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/counter/ti-eqep.yaml b/Documentation/devicetree/bindings/counter/ti-eqep.yaml
--- a/Documentation/devicetree/bindings/counter/ti-eqep.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/counter/ti-eqep.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -21,7 +21,7 @@
     maxItems: 1
 
   clocks:
-    description: The clock that determines the SYSCLKOUT rate for the eQEP
+    description: The clock that determines the clock rate for the eQEP
       peripheral.
     maxItems: 1
 
@@ -42,9 +42,10 @@
     eqep0: counter@180 {
         compatible = "ti,am3352-eqep";
         reg = <0x180 0x80>;
-        clocks = <&l4ls_gclk>;
-        clock-names = "sysclkout";
-        interrupts = <79>;
+        power-domains = <&k3_pds 59 TI_SCI_PD_EXCLUSIVE>;
+        clocks = <&k3_clks 59 0>;
+        clock-names = "fck";
+        interrupts = <GIC_SPI 116 IRQ_TYPE_EDGE_RISING>;
     };
 
 ...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/crypto/ti,mcrc.yaml b/Documentation/devicetree/bindings/crypto/ti,mcrc.yaml
--- a/Documentation/devicetree/bindings/crypto/ti,mcrc.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/crypto/ti,mcrc.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/crypto/ti,mcrc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments MCRC bindings
+
+maintainers:
+  - Kamlesh Gurudasani  <kamlesh@ti.com>
+
+properties:
+  compatible:
+    const: ti,mcrc
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - power-domains
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+    mcrc: mcrc@30300000 {
+      compatible = "ti,mcrc";
+      reg = <0x00 0x30300000 0x00 0x1000>;
+      clocks = <&k3_clks 116 0>;
+      power-domains = <&k3_pds 116 TI_SCI_PD_EXCLUSIVE>;
+      };
+
+...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/crypto/ti,sa2ul.yaml b/Documentation/devicetree/bindings/crypto/ti,sa2ul.yaml
--- a/Documentation/devicetree/bindings/crypto/ti,sa2ul.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/crypto/ti,sa2ul.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -66,10 +66,22 @@
 required:
   - compatible
   - reg
-  - power-domains
   - dmas
   - dma-names
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,am62-sa3ul
+    then:
+      properties:
+        power-domains: false
+    else:
+      required:
+        - power-domains
+
 additionalProperties: false
 
 examples:
diff -Naur --no-dereference a/Documentation/devicetree/bindings/display/bridge/cdns,dsi.txt b/Documentation/devicetree/bindings/display/bridge/cdns,dsi.txt
--- a/Documentation/devicetree/bindings/display/bridge/cdns,dsi.txt	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/display/bridge/cdns,dsi.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,112 +0,0 @@
-Cadence DSI bridge
-==================
-
-The Cadence DSI bridge is a DPI to DSI bridge supporting up to 4 DSI lanes.
-
-Required properties:
-- compatible: should be set to "cdns,dsi".
-- reg: physical base address and length of the controller's registers.
-- interrupts: interrupt line connected to the DSI bridge.
-- clocks: DSI bridge clocks.
-- clock-names: must contain "dsi_p_clk" and "dsi_sys_clk".
-- phys: phandle link to the MIPI D-PHY controller.
-- phy-names: must contain "dphy".
-- #address-cells: must be set to 1.
-- #size-cells: must be set to 0.
-
-Optional properties:
-- resets: DSI reset lines.
-- reset-names: can contain "dsi_p_rst".
-
-Required subnodes:
-- ports: Ports as described in Documentation/devicetree/bindings/graph.txt.
-  2 ports are available:
-  * port 0: this port is only needed if some of your DSI devices are
-	    controlled through  an external bus like I2C or SPI. Can have at
-	    most 4 endpoints. The endpoint number is directly encoding the
-	    DSI virtual channel used by this device.
-  * port 1: represents the DPI input.
-  Other ports will be added later to support the new kind of inputs.
-
-- one subnode per DSI device connected on the DSI bus. Each DSI device should
-  contain a reg property encoding its virtual channel.
-
-Example:
-	dsi0: dsi@fd0c0000 {
-		compatible = "cdns,dsi";
-		reg = <0x0 0xfd0c0000 0x0 0x1000>;
-		clocks = <&pclk>, <&sysclk>;
-		clock-names = "dsi_p_clk", "dsi_sys_clk";
-		interrupts = <1>;
-		phys = <&dphy0>;
-		phy-names = "dphy";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		ports {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			port@1 {
-				reg = <1>;
-				dsi0_dpi_input: endpoint {
-					remote-endpoint = <&xxx_dpi_output>;
-				};
-			};
-		};
-
-		panel: dsi-dev@0 {
-			compatible = "<vendor,panel>";
-			reg = <0>;
-		};
-	};
-
-or
-
-	dsi0: dsi@fd0c0000 {
-		compatible = "cdns,dsi";
-		reg = <0x0 0xfd0c0000 0x0 0x1000>;
-		clocks = <&pclk>, <&sysclk>;
-		clock-names = "dsi_p_clk", "dsi_sys_clk";
-		interrupts = <1>;
-		phys = <&dphy1>;
-		phy-names = "dphy";
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		ports {
-			#address-cells = <1>;
-			#size-cells = <0>;
-
-			port@0 {
-				reg = <0>;
-				#address-cells = <1>;
-				#size-cells = <0>;
-
-				dsi0_output: endpoint@0 {
-					reg = <0>;
-					remote-endpoint = <&dsi_panel_input>;
-				};
-			};
-
-			port@1 {
-				reg = <1>;
-				dsi0_dpi_input: endpoint {
-					remote-endpoint = <&xxx_dpi_output>;
-				};
-			};
-		};
-	};
-
-	i2c@xxx {
-		panel: panel@59 {
-			compatible = "<vendor,panel>";
-			reg = <0x59>;
-
-			port {
-				dsi_panel_input: endpoint {
-					remote-endpoint = <&dsi0_output>;
-				};
-			};
-		};
-	};
diff -Naur --no-dereference a/Documentation/devicetree/bindings/display/bridge/cdns,dsi.yaml b/Documentation/devicetree/bindings/display/bridge/cdns,dsi.yaml
--- a/Documentation/devicetree/bindings/display/bridge/cdns,dsi.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/display/bridge/cdns,dsi.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,180 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/cdns,dsi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cadence DSI bridge
+
+maintainers:
+  - Boris Brezillon <boris.brezillon@bootlin.com>
+
+description: |
+   CDNS DSI is a bridge device which converts DPI to DSI
+
+properties:
+  compatible:
+    enum:
+      - cdns,dsi
+      - ti,j721e-dsi
+
+  reg:
+    minItems: 1
+    items:
+      - description:
+          Register block for controller's registers.
+      - description:
+          Register block for wrapper settings registers in case of TI J7 SoCs.
+
+  clocks:
+    items:
+      - description: PSM clock, used by the IP
+      - description: sys clock, used by the IP
+
+  clock-names:
+    items:
+      - const: dsi_p_clk
+      - const: dsi_sys_clk
+
+  phys:
+    maxItems: 1
+
+  phy-names:
+    const: dphy
+
+  interrupts:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    const: dsi_p_rst
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/properties/port
+        description:
+          Output port representing the DSI output. It can have
+          at most 4 endpoints. The endpoint number is directly encoding
+          the DSI virtual channel used by this device.
+
+      port@1:
+        $ref: /schemas/graph.yaml#/properties/port
+        description:
+          Input port representing the DPI input.
+
+    required:
+      - port@1
+
+allOf:
+  - $ref: ../dsi-controller.yaml#
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,j721e-dsi
+    then:
+      properties:
+        reg:
+          minItems: 2
+          maxItems: 2
+        power-domains:
+          maxItems: 1
+    else:
+      properties:
+        reg:
+          maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+  - phys
+  - phy-names
+  - ports
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    bus {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        dsi@fd0c0000 {
+            compatible = "cdns,dsi";
+            reg = <0x0 0xfd0c0000 0x0 0x1000>;
+            clocks = <&pclk>, <&sysclk>;
+            clock-names = "dsi_p_clk", "dsi_sys_clk";
+            interrupts = <1>;
+            phys = <&dphy0>;
+            phy-names = "dphy";
+
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port@1 {
+                    reg = <1>;
+                    endpoint {
+                        remote-endpoint = <&xxx_dpi_output>;
+                    };
+                };
+            };
+
+            panel@0 {
+                compatible = "panasonic,vvx10f034n00";
+                reg = <0>;
+                power-supply = <&vcc_lcd_reg>;
+            };
+        };
+    };
+
+  - |
+    bus {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        dsi@fd0c0000 {
+            compatible = "cdns,dsi";
+            reg = <0x0 0xfd0c0000 0x0 0x1000>;
+            clocks = <&pclk>, <&sysclk>;
+            clock-names = "dsi_p_clk", "dsi_sys_clk";
+            interrupts = <1>;
+            phys = <&dphy1>;
+            phy-names = "dphy";
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port@0 {
+                    reg = <0>;
+                    #address-cells = <1>;
+                    #size-cells = <0>;
+
+                    endpoint@0 {
+                        reg = <0>;
+                        remote-endpoint = <&dsi_panel_input>;
+                    };
+                };
+
+                port@1 {
+                    reg = <1>;
+                    endpoint {
+                        remote-endpoint = <&xxx_dpi_output>;
+                    };
+                };
+            };
+        };
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml
--- a/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/display/bridge/cdns,mhdp8546.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -57,6 +57,12 @@
   interrupts:
     maxItems: 1
 
+  cdns,no-hpd:
+    type: boolean
+    description:
+      Set if the HPD line on the bridge isn't hooked up to anything or is
+      otherwise unusable.
+
   ports:
     $ref: /schemas/graph.yaml#/properties/ports
 
diff -Naur --no-dereference a/Documentation/devicetree/bindings/display/panel/panel-edp.yaml b/Documentation/devicetree/bindings/display/panel/panel-edp.yaml
--- a/Documentation/devicetree/bindings/display/panel/panel-edp.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/display/panel/panel-edp.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -86,7 +86,11 @@
 
 properties:
   compatible:
-    const: edp-panel
+    enum:
+        # Generic Panel EDP
+      - edp-panel
+        # TI Simple Panel EDP
+      - ti,panel-edp
 
   hpd-reliable-delay-ms:
     description:
diff -Naur --no-dereference a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml
--- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -220,6 +220,8 @@
       - lg,lp120up1
         # LG 12.9" (2560x1700 pixels) TFT LCD panel
       - lg,lp129qe
+        # Lincoln Technology Solutions, LCD185-101CT 10.1" TFT 1920x1200
+      - lincolntech,lcd185-101ct
         # Logic Technologies LT161010-2NHC 7" WVGA TFT Cap Touch Module
       - logictechno,lt161010-2nhc
         # Logic Technologies LT161010-2NHR 7" WVGA TFT Resistive Touch Module
@@ -230,6 +232,10 @@
       - logictechno,lttd800480070-l2rt
         # Logic Technologies LTTD800480070-L6WH-RT 7” 800x480 TFT Resistive Touch Module
       - logictechno,lttd800480070-l6wh-rt
+        # Microtips Technology MF-101HIEBCAF0 10.1" WUXGA (1920x1200) TFT LCD panel
+      - microtips,mf-101hiebcaf0
+        # Microtips Technology MF-103HIEB0GA0 10.25" 1920x720 TFT LCD panel
+      - microtips,mf-103hieb0ga0
         # Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel
       - mitsubishi,aa070mc01-ca1
         # Multi-Inno Technology Co.,Ltd MI0700S4T-6 7" 800x480 TFT Resistive Touch Module
diff -Naur --no-dereference a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
--- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -19,7 +19,11 @@
 
 properties:
   compatible:
-    const: ti,am65x-dss
+    enum:
+      - ti,am625-dss
+      - ti,am62a7-dss
+      - ti,am62p51-dss
+      - ti,am65x-dss
 
   reg:
     description:
@@ -32,6 +36,7 @@
       - description: OVR2 overlay manager for vp2
       - description: VP1 video port 1
       - description: VP2 video port 2
+      - description: common1 DSS register area
 
   reg-names:
     items:
@@ -42,6 +47,7 @@
       - const: ovr2
       - const: vp1
       - const: vp2
+      - const: common1
 
   clocks:
     items:
@@ -67,7 +73,8 @@
     maxItems: 1
 
   power-domains:
-    maxItems: 1
+    minItems: 1
+    maxItems: 3
     description: phandle to the associated power domain
 
   dma-coherent:
@@ -80,12 +87,22 @@
       port@0:
         $ref: /schemas/graph.yaml#/properties/port
         description:
-          The DSS OLDI output port node form video port 1
+          For AM625, AM62P51 and AM65x, this maps to DSS OLDI output
+          port node (OLDI TX 0) forwarded from video port 1.
+          For AM62A7, this maps to DSS DPI output port node forwarded
+          from video port 2. (video port 1 remains tied off.)
 
       port@1:
         $ref: /schemas/graph.yaml#/properties/port
         description:
-          The DSS DPI output port node from video port 2
+          This maps to DSS DPI output port node forwarded from
+          video port 2.
+
+      port@2:
+        $ref: /schemas/graph.yaml#/properties/port
+        description:
+          For AM625, AM62P51, this maps to DSS OLDI output port node
+          (OLDI TX 1) forwarded from video port 1.
 
   ti,am65x-oldi-io-ctrl:
     $ref: "/schemas/types.yaml#/definitions/phandle"
@@ -102,6 +119,112 @@
       Input memory (from main memory to dispc) bandwidth limit in
       bytes per second
 
+  ti,dss-shared-mode:
+    type: boolean
+    description:
+      TI DSS7 supports sharing of display between multiple hosts
+      as it provides separate register space for display configuration and
+      unique interrupt line to each host.
+      One of the host is provided access to the global display
+      configuration labelled as "common" region of DSS allows that host
+      exclusive access to global registers of DSS while other host can
+      configure the display for it's usage using a separate register
+      space labelled as "common1".
+      The DSS resources can be partitioned in such a way that one or more
+      of the video planes are owned by Linux whereas other video planes
+      can be owned by a remote core.
+      The video port controlling these planes acts as a shared video port
+      and it can be configured with write access either by Linux or the
+      remote core in which case Linux only has read-only access to that
+      video port.
+
+  ti,dss-shared-mode-planes:
+    description:
+      The video layer that is owned by processing core running Linux.
+      The display driver running from Linux has exclusive write access to
+      this video layer.
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [vidl, vid]
+
+  ti,dss-shared-mode-vp:
+    description:
+      The video port that is being used in context of processing core
+      running Linux with display susbsytem being used in shared mode.
+      This can be owned either by the processing core running Linux in
+      which case Linux has the write access and the responsibility to
+      configure this video port and the associated overlay manager or
+      it can be shared between core running Linux and a remote core
+      with remote core provided with write access to this video port and
+      associated overlay managers and remote core configures and drives
+      this video port also feeding data from one or more of the
+      video planes owned by Linux, with Linux only having read-only access
+      to this video port and associated overlay managers.
+
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [vp1, vp2]
+
+  ti,dss-shared-mode-common:
+    description:
+      The DSS register region owned by processing core running Linux.
+    $ref: /schemas/types.yaml#/definitions/string
+    enum: [common, common1]
+
+  ti,dss-shared-mode-vp-owned:
+    description:
+      This tells whether processing core running Linux has write access to
+      the video ports enlisted in ti,dss-shared-mode-vps.
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1]
+
+  ti,dss-shared-mode-plane-zorder:
+    description:
+      The zorder of the planes owned by Linux.
+      For the scenario where Linux is not having write access to associated
+      video port, this field is just for
+      informational purpose to enumerate the zorder configuration
+      being used by remote core.
+
+    $ref: /schemas/types.yaml#/definitions/uint32
+    enum: [0, 1]
+
+dependencies:
+  ti,dss-shared-mode: [ 'ti,dss-shared-mode-planes', 'ti,dss-shared-mode-vp',
+                        'ti,dss-shared-mode-plane-zorder', 'ti,dss-shared-mode-vp-owned']
+  ti,dss-shared-mode-vp: ['ti,dss-shared-mode', 'ti,dss-shared-mode-planes',
+                          'ti,dss-shared-mode-plane-zorder', 'ti,dss-shared-mode-vp-owned']
+  ti,dss-shared-mode-planes: ['ti,dss-shared-mode', 'ti,dss-shared-mode-vp',
+                              'ti,dss-shared-mode-plane-zorder', 'ti,dss-shared-mode-vp-owned']
+  ti,dss-shared-mode-plane-zorder: ['ti,dss-shared-mode-planes', 'ti,dss-shared-mode-vp',
+                                    'ti,dss-shared-mode', 'ti,dss-shared-mode-vp-owned']
+  ti,dss-shared-mode-vp-owned: ['ti,dss-shared-mode-planes', 'ti,dss-shared-mode-vp',
+                                'ti,dss-shared-mode', 'ti,dss-shared-mode-plane-zorder']
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,am65x-dss
+    then:
+      properties:
+        ports:
+          properties:
+            port@2: false
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,am62a7-dss
+    then:
+      properties:
+        ports:
+          properties:
+            port@1: false
+            port@2: false
+        ti,dss-shared-mode-vp:
+          enum: [vp2]
+
 required:
   - compatible
   - reg
@@ -127,9 +250,10 @@
                     <0x04a07000 0x1000>, /* ovr1 */
                     <0x04a08000 0x1000>, /* ovr2 */
                     <0x04a0a000 0x1000>, /* vp1 */
-                    <0x04a0b000 0x1000>; /* vp2 */
+                    <0x04a0b000 0x1000>, /* vp2 */
+                    <0x04a01000 0x1000>; /* common1 */
             reg-names = "common", "vidl1", "vid",
-                    "ovr1", "ovr2", "vp1", "vp2";
+                    "ovr1", "ovr2", "vp1", "vp2", "common1";
             ti,am65x-oldi-io-ctrl = <&dss_oldi_io_ctrl>;
             power-domains = <&k3_pds 67 TI_SCI_PD_EXCLUSIVE>;
             clocks =        <&k3_clks 67 1>,
diff -Naur --no-dereference a/Documentation/devicetree/bindings/dma/ti/k3-bcdma.yaml b/Documentation/devicetree/bindings/dma/ti/k3-bcdma.yaml
--- a/Documentation/devicetree/bindings/dma/ti/k3-bcdma.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/dma/ti/k3-bcdma.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -28,13 +28,22 @@
   PDMAs can be configured via BCDMA split channel's peer registers to match with
   the configuration of the legacy peripheral.
 
-allOf:
-  - $ref: /schemas/dma/dma-controller.yaml#
-  - $ref: /schemas/arm/keystone/ti,k3-sci-common.yaml#
-
 properties:
   compatible:
-    const: ti,am64-dmss-bcdma
+    enum:
+      - ti,am62a-dmss-bcdma-csirx
+      - ti,am64-dmss-bcdma
+      - ti,j721s2-dmss-bcdma-csi
+      - ti,j722s-dmss-bcdma-csi
+
+
+  reg:
+    minItems: 3
+    maxItems: 5
+
+  reg-names:
+    minItems: 3
+    maxItems: 5
 
   "#dma-cells":
     const: 3
@@ -65,19 +74,13 @@
 
       cell 3: ASEL value for the channel
 
-  reg:
-    maxItems: 5
-
-  reg-names:
-    items:
-      - const: gcfg
-      - const: bchanrt
-      - const: rchanrt
-      - const: tchanrt
-      - const: ringrt
-
   msi-parent: true
 
+  power-domains:
+    description:
+      Power domain if available
+    maxItems: 1
+
   ti,asel:
     $ref: /schemas/types.yaml#/definitions/uint32
     description: ASEL value for non slave channels
@@ -123,10 +126,80 @@
   - msi-parent
   - ti,sci
   - ti,sci-dev-id
-  - ti,sci-rm-range-bchan
-  - ti,sci-rm-range-tchan
   - ti,sci-rm-range-rchan
 
+allOf:
+  - $ref: /schemas/dma/dma-controller.yaml#
+  - $ref: /schemas/arm/keystone/ti,k3-sci-common.yaml#
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,am62a-dmss-bcdma-csirx
+    then:
+      properties:
+        ti,sci-rm-range-bchan: false
+        ti,sci-rm-range-tchan: false
+
+        reg:
+          maxItems: 3
+
+        reg-names:
+          items:
+            - const: gcfg
+            - const: rchanrt
+            - const: ringrt
+
+      required:
+        - power-domains
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,am64-dmss-bcdma
+    then:
+      properties:
+        reg:
+          minItems: 5
+
+        reg-names:
+          items:
+            - const: gcfg
+            - const: bchanrt
+            - const: rchanrt
+            - const: tchanrt
+            - const: ringrt
+
+      required:
+        - ti,sci-rm-range-bchan
+        - ti,sci-rm-range-tchan
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - ti,j721s2-dmss-bcdma-csi
+              - ti,j722s-dmss-bcdma-csi
+    then:
+      properties:
+        ti,sci-rm-range-bchan: false
+
+        reg:
+          maxItems: 4
+
+        reg-names:
+          items:
+            - const: gcfg
+            - const: rchanrt
+            - const: tchanrt
+            - const: ringrt
+
+      required:
+        - ti,sci-rm-range-tchan
+
 unevaluatedProperties: false
 
 examples:
diff -Naur --no-dereference a/Documentation/devicetree/bindings/gpu/img,sgx530.yaml b/Documentation/devicetree/bindings/gpu/img,sgx530.yaml
--- a/Documentation/devicetree/bindings/gpu/img,sgx530.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/gpu/img,sgx530.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpu/img,sgx530.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Imagination SGX530 3D Graphics Processing Unit
+
+maintainers:
+  - Andrew Davis <afd@ti.com>
+
+description: |
+  SGX530 is a 3D Graphics Processing Unit from Imagination Technologies.
+  SGX is codename for 5th generation / Series 5 of PowerVR chipset family.
+
+properties:
+  $nodename:
+    pattern: '^gpu@[a-f0-9]+$'
+
+  compatible:
+    items:
+      - enum:
+          - ti,omap3530-sgx530  # TI OMAP35x
+          - ti,omap3630-sgx530  # TI OMAP36x
+          - ti,am3352-sgx530  # TI AM33x
+          - ti,am4376-sgx530  # TI AM43x
+      - const: img,sgx530
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+    gpu@56000000 {
+      compatible = "ti,am4376-sgx530", "img,sgx530";
+      reg = <0x56000000 0x10000>;
+      interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+    };
+
+...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/gpu/img,sgx540.yaml b/Documentation/devicetree/bindings/gpu/img,sgx540.yaml
--- a/Documentation/devicetree/bindings/gpu/img,sgx540.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/gpu/img,sgx540.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpu/img,sgx540.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Imagination SGX540 3D Graphics Processing Unit
+
+maintainers:
+  - Andrew Davis <afd@ti.com>
+
+description: |
+  SGX540 is a 3D Graphics Processing Unit from Imagination Technologies.
+  SGX is codename for 5th generation / Series 5 of PowerVR chipset family.
+
+properties:
+  $nodename:
+    pattern: '^gpu@[a-f0-9]+$'
+
+  compatible:
+    items:
+      - enum:
+          - ti,omap4430-sgx540  # TI OMAP443x
+          - ti,omap4460-sgx540  # TI OMAP446x
+      - const: img,sgx540
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+    gpu@0 {
+       compatible = "ti,omap4430-sgx540", "img,sgx540";
+       reg = <0x0 0x2000000>; /* 32MB */
+       interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+    };
+
+...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/gpu/img,sgx544.yaml b/Documentation/devicetree/bindings/gpu/img,sgx544.yaml
--- a/Documentation/devicetree/bindings/gpu/img,sgx544.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/gpu/img,sgx544.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpu/img,sgx544.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Imagination SGX544 3D Graphics Processing Unit
+
+maintainers:
+  - Andrew Davis <afd@ti.com>
+
+description: |
+  SGX544 is a 3D Graphics Processing Unit from Imagination Technologies.
+  SGX is codename for 5th generation / Series 5 of PowerVR chipset family.
+
+properties:
+  $nodename:
+    pattern: '^gpu@[a-f0-9]+$'
+
+  compatible:
+    items:
+      - enum:
+          - ti,omap4470-sgx544  # TI OMAP447x
+          - ti,omap5432-sgx544  # TI OMAP543x
+          - ti,dra7-sgx544  # TI DRA7xx / AM57x
+          - ti,am654-sgx544  # TI AM654
+      - const: img,sgx544
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,am654-sgx544
+    then:
+      properties:
+        power-domains:
+          minItems: 1
+      required:
+        - power-domains
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+    bus {
+      #address-cells = <2>;
+      #size-cells = <2>;
+      gpu: gpu@7000000 {
+        compatible = "ti,am654-sgx544", "img,sgx544";
+        reg = <0x0 0x7000000 0x0 0x10000>;
+        interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
+        power-domains = <&k3_pds 65 TI_SCI_PD_EXCLUSIVE>;
+      };
+    };
+
+...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/gpu/ti,rogue.yaml b/Documentation/devicetree/bindings/gpu/ti,rogue.yaml
--- a/Documentation/devicetree/bindings/gpu/ti,rogue.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/gpu/ti,rogue.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,209 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/gpu/ti,rogue.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments PowerVR Rogue GPU
+
+description: |
+  PowerVR Rogue is a family of 3D graphics processing units from Imagination
+  Technologies. Texas Instruments SoCs have integrated different generations of
+  PowerVR GPUs and this binding describes the GPU's integrated in Texas
+  Instruments SoCs in the K3 generation.
+
+maintainers:
+  - Darren Etheridge <detheridge@ti.com>
+  - Randolph Sapp <rs@ti.com>
+
+properties:
+  $nodename:
+    pattern: '^gpu@[a-f0-9]+$'
+
+  compatible:
+    oneOf:
+      - items:
+          - enum:
+              - ti,j721s2-pvr
+          - const: img,pvr-bxs64
+      - items:
+          - enum:
+              - ti,am62-pvr
+          - const: img,pvr-axe116m
+      - items:
+          - enum:
+              - ti,j721e-pvr
+          - const: img,pvr-ge8430
+      - items:
+          - enum:
+              - ti,am62p-pvr
+          - const: img,pvr-bxs64
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    maxItems: 1
+
+  power-domains:
+    minItems: 1
+    maxItems: 2
+
+  power-domain-names:
+    maxItems: 2
+
+  assigned-clocks:
+    maxItems: 1
+
+  assigned-clock-rates:
+    maxItems: 1
+    description: |
+      Allows users to override the default clock value used for the GPU.
+      Currently ignored on devices other than ti,am62p-pvr. This will be ported
+      to other devices soon.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - power-domains
+  - clocks
+
+additionalProperties: false
+
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - ti,j721s2-pvr
+              - ti,j721e-pvr
+              - ti,am62-pvr
+    then:
+      properties:
+        reg:
+          minItems: 1
+        interrupts:
+          minItems: 1
+        clocks:
+          minItems: 1
+        power-domains:
+          minItems: 1
+          maxItems: 1
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - ti,am62p-pvr
+    then:
+      required:
+        - power-domain-names
+        - assigned-clocks
+        - clock-names
+      properties:
+        reg:
+          minItems: 1
+        interrupts:
+          minItems: 1
+        clocks:
+          minItems: 1
+        clock-names:
+          items:
+            - const: core
+        power-domains:
+          minItems: 2
+        power-domain-names:
+          items:
+            - const: firmware
+            - const: dust
+        assigned-clocks:
+          minItems: 1
+        assigned-clock-rates:
+          default: 800000000
+    else:
+      properties:
+        assigned-clocks: false
+        assigned-clock-rates: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+    bus {
+        #address-cells = <2>;
+        #size-cells = <2>;
+        gpu@fd00000 {
+            compatible = "ti,am62-pvr", "img,pvr-axe116m";
+            reg = <0x00 0x0fd00000 0x00 0x20000>;
+            interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+            power-domains = <&k3_pds 187 TI_SCI_PD_EXCLUSIVE>;
+            clocks = <&k3_clks 187 0>;
+        };
+    };
+
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+    bus {
+        #address-cells = <2>;
+        #size-cells = <2>;
+        gpu@4e20000000 {
+            compatible = "ti,j721s2-pvr", "img,pvr-bxs64";
+            reg = <0x4e 0x20000000 0x00 0x80000>;
+            interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+            power-domains = <&k3_pds 373 TI_SCI_PD_EXCLUSIVE>;
+            clocks = <&k3_clks 130 1>;
+        };
+    };
+
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+    bus {
+        #address-cells = <2>;
+        #size-cells = <2>;
+        gpu@4e20000000 {
+            compatible = "ti,j721e-pvr", "img,pvr-ge8430";
+            reg = <0x4e 0x20000000 0x00 0x80000>;
+            interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+            power-domains = <&k3_pds 126 TI_SCI_PD_EXCLUSIVE>;
+            clocks = <&k3_clks 125 0>;
+        };
+    };
+
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+    bus {
+        #address-cells = <2>;
+        #size-cells = <2>;
+        gpu@fd80000 {
+            compatible = "ti,am62p-pvr", "img,pvr-bxs64";
+            reg = <0x00 0x0fd80000 0x00 0x80000>;
+            interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
+            power-domains = <&k3_pds 237 TI_SCI_PD_EXCLUSIVE>,
+                            <&k3_pds 242 TI_SCI_PD_EXCLUSIVE>;
+            assigned-clocks = <&k3_clks 237 3>;
+            assigned-clock-rates = <720000000>;
+            power-domain-names = "firmware", "dust";
+            clocks = <&k3_clks 237 3>;
+            clock-names = "core";
+        };
+    };
+...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/i2c/i2c-atr.yaml b/Documentation/devicetree/bindings/i2c/i2c-atr.yaml
--- a/Documentation/devicetree/bindings/i2c/i2c-atr.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/i2c/i2c-atr.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/i2c/i2c-atr.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Common i2c address translator properties
+
+maintainers:
+  - Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+description:
+  An I2C Address Translator (ATR) is a device with an I2C slave parent
+  ("upstream") port and N I2C master child ("downstream") ports, and
+  forwards transactions from upstream to the appropriate downstream port
+  with a modified slave address. The address used on the parent bus is
+  called the "alias" and is (potentially) different from the physical
+  slave address of the child bus. Address translation is done by the
+  hardware.
+
+properties:
+  i2c-alias-pool:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    description:
+      I2C alias pool is a pool of I2C addresses on the main I2C bus that can be
+      used to access the remote peripherals on the serializer's I2C bus. The
+      addresses must be available, not used by any other peripheral. Each
+      remote peripheral is assigned an alias from the pool, and transactions to
+      that address will be forwarded to the remote peripheral, with the address
+      translated to the remote peripheral's real address. This property is not
+      needed if there are no I2C addressable remote peripherals.
+
+additionalProperties: true
+...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/input/gpio-keys.yaml b/Documentation/devicetree/bindings/input/gpio-keys.yaml
--- a/Documentation/devicetree/bindings/input/gpio-keys.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/input/gpio-keys.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -31,7 +31,23 @@
         maxItems: 1
 
       interrupts:
-        maxItems: 1
+        oneOf:
+          - items:
+              - description: Optional key interrupt or wakeup interrupt
+          - items:
+              - description: Key interrupt
+              - description: Wakeup interrupt
+
+      interrupt-names:
+        description:
+          Optional interrupt names, can be used to specify a separate dedicated
+          wake-up interrupt in addition to the gpio irq
+        oneOf:
+          - items:
+              - enum: [ irq, wakeup ]
+          - items:
+              - const: irq
+              - const: wakeup
 
       label:
         description: Descriptive name of the key.
@@ -97,6 +113,20 @@
       - required:
           - gpios
 
+    allOf:
+      - if:
+          properties:
+            interrupts:
+              minItems: 2
+          required:
+            - interrupts
+        then:
+          properties:
+            interrupt-names:
+              minItems: 2
+          required:
+            - interrupt-names
+
     dependencies:
       wakeup-event-action: [ wakeup-source ]
       linux,input-value: [ gpios ]
@@ -137,6 +167,15 @@
             linux,code = <108>;
             interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
         };
+
+        key-wakeup {
+            label = "GPIO Key WAKEUP";
+            linux,code = <143>;
+            interrupts-extended = <&intc 2 IRQ_TYPE_EDGE_FALLING>,
+                                  <&intc_wakeup 0 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "irq", "wakeup";
+            wakeup-source;
+        };
     };
 
 ...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/cdns,csi2rx.txt b/Documentation/devicetree/bindings/media/cdns,csi2rx.txt
--- a/Documentation/devicetree/bindings/media/cdns,csi2rx.txt	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/media/cdns,csi2rx.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-Cadence MIPI-CSI2 RX controller
-===============================
-
-The Cadence MIPI-CSI2 RX controller is a CSI-2 bridge supporting up to 4 CSI
-lanes in input, and 4 different pixel streams in output.
-
-Required properties:
-  - compatible: must be set to "cdns,csi2rx" and an SoC-specific compatible
-  - reg: base address and size of the memory mapped region
-  - clocks: phandles to the clocks driving the controller
-  - clock-names: must contain:
-    * sys_clk: main clock
-    * p_clk: register bank clock
-    * pixel_if[0-3]_clk: pixel stream output clock, one for each stream
-                         implemented in hardware, between 0 and 3
-
-Optional properties:
-  - phys: phandle to the external D-PHY, phy-names must be provided
-  - phy-names: must contain "dphy", if the implementation uses an
-               external D-PHY
-
-Required subnodes:
-  - ports: A ports node with one port child node per device input and output
-           port, in accordance with the video interface bindings defined in
-           Documentation/devicetree/bindings/media/video-interfaces.txt. The
-           port nodes are numbered as follows:
-
-           Port Description
-           -----------------------------
-           0    CSI-2 input
-           1    Stream 0 output
-           2    Stream 1 output
-           3    Stream 2 output
-           4    Stream 3 output
-
-           The stream output port nodes are optional if they are not
-           connected to anything at the hardware level or implemented
-           in the design.Since there is only one endpoint per port,
-           the endpoints are not numbered.
-
-
-Example:
-
-csi2rx: csi-bridge@0d060000 {
-	compatible = "cdns,csi2rx";
-	reg = <0x0d060000 0x1000>;
-	clocks = <&byteclock>, <&byteclock>
-		 <&coreclock>, <&coreclock>,
-		 <&coreclock>, <&coreclock>;
-	clock-names = "sys_clk", "p_clk",
-		      "pixel_if0_clk", "pixel_if1_clk",
-		      "pixel_if2_clk", "pixel_if3_clk";
-
-	ports {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		port@0 {
-			reg = <0>;
-
-			csi2rx_in_sensor: endpoint {
-				remote-endpoint = <&sensor_out_csi2rx>;
-				clock-lanes = <0>;
-				data-lanes = <1 2>;
-			};
-		};
-
-		port@1 {
-			reg = <1>;
-
-			csi2rx_out_grabber0: endpoint {
-				remote-endpoint = <&grabber0_in_csi2rx>;
-			};
-		};
-
-		port@2 {
-			reg = <2>;
-
-			csi2rx_out_grabber1: endpoint {
-				remote-endpoint = <&grabber1_in_csi2rx>;
-			};
-		};
-
-		port@3 {
-			reg = <3>;
-
-			csi2rx_out_grabber2: endpoint {
-				remote-endpoint = <&grabber2_in_csi2rx>;
-			};
-		};
-
-		port@4 {
-			reg = <4>;
-
-			csi2rx_out_grabber3: endpoint {
-				remote-endpoint = <&grabber3_in_csi2rx>;
-			};
-		};
-	};
-};
diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
--- a/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/media/cdns,csi2rx.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,176 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/cdns,csi2rx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cadence MIPI-CSI2 RX controller
+
+description: |
+  The Cadence MIPI-CSI2 RX controller is a CSI-2 bridge supporting up to 4 CSI
+  lanes in input, and 4 different pixel streams in output.
+
+maintainers:
+  - Pratyush Yadav <p.yadav@ti.com>
+
+properties:
+  compatible:
+    contains:
+      const: cdns,csi2rx
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    minItems: 3
+    items:
+      - description: Main clock
+      - description: Register bank clock
+      - description: Pixel stream 0 output clock
+      - description: Pixel stream 1 output clock
+      - description: Pixel stream 2 output clock
+      - description: Pixel stream 3 output clock
+
+  clock-names:
+    minItems: 3
+    items:
+      - const: sys_clk
+      - const: p_clk
+      - const: pixel_if0_clk
+      - const: pixel_if1_clk
+      - const: pixel_if2_clk
+      - const: pixel_if3_clk
+
+  phys:
+    maxItems: 1
+    description: phandle to the external D-PHY
+
+  phy-names:
+    items:
+      - const: dphy
+
+  power-domains:
+    maxItems: 1
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: CSI-2 input
+
+        properties:
+          endpoint:
+            $ref: video-interfaces.yaml#
+            unevaluatedProperties: false
+
+            properties:
+              clock-lanes:
+                maxItems: 1
+
+              data-lanes:
+                minItems: 1
+                maxItems: 4
+                items:
+                  maximum: 4
+
+            required:
+              - clock-lanes
+              - data-lanes
+
+      port@1:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: Stream 0 output
+
+      port@2:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: Stream 1 output
+
+      port@3:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: Stream 2 output
+
+      port@4:
+        $ref: /schemas/graph.yaml#/properties/port
+        description: Stream 3 output
+
+    required:
+      - port@0
+
+
+dependencies:
+  phys: [ 'phy-names' ]
+  phy-names: [ 'phys' ]
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+    csi2rx: csi-bridge@d060000 {
+      compatible = "cdns,csi2rx";
+      reg = <0x0d060000 0x1000>;
+      clocks = <&byteclock>, <&byteclock>,
+        <&coreclock>, <&coreclock>,
+        <&coreclock>, <&coreclock>;
+      clock-names = "sys_clk", "p_clk",
+              "pixel_if0_clk", "pixel_if1_clk",
+              "pixel_if2_clk", "pixel_if3_clk";
+      phys = <&dphy0>;
+      phy-names = "dphy";
+
+      ports {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        port@0 {
+          reg = <0>;
+
+          csi2rx_in_sensor: endpoint {
+            remote-endpoint = <&sensor_out_csi2rx>;
+            clock-lanes = <0>;
+            data-lanes = <1 2>;
+          };
+        };
+
+        port@1 {
+          reg = <1>;
+
+          csi2rx_out_grabber0: endpoint {
+            remote-endpoint = <&grabber0_in_csi2rx>;
+          };
+        };
+
+        port@2 {
+          reg = <2>;
+
+          csi2rx_out_grabber1: endpoint {
+            remote-endpoint = <&grabber1_in_csi2rx>;
+          };
+        };
+
+        port@3 {
+          reg = <3>;
+
+          csi2rx_out_grabber2: endpoint {
+            remote-endpoint = <&grabber2_in_csi2rx>;
+          };
+        };
+
+        port@4 {
+          reg = <4>;
+
+          csi2rx_out_grabber3: endpoint {
+            remote-endpoint = <&grabber3_in_csi2rx>;
+          };
+        };
+      };
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/cnm,wave5.yml b/Documentation/devicetree/bindings/media/cnm,wave5.yml
--- a/Documentation/devicetree/bindings/media/cnm,wave5.yml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/media/cnm,wave5.yml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/wave5.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Chips&Media Wave 5 Series multi-standard codec IP
+
+maintainers:
+  - Nas Chung <nas.chung@chipsnmedia.com>
+  - Robert Beckett <bob.beckett@collabora.com>
+  - Sebastian Fricke <sebastian.fricke@collabora.com>
+
+description: |-
+  The Chips&Media WAVE codec IP is a multi format video encoder/decoder
+
+properties:
+  compatible:
+    anyOf:
+      - items:
+        - enum:
+            - cnm,cm511-vpu
+            - cnm,cm517-vpu
+            - cnm,cm521-vpu
+            - cnm,cm521c-vpu
+            - cnm,cm521c-dual-vpu
+            - cnm,cm521e1-vpu
+            - cnm,cm537-vpu
+  reg:
+    maxItems: 1
+
+  clocks:
+    minItems: 1
+    maxItems: 4
+
+  clock-names:
+    minItems: 1
+    maxItems: 4
+
+  interrupts:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  sram:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: phandle pointing to the SRAM device node
+    maxItems: 1
+
+  sram-size:
+    description: Amount to allocate from SRAM device node
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+
+additionalProperties: false
+
+examples:
+  - |
+    vpu: video-codec@12345678 {
+        compatible = "cnm,cm521-vpu";
+        reg = <0x12345678 0x1000>;
+        interrupts = <42>;
+        clocks = <&clks 42>;
+        clock-names = "vcodec";
+        sram = <&sram>;
+	sram-size = <0x12345>;
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/i2c/sony,imx390.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx390.yaml
--- a/Documentation/devicetree/bindings/media/i2c/sony,imx390.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/media/i2c/sony,imx390.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/sony,imx390.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sony IMX390 Camera Sensor
+
+maintainers:
+  - Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+description: |-
+  Sony IMX390 camera sensor.
+
+properties:
+  compatible:
+    enum:
+      - sony,imx390
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  clock-names:
+    const: inck
+
+  xclr-gpios:
+    maxItems: 1
+    description:
+      Specifier for the GPIO connected to the XCLR (System Reset) pin.
+
+  port:
+    $ref: /schemas/graph.yaml#/properties/port
+    additionalProperties: false
+
+    properties:
+      endpoint:
+        $ref: ../video-interfaces.yaml#
+        unevaluatedProperties: false
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - port
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+        clock-frequency = <400000>;
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        camera@21 {
+            compatible = "sony,imx390";
+            reg = <0x21>;
+
+            clocks = <&fixed_clock>;
+            clock-names = "inck";
+
+            xclr-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>;
+
+            port {
+                camera1: endpoint {
+                    remote-endpoint = <&vin1a_ep>;
+                };
+            };
+        };
+    };
+
+...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub913.yaml b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub913.yaml
--- a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub913.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub913.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,133 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/ti,ds90ub913.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments DS90UB913 FPD-Link III Serializer
+
+maintainers:
+  - Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+description:
+  The TI DS90UB913 is an FPD-Link III video serializer for parallel video.
+
+properties:
+  compatible:
+    enum:
+      - ti,ds90ub913a-q1
+
+  '#gpio-cells':
+    const: 2
+    description:
+      First cell is the GPO pin number, second cell is the flags. The GPO pin
+      number must be in range of [0, 3]. Note that GPOs 2 and 3 are not
+      available in external oscillator mode.
+
+  gpio-controller: true
+
+  clocks:
+    maxItems: 1
+    description:
+      Reference clock connected to the CLKIN pin.
+
+  clock-names:
+    items:
+      - const: clkin
+
+  '#clock-cells':
+    const: 0
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: Parallel input port
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+
+            required:
+              - pclk-sample
+
+      port@1:
+        $ref: /schemas/graph.yaml#/properties/port
+        unevaluatedProperties: false
+        description: FPD-Link III output port
+
+    required:
+      - port@0
+      - port@1
+
+  i2c:
+    $ref: /schemas/i2c/i2c-controller.yaml#
+    unevaluatedProperties: false
+
+required:
+  - compatible
+  - '#gpio-cells'
+  - gpio-controller
+  - '#clock-cells'
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    serializer {
+      compatible = "ti,ds90ub913a-q1";
+
+      gpio-controller;
+      #gpio-cells = <2>;
+
+      clocks = <&clk_cam_48M>;
+      clock-names = "clkin";
+
+      #clock-cells = <0>;
+
+      ports {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        port@0 {
+          reg = <0>;
+          ub913_in: endpoint {
+            remote-endpoint = <&sensor_out>;
+            pclk-sample = <1>;
+          };
+        };
+
+        port@1 {
+          reg = <1>;
+          endpoint {
+            remote-endpoint = <&deser_fpd_in>;
+          };
+        };
+      };
+
+      i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        sensor@48 {
+          compatible = "aptina,mt9v111";
+          reg = <0x48>;
+
+          clocks = <&fixed_clock>;
+
+          port {
+            sensor_out: endpoint {
+              remote-endpoint = <&ub913_in>;
+            };
+          };
+        };
+      };
+    };
+...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub953.yaml b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub953.yaml
--- a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub953.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub953.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,134 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/ti,ds90ub953.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments DS90UB953 FPD-Link III Serializer
+
+maintainers:
+  - Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+description:
+  The TI DS90UB953 is an FPD-Link III video serializer for MIPI CSI-2.
+
+properties:
+  compatible:
+    enum:
+      - ti,ds90ub953-q1
+      - ti,ds90ub971-q1
+
+  '#gpio-cells':
+    const: 2
+    description:
+      First cell is the GPIO pin number, second cell is the flags. The GPIO pin
+      number must be in range of [0, 3].
+
+  gpio-controller: true
+
+  clocks:
+    maxItems: 1
+    description:
+      Reference clock connected to the CLKIN pin.
+
+  clock-names:
+    items:
+      - const: clkin
+
+  '#clock-cells':
+    const: 0
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: CSI-2 input port
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+
+            required:
+              - data-lanes
+
+      port@1:
+        $ref: /schemas/graph.yaml#/properties/port
+        unevaluatedProperties: false
+        description: FPD-Link III output port
+
+    required:
+      - port@0
+      - port@1
+
+  i2c:
+    $ref: /schemas/i2c/i2c-controller.yaml#
+    unevaluatedProperties: false
+
+required:
+  - compatible
+  - '#gpio-cells'
+  - gpio-controller
+  - '#clock-cells'
+  - ports
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    serializer {
+      compatible = "ti,ds90ub953-q1";
+
+      gpio-controller;
+      #gpio-cells = <2>;
+
+      #clock-cells = <0>;
+
+      ports {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        port@0 {
+          reg = <0>;
+          ub953_in: endpoint {
+            clock-lanes = <0>;
+            data-lanes = <1 2 3 4>;
+            remote-endpoint = <&sensor_out>;
+          };
+        };
+
+        port@1 {
+          reg = <1>;
+          endpoint {
+            remote-endpoint = <&deser_fpd_in>;
+          };
+        };
+      };
+
+      i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        sensor@1a {
+          compatible = "sony,imx274";
+          reg = <0x1a>;
+
+          reset-gpios = <&serializer 0 GPIO_ACTIVE_LOW>;
+
+          clocks = <&serializer>;
+          clock-names = "inck";
+
+          port {
+            sensor_out: endpoint {
+              remote-endpoint = <&ub953_in>;
+            };
+          };
+        };
+      };
+    };
+...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml
--- a/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/media/i2c/ti,ds90ub960.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,428 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/ti,ds90ub960.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments DS90UB9XX Family FPD-Link Deserializer Hubs
+
+maintainers:
+  - Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+description:
+  The TI DS90UB9XX devices are FPD-Link video deserializers with I2C and GPIO
+  forwarding.
+
+allOf:
+  - $ref: /schemas/i2c/i2c-atr.yaml#
+
+properties:
+  compatible:
+    enum:
+      - ti,ds90ub954-q1
+      - ti,ds90ub960-q1
+      - ti,ds90ub9702-q1
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+    description:
+      Reference clock connected to the REFCLK pin.
+
+  clock-names:
+    items:
+      - const: refclk
+
+  powerdown-gpios:
+    maxItems: 1
+    description:
+      Specifier for the GPIO connected to the PDB pin.
+
+  i2c-alias-pool:
+    minItems: 1
+    maxItems: 32
+
+  links:
+    type: object
+    additionalProperties: false
+
+    properties:
+      '#address-cells':
+        const: 1
+
+      '#size-cells':
+        const: 0
+
+      ti,manual-strobe:
+        type: boolean
+        description:
+          Enable manual strobe position and EQ level
+
+    patternProperties:
+      '^link@[0-3]$':
+        type: object
+        additionalProperties: false
+        properties:
+          reg:
+            description: The link number
+            maxItems: 1
+
+          i2c-alias:
+            description:
+              The I2C address used for the serializer. Transactions to this
+              address on the I2C bus where the deserializer resides are
+              forwarded to the serializer.
+
+          ti,rx-mode:
+            $ref: /schemas/types.yaml#/definitions/uint32
+            enum:
+              - 0 # RAW10
+              - 1 # RAW12 HF
+              - 2 # RAW12 LF
+              - 3 # CSI2 SYNC
+              - 4 # CSI2 NON-SYNC
+            description:
+              FPD-Link Input Mode. This should reflect the hardware and the
+              default mode of the connected device.
+
+          ti,cdr-mode:
+            $ref: /schemas/types.yaml#/definitions/uint32
+            enum:
+              - 0 # FPD-Link III
+              - 1 # FPD-Link IV
+            description:
+              FPD-Link CDR Mode. This should reflect the hardware and the
+              default mode of the connected device.
+
+          ti,strobe-pos:
+            $ref: /schemas/types.yaml#/definitions/int32
+            minimum: -13
+            maximum: 13
+            description: Manual strobe position
+
+          ti,eq-level:
+            $ref: /schemas/types.yaml#/definitions/uint32
+            maximum: 14
+            description: Manual EQ level
+
+          serializer:
+            type: object
+            description: FPD-Link Serializer node
+
+        required:
+          - reg
+          - i2c-alias
+          - ti,rx-mode
+          - serializer
+
+  ports:
+    $ref: /schemas/graph.yaml#/properties/ports
+
+    properties:
+      port@0:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: FPD-Link input 0
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+            description:
+              Endpoint for FPD-Link port. If the RX mode for this port is RAW,
+              hsync-active and vsync-active must be defined.
+
+      port@1:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: FPD-Link input 1
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+            description:
+              Endpoint for FPD-Link port. If the RX mode for this port is RAW,
+              hsync-active and vsync-active must be defined.
+
+      port@2:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: FPD-Link input 2
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+            description:
+              Endpoint for FPD-Link port. If the RX mode for this port is RAW,
+              hsync-active and vsync-active must be defined.
+
+      port@3:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: FPD-Link input 3
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+            description:
+              Endpoint for FPD-Link port. If the RX mode for this port is RAW,
+              hsync-active and vsync-active must be defined.
+
+      port@4:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: CSI-2 Output 0
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+
+            properties:
+              data-lanes:
+                minItems: 1
+                maxItems: 4
+              link-frequencies:
+                maxItems: 1
+
+            required:
+              - data-lanes
+              - link-frequencies
+
+      port@5:
+        $ref: /schemas/graph.yaml#/$defs/port-base
+        unevaluatedProperties: false
+        description: CSI-2 Output 1
+
+        properties:
+          endpoint:
+            $ref: /schemas/media/video-interfaces.yaml#
+            unevaluatedProperties: false
+
+            properties:
+              data-lanes:
+                minItems: 1
+                maxItems: 4
+              link-frequencies:
+                maxItems: 1
+
+            required:
+              - data-lanes
+              - link-frequencies
+
+    required:
+      - port@0
+      - port@1
+      - port@2
+      - port@3
+      - port@4
+      - port@5
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - clock-names
+  - ports
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/gpio/gpio.h>
+
+    i2c {
+      clock-frequency = <400000>;
+      #address-cells = <1>;
+      #size-cells = <0>;
+
+      deser@3d {
+        compatible = "ti,ds90ub960-q1";
+        reg = <0x3d>;
+
+        clock-names = "refclk";
+        clocks = <&fixed_clock>;
+
+        powerdown-gpios = <&pca9555 7 GPIO_ACTIVE_LOW>;
+
+        i2c-alias-pool = <0x4a 0x4b 0x4c 0x4d 0x4e 0x4f>;
+
+        ports {
+          #address-cells = <1>;
+          #size-cells = <0>;
+
+          /* Port 0, Camera 0 */
+          port@0 {
+            reg = <0>;
+
+            ub960_fpd3_1_in: endpoint {
+              remote-endpoint = <&ub953_1_out>;
+            };
+          };
+
+          /* Port 1, Camera 1 */
+          port@1 {
+            reg = <1>;
+
+            ub960_fpd3_2_in: endpoint {
+              remote-endpoint = <&ub913_2_out>;
+              hsync-active = <0>;
+              vsync-active = <1>;
+            };
+          };
+
+          /* Port 2, unconnected */
+          port@2 {
+            reg = <2>;
+          };
+
+          /* Port 3, unconnected */
+          port@3 {
+            reg = <3>;
+          };
+
+          /* Port 4, CSI-2 TX */
+          port@4 {
+            reg = <4>;
+            ds90ub960_0_csi_out: endpoint {
+              data-lanes = <1 2 3 4>;
+              link-frequencies = /bits/ 64 <800000000>;
+              remote-endpoint = <&csi2_phy0>;
+            };
+          };
+
+          /* Port 5, unconnected */
+          port@5 {
+            reg = <5>;
+          };
+        };
+
+        links {
+          #address-cells = <1>;
+          #size-cells = <0>;
+
+          /* Link 0 has DS90UB953 serializer and IMX274 sensor */
+
+          link@0 {
+            reg = <0>;
+            i2c-alias = <0x44>;
+
+            ti,rx-mode = <3>;
+
+            serializer1: serializer {
+              compatible = "ti,ds90ub953-q1";
+
+              gpio-controller;
+              #gpio-cells = <2>;
+
+              #clock-cells = <0>;
+
+              ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port@0 {
+                  reg = <0>;
+                  ub953_1_in: endpoint {
+                    data-lanes = <1 2 3 4>;
+                    remote-endpoint = <&sensor_1_out>;
+                  };
+                };
+
+                port@1 {
+                  reg = <1>;
+
+                  ub953_1_out: endpoint {
+                    remote-endpoint = <&ub960_fpd3_1_in>;
+                  };
+                };
+              };
+
+              i2c {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                sensor@1a {
+                  compatible = "sony,imx274";
+                  reg = <0x1a>;
+
+                  reset-gpios = <&serializer1 0 GPIO_ACTIVE_LOW>;
+
+                  port {
+                    sensor_1_out: endpoint {
+                      remote-endpoint = <&ub953_1_in>;
+                    };
+                  };
+                };
+              };
+            };
+          };  /* End of link@0 */
+
+          /* Link 1 has DS90UB913 serializer and MT9V111 sensor */
+
+          link@1 {
+            reg = <1>;
+            i2c-alias = <0x45>;
+
+            ti,rx-mode = <0>;
+
+            serializer2: serializer {
+              compatible = "ti,ds90ub913a-q1";
+
+              gpio-controller;
+              #gpio-cells = <2>;
+
+              clocks = <&clk_cam_48M>;
+              clock-names = "clkin";
+
+              #clock-cells = <0>;
+
+              ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port@0 {
+                  reg = <0>;
+                  ub913_2_in: endpoint {
+                    remote-endpoint = <&sensor_2_out>;
+                    pclk-sample = <1>;
+                  };
+                };
+
+                port@1 {
+                  reg = <1>;
+
+                  ub913_2_out: endpoint {
+                    remote-endpoint = <&ub960_fpd3_2_in>;
+                  };
+                };
+              };
+
+              i2c {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                sensor@48 {
+                  compatible = "aptina,mt9v111";
+                  reg = <0x48>;
+
+                  clocks = <&serializer2>;
+
+                  port {
+                    sensor_2_out: endpoint {
+                      remote-endpoint = <&ub913_2_in>;
+                    };
+                  };
+                };
+              };
+            };
+          }; /* End of link@1 */
+        };
+      };
+    };
+...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/img,d5500-vxd.yaml b/Documentation/devicetree/bindings/media/img,d5500-vxd.yaml
--- a/Documentation/devicetree/bindings/media/img,d5500-vxd.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/media/img,d5500-vxd.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/img,d5500-vxd.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Imagination D5520-VXD Driver
+
+maintainers:
+  - Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+  - Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+
+description: |
+ The IMG VXD video decode driver for the D5500-VXD is a video decoder for
+ multiple video formats including H.264 and HEVC on the TI J721E family
+ of SoCs.
+
+properties:
+  compatible:
+    const: img,d5500-vxd
+
+  reg:
+    maxItems: 2
+
+  interrupts:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/irq.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    d5520: video-decoder@4300000 {
+            /* IMG D5520 driver configuration */
+            compatible = "img,d5500-vxd";
+            reg = <0x00 0x04300000>,
+                  <0x00 0x100000>;
+            power-domains = <&k3_pds 144>;
+            interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+    };
+
+...
diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml b/Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml
--- a/Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/img,e5010-jpeg-enc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Imagination E5010 JPEG Encoder
+
+maintainers:
+  - Devarsh Thakkar <devarsht@ti.com>
+
+description: |
+  The E5010 is a JPEG encoder from Imagination Technologies implemented on
+  TI's AM62A SoC. It is capable of real time encoding of YUV420 and YUV422
+  inputs to JPEG and M-JPEG. It supports baseline JPEG Encoding up to
+  8Kx8K resolution.
+
+properties:
+  compatible:
+    const: img,e5010-jpeg-enc
+
+  reg:
+    items:
+      - description: The E5010 main register region
+      - description: The E5010 mmu register region
+
+  reg-names:
+    items:
+      - const: regjasper
+      - const: regmmu
+
+  power-domains:
+    maxItems: 1
+
+  resets:
+    maxItems: 1
+
+  clocks:
+    minItems: 1
+    maxItems: 2
+
+  clock-names:
+    minItems: 1
+    maxItems: 2
+
+  interrupts:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - interrupts
+  - clocks
+  - clock-names
+  - power-domains
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    e5010: e5010@fd20000 {
+        compatible = "img,e5010-jpeg-enc";
+        reg = <0x00 0xfd20000 0x00 0x100>,
+              <0x00 0xfd20200 0x00 0x200>;
+        reg-names = "regjasper", "regmmu";
+        clocks = <&k3_clks 201 0>;
+        clock-names = "core_clk";
+        power-domains = <&k3_pds 201 TI_SCI_PD_EXCLUSIVE>;
+        interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/img,vxe384.yaml b/Documentation/devicetree/bindings/media/img,vxe384.yaml
--- a/Documentation/devicetree/bindings/media/img,vxe384.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/media/img,vxe384.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/media/img,vxe384.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Imagination VXE384 Driver
+
+maintainers:
+  - Sidraya Jayagond  <sidraya.bj@pathpartnertech.com>
+
+description: |
+  The IMG VXE384 video encode driver for the VXE384 is a video encoder for
+  multiple video formats including H.264 on the TI J721E family of SoCs.
+
+properties:
+  compatible:
+    const: img,vxe384
+
+  reg:
+    maxItems: 2
+
+  interrupts:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+       #include <dt-bindings/interrupt-controller/irq.h>
+       #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+       vxe384: video-encoder@4200000 {
+               compatible = "img,vxe384";
+               reg = <0x00 0x04200000>,
+                     <0x00 0x100000>;
+               power-domains = <&k3_pds 153>;
+               interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
+       };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/ti,j721e-csi2rx.yaml b/Documentation/devicetree/bindings/media/ti,j721e-csi2rx.yaml
--- a/Documentation/devicetree/bindings/media/ti,j721e-csi2rx.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/media/ti,j721e-csi2rx.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,100 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/ti,j721e-csi2rx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI J721E CSI2RX Wrapper
+
+description: |
+  The TI J721E CSI2RX Wrapper is a wrapper around Cadence CSI2RX bridge that
+  enables sending captured frames to memory over PSI-L DMA. In the J721E
+  Technical Reference Manual (SPRUIL1B) it is referred to as "SHIM" under the
+  CSI_RX_IF section.
+
+maintainers:
+  - Vaishnav Achath <vaishnav.a@ti.com>
+
+properties:
+  compatible:
+      - const: ti,j721e-csi2rx
+
+  dmas:
+    maxItems: 1
+
+  dma-names:
+    items:
+      - const: rx0
+
+  reg:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  ranges: true
+
+  "#address-cells": true
+
+  "#size-cells": true
+
+patternProperties:
+  "^csi-bridge@":
+    type: object
+    description: CSI2 bridge node.
+    $ref: cdns,csi2rx.yaml#
+
+required:
+  - compatible
+  - reg
+  - dmas
+  - dma-names
+  - power-domains
+  - ranges
+  - "#address-cells"
+  - "#size-cells"
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+
+    ti_csi2rx0: ticsi2rx@4500000 {
+        compatible = "ti,j721e-csi2rx";
+        dmas = <&main_udmap 0x4940>;
+        dma-names = "rx0";
+        reg = <0x4500000 0x1000>;
+        power-domains = <&k3_pds 26 TI_SCI_PD_EXCLUSIVE>;
+        #address-cells = <1>;
+        #size-cells = <1>;
+        ranges;
+
+        cdns_csi2rx: csi-bridge@4504000 {
+            compatible = "cdns,csi2rx";
+            reg = <0x4504000 0x1000>;
+            clocks = <&k3_clks 26 2>, <&k3_clks 26 0>, <&k3_clks 26 2>,
+              <&k3_clks 26 2>, <&k3_clks 26 3>, <&k3_clks 26 3>;
+            clock-names = "sys_clk", "p_clk", "pixel_if0_clk",
+              "pixel_if1_clk", "pixel_if2_clk", "pixel_if3_clk";
+            phys = <&dphy0>;
+            phy-names = "dphy";
+
+            ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                csi2_0: port@0 {
+
+                    reg = <0>;
+
+                    csi2rx0_in_sensor: endpoint {
+                        remote-endpoint = <&csi2_cam0>;
+                        bus-type = <4>; /* CSI2 DPHY. */
+                        clock-lanes = <0>;
+                        data-lanes = <1 2>;
+                    };
+                };
+            };
+        };
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/media/video-interfaces.yaml b/Documentation/devicetree/bindings/media/video-interfaces.yaml
--- a/Documentation/devicetree/bindings/media/video-interfaces.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/media/video-interfaces.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -159,6 +159,7 @@
     $ref: /schemas/types.yaml#/definitions/uint32-array
     minItems: 1
     maxItems: 8
+    uniqueItems: true
     items:
       # Assume up to 9 physical lane indices
       maximum: 8
diff -Naur --no-dereference a/Documentation/devicetree/bindings/mfd/ti,tps6594.yaml b/Documentation/devicetree/bindings/mfd/ti,tps6594.yaml
--- a/Documentation/devicetree/bindings/mfd/ti,tps6594.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/mfd/ti,tps6594.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,193 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/ti,tps6594.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI TPS6594 Power Management Integrated Circuit
+
+maintainers:
+  - Julien Panis <jpanis@baylibre.com>
+
+description:
+  TPS6594 is a Power Management IC which provides regulators and others
+  features like GPIOs, RTC, watchdog, ESMs (Error Signal Monitor), and
+  PFSM (Pre-configurable Finite State Machine) managing the state of the device.
+  TPS6594 is the super-set device while TPS6593 and LP8764 are derivatives.
+
+properties:
+  compatible:
+    enum:
+      - ti,lp8764-q1
+      - ti,tps6593-q1
+      - ti,tps6594-q1
+
+  reg:
+    description: I2C slave address or SPI chip select number.
+    maxItems: 1
+
+  ti,primary-pmic:
+    type: boolean
+    description: |
+      Identify the primary PMIC on SPMI bus.
+      A multi-PMIC synchronization scheme is implemented in the PMIC device
+      to synchronize the power state changes with other PMIC devices. This is
+      accomplished through a SPMI bus: the primary PMIC is the controller
+      device on the SPMI bus, and the secondary PMICs are the target devices
+      on the SPMI bus.
+
+  system-power-controller: true
+
+  gpio-controller: true
+
+  '#gpio-cells':
+    const: 2
+    description: |
+      The first cell is the pin number, the second cell is used to specify flags.
+      See ../gpio/gpio.txt for more information.
+
+  interrupts:
+    maxItems: 1
+
+  regulators:
+    type: object
+    description: List of regulators provided by this controller.
+
+    patternProperties:
+      "^buck([1-5]|12|34|123|1234)$":
+        type: object
+        $ref: /schemas/regulator/regulator.yaml#
+
+        unevaluatedProperties: false
+
+      "^ldo[1-4]$":
+        type: object
+        $ref: /schemas/regulator/regulator.yaml#
+
+        unevaluatedProperties: false
+
+    allOf:
+      - if:
+          required:
+            - buck12
+        then:
+          properties:
+            buck123: false
+            buck1234: false
+      - if:
+          required:
+            - buck123
+        then:
+          properties:
+            buck34: false
+      - if:
+          required:
+            - buck1234
+        then:
+          properties:
+            buck34: false
+
+    additionalProperties: false
+
+patternProperties:
+  "^buck([1-5]|12|34|123|1234)-supply$":
+    description: Input supply phandle for each buck.
+
+  "^ldo[1-4]-supply$":
+    description: Input supply phandle for each ldo.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    i2c {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        tps6593: pmic@48 {
+            compatible = "ti,tps6593-q1";
+            reg = <0x48>;
+            ti,primary-pmic;
+            system-power-controller;
+
+            gpio-controller;
+            #gpio-cells = <2>;
+
+            pinctrl-names = "default";
+            pinctrl-0 = <&pmic_irq_pins_default>;
+            interrupt-parent = <&mcu_gpio0>;
+            interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
+
+            buck123-supply = <&vcc_3v3_sys>;
+            buck4-supply = <&vcc_3v3_sys>;
+            buck5-supply = <&vcc_3v3_sys>;
+            ldo1-supply = <&vcc_3v3_sys>;
+            ldo2-supply = <&vcc_3v3_sys>;
+            ldo3-supply = <&buck5>;
+            ldo4-supply = <&vcc_3v3_sys>;
+
+            regulators {
+                buck123: buck123 {
+                    regulator-name = "vcc_core";
+                    regulator-min-microvolt = <750000>;
+                    regulator-max-microvolt = <850000>;
+                    regulator-boot-on;
+                    regulator-always-on;
+                };
+
+                buck4: buck4 {
+                    regulator-name = "vcc_1v1";
+                    regulator-min-microvolt = <1100000>;
+                    regulator-max-microvolt = <1100000>;
+                    regulator-boot-on;
+                    regulator-always-on;
+                };
+
+                buck5: buck5 {
+                    regulator-name = "vcc_1v8_sys";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <1800000>;
+                    regulator-boot-on;
+                    regulator-always-on;
+                };
+
+                ldo1: ldo1 {
+                    regulator-name = "vddshv5_sdio";
+                    regulator-min-microvolt = <3300000>;
+                    regulator-max-microvolt = <3300000>;
+                    regulator-boot-on;
+                    regulator-always-on;
+                };
+
+                ldo2: ldo2 {
+                    regulator-name = "vpp_1v8";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <1800000>;
+                    regulator-boot-on;
+                    regulator-always-on;
+                };
+
+                ldo3: ldo3 {
+                    regulator-name = "vcc_0v85";
+                    regulator-min-microvolt = <850000>;
+                    regulator-max-microvolt = <850000>;
+                    regulator-boot-on;
+                    regulator-always-on;
+                };
+
+                ldo4: ldo4 {
+                    regulator-name = "vdda_1v8";
+                    regulator-min-microvolt = <1800000>;
+                    regulator-max-microvolt = <1800000>;
+                    regulator-boot-on;
+                    regulator-always-on;
+                };
+            };
+        };
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/misc/ti,dma-buf-phys.yaml b/Documentation/devicetree/bindings/misc/ti,dma-buf-phys.yaml
--- a/Documentation/devicetree/bindings/misc/ti,dma-buf-phys.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/misc/ti,dma-buf-phys.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+# Copyright (C) 2020 Texas Instruments Incorporated - https://www.ti.com/
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/ti,dma-buf-phys.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: DMA-BUF contiguous buffer physical address user-space exporter binding
+
+description: |
+  Driver allowing user-space attaching of DMA-BUFs returning CPU physical
+  addresses. The reasoning for making this act like a regular device
+  described by DT is so the virtual device that binds the buffer can be
+  made to act as if it is out on a bus or behind an IOMMU, for example.
+
+maintainers:
+  - Andrew Davis <afd@ti.com>
+
+properties:
+  compatible:
+    const: ti,dma-buf-phys
+
+  iommus:
+    maxItems: 1
+
+  dma-coherent: true
+
+required:
+  - compatible
+
+additionalProperties: false
+
+examples:
+  - |
+    dma-buf-phys {
+      compatible = "ti,dma-buf-phys";
+      iommus = <&some_iommu>;
+      dma-coherent;
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml b/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml
--- a/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -118,12 +118,14 @@
   phys:
     maxItems: 1
 
+  wakeup-source:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description: This device is capable to wakeup the SoC.
+
 required:
   - compatible
   - reg
   - reg-names
-  - interrupts
-  - interrupt-names
   - clocks
   - clock-names
   - bosch,mram-cfg
@@ -132,6 +134,7 @@
 
 examples:
   - |
+    // Example with interrupts
     #include <dt-bindings/clock/imx6sx-clock.h>
     can@20e8000 {
       compatible = "bosch,m_can";
@@ -142,6 +145,23 @@
       clocks = <&clks IMX6SX_CLK_CANFD>,
                <&clks IMX6SX_CLK_CANFD>;
       clock-names = "hclk", "cclk";
+      bosch,mram-cfg = <0x0 0 0 32 0 0 0 1>;
+
+      can-transceiver {
+        max-bitrate = <5000000>;
+      };
+    };
+
+  - |
+    // Example with timer polling
+    #include <dt-bindings/clock/imx6sx-clock.h>
+    can@20e8000 {
+      compatible = "bosch,m_can";
+      reg = <0x020e8000 0x4000>, <0x02298000 0x4000>;
+      reg-names = "m_can", "message_ram";
+      clocks = <&clks IMX6SX_CLK_CANFD>,
+               <&clks IMX6SX_CLK_CANFD>;
+      clock-names = "hclk", "cclk";
       bosch,mram-cfg = <0x0 0 0 32 0 0 0 1>;
 
       can-transceiver {
diff -Naur --no-dereference a/Documentation/devicetree/bindings/net/ti,cpsw-virt-mac.yaml b/Documentation/devicetree/bindings/net/ti,cpsw-virt-mac.yaml
--- a/Documentation/devicetree/bindings/net/ti,cpsw-virt-mac.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/net/ti,cpsw-virt-mac.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,104 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/ti,cpsw-virt-mac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI J721E VIRT CPSWxg Ethernet mac
+
+maintainers:
+  - Siddharth Vadapalli <s-vadapalli@ti.com>
+
+description: |
+  This document defines the bindings for the Virtual Mac thin client Linux
+  driver that utilizes Remoteproc Framework to communicate and exchange
+  network data with the EthSwitch Firmware running on the R-Core.
+
+properties:
+  compatible:
+    const: ti,j721e-cpsw-virt-mac
+
+  dma-coherent: true
+
+  dmas:
+    maxItems: 9
+
+  dma-names:
+    items:
+      - const: tx0
+      - const: tx1
+      - const: tx2
+      - const: tx3
+      - const: tx4
+      - const: tx5
+      - const: tx6
+      - const: tx7
+      - const: rx
+
+  ti,psil-base:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      CPSWxg NUSS PSI-L endpoint thread ID base of the UDMA-P
+      channels. The PSI-L endpoint node thread configuration
+      subnodes must be present with ti,psil-configX naming
+      convention, where X is the thread ID offset.
+
+  ti,remote-name:
+    $ref: /schemas/types.yaml#/definitions/string
+    description: |
+      Name of the connected rpmsg-kdrv device represented
+      by Eth switch FW running on one of the R5F cores.
+    items:
+      - enum:
+          - mpu_1_0_ethswitch-device-0
+          - mpu_1_0_ethmac-device-1
+
+  virt-emac-port:
+    type: object
+    properties:
+
+      ti,label:
+        $ref: /schemas/types.yaml#/definitions/string
+        description: |
+          Describes the label associated with this port.
+        items:
+          - const: virt-port
+
+      local-mac-address: true
+
+required:
+  - compatible
+  - dmas
+  - dma-names
+  - ti,psil-base
+  - ti,remote-name
+  - virt-emac-port
+
+additionalProperties: false
+
+examples:
+  - |
+    cpsw9g_virt_mac: main-r5fss-cpsw9g-virt-mac0 {
+            compatible = "ti,j721e-cpsw-virt-mac";
+            dma-coherent;
+            ti,psil-base = <0x4a00>;
+            ti,remote-name = "mpu_1_0_ethswitch-device-0";
+
+            dmas = <&main_udmap 0xca00>,
+                   <&main_udmap 0xca01>,
+                   <&main_udmap 0xca02>,
+                   <&main_udmap 0xca03>,
+                   <&main_udmap 0xca04>,
+                   <&main_udmap 0xca05>,
+                   <&main_udmap 0xca06>,
+                   <&main_udmap 0xca07>,
+                   <&main_udmap 0x4a00>;
+            dma-names = "tx0", "tx1", "tx2", "tx3",
+                        "tx4", "tx5", "tx6", "tx7",
+                        "rx";
+
+            virt-emac-port {
+                    ti,label = "virt-port";
+                    /* local-mac-address = [0 0 0 0 0 0]; */
+            };
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml b/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml
--- a/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/net/ti,icssg-prueth.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,198 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/ti,icssg-prueth.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments ICSSG PRUSS Ethernet
+
+maintainers:
+  - Md Danish Anwar <danishanwar@ti.com>
+
+description:
+  Ethernet based on the Programmable Real-Time Unit and Industrial
+  Communication Subsystem.
+
+allOf:
+  - $ref: /schemas/remoteproc/ti,pru-consumer.yaml#
+
+properties:
+  compatible:
+    enum:
+      - ti,am654-icssg-prueth  # for AM65x SoC family
+      - ti,am642-icssg-prueth  # for AM64x SoC family
+
+  sram:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      phandle to MSMC SRAM node
+
+  dmas:
+    maxItems: 10
+
+  dma-names:
+    items:
+      - const: tx0-0
+      - const: tx0-1
+      - const: tx0-2
+      - const: tx0-3
+      - const: tx1-0
+      - const: tx1-1
+      - const: tx1-2
+      - const: tx1-3
+      - const: rx0
+      - const: rx1
+
+  ti,mii-g-rt:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      phandle to MII_G_RT module's syscon regmap.
+
+  ti,mii-rt:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      phandle to MII_RT module's syscon regmap
+
+  ti,pa-stats:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description:
+      phandle to PA_STATS module's syscon regmap
+
+  interrupts:
+    maxItems: 2
+    description:
+      Interrupt specifiers to TX timestamp IRQ.
+
+  interrupt-names:
+    items:
+      - const: tx_ts0
+      - const: tx_ts1
+
+  ethernet-ports:
+    type: object
+    additionalProperties: false
+
+    properties:
+      '#address-cells':
+        const: 1
+      '#size-cells':
+        const: 0
+
+    patternProperties:
+      ^port@[0-1]$:
+        type: object
+        description: ICSSG PRUETH external ports
+        $ref: ethernet-controller.yaml#
+        unevaluatedProperties: false
+
+        properties:
+          reg:
+            items:
+              - enum: [0, 1]
+            description: ICSSG PRUETH port number
+
+          interrupts:
+            maxItems: 1
+
+          ti,syscon-rgmii-delay:
+            items:
+              - items:
+                  - description: phandle to system controller node
+                  - description: The offset to ICSSG control register
+            $ref: /schemas/types.yaml#/definitions/phandle-array
+            description:
+              phandle to system controller node and register offset
+              to ICSSG control register for RGMII transmit delay
+
+          ti,half-duplex-capable:
+            description:
+              Enable half duplex operation on ICSSG MII port. This requires
+              PHY output pin (COL) to be routed to ICSSG GPIO pin
+              (PRGx_PRU0/1_GPIO10) as input.
+
+        required:
+          - reg
+    anyOf:
+      - required:
+          - port@0
+      - required:
+          - port@1
+
+required:
+  - compatible
+  - sram
+  - dmas
+  - dma-names
+  - ethernet-ports
+  - ti,mii-g-rt
+  - ti,pa-stats
+  - interrupts
+  - interrupt-names
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    /* Example k3-am654 base board SR2.0, dual-emac */
+    pruss2_eth: ethernet {
+        compatible = "ti,am654-icssg-prueth";
+        pinctrl-names = "default";
+        pinctrl-0 = <&icssg2_rgmii_pins_default>;
+        sram = <&msmc_ram>;
+
+        ti,prus = <&pru2_0>, <&rtu2_0>, <&tx_pru2_0>,
+                  <&pru2_1>, <&rtu2_1>, <&tx_pru2_1>;
+        firmware-name = "ti-pruss/am65x-pru0-prueth-fw.elf",
+                        "ti-pruss/am65x-rtu0-prueth-fw.elf",
+                        "ti-pruss/am65x-txpru0-prueth-fw.elf",
+                        "ti-pruss/am65x-pru1-prueth-fw.elf",
+                        "ti-pruss/am65x-rtu1-prueth-fw.elf",
+                        "ti-pruss/am65x-txpru1-prueth-fw.elf";
+        ti,pruss-gp-mux-sel = <2>,      /* MII mode */
+                              <2>,
+                              <2>,
+                              <2>,      /* MII mode */
+                              <2>,
+                              <2>;
+        dmas = <&main_udmap 0xc300>, /* egress slice 0 */
+               <&main_udmap 0xc301>, /* egress slice 0 */
+               <&main_udmap 0xc302>, /* egress slice 0 */
+               <&main_udmap 0xc303>, /* egress slice 0 */
+               <&main_udmap 0xc304>, /* egress slice 1 */
+               <&main_udmap 0xc305>, /* egress slice 1 */
+               <&main_udmap 0xc306>, /* egress slice 1 */
+               <&main_udmap 0xc307>, /* egress slice 1 */
+               <&main_udmap 0x4300>, /* ingress slice 0 */
+               <&main_udmap 0x4301>; /* ingress slice 1 */
+        dma-names = "tx0-0", "tx0-1", "tx0-2", "tx0-3",
+                    "tx1-0", "tx1-1", "tx1-2", "tx1-3",
+                    "rx0", "rx1";
+        ti,mii-g-rt = <&icssg2_mii_g_rt>;
+        ti,pa-stats = <&icssg2_pa_stats>;
+        interrupt-parent = <&icssg2_intc>;
+        interrupts = <24 0 2>, <25 1 3>;
+        interrupt-names = "tx_ts0", "tx_ts1";
+        ethernet-ports {
+            #address-cells = <1>;
+            #size-cells = <0>;
+            pruss2_emac0: port@0 {
+                reg = <0>;
+                phy-handle = <&pruss2_eth0_phy>;
+                phy-mode = "rgmii-id";
+                interrupts-extended = <&icssg2_intc 24>;
+                ti,syscon-rgmii-delay = <&scm_conf 0x4120>;
+                /* Filled in by bootloader */
+                local-mac-address = [00 00 00 00 00 00];
+            };
+
+            pruss2_emac1: port@1 {
+                reg = <1>;
+                phy-handle = <&pruss2_eth1_phy>;
+                phy-mode = "rgmii-id";
+                interrupts-extended = <&icssg2_intc 25>;
+                ti,syscon-rgmii-delay = <&scm_conf 0x4124>;
+                /* Filled in by bootloader */
+                local-mac-address = [00 00 00 00 00 00];
+            };
+        };
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/net/ti,icss-iep.yaml b/Documentation/devicetree/bindings/net/ti,icss-iep.yaml
--- a/Documentation/devicetree/bindings/net/ti,icss-iep.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/net/ti,icss-iep.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/ti,icss-iep.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments ICSS Industrial Ethernet Peripheral (IEP) module
+
+maintainers:
+  - Lokesh Vutla <lokeshvutla@ti.com>
+
+properties:
+  compatible:
+    enum:
+      - ti,am654-icss-iep   # for K3 AM65x, J721E and AM64x SoCs
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+    description: phandle to the IEP source clock
+
+required:
+  - compatible
+  - reg
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    icssg0_iep0: iep@2e000 {
+        compatible = "ti,am654-icss-iep";
+        reg = <0x2e000 0x1000>;
+        clocks = <&icssg0_iepclk_mux>;
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml b/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml
--- a/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -54,10 +54,12 @@
 
   compatible:
     enum:
+      - ti,am642-cpsw-nuss
       - ti,am654-cpsw-nuss
       - ti,j7200-cpswxg-nuss
       - ti,j721e-cpsw-nuss
-      - ti,am642-cpsw-nuss
+      - ti,j721e-cpswxg-nuss
+      - ti,j784s4-cpswxg-nuss
 
   reg:
     maxItems: 1
@@ -111,7 +113,7 @@
         const: 0
 
     patternProperties:
-      "^port@[1-4]$":
+      "^port@[1-8]$":
         type: object
         description: CPSWxG NUSS external ports
 
@@ -121,12 +123,22 @@
         properties:
           reg:
             minimum: 1
-            maximum: 4
+            maximum: 8
             description: CPSW port number
 
           phys:
-            maxItems: 1
-            description: phandle on phy-gmii-sel PHY
+            minItems: 1
+            items:
+              - description: CPSW MAC's PHY.
+              - description: Serdes PHY. Serdes PHY is required only if
+                             the Serdes has to be configured in the
+                             Single-Link configuration.
+
+          phy-names:
+            minItems: 1
+            items:
+              - const: mac
+              - const: serdes
 
           label:
             description: label associated with this port
@@ -186,18 +198,44 @@
         properties:
           compatible:
             contains:
-              const: ti,j7200-cpswxg-nuss
+              enum:
+                - ti,j721e-cpswxg-nuss
+                - ti,j784s4-cpswxg-nuss
+    then:
+      properties:
+        ethernet-ports:
+          patternProperties:
+            "^port@[5-8]$": false
+            "^port@[1-4]$":
+              properties:
+                reg:
+                  minimum: 1
+                  maximum: 4
+
+  - if:
+      not:
+        properties:
+          compatible:
+            contains:
+              enum:
+                - ti,j7200-cpswxg-nuss
+                - ti,j721e-cpswxg-nuss
+                - ti,j784s4-cpswxg-nuss
     then:
       properties:
         ethernet-ports:
           patternProperties:
-            "^port@[3-4]$": false
+            "^port@[3-8]$": false
+            "^port@[1-2]$":
+              properties:
+                reg:
+                  minimum: 1
+                  maximum: 2
 
 additionalProperties: false
 
 examples:
   - |
-    #include <dt-bindings/pinctrl/k3.h>
     #include <dt-bindings/soc/ti,sci_pm_domain.h>
     #include <dt-bindings/net/ti-dp83867.h>
     #include <dt-bindings/interrupt-controller/irq.h>
diff -Naur --no-dereference a/Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml b/Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml
--- a/Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -93,6 +93,14 @@
     description:
       Number of timestamp Generator function outputs (TS_GENFx)
 
+  ti,pps:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    minItems: 2
+    maxItems: 2
+    description: |
+      The pair of HWx_TS_PUSH input and TS_GENFy output indexes used for
+      PPS events generation. Platform/board specific.
+
   refclk-mux:
     type: object
     additionalProperties: false
diff -Naur --no-dereference a/Documentation/devicetree/bindings/pci/ti,am65-pci-ep.yaml b/Documentation/devicetree/bindings/pci/ti,am65-pci-ep.yaml
--- a/Documentation/devicetree/bindings/pci/ti,am65-pci-ep.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/pci/ti,am65-pci-ep.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -49,28 +49,40 @@
   - reg
   - reg-names
   - max-link-speed
+  - num-lanes
   - power-domains
   - ti,syscon-pcie-mode
+  - phys
+  - phy-names
   - dma-coherent
 
 unevaluatedProperties: false
 
 examples:
   - |
+    #include <dt-bindings/soc/ti,sci_pm_domain.h>
+    #include <dt-bindings/gpio/gpio.h>
     #include <dt-bindings/interrupt-controller/arm-gic.h>
     #include <dt-bindings/interrupt-controller/irq.h>
-    #include <dt-bindings/soc/ti,sci_pm_domain.h>
 
-    pcie0_ep: pcie-ep@5500000 {
-        compatible = "ti,am654-pcie-ep";
-        reg =  <0x5500000 0x1000>,
-               <0x5501000 0x1000>,
-               <0x10000000 0x8000000>,
-               <0x5506000 0x1000>;
-        reg-names = "app", "dbics", "addr_space", "atu";
-        power-domains = <&k3_pds 120 TI_SCI_PD_EXCLUSIVE>;
-        ti,syscon-pcie-mode = <&scm_conf 0x4060>;
-        max-link-speed = <2>;
-        dma-coherent;
-        interrupts = <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>;
+
+    bus {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        pcie0_ep: pcie-ep@5500000 {
+                compatible = "ti,am654-pcie-ep";
+                reg =  <0x0 0x5500000 0x0 0x1000>,
+                       <0x0 0x5501000 0x0 0x1000>,
+                       <0x0 0x10000000 0x0 0x8000000>,
+                       <0x0 0x5506000 0x0 0x1000>;
+                reg-names = "app", "dbics", "addr_space", "atu";
+                power-domains = <&k3_pds 120 TI_SCI_PD_EXCLUSIVE>;
+                ti,syscon-pcie-mode = <&pcie0_mode>;
+                num-ib-windows = <16>;
+                num-ob-windows = <16>;
+                max-link-speed = <2>;
+                dma-coherent;
+                interrupts = <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>;
+        };
     };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml b/Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml
--- a/Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/pci/ti,am65-pci-host.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -55,13 +55,25 @@
 
   dma-coherent: true
 
+patternProperties:
+  "interrupt-controller":
+    type: object
+    description: interrupt controller to handle legacy interrupts.
+
 required:
   - compatible
   - reg
   - reg-names
   - max-link-speed
+  - num-lanes
+  - power-domains
+  - reset-gpios
+  - phys
+  - phy-names
+  - dma-coherent
   - ti,syscon-pcie-id
   - ti,syscon-pcie-mode
+  - msi-map
   - ranges
 
 if:
@@ -82,25 +94,44 @@
     #include <dt-bindings/interrupt-controller/arm-gic.h>
     #include <dt-bindings/interrupt-controller/irq.h>
     #include <dt-bindings/soc/ti,sci_pm_domain.h>
+    #include <dt-bindings/gpio/gpio.h>
 
-    pcie0_rc: pcie@5500000 {
-        compatible = "ti,am654-pcie-rc";
-        reg =  <0x5500000 0x1000>,
-               <0x5501000 0x1000>,
-               <0x10000000 0x2000>,
-               <0x5506000 0x1000>;
-        reg-names = "app", "dbics", "config", "atu";
-        power-domains = <&k3_pds 120 TI_SCI_PD_EXCLUSIVE>;
-        #address-cells = <3>;
+    bus {
+        #address-cells = <2>;
         #size-cells = <2>;
-        ranges = <0x81000000 0 0          0x10020000 0 0x00010000>,
-                 <0x82000000 0 0x10030000 0x10030000 0 0x07FD0000>;
-        ti,syscon-pcie-id = <&scm_conf 0x0210>;
-        ti,syscon-pcie-mode = <&scm_conf 0x4060>;
-        bus-range = <0x0 0xff>;
-        max-link-speed = <2>;
-        dma-coherent;
-        interrupts = <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>;
-        msi-map = <0x0 &gic_its 0x0 0x10000>;
-        device_type = "pci";
+
+        pcie0_rc: pcie@5500000 {
+                compatible = "ti,am654-pcie-rc";
+                reg =  <0x0 0x5500000 0x0 0x1000>,
+                       <0x0 0x5501000 0x0 0x1000>,
+                       <0x0 0x10000000 0x0 0x2000>,
+                       <0x0 0x5506000 0x0 0x1000>;
+                reg-names = "app", "dbics", "config", "atu";
+                power-domains = <&k3_pds 120 TI_SCI_PD_EXCLUSIVE>;
+                #address-cells = <3>;
+                #size-cells = <2>;
+                ranges = <0x81000000 0 0          0x0 0x10020000 0 0x00010000>,
+                         <0x82000000 0 0x10030000 0x0 0x10030000 0 0x07FD0000>;
+                ti,syscon-pcie-id = <&pcie_devid>;
+                ti,syscon-pcie-mode = <&pcie0_mode>;
+                bus-range = <0x0 0xff>;
+                num-viewport = <16>;
+                max-link-speed = <2>;
+                dma-coherent;
+                interrupts = <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>;
+                msi-map = <0x0 &gic_its 0x0 0x10000>;
+                #interrupt-cells = <1>;
+                interrupt-map-mask = <0 0 0 7>;
+                interrupt-map = <0 0 0 1 &pcie0_intc 0>, /* INT A */
+                                <0 0 0 2 &pcie0_intc 0>, /* INT B */
+                                <0 0 0 3 &pcie0_intc 0>, /* INT C */
+                                <0 0 0 4 &pcie0_intc 0>; /* INT D */
+
+                pcie0_intc: interrupt-controller {
+                        interrupt-controller;
+                        #interrupt-cells = <1>;
+                        interrupt-parent = <&gic500>;
+                        interrupts = <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>;
+                };
+        };
     };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/pci/ti,j721e-pci-ep.yaml b/Documentation/devicetree/bindings/pci/ti,j721e-pci-ep.yaml
--- a/Documentation/devicetree/bindings/pci/ti,j721e-pci-ep.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/pci/ti,j721e-pci-ep.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -10,13 +10,11 @@
 maintainers:
   - Kishon Vijay Abraham I <kishon@ti.com>
 
-allOf:
-  - $ref: "cdns-pcie-ep.yaml#"
-
 properties:
   compatible:
     oneOf:
       - const: ti,j721e-pcie-ep
+      - const: ti,j784s4-pcie-ep
       - description: PCIe EP controller in AM64
         items:
           - const: ti,am64-pcie-ep
@@ -58,6 +56,48 @@
   dma-coherent:
     description: Indicates that the PCIe IP block can ensure the coherency
 
+  interrupts:
+    maxItems: 1
+
+  interrupt-names:
+    items:
+      - const: link_state
+
+allOf:
+  - $ref: cdns-pcie-ep.yaml#
+  - if:
+      properties:
+        compatible:
+          enum:
+            - ti,am64-pcie-ep
+    then:
+      properties:
+        num-lanes:
+          const: 1
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - ti,j7200-pcie-ep
+            - ti,j721e-pcie-ep
+    then:
+      properties:
+        num-lanes:
+          minimum: 1
+          maximum: 2
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - ti,j784s4-pcie-ep
+    then:
+      properties:
+        num-lanes:
+          minimum: 1
+          maximum: 4
+
 required:
   - compatible
   - reg
diff -Naur --no-dereference a/Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml b/Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml
--- a/Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/pci/ti,j721e-pci-host.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -10,13 +10,11 @@
 maintainers:
   - Kishon Vijay Abraham I <kishon@ti.com>
 
-allOf:
-  - $ref: "cdns-pcie-host.yaml#"
-
 properties:
   compatible:
     oneOf:
       - const: ti,j721e-pcie-host
+      - const: ti,j784s4-pcie-host
       - description: PCIe controller in AM64
         items:
           - const: ti,am64-pcie-host
@@ -44,6 +42,18 @@
           - description: pcie_ctrl register offset within SYSCON
     description: Specifier for configuring PCIe mode and link speed.
 
+  ti,syscon-pcie-refclk-out:
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    items:
+      - items:
+          - description: Phandle to the SYSCON entry
+          - description: lock2_kick0 register offset within SYSCON
+          - description: lock2_kick1 register offset within SYSCON
+          - description: acspcie_ctrl register offset within SYSCON
+          - description: pcie_refclk_clksel register offset within SYSCON
+          - description: clock source index to source ref clock
+    description: Specifier for enabling ACSPCIe clock buffer for reference clock output.
+
   power-domains:
     maxItems: 1
 
@@ -73,14 +83,72 @@
           - const: 0xb00f
       - items:
           - const: 0xb010
+      - items:
+          - const: 0xb013
 
   msi-map: true
 
+  interrupts:
+    maxItems: 1
+
+  interrupt-names:
+    items:
+      - const: link_state
+
+  interrupt-controller:
+    type: object
+    additionalProperties: false
+
+    properties:
+      interrupt-controller: true
+
+      '#interrupt-cells':
+        const: 1
+
+      interrupts:
+        maxItems: 1
+
+allOf:
+  - $ref: cdns-pcie-host.yaml#
+  - if:
+      properties:
+        compatible:
+          enum:
+            - ti,am64-pcie-host
+    then:
+      properties:
+        num-lanes:
+          const: 1
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - ti,j7200-pcie-host
+            - ti,j721e-pcie-host
+    then:
+      properties:
+        num-lanes:
+          minimum: 1
+          maximum: 2
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - ti,j784s4-pcie-host
+    then:
+      properties:
+        num-lanes:
+          minimum: 1
+          maximum: 4
+
 required:
   - compatible
   - reg
   - reg-names
   - ti,syscon-pcie-ctrl
+  - ti,syscon-pcie-refclk-out
   - max-link-speed
   - num-lanes
   - power-domains
@@ -101,6 +169,8 @@
   - |
     #include <dt-bindings/soc/ti,sci_pm_domain.h>
     #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
 
     bus {
         #address-cells = <2>;
@@ -133,5 +203,75 @@
             ranges = <0x01000000 0x0 0x10001000  0x00 0x10001000  0x0 0x0010000>,
                      <0x02000000 0x0 0x10011000  0x00 0x10011000  0x0 0x7fef000>;
             dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+            #interrupt-cells = <1>;
+            interrupt-map-mask = <0 0 0 7>;
+            interrupt-map = <0 0 0 1 &pcie1_intc 0>, /* INT A */
+                            <0 0 0 2 &pcie1_intc 0>, /* INT B */
+                            <0 0 0 3 &pcie1_intc 0>, /* INT C */
+                            <0 0 0 4 &pcie1_intc 0>; /* INT D */
+
+            pcie1_intc: interrupt-controller {
+                    interrupt-controller;
+                    #interrupt-cells = <1>;
+                    interrupt-parent = <&gic500>;
+                    interrupts = <GIC_SPI 324 IRQ_TYPE_EDGE_RISING>;
+            };
+
+        };
+    };
+
+  - |
+    #include <dt-bindings/mux/mux.h>
+    #include <dt-bindings/mux/ti-serdes.h>
+    #include <dt-bindings/phy/phy.h>
+    #include <dt-bindings/phy/phy-ti.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
+
+    bus {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        pcie1_rc: pcie@2910000 {
+                compatible = "ti,j784s4-pcie-host";
+                reg = <0x00 0x02910000 0x00 0x1000>,
+                      <0x00 0x02917000 0x00 0x400>,
+                      <0x00 0x0d800000 0x00 0x00800000>,
+                      <0x00 0x18000000 0x00 0x00001000>;
+                reg-names = "intd_cfg", "user_cfg", "reg", "cfg";
+                interrupt-names = "link_state";
+                interrupts = <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>;
+                device_type = "pci";
+                ti,syscon-pcie-ctrl = <&scm_conf 0x4074>;
+                ti,syscon-pcie-refclk-out = <&scm_conf 0x9008 0x900c 0x18090 0x8074 0x1>;
+                max-link-speed = <3>;
+                num-lanes = <4>;
+                power-domains = <&k3_pds 333 TI_SCI_PD_EXCLUSIVE>;
+                clocks = <&k3_clks 333 0>;
+                clock-names = "fck";
+                #address-cells = <3>;
+                #size-cells = <2>;
+                bus-range = <0x0 0xff>;
+                vendor-id = <0x104c>;
+                device-id = <0xb013>;
+                msi-map = <0x0 &gic_its 0x10000 0x10000>;
+                dma-coherent;
+                ranges = <0x01000000 0x0 0x18001000  0x00 0x18001000  0x0 0x0010000>,
+                         <0x02000000 0x0 0x18011000  0x00 0x18011000  0x0 0x7fef000>;
+                dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x10000 0x0>;
+                #interrupt-cells = <1>;
+                interrupt-map-mask = <0 0 0 7>;
+                interrupt-map = <0 0 0 1 &pcie0_intc 0>,
+                                <0 0 0 2 &pcie0_intc 0>,
+                                <0 0 0 3 &pcie0_intc 0>,
+                                <0 0 0 4 &pcie0_intc 0>;
+                status = "disabled";
+
+                pcie0_intc: interrupt-controller {
+                        interrupt-controller;
+                        #interrupt-cells = <1>;
+                        interrupt-parent = <&gic500>;
+                        interrupts = <GIC_SPI 312 IRQ_TYPE_EDGE_RISING>;
+                };
         };
     };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml b/Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml
--- a/Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -20,6 +20,7 @@
   compatible:
     enum:
       - cdns,torrent-phy
+      - ti,j7200-serdes-10g
       - ti,j721e-serdes-10g
 
   '#address-cells':
diff -Naur --no-dereference a/Documentation/devicetree/bindings/phy/ti,phy-gmii-sel.yaml b/Documentation/devicetree/bindings/phy/ti,phy-gmii-sel.yaml
--- a/Documentation/devicetree/bindings/phy/ti,phy-gmii-sel.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/phy/ti,phy-gmii-sel.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -54,6 +54,8 @@
       - ti,dm814-phy-gmii-sel
       - ti,am654-phy-gmii-sel
       - ti,j7200-cpsw5g-phy-gmii-sel
+      - ti,j721e-cpsw9g-phy-gmii-sel
+      - ti,j784s4-cpsw9g-phy-gmii-sel
 
   reg:
     maxItems: 1
@@ -63,14 +65,17 @@
   ti,qsgmii-main-ports:
     $ref: /schemas/types.yaml#/definitions/uint32-array
     description: |
-      Required only for QSGMII mode. Array to select the port for
-      QSGMII main mode. Rest of the ports are selected as QSGMII_SUB
-      ports automatically. Any one of the 4 CPSW5G ports can act as the
-      main port with the rest of them being the QSGMII_SUB ports.
-    maxItems: 1
+      Required only for QSGMII mode. Array to select the port/s for QSGMII
+      main mode. The size of the array corresponds to the number of QSGMII
+      interfaces and thus, the number of distinct QSGMII main ports,
+      supported by the device. If the device supports two QSGMII interfaces
+      but only one QSGMII interface is desired, repeat the QSGMII main port
+      value corresponding to the QSGMII interface in the array.
+    minItems: 1
+    maxItems: 2
     items:
       minimum: 1
-      maximum: 4
+      maximum: 8
 
 allOf:
   - if:
@@ -81,6 +86,9 @@
               - ti,dra7xx-phy-gmii-sel
               - ti,dm814-phy-gmii-sel
               - ti,am654-phy-gmii-sel
+              - ti,j7200-cpsw5g-phy-gmii-sel
+              - ti,j721e-cpsw9g-phy-gmii-sel
+              - ti,j784s4-cpsw9g-phy-gmii-sel
     then:
       properties:
         '#phy-cells':
@@ -88,12 +96,44 @@
           description: CPSW port number (starting from 1)
 
   - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - ti,j7200-cpsw5g-phy-gmii-sel
+    then:
+      properties:
+        ti,qsgmii-main-ports:
+          maxItems: 1
+          items:
+            minimum: 1
+            maximum: 4
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - ti,j721e-cpsw9g-phy-gmii-sel
+              - ti,j784s4-cpsw9g-phy-gmii-sel
+    then:
+      properties:
+        ti,qsgmii-main-ports:
+          minItems: 2
+          maxItems: 2
+          items:
+            minimum: 1
+            maximum: 8
+
+  - if:
       not:
         properties:
           compatible:
             contains:
               enum:
                 - ti,j7200-cpsw5g-phy-gmii-sel
+                - ti,j721e-cpsw9g-phy-gmii-sel
+                - ti,j784s4-cpsw9g-phy-gmii-sel
     then:
       properties:
         ti,qsgmii-main-ports: false
diff -Naur --no-dereference a/Documentation/devicetree/bindings/phy/ti,phy-j721e-wiz.yaml b/Documentation/devicetree/bindings/phy/ti,phy-j721e-wiz.yaml
--- a/Documentation/devicetree/bindings/phy/ti,phy-j721e-wiz.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/phy/ti,phy-j721e-wiz.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -15,8 +15,10 @@
     enum:
       - ti,j721e-wiz-16g
       - ti,j721e-wiz-10g
+      - ti,j721s2-wiz-10g
       - ti,am64-wiz-10g
       - ti,j7200-wiz-10g
+      - ti,j784s4-wiz-10g
 
   power-domains:
     maxItems: 1
diff -Naur --no-dereference a/Documentation/devicetree/bindings/pinctrl/ti,omap-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/ti,omap-pinctrl.txt
--- a/Documentation/devicetree/bindings/pinctrl/ti,omap-pinctrl.txt	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/pinctrl/ti,omap-pinctrl.txt	2024-01-28 14:01:31.232353751 -0500
@@ -9,5 +9,6 @@
   "ti,omap5-padconf" - OMAP5 compatible pinctrl
   "ti,dra7-padconf" - DRA7 compatible pinctrl
   "ti,am437-padconf" - AM437x compatible pinctrl
+  "ti,am6-padconf" - AM62x compatible pinctrl
 
 See Documentation/devicetree/bindings/pinctrl/pinctrl-single.txt for further details.
diff -Naur --no-dereference a/Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml
--- a/Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/remoteproc/ti,k3-dsp-rproc.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -31,10 +31,12 @@
 properties:
   compatible:
     enum:
+      - ti,am62a-c7xv-dsp
       - ti,j721e-c66-dsp
       - ti,j721e-c71-dsp
       - ti,j721s2-c71-dsp
     description:
+      Use "ti,am62a-c7xv-dsp" for AM62A Deep learning DSPs on K3 AM62A SoCs
       Use "ti,j721e-c66-dsp" for C66x DSPs on K3 J721E SoCs
       Use "ti,j721e-c71-dsp" for C71x DSPs on K3 J721E SoCs
       Use "ti,j721s2-c71-dsp" for C71x DSPs on K3 J721S2 SoCs
@@ -109,6 +111,7 @@
     properties:
       compatible:
         enum:
+          - ti,am62a-c7xv-dsp
           - ti,j721e-c71-dsp
           - ti,j721s2-c71-dsp
   then:
diff -Naur --no-dereference a/Documentation/devicetree/bindings/remoteproc/ti,k3-m4f-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/ti,k3-m4f-rproc.yaml
--- a/Documentation/devicetree/bindings/remoteproc/ti,k3-m4f-rproc.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/remoteproc/ti,k3-m4f-rproc.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,158 @@
+# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/remoteproc/ti,k3-m4f-rproc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI K3 M4F processor subsystems
+
+maintainers:
+  - Hari Nagalla <hnagalla@ti.com>
+
+description: |
+  Some K3 family SoCs have Arm Cortex M4F cores. AM64x is a SoC in K3
+  family with a M4F core. Typically safety oriented applications may use
+  the M4F core in isolation without an IPC. Where as some industrial and
+  home automation applications, may use the M4F core as a remote processor
+  with IPC communications.
+
+$ref: /schemas/arm/keystone/ti,k3-sci-common.yaml#
+
+properties:
+  $nodename:
+    pattern: "^m4fss(@.*)?"
+
+  compatible:
+    enum:
+      - ti,am64-m4fss
+
+  power-domains:
+    description: |
+      Should contain a phandle to a PM domain provider node and an args
+      specifier containing the M4FSS device id value.
+    maxItems: 1
+
+  "#address-cells":
+    const: 2
+
+  "#size-cells":
+    const: 2
+
+  reg:
+    items:
+      - description: Address and Size of the IRAM internal memory region
+      - description: Address and Size of the DRAM internal memory region
+
+  reg-names:
+    items:
+      - const: iram
+      - const: dram
+
+  resets:
+    description: |
+      Should contain the phandle to the reset controller node managing the
+      local resets for this device, and a reset specifier.
+    maxItems: 1
+
+  firmware-name:
+    description: |
+      Should contain the name of the default firmware image
+      file located on the firmware search path
+
+  mboxes:
+    description: |
+      OMAP Mailbox specifier denoting the sub-mailbox, to be used for
+      communication with the remote processor. This property should match
+      with the sub-mailbox node used in the firmware image.
+    maxItems: 1
+
+  memory-region:
+    description: |
+      phandle to the reserved memory nodes to be associated with the
+      remoteproc device. There should be at least two reserved memory nodes
+      defined. The reserved memory nodes should be carveout nodes, and
+      should be defined with a "no-map" property as per the bindings in
+      Documentation/devicetree/bindings/reserved-memory/reserved-memory.yaml
+    minItems: 2
+    maxItems: 8
+    items:
+      - description: region used for dynamic DMA allocations like vrings and
+                     vring buffers
+      - description: region reserved for firmware image sections
+    additionalItems: true
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - ti,sci
+  - ti,sci-dev-id
+  - ti,sci-proc-ids
+  - resets
+  - firmware-name
+  - mboxes
+  - memory-region
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    reserved-memory {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        mcu_m4fss_dma_memory_region: m4f-dma-memory@9cb00000 {
+            compatible = "shared-dma-pool";
+            reg = <0x00 0x9cb00000 0x00 0x100000>;
+            no-map;
+        };
+
+        mcu_m4fss_memory_region: m4f-memory@9cc00000 {
+            compatible = "shared-dma-pool";
+            reg = <0x00 0x9cc00000 0x00 0xe00000>;
+            no-map;
+        };
+    };
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        mailbox0_cluster0: mailbox-0 {
+            #mbox-cells = <1>;
+
+            mbox_m4_0: mbox-m4-0 {
+                ti,mbox-rx = <0 0 0>;
+                ti,mbox-tx = <1 0 0>;
+            };
+        };
+
+        bus@f0000 {
+            compatible = "simple-bus";
+            #address-cells = <2>;
+            #size-cells = <2>;
+            ranges = <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>;
+
+            bus@4000000 {
+                compatible = "simple-bus";
+                #address-cells = <2>;
+                #size-cells = <2>;
+                ranges = <0x00 0x04000000 0x00 0x04000000 0x00 0x01ff1400>;
+
+                mcu_m4fss: m4fss@5000000 {
+                    compatible = "ti,am64-m4fss";
+                    reg = <0x00 0x5000000 0x00 0x30000>,
+                          <0x00 0x5040000 0x00 0x10000>;
+                    reg-names = "iram", "dram";
+                    ti,sci = <&dmsc>;
+                    ti,sci-dev-id = <9>;
+                    ti,sci-proc-ids = <0x18 0xff>;
+                    resets = <&k3_reset 9 1>;
+                    firmware-name = "am62-mcu-m4f0_0-fw";
+                    mboxes = <&mailbox0_cluster0 &mbox_m4_0>;
+                    memory-region = <&mcu_m4fss_dma_memory_region>,
+                                    <&mcu_m4fss_memory_region>;
+                };
+            };
+        };
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/remoteproc/ti,k3-r5f-rproc.yaml b/Documentation/devicetree/bindings/remoteproc/ti,k3-r5f-rproc.yaml
--- a/Documentation/devicetree/bindings/remoteproc/ti,k3-r5f-rproc.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/remoteproc/ti,k3-r5f-rproc.yaml	2024-01-28 14:01:31.232353751 -0500
@@ -21,6 +21,9 @@
   called "Single-CPU" mode, where only Core0 is used, but with ability to use
   Core1's TCMs as well.
 
+  AM62 SoC family support a single R5F core only which runs Device Manager
+  firmware and can also be used as a remote processor with IPC communication.
+
   Each Dual-Core R5F sub-system is represented as a single DTS node
   representing the cluster, with a pair of child DT nodes representing
   the individual R5F cores. Each node has a number of required or optional
@@ -34,10 +37,11 @@
 
   compatible:
     enum:
+      - ti,am62-r5fss
+      - ti,am64-r5fss
       - ti,am654-r5fss
-      - ti,j721e-r5fss
       - ti,j7200-r5fss
-      - ti,am64-r5fss
+      - ti,j721e-r5fss
       - ti,j721s2-r5fss
 
   power-domains:
@@ -64,10 +68,17 @@
     $ref: /schemas/types.yaml#/definitions/uint32
     description: |
       Configuration Mode for the Dual R5F cores within the R5F cluster.
-      Should be either a value of 1 (LockStep mode) or 0 (Split mode) on
+      For most SoCs (AM65x, J721E, J7200, J721s2),
+      It should be either a value of 1 (LockStep mode) or 0 (Split mode) on
       most SoCs (AM65x, J721E, J7200, J721s2), default is LockStep mode if
-      omitted; and should be either a value of 0 (Split mode) or 2
-      (Single-CPU mode) on AM64x SoCs, default is Split mode if omitted.
+      omitted.
+      For AM64x SoCs,
+      It  should be either a value of 0 (Split mode) or 2 (Single-CPU mode) and
+      default is Split mode if omitted.
+      For AM62x SoCs,
+      It should be set as 3 (Single-Core mode) which is also the default if
+      omitted.
+
 
 # R5F Processor Child Nodes:
 # ==========================
@@ -80,7 +91,9 @@
       node representing a TI instantiation of the Arm Cortex R5F core. There
       are some specific integration differences for the IP like the usage of
       a Region Address Translator (RAT) for translating the larger SoC bus
-      addresses into a 32-bit address space for the processor.
+      addresses into a 32-bit address space for the processor. For AM62x,
+      the R5F Sub-System device node should only define one R5F child node
+      as it has only one core available.
 
       Each R5F core has an associated 64 KB of Tightly-Coupled Memory (TCM)
       internal memories split between two banks - TCMA and TCMB (further
@@ -100,10 +113,11 @@
     properties:
       compatible:
         enum:
+          - ti,am62-r5f
+          - ti,am64-r5f
           - ti,am654-r5f
-          - ti,j721e-r5f
           - ti,j7200-r5f
-          - ti,am64-r5f
+          - ti,j721e-r5f
           - ti,j721s2-r5f
 
       reg:
@@ -208,19 +222,39 @@
 
     unevaluatedProperties: false
 
-if:
-  properties:
-    compatible:
-      enum:
-        - ti,am64-r5fss
-then:
-  properties:
-    ti,cluster-mode:
-      enum: [0, 2]
-else:
-  properties:
-    ti,cluster-mode:
-      enum: [0, 1]
+allOf:
+  - if:
+      properties:
+        compatible:
+          enum:
+            - ti,am64-r5fss
+    then:
+      properties:
+        ti,cluster-mode:
+          enum: [0, 2]
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - ti,am654-r5fss
+            - ti,j7200-r5fss
+            - ti,j721e-r5fss
+            - ti,j721s2-r5fss
+    then:
+      properties:
+        ti,cluster-mode:
+          enum: [0, 1]
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - ti,am62-r5fss
+    then:
+      properties:
+        ti,cluster-mode:
+          enum: [3]
 
 required:
   - compatible
diff -Naur --no-dereference a/Documentation/devicetree/bindings/remoteproc/ti,pru-consumer.yaml b/Documentation/devicetree/bindings/remoteproc/ti,pru-consumer.yaml
--- a/Documentation/devicetree/bindings/remoteproc/ti,pru-consumer.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/remoteproc/ti,pru-consumer.yaml	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/remoteproc/ti,pru-consumer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Common TI PRU Consumer Binding
+
+maintainers:
+  - Suman Anna <s-anna@ti.com>
+
+description: |
+  A PRU application/consumer/user node typically uses one or more PRU device
+  nodes to implement a PRU application/functionality. Each application/client
+  node would need a reference to at least a PRU node, and optionally define
+  some properties needed for hardware/firmware configuration. The below
+  properties are a list of common properties supported by the PRU remoteproc
+  infrastructure.
+
+  The application nodes shall define their own bindings like regular platform
+  devices, so below are in addition to each node's bindings.
+
+properties:
+  ti,prus:
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    description: phandles to the PRU, RTU or Tx_PRU nodes used
+    minItems: 1
+    maxItems: 6
+    items:
+      maxItems: 1
+
+  firmware-name:
+    $ref: /schemas/types.yaml#/definitions/string-array
+    minItems: 1
+    maxItems: 6
+    description: |
+      firmwares for the PRU cores, the default firmware for the core from
+      the PRU node will be used if not provided. The firmware names should
+      correspond to the PRU cores listed in the 'ti,prus' property
+
+  ti,pruss-gp-mux-sel:
+    $ref: /schemas/types.yaml#/definitions/uint32-array
+    minItems: 1
+    maxItems: 6
+    items:
+      enum: [0, 1, 2, 3, 4]
+    description: |
+      array of values for the GP_MUX_SEL under PRUSS_GPCFG register for a PRU.
+      This selects the internal muxing scheme for the PRU instance. Values
+      should correspond to the PRU cores listed in the 'ti,prus' property. The
+      GP_MUX_SEL setting is a per-slice setting (one setting for PRU0, RTU0,
+      and Tx_PRU0 on K3 SoCs). Use the same value for all cores within the
+      same slice in the associative array. If the array size is smaller than
+      the size of 'ti,prus' property, the default out-of-reset value (0) for the
+      PRU core is used.
+
+required:
+  - ti,prus
+
+additionalProperties: true
diff -Naur --no-dereference a/Documentation/devicetree/bindings/serial/ti,pruss-uart.yaml b/Documentation/devicetree/bindings/serial/ti,pruss-uart.yaml
--- a/Documentation/devicetree/bindings/serial/ti,pruss-uart.yaml	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/devicetree/bindings/serial/ti,pruss-uart.yaml	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/serial/ti,pruss-uart.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI PRUSS serial UART
+
+maintainers:
+  - Bin Liu <b-liu@ti.com>
+
+description: |
+  The PRU-ICSS module has a serial UART peripheral, which is based on
+  industry standard TL16C550, with 16-bytes TX/RX FIFOs.
+
+allOf:
+  - $ref: /schemas/serial.yaml#
+
+properties:
+  compatible:
+    items:
+      - const: ti,pruss-uart
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+  interrupts:
+    minItems: 3
+    maxItems: 3
+    description: |
+      PRU UART interrupt mappings, containing an entry of 3 cell-values.
+      The first is the PRU System Event id for PRU UART Interrupt Request.
+      The second is the PRU interrupt channel id.
+      The third is the PRU host interrupt id.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - interrupt-parent
+  - interrupts
+
+examples:
+  - |
+    pruss_uart: serial@28000 {
+        compatible = "ti,pruss-uart";
+        reg = <0x28000 0x38>;
+        clocks = <&dpll_per_m2_ck>;
+        interrupt-parent = <&pruss_intc>;
+        interrupts = <6 2 2>;
+    };
diff -Naur --no-dereference a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml
--- a/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/soc/ti/ti,pruss.yaml	2024-01-28 14:01:31.236353764 -0500
@@ -277,6 +277,23 @@
 
     additionalProperties: false
 
+  pa-stats@[a-f0-9]+$:
+    description: |
+      PA-STATS sub-module represented as a SysCon.
+
+    type: object
+
+    properties:
+      compatible:
+        items:
+          - const: ti,pruss-pa-st
+          - const: syscon
+
+      reg:
+        maxItems: 1
+
+    additionalProperties: false
+
   interrupt-controller@[a-f0-9]+$:
     description: |
       PRUSS INTC Node. Each PRUSS has a single interrupt controller instance
diff -Naur --no-dereference a/Documentation/devicetree/bindings/thermal/ti,j72xx-thermal.yaml b/Documentation/devicetree/bindings/thermal/ti,j72xx-thermal.yaml
--- a/Documentation/devicetree/bindings/thermal/ti,j72xx-thermal.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/thermal/ti,j72xx-thermal.yaml	2024-01-28 14:01:31.236353764 -0500
@@ -9,6 +9,19 @@
 maintainers:
   - Keerthy <j-keerthy@ti.com>
 
+description: |
+  The TI K3 family of SoCs typically have a Voltage & Thermal
+  Management (VTM) device to control up to 8 temperature diode
+  sensors to measure silicon junction temperatures from different
+  hotspots of the chip as well as provide temperature, interrupt
+  and alerting information.
+
+  The following polynomial equation can then be used to convert
+  value returned by this device into a temperature in Celsius
+
+  Temp(C) = (-9.2627e-12) * x^4 + (6.0373e-08) * x^3 + \
+            (-1.7058e-04) * x^2 + (3.2512e-01) * x   + (-4.9003e+01)
+
 properties:
   compatible:
     enum:
@@ -19,7 +32,12 @@
     items:
       - description: VTM cfg1 register space
       - description: VTM cfg2 register space
-      - description: VTM efuse register space
+      - description: |
+          A software trimming method must be applied to some Jacinto
+          devices to function properly. This eFuse region provides
+          the information needed for these SoCs to report
+          temperatures accurately.
+    minItems: 2
 
   power-domains:
     maxItems: 1
@@ -27,6 +45,21 @@
   "#thermal-sensor-cells":
     const: 1
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: ti,j721e-vtm
+    then:
+      properties:
+        reg:
+          minItems: 3
+    else:
+      properties:
+        reg:
+          maxItems: 2
+
 required:
   - compatible
   - reg
diff -Naur --no-dereference a/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml b/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml
--- a/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/usb/ti,tps6598x.yaml	2024-01-28 14:01:31.236353764 -0500
@@ -23,6 +23,8 @@
   reg:
     maxItems: 1
 
+  wakeup-source: true
+
   interrupts:
     maxItems: 1
 
@@ -33,8 +35,6 @@
 required:
   - compatible
   - reg
-  - interrupts
-  - interrupt-names
 
 additionalProperties: true
 
@@ -48,6 +48,7 @@
         tps6598x: tps6598x@38 {
             compatible = "ti,tps6598x";
             reg = <0x38>;
+            wakeup-source;
 
             interrupt-parent = <&msmgpio>;
             interrupts = <107 IRQ_TYPE_LEVEL_LOW>;
diff -Naur --no-dereference a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml	2024-01-28 14:01:31.236353764 -0500
@@ -745,6 +745,8 @@
     description: LSI Corp. (LSI Logic)
   "^lwn,.*":
     description: Liebherr-Werk Nenzing GmbH
+  "^lincolntech,.*":
+    description: Lincoln Technology Solutions
   "^lxa,.*":
     description: Linux Automation GmbH
   "^m5stack,.*":
@@ -807,6 +809,8 @@
     description: Microsoft Corporation
   "^microsys,.*":
     description: MicroSys Electronics GmbH
+  "^microtips,.*":
+    description: Microtips Technology USA
   "^mikroe,.*":
     description: MikroElektronika d.o.o.
   "^mikrotik,.*":
diff -Naur --no-dereference a/Documentation/driver-api/media/v4l2-subdev.rst b/Documentation/driver-api/media/v4l2-subdev.rst
--- a/Documentation/driver-api/media/v4l2-subdev.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/driver-api/media/v4l2-subdev.rst	2024-01-28 14:01:31.236353764 -0500
@@ -593,6 +593,14 @@
 
 This shares the driver's private mutex between the controls and the states.
 
+Streams, multiplexed media pads and internal routing
+----------------------------------------------------
+
+A subdevice driver can implement support for multiplexed streams by setting
+the V4L2_SUBDEV_FL_STREAMS subdev flag and implementing support for
+centrally managed subdev active state, routing and stream based
+configuration.
+
 V4L2 sub-device functions and data structures
 ---------------------------------------------
 
diff -Naur --no-dereference a/Documentation/driver-api/phy/phy.rst b/Documentation/driver-api/phy/phy.rst
--- a/Documentation/driver-api/phy/phy.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/driver-api/phy/phy.rst	2024-01-28 14:01:31.236353764 -0500
@@ -102,27 +102,31 @@
 ::
 
 	struct phy *phy_get(struct device *dev, const char *string);
-	struct phy *phy_optional_get(struct device *dev, const char *string);
 	struct phy *devm_phy_get(struct device *dev, const char *string);
 	struct phy *devm_phy_optional_get(struct device *dev,
 					  const char *string);
+	struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
+				    const char *con_id);
+	struct phy *devm_of_phy_optional_get(struct device *dev,
+					     struct device_node *np,
+					     const char *con_id);
 	struct phy *devm_of_phy_get_by_index(struct device *dev,
 					     struct device_node *np,
 					     int index);
 
-phy_get, phy_optional_get, devm_phy_get and devm_phy_optional_get can
-be used to get the PHY. In the case of dt boot, the string arguments
+phy_get, devm_phy_get and devm_phy_optional_get can be used to get the PHY.
+In the case of dt boot, the string arguments
 should contain the phy name as given in the dt data and in the case of
 non-dt boot, it should contain the label of the PHY.  The two
 devm_phy_get associates the device with the PHY using devres on
 successful PHY get. On driver detach, release function is invoked on
-the devres data and devres data is freed. phy_optional_get and
-devm_phy_optional_get should be used when the phy is optional. These
-two functions will never return -ENODEV, but instead returns NULL when
-the phy cannot be found.Some generic drivers, such as ehci, may use multiple
-phys and for such drivers referencing phy(s) by name(s) does not make sense. In
-this case, devm_of_phy_get_by_index can be used to get a phy reference based on
-the index.
+the devres data and devres data is freed.
+The _optional_get variants should be used when the phy is optional. These
+functions will never return -ENODEV, but instead return NULL when
+the phy cannot be found.
+Some generic drivers, such as ehci, may use multiple phys. In this case,
+devm_of_phy_get or devm_of_phy_get_by_index can be used to get a phy
+reference based on name or index.
 
 It should be noted that NULL is a valid phy reference. All phy
 consumer calls on the NULL phy become NOPs. That is the release calls,
diff -Naur --no-dereference a/Documentation/i2c/i2c-address-translators.rst b/Documentation/i2c/i2c-address-translators.rst
--- a/Documentation/i2c/i2c-address-translators.rst	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/i2c/i2c-address-translators.rst	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,96 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======================
+I2C Address Translators
+=======================
+
+Author: Luca Ceresoli <luca@lucaceresoli.net>
+Author: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+
+Description
+-----------
+
+An I2C Address Translator (ATR) is a device with an I2C slave parent
+("upstream") port and N I2C master child ("downstream") ports, and
+forwards transactions from upstream to the appropriate downstream port
+with a modified slave address. The address used on the parent bus is
+called the "alias" and is (potentially) different from the physical
+slave address of the child bus. Address translation is done by the
+hardware.
+
+An ATR looks similar to an i2c-mux except:
+ - the address on the parent and child busses can be different
+ - there is normally no need to select the child port; the alias used on the
+   parent bus implies it
+
+The ATR functionality can be provided by a chip with many other features.
+The kernel i2c-atr provides a helper to implement an ATR within a driver.
+
+The ATR creates a new I2C "child" adapter on each child bus. Adding
+devices on the child bus ends up in invoking the driver code to select
+an available alias. Maintaining an appropriate pool of available aliases
+and picking one for each new device is up to the driver implementer. The
+ATR maintains a table of currently assigned alias and uses it to modify
+all I2C transactions directed to devices on the child buses.
+
+A typical example follows.
+
+Topology::
+
+                      Slave X @ 0x10
+              .-----.   |
+  .-----.     |     |---+---- B
+  | CPU |--A--| ATR |
+  `-----'     |     |---+---- C
+              `-----'   |
+                      Slave Y @ 0x10
+
+Alias table:
+
+A, B and C are three physical I2C busses, electrically independent from
+each other. The ATR receives the transactions initiated on bus A and
+propagates them on bus B or bus C or none depending on the device address
+in the transaction and based on the alias table.
+
+Alias table:
+
+.. table::
+
+   ===============   =====
+   Client            Alias
+   ===============   =====
+   X (bus B, 0x10)   0x20
+   Y (bus C, 0x10)   0x30
+   ===============   =====
+
+Transaction:
+
+ - Slave X driver requests a transaction (on adapter B), slave address 0x10
+ - ATR driver finds slave X is on bus B and has alias 0x20, rewrites
+   messages with address 0x20, forwards to adapter A
+ - Physical I2C transaction on bus A, slave address 0x20
+ - ATR chip detects transaction on address 0x20, finds it in table,
+   propagates transaction on bus B with address translated to 0x10,
+   keeps clock streched on bus A waiting for reply
+ - Slave X chip (on bus B) detects transaction at its own physical
+   address 0x10 and replies normally
+ - ATR chip stops clock stretching and forwards reply on bus A,
+   with address translated back to 0x20
+ - ATR driver receives the reply, rewrites messages with address 0x10
+   as they were initially
+ - Slave X driver gets back the msgs[], with reply and address 0x10
+
+Usage:
+
+ 1. In the driver (typically in the probe function) add an ATR by
+    calling i2c_atr_new() passing attach/detach callbacks
+ 2. When the attach callback is called pick an appropriate alias,
+    configure it in the chip and return the chosen alias in the
+    alias_id parameter
+ 3. When the detach callback is called, deconfigure the alias from
+    the chip and put the alias back in the pool for later usage
+
+I2C ATR functions and data structures
+-------------------------------------
+
+.. kernel-doc:: include/linux/i2c-atr.h
diff -Naur --no-dereference a/Documentation/i2c/index.rst b/Documentation/i2c/index.rst
--- a/Documentation/i2c/index.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/i2c/index.rst	2024-01-28 14:01:31.236353764 -0500
@@ -18,6 +18,7 @@
    i2c-topology
    muxes/i2c-mux-gpio
    i2c-sysfs
+   i2c-address-translators
 
 Writing device drivers
 ======================
diff -Naur --no-dereference a/Documentation/misc-devices/index.rst b/Documentation/misc-devices/index.rst
--- a/Documentation/misc-devices/index.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/misc-devices/index.rst	2024-01-28 14:01:31.236353764 -0500
@@ -28,5 +28,6 @@
    oxsemi-tornado
    pci-endpoint-test
    spear-pcie-gadget
+   tps6594-pfsm
    uacce
    xilinx_sdfec
diff -Naur --no-dereference a/Documentation/misc-devices/tps6594-pfsm.rst b/Documentation/misc-devices/tps6594-pfsm.rst
--- a/Documentation/misc-devices/tps6594-pfsm.rst	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/misc-devices/tps6594-pfsm.rst	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,87 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================================
+Texas Instruments TPS6594 PFSM driver
+=====================================
+
+Author: Julien Panis (jpanis@baylibre.com)
+
+Overview
+========
+
+Strictly speaking, PFSM (Pre-configurable Finite State Machine) is not
+hardware. It is a piece of code.
+
+The TPS6594 PMIC (Power Management IC) integrates a state machine which
+manages operational modes. Depending on the current operational mode,
+some voltage domains remain energized while others can be off.
+
+The PFSM driver can be used to trigger transitions between configured
+states. It also provides R/W access to the device registers.
+
+Supported chips
+---------------
+
+- tps6594-q1
+- tps6593-q1
+- lp8764-q1
+
+Driver location
+===============
+
+drivers/misc/tps6594-pfsm.c
+
+Driver type definitions
+=======================
+
+include/uapi/linux/tps6594_pfsm.h
+
+Driver IOCTLs
+=============
+
+:c:macro::`PMIC_GOTO_STANDBY`
+All device resources are powered down. The processor is off, and
+no voltage domains are energized.
+
+:c:macro::`PMIC_GOTO_LP_STANDBY`
+The digital and analog functions of the PMIC, which are not
+required to be always-on, are turned off (low-power).
+
+:c:macro::`PMIC_UPDATE_PGM`
+Triggers a firmware update.
+
+:c:macro::`PMIC_SET_ACTIVE_STATE`
+One of the operational modes.
+The PMICs are fully functional and supply power to all PDN loads.
+All voltage domains are energized in both MCU and Main processor
+sections.
+
+:c:macro::`PMIC_SET_MCU_ONLY_STATE`
+One of the operational modes.
+Only the power resources assigned to the MCU Safety Island are on.
+
+:c:macro::`PMIC_SET_RETENTION_STATE`
+One of the operational modes.
+Depending on the triggers set, some DDR/GPIO voltage domains can
+remain energized, while all other domains are off to minimize
+total system power.
+
+Driver usage
+============
+
+See available PFSMs::
+
+    # ls /dev/pfsm*
+
+Dump the registers of pages 0 and 1::
+
+    # hexdump -C /dev/pfsm-0-0x48
+
+See PFSM events::
+
+    # cat /proc/interrupts
+
+Userspace code example
+----------------------
+
+samples/pfsm/pfsm-wakeup.c
diff -Naur --no-dereference a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
--- a/Documentation/userspace-api/ioctl/ioctl-number.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst	2024-01-28 14:01:31.236353764 -0500
@@ -179,6 +179,7 @@
 'P'   00-0F  drivers/usb/class/usblp.c                               conflict!
 'P'   01-09  drivers/misc/pci_endpoint_test.c                        conflict!
 'P'   00-0F  xen/privcmd.h                                           conflict!
+'P'   00-05  linux/tps6594_pfsm.h                                    conflict!
 'Q'   all    linux/soundcard.h
 'R'   00-1F  linux/random.h                                          conflict!
 'R'   01     linux/rfkill.h                                          conflict!
diff -Naur --no-dereference a/Documentation/userspace-api/media/v4l/dev-subdev.rst b/Documentation/userspace-api/media/v4l/dev-subdev.rst
--- a/Documentation/userspace-api/media/v4l/dev-subdev.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/userspace-api/media/v4l/dev-subdev.rst	2024-01-28 14:01:31.236353764 -0500
@@ -29,6 +29,8 @@
 
 -  negotiate image formats on individual pads
 
+-  inspect and modify internal data routing between pads of the same entity
+
 Sub-device character device nodes, conventionally named
 ``/dev/v4l-subdev*``, use major number 81.
 
@@ -404,6 +406,8 @@
 size may also be smaller than the BOUNDS rectangle.
 
 
+.. _format-propagation:
+
 Order of configuration and format propagation
 ---------------------------------------------
 
@@ -501,3 +505,165 @@
     :maxdepth: 1
 
     subdev-formats
+
+Streams, multiplexed media pads and internal routing
+----------------------------------------------------
+
+Simple V4L2 sub-devices do not support multiple, unrelated video streams,
+and only a single stream can pass through a media link and a media pad.
+Thus each pad contains a format and selection configuration for that
+single stream. A subdev can do stream processing and split a stream into
+two or compose two streams into one, but the inputs and outputs for the
+subdev are still a single stream per pad.
+
+Some hardware, e.g. MIPI CSI-2, support multiplexed streams, that is, multiple
+data streams are transmitted on the same bus, which is represented by a media
+link connecting a transmitter source pad with a sink pad on the receiver. For
+example, a camera sensor can produce two distinct streams, a pixel stream and a
+metadata stream, which are transmitted on the multiplexed data bus, represented
+by a media link which connects the single sensor's source pad with the receiver
+sink pad. The stream-aware receiver will de-multiplex the streams received on
+the its sink pad and allows to route them individually to one of its source
+pads.
+
+Subdevice drivers that support multiplexed streams are compatible with
+non-multiplexed subdev drivers, but, of course, require a routing configuration
+where the link between those two types of drivers contains only a single
+stream.
+
+Understanding streams
+^^^^^^^^^^^^^^^^^^^^^
+
+A stream is a stream of content (e.g. pixel data or metadata) flowing through
+the media pipeline from a source (e.g. a sensor) towards the final sink (e.g. a
+receiver and demultiplexer in a SoC). Each media link carries all the enabled
+streams from one end of the link to the other, and sub-devices have routing
+tables which describe how the incoming streams from sink pads are routed to the
+source pads.
+
+A stream ID is a media pad-local identifier for a stream. Streams IDs of
+the same stream must be equal on both ends of a link. In other words,
+a particular stream ID must exist on both sides of a media
+link, but another stream ID can be used for the same stream at the other side
+of the sub-device.
+
+A stream at a specific point in the media pipeline is identified by the
+sub-device and a (pad, stream) pair. For sub-devices that do not support
+multiplexed streams the 'stream' field is always 0.
+
+Interaction between routes, streams, formats and selections
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The addition of streams to the V4L2 sub-device interface moves the sub-device
+formats and selections from pads to (pad, stream) pairs. Besides the
+usual pad, also the stream ID needs to be provided for setting formats and
+selections. The order of configuring formats and selections along a stream is
+the same as without streams (see :ref:`format-propagation`).
+
+Instead of the sub-device wide merging of streams from all sink pads
+towards all source pads, data flows for each route are separate from each
+other. Any number of routes from streams on sink pads towards streams on
+source pads is allowed, to the extent supported by drivers. For every
+stream on a source pad, however, only a single route is allowed.
+
+Any configurations of a stream within a pad, such as format or selections,
+are independent of similar configurations on other streams. This is
+subject to change in the future.
+
+Configuring streams
+^^^^^^^^^^^^^^^^^^^
+
+The configuration of the streams is done individually for each sub-device and
+the validity of the streams between sub-devices is validated when the pipeline
+is started.
+
+There are three steps in configuring the streams:
+
+1) Set up links. Connect the pads between sub-devices using the :ref:`Media
+Controller API <media_controller>`
+
+2) Streams. Streams are declared and their routing is configured by
+setting the routing table for the sub-device using
+:ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl. Note that
+setting the routing table will reset formats and selections in the
+sub-device to default values.
+
+3) Configure formats and selections. Formats and selections of each stream
+are configured separately as documented for plain sub-devices in
+:ref:`format-propagation`. The stream ID is set to the same stream ID
+associated with either sink or source pads of routes configured using the
+:ref:`VIDIOC_SUBDEV_S_ROUTING <VIDIOC_SUBDEV_G_ROUTING>` ioctl.
+
+Multiplexed streams setup example
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A simple example of a multiplexed stream setup might be as follows:
+
+- Two identical sensors (Sensor A and Sensor B). Each sensor has a single source
+  pad (pad 0) which carries a pixel data stream.
+
+- Multiplexer bridge (Bridge). The bridge has two sink pads, connected to the
+  sensors (pads 0, 1), and one source pad (pad 2), which outputs two streams.
+
+- Receiver in the SoC (Receiver). The receiver has a single sink pad (pad 0),
+  connected to the bridge, and two source pads (pads 1-2), going to the DMA
+  engine. The receiver demultiplexes the incoming streams to the source pads.
+
+- DMA Engines in the SoC (DMA Engine), one for each stream. Each DMA engine is
+  connected to a single source pad in the receiver.
+
+The sensors, the bridge and the receiver are modeled as V4L2 sub-devices,
+exposed to userspace via /dev/v4l-subdevX device nodes. The DMA engines are
+modeled as V4L2 devices, exposed to userspace via /dev/videoX nodes.
+
+To configure this pipeline, the userspace must take the following steps:
+
+1) Set up media links between entities: connect the sensors to the bridge,
+bridge to the receiver, and the receiver to the DMA engines. This step does
+not differ from normal non-multiplexed media controller setup.
+
+2) Configure routing
+
+.. flat-table:: Bridge routing table
+    :header-rows:  1
+
+    * - Sink Pad/Stream
+      - Source Pad/Stream
+      - Routing Flags
+      - Comments
+    * - 0/0
+      - 2/0
+      - V4L2_SUBDEV_ROUTE_FL_ACTIVE
+      - Pixel data stream from Sensor A
+    * - 1/0
+      - 2/1
+      - V4L2_SUBDEV_ROUTE_FL_ACTIVE
+      - Pixel data stream from Sensor B
+
+.. flat-table:: Receiver routing table
+    :header-rows:  1
+
+    * - Sink Pad/Stream
+      - Source Pad/Stream
+      - Routing Flags
+      - Comments
+    * - 0/0
+      - 1/0
+      - V4L2_SUBDEV_ROUTE_FL_ACTIVE
+      - Pixel data stream from Sensor A
+    * - 0/1
+      - 2/0
+      - V4L2_SUBDEV_ROUTE_FL_ACTIVE
+      - Pixel data stream from Sensor B
+
+3) Configure formats and selections
+
+After configuring routing, the next step is configuring the formats and
+selections for the streams. This is similar to performing this step without
+streams, with just one exception: the ``stream`` field needs to be assigned
+to the value of the stream ID.
+
+A common way to accomplish this is to start from the sensors and propagate the
+configurations along the stream towards the receiver,
+using :ref:`VIDIOC_SUBDEV_S_FMT <VIDIOC_SUBDEV_G_FMT>` ioctls to configure each
+stream endpoint in each sub-device.
diff -Naur --no-dereference a/Documentation/userspace-api/media/v4l/user-func.rst b/Documentation/userspace-api/media/v4l/user-func.rst
--- a/Documentation/userspace-api/media/v4l/user-func.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/userspace-api/media/v4l/user-func.rst	2024-01-28 14:01:31.236353764 -0500
@@ -70,6 +70,7 @@
     vidioc-subdev-g-crop
     vidioc-subdev-g-fmt
     vidioc-subdev-g-frame-interval
+    vidioc-subdev-g-routing
     vidioc-subdev-g-selection
     vidioc-subdev-querycap
     vidioc-subscribe-event
diff -Naur --no-dereference a/Documentation/userspace-api/media/v4l/vidioc-subdev-enum-frame-interval.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-enum-frame-interval.rst
--- a/Documentation/userspace-api/media/v4l/vidioc-subdev-enum-frame-interval.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-enum-frame-interval.rst	2024-01-28 14:01:31.236353764 -0500
@@ -92,7 +92,10 @@
       - Frame intervals to be enumerated, from enum
 	:ref:`v4l2_subdev_format_whence <v4l2-subdev-format-whence>`.
     * - __u32
-      - ``reserved``\ [8]
+      - ``stream``
+      - Stream identifier.
+    * - __u32
+      - ``reserved``\ [7]
       - Reserved for future extensions. Applications and drivers must set
 	the array to zero.
 
diff -Naur --no-dereference a/Documentation/userspace-api/media/v4l/vidioc-subdev-enum-frame-size.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-enum-frame-size.rst
--- a/Documentation/userspace-api/media/v4l/vidioc-subdev-enum-frame-size.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-enum-frame-size.rst	2024-01-28 14:01:31.236353764 -0500
@@ -97,7 +97,10 @@
       - Frame sizes to be enumerated, from enum
 	:ref:`v4l2_subdev_format_whence <v4l2-subdev-format-whence>`.
     * - __u32
-      - ``reserved``\ [8]
+      - ``stream``
+      - Stream identifier.
+    * - __u32
+      - ``reserved``\ [7]
       - Reserved for future extensions. Applications and drivers must set
 	the array to zero.
 
diff -Naur --no-dereference a/Documentation/userspace-api/media/v4l/vidioc-subdev-enum-mbus-code.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-enum-mbus-code.rst
--- a/Documentation/userspace-api/media/v4l/vidioc-subdev-enum-mbus-code.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-enum-mbus-code.rst	2024-01-28 14:01:31.236353764 -0500
@@ -73,7 +73,10 @@
       - ``flags``
       - See :ref:`v4l2-subdev-mbus-code-flags`
     * - __u32
-      - ``reserved``\ [7]
+      - ``stream``
+      - Stream identifier.
+    * - __u32
+      - ``reserved``\ [6]
       - Reserved for future extensions. Applications and drivers must set
 	the array to zero.
 
diff -Naur --no-dereference a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-crop.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-crop.rst
--- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-crop.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-crop.rst	2024-01-28 14:01:31.236353764 -0500
@@ -96,7 +96,10 @@
       - ``rect``
       - Crop rectangle boundaries, in pixels.
     * - __u32
-      - ``reserved``\ [8]
+      - ``stream``
+      - Stream identifier.
+    * - __u32
+      - ``reserved``\ [7]
       - Reserved for future extensions. Applications and drivers must set
 	the array to zero.
 
diff -Naur --no-dereference a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-fmt.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-fmt.rst
--- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-fmt.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-fmt.rst	2024-01-28 14:01:31.236353764 -0500
@@ -102,7 +102,10 @@
       - Definition of an image format, see :c:type:`v4l2_mbus_framefmt` for
 	details.
     * - __u32
-      - ``reserved``\ [8]
+      - ``stream``
+      - Stream identifier.
+    * - __u32
+      - ``reserved``\ [7]
       - Reserved for future extensions. Applications and drivers must set
 	the array to zero.
 
diff -Naur --no-dereference a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-frame-interval.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-frame-interval.rst
--- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-frame-interval.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-frame-interval.rst	2024-01-28 14:01:31.236353764 -0500
@@ -90,7 +90,10 @@
       - ``interval``
       - Period, in seconds, between consecutive video frames.
     * - __u32
-      - ``reserved``\ [9]
+      - ``stream``
+      - Stream identifier.
+    * - __u32
+      - ``reserved``\ [8]
       - Reserved for future extensions. Applications and drivers must set
 	the array to zero.
 
diff -Naur --no-dereference a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst
--- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst	1969-12-31 19:00:00.000000000 -0500
+++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-routing.rst	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,147 @@
+.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. c:namespace:: V4L
+
+.. _VIDIOC_SUBDEV_G_ROUTING:
+
+******************************************************
+ioctl VIDIOC_SUBDEV_G_ROUTING, VIDIOC_SUBDEV_S_ROUTING
+******************************************************
+
+Name
+====
+
+VIDIOC_SUBDEV_G_ROUTING - VIDIOC_SUBDEV_S_ROUTING - Get or set routing between streams of media pads in a media entity.
+
+
+Synopsis
+========
+
+.. c:macro:: VIDIOC_SUBDEV_G_ROUTING
+
+``int ioctl(int fd, VIDIOC_SUBDEV_G_ROUTING, struct v4l2_subdev_routing *argp)``
+
+.. c:macro:: VIDIOC_SUBDEV_S_ROUTING
+
+``int ioctl(int fd, VIDIOC_SUBDEV_S_ROUTING, struct v4l2_subdev_routing *argp)``
+
+Arguments
+=========
+
+``fd``
+    File descriptor returned by :ref:`open() <func-open>`.
+
+``argp``
+    Pointer to struct :c:type:`v4l2_subdev_routing`.
+
+
+Description
+===========
+
+These ioctls are used to get and set the routing in a media entity.
+The routing configuration determines the flows of data inside an entity.
+
+Drivers report their current routing tables using the
+``VIDIOC_SUBDEV_G_ROUTING`` ioctl and application may enable or disable routes
+with the ``VIDIOC_SUBDEV_S_ROUTING`` ioctl, by adding or removing routes and
+setting or clearing flags of the  ``flags`` field of a
+struct :c:type:`v4l2_subdev_route`.
+
+All stream configurations are reset when ``VIDIOC_SUBDEV_S_ROUTING`` is called. This
+means that the userspace must reconfigure all streams after calling the ioctl
+with e.g. ``VIDIOC_SUBDEV_S_FMT``.
+
+Only subdevices which have both sink and source pads can support routing.
+
+When inspecting routes through ``VIDIOC_SUBDEV_G_ROUTING`` and the application
+provided ``num_routes`` is not big enough to contain all the available routes
+the subdevice exposes, drivers return the ENOSPC error code and adjust the
+value of the ``num_routes`` field. Application should then reserve enough memory
+for all the route entries and call ``VIDIOC_SUBDEV_G_ROUTING`` again.
+
+.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}|
+
+.. c:type:: v4l2_subdev_routing
+
+.. flat-table:: struct v4l2_subdev_routing
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u32
+      - ``which``
+      - Format to modified, from enum
+        :ref:`v4l2_subdev_format_whence <v4l2-subdev-format-whence>`.
+    * - struct :c:type:`v4l2_subdev_route`
+      - ``routes[]``
+      - Array of struct :c:type:`v4l2_subdev_route` entries
+    * - __u32
+      - ``num_routes``
+      - Number of entries of the routes array
+    * - __u32
+      - ``reserved``\ [5]
+      - Reserved for future extensions. Applications and drivers must set
+	the array to zero.
+
+.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}|
+
+.. c:type:: v4l2_subdev_route
+
+.. flat-table:: struct v4l2_subdev_route
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       1 1 2
+
+    * - __u32
+      - ``sink_pad``
+      - Sink pad number.
+    * - __u32
+      - ``sink_stream``
+      - Sink pad stream number.
+    * - __u32
+      - ``source_pad``
+      - Source pad number.
+    * - __u32
+      - ``source_stream``
+      - Source pad stream number.
+    * - __u32
+      - ``flags``
+      - Route enable/disable flags
+	:ref:`v4l2_subdev_routing_flags <v4l2-subdev-routing-flags>`.
+    * - __u32
+      - ``reserved``\ [5]
+      - Reserved for future extensions. Applications and drivers must set
+	the array to zero.
+
+.. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}|
+
+.. _v4l2-subdev-routing-flags:
+
+.. flat-table:: enum v4l2_subdev_routing_flags
+    :header-rows:  0
+    :stub-columns: 0
+    :widths:       3 1 4
+
+    * - V4L2_SUBDEV_ROUTE_FL_ACTIVE
+      - 0
+      - The route is enabled. Set by applications.
+
+Return Value
+============
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes <gen-errors>` chapter.
+
+ENOSPC
+   The application provided ``num_routes`` is not big enough to contain
+   all the available routes the subdevice exposes.
+
+EINVAL
+   The sink or source pad identifiers reference a non-existing pad, or reference
+   pads of different types (ie. the sink_pad identifiers refers to a source pad)
+   or the sink or source stream identifiers reference a non-existing stream on
+   the sink or source pad.
+
+E2BIG
+   The application provided ``num_routes`` for ``VIDIOC_SUBDEV_S_ROUTING`` is
+   larger than the number of routes the driver can handle.
diff -Naur --no-dereference a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-selection.rst b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-selection.rst
--- a/Documentation/userspace-api/media/v4l/vidioc-subdev-g-selection.rst	2023-12-20 11:00:29.000000000 -0500
+++ b/Documentation/userspace-api/media/v4l/vidioc-subdev-g-selection.rst	2024-01-28 14:01:31.236353764 -0500
@@ -94,7 +94,10 @@
       - ``r``
       - Selection rectangle, in pixels.
     * - __u32
-      - ``reserved``\ [8]
+      - ``stream``
+      - Stream identifier.
+    * - __u32
+      - ``reserved``\ [7]
       - Reserved for future extensions. Applications and drivers must set
 	the array to zero.
 
diff -Naur --no-dereference a/drivers/bus/Kconfig b/drivers/bus/Kconfig
--- a/drivers/bus/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/bus/Kconfig	2024-01-28 14:01:31.240353775 -0500
@@ -210,7 +210,8 @@
 
 config TI_SYSC
 	bool "TI sysc interconnect target module driver"
-	depends on ARCH_OMAP2PLUS
+	depends on ARCH_OMAP2PLUS || ARCH_K3
+	default y
 	help
 	  Generic driver for Texas Instruments interconnect target module
 	  found on many TI SoCs.
diff -Naur --no-dereference a/drivers/clk/keystone/syscon-clk.c b/drivers/clk/keystone/syscon-clk.c
--- a/drivers/clk/keystone/syscon-clk.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/clk/keystone/syscon-clk.c	2024-01-28 14:01:31.240353775 -0500
@@ -4,10 +4,12 @@
  */
 
 #include <linux/clk-provider.h>
+#include <linux/kernel.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
+#include <linux/slab.h>
 
 struct ti_syscon_gate_clk_priv {
 	struct clk_hw hw;
@@ -61,21 +63,31 @@
 
 static struct clk_hw
 *ti_syscon_gate_clk_register(struct device *dev, struct regmap *regmap,
+			     const char *parent_name,
 			     const struct ti_syscon_gate_clk_data *data)
 {
 	struct ti_syscon_gate_clk_priv *priv;
 	struct clk_init_data init;
+	char *name = NULL;
 	int ret;
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return ERR_PTR(-ENOMEM);
 
-	init.name = data->name;
 	init.ops = &ti_syscon_gate_clk_ops;
-	init.parent_names = NULL;
-	init.num_parents = 0;
-	init.flags = 0;
+	if (parent_name) {
+		name = kasprintf(GFP_KERNEL, "%s:%s", data->name, parent_name);
+		init.name = name;
+		init.parent_names = &parent_name;
+		init.num_parents = 1;
+		init.flags = CLK_SET_RATE_PARENT;
+	} else {
+		init.name = data->name;
+		init.parent_names = NULL;
+		init.num_parents = 0;
+		init.flags = 0;
+	}
 
 	priv->regmap = regmap;
 	priv->reg = data->offset;
@@ -83,6 +95,10 @@
 	priv->hw.init = &init;
 
 	ret = devm_clk_hw_register(dev, &priv->hw);
+
+	if (name)
+		kfree(init.name);
+
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -94,25 +110,30 @@
 	const struct ti_syscon_gate_clk_data *data, *p;
 	struct clk_hw_onecell_data *hw_data;
 	struct device *dev = &pdev->dev;
+	int num_clks, num_parents, i;
+	const char *parent_name;
 	struct regmap *regmap;
-	int num_clks, i;
 
 	data = device_get_match_data(dev);
 	if (!data)
 		return -EINVAL;
 
-	regmap = syscon_node_to_regmap(dev->of_node);
-	if (IS_ERR(regmap)) {
-		if (PTR_ERR(regmap) == -EPROBE_DEFER)
-			return -EPROBE_DEFER;
-		dev_err(dev, "failed to find parent regmap\n");
-		return PTR_ERR(regmap);
-	}
+	regmap = device_node_to_regmap(dev->of_node);
+	if (IS_ERR(regmap))
+		return dev_err_probe(dev, PTR_ERR(regmap),
+				     "failed to get regmap\n");
 
 	num_clks = 0;
 	for (p = data; p->name; p++)
 		num_clks++;
 
+	num_parents = of_clk_get_parent_count(dev->of_node);
+	if (of_device_is_compatible(dev->of_node, "ti,am62-audio-refclk") &&
+	    num_parents == 0) {
+		return dev_err_probe(dev, -EINVAL,
+				     "must specify a parent clock\n");
+	}
+
 	hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, num_clks),
 			       GFP_KERNEL);
 	if (!hw_data)
@@ -120,16 +141,20 @@
 
 	hw_data->num = num_clks;
 
+	parent_name = of_clk_get_parent_name(dev->of_node, 0);
 	for (i = 0; i < num_clks; i++) {
 		hw_data->hws[i] = ti_syscon_gate_clk_register(dev, regmap,
+							      parent_name,
 							      &data[i]);
 		if (IS_ERR(hw_data->hws[i]))
 			dev_warn(dev, "failed to register %s\n",
 				 data[i].name);
 	}
 
-	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
-					   hw_data);
+	if (num_clks == 1)
+		return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+						   hw_data->hws[0]);
+	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data);
 }
 
 #define TI_SYSCON_CLK_GATE(_name, _offset, _bit_idx)	\
@@ -169,6 +194,11 @@
 	{ /* Sentinel */ },
 };
 
+static const struct ti_syscon_gate_clk_data am62_audio_clk_data[] = {
+	TI_SYSCON_CLK_GATE("audio_refclk", 0x0, 15),
+	{ /* Sentinel */ },
+};
+
 static const struct of_device_id ti_syscon_gate_clk_ids[] = {
 	{
 		.compatible = "ti,am654-ehrpwm-tbclk",
@@ -182,6 +212,10 @@
 		.compatible = "ti,am62-epwm-tbclk",
 		.data = &am62_clk_data,
 	},
+	{
+		.compatible = "ti,am62-audio-refclk",
+		.data = &am62_audio_clk_data,
+	},
 	{ }
 };
 MODULE_DEVICE_TABLE(of, ti_syscon_gate_clk_ids);
diff -Naur --no-dereference a/drivers/counter/Kconfig b/drivers/counter/Kconfig
--- a/drivers/counter/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/counter/Kconfig	2024-01-28 14:01:31.240353775 -0500
@@ -61,7 +61,7 @@
 
 config TI_EQEP
 	tristate "TI eQEP counter driver"
-	depends on (SOC_AM33XX || COMPILE_TEST)
+	depends on SOC_AM33XX || COMPILE_TEST || ARCH_K3
 	select REGMAP_MMIO
 	help
 	  Select this option to enable the Texas Instruments Enhanced Quadrature
diff -Naur --no-dereference a/drivers/counter/ti-eqep.c b/drivers/counter/ti-eqep.c
--- a/drivers/counter/ti-eqep.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/counter/ti-eqep.c	2024-01-28 14:01:31.240353775 -0500
@@ -6,7 +6,9 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/clk.h>
 #include <linux/counter.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/mod_devicetable.h>
 #include <linux/module.h>
@@ -67,6 +69,59 @@
 #define QEPCTL_UTE		BIT(1)
 #define QEPCTL_WDE		BIT(0)
 
+#define QEINT_UTO		BIT(11)
+#define QEINT_IEL		BIT(10)
+#define QEINT_SEL		BIT(9)
+#define QEINT_PCM		BIT(8)
+#define QEINT_PCR		BIT(7)
+#define QEINT_PCO		BIT(6)
+#define QEINT_PCU		BIT(5)
+#define QEINT_WTO		BIT(4)
+#define QEINT_QDC		BIT(3)
+#define QEINT_PHE		BIT(2)
+#define QEINT_PCE		BIT(1)
+
+#define QFLG_UTO		BIT(11)
+#define QFLG_IEL		BIT(10)
+#define QFLG_SEL		BIT(9)
+#define QFLG_PCM		BIT(8)
+#define QFLG_PCR		BIT(7)
+#define QFLG_PCO		BIT(6)
+#define QFLG_PCU		BIT(5)
+#define QFLG_WTO		BIT(4)
+#define QFLG_QDC		BIT(3)
+#define QFLG_PHE		BIT(2)
+#define QFLG_PCE		BIT(1)
+#define QFLG_INT		BIT(0)
+
+#define QCLR_UTO		BIT(11)
+#define QCLR_IEL		BIT(10)
+#define QCLR_SEL		BIT(9)
+#define QCLR_PCM		BIT(8)
+#define QCLR_PCR		BIT(7)
+#define QCLR_PCO		BIT(6)
+#define QCLR_PCU		BIT(5)
+#define QCLR_WTO		BIT(4)
+#define QCLR_QDC		BIT(3)
+#define QCLR_PHE		BIT(2)
+#define QCLR_PCE		BIT(1)
+#define QCLR_INT		BIT(0)
+
+#define QEPSTS_UPEVNT		BIT(7)
+#define QEPSTS_FDF		BIT(6)
+#define QEPSTS_QDF		BIT(5)
+#define QEPSTS_QDLF		BIT(4)
+#define QEPSTS_COEF		BIT(3)
+#define QEPSTS_CDEF		BIT(2)
+#define QEPSTS_FIMF		BIT(1)
+#define QEPSTS_PCEF		BIT(0)
+
+#define QCAPCTL_CEN		BIT(15)
+#define QCAPCTL_CCPS_SHIFT	4
+#define QCAPCTL_CCPS		GENMASK(6, 4)
+#define QCAPCTL_UPPS_SHIFT	0
+#define QCAPCTL_UPPS		GENMASK(3, 0)
+
 /* EQEP Inputs */
 enum {
 	TI_EQEP_SIGNAL_QEPA,	/* QEPA/XCLK */
@@ -83,6 +138,7 @@
 
 struct ti_eqep_cnt {
 	struct counter_device counter;
+	unsigned long clock_rate;
 	struct regmap *regmap32;
 	struct regmap *regmap16;
 };
@@ -238,12 +294,54 @@
 	}
 }
 
+static int ti_eqep_events_configure(struct counter_device *counter)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	struct counter_event_node *event_node;
+	u32 qeint = 0;
+
+	list_for_each_entry(event_node, &counter->events_list, l) {
+		switch (event_node->event) {
+		case COUNTER_EVENT_OVERFLOW:
+			qeint |= QEINT_PCO;
+			break;
+		case COUNTER_EVENT_UNDERFLOW:
+			qeint |= QEINT_PCU;
+			break;
+		case COUNTER_EVENT_DIRECTION_CHANGE:
+			qeint |= QEINT_QDC;
+			break;
+		case COUNTER_EVENT_TIMEOUT:
+			qeint |= QEINT_UTO;
+			break;
+		}
+	}
+
+	return regmap_write_bits(priv->regmap16, QEINT, qeint, ~0);
+}
+
+static int ti_eqep_watch_validate(struct counter_device *counter,
+				  const struct counter_watch *watch)
+{
+	switch (watch->event) {
+	case COUNTER_EVENT_OVERFLOW:
+	case COUNTER_EVENT_UNDERFLOW:
+	case COUNTER_EVENT_DIRECTION_CHANGE:
+	case COUNTER_EVENT_TIMEOUT:
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
 static const struct counter_ops ti_eqep_counter_ops = {
 	.count_read	= ti_eqep_count_read,
 	.count_write	= ti_eqep_count_write,
 	.function_read	= ti_eqep_function_read,
 	.function_write	= ti_eqep_function_write,
 	.action_read	= ti_eqep_action_read,
+	.events_configure = ti_eqep_events_configure,
+	.watch_validate	= ti_eqep_watch_validate,
 };
 
 static int ti_eqep_position_ceiling_read(struct counter_device *counter,
@@ -265,11 +363,17 @@
 					  u64 ceiling)
 {
 	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 qposmax = ceiling;
 
-	if (ceiling != (u32)ceiling)
+	/* ensure that value fits in 32-bit register */
+	if (qposmax != ceiling)
 		return -ERANGE;
 
-	regmap_write(priv->regmap32, QPOSMAX, ceiling);
+	/* protect against infinite overflow interrupts */
+	if (qposmax == 0)
+		return -EINVAL;
+
+	regmap_write(priv->regmap32, QPOSMAX, qposmax);
 
 	return 0;
 }
@@ -297,11 +401,43 @@
 	return 0;
 }
 
+static int ti_eqep_direction_read(struct counter_device *counter,
+				  struct counter_count *count,
+				  enum counter_count_direction *direction)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 qepsts;
+
+	regmap_read(priv->regmap16, QEPSTS, &qepsts);
+
+	*direction = (qepsts & QEPSTS_QDF) ? COUNTER_COUNT_DIRECTION_FORWARD
+					   : COUNTER_COUNT_DIRECTION_BACKWARD;
+
+	return 0;
+}
+
+static int ti_eqep_position_latched_count_read(struct counter_device *counter,
+					       struct counter_count *count,
+					       u64 *value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 qposlat;
+
+	regmap_read(priv->regmap32, QPOSLAT, &qposlat);
+
+	*value = qposlat;
+
+	return 0;
+}
+
 static struct counter_comp ti_eqep_position_ext[] = {
 	COUNTER_COMP_CEILING(ti_eqep_position_ceiling_read,
 			     ti_eqep_position_ceiling_write),
 	COUNTER_COMP_ENABLE(ti_eqep_position_enable_read,
 			    ti_eqep_position_enable_write),
+	COUNTER_COMP_DIRECTION(ti_eqep_direction_read),
+	COUNTER_COMP_COUNT_U64("latched_count",
+			       ti_eqep_position_latched_count_read, NULL),
 };
 
 static struct counter_signal ti_eqep_signals[] = {
@@ -354,6 +490,314 @@
 	},
 };
 
+static int ti_eqep_edge_capture_unit_enable_read(struct counter_device *counter,
+						 u8 *value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 qcapctl;
+
+	regmap_read(priv->regmap16, QCAPCTL, &qcapctl);
+	*value = !!(qcapctl & QCAPCTL_CEN);
+
+	return 0;
+}
+
+static int ti_eqep_edge_capture_unit_enable_write(struct counter_device *counter,
+						  u8 value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+
+	if (value)
+		regmap_set_bits(priv->regmap16, QCAPCTL, QCAPCTL_CEN);
+	else
+		regmap_clear_bits(priv->regmap16, QCAPCTL, QCAPCTL_CEN);
+
+	return 0;
+}
+
+static int ti_eqep_edge_capture_unit_latched_period_read(struct counter_device *counter,
+					      u64 *value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 qcprdlat, qcapctl;
+	u8 ccps;
+
+	regmap_read(priv->regmap16, QCPRDLAT, &qcprdlat);
+	regmap_read(priv->regmap16, QCAPCTL, &qcapctl);
+	ccps = (qcapctl & QCAPCTL_CCPS) >> QCAPCTL_CCPS_SHIFT;
+
+	/* convert timer ticks to nanoseconds */
+	*value = mul_u64_u32_div(qcprdlat << ccps, NSEC_PER_SEC, priv->clock_rate);
+
+	return 0;
+}
+
+static int ti_eqep_edge_capture_unit_max_period_read(struct counter_device *counter,
+					  u64 *value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 qcapctl;
+	u8 ccps;
+
+	regmap_read(priv->regmap16, QCAPCTL, &qcapctl);
+	ccps = (qcapctl & QCAPCTL_CCPS) >> QCAPCTL_CCPS_SHIFT;
+
+	/* convert timer ticks to nanoseconds */
+	*value = mul_u64_u32_div(USHRT_MAX << ccps, NSEC_PER_SEC,
+				 priv->clock_rate);
+
+	return 0;
+}
+
+static int ti_eqep_edge_capture_unit_max_period_write(struct counter_device *counter,
+					   u64 value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 period;
+	u8 ccps;
+
+	/* convert nanoseconds to timer ticks */
+	period = value = mul_u64_u32_div(value, priv->clock_rate, NSEC_PER_SEC);
+	if (period != value)
+		return -ERANGE;
+
+	/* find the smallest divider that will fit the requested period */
+	for (ccps = 0; ccps <= 7; ccps++)
+		if (USHRT_MAX << ccps >= period)
+			break;
+
+	if (ccps > 7)
+		return -EINVAL;
+
+	regmap_write_bits(priv->regmap16, QCAPCTL, QCAPCTL_CCPS,
+			  ccps << QCAPCTL_CCPS_SHIFT);
+
+	return 0;
+}
+
+static int ti_eqep_edge_capture_unit_prescaler_read(struct counter_device *counter,
+					 u32 *value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 qcapctl;
+
+	regmap_read(priv->regmap16, QCAPCTL, &qcapctl);
+	*value = (qcapctl & QCAPCTL_UPPS) >> QCAPCTL_UPPS_SHIFT;
+
+	return 0;
+}
+
+static int ti_eqep_edge_capture_unit_prescaler_write(struct counter_device *counter,
+					  u32 value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+
+	regmap_write_bits(priv->regmap16, QCAPCTL, QCAPCTL_UPPS,
+			  value << QCAPCTL_UPPS_SHIFT);
+
+	return 0;
+}
+
+static const char *const ti_eqep_edge_capture_unit_prescaler_values[] = {
+	"1",
+	"2",
+	"4",
+	"8",
+	"16",
+	"32",
+	"64",
+	"128",
+	"256",
+	"512",
+	"1024",
+	"2048",
+};
+
+static DEFINE_COUNTER_ENUM(ti_eqep_edge_capture_unit_prescaler_available,
+			   ti_eqep_edge_capture_unit_prescaler_values);
+
+static int ti_eqep_latch_mode_read(struct counter_device *counter,
+					    u32 *value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 qepctl;
+
+	regmap_read(priv->regmap16, QEPCTL, &qepctl);
+	*value = !!(qepctl & QEPCTL_QCLM);
+
+	return 0;
+}
+
+static int ti_eqep_latch_mode_write(struct counter_device *counter,
+					     u32 value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+
+	if (value)
+		regmap_set_bits(priv->regmap16, QEPCTL, QEPCTL_QCLM);
+	else
+		regmap_clear_bits(priv->regmap16, QEPCTL, QEPCTL_QCLM);
+
+	return 0;
+}
+
+static const char *const ti_eqep_latch_mode_names[] = {
+	"Read count",
+	"Unit timeout",
+};
+
+static DEFINE_COUNTER_ENUM(ti_eqep_latch_modes, ti_eqep_latch_mode_names);
+
+static int ti_eqep_unit_timer_time_read(struct counter_device *counter,
+				       u64 *value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 qutmr;
+
+	regmap_read(priv->regmap32, QUTMR, &qutmr);
+
+	/* convert timer ticks to nanoseconds */
+	*value = mul_u64_u32_div(qutmr, NSEC_PER_SEC, priv->clock_rate);
+
+	return 0;
+}
+
+static int ti_eqep_unit_timer_time_write(struct counter_device *counter,
+					u64 value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 qutmr;
+
+	/* convert nanoseconds to timer ticks */
+	qutmr = value = mul_u64_u32_div(value, priv->clock_rate, NSEC_PER_SEC);
+	if (qutmr != value)
+		return -ERANGE;
+
+	regmap_write(priv->regmap32, QUTMR, qutmr);
+
+	return 0;
+}
+
+static int ti_eqep_unit_timer_period_read(struct counter_device *counter,
+					  u64 *value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 quprd;
+
+	regmap_read(priv->regmap32, QUPRD, &quprd);
+
+	/* convert timer ticks to nanoseconds */
+	*value = mul_u64_u32_div(quprd, NSEC_PER_SEC, priv->clock_rate);
+
+	return 0;
+}
+
+static int ti_eqep_unit_timer_period_write(struct counter_device *counter,
+					   u64 value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 quprd;
+
+	/* convert nanoseconds to timer ticks */
+	quprd = value = mul_u64_u32_div(value, priv->clock_rate, NSEC_PER_SEC);
+	if (quprd != value)
+		return -ERANGE;
+
+	/* protect against infinite unit timeout interrupts */
+	if (quprd == 0)
+		return -EINVAL;
+
+	regmap_write(priv->regmap32, QUPRD, quprd);
+
+	return 0;
+}
+
+static int ti_eqep_unit_timer_enable_read(struct counter_device *counter,
+					  u8 *value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+	u32 qepctl;
+
+	regmap_read(priv->regmap16, QEPCTL, &qepctl);
+	*value = !!(qepctl & QEPCTL_UTE);
+
+	return 0;
+}
+
+static int ti_eqep_unit_timer_enable_write(struct counter_device *counter,
+					   u8 value)
+{
+	struct ti_eqep_cnt *priv = ti_eqep_count_from_counter(counter);
+
+	if (value)
+		regmap_set_bits(priv->regmap16, QEPCTL, QEPCTL_UTE);
+	else
+		regmap_clear_bits(priv->regmap16, QEPCTL, QEPCTL_UTE);
+
+	return 0;
+}
+
+static struct counter_comp ti_eqep_device_ext[] = {
+	COUNTER_COMP_DEVICE_BOOL("edge_capture_unit_enable",
+				 ti_eqep_edge_capture_unit_enable_read,
+				 ti_eqep_edge_capture_unit_enable_write),
+	COUNTER_COMP_DEVICE_U64("edge_capture_unit_latched_period",
+				ti_eqep_edge_capture_unit_latched_period_read,
+				NULL),
+	COUNTER_COMP_DEVICE_U64("edge_capture_unit_max_period",
+				ti_eqep_edge_capture_unit_max_period_read,
+				ti_eqep_edge_capture_unit_max_period_write),
+	COUNTER_COMP_DEVICE_ENUM("edge_capture_unit_prescaler",
+				 ti_eqep_edge_capture_unit_prescaler_read,
+				 ti_eqep_edge_capture_unit_prescaler_write,
+				 ti_eqep_edge_capture_unit_prescaler_available),
+	COUNTER_COMP_DEVICE_ENUM("latch_mode", ti_eqep_latch_mode_read,
+				ti_eqep_latch_mode_write, ti_eqep_latch_modes),
+	COUNTER_COMP_DEVICE_U64("unit_timer_time", ti_eqep_unit_timer_time_read,
+				ti_eqep_unit_timer_time_write),
+	COUNTER_COMP_DEVICE_U64("unit_timer_period",
+				ti_eqep_unit_timer_period_read,
+				ti_eqep_unit_timer_period_write),
+	COUNTER_COMP_DEVICE_BOOL("unit_timer_enable",
+				 ti_eqep_unit_timer_enable_read,
+				 ti_eqep_unit_timer_enable_write),
+};
+
+static irqreturn_t ti_eqep_irq_handler(int irq, void *dev_id)
+{
+	struct ti_eqep_cnt *priv = dev_id;
+	struct counter_device *counter = &priv->counter;
+	u32 qflg;
+	u32 qclr = 0;
+
+	regmap_read(priv->regmap16, QFLG, &qflg);
+
+	if (qflg & QFLG_PCO) {
+		qclr |= QFLG_PCO;
+		counter_push_event(counter, COUNTER_EVENT_OVERFLOW, 0);
+	}
+
+	if (qflg & QFLG_PCU) {
+		qclr |= QFLG_PCU;
+		counter_push_event(counter, COUNTER_EVENT_UNDERFLOW, 0);
+	}
+
+	if (qflg & QFLG_QDC) {
+		qclr |= QFLG_QDC;
+		counter_push_event(counter, COUNTER_EVENT_DIRECTION_CHANGE, 0);
+	}
+
+	if (qflg & QFLG_UTO) {
+		qclr |= QFLG_UTO;
+		counter_push_event(counter, COUNTER_EVENT_TIMEOUT, 0);
+	}
+
+	qclr |= QCLR_INT;
+	regmap_write_bits(priv->regmap16, QCLR, qclr, ~0);
+
+	return IRQ_HANDLED;
+}
+
 static const struct regmap_config ti_eqep_regmap32_config = {
 	.name = "32-bit",
 	.reg_bits = 32,
@@ -375,14 +819,29 @@
 	struct device *dev = &pdev->dev;
 	struct counter_device *counter;
 	struct ti_eqep_cnt *priv;
+	struct clk *clk;
 	void __iomem *base;
 	int err;
+	int irq;
 
 	counter = devm_counter_alloc(dev, sizeof(*priv));
 	if (!counter)
 		return -ENOMEM;
 	priv = counter_priv(counter);
 
+	clk = devm_clk_get(dev, "fck");
+	if (IS_ERR(clk)) {
+		if (PTR_ERR(clk) != -EPROBE_DEFER)
+			dev_err(dev, "failed to get fck clock");
+		return PTR_ERR(clk);
+	}
+
+	priv->clock_rate = clk_get_rate(clk);
+	if (priv->clock_rate == 0) {
+		dev_err(dev, "failed to get fck clock rate");
+		return -EINVAL;
+	}
+
 	base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
@@ -397,11 +856,22 @@
 	if (IS_ERR(priv->regmap16))
 		return PTR_ERR(priv->regmap16);
 
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	err = devm_request_threaded_irq(dev, irq, NULL, ti_eqep_irq_handler,
+					IRQF_ONESHOT, dev_name(dev), priv);
+	if (err < 0)
+		return err;
+
 	counter->name = dev_name(dev);
 	counter->parent = dev;
 	counter->ops = &ti_eqep_counter_ops;
 	counter->counts = ti_eqep_counts;
 	counter->num_counts = ARRAY_SIZE(ti_eqep_counts);
+	counter->ext = ti_eqep_device_ext;
+	counter->num_ext = ARRAY_SIZE(ti_eqep_device_ext);
 	counter->signals = ti_eqep_signals;
 	counter->num_signals = ARRAY_SIZE(ti_eqep_signals);
 
@@ -415,6 +885,14 @@
 	pm_runtime_enable(dev);
 	pm_runtime_get_sync(dev);
 
+	/*
+	 * We can end up with an interrupt infinite loop (interrupts triggered
+	 * as soon as they are cleared) if we leave these at the default value
+	 * of 0 and events are enabled.
+	 */
+	regmap_write(priv->regmap32, QPOSMAX, UINT_MAX);
+	regmap_write(priv->regmap32, QUPRD, UINT_MAX);
+
 	err = counter_add(counter);
 	if (err < 0) {
 		pm_runtime_put_sync(dev);
diff -Naur --no-dereference a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
--- a/drivers/cpufreq/cpufreq-dt-platdev.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c	2024-01-28 14:01:31.240353775 -0500
@@ -162,6 +162,9 @@
 	{ .compatible = "ti,am43", },
 	{ .compatible = "ti,dra7", },
 	{ .compatible = "ti,omap3", },
+	{ .compatible = "ti,am625", },
+	{ .compatible = "ti,am62a7", },
+	{ .compatible = "ti,am62p5", },
 
 	{ .compatible = "qcom,ipq8064", },
 	{ .compatible = "qcom,apq8064", },
diff -Naur --no-dereference a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
--- a/drivers/cpufreq/Kconfig.arm	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/cpufreq/Kconfig.arm	2024-01-28 14:01:31.240353775 -0500
@@ -340,8 +340,8 @@
 
 config ARM_TI_CPUFREQ
 	bool "Texas Instruments CPUFreq support"
-	depends on ARCH_OMAP2PLUS
-	default ARCH_OMAP2PLUS
+	depends on ARCH_OMAP2PLUS || ARCH_K3
+	default y
 	help
 	  This driver enables valid OPPs on the running platform based on
 	  values contained within the SoC in use. Enable this in order to
diff -Naur --no-dereference a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
--- a/drivers/cpufreq/ti-cpufreq.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/cpufreq/ti-cpufreq.c	2024-01-28 14:01:31.240353775 -0500
@@ -39,6 +39,16 @@
 #define OMAP34xx_ProdID_SKUID			0x4830A20C
 #define OMAP3_SYSCON_BASE	(0x48000000 + 0x2000 + 0x270)
 
+#define AM625_EFUSE_K_MPU_OPP			11
+#define AM625_EFUSE_S_MPU_OPP			19
+#define AM625_EFUSE_T_MPU_OPP			20
+#define AM625_EFUSE_U_MPU_OPP			21
+#define AM625_EFUSE_V_MPU_OPP			22
+
+#define AM625_SUPPORT_K_MPU_OPP			BIT(0)
+#define AM625_SUPPORT_S_MPU_OPP			BIT(1)
+#define AM625_SUPPORT_T_MPU_OPP			BIT(2)
+
 #define VERSION_COUNT				2
 
 struct ti_cpufreq_data;
@@ -104,6 +114,27 @@
 	return BIT(efuse);
 }
 
+static unsigned long am625_efuse_xlate(struct ti_cpufreq_data *opp_data,
+				       unsigned long efuse)
+{
+	unsigned long calculated_efuse = AM625_SUPPORT_K_MPU_OPP;
+
+	switch (efuse) {
+	case AM625_EFUSE_V_MPU_OPP:
+	case AM625_EFUSE_U_MPU_OPP:
+	case AM625_EFUSE_T_MPU_OPP:
+		calculated_efuse |= AM625_SUPPORT_T_MPU_OPP;
+		fallthrough;
+	case AM625_EFUSE_S_MPU_OPP:
+		calculated_efuse |= AM625_SUPPORT_S_MPU_OPP;
+		fallthrough;
+	case AM625_EFUSE_K_MPU_OPP:
+		calculated_efuse |= AM625_SUPPORT_K_MPU_OPP;
+	}
+
+	return calculated_efuse;
+}
+
 static struct ti_cpufreq_soc_data am3x_soc_data = {
 	.efuse_xlate = amx3_efuse_xlate,
 	.efuse_fallback = AM33XX_800M_ARM_MPU_MAX_FREQ,
@@ -198,6 +229,14 @@
 	.multi_regulator = false,
 };
 
+static struct ti_cpufreq_soc_data am625_soc_data = {
+	.efuse_xlate = am625_efuse_xlate,
+	.efuse_offset = 0x0018,
+	.efuse_mask = 0x07c0,
+	.efuse_shift = 0x6,
+	.rev_offset = 0x0014,
+	.multi_regulator = false,
+};
 
 /**
  * ti_cpufreq_get_efuse() - Parse and return efuse value present on SoC
@@ -301,6 +340,9 @@
 	{ .compatible = "ti,dra7", .data = &dra7_soc_data },
 	{ .compatible = "ti,omap34xx", .data = &omap34xx_soc_data, },
 	{ .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, },
+	{ .compatible = "ti,am625", .data = &am625_soc_data, },
+	{ .compatible = "ti,am62a7", .data = &am625_soc_data, },
+	{ .compatible = "ti,am62p5", .data = &am625_soc_data, },
 	/* legacy */
 	{ .compatible = "ti,omap3430", .data = &omap34xx_soc_data, },
 	{ .compatible = "ti,omap3630", .data = &omap36xx_soc_data, },
diff -Naur --no-dereference a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
--- a/drivers/crypto/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/crypto/Kconfig	2024-01-28 14:01:31.240353775 -0500
@@ -824,4 +824,6 @@
 source "drivers/crypto/keembay/Kconfig"
 source "drivers/crypto/aspeed/Kconfig"
 
+source "drivers/crypto/ti/Kconfig"
+
 endif # CRYPTO_HW
diff -Naur --no-dereference a/drivers/crypto/Makefile b/drivers/crypto/Makefile
--- a/drivers/crypto/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/crypto/Makefile	2024-01-28 14:01:31.240353775 -0500
@@ -43,6 +43,7 @@
 obj-$(CONFIG_CRYPTO_DEV_SL3516) += gemini/
 obj-$(CONFIG_ARCH_STM32) += stm32/
 obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o
+obj-$(CONFIG_ARCH_K3) += ti/
 obj-$(CONFIG_CRYPTO_DEV_UX500) += ux500/
 obj-$(CONFIG_CRYPTO_DEV_VIRTIO) += virtio/
 obj-$(CONFIG_CRYPTO_DEV_VMX) += vmx/
diff -Naur --no-dereference a/drivers/crypto/sa2ul.h b/drivers/crypto/sa2ul.h
--- a/drivers/crypto/sa2ul.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/crypto/sa2ul.h	2024-01-28 14:01:31.240353775 -0500
@@ -170,7 +170,7 @@
  * the following range, so avoid using it.
  */
 #define SA_UNSAFE_DATA_SZ_MIN	240
-#define SA_UNSAFE_DATA_SZ_MAX	256
+#define SA_UNSAFE_DATA_SZ_MAX	255
 
 struct sa_match_data;
 
diff -Naur --no-dereference a/drivers/crypto/ti/Kconfig b/drivers/crypto/ti/Kconfig
--- a/drivers/crypto/ti/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/crypto/ti/Kconfig	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config CRYPTO_DEV_TI_MCRC64
+	tristate "Support for TI MCRC64 crc accelerators"
+	depends on ARCH_K3
+	select CRYPTO_HASH
+	help
+	  This enables support for the MCRC hw accelerator
+	  which can be found on TI SOC.
+	  MCRC support 64-bit CRC calculation using
+	  Full-CPU mode.
\ No newline at end of file
diff -Naur --no-dereference a/drivers/crypto/ti/Makefile b/drivers/crypto/ti/Makefile
--- a/drivers/crypto/ti/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/crypto/ti/Makefile	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_CRYPTO_DEV_TI_MCRC64) += mcrc.o
diff -Naur --no-dereference a/drivers/crypto/ti/mcrc.c b/drivers/crypto/ti/mcrc.c
--- a/drivers/crypto/ti/mcrc.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/crypto/ti/mcrc.c	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,372 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) Texas Instruments 2023 - http://www.ti.com
+ * Author: Kamlesh Gurudasani <kamlesh@ti.com>
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include <crypto/internal/hash.h>
+
+#include <asm/unaligned.h>
+
+#define DRIVER_NAME		"ti-mcrc"
+#define CHKSUM_DIGEST_SIZE	8
+#define CHKSUM_BLOCK_SIZE	1
+
+/* Registers */
+#define CRC_CTRL0 0x0000 /* CRC Global Control Register 0 */
+#define CH_PSA_SWRE(ch) BIT(((ch) - 1) << 3) /* PSA Software Reset  */
+
+#define CRC_CTRL1 0x0008 /* CRC Global Control Register 1 */
+#define PWDN BIT(0) /* Power Down  */
+
+#define CRC_CTRL2 0x0010 /* CRC Global Control Register 2 */
+#define CH_MODE(ch, m) ((m) << (((ch) - 1) << 3))
+
+#define PSA_SIGREGL(ch) ((0x6 + (4 * ((ch) - 1))) << 4) /* Signature register */
+
+#define MCRC_ALG_MASK 0x8000000000000000
+#define MCRC_CRC64_POLY 0x000000000000001b
+
+#define MCRC_AUTOSUSPEND_DELAY	50
+
+static struct device *mcrc_k3_dev;
+
+static unsigned int burst_size;
+
+module_param(burst_size, uint, 0644);
+MODULE_PARM_DESC(burst_size, "Select burst byte size (0 unlimited)");
+
+enum mcrc_mode {
+	MCRC_MODE_DATA_CAPTURE = 0,
+	MCRC_MODE_AUTO,
+	MCRC_MODE_SEMI_CPU,
+	MCRC_MODE_FULL_CPU,
+	MCRC_MODE_INVALID,
+};
+
+enum mcrc_channel {
+	MCRC_CHANNEL_1 = 1,
+	MCRC_CHANNEL_2,
+	MCRC_CHANNEL_3,
+	MCRC_CHANNEL_4,
+	MCRC_CHANNEL_INVALID,
+};
+
+struct mcrc_data {
+	struct device	 *dev;
+	void __iomem	 *regs;
+};
+
+struct mcrc_ctx {
+	u32 key;
+};
+
+struct mcrc_desc_ctx {
+	u64    signature;
+};
+
+static int mcrc_set_mode(void __iomem *regs, u32 channel, u32 mode)
+{
+	u32 crc_ctrl2_reg, mode_set_val;
+
+	if (mode < 0 || mode >= MCRC_MODE_INVALID)
+		return -EINVAL;
+
+	if (channel <= 0 || channel >= MCRC_CHANNEL_INVALID)
+		return -EINVAL;
+
+	crc_ctrl2_reg = readl_relaxed(regs + CRC_CTRL2);
+
+	mode_set_val = crc_ctrl2_reg | CH_MODE(channel, mode);
+
+	/* Write CRC_CTRL2, set mode */
+	writel_relaxed(mode_set_val, regs + CRC_CTRL2);
+
+	return 0;
+}
+
+static int mcrc_reset_signature(void __iomem *regs, u32 channel)
+{
+	u32 crc_ctrl0_reg, reset_val, reset_undo_val;
+
+	if (channel <= 0 || channel >= MCRC_CHANNEL_INVALID)
+		return -EINVAL;
+
+	/* reset PSA */
+	crc_ctrl0_reg = readl_relaxed(regs + CRC_CTRL0);
+
+	reset_val = crc_ctrl0_reg | CH_PSA_SWRE(channel);
+	reset_undo_val = crc_ctrl0_reg & ~CH_PSA_SWRE(channel);
+
+	/* Write CRC_CTRL0 register, reset PSA register */
+	writel_relaxed(reset_val, regs + CRC_CTRL0);
+	writel_relaxed(reset_undo_val, regs + CRC_CTRL0);
+
+	return 0;
+}
+
+/* This helper implements crc64 calculation using CPU */
+static u64 mcrc_calculate_sw_crc(u64 crc, u8 byte)
+{
+	u64 bit = 0;
+	u8 j;
+
+	for (j = 0; j < 8; j++) {
+		bit = crc & MCRC_ALG_MASK;
+		crc <<= 1;
+		if (byte & (0x80 >> j))
+			bit ^= MCRC_ALG_MASK;
+		if (bit)
+			crc ^= MCRC_CRC64_POLY;
+	}
+
+	return crc;
+}
+
+static int mcrc_calculate_crc(void __iomem *regs, u32 channel,
+			      const u8 *d8, size_t length, u64 *crc64)
+{
+	void __iomem *psa_reg;
+	u64 signature = 0;
+
+	if (channel <= 0 || channel >= MCRC_CHANNEL_INVALID)
+		return -EINVAL;
+
+	psa_reg = regs + PSA_SIGREGL(channel);
+
+	for (; length >= sizeof(u64); d8 += sizeof(u64), length -= sizeof(u64)) {
+		writeq_relaxed(cpu_to_be64p((u64 *)d8), psa_reg);
+		signature = readq_relaxed(psa_reg);
+	}
+
+	while (length--)
+		signature = mcrc_calculate_sw_crc(signature, *d8++);
+
+	*crc64 = signature;
+
+	return 0;
+}
+
+static int mcrc_cra_init(struct crypto_tfm *tfm)
+{
+	struct mcrc_ctx *mctx = crypto_tfm_ctx(tfm);
+
+	struct mcrc_data *dev_data = dev_get_drvdata(mcrc_k3_dev);
+
+	pm_runtime_get_sync(dev_data->dev);
+
+	mctx->key = 0;
+
+	return 0;
+}
+
+static void mcrc_cra_exit(struct crypto_tfm *tfm)
+{
+	struct mcrc_data *dev_data = dev_get_drvdata(mcrc_k3_dev);
+
+	pm_runtime_mark_last_busy(dev_data->dev);
+	pm_runtime_put_autosuspend(dev_data->dev);
+}
+
+static int mcrc_setkey(struct crypto_shash *tfm, const u8 *key,
+		       unsigned int keylen)
+{
+	struct mcrc_ctx *mctx = crypto_shash_ctx(tfm);
+
+	if (keylen != sizeof(u32))
+		return -EINVAL;
+
+	mctx->key = get_unaligned_le32(key);
+
+	return 0;
+}
+
+static int mcrc_init(struct shash_desc *desc)
+{
+	struct mcrc_data *dev_data = dev_get_drvdata(mcrc_k3_dev);
+
+	/* set full cpu mode */
+	int ret = mcrc_set_mode(dev_data->regs, MCRC_CHANNEL_1,
+				MCRC_MODE_FULL_CPU);
+	if (ret)
+		return ret;
+
+	/* reset PSA */
+	return mcrc_reset_signature(dev_data->regs, MCRC_CHANNEL_1);
+}
+
+static int burst_update(struct shash_desc *desc, const u8 *d8,
+			size_t length)
+{
+	struct mcrc_desc_ctx *ctx = shash_desc_ctx(desc);
+	struct mcrc_data *dev_data = dev_get_drvdata(mcrc_k3_dev);
+
+	return mcrc_calculate_crc(dev_data->regs, MCRC_CHANNEL_1,
+				  d8, length, &ctx->signature);
+}
+
+static int mcrc_update(struct shash_desc *desc, const u8 *d8,
+		       unsigned int length)
+{
+	const unsigned int burst_sz = burst_size;
+	unsigned int rem_sz;
+	const u8 *cur;
+	size_t size;
+	int ret;
+
+	if (!burst_sz)
+		return burst_update(desc, d8, length);
+
+	/* Digest first bytes not 64bit aligned at first pass in the loop */
+	size = min_t(size_t, length, burst_sz + (size_t)d8 -
+		ALIGN_DOWN((size_t)d8, sizeof(u64)));
+	for (rem_sz = length, cur = d8; rem_sz;
+	     rem_sz -= size, cur += size, size = min(rem_sz, burst_sz)) {
+		ret = burst_update(desc, cur, size);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int mcrc_final(struct shash_desc *desc, u8 *out)
+{
+	struct mcrc_desc_ctx *ctx = shash_desc_ctx(desc);
+
+	/* Send computed CRC */
+	put_unaligned_le64(ctx->signature, out);
+	return 0;
+}
+
+static int mcrc_finup(struct shash_desc *desc, const u8 *data,
+		      unsigned int length, u8 *out)
+{
+	return mcrc_update(desc, data, length) ?:
+		mcrc_final(desc, out);
+}
+
+static int mcrc_digest(struct shash_desc *desc, const u8 *data,
+		       unsigned int length, u8 *out)
+{
+	return mcrc_init(desc) ?: mcrc_finup(desc, data, length, out);
+}
+
+static struct shash_alg algs[] = {
+	/* CRC-64 */
+	{
+		.setkey		= mcrc_setkey,
+		.init		= mcrc_init,
+		.update		= mcrc_update,
+		.final		= mcrc_final,
+		.finup		= mcrc_finup,
+		.digest		= mcrc_digest,
+		.descsize	= sizeof(struct mcrc_desc_ctx),
+		.digestsize	= CHKSUM_DIGEST_SIZE,
+		.base		= {
+			.cra_name		= "crc64",
+			.cra_driver_name	= "mcrc",
+			.cra_priority		= 200,
+			.cra_flags		= CRYPTO_ALG_OPTIONAL_KEY,
+			.cra_blocksize		= CHKSUM_BLOCK_SIZE,
+			.cra_alignmask		= 7,
+			.cra_ctxsize		= sizeof(struct mcrc_ctx),
+			.cra_module		= THIS_MODULE,
+			.cra_init		= mcrc_cra_init,
+			.cra_exit		= mcrc_cra_exit,
+		}
+	}
+};
+
+static int mcrc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mcrc_data *dev_data;
+
+	dev_data = devm_kzalloc(dev, sizeof(*dev_data), GFP_KERNEL);
+	if (!dev_data)
+		return -ENOMEM;
+
+	mcrc_k3_dev = dev;
+	dev_data->dev = dev;
+	dev_data->regs = devm_platform_ioremap_resource(pdev, 0);
+
+	platform_set_drvdata(pdev, dev_data);
+	dev_set_drvdata(mcrc_k3_dev, dev_data);
+
+	crypto_register_shashes(algs, ARRAY_SIZE(algs));
+
+	pm_runtime_set_autosuspend_delay(dev, MCRC_AUTOSUSPEND_DELAY);
+	pm_runtime_use_autosuspend(dev);
+
+	pm_runtime_get_noresume(dev);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
+
+	pm_runtime_put_sync(dev);
+
+	return 0;
+}
+
+static int mcrc_remove(struct platform_device *pdev)
+{
+	struct mcrc_data *dev_data = platform_get_drvdata(pdev);
+
+	int ret = pm_runtime_get_sync(dev_data->dev);
+
+	if (ret < 0) {
+		pm_runtime_put_noidle(dev_data->dev);
+		return ret;
+	}
+
+	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+
+	pm_runtime_disable(dev_data->dev);
+	pm_runtime_put_noidle(dev_data->dev);
+
+	return 0;
+}
+
+static int __maybe_unused mcrc_suspend(struct device *dev)
+{
+	return	pm_runtime_force_suspend(dev);
+}
+
+static int __maybe_unused mcrc_resume(struct device *dev)
+{
+	return pm_runtime_force_resume(dev);
+}
+
+static const struct dev_pm_ops mcrc_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(mcrc_suspend,
+				mcrc_resume)
+};
+
+static const struct of_device_id of_match[] = {
+	{ .compatible = "ti,mcrc", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_match);
+
+static struct platform_driver mcrc_driver = {
+	.probe	= mcrc_probe,
+	.remove = mcrc_remove,
+	.driver = {
+		.name		= DRIVER_NAME,
+		.pm		= &mcrc_pm_ops,
+		.of_match_table = of_match,
+	},
+};
+
+module_platform_driver(mcrc_driver);
+
+MODULE_AUTHOR("Kamlesh Gurudasani <kamlesh@ti.com>");
+MODULE_DESCRIPTION("Texas Instruments MCRC hardware driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/dma/ti/k3-psil-am62a.c b/drivers/dma/ti/k3-psil-am62a.c
--- a/drivers/dma/ti/k3-psil-am62a.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/dma/ti/k3-psil-am62a.c	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com
+ */
+
+#include <linux/kernel.h>
+
+#include "k3-psil-priv.h"
+
+#define PSIL_PDMA_XY_TR(x)					\
+	{							\
+		.thread_id = x,					\
+		.ep_config = {					\
+			.ep_type = PSIL_EP_PDMA_XY,		\
+			.mapped_channel_id = -1,		\
+			.default_flow_id = -1,			\
+		},						\
+	}
+
+#define PSIL_PDMA_XY_PKT(x)					\
+	{							\
+		.thread_id = x,					\
+		.ep_config = {					\
+			.ep_type = PSIL_EP_PDMA_XY,		\
+			.mapped_channel_id = -1,		\
+			.default_flow_id = -1,			\
+			.pkt_mode = 1,				\
+		},						\
+	}
+
+#define PSIL_ETHERNET(x, ch, flow_base, flow_cnt)		\
+	{							\
+		.thread_id = x,					\
+		.ep_config = {					\
+			.ep_type = PSIL_EP_NATIVE,		\
+			.pkt_mode = 1,				\
+			.needs_epib = 1,			\
+			.psd_size = 16,				\
+			.mapped_channel_id = ch,		\
+			.flow_start = flow_base,		\
+			.flow_num = flow_cnt,			\
+			.default_flow_id = flow_base,		\
+		},						\
+	}
+
+#define PSIL_SAUL(x, ch, flow_base, flow_cnt, default_flow, tx)	\
+	{							\
+		.thread_id = x,					\
+		.ep_config = {					\
+			.ep_type = PSIL_EP_NATIVE,		\
+			.pkt_mode = 1,				\
+			.needs_epib = 1,			\
+			.psd_size = 64,				\
+			.mapped_channel_id = ch,		\
+			.flow_start = flow_base,		\
+			.flow_num = flow_cnt,			\
+			.default_flow_id = default_flow,	\
+			.notdpkt = tx,				\
+		},						\
+	}
+
+#define PSIL_PDMA_MCASP(x)				\
+	{						\
+		.thread_id = x,				\
+		.ep_config = {				\
+			.ep_type = PSIL_EP_PDMA_XY,	\
+			.pdma_acc32 = 1,		\
+			.pdma_burst = 1,		\
+		},					\
+	}
+
+#define PSIL_CSI2RX(x)					\
+	{						\
+		.thread_id = x,				\
+		.ep_config = {				\
+			.ep_type = PSIL_EP_NATIVE,	\
+		},					\
+	}
+
+/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */
+static struct psil_ep am62a_src_ep_map[] = {
+	/* SAUL */
+	PSIL_SAUL(0x7504, 20, 35, 8, 35, 0),
+	PSIL_SAUL(0x7505, 21, 35, 8, 36, 0),
+	PSIL_SAUL(0x7506, 22, 43, 8, 43, 0),
+	PSIL_SAUL(0x7507, 23, 43, 8, 44, 0),
+	/* PDMA_MAIN0 - SPI0-2 */
+	PSIL_PDMA_XY_PKT(0x4300),
+	PSIL_PDMA_XY_PKT(0x4301),
+	PSIL_PDMA_XY_PKT(0x4302),
+	PSIL_PDMA_XY_PKT(0x4303),
+	PSIL_PDMA_XY_PKT(0x4304),
+	PSIL_PDMA_XY_PKT(0x4305),
+	PSIL_PDMA_XY_PKT(0x4306),
+	PSIL_PDMA_XY_PKT(0x4307),
+	PSIL_PDMA_XY_PKT(0x4308),
+	PSIL_PDMA_XY_PKT(0x4309),
+	PSIL_PDMA_XY_PKT(0x430a),
+	PSIL_PDMA_XY_PKT(0x430b),
+	/* PDMA_MAIN1 - UART0-6 */
+	PSIL_PDMA_XY_PKT(0x4400),
+	PSIL_PDMA_XY_PKT(0x4401),
+	PSIL_PDMA_XY_PKT(0x4402),
+	PSIL_PDMA_XY_PKT(0x4403),
+	PSIL_PDMA_XY_PKT(0x4404),
+	PSIL_PDMA_XY_PKT(0x4405),
+	PSIL_PDMA_XY_PKT(0x4406),
+	/* PDMA_MAIN2 - MCASP0-2 */
+	PSIL_PDMA_MCASP(0x4500),
+	PSIL_PDMA_MCASP(0x4501),
+	PSIL_PDMA_MCASP(0x4502),
+	/* CPSW3G */
+	PSIL_ETHERNET(0x4600, 19, 19, 16),
+	/* CSI2RX */
+	PSIL_CSI2RX(0x5000),
+	PSIL_CSI2RX(0x5001),
+	PSIL_CSI2RX(0x5002),
+	PSIL_CSI2RX(0x5003),
+	PSIL_CSI2RX(0x5004),
+	PSIL_CSI2RX(0x5005),
+	PSIL_CSI2RX(0x5006),
+	PSIL_CSI2RX(0x5007),
+	PSIL_CSI2RX(0x5008),
+	PSIL_CSI2RX(0x5009),
+	PSIL_CSI2RX(0x500a),
+	PSIL_CSI2RX(0x500b),
+	PSIL_CSI2RX(0x500c),
+	PSIL_CSI2RX(0x500d),
+	PSIL_CSI2RX(0x500e),
+	PSIL_CSI2RX(0x500f),
+	PSIL_CSI2RX(0x5010),
+	PSIL_CSI2RX(0x5011),
+	PSIL_CSI2RX(0x5012),
+	PSIL_CSI2RX(0x5013),
+	PSIL_CSI2RX(0x5014),
+	PSIL_CSI2RX(0x5015),
+	PSIL_CSI2RX(0x5016),
+	PSIL_CSI2RX(0x5017),
+	PSIL_CSI2RX(0x5018),
+	PSIL_CSI2RX(0x5019),
+	PSIL_CSI2RX(0x501a),
+	PSIL_CSI2RX(0x501b),
+	PSIL_CSI2RX(0x501c),
+	PSIL_CSI2RX(0x501d),
+	PSIL_CSI2RX(0x501e),
+	PSIL_CSI2RX(0x501f),
+};
+
+/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */
+static struct psil_ep am62a_dst_ep_map[] = {
+	/* SAUL */
+	PSIL_SAUL(0xf500, 27, 83, 8, 83, 1),
+	PSIL_SAUL(0xf501, 28, 91, 8, 91, 1),
+	/* PDMA_MAIN0 - SPI0-2 */
+	PSIL_PDMA_XY_PKT(0xc300),
+	PSIL_PDMA_XY_PKT(0xc301),
+	PSIL_PDMA_XY_PKT(0xc302),
+	PSIL_PDMA_XY_PKT(0xc303),
+	PSIL_PDMA_XY_PKT(0xc304),
+	PSIL_PDMA_XY_PKT(0xc305),
+	PSIL_PDMA_XY_PKT(0xc306),
+	PSIL_PDMA_XY_PKT(0xc307),
+	PSIL_PDMA_XY_PKT(0xc308),
+	PSIL_PDMA_XY_PKT(0xc309),
+	PSIL_PDMA_XY_PKT(0xc30a),
+	PSIL_PDMA_XY_PKT(0xc30b),
+	/* PDMA_MAIN1 - UART0-6 */
+	PSIL_PDMA_XY_PKT(0xc400),
+	PSIL_PDMA_XY_PKT(0xc401),
+	PSIL_PDMA_XY_PKT(0xc402),
+	PSIL_PDMA_XY_PKT(0xc403),
+	PSIL_PDMA_XY_PKT(0xc404),
+	PSIL_PDMA_XY_PKT(0xc405),
+	PSIL_PDMA_XY_PKT(0xc406),
+	/* PDMA_MAIN2 - MCASP0-2 */
+	PSIL_PDMA_MCASP(0xc500),
+	PSIL_PDMA_MCASP(0xc501),
+	PSIL_PDMA_MCASP(0xc502),
+	/* CPSW3G */
+	PSIL_ETHERNET(0xc600, 19, 19, 8),
+	PSIL_ETHERNET(0xc601, 20, 27, 8),
+	PSIL_ETHERNET(0xc602, 21, 35, 8),
+	PSIL_ETHERNET(0xc603, 22, 43, 8),
+	PSIL_ETHERNET(0xc604, 23, 51, 8),
+	PSIL_ETHERNET(0xc605, 24, 59, 8),
+	PSIL_ETHERNET(0xc606, 25, 67, 8),
+	PSIL_ETHERNET(0xc607, 26, 75, 8),
+};
+
+struct psil_ep_map am62a_ep_map = {
+	.name = "am62a",
+	.src = am62a_src_ep_map,
+	.src_count = ARRAY_SIZE(am62a_src_ep_map),
+	.dst = am62a_dst_ep_map,
+	.dst_count = ARRAY_SIZE(am62a_dst_ep_map),
+};
diff -Naur --no-dereference a/drivers/dma/ti/k3-psil-am62.c b/drivers/dma/ti/k3-psil-am62.c
--- a/drivers/dma/ti/k3-psil-am62.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/dma/ti/k3-psil-am62.c	2024-01-28 14:01:31.240353775 -0500
@@ -74,7 +74,9 @@
 	PSIL_SAUL(0x7505, 21, 35, 8, 36, 0),
 	PSIL_SAUL(0x7506, 22, 43, 8, 43, 0),
 	PSIL_SAUL(0x7507, 23, 43, 8, 44, 0),
-	/* PDMA_MAIN0 - SPI0-3 */
+	/* PDMA_MAIN0 - SPI0-2 */
+	PSIL_PDMA_XY_PKT(0x4300),
+	PSIL_PDMA_XY_PKT(0x4301),
 	PSIL_PDMA_XY_PKT(0x4302),
 	PSIL_PDMA_XY_PKT(0x4303),
 	PSIL_PDMA_XY_PKT(0x4304),
@@ -85,8 +87,6 @@
 	PSIL_PDMA_XY_PKT(0x4309),
 	PSIL_PDMA_XY_PKT(0x430a),
 	PSIL_PDMA_XY_PKT(0x430b),
-	PSIL_PDMA_XY_PKT(0x430c),
-	PSIL_PDMA_XY_PKT(0x430d),
 	/* PDMA_MAIN1 - UART0-6 */
 	PSIL_PDMA_XY_PKT(0x4400),
 	PSIL_PDMA_XY_PKT(0x4401),
@@ -141,7 +141,9 @@
 	/* SAUL */
 	PSIL_SAUL(0xf500, 27, 83, 8, 83, 1),
 	PSIL_SAUL(0xf501, 28, 91, 8, 91, 1),
-	/* PDMA_MAIN0 - SPI0-3 */
+	/* PDMA_MAIN0 - SPI0-2 */
+	PSIL_PDMA_XY_PKT(0xc300),
+	PSIL_PDMA_XY_PKT(0xc301),
 	PSIL_PDMA_XY_PKT(0xc302),
 	PSIL_PDMA_XY_PKT(0xc303),
 	PSIL_PDMA_XY_PKT(0xc304),
@@ -152,8 +154,6 @@
 	PSIL_PDMA_XY_PKT(0xc309),
 	PSIL_PDMA_XY_PKT(0xc30a),
 	PSIL_PDMA_XY_PKT(0xc30b),
-	PSIL_PDMA_XY_PKT(0xc30c),
-	PSIL_PDMA_XY_PKT(0xc30d),
 	/* PDMA_MAIN1 - UART0-6 */
 	PSIL_PDMA_XY_PKT(0xc400),
 	PSIL_PDMA_XY_PKT(0xc401),
diff -Naur --no-dereference a/drivers/dma/ti/k3-psil-am62p.c b/drivers/dma/ti/k3-psil-am62p.c
--- a/drivers/dma/ti/k3-psil-am62p.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/dma/ti/k3-psil-am62p.c	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com
+ */
+
+#include <linux/kernel.h>
+
+#include "k3-psil-priv.h"
+
+#define PSIL_PDMA_XY_TR(x)					\
+	{							\
+		.thread_id = x,					\
+		.ep_config = {					\
+			.ep_type = PSIL_EP_PDMA_XY,		\
+			.mapped_channel_id = -1,		\
+			.default_flow_id = -1,			\
+		},						\
+	}
+
+#define PSIL_PDMA_XY_PKT(x)					\
+	{							\
+		.thread_id = x,					\
+		.ep_config = {					\
+			.ep_type = PSIL_EP_PDMA_XY,		\
+			.mapped_channel_id = -1,		\
+			.default_flow_id = -1,			\
+			.pkt_mode = 1,				\
+		},						\
+	}
+
+#define PSIL_ETHERNET(x, ch, flow_base, flow_cnt)		\
+	{							\
+		.thread_id = x,					\
+		.ep_config = {					\
+			.ep_type = PSIL_EP_NATIVE,		\
+			.pkt_mode = 1,				\
+			.needs_epib = 1,			\
+			.psd_size = 16,				\
+			.mapped_channel_id = ch,		\
+			.flow_start = flow_base,		\
+			.flow_num = flow_cnt,			\
+			.default_flow_id = flow_base,		\
+		},						\
+	}
+
+#define PSIL_SAUL(x, ch, flow_base, flow_cnt, default_flow, tx)	\
+	{							\
+		.thread_id = x,					\
+		.ep_config = {					\
+			.ep_type = PSIL_EP_NATIVE,		\
+			.pkt_mode = 1,				\
+			.needs_epib = 1,			\
+			.psd_size = 64,				\
+			.mapped_channel_id = ch,		\
+			.flow_start = flow_base,		\
+			.flow_num = flow_cnt,			\
+			.default_flow_id = default_flow,	\
+			.notdpkt = tx,				\
+		},						\
+	}
+
+#define PSIL_PDMA_MCASP(x)				\
+	{						\
+		.thread_id = x,				\
+		.ep_config = {				\
+			.ep_type = PSIL_EP_PDMA_XY,	\
+			.pdma_acc32 = 1,		\
+			.pdma_burst = 1,		\
+		},					\
+	}
+
+#define PSIL_CSI2RX(x)					\
+	{						\
+		.thread_id = x,				\
+		.ep_config = {				\
+			.ep_type = PSIL_EP_NATIVE,	\
+		},					\
+	}
+
+/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */
+static struct psil_ep am62p_src_ep_map[] = {
+	/* SAUL */
+	PSIL_SAUL(0x7504, 20, 35, 8, 35, 0),
+	PSIL_SAUL(0x7505, 21, 35, 8, 36, 0),
+	PSIL_SAUL(0x7506, 22, 43, 8, 43, 0),
+	PSIL_SAUL(0x7507, 23, 43, 8, 44, 0),
+	/* PDMA_MAIN0 - SPI0-2 */
+	PSIL_PDMA_XY_PKT(0x4300),
+	PSIL_PDMA_XY_PKT(0x4301),
+	PSIL_PDMA_XY_PKT(0x4302),
+	PSIL_PDMA_XY_PKT(0x4303),
+	PSIL_PDMA_XY_PKT(0x4304),
+	PSIL_PDMA_XY_PKT(0x4305),
+	PSIL_PDMA_XY_PKT(0x4306),
+	PSIL_PDMA_XY_PKT(0x4307),
+	PSIL_PDMA_XY_PKT(0x4308),
+	PSIL_PDMA_XY_PKT(0x4309),
+	PSIL_PDMA_XY_PKT(0x430a),
+	PSIL_PDMA_XY_PKT(0x430b),
+	/* PDMA_MAIN1 - UART0-6 */
+	PSIL_PDMA_XY_PKT(0x4400),
+	PSIL_PDMA_XY_PKT(0x4401),
+	PSIL_PDMA_XY_PKT(0x4402),
+	PSIL_PDMA_XY_PKT(0x4403),
+	PSIL_PDMA_XY_PKT(0x4404),
+	PSIL_PDMA_XY_PKT(0x4405),
+	PSIL_PDMA_XY_PKT(0x4406),
+	/* PDMA_MAIN2 - MCASP0-2 */
+	PSIL_PDMA_MCASP(0x4500),
+	PSIL_PDMA_MCASP(0x4501),
+	PSIL_PDMA_MCASP(0x4502),
+	/* CPSW3G */
+	PSIL_ETHERNET(0x4600, 19, 19, 16),
+	/* CSI2RX */
+	PSIL_CSI2RX(0x5000),
+	PSIL_CSI2RX(0x5001),
+	PSIL_CSI2RX(0x5002),
+	PSIL_CSI2RX(0x5003),
+	PSIL_CSI2RX(0x5004),
+	PSIL_CSI2RX(0x5005),
+	PSIL_CSI2RX(0x5006),
+	PSIL_CSI2RX(0x5007),
+	PSIL_CSI2RX(0x5008),
+	PSIL_CSI2RX(0x5009),
+	PSIL_CSI2RX(0x500a),
+	PSIL_CSI2RX(0x500b),
+	PSIL_CSI2RX(0x500c),
+	PSIL_CSI2RX(0x500d),
+	PSIL_CSI2RX(0x500e),
+	PSIL_CSI2RX(0x500f),
+	PSIL_CSI2RX(0x5010),
+	PSIL_CSI2RX(0x5011),
+	PSIL_CSI2RX(0x5012),
+	PSIL_CSI2RX(0x5013),
+	PSIL_CSI2RX(0x5014),
+	PSIL_CSI2RX(0x5015),
+	PSIL_CSI2RX(0x5016),
+	PSIL_CSI2RX(0x5017),
+	PSIL_CSI2RX(0x5018),
+	PSIL_CSI2RX(0x5019),
+	PSIL_CSI2RX(0x501a),
+	PSIL_CSI2RX(0x501b),
+	PSIL_CSI2RX(0x501c),
+	PSIL_CSI2RX(0x501d),
+	PSIL_CSI2RX(0x501e),
+	PSIL_CSI2RX(0x501f),
+	/* CSIRX 1-3 (only for J722S) */
+	PSIL_CSI2RX(0x5100),
+	PSIL_CSI2RX(0x5101),
+	PSIL_CSI2RX(0x5102),
+	PSIL_CSI2RX(0x5103),
+	PSIL_CSI2RX(0x5104),
+	PSIL_CSI2RX(0x5105),
+	PSIL_CSI2RX(0x5106),
+	PSIL_CSI2RX(0x5107),
+	PSIL_CSI2RX(0x5108),
+	PSIL_CSI2RX(0x5109),
+	PSIL_CSI2RX(0x510a),
+	PSIL_CSI2RX(0x510b),
+	PSIL_CSI2RX(0x510c),
+	PSIL_CSI2RX(0x510d),
+	PSIL_CSI2RX(0x510e),
+	PSIL_CSI2RX(0x510f),
+	PSIL_CSI2RX(0x5110),
+	PSIL_CSI2RX(0x5111),
+	PSIL_CSI2RX(0x5112),
+	PSIL_CSI2RX(0x5113),
+	PSIL_CSI2RX(0x5114),
+	PSIL_CSI2RX(0x5115),
+	PSIL_CSI2RX(0x5116),
+	PSIL_CSI2RX(0x5117),
+	PSIL_CSI2RX(0x5118),
+	PSIL_CSI2RX(0x5119),
+	PSIL_CSI2RX(0x511a),
+	PSIL_CSI2RX(0x511b),
+	PSIL_CSI2RX(0x511c),
+	PSIL_CSI2RX(0x511d),
+	PSIL_CSI2RX(0x511e),
+	PSIL_CSI2RX(0x511f),
+	PSIL_CSI2RX(0x5200),
+	PSIL_CSI2RX(0x5201),
+	PSIL_CSI2RX(0x5202),
+	PSIL_CSI2RX(0x5203),
+	PSIL_CSI2RX(0x5204),
+	PSIL_CSI2RX(0x5205),
+	PSIL_CSI2RX(0x5206),
+	PSIL_CSI2RX(0x5207),
+	PSIL_CSI2RX(0x5208),
+	PSIL_CSI2RX(0x5209),
+	PSIL_CSI2RX(0x520a),
+	PSIL_CSI2RX(0x520b),
+	PSIL_CSI2RX(0x520c),
+	PSIL_CSI2RX(0x520d),
+	PSIL_CSI2RX(0x520e),
+	PSIL_CSI2RX(0x520f),
+	PSIL_CSI2RX(0x5210),
+	PSIL_CSI2RX(0x5211),
+	PSIL_CSI2RX(0x5212),
+	PSIL_CSI2RX(0x5213),
+	PSIL_CSI2RX(0x5214),
+	PSIL_CSI2RX(0x5215),
+	PSIL_CSI2RX(0x5216),
+	PSIL_CSI2RX(0x5217),
+	PSIL_CSI2RX(0x5218),
+	PSIL_CSI2RX(0x5219),
+	PSIL_CSI2RX(0x521a),
+	PSIL_CSI2RX(0x521b),
+	PSIL_CSI2RX(0x521c),
+	PSIL_CSI2RX(0x521d),
+	PSIL_CSI2RX(0x521e),
+	PSIL_CSI2RX(0x521f),
+	PSIL_CSI2RX(0x5300),
+	PSIL_CSI2RX(0x5301),
+	PSIL_CSI2RX(0x5302),
+	PSIL_CSI2RX(0x5303),
+	PSIL_CSI2RX(0x5304),
+	PSIL_CSI2RX(0x5305),
+	PSIL_CSI2RX(0x5306),
+	PSIL_CSI2RX(0x5307),
+	PSIL_CSI2RX(0x5308),
+	PSIL_CSI2RX(0x5309),
+	PSIL_CSI2RX(0x530a),
+	PSIL_CSI2RX(0x530b),
+	PSIL_CSI2RX(0x530c),
+	PSIL_CSI2RX(0x530d),
+	PSIL_CSI2RX(0x530e),
+	PSIL_CSI2RX(0x530f),
+	PSIL_CSI2RX(0x5310),
+	PSIL_CSI2RX(0x5311),
+	PSIL_CSI2RX(0x5312),
+	PSIL_CSI2RX(0x5313),
+	PSIL_CSI2RX(0x5314),
+	PSIL_CSI2RX(0x5315),
+	PSIL_CSI2RX(0x5316),
+	PSIL_CSI2RX(0x5317),
+	PSIL_CSI2RX(0x5318),
+	PSIL_CSI2RX(0x5319),
+	PSIL_CSI2RX(0x531a),
+	PSIL_CSI2RX(0x531b),
+	PSIL_CSI2RX(0x531c),
+	PSIL_CSI2RX(0x531d),
+	PSIL_CSI2RX(0x531e),
+	PSIL_CSI2RX(0x531f),
+
+};
+
+/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */
+static struct psil_ep am62p_dst_ep_map[] = {
+	/* SAUL */
+	PSIL_SAUL(0xf500, 27, 83, 8, 83, 1),
+	PSIL_SAUL(0xf501, 28, 91, 8, 91, 1),
+	/* PDMA_MAIN0 - SPI0-2 */
+	PSIL_PDMA_XY_PKT(0xc300),
+	PSIL_PDMA_XY_PKT(0xc301),
+	PSIL_PDMA_XY_PKT(0xc302),
+	PSIL_PDMA_XY_PKT(0xc303),
+	PSIL_PDMA_XY_PKT(0xc304),
+	PSIL_PDMA_XY_PKT(0xc305),
+	PSIL_PDMA_XY_PKT(0xc306),
+	PSIL_PDMA_XY_PKT(0xc307),
+	PSIL_PDMA_XY_PKT(0xc308),
+	PSIL_PDMA_XY_PKT(0xc309),
+	PSIL_PDMA_XY_PKT(0xc30a),
+	PSIL_PDMA_XY_PKT(0xc30b),
+	/* PDMA_MAIN1 - UART0-6 */
+	PSIL_PDMA_XY_PKT(0xc400),
+	PSIL_PDMA_XY_PKT(0xc401),
+	PSIL_PDMA_XY_PKT(0xc402),
+	PSIL_PDMA_XY_PKT(0xc403),
+	PSIL_PDMA_XY_PKT(0xc404),
+	PSIL_PDMA_XY_PKT(0xc405),
+	PSIL_PDMA_XY_PKT(0xc406),
+	/* PDMA_MAIN2 - MCASP0-2 */
+	PSIL_PDMA_MCASP(0xc500),
+	PSIL_PDMA_MCASP(0xc501),
+	PSIL_PDMA_MCASP(0xc502),
+	/* CPSW3G */
+	PSIL_ETHERNET(0xc600, 19, 19, 8),
+	PSIL_ETHERNET(0xc601, 20, 27, 8),
+	PSIL_ETHERNET(0xc602, 21, 35, 8),
+	PSIL_ETHERNET(0xc603, 22, 43, 8),
+	PSIL_ETHERNET(0xc604, 23, 51, 8),
+	PSIL_ETHERNET(0xc605, 24, 59, 8),
+	PSIL_ETHERNET(0xc606, 25, 67, 8),
+	PSIL_ETHERNET(0xc607, 26, 75, 8),
+};
+
+struct psil_ep_map am62p_ep_map = {
+	.name = "am62p",
+	.src = am62p_src_ep_map,
+	.src_count = ARRAY_SIZE(am62p_src_ep_map),
+	.dst = am62p_dst_ep_map,
+	.dst_count = ARRAY_SIZE(am62p_dst_ep_map),
+};
diff -Naur --no-dereference a/drivers/dma/ti/k3-psil.c b/drivers/dma/ti/k3-psil.c
--- a/drivers/dma/ti/k3-psil.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/dma/ti/k3-psil.c	2024-01-28 14:01:31.240353775 -0500
@@ -5,6 +5,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
@@ -23,6 +24,10 @@
 	{ .family = "AM64X", .data = &am64_ep_map },
 	{ .family = "J721S2", .data = &j721s2_ep_map },
 	{ .family = "AM62X", .data = &am62_ep_map },
+	{ .family = "AM62AX", .data = &am62a_ep_map },
+	{ .family = "J784S4", .data = &j784s4_ep_map },
+	{ .family = "AM62PX", .data = &am62p_ep_map },
+	{ .family = "J722S", .data = &am62p_ep_map },
 	{ /* sentinel */ }
 };
 
@@ -101,3 +106,4 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(psil_set_new_ep_config);
+MODULE_LICENSE("GPL v2");
diff -Naur --no-dereference a/drivers/dma/ti/k3-psil-j721s2.c b/drivers/dma/ti/k3-psil-j721s2.c
--- a/drivers/dma/ti/k3-psil-j721s2.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/dma/ti/k3-psil-j721s2.c	2024-01-28 14:01:31.240353775 -0500
@@ -57,6 +57,14 @@
 		},					\
 	}
 
+#define PSIL_CSI2RX(x)					\
+	{						\
+		.thread_id = x,				\
+		.ep_config = {				\
+			.ep_type = PSIL_EP_NATIVE,	\
+		},					\
+	}
+
 /* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */
 static struct psil_ep j721s2_src_ep_map[] = {
 	/* PDMA_MCASP - McASP0-4 */
@@ -99,6 +107,8 @@
 	PSIL_PDMA_XY_PKT(0x461d),
 	PSIL_PDMA_XY_PKT(0x461e),
 	PSIL_PDMA_XY_PKT(0x461f),
+	/* MAIN_CPSW2G */
+	PSIL_ETHERNET(0x4640),
 	/* PDMA_USART_G0 - UART0-1 */
 	PSIL_PDMA_XY_PKT(0x4700),
 	PSIL_PDMA_XY_PKT(0x4701),
@@ -112,6 +122,71 @@
 	PSIL_PDMA_XY_PKT(0x4707),
 	PSIL_PDMA_XY_PKT(0x4708),
 	PSIL_PDMA_XY_PKT(0x4709),
+	/* CSI2RX */
+	PSIL_CSI2RX(0x4940),
+	PSIL_CSI2RX(0x4941),
+	PSIL_CSI2RX(0x4942),
+	PSIL_CSI2RX(0x4943),
+	PSIL_CSI2RX(0x4944),
+	PSIL_CSI2RX(0x4945),
+	PSIL_CSI2RX(0x4946),
+	PSIL_CSI2RX(0x4947),
+	PSIL_CSI2RX(0x4948),
+	PSIL_CSI2RX(0x4949),
+	PSIL_CSI2RX(0x494a),
+	PSIL_CSI2RX(0x494b),
+	PSIL_CSI2RX(0x494c),
+	PSIL_CSI2RX(0x494d),
+	PSIL_CSI2RX(0x494e),
+	PSIL_CSI2RX(0x494f),
+	PSIL_CSI2RX(0x4950),
+	PSIL_CSI2RX(0x4951),
+	PSIL_CSI2RX(0x4952),
+	PSIL_CSI2RX(0x4953),
+	PSIL_CSI2RX(0x4954),
+	PSIL_CSI2RX(0x4955),
+	PSIL_CSI2RX(0x4956),
+	PSIL_CSI2RX(0x4957),
+	PSIL_CSI2RX(0x4958),
+	PSIL_CSI2RX(0x4959),
+	PSIL_CSI2RX(0x495a),
+	PSIL_CSI2RX(0x495b),
+	PSIL_CSI2RX(0x495c),
+	PSIL_CSI2RX(0x495d),
+	PSIL_CSI2RX(0x495e),
+	PSIL_CSI2RX(0x495f),
+	PSIL_CSI2RX(0x4960),
+	PSIL_CSI2RX(0x4961),
+	PSIL_CSI2RX(0x4962),
+	PSIL_CSI2RX(0x4963),
+	PSIL_CSI2RX(0x4964),
+	PSIL_CSI2RX(0x4965),
+	PSIL_CSI2RX(0x4966),
+	PSIL_CSI2RX(0x4967),
+	PSIL_CSI2RX(0x4968),
+	PSIL_CSI2RX(0x4969),
+	PSIL_CSI2RX(0x496a),
+	PSIL_CSI2RX(0x496b),
+	PSIL_CSI2RX(0x496c),
+	PSIL_CSI2RX(0x496d),
+	PSIL_CSI2RX(0x496e),
+	PSIL_CSI2RX(0x496f),
+	PSIL_CSI2RX(0x4970),
+	PSIL_CSI2RX(0x4971),
+	PSIL_CSI2RX(0x4972),
+	PSIL_CSI2RX(0x4973),
+	PSIL_CSI2RX(0x4974),
+	PSIL_CSI2RX(0x4975),
+	PSIL_CSI2RX(0x4976),
+	PSIL_CSI2RX(0x4977),
+	PSIL_CSI2RX(0x4978),
+	PSIL_CSI2RX(0x4979),
+	PSIL_CSI2RX(0x497a),
+	PSIL_CSI2RX(0x497b),
+	PSIL_CSI2RX(0x497c),
+	PSIL_CSI2RX(0x497d),
+	PSIL_CSI2RX(0x497e),
+	PSIL_CSI2RX(0x497f),
 	/* MAIN SA2UL */
 	PSIL_SA2UL(0x4a40, 0),
 	PSIL_SA2UL(0x4a41, 0),
@@ -161,6 +236,15 @@
 	PSIL_ETHERNET(0xf005),
 	PSIL_ETHERNET(0xf006),
 	PSIL_ETHERNET(0xf007),
+	/* MAIN_CPSW2G */
+	PSIL_ETHERNET(0xc640),
+	PSIL_ETHERNET(0xc641),
+	PSIL_ETHERNET(0xc642),
+	PSIL_ETHERNET(0xc643),
+	PSIL_ETHERNET(0xc644),
+	PSIL_ETHERNET(0xc645),
+	PSIL_ETHERNET(0xc646),
+	PSIL_ETHERNET(0xc647),
 	/* SA2UL */
 	PSIL_SA2UL(0xf500, 1),
 	PSIL_SA2UL(0xf501, 1),
diff -Naur --no-dereference a/drivers/dma/ti/k3-psil-j784s4.c b/drivers/dma/ti/k3-psil-j784s4.c
--- a/drivers/dma/ti/k3-psil-j784s4.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/dma/ti/k3-psil-j784s4.c	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,354 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com
+ */
+
+#include <linux/kernel.h>
+
+#include "k3-psil-priv.h"
+
+#define PSIL_PDMA_XY_TR(x)				\
+	{						\
+		.thread_id = x,				\
+		.ep_config = {				\
+			.ep_type = PSIL_EP_PDMA_XY,	\
+		},					\
+	}
+
+#define PSIL_PDMA_XY_PKT(x)				\
+	{						\
+		.thread_id = x,				\
+		.ep_config = {				\
+			.ep_type = PSIL_EP_PDMA_XY,	\
+			.pkt_mode = 1,			\
+		},					\
+	}
+
+#define PSIL_PDMA_MCASP(x)				\
+	{						\
+		.thread_id = x,				\
+		.ep_config = {				\
+			.ep_type = PSIL_EP_PDMA_XY,	\
+			.pdma_acc32 = 1,		\
+			.pdma_burst = 1,		\
+		},					\
+	}
+
+#define PSIL_ETHERNET(x)				\
+	{						\
+		.thread_id = x,				\
+		.ep_config = {				\
+			.ep_type = PSIL_EP_NATIVE,	\
+			.pkt_mode = 1,			\
+			.needs_epib = 1,		\
+			.psd_size = 16,			\
+		},					\
+	}
+
+#define PSIL_SA2UL(x, tx)				\
+	{						\
+		.thread_id = x,				\
+		.ep_config = {				\
+			.ep_type = PSIL_EP_NATIVE,	\
+			.pkt_mode = 1,			\
+			.needs_epib = 1,		\
+			.psd_size = 64,			\
+			.notdpkt = tx,			\
+		},					\
+	}
+
+#define PSIL_CSI2RX(x)					\
+	{						\
+		.thread_id = x,				\
+		.ep_config = {				\
+			.ep_type = PSIL_EP_NATIVE,	\
+		},					\
+	}
+
+/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */
+static struct psil_ep j784s4_src_ep_map[] = {
+	/* PDMA_MCASP - McASP0-4 */
+	PSIL_PDMA_MCASP(0x4400),
+	PSIL_PDMA_MCASP(0x4401),
+	PSIL_PDMA_MCASP(0x4402),
+	PSIL_PDMA_MCASP(0x4403),
+	PSIL_PDMA_MCASP(0x4404),
+	/* PDMA_SPI_G0 - SPI0-3 */
+	PSIL_PDMA_XY_PKT(0x4600),
+	PSIL_PDMA_XY_PKT(0x4601),
+	PSIL_PDMA_XY_PKT(0x4602),
+	PSIL_PDMA_XY_PKT(0x4603),
+	PSIL_PDMA_XY_PKT(0x4604),
+	PSIL_PDMA_XY_PKT(0x4605),
+	PSIL_PDMA_XY_PKT(0x4606),
+	PSIL_PDMA_XY_PKT(0x4607),
+	PSIL_PDMA_XY_PKT(0x4608),
+	PSIL_PDMA_XY_PKT(0x4609),
+	PSIL_PDMA_XY_PKT(0x460a),
+	PSIL_PDMA_XY_PKT(0x460b),
+	PSIL_PDMA_XY_PKT(0x460c),
+	PSIL_PDMA_XY_PKT(0x460d),
+	PSIL_PDMA_XY_PKT(0x460e),
+	PSIL_PDMA_XY_PKT(0x460f),
+	/* PDMA_SPI_G1 - SPI4-7 */
+	PSIL_PDMA_XY_PKT(0x4620),
+	PSIL_PDMA_XY_PKT(0x4621),
+	PSIL_PDMA_XY_PKT(0x4622),
+	PSIL_PDMA_XY_PKT(0x4623),
+	PSIL_PDMA_XY_PKT(0x4624),
+	PSIL_PDMA_XY_PKT(0x4625),
+	PSIL_PDMA_XY_PKT(0x4626),
+	PSIL_PDMA_XY_PKT(0x4627),
+	PSIL_PDMA_XY_PKT(0x4628),
+	PSIL_PDMA_XY_PKT(0x4629),
+	PSIL_PDMA_XY_PKT(0x462a),
+	PSIL_PDMA_XY_PKT(0x462b),
+	PSIL_PDMA_XY_PKT(0x462c),
+	PSIL_PDMA_XY_PKT(0x462d),
+	PSIL_PDMA_XY_PKT(0x462e),
+	PSIL_PDMA_XY_PKT(0x462f),
+	/* MAIN_CPSW2G */
+	PSIL_ETHERNET(0x4640),
+	/* PDMA_USART_G0 - UART0-1 */
+	PSIL_PDMA_XY_PKT(0x4700),
+	PSIL_PDMA_XY_PKT(0x4701),
+	/* PDMA_USART_G1 - UART2-3 */
+	PSIL_PDMA_XY_PKT(0x4702),
+	PSIL_PDMA_XY_PKT(0x4703),
+	/* PDMA_USART_G2 - UART4-9 */
+	PSIL_PDMA_XY_PKT(0x4704),
+	PSIL_PDMA_XY_PKT(0x4705),
+	PSIL_PDMA_XY_PKT(0x4706),
+	PSIL_PDMA_XY_PKT(0x4707),
+	PSIL_PDMA_XY_PKT(0x4708),
+	PSIL_PDMA_XY_PKT(0x4709),
+	/* CSI2RX */
+	PSIL_CSI2RX(0x4900),
+	PSIL_CSI2RX(0x4901),
+	PSIL_CSI2RX(0x4902),
+	PSIL_CSI2RX(0x4903),
+	PSIL_CSI2RX(0x4940),
+	PSIL_CSI2RX(0x4941),
+	PSIL_CSI2RX(0x4942),
+	PSIL_CSI2RX(0x4943),
+	PSIL_CSI2RX(0x4944),
+	PSIL_CSI2RX(0x4945),
+	PSIL_CSI2RX(0x4946),
+	PSIL_CSI2RX(0x4947),
+	PSIL_CSI2RX(0x4948),
+	PSIL_CSI2RX(0x4949),
+	PSIL_CSI2RX(0x494a),
+	PSIL_CSI2RX(0x494b),
+	PSIL_CSI2RX(0x494c),
+	PSIL_CSI2RX(0x494d),
+	PSIL_CSI2RX(0x494e),
+	PSIL_CSI2RX(0x494f),
+	PSIL_CSI2RX(0x4950),
+	PSIL_CSI2RX(0x4951),
+	PSIL_CSI2RX(0x4952),
+	PSIL_CSI2RX(0x4953),
+	PSIL_CSI2RX(0x4954),
+	PSIL_CSI2RX(0x4955),
+	PSIL_CSI2RX(0x4956),
+	PSIL_CSI2RX(0x4957),
+	PSIL_CSI2RX(0x4958),
+	PSIL_CSI2RX(0x4959),
+	PSIL_CSI2RX(0x495a),
+	PSIL_CSI2RX(0x495b),
+	PSIL_CSI2RX(0x495c),
+	PSIL_CSI2RX(0x495d),
+	PSIL_CSI2RX(0x495e),
+	PSIL_CSI2RX(0x495f),
+	PSIL_CSI2RX(0x4960),
+	PSIL_CSI2RX(0x4961),
+	PSIL_CSI2RX(0x4962),
+	PSIL_CSI2RX(0x4963),
+	PSIL_CSI2RX(0x4964),
+	PSIL_CSI2RX(0x4965),
+	PSIL_CSI2RX(0x4966),
+	PSIL_CSI2RX(0x4967),
+	PSIL_CSI2RX(0x4968),
+	PSIL_CSI2RX(0x4969),
+	PSIL_CSI2RX(0x496a),
+	PSIL_CSI2RX(0x496b),
+	PSIL_CSI2RX(0x496c),
+	PSIL_CSI2RX(0x496d),
+	PSIL_CSI2RX(0x496e),
+	PSIL_CSI2RX(0x496f),
+	PSIL_CSI2RX(0x4970),
+	PSIL_CSI2RX(0x4971),
+	PSIL_CSI2RX(0x4972),
+	PSIL_CSI2RX(0x4973),
+	PSIL_CSI2RX(0x4974),
+	PSIL_CSI2RX(0x4975),
+	PSIL_CSI2RX(0x4976),
+	PSIL_CSI2RX(0x4977),
+	PSIL_CSI2RX(0x4978),
+	PSIL_CSI2RX(0x4979),
+	PSIL_CSI2RX(0x497a),
+	PSIL_CSI2RX(0x497b),
+	PSIL_CSI2RX(0x497c),
+	PSIL_CSI2RX(0x497d),
+	PSIL_CSI2RX(0x497e),
+	PSIL_CSI2RX(0x497f),
+	PSIL_CSI2RX(0x4980),
+	PSIL_CSI2RX(0x4981),
+	PSIL_CSI2RX(0x4982),
+	PSIL_CSI2RX(0x4983),
+	PSIL_CSI2RX(0x4984),
+	PSIL_CSI2RX(0x4985),
+	PSIL_CSI2RX(0x4986),
+	PSIL_CSI2RX(0x4987),
+	PSIL_CSI2RX(0x4988),
+	PSIL_CSI2RX(0x4989),
+	PSIL_CSI2RX(0x498a),
+	PSIL_CSI2RX(0x498b),
+	PSIL_CSI2RX(0x498c),
+	PSIL_CSI2RX(0x498d),
+	PSIL_CSI2RX(0x498e),
+	PSIL_CSI2RX(0x498f),
+	PSIL_CSI2RX(0x4990),
+	PSIL_CSI2RX(0x4991),
+	PSIL_CSI2RX(0x4992),
+	PSIL_CSI2RX(0x4993),
+	PSIL_CSI2RX(0x4994),
+	PSIL_CSI2RX(0x4995),
+	PSIL_CSI2RX(0x4996),
+	PSIL_CSI2RX(0x4997),
+	PSIL_CSI2RX(0x4998),
+	PSIL_CSI2RX(0x4999),
+	PSIL_CSI2RX(0x499a),
+	PSIL_CSI2RX(0x499b),
+	PSIL_CSI2RX(0x499c),
+	PSIL_CSI2RX(0x499d),
+	PSIL_CSI2RX(0x499e),
+	PSIL_CSI2RX(0x499f),
+	/* MAIN_CPSW9G */
+	PSIL_ETHERNET(0x4a00),
+	/* MAIN-SA2UL */
+	PSIL_SA2UL(0x4a40, 0),
+	PSIL_SA2UL(0x4a41, 0),
+	PSIL_SA2UL(0x4a42, 0),
+	PSIL_SA2UL(0x4a43, 0),
+	/* MCU_CPSW0 */
+	PSIL_ETHERNET(0x7000),
+	/* MCU_PDMA0 (MCU_PDMA_MISC_G0) - SPI0 */
+	PSIL_PDMA_XY_PKT(0x7100),
+	PSIL_PDMA_XY_PKT(0x7101),
+	PSIL_PDMA_XY_PKT(0x7102),
+	PSIL_PDMA_XY_PKT(0x7103),
+	/* MCU_PDMA1 (MCU_PDMA_MISC_G1) - SPI1-2 */
+	PSIL_PDMA_XY_PKT(0x7200),
+	PSIL_PDMA_XY_PKT(0x7201),
+	PSIL_PDMA_XY_PKT(0x7202),
+	PSIL_PDMA_XY_PKT(0x7203),
+	PSIL_PDMA_XY_PKT(0x7204),
+	PSIL_PDMA_XY_PKT(0x7205),
+	PSIL_PDMA_XY_PKT(0x7206),
+	PSIL_PDMA_XY_PKT(0x7207),
+	/* MCU_PDMA2 (MCU_PDMA_MISC_G2) - UART0 */
+	PSIL_PDMA_XY_PKT(0x7300),
+	/* MCU_PDMA_ADC - ADC0-1 */
+	PSIL_PDMA_XY_TR(0x7400),
+	PSIL_PDMA_XY_TR(0x7401),
+	PSIL_PDMA_XY_TR(0x7402),
+	PSIL_PDMA_XY_TR(0x7403),
+	/* MCU_SA2UL */
+	PSIL_SA2UL(0x7500, 0),
+	PSIL_SA2UL(0x7501, 0),
+	PSIL_SA2UL(0x7502, 0),
+	PSIL_SA2UL(0x7503, 0),
+};
+
+/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */
+static struct psil_ep j784s4_dst_ep_map[] = {
+	/* MAIN_CPSW2G */
+	PSIL_ETHERNET(0xc640),
+	PSIL_ETHERNET(0xc641),
+	PSIL_ETHERNET(0xc642),
+	PSIL_ETHERNET(0xc643),
+	PSIL_ETHERNET(0xc644),
+	PSIL_ETHERNET(0xc645),
+	PSIL_ETHERNET(0xc646),
+	PSIL_ETHERNET(0xc647),
+	/* MAIN_CPSW9G */
+	PSIL_ETHERNET(0xca00),
+	PSIL_ETHERNET(0xca01),
+	PSIL_ETHERNET(0xca02),
+	PSIL_ETHERNET(0xca03),
+	PSIL_ETHERNET(0xca04),
+	PSIL_ETHERNET(0xca05),
+	PSIL_ETHERNET(0xca06),
+	PSIL_ETHERNET(0xca07),
+	/* MAIN-SA2UL */
+	PSIL_SA2UL(0xca40, 1),
+	PSIL_SA2UL(0xca41, 1),
+	/* PDMA_SPI_G0 - SPI0-3 */
+	PSIL_PDMA_XY_PKT(0xc600),
+	PSIL_PDMA_XY_PKT(0xc601),
+	PSIL_PDMA_XY_PKT(0xc602),
+	PSIL_PDMA_XY_PKT(0xc603),
+	PSIL_PDMA_XY_PKT(0xc604),
+	PSIL_PDMA_XY_PKT(0xc605),
+	PSIL_PDMA_XY_PKT(0xc606),
+	PSIL_PDMA_XY_PKT(0xc607),
+	PSIL_PDMA_XY_PKT(0xc608),
+	PSIL_PDMA_XY_PKT(0xc609),
+	PSIL_PDMA_XY_PKT(0xc60a),
+	PSIL_PDMA_XY_PKT(0xc60b),
+	PSIL_PDMA_XY_PKT(0xc60c),
+	PSIL_PDMA_XY_PKT(0xc60d),
+	PSIL_PDMA_XY_PKT(0xc60e),
+	PSIL_PDMA_XY_PKT(0xc60f),
+	/* PDMA_SPI_G1 - SPI4-7 */
+	PSIL_PDMA_XY_PKT(0xc620),
+	PSIL_PDMA_XY_PKT(0xc621),
+	PSIL_PDMA_XY_PKT(0xc622),
+	PSIL_PDMA_XY_PKT(0xc623),
+	PSIL_PDMA_XY_PKT(0xc624),
+	PSIL_PDMA_XY_PKT(0xc625),
+	PSIL_PDMA_XY_PKT(0xc626),
+	PSIL_PDMA_XY_PKT(0xc627),
+	PSIL_PDMA_XY_PKT(0xc628),
+	PSIL_PDMA_XY_PKT(0xc629),
+	PSIL_PDMA_XY_PKT(0xc62a),
+	PSIL_PDMA_XY_PKT(0xc62b),
+	PSIL_PDMA_XY_PKT(0xc62c),
+	PSIL_PDMA_XY_PKT(0xc62d),
+	PSIL_PDMA_XY_PKT(0xc62e),
+	PSIL_PDMA_XY_PKT(0xc62f),
+	/* MCU_CPSW0 */
+	PSIL_ETHERNET(0xf000),
+	PSIL_ETHERNET(0xf001),
+	PSIL_ETHERNET(0xf002),
+	PSIL_ETHERNET(0xf003),
+	PSIL_ETHERNET(0xf004),
+	PSIL_ETHERNET(0xf005),
+	PSIL_ETHERNET(0xf006),
+	PSIL_ETHERNET(0xf007),
+	/* MCU_PDMA_MISC_G0 - SPI0 */
+	PSIL_PDMA_XY_PKT(0xf100),
+	PSIL_PDMA_XY_PKT(0xf101),
+	PSIL_PDMA_XY_PKT(0xf102),
+	PSIL_PDMA_XY_PKT(0xf103),
+	/* MCU_PDMA_MISC_G1 - SPI1-2 */
+	PSIL_PDMA_XY_PKT(0xf200),
+	PSIL_PDMA_XY_PKT(0xf201),
+	PSIL_PDMA_XY_PKT(0xf202),
+	PSIL_PDMA_XY_PKT(0xf203),
+	PSIL_PDMA_XY_PKT(0xf204),
+	PSIL_PDMA_XY_PKT(0xf205),
+	PSIL_PDMA_XY_PKT(0xf206),
+	PSIL_PDMA_XY_PKT(0xf207),
+	/* MCU_SA2UL */
+	PSIL_SA2UL(0xf500, 1),
+	PSIL_SA2UL(0xf501, 1),
+};
+
+struct psil_ep_map j784s4_ep_map = {
+	.name = "j784s4",
+	.src = j784s4_src_ep_map,
+	.src_count = ARRAY_SIZE(j784s4_src_ep_map),
+	.dst = j784s4_dst_ep_map,
+	.dst_count = ARRAY_SIZE(j784s4_dst_ep_map),
+};
diff -Naur --no-dereference a/drivers/dma/ti/k3-psil-priv.h b/drivers/dma/ti/k3-psil-priv.h
--- a/drivers/dma/ti/k3-psil-priv.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/dma/ti/k3-psil-priv.h	2024-01-28 14:01:31.240353775 -0500
@@ -43,5 +43,8 @@
 extern struct psil_ep_map am64_ep_map;
 extern struct psil_ep_map j721s2_ep_map;
 extern struct psil_ep_map am62_ep_map;
+extern struct psil_ep_map am62a_ep_map;
+extern struct psil_ep_map j784s4_ep_map;
+extern struct psil_ep_map am62p_ep_map;
 
 #endif /* K3_PSIL_PRIV_H_ */
diff -Naur --no-dereference a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
--- a/drivers/dma/ti/k3-udma.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/dma/ti/k3-udma.c	2024-01-28 14:01:31.240353775 -0500
@@ -5,6 +5,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
@@ -54,6 +55,8 @@
 #define UDMA_RFLOW_DSTTAG_DST_TAG_LO	4
 #define UDMA_RFLOW_DSTTAG_DST_TAG_HI	5
 
+#define UDMA_J722S_BCDMA_PSIL_BASE		0x3100
+
 struct udma_chan;
 
 enum k3_dma_type {
@@ -134,6 +137,8 @@
 	u32 flags;
 	u32 statictr_z_mask;
 	u8 burst_size[3];
+	struct udma_soc_data *soc_data;
+	u8 order_id;
 };
 
 struct udma_soc_data {
@@ -303,6 +308,8 @@
 
 	/* Channel configuration parameters */
 	struct udma_chan_config config;
+	/* Channel configuration parameters (backup) */
+	struct udma_chan_config backup_config;
 
 	/* dmapool for packet mode descriptors */
 	bool use_dma_pool;
@@ -1009,9 +1016,14 @@
 		if (!uc->cyclic && !uc->desc)
 			udma_push_to_ring(uc, -1);
 
-		udma_rchanrt_write(uc, UDMA_CHAN_RT_PEER_RT_EN_REG,
-				   UDMA_PEER_RT_EN_ENABLE |
-				   UDMA_PEER_RT_EN_TEARDOWN);
+		/* FIXME: Doing a forced teardown for McASP PDMA to prevent channel corruption */
+		if (uc->cyclic && uc->config.ep_type == PSIL_EP_PDMA_XY &&
+		    uc->config.enable_acc32 && uc->config.enable_burst)
+			udma_rchanrt_write(uc, UDMA_CHAN_RT_PEER_RT_EN_REG, 0);
+		else
+			udma_rchanrt_write(uc, UDMA_CHAN_RT_PEER_RT_EN_REG,
+					   UDMA_PEER_RT_EN_ENABLE |
+					   UDMA_PEER_RT_EN_TEARDOWN);
 		break;
 	case DMA_MEM_TO_DEV:
 		udma_tchanrt_write(uc, UDMA_CHAN_RT_PEER_RT_EN_REG,
@@ -2107,6 +2119,7 @@
 static int bcdma_tisci_rx_channel_config(struct udma_chan *uc)
 {
 	struct udma_dev *ud = uc->ud;
+	const struct udma_match_data *match_data = ud->match_data;
 	struct udma_tisci_rm *tisci_rm = &ud->tisci_rm;
 	const struct ti_sci_rm_udmap_ops *tisci_ops = tisci_rm->tisci_udmap_ops;
 	struct udma_rchan *rchan = uc->rchan;
@@ -2117,6 +2130,11 @@
 	req_rx.nav_id = tisci_rm->tisci_dev_id;
 	req_rx.index = rchan->id;
 
+	if (match_data->order_id) {
+		req_rx.valid_params |= TI_SCI_MSG_VALUE_RM_UDMAP_CH_ORDER_ID_VALID;
+		req_rx.rx_orderid = match_data->order_id;
+	}
+
 	ret = tisci_ops->rx_ch_cfg(tisci_rm->tisci, &req_rx);
 	if (ret)
 		dev_err(ud->dev, "rchan%d cfg failed %d\n", rchan->id, ret);
@@ -2962,6 +2980,7 @@
 	struct scatterlist *sgent;
 	struct cppi5_tr_type15_t *tr_req = NULL;
 	enum dma_slave_buswidth dev_width;
+	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
 	u16 tr_cnt0, tr_cnt1;
 	dma_addr_t dev_addr;
 	struct udma_desc *d;
@@ -3032,6 +3051,7 @@
 
 	if (uc->ud->match_data->type == DMA_TYPE_UDMA) {
 		asel = 0;
+		csf |= CPPI5_TR_CSF_EOL_ICNT0;
 	} else {
 		asel = (u64)uc->config.asel << K3_ADDRESS_ASEL_SHIFT;
 		dev_addr |= asel;
@@ -3055,7 +3075,7 @@
 
 		cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE15, false,
 			      true, CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
-		cppi5_tr_csf_set(&tr_req[tr_idx].flags, CPPI5_TR_CSF_SUPR_EVT);
+		cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
 		cppi5_tr_set_trigger(&tr_req[tr_idx].flags,
 				     uc->config.tr_trigger_type,
 				     CPPI5_TR_TRIGGER_TYPE_ICNT2_DEC, 0, 0);
@@ -3101,8 +3121,7 @@
 			cppi5_tr_init(&tr_req[tr_idx].flags, CPPI5_TR_TYPE15,
 				      false, true,
 				      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
-			cppi5_tr_csf_set(&tr_req[tr_idx].flags,
-					 CPPI5_TR_CSF_SUPR_EVT);
+			cppi5_tr_csf_set(&tr_req[tr_idx].flags, csf);
 			cppi5_tr_set_trigger(&tr_req[tr_idx].flags,
 					     uc->config.tr_trigger_type,
 					     CPPI5_TR_TRIGGER_TYPE_ICNT2_DEC,
@@ -3146,8 +3165,7 @@
 		d->residue += sg_len;
 	}
 
-	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags,
-			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
+	cppi5_tr_csf_set(&tr_req[tr_idx - 1].flags, csf | CPPI5_TR_CSF_EOP);
 
 	return d;
 }
@@ -3676,6 +3694,7 @@
 	int num_tr;
 	size_t tr_size = sizeof(struct cppi5_tr_type15_t);
 	u16 tr0_cnt0, tr0_cnt1, tr1_cnt0;
+	u32 csf = CPPI5_TR_CSF_SUPR_EVT;
 
 	if (uc->config.dir != DMA_MEM_TO_MEM) {
 		dev_err(chan->device->dev,
@@ -3706,13 +3725,15 @@
 	if (uc->ud->match_data->type != DMA_TYPE_UDMA) {
 		src |= (u64)uc->ud->asel << K3_ADDRESS_ASEL_SHIFT;
 		dest |= (u64)uc->ud->asel << K3_ADDRESS_ASEL_SHIFT;
+	} else {
+		csf |= CPPI5_TR_CSF_EOL_ICNT0;
 	}
 
 	tr_req = d->hwdesc[0].tr_req_base;
 
 	cppi5_tr_init(&tr_req[0].flags, CPPI5_TR_TYPE15, false, true,
 		      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
-	cppi5_tr_csf_set(&tr_req[0].flags, CPPI5_TR_CSF_SUPR_EVT);
+	cppi5_tr_csf_set(&tr_req[0].flags, csf);
 
 	tr_req[0].addr = src;
 	tr_req[0].icnt0 = tr0_cnt0;
@@ -3731,7 +3752,7 @@
 	if (num_tr == 2) {
 		cppi5_tr_init(&tr_req[1].flags, CPPI5_TR_TYPE15, false, true,
 			      CPPI5_TR_EVENT_SIZE_COMPLETION, 0);
-		cppi5_tr_csf_set(&tr_req[1].flags, CPPI5_TR_CSF_SUPR_EVT);
+		cppi5_tr_csf_set(&tr_req[1].flags, csf);
 
 		tr_req[1].addr = src + tr0_cnt1 * tr0_cnt0;
 		tr_req[1].icnt0 = tr1_cnt0;
@@ -3746,8 +3767,7 @@
 		tr_req[1].dicnt3 = 1;
 	}
 
-	cppi5_tr_csf_set(&tr_req[num_tr - 1].flags,
-			 CPPI5_TR_CSF_SUPR_EVT | CPPI5_TR_CSF_EOP);
+	cppi5_tr_csf_set(&tr_req[num_tr - 1].flags, csf | CPPI5_TR_CSF_EOP);
 
 	if (uc->config.metadata_size)
 		d->vd.tx.metadata_ops = &metadata_ops;
@@ -4295,6 +4315,61 @@
 	},
 };
 
+static struct udma_soc_data j721s2_bcdma_soc_data = {
+	.oes = {
+		.bcdma_tchan_data = 0x800,
+		.bcdma_tchan_ring = 0xa00,
+		.bcdma_rchan_data = 0xe00,
+		.bcdma_rchan_ring = 0x1000,
+	},
+};
+
+static struct udma_soc_data am62a_dmss_csi_soc_data = {
+	.oes = {
+		.bcdma_rchan_data = 0xe00,
+		.bcdma_rchan_ring = 0x1000,
+	},
+};
+
+static struct udma_match_data am62a_bcdma_csirx_data = {
+	.type = DMA_TYPE_BCDMA,
+	.psil_base = 0x3100,
+	.enable_memcpy_support = false,
+	.burst_size = {
+		TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_64_BYTES, /* Normal Channels */
+		0, /* No H Channels */
+		0, /* No UH Channels */
+	},
+	.soc_data = &am62a_dmss_csi_soc_data,
+	.order_id = 8,
+};
+
+static struct udma_match_data j721s2_bcdma_data = {
+	.type = DMA_TYPE_BCDMA,
+	.psil_base = 0x2000,
+	.enable_memcpy_support = false,
+	.burst_size = {
+		TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_64_BYTES, /* Normal Channels */
+		0, /* No H Channels */
+		0, /* No UH Channels */
+	},
+	.soc_data = &j721s2_bcdma_soc_data,
+	.order_id = 15,
+};
+
+static struct udma_match_data j722s_bcdma_data = {
+	.type = DMA_TYPE_BCDMA,
+	.psil_base = UDMA_J722S_BCDMA_PSIL_BASE,
+	.enable_memcpy_support = false,
+	.burst_size = {
+		TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_64_BYTES, /* Normal Channels */
+		0, /* No H Channels */
+		0, /* No UH Channels */
+	},
+	.soc_data = &j721s2_bcdma_soc_data,
+	.order_id = 15,
+};
+
 static struct udma_match_data am64_bcdma_data = {
 	.type = DMA_TYPE_BCDMA,
 	.psil_base = 0x2000, /* for tchan and rchan, not applicable to bchan */
@@ -4336,22 +4411,26 @@
 		.compatible = "ti,j721e-navss-mcu-udmap",
 		.data = &j721e_mcu_data,
 	},
-	{ /* Sentinel */ },
-};
-
-static const struct of_device_id bcdma_of_match[] = {
 	{
 		.compatible = "ti,am64-dmss-bcdma",
 		.data = &am64_bcdma_data,
 	},
-	{ /* Sentinel */ },
-};
-
-static const struct of_device_id pktdma_of_match[] = {
 	{
 		.compatible = "ti,am64-dmss-pktdma",
 		.data = &am64_pktdma_data,
 	},
+	{
+		.compatible = "ti,am62a-dmss-bcdma-csirx",
+		.data = &am62a_bcdma_csirx_data,
+	},
+	{
+		.compatible = "ti,j721s2-dmss-bcdma-csi",
+		.data = &j721s2_bcdma_data,
+	},
+	{
+		.compatible = "ti,j722s-dmss-bcdma-csi",
+		.data = &j722s_bcdma_data,
+	},
 	{ /* Sentinel */ },
 };
 
@@ -4394,6 +4473,10 @@
 	{ .family = "AM64X", .data = &am64_soc_data },
 	{ .family = "J721S2", .data = &j721e_soc_data},
 	{ .family = "AM62X", .data = &am64_soc_data },
+	{ .family = "AM62AX", .data = &am64_soc_data },
+	{ .family = "J784S4", .data = &j721e_soc_data },
+	{ .family = "AM62PX", .data = &am64_soc_data },
+	{ .family = "J722S", .data = &am64_soc_data },
 	{ /* sentinel */ }
 };
 
@@ -4418,6 +4501,7 @@
 		break;
 	case DMA_TYPE_BCDMA:
 		ud->bchan_cnt = BCDMA_CAP2_BCHAN_CNT(cap2);
+		ud->bchan_cnt += BCDMA_CAP3_HBCHAN_CNT(cap3) + BCDMA_CAP3_UBCHAN_CNT(cap3);
 		ud->tchan_cnt = BCDMA_CAP2_TCHAN_CNT(cap2);
 		ud->rchan_cnt = BCDMA_CAP2_RCHAN_CNT(cap2);
 		ud->rflow_cnt = ud->rchan_cnt;
@@ -4782,7 +4866,10 @@
 				irq_res.desc[i].num = rm_res->desc[i].num;
 			}
 		}
+	} else {
+		i = 0;
 	}
+
 	if (ud->tchan_cnt) {
 		rm_res = tisci_rm->rm_ranges[RM_RANGE_TCHAN];
 		if (IS_ERR(rm_res)) {
@@ -5272,23 +5359,21 @@
 		return -ENOMEM;
 
 	match = of_match_node(udma_of_match, dev->of_node);
-	if (!match)
-		match = of_match_node(bcdma_of_match, dev->of_node);
 	if (!match) {
-		match = of_match_node(pktdma_of_match, dev->of_node);
-		if (!match) {
-			dev_err(dev, "No compatible match found\n");
-			return -ENODEV;
-		}
+		dev_err(dev, "No compatible match found\n");
+		return -ENODEV;
 	}
 	ud->match_data = match->data;
 
-	soc = soc_device_match(k3_soc_devices);
-	if (!soc) {
-		dev_err(dev, "No compatible SoC found\n");
-		return -ENODEV;
+	ud->soc_data = ud->match_data->soc_data;
+	if (!ud->soc_data) {
+		soc = soc_device_match(k3_soc_devices);
+		if (!soc) {
+			dev_err(dev, "No compatible SoC found\n");
+			return -ENODEV;
+		}
+		ud->soc_data = soc->data;
 	}
-	ud->soc_data = soc->data;
 
 	ret = udma_get_mmrs(pdev, ud);
 	if (ret)
@@ -5357,7 +5442,6 @@
 	dev->msi.domain = of_msi_get_domain(dev, dev->of_node,
 					    DOMAIN_BUS_TI_SCI_INTA_MSI);
 	if (!dev->msi.domain) {
-		dev_err(dev, "Failed to get MSI domain\n");
 		return -EPROBE_DEFER;
 	}
 
@@ -5504,35 +5588,69 @@
 	return ret;
 }
 
+static int udma_pm_suspend(struct device *dev)
+{
+	struct udma_dev *ud = dev_get_drvdata(dev);
+	struct dma_device *dma_dev = &ud->ddev;
+	struct dma_chan *chan;
+	struct udma_chan *uc;
+
+	list_for_each_entry(chan, &dma_dev->channels, device_node) {
+		if (chan->client_count) {
+			uc = to_udma_chan(chan);
+			/* backup the channel configuration */
+			memcpy(&uc->backup_config, &uc->config,
+			       sizeof(struct udma_chan_config));
+			dev_dbg(dev, "Suspending channel %s\n",
+				dma_chan_name(chan));
+			ud->ddev.device_free_chan_resources(chan);
+		}
+	}
+
+	return 0;
+}
+
+static int udma_pm_resume(struct device *dev)
+{
+	struct udma_dev *ud = dev_get_drvdata(dev);
+	struct dma_device *dma_dev = &ud->ddev;
+	struct dma_chan *chan;
+	struct udma_chan *uc;
+	int ret;
+
+	list_for_each_entry(chan, &dma_dev->channels, device_node) {
+		if (chan->client_count) {
+			uc = to_udma_chan(chan);
+			/* restore the channel configuration */
+			memcpy(&uc->config, &uc->backup_config,
+			       sizeof(struct udma_chan_config));
+			dev_dbg(dev, "Resuming channel %s\n",
+				dma_chan_name(chan));
+			ret = ud->ddev.device_alloc_chan_resources(chan);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops udma_pm_ops = {
+	SET_LATE_SYSTEM_SLEEP_PM_OPS(udma_pm_suspend, udma_pm_resume)
+};
+
 static struct platform_driver udma_driver = {
 	.driver = {
 		.name	= "ti-udma",
 		.of_match_table = udma_of_match,
 		.suppress_bind_attrs = true,
+		.pm = &udma_pm_ops,
 	},
 	.probe		= udma_probe,
 };
-builtin_platform_driver(udma_driver);
 
-static struct platform_driver bcdma_driver = {
-	.driver = {
-		.name	= "ti-bcdma",
-		.of_match_table = bcdma_of_match,
-		.suppress_bind_attrs = true,
-	},
-	.probe		= udma_probe,
-};
-builtin_platform_driver(bcdma_driver);
-
-static struct platform_driver pktdma_driver = {
-	.driver = {
-		.name	= "ti-pktdma",
-		.of_match_table = pktdma_of_match,
-		.suppress_bind_attrs = true,
-	},
-	.probe		= udma_probe,
-};
-builtin_platform_driver(pktdma_driver);
+module_platform_driver(udma_driver);
+MODULE_LICENSE("GPL v2");
 
 /* Private interfaces to UDMA */
 #include "k3-udma-private.c"
diff -Naur --no-dereference a/drivers/dma/ti/k3-udma-glue.c b/drivers/dma/ti/k3-udma-glue.c
--- a/drivers/dma/ti/k3-udma-glue.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/dma/ti/k3-udma-glue.c	2024-01-28 14:01:31.240353775 -0500
@@ -6,6 +6,7 @@
  *
  */
 
+#include <linux/module.h>
 #include <linux/atomic.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
@@ -110,6 +111,35 @@
 	return 0;
 }
 
+static int of_k3_udma_glue_parse_chn_common(struct k3_udma_glue_common *common, u32 thread_id,
+					    bool tx_chn)
+{
+	if (tx_chn && !(thread_id & K3_PSIL_DST_THREAD_ID_OFFSET))
+		return -EINVAL;
+
+	if (!tx_chn && (thread_id & K3_PSIL_DST_THREAD_ID_OFFSET))
+		return -EINVAL;
+
+	/* get psil endpoint config */
+	common->ep_config = psil_get_ep_config(thread_id);
+	if (IS_ERR(common->ep_config)) {
+		dev_err(common->dev,
+			"No configuration for psi-l thread 0x%04x\n",
+			thread_id);
+		return PTR_ERR(common->ep_config);
+	}
+
+	common->epib = common->ep_config->needs_epib;
+	common->psdata_size = common->ep_config->psd_size;
+
+	if (tx_chn)
+		common->dst_thread = thread_id;
+	else
+		common->src_thread = thread_id;
+
+	return 0;
+}
+
 static int of_k3_udma_glue_parse_chn(struct device_node *chn_np,
 		const char *name, struct k3_udma_glue_common *common,
 		bool tx_chn)
@@ -152,38 +182,32 @@
 		common->atype_asel = dma_spec.args[1];
 	}
 
-	if (tx_chn && !(thread_id & K3_PSIL_DST_THREAD_ID_OFFSET)) {
-		ret = -EINVAL;
-		goto out_put_spec;
-	}
+	ret = of_k3_udma_glue_parse_chn_common(common, thread_id, tx_chn);
 
-	if (!tx_chn && (thread_id & K3_PSIL_DST_THREAD_ID_OFFSET)) {
-		ret = -EINVAL;
-		goto out_put_spec;
-	}
+out_put_spec:
+	of_node_put(dma_spec.np);
+	return ret;
+}
 
-	/* get psil endpoint config */
-	common->ep_config = psil_get_ep_config(thread_id);
-	if (IS_ERR(common->ep_config)) {
-		dev_err(common->dev,
-			"No configuration for psi-l thread 0x%04x\n",
-			thread_id);
-		ret = PTR_ERR(common->ep_config);
-		goto out_put_spec;
-	}
+static int
+of_k3_udma_glue_parse_chn_by_id(struct device_node *udmax_np, struct k3_udma_glue_common *common,
+				bool tx_chn, u32 thread_id)
+{
+	int ret = 0;
 
-	common->epib = common->ep_config->needs_epib;
-	common->psdata_size = common->ep_config->psd_size;
+	if (unlikely(!udmax_np))
+		return -EINVAL;
 
-	if (tx_chn)
-		common->dst_thread = thread_id;
-	else
-		common->src_thread = thread_id;
+	ret = of_k3_udma_glue_parse(udmax_np, common);
+	if (ret)
+		goto out_put_spec;
+
+	ret = of_k3_udma_glue_parse_chn_common(common, thread_id, tx_chn);
 
 out_put_spec:
-	of_node_put(dma_spec.np);
+	of_node_put(udmax_np);
 	return ret;
-};
+}
 
 static void k3_udma_glue_dump_tx_chn(struct k3_udma_glue_tx_channel *tx_chn)
 {
@@ -250,29 +274,13 @@
 	return tisci_rm->tisci_udmap_ops->tx_ch_cfg(tisci_rm->tisci, &req);
 }
 
-struct k3_udma_glue_tx_channel *k3_udma_glue_request_tx_chn(struct device *dev,
-		const char *name, struct k3_udma_glue_tx_channel_cfg *cfg)
+static int
+k3_udma_glue_request_tx_chn_common(struct device *dev,
+				   struct k3_udma_glue_tx_channel *tx_chn,
+				   struct k3_udma_glue_tx_channel_cfg *cfg)
 {
-	struct k3_udma_glue_tx_channel *tx_chn;
 	int ret;
 
-	tx_chn = devm_kzalloc(dev, sizeof(*tx_chn), GFP_KERNEL);
-	if (!tx_chn)
-		return ERR_PTR(-ENOMEM);
-
-	tx_chn->common.dev = dev;
-	tx_chn->common.swdata_size = cfg->swdata_size;
-	tx_chn->tx_pause_on_err = cfg->tx_pause_on_err;
-	tx_chn->tx_filt_einfo = cfg->tx_filt_einfo;
-	tx_chn->tx_filt_pswords = cfg->tx_filt_pswords;
-	tx_chn->tx_supr_tdpkt = cfg->tx_supr_tdpkt;
-
-	/* parse of udmap channel */
-	ret = of_k3_udma_glue_parse_chn(dev->of_node, name,
-					&tx_chn->common, true);
-	if (ret)
-		goto err;
-
 	tx_chn->common.hdesc_size = cppi5_hdesc_calc_size(tx_chn->common.epib,
 						tx_chn->common.psdata_size,
 						tx_chn->common.swdata_size);
@@ -288,23 +296,22 @@
 	if (IS_ERR(tx_chn->udma_tchanx)) {
 		ret = PTR_ERR(tx_chn->udma_tchanx);
 		dev_err(dev, "UDMAX tchanx get err %d\n", ret);
-		goto err;
+		return ret;
 	}
 	tx_chn->udma_tchan_id = xudma_tchan_get_id(tx_chn->udma_tchanx);
 
-	tx_chn->common.chan_dev.class = &k3_udma_glue_devclass;
-	tx_chn->common.chan_dev.parent = xudma_get_device(tx_chn->common.udmax);
-	dev_set_name(&tx_chn->common.chan_dev, "tchan%d-0x%04x",
-		     tx_chn->udma_tchan_id, tx_chn->common.dst_thread);
-	ret = device_register(&tx_chn->common.chan_dev);
-	if (ret) {
-		dev_err(dev, "Channel Device registration failed %d\n", ret);
-		put_device(&tx_chn->common.chan_dev);
-		tx_chn->common.chan_dev.parent = NULL;
-		goto err;
-	}
-
 	if (xudma_is_pktdma(tx_chn->common.udmax)) {
+		tx_chn->common.chan_dev.class = &k3_udma_glue_devclass;
+		tx_chn->common.chan_dev.parent = xudma_get_device(tx_chn->common.udmax);
+		dev_set_name(&tx_chn->common.chan_dev, "tchan%d-0x%04x",
+			     tx_chn->udma_tchan_id, tx_chn->common.dst_thread);
+		ret = device_register(&tx_chn->common.chan_dev);
+		if (ret) {
+			dev_err(dev, "Channel Device registration failed %d\n", ret);
+			tx_chn->common.chan_dev.parent = NULL;
+			return ret;
+		}
+
 		/* prepare the channel device as coherent */
 		tx_chn->common.chan_dev.dma_coherent = true;
 		dma_coerce_mask_and_coherent(&tx_chn->common.chan_dev,
@@ -325,7 +332,7 @@
 					     &tx_chn->ringtxcq);
 	if (ret) {
 		dev_err(dev, "Failed to get TX/TXCQ rings %d\n", ret);
-		goto err;
+		return ret;
 	}
 
 	/* Set the dma_dev for the rings to be configured */
@@ -341,13 +348,13 @@
 	ret = k3_ringacc_ring_cfg(tx_chn->ringtx, &cfg->tx_cfg);
 	if (ret) {
 		dev_err(dev, "Failed to cfg ringtx %d\n", ret);
-		goto err;
+		return ret;
 	}
 
 	ret = k3_ringacc_ring_cfg(tx_chn->ringtxcq, &cfg->txcq_cfg);
 	if (ret) {
 		dev_err(dev, "Failed to cfg ringtx %d\n", ret);
-		goto err;
+		return ret;
 	}
 
 	/* request and cfg psi-l */
@@ -358,11 +365,42 @@
 	ret = k3_udma_glue_cfg_tx_chn(tx_chn);
 	if (ret) {
 		dev_err(dev, "Failed to cfg tchan %d\n", ret);
-		goto err;
+		return ret;
 	}
 
 	k3_udma_glue_dump_tx_chn(tx_chn);
 
+	return 0;
+}
+
+struct k3_udma_glue_tx_channel *
+k3_udma_glue_request_tx_chn(struct device *dev, const char *name,
+			    struct k3_udma_glue_tx_channel_cfg *cfg)
+{
+	struct k3_udma_glue_tx_channel *tx_chn;
+	int ret;
+
+	tx_chn = devm_kzalloc(dev, sizeof(*tx_chn), GFP_KERNEL);
+	if (!tx_chn)
+		return ERR_PTR(-ENOMEM);
+
+	tx_chn->common.dev = dev;
+	tx_chn->common.swdata_size = cfg->swdata_size;
+	tx_chn->tx_pause_on_err = cfg->tx_pause_on_err;
+	tx_chn->tx_filt_einfo = cfg->tx_filt_einfo;
+	tx_chn->tx_filt_pswords = cfg->tx_filt_pswords;
+	tx_chn->tx_supr_tdpkt = cfg->tx_supr_tdpkt;
+
+	/* parse of udmap channel */
+	ret = of_k3_udma_glue_parse_chn(dev->of_node, name,
+					&tx_chn->common, true);
+	if (ret)
+		goto err;
+
+	ret = k3_udma_glue_request_tx_chn_common(dev, tx_chn, cfg);
+	if (ret)
+		goto err;
+
 	return tx_chn;
 
 err:
@@ -371,6 +409,40 @@
 }
 EXPORT_SYMBOL_GPL(k3_udma_glue_request_tx_chn);
 
+struct k3_udma_glue_tx_channel *
+k3_udma_glue_request_tx_chn_by_id(struct device *dev, struct k3_udma_glue_tx_channel_cfg *cfg,
+				  struct device_node *udmax_np, u32 thread_id)
+{
+	struct k3_udma_glue_tx_channel *tx_chn;
+	int ret;
+
+	tx_chn = devm_kzalloc(dev, sizeof(*tx_chn), GFP_KERNEL);
+	if (!tx_chn)
+		return ERR_PTR(-ENOMEM);
+
+	tx_chn->common.dev = dev;
+	tx_chn->common.swdata_size = cfg->swdata_size;
+	tx_chn->tx_pause_on_err = cfg->tx_pause_on_err;
+	tx_chn->tx_filt_einfo = cfg->tx_filt_einfo;
+	tx_chn->tx_filt_pswords = cfg->tx_filt_pswords;
+	tx_chn->tx_supr_tdpkt = cfg->tx_supr_tdpkt;
+
+	ret = of_k3_udma_glue_parse_chn_by_id(udmax_np, &tx_chn->common, true, thread_id);
+	if (ret)
+		goto err;
+
+	ret = k3_udma_glue_request_tx_chn_common(dev, tx_chn, cfg);
+	if (ret)
+		goto err;
+
+	return tx_chn;
+
+err:
+	k3_udma_glue_release_tx_chn(tx_chn);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(k3_udma_glue_request_tx_chn_by_id);
+
 void k3_udma_glue_release_tx_chn(struct k3_udma_glue_tx_channel *tx_chn)
 {
 	if (tx_chn->psil_paired) {
@@ -911,19 +983,18 @@
 	}
 	rx_chn->udma_rchan_id = xudma_rchan_get_id(rx_chn->udma_rchanx);
 
-	rx_chn->common.chan_dev.class = &k3_udma_glue_devclass;
-	rx_chn->common.chan_dev.parent = xudma_get_device(rx_chn->common.udmax);
-	dev_set_name(&rx_chn->common.chan_dev, "rchan%d-0x%04x",
-		     rx_chn->udma_rchan_id, rx_chn->common.src_thread);
-	ret = device_register(&rx_chn->common.chan_dev);
-	if (ret) {
-		dev_err(dev, "Channel Device registration failed %d\n", ret);
-		put_device(&rx_chn->common.chan_dev);
-		rx_chn->common.chan_dev.parent = NULL;
-		goto err;
-	}
-
 	if (xudma_is_pktdma(rx_chn->common.udmax)) {
+		rx_chn->common.chan_dev.class = &k3_udma_glue_devclass;
+		rx_chn->common.chan_dev.parent = xudma_get_device(rx_chn->common.udmax);
+		dev_set_name(&rx_chn->common.chan_dev, "rchan%d-0x%04x",
+			     rx_chn->udma_rchan_id, rx_chn->common.src_thread);
+		ret = device_register(&rx_chn->common.chan_dev);
+		if (ret) {
+			dev_err(dev, "Channel Device registration failed %d\n", ret);
+			rx_chn->common.chan_dev.parent = NULL;
+			goto err;
+		}
+
 		/* prepare the channel device as coherent */
 		rx_chn->common.chan_dev.dma_coherent = true;
 		dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev,
@@ -996,12 +1067,59 @@
 	return ERR_PTR(ret);
 }
 
+static int
+k3_udma_glue_request_remote_rx_chn_common(struct k3_udma_glue_rx_channel *rx_chn,
+					  struct k3_udma_glue_rx_channel_cfg *cfg,
+					  struct device *dev)
+{
+	int ret, i;
+
+	rx_chn->common.hdesc_size = cppi5_hdesc_calc_size(rx_chn->common.epib,
+						rx_chn->common.psdata_size,
+						rx_chn->common.swdata_size);
+
+	rx_chn->flows = devm_kcalloc(dev, rx_chn->flow_num,
+				     sizeof(*rx_chn->flows), GFP_KERNEL);
+	if (!rx_chn->flows)
+		return -ENOMEM;
+
+	if (xudma_is_pktdma(rx_chn->common.udmax)) {
+		rx_chn->common.chan_dev.class = &k3_udma_glue_devclass;
+		rx_chn->common.chan_dev.parent = xudma_get_device(rx_chn->common.udmax);
+		dev_set_name(&rx_chn->common.chan_dev, "rchan_remote-0x%04x-0x%02x",
+			     rx_chn->common.src_thread, rx_chn->flow_id_base);
+
+		ret = device_register(&rx_chn->common.chan_dev);
+		if (ret) {
+			dev_err(dev, "Channel Device registration failed %d\n", ret);
+			rx_chn->common.chan_dev.parent = NULL;
+			return ret;
+		}
+
+		/* prepare the channel device as coherent */
+		rx_chn->common.chan_dev.dma_coherent = true;
+		dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev,
+					     DMA_BIT_MASK(48));
+	}
+
+	ret = k3_udma_glue_allocate_rx_flows(rx_chn, cfg);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < rx_chn->flow_num; i++)
+		rx_chn->flows[i].udma_rflow_id = rx_chn->flow_id_base + i;
+
+	k3_udma_glue_dump_rx_chn(rx_chn);
+
+	return 0;
+}
+
 static struct k3_udma_glue_rx_channel *
 k3_udma_glue_request_remote_rx_chn(struct device *dev, const char *name,
 				   struct k3_udma_glue_rx_channel_cfg *cfg)
 {
 	struct k3_udma_glue_rx_channel *rx_chn;
-	int ret, i;
+	int ret;
 
 	if (cfg->flow_id_num <= 0 ||
 	    cfg->flow_id_use_rxchan_id ||
@@ -1032,44 +1150,54 @@
 	if (ret)
 		goto err;
 
-	rx_chn->common.hdesc_size = cppi5_hdesc_calc_size(rx_chn->common.epib,
-						rx_chn->common.psdata_size,
-						rx_chn->common.swdata_size);
-
-	rx_chn->flows = devm_kcalloc(dev, rx_chn->flow_num,
-				     sizeof(*rx_chn->flows), GFP_KERNEL);
-	if (!rx_chn->flows) {
-		ret = -ENOMEM;
+	ret = k3_udma_glue_request_remote_rx_chn_common(rx_chn, cfg, dev);
+	if (ret)
 		goto err;
-	}
 
-	rx_chn->common.chan_dev.class = &k3_udma_glue_devclass;
-	rx_chn->common.chan_dev.parent = xudma_get_device(rx_chn->common.udmax);
-	dev_set_name(&rx_chn->common.chan_dev, "rchan_remote-0x%04x",
-		     rx_chn->common.src_thread);
-	ret = device_register(&rx_chn->common.chan_dev);
-	if (ret) {
-		dev_err(dev, "Channel Device registration failed %d\n", ret);
-		put_device(&rx_chn->common.chan_dev);
-		rx_chn->common.chan_dev.parent = NULL;
-		goto err;
-	}
+	return rx_chn;
 
-	if (xudma_is_pktdma(rx_chn->common.udmax)) {
-		/* prepare the channel device as coherent */
-		rx_chn->common.chan_dev.dma_coherent = true;
-		dma_coerce_mask_and_coherent(&rx_chn->common.chan_dev,
-					     DMA_BIT_MASK(48));
-	}
+err:
+	k3_udma_glue_release_rx_chn(rx_chn);
+	return ERR_PTR(ret);
+}
 
-	ret = k3_udma_glue_allocate_rx_flows(rx_chn, cfg);
+struct k3_udma_glue_rx_channel *
+k3_udma_glue_request_remote_rx_chn_by_id(struct device *dev, struct device_node *udmax_np,
+					 struct k3_udma_glue_rx_channel_cfg *cfg, u32 thread_id)
+{
+	struct k3_udma_glue_rx_channel *rx_chn;
+	int ret;
+
+	if (cfg->flow_id_num <= 0 ||
+	    cfg->flow_id_use_rxchan_id ||
+	    cfg->def_flow_cfg ||
+	    cfg->flow_id_base < 0)
+		return ERR_PTR(-EINVAL);
+
+	/*
+	 * Remote RX channel is under control of Remote CPU core, so
+	 * Linux can only request and manipulate by dedicated RX flows
+	 */
+
+	rx_chn = devm_kzalloc(dev, sizeof(*rx_chn), GFP_KERNEL);
+	if (!rx_chn)
+		return ERR_PTR(-ENOMEM);
+
+	rx_chn->common.dev = dev;
+	rx_chn->common.swdata_size = cfg->swdata_size;
+	rx_chn->remote = true;
+	rx_chn->udma_rchan_id = -1;
+	rx_chn->flow_num = cfg->flow_id_num;
+	rx_chn->flow_id_base = cfg->flow_id_base;
+	rx_chn->psil_paired = false;
+
+	ret = of_k3_udma_glue_parse_chn_by_id(udmax_np, &rx_chn->common, false, thread_id);
 	if (ret)
 		goto err;
 
-	for (i = 0; i < rx_chn->flow_num; i++)
-		rx_chn->flows[i].udma_rflow_id = rx_chn->flow_id_base + i;
-
-	k3_udma_glue_dump_rx_chn(rx_chn);
+	ret = k3_udma_glue_request_remote_rx_chn_common(rx_chn, cfg, dev);
+	if (ret)
+		goto err;
 
 	return rx_chn;
 
@@ -1077,6 +1205,7 @@
 	k3_udma_glue_release_rx_chn(rx_chn);
 	return ERR_PTR(ret);
 }
+EXPORT_SYMBOL_GPL(k3_udma_glue_request_remote_rx_chn_by_id);
 
 struct k3_udma_glue_rx_channel *
 k3_udma_glue_request_rx_chn(struct device *dev, const char *name,
@@ -1436,4 +1565,6 @@
 {
 	return class_register(&k3_udma_glue_devclass);
 }
-arch_initcall(k3_udma_glue_class_init);
+
+module_init(k3_udma_glue_class_init);
+MODULE_LICENSE("GPL v2");
diff -Naur --no-dereference a/drivers/dma/ti/Kconfig b/drivers/dma/ti/Kconfig
--- a/drivers/dma/ti/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/dma/ti/Kconfig	2024-01-28 14:01:31.240353775 -0500
@@ -35,7 +35,7 @@
 	  DMA engine is found on OMAP and DRA7xx parts.
 
 config TI_K3_UDMA
-	bool "Texas Instruments UDMA support"
+	tristate "Texas Instruments UDMA support"
 	depends on ARCH_K3
 	depends on TI_SCI_PROTOCOL
 	depends on TI_SCI_INTA_IRQCHIP
@@ -48,7 +48,7 @@
 	  DMA engine is used in AM65x and j721e.
 
 config TI_K3_UDMA_GLUE_LAYER
-	bool "Texas Instruments UDMA Glue layer for non DMAengine users"
+	tristate "Texas Instruments UDMA Glue layer for non DMAengine users"
 	depends on ARCH_K3
 	depends on TI_K3_UDMA
 	help
@@ -56,7 +56,8 @@
 	  If unsure, say N.
 
 config TI_K3_PSIL
-	bool
+       tristate
+       default TI_K3_UDMA
 
 config TI_DMA_CROSSBAR
 	bool
diff -Naur --no-dereference a/drivers/dma/ti/Makefile b/drivers/dma/ti/Makefile
--- a/drivers/dma/ti/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/dma/ti/Makefile	2024-01-28 14:01:31.240353775 -0500
@@ -4,11 +4,15 @@
 obj-$(CONFIG_DMA_OMAP) += omap-dma.o
 obj-$(CONFIG_TI_K3_UDMA) += k3-udma.o
 obj-$(CONFIG_TI_K3_UDMA_GLUE_LAYER) += k3-udma-glue.o
-obj-$(CONFIG_TI_K3_PSIL) += k3-psil.o \
-			    k3-psil-am654.o \
-			    k3-psil-j721e.o \
-			    k3-psil-j7200.o \
-			    k3-psil-am64.o \
-			    k3-psil-j721s2.o \
-			    k3-psil-am62.o
+k3-psil-lib-objs := k3-psil.o \
+		    k3-psil-am654.o \
+		    k3-psil-j721e.o \
+		    k3-psil-j7200.o \
+		    k3-psil-am64.o \
+		    k3-psil-j721s2.o \
+		    k3-psil-am62.o \
+		    k3-psil-am62a.o \
+		    k3-psil-j784s4.o \
+		    k3-psil-am62p.o
+obj-$(CONFIG_TI_K3_PSIL) += k3-psil-lib.o
 obj-$(CONFIG_TI_DMA_CROSSBAR) += dma-crossbar.o
diff -Naur --no-dereference a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c
--- a/drivers/dma-buf/dma-heap.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/dma-buf/dma-heap.c	2024-01-28 14:01:31.240353775 -0500
@@ -323,4 +323,4 @@
 
 	return 0;
 }
-subsys_initcall(dma_heap_init);
+core_initcall(dma_heap_init);
diff -Naur --no-dereference a/drivers/dma-buf/heaps/carveout-heap.c b/drivers/dma-buf/heaps/carveout-heap.c
--- a/drivers/dma-buf/heaps/carveout-heap.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/dma-buf/heaps/carveout-heap.c	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,411 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Carveout DMA-Heap userspace exporter
+ *
+ * Copyright (C) 2019-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *	Andrew Davis <afd@ti.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/genalloc.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/highmem.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-heap.h>
+
+struct carveout_dma_heap {
+	struct dma_heap *heap;
+	struct gen_pool *pool;
+	bool cached;
+};
+
+struct carveout_dma_heap_buffer {
+	struct gen_pool *pool;
+	struct list_head attachments;
+	struct mutex attachments_lock;
+	struct mutex vmap_lock;
+	int vmap_cnt;
+	unsigned long len;
+	void *vaddr;
+	phys_addr_t paddr;
+	bool cached;
+};
+
+struct dma_heap_attachment {
+	struct device *dev;
+	struct sg_table *table;
+	struct list_head list;
+};
+
+static int dma_heap_attach(struct dma_buf *dmabuf,
+			   struct dma_buf_attachment *attachment)
+{
+	struct carveout_dma_heap_buffer *buffer = dmabuf->priv;
+	struct dma_heap_attachment *a;
+	struct sg_table *table;
+
+	a = kzalloc(sizeof(*a), GFP_KERNEL);
+	if (!a)
+		return -ENOMEM;
+
+	table = kmalloc(sizeof(*table), GFP_KERNEL);
+	if (!table) {
+		kfree(a);
+		return -ENOMEM;
+	}
+	if (sg_alloc_table(table, 1, GFP_KERNEL)) {
+		kfree(a);
+		return -ENOMEM;
+	}
+	sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(buffer->paddr)), buffer->len, 0);
+
+	a->table = table;
+	a->dev = attachment->dev;
+	INIT_LIST_HEAD(&a->list);
+
+	attachment->priv = a;
+
+	mutex_lock(&buffer->attachments_lock);
+	list_add(&a->list, &buffer->attachments);
+	mutex_unlock(&buffer->attachments_lock);
+
+	return 0;
+}
+
+static void dma_heap_detatch(struct dma_buf *dmabuf,
+			     struct dma_buf_attachment *attachment)
+{
+	struct carveout_dma_heap_buffer *buffer = dmabuf->priv;
+	struct dma_heap_attachment *a = attachment->priv;
+
+	mutex_lock(&buffer->attachments_lock);
+	list_del(&a->list);
+	mutex_unlock(&buffer->attachments_lock);
+
+	sg_free_table(a->table);
+	kfree(a->table);
+	kfree(a);
+}
+
+static struct sg_table *dma_heap_map_dma_buf(struct dma_buf_attachment *attachment,
+					     enum dma_data_direction direction)
+{
+	struct carveout_dma_heap_buffer *buffer = attachment->dmabuf->priv;
+	struct dma_heap_attachment *a = attachment->priv;
+	struct sg_table *table = a->table;
+
+	unsigned long attrs = buffer->cached ? 0 : DMA_ATTR_SKIP_CPU_SYNC;
+
+	if (!dma_map_sg_attrs(attachment->dev, table->sgl, table->nents,
+			      direction, attrs))
+		return ERR_PTR(-ENOMEM);
+
+	return table;
+}
+
+static void dma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
+				   struct sg_table *table,
+				   enum dma_data_direction direction)
+{
+	struct carveout_dma_heap_buffer *buffer = attachment->dmabuf->priv;
+	unsigned long attrs = buffer->cached ? 0 : DMA_ATTR_SKIP_CPU_SYNC;
+
+	dma_unmap_sg_attrs(attachment->dev, table->sgl, table->nents,
+			   direction, attrs);
+}
+
+static void dma_heap_dma_buf_release(struct dma_buf *dmabuf)
+{
+	struct carveout_dma_heap_buffer *buffer = dmabuf->priv;
+
+	if (buffer->vmap_cnt > 0) {
+		WARN(1, "%s: buffer still mapped in the kernel\n", __func__);
+		memunmap(buffer->vaddr);
+	}
+
+	gen_pool_free(buffer->pool, buffer->paddr, buffer->len);
+	kfree(buffer);
+}
+
+static int dma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
+					     enum dma_data_direction direction)
+{
+	struct carveout_dma_heap_buffer *buffer = dmabuf->priv;
+	struct dma_heap_attachment *a;
+
+	if (!buffer->cached)
+		return 0;
+
+	mutex_lock(&buffer->vmap_lock);
+	if (buffer->vmap_cnt)
+		invalidate_kernel_vmap_range(buffer->vaddr, buffer->len);
+	mutex_unlock(&buffer->vmap_lock);
+
+	mutex_lock(&buffer->attachments_lock);
+	list_for_each_entry(a, &buffer->attachments, list) {
+		dma_sync_sg_for_cpu(a->dev, a->table->sgl, a->table->nents,
+				    direction);
+	}
+	mutex_unlock(&buffer->attachments_lock);
+
+	return 0;
+}
+
+static int dma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf,
+					   enum dma_data_direction direction)
+{
+	struct carveout_dma_heap_buffer *buffer = dmabuf->priv;
+	struct dma_heap_attachment *a;
+
+	if (!buffer->cached)
+		return 0;
+
+	mutex_lock(&buffer->vmap_lock);
+	if (buffer->vmap_cnt)
+		flush_kernel_vmap_range(buffer->vaddr, buffer->len);
+	mutex_unlock(&buffer->vmap_lock);
+
+	mutex_lock(&buffer->attachments_lock);
+	list_for_each_entry(a, &buffer->attachments, list) {
+		dma_sync_sg_for_device(a->dev, a->table->sgl, a->table->nents,
+				       direction);
+	}
+	mutex_unlock(&buffer->attachments_lock);
+
+	return 0;
+}
+
+static int dma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+{
+	struct carveout_dma_heap_buffer *buffer = dmabuf->priv;
+	int ret;
+
+	if (!buffer->cached)
+		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+	ret = vm_iomap_memory(vma, buffer->paddr, buffer->len);
+	if (ret)
+		pr_err("Could not map buffer to userspace\n");
+
+	return ret;
+}
+
+static int dma_heap_vmap(struct dma_buf *dmabuf, struct iosys_map *map)
+{
+	struct carveout_dma_heap_buffer *buffer = dmabuf->priv;
+	void *vaddr;
+	int ret = 0;
+
+	mutex_lock(&buffer->vmap_lock);
+
+	if (buffer->vmap_cnt) {
+		buffer->vmap_cnt++;
+		iosys_map_set_vaddr(map, buffer->vaddr);
+		goto exit;
+	}
+	if (buffer->cached)
+		vaddr = memremap(buffer->paddr, buffer->len, MEMREMAP_WB);
+	else
+		vaddr = memremap(buffer->paddr, buffer->len, MEMREMAP_WC);
+	if (!vaddr) {
+		pr_err("Could not memremap buffer\n");
+		ret = -ENOMEM;
+		goto exit;
+	}
+	if (IS_ERR(vaddr)) {
+		ret = PTR_ERR(vaddr);
+		goto exit;
+	}
+
+	buffer->vaddr = vaddr;
+	buffer->vmap_cnt++;
+	iosys_map_set_vaddr(map, buffer->vaddr);
+exit:
+	mutex_unlock(&buffer->vmap_lock);
+
+	return ret;
+}
+
+static void dma_heap_vunmap(struct dma_buf *dmabuf, struct iosys_map *map)
+{
+	struct carveout_dma_heap_buffer *buffer = dmabuf->priv;
+
+	mutex_lock(&buffer->vmap_lock);
+	if (!--buffer->vmap_cnt) {
+		memunmap(buffer->vaddr);
+		buffer->vaddr = NULL;
+	}
+	mutex_unlock(&buffer->vmap_lock);
+}
+
+static const struct dma_buf_ops carveout_dma_heap_buf_ops = {
+	.attach = dma_heap_attach,
+	.detach = dma_heap_detatch,
+	.map_dma_buf = dma_heap_map_dma_buf,
+	.unmap_dma_buf = dma_heap_unmap_dma_buf,
+	.release = dma_heap_dma_buf_release,
+	.begin_cpu_access = dma_heap_dma_buf_begin_cpu_access,
+	.end_cpu_access = dma_heap_dma_buf_end_cpu_access,
+	.mmap = dma_heap_mmap,
+	.vmap = dma_heap_vmap,
+	.vunmap = dma_heap_vunmap,
+};
+
+static struct dma_buf *carveout_dma_heap_allocate(struct dma_heap *heap,
+						  unsigned long len,
+						  unsigned long fd_flags,
+						  unsigned long heap_flags)
+{
+	struct carveout_dma_heap *carveout_dma_heap = dma_heap_get_drvdata(heap);
+	struct carveout_dma_heap_buffer *buffer;
+
+	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+	struct dma_buf *dmabuf;
+	int ret = 0;
+
+	buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+	if (!buffer)
+		return ERR_PTR(ret);
+	buffer->pool = carveout_dma_heap->pool;
+	buffer->cached = carveout_dma_heap->cached;
+	INIT_LIST_HEAD(&buffer->attachments);
+	mutex_init(&buffer->attachments_lock);
+	mutex_init(&buffer->vmap_lock);
+	buffer->len = len;
+
+	buffer->paddr = gen_pool_alloc(buffer->pool, buffer->len);
+	if (!buffer->paddr) {
+		ret = -ENOMEM;
+		goto free_buffer;
+	}
+
+	/* create the dmabuf */
+	exp_info.exp_name = dma_heap_get_name(heap);
+	exp_info.ops = &carveout_dma_heap_buf_ops;
+	exp_info.size = buffer->len;
+	exp_info.flags = fd_flags;
+	exp_info.priv = buffer;
+	dmabuf = dma_buf_export(&exp_info);
+	if (IS_ERR(dmabuf)) {
+		ret = PTR_ERR(dmabuf);
+		goto free_pool;
+	}
+
+	return dmabuf;
+
+free_pool:
+	gen_pool_free(buffer->pool, buffer->paddr, buffer->len);
+free_buffer:
+	kfree(buffer);
+
+	return ERR_PTR(ret);
+}
+
+static struct dma_heap_ops carveout_dma_heap_ops = {
+	.allocate = carveout_dma_heap_allocate,
+};
+
+static int carveout_dma_heap_export(phys_addr_t base, size_t size, const char *name, bool cached)
+{
+	struct carveout_dma_heap *carveout_dma_heap;
+	struct dma_heap_export_info exp_info;
+	int ret;
+
+	carveout_dma_heap = kzalloc(sizeof(*carveout_dma_heap), GFP_KERNEL);
+	if (!carveout_dma_heap)
+		return -ENOMEM;
+
+	carveout_dma_heap->pool = gen_pool_create(PAGE_SHIFT, NUMA_NO_NODE);
+	if (IS_ERR(carveout_dma_heap->pool)) {
+		pr_err("Carveout Heap: Could not create memory pool\n");
+		ret = PTR_ERR(carveout_dma_heap->pool);
+		goto free_carveout_dma_heap;
+	}
+	ret = gen_pool_add(carveout_dma_heap->pool, base, size, NUMA_NO_NODE);
+	if (ret) {
+		pr_err("Carveout Heap: Could not add memory to pool\n");
+		goto free_pool;
+	}
+
+	carveout_dma_heap->cached = cached;
+
+	exp_info.name = kasprintf(GFP_KERNEL, "carveout_%s", name);
+	exp_info.ops = &carveout_dma_heap_ops;
+	exp_info.priv = carveout_dma_heap;
+	carveout_dma_heap->heap = dma_heap_add(&exp_info);
+	if (IS_ERR(carveout_dma_heap->heap)) {
+		pr_err("Carveout Heap: Could not add DMA-Heap\n");
+		ret = PTR_ERR(carveout_dma_heap->heap);
+		goto free_pool;
+	}
+
+	pr_info("Carveout Heap: Exported %zu MiB at %pa\n", size / SZ_1M, &base);
+
+	return 0;
+
+free_pool:
+	gen_pool_destroy(carveout_dma_heap->pool);
+free_carveout_dma_heap:
+	kfree(carveout_dma_heap);
+	return ret;
+}
+
+#ifdef CONFIG_OF_RESERVED_MEM
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_reserved_mem.h>
+
+#define MAX_HEAP_AREAS 7
+struct reserved_mem heap_areas[MAX_HEAP_AREAS];
+size_t heap_area_count;
+
+static int __init carveout_dma_heap_init_areas(void)
+{
+	int i;
+
+	for (i = 0; i < heap_area_count; i++) {
+		struct reserved_mem *rmem = &heap_areas[i];
+		bool cached = !of_get_flat_dt_prop(rmem->fdt_node, "no-map", NULL);
+		int ret = carveout_dma_heap_export(rmem->base, rmem->size, rmem->name, cached);
+		if (ret) {
+			pr_err("Carveout Heap: could not export as DMA-Heap\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+fs_initcall(carveout_dma_heap_init_areas);
+
+static int __init rmem_dma_heap_carveout_setup(struct reserved_mem *rmem)
+{
+	phys_addr_t align = PAGE_SIZE;
+	phys_addr_t mask = align - 1;
+
+	if ((rmem->base & mask) || (rmem->size & mask)) {
+		pr_err("Carveout Heap: incorrect alignment of region\n");
+		return -EINVAL;
+	}
+
+	/* Sanity check */
+	if (heap_area_count == ARRAY_SIZE(heap_areas)) {
+		pr_err("Not enough slots for DMA-Heap reserved regions!\n");
+		return -ENOSPC;
+	}
+
+	/*
+	 * Each reserved area must be initialized later, when more kernel
+	 * subsystems (like slab allocator) are available.
+	 */
+	heap_areas[heap_area_count] = *rmem;
+	heap_area_count++;
+
+	return 0;
+}
+RESERVEDMEM_OF_DECLARE(dma_heap_carveout, "dma-heap-carveout", rmem_dma_heap_carveout_setup);
+
+#endif
diff -Naur --no-dereference a/drivers/dma-buf/heaps/Kconfig b/drivers/dma-buf/heaps/Kconfig
--- a/drivers/dma-buf/heaps/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/dma-buf/heaps/Kconfig	2024-01-28 14:01:31.240353775 -0500
@@ -12,3 +12,13 @@
 	  Choose this option to enable dma-buf CMA heap. This heap is backed
 	  by the Contiguous Memory Allocator (CMA). If your system has these
 	  regions, you should say Y here.
+
+config DMABUF_HEAPS_CARVEOUT
+	bool "DMA-BUF Carveout Heap"
+	depends on DMABUF_HEAPS && HAS_IOMEM
+	depends on OF_RESERVED_MEM
+	select GENERIC_ALLOCATOR
+	help
+	  Choose this option to enable dma-buf Carveout heap. This heap is
+	  backed by the a carved-out of memory. If your system has these
+	  regions, you should say Y here.
diff -Naur --no-dereference a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile
--- a/drivers/dma-buf/heaps/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/dma-buf/heaps/Makefile	2024-01-28 14:01:31.240353775 -0500
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_DMABUF_HEAPS_SYSTEM)	+= system_heap.o
 obj-$(CONFIG_DMABUF_HEAPS_CMA)		+= cma_heap.o
+obj-$(CONFIG_DMABUF_HEAPS_CARVEOUT)	+= carveout-heap.o
diff -Naur --no-dereference a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
--- a/drivers/firmware/ti_sci.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/firmware/ti_sci.c	2024-01-28 14:01:31.240353775 -0500
@@ -10,7 +10,9 @@
 
 #include <linux/bitmap.h>
 #include <linux/debugfs.h>
+#include <linux/dma-mapping.h>
 #include <linux/export.h>
+#include <linux/firmware.h>
 #include <linux/io.h>
 #include <linux/iopoll.h>
 #include <linux/kernel.h>
@@ -21,10 +23,16 @@
 #include <linux/slab.h>
 #include <linux/soc/ti/ti-msgmgr.h>
 #include <linux/soc/ti/ti_sci_protocol.h>
+#include <linux/suspend.h>
 #include <linux/reboot.h>
 
 #include "ti_sci.h"
 
+/* Low power mode memory context size */
+#define LPM_CTX_MEM_SIZE 0x80000
+
+#define AM62X_DEV_MCU_M4FSS0_CORE0_DEV_ID 9
+
 /* List of all TI SCI devices active in system */
 static LIST_HEAD(ti_sci_list);
 /* Protection for the entire list */
@@ -96,6 +104,9 @@
  * @minfo:	Message info
  * @node:	list head
  * @host_id:	Host ID
+ * @ctx_mem_addr: Low power context memory phys address
+ * @ctx_mem_buf: Low power context memory buffer
+ * @fw_caps:	FW/SoC low power capabilities
  * @users:	Number of users of this instance
  */
 struct ti_sci_info {
@@ -113,8 +124,14 @@
 	struct ti_sci_xfers_info minfo;
 	struct list_head node;
 	u8 host_id;
+	dma_addr_t ctx_mem_addr;
+	void *ctx_mem_buf;
+	u64 fw_caps;
 	/* protected by ti_sci_list_mutex */
 	int users;
+
+	int nr_wakeup_sources;
+	struct device_node **wakeup_source_nodes;
 };
 
 #define cl_to_ti_sci_info(c)	container_of(c, struct ti_sci_info, cl)
@@ -381,6 +398,28 @@
 }
 
 /**
+ * ti_sci_do_send() - Do one send, do not expect a response
+ * @info:	Pointer to SCI entity information
+ * @xfer:	Transfer to initiate
+ *
+ * Return: If send error, return corresponding error, else
+ *	   if all goes well, return 0.
+ */
+static inline int ti_sci_do_send(struct ti_sci_info *info,
+				 struct ti_sci_xfer *xfer)
+{
+	int ret;
+
+	ret = mbox_send_message(info->chan_tx, &xfer->tx_message);
+	if (ret < 0)
+		return ret;
+
+	mbox_client_txdone(info->chan_tx, ret);
+
+	return 0;
+}
+
+/**
  * ti_sci_do_xfer() - Do one transfer
  * @info:	Pointer to SCI entity information
  * @xfer:	Transfer to initiate and wait for response
@@ -1651,6 +1690,232 @@
 	return ret;
 }
 
+/**
+ * ti_sci_cmd_prepare_sleep() - Prepare system for system suspend
+ * @handle:		pointer to TI SCI handle
+ * @mode:		Device identifier
+ * @ctx_lo:		Low part of address for context save
+ * @ctx_hi:		High part of address for context save
+ * @debug_flags:	Debug flags to pass to firmware
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_prepare_sleep(const struct ti_sci_handle *handle, u8 mode,
+				    u32 ctx_lo, u32 ctx_hi, u32 debug_flags)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_prepare_sleep *req;
+	struct ti_sci_msg_hdr *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PREPARE_SLEEP,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+
+	req = (struct ti_sci_msg_req_prepare_sleep *)xfer->xfer_buf;
+	req->mode = mode;
+	req->ctx_lo = ctx_lo;
+	req->ctx_hi = ctx_hi;
+	req->debug_flags = debug_flags;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
+
+	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_msg_cmd_query_fw_caps() - Get the FW/SoC capabilities
+ * @handle:		Pointer to TI SCI handle
+ * @fw_caps:		Each bit in fw_caps indicating one FW/SOC capability
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_msg_cmd_query_fw_caps(const struct ti_sci_handle *handle,
+					u64 *fw_caps)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_xfer *xfer;
+	struct ti_sci_msg_resp_query_fw_caps *resp;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_QUERY_FW_CAPS,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(struct ti_sci_msg_hdr),
+				   sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_resp_query_fw_caps *)xfer->xfer_buf;
+
+	if (!ti_sci_is_response_ack(resp)) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	if (fw_caps)
+		*fw_caps = resp->fw_caps;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_msg_cmd_lpm_wake_reason() - Get the wakeup source from LPM
+ * @handle:		Pointer to TI SCI handle
+ * @source:		The wakeup source that woke the SoC from LPM
+ * @timestamp:		Timestamp of the wakeup event
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_msg_cmd_lpm_wake_reason(const struct ti_sci_handle *handle,
+					  u32 *source, u64 *timestamp)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_xfer *xfer;
+	struct ti_sci_msg_resp_lpm_wake_reason *resp;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_LPM_WAKE_REASON,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(struct ti_sci_msg_hdr),
+				   sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_resp_lpm_wake_reason *)xfer->xfer_buf;
+
+	if (!ti_sci_is_response_ack(resp)) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	if (source)
+		*source = resp->wake_source;
+	if (timestamp)
+		*timestamp = resp->wake_timestamp;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+/**
+ * ti_sci_cmd_set_io_isolation() - Enable IO isolation in LPM
+ * @handle:		Pointer to TI SCI handle
+ * @state:		The desired state of the IO isolation
+ *
+ * Return: 0 if all went well, else returns appropriate error value.
+ */
+static int ti_sci_cmd_set_io_isolation(const struct ti_sci_handle *handle,
+				       u8 state)
+{
+	struct ti_sci_info *info;
+	struct ti_sci_msg_req_set_io_isolation *req;
+	struct ti_sci_msg_hdr *resp;
+	struct ti_sci_xfer *xfer;
+	struct device *dev;
+	int ret = 0;
+
+	if (IS_ERR(handle))
+		return PTR_ERR(handle);
+	if (!handle)
+		return -EINVAL;
+
+	info = handle_to_ti_sci_info(handle);
+	dev = info->dev;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_IO_ISOLATION,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(*resp));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+	req = (struct ti_sci_msg_req_set_io_isolation *)xfer->xfer_buf;
+	req->state = state;
+
+	ret = ti_sci_do_xfer(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+	resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf;
+
+	ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV;
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
 static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
 {
 	struct ti_sci_info *info;
@@ -2792,6 +3057,7 @@
 	struct ti_sci_core_ops *core_ops = &ops->core_ops;
 	struct ti_sci_dev_ops *dops = &ops->dev_ops;
 	struct ti_sci_clk_ops *cops = &ops->clk_ops;
+	struct ti_sci_pm_ops *pmops = &ops->pm_ops;
 	struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops;
 	struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops;
 	struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops;
@@ -2831,6 +3097,10 @@
 	cops->set_freq = ti_sci_cmd_clk_set_freq;
 	cops->get_freq = ti_sci_cmd_clk_get_freq;
 
+	pmops->prepare_sleep = ti_sci_cmd_prepare_sleep;
+	pmops->lpm_wake_reason = ti_sci_msg_cmd_lpm_wake_reason;
+	pmops->set_io_isolation = ti_sci_cmd_set_io_isolation;
+
 	rm_core_ops->get_range = ti_sci_cmd_get_resource_range;
 	rm_core_ops->get_range_from_shost =
 				ti_sci_cmd_get_resource_range_from_shost;
@@ -3267,6 +3537,180 @@
 	return NOTIFY_BAD;
 }
 
+static int ti_sci_prepare_system_suspend(struct ti_sci_info *info)
+{
+#if IS_ENABLED(CONFIG_SUSPEND)
+	u8 mode, unused;
+	u8 mcu_state = 0;
+
+	/*
+	 * Dev ID 9 is AM62X_DEV_MCU_M4FSS0_CORE0. Check state to determine
+	 * MCU only or deep sleep mode
+	 */
+	ti_sci_get_device_state(&info->handle, AM62X_DEV_MCU_M4FSS0_CORE0_DEV_ID,
+				NULL, NULL, &mcu_state, &unused);
+
+	/* Map and validate the target Linux suspend state to TISCI LPM. */
+	switch (pm_suspend_target_state) {
+	case PM_SUSPEND_MEM:
+		/* S2MEM is not supported by the firmware. */
+		if (!(info->fw_caps & MSG_FLAG_CAPS_LPM_DEEP_SLEEP))
+			return 0;
+
+		mode = mcu_state ? TISCI_MSG_VALUE_SLEEP_MODE_MCU_ONLY
+			: TISCI_MSG_VALUE_SLEEP_MODE_DEEP_SLEEP;
+
+		break;
+	default:
+		/*
+		 * Do not fail if we don't have action to take for a
+		 * specific suspend mode.
+		 */
+		return 0;
+	}
+
+	return ti_sci_cmd_prepare_sleep(&info->handle, mode,
+					(u32)(info->ctx_mem_addr & 0xffffffff),
+					(u32)((u64)info->ctx_mem_addr >> 32), 0);
+#else
+	return 0;
+#endif
+}
+
+static int ti_sci_suspend(struct device *dev)
+{
+	struct ti_sci_info *info = dev_get_drvdata(dev);
+	int ret;
+
+	ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_ENABLE);
+	if (ret)
+		return ret;
+	dev_dbg(dev, "%s: set isolation: %d\n", __func__, ret);
+
+	ret = ti_sci_prepare_system_suspend(info);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int ti_sci_resume(struct device *dev)
+{
+	struct ti_sci_info *info = dev_get_drvdata(dev);
+	u32 source;
+	u64 time;
+	int ret = 0;
+
+	ret = ti_sci_cmd_set_io_isolation(&info->handle, TISCI_MSG_VALUE_IO_DISABLE);
+	if (ret)
+		return ret;
+	dev_dbg(dev, "%s: disable isolation: %d\n", __func__, ret);
+
+	ti_sci_msg_cmd_lpm_wake_reason(&info->handle, &source, &time);
+	dev_info(dev, "%s: wakeup source: 0x%X\n", __func__, source);
+
+	return 0;
+}
+
+static const struct dev_pm_ops ti_sci_pm_ops = {
+	.suspend_noirq = ti_sci_suspend,
+	.resume_noirq = ti_sci_resume,
+};
+
+/* Does not return if successful */
+static int tisci_enter_partial_io(struct ti_sci_info *info)
+{
+	struct ti_sci_msg_req_prepare_sleep *req;
+	struct ti_sci_xfer *xfer;
+	struct device *dev = info->dev;
+	u32 ctx_lo = (u32)(info->ctx_mem_addr & 0xffffffff);
+	u32 ctx_hi = (u32)((u64)info->ctx_mem_addr >> 32);
+	int ret = 0;
+
+	xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PREPARE_SLEEP,
+				   TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+				   sizeof(*req), sizeof(struct ti_sci_msg_hdr));
+	if (IS_ERR(xfer)) {
+		ret = PTR_ERR(xfer);
+		dev_err(dev, "Message alloc failed(%d)\n", ret);
+		return ret;
+	}
+
+	req = (struct ti_sci_msg_req_prepare_sleep *)xfer->xfer_buf;
+	req->mode = TISCI_MSG_VALUE_SLEEP_MODE_PARTIAL_IO;
+	req->ctx_lo = ctx_lo;
+	req->ctx_hi = ctx_hi;
+	req->debug_flags = 0;
+
+	ret = ti_sci_do_send(info, xfer);
+	if (ret) {
+		dev_err(dev, "Mbox send fail %d\n", ret);
+		goto fail;
+	}
+
+fail:
+	ti_sci_put_one_xfer(&info->minfo, xfer);
+
+	return ret;
+}
+
+static int tisci_sys_off_handler(struct sys_off_data *data)
+{
+	struct ti_sci_info *info = data->cb_data;
+	int i;
+	int ret;
+	bool enter_partial_io = false;
+
+	for (i = 0; i != info->nr_wakeup_sources; ++i) {
+		struct platform_device *pdev =
+			of_find_device_by_node(info->wakeup_source_nodes[i]);
+
+		if (!pdev)
+			continue;
+
+		if (device_may_wakeup(&pdev->dev)) {
+			dev_dbg(info->dev, "%pOFp identified as wakeup source\n",
+				info->wakeup_source_nodes[i]);
+			enter_partial_io = true;
+		}
+	}
+
+	if (!enter_partial_io)
+		return NOTIFY_DONE;
+
+	ret = tisci_enter_partial_io(info);
+
+	if (ret)
+		dev_err(info->dev,
+			"Failed to enter Partial-IO %pe, halting system\n",
+			ERR_PTR(ret));
+
+	/* Halt system/code execution */
+	while (1)
+		;
+
+	return NOTIFY_DONE;
+}
+
+static int ti_sci_init_suspend(struct platform_device *pdev,
+			       struct ti_sci_info *info)
+{
+	struct device *dev = &pdev->dev;
+
+	dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
+	info->ctx_mem_buf = dma_alloc_attrs(info->dev, LPM_CTX_MEM_SIZE,
+					    &info->ctx_mem_addr,
+					    GFP_KERNEL,
+					    DMA_ATTR_NO_KERNEL_MAPPING |
+					    DMA_ATTR_FORCE_CONTIGUOUS);
+	if (!info->ctx_mem_buf) {
+		dev_err(info->dev, "Failed to allocate LPM context memory\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
 /* Description for K2G */
 static const struct ti_sci_desc ti_sci_pmmc_k2g_desc = {
 	.default_host_id = 2,
@@ -3419,6 +3863,44 @@
 		}
 	}
 
+	if (of_property_read_bool(dev->of_node, "ti,partial-io-wakeup-sources")) {
+		info->nr_wakeup_sources =
+			of_count_phandle_with_args(dev->of_node,
+						   "ti,partial-io-wakeup-sources",
+						   NULL);
+		info->wakeup_source_nodes =
+			devm_kzalloc(dev, sizeof(*info->wakeup_source_nodes),
+				     GFP_KERNEL);
+
+		for (i = 0; i != info->nr_wakeup_sources; ++i) {
+			struct device_node *devnode =
+				of_parse_phandle(dev->of_node,
+						 "ti,partial-io-wakeup-sources",
+						 i);
+			info->wakeup_source_nodes[i] = devnode;
+		}
+
+		ret = devm_register_sys_off_handler(dev,
+						    SYS_OFF_MODE_POWER_OFF,
+						    SYS_OFF_PRIO_FIRMWARE,
+						    tisci_sys_off_handler,
+						    info);
+		if (ret) {
+			dev_err(dev, "Failed to register sys_off_handler %pe\n",
+				ERR_PTR(ret));
+			goto unregister_restart;
+		}
+	}
+
+	/*
+	 * Check if the firmware supports any optional low power modes
+	 * and initialize them if present. Old revisions of TIFS (< 08.04)
+	 * will NACK the request.
+	 */
+	ret = ti_sci_msg_cmd_query_fw_caps(&info->handle, &info->fw_caps);
+	if (!ret && (info->fw_caps & MSG_MASK_CAPS_LPM))
+		ti_sci_init_suspend(pdev, info);
+
 	dev_info(dev, "ABI: %d.%d (firmware rev 0x%04x '%s')\n",
 		 info->handle.version.abi_major, info->handle.version.abi_minor,
 		 info->handle.version.firmware_revision,
@@ -3428,7 +3910,17 @@
 	list_add_tail(&info->node, &ti_sci_list);
 	mutex_unlock(&ti_sci_list_mutex);
 
-	return of_platform_populate(dev->of_node, NULL, NULL, dev);
+	ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+	if (ret) {
+		dev_err(dev, "platform_populate failed %pe\n", ERR_PTR(ret));
+		goto unregister_restart;
+	}
+	return 0;
+
+unregister_restart:
+	if (info->nb.notifier_call)
+		unregister_restart_handler(&info->nb);
+
 out:
 	if (!IS_ERR(info->chan_tx))
 		mbox_free_channel(info->chan_tx);
@@ -3444,6 +3936,7 @@
 		   .name = "ti-sci",
 		   .of_match_table = of_match_ptr(ti_sci_of_match),
 		   .suppress_bind_attrs = true,
+		   .pm = &ti_sci_pm_ops,
 	},
 };
 module_platform_driver(ti_sci_driver);
diff -Naur --no-dereference a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
--- a/drivers/firmware/ti_sci.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/firmware/ti_sci.h	2024-01-28 14:01:31.240353775 -0500
@@ -6,7 +6,7 @@
  * The system works in a message response protocol
  * See: http://processors.wiki.ti.com/index.php/TISCI for details
  *
- * Copyright (C)  2015-2016 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C)  2015-2022 Texas Instruments Incorporated - https://www.ti.com/
  */
 
 #ifndef __TI_SCI_H
@@ -19,6 +19,7 @@
 #define TI_SCI_MSG_WAKE_REASON	0x0003
 #define TI_SCI_MSG_GOODBYE	0x0004
 #define TI_SCI_MSG_SYS_RESET	0x0005
+#define TI_SCI_MSG_QUERY_FW_CAPS	0x0022
 
 /* Device requests */
 #define TI_SCI_MSG_SET_DEVICE_STATE	0x0200
@@ -35,6 +36,11 @@
 #define TI_SCI_MSG_QUERY_CLOCK_FREQ	0x010d
 #define TI_SCI_MSG_GET_CLOCK_FREQ	0x010e
 
+/* Low Power Mode Requests */
+#define TI_SCI_MSG_PREPARE_SLEEP       0x0300
+#define TI_SCI_MSG_LPM_WAKE_REASON	0x0306
+#define TI_SCI_MSG_SET_IO_ISOLATION	0x0307
+
 /* Resource Management Requests */
 #define TI_SCI_MSG_GET_RESOURCE_RANGE	0x1500
 
@@ -133,6 +139,31 @@
 } __packed;
 
 /**
+ * struct ti_sci_msg_resp_query_fw_caps - Response for query firmware caps
+ * @hdr:	Generic header
+ * @fw_caps:	Each bit in fw_caps indicating one FW/SOC capability
+ *		MSG_FLAG_CAPS_GENERIC: Generic capability (LPM not supported)
+ *		MSG_FLAG_CAPS_LPM_DEEP_SLEEP: Deep Sleep LPM
+ *		MSG_FLAG_CAPS_LPM_MCU_ONLY: MCU only LPM
+ *		MSG_FLAG_CAPS_LPM_STANDBY: Standby LPM
+ *		MSG_FLAG_CAPS_LPM_PARTIAL_IO: Partial IO in LPM
+ *
+ * Response to a generic message with message type TI_SCI_MSG_QUERY_FW_CAPS
+ * providing currently available SOC/firmware capabilities. SoC that don't
+ * support low power modes return only MSG_FLAG_CAPS_GENERIC capability.
+ */
+struct ti_sci_msg_resp_query_fw_caps {
+	struct ti_sci_msg_hdr hdr;
+#define MSG_FLAG_CAPS_GENERIC		TI_SCI_MSG_FLAG(0)
+#define MSG_FLAG_CAPS_LPM_DEEP_SLEEP	TI_SCI_MSG_FLAG(1)
+#define MSG_FLAG_CAPS_LPM_MCU_ONLY	TI_SCI_MSG_FLAG(2)
+#define MSG_FLAG_CAPS_LPM_STANDBY	TI_SCI_MSG_FLAG(3)
+#define MSG_FLAG_CAPS_LPM_PARTIAL_IO	TI_SCI_MSG_FLAG(4)
+#define MSG_MASK_CAPS_LPM		GENMASK_ULL(4, 1)
+	u64 fw_caps;
+} __packed;
+
+/**
  * struct ti_sci_msg_req_set_device_state - Set the desired state of the device
  * @hdr:		Generic header
  * @id:	Indicates which device to modify
@@ -545,6 +576,64 @@
 	u64 freq_hz;
 } __packed;
 
+#define TISCI_MSG_VALUE_SLEEP_MODE_DEEP_SLEEP				0x0
+#define TISCI_MSG_VALUE_SLEEP_MODE_MCU_ONLY				0x1
+#define TISCI_MSG_VALUE_SLEEP_MODE_STANDBY				0x2
+#define TISCI_MSG_VALUE_SLEEP_MODE_PARTIAL_IO				0x3
+
+/**
+ * struct tisci_msg_prepare_sleep_req - Request for TISCI_MSG_PREPARE_SLEEP.
+ *
+ * @hdr				TISCI header to provide ACK/NAK flags to the host.
+ * @mode			Low power mode to enter.
+ * @ctx_lo			Low 32-bits of physical pointer to address to use for context save.
+ * @ctx_hi			High 32-bits of physical pointer to address to use for context save.
+ * @debug_flags			Flags that can be set to halt the sequence during suspend or
+ *				resume to allow JTAG connection and debug.
+ *
+ * This message is used as the first step of entering a low power mode. It
+ * allows configurable information, including which state to enter to be
+ * easily shared from the application, as this is a non-secure message and
+ * therefore can be sent by anyone.
+ */
+struct ti_sci_msg_req_prepare_sleep {
+	struct ti_sci_msg_hdr	hdr;
+	u8			mode;
+	u32			ctx_lo;
+	u32			ctx_hi;
+	u32			debug_flags;
+} __packed;
+
+/**
+ * struct ti_sci_msg_resp_lpm_wake_reason - Response for TI_SCI_MSG_LPM_WAKE_REASON.
+ *
+ * @hdr:		Generic header.
+ * @wake_source:	The wake up source that woke soc from LPM.
+ * @wake_timestamp:	Timestamp at which soc woke.
+ *
+ * Response to a generic message with message type TI_SCI_MSG_LPM_WAKE_REASON,
+ * used to query the wake up source from low power mode.
+ */
+struct ti_sci_msg_resp_lpm_wake_reason {
+	struct ti_sci_msg_hdr hdr;
+	u32 wake_source;
+	u64 wake_timestamp;
+} __packed;
+
+/**
+ * struct tisci_msg_set_io_isolation_req - Request for TI_SCI_MSG_SET_IO_ISOLATION.
+ *
+ * @hdr:	Generic header
+ * @state:	The deseared state of the IO isolation.
+ *
+ * This message is used to enable/disable IO isolation for low power modes.
+ * Response is generic ACK / NACK message.
+ */
+struct ti_sci_msg_req_set_io_isolation {
+	struct ti_sci_msg_hdr hdr;
+	u8 state;
+} __packed;
+
 #define TI_SCI_IRQ_SECONDARY_HOST_INVALID	0xff
 
 /**
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,1320 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright: 2017 Cadence Design Systems, Inc.
+ *
+ * Author: Boris Brezillon <boris.brezillon@bootlin.com>
+ */
+
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_probe_helper.h>
+#include <video/mipi_display.h>
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_graph.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+
+#include <linux/phy/phy-mipi-dphy.h>
+
+#include "cdns-dsi-core.h"
+#ifdef CONFIG_DRM_CDNS_DSI_J721E
+#include "cdns-dsi-j721e.h"
+#endif
+
+#define IP_CONF				0x0
+#define SP_HS_FIFO_DEPTH(x)		(((x) & GENMASK(30, 26)) >> 26)
+#define SP_LP_FIFO_DEPTH(x)		(((x) & GENMASK(25, 21)) >> 21)
+#define VRS_FIFO_DEPTH(x)		(((x) & GENMASK(20, 16)) >> 16)
+#define DIRCMD_FIFO_DEPTH(x)		(((x) & GENMASK(15, 13)) >> 13)
+#define SDI_IFACE_32			BIT(12)
+#define INTERNAL_DATAPATH_32		(0 << 10)
+#define INTERNAL_DATAPATH_16		(1 << 10)
+#define INTERNAL_DATAPATH_8		(3 << 10)
+#define INTERNAL_DATAPATH_SIZE		((x) & GENMASK(11, 10))
+#define NUM_IFACE(x)			((((x) & GENMASK(9, 8)) >> 8) + 1)
+#define MAX_LANE_NB(x)			(((x) & GENMASK(7, 6)) >> 6)
+#define RX_FIFO_DEPTH(x)		((x) & GENMASK(5, 0))
+
+#define MCTL_MAIN_DATA_CTL		0x4
+#define TE_MIPI_POLLING_EN		BIT(25)
+#define TE_HW_POLLING_EN		BIT(24)
+#define DISP_EOT_GEN			BIT(18)
+#define HOST_EOT_GEN			BIT(17)
+#define DISP_GEN_CHECKSUM		BIT(16)
+#define DISP_GEN_ECC			BIT(15)
+#define BTA_EN				BIT(14)
+#define READ_EN				BIT(13)
+#define REG_TE_EN			BIT(12)
+#define IF_TE_EN(x)			BIT(8 + (x))
+#define TVG_SEL				BIT(6)
+#define VID_EN				BIT(5)
+#define IF_VID_SELECT(x)		((x) << 2)
+#define IF_VID_SELECT_MASK		GENMASK(3, 2)
+#define IF_VID_MODE			BIT(1)
+#define LINK_EN				BIT(0)
+
+#define MCTL_MAIN_PHY_CTL		0x8
+#define HS_INVERT_DAT(x)		BIT(19 + ((x) * 2))
+#define SWAP_PINS_DAT(x)		BIT(18 + ((x) * 2))
+#define HS_INVERT_CLK			BIT(17)
+#define SWAP_PINS_CLK			BIT(16)
+#define HS_SKEWCAL_EN			BIT(15)
+#define WAIT_BURST_TIME(x)		((x) << 10)
+#define DATA_ULPM_EN(x)			BIT(6 + (x))
+#define CLK_ULPM_EN			BIT(5)
+#define CLK_CONTINUOUS			BIT(4)
+#define DATA_LANE_EN(x)			BIT((x) - 1)
+
+#define MCTL_MAIN_EN			0xc
+#define DATA_FORCE_STOP			BIT(17)
+#define CLK_FORCE_STOP			BIT(16)
+#define IF_EN(x)			BIT(13 + (x))
+#define DATA_LANE_ULPM_REQ(l)		BIT(9 + (l))
+#define CLK_LANE_ULPM_REQ		BIT(8)
+#define DATA_LANE_START(x)		BIT(4 + (x))
+#define CLK_LANE_EN			BIT(3)
+#define PLL_START			BIT(0)
+
+#define MCTL_DPHY_CFG0			0x10
+#define DPHY_C_RSTB			BIT(20)
+#define DPHY_D_RSTB(x)			GENMASK(15 + (x), 16)
+#define DPHY_PLL_PDN			BIT(10)
+#define DPHY_CMN_PDN			BIT(9)
+#define DPHY_C_PDN			BIT(8)
+#define DPHY_D_PDN(x)			GENMASK(3 + (x), 4)
+#define DPHY_ALL_D_PDN			GENMASK(7, 4)
+#define DPHY_PLL_PSO			BIT(1)
+#define DPHY_CMN_PSO			BIT(0)
+
+#define MCTL_DPHY_TIMEOUT1		0x14
+#define HSTX_TIMEOUT(x)			((x) << 4)
+#define HSTX_TIMEOUT_MAX		GENMASK(17, 0)
+#define CLK_DIV(x)			(x)
+#define CLK_DIV_MAX			GENMASK(3, 0)
+
+#define MCTL_DPHY_TIMEOUT2		0x18
+#define LPRX_TIMEOUT(x)			(x)
+
+#define MCTL_ULPOUT_TIME		0x1c
+#define DATA_LANE_ULPOUT_TIME(x)	((x) << 9)
+#define CLK_LANE_ULPOUT_TIME(x)		(x)
+
+#define MCTL_3DVIDEO_CTL		0x20
+#define VID_VSYNC_3D_EN			BIT(7)
+#define VID_VSYNC_3D_LR			BIT(5)
+#define VID_VSYNC_3D_SECOND_EN		BIT(4)
+#define VID_VSYNC_3DFORMAT_LINE		(0 << 2)
+#define VID_VSYNC_3DFORMAT_FRAME	(1 << 2)
+#define VID_VSYNC_3DFORMAT_PIXEL	(2 << 2)
+#define VID_VSYNC_3DMODE_OFF		0
+#define VID_VSYNC_3DMODE_PORTRAIT	1
+#define VID_VSYNC_3DMODE_LANDSCAPE	2
+
+#define MCTL_MAIN_STS			0x24
+#define MCTL_MAIN_STS_CTL		0x130
+#define MCTL_MAIN_STS_CLR		0x150
+#define MCTL_MAIN_STS_FLAG		0x170
+#define HS_SKEWCAL_DONE			BIT(11)
+#define IF_UNTERM_PKT_ERR(x)		BIT(8 + (x))
+#define LPRX_TIMEOUT_ERR		BIT(7)
+#define HSTX_TIMEOUT_ERR		BIT(6)
+#define DATA_LANE_RDY(l)		BIT(2 + (l))
+#define CLK_LANE_RDY			BIT(1)
+#define PLL_LOCKED			BIT(0)
+
+#define MCTL_DPHY_ERR			0x28
+#define MCTL_DPHY_ERR_CTL1		0x148
+#define MCTL_DPHY_ERR_CLR		0x168
+#define MCTL_DPHY_ERR_FLAG		0x188
+#define ERR_CONT_LP(x, l)		BIT(18 + ((x) * 4) + (l))
+#define ERR_CONTROL(l)			BIT(14 + (l))
+#define ERR_SYNESC(l)			BIT(10 + (l))
+#define ERR_ESC(l)			BIT(6 + (l))
+
+#define MCTL_DPHY_ERR_CTL2		0x14c
+#define ERR_CONT_LP_EDGE(x, l)		BIT(12 + ((x) * 4) + (l))
+#define ERR_CONTROL_EDGE(l)		BIT(8 + (l))
+#define ERR_SYN_ESC_EDGE(l)		BIT(4 + (l))
+#define ERR_ESC_EDGE(l)			BIT(0 + (l))
+
+#define MCTL_LANE_STS			0x2c
+#define PPI_C_TX_READY_HS		BIT(18)
+#define DPHY_PLL_LOCK			BIT(17)
+#define PPI_D_RX_ULPS_ESC(x)		(((x) & GENMASK(15, 12)) >> 12)
+#define LANE_STATE_START		0
+#define LANE_STATE_IDLE			1
+#define LANE_STATE_WRITE		2
+#define LANE_STATE_ULPM			3
+#define LANE_STATE_READ			4
+#define DATA_LANE_STATE(l, val)		\
+	(((val) >> (2 + 2 * (l) + ((l) ? 1 : 0))) & GENMASK((l) ? 1 : 2, 0))
+#define CLK_LANE_STATE_HS		2
+#define CLK_LANE_STATE(val)		((val) & GENMASK(1, 0))
+
+#define DSC_MODE_CTL			0x30
+#define DSC_MODE_EN			BIT(0)
+
+#define DSC_CMD_SEND			0x34
+#define DSC_SEND_PPS			BIT(0)
+#define DSC_EXECUTE_QUEUE		BIT(1)
+
+#define DSC_PPS_WRDAT			0x38
+
+#define DSC_MODE_STS			0x3c
+#define DSC_PPS_DONE			BIT(1)
+#define DSC_EXEC_DONE			BIT(2)
+
+#define CMD_MODE_CTL			0x70
+#define IF_LP_EN(x)			BIT(9 + (x))
+#define IF_VCHAN_ID(x, c)		((c) << ((x) * 2))
+
+#define CMD_MODE_CTL2			0x74
+#define TE_TIMEOUT(x)			((x) << 11)
+#define FILL_VALUE(x)			((x) << 3)
+#define ARB_IF_WITH_HIGHEST_PRIORITY(x)	((x) << 1)
+#define ARB_ROUND_ROBIN_MODE		BIT(0)
+
+#define CMD_MODE_STS			0x78
+#define CMD_MODE_STS_CTL		0x134
+#define CMD_MODE_STS_CLR		0x154
+#define CMD_MODE_STS_FLAG		0x174
+#define ERR_IF_UNDERRUN(x)		BIT(4 + (x))
+#define ERR_UNWANTED_READ		BIT(3)
+#define ERR_TE_MISS			BIT(2)
+#define ERR_NO_TE			BIT(1)
+#define CSM_RUNNING			BIT(0)
+
+#define DIRECT_CMD_SEND			0x80
+
+#define DIRECT_CMD_MAIN_SETTINGS	0x84
+#define TRIGGER_VAL(x)			((x) << 25)
+#define CMD_LP_EN			BIT(24)
+#define CMD_SIZE(x)			((x) << 16)
+#define CMD_VCHAN_ID(x)			((x) << 14)
+#define CMD_DATATYPE(x)			((x) << 8)
+#define CMD_LONG			BIT(3)
+#define WRITE_CMD			0
+#define READ_CMD			1
+#define TE_REQ				4
+#define TRIGGER_REQ			5
+#define BTA_REQ				6
+
+#define DIRECT_CMD_STS			0x88
+#define DIRECT_CMD_STS_CTL		0x138
+#define DIRECT_CMD_STS_CLR		0x158
+#define DIRECT_CMD_STS_FLAG		0x178
+#define RCVD_ACK_VAL(val)		((val) >> 16)
+#define RCVD_TRIGGER_VAL(val)		(((val) & GENMASK(14, 11)) >> 11)
+#define READ_COMPLETED_WITH_ERR		BIT(10)
+#define BTA_FINISHED			BIT(9)
+#define BTA_COMPLETED			BIT(8)
+#define TE_RCVD				BIT(7)
+#define TRIGGER_RCVD			BIT(6)
+#define ACK_WITH_ERR_RCVD		BIT(5)
+#define ACK_RCVD			BIT(4)
+#define READ_COMPLETED			BIT(3)
+#define TRIGGER_COMPLETED		BIT(2)
+#define WRITE_COMPLETED			BIT(1)
+#define SENDING_CMD			BIT(0)
+
+#define DIRECT_CMD_STOP_READ		0x8c
+
+#define DIRECT_CMD_WRDATA		0x90
+
+#define DIRECT_CMD_FIFO_RST		0x94
+
+#define DIRECT_CMD_RDDATA		0xa0
+
+#define DIRECT_CMD_RD_PROPS		0xa4
+#define RD_DCS				BIT(18)
+#define RD_VCHAN_ID(val)		(((val) >> 16) & GENMASK(1, 0))
+#define RD_SIZE(val)			((val) & GENMASK(15, 0))
+
+#define DIRECT_CMD_RD_STS		0xa8
+#define DIRECT_CMD_RD_STS_CTL		0x13c
+#define DIRECT_CMD_RD_STS_CLR		0x15c
+#define DIRECT_CMD_RD_STS_FLAG		0x17c
+#define ERR_EOT_WITH_ERR		BIT(8)
+#define ERR_MISSING_EOT			BIT(7)
+#define ERR_WRONG_LENGTH		BIT(6)
+#define ERR_OVERSIZE			BIT(5)
+#define ERR_RECEIVE			BIT(4)
+#define ERR_UNDECODABLE			BIT(3)
+#define ERR_CHECKSUM			BIT(2)
+#define ERR_UNCORRECTABLE		BIT(1)
+#define ERR_FIXED			BIT(0)
+
+#define VID_MAIN_CTL			0xb0
+#define VID_IGNORE_MISS_VSYNC		BIT(31)
+#define VID_FIELD_SW			BIT(28)
+#define VID_INTERLACED_EN		BIT(27)
+#define RECOVERY_MODE(x)		((x) << 25)
+#define RECOVERY_MODE_NEXT_HSYNC	0
+#define RECOVERY_MODE_NEXT_STOP_POINT	2
+#define RECOVERY_MODE_NEXT_VSYNC	3
+#define REG_BLKEOL_MODE(x)		((x) << 23)
+#define REG_BLKLINE_MODE(x)		((x) << 21)
+#define REG_BLK_MODE_NULL_PKT		0
+#define REG_BLK_MODE_BLANKING_PKT	1
+#define REG_BLK_MODE_LP			2
+#define SYNC_PULSE_HORIZONTAL		BIT(20)
+#define SYNC_PULSE_ACTIVE		BIT(19)
+#define BURST_MODE			BIT(18)
+#define VID_PIXEL_MODE_MASK		GENMASK(17, 14)
+#define VID_PIXEL_MODE_RGB565		(0 << 14)
+#define VID_PIXEL_MODE_RGB666_PACKED	(1 << 14)
+#define VID_PIXEL_MODE_RGB666		(2 << 14)
+#define VID_PIXEL_MODE_RGB888		(3 << 14)
+#define VID_PIXEL_MODE_RGB101010	(4 << 14)
+#define VID_PIXEL_MODE_RGB121212	(5 << 14)
+#define VID_PIXEL_MODE_YUV420		(8 << 14)
+#define VID_PIXEL_MODE_YUV422_PACKED	(9 << 14)
+#define VID_PIXEL_MODE_YUV422		(10 << 14)
+#define VID_PIXEL_MODE_YUV422_24B	(11 << 14)
+#define VID_PIXEL_MODE_DSC_COMP		(12 << 14)
+#define VID_DATATYPE(x)			((x) << 8)
+#define VID_VIRTCHAN_ID(iface, x)	((x) << (4 + (iface) * 2))
+#define STOP_MODE(x)			((x) << 2)
+#define START_MODE(x)			(x)
+
+#define VID_VSIZE1			0xb4
+#define VFP_LEN(x)			((x) << 12)
+#define VBP_LEN(x)			((x) << 6)
+#define VSA_LEN(x)			(x)
+
+#define VID_VSIZE2			0xb8
+#define VACT_LEN(x)			(x)
+
+#define VID_HSIZE1			0xc0
+#define HBP_LEN(x)			((x) << 16)
+#define HSA_LEN(x)			(x)
+
+#define VID_HSIZE2			0xc4
+#define HFP_LEN(x)			((x) << 16)
+#define HACT_LEN(x)			(x)
+
+#define VID_BLKSIZE1			0xcc
+#define BLK_EOL_PKT_LEN(x)		((x) << 15)
+#define BLK_LINE_EVENT_PKT_LEN(x)	(x)
+
+#define VID_BLKSIZE2			0xd0
+#define BLK_LINE_PULSE_PKT_LEN(x)	(x)
+
+#define VID_PKT_TIME			0xd8
+#define BLK_EOL_DURATION(x)		(x)
+
+#define VID_DPHY_TIME			0xdc
+#define REG_WAKEUP_TIME(x)		((x) << 17)
+#define REG_LINE_DURATION(x)		(x)
+
+#define VID_ERR_COLOR1			0xe0
+#define COL_GREEN(x)			((x) << 12)
+#define COL_RED(x)			(x)
+
+#define VID_ERR_COLOR2			0xe4
+#define PAD_VAL(x)			((x) << 12)
+#define COL_BLUE(x)			(x)
+
+#define VID_VPOS			0xe8
+#define LINE_VAL(val)			(((val) & GENMASK(14, 2)) >> 2)
+#define LINE_POS(val)			((val) & GENMASK(1, 0))
+
+#define VID_HPOS			0xec
+#define HORIZ_VAL(val)			(((val) & GENMASK(17, 3)) >> 3)
+#define HORIZ_POS(val)			((val) & GENMASK(2, 0))
+
+#define VID_MODE_STS			0xf0
+#define VID_MODE_STS_CTL		0x140
+#define VID_MODE_STS_CLR		0x160
+#define VID_MODE_STS_FLAG		0x180
+#define VSG_RECOVERY			BIT(10)
+#define ERR_VRS_WRONG_LEN		BIT(9)
+#define ERR_LONG_READ			BIT(8)
+#define ERR_LINE_WRITE			BIT(7)
+#define ERR_BURST_WRITE			BIT(6)
+#define ERR_SMALL_HEIGHT		BIT(5)
+#define ERR_SMALL_LEN			BIT(4)
+#define ERR_MISSING_VSYNC		BIT(3)
+#define ERR_MISSING_HSYNC		BIT(2)
+#define ERR_MISSING_DATA		BIT(1)
+#define VSG_RUNNING			BIT(0)
+
+#define VID_VCA_SETTING1		0xf4
+#define BURST_LP			BIT(16)
+#define MAX_BURST_LIMIT(x)		(x)
+
+#define VID_VCA_SETTING2		0xf8
+#define MAX_LINE_LIMIT(x)		((x) << 16)
+#define EXACT_BURST_LIMIT(x)		(x)
+
+#define TVG_CTL				0xfc
+#define TVG_STRIPE_SIZE(x)		((x) << 5)
+#define TVG_MODE_MASK			GENMASK(4, 3)
+#define TVG_MODE_SINGLE_COLOR		(0 << 3)
+#define TVG_MODE_VSTRIPES		(2 << 3)
+#define TVG_MODE_HSTRIPES		(3 << 3)
+#define TVG_STOPMODE_MASK		GENMASK(2, 1)
+#define TVG_STOPMODE_EOF		(0 << 1)
+#define TVG_STOPMODE_EOL		(1 << 1)
+#define TVG_STOPMODE_NOW		(2 << 1)
+#define TVG_RUN				BIT(0)
+
+#define TVG_IMG_SIZE			0x100
+#define TVG_NBLINES(x)			((x) << 16)
+#define TVG_LINE_SIZE(x)		(x)
+
+#define TVG_COLOR1			0x104
+#define TVG_COL1_GREEN(x)		((x) << 12)
+#define TVG_COL1_RED(x)			(x)
+
+#define TVG_COLOR1_BIS			0x108
+#define TVG_COL1_BLUE(x)		(x)
+
+#define TVG_COLOR2			0x10c
+#define TVG_COL2_GREEN(x)		((x) << 12)
+#define TVG_COL2_RED(x)			(x)
+
+#define TVG_COLOR2_BIS			0x110
+#define TVG_COL2_BLUE(x)		(x)
+
+#define TVG_STS				0x114
+#define TVG_STS_CTL			0x144
+#define TVG_STS_CLR			0x164
+#define TVG_STS_FLAG			0x184
+#define TVG_STS_RUNNING			BIT(0)
+
+#define STS_CTL_EDGE(e)			((e) << 16)
+
+#define DPHY_LANES_MAP			0x198
+#define DAT_REMAP_CFG(b, l)		((l) << ((b) * 8))
+
+#define DPI_IRQ_EN			0x1a0
+#define DPI_IRQ_CLR			0x1a4
+#define DPI_IRQ_STS			0x1a8
+#define PIXEL_BUF_OVERFLOW		BIT(0)
+
+#define DPI_CFG				0x1ac
+#define DPI_CFG_FIFO_DEPTH(x)		((x) >> 16)
+#define DPI_CFG_FIFO_LEVEL(x)		((x) & GENMASK(15, 0))
+
+#define TEST_GENERIC			0x1f0
+#define TEST_STATUS(x)			((x) >> 16)
+#define TEST_CTRL(x)			(x)
+
+#define ID_REG				0x1fc
+#define REV_VENDOR_ID(x)		(((x) & GENMASK(31, 20)) >> 20)
+#define REV_PRODUCT_ID(x)		(((x) & GENMASK(19, 12)) >> 12)
+#define REV_HW(x)			(((x) & GENMASK(11, 8)) >> 8)
+#define REV_MAJOR(x)			(((x) & GENMASK(7, 4)) >> 4)
+#define REV_MINOR(x)			((x) & GENMASK(3, 0))
+
+#define DSI_OUTPUT_PORT			0
+#define DSI_INPUT_PORT(inputid)		(1 + (inputid))
+
+#define DSI_HBP_FRAME_OVERHEAD		12
+#define DSI_HSA_FRAME_OVERHEAD		14
+#define DSI_HFP_FRAME_OVERHEAD		6
+#define DSI_HSS_VSS_VSE_FRAME_OVERHEAD	4
+#define DSI_BLANKING_FRAME_OVERHEAD	6
+#define DSI_NULL_FRAME_OVERHEAD		6
+#define DSI_EOT_PKT_SIZE		4
+
+static inline struct cdns_dsi *input_to_dsi(struct cdns_dsi_input *input)
+{
+	return container_of(input, struct cdns_dsi, input);
+}
+
+static inline struct cdns_dsi *to_cdns_dsi(struct mipi_dsi_host *host)
+{
+	return container_of(host, struct cdns_dsi, base);
+}
+
+static inline struct cdns_dsi_input *
+bridge_to_cdns_dsi_input(struct drm_bridge *bridge)
+{
+	return container_of(bridge, struct cdns_dsi_input, bridge);
+}
+
+static unsigned int mode_to_dpi_hfp(const struct drm_display_mode *mode,
+				    bool mode_valid_check)
+{
+	if (mode_valid_check)
+		return mode->hsync_start - mode->hdisplay;
+
+	return mode->crtc_hsync_start - mode->crtc_hdisplay;
+}
+
+static unsigned int dpi_to_dsi_timing(unsigned int dpi_timing,
+				      unsigned int dpi_bpp,
+				      unsigned int dsi_pkt_overhead)
+{
+	unsigned int dsi_timing = DIV_ROUND_UP(dpi_timing * dpi_bpp, 8);
+
+	if (dsi_timing < dsi_pkt_overhead)
+		dsi_timing = 0;
+	else
+		dsi_timing -= dsi_pkt_overhead;
+
+	return dsi_timing;
+}
+
+static int cdns_dsi_mode2cfg(struct cdns_dsi *dsi,
+			     const struct drm_display_mode *mode,
+			     struct cdns_dsi_cfg *dsi_cfg,
+			     bool mode_valid_check)
+{
+	struct cdns_dsi_output *output = &dsi->output;
+	unsigned int tmp;
+	bool sync_pulse = false;
+	int bpp;
+
+	memset(dsi_cfg, 0, sizeof(*dsi_cfg));
+
+	if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+		sync_pulse = true;
+
+	bpp = mipi_dsi_pixel_format_to_bpp(output->dev->format);
+
+	if (mode_valid_check)
+		tmp = mode->htotal -
+		      (sync_pulse ? mode->hsync_end : mode->hsync_start);
+	else
+		tmp = mode->crtc_htotal -
+		      (sync_pulse ?
+		       mode->crtc_hsync_end : mode->crtc_hsync_start);
+
+	dsi_cfg->hbp = dpi_to_dsi_timing(tmp, bpp, DSI_HBP_FRAME_OVERHEAD);
+
+	if (sync_pulse) {
+		if (mode_valid_check)
+			tmp = mode->hsync_end - mode->hsync_start;
+		else
+			tmp = mode->crtc_hsync_end - mode->crtc_hsync_start;
+
+		dsi_cfg->hsa = dpi_to_dsi_timing(tmp, bpp,
+						 DSI_HSA_FRAME_OVERHEAD);
+	}
+
+	dsi_cfg->hact = dpi_to_dsi_timing(mode_valid_check ?
+					  mode->hdisplay : mode->crtc_hdisplay,
+					  bpp, 0);
+	dsi_cfg->hfp = dpi_to_dsi_timing(mode_to_dpi_hfp(mode, mode_valid_check),
+					 bpp, DSI_HFP_FRAME_OVERHEAD);
+
+	return 0;
+}
+
+static int cdns_dsi_adjust_phy_config(struct cdns_dsi *dsi,
+			      struct cdns_dsi_cfg *dsi_cfg,
+			      struct phy_configure_opts_mipi_dphy *phy_cfg,
+			      const struct drm_display_mode *mode,
+			      bool mode_valid_check)
+{
+	struct cdns_dsi_output *output = &dsi->output;
+	unsigned long long dlane_bps;
+	unsigned long adj_dsi_htotal;
+	unsigned long dsi_htotal;
+	unsigned long dpi_htotal;
+	unsigned long dpi_hz;
+	unsigned int dsi_hfp_ext;
+	unsigned int lanes = output->dev->lanes;
+
+	dsi_htotal = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
+	if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+		dsi_htotal += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
+
+	dsi_htotal += dsi_cfg->hact;
+	dsi_htotal += dsi_cfg->hfp + DSI_HFP_FRAME_OVERHEAD;
+
+	/*
+	 * Make sure DSI htotal is aligned on a lane boundary when calculating
+	 * the expected data rate. This is done by extending HFP in case of
+	 * misalignment.
+	 */
+	adj_dsi_htotal = dsi_htotal;
+	if (dsi_htotal % lanes)
+		adj_dsi_htotal += lanes - (dsi_htotal % lanes);
+
+	dpi_hz = (mode_valid_check ? mode->clock : mode->crtc_clock) * 1000;
+	dlane_bps = (unsigned long long)dpi_hz * adj_dsi_htotal;
+
+	/* data rate in bytes/sec is not an integer, refuse the mode. */
+	dpi_htotal = mode_valid_check ? mode->htotal : mode->crtc_htotal;
+	if (do_div(dlane_bps, lanes * dpi_htotal))
+		return -EINVAL;
+
+	/* data rate was in bytes/sec, convert to bits/sec. */
+	phy_cfg->hs_clk_rate = dlane_bps * 8;
+
+	dsi_hfp_ext = adj_dsi_htotal - dsi_htotal;
+	dsi_cfg->hfp += dsi_hfp_ext;
+	dsi_cfg->htotal = dsi_htotal + dsi_hfp_ext;
+
+	return 0;
+}
+
+static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
+			       const struct drm_display_mode *mode,
+			       struct cdns_dsi_cfg *dsi_cfg,
+			       bool mode_valid_check)
+{
+	struct cdns_dsi_output *output = &dsi->output;
+	struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
+	unsigned long dsi_hss_hsa_hse_hbp;
+	unsigned int nlanes = output->dev->lanes;
+	int ret;
+
+	ret = cdns_dsi_mode2cfg(dsi, mode, dsi_cfg, mode_valid_check);
+	if (ret)
+		return ret;
+
+	phy_mipi_dphy_get_default_config(mode->crtc_clock * 1000,
+					 mipi_dsi_pixel_format_to_bpp(output->dev->format),
+					 nlanes, phy_cfg);
+
+	ret = cdns_dsi_adjust_phy_config(dsi, dsi_cfg, phy_cfg, mode, mode_valid_check);
+	if (ret)
+		return ret;
+
+	ret = phy_validate(dsi->dphy, PHY_MODE_MIPI_DPHY, 0, &output->phy_opts);
+	if (ret)
+		return ret;
+
+	dsi_hss_hsa_hse_hbp = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
+	if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+		dsi_hss_hsa_hse_hbp += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
+
+	/*
+	 * Make sure DPI(HFP) > DSI(HSS+HSA+HSE+HBP) to guarantee that the FIFO
+	 * is empty before we start a receiving a new line on the DPI
+	 * interface.
+	 */
+	if ((u64)phy_cfg->hs_clk_rate *
+	    mode_to_dpi_hfp(mode, mode_valid_check) * nlanes <
+	    (u64)dsi_hss_hsa_hse_hbp *
+	    (mode_valid_check ? mode->clock : mode->crtc_clock) * 1000)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int cdns_dsi_bridge_attach(struct drm_bridge *bridge,
+				  enum drm_bridge_attach_flags flags)
+{
+	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
+	struct cdns_dsi *dsi = input_to_dsi(input);
+	struct cdns_dsi_output *output = &dsi->output;
+
+	if (!drm_core_check_feature(bridge->dev, DRIVER_ATOMIC)) {
+		dev_err(dsi->base.dev,
+			"cdns-dsi driver is only compatible with DRM devices supporting atomic updates");
+		return -ENOTSUPP;
+	}
+
+	return drm_bridge_attach(bridge->encoder, output->bridge, bridge,
+				 flags);
+}
+
+static enum drm_mode_status
+cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
+			   const struct drm_display_info *info,
+			   const struct drm_display_mode *mode)
+{
+	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
+	struct cdns_dsi *dsi = input_to_dsi(input);
+	struct cdns_dsi_output *output = &dsi->output;
+	struct cdns_dsi_cfg dsi_cfg;
+	int bpp, ret;
+
+	/*
+	 * VFP_DSI should be less than VFP_DPI and VFP_DSI should be at
+	 * least 1.
+	 */
+	if (mode->vtotal - mode->vsync_end < 2)
+		return MODE_V_ILLEGAL;
+
+	/* VSA_DSI = VSA_DPI and must be at least 2. */
+	if (mode->vsync_end - mode->vsync_start < 2)
+		return MODE_V_ILLEGAL;
+
+	/* HACT must be 32-bits aligned. */
+	bpp = mipi_dsi_pixel_format_to_bpp(output->dev->format);
+	if ((mode->hdisplay * bpp) % 32)
+		return MODE_H_ILLEGAL;
+
+	ret = cdns_dsi_check_conf(dsi, mode, &dsi_cfg, true);
+	if (ret)
+		return MODE_BAD;
+
+	return MODE_OK;
+}
+
+static void cdns_dsi_bridge_disable(struct drm_bridge *bridge)
+{
+	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
+	struct cdns_dsi *dsi = input_to_dsi(input);
+	u32 val;
+
+	val = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
+	val &= ~(IF_VID_SELECT_MASK | IF_VID_MODE | VID_EN | HOST_EOT_GEN |
+		 DISP_EOT_GEN);
+	writel(val, dsi->regs + MCTL_MAIN_DATA_CTL);
+
+	val = readl(dsi->regs + MCTL_MAIN_EN) & ~IF_EN(input->id);
+	writel(val, dsi->regs + MCTL_MAIN_EN);
+
+	if (dsi->platform_ops && dsi->platform_ops->disable)
+		dsi->platform_ops->disable(dsi);
+
+	pm_runtime_put(dsi->base.dev);
+}
+
+static void cdns_dsi_bridge_post_disable(struct drm_bridge *bridge)
+{
+	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
+	struct cdns_dsi *dsi = input_to_dsi(input);
+
+	pm_runtime_put(dsi->base.dev);
+}
+
+static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
+{
+	struct cdns_dsi_output *output = &dsi->output;
+	u32 status;
+
+	if (dsi->phy_initialized)
+		return;
+	/*
+	 * Power all internal DPHY blocks down and maintain their reset line
+	 * asserted before changing the DPHY config.
+	 */
+	writel(DPHY_CMN_PSO | DPHY_PLL_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN |
+	       DPHY_CMN_PDN | DPHY_PLL_PDN,
+	       dsi->regs + MCTL_DPHY_CFG0);
+
+	phy_init(dsi->dphy);
+	phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY);
+	phy_configure(dsi->dphy, &output->phy_opts);
+	phy_power_on(dsi->dphy);
+
+	/* Activate the PLL and wait until it's locked. */
+	writel(PLL_LOCKED, dsi->regs + MCTL_MAIN_STS_CLR);
+	writel(DPHY_CMN_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN | DPHY_CMN_PDN,
+	       dsi->regs + MCTL_DPHY_CFG0);
+	WARN_ON_ONCE(readl_poll_timeout(dsi->regs + MCTL_MAIN_STS, status,
+					status & PLL_LOCKED, 100, 100));
+	/* De-assert data and clock reset lines. */
+	writel(DPHY_CMN_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN | DPHY_CMN_PDN |
+	       DPHY_D_RSTB(output->dev->lanes) | DPHY_C_RSTB,
+	       dsi->regs + MCTL_DPHY_CFG0);
+	dsi->phy_initialized = true;
+}
+
+static void cdns_dsi_init_link(struct cdns_dsi *dsi)
+{
+	struct cdns_dsi_output *output = &dsi->output;
+	unsigned long sysclk_period, ulpout;
+	u32 val;
+	int i;
+
+	if (dsi->link_initialized)
+		return;
+
+	val = 0;
+	for (i = 1; i < output->dev->lanes; i++)
+		val |= DATA_LANE_EN(i);
+
+	if (!(output->dev->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
+		val |= CLK_CONTINUOUS;
+
+	writel(val, dsi->regs + MCTL_MAIN_PHY_CTL);
+
+	/* ULPOUT should be set to 1ms and is expressed in sysclk cycles. */
+	sysclk_period = NSEC_PER_SEC / clk_get_rate(dsi->dsi_sys_clk);
+	ulpout = DIV_ROUND_UP(NSEC_PER_MSEC, sysclk_period);
+	writel(CLK_LANE_ULPOUT_TIME(ulpout) | DATA_LANE_ULPOUT_TIME(ulpout),
+	       dsi->regs + MCTL_ULPOUT_TIME);
+
+	writel(LINK_EN, dsi->regs + MCTL_MAIN_DATA_CTL);
+
+	val = CLK_LANE_EN | PLL_START;
+	for (i = 0; i < output->dev->lanes; i++)
+		val |= DATA_LANE_START(i);
+
+	writel(val, dsi->regs + MCTL_MAIN_EN);
+
+	dsi->link_initialized = true;
+}
+
+static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
+{
+	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
+	struct cdns_dsi *dsi = input_to_dsi(input);
+	struct cdns_dsi_output *output = &dsi->output;
+	struct drm_display_mode *mode;
+	struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
+	unsigned long tx_byte_period;
+	struct cdns_dsi_cfg dsi_cfg;
+	u32 tmp, reg_wakeup, div;
+	int nlanes;
+
+	if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
+		return;
+
+	if (dsi->platform_ops && dsi->platform_ops->enable)
+		dsi->platform_ops->enable(dsi);
+
+	mode = &bridge->encoder->crtc->state->adjusted_mode;
+	nlanes = output->dev->lanes;
+
+	WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, false));
+
+	cdns_dsi_hs_init(dsi);
+	cdns_dsi_init_link(dsi);
+
+	writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
+	       dsi->regs + VID_HSIZE1);
+	writel(HFP_LEN(dsi_cfg.hfp) | HACT_LEN(dsi_cfg.hact),
+	       dsi->regs + VID_HSIZE2);
+
+	writel(VBP_LEN(mode->crtc_vtotal - mode->crtc_vsync_end - 1) |
+	       VFP_LEN(mode->crtc_vsync_start - mode->crtc_vdisplay) |
+	       VSA_LEN(mode->crtc_vsync_end - mode->crtc_vsync_start + 1),
+	       dsi->regs + VID_VSIZE1);
+	writel(mode->crtc_vdisplay, dsi->regs + VID_VSIZE2);
+
+	tmp = dsi_cfg.htotal -
+	      (dsi_cfg.hsa + DSI_BLANKING_FRAME_OVERHEAD +
+	       DSI_HSA_FRAME_OVERHEAD);
+	writel(BLK_LINE_PULSE_PKT_LEN(tmp), dsi->regs + VID_BLKSIZE2);
+	if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+		writel(MAX_LINE_LIMIT(tmp - DSI_NULL_FRAME_OVERHEAD),
+		       dsi->regs + VID_VCA_SETTING2);
+
+	tmp = dsi_cfg.htotal -
+	      (DSI_HSS_VSS_VSE_FRAME_OVERHEAD + DSI_BLANKING_FRAME_OVERHEAD);
+	writel(BLK_LINE_EVENT_PKT_LEN(tmp), dsi->regs + VID_BLKSIZE1);
+	if (!(output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))
+		writel(MAX_LINE_LIMIT(tmp - DSI_NULL_FRAME_OVERHEAD),
+		       dsi->regs + VID_VCA_SETTING2);
+
+	tmp = DIV_ROUND_UP(dsi_cfg.htotal, nlanes) -
+	      DIV_ROUND_UP(dsi_cfg.hsa, nlanes);
+
+	if (!(output->dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
+		tmp -= DIV_ROUND_UP(DSI_EOT_PKT_SIZE, nlanes);
+
+	tx_byte_period = DIV_ROUND_DOWN_ULL((u64)NSEC_PER_SEC * 8,
+					    phy_cfg->hs_clk_rate);
+	reg_wakeup = (phy_cfg->hs_prepare + phy_cfg->hs_zero) / tx_byte_period;
+	writel(REG_WAKEUP_TIME(reg_wakeup) | REG_LINE_DURATION(tmp),
+	       dsi->regs + VID_DPHY_TIME);
+
+	/*
+	 * HSTX and LPRX timeouts are both expressed in TX byte clk cycles and
+	 * both should be set to at least the time it takes to transmit a
+	 * frame.
+	 */
+	tmp = NSEC_PER_SEC / drm_mode_vrefresh(mode);
+	tmp /= tx_byte_period;
+
+	for (div = 0; div <= CLK_DIV_MAX; div++) {
+		if (tmp <= HSTX_TIMEOUT_MAX)
+			break;
+
+		tmp >>= 1;
+	}
+
+	if (tmp > HSTX_TIMEOUT_MAX)
+		tmp = HSTX_TIMEOUT_MAX;
+
+	writel(CLK_DIV(div) | HSTX_TIMEOUT(tmp),
+	       dsi->regs + MCTL_DPHY_TIMEOUT1);
+
+	writel(LPRX_TIMEOUT(tmp), dsi->regs + MCTL_DPHY_TIMEOUT2);
+
+	if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO) {
+		switch (output->dev->format) {
+		case MIPI_DSI_FMT_RGB888:
+			tmp = VID_PIXEL_MODE_RGB888 |
+			      VID_DATATYPE(MIPI_DSI_PACKED_PIXEL_STREAM_24);
+			break;
+
+		case MIPI_DSI_FMT_RGB666:
+			tmp = VID_PIXEL_MODE_RGB666 |
+			      VID_DATATYPE(MIPI_DSI_PIXEL_STREAM_3BYTE_18);
+			break;
+
+		case MIPI_DSI_FMT_RGB666_PACKED:
+			tmp = VID_PIXEL_MODE_RGB666_PACKED |
+			      VID_DATATYPE(MIPI_DSI_PACKED_PIXEL_STREAM_18);
+			break;
+
+		case MIPI_DSI_FMT_RGB565:
+			tmp = VID_PIXEL_MODE_RGB565 |
+			      VID_DATATYPE(MIPI_DSI_PACKED_PIXEL_STREAM_16);
+			break;
+
+		default:
+			dev_err(dsi->base.dev, "Unsupported DSI format\n");
+			return;
+		}
+
+		if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
+			tmp |= SYNC_PULSE_ACTIVE | SYNC_PULSE_HORIZONTAL;
+
+		tmp |= REG_BLKLINE_MODE(REG_BLK_MODE_BLANKING_PKT) |
+		       REG_BLKEOL_MODE(REG_BLK_MODE_BLANKING_PKT) |
+		       RECOVERY_MODE(RECOVERY_MODE_NEXT_HSYNC) |
+		       VID_IGNORE_MISS_VSYNC;
+
+		writel(tmp, dsi->regs + VID_MAIN_CTL);
+	}
+
+	tmp = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
+	tmp &= ~(IF_VID_SELECT_MASK | HOST_EOT_GEN | IF_VID_MODE);
+
+	if (!(output->dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
+		tmp |= HOST_EOT_GEN;
+
+	if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO)
+		tmp |= IF_VID_MODE | IF_VID_SELECT(input->id) | VID_EN;
+
+	writel(tmp, dsi->regs + MCTL_MAIN_DATA_CTL);
+
+	tmp = readl(dsi->regs + MCTL_MAIN_EN) | IF_EN(input->id);
+	writel(tmp, dsi->regs + MCTL_MAIN_EN);
+}
+
+static void cdns_dsi_bridge_pre_enable(struct drm_bridge *bridge)
+{
+	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
+	struct cdns_dsi *dsi = input_to_dsi(input);
+
+	if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
+		return;
+
+	cdns_dsi_init_link(dsi);
+	cdns_dsi_hs_init(dsi);
+}
+
+static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
+	.attach = cdns_dsi_bridge_attach,
+	.mode_valid = cdns_dsi_bridge_mode_valid,
+	.disable = cdns_dsi_bridge_disable,
+	.pre_enable = cdns_dsi_bridge_pre_enable,
+	.enable = cdns_dsi_bridge_enable,
+	.post_disable = cdns_dsi_bridge_post_disable,
+};
+
+static int cdns_dsi_attach(struct mipi_dsi_host *host,
+			   struct mipi_dsi_device *dev)
+{
+	struct cdns_dsi *dsi = to_cdns_dsi(host);
+	struct cdns_dsi_output *output = &dsi->output;
+	struct cdns_dsi_input *input = &dsi->input;
+	struct drm_bridge *bridge;
+	struct drm_panel *panel;
+	struct device_node *np;
+	int ret;
+
+	/*
+	 * We currently do not support connecting several DSI devices to the
+	 * same host. In order to support that we'd need the DRM bridge
+	 * framework to allow dynamic reconfiguration of the bridge chain.
+	 */
+	if (output->dev)
+		return -EBUSY;
+
+	/* We do not support burst mode yet. */
+	if (dev->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
+		return -ENOTSUPP;
+
+	/*
+	 * The host <-> device link might be described using an OF-graph
+	 * representation, in this case we extract the device of_node from
+	 * this representation, otherwise we use dsidev->dev.of_node which
+	 * should have been filled by the core.
+	 */
+	np = of_graph_get_remote_node(dsi->base.dev->of_node, DSI_OUTPUT_PORT,
+				      dev->channel);
+	if (!np)
+		np = of_node_get(dev->dev.of_node);
+
+	panel = of_drm_find_panel(np);
+	if (!IS_ERR(panel)) {
+		bridge = drm_panel_bridge_add_typed(panel,
+						    DRM_MODE_CONNECTOR_DSI);
+	} else {
+		bridge = of_drm_find_bridge(np);
+		if (!bridge)
+			bridge = ERR_PTR(-EINVAL);
+	}
+
+	of_node_put(np);
+
+	if (IS_ERR(bridge)) {
+		ret = PTR_ERR(bridge);
+		dev_err(host->dev, "failed to add DSI device %s (err = %d)",
+			dev->name, ret);
+		return ret;
+	}
+
+	output->dev = dev;
+	output->bridge = bridge;
+	output->panel = panel;
+
+	/*
+	 * The DSI output has been properly configured, we can now safely
+	 * register the input to the bridge framework so that it can take place
+	 * in a display pipeline.
+	 */
+	drm_bridge_add(&input->bridge);
+
+	return 0;
+}
+
+static int cdns_dsi_detach(struct mipi_dsi_host *host,
+			   struct mipi_dsi_device *dev)
+{
+	struct cdns_dsi *dsi = to_cdns_dsi(host);
+	struct cdns_dsi_output *output = &dsi->output;
+	struct cdns_dsi_input *input = &dsi->input;
+
+	drm_bridge_remove(&input->bridge);
+	if (output->panel)
+		drm_panel_bridge_remove(output->bridge);
+
+	return 0;
+}
+
+static irqreturn_t cdns_dsi_interrupt(int irq, void *data)
+{
+	struct cdns_dsi *dsi = data;
+	irqreturn_t ret = IRQ_NONE;
+	u32 flag, ctl;
+
+	flag = readl(dsi->regs + DIRECT_CMD_STS_FLAG);
+	if (flag) {
+		ctl = readl(dsi->regs + DIRECT_CMD_STS_CTL);
+		ctl &= ~flag;
+		writel(ctl, dsi->regs + DIRECT_CMD_STS_CTL);
+		complete(&dsi->direct_cmd_comp);
+		ret = IRQ_HANDLED;
+	}
+
+	return ret;
+}
+
+static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host,
+				 const struct mipi_dsi_msg *msg)
+{
+	struct cdns_dsi *dsi = to_cdns_dsi(host);
+	u32 cmd, sts, val, wait = WRITE_COMPLETED, ctl = 0;
+	struct mipi_dsi_packet packet;
+	int ret, i, tx_len, rx_len;
+
+	ret = pm_runtime_resume_and_get(host->dev);
+	if (ret < 0)
+		return ret;
+
+	cdns_dsi_init_link(dsi);
+
+	ret = mipi_dsi_create_packet(&packet, msg);
+	if (ret)
+		goto out;
+
+	tx_len = msg->tx_buf ? msg->tx_len : 0;
+	rx_len = msg->rx_buf ? msg->rx_len : 0;
+
+	/* For read operations, the maximum TX len is 2. */
+	if (rx_len && tx_len > 2) {
+		ret = -ENOTSUPP;
+		goto out;
+	}
+
+	/* TX len is limited by the CMD FIFO depth. */
+	if (tx_len > dsi->direct_cmd_fifo_depth) {
+		ret = -ENOTSUPP;
+		goto out;
+	}
+
+	/* RX len is limited by the RX FIFO depth. */
+	if (rx_len > dsi->rx_fifo_depth) {
+		ret = -ENOTSUPP;
+		goto out;
+	}
+
+	cmd = CMD_SIZE(tx_len) | CMD_VCHAN_ID(msg->channel) |
+	      CMD_DATATYPE(msg->type);
+
+	if (msg->flags & MIPI_DSI_MSG_USE_LPM)
+		cmd |= CMD_LP_EN;
+
+	if (mipi_dsi_packet_format_is_long(msg->type))
+		cmd |= CMD_LONG;
+
+	if (rx_len) {
+		cmd |= READ_CMD;
+		wait = READ_COMPLETED_WITH_ERR | READ_COMPLETED;
+		ctl = READ_EN | BTA_EN;
+	} else if (msg->flags & MIPI_DSI_MSG_REQ_ACK) {
+		cmd |= BTA_REQ;
+		wait = ACK_WITH_ERR_RCVD | ACK_RCVD;
+		ctl = BTA_EN;
+	}
+
+	writel(readl(dsi->regs + MCTL_MAIN_DATA_CTL) | ctl,
+	       dsi->regs + MCTL_MAIN_DATA_CTL);
+
+	writel(cmd, dsi->regs + DIRECT_CMD_MAIN_SETTINGS);
+
+	for (i = 0; i < tx_len; i += 4) {
+		const u8 *buf = msg->tx_buf;
+		int j;
+
+		val = 0;
+		for (j = 0; j < 4 && j + i < tx_len; j++)
+			val |= (u32)buf[i + j] << (8 * j);
+
+		writel(val, dsi->regs + DIRECT_CMD_WRDATA);
+	}
+
+	/* Clear status flags before sending the command. */
+	writel(wait, dsi->regs + DIRECT_CMD_STS_CLR);
+	writel(wait, dsi->regs + DIRECT_CMD_STS_CTL);
+	reinit_completion(&dsi->direct_cmd_comp);
+	writel(0, dsi->regs + DIRECT_CMD_SEND);
+
+	wait_for_completion_timeout(&dsi->direct_cmd_comp,
+				    msecs_to_jiffies(1000));
+
+	sts = readl(dsi->regs + DIRECT_CMD_STS);
+	writel(wait, dsi->regs + DIRECT_CMD_STS_CLR);
+	writel(0, dsi->regs + DIRECT_CMD_STS_CTL);
+
+	writel(readl(dsi->regs + MCTL_MAIN_DATA_CTL) & ~ctl,
+	       dsi->regs + MCTL_MAIN_DATA_CTL);
+
+	/* We did not receive the events we were waiting for. */
+	if (!(sts & wait)) {
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+
+	/* 'READ' or 'WRITE with ACK' failed. */
+	if (sts & (READ_COMPLETED_WITH_ERR | ACK_WITH_ERR_RCVD)) {
+		ret = -EIO;
+		goto out;
+	}
+
+	for (i = 0; i < rx_len; i += 4) {
+		u8 *buf = msg->rx_buf;
+		int j;
+
+		val = readl(dsi->regs + DIRECT_CMD_RDDATA);
+		for (j = 0; j < 4 && j + i < rx_len; j++)
+			buf[i + j] = val >> (8 * j);
+	}
+
+out:
+	pm_runtime_put(host->dev);
+	return ret;
+}
+
+static const struct mipi_dsi_host_ops cdns_dsi_ops = {
+	.attach = cdns_dsi_attach,
+	.detach = cdns_dsi_detach,
+	.transfer = cdns_dsi_transfer,
+};
+
+static int __maybe_unused cdns_dsi_resume(struct device *dev)
+{
+	struct cdns_dsi *dsi = dev_get_drvdata(dev);
+
+	reset_control_deassert(dsi->dsi_p_rst);
+	clk_prepare_enable(dsi->dsi_p_clk);
+	clk_prepare_enable(dsi->dsi_sys_clk);
+
+	return 0;
+}
+
+static int __maybe_unused cdns_dsi_suspend(struct device *dev)
+{
+	struct cdns_dsi *dsi = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(dsi->dsi_sys_clk);
+	clk_disable_unprepare(dsi->dsi_p_clk);
+	reset_control_assert(dsi->dsi_p_rst);
+	dsi->link_initialized = false;
+	dsi->phy_initialized = false;
+	return 0;
+}
+
+static UNIVERSAL_DEV_PM_OPS(cdns_dsi_pm_ops, cdns_dsi_suspend, cdns_dsi_resume,
+			    NULL);
+
+static int cdns_dsi_drm_probe(struct platform_device *pdev)
+{
+	struct cdns_dsi *dsi;
+	struct cdns_dsi_input *input;
+	int ret, irq;
+	u32 val;
+
+	dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
+	if (!dsi)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, dsi);
+
+	input = &dsi->input;
+
+	dsi->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(dsi->regs))
+		return PTR_ERR(dsi->regs);
+
+	dsi->dsi_p_clk = devm_clk_get(&pdev->dev, "dsi_p_clk");
+	if (IS_ERR(dsi->dsi_p_clk))
+		return PTR_ERR(dsi->dsi_p_clk);
+
+	dsi->dsi_p_rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
+								"dsi_p_rst");
+	if (IS_ERR(dsi->dsi_p_rst))
+		return PTR_ERR(dsi->dsi_p_rst);
+
+	dsi->dsi_sys_clk = devm_clk_get(&pdev->dev, "dsi_sys_clk");
+	if (IS_ERR(dsi->dsi_sys_clk))
+		return PTR_ERR(dsi->dsi_sys_clk);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	dsi->dphy = devm_phy_get(&pdev->dev, "dphy");
+	if (IS_ERR(dsi->dphy))
+		return PTR_ERR(dsi->dphy);
+
+	ret = clk_prepare_enable(dsi->dsi_p_clk);
+	if (ret)
+		return ret;
+
+	val = readl(dsi->regs + ID_REG);
+	if (REV_VENDOR_ID(val) != 0xcad) {
+		dev_err(&pdev->dev, "invalid vendor id\n");
+		ret = -EINVAL;
+		goto err_disable_pclk;
+	}
+
+	dsi->platform_ops = of_device_get_match_data(&pdev->dev);
+
+	val = readl(dsi->regs + IP_CONF);
+	dsi->direct_cmd_fifo_depth = 1 << (DIRCMD_FIFO_DEPTH(val) + 2);
+	dsi->rx_fifo_depth = RX_FIFO_DEPTH(val);
+	init_completion(&dsi->direct_cmd_comp);
+
+	writel(0, dsi->regs + MCTL_MAIN_DATA_CTL);
+	writel(0, dsi->regs + MCTL_MAIN_EN);
+	writel(0, dsi->regs + MCTL_MAIN_PHY_CTL);
+
+	/*
+	 * We only support the DPI input, so force input->id to
+	 * CDNS_DPI_INPUT.
+	 */
+	input->id = CDNS_DPI_INPUT;
+	input->bridge.funcs = &cdns_dsi_bridge_funcs;
+	input->bridge.of_node = pdev->dev.of_node;
+
+	/* Mask all interrupts before registering the IRQ handler. */
+	writel(0, dsi->regs + MCTL_MAIN_STS_CTL);
+	writel(0, dsi->regs + MCTL_DPHY_ERR_CTL1);
+	writel(0, dsi->regs + CMD_MODE_STS_CTL);
+	writel(0, dsi->regs + DIRECT_CMD_STS_CTL);
+	writel(0, dsi->regs + DIRECT_CMD_RD_STS_CTL);
+	writel(0, dsi->regs + VID_MODE_STS_CTL);
+	writel(0, dsi->regs + TVG_STS_CTL);
+	writel(0, dsi->regs + DPI_IRQ_EN);
+	ret = devm_request_irq(&pdev->dev, irq, cdns_dsi_interrupt, 0,
+			       dev_name(&pdev->dev), dsi);
+	if (ret)
+		goto err_disable_pclk;
+
+	pm_runtime_enable(&pdev->dev);
+	dsi->base.dev = &pdev->dev;
+	dsi->base.ops = &cdns_dsi_ops;
+
+	if (dsi->platform_ops && dsi->platform_ops->init) {
+		ret = dsi->platform_ops->init(dsi);
+		if (ret != 0) {
+			dev_err(&pdev->dev, "platform initialization failed: %d\n",
+				ret);
+			goto err_disable_runtime_pm;
+		}
+	}
+
+	ret = mipi_dsi_host_register(&dsi->base);
+	if (ret)
+		goto err_deinit_platform;
+
+	clk_disable_unprepare(dsi->dsi_p_clk);
+
+	return 0;
+
+err_deinit_platform:
+	if (dsi->platform_ops && dsi->platform_ops->deinit)
+		dsi->platform_ops->deinit(dsi);
+
+err_disable_runtime_pm:
+	pm_runtime_disable(&pdev->dev);
+
+err_disable_pclk:
+	clk_disable_unprepare(dsi->dsi_p_clk);
+
+	return ret;
+}
+
+static int cdns_dsi_drm_remove(struct platform_device *pdev)
+{
+	struct cdns_dsi *dsi = platform_get_drvdata(pdev);
+
+	mipi_dsi_host_unregister(&dsi->base);
+
+	if (dsi->platform_ops && dsi->platform_ops->deinit)
+		dsi->platform_ops->deinit(dsi);
+
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id cdns_dsi_of_match[] = {
+	{ .compatible = "cdns,dsi" },
+#ifdef CONFIG_DRM_CDNS_DSI_J721E
+	{ .compatible = "ti,j721e-dsi", .data = &dsi_ti_j721e_ops, },
+#endif
+	{ },
+};
+MODULE_DEVICE_TABLE(of, cdns_dsi_of_match);
+
+static struct platform_driver cdns_dsi_platform_driver = {
+	.probe  = cdns_dsi_drm_probe,
+	.remove = cdns_dsi_drm_remove,
+	.driver = {
+		.name   = "cdns-dsi",
+		.of_match_table = cdns_dsi_of_match,
+		.pm = &cdns_dsi_pm_ops,
+	},
+};
+module_platform_driver(cdns_dsi_platform_driver);
+
+MODULE_AUTHOR("Boris Brezillon <boris.brezillon@bootlin.com>");
+MODULE_DESCRIPTION("Cadence DSI driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:cdns-dsi");
+
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.h	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright: 2017 Cadence Design Systems, Inc.
+ *
+ * Author: Boris Brezillon <boris.brezillon@bootlin.com>
+ */
+
+#ifndef __CDNS_DSI_H__
+#define __CDNS_DSI_H__
+
+#include <drm/drm_bridge.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_panel.h>
+
+#include <linux/bits.h>
+#include <linux/completion.h>
+#include <linux/phy/phy.h>
+
+struct clk;
+struct reset_control;
+
+struct cdns_dsi_output {
+	struct mipi_dsi_device *dev;
+	struct drm_panel *panel;
+	struct drm_bridge *bridge;
+	union phy_configure_opts phy_opts;
+};
+
+enum cdns_dsi_input_id {
+	CDNS_SDI_INPUT,
+	CDNS_DPI_INPUT,
+	CDNS_DSC_INPUT,
+};
+
+struct cdns_dsi_cfg {
+	unsigned int hfp;
+	unsigned int hsa;
+	unsigned int hbp;
+	unsigned int hact;
+	unsigned int htotal;
+};
+
+struct cdns_dsi_input {
+	enum cdns_dsi_input_id id;
+	struct drm_bridge bridge;
+};
+
+struct cdns_dsi;
+
+/**
+ * struct cdns_dsi_platform_ops - CDNS DSI Platform operations
+ * @init: Called in the CDNS DSI probe
+ * @deinit: Called in the CDNS DSI remove
+ * @enable: Called at the beginning of CDNS DSI bridge enable
+ * @disable: Called at the end of CDNS DSI bridge disable
+ */
+struct cdns_dsi_platform_ops {
+	int (*init)(struct cdns_dsi *dsi);
+	void (*deinit)(struct cdns_dsi *dsi);
+	void (*enable)(struct cdns_dsi *dsi);
+	void (*disable)(struct cdns_dsi *dsi);
+};
+
+struct cdns_dsi {
+	struct mipi_dsi_host base;
+	void __iomem *regs;
+#ifdef CONFIG_DRM_CDNS_DSI_J721E
+	void __iomem *j721e_regs;
+#endif
+	const struct cdns_dsi_platform_ops *platform_ops;
+	struct cdns_dsi_input input;
+	struct cdns_dsi_output output;
+	unsigned int direct_cmd_fifo_depth;
+	unsigned int rx_fifo_depth;
+	struct completion direct_cmd_comp;
+	struct clk *dsi_p_clk;
+	struct reset_control *dsi_p_rst;
+	struct clk *dsi_sys_clk;
+	bool link_initialized;
+	bool phy_initialized;
+	struct phy *dphy;
+};
+
+#endif /* !__CDNS_DSI_H__ */
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.c
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.c	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TI j721e Cadence DSI wrapper
+ *
+ * Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Rahul T R <r-ravikumar@ti.com>
+ */
+
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include "cdns-dsi-j721e.h"
+
+#define DSI_WRAP_REVISION		0x0
+#define DSI_WRAP_DPI_CONTROL		0x4
+#define DSI_WRAP_DSC_CONTROL		0x8
+#define DSI_WRAP_DPI_SECURE		0xc
+#define DSI_WRAP_DSI_0_ASF_STATUS	0x10
+
+#define DSI_WRAP_DPI_0_EN		BIT(0)
+#define DSI_WRAP_DSI2_MUX_SEL		BIT(4)
+
+static int cdns_dsi_j721e_init(struct cdns_dsi *dsi)
+{
+	struct platform_device *pdev = to_platform_device(dsi->base.dev);
+
+	dsi->j721e_regs = devm_platform_ioremap_resource(pdev, 1);
+	return PTR_ERR_OR_ZERO(dsi->j721e_regs);
+}
+
+static void cdns_dsi_j721e_enable(struct cdns_dsi *dsi)
+{
+	/*
+	 * Enable DPI0 as its input. DSS0 DPI2 is connected
+	 * to DSI DPI0. This is the only supported configuration on
+	 * J721E.
+	 */
+	writel(DSI_WRAP_DPI_0_EN, dsi->j721e_regs + DSI_WRAP_DPI_CONTROL);
+}
+
+static void cdns_dsi_j721e_disable(struct cdns_dsi *dsi)
+{
+	/* Put everything to defaults  */
+	writel(0, dsi->j721e_regs + DSI_WRAP_DPI_CONTROL);
+}
+
+const struct cdns_dsi_platform_ops dsi_ti_j721e_ops = {
+	.init = cdns_dsi_j721e_init,
+	.enable = cdns_dsi_j721e_enable,
+	.disable = cdns_dsi_j721e_disable,
+};
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.h b/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.h
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-j721e.h	2024-01-28 14:01:31.240353775 -0500
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * TI j721e Cadence DSI wrapper
+ *
+ * Copyright (C) 2022 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Rahul T R <r-ravikumar@ti.com>
+ */
+
+#ifndef __CDNS_DSI_J721E_H__
+#define __CDNS_DSI_J721E_H__
+
+#include "cdns-dsi-core.h"
+
+extern const struct cdns_dsi_platform_ops dsi_ti_j721e_ops;
+
+#endif /* !__CDNS_DSI_J721E_H__ */
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c	2024-01-28 14:01:31.240353775 -0500
@@ -55,6 +55,8 @@
 #include "cdns-mhdp8546-hdcp.h"
 #include "cdns-mhdp8546-j721e.h"
 
+static int cdns_mhdp_update_link_status(struct cdns_mhdp_device *mhdp);
+
 static int cdns_mhdp_mailbox_read(struct cdns_mhdp_device *mhdp)
 {
 	int ret, empty;
@@ -750,7 +752,7 @@
 	 * MHDP_HW_STOPPED happens only due to driver removal when
 	 * bridge should already be detached.
 	 */
-	if (mhdp->bridge_attached)
+	if (mhdp->bridge_attached && !mhdp->no_hpd)
 		writel(~(u32)CDNS_APB_INT_MASK_SW_EVENT_INT,
 		       mhdp->regs + CDNS_APB_INT_MASK);
 
@@ -846,7 +848,7 @@
 		ret = cdns_mhdp_dpcd_read(mhdp, msg->address,
 					  msg->buffer, msg->size);
 		if (ret) {
-			dev_err(mhdp->dev,
+			dev_dbg(mhdp->dev,
 				"Failed to read DPCD addr %u\n",
 				msg->address);
 
@@ -1739,6 +1741,19 @@
 
 	spin_unlock(&mhdp->start_lock);
 
+	if (mhdp->no_hpd) {
+		ret = wait_event_timeout(mhdp->fw_load_wq,
+					 mhdp->hw_state == MHDP_HW_READY,
+					 msecs_to_jiffies(100));
+		if (ret == 0) {
+			dev_err(mhdp->dev, "%s: Timeout waiting for fw loading\n",
+				__func__);
+			return -ETIMEDOUT;
+		}
+
+		cdns_mhdp_update_link_status(mhdp);
+		return 0;
+	}
 	/* Enable SW event interrupts */
 	if (hw_ready)
 		writel(~(u32)CDNS_APB_INT_MASK_SW_EVENT_INT,
@@ -2257,7 +2272,16 @@
 
 	mutex_lock(&mhdp->link_mutex);
 
-	mhdp->plugged = cdns_mhdp_detect_hpd(mhdp, &hpd_pulse);
+	if (mhdp->no_hpd) {
+		ret = drm_dp_dpcd_read_link_status(&mhdp->aux, status);
+		hpd_pulse = false;
+		if (ret < 0)
+			mhdp->plugged = false;
+		else
+			mhdp->plugged = true;
+	} else {
+		mhdp->plugged = cdns_mhdp_detect_hpd(mhdp, &hpd_pulse);
+	}
 
 	if (!mhdp->plugged) {
 		cdns_mhdp_link_down(mhdp);
@@ -2452,6 +2476,8 @@
 	mhdp->aux.dev = dev;
 	mhdp->aux.transfer = cdns_mhdp_transfer;
 
+	mhdp->no_hpd = of_property_read_bool(dev->of_node, "cdns,no-hpd");
+
 	mhdp->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(mhdp->regs)) {
 		dev_err(dev, "Failed to get memory resource\n");
@@ -2527,8 +2553,9 @@
 
 	mhdp->bridge.of_node = pdev->dev.of_node;
 	mhdp->bridge.funcs = &cdns_mhdp_bridge_funcs;
-	mhdp->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID |
-			   DRM_BRIDGE_OP_HPD;
+	mhdp->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID;
+	if (!mhdp->no_hpd)
+		mhdp->bridge.ops |= DRM_BRIDGE_OP_HPD;
 	mhdp->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
 	if (mhdp->info)
 		mhdp->bridge.timings = mhdp->info->timings;
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.h	2024-01-28 14:01:31.240353775 -0500
@@ -388,6 +388,7 @@
 
 	bool link_up;
 	bool plugged;
+	bool no_hpd;
 
 	/*
 	 * "start_lock" protects the access to bridge_attached and
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/cadence/Kconfig b/drivers/gpu/drm/bridge/cadence/Kconfig
--- a/drivers/gpu/drm/bridge/cadence/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/bridge/cadence/Kconfig	2024-01-28 14:01:31.240353775 -0500
@@ -1,4 +1,25 @@
 # SPDX-License-Identifier: GPL-2.0-only
+config DRM_CDNS_DSI
+	tristate "Cadence DPI/DSI bridge"
+	select DRM_KMS_HELPER
+	select DRM_MIPI_DSI
+	select DRM_PANEL_BRIDGE
+	select GENERIC_PHY_MIPI_DPHY
+	depends on OF
+	help
+	  Support Cadence DPI to DSI bridge. This is an internal
+	  bridge and is meant to be directly embedded in a SoC.
+
+if DRM_CDNS_DSI
+
+config DRM_CDNS_DSI_J721E
+	bool "J721E Cadence DSI wrapper support"
+	default y
+	help
+	  Support J721E Cadence DSI wrapper. The wrapper manages
+	  the routing of the DSS DPI signal to the Cadence DSI.
+endif
+
 config DRM_CDNS_MHDP8546
 	tristate "Cadence DPI/DP bridge"
 	select DRM_DISPLAY_DP_HELPER
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/cadence/Makefile b/drivers/gpu/drm/bridge/cadence/Makefile
--- a/drivers/gpu/drm/bridge/cadence/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/bridge/cadence/Makefile	2024-01-28 14:01:31.240353775 -0500
@@ -1,4 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
+cdns-dsi-y := cdns-dsi-core.o
+cdns-dsi-$(CONFIG_DRM_CDNS_DSI_J721E) += cdns-dsi-j721e.o
 obj-$(CONFIG_DRM_CDNS_MHDP8546) += cdns-mhdp8546.o
 cdns-mhdp8546-y := cdns-mhdp8546-core.o cdns-mhdp8546-hdcp.o
 cdns-mhdp8546-$(CONFIG_DRM_CDNS_MHDP8546_J721E) += cdns-mhdp8546-j721e.o
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c
--- a/drivers/gpu/drm/bridge/cdns-dsi.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/bridge/cdns-dsi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1330 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright: 2017 Cadence Design Systems, Inc.
- *
- * Author: Boris Brezillon <boris.brezillon@bootlin.com>
- */
-
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_bridge.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_mipi_dsi.h>
-#include <drm/drm_panel.h>
-#include <drm/drm_probe_helper.h>
-#include <video/mipi_display.h>
-
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/iopoll.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_graph.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/reset.h>
-
-#include <linux/phy/phy.h>
-#include <linux/phy/phy-mipi-dphy.h>
-
-#define IP_CONF				0x0
-#define SP_HS_FIFO_DEPTH(x)		(((x) & GENMASK(30, 26)) >> 26)
-#define SP_LP_FIFO_DEPTH(x)		(((x) & GENMASK(25, 21)) >> 21)
-#define VRS_FIFO_DEPTH(x)		(((x) & GENMASK(20, 16)) >> 16)
-#define DIRCMD_FIFO_DEPTH(x)		(((x) & GENMASK(15, 13)) >> 13)
-#define SDI_IFACE_32			BIT(12)
-#define INTERNAL_DATAPATH_32		(0 << 10)
-#define INTERNAL_DATAPATH_16		(1 << 10)
-#define INTERNAL_DATAPATH_8		(3 << 10)
-#define INTERNAL_DATAPATH_SIZE		((x) & GENMASK(11, 10))
-#define NUM_IFACE(x)			((((x) & GENMASK(9, 8)) >> 8) + 1)
-#define MAX_LANE_NB(x)			(((x) & GENMASK(7, 6)) >> 6)
-#define RX_FIFO_DEPTH(x)		((x) & GENMASK(5, 0))
-
-#define MCTL_MAIN_DATA_CTL		0x4
-#define TE_MIPI_POLLING_EN		BIT(25)
-#define TE_HW_POLLING_EN		BIT(24)
-#define DISP_EOT_GEN			BIT(18)
-#define HOST_EOT_GEN			BIT(17)
-#define DISP_GEN_CHECKSUM		BIT(16)
-#define DISP_GEN_ECC			BIT(15)
-#define BTA_EN				BIT(14)
-#define READ_EN				BIT(13)
-#define REG_TE_EN			BIT(12)
-#define IF_TE_EN(x)			BIT(8 + (x))
-#define TVG_SEL				BIT(6)
-#define VID_EN				BIT(5)
-#define IF_VID_SELECT(x)		((x) << 2)
-#define IF_VID_SELECT_MASK		GENMASK(3, 2)
-#define IF_VID_MODE			BIT(1)
-#define LINK_EN				BIT(0)
-
-#define MCTL_MAIN_PHY_CTL		0x8
-#define HS_INVERT_DAT(x)		BIT(19 + ((x) * 2))
-#define SWAP_PINS_DAT(x)		BIT(18 + ((x) * 2))
-#define HS_INVERT_CLK			BIT(17)
-#define SWAP_PINS_CLK			BIT(16)
-#define HS_SKEWCAL_EN			BIT(15)
-#define WAIT_BURST_TIME(x)		((x) << 10)
-#define DATA_ULPM_EN(x)			BIT(6 + (x))
-#define CLK_ULPM_EN			BIT(5)
-#define CLK_CONTINUOUS			BIT(4)
-#define DATA_LANE_EN(x)			BIT((x) - 1)
-
-#define MCTL_MAIN_EN			0xc
-#define DATA_FORCE_STOP			BIT(17)
-#define CLK_FORCE_STOP			BIT(16)
-#define IF_EN(x)			BIT(13 + (x))
-#define DATA_LANE_ULPM_REQ(l)		BIT(9 + (l))
-#define CLK_LANE_ULPM_REQ		BIT(8)
-#define DATA_LANE_START(x)		BIT(4 + (x))
-#define CLK_LANE_EN			BIT(3)
-#define PLL_START			BIT(0)
-
-#define MCTL_DPHY_CFG0			0x10
-#define DPHY_C_RSTB			BIT(20)
-#define DPHY_D_RSTB(x)			GENMASK(15 + (x), 16)
-#define DPHY_PLL_PDN			BIT(10)
-#define DPHY_CMN_PDN			BIT(9)
-#define DPHY_C_PDN			BIT(8)
-#define DPHY_D_PDN(x)			GENMASK(3 + (x), 4)
-#define DPHY_ALL_D_PDN			GENMASK(7, 4)
-#define DPHY_PLL_PSO			BIT(1)
-#define DPHY_CMN_PSO			BIT(0)
-
-#define MCTL_DPHY_TIMEOUT1		0x14
-#define HSTX_TIMEOUT(x)			((x) << 4)
-#define HSTX_TIMEOUT_MAX		GENMASK(17, 0)
-#define CLK_DIV(x)			(x)
-#define CLK_DIV_MAX			GENMASK(3, 0)
-
-#define MCTL_DPHY_TIMEOUT2		0x18
-#define LPRX_TIMEOUT(x)			(x)
-
-#define MCTL_ULPOUT_TIME		0x1c
-#define DATA_LANE_ULPOUT_TIME(x)	((x) << 9)
-#define CLK_LANE_ULPOUT_TIME(x)		(x)
-
-#define MCTL_3DVIDEO_CTL		0x20
-#define VID_VSYNC_3D_EN			BIT(7)
-#define VID_VSYNC_3D_LR			BIT(5)
-#define VID_VSYNC_3D_SECOND_EN		BIT(4)
-#define VID_VSYNC_3DFORMAT_LINE		(0 << 2)
-#define VID_VSYNC_3DFORMAT_FRAME	(1 << 2)
-#define VID_VSYNC_3DFORMAT_PIXEL	(2 << 2)
-#define VID_VSYNC_3DMODE_OFF		0
-#define VID_VSYNC_3DMODE_PORTRAIT	1
-#define VID_VSYNC_3DMODE_LANDSCAPE	2
-
-#define MCTL_MAIN_STS			0x24
-#define MCTL_MAIN_STS_CTL		0x130
-#define MCTL_MAIN_STS_CLR		0x150
-#define MCTL_MAIN_STS_FLAG		0x170
-#define HS_SKEWCAL_DONE			BIT(11)
-#define IF_UNTERM_PKT_ERR(x)		BIT(8 + (x))
-#define LPRX_TIMEOUT_ERR		BIT(7)
-#define HSTX_TIMEOUT_ERR		BIT(6)
-#define DATA_LANE_RDY(l)		BIT(2 + (l))
-#define CLK_LANE_RDY			BIT(1)
-#define PLL_LOCKED			BIT(0)
-
-#define MCTL_DPHY_ERR			0x28
-#define MCTL_DPHY_ERR_CTL1		0x148
-#define MCTL_DPHY_ERR_CLR		0x168
-#define MCTL_DPHY_ERR_FLAG		0x188
-#define ERR_CONT_LP(x, l)		BIT(18 + ((x) * 4) + (l))
-#define ERR_CONTROL(l)			BIT(14 + (l))
-#define ERR_SYNESC(l)			BIT(10 + (l))
-#define ERR_ESC(l)			BIT(6 + (l))
-
-#define MCTL_DPHY_ERR_CTL2		0x14c
-#define ERR_CONT_LP_EDGE(x, l)		BIT(12 + ((x) * 4) + (l))
-#define ERR_CONTROL_EDGE(l)		BIT(8 + (l))
-#define ERR_SYN_ESC_EDGE(l)		BIT(4 + (l))
-#define ERR_ESC_EDGE(l)			BIT(0 + (l))
-
-#define MCTL_LANE_STS			0x2c
-#define PPI_C_TX_READY_HS		BIT(18)
-#define DPHY_PLL_LOCK			BIT(17)
-#define PPI_D_RX_ULPS_ESC(x)		(((x) & GENMASK(15, 12)) >> 12)
-#define LANE_STATE_START		0
-#define LANE_STATE_IDLE			1
-#define LANE_STATE_WRITE		2
-#define LANE_STATE_ULPM			3
-#define LANE_STATE_READ			4
-#define DATA_LANE_STATE(l, val)		\
-	(((val) >> (2 + 2 * (l) + ((l) ? 1 : 0))) & GENMASK((l) ? 1 : 2, 0))
-#define CLK_LANE_STATE_HS		2
-#define CLK_LANE_STATE(val)		((val) & GENMASK(1, 0))
-
-#define DSC_MODE_CTL			0x30
-#define DSC_MODE_EN			BIT(0)
-
-#define DSC_CMD_SEND			0x34
-#define DSC_SEND_PPS			BIT(0)
-#define DSC_EXECUTE_QUEUE		BIT(1)
-
-#define DSC_PPS_WRDAT			0x38
-
-#define DSC_MODE_STS			0x3c
-#define DSC_PPS_DONE			BIT(1)
-#define DSC_EXEC_DONE			BIT(2)
-
-#define CMD_MODE_CTL			0x70
-#define IF_LP_EN(x)			BIT(9 + (x))
-#define IF_VCHAN_ID(x, c)		((c) << ((x) * 2))
-
-#define CMD_MODE_CTL2			0x74
-#define TE_TIMEOUT(x)			((x) << 11)
-#define FILL_VALUE(x)			((x) << 3)
-#define ARB_IF_WITH_HIGHEST_PRIORITY(x)	((x) << 1)
-#define ARB_ROUND_ROBIN_MODE		BIT(0)
-
-#define CMD_MODE_STS			0x78
-#define CMD_MODE_STS_CTL		0x134
-#define CMD_MODE_STS_CLR		0x154
-#define CMD_MODE_STS_FLAG		0x174
-#define ERR_IF_UNDERRUN(x)		BIT(4 + (x))
-#define ERR_UNWANTED_READ		BIT(3)
-#define ERR_TE_MISS			BIT(2)
-#define ERR_NO_TE			BIT(1)
-#define CSM_RUNNING			BIT(0)
-
-#define DIRECT_CMD_SEND			0x80
-
-#define DIRECT_CMD_MAIN_SETTINGS	0x84
-#define TRIGGER_VAL(x)			((x) << 25)
-#define CMD_LP_EN			BIT(24)
-#define CMD_SIZE(x)			((x) << 16)
-#define CMD_VCHAN_ID(x)			((x) << 14)
-#define CMD_DATATYPE(x)			((x) << 8)
-#define CMD_LONG			BIT(3)
-#define WRITE_CMD			0
-#define READ_CMD			1
-#define TE_REQ				4
-#define TRIGGER_REQ			5
-#define BTA_REQ				6
-
-#define DIRECT_CMD_STS			0x88
-#define DIRECT_CMD_STS_CTL		0x138
-#define DIRECT_CMD_STS_CLR		0x158
-#define DIRECT_CMD_STS_FLAG		0x178
-#define RCVD_ACK_VAL(val)		((val) >> 16)
-#define RCVD_TRIGGER_VAL(val)		(((val) & GENMASK(14, 11)) >> 11)
-#define READ_COMPLETED_WITH_ERR		BIT(10)
-#define BTA_FINISHED			BIT(9)
-#define BTA_COMPLETED			BIT(8)
-#define TE_RCVD				BIT(7)
-#define TRIGGER_RCVD			BIT(6)
-#define ACK_WITH_ERR_RCVD		BIT(5)
-#define ACK_RCVD			BIT(4)
-#define READ_COMPLETED			BIT(3)
-#define TRIGGER_COMPLETED		BIT(2)
-#define WRITE_COMPLETED			BIT(1)
-#define SENDING_CMD			BIT(0)
-
-#define DIRECT_CMD_STOP_READ		0x8c
-
-#define DIRECT_CMD_WRDATA		0x90
-
-#define DIRECT_CMD_FIFO_RST		0x94
-
-#define DIRECT_CMD_RDDATA		0xa0
-
-#define DIRECT_CMD_RD_PROPS		0xa4
-#define RD_DCS				BIT(18)
-#define RD_VCHAN_ID(val)		(((val) >> 16) & GENMASK(1, 0))
-#define RD_SIZE(val)			((val) & GENMASK(15, 0))
-
-#define DIRECT_CMD_RD_STS		0xa8
-#define DIRECT_CMD_RD_STS_CTL		0x13c
-#define DIRECT_CMD_RD_STS_CLR		0x15c
-#define DIRECT_CMD_RD_STS_FLAG		0x17c
-#define ERR_EOT_WITH_ERR		BIT(8)
-#define ERR_MISSING_EOT			BIT(7)
-#define ERR_WRONG_LENGTH		BIT(6)
-#define ERR_OVERSIZE			BIT(5)
-#define ERR_RECEIVE			BIT(4)
-#define ERR_UNDECODABLE			BIT(3)
-#define ERR_CHECKSUM			BIT(2)
-#define ERR_UNCORRECTABLE		BIT(1)
-#define ERR_FIXED			BIT(0)
-
-#define VID_MAIN_CTL			0xb0
-#define VID_IGNORE_MISS_VSYNC		BIT(31)
-#define VID_FIELD_SW			BIT(28)
-#define VID_INTERLACED_EN		BIT(27)
-#define RECOVERY_MODE(x)		((x) << 25)
-#define RECOVERY_MODE_NEXT_HSYNC	0
-#define RECOVERY_MODE_NEXT_STOP_POINT	2
-#define RECOVERY_MODE_NEXT_VSYNC	3
-#define REG_BLKEOL_MODE(x)		((x) << 23)
-#define REG_BLKLINE_MODE(x)		((x) << 21)
-#define REG_BLK_MODE_NULL_PKT		0
-#define REG_BLK_MODE_BLANKING_PKT	1
-#define REG_BLK_MODE_LP			2
-#define SYNC_PULSE_HORIZONTAL		BIT(20)
-#define SYNC_PULSE_ACTIVE		BIT(19)
-#define BURST_MODE			BIT(18)
-#define VID_PIXEL_MODE_MASK		GENMASK(17, 14)
-#define VID_PIXEL_MODE_RGB565		(0 << 14)
-#define VID_PIXEL_MODE_RGB666_PACKED	(1 << 14)
-#define VID_PIXEL_MODE_RGB666		(2 << 14)
-#define VID_PIXEL_MODE_RGB888		(3 << 14)
-#define VID_PIXEL_MODE_RGB101010	(4 << 14)
-#define VID_PIXEL_MODE_RGB121212	(5 << 14)
-#define VID_PIXEL_MODE_YUV420		(8 << 14)
-#define VID_PIXEL_MODE_YUV422_PACKED	(9 << 14)
-#define VID_PIXEL_MODE_YUV422		(10 << 14)
-#define VID_PIXEL_MODE_YUV422_24B	(11 << 14)
-#define VID_PIXEL_MODE_DSC_COMP		(12 << 14)
-#define VID_DATATYPE(x)			((x) << 8)
-#define VID_VIRTCHAN_ID(iface, x)	((x) << (4 + (iface) * 2))
-#define STOP_MODE(x)			((x) << 2)
-#define START_MODE(x)			(x)
-
-#define VID_VSIZE1			0xb4
-#define VFP_LEN(x)			((x) << 12)
-#define VBP_LEN(x)			((x) << 6)
-#define VSA_LEN(x)			(x)
-
-#define VID_VSIZE2			0xb8
-#define VACT_LEN(x)			(x)
-
-#define VID_HSIZE1			0xc0
-#define HBP_LEN(x)			((x) << 16)
-#define HSA_LEN(x)			(x)
-
-#define VID_HSIZE2			0xc4
-#define HFP_LEN(x)			((x) << 16)
-#define HACT_LEN(x)			(x)
-
-#define VID_BLKSIZE1			0xcc
-#define BLK_EOL_PKT_LEN(x)		((x) << 15)
-#define BLK_LINE_EVENT_PKT_LEN(x)	(x)
-
-#define VID_BLKSIZE2			0xd0
-#define BLK_LINE_PULSE_PKT_LEN(x)	(x)
-
-#define VID_PKT_TIME			0xd8
-#define BLK_EOL_DURATION(x)		(x)
-
-#define VID_DPHY_TIME			0xdc
-#define REG_WAKEUP_TIME(x)		((x) << 17)
-#define REG_LINE_DURATION(x)		(x)
-
-#define VID_ERR_COLOR1			0xe0
-#define COL_GREEN(x)			((x) << 12)
-#define COL_RED(x)			(x)
-
-#define VID_ERR_COLOR2			0xe4
-#define PAD_VAL(x)			((x) << 12)
-#define COL_BLUE(x)			(x)
-
-#define VID_VPOS			0xe8
-#define LINE_VAL(val)			(((val) & GENMASK(14, 2)) >> 2)
-#define LINE_POS(val)			((val) & GENMASK(1, 0))
-
-#define VID_HPOS			0xec
-#define HORIZ_VAL(val)			(((val) & GENMASK(17, 3)) >> 3)
-#define HORIZ_POS(val)			((val) & GENMASK(2, 0))
-
-#define VID_MODE_STS			0xf0
-#define VID_MODE_STS_CTL		0x140
-#define VID_MODE_STS_CLR		0x160
-#define VID_MODE_STS_FLAG		0x180
-#define VSG_RECOVERY			BIT(10)
-#define ERR_VRS_WRONG_LEN		BIT(9)
-#define ERR_LONG_READ			BIT(8)
-#define ERR_LINE_WRITE			BIT(7)
-#define ERR_BURST_WRITE			BIT(6)
-#define ERR_SMALL_HEIGHT		BIT(5)
-#define ERR_SMALL_LEN			BIT(4)
-#define ERR_MISSING_VSYNC		BIT(3)
-#define ERR_MISSING_HSYNC		BIT(2)
-#define ERR_MISSING_DATA		BIT(1)
-#define VSG_RUNNING			BIT(0)
-
-#define VID_VCA_SETTING1		0xf4
-#define BURST_LP			BIT(16)
-#define MAX_BURST_LIMIT(x)		(x)
-
-#define VID_VCA_SETTING2		0xf8
-#define MAX_LINE_LIMIT(x)		((x) << 16)
-#define EXACT_BURST_LIMIT(x)		(x)
-
-#define TVG_CTL				0xfc
-#define TVG_STRIPE_SIZE(x)		((x) << 5)
-#define TVG_MODE_MASK			GENMASK(4, 3)
-#define TVG_MODE_SINGLE_COLOR		(0 << 3)
-#define TVG_MODE_VSTRIPES		(2 << 3)
-#define TVG_MODE_HSTRIPES		(3 << 3)
-#define TVG_STOPMODE_MASK		GENMASK(2, 1)
-#define TVG_STOPMODE_EOF		(0 << 1)
-#define TVG_STOPMODE_EOL		(1 << 1)
-#define TVG_STOPMODE_NOW		(2 << 1)
-#define TVG_RUN				BIT(0)
-
-#define TVG_IMG_SIZE			0x100
-#define TVG_NBLINES(x)			((x) << 16)
-#define TVG_LINE_SIZE(x)		(x)
-
-#define TVG_COLOR1			0x104
-#define TVG_COL1_GREEN(x)		((x) << 12)
-#define TVG_COL1_RED(x)			(x)
-
-#define TVG_COLOR1_BIS			0x108
-#define TVG_COL1_BLUE(x)		(x)
-
-#define TVG_COLOR2			0x10c
-#define TVG_COL2_GREEN(x)		((x) << 12)
-#define TVG_COL2_RED(x)			(x)
-
-#define TVG_COLOR2_BIS			0x110
-#define TVG_COL2_BLUE(x)		(x)
-
-#define TVG_STS				0x114
-#define TVG_STS_CTL			0x144
-#define TVG_STS_CLR			0x164
-#define TVG_STS_FLAG			0x184
-#define TVG_STS_RUNNING			BIT(0)
-
-#define STS_CTL_EDGE(e)			((e) << 16)
-
-#define DPHY_LANES_MAP			0x198
-#define DAT_REMAP_CFG(b, l)		((l) << ((b) * 8))
-
-#define DPI_IRQ_EN			0x1a0
-#define DPI_IRQ_CLR			0x1a4
-#define DPI_IRQ_STS			0x1a8
-#define PIXEL_BUF_OVERFLOW		BIT(0)
-
-#define DPI_CFG				0x1ac
-#define DPI_CFG_FIFO_DEPTH(x)		((x) >> 16)
-#define DPI_CFG_FIFO_LEVEL(x)		((x) & GENMASK(15, 0))
-
-#define TEST_GENERIC			0x1f0
-#define TEST_STATUS(x)			((x) >> 16)
-#define TEST_CTRL(x)			(x)
-
-#define ID_REG				0x1fc
-#define REV_VENDOR_ID(x)		(((x) & GENMASK(31, 20)) >> 20)
-#define REV_PRODUCT_ID(x)		(((x) & GENMASK(19, 12)) >> 12)
-#define REV_HW(x)			(((x) & GENMASK(11, 8)) >> 8)
-#define REV_MAJOR(x)			(((x) & GENMASK(7, 4)) >> 4)
-#define REV_MINOR(x)			((x) & GENMASK(3, 0))
-
-#define DSI_OUTPUT_PORT			0
-#define DSI_INPUT_PORT(inputid)		(1 + (inputid))
-
-#define DSI_HBP_FRAME_OVERHEAD		12
-#define DSI_HSA_FRAME_OVERHEAD		14
-#define DSI_HFP_FRAME_OVERHEAD		6
-#define DSI_HSS_VSS_VSE_FRAME_OVERHEAD	4
-#define DSI_BLANKING_FRAME_OVERHEAD	6
-#define DSI_NULL_FRAME_OVERHEAD		6
-#define DSI_EOT_PKT_SIZE		4
-
-struct cdns_dsi_output {
-	struct mipi_dsi_device *dev;
-	struct drm_panel *panel;
-	struct drm_bridge *bridge;
-	union phy_configure_opts phy_opts;
-};
-
-enum cdns_dsi_input_id {
-	CDNS_SDI_INPUT,
-	CDNS_DPI_INPUT,
-	CDNS_DSC_INPUT,
-};
-
-struct cdns_dsi_cfg {
-	unsigned int hfp;
-	unsigned int hsa;
-	unsigned int hbp;
-	unsigned int hact;
-	unsigned int htotal;
-};
-
-struct cdns_dsi_input {
-	enum cdns_dsi_input_id id;
-	struct drm_bridge bridge;
-};
-
-struct cdns_dsi {
-	struct mipi_dsi_host base;
-	void __iomem *regs;
-	struct cdns_dsi_input input;
-	struct cdns_dsi_output output;
-	unsigned int direct_cmd_fifo_depth;
-	unsigned int rx_fifo_depth;
-	struct completion direct_cmd_comp;
-	struct clk *dsi_p_clk;
-	struct reset_control *dsi_p_rst;
-	struct clk *dsi_sys_clk;
-	bool link_initialized;
-	bool phy_initialized;
-	struct phy *dphy;
-};
-
-static inline struct cdns_dsi *input_to_dsi(struct cdns_dsi_input *input)
-{
-	return container_of(input, struct cdns_dsi, input);
-}
-
-static inline struct cdns_dsi *to_cdns_dsi(struct mipi_dsi_host *host)
-{
-	return container_of(host, struct cdns_dsi, base);
-}
-
-static inline struct cdns_dsi_input *
-bridge_to_cdns_dsi_input(struct drm_bridge *bridge)
-{
-	return container_of(bridge, struct cdns_dsi_input, bridge);
-}
-
-static unsigned int mode_to_dpi_hfp(const struct drm_display_mode *mode,
-				    bool mode_valid_check)
-{
-	if (mode_valid_check)
-		return mode->hsync_start - mode->hdisplay;
-
-	return mode->crtc_hsync_start - mode->crtc_hdisplay;
-}
-
-static unsigned int dpi_to_dsi_timing(unsigned int dpi_timing,
-				      unsigned int dpi_bpp,
-				      unsigned int dsi_pkt_overhead)
-{
-	unsigned int dsi_timing = DIV_ROUND_UP(dpi_timing * dpi_bpp, 8);
-
-	if (dsi_timing < dsi_pkt_overhead)
-		dsi_timing = 0;
-	else
-		dsi_timing -= dsi_pkt_overhead;
-
-	return dsi_timing;
-}
-
-static int cdns_dsi_mode2cfg(struct cdns_dsi *dsi,
-			     const struct drm_display_mode *mode,
-			     struct cdns_dsi_cfg *dsi_cfg,
-			     bool mode_valid_check)
-{
-	struct cdns_dsi_output *output = &dsi->output;
-	unsigned int tmp;
-	bool sync_pulse = false;
-	int bpp;
-
-	memset(dsi_cfg, 0, sizeof(*dsi_cfg));
-
-	if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
-		sync_pulse = true;
-
-	bpp = mipi_dsi_pixel_format_to_bpp(output->dev->format);
-
-	if (mode_valid_check)
-		tmp = mode->htotal -
-		      (sync_pulse ? mode->hsync_end : mode->hsync_start);
-	else
-		tmp = mode->crtc_htotal -
-		      (sync_pulse ?
-		       mode->crtc_hsync_end : mode->crtc_hsync_start);
-
-	dsi_cfg->hbp = dpi_to_dsi_timing(tmp, bpp, DSI_HBP_FRAME_OVERHEAD);
-
-	if (sync_pulse) {
-		if (mode_valid_check)
-			tmp = mode->hsync_end - mode->hsync_start;
-		else
-			tmp = mode->crtc_hsync_end - mode->crtc_hsync_start;
-
-		dsi_cfg->hsa = dpi_to_dsi_timing(tmp, bpp,
-						 DSI_HSA_FRAME_OVERHEAD);
-	}
-
-	dsi_cfg->hact = dpi_to_dsi_timing(mode_valid_check ?
-					  mode->hdisplay : mode->crtc_hdisplay,
-					  bpp, 0);
-	dsi_cfg->hfp = dpi_to_dsi_timing(mode_to_dpi_hfp(mode, mode_valid_check),
-					 bpp, DSI_HFP_FRAME_OVERHEAD);
-
-	return 0;
-}
-
-static int cdns_dsi_adjust_phy_config(struct cdns_dsi *dsi,
-			      struct cdns_dsi_cfg *dsi_cfg,
-			      struct phy_configure_opts_mipi_dphy *phy_cfg,
-			      const struct drm_display_mode *mode,
-			      bool mode_valid_check)
-{
-	struct cdns_dsi_output *output = &dsi->output;
-	unsigned long long dlane_bps;
-	unsigned long adj_dsi_htotal;
-	unsigned long dsi_htotal;
-	unsigned long dpi_htotal;
-	unsigned long dpi_hz;
-	unsigned int dsi_hfp_ext;
-	unsigned int lanes = output->dev->lanes;
-
-	dsi_htotal = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
-	if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
-		dsi_htotal += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
-
-	dsi_htotal += dsi_cfg->hact;
-	dsi_htotal += dsi_cfg->hfp + DSI_HFP_FRAME_OVERHEAD;
-
-	/*
-	 * Make sure DSI htotal is aligned on a lane boundary when calculating
-	 * the expected data rate. This is done by extending HFP in case of
-	 * misalignment.
-	 */
-	adj_dsi_htotal = dsi_htotal;
-	if (dsi_htotal % lanes)
-		adj_dsi_htotal += lanes - (dsi_htotal % lanes);
-
-	dpi_hz = (mode_valid_check ? mode->clock : mode->crtc_clock) * 1000;
-	dlane_bps = (unsigned long long)dpi_hz * adj_dsi_htotal;
-
-	/* data rate in bytes/sec is not an integer, refuse the mode. */
-	dpi_htotal = mode_valid_check ? mode->htotal : mode->crtc_htotal;
-	if (do_div(dlane_bps, lanes * dpi_htotal))
-		return -EINVAL;
-
-	/* data rate was in bytes/sec, convert to bits/sec. */
-	phy_cfg->hs_clk_rate = dlane_bps * 8;
-
-	dsi_hfp_ext = adj_dsi_htotal - dsi_htotal;
-	dsi_cfg->hfp += dsi_hfp_ext;
-	dsi_cfg->htotal = dsi_htotal + dsi_hfp_ext;
-
-	return 0;
-}
-
-static int cdns_dsi_check_conf(struct cdns_dsi *dsi,
-			       const struct drm_display_mode *mode,
-			       struct cdns_dsi_cfg *dsi_cfg,
-			       bool mode_valid_check)
-{
-	struct cdns_dsi_output *output = &dsi->output;
-	struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
-	unsigned long dsi_hss_hsa_hse_hbp;
-	unsigned int nlanes = output->dev->lanes;
-	int ret;
-
-	ret = cdns_dsi_mode2cfg(dsi, mode, dsi_cfg, mode_valid_check);
-	if (ret)
-		return ret;
-
-	phy_mipi_dphy_get_default_config(mode->crtc_clock * 1000,
-					 mipi_dsi_pixel_format_to_bpp(output->dev->format),
-					 nlanes, phy_cfg);
-
-	ret = cdns_dsi_adjust_phy_config(dsi, dsi_cfg, phy_cfg, mode, mode_valid_check);
-	if (ret)
-		return ret;
-
-	ret = phy_validate(dsi->dphy, PHY_MODE_MIPI_DPHY, 0, &output->phy_opts);
-	if (ret)
-		return ret;
-
-	dsi_hss_hsa_hse_hbp = dsi_cfg->hbp + DSI_HBP_FRAME_OVERHEAD;
-	if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
-		dsi_hss_hsa_hse_hbp += dsi_cfg->hsa + DSI_HSA_FRAME_OVERHEAD;
-
-	/*
-	 * Make sure DPI(HFP) > DSI(HSS+HSA+HSE+HBP) to guarantee that the FIFO
-	 * is empty before we start a receiving a new line on the DPI
-	 * interface.
-	 */
-	if ((u64)phy_cfg->hs_clk_rate *
-	    mode_to_dpi_hfp(mode, mode_valid_check) * nlanes <
-	    (u64)dsi_hss_hsa_hse_hbp *
-	    (mode_valid_check ? mode->clock : mode->crtc_clock) * 1000)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int cdns_dsi_bridge_attach(struct drm_bridge *bridge,
-				  enum drm_bridge_attach_flags flags)
-{
-	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-	struct cdns_dsi *dsi = input_to_dsi(input);
-	struct cdns_dsi_output *output = &dsi->output;
-
-	if (!drm_core_check_feature(bridge->dev, DRIVER_ATOMIC)) {
-		dev_err(dsi->base.dev,
-			"cdns-dsi driver is only compatible with DRM devices supporting atomic updates");
-		return -ENOTSUPP;
-	}
-
-	return drm_bridge_attach(bridge->encoder, output->bridge, bridge,
-				 flags);
-}
-
-static enum drm_mode_status
-cdns_dsi_bridge_mode_valid(struct drm_bridge *bridge,
-			   const struct drm_display_info *info,
-			   const struct drm_display_mode *mode)
-{
-	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-	struct cdns_dsi *dsi = input_to_dsi(input);
-	struct cdns_dsi_output *output = &dsi->output;
-	struct cdns_dsi_cfg dsi_cfg;
-	int bpp, ret;
-
-	/*
-	 * VFP_DSI should be less than VFP_DPI and VFP_DSI should be at
-	 * least 1.
-	 */
-	if (mode->vtotal - mode->vsync_end < 2)
-		return MODE_V_ILLEGAL;
-
-	/* VSA_DSI = VSA_DPI and must be at least 2. */
-	if (mode->vsync_end - mode->vsync_start < 2)
-		return MODE_V_ILLEGAL;
-
-	/* HACT must be 32-bits aligned. */
-	bpp = mipi_dsi_pixel_format_to_bpp(output->dev->format);
-	if ((mode->hdisplay * bpp) % 32)
-		return MODE_H_ILLEGAL;
-
-	ret = cdns_dsi_check_conf(dsi, mode, &dsi_cfg, true);
-	if (ret)
-		return MODE_BAD;
-
-	return MODE_OK;
-}
-
-static void cdns_dsi_bridge_disable(struct drm_bridge *bridge)
-{
-	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-	struct cdns_dsi *dsi = input_to_dsi(input);
-	u32 val;
-
-	val = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
-	val &= ~(IF_VID_SELECT_MASK | IF_VID_MODE | VID_EN | HOST_EOT_GEN |
-		 DISP_EOT_GEN);
-	writel(val, dsi->regs + MCTL_MAIN_DATA_CTL);
-
-	val = readl(dsi->regs + MCTL_MAIN_EN) & ~IF_EN(input->id);
-	writel(val, dsi->regs + MCTL_MAIN_EN);
-	pm_runtime_put(dsi->base.dev);
-}
-
-static void cdns_dsi_bridge_post_disable(struct drm_bridge *bridge)
-{
-	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-	struct cdns_dsi *dsi = input_to_dsi(input);
-
-	pm_runtime_put(dsi->base.dev);
-}
-
-static void cdns_dsi_hs_init(struct cdns_dsi *dsi)
-{
-	struct cdns_dsi_output *output = &dsi->output;
-	u32 status;
-
-	if (dsi->phy_initialized)
-		return;
-	/*
-	 * Power all internal DPHY blocks down and maintain their reset line
-	 * asserted before changing the DPHY config.
-	 */
-	writel(DPHY_CMN_PSO | DPHY_PLL_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN |
-	       DPHY_CMN_PDN | DPHY_PLL_PDN,
-	       dsi->regs + MCTL_DPHY_CFG0);
-
-	phy_init(dsi->dphy);
-	phy_set_mode(dsi->dphy, PHY_MODE_MIPI_DPHY);
-	phy_configure(dsi->dphy, &output->phy_opts);
-	phy_power_on(dsi->dphy);
-
-	/* Activate the PLL and wait until it's locked. */
-	writel(PLL_LOCKED, dsi->regs + MCTL_MAIN_STS_CLR);
-	writel(DPHY_CMN_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN | DPHY_CMN_PDN,
-	       dsi->regs + MCTL_DPHY_CFG0);
-	WARN_ON_ONCE(readl_poll_timeout(dsi->regs + MCTL_MAIN_STS, status,
-					status & PLL_LOCKED, 100, 100));
-	/* De-assert data and clock reset lines. */
-	writel(DPHY_CMN_PSO | DPHY_ALL_D_PDN | DPHY_C_PDN | DPHY_CMN_PDN |
-	       DPHY_D_RSTB(output->dev->lanes) | DPHY_C_RSTB,
-	       dsi->regs + MCTL_DPHY_CFG0);
-	dsi->phy_initialized = true;
-}
-
-static void cdns_dsi_init_link(struct cdns_dsi *dsi)
-{
-	struct cdns_dsi_output *output = &dsi->output;
-	unsigned long sysclk_period, ulpout;
-	u32 val;
-	int i;
-
-	if (dsi->link_initialized)
-		return;
-
-	val = 0;
-	for (i = 1; i < output->dev->lanes; i++)
-		val |= DATA_LANE_EN(i);
-
-	if (!(output->dev->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
-		val |= CLK_CONTINUOUS;
-
-	writel(val, dsi->regs + MCTL_MAIN_PHY_CTL);
-
-	/* ULPOUT should be set to 1ms and is expressed in sysclk cycles. */
-	sysclk_period = NSEC_PER_SEC / clk_get_rate(dsi->dsi_sys_clk);
-	ulpout = DIV_ROUND_UP(NSEC_PER_MSEC, sysclk_period);
-	writel(CLK_LANE_ULPOUT_TIME(ulpout) | DATA_LANE_ULPOUT_TIME(ulpout),
-	       dsi->regs + MCTL_ULPOUT_TIME);
-
-	writel(LINK_EN, dsi->regs + MCTL_MAIN_DATA_CTL);
-
-	val = CLK_LANE_EN | PLL_START;
-	for (i = 0; i < output->dev->lanes; i++)
-		val |= DATA_LANE_START(i);
-
-	writel(val, dsi->regs + MCTL_MAIN_EN);
-
-	dsi->link_initialized = true;
-}
-
-static void cdns_dsi_bridge_enable(struct drm_bridge *bridge)
-{
-	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-	struct cdns_dsi *dsi = input_to_dsi(input);
-	struct cdns_dsi_output *output = &dsi->output;
-	struct drm_display_mode *mode;
-	struct phy_configure_opts_mipi_dphy *phy_cfg = &output->phy_opts.mipi_dphy;
-	unsigned long tx_byte_period;
-	struct cdns_dsi_cfg dsi_cfg;
-	u32 tmp, reg_wakeup, div;
-	int nlanes;
-
-	if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
-		return;
-
-	mode = &bridge->encoder->crtc->state->adjusted_mode;
-	nlanes = output->dev->lanes;
-
-	WARN_ON_ONCE(cdns_dsi_check_conf(dsi, mode, &dsi_cfg, false));
-
-	cdns_dsi_hs_init(dsi);
-	cdns_dsi_init_link(dsi);
-
-	writel(HBP_LEN(dsi_cfg.hbp) | HSA_LEN(dsi_cfg.hsa),
-	       dsi->regs + VID_HSIZE1);
-	writel(HFP_LEN(dsi_cfg.hfp) | HACT_LEN(dsi_cfg.hact),
-	       dsi->regs + VID_HSIZE2);
-
-	writel(VBP_LEN(mode->crtc_vtotal - mode->crtc_vsync_end - 1) |
-	       VFP_LEN(mode->crtc_vsync_start - mode->crtc_vdisplay) |
-	       VSA_LEN(mode->crtc_vsync_end - mode->crtc_vsync_start + 1),
-	       dsi->regs + VID_VSIZE1);
-	writel(mode->crtc_vdisplay, dsi->regs + VID_VSIZE2);
-
-	tmp = dsi_cfg.htotal -
-	      (dsi_cfg.hsa + DSI_BLANKING_FRAME_OVERHEAD +
-	       DSI_HSA_FRAME_OVERHEAD);
-	writel(BLK_LINE_PULSE_PKT_LEN(tmp), dsi->regs + VID_BLKSIZE2);
-	if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
-		writel(MAX_LINE_LIMIT(tmp - DSI_NULL_FRAME_OVERHEAD),
-		       dsi->regs + VID_VCA_SETTING2);
-
-	tmp = dsi_cfg.htotal -
-	      (DSI_HSS_VSS_VSE_FRAME_OVERHEAD + DSI_BLANKING_FRAME_OVERHEAD);
-	writel(BLK_LINE_EVENT_PKT_LEN(tmp), dsi->regs + VID_BLKSIZE1);
-	if (!(output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE))
-		writel(MAX_LINE_LIMIT(tmp - DSI_NULL_FRAME_OVERHEAD),
-		       dsi->regs + VID_VCA_SETTING2);
-
-	tmp = DIV_ROUND_UP(dsi_cfg.htotal, nlanes) -
-	      DIV_ROUND_UP(dsi_cfg.hsa, nlanes);
-
-	if (!(output->dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
-		tmp -= DIV_ROUND_UP(DSI_EOT_PKT_SIZE, nlanes);
-
-	tx_byte_period = DIV_ROUND_DOWN_ULL((u64)NSEC_PER_SEC * 8,
-					    phy_cfg->hs_clk_rate);
-	reg_wakeup = (phy_cfg->hs_prepare + phy_cfg->hs_zero) / tx_byte_period;
-	writel(REG_WAKEUP_TIME(reg_wakeup) | REG_LINE_DURATION(tmp),
-	       dsi->regs + VID_DPHY_TIME);
-
-	/*
-	 * HSTX and LPRX timeouts are both expressed in TX byte clk cycles and
-	 * both should be set to at least the time it takes to transmit a
-	 * frame.
-	 */
-	tmp = NSEC_PER_SEC / drm_mode_vrefresh(mode);
-	tmp /= tx_byte_period;
-
-	for (div = 0; div <= CLK_DIV_MAX; div++) {
-		if (tmp <= HSTX_TIMEOUT_MAX)
-			break;
-
-		tmp >>= 1;
-	}
-
-	if (tmp > HSTX_TIMEOUT_MAX)
-		tmp = HSTX_TIMEOUT_MAX;
-
-	writel(CLK_DIV(div) | HSTX_TIMEOUT(tmp),
-	       dsi->regs + MCTL_DPHY_TIMEOUT1);
-
-	writel(LPRX_TIMEOUT(tmp), dsi->regs + MCTL_DPHY_TIMEOUT2);
-
-	if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO) {
-		switch (output->dev->format) {
-		case MIPI_DSI_FMT_RGB888:
-			tmp = VID_PIXEL_MODE_RGB888 |
-			      VID_DATATYPE(MIPI_DSI_PACKED_PIXEL_STREAM_24);
-			break;
-
-		case MIPI_DSI_FMT_RGB666:
-			tmp = VID_PIXEL_MODE_RGB666 |
-			      VID_DATATYPE(MIPI_DSI_PIXEL_STREAM_3BYTE_18);
-			break;
-
-		case MIPI_DSI_FMT_RGB666_PACKED:
-			tmp = VID_PIXEL_MODE_RGB666_PACKED |
-			      VID_DATATYPE(MIPI_DSI_PACKED_PIXEL_STREAM_18);
-			break;
-
-		case MIPI_DSI_FMT_RGB565:
-			tmp = VID_PIXEL_MODE_RGB565 |
-			      VID_DATATYPE(MIPI_DSI_PACKED_PIXEL_STREAM_16);
-			break;
-
-		default:
-			dev_err(dsi->base.dev, "Unsupported DSI format\n");
-			return;
-		}
-
-		if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
-			tmp |= SYNC_PULSE_ACTIVE | SYNC_PULSE_HORIZONTAL;
-
-		tmp |= REG_BLKLINE_MODE(REG_BLK_MODE_BLANKING_PKT) |
-		       REG_BLKEOL_MODE(REG_BLK_MODE_BLANKING_PKT) |
-		       RECOVERY_MODE(RECOVERY_MODE_NEXT_HSYNC) |
-		       VID_IGNORE_MISS_VSYNC;
-
-		writel(tmp, dsi->regs + VID_MAIN_CTL);
-	}
-
-	tmp = readl(dsi->regs + MCTL_MAIN_DATA_CTL);
-	tmp &= ~(IF_VID_SELECT_MASK | HOST_EOT_GEN | IF_VID_MODE);
-
-	if (!(output->dev->mode_flags & MIPI_DSI_MODE_NO_EOT_PACKET))
-		tmp |= HOST_EOT_GEN;
-
-	if (output->dev->mode_flags & MIPI_DSI_MODE_VIDEO)
-		tmp |= IF_VID_MODE | IF_VID_SELECT(input->id) | VID_EN;
-
-	writel(tmp, dsi->regs + MCTL_MAIN_DATA_CTL);
-
-	tmp = readl(dsi->regs + MCTL_MAIN_EN) | IF_EN(input->id);
-	writel(tmp, dsi->regs + MCTL_MAIN_EN);
-}
-
-static void cdns_dsi_bridge_pre_enable(struct drm_bridge *bridge)
-{
-	struct cdns_dsi_input *input = bridge_to_cdns_dsi_input(bridge);
-	struct cdns_dsi *dsi = input_to_dsi(input);
-
-	if (WARN_ON(pm_runtime_get_sync(dsi->base.dev) < 0))
-		return;
-
-	cdns_dsi_init_link(dsi);
-	cdns_dsi_hs_init(dsi);
-}
-
-static const struct drm_bridge_funcs cdns_dsi_bridge_funcs = {
-	.attach = cdns_dsi_bridge_attach,
-	.mode_valid = cdns_dsi_bridge_mode_valid,
-	.disable = cdns_dsi_bridge_disable,
-	.pre_enable = cdns_dsi_bridge_pre_enable,
-	.enable = cdns_dsi_bridge_enable,
-	.post_disable = cdns_dsi_bridge_post_disable,
-};
-
-static int cdns_dsi_attach(struct mipi_dsi_host *host,
-			   struct mipi_dsi_device *dev)
-{
-	struct cdns_dsi *dsi = to_cdns_dsi(host);
-	struct cdns_dsi_output *output = &dsi->output;
-	struct cdns_dsi_input *input = &dsi->input;
-	struct drm_bridge *bridge;
-	struct drm_panel *panel;
-	struct device_node *np;
-	int ret;
-
-	/*
-	 * We currently do not support connecting several DSI devices to the
-	 * same host. In order to support that we'd need the DRM bridge
-	 * framework to allow dynamic reconfiguration of the bridge chain.
-	 */
-	if (output->dev)
-		return -EBUSY;
-
-	/* We do not support burst mode yet. */
-	if (dev->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
-		return -ENOTSUPP;
-
-	/*
-	 * The host <-> device link might be described using an OF-graph
-	 * representation, in this case we extract the device of_node from
-	 * this representation, otherwise we use dsidev->dev.of_node which
-	 * should have been filled by the core.
-	 */
-	np = of_graph_get_remote_node(dsi->base.dev->of_node, DSI_OUTPUT_PORT,
-				      dev->channel);
-	if (!np)
-		np = of_node_get(dev->dev.of_node);
-
-	panel = of_drm_find_panel(np);
-	if (!IS_ERR(panel)) {
-		bridge = drm_panel_bridge_add_typed(panel,
-						    DRM_MODE_CONNECTOR_DSI);
-	} else {
-		bridge = of_drm_find_bridge(dev->dev.of_node);
-		if (!bridge)
-			bridge = ERR_PTR(-EINVAL);
-	}
-
-	of_node_put(np);
-
-	if (IS_ERR(bridge)) {
-		ret = PTR_ERR(bridge);
-		dev_err(host->dev, "failed to add DSI device %s (err = %d)",
-			dev->name, ret);
-		return ret;
-	}
-
-	output->dev = dev;
-	output->bridge = bridge;
-	output->panel = panel;
-
-	/*
-	 * The DSI output has been properly configured, we can now safely
-	 * register the input to the bridge framework so that it can take place
-	 * in a display pipeline.
-	 */
-	drm_bridge_add(&input->bridge);
-
-	return 0;
-}
-
-static int cdns_dsi_detach(struct mipi_dsi_host *host,
-			   struct mipi_dsi_device *dev)
-{
-	struct cdns_dsi *dsi = to_cdns_dsi(host);
-	struct cdns_dsi_output *output = &dsi->output;
-	struct cdns_dsi_input *input = &dsi->input;
-
-	drm_bridge_remove(&input->bridge);
-	if (output->panel)
-		drm_panel_bridge_remove(output->bridge);
-
-	return 0;
-}
-
-static irqreturn_t cdns_dsi_interrupt(int irq, void *data)
-{
-	struct cdns_dsi *dsi = data;
-	irqreturn_t ret = IRQ_NONE;
-	u32 flag, ctl;
-
-	flag = readl(dsi->regs + DIRECT_CMD_STS_FLAG);
-	if (flag) {
-		ctl = readl(dsi->regs + DIRECT_CMD_STS_CTL);
-		ctl &= ~flag;
-		writel(ctl, dsi->regs + DIRECT_CMD_STS_CTL);
-		complete(&dsi->direct_cmd_comp);
-		ret = IRQ_HANDLED;
-	}
-
-	return ret;
-}
-
-static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host,
-				 const struct mipi_dsi_msg *msg)
-{
-	struct cdns_dsi *dsi = to_cdns_dsi(host);
-	u32 cmd, sts, val, wait = WRITE_COMPLETED, ctl = 0;
-	struct mipi_dsi_packet packet;
-	int ret, i, tx_len, rx_len;
-
-	ret = pm_runtime_resume_and_get(host->dev);
-	if (ret < 0)
-		return ret;
-
-	cdns_dsi_init_link(dsi);
-
-	ret = mipi_dsi_create_packet(&packet, msg);
-	if (ret)
-		goto out;
-
-	tx_len = msg->tx_buf ? msg->tx_len : 0;
-	rx_len = msg->rx_buf ? msg->rx_len : 0;
-
-	/* For read operations, the maximum TX len is 2. */
-	if (rx_len && tx_len > 2) {
-		ret = -ENOTSUPP;
-		goto out;
-	}
-
-	/* TX len is limited by the CMD FIFO depth. */
-	if (tx_len > dsi->direct_cmd_fifo_depth) {
-		ret = -ENOTSUPP;
-		goto out;
-	}
-
-	/* RX len is limited by the RX FIFO depth. */
-	if (rx_len > dsi->rx_fifo_depth) {
-		ret = -ENOTSUPP;
-		goto out;
-	}
-
-	cmd = CMD_SIZE(tx_len) | CMD_VCHAN_ID(msg->channel) |
-	      CMD_DATATYPE(msg->type);
-
-	if (msg->flags & MIPI_DSI_MSG_USE_LPM)
-		cmd |= CMD_LP_EN;
-
-	if (mipi_dsi_packet_format_is_long(msg->type))
-		cmd |= CMD_LONG;
-
-	if (rx_len) {
-		cmd |= READ_CMD;
-		wait = READ_COMPLETED_WITH_ERR | READ_COMPLETED;
-		ctl = READ_EN | BTA_EN;
-	} else if (msg->flags & MIPI_DSI_MSG_REQ_ACK) {
-		cmd |= BTA_REQ;
-		wait = ACK_WITH_ERR_RCVD | ACK_RCVD;
-		ctl = BTA_EN;
-	}
-
-	writel(readl(dsi->regs + MCTL_MAIN_DATA_CTL) | ctl,
-	       dsi->regs + MCTL_MAIN_DATA_CTL);
-
-	writel(cmd, dsi->regs + DIRECT_CMD_MAIN_SETTINGS);
-
-	for (i = 0; i < tx_len; i += 4) {
-		const u8 *buf = msg->tx_buf;
-		int j;
-
-		val = 0;
-		for (j = 0; j < 4 && j + i < tx_len; j++)
-			val |= (u32)buf[i + j] << (8 * j);
-
-		writel(val, dsi->regs + DIRECT_CMD_WRDATA);
-	}
-
-	/* Clear status flags before sending the command. */
-	writel(wait, dsi->regs + DIRECT_CMD_STS_CLR);
-	writel(wait, dsi->regs + DIRECT_CMD_STS_CTL);
-	reinit_completion(&dsi->direct_cmd_comp);
-	writel(0, dsi->regs + DIRECT_CMD_SEND);
-
-	wait_for_completion_timeout(&dsi->direct_cmd_comp,
-				    msecs_to_jiffies(1000));
-
-	sts = readl(dsi->regs + DIRECT_CMD_STS);
-	writel(wait, dsi->regs + DIRECT_CMD_STS_CLR);
-	writel(0, dsi->regs + DIRECT_CMD_STS_CTL);
-
-	writel(readl(dsi->regs + MCTL_MAIN_DATA_CTL) & ~ctl,
-	       dsi->regs + MCTL_MAIN_DATA_CTL);
-
-	/* We did not receive the events we were waiting for. */
-	if (!(sts & wait)) {
-		ret = -ETIMEDOUT;
-		goto out;
-	}
-
-	/* 'READ' or 'WRITE with ACK' failed. */
-	if (sts & (READ_COMPLETED_WITH_ERR | ACK_WITH_ERR_RCVD)) {
-		ret = -EIO;
-		goto out;
-	}
-
-	for (i = 0; i < rx_len; i += 4) {
-		u8 *buf = msg->rx_buf;
-		int j;
-
-		val = readl(dsi->regs + DIRECT_CMD_RDDATA);
-		for (j = 0; j < 4 && j + i < rx_len; j++)
-			buf[i + j] = val >> (8 * j);
-	}
-
-out:
-	pm_runtime_put(host->dev);
-	return ret;
-}
-
-static const struct mipi_dsi_host_ops cdns_dsi_ops = {
-	.attach = cdns_dsi_attach,
-	.detach = cdns_dsi_detach,
-	.transfer = cdns_dsi_transfer,
-};
-
-static int __maybe_unused cdns_dsi_resume(struct device *dev)
-{
-	struct cdns_dsi *dsi = dev_get_drvdata(dev);
-
-	reset_control_deassert(dsi->dsi_p_rst);
-	clk_prepare_enable(dsi->dsi_p_clk);
-	clk_prepare_enable(dsi->dsi_sys_clk);
-
-	return 0;
-}
-
-static int __maybe_unused cdns_dsi_suspend(struct device *dev)
-{
-	struct cdns_dsi *dsi = dev_get_drvdata(dev);
-
-	clk_disable_unprepare(dsi->dsi_sys_clk);
-	clk_disable_unprepare(dsi->dsi_p_clk);
-	reset_control_assert(dsi->dsi_p_rst);
-	dsi->link_initialized = false;
-	return 0;
-}
-
-static UNIVERSAL_DEV_PM_OPS(cdns_dsi_pm_ops, cdns_dsi_suspend, cdns_dsi_resume,
-			    NULL);
-
-static int cdns_dsi_drm_probe(struct platform_device *pdev)
-{
-	struct cdns_dsi *dsi;
-	struct cdns_dsi_input *input;
-	int ret, irq;
-	u32 val;
-
-	dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
-	if (!dsi)
-		return -ENOMEM;
-
-	platform_set_drvdata(pdev, dsi);
-
-	input = &dsi->input;
-
-	dsi->regs = devm_platform_ioremap_resource(pdev, 0);
-	if (IS_ERR(dsi->regs))
-		return PTR_ERR(dsi->regs);
-
-	dsi->dsi_p_clk = devm_clk_get(&pdev->dev, "dsi_p_clk");
-	if (IS_ERR(dsi->dsi_p_clk))
-		return PTR_ERR(dsi->dsi_p_clk);
-
-	dsi->dsi_p_rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
-								"dsi_p_rst");
-	if (IS_ERR(dsi->dsi_p_rst))
-		return PTR_ERR(dsi->dsi_p_rst);
-
-	dsi->dsi_sys_clk = devm_clk_get(&pdev->dev, "dsi_sys_clk");
-	if (IS_ERR(dsi->dsi_sys_clk))
-		return PTR_ERR(dsi->dsi_sys_clk);
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	dsi->dphy = devm_phy_get(&pdev->dev, "dphy");
-	if (IS_ERR(dsi->dphy))
-		return PTR_ERR(dsi->dphy);
-
-	ret = clk_prepare_enable(dsi->dsi_p_clk);
-	if (ret)
-		return ret;
-
-	val = readl(dsi->regs + ID_REG);
-	if (REV_VENDOR_ID(val) != 0xcad) {
-		dev_err(&pdev->dev, "invalid vendor id\n");
-		ret = -EINVAL;
-		goto err_disable_pclk;
-	}
-
-	val = readl(dsi->regs + IP_CONF);
-	dsi->direct_cmd_fifo_depth = 1 << (DIRCMD_FIFO_DEPTH(val) + 2);
-	dsi->rx_fifo_depth = RX_FIFO_DEPTH(val);
-	init_completion(&dsi->direct_cmd_comp);
-
-	writel(0, dsi->regs + MCTL_MAIN_DATA_CTL);
-	writel(0, dsi->regs + MCTL_MAIN_EN);
-	writel(0, dsi->regs + MCTL_MAIN_PHY_CTL);
-
-	/*
-	 * We only support the DPI input, so force input->id to
-	 * CDNS_DPI_INPUT.
-	 */
-	input->id = CDNS_DPI_INPUT;
-	input->bridge.funcs = &cdns_dsi_bridge_funcs;
-	input->bridge.of_node = pdev->dev.of_node;
-
-	/* Mask all interrupts before registering the IRQ handler. */
-	writel(0, dsi->regs + MCTL_MAIN_STS_CTL);
-	writel(0, dsi->regs + MCTL_DPHY_ERR_CTL1);
-	writel(0, dsi->regs + CMD_MODE_STS_CTL);
-	writel(0, dsi->regs + DIRECT_CMD_STS_CTL);
-	writel(0, dsi->regs + DIRECT_CMD_RD_STS_CTL);
-	writel(0, dsi->regs + VID_MODE_STS_CTL);
-	writel(0, dsi->regs + TVG_STS_CTL);
-	writel(0, dsi->regs + DPI_IRQ_EN);
-	ret = devm_request_irq(&pdev->dev, irq, cdns_dsi_interrupt, 0,
-			       dev_name(&pdev->dev), dsi);
-	if (ret)
-		goto err_disable_pclk;
-
-	pm_runtime_enable(&pdev->dev);
-	dsi->base.dev = &pdev->dev;
-	dsi->base.ops = &cdns_dsi_ops;
-
-	ret = mipi_dsi_host_register(&dsi->base);
-	if (ret)
-		goto err_disable_runtime_pm;
-
-	clk_disable_unprepare(dsi->dsi_p_clk);
-
-	return 0;
-
-err_disable_runtime_pm:
-	pm_runtime_disable(&pdev->dev);
-
-err_disable_pclk:
-	clk_disable_unprepare(dsi->dsi_p_clk);
-
-	return ret;
-}
-
-static int cdns_dsi_drm_remove(struct platform_device *pdev)
-{
-	struct cdns_dsi *dsi = platform_get_drvdata(pdev);
-
-	mipi_dsi_host_unregister(&dsi->base);
-	pm_runtime_disable(&pdev->dev);
-
-	return 0;
-}
-
-static const struct of_device_id cdns_dsi_of_match[] = {
-	{ .compatible = "cdns,dsi" },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, cdns_dsi_of_match);
-
-static struct platform_driver cdns_dsi_platform_driver = {
-	.probe  = cdns_dsi_drm_probe,
-	.remove = cdns_dsi_drm_remove,
-	.driver = {
-		.name   = "cdns-dsi",
-		.of_match_table = cdns_dsi_of_match,
-		.pm = &cdns_dsi_pm_ops,
-	},
-};
-module_platform_driver(cdns_dsi_platform_driver);
-
-MODULE_AUTHOR("Boris Brezillon <boris.brezillon@bootlin.com>");
-MODULE_DESCRIPTION("Cadence DSI driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:cdns-dsi");
-
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c
--- a/drivers/gpu/drm/bridge/ite-it66121.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/bridge/ite-it66121.c	2024-01-28 14:01:31.240353775 -0500
@@ -297,7 +297,7 @@
 	struct regmap *regmap;
 	struct drm_bridge bridge;
 	struct drm_bridge *next_bridge;
-	struct drm_connector *connector;
+	struct drm_connector connector;
 	struct device *dev;
 	struct gpio_desc *gpio_reset;
 	struct i2c_client *client;
@@ -314,6 +314,11 @@
 	} audio;
 };
 
+static inline struct it66121_ctx *connector_to_it66121(struct drm_connector *con)
+{
+	return container_of(con, struct it66121_ctx, connector);
+}
+
 static const struct regmap_range_cfg it66121_regmap_banks[] = {
 	{
 		.name = "it66121",
@@ -622,19 +627,107 @@
 	return val & IT66121_SYS_STATUS_HPDETECT;
 }
 
+static enum drm_mode_status it66121_mode_valid(struct drm_connector *connector,
+					       struct drm_display_mode *mode)
+{
+	struct it66121_ctx *ctx = connector_to_it66121(connector);
+	unsigned long max_clock;
+
+	max_clock = (ctx->bus_width == 12) ? 74250 : 148500;
+
+	if (mode->clock > max_clock)
+		return MODE_CLOCK_HIGH;
+
+	if (mode->clock < 25000)
+		return MODE_CLOCK_LOW;
+
+	return MODE_OK;
+}
+
+static struct edid *it66121_get_edid(struct it66121_ctx *ctx,
+				     struct drm_connector *connector)
+{
+	struct edid *edid;
+
+	mutex_lock(&ctx->lock);
+	edid = drm_do_get_edid(connector, it66121_get_edid_block, ctx);
+	mutex_unlock(&ctx->lock);
+
+	return edid;
+}
+
+static int it66121_get_modes(struct drm_connector *connector)
+{
+	struct it66121_ctx *ctx = connector_to_it66121(connector);
+	struct edid *edid;
+	int num = 0;
+
+	edid = it66121_get_edid(ctx, connector);
+	drm_connector_update_edid_property(connector, edid);
+	if (edid) {
+		num = drm_add_edid_modes(connector, edid);
+		kfree(edid);
+	}
+
+	return num;
+}
+
+static const struct drm_connector_helper_funcs it66121_connector_helper_funcs = {
+	.get_modes = it66121_get_modes,
+	.mode_valid = it66121_mode_valid,
+};
+
+static enum drm_connector_status
+it66121_connector_detect(struct drm_connector *connector, bool force)
+{
+	struct it66121_ctx *ctx = connector_to_it66121(connector);
+
+	return it66121_is_hpd_detect(ctx) ? connector_status_connected
+					  : connector_status_disconnected;
+}
+
+static const struct drm_connector_funcs it66121_connector_funcs = {
+	.detect = it66121_connector_detect,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.destroy = drm_connector_cleanup,
+	.reset = drm_atomic_helper_connector_reset,
+	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
 static int it66121_bridge_attach(struct drm_bridge *bridge,
 				 enum drm_bridge_attach_flags flags)
 {
 	struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
+	u32 bus_format;
 	int ret;
 
-	if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
+	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
+		DRM_ERROR("DRM_BRIDGE_ATTACH_NO_CONNECTOR mode is not supported.\n");
 		return -EINVAL;
+	}
+
+	if (ctx->bus_width == 12)
+		bus_format = MEDIA_BUS_FMT_RGB888_2X12_LE;
+	else
+		bus_format = MEDIA_BUS_FMT_RGB888_1X24;
+
+	drm_connector_helper_add(&ctx->connector,
+				 &it66121_connector_helper_funcs);
 
-	ret = drm_bridge_attach(bridge->encoder, ctx->next_bridge, bridge, flags);
+	ret = drm_connector_init(bridge->dev, &ctx->connector,
+				 &it66121_connector_funcs,
+				 DRM_MODE_CONNECTOR_HDMIA);
 	if (ret)
 		return ret;
 
+	ret = drm_display_info_set_bus_formats(&ctx->connector.display_info,
+					       &bus_format, 1);
+	if (ret)
+		return ret;
+
+	drm_connector_attach_encoder(&ctx->connector, bridge->encoder);
+
 	ret = regmap_write_bits(ctx->regmap, IT66121_CLK_BANK_REG,
 				IT66121_CLK_BANK_PWROFF_RCLK, 0);
 	if (ret)
@@ -763,9 +856,6 @@
 				  struct drm_bridge_state *bridge_state)
 {
 	struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
-	struct drm_atomic_state *state = bridge_state->base.state;
-
-	ctx->connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
 
 	it66121_set_mute(ctx, false);
 }
@@ -776,8 +866,6 @@
 	struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
 
 	it66121_set_mute(ctx, true);
-
-	ctx->connector = NULL;
 }
 
 static
@@ -808,7 +896,7 @@
 
 	hdmi_avi_infoframe_init(&ctx->hdmi_avi_infoframe);
 
-	ret = drm_hdmi_avi_infoframe_from_display_mode(&ctx->hdmi_avi_infoframe, ctx->connector,
+	ret = drm_hdmi_avi_infoframe_from_display_mode(&ctx->hdmi_avi_infoframe, &ctx->connector,
 						       adjusted_mode);
 	if (ret) {
 		DRM_ERROR("Failed to setup AVI infoframe: %d\n", ret);
@@ -905,13 +993,8 @@
 					    struct drm_connector *connector)
 {
 	struct it66121_ctx *ctx = container_of(bridge, struct it66121_ctx, bridge);
-	struct edid *edid;
-
-	mutex_lock(&ctx->lock);
-	edid = drm_do_get_edid(connector, it66121_get_edid_block, ctx);
-	mutex_unlock(&ctx->lock);
 
-	return edid;
+	return it66121_get_edid(ctx, connector);
 }
 
 static const struct drm_bridge_funcs it66121_bridge_funcs = {
@@ -1464,14 +1547,10 @@
 	struct it66121_ctx *ctx = dev_get_drvdata(dev);
 
 	mutex_lock(&ctx->lock);
-	if (!ctx->connector) {
-		/* Pass en empty ELD if connector not available */
-		dev_dbg(dev, "No connector present, passing empty EDID data");
-		memset(buf, 0, len);
-	} else {
-		memcpy(buf, ctx->connector->eld,
-		       min(sizeof(ctx->connector->eld), len));
-	}
+
+	memcpy(buf, ctx->connector.eld,
+	       min(sizeof(ctx->connector.eld), len));
+
 	mutex_unlock(&ctx->lock);
 
 	return 0;
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
--- a/drivers/gpu/drm/bridge/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/bridge/Kconfig	2024-01-28 14:01:31.240353775 -0500
@@ -15,17 +15,6 @@
 menu "Display Interface Bridges"
 	depends on DRM && DRM_BRIDGE
 
-config DRM_CDNS_DSI
-	tristate "Cadence DPI/DSI bridge"
-	select DRM_KMS_HELPER
-	select DRM_MIPI_DSI
-	select DRM_PANEL_BRIDGE
-	select GENERIC_PHY_MIPI_DPHY
-	depends on OF
-	help
-	  Support Cadence DPI to DSI bridge. This is an internal
-	  bridge and is meant to be directly embedded in a SoC.
-
 config DRM_CHIPONE_ICN6211
 	tristate "Chipone ICN6211 MIPI-DSI/RGB Converter bridge"
 	depends on OF
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
--- a/drivers/gpu/drm/bridge/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/bridge/Makefile	2024-01-28 14:01:31.240353775 -0500
@@ -1,5 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o
 obj-$(CONFIG_DRM_CHIPONE_ICN6211) += chipone-icn6211.o
 obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o
 obj-$(CONFIG_DRM_CROS_EC_ANX7688) += cros-ec-anx7688.o
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c
--- a/drivers/gpu/drm/bridge/panel.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/bridge/panel.c	2024-01-28 14:01:31.240353775 -0500
@@ -254,6 +254,9 @@
 	panel_bridge->bridge.ops = DRM_BRIDGE_OP_MODES;
 	panel_bridge->bridge.type = connector_type;
 
+	panel_bridge->bridge.pre_enable_prev_first =
+						panel->prepare_upstream_first;
+
 	drm_bridge_add(&panel_bridge->bridge);
 
 	return &panel_bridge->bridge;
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c
--- a/drivers/gpu/drm/bridge/sii902x.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/bridge/sii902x.c	2024-01-28 14:01:31.240353775 -0500
@@ -173,6 +173,10 @@
 	struct i2c_mux_core *i2cmux;
 	struct regulator_bulk_data supplies[2];
 	bool sink_is_hdmi;
+	struct device_link *link;
+	unsigned int ctx_tpi;
+	unsigned int ctx_interrupt;
+
 	/*
 	 * Mutex protects audio and video functions from interfering
 	 * each other, by keeping their i2c command sequences atomic.
@@ -423,8 +427,15 @@
 	struct sii902x *sii902x = bridge_to_sii902x(bridge);
 	u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
 	struct drm_device *drm = bridge->dev;
+	struct device *dev = &sii902x->i2c->dev;
 	int ret;
 
+	sii902x->link = device_link_add(drm->dev, dev, DL_FLAG_STATELESS);
+	if (!sii902x->link) {
+		dev_err(dev, "failed to create device link");
+		return -EINVAL;
+	}
+
 	if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
 		return drm_bridge_attach(bridge->encoder, sii902x->next_bridge,
 					 bridge, flags);
@@ -433,16 +444,17 @@
 				 &sii902x_connector_helper_funcs);
 
 	if (!drm_core_check_feature(drm, DRIVER_ATOMIC)) {
-		dev_err(&sii902x->i2c->dev,
+		dev_err(dev,
 			"sii902x driver is only compatible with DRM devices supporting atomic updates\n");
-		return -ENOTSUPP;
+		ret = -ENOTSUPP;
+		goto err_bridge_attach;
 	}
 
 	ret = drm_connector_init(drm, &sii902x->connector,
 				 &sii902x_connector_funcs,
 				 DRM_MODE_CONNECTOR_HDMIA);
 	if (ret)
-		return ret;
+		goto err_bridge_attach;
 
 	if (sii902x->i2c->irq > 0)
 		sii902x->connector.polled = DRM_CONNECTOR_POLL_HPD;
@@ -452,11 +464,16 @@
 	ret = drm_display_info_set_bus_formats(&sii902x->connector.display_info,
 					       &bus_format, 1);
 	if (ret)
-		return ret;
+		goto err_bridge_attach;
 
 	drm_connector_attach_encoder(&sii902x->connector, bridge->encoder);
 
 	return 0;
+
+err_bridge_attach:
+	device_link_del(sii902x->link);
+
+	return ret;
 }
 
 static enum drm_connector_status sii902x_bridge_detect(struct drm_bridge *bridge)
@@ -999,6 +1016,76 @@
 		 | DRM_BUS_FLAG_DE_HIGH,
 };
 
+static int __maybe_unused sii902x_resume(struct device *dev)
+{
+	struct sii902x *sii902x = dev_get_drvdata(dev);
+	unsigned int tpi_reg, status;
+	int ret;
+
+	ret = regulator_bulk_enable(ARRAY_SIZE(sii902x->supplies),
+				    sii902x->supplies);
+	if (ret < 0) {
+		dev_err(dev, "Failed to enable supplies");
+		return ret;
+	}
+
+	ret = regmap_read(sii902x->regmap, SII902X_REG_TPI_RQB, &tpi_reg);
+	if (ret)
+		goto err_disable_supply;
+
+	if (tpi_reg != sii902x->ctx_tpi) {
+		/*
+		 * TPI register context has changed. SII902X power supply
+		 * device has been turned off and on.
+		 */
+
+		sii902x_reset(sii902x);
+
+		/* Configure the device to enter TPI mode. */
+		ret = regmap_write(sii902x->regmap, SII902X_REG_TPI_RQB, 0x0);
+		if (ret)
+			goto err_disable_supply;
+
+		/* Re enable the interrupts */
+		regmap_write(sii902x->regmap, SII902X_INT_ENABLE,
+			     sii902x->ctx_interrupt);
+	}
+
+	/* Clear all pending interrupts */
+	regmap_read(sii902x->regmap, SII902X_INT_STATUS, &status);
+	regmap_write(sii902x->regmap, SII902X_INT_STATUS, status);
+
+	return 0;
+
+err_disable_supply:
+
+	regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
+			       sii902x->supplies);
+
+	return ret;
+}
+
+static int __maybe_unused sii902x_suspend(struct device *dev)
+{
+	struct sii902x *sii902x = dev_get_drvdata(dev);
+	int ret;
+
+	regmap_read(sii902x->regmap, SII902X_REG_TPI_RQB,
+		    &sii902x->ctx_tpi);
+
+	regmap_read(sii902x->regmap, SII902X_INT_ENABLE,
+		    &sii902x->ctx_interrupt);
+
+	ret = regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
+				     sii902x->supplies);
+
+	return ret;
+}
+
+static const struct dev_pm_ops sii902x_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(sii902x_suspend, sii902x_resume)
+};
+
 static int sii902x_init(struct sii902x *sii902x)
 {
 	struct device *dev = &sii902x->i2c->dev;
@@ -1151,6 +1238,10 @@
 	struct sii902x *sii902x = i2c_get_clientdata(client);
 
 	i2c_mux_del_adapters(sii902x->i2cmux);
+
+	if (sii902x->link)
+		device_link_del(sii902x->link);
+
 	drm_bridge_remove(&sii902x->bridge);
 	regulator_bulk_disable(ARRAY_SIZE(sii902x->supplies),
 			       sii902x->supplies);
@@ -1173,6 +1264,7 @@
 	.remove = sii902x_remove,
 	.driver = {
 		.name = "sii902x",
+		.pm = &sii902x_pm_ops,
 		.of_match_table = sii902x_dt_ids,
 	},
 	.id_table = sii902x_i2c_ids,
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
--- a/drivers/gpu/drm/bridge/tc358762.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/bridge/tc358762.c	2024-01-28 14:01:31.240353775 -0500
@@ -229,6 +229,7 @@
 	ctx->bridge.funcs = &tc358762_bridge_funcs;
 	ctx->bridge.type = DRM_MODE_CONNECTOR_DPI;
 	ctx->bridge.of_node = dev->of_node;
+	ctx->bridge.pre_enable_prev_first = true;
 
 	drm_bridge_add(&ctx->bridge);
 
diff -Naur --no-dereference a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c	2024-01-28 14:01:31.240353775 -0500
@@ -152,6 +152,7 @@
  * @ln_assign:    Value to program to the LN_ASSIGN register.
  * @ln_polrs:     Value for the 4-bit LN_POLRS field of SN_ENH_FRAME_REG.
  * @comms_enabled: If true then communication over the aux channel is enabled.
+ * @plugged:       Plug connection status
  * @comms_mutex:   Protects modification of comms_enabled.
  *
  * @gchip:        If we expose our GPIOs, this is used.
@@ -190,6 +191,7 @@
 	u8				ln_assign;
 	u8				ln_polrs;
 	bool				comms_enabled;
+	bool				plugged;
 	struct mutex			comms_mutex;
 
 #if defined(CONFIG_OF_GPIO)
@@ -367,7 +369,7 @@
 	/* td2: min 100 us after regulators before enabling the GPIO */
 	usleep_range(100, 110);
 
-	gpiod_set_value(pdata->enable_gpio, 1);
+	gpiod_set_value_cansleep(pdata->enable_gpio, 1);
 
 	/*
 	 * If we have a reference clock we can enable communication w/ the
@@ -390,7 +392,7 @@
 	if (pdata->refclk)
 		ti_sn65dsi86_disable_comms(pdata);
 
-	gpiod_set_value(pdata->enable_gpio, 0);
+	gpiod_set_value_cansleep(pdata->enable_gpio, 0);
 
 	ret = regulator_bulk_disable(SN_REGULATOR_SUPPLY_NUM, pdata->supplies);
 	if (ret)
@@ -692,10 +694,11 @@
 	if (IS_ERR(dsi))
 		return PTR_ERR(dsi);
 
-	/* TODO: setting to 4 MIPI lanes always for now */
-	dsi->lanes = 4;
+	/* TODO: setting to 2 MIPI lanes always for now */
+	dsi->lanes = 2;
 	dsi->format = MIPI_DSI_FMT_RGB888;
-	dsi->mode_flags = MIPI_DSI_MODE_VIDEO;
+	dsi->mode_flags = MIPI_DSI_MODE_VIDEO |
+		MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_VIDEO_SYNC_PULSE;
 
 	/* check if continuous dsi clock is required or not */
 	pm_runtime_get_sync(dev);
@@ -1070,6 +1073,15 @@
 		return;
 	}
 
+	/*
+	 * Disable ASSR Display Authentication, since its supported only in eDP
+	 * and not spupperted in DP
+	 */
+	regmap_write(pdata->regmap, 0xFF, 0x7);
+	regmap_write(pdata->regmap, 0x16, 0x1);
+	regmap_write(pdata->regmap, 0xFF, 0x0);
+	regmap_update_bits(pdata->regmap, 0x5A, BIT(0), 0);
+
 	max_dp_lanes = ti_sn_get_max_lanes(pdata);
 	pdata->dp_lanes = min(pdata->dp_lanes, max_dp_lanes);
 
@@ -1085,26 +1097,6 @@
 	/* set dsi clk frequency value */
 	ti_sn_bridge_set_dsi_rate(pdata);
 
-	/*
-	 * The SN65DSI86 only supports ASSR Display Authentication method and
-	 * this method is enabled for eDP panels. An eDP panel must support this
-	 * authentication method. We need to enable this method in the eDP panel
-	 * at DisplayPort address 0x0010A prior to link training.
-	 *
-	 * As only ASSR is supported by SN65DSI86, for full DisplayPort displays
-	 * we need to disable the scrambler.
-	 */
-	if (pdata->bridge.type == DRM_MODE_CONNECTOR_eDP) {
-		drm_dp_dpcd_writeb(&pdata->aux, DP_EDP_CONFIGURATION_SET,
-				   DP_ALTERNATE_SCRAMBLER_RESET_ENABLE);
-
-		regmap_update_bits(pdata->regmap, SN_TRAINING_SETTING_REG,
-				   SCRAMBLE_DISABLE, 0);
-	} else {
-		regmap_update_bits(pdata->regmap, SN_TRAINING_SETTING_REG,
-				   SCRAMBLE_DISABLE, SCRAMBLE_DISABLE);
-	}
-
 	bpp = ti_sn_bridge_get_bpp(connector);
 	/* Set the DP output format (18 bpp or 24 bpp) */
 	val = bpp == 18 ? BPP_18_RGB : 0;
@@ -1176,14 +1168,19 @@
 static enum drm_connector_status ti_sn_bridge_detect(struct drm_bridge *bridge)
 {
 	struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
-	int val = 0;
+	int val;
+	u8 link_status[DP_LINK_STATUS_SIZE];
 
-	pm_runtime_get_sync(pdata->dev);
-	regmap_read(pdata->regmap, SN_HPD_DISABLE_REG, &val);
-	pm_runtime_put_autosuspend(pdata->dev);
+	if (!pdata->plugged) {
+		pm_runtime_get_sync(pdata->dev);
+		val = drm_dp_dpcd_read_link_status(&pdata->aux, link_status);
+		pm_runtime_put_autosuspend(pdata->dev);
+		if (val > 0)
+			pdata->plugged = true;
+	}
 
-	return val & HPD_DEBOUNCED_STATE ? connector_status_connected
-					 : connector_status_disconnected;
+	return pdata->plugged ? connector_status_connected
+			      : connector_status_disconnected;
 }
 
 static struct edid *ti_sn_bridge_get_edid(struct drm_bridge *bridge,
@@ -1295,8 +1292,11 @@
 	pdata->bridge.type = pdata->next_bridge->type == DRM_MODE_CONNECTOR_DisplayPort
 			   ? DRM_MODE_CONNECTOR_DisplayPort : DRM_MODE_CONNECTOR_eDP;
 
+	pdata->plugged = false;
+	pdata->bridge.ops |= DRM_BRIDGE_OP_DETECT;
+
 	if (pdata->bridge.type == DRM_MODE_CONNECTOR_DisplayPort)
-		pdata->bridge.ops = DRM_BRIDGE_OP_EDID | DRM_BRIDGE_OP_DETECT;
+		pdata->bridge.ops |= DRM_BRIDGE_OP_EDID;
 
 	drm_bridge_add(&pdata->bridge);
 
diff -Naur --no-dereference a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
--- a/drivers/gpu/drm/panel/panel-edp.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/panel/panel-edp.c	2024-01-28 14:01:31.240353775 -0500
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/gpio/consumer.h>
 #include <linux/iopoll.h>
+#include <linux/media-bus-format.h>
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
@@ -189,6 +190,9 @@
 
 	/** @delay: Structure containing various delay values for this panel. */
 	struct panel_delay delay;
+
+	/** @bus_format: See MEDIA_BUS_FMT_... defines. */
+	u32 bus_format;
 };
 
 /**
@@ -339,6 +343,9 @@
 	connector->display_info.bpc = panel->desc->bpc;
 	connector->display_info.width_mm = panel->desc->size.width;
 	connector->display_info.height_mm = panel->desc->size.height;
+	if (panel->desc->bus_format)
+		drm_display_info_set_bus_formats(&connector->display_info,
+						 &panel->desc->bus_format, 1);
 
 	return num;
 }
@@ -880,13 +887,15 @@
 		dev_warn(dev, "Expected bpc in {6,8,10} but got: %u\n", desc->bpc);
 	}
 
-	if (!panel->base.backlight && panel->aux) {
-		pm_runtime_get_sync(dev);
-		err = drm_panel_dp_aux_backlight(&panel->base, panel->aux);
-		pm_runtime_mark_last_busy(dev);
-		pm_runtime_put_autosuspend(dev);
-		if (err)
-			goto err_finished_pm_runtime;
+	if (!of_device_is_compatible(dev->of_node, "ti,panel-edp")) {
+		if (!panel->base.backlight && panel->aux) {
+			pm_runtime_get_sync(dev);
+			err = drm_panel_dp_aux_backlight(&panel->base, panel->aux);
+			pm_runtime_mark_last_busy(dev);
+			pm_runtime_put_autosuspend(dev);
+			if (err)
+				goto err_finished_pm_runtime;
+		}
 	}
 
 	drm_panel_add(&panel->base);
@@ -1717,6 +1726,37 @@
 	},
 };
 
+static const struct drm_display_mode ti_panel_edp_mode = {
+	.clock = 40000,
+	.hdisplay = 800,
+	.hsync_start = 800 + 40,
+	.hsync_end = 800 + 40 + 128,
+	.htotal = 800 + 40 + 128 + 88,
+	.vdisplay = 600,
+	.vsync_start = 600 + 1,
+	.vsync_end = 600 + 1 + 4,
+	.vtotal = 600 + 1 + 4 + 23,
+
+	.crtc_clock = 40000,
+	.crtc_hdisplay = 800,
+	.crtc_hsync_start = 800 + 40,
+	.crtc_hsync_end = 800 + 40 + 128,
+	.crtc_htotal = 800 + 40 + 128 + 88,
+	.crtc_vdisplay = 600,
+	.crtc_vsync_start = 600 + 1,
+	.crtc_vsync_end = 600 + 1 + 4,
+	.crtc_vtotal = 600 + 1 + 4 + 23,
+
+	.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+static const struct panel_desc ti_panel_edp = {
+	.modes = &ti_panel_edp_mode,
+	.num_modes = 1,
+	.bpc = 8,
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+};
+
 static const struct of_device_id platform_of_match[] = {
 	{
 		/* Must be first */
@@ -1809,6 +1849,9 @@
 		.compatible = "starry,kr122ea0sra",
 		.data = &starry_kr122ea0sra,
 	}, {
+		.compatible = "ti,panel-edp",
+		.data = &ti_panel_edp,
+	}, {
 		/* sentinel */
 	}
 };
diff -Naur --no-dereference a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
--- a/drivers/gpu/drm/panel/panel-simple.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/panel/panel-simple.c	2024-01-28 14:01:31.240353775 -0500
@@ -2486,6 +2486,35 @@
 	.connector_type = DRM_MODE_CONNECTOR_LVDS,
 };
 
+static const struct drm_display_mode lincolntech_lcd185_101ct_mode = {
+	.clock = 155127,
+	.hdisplay = 1920,
+	.hsync_start = 1920 + 128,
+	.hsync_end = 1920 + 128 + 20,
+	.htotal = 1920 + 128 + 20 + 12,
+	.vdisplay = 1200,
+	.vsync_start = 1200 + 19,
+	.vsync_end = 1200 + 19 + 4,
+	.vtotal = 1200 + 19 + 4 + 20,
+};
+
+static const struct panel_desc lincolntech_lcd185_101ct = {
+	.modes = &lincolntech_lcd185_101ct_mode,
+	.bpc = 8,
+	.num_modes = 1,
+	.size = {
+		.width = 217,
+		.height = 136,
+	},
+	.delay = {
+		.prepare = 50,
+		.disable = 50,
+	},
+	.bus_flags = DRM_BUS_FLAG_DE_HIGH,
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
 static const struct display_timing logictechno_lt161010_2nh_timing = {
 	.pixelclock = { 26400000, 33300000, 46800000 },
 	.hactive = { 800, 800, 800 },
@@ -2674,6 +2703,64 @@
 	.bus_flags = DRM_BUS_FLAG_DE_HIGH,
 };
 
+static const struct drm_display_mode microtips_mf_101hiebcaf0_mode = {
+	.clock = 150275,
+	.hdisplay = 1920,
+	.hsync_start = 1920 + 32,
+	.hsync_end = 1920 + 32 + 52,
+	.htotal = 1920 + 32 + 52 + 24,
+	.vdisplay = 1200,
+	.vsync_start = 1200 + 24,
+	.vsync_end = 1200 + 24 + 8,
+	.vtotal = 1200 + 24 + 8 + 3,
+};
+
+static const struct panel_desc microtips_mf_101hiebcaf0 = {
+	.modes = &microtips_mf_101hiebcaf0_mode,
+	.bpc = 8,
+	.num_modes = 1,
+	.size = {
+		.width = 217,
+		.height = 136,
+	},
+	.delay = {
+		.prepare = 50,
+		.disable = 50,
+	},
+	.bus_flags = DRM_BUS_FLAG_DE_HIGH,
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
+static const struct drm_display_mode microtips_mf_103hieb0ga0_mode = {
+	.clock = 93301,
+	.hdisplay = 1920,
+	.hsync_start = 1920 + 72,
+	.hsync_end = 1920 + 72 + 72,
+	.htotal = 1920 + 72 + 72 + 72,
+	.vdisplay = 720,
+	.vsync_start = 720 + 3,
+	.vsync_end = 720 + 3 + 3,
+	.vtotal = 720 + 3 + 3 + 2,
+};
+
+static const struct panel_desc microtips_mf_103hieb0ga0 = {
+	.modes = &microtips_mf_103hieb0ga0_mode,
+	.bpc = 8,
+	.num_modes = 1,
+	.size = {
+		.width = 244,
+		.height = 92,
+	},
+	.delay = {
+		.prepare = 50,
+		.disable = 50,
+	},
+	.bus_flags = DRM_BUS_FLAG_DE_HIGH,
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+	.connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
 static const struct display_timing multi_inno_mi0700s4t_6_timing = {
 	.pixelclock = { 29000000, 33000000, 38000000 },
 	.hactive = { 800, 800, 800 },
@@ -3193,6 +3280,42 @@
 	.connector_type = DRM_MODE_CONNECTOR_DPI,
 };
 
+static const struct drm_display_mode raspberrypi_7inch_mode = {
+	.clock = 28569600 / 1000,
+	.hdisplay = 800,
+	.hsync_start = 800 + 48, //848
+	.hsync_end = 800 + 48 + 32, //880
+	.htotal = 800 + 48 + 32 + 80, //960
+	.vdisplay = 480,
+	.vsync_start = 480 + 3, //487
+	.vsync_end = 480 + 3 + 7, //450
+	.vtotal = 480 + 3 + 7 + 6, //496
+
+	.crtc_clock = 28569600 / 1000,
+	.crtc_hdisplay = 800,
+	.crtc_hsync_start = 800 + 48, //848
+	.crtc_hsync_end = 800 + 48 + 32, //880
+	.crtc_htotal = 800 + 48 + 32 + 80, //960
+	.crtc_vdisplay = 480,
+	.crtc_vsync_start = 480 + 3, //487
+	.crtc_vsync_end = 480 + 3 + 7, //450
+	.crtc_vtotal = 480 + 3 + 7 + 6, //496
+
+	.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+static const struct panel_desc raspberrypi_7inch = {
+	.modes = &raspberrypi_7inch_mode,
+	.num_modes = 1,
+	.bpc = 8,
+	.size = {
+		.width = 154,
+		.height = 86,
+	},
+	.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+	.connector_type = DRM_MODE_CONNECTOR_DSI,
+};
+
 static const struct display_timing rocktech_rk070er9427_timing = {
 	.pixelclock = { 26400000, 33300000, 46800000 },
 	.hactive = { 800, 800, 800 },
@@ -4143,6 +4266,9 @@
 		.compatible = "lg,lb070wv8",
 		.data = &lg_lb070wv8,
 	}, {
+		.compatible = "lincolntech,lcd185-101ct",
+		.data = &lincolntech_lcd185_101ct,
+	}, {
 		.compatible = "logicpd,type28",
 		.data = &logicpd_type_28,
 	}, {
@@ -4161,6 +4287,12 @@
 		.compatible = "logictechno,lttd800480070-l6wh-rt",
 		.data = &logictechno_lttd800480070_l6wh_rt,
 	}, {
+		.compatible = "microtips,mf-101hiebcaf0",
+		.data = &microtips_mf_101hiebcaf0,
+	}, {
+		.compatible = "microtips,mf-103hieb0ga0",
+		.data = &microtips_mf_103hieb0ga0,
+	}, {
 		.compatible = "mitsubishi,aa070mc01-ca1",
 		.data = &mitsubishi_aa070mc01,
 	}, {
@@ -4224,6 +4356,9 @@
 		.compatible = "qishenglong,gopher2b-lcd",
 		.data = &qishenglong_gopher2b_lcd,
 	}, {
+		.compatible = "raspberrypi,7inch-dsi",
+		.data = &raspberrypi_7inch,
+	}, {
 		.compatible = "rocktech,rk070er9427",
 		.data = &rocktech_rk070er9427,
 	}, {
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_crtc.c b/drivers/gpu/drm/tidss/tidss_crtc.c
--- a/drivers/gpu/drm/tidss/tidss_crtc.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_crtc.c	2024-01-28 14:01:31.240353775 -0500
@@ -34,11 +34,17 @@
 	 * the same time. This happens before the vertical blank interrupt.
 	 * So there is a small change that the driver sets GO bit after VFP, but
 	 * before vblank, and we have to check for that case here.
+	 *
+	 * For a video port shared between Linux and remote core but owned by remote core,
+	 * this is not required since Linux just attaches to mode that was preset by remote
+	 * core with which display is being shared.
 	 */
-	busy = dispc_vp_go_busy(tidss->dispc, tcrtc->hw_videoport);
-	if (busy) {
-		spin_unlock_irqrestore(&ddev->event_lock, flags);
-		return;
+	if (!tidss->shared_mode || tidss->shared_mode_owned_vps[tcrtc->vp_idx]) {
+		busy = dispc_vp_go_busy(tidss->dispc, tcrtc->vp_idx);
+		if (busy) {
+			spin_unlock_irqrestore(&ddev->event_lock, flags);
+			return;
+		}
 	}
 
 	event = tcrtc->event;
@@ -77,7 +83,7 @@
 	struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
 
 	dev_err_ratelimited(crtc->dev->dev, "CRTC%u SYNC LOST: (irq %llx)\n",
-			    tcrtc->hw_videoport, irqstatus);
+			    tcrtc->vp_idx, irqstatus);
 }
 
 /* drm_crtc_helper_funcs */
@@ -91,7 +97,7 @@
 	struct tidss_device *tidss = to_tidss(ddev);
 	struct dispc_device *dispc = tidss->dispc;
 	struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
-	u32 hw_videoport = tcrtc->hw_videoport;
+	u32 vp_idx = tcrtc->vp_idx;
 	const struct drm_display_mode *mode;
 	enum drm_mode_status ok;
 
@@ -102,14 +108,14 @@
 
 	mode = &crtc_state->adjusted_mode;
 
-	ok = dispc_vp_mode_valid(dispc, hw_videoport, mode);
+	ok = dispc_vp_mode_valid(dispc, vp_idx, mode);
 	if (ok != MODE_OK) {
 		dev_dbg(ddev->dev, "%s: bad mode: %ux%u pclk %u kHz\n",
 			__func__, mode->hdisplay, mode->vdisplay, mode->clock);
 		return -EINVAL;
 	}
 
-	return dispc_vp_bus_check(dispc, hw_videoport, crtc_state);
+	return dispc_vp_bus_check(dispc, vp_idx, crtc_state);
 }
 
 /*
@@ -151,11 +157,11 @@
 			struct tidss_plane *tplane = to_tidss_plane(plane);
 
 			dispc_ovr_set_plane(tidss->dispc, tplane->hw_plane_id,
-					    tcrtc->hw_videoport,
+					    tcrtc->vp_idx,
 					    pstate->crtc_x, pstate->crtc_y,
 					    layer);
 		}
-		dispc_ovr_enable_layer(tidss->dispc, tcrtc->hw_videoport, layer,
+		dispc_ovr_enable_layer(tidss->dispc, tcrtc->vp_idx, layer,
 				       layer_active);
 	}
 }
@@ -170,14 +176,10 @@
 	struct tidss_device *tidss = to_tidss(ddev);
 	unsigned long flags;
 
-	dev_dbg(ddev->dev,
-		"%s: %s enabled %d, needs modeset %d, event %p\n", __func__,
-		crtc->name, drm_atomic_crtc_needs_modeset(crtc->state),
-		crtc->state->enable, crtc->state->event);
-
-	/* There is nothing to do if CRTC is not going to be enabled. */
-	if (!crtc->state->enable)
-		return;
+	dev_dbg(ddev->dev, "%s: %s is %sactive, %s modeset, event %p\n",
+		__func__, crtc->name, crtc->state->active ? "" : "not ",
+		drm_atomic_crtc_needs_modeset(crtc->state) ? "needs" : "doesn't need",
+		crtc->state->event);
 
 	/*
 	 * Flush CRTC changes with go bit only if new modeset is not
@@ -187,7 +189,7 @@
 		return;
 
 	/* If the GO bit is stuck we better quit here. */
-	if (WARN_ON(dispc_vp_go_busy(tidss->dispc, tcrtc->hw_videoport)))
+	if (WARN_ON(dispc_vp_go_busy(tidss->dispc, tcrtc->vp_idx)))
 		return;
 
 	/* We should have event if CRTC is enabled through out this commit. */
@@ -195,7 +197,7 @@
 		return;
 
 	/* Write vp properties to HW if needed. */
-	dispc_vp_setup(tidss->dispc, tcrtc->hw_videoport, crtc->state, false);
+	dispc_vp_setup(tidss->dispc, tcrtc->vp_idx, crtc->state, false);
 
 	/* Update plane positions if needed. */
 	tidss_crtc_position_planes(tidss, crtc, old_crtc_state, false);
@@ -203,7 +205,45 @@
 	WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 
 	spin_lock_irqsave(&ddev->event_lock, flags);
-	dispc_vp_go(tidss->dispc, tcrtc->hw_videoport);
+	dispc_vp_go(tidss->dispc, tcrtc->vp_idx);
+
+	WARN_ON(tcrtc->event);
+
+	tcrtc->event = crtc->state->event;
+	crtc->state->event = NULL;
+
+	spin_unlock_irqrestore(&ddev->event_lock, flags);
+}
+
+static void tidss_shared_vp_crtc_atomic_flush(struct drm_crtc *crtc,
+					      struct drm_atomic_state *state)
+{
+	struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
+	struct drm_device *ddev = crtc->dev;
+	unsigned long flags;
+
+	dev_dbg(ddev->dev,
+		"%s: %s enabled %d, needs modeset %d, event %p\n", __func__,
+		crtc->name, drm_atomic_crtc_needs_modeset(crtc->state),
+		crtc->state->enable, crtc->state->event);
+
+	/* There is nothing to do if CRTC is not going to be enabled. */
+	if (!crtc->state->enable)
+		return;
+	/*
+	 * Flush CRTC changes with go bit only if new modeset is not
+	 * coming, so CRTC is enabled trough out the commit.
+	 */
+	if (drm_atomic_crtc_needs_modeset(crtc->state))
+		return;
+
+	/* We should have event if CRTC is enabled through out this commit. */
+	if (WARN_ON(!crtc->state->event))
+		return;
+
+	WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+	spin_lock_irqsave(&ddev->event_lock, flags);
 
 	WARN_ON(tcrtc->event);
 
@@ -229,24 +269,45 @@
 
 	tidss_runtime_get(tidss);
 
-	r = dispc_vp_set_clk_rate(tidss->dispc, tcrtc->hw_videoport,
+	r = dispc_vp_set_clk_rate(tidss->dispc, tcrtc->vp_idx,
 				  mode->clock * 1000);
 	if (r != 0)
 		return;
 
-	r = dispc_vp_enable_clk(tidss->dispc, tcrtc->hw_videoport);
+	r = dispc_vp_enable_clk(tidss->dispc, tcrtc->vp_idx);
 	if (r != 0)
 		return;
 
-	dispc_vp_setup(tidss->dispc, tcrtc->hw_videoport, crtc->state, true);
+	dispc_vp_setup(tidss->dispc, tcrtc->vp_idx, crtc->state, true);
 	tidss_crtc_position_planes(tidss, crtc, old_state, true);
 
 	/* Turn vertical blanking interrupt reporting on. */
 	drm_crtc_vblank_on(crtc);
 
-	dispc_vp_prepare(tidss->dispc, tcrtc->hw_videoport, crtc->state);
+	dispc_vp_prepare(tidss->dispc, tcrtc->vp_idx, crtc->state);
 
-	dispc_vp_enable(tidss->dispc, tcrtc->hw_videoport, crtc->state);
+	dispc_vp_enable(tidss->dispc, tcrtc->vp_idx, crtc->state);
+
+	spin_lock_irqsave(&ddev->event_lock, flags);
+
+	if (crtc->state->event) {
+		drm_crtc_send_vblank_event(crtc, crtc->state->event);
+		crtc->state->event = NULL;
+	}
+
+	spin_unlock_irqrestore(&ddev->event_lock, flags);
+}
+
+static void tidss_shared_vp_crtc_atomic_enable(struct drm_crtc *crtc,
+					       struct drm_atomic_state *state)
+{
+	struct drm_device *ddev = crtc->dev;
+	unsigned long flags;
+
+	dev_dbg(ddev->dev, "%s, event %p\n", __func__, crtc->state->event);
+
+	/* Turn vertical blanking interrupt reporting on. */
+	drm_crtc_vblank_on(crtc);
 
 	spin_lock_irqsave(&ddev->event_lock, flags);
 
@@ -270,14 +331,14 @@
 
 	reinit_completion(&tcrtc->framedone_completion);
 
-	dispc_vp_disable(tidss->dispc, tcrtc->hw_videoport);
+	dispc_vp_disable(tidss->dispc, tcrtc->vp_idx);
 
 	if (!wait_for_completion_timeout(&tcrtc->framedone_completion,
 					 msecs_to_jiffies(500)))
 		dev_err(tidss->dev, "Timeout waiting for framedone on crtc %d",
-			tcrtc->hw_videoport);
+			tcrtc->vp_idx);
 
-	dispc_vp_unprepare(tidss->dispc, tcrtc->hw_videoport);
+	dispc_vp_unprepare(tidss->dispc, tcrtc->vp_idx);
 
 	spin_lock_irqsave(&ddev->event_lock, flags);
 	if (crtc->state->event) {
@@ -288,11 +349,32 @@
 
 	drm_crtc_vblank_off(crtc);
 
-	dispc_vp_disable_clk(tidss->dispc, tcrtc->hw_videoport);
+	dispc_vp_disable_clk(tidss->dispc, tcrtc->vp_idx);
 
 	tidss_runtime_put(tidss);
 }
 
+static void tidss_shared_vp_crtc_atomic_disable(struct drm_crtc *crtc,
+						struct drm_atomic_state *state)
+{
+	struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
+	struct drm_device *ddev = crtc->dev;
+	unsigned long flags;
+
+	dev_dbg(ddev->dev, "%s, event %p\n", __func__, crtc->state->event);
+
+	reinit_completion(&tcrtc->framedone_completion);
+
+	spin_lock_irqsave(&ddev->event_lock, flags);
+	if (crtc->state->event) {
+		drm_crtc_send_vblank_event(crtc, crtc->state->event);
+		crtc->state->event = NULL;
+	}
+	spin_unlock_irqrestore(&ddev->event_lock, flags);
+
+	drm_crtc_vblank_off(crtc);
+}
+
 static
 enum drm_mode_status tidss_crtc_mode_valid(struct drm_crtc *crtc,
 					   const struct drm_display_mode *mode)
@@ -301,7 +383,7 @@
 	struct drm_device *ddev = crtc->dev;
 	struct tidss_device *tidss = to_tidss(ddev);
 
-	return dispc_vp_mode_valid(tidss->dispc, tcrtc->hw_videoport, mode);
+	return dispc_vp_mode_valid(tidss->dispc, tcrtc->vp_idx, mode);
 }
 
 static const struct drm_crtc_helper_funcs tidss_crtc_helper_funcs = {
@@ -309,7 +391,14 @@
 	.atomic_flush = tidss_crtc_atomic_flush,
 	.atomic_enable = tidss_crtc_atomic_enable,
 	.atomic_disable = tidss_crtc_atomic_disable,
+	.mode_valid = tidss_crtc_mode_valid,
+};
 
+static const struct drm_crtc_helper_funcs tidss_shared_vp_crtc_helper_funcs = {
+	.atomic_check = tidss_crtc_atomic_check,
+	.atomic_flush = tidss_shared_vp_crtc_atomic_flush,
+	.atomic_enable = tidss_shared_vp_crtc_atomic_enable,
+	.atomic_disable = tidss_shared_vp_crtc_atomic_disable,
 	.mode_valid = tidss_crtc_mode_valid,
 };
 
@@ -402,7 +491,7 @@
 };
 
 struct tidss_crtc *tidss_crtc_create(struct tidss_device *tidss,
-				     u32 hw_videoport,
+				     u32 vp_idx,
 				     struct drm_plane *primary)
 {
 	struct tidss_crtc *tcrtc;
@@ -411,11 +500,13 @@
 	bool has_ctm = tidss->feat->vp_feat.color.has_ctm;
 	int ret;
 
+	dev_dbg(tidss->dev, "%s: tidss->shared_mode: %d tidss->shared_mode_owned_vps[%d] = %d\n",
+		__func__, tidss->shared_mode, vp_idx, tidss->shared_mode_owned_vps[vp_idx]);
 	tcrtc = kzalloc(sizeof(*tcrtc), GFP_KERNEL);
 	if (!tcrtc)
 		return ERR_PTR(-ENOMEM);
 
-	tcrtc->hw_videoport = hw_videoport;
+	tcrtc->vp_idx = vp_idx;
 	init_completion(&tcrtc->framedone_completion);
 
 	crtc =  &tcrtc->crtc;
@@ -427,8 +518,16 @@
 		return ERR_PTR(ret);
 	}
 
-	drm_crtc_helper_add(crtc, &tidss_crtc_helper_funcs);
-
+	/* Use shared video port CRTC helpers which don't access associated
+	 * video port and overlay register spaces when Linux is not owning the
+	 * video port.
+	 */
+	if (tidss->shared_mode && !tidss->shared_mode_owned_vps[vp_idx]) {
+		drm_crtc_helper_add(crtc, &tidss_shared_vp_crtc_helper_funcs);
+		dev_dbg(tidss->dev, "%s: vp%d is being shared with Linux\n", __func__, vp_idx + 1);
+	} else {
+		drm_crtc_helper_add(crtc, &tidss_crtc_helper_funcs);
+	}
 	/*
 	 * The dispc gamma functions adapt to what ever size we ask
 	 * from it no matter what HW supports. X-server assumes 256
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_crtc.h b/drivers/gpu/drm/tidss/tidss_crtc.h
--- a/drivers/gpu/drm/tidss/tidss_crtc.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_crtc.h	2024-01-28 14:01:31.240353775 -0500
@@ -19,7 +19,7 @@
 struct tidss_crtc {
 	struct drm_crtc crtc;
 
-	u32 hw_videoport;
+	u32 vp_idx;
 
 	struct drm_pending_vblank_event *event;
 
@@ -43,6 +43,5 @@
 void tidss_crtc_error_irq(struct drm_crtc *crtc, u64 irqstatus);
 
 struct tidss_crtc *tidss_crtc_create(struct tidss_device *tidss,
-				     u32 hw_videoport,
-				     struct drm_plane *primary);
+				     u32 vp_idx, struct drm_plane *primary);
 #endif
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_dispc.c b/drivers/gpu/drm/tidss/tidss_dispc.c
--- a/drivers/gpu/drm/tidss/tidss_dispc.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_dispc.c	2024-01-28 14:01:31.240353775 -0500
@@ -61,7 +61,7 @@
 	.min_pclk_khz = 4375,
 
 	.max_pclk_khz = {
-		[DISPC_VP_DPI] = 150000,
+		[DISPC_OUTPUT_DPI] = 150000,
 	},
 
 	/*
@@ -88,6 +88,8 @@
 
 	.subrev = DISPC_K2G,
 
+	.has_oldi = false,
+
 	.common = "common",
 
 	.common_regs = tidss_k2g_common_regs,
@@ -96,7 +98,6 @@
 	.vp_name = { "vp1" },
 	.ovr_name = { "ovr1" },
 	.vpclk_name =  { "vp1" },
-	.vp_bus_type = { DISPC_VP_DPI },
 
 	.vp_feat = { .color = {
 			.has_ctm = true,
@@ -109,6 +110,10 @@
 	.vid_name = { "vid1" },
 	.vid_lite = { false },
 	.vid_order = { 0 },
+
+	.num_outputs = 1,
+	.output_type = { DISPC_OUTPUT_DPI, },
+	.output_source_vp = { 0, },
 };
 
 static const u16 tidss_am65x_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
@@ -138,10 +143,130 @@
 	[DISPC_SECURE_DISABLE_OFF] =		0xac,
 };
 
+static const u16 tidss_am62_common1_regs[DISPC_COMMON_REG_TABLE_LEN] = {
+	[DISPC_IRQ_EOI_OFF] =			0x24,
+	[DISPC_IRQSTATUS_RAW_OFF] =		0x28,
+	[DISPC_IRQSTATUS_OFF] =			0x2c,
+	[DISPC_IRQENABLE_SET_OFF] =		0x30,
+	[DISPC_IRQENABLE_CLR_OFF] =		0x40,
+	[DISPC_VID_IRQENABLE_OFF] =		0x44,
+	[DISPC_VID_IRQSTATUS_OFF] =		0x58,
+	[DISPC_VP_IRQENABLE_OFF] =		0x70,
+	[DISPC_VP_IRQSTATUS_OFF] =		0x7c,
+};
+
+const struct dispc_features dispc_am625_feats = {
+	.max_pclk_khz = {
+		[DISPC_OUTPUT_DPI] = 165000,
+		[DISPC_OUTPUT_OLDI] = 165000,
+	},
+
+	.scaling = {
+		.in_width_max_5tap_rgb = 1280,
+		.in_width_max_3tap_rgb = 2560,
+		.in_width_max_5tap_yuv = 2560,
+		.in_width_max_3tap_yuv = 4096,
+		.upscale_limit = 16,
+		.downscale_limit_5tap = 4,
+		.downscale_limit_3tap = 2,
+		/*
+		 * The max supported pixel inc value is 255. The value
+		 * of pixel inc is calculated like this: 1+(xinc-1)*bpp.
+		 * The maximum bpp of all formats supported by the HW
+		 * is 8. So the maximum supported xinc value is 32,
+		 * because 1+(32-1)*8 < 255 < 1+(33-1)*4.
+		 */
+		.xinc_max = 32,
+	},
+
+	.subrev = DISPC_AM625,
+
+	.has_oldi = true,
+
+	.common = "common",
+	.common_regs = tidss_am65x_common_regs,
+
+	.num_vps = 2,
+	.vp_name = { "vp1", "vp2" },
+	.ovr_name = { "ovr1", "ovr2" },
+	.vpclk_name =  { "vp1", "vp2" },
+
+	.vp_feat = { .color = {
+			.has_ctm = true,
+			.gamma_size = 256,
+			.gamma_type = TIDSS_GAMMA_8BIT,
+		},
+	},
+
+	.num_planes = 2,
+	/* note: vid is plane_id 0 and vidl1 is plane_id 1 */
+	.vid_name = { "vid", "vidl1" },
+	.vid_lite = { false, true, },
+	.vid_order = { 1, 0 },
+
+	/* 3rd output port is not representative of a 3rd pipeline */
+	.num_outputs = 3,
+	.output_type = { DISPC_OUTPUT_OLDI, DISPC_OUTPUT_DPI, DISPC_OUTPUT_OLDI, },
+	.output_source_vp = { 0, 1, 0, },
+};
+
+const struct dispc_features dispc_am62a7_feats = {
+	.max_pclk_khz = {
+		[DISPC_OUTPUT_DPI] = 165000,
+	},
+
+	.scaling = {
+		.in_width_max_5tap_rgb = 1280,
+		.in_width_max_3tap_rgb = 2560,
+		.in_width_max_5tap_yuv = 2560,
+		.in_width_max_3tap_yuv = 4096,
+		.upscale_limit = 16,
+		.downscale_limit_5tap = 4,
+		.downscale_limit_3tap = 2,
+		/*
+		 * The max supported pixel inc value is 255. The value
+		 * of pixel inc is calculated like this: 1+(xinc-1)*bpp.
+		 * The maximum bpp of all formats supported by the HW
+		 * is 8. So the maximum supported xinc value is 32,
+		 * because 1+(32-1)*8 < 255 < 1+(33-1)*4.
+		 */
+		.xinc_max = 32,
+	},
+
+	.subrev = DISPC_AM62A7,
+
+	.has_oldi = false,
+
+	.common = "common",
+	.common_regs = tidss_am65x_common_regs,
+
+	.num_vps = 2,
+	.vp_name = { "vp1", "vp2" },
+	.ovr_name = { "ovr1", "ovr2" },
+	.vpclk_name =  { "vp1", "vp2" },
+
+	.vp_feat = { .color = {
+			.has_ctm = true,
+			.gamma_size = 256,
+			.gamma_type = TIDSS_GAMMA_8BIT,
+		},
+	},
+
+	.num_planes = 2,
+	/* note: vid is plane_id 0 and vidl1 is plane_id 1 */
+	.vid_name = { "vid", "vidl1" },
+	.vid_lite = { false, true, },
+	.vid_order = { 1, 0 },
+
+	.num_outputs = 1,
+	.output_type = { DISPC_OUTPUT_DPI, },
+	.output_source_vp = { 1, },
+};
+
 const struct dispc_features dispc_am65x_feats = {
 	.max_pclk_khz = {
-		[DISPC_VP_DPI] = 165000,
-		[DISPC_VP_OLDI] = 165000,
+		[DISPC_OUTPUT_DPI] = 165000,
+		[DISPC_OUTPUT_OLDI] = 165000,
 	},
 
 	.scaling = {
@@ -164,6 +289,8 @@
 
 	.subrev = DISPC_AM65X,
 
+	.has_oldi = true,
+
 	.common = "common",
 	.common_regs = tidss_am65x_common_regs,
 
@@ -171,7 +298,6 @@
 	.vp_name = { "vp1", "vp2" },
 	.ovr_name = { "ovr1", "ovr2" },
 	.vpclk_name =  { "vp1", "vp2" },
-	.vp_bus_type = { DISPC_VP_OLDI, DISPC_VP_DPI },
 
 	.vp_feat = { .color = {
 			.has_ctm = true,
@@ -185,6 +311,10 @@
 	.vid_name = { "vid", "vidl1" },
 	.vid_lite = { false, true, },
 	.vid_order = { 1, 0 },
+
+	.num_outputs = 2,
+	.output_type = { DISPC_OUTPUT_OLDI, DISPC_OUTPUT_DPI, },
+	.output_source_vp = { 0, 1, },
 };
 
 static const u16 tidss_j721e_common_regs[DISPC_COMMON_REG_TABLE_LEN] = {
@@ -229,8 +359,8 @@
 
 const struct dispc_features dispc_j721e_feats = {
 	.max_pclk_khz = {
-		[DISPC_VP_DPI] = 170000,
-		[DISPC_VP_INTERNAL] = 600000,
+		[DISPC_OUTPUT_DPI] = 170000,
+		[DISPC_OUTPUT_INTERNAL] = 600000,
 	},
 
 	.scaling = {
@@ -253,6 +383,8 @@
 
 	.subrev = DISPC_J721E,
 
+	.has_oldi = false,
+
 	.common = "common_m",
 	.common_regs = tidss_j721e_common_regs,
 
@@ -260,9 +392,6 @@
 	.vp_name = { "vp1", "vp2", "vp3", "vp4" },
 	.ovr_name = { "ovr1", "ovr2", "ovr3", "ovr4" },
 	.vpclk_name = { "vp1", "vp2", "vp3", "vp4" },
-	/* Currently hard coded VP routing (see dispc_initial_config()) */
-	.vp_bus_type =	{ DISPC_VP_INTERNAL, DISPC_VP_DPI,
-			  DISPC_VP_INTERNAL, DISPC_VP_DPI, },
 	.vp_feat = { .color = {
 			.has_ctm = true,
 			.gamma_size = 1024,
@@ -273,6 +402,122 @@
 	.vid_name = { "vid1", "vidl1", "vid2", "vidl2" },
 	.vid_lite = { 0, 1, 0, 1, },
 	.vid_order = { 1, 3, 0, 2 },
+
+	.num_outputs = 4,
+	/* Currently hard coded VP routing (see dispc_initial_config()) */
+	.output_type = { DISPC_OUTPUT_INTERNAL, DISPC_OUTPUT_DPI,
+			 DISPC_OUTPUT_INTERNAL, DISPC_OUTPUT_DPI, },
+	.output_source_vp = { 0, 1, 2, 3, },
+};
+
+const struct dispc_features dispc_am62p51_feats = {
+	.max_pclk_khz = {
+		[DISPC_OUTPUT_DPI] = 165000,
+		[DISPC_OUTPUT_OLDI] = 300000,
+	},
+
+	.scaling = {
+		.in_width_max_5tap_rgb = 1280,
+		.in_width_max_3tap_rgb = 2560,
+		.in_width_max_5tap_yuv = 2560,
+		.in_width_max_3tap_yuv = 4096,
+		.upscale_limit = 16,
+		.downscale_limit_5tap = 4,
+		.downscale_limit_3tap = 2,
+		/*
+		 * The max supported pixel inc value is 255. The value
+		 * of pixel inc is calculated like this: 1+(xinc-1)*bpp.
+		 * The maximum bpp of all formats supported by the HW
+		 * is 8. So the maximum supported xinc value is 32,
+		 * because 1+(32-1)*8 < 255 < 1+(33-1)*4.
+		 */
+		.xinc_max = 32,
+	},
+
+	.subrev = DISPC_AM62P51,
+
+	.has_oldi = true,
+
+	.common = "common",
+	.common_regs = tidss_am65x_common_regs,
+
+	.num_vps = 2,
+	.vp_name = { "vp1", "vp2" },
+	.ovr_name = { "ovr1", "ovr2" },
+	.vpclk_name =  { "vp1", "vp2" },
+
+	.vp_feat = { .color = {
+			.has_ctm = true,
+			.gamma_size = 256,
+			.gamma_type = TIDSS_GAMMA_8BIT,
+		},
+	},
+
+	.num_planes = 2,
+	/* note: vid is plane_id 0 and vidl1 is plane_id 1 */
+	.vid_name = { "vid", "vidl1" },
+	.vid_lite = { false, true, },
+	.vid_order = { 1, 0 },
+
+	/* 3rd output port is not representative of a 3rd pipeline */
+	.num_outputs = 3,
+	.output_type = { DISPC_OUTPUT_OLDI, DISPC_OUTPUT_DPI, DISPC_OUTPUT_OLDI, },
+	.output_source_vp = { 0, 1, 0, },
+};
+
+const struct dispc_features dispc_am62p52_feats = {
+	.max_pclk_khz = {
+		[DISPC_OUTPUT_DPI] = 165000,
+		[DISPC_OUTPUT_OLDI] = 100000,
+		[DISPC_OUTPUT_INTERNAL] = 300000,
+	},
+
+	.scaling = {
+		.in_width_max_5tap_rgb = 1280,
+		.in_width_max_3tap_rgb = 2560,
+		.in_width_max_5tap_yuv = 2560,
+		.in_width_max_3tap_yuv = 4096,
+		.upscale_limit = 16,
+		.downscale_limit_5tap = 4,
+		.downscale_limit_3tap = 2,
+		/*
+		 * The max supported pixel inc value is 255. The value
+		 * of pixel inc is calculated like this: 1+(xinc-1)*bpp.
+		 * The maximum bpp of all formats supported by the HW
+		 * is 8. So the maximum supported xinc value is 32,
+		 * because 1+(32-1)*8 < 255 < 1+(33-1)*4.
+		 */
+		.xinc_max = 32,
+	},
+
+	.subrev = DISPC_AM62P52,
+
+	.has_oldi = true,
+
+	.common = "common",
+	.common_regs = tidss_am65x_common_regs,
+
+	.num_vps = 2,
+	.vp_name = { "vp1", "vp2" },
+	.ovr_name = { "ovr1", "ovr2" },
+	.vpclk_name =  { "vp1", "vp2" },
+
+	.vp_feat = { .color = {
+			.has_ctm = true,
+			.gamma_size = 256,
+			.gamma_type = TIDSS_GAMMA_8BIT,
+		},
+	},
+
+	.num_planes = 2,
+	/* note: vid is plane_id 0 and vidl1 is plane_id 1 */
+	.vid_name = { "vid", "vidl1" },
+	.vid_lite = { false, true, },
+	.vid_order = { 1, 0 },
+
+	.num_outputs = 2,
+	.output_type = { DISPC_OUTPUT_INTERNAL, DISPC_OUTPUT_INTERNAL, },
+	.output_source_vp = { 0, 1, },
 };
 
 static const u16 *dispc_common_regmap;
@@ -287,12 +532,12 @@
 
 	void __iomem *base_common;
 	void __iomem *base_vid[TIDSS_MAX_PLANES];
-	void __iomem *base_ovr[TIDSS_MAX_PORTS];
-	void __iomem *base_vp[TIDSS_MAX_PORTS];
+	void __iomem *base_ovr[TIDSS_MAX_VPS];
+	void __iomem *base_vp[TIDSS_MAX_VPS];
 
 	struct regmap *oldi_io_ctrl;
 
-	struct clk *vp_clk[TIDSS_MAX_PORTS];
+	struct clk *vp_clk[TIDSS_MAX_VPS];
 
 	const struct dispc_features *feat;
 
@@ -300,7 +545,9 @@
 
 	bool is_enabled;
 
-	struct dss_vp_data vp_data[TIDSS_MAX_PORTS];
+	struct dss_vp_data vp_data[TIDSS_MAX_VPS];
+
+	enum dispc_oldi_modes oldi_mode;
 
 	u32 *fourccs;
 	u32 num_fourccs;
@@ -335,32 +582,32 @@
 	return ioread32(base + reg);
 }
 
-static void dispc_ovr_write(struct dispc_device *dispc, u32 hw_videoport,
-			    u16 reg, u32 val)
+static void dispc_ovr_write(struct dispc_device *dispc, u32 vp_idx, u16 reg,
+			    u32 val)
 {
-	void __iomem *base = dispc->base_ovr[hw_videoport];
+	void __iomem *base = dispc->base_ovr[vp_idx];
 
 	iowrite32(val, base + reg);
 }
 
-static u32 dispc_ovr_read(struct dispc_device *dispc, u32 hw_videoport, u16 reg)
+static u32 dispc_ovr_read(struct dispc_device *dispc, u32 vp_idx, u16 reg)
 {
-	void __iomem *base = dispc->base_ovr[hw_videoport];
+	void __iomem *base = dispc->base_ovr[vp_idx];
 
 	return ioread32(base + reg);
 }
 
-static void dispc_vp_write(struct dispc_device *dispc, u32 hw_videoport,
-			   u16 reg, u32 val)
+static void dispc_vp_write(struct dispc_device *dispc, u32 vp_idx, u16 reg,
+			   u32 val)
 {
-	void __iomem *base = dispc->base_vp[hw_videoport];
+	void __iomem *base = dispc->base_vp[vp_idx];
 
 	iowrite32(val, base + reg);
 }
 
-static u32 dispc_vp_read(struct dispc_device *dispc, u32 hw_videoport, u16 reg)
+static u32 dispc_vp_read(struct dispc_device *dispc, u32 vp_idx, u16 reg)
 {
-	void __iomem *base = dispc->base_vp[hw_videoport];
+	void __iomem *base = dispc->base_vp[vp_idx];
 
 	return ioread32(base + reg);
 }
@@ -444,33 +691,45 @@
 				val, start, end));
 }
 
-static dispc_irq_t dispc_vp_irq_from_raw(u32 stat, u32 hw_videoport)
+enum dispc_output_type dispc_get_output_type(struct dispc_device *dispc,
+					     u32 vp_idx)
+{
+	u32 i;
+
+	for (i = 0; i < dispc->feat->num_outputs; i++)
+		if (dispc->feat->output_source_vp[i] == vp_idx)
+			return dispc->feat->output_type[i];
+
+	return DISPC_OUTPUT_DPI;
+}
+
+static dispc_irq_t dispc_vp_irq_from_raw(u32 stat, u32 vp_idx)
 {
 	dispc_irq_t vp_stat = 0;
 
 	if (stat & BIT(0))
-		vp_stat |= DSS_IRQ_VP_FRAME_DONE(hw_videoport);
+		vp_stat |= DSS_IRQ_VP_FRAME_DONE(vp_idx);
 	if (stat & BIT(1))
-		vp_stat |= DSS_IRQ_VP_VSYNC_EVEN(hw_videoport);
+		vp_stat |= DSS_IRQ_VP_VSYNC_EVEN(vp_idx);
 	if (stat & BIT(2))
-		vp_stat |= DSS_IRQ_VP_VSYNC_ODD(hw_videoport);
+		vp_stat |= DSS_IRQ_VP_VSYNC_ODD(vp_idx);
 	if (stat & BIT(4))
-		vp_stat |= DSS_IRQ_VP_SYNC_LOST(hw_videoport);
+		vp_stat |= DSS_IRQ_VP_SYNC_LOST(vp_idx);
 
 	return vp_stat;
 }
 
-static u32 dispc_vp_irq_to_raw(dispc_irq_t vpstat, u32 hw_videoport)
+static u32 dispc_vp_irq_to_raw(dispc_irq_t vpstat, u32 vp_idx)
 {
 	u32 stat = 0;
 
-	if (vpstat & DSS_IRQ_VP_FRAME_DONE(hw_videoport))
+	if (vpstat & DSS_IRQ_VP_FRAME_DONE(vp_idx))
 		stat |= BIT(0);
-	if (vpstat & DSS_IRQ_VP_VSYNC_EVEN(hw_videoport))
+	if (vpstat & DSS_IRQ_VP_VSYNC_EVEN(vp_idx))
 		stat |= BIT(1);
-	if (vpstat & DSS_IRQ_VP_VSYNC_ODD(hw_videoport))
+	if (vpstat & DSS_IRQ_VP_VSYNC_ODD(vp_idx))
 		stat |= BIT(2);
-	if (vpstat & DSS_IRQ_VP_SYNC_LOST(hw_videoport))
+	if (vpstat & DSS_IRQ_VP_SYNC_LOST(vp_idx))
 		stat |= BIT(4);
 
 	return stat;
@@ -497,19 +756,19 @@
 }
 
 static dispc_irq_t dispc_k2g_vp_read_irqstatus(struct dispc_device *dispc,
-					       u32 hw_videoport)
+					       u32 vp_idx)
 {
-	u32 stat = dispc_vp_read(dispc, hw_videoport, DISPC_VP_K2G_IRQSTATUS);
+	u32 stat = dispc_vp_read(dispc, vp_idx, DISPC_VP_K2G_IRQSTATUS);
 
-	return dispc_vp_irq_from_raw(stat, hw_videoport);
+	return dispc_vp_irq_from_raw(stat, vp_idx);
 }
 
-static void dispc_k2g_vp_write_irqstatus(struct dispc_device *dispc,
-					 u32 hw_videoport, dispc_irq_t vpstat)
+static void dispc_k2g_vp_write_irqstatus(struct dispc_device *dispc, u32 vp_idx,
+					 dispc_irq_t vpstat)
 {
-	u32 stat = dispc_vp_irq_to_raw(vpstat, hw_videoport);
+	u32 stat = dispc_vp_irq_to_raw(vpstat, vp_idx);
 
-	dispc_vp_write(dispc, hw_videoport, DISPC_VP_K2G_IRQSTATUS, stat);
+	dispc_vp_write(dispc, vp_idx, DISPC_VP_K2G_IRQSTATUS, stat);
 }
 
 static dispc_irq_t dispc_k2g_vid_read_irqstatus(struct dispc_device *dispc,
@@ -529,19 +788,19 @@
 }
 
 static dispc_irq_t dispc_k2g_vp_read_irqenable(struct dispc_device *dispc,
-					       u32 hw_videoport)
+					       u32 vp_idx)
 {
-	u32 stat = dispc_vp_read(dispc, hw_videoport, DISPC_VP_K2G_IRQENABLE);
+	u32 stat = dispc_vp_read(dispc, vp_idx, DISPC_VP_K2G_IRQENABLE);
 
-	return dispc_vp_irq_from_raw(stat, hw_videoport);
+	return dispc_vp_irq_from_raw(stat, vp_idx);
 }
 
 static void dispc_k2g_vp_set_irqenable(struct dispc_device *dispc,
-				       u32 hw_videoport, dispc_irq_t vpstat)
+				       u32 vp_idx, dispc_irq_t vpstat)
 {
-	u32 stat = dispc_vp_irq_to_raw(vpstat, hw_videoport);
+	u32 stat = dispc_vp_irq_to_raw(vpstat, vp_idx);
 
-	dispc_vp_write(dispc, hw_videoport, DISPC_VP_K2G_IRQENABLE, stat);
+	dispc_vp_write(dispc, vp_idx, DISPC_VP_K2G_IRQENABLE, stat);
 }
 
 static dispc_irq_t dispc_k2g_vid_read_irqenable(struct dispc_device *dispc,
@@ -612,19 +871,19 @@
 }
 
 static dispc_irq_t dispc_k3_vp_read_irqstatus(struct dispc_device *dispc,
-					      u32 hw_videoport)
+					      u32 vp_idx)
 {
-	u32 stat = dispc_read(dispc, DISPC_VP_IRQSTATUS(hw_videoport));
+	u32 stat = dispc_read(dispc, DISPC_VP_IRQSTATUS(vp_idx));
 
-	return dispc_vp_irq_from_raw(stat, hw_videoport);
+	return dispc_vp_irq_from_raw(stat, vp_idx);
 }
 
 static void dispc_k3_vp_write_irqstatus(struct dispc_device *dispc,
-					u32 hw_videoport, dispc_irq_t vpstat)
+					u32 vp_idx, dispc_irq_t vpstat)
 {
-	u32 stat = dispc_vp_irq_to_raw(vpstat, hw_videoport);
+	u32 stat = dispc_vp_irq_to_raw(vpstat, vp_idx);
 
-	dispc_write(dispc, DISPC_VP_IRQSTATUS(hw_videoport), stat);
+	dispc_write(dispc, DISPC_VP_IRQSTATUS(vp_idx), stat);
 }
 
 static dispc_irq_t dispc_k3_vid_read_irqstatus(struct dispc_device *dispc,
@@ -644,19 +903,19 @@
 }
 
 static dispc_irq_t dispc_k3_vp_read_irqenable(struct dispc_device *dispc,
-					      u32 hw_videoport)
+					      u32 vp_idx)
 {
-	u32 stat = dispc_read(dispc, DISPC_VP_IRQENABLE(hw_videoport));
+	u32 stat = dispc_read(dispc, DISPC_VP_IRQENABLE(vp_idx));
 
-	return dispc_vp_irq_from_raw(stat, hw_videoport);
+	return dispc_vp_irq_from_raw(stat, vp_idx);
 }
 
-static void dispc_k3_vp_set_irqenable(struct dispc_device *dispc,
-				      u32 hw_videoport, dispc_irq_t vpstat)
+static void dispc_k3_vp_set_irqenable(struct dispc_device *dispc, u32 vp_idx,
+				      dispc_irq_t vpstat)
 {
-	u32 stat = dispc_vp_irq_to_raw(vpstat, hw_videoport);
+	u32 stat = dispc_vp_irq_to_raw(vpstat, vp_idx);
 
-	dispc_write(dispc, DISPC_VP_IRQENABLE(hw_videoport), stat);
+	dispc_write(dispc, DISPC_VP_IRQENABLE(vp_idx), stat);
 }
 
 static dispc_irq_t dispc_k3_vid_read_irqenable(struct dispc_device *dispc,
@@ -776,6 +1035,10 @@
 	switch (dispc->feat->subrev) {
 	case DISPC_K2G:
 		return dispc_k2g_read_and_clear_irqstatus(dispc);
+	case DISPC_AM625:
+	case DISPC_AM62A7:
+	case DISPC_AM62P51:
+	case DISPC_AM62P52:
 	case DISPC_AM65X:
 	case DISPC_J721E:
 		return dispc_k3_read_and_clear_irqstatus(dispc);
@@ -791,6 +1054,10 @@
 	case DISPC_K2G:
 		dispc_k2g_set_irqenable(dispc, mask);
 		break;
+	case DISPC_AM625:
+	case DISPC_AM62A7:
+	case DISPC_AM62P51:
+	case DISPC_AM62P52:
 	case DISPC_AM65X:
 	case DISPC_J721E:
 		dispc_k3_set_irqenable(dispc, mask);
@@ -824,8 +1091,8 @@
 
 static const
 struct dispc_bus_format *dispc_vp_find_bus_fmt(struct dispc_device *dispc,
-					       u32 hw_videoport,
-					       u32 bus_fmt, u32 bus_flags)
+					       u32 vp_idx, u32 bus_fmt,
+					       u32 bus_flags)
 {
 	unsigned int i;
 
@@ -837,13 +1104,14 @@
 	return NULL;
 }
 
-int dispc_vp_bus_check(struct dispc_device *dispc, u32 hw_videoport,
+int dispc_vp_bus_check(struct dispc_device *dispc, u32 vp_idx,
 		       const struct drm_crtc_state *state)
 {
 	const struct tidss_crtc_state *tstate = to_tidss_crtc_state(state);
 	const struct dispc_bus_format *fmt;
+	enum dispc_output_type output_type;
 
-	fmt = dispc_vp_find_bus_fmt(dispc, hw_videoport, tstate->bus_format,
+	fmt = dispc_vp_find_bus_fmt(dispc, vp_idx, tstate->bus_format,
 				    tstate->bus_flags);
 	if (!fmt) {
 		dev_dbg(dispc->dev, "%s: Unsupported bus format: %u\n",
@@ -851,10 +1119,10 @@
 		return -EINVAL;
 	}
 
-	if (dispc->feat->vp_bus_type[hw_videoport] != DISPC_VP_OLDI &&
-	    fmt->is_oldi_fmt) {
+	output_type = dispc_get_output_type(dispc, vp_idx);
+	if (output_type != DISPC_OUTPUT_OLDI && fmt->is_oldi_fmt) {
 		dev_dbg(dispc->dev, "%s: %s is not OLDI-port\n",
-			__func__, dispc->feat->vp_name[hw_videoport]);
+			__func__, dispc->feat->vp_name[vp_idx]);
 		return -EINVAL;
 	}
 
@@ -863,25 +1131,102 @@
 
 static void dispc_oldi_tx_power(struct dispc_device *dispc, bool power)
 {
-	u32 val = power ? 0 : OLDI_PWRDN_TX;
+	u32 val = 0;
 
 	if (WARN_ON(!dispc->oldi_io_ctrl))
 		return;
 
-	regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT0_IO_CTRL,
-			   OLDI_PWRDN_TX, val);
-	regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT1_IO_CTRL,
-			   OLDI_PWRDN_TX, val);
-	regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT2_IO_CTRL,
-			   OLDI_PWRDN_TX, val);
-	regmap_update_bits(dispc->oldi_io_ctrl, OLDI_DAT3_IO_CTRL,
-			   OLDI_PWRDN_TX, val);
-	regmap_update_bits(dispc->oldi_io_ctrl, OLDI_CLK_IO_CTRL,
-			   OLDI_PWRDN_TX, val);
+	/*
+	 * The power control bits are Active Low, and remain powered off by
+	 * default. That is, the bits are set to 1. To power on the OLDI TXes,
+	 * the bits must be cleared to 0. Since there are cases where not all
+	 * OLDI TXes are being used, the power logic selectively powers them
+	 * on.
+	 * Setting the variable 'val' to particular bit masks, makes sure that
+	 * the unrequired OLDI TXes remain powered off.
+	 */
+	switch (dispc->feat->subrev) {
+	case DISPC_AM625:
+		if (power) {
+			switch (dispc->oldi_mode) {
+			case OLDI_MODE_SINGLE_LINK:
+				/* Power down OLDI TX 1 */
+				val = AM625_OLDI1_PWRDN_TX;
+				break;
+
+			case OLDI_MODE_CLONE_SINGLE_LINK:
+			case OLDI_MODE_DUAL_LINK:
+				/* No Power down */
+				val = 0;
+				break;
+
+			default:
+				/* Power down both OLDI TXes and LVDS Bandgap */
+				val = AM625_OLDI0_PWRDN_TX | AM625_OLDI1_PWRDN_TX |
+				      AM625_OLDI_PWRDN_BG;
+				break;
+			}
+
+		} else {
+			/* Power down both OLDI TXes and LVDS Bandgap */
+			val = AM625_OLDI0_PWRDN_TX | AM625_OLDI1_PWRDN_TX |
+			      AM625_OLDI_PWRDN_BG;
+		}
+
+		regmap_update_bits(dispc->oldi_io_ctrl, AM625_OLDI_PD_CTRL,
+				   AM625_OLDI0_PWRDN_TX | AM625_OLDI1_PWRDN_TX |
+				   AM625_OLDI_PWRDN_BG, val);
+		break;
+
+	case DISPC_AM62P51:
+	case DISPC_AM62P52:
+		if (power) {
+			switch (dispc->oldi_mode) {
+			case OLDI_MODE_SINGLE_LINK:
+			case OLDI_MODE_CLONE_SINGLE_LINK:
+			case OLDI_MODE_DUAL_LINK:
+				/* No Power down because the other AM62P DSS could be using it. */
+				val = 0;
+				break;
+
+			default:
+				/* Power down both OLDI TXes and LVDS Bandgap */
+				val = AM625_OLDI0_PWRDN_TX | AM625_OLDI1_PWRDN_TX |
+				      AM625_OLDI_PWRDN_BG;
+				break;
+			}
+
+		} else {
+			/* No Power down because the other AM62P DSS could be using it. */
+			val = 0;
+		}
+
+		regmap_update_bits(dispc->oldi_io_ctrl, AM625_OLDI_PD_CTRL,
+				   AM625_OLDI0_PWRDN_TX | AM625_OLDI1_PWRDN_TX |
+				   AM625_OLDI_PWRDN_BG, val);
+		break;
+
+	case DISPC_AM65X:
+		val = power ? 0 : AM65X_OLDI_PWRDN_TX;
+
+		regmap_update_bits(dispc->oldi_io_ctrl, AM65X_OLDI_DAT0_IO_CTRL,
+				   AM65X_OLDI_PWRDN_TX, val);
+		regmap_update_bits(dispc->oldi_io_ctrl, AM65X_OLDI_DAT1_IO_CTRL,
+				   AM65X_OLDI_PWRDN_TX, val);
+		regmap_update_bits(dispc->oldi_io_ctrl, AM65X_OLDI_DAT2_IO_CTRL,
+				   AM65X_OLDI_PWRDN_TX, val);
+		regmap_update_bits(dispc->oldi_io_ctrl, AM65X_OLDI_DAT3_IO_CTRL,
+				   AM65X_OLDI_PWRDN_TX, val);
+		regmap_update_bits(dispc->oldi_io_ctrl, AM65X_OLDI_CLK_IO_CTRL,
+				   AM65X_OLDI_PWRDN_TX, val);
+		break;
+	default:
+		break;
+	}
 }
 
-static void dispc_set_num_datalines(struct dispc_device *dispc,
-				    u32 hw_videoport, int num_lines)
+static void dispc_set_num_datalines(struct dispc_device *dispc, u32 vp_idx,
+				    int num_lines)
 {
 	int v;
 
@@ -903,19 +1248,19 @@
 		v = 3;
 	}
 
-	VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, v, 10, 8);
+	VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONTROL, v, 10, 8);
 }
 
-static void dispc_enable_oldi(struct dispc_device *dispc, u32 hw_videoport,
+static void dispc_enable_oldi(struct dispc_device *dispc, u32 vp_idx,
 			      const struct dispc_bus_format *fmt)
 {
 	u32 oldi_cfg = 0;
-	u32 oldi_reset_bit = BIT(5 + hw_videoport);
+	u32 oldi_reset_bit = BIT(5 + vp_idx);
 	int count = 0;
 
 	/*
-	 * For the moment DUALMODESYNC, MASTERSLAVE, MODE, and SRC
-	 * bits of DISPC_VP_DSS_OLDI_CFG are set statically to 0.
+	 * For the moment MASTERSLAVE, and SRC bits of DISPC_VP_DSS_OLDI_CFG are
+	 * always set to 0.
 	 */
 
 	if (fmt->data_width == 24)
@@ -932,7 +1277,27 @@
 
 	oldi_cfg |= BIT(0); /* ENABLE */
 
-	dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, oldi_cfg);
+	switch (dispc->oldi_mode) {
+	case OLDI_MODE_SINGLE_LINK:
+		/* All configuration is done for this mode.  */
+		break;
+
+	case OLDI_MODE_CLONE_SINGLE_LINK:
+		oldi_cfg |= BIT(5); /* CLONE MODE */
+		break;
+
+	case OLDI_MODE_DUAL_LINK:
+		oldi_cfg |= BIT(11); /* DUALMODESYNC */
+		oldi_cfg |= BIT(3); /* data-mapping field also indicates dual-link mode */
+		break;
+
+	default:
+		dev_warn(dispc->dev, "%s: Incorrect oldi mode. Returning.\n",
+			 __func__);
+		return;
+	}
+
+	dispc_vp_write(dispc, vp_idx, DISPC_VP_DSS_OLDI_CFG, oldi_cfg);
 
 	while (!(oldi_reset_bit & dispc_read(dispc, DSS_SYSSTATUS)) &&
 	       count < 10000)
@@ -943,26 +1308,28 @@
 			 __func__);
 }
 
-void dispc_vp_prepare(struct dispc_device *dispc, u32 hw_videoport,
+void dispc_vp_prepare(struct dispc_device *dispc, u32 vp_idx,
 		      const struct drm_crtc_state *state)
 {
 	const struct tidss_crtc_state *tstate = to_tidss_crtc_state(state);
 	const struct dispc_bus_format *fmt;
+	enum dispc_output_type output_type;
 
-	fmt = dispc_vp_find_bus_fmt(dispc, hw_videoport, tstate->bus_format,
+	fmt = dispc_vp_find_bus_fmt(dispc, vp_idx, tstate->bus_format,
 				    tstate->bus_flags);
 
 	if (WARN_ON(!fmt))
 		return;
 
-	if (dispc->feat->vp_bus_type[hw_videoport] == DISPC_VP_OLDI) {
+	output_type = dispc_get_output_type(dispc, vp_idx);
+	if (output_type == DISPC_OUTPUT_OLDI) {
 		dispc_oldi_tx_power(dispc, true);
 
-		dispc_enable_oldi(dispc, hw_videoport, fmt);
+		dispc_enable_oldi(dispc, vp_idx, fmt);
 	}
 }
 
-void dispc_vp_enable(struct dispc_device *dispc, u32 hw_videoport,
+void dispc_vp_enable(struct dispc_device *dispc, u32 vp_idx,
 		     const struct drm_crtc_state *state)
 {
 	const struct drm_display_mode *mode = &state->adjusted_mode;
@@ -970,14 +1337,15 @@
 	bool align, onoff, rf, ieo, ipc, ihs, ivs;
 	const struct dispc_bus_format *fmt;
 	u32 hsw, hfp, hbp, vsw, vfp, vbp;
+	enum dispc_output_type output_type;
 
-	fmt = dispc_vp_find_bus_fmt(dispc, hw_videoport, tstate->bus_format,
+	fmt = dispc_vp_find_bus_fmt(dispc, vp_idx, tstate->bus_format,
 				    tstate->bus_flags);
 
 	if (WARN_ON(!fmt))
 		return;
 
-	dispc_set_num_datalines(dispc, hw_videoport, fmt->data_width);
+	dispc_set_num_datalines(dispc, vp_idx, fmt->data_width);
 
 	hfp = mode->hsync_start - mode->hdisplay;
 	hsw = mode->hsync_end - mode->hsync_start;
@@ -987,12 +1355,12 @@
 	vsw = mode->vsync_end - mode->vsync_start;
 	vbp = mode->vtotal - mode->vsync_end;
 
-	dispc_vp_write(dispc, hw_videoport, DISPC_VP_TIMING_H,
+	dispc_vp_write(dispc, vp_idx, DISPC_VP_TIMING_H,
 		       FLD_VAL(hsw - 1, 7, 0) |
 		       FLD_VAL(hfp - 1, 19, 8) |
 		       FLD_VAL(hbp - 1, 31, 20));
 
-	dispc_vp_write(dispc, hw_videoport, DISPC_VP_TIMING_V,
+	dispc_vp_write(dispc, vp_idx, DISPC_VP_TIMING_V,
 		       FLD_VAL(vsw - 1, 7, 0) |
 		       FLD_VAL(vfp, 19, 8) |
 		       FLD_VAL(vbp, 31, 20));
@@ -1014,10 +1382,11 @@
 	align = true;
 
 	/* always use DE_HIGH for OLDI */
-	if (dispc->feat->vp_bus_type[hw_videoport] == DISPC_VP_OLDI)
+	output_type = dispc_get_output_type(dispc, vp_idx);
+	if (output_type == DISPC_OUTPUT_OLDI)
 		ieo = false;
 
-	dispc_vp_write(dispc, hw_videoport, DISPC_VP_POL_FREQ,
+	dispc_vp_write(dispc, vp_idx, DISPC_VP_POL_FREQ,
 		       FLD_VAL(align, 18, 18) |
 		       FLD_VAL(onoff, 17, 17) |
 		       FLD_VAL(rf, 16, 16) |
@@ -1026,36 +1395,39 @@
 		       FLD_VAL(ihs, 13, 13) |
 		       FLD_VAL(ivs, 12, 12));
 
-	dispc_vp_write(dispc, hw_videoport, DISPC_VP_SIZE_SCREEN,
+	dispc_vp_write(dispc, vp_idx, DISPC_VP_SIZE_SCREEN,
 		       FLD_VAL(mode->hdisplay - 1, 11, 0) |
 		       FLD_VAL(mode->vdisplay - 1, 27, 16));
 
-	VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 1, 0, 0);
+	VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONTROL, 1, 0, 0);
 }
 
-void dispc_vp_disable(struct dispc_device *dispc, u32 hw_videoport)
+void dispc_vp_disable(struct dispc_device *dispc, u32 vp_idx)
 {
-	VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 0, 0, 0);
+	VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONTROL, 0, 0, 0);
 }
 
-void dispc_vp_unprepare(struct dispc_device *dispc, u32 hw_videoport)
+void dispc_vp_unprepare(struct dispc_device *dispc, u32 vp_idx)
 {
-	if (dispc->feat->vp_bus_type[hw_videoport] == DISPC_VP_OLDI) {
-		dispc_vp_write(dispc, hw_videoport, DISPC_VP_DSS_OLDI_CFG, 0);
+	enum dispc_output_type output_type;
+
+	output_type = dispc_get_output_type(dispc, vp_idx);
+	if (output_type == DISPC_OUTPUT_OLDI) {
+		dispc_vp_write(dispc, vp_idx, DISPC_VP_DSS_OLDI_CFG, 0);
 
 		dispc_oldi_tx_power(dispc, false);
 	}
 }
 
-bool dispc_vp_go_busy(struct dispc_device *dispc, u32 hw_videoport)
+bool dispc_vp_go_busy(struct dispc_device *dispc, u32 vp_idx)
 {
-	return VP_REG_GET(dispc, hw_videoport, DISPC_VP_CONTROL, 5, 5);
+	return VP_REG_GET(dispc, vp_idx, DISPC_VP_CONTROL, 5, 5);
 }
 
-void dispc_vp_go(struct dispc_device *dispc, u32 hw_videoport)
+void dispc_vp_go(struct dispc_device *dispc, u32 vp_idx)
 {
-	WARN_ON(VP_REG_GET(dispc, hw_videoport, DISPC_VP_CONTROL, 5, 5));
-	VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONTROL, 1, 5, 5);
+	WARN_ON(VP_REG_GET(dispc, vp_idx, DISPC_VP_CONTROL, 5, 5));
+	VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONTROL, 1, 5, 5);
 }
 
 enum c8_to_c12_mode { C8_TO_C12_REPLICATE, C8_TO_C12_MAX, C8_TO_C12_MIN };
@@ -1098,30 +1470,45 @@
 	return v;
 }
 
-static void dispc_vp_set_default_color(struct dispc_device *dispc,
-				       u32 hw_videoport, u32 default_color)
+static void dispc_vp_set_default_color(struct dispc_device *dispc, u32 vp_idx,
+				       u32 default_color)
 {
 	u64 v;
 
 	v = argb8888_to_argb12121212(default_color, C8_TO_C12_REPLICATE);
 
-	dispc_ovr_write(dispc, hw_videoport,
+	dispc_ovr_write(dispc, vp_idx,
 			DISPC_OVR_DEFAULT_COLOR, v & 0xffffffff);
-	dispc_ovr_write(dispc, hw_videoport,
+	dispc_ovr_write(dispc, vp_idx,
 			DISPC_OVR_DEFAULT_COLOR2, (v >> 32) & 0xffff);
 }
 
-enum drm_mode_status dispc_vp_mode_valid(struct dispc_device *dispc,
-					 u32 hw_videoport,
+enum drm_mode_status dispc_vp_mode_valid(struct dispc_device *dispc, u32 vp_idx,
 					 const struct drm_display_mode *mode)
 {
 	u32 hsw, hfp, hbp, vsw, vfp, vbp;
-	enum dispc_vp_bus_type bus_type;
+	enum dispc_output_type output_type;
 	int max_pclk;
 
-	bus_type = dispc->feat->vp_bus_type[hw_videoport];
+	output_type = dispc_get_output_type(dispc, vp_idx);
+
+	max_pclk = dispc->feat->max_pclk_khz[output_type];
 
-	max_pclk = dispc->feat->max_pclk_khz[bus_type];
+	/*
+	 * For shared mode, with remote core driving the video port, make sure that Linux
+	 * controlled primary plane doesn't exceed video port screen size set by remote core
+	 */
+	if (dispc->tidss->shared_mode && !dispc->tidss->shared_mode_owned_vps[vp_idx]) {
+		int vp_hdisplay = VP_REG_GET(dispc, vp_idx, DISPC_VP_SIZE_SCREEN, 11, 0) + 1;
+		int vp_vdisplay = VP_REG_GET(dispc, vp_idx, DISPC_VP_SIZE_SCREEN, 27, 16) + 1;
+
+		if (mode->hdisplay > vp_hdisplay ||
+		    mode->vdisplay > vp_vdisplay) {
+			dev_err(dispc->dev, "%dx%d exceeds VP screen size %dx%d in shared mode\n",
+				mode->hdisplay, mode->vdisplay, vp_hdisplay, vp_vdisplay);
+			return MODE_BAD;
+		}
+	}
 
 	if (WARN_ON(max_pclk == 0))
 		return MODE_BAD;
@@ -1171,23 +1558,25 @@
 		return MODE_BAD_VVALUE;
 
 	if (dispc->memory_bandwidth_limit) {
-		const unsigned int bpp = 4;
-		u64 bandwidth;
-
-		bandwidth = 1000 * mode->clock;
-		bandwidth = bandwidth * mode->hdisplay * mode->vdisplay * bpp;
-		bandwidth = div_u64(bandwidth, mode->htotal * mode->vtotal);
+		if (!dispc->tidss->shared_mode || dispc->tidss->shared_mode_owned_vps[vp_idx]) {
+			const unsigned int bpp = 4;
+			u64 bandwidth;
+
+			bandwidth = 1000 * mode->clock;
+			bandwidth = bandwidth * mode->hdisplay * mode->vdisplay * bpp;
+			bandwidth = div_u64(bandwidth, mode->htotal * mode->vtotal);
 
-		if (dispc->memory_bandwidth_limit < bandwidth)
-			return MODE_BAD;
+			if (dispc->memory_bandwidth_limit < bandwidth)
+				return MODE_BAD;
+		}
 	}
 
 	return MODE_OK;
 }
 
-int dispc_vp_enable_clk(struct dispc_device *dispc, u32 hw_videoport)
+int dispc_vp_enable_clk(struct dispc_device *dispc, u32 vp_idx)
 {
-	int ret = clk_prepare_enable(dispc->vp_clk[hw_videoport]);
+	int ret = clk_prepare_enable(dispc->vp_clk[vp_idx]);
 
 	if (ret)
 		dev_err(dispc->dev, "%s: enabling clk failed: %d\n", __func__,
@@ -1196,9 +1585,9 @@
 	return ret;
 }
 
-void dispc_vp_disable_clk(struct dispc_device *dispc, u32 hw_videoport)
+void dispc_vp_disable_clk(struct dispc_device *dispc, u32 vp_idx)
 {
-	clk_disable_unprepare(dispc->vp_clk[hw_videoport]);
+	clk_disable_unprepare(dispc->vp_clk[vp_idx]);
 }
 
 /*
@@ -1213,35 +1602,47 @@
 	return (unsigned int)(abs(((rr - r) * 100) / r));
 }
 
-int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport,
+int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 vp_idx,
 			  unsigned long rate)
 {
 	int r;
 	unsigned long new_rate;
 
-	r = clk_set_rate(dispc->vp_clk[hw_videoport], rate);
+	/*
+	 * For AM625 OLDI video ports, the requested pixel clock needs to take into account the
+	 * serial clock required for the serialization of DPI signals into LVDS signals. The
+	 * incoming pixel clock on the OLDI video port gets divided by 7 whenever OLDI enable bit
+	 * gets set.
+	 */
+	if (dispc_get_output_type(dispc, vp_idx) == DISPC_OUTPUT_OLDI &&
+	    ((dispc->feat->subrev == DISPC_AM625) ||
+	     (dispc->feat->subrev == DISPC_AM62P51) ||
+	     (dispc->feat->subrev == DISPC_AM62P52)))
+		rate *= 7;
+
+	r = clk_set_rate(dispc->vp_clk[vp_idx], rate);
 	if (r) {
 		dev_err(dispc->dev, "vp%d: failed to set clk rate to %lu\n",
-			hw_videoport, rate);
+			vp_idx, rate);
 		return r;
 	}
 
-	new_rate = clk_get_rate(dispc->vp_clk[hw_videoport]);
+	new_rate = clk_get_rate(dispc->vp_clk[vp_idx]);
 
 	if (dispc_pclk_diff(rate, new_rate) > 5)
 		dev_warn(dispc->dev,
 			 "vp%d: Clock rate %lu differs over 5%% from requested %lu\n",
-			 hw_videoport, new_rate, rate);
+			 vp_idx, new_rate, rate);
 
 	dev_dbg(dispc->dev, "vp%d: new rate %lu Hz (requested %lu Hz)\n",
-		hw_videoport, clk_get_rate(dispc->vp_clk[hw_videoport]), rate);
+		vp_idx, clk_get_rate(dispc->vp_clk[vp_idx]), rate);
 
 	return 0;
 }
 
 /* OVR */
 static void dispc_k2g_ovr_set_plane(struct dispc_device *dispc,
-				    u32 hw_plane, u32 hw_videoport,
+				    u32 hw_plane, u32 vp_idx,
 				    u32 x, u32 y, u32 layer)
 {
 	/* On k2g there is only one plane and no need for ovr */
@@ -1250,43 +1651,47 @@
 }
 
 static void dispc_am65x_ovr_set_plane(struct dispc_device *dispc,
-				      u32 hw_plane, u32 hw_videoport,
+				      u32 hw_plane, u32 vp_idx,
 				      u32 x, u32 y, u32 layer)
 {
-	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
+	OVR_REG_FLD_MOD(dispc, vp_idx, DISPC_OVR_ATTRIBUTES(layer),
 			hw_plane, 4, 1);
-	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
+	OVR_REG_FLD_MOD(dispc, vp_idx, DISPC_OVR_ATTRIBUTES(layer),
 			x, 17, 6);
-	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
+	OVR_REG_FLD_MOD(dispc, vp_idx, DISPC_OVR_ATTRIBUTES(layer),
 			y, 30, 19);
 }
 
 static void dispc_j721e_ovr_set_plane(struct dispc_device *dispc,
-				      u32 hw_plane, u32 hw_videoport,
+				      u32 hw_plane, u32 vp_idx,
 				      u32 x, u32 y, u32 layer)
 {
-	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
+	OVR_REG_FLD_MOD(dispc, vp_idx, DISPC_OVR_ATTRIBUTES(layer),
 			hw_plane, 4, 1);
-	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(layer),
+	OVR_REG_FLD_MOD(dispc, vp_idx, DISPC_OVR_ATTRIBUTES2(layer),
 			x, 13, 0);
-	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES2(layer),
+	OVR_REG_FLD_MOD(dispc, vp_idx, DISPC_OVR_ATTRIBUTES2(layer),
 			y, 29, 16);
 }
 
 void dispc_ovr_set_plane(struct dispc_device *dispc, u32 hw_plane,
-			 u32 hw_videoport, u32 x, u32 y, u32 layer)
+			 u32 vp_idx, u32 x, u32 y, u32 layer)
 {
 	switch (dispc->feat->subrev) {
 	case DISPC_K2G:
-		dispc_k2g_ovr_set_plane(dispc, hw_plane, hw_videoport,
+		dispc_k2g_ovr_set_plane(dispc, hw_plane, vp_idx,
 					x, y, layer);
 		break;
+	case DISPC_AM625:
+	case DISPC_AM62A7:
+	case DISPC_AM62P51:
+	case DISPC_AM62P52:
 	case DISPC_AM65X:
-		dispc_am65x_ovr_set_plane(dispc, hw_plane, hw_videoport,
+		dispc_am65x_ovr_set_plane(dispc, hw_plane, vp_idx,
 					  x, y, layer);
 		break;
 	case DISPC_J721E:
-		dispc_j721e_ovr_set_plane(dispc, hw_plane, hw_videoport,
+		dispc_j721e_ovr_set_plane(dispc, hw_plane, vp_idx,
 					  x, y, layer);
 		break;
 	default:
@@ -1295,13 +1700,13 @@
 	}
 }
 
-void dispc_ovr_enable_layer(struct dispc_device *dispc,
-			    u32 hw_videoport, u32 layer, bool enable)
+void dispc_ovr_enable_layer(struct dispc_device *dispc, u32 vp_idx,
+			    u32 layer, bool enable)
 {
 	if (dispc->feat->subrev == DISPC_K2G)
 		return;
 
-	OVR_REG_FLD_MOD(dispc, hw_videoport, DISPC_OVR_ATTRIBUTES(layer),
+	OVR_REG_FLD_MOD(dispc, vp_idx, DISPC_OVR_ATTRIBUTES(layer),
 			!!enable, 0, 0);
 }
 
@@ -1901,6 +2306,12 @@
 	return dispc->fourccs;
 }
 
+void dispc_set_oldi_mode(struct dispc_device *dispc,
+			 enum dispc_oldi_modes oldi_mode)
+{
+	dispc->oldi_mode = oldi_mode;
+}
+
 static s32 pixinc(int pixels, u8 ps)
 {
 	if (pixels == 1)
@@ -1916,7 +2327,7 @@
 
 int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane,
 		      const struct drm_plane_state *state,
-		      u32 hw_videoport)
+		      u32 vp_idx)
 {
 	bool lite = dispc->feat->vid_lite[hw_plane];
 	u32 fourcc = state->fb->format->format;
@@ -1987,7 +2398,7 @@
 
 int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane,
 		      const struct drm_plane_state *state,
-		      u32 hw_videoport)
+		      u32 vp_idx)
 {
 	bool lite = dispc->feat->vid_lite[hw_plane];
 	u32 fourcc = state->fb->format->format;
@@ -2203,6 +2614,10 @@
 	case DISPC_K2G:
 		dispc_k2g_plane_init(dispc);
 		break;
+	case DISPC_AM625:
+	case DISPC_AM62A7:
+	case DISPC_AM62P51:
+	case DISPC_AM62P52:
 	case DISPC_AM65X:
 	case DISPC_J721E:
 		dispc_k3_plane_init(dispc);
@@ -2238,13 +2653,13 @@
 }
 
 static void dispc_k2g_vp_write_gamma_table(struct dispc_device *dispc,
-					   u32 hw_videoport)
+					   u32 vp_idx)
 {
-	u32 *table = dispc->vp_data[hw_videoport].gamma_table;
+	u32 *table = dispc->vp_data[vp_idx].gamma_table;
 	u32 hwlen = dispc->feat->vp_feat.color.gamma_size;
 	unsigned int i;
 
-	dev_dbg(dispc->dev, "%s: hw_videoport %d\n", __func__, hw_videoport);
+	dev_dbg(dispc->dev, "%s: vp_idx %d\n", __func__, vp_idx);
 
 	if (WARN_ON(dispc->feat->vp_feat.color.gamma_type != TIDSS_GAMMA_8BIT))
 		return;
@@ -2254,19 +2669,18 @@
 
 		v |= i << 24;
 
-		dispc_vp_write(dispc, hw_videoport, DISPC_VP_K2G_GAMMA_TABLE,
-			       v);
+		dispc_vp_write(dispc, vp_idx, DISPC_VP_K2G_GAMMA_TABLE, v);
 	}
 }
 
 static void dispc_am65x_vp_write_gamma_table(struct dispc_device *dispc,
-					     u32 hw_videoport)
+					     u32 vp_idx)
 {
-	u32 *table = dispc->vp_data[hw_videoport].gamma_table;
+	u32 *table = dispc->vp_data[vp_idx].gamma_table;
 	u32 hwlen = dispc->feat->vp_feat.color.gamma_size;
 	unsigned int i;
 
-	dev_dbg(dispc->dev, "%s: hw_videoport %d\n", __func__, hw_videoport);
+	dev_dbg(dispc->dev, "%s: vp_idx %d\n", __func__, vp_idx);
 
 	if (WARN_ON(dispc->feat->vp_feat.color.gamma_type != TIDSS_GAMMA_8BIT))
 		return;
@@ -2276,18 +2690,18 @@
 
 		v |= i << 24;
 
-		dispc_vp_write(dispc, hw_videoport, DISPC_VP_GAMMA_TABLE, v);
+		dispc_vp_write(dispc, vp_idx, DISPC_VP_GAMMA_TABLE, v);
 	}
 }
 
 static void dispc_j721e_vp_write_gamma_table(struct dispc_device *dispc,
-					     u32 hw_videoport)
+					     u32 vp_idx)
 {
-	u32 *table = dispc->vp_data[hw_videoport].gamma_table;
+	u32 *table = dispc->vp_data[vp_idx].gamma_table;
 	u32 hwlen = dispc->feat->vp_feat.color.gamma_size;
 	unsigned int i;
 
-	dev_dbg(dispc->dev, "%s: hw_videoport %d\n", __func__, hw_videoport);
+	dev_dbg(dispc->dev, "%s: vp_idx %d\n", __func__, vp_idx);
 
 	if (WARN_ON(dispc->feat->vp_feat.color.gamma_type != TIDSS_GAMMA_10BIT))
 		return;
@@ -2298,22 +2712,25 @@
 		if (i == 0)
 			v |= 1 << 31;
 
-		dispc_vp_write(dispc, hw_videoport, DISPC_VP_GAMMA_TABLE, v);
+		dispc_vp_write(dispc, vp_idx, DISPC_VP_GAMMA_TABLE, v);
 	}
 }
 
-static void dispc_vp_write_gamma_table(struct dispc_device *dispc,
-				       u32 hw_videoport)
+static void dispc_vp_write_gamma_table(struct dispc_device *dispc, u32 vp_idx)
 {
 	switch (dispc->feat->subrev) {
 	case DISPC_K2G:
-		dispc_k2g_vp_write_gamma_table(dispc, hw_videoport);
+		dispc_k2g_vp_write_gamma_table(dispc, vp_idx);
 		break;
+	case DISPC_AM625:
+	case DISPC_AM62A7:
+	case DISPC_AM62P51:
+	case DISPC_AM62P52:
 	case DISPC_AM65X:
-		dispc_am65x_vp_write_gamma_table(dispc, hw_videoport);
+		dispc_am65x_vp_write_gamma_table(dispc, vp_idx);
 		break;
 	case DISPC_J721E:
-		dispc_j721e_vp_write_gamma_table(dispc, hw_videoport);
+		dispc_j721e_vp_write_gamma_table(dispc, vp_idx);
 		break;
 	default:
 		WARN_ON(1);
@@ -2326,18 +2743,17 @@
 	{ .red = U16_MAX, .green = U16_MAX, .blue = U16_MAX, },
 };
 
-static void dispc_vp_set_gamma(struct dispc_device *dispc,
-			       u32 hw_videoport,
+static void dispc_vp_set_gamma(struct dispc_device *dispc, u32 vp_idx,
 			       const struct drm_color_lut *lut,
 			       unsigned int length)
 {
-	u32 *table = dispc->vp_data[hw_videoport].gamma_table;
+	u32 *table = dispc->vp_data[vp_idx].gamma_table;
 	u32 hwlen = dispc->feat->vp_feat.color.gamma_size;
 	u32 hwbits;
 	unsigned int i;
 
-	dev_dbg(dispc->dev, "%s: hw_videoport %d, lut len %u, hw len %u\n",
-		__func__, hw_videoport, length, hwlen);
+	dev_dbg(dispc->dev, "%s: vp_idx %d, lut len %u, hw len %u\n",
+		__func__, vp_idx, length, hwlen);
 
 	if (dispc->feat->vp_feat.color.gamma_type == TIDSS_GAMMA_10BIT)
 		hwbits = 10;
@@ -2373,7 +2789,7 @@
 		}
 	}
 
-	dispc_vp_write_gamma_table(dispc, hw_videoport);
+	dispc_vp_write_gamma_table(dispc, vp_idx);
 }
 
 static s16 dispc_S31_32_to_s2_8(s64 coef)
@@ -2420,7 +2836,7 @@
 
 #undef CVAL
 
-static void dispc_k2g_vp_write_csc(struct dispc_device *dispc, u32 hw_videoport,
+static void dispc_k2g_vp_write_csc(struct dispc_device *dispc, u32 vp_idx,
 				   const struct dispc_csc_coef *csc)
 {
 	static const u16 dispc_vp_cpr_coef_reg[] = {
@@ -2433,11 +2849,11 @@
 	dispc_k2g_vp_csc_cpr_regval(csc, regval);
 
 	for (i = 0; i < ARRAY_SIZE(dispc_vp_cpr_coef_reg); i++)
-		dispc_vp_write(dispc, hw_videoport, dispc_vp_cpr_coef_reg[i],
+		dispc_vp_write(dispc, vp_idx, dispc_vp_cpr_coef_reg[i],
 			       regval[i]);
 }
 
-static void dispc_k2g_vp_set_ctm(struct dispc_device *dispc, u32 hw_videoport,
+static void dispc_k2g_vp_set_ctm(struct dispc_device *dispc, u32 vp_idx,
 				 struct drm_color_ctm *ctm)
 {
 	u32 cprenable = 0;
@@ -2446,11 +2862,11 @@
 		struct dispc_csc_coef cpr;
 
 		dispc_k2g_cpr_from_ctm(ctm, &cpr);
-		dispc_k2g_vp_write_csc(dispc, hw_videoport, &cpr);
+		dispc_k2g_vp_write_csc(dispc, vp_idx, &cpr);
 		cprenable = 1;
 	}
 
-	VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONFIG,
+	VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONFIG,
 		       cprenable, 15, 15);
 }
 
@@ -2485,7 +2901,7 @@
 	cpr->m[CSC_BB] = dispc_S31_32_to_s3_8(ctm->matrix[8]);
 }
 
-static void dispc_k3_vp_write_csc(struct dispc_device *dispc, u32 hw_videoport,
+static void dispc_k3_vp_write_csc(struct dispc_device *dispc, u32 vp_idx,
 				  const struct dispc_csc_coef *csc)
 {
 	static const u16 dispc_vp_csc_coef_reg[DISPC_CSC_REGVAL_LEN] = {
@@ -2499,11 +2915,11 @@
 	csc->to_regval(csc, regval);
 
 	for (i = 0; i < ARRAY_SIZE(regval); i++)
-		dispc_vp_write(dispc, hw_videoport, dispc_vp_csc_coef_reg[i],
+		dispc_vp_write(dispc, vp_idx, dispc_vp_csc_coef_reg[i],
 			       regval[i]);
 }
 
-static void dispc_k3_vp_set_ctm(struct dispc_device *dispc, u32 hw_videoport,
+static void dispc_k3_vp_set_ctm(struct dispc_device *dispc, u32 vp_idx,
 				struct drm_color_ctm *ctm)
 {
 	u32 colorconvenable = 0;
@@ -2512,16 +2928,15 @@
 		struct dispc_csc_coef csc;
 
 		dispc_csc_from_ctm(ctm, &csc);
-		dispc_k3_vp_write_csc(dispc, hw_videoport, &csc);
+		dispc_k3_vp_write_csc(dispc, vp_idx, &csc);
 		colorconvenable = 1;
 	}
 
-	VP_REG_FLD_MOD(dispc, hw_videoport, DISPC_VP_CONFIG,
+	VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONFIG,
 		       colorconvenable, 24, 24);
 }
 
-static void dispc_vp_set_color_mgmt(struct dispc_device *dispc,
-				    u32 hw_videoport,
+static void dispc_vp_set_color_mgmt(struct dispc_device *dispc, u32 vp_idx,
 				    const struct drm_crtc_state *state,
 				    bool newmodeset)
 {
@@ -2537,28 +2952,215 @@
 		length = state->gamma_lut->length / sizeof(*lut);
 	}
 
-	dispc_vp_set_gamma(dispc, hw_videoport, lut, length);
+	dispc_vp_set_gamma(dispc, vp_idx, lut, length);
 
 	if (state->ctm)
 		ctm = (struct drm_color_ctm *)state->ctm->data;
 
 	if (dispc->feat->subrev == DISPC_K2G)
-		dispc_k2g_vp_set_ctm(dispc, hw_videoport, ctm);
+		dispc_k2g_vp_set_ctm(dispc, vp_idx, ctm);
+	else
+		dispc_k3_vp_set_ctm(dispc, vp_idx, ctm);
+}
+
+static const char *get_vp_from_vp_idx(u32 vp_idx)
+{
+	const char *vp_name = NULL;
+
+	switch (vp_idx) {
+	case 0:
+		vp_name = "vp1";
+		break;
+	case 1:
+		vp_name = "vp2";
+		break;
+	case 2:
+		vp_name = "vp3";
+		break;
+	case 3:
+		vp_name = "vp4";
+		break;
+	default:
+		vp_name = NULL;
+		break;
+	}
+
+	return vp_name;
+}
+
+static const char *get_ovr_from_vp(const char *vp_name)
+{
+	const char *ovr_name = NULL;
+
+	if (!strcmp("vp1", vp_name))
+		ovr_name = "ovr1";
+	else if (!strcmp("vp2", vp_name))
+		ovr_name = "ovr2";
+	else if (!strcmp("vp3", vp_name))
+		ovr_name = "ovr3";
+	else if (!strcmp("vp4", vp_name))
+		ovr_name = "ovr4";
 	else
-		dispc_k3_vp_set_ctm(dispc, hw_videoport, ctm);
+		return NULL;
+
+	return ovr_name;
+}
+
+static void dispc_shared_mode_update_outputs(struct dispc_features *shared_mode_feat,
+					     struct dispc_device *dispc)
+{
+	u32 i, j;
+	int num_outputs = shared_mode_feat->num_outputs;
+	u32 output_source_vp[TIDSS_MAX_OUTPUTS];
+	enum dispc_output_type output_type[TIDSS_MAX_OUTPUTS];
+
+	memcpy((void *)output_source_vp, (void *)shared_mode_feat->output_source_vp,
+	       sizeof(output_source_vp));
+	memset(shared_mode_feat->output_source_vp, 0, sizeof(output_source_vp));
+	memcpy((void *)output_type, (void *)shared_mode_feat->output_type,
+	       sizeof(output_type));
+	memset(shared_mode_feat->output_type, 0, sizeof(output_type));
+
+	for (i = 0, j = 0; i < num_outputs; i++) {
+		/*
+		 * Find corresponding output type and source video port index from video ports that
+		 * were made available to Linux either in shared context
+		 * or ownership context.
+		 */
+		if (get_vp_from_vp_idx(output_source_vp[i]) &&
+		    match_string(shared_mode_feat->vp_name, shared_mode_feat->num_vps,
+				 get_vp_from_vp_idx(output_source_vp[i])) >=  0) {
+			shared_mode_feat->output_source_vp[j] = output_source_vp[i];
+			shared_mode_feat->output_type[j++] = output_type[i];
+			if (dispc->tidss->shared_mode_owned_vps[output_source_vp[i]] &&
+			    output_type[i] == DISPC_OUTPUT_OLDI)
+				dispc->tidss->shared_mode_own_oldi = true;
+			dev_dbg(dispc->dev, "output_source_vp[%d] : %u, output_type[%d] : %u\n",
+				j - 1, shared_mode_feat->output_source_vp[j - 1], j - 1,
+				shared_mode_feat->output_type[j - 1]);
+		}
+	}
+
+	shared_mode_feat->num_outputs = j;
+	dev_dbg(dispc->dev, "num_outputs : %u, tidss->shared_mode_own_oldi : %s\n",
+		shared_mode_feat->num_outputs,
+		dispc->tidss->shared_mode_own_oldi ? "true" : "false");
+}
+
+static int dispc_update_shared_mode_features(struct dispc_features *shared_mode_feat,
+					     struct dispc_device *dispc)
+{
+	int r = 0, i = 0;
+
+	dev_dbg(dispc->dev, "Start updating dispc feature list for shared mode:\n");
+
+	/*
+	 * Start with a shallow copy from existing features and prune the list
+	 * as per what is actually made available to Linux
+	 */
+	memcpy((void *)shared_mode_feat, (void *)dispc->feat, sizeof(*shared_mode_feat));
+	shared_mode_feat->num_vps = device_property_string_array_count(dispc->dev,
+								       "ti,dss-shared-mode-vp");
+	shared_mode_feat->num_planes = device_property_string_array_count(dispc->dev,
+									  "ti,dss-shared-mode-planes");
+
+	r = device_property_read_string(dispc->dev, "ti,dss-shared-mode-common",
+					(const char **)&shared_mode_feat->common);
+	if (r) {
+		dev_err(dispc->dev, "failed to read shared video port name: %d\n", r);
+		return r;
+	}
+
+	memset(shared_mode_feat->vid_name, 0, sizeof(shared_mode_feat->vid_name));
+	r = device_property_read_string_array(dispc->dev, "ti,dss-shared-mode-planes",
+					      shared_mode_feat->vid_name, TIDSS_MAX_PLANES);
+	if (r < 0) {
+		dev_err(dispc->dev, "failed to read client vid layer name: %d\n", r);
+		return r;
+	}
+
+	r = device_property_read_u32_array(dispc->dev, "ti,dss-shared-mode-vp-owned",
+					   dispc->tidss->shared_mode_owned_vps,
+					   shared_mode_feat->num_vps);
+	if (r < 0) {
+		dev_err(dispc->dev, "failed to read owned vp list: %d\n", r);
+		return r;
+	}
+
+	memset(shared_mode_feat->vp_name, 0, sizeof(shared_mode_feat->vp_name));
+	r = device_property_read_string_array(dispc->dev, "ti,dss-shared-mode-vp",
+					      shared_mode_feat->vp_name, TIDSS_MAX_VPS);
+	if (r < 0) {
+		dev_err(dispc->dev, "failed to read shared video port name: %d\n", r);
+		return r;
+	}
+
+	memset(shared_mode_feat->vid_order, 0, sizeof(shared_mode_feat->vid_order));
+	r = device_property_read_u32_array(dispc->dev, "ti,dss-shared-mode-plane-zorder",
+					   shared_mode_feat->vid_order,
+					   shared_mode_feat->num_planes);
+	if (r < 0) {
+		dev_err(dispc->dev, "failed to read vid_order array name: %d\n", r);
+		return r;
+	}
+	memcpy((void *)shared_mode_feat->vpclk_name, (void *)shared_mode_feat->vp_name,
+	       sizeof(shared_mode_feat->vpclk_name));
+	memset(shared_mode_feat->ovr_name, 0, sizeof(shared_mode_feat->ovr_name));
+
+	for (i = 0; i < shared_mode_feat->num_vps; i++) {
+		shared_mode_feat->ovr_name[i] = get_ovr_from_vp(shared_mode_feat->vp_name[i]);
+		dev_dbg(dispc->dev, "vp[%d] = %s, ovr[%d] = %s vpclk[%d] = %s vp_owned[%d] = %d\n",
+			i,  shared_mode_feat->vp_name[i], i, shared_mode_feat->ovr_name[i], i,
+			shared_mode_feat->vpclk_name[i], i, dispc->tidss->shared_mode_owned_vps[i]);
+	}
+
+	for (i = 0; i < shared_mode_feat->num_planes; i++) {
+		if (!strncmp("vidl", shared_mode_feat->vid_name[i], 4))
+			shared_mode_feat->vid_lite[i] = true;
+		dev_dbg(dispc->dev, "vid[%d] = %s, vid_order[%d] = %u vid_lite[%d] = %u\n", i,
+			shared_mode_feat->vid_name[i], i, shared_mode_feat->vid_order[i], i,
+			shared_mode_feat->vid_lite[i]);
+	}
+
+	if (!strcmp(shared_mode_feat->common, "common1"))
+		shared_mode_feat->common_regs = tidss_am62_common1_regs;
+
+	dev_dbg(dispc->dev, "common : %s\n", shared_mode_feat->common);
+	dispc_shared_mode_update_outputs(shared_mode_feat, dispc);
+	dev_dbg(dispc->dev, "Feature list updated for shared mode\n");
+
+	return 0;
 }
 
-void dispc_vp_setup(struct dispc_device *dispc, u32 hw_videoport,
+void dispc_vp_setup(struct dispc_device *dispc, u32 vp_idx,
 		    const struct drm_crtc_state *state, bool newmodeset)
 {
-	dispc_vp_set_default_color(dispc, hw_videoport, 0);
-	dispc_vp_set_color_mgmt(dispc, hw_videoport, state, newmodeset);
+	dispc_vp_set_default_color(dispc, vp_idx, 0);
+	dispc_vp_set_color_mgmt(dispc, vp_idx, state, newmodeset);
+}
+
+static bool dispc_is_idle(struct dispc_device *dispc)
+{
+	return REG_GET(dispc, DSS_SYSSTATUS, 9, 9);
+}
+
+static bool dispc_owns_global_common_in_shared_mode(struct dispc_device *dispc)
+{
+	if ((!strcmp(dispc->feat->common, "common") ||
+	     !strcmp(dispc->feat->common, "common_m")) &&
+	     dispc->tidss->shared_mode)
+		return true;
+	else
+		return false;
 }
 
 int dispc_runtime_suspend(struct dispc_device *dispc)
 {
 	dev_dbg(dispc->dev, "suspend\n");
 
+	if (!dispc_is_idle(dispc))
+		dev_warn(dispc->dev, "Bad HW state: DSS not idle when suspending");
+
 	dispc->is_enabled = false;
 
 	clk_disable_unprepare(dispc->fclk);
@@ -2572,6 +3174,9 @@
 
 	clk_prepare_enable(dispc->fclk);
 
+	if (!dispc_is_idle(dispc))
+		dev_warn(dispc->dev, "Bad HW state: DSS not idle when resuming");
+
 	if (REG_GET(dispc, DSS_SYSSTATUS, 0, 0) == 0)
 		dev_warn(dispc->dev, "DSS FUNC RESET not done!\n");
 
@@ -2583,7 +3188,7 @@
 		REG_GET(dispc, DSS_SYSSTATUS, 2, 2),
 		REG_GET(dispc, DSS_SYSSTATUS, 3, 3));
 
-	if (dispc->feat->subrev == DISPC_AM65X)
+	if (dispc->feat->has_oldi)
 		dev_dbg(dispc->dev, "OLDI RESETDONE %d,%d,%d\n",
 			REG_GET(dispc, DSS_SYSSTATUS, 5, 5),
 			REG_GET(dispc, DSS_SYSSTATUS, 6, 6),
@@ -2624,7 +3229,7 @@
 	return 0;
 }
 
-static int dispc_init_am65x_oldi_io_ctrl(struct device *dev,
+static int dispc_init_am6xx_oldi_io_ctrl(struct device *dev,
 					 struct dispc_device *dispc)
 {
 	dispc->oldi_io_ctrl =
@@ -2653,18 +3258,162 @@
 	}
 }
 
-static void dispc_softreset(struct dispc_device *dispc)
+/*
+ * K2G display controller does not support soft reset, so we do a basic manual
+ * reset here: make sure the IRQs are masked and VPs are disabled.
+ */
+static void dispc_softreset_k2g(struct dispc_device *dispc)
+{
+	dispc_set_irqenable(dispc, 0);
+	dispc_read_and_clear_irqstatus(dispc);
+
+	for (unsigned int vp_idx = 0; vp_idx < dispc->feat->num_vps; ++vp_idx)
+		VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONTROL, 0, 0, 0);
+}
+
+static int dispc_softreset(struct dispc_device *dispc)
 {
 	u32 val;
-	int ret = 0;
+	int ret;
+
+	if (dispc->feat->subrev == DISPC_K2G) {
+		dispc_softreset_k2g(dispc);
+		return 0;
+	}
+
+	/*
+	 * When we reset the DSS, we also reset the OLDI enable. This disables
+	 * a /7 divider and could, in some cases, lead to the DSS receiving a
+	 * much too high pixel clock. According to the HW folks, receiving such
+	 * a high clock can potentially cause damage to the DSS controller hardware.
+	 *
+	 * So set the VP clock rate for OLDI to a lower frequency before
+	 * resetting the DSS.
+	 */
+	for (u32 vp_idx = 0; vp_idx < dispc->feat->num_vps; vp_idx++) {
+		if (dispc_get_output_type(dispc, vp_idx) == DISPC_OUTPUT_OLDI &&
+		    ((dispc->feat->subrev == DISPC_AM625) ||
+		     (dispc->feat->subrev == DISPC_AM62P51) ||
+		     (dispc->feat->subrev == DISPC_AM62P52))) {
+			ret = clk_set_rate(dispc->vp_clk[vp_idx],
+					   TIDSS_AM625_IDLE_OLDI_CLOCK);
+			if (ret) {
+				dev_err(dispc->dev,
+					"vp%d: failed to set oldi clk rate to %u\n",
+					vp_idx, TIDSS_AM625_IDLE_OLDI_CLOCK);
+				return ret;
+			}
+		}
+	}
 
 	/* Soft reset */
 	REG_FLD_MOD(dispc, DSS_SYSCONFIG, 1, 1, 1);
 	/* Wait for reset to complete */
 	ret = readl_poll_timeout(dispc->base_common + DSS_SYSSTATUS,
 				 val, val & 1, 100, 5000);
-	if (ret)
-		dev_warn(dispc->dev, "failed to reset dispc\n");
+	if (ret) {
+		dev_err(dispc->dev, "failed to reset dispc\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dispc_init_hw(struct dispc_device *dispc)
+{
+	struct device *dev = dispc->dev;
+	int ret;
+
+	ret = pm_runtime_set_active(dev);
+	if (ret) {
+		dev_err(dev, "Failed to set DSS PM to active\n");
+		return ret;
+	}
+
+	ret = clk_prepare_enable(dispc->fclk);
+	if (ret) {
+		dev_err(dev, "Failed to enable DSS fclk\n");
+		goto err_runtime_suspend;
+	}
+
+	dispc->tidss->boot_enabled_vp_mask = 0;
+
+	if (dispc_is_idle(dispc)) {
+		ret = dispc_softreset(dispc);
+		if (ret)
+			goto err_clk_disable;
+	} else {
+		for (u32 vp_idx = 0; vp_idx < dispc->feat->num_vps; vp_idx++) {
+			bool enabled = VP_REG_GET(dispc, vp_idx,
+						  DISPC_VP_CONTROL, 0, 0);
+
+			if (!enabled)
+				continue;
+
+			dispc->tidss->boot_enabled_vp_mask |= BIT(vp_idx);
+
+			/* Keep the VP clk enabled */
+			ret = clk_prepare_enable(dispc->vp_clk[vp_idx]);
+			if (ret) {
+				while (vp_idx--) {
+					if (!(dispc->tidss->boot_enabled_vp_mask &
+					      BIT(vp_idx)))
+						continue;
+
+					clk_disable_unprepare(dispc->vp_clk[vp_idx]);
+				}
+
+				goto err_clk_disable;
+			}
+		}
+
+		if (!dispc->tidss->boot_enabled_vp_mask) {
+			dev_warn(dev,
+				 "Bad HW state: DSS not idle but no VPs are enabled. Resetting.\n");
+			ret = dispc_softreset(dispc);
+			if (ret)
+				goto err_clk_disable;
+		} else {
+			/*
+			 * Do basic HW init here, which won't interrupt the
+			 * splash-screen.
+			 */
+
+			/* Ensure we won't get interrupts */
+			dispc_set_irqenable(dispc, 0);
+			dispc_read_and_clear_irqstatus(dispc);
+		}
+	}
+
+	if (dispc->tidss->boot_enabled_vp_mask) {
+		dev_dbg(dev,
+			"Bootloader splash-screen detected, leaving DSS active.\n");
+		pm_runtime_get_noresume(dev);
+	} else {
+		/*
+		 * No splash-screen. Disable the clock and set DSS back to suspended.
+		 */
+		clk_disable_unprepare(dispc->fclk);
+		ret = pm_runtime_set_suspended(dev);
+		if (ret) {
+			dev_err(dev, "Failed to set DSS PM to suspended\n");
+			return ret;
+		}
+	}
+
+	return 0;
+
+err_clk_disable:
+	clk_disable_unprepare(dispc->fclk);
+
+err_runtime_suspend:
+	ret = pm_runtime_set_suspended(dev);
+	if (ret) {
+		dev_err(dev, "Failed to set DSS PM to suspended\n");
+		return ret;
+	}
+
+	return ret;
 }
 
 int dispc_init(struct tidss_device *tidss)
@@ -2673,6 +3422,7 @@
 	struct platform_device *pdev = to_platform_device(dev);
 	struct dispc_device *dispc;
 	const struct dispc_features *feat;
+	struct dispc_features *shared_mode_feat;
 	unsigned int i, num_fourccs;
 	int r = 0;
 
@@ -2712,6 +3462,21 @@
 
 	dispc->num_fourccs = num_fourccs;
 
+	if (tidss->shared_mode) {
+		dev_dbg(dev, "%s : DSS is being shared with remote core\n", __func__);
+		shared_mode_feat = devm_kzalloc(dev, sizeof(*shared_mode_feat), GFP_KERNEL);
+		if (!shared_mode_feat)
+			return -ENOMEM;
+
+		r = dispc_update_shared_mode_features(shared_mode_feat, dispc);
+		if (r)
+			return r;
+
+		tidss->feat = (const struct dispc_features *)shared_mode_feat;
+		feat = tidss->feat;
+		dispc->feat = feat;
+	}
+
 	dispc_common_regmap = dispc->feat->common_regs;
 
 	r = dispc_iomap_resource(pdev, dispc->feat->common,
@@ -2726,10 +3491,6 @@
 			return r;
 	}
 
-	/* K2G display controller does not support soft reset */
-	if (feat->subrev != DISPC_K2G)
-		dispc_softreset(dispc);
-
 	for (i = 0; i < dispc->feat->num_vps; i++) {
 		u32 gamma_size = dispc->feat->vp_feat.color.gamma_size;
 		u32 *gamma_table;
@@ -2761,24 +3522,74 @@
 		dispc->vp_data[i].gamma_table = gamma_table;
 	}
 
-	if (feat->subrev == DISPC_AM65X) {
-		r = dispc_init_am65x_oldi_io_ctrl(dev, dispc);
-		if (r)
-			return r;
-	}
-
-	dispc->fclk = devm_clk_get(dev, "fck");
-	if (IS_ERR(dispc->fclk)) {
-		dev_err(dev, "%s: Failed to get fclk: %ld\n",
-			__func__, PTR_ERR(dispc->fclk));
-		return PTR_ERR(dispc->fclk);
+	if (feat->has_oldi) {
+		/*
+		 * For shared mode, Initialize the OLDI IO control only if we own
+		 * the OLDI Tx ports
+		 */
+		if (!tidss->shared_mode || tidss->shared_mode_own_oldi) {
+			r = dispc_init_am6xx_oldi_io_ctrl(dev, dispc);
+			if (r)
+				return r;
+		}
 	}
-	dev_dbg(dev, "DSS fclk %lu Hz\n", clk_get_rate(dispc->fclk));
 
 	of_property_read_u32(dispc->dev->of_node, "max-memory-bandwidth",
 			     &dispc->memory_bandwidth_limit);
+	/*
+	 * For shared mode, Initialize the hardware and clocking only if processing core running
+	 * Linux has ownership of DSS global register space
+	 */
+	if (!tidss->shared_mode || dispc_owns_global_common_in_shared_mode(dispc)) {
+		dispc->fclk = devm_clk_get(dev, "fck");
+		if (IS_ERR(dispc->fclk)) {
+			dev_err(dev, "%s: Failed to get fclk: %ld\n",
+				__func__, PTR_ERR(dispc->fclk));
+			return PTR_ERR(dispc->fclk);
+		}
+		dev_dbg(dev, "DSS fclk %lu Hz\n", clk_get_rate(dispc->fclk));
+
+		r = dispc_init_hw(dispc);
+		if (r)
+			return r;
+	}
 
 	tidss->dispc = dispc;
 
 	return 0;
 }
+
+void dispc_splash_fini(struct dispc_device *dispc)
+{
+	if (WARN_ON(!dispc->tidss->boot_enabled_vp_mask))
+		return;
+
+	/*
+	 * Do a reset now, to clean up the bootloader setup, as we're about to
+	 * do a modeset.
+	 */
+	dispc_softreset(dispc);
+
+	/*
+	 * Call resume manually. This will clk_prepare_enable() the fclk, and do
+	 * the common basic HW configuration.
+	 */
+	dispc_runtime_resume(dispc);
+
+	/*
+	 * Call clk_disable_unprepare() to counter the clk_prepare_enable() we
+	 * did in the dispc_check_hw_state(). The fclk will still be enabled,
+	 * as the dispc_runtime_resume() above does a clk_prepare_enable().
+	 */
+	clk_disable_unprepare(dispc->fclk);
+
+	for (u32 vp_idx = 0; vp_idx < dispc->feat->num_vps; vp_idx++) {
+		if (dispc->tidss->boot_enabled_vp_mask & BIT(vp_idx))
+			clk_disable_unprepare(dispc->vp_clk[vp_idx]);
+	}
+
+	/* counter the pm_runtime_get_noresume() */
+	pm_runtime_put_noidle(dispc->dev);
+
+	dispc->tidss->boot_enabled_vp_mask = 0;
+}
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_dispc.h b/drivers/gpu/drm/tidss/tidss_dispc.h
--- a/drivers/gpu/drm/tidss/tidss_dispc.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_dispc.h	2024-01-28 14:01:31.240353775 -0500
@@ -50,86 +50,109 @@
 	bool i2000; /* DSS Does Not Support YUV Pixel Data Formats */
 };
 
-enum dispc_vp_bus_type {
-	DISPC_VP_DPI,		/* DPI output */
-	DISPC_VP_OLDI,		/* OLDI (LVDS) output */
-	DISPC_VP_INTERNAL,	/* SoC internal routing */
-	DISPC_VP_MAX_BUS_TYPE,
+enum dispc_output_type {
+	DISPC_OUTPUT_DPI,		/* DPI output */
+	DISPC_OUTPUT_OLDI,		/* OLDI (LVDS) output */
+	DISPC_OUTPUT_INTERNAL,		/* SoC internal routing */
+	DISPC_OUTPUT_TYPES_MAX,
 };
 
 enum dispc_dss_subrevision {
 	DISPC_K2G,
+	DISPC_AM625,
+	DISPC_AM62A7,
+	DISPC_AM62P51,
+	DISPC_AM62P52,
 	DISPC_AM65X,
 	DISPC_J721E,
 };
 
+enum dispc_oldi_modes {
+	OLDI_MODE_SINGLE_LINK,		/* Single output over OLDI 0. */
+	OLDI_MODE_CLONE_SINGLE_LINK,	/* Cloned output over OLDI 0 and 1. */
+	OLDI_MODE_DUAL_LINK,		/* Combined output over OLDI 0 and 1. */
+	OLDI_MODE_OFF,			/* OLDI TXes not connected in OF. */
+	OLDI_MODE_UNSUPPORTED,		/* Unsupported OLDI configuration in OF. */
+	OLDI_MODE_UNAVAILABLE,		/* OLDI TXes not available in SoC. */
+};
+
 struct dispc_features {
 	int min_pclk_khz;
-	int max_pclk_khz[DISPC_VP_MAX_BUS_TYPE];
+	int max_pclk_khz[DISPC_OUTPUT_TYPES_MAX];
 
 	struct dispc_features_scaling scaling;
 
 	enum dispc_dss_subrevision subrev;
 
+	bool has_oldi;
+
 	const char *common;
 	const u16 *common_regs;
 	u32 num_vps;
-	const char *vp_name[TIDSS_MAX_PORTS]; /* Should match dt reg names */
-	const char *ovr_name[TIDSS_MAX_PORTS]; /* Should match dt reg names */
-	const char *vpclk_name[TIDSS_MAX_PORTS]; /* Should match dt clk names */
-	const enum dispc_vp_bus_type vp_bus_type[TIDSS_MAX_PORTS];
+	const char *vp_name[TIDSS_MAX_VPS]; /* Should match dt reg names */
+	const char *ovr_name[TIDSS_MAX_VPS]; /* Should match dt reg names */
+	const char *vpclk_name[TIDSS_MAX_VPS]; /* Should match dt clk names */
 	struct tidss_vp_feat vp_feat;
 	u32 num_planes;
 	const char *vid_name[TIDSS_MAX_PLANES]; /* Should match dt reg names */
 	bool vid_lite[TIDSS_MAX_PLANES];
 	u32 vid_order[TIDSS_MAX_PLANES];
+	u32 num_outputs;
+	enum dispc_output_type output_type[TIDSS_MAX_OUTPUTS];
+	u32 output_source_vp[TIDSS_MAX_OUTPUTS];
 };
 
 extern const struct dispc_features dispc_k2g_feats;
+extern const struct dispc_features dispc_am625_feats;
+extern const struct dispc_features dispc_am62a7_feats;
+extern const struct dispc_features dispc_am62p51_feats;
+extern const struct dispc_features dispc_am62p52_feats;
 extern const struct dispc_features dispc_am65x_feats;
 extern const struct dispc_features dispc_j721e_feats;
 
+enum dispc_output_type dispc_get_output_type(struct dispc_device *dispc,
+					     u32 vp_idx);
 void dispc_set_irqenable(struct dispc_device *dispc, dispc_irq_t mask);
 dispc_irq_t dispc_read_and_clear_irqstatus(struct dispc_device *dispc);
 
-void dispc_ovr_set_plane(struct dispc_device *dispc, u32 hw_plane,
-			 u32 hw_videoport, u32 x, u32 y, u32 layer);
-void dispc_ovr_enable_layer(struct dispc_device *dispc,
-			    u32 hw_videoport, u32 layer, bool enable);
+void dispc_ovr_set_plane(struct dispc_device *dispc, u32 hw_plane, u32 vp_idx,
+			 u32 x, u32 y, u32 layer);
+void dispc_ovr_enable_layer(struct dispc_device *dispc, u32 vp_idx,
+			    u32 layer, bool enable);
 
-void dispc_vp_prepare(struct dispc_device *dispc, u32 hw_videoport,
+void dispc_vp_prepare(struct dispc_device *dispc, u32 vp_idx,
 		      const struct drm_crtc_state *state);
-void dispc_vp_enable(struct dispc_device *dispc, u32 hw_videoport,
+void dispc_vp_enable(struct dispc_device *dispc, u32 vp_idx,
 		     const struct drm_crtc_state *state);
-void dispc_vp_disable(struct dispc_device *dispc, u32 hw_videoport);
-void dispc_vp_unprepare(struct dispc_device *dispc, u32 hw_videoport);
-bool dispc_vp_go_busy(struct dispc_device *dispc, u32 hw_videoport);
-void dispc_vp_go(struct dispc_device *dispc, u32 hw_videoport);
-int dispc_vp_bus_check(struct dispc_device *dispc, u32 hw_videoport,
+void dispc_vp_disable(struct dispc_device *dispc, u32 vp_idx);
+void dispc_vp_unprepare(struct dispc_device *dispc, u32 vp_idx);
+bool dispc_vp_go_busy(struct dispc_device *dispc, u32 vp_idx);
+void dispc_vp_go(struct dispc_device *dispc, u32 vp_idx);
+int dispc_vp_bus_check(struct dispc_device *dispc, u32 vp_idx,
 		       const struct drm_crtc_state *state);
-enum drm_mode_status dispc_vp_mode_valid(struct dispc_device *dispc,
-					 u32 hw_videoport,
+enum drm_mode_status dispc_vp_mode_valid(struct dispc_device *dispc, u32 vp_idx,
 					 const struct drm_display_mode *mode);
-int dispc_vp_enable_clk(struct dispc_device *dispc, u32 hw_videoport);
-void dispc_vp_disable_clk(struct dispc_device *dispc, u32 hw_videoport);
-int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 hw_videoport,
+int dispc_vp_enable_clk(struct dispc_device *dispc, u32 vp_idx);
+void dispc_vp_disable_clk(struct dispc_device *dispc, u32 vp_idx);
+int dispc_vp_set_clk_rate(struct dispc_device *dispc, u32 vp_idx,
 			  unsigned long rate);
-void dispc_vp_setup(struct dispc_device *dispc, u32 hw_videoport,
+void dispc_vp_setup(struct dispc_device *dispc, u32 vp_idx,
 		    const struct drm_crtc_state *state, bool newmodeset);
 
 int dispc_runtime_suspend(struct dispc_device *dispc);
 int dispc_runtime_resume(struct dispc_device *dispc);
 
 int dispc_plane_check(struct dispc_device *dispc, u32 hw_plane,
-		      const struct drm_plane_state *state,
-		      u32 hw_videoport);
+		      const struct drm_plane_state *state, u32 vp_idx);
 int dispc_plane_setup(struct dispc_device *dispc, u32 hw_plane,
-		      const struct drm_plane_state *state,
-		      u32 hw_videoport);
+		      const struct drm_plane_state *state, u32 vp_idx);
 int dispc_plane_enable(struct dispc_device *dispc, u32 hw_plane, bool enable);
 const u32 *dispc_plane_formats(struct dispc_device *dispc, unsigned int *len);
+void dispc_set_oldi_mode(struct dispc_device *dispc, enum dispc_oldi_modes oldi_mode);
 
 int dispc_init(struct tidss_device *tidss);
 void dispc_remove(struct tidss_device *tidss);
 
+void dispc_splash_fini(struct dispc_device *dispc);
+
 #endif
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_dispc_regs.h b/drivers/gpu/drm/tidss/tidss_dispc_regs.h
--- a/drivers/gpu/drm/tidss/tidss_dispc_regs.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_dispc_regs.h	2024-01-28 14:01:31.244353788 -0500
@@ -227,17 +227,37 @@
 #define DISPC_VP_DSS_DMA_THREADSIZE_STATUS	0x174 /* J721E */
 
 /*
- * OLDI IO_CTRL register offsets. On AM654 the registers are found
- * from CTRL_MMR0, there the syscon regmap should map 0x14 bytes from
- * CTRLMMR0P1_OLDI_DAT0_IO_CTRL to CTRLMMR0P1_OLDI_CLK_IO_CTRL
- * register range.
+ * OLDI IO and PD CTRL register offsets.
+ * These registers are found in the CTRL_MMR0, where the syscon regmap should map
+ *
+ * 1. 0x14 bytes from CTRLMMR0P1_OLDI_DAT0_IO_CTRL to CTRLMMR0P1_OLDI_CLK_IO_CTRL
+ * register range for the AM65X DSS, and
+ *
+ * 2. 0x200 bytes from OLDI0_DAT0_IO_CTRL to OLDI_LB_CTRL register range for the
+ * AM625 DSS.
  */
-#define OLDI_DAT0_IO_CTRL			0x00
-#define OLDI_DAT1_IO_CTRL			0x04
-#define OLDI_DAT2_IO_CTRL			0x08
-#define OLDI_DAT3_IO_CTRL			0x0C
-#define OLDI_CLK_IO_CTRL			0x10
 
-#define OLDI_PWRDN_TX				BIT(8)
+/* -- For AM65X OLDI TX -- */
+/* Register offsets */
+#define AM65X_OLDI_DAT0_IO_CTRL			0x00
+#define AM65X_OLDI_DAT1_IO_CTRL			0x04
+#define AM65X_OLDI_DAT2_IO_CTRL			0x08
+#define AM65X_OLDI_DAT3_IO_CTRL			0x0C
+#define AM65X_OLDI_CLK_IO_CTRL			0x10
+
+/* Power control bits */
+#define AM65X_OLDI_PWRDN_TX			BIT(8)
+
+/* -- For AM625 OLDI TX -- */
+/* Register offsets */
+#define AM625_OLDI_PD_CTRL			0x100
+#define AM625_OLDI_LB_CTRL			0x104
+
+/* Power control bits */
+#define AM625_OLDI0_PWRDN_TX			BIT(0)
+#define AM625_OLDI1_PWRDN_TX			BIT(1)
+
+/* LVDS Bandgap reference Enable/Disable */
+#define AM625_OLDI_PWRDN_BG			BIT(8)
 
 #endif /* __TIDSS_DISPC_REGS_H */
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c
--- a/drivers/gpu/drm/tidss/tidss_drv.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_drv.c	2024-01-28 14:01:31.244353788 -0500
@@ -8,7 +8,9 @@
 #include <linux/of_device.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
+#include <linux/pm_domain.h>
 
+#include <drm/drm_aperture.h>
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_crtc.h>
@@ -33,9 +35,27 @@
 
 	dev_dbg(tidss->dev, "%s\n", __func__);
 
-	r = pm_runtime_get_sync(tidss->dev);
-	WARN_ON(r < 0);
-	return r < 0 ? r : 0;
+	/* No PM in display sharing mode */
+	if (tidss->shared_mode)
+		return 0;
+
+	r = pm_runtime_resume_and_get(tidss->dev);
+	if (WARN_ON(r < 0))
+		return r;
+
+	if (tidss->boot_enabled_vp_mask) {
+		/*
+		 * If 'boot_enabled_vp_mask' is set, it means that the DSS is
+		 * enabled and bootloader splash-screen is still on the screen,
+		 * using bootloader's DSS HW config.
+		 *
+		 * This is the first time the driver is about to use the HW, and
+		 * we need to do some cleanup and initial setup.
+		 */
+		dispc_splash_fini(tidss->dispc);
+	}
+
+	return 0;
 }
 
 void tidss_runtime_put(struct tidss_device *tidss)
@@ -44,7 +64,12 @@
 
 	dev_dbg(tidss->dev, "%s\n", __func__);
 
-	r = pm_runtime_put_sync(tidss->dev);
+	if (tidss->shared_mode)
+		return;
+
+	pm_runtime_mark_last_busy(tidss->dev);
+
+	r = pm_runtime_put_autosuspend(tidss->dev);
 	WARN_ON(r < 0);
 }
 
@@ -115,6 +140,72 @@
 	.minor			= 0,
 };
 
+static int tidss_detach_pm_domains(struct tidss_device *tidss)
+{
+	int i;
+
+	if (tidss->num_domains <= 1)
+		return 0;
+
+	for (i = 0; i < tidss->num_domains; i++) {
+		if (tidss->pd_link[i] && !IS_ERR(tidss->pd_link[i]))
+			device_link_del(tidss->pd_link[i]);
+		if (tidss->pd_dev[i] && !IS_ERR(tidss->pd_dev[i]))
+			dev_pm_domain_detach(tidss->pd_dev[i], true);
+		tidss->pd_dev[i] = NULL;
+		tidss->pd_link[i] = NULL;
+	}
+
+	return 0;
+}
+
+static int tidss_attach_pm_domains(struct tidss_device *tidss)
+{
+	struct device *dev = tidss->dev;
+	int i;
+	int ret;
+	struct platform_device *pdev = to_platform_device(dev);
+	struct device_node *np = pdev->dev.of_node;
+
+	tidss->num_domains = of_count_phandle_with_args(np, "power-domains",
+							"#power-domain-cells");
+	if (tidss->num_domains <= 1) {
+		dev_dbg(dev, "One or less power domains, no need to do attach domains\n");
+		return 0;
+	}
+
+	tidss->pd_dev = devm_kmalloc_array(dev, tidss->num_domains,
+					   sizeof(*tidss->pd_dev), GFP_KERNEL);
+	if (!tidss->pd_dev)
+		return -ENOMEM;
+
+	tidss->pd_link = devm_kmalloc_array(dev, tidss->num_domains,
+					    sizeof(*tidss->pd_link), GFP_KERNEL);
+	if (!tidss->pd_link)
+		return -ENOMEM;
+
+	for (i = 0; i < tidss->num_domains; i++) {
+		tidss->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
+		if (IS_ERR(tidss->pd_dev[i])) {
+			ret = PTR_ERR(tidss->pd_dev[i]);
+			goto fail;
+		}
+
+		tidss->pd_link[i] = device_link_add(dev, tidss->pd_dev[i],
+						    DL_FLAG_STATELESS |
+						    DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE);
+		if (!tidss->pd_link[i]) {
+			ret = -EINVAL;
+			goto fail;
+		}
+	}
+
+	return 0;
+fail:
+	tidss_detach_pm_domains(tidss);
+	return ret;
+}
+
 static int tidss_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -137,18 +228,35 @@
 
 	platform_set_drvdata(pdev, tidss);
 
+	spin_lock_init(&tidss->wait_lock);
+
+	tidss->shared_mode = device_property_read_bool(dev, "ti,dss-shared-mode");
+
+	/* powering up associated OLDI domains */
+	if (!tidss->shared_mode) {
+		ret = tidss_attach_pm_domains(tidss);
+		if (ret < 0) {
+			dev_err(dev, "failed to attach power domains %d\n", ret);
+			return ret;
+		}
+	}
+
 	ret = dispc_init(tidss);
 	if (ret) {
 		dev_err(dev, "failed to initialize dispc: %d\n", ret);
 		return ret;
 	}
 
-	pm_runtime_enable(dev);
+	if (!tidss->shared_mode) {
+		pm_runtime_enable(dev);
+		pm_runtime_set_autosuspend_delay(dev, 1000);
+		pm_runtime_use_autosuspend(dev);
 
 #ifndef CONFIG_PM
-	/* If we don't have PM, we need to call resume manually */
-	dispc_runtime_resume(tidss->dispc);
+		/* If we don't have PM, we need to call resume manually */
+		dispc_runtime_resume(tidss->dispc);
 #endif
+	}
 
 	ret = tidss_modeset_init(tidss);
 	if (ret < 0) {
@@ -180,20 +288,32 @@
 		goto err_irq_uninstall;
 	}
 
+	/* Remove possible early fb before setting up the fbdev */
+	ret = drm_aperture_remove_framebuffers(&tidss_driver);
+	if (ret)
+		goto err_drm_dev_unreg;
+
 	drm_fbdev_generic_setup(ddev, 32);
 
 	dev_dbg(dev, "%s done\n", __func__);
 
 	return 0;
 
+err_drm_dev_unreg:
+	drm_dev_unregister(ddev);
+
 err_irq_uninstall:
 	tidss_irq_uninstall(ddev);
 
 err_runtime_suspend:
+	if (tidss->shared_mode)
+		return ret;
 #ifndef CONFIG_PM
 	dispc_runtime_suspend(tidss->dispc);
 #endif
+	pm_runtime_dont_use_autosuspend(dev);
 	pm_runtime_disable(dev);
+	tidss_detach_pm_domains(tidss);
 
 	return ret;
 }
@@ -212,11 +332,15 @@
 
 	tidss_irq_uninstall(ddev);
 
+	if (!tidss->shared_mode) {
 #ifndef CONFIG_PM
-	/* If we don't have PM, we need to call suspend manually */
-	dispc_runtime_suspend(tidss->dispc);
+		/* If we don't have PM, we need to call suspend manually */
+		dispc_runtime_suspend(tidss->dispc);
 #endif
-	pm_runtime_disable(dev);
+		pm_runtime_dont_use_autosuspend(dev);
+		pm_runtime_disable(dev);
+		tidss_detach_pm_domains(tidss);
+	}
 
 	/* devm allocated dispc goes away with the dev so mark it NULL */
 	dispc_remove(tidss);
@@ -233,6 +357,10 @@
 
 static const struct of_device_id tidss_of_table[] = {
 	{ .compatible = "ti,k2g-dss", .data = &dispc_k2g_feats, },
+	{ .compatible = "ti,am625-dss", .data = &dispc_am625_feats, },
+	{ .compatible = "ti,am62a7-dss", .data = &dispc_am62a7_feats, },
+	{ .compatible = "ti,am62p51-dss", .data = &dispc_am62p51_feats, },
+	{ .compatible = "ti,am62p52-dss", .data = &dispc_am62p52_feats, },
 	{ .compatible = "ti,am65x-dss", .data = &dispc_am65x_feats, },
 	{ .compatible = "ti,j721e-dss", .data = &dispc_j721e_feats, },
 	{ }
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_drv.h b/drivers/gpu/drm/tidss/tidss_drv.h
--- a/drivers/gpu/drm/tidss/tidss_drv.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_drv.h	2024-01-28 14:01:31.244353788 -0500
@@ -9,9 +9,20 @@
 
 #include <linux/spinlock.h>
 
-#define TIDSS_MAX_PORTS 4
+#define TIDSS_MAX_VPS 4
 #define TIDSS_MAX_PLANES 4
 
+/*
+ * This is not dependent on the number of VPs.
+ * For example, some SoCs have 2 VPs but 3 outputs coming out.
+ */
+#define TIDSS_MAX_OUTPUTS 4
+
+/* For DSSes with 2 OLDI TXes */
+#define TIDSS_MAX_BRIDGES_PER_PIPE	2
+
+#define TIDSS_AM625_IDLE_OLDI_CLOCK 25000000
+
 typedef u32 dispc_irq_t;
 
 struct tidss_device {
@@ -22,7 +33,7 @@
 	struct dispc_device *dispc;
 
 	unsigned int num_crtcs;
-	struct drm_crtc *crtcs[TIDSS_MAX_PORTS];
+	struct drm_crtc *crtcs[TIDSS_MAX_VPS];
 
 	unsigned int num_planes;
 	struct drm_plane *planes[TIDSS_MAX_PLANES];
@@ -31,6 +42,18 @@
 
 	spinlock_t wait_lock;	/* protects the irq masks */
 	dispc_irq_t irq_mask;	/* enabled irqs in addition to wait_list */
+
+	int num_domains; /* Handle attached PM domains */
+	struct device **pd_dev;
+	struct device_link **pd_link;
+
+	u32 boot_enabled_vp_mask;
+
+	bool shared_mode; /* DSS resources shared between remote core and Linux */
+
+	/* 1: VP owned by Linux 0: VP is owned by remote and shared with Linux */
+	u32 shared_mode_owned_vps[TIDSS_MAX_VPS];
+	bool shared_mode_own_oldi; /* Linux needs to configure OLDI in shared mode */
 };
 
 #define to_tidss(__dev) container_of(__dev, struct tidss_device, ddev)
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_encoder.c b/drivers/gpu/drm/tidss/tidss_encoder.c
--- a/drivers/gpu/drm/tidss/tidss_encoder.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_encoder.c	2024-01-28 14:01:31.244353788 -0500
@@ -70,7 +70,8 @@
 };
 
 struct drm_encoder *tidss_encoder_create(struct tidss_device *tidss,
-					 u32 encoder_type, u32 possible_crtcs)
+					 u32 encoder_type, u32 possible_crtcs,
+					 u32 possible_clones)
 {
 	struct drm_encoder *enc;
 	int ret;
@@ -80,6 +81,7 @@
 		return ERR_PTR(-ENOMEM);
 
 	enc->possible_crtcs = possible_crtcs;
+	enc->possible_clones = possible_clones;
 
 	ret = drm_encoder_init(&tidss->ddev, enc, &encoder_funcs,
 			       encoder_type, NULL);
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_encoder.h b/drivers/gpu/drm/tidss/tidss_encoder.h
--- a/drivers/gpu/drm/tidss/tidss_encoder.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_encoder.h	2024-01-28 14:01:31.244353788 -0500
@@ -12,6 +12,7 @@
 struct tidss_device;
 
 struct drm_encoder *tidss_encoder_create(struct tidss_device *tidss,
-					 u32 encoder_type, u32 possible_crtcs);
+					 u32 encoder_type, u32 possible_crtcs,
+					 u32 possible_clones);
 
 #endif
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_irq.c b/drivers/gpu/drm/tidss/tidss_irq.c
--- a/drivers/gpu/drm/tidss/tidss_irq.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_irq.c	2024-01-28 14:01:31.244353788 -0500
@@ -28,12 +28,12 @@
 	struct drm_device *ddev = crtc->dev;
 	struct tidss_device *tidss = to_tidss(ddev);
 	struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
-	u32 hw_videoport = tcrtc->hw_videoport;
+	u32 vp_idx = tcrtc->vp_idx;
 	unsigned long flags;
 
 	spin_lock_irqsave(&tidss->wait_lock, flags);
-	tidss->irq_mask |= DSS_IRQ_VP_VSYNC_EVEN(hw_videoport) |
-			   DSS_IRQ_VP_VSYNC_ODD(hw_videoport);
+	tidss->irq_mask |= DSS_IRQ_VP_VSYNC_EVEN(vp_idx) |
+			   DSS_IRQ_VP_VSYNC_ODD(vp_idx);
 	tidss_irq_update(tidss);
 	spin_unlock_irqrestore(&tidss->wait_lock, flags);
 }
@@ -43,12 +43,12 @@
 	struct drm_device *ddev = crtc->dev;
 	struct tidss_device *tidss = to_tidss(ddev);
 	struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
-	u32 hw_videoport = tcrtc->hw_videoport;
+	u32 vp_idx = tcrtc->vp_idx;
 	unsigned long flags;
 
 	spin_lock_irqsave(&tidss->wait_lock, flags);
-	tidss->irq_mask &= ~(DSS_IRQ_VP_VSYNC_EVEN(hw_videoport) |
-			     DSS_IRQ_VP_VSYNC_ODD(hw_videoport));
+	tidss->irq_mask &= ~(DSS_IRQ_VP_VSYNC_EVEN(vp_idx) |
+			     DSS_IRQ_VP_VSYNC_ODD(vp_idx));
 	tidss_irq_update(tidss);
 	spin_unlock_irqrestore(&tidss->wait_lock, flags);
 }
@@ -65,16 +65,16 @@
 	for (id = 0; id < tidss->num_crtcs; id++) {
 		struct drm_crtc *crtc = tidss->crtcs[id];
 		struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
-		u32 hw_videoport = tcrtc->hw_videoport;
+		u32 vp_idx = tcrtc->vp_idx;
 
-		if (irqstatus & (DSS_IRQ_VP_VSYNC_EVEN(hw_videoport) |
-				 DSS_IRQ_VP_VSYNC_ODD(hw_videoport)))
+		if (irqstatus & (DSS_IRQ_VP_VSYNC_EVEN(vp_idx) |
+				 DSS_IRQ_VP_VSYNC_ODD(vp_idx)))
 			tidss_crtc_vblank_irq(crtc);
 
-		if (irqstatus & (DSS_IRQ_VP_FRAME_DONE(hw_videoport)))
+		if (irqstatus & (DSS_IRQ_VP_FRAME_DONE(vp_idx)))
 			tidss_crtc_framedone_irq(crtc);
 
-		if (irqstatus & DSS_IRQ_VP_SYNC_LOST(hw_videoport))
+		if (irqstatus & DSS_IRQ_VP_SYNC_LOST(vp_idx))
 			tidss_crtc_error_irq(crtc, irqstatus);
 	}
 
@@ -93,61 +93,27 @@
 	spin_unlock_irqrestore(&tidss->wait_lock, flags);
 }
 
-static void tidss_irq_preinstall(struct drm_device *ddev)
-{
-	struct tidss_device *tidss = to_tidss(ddev);
-
-	spin_lock_init(&tidss->wait_lock);
-
-	tidss_runtime_get(tidss);
-
-	dispc_set_irqenable(tidss->dispc, 0);
-	dispc_read_and_clear_irqstatus(tidss->dispc);
-
-	tidss_runtime_put(tidss);
-}
-
-static void tidss_irq_postinstall(struct drm_device *ddev)
-{
-	struct tidss_device *tidss = to_tidss(ddev);
-	unsigned long flags;
-	unsigned int i;
-
-	tidss_runtime_get(tidss);
-
-	spin_lock_irqsave(&tidss->wait_lock, flags);
-
-	tidss->irq_mask = DSS_IRQ_DEVICE_OCP_ERR;
-
-	for (i = 0; i < tidss->num_crtcs; ++i) {
-		struct tidss_crtc *tcrtc = to_tidss_crtc(tidss->crtcs[i]);
-
-		tidss->irq_mask |= DSS_IRQ_VP_SYNC_LOST(tcrtc->hw_videoport);
-
-		tidss->irq_mask |= DSS_IRQ_VP_FRAME_DONE(tcrtc->hw_videoport);
-	}
-
-	tidss_irq_update(tidss);
-
-	spin_unlock_irqrestore(&tidss->wait_lock, flags);
-
-	tidss_runtime_put(tidss);
-}
-
 int tidss_irq_install(struct drm_device *ddev, unsigned int irq)
 {
+	struct tidss_device *tidss = to_tidss(ddev);
 	int ret;
 
 	if (irq == IRQ_NOTCONNECTED)
 		return -ENOTCONN;
 
-	tidss_irq_preinstall(ddev);
-
 	ret = request_irq(irq, tidss_irq_handler, 0, ddev->driver->name, ddev);
 	if (ret)
 		return ret;
 
-	tidss_irq_postinstall(ddev);
+	tidss->irq_mask = DSS_IRQ_DEVICE_OCP_ERR;
+
+	for (unsigned int i = 0; i < tidss->num_crtcs; ++i) {
+		struct tidss_crtc *tcrtc = to_tidss_crtc(tidss->crtcs[i]);
+
+		tidss->irq_mask |= DSS_IRQ_VP_SYNC_LOST(tcrtc->vp_idx);
+
+		tidss->irq_mask |= DSS_IRQ_VP_FRAME_DONE(tcrtc->vp_idx);
+	}
 
 	return 0;
 }
@@ -156,9 +122,5 @@
 {
 	struct tidss_device *tidss = to_tidss(ddev);
 
-	tidss_runtime_get(tidss);
-	dispc_set_irqenable(tidss->dispc, 0);
-	tidss_runtime_put(tidss);
-
 	free_irq(tidss->irq, ddev);
 }
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_irq.h b/drivers/gpu/drm/tidss/tidss_irq.h
--- a/drivers/gpu/drm/tidss/tidss_irq.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_irq.h	2024-01-28 14:01:31.244353788 -0500
@@ -35,7 +35,7 @@
 
 #define DSS_IRQ_VP_BIT_N(ch, bit)	(4 + 4 * (ch) + (bit))
 #define DSS_IRQ_PLANE_BIT_N(plane, bit) \
-	(DSS_IRQ_VP_BIT_N(TIDSS_MAX_PORTS, 0) + 1 * (plane) + (bit))
+	(DSS_IRQ_VP_BIT_N(TIDSS_MAX_VPS, 0) + 1 * (plane) + (bit))
 
 #define DSS_IRQ_VP_BIT(ch, bit)	BIT(DSS_IRQ_VP_BIT_N((ch), (bit)))
 #define DSS_IRQ_PLANE_BIT(plane, bit) \
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_kms.c b/drivers/gpu/drm/tidss/tidss_kms.c
--- a/drivers/gpu/drm/tidss/tidss_kms.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_kms.c	2024-01-28 14:01:31.244353788 -0500
@@ -4,8 +4,6 @@
  * Author: Tomi Valkeinen <tomi.valkeinen@ti.com>
  */
 
-#include <linux/dma-fence.h>
-
 #include <drm/drm_atomic.h>
 #include <drm/drm_atomic_helper.h>
 #include <drm/drm_bridge.h>
@@ -15,6 +13,7 @@
 #include <drm/drm_of.h>
 #include <drm/drm_panel.h>
 #include <drm/drm_vblank.h>
+#include <linux/of.h>
 
 #include "tidss_crtc.h"
 #include "tidss_dispc.h"
@@ -27,18 +26,16 @@
 {
 	struct drm_device *ddev = old_state->dev;
 	struct tidss_device *tidss = to_tidss(ddev);
-	bool fence_cookie = dma_fence_begin_signalling();
 
 	dev_dbg(ddev->dev, "%s\n", __func__);
 
 	tidss_runtime_get(tidss);
 
 	drm_atomic_helper_commit_modeset_disables(ddev, old_state);
-	drm_atomic_helper_commit_planes(ddev, old_state, 0);
+	drm_atomic_helper_commit_planes(ddev, old_state, DRM_PLANE_COMMIT_ACTIVE_ONLY);
 	drm_atomic_helper_commit_modeset_enables(ddev, old_state);
 
 	drm_atomic_helper_commit_hw_done(old_state);
-	dma_fence_end_signalling(fence_cookie);
 	drm_atomic_helper_wait_for_flip_done(ddev, old_state);
 
 	drm_atomic_helper_cleanup_planes(ddev, old_state);
@@ -106,30 +103,141 @@
 	.atomic_commit = drm_atomic_helper_commit,
 };
 
+static enum dispc_oldi_modes tidss_parse_oldi_properties(struct tidss_device *tidss)
+{
+	int pixel_order;
+	enum dispc_oldi_modes oldi_mode;
+	struct device_node *oldi0_port, *oldi1_port;
+
+	/*
+	 * For dual-link / clone mode connections, the OLDI ports are expected
+	 * at port reg = 0 and 2, while for single-link cases the OLDI port is
+	 * expected only at port reg = 0.
+	 */
+	const u32 portnum_oldi0 = 0, portnum_oldi1 = 2;
+
+	oldi0_port = of_graph_get_port_by_id(tidss->dev->of_node, portnum_oldi0);
+	oldi1_port = of_graph_get_port_by_id(tidss->dev->of_node, portnum_oldi1);
+
+	if (!(oldi0_port || oldi1_port)) {
+		/* Keep OLDI TXes OFF if neither OLDI port is present. */
+		oldi_mode = OLDI_MODE_OFF;
+	} else if (oldi0_port && !oldi1_port) {
+		/*
+		 * OLDI0 port found, but not OLDI1 port. Setting single
+		 * link output mode.
+		 */
+		oldi_mode = OLDI_MODE_SINGLE_LINK;
+	} else if (!oldi0_port && oldi1_port) {
+		/*
+		 * The 2nd OLDI TX cannot be operated alone. This use case is
+		 * not supported in the HW. Since the pins for OLDIs 0 and 1 are
+		 * separate, one could theoretically set a clone mode over OLDIs
+		 * 0 and 1 and just simply not use the OLDI 0. This is a hacky
+		 * way to enable only OLDI TX 1 and hence is not officially
+		 * supported.
+		 */
+		dev_err(tidss->dev,
+			"%s: Single Mode over OLDI 1 is not supported in HW.\n",
+			__func__);
+		oldi_mode = OLDI_MODE_UNSUPPORTED;
+	} else {
+		/*
+		 * OLDI Ports found for both the OLDI TXes. The DSS is to be
+		 * configured in either Dual Link or Clone Mode.
+		 */
+		pixel_order = drm_of_lvds_get_dual_link_pixel_order(oldi0_port,
+								    oldi1_port);
+		switch (pixel_order) {
+		case -EINVAL:
+			/*
+			 * The dual link properties were not found in at least
+			 * one of the sink nodes. Since 2 OLDI ports are present
+			 * in the DT, it can be safely assumed that the required
+			 * configuration is Clone Mode.
+			 */
+			oldi_mode = OLDI_MODE_CLONE_SINGLE_LINK;
+			break;
+
+		case DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS:
+			/*
+			 * Note that the OLDI TX 0 transmits the odd set of
+			 * pixels while the OLDI TX 1 transmits the even set.
+			 * This is a fixed configuration in the HW and an cannot
+			 * be change via SW.
+			 */
+			dev_err(tidss->dev,
+				"%s: EVEN-ODD Dual-Link Mode is not supported in HW.\n",
+				__func__);
+			oldi_mode = OLDI_MODE_UNSUPPORTED;
+			break;
+
+		case DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS:
+			oldi_mode = OLDI_MODE_DUAL_LINK;
+			break;
+
+		default:
+			dev_err(tidss->dev, "%s: Unrecognized OLDI mode.\n",
+				__func__);
+			oldi_mode = OLDI_MODE_UNSUPPORTED;
+			break;
+		}
+	}
+
+	of_node_put(oldi0_port);
+	of_node_put(oldi1_port);
+
+	return oldi_mode;
+}
+
 static int tidss_dispc_modeset_init(struct tidss_device *tidss)
 {
 	struct device *dev = tidss->dev;
 	unsigned int fourccs_len;
 	const u32 *fourccs = dispc_plane_formats(tidss->dispc, &fourccs_len);
-	unsigned int i;
+	unsigned int i, j;
 
 	struct pipe {
-		u32 hw_videoport;
-		struct drm_bridge *bridge;
+		u32 vp_idx;
+		struct drm_bridge *bridge[TIDSS_MAX_BRIDGES_PER_PIPE];
 		u32 enc_type;
+		u32 num_bridges;
 	};
 
 	const struct dispc_features *feat = tidss->feat;
-	u32 max_vps = feat->num_vps;
+	u32 num_outputs = feat->num_outputs;
 	u32 max_planes = feat->num_planes;
 
-	struct pipe pipes[TIDSS_MAX_PORTS];
+	struct pipe pipes[TIDSS_MAX_VPS] = {0};
+
 	u32 num_pipes = 0;
 	u32 crtc_mask;
+	enum dispc_oldi_modes oldi_mode = OLDI_MODE_UNAVAILABLE;
+	u32 num_oldi = 0;
+	u32 num_encoders = 0;
+	u32 oldi_pipe_index = 0;
+
+	if (feat->has_oldi) {
+		oldi_mode = tidss_parse_oldi_properties(tidss);
+
+		if ((oldi_mode == OLDI_MODE_DUAL_LINK ||
+		     oldi_mode == OLDI_MODE_CLONE_SINGLE_LINK) &&
+		    feat->subrev == DISPC_AM65X) {
+			dev_err(dev,
+				"%s: am65x-dss does not support this OLDI mode.\n",
+				__func__);
+			oldi_mode = OLDI_MODE_UNSUPPORTED;
+		}
+	}
+
+	if (oldi_mode == OLDI_MODE_UNSUPPORTED)
+		return -EINVAL;
+
+	dispc_set_oldi_mode(tidss->dispc, oldi_mode);
 
 	/* first find all the connected panels & bridges */
 
-	for (i = 0; i < max_vps; i++) {
+	for (i = 0; i < num_outputs; i++) {
 		struct drm_panel *panel;
 		struct drm_bridge *bridge;
 		u32 enc_type = DRM_MODE_ENCODER_NONE;
@@ -150,12 +258,12 @@
 
 			dev_dbg(dev, "Setting up panel for port %d\n", i);
 
-			switch (feat->vp_bus_type[i]) {
-			case DISPC_VP_OLDI:
+			switch (feat->output_type[i]) {
+			case DISPC_OUTPUT_OLDI:
 				enc_type = DRM_MODE_ENCODER_LVDS;
 				conn_type = DRM_MODE_CONNECTOR_LVDS;
 				break;
-			case DISPC_VP_DPI:
+			case DISPC_OUTPUT_DPI:
 				enc_type = DRM_MODE_ENCODER_DPI;
 				conn_type = DRM_MODE_CONNECTOR_DPI;
 				break;
@@ -181,10 +289,74 @@
 			}
 		}
 
-		pipes[num_pipes].hw_videoport = i;
-		pipes[num_pipes].bridge = bridge;
-		pipes[num_pipes].enc_type = enc_type;
-		num_pipes++;
+		if (feat->output_type[i] == DISPC_OUTPUT_OLDI) {
+			switch (oldi_mode) {
+			case OLDI_MODE_OFF:
+				dev_dbg(dev, "OLDI disconnected on port %d\n", i);
+				continue;
+
+			case OLDI_MODE_DUAL_LINK:
+				/*
+				 * The 2nd OLDI port of a dual-link sink does
+				 * not require a separate bridge entity.
+				 */
+				if (num_oldi > 0) {
+					drm_panel_bridge_remove(bridge);
+					continue;
+				}
+
+				fallthrough;
+
+			case OLDI_MODE_CLONE_SINGLE_LINK:
+			case OLDI_MODE_SINGLE_LINK:
+				/*
+				 * Setting up pipe parameters when 1st OLDI
+				 * port is detected.
+				 */
+				if (num_oldi == 0) {
+					pipes[num_pipes].vp_idx = feat->output_source_vp[i];
+					pipes[num_pipes].enc_type = enc_type;
+
+					/*
+					 * Saving the pipe index in case its
+					 * required for 2nd OLDI Port.
+					 */
+					oldi_pipe_index = num_pipes;
+
+					/*
+					 * Incrememnt num_pipe when 1st oldi
+					 * port is discovered. For the 2nd OLDI
+					 * port, num_pipe need not be
+					 * incremented because the 2nd
+					 * Encoder-to-Bridge connection will
+					 * still be the part of the first OLDI
+					 * Port pipe.
+					 */
+					num_pipes++;
+				}
+
+				/*
+				 * Bridge is required to be added only if the
+				 * detected port is the first OLDI port (of any
+				 * mode) or a subsequent port in Clone Mode.
+				 */
+				pipes[oldi_pipe_index].bridge[num_oldi] = bridge;
+				pipes[oldi_pipe_index].num_bridges++;
+				num_oldi++;
+				break;
+
+			case OLDI_MODE_UNAVAILABLE:
+			default:
+				dev_dbg(dev, "OLDI unavailable on this device.\n");
+				break;
+			}
+		} else {
+			pipes[num_pipes].vp_idx = feat->output_source_vp[i];
+			pipes[num_pipes].bridge[0] = bridge;
+			pipes[num_pipes].num_bridges++;
+			pipes[num_pipes].enc_type = enc_type;
+			num_pipes++;
+		}
 	}
 
 	/* all planes can be on any crtc */
@@ -196,6 +368,7 @@
 		struct tidss_plane *tplane;
 		struct tidss_crtc *tcrtc;
 		struct drm_encoder *enc;
+		u32 possible_clones = 0;
 		u32 hw_plane_id = feat->vid_order[tidss->num_planes];
 		int ret;
 
@@ -209,7 +382,7 @@
 
 		tidss->planes[tidss->num_planes++] = &tplane->plane;
 
-		tcrtc = tidss_crtc_create(tidss, pipes[i].hw_videoport,
+		tcrtc = tidss_crtc_create(tidss, pipes[i].vp_idx,
 					  &tplane->plane);
 		if (IS_ERR(tcrtc)) {
 			dev_err(tidss->dev, "crtc create failed\n");
@@ -218,16 +391,23 @@
 
 		tidss->crtcs[tidss->num_crtcs++] = &tcrtc->crtc;
 
-		enc = tidss_encoder_create(tidss, pipes[i].enc_type,
-					   1 << tcrtc->crtc.index);
-		if (IS_ERR(enc)) {
-			dev_err(tidss->dev, "encoder create failed\n");
-			return PTR_ERR(enc);
-		}
+		possible_clones = (((1 << pipes[i].num_bridges) - 1)
+				   << num_encoders);
 
-		ret = drm_bridge_attach(enc, pipes[i].bridge, NULL, 0);
-		if (ret)
-			return ret;
+		for (j = 0; j < pipes[i].num_bridges; j++) {
+			enc = tidss_encoder_create(tidss, pipes[i].enc_type,
+						   1 << tcrtc->crtc.index,
+						   possible_clones);
+			if (IS_ERR(enc)) {
+				dev_err(tidss->dev, "encoder create failed\n");
+				return PTR_ERR(enc);
+			}
+
+			ret = drm_bridge_attach(enc, pipes[i].bridge[j], NULL, 0);
+			if (ret)
+				return ret;
+		}
+		num_encoders += pipes[i].num_bridges;
 	}
 
 	/* create overlay planes of the leftover planes */
diff -Naur --no-dereference a/drivers/gpu/drm/tidss/tidss_plane.c b/drivers/gpu/drm/tidss/tidss_plane.c
--- a/drivers/gpu/drm/tidss/tidss_plane.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/gpu/drm/tidss/tidss_plane.c	2024-01-28 14:01:31.244353788 -0500
@@ -31,7 +31,7 @@
 	const struct drm_format_info *finfo;
 	struct drm_crtc_state *crtc_state;
 	u32 hw_plane = tplane->hw_plane_id;
-	u32 hw_videoport;
+	u32 vp_idx;
 	int ret;
 
 	dev_dbg(ddev->dev, "%s\n", __func__);
@@ -95,10 +95,10 @@
 	if (!new_plane_state->visible)
 		return 0;
 
-	hw_videoport = to_tidss_crtc(new_plane_state->crtc)->hw_videoport;
+	vp_idx = to_tidss_crtc(new_plane_state->crtc)->vp_idx;
 
 	ret = dispc_plane_check(tidss->dispc, hw_plane, new_plane_state,
-				hw_videoport);
+				vp_idx);
 	if (ret)
 		return ret;
 
@@ -113,7 +113,7 @@
 	struct tidss_plane *tplane = to_tidss_plane(plane);
 	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
 									   plane);
-	u32 hw_videoport;
+	u32 vp_idx;
 	int ret;
 
 	dev_dbg(ddev->dev, "%s\n", __func__);
@@ -123,10 +123,10 @@
 		return;
 	}
 
-	hw_videoport = to_tidss_crtc(new_state->crtc)->hw_videoport;
+	vp_idx = to_tidss_crtc(new_state->crtc)->vp_idx;
 
 	ret = dispc_plane_setup(tidss->dispc, tplane->hw_plane_id,
-				new_state, hw_videoport);
+				new_state, vp_idx);
 
 	if (ret) {
 		dev_err(plane->dev->dev, "%s: Failed to setup plane %d\n",
diff -Naur --no-dereference a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c
--- a/drivers/hwmon/sht3x.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/hwmon/sht3x.c	2024-01-28 14:01:31.244353788 -0500
@@ -738,9 +738,16 @@
 	{"sts3x", sts3x},
 	{}
 };
-
 MODULE_DEVICE_TABLE(i2c, sht3x_ids);
 
+static const struct of_device_id shtc1_of_match[] = {
+	{ .compatible = "sensirion,shtc1" },
+	{ .compatible = "sensirion,shtw1" },
+	{ .compatible = "sensirion,shtc3" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, shtc1_of_match);
+
 static struct i2c_driver sht3x_i2c_driver = {
 	.driver.name = "sht3x",
 	.probe_new   = sht3x_probe,
diff -Naur --no-dereference a/drivers/i2c/i2c-atr.c b/drivers/i2c/i2c-atr.c
--- a/drivers/i2c/i2c-atr.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/i2c/i2c-atr.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,710 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * I2C Address Translator
+ *
+ * Copyright (c) 2019,2022 Luca Ceresoli <luca@lucaceresoli.net>
+ * Copyright (c) 2022,2023 Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+ *
+ * Originally based on i2c-mux.c
+ */
+
+#include <linux/fwnode.h>
+#include <linux/i2c-atr.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+#define ATR_MAX_ADAPTERS 100	/* Just a sanity limit */
+#define ATR_MAX_SYMLINK_LEN 11	/* Longest name is 10 chars: "channel-99" */
+
+/**
+ * struct i2c_atr_alias_pair - Holds the alias assigned to a client.
+ * @node:   List node
+ * @client: Pointer to the client on the child bus
+ * @alias:  I2C alias address assigned by the driver.
+ *          This is the address that will be used to issue I2C transactions
+ *          on the parent (physical) bus.
+ */
+struct i2c_atr_alias_pair {
+	struct list_head node;
+	const struct i2c_client *client;
+	u16 alias;
+};
+
+/**
+ * struct i2c_atr_chan - Data for a channel.
+ * @adap:            The &struct i2c_adapter for the channel
+ * @atr:             The parent I2C ATR
+ * @chan_id:         The ID of this channel
+ * @alias_list:      List of @struct i2c_atr_alias_pair containing the
+ *                   assigned aliases
+ * @orig_addrs_lock: Mutex protecting @orig_addrs
+ * @orig_addrs:      Buffer used to store the original addresses during transmit
+ * @orig_addrs_size: Size of @orig_addrs
+ */
+struct i2c_atr_chan {
+	struct i2c_adapter adap;
+	struct i2c_atr *atr;
+	u32 chan_id;
+
+	struct list_head alias_list;
+
+	/* Lock orig_addrs during xfer */
+	struct mutex orig_addrs_lock;
+	u16 *orig_addrs;
+	unsigned int orig_addrs_size;
+};
+
+/**
+ * struct i2c_atr - The I2C ATR instance
+ * @parent:    The parent &struct i2c_adapter
+ * @dev:       The device that owns the I2C ATR instance
+ * @ops:       &struct i2c_atr_ops
+ * @priv:      Private driver data, set with i2c_atr_set_driver_data()
+ * @algo:      The &struct i2c_algorithm for adapters
+ * @lock:      Lock for the I2C bus segment (see &struct i2c_lock_operations)
+ * @max_adapters: Maximum number of adapters this I2C ATR can have
+ * @num_aliases: Number of aliases in the aliases array
+ * @aliases:   The aliases array
+ * @alias_mask_lock: Lock protecting alias_use_mask
+ * @alias_use_mask: Bitmask for used aliases in aliases array
+ * @i2c_nb:    Notifier for remote client add & del events
+ * @adapter:   Array of adapters
+ */
+struct i2c_atr {
+	struct i2c_adapter *parent;
+	struct device *dev;
+	const struct i2c_atr_ops *ops;
+
+	void *priv;
+
+	struct i2c_algorithm algo;
+	/* lock for the I2C bus segment (see struct i2c_lock_operations) */
+	struct mutex lock;
+	int max_adapters;
+
+	size_t num_aliases;
+	const u16 *aliases;
+	/* Protects alias_use_mask */
+	spinlock_t alias_mask_lock;
+	unsigned long *alias_use_mask;
+
+	struct notifier_block i2c_nb;
+
+	struct i2c_adapter *adapter[];
+};
+
+static struct i2c_atr_alias_pair *
+i2c_atr_find_mapping_by_client(const struct list_head *list,
+			       const struct i2c_client *client)
+{
+	struct i2c_atr_alias_pair *c2a;
+
+	list_for_each_entry(c2a, list, node) {
+		if (c2a->client == client)
+			return c2a;
+	}
+
+	return NULL;
+}
+
+static struct i2c_atr_alias_pair *
+i2c_atr_find_mapping_by_addr(const struct list_head *list, u16 phys_addr)
+{
+	struct i2c_atr_alias_pair *c2a;
+
+	list_for_each_entry(c2a, list, node) {
+		if (c2a->client->addr == phys_addr)
+			return c2a;
+	}
+
+	return NULL;
+}
+
+/*
+ * Replace all message addresses with their aliases, saving the original
+ * addresses.
+ *
+ * This function is internal for use in i2c_atr_master_xfer(). It must be
+ * followed by i2c_atr_unmap_msgs() to restore the original addresses.
+ */
+static int i2c_atr_map_msgs(struct i2c_atr_chan *chan, struct i2c_msg *msgs,
+			    int num)
+{
+	struct i2c_atr *atr = chan->atr;
+	static struct i2c_atr_alias_pair *c2a;
+	int i;
+
+	/* Ensure we have enough room to save the original addresses */
+	if (unlikely(chan->orig_addrs_size < num)) {
+		u16 *new_buf;
+
+		/* We don't care about old data, hence no realloc() */
+		new_buf = kmalloc_array(num, sizeof(*new_buf), GFP_KERNEL);
+		if (!new_buf)
+			return -ENOMEM;
+
+		kfree(chan->orig_addrs);
+		chan->orig_addrs = new_buf;
+		chan->orig_addrs_size = num;
+	}
+
+	for (i = 0; i < num; i++) {
+		chan->orig_addrs[i] = msgs[i].addr;
+
+		c2a = i2c_atr_find_mapping_by_addr(&chan->alias_list,
+						   msgs[i].addr);
+		if (!c2a) {
+			dev_err(atr->dev, "client 0x%02x not mapped!\n",
+				msgs[i].addr);
+
+			while (i--)
+				msgs[i].addr = chan->orig_addrs[i];
+
+			return -ENXIO;
+		}
+
+		msgs[i].addr = c2a->alias;
+	}
+
+	return 0;
+}
+
+/*
+ * Restore all message address aliases with the original addresses. This
+ * function is internal for use in i2c_atr_master_xfer() and for this reason it
+ * needs no null and size checks on orig_addr.
+ *
+ * @see i2c_atr_map_msgs()
+ */
+static void i2c_atr_unmap_msgs(struct i2c_atr_chan *chan, struct i2c_msg *msgs,
+			       int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++)
+		msgs[i].addr = chan->orig_addrs[i];
+}
+
+static int i2c_atr_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+			       int num)
+{
+	struct i2c_atr_chan *chan = adap->algo_data;
+	struct i2c_atr *atr = chan->atr;
+	struct i2c_adapter *parent = atr->parent;
+	int ret;
+
+	/* Translate addresses */
+	mutex_lock(&chan->orig_addrs_lock);
+
+	ret = i2c_atr_map_msgs(chan, msgs, num);
+	if (ret < 0)
+		goto err_unlock;
+
+	/* Perform the transfer */
+	ret = i2c_transfer(parent, msgs, num);
+
+	/* Restore addresses */
+	i2c_atr_unmap_msgs(chan, msgs, num);
+
+err_unlock:
+	mutex_unlock(&chan->orig_addrs_lock);
+
+	return ret;
+}
+
+static int i2c_atr_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+			      unsigned short flags, char read_write, u8 command,
+			      int size, union i2c_smbus_data *data)
+{
+	struct i2c_atr_chan *chan = adap->algo_data;
+	struct i2c_atr *atr = chan->atr;
+	struct i2c_adapter *parent = atr->parent;
+	struct i2c_atr_alias_pair *c2a;
+
+	c2a = i2c_atr_find_mapping_by_addr(&chan->alias_list, addr);
+	if (!c2a) {
+		dev_err(atr->dev, "client 0x%02x not mapped!\n", addr);
+		return -ENXIO;
+	}
+
+	return i2c_smbus_xfer(parent, c2a->alias, flags, read_write, command,
+			      size, data);
+}
+
+static u32 i2c_atr_functionality(struct i2c_adapter *adap)
+{
+	struct i2c_atr_chan *chan = adap->algo_data;
+	struct i2c_adapter *parent = chan->atr->parent;
+
+	return parent->algo->functionality(parent);
+}
+
+static void i2c_atr_lock_bus(struct i2c_adapter *adapter, unsigned int flags)
+{
+	struct i2c_atr_chan *chan = adapter->algo_data;
+	struct i2c_atr *atr = chan->atr;
+
+	mutex_lock(&atr->lock);
+}
+
+static int i2c_atr_trylock_bus(struct i2c_adapter *adapter, unsigned int flags)
+{
+	struct i2c_atr_chan *chan = adapter->algo_data;
+	struct i2c_atr *atr = chan->atr;
+
+	return mutex_trylock(&atr->lock);
+}
+
+static void i2c_atr_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)
+{
+	struct i2c_atr_chan *chan = adapter->algo_data;
+	struct i2c_atr *atr = chan->atr;
+
+	mutex_unlock(&atr->lock);
+}
+
+static const struct i2c_lock_operations i2c_atr_lock_ops = {
+	.lock_bus =    i2c_atr_lock_bus,
+	.trylock_bus = i2c_atr_trylock_bus,
+	.unlock_bus =  i2c_atr_unlock_bus,
+};
+
+static int i2c_atr_reserve_alias(struct i2c_atr *atr)
+{
+	unsigned long idx;
+
+	spin_lock(&atr->alias_mask_lock);
+
+	idx = find_first_zero_bit(atr->alias_use_mask, atr->num_aliases);
+	if (idx >= atr->num_aliases) {
+		spin_unlock(&atr->alias_mask_lock);
+		dev_err(atr->dev, "failed to find a free alias\n");
+		return -EBUSY;
+	}
+
+	set_bit(idx, atr->alias_use_mask);
+
+	spin_unlock(&atr->alias_mask_lock);
+
+	return atr->aliases[idx];
+}
+
+static void i2c_atr_release_alias(struct i2c_atr *atr, u16 alias)
+{
+	unsigned int idx;
+
+	spin_lock(&atr->alias_mask_lock);
+
+	for (idx = 0; idx < atr->num_aliases; ++idx) {
+		if (atr->aliases[idx] == alias) {
+			clear_bit(idx, atr->alias_use_mask);
+			spin_unlock(&atr->alias_mask_lock);
+			return;
+		}
+	}
+
+	spin_unlock(&atr->alias_mask_lock);
+
+	 /* This should never happen */
+	dev_warn(atr->dev, "Unable to find mapped alias\n");
+}
+
+static int i2c_atr_attach_client(struct i2c_adapter *adapter,
+				 const struct i2c_client *client)
+{
+	struct i2c_atr_chan *chan = adapter->algo_data;
+	struct i2c_atr *atr = chan->atr;
+	struct i2c_atr_alias_pair *c2a;
+	u16 alias;
+	int ret;
+
+	ret = i2c_atr_reserve_alias(atr);
+	if (ret < 0)
+		return ret;
+
+	alias = ret;
+
+	c2a = kzalloc(sizeof(*c2a), GFP_KERNEL);
+	if (!c2a) {
+		ret = -ENOMEM;
+		goto err_release_alias;
+	}
+
+	ret = atr->ops->attach_client(atr, chan->chan_id, client, alias);
+	if (ret)
+		goto err_free;
+
+	dev_dbg(atr->dev, "chan%u: client 0x%02x mapped at alias 0x%02x (%s)\n",
+		chan->chan_id, client->addr, alias, client->name);
+
+	c2a->client = client;
+	c2a->alias = alias;
+	list_add(&c2a->node, &chan->alias_list);
+
+	return 0;
+
+err_free:
+	kfree(c2a);
+err_release_alias:
+	i2c_atr_release_alias(atr, alias);
+
+	return ret;
+}
+
+static void i2c_atr_detach_client(struct i2c_adapter *adapter,
+				  const struct i2c_client *client)
+{
+	struct i2c_atr_chan *chan = adapter->algo_data;
+	struct i2c_atr *atr = chan->atr;
+	struct i2c_atr_alias_pair *c2a;
+
+	atr->ops->detach_client(atr, chan->chan_id, client);
+
+	c2a = i2c_atr_find_mapping_by_client(&chan->alias_list, client);
+	if (!c2a) {
+		 /* This should never happen */
+		dev_warn(atr->dev, "Unable to find address mapping\n");
+		return;
+	}
+
+	i2c_atr_release_alias(atr, c2a->alias);
+
+	dev_dbg(atr->dev,
+		"chan%u: client 0x%02x unmapped from alias 0x%02x (%s)\n",
+		chan->chan_id, client->addr, c2a->alias, client->name);
+
+	list_del(&c2a->node);
+	kfree(c2a);
+}
+
+static int i2c_atr_bus_notifier_call(struct notifier_block *nb,
+				     unsigned long event, void *device)
+{
+	struct i2c_atr *atr = container_of(nb, struct i2c_atr, i2c_nb);
+	struct device *dev = device;
+	struct i2c_client *client;
+	u32 chan_id;
+	int ret;
+
+	client = i2c_verify_client(dev);
+	if (!client)
+		return NOTIFY_DONE;
+
+	/* Is the client in one of our adapters? */
+	for (chan_id = 0; chan_id < atr->max_adapters; ++chan_id) {
+		if (client->adapter == atr->adapter[chan_id])
+			break;
+	}
+
+	if (chan_id == atr->max_adapters)
+		return NOTIFY_DONE;
+
+	switch (event) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		ret = i2c_atr_attach_client(client->adapter, client);
+		if (ret)
+			dev_err(atr->dev,
+				"Failed to attach remote client '%s': %d\n",
+				dev_name(dev), ret);
+		break;
+
+	case BUS_NOTIFY_DEL_DEVICE:
+		i2c_atr_detach_client(client->adapter, client);
+		break;
+
+	default:
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int i2c_atr_parse_alias_pool(struct i2c_atr *atr)
+{
+	struct device *dev = atr->dev;
+	unsigned long *alias_use_mask;
+	size_t num_aliases;
+	unsigned int i;
+	u32 *aliases32;
+	u16 *aliases16;
+	int ret;
+
+	ret = fwnode_property_count_u32(dev_fwnode(dev), "i2c-alias-pool");
+	if (ret < 0) {
+		dev_err(dev, "Failed to count 'i2c-alias-pool' property: %d\n",
+			ret);
+		return ret;
+	}
+
+	num_aliases = ret;
+
+	if (!num_aliases)
+		return 0;
+
+	aliases32 = kcalloc(num_aliases, sizeof(*aliases32), GFP_KERNEL);
+	if (!aliases32)
+		return -ENOMEM;
+
+	ret = fwnode_property_read_u32_array(dev_fwnode(dev), "i2c-alias-pool",
+					     aliases32, num_aliases);
+	if (ret < 0) {
+		dev_err(dev, "Failed to read 'i2c-alias-pool' property: %d\n",
+			ret);
+		goto err_free_aliases32;
+	}
+
+	aliases16 = kcalloc(num_aliases, sizeof(*aliases16), GFP_KERNEL);
+	if (!aliases16) {
+		ret = -ENOMEM;
+		goto err_free_aliases32;
+	}
+
+	for (i = 0; i < num_aliases; i++) {
+		if (!(aliases32[i] & 0xffff0000)) {
+			aliases16[i] = aliases32[i];
+			continue;
+		}
+
+		dev_err(dev, "Failed to parse 'i2c-alias-pool' property: I2C flags are not supported\n");
+		ret = -EINVAL;
+		goto err_free_aliases16;
+	}
+
+	alias_use_mask = bitmap_zalloc(num_aliases, GFP_KERNEL);
+	if (!alias_use_mask) {
+		ret = -ENOMEM;
+		goto err_free_aliases16;
+	}
+
+	kfree(aliases32);
+
+	atr->num_aliases = num_aliases;
+	atr->aliases = aliases16;
+	atr->alias_use_mask = alias_use_mask;
+
+	dev_dbg(dev, "i2c-alias-pool has %zu aliases", atr->num_aliases);
+
+	return 0;
+
+err_free_aliases16:
+	kfree(aliases16);
+err_free_aliases32:
+	kfree(aliases32);
+	return ret;
+}
+
+struct i2c_atr *i2c_atr_new(struct i2c_adapter *parent, struct device *dev,
+			    const struct i2c_atr_ops *ops, int max_adapters)
+{
+	struct i2c_atr *atr;
+	int ret;
+
+	if (max_adapters > ATR_MAX_ADAPTERS)
+		return ERR_PTR(-EINVAL);
+
+	if (!ops || !ops->attach_client || !ops->detach_client)
+		return ERR_PTR(-EINVAL);
+
+	atr = kzalloc(struct_size(atr, adapter, max_adapters), GFP_KERNEL);
+	if (!atr)
+		return ERR_PTR(-ENOMEM);
+
+	mutex_init(&atr->lock);
+	spin_lock_init(&atr->alias_mask_lock);
+
+	atr->parent = parent;
+	atr->dev = dev;
+	atr->ops = ops;
+	atr->max_adapters = max_adapters;
+
+	if (parent->algo->master_xfer)
+		atr->algo.master_xfer = i2c_atr_master_xfer;
+	if (parent->algo->smbus_xfer)
+		atr->algo.smbus_xfer = i2c_atr_smbus_xfer;
+	atr->algo.functionality = i2c_atr_functionality;
+
+	ret = i2c_atr_parse_alias_pool(atr);
+	if (ret)
+		goto err_destroy_mutex;
+
+	atr->i2c_nb.notifier_call = i2c_atr_bus_notifier_call;
+	ret = bus_register_notifier(&i2c_bus_type, &atr->i2c_nb);
+	if (ret)
+		goto err_free_aliases;
+
+	return atr;
+
+err_free_aliases:
+	bitmap_free(atr->alias_use_mask);
+	kfree(atr->aliases);
+err_destroy_mutex:
+	mutex_destroy(&atr->lock);
+	kfree(atr);
+
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_NS_GPL(i2c_atr_new, I2C_ATR);
+
+void i2c_atr_delete(struct i2c_atr *atr)
+{
+	unsigned int i;
+
+	for (i = 0; i < atr->max_adapters; ++i)
+		WARN_ON(atr->adapter[i]);
+
+	bus_unregister_notifier(&i2c_bus_type, &atr->i2c_nb);
+	bitmap_free(atr->alias_use_mask);
+	kfree(atr->aliases);
+	mutex_destroy(&atr->lock);
+	kfree(atr);
+}
+EXPORT_SYMBOL_NS_GPL(i2c_atr_delete, I2C_ATR);
+
+int i2c_atr_add_adapter(struct i2c_atr *atr, u32 chan_id,
+			struct device *adapter_parent,
+			struct fwnode_handle *bus_handle)
+{
+	struct i2c_adapter *parent = atr->parent;
+	struct device *dev = atr->dev;
+	struct i2c_atr_chan *chan;
+	char symlink_name[ATR_MAX_SYMLINK_LEN];
+	int ret;
+
+	if (chan_id >= atr->max_adapters) {
+		dev_err(dev, "No room for more i2c-atr adapters\n");
+		return -EINVAL;
+	}
+
+	if (atr->adapter[chan_id]) {
+		dev_err(dev, "Adapter %d already present\n", chan_id);
+		return -EEXIST;
+	}
+
+	chan = kzalloc(sizeof(*chan), GFP_KERNEL);
+	if (!chan)
+		return -ENOMEM;
+
+	if (!adapter_parent)
+		adapter_parent = dev;
+
+	chan->atr = atr;
+	chan->chan_id = chan_id;
+	INIT_LIST_HEAD(&chan->alias_list);
+	mutex_init(&chan->orig_addrs_lock);
+
+	snprintf(chan->adap.name, sizeof(chan->adap.name), "i2c-%d-atr-%d",
+		 i2c_adapter_id(parent), chan_id);
+	chan->adap.owner = THIS_MODULE;
+	chan->adap.algo = &atr->algo;
+	chan->adap.algo_data = chan;
+	chan->adap.dev.parent = adapter_parent;
+	chan->adap.retries = parent->retries;
+	chan->adap.timeout = parent->timeout;
+	chan->adap.quirks = parent->quirks;
+	chan->adap.lock_ops = &i2c_atr_lock_ops;
+
+	if (bus_handle) {
+		device_set_node(&chan->adap.dev, fwnode_handle_get(bus_handle));
+	} else {
+		struct fwnode_handle *atr_node;
+		struct fwnode_handle *child;
+		u32 reg;
+
+		atr_node = device_get_named_child_node(dev, "i2c-atr");
+
+		fwnode_for_each_child_node(atr_node, child) {
+			ret = fwnode_property_read_u32(child, "reg", &reg);
+			if (ret)
+				continue;
+			if (chan_id == reg)
+				break;
+		}
+
+		device_set_node(&chan->adap.dev, child);
+		fwnode_handle_put(atr_node);
+	}
+
+	atr->adapter[chan_id] = &chan->adap;
+
+	ret = i2c_add_adapter(&chan->adap);
+	if (ret) {
+		dev_err(dev, "failed to add atr-adapter %u (error=%d)\n",
+			chan_id, ret);
+		goto err_fwnode_put;
+	}
+
+	snprintf(symlink_name, sizeof(symlink_name), "channel-%u",
+		 chan->chan_id);
+
+	ret = sysfs_create_link(&chan->adap.dev.kobj, &dev->kobj, "atr_device");
+	if (ret)
+		dev_warn(dev, "can't create symlink to atr device\n");
+	ret = sysfs_create_link(&dev->kobj, &chan->adap.dev.kobj, symlink_name);
+	if (ret)
+		dev_warn(dev, "can't create symlink for channel %u\n", chan_id);
+
+	dev_dbg(dev, "Added ATR child bus %d\n", i2c_adapter_id(&chan->adap));
+
+	return 0;
+
+err_fwnode_put:
+	fwnode_handle_put(dev_fwnode(&chan->adap.dev));
+	mutex_destroy(&chan->orig_addrs_lock);
+	kfree(chan);
+	return ret;
+}
+EXPORT_SYMBOL_NS_GPL(i2c_atr_add_adapter, I2C_ATR);
+
+void i2c_atr_del_adapter(struct i2c_atr *atr, u32 chan_id)
+{
+	char symlink_name[ATR_MAX_SYMLINK_LEN];
+	struct i2c_adapter *adap;
+	struct i2c_atr_chan *chan;
+	struct fwnode_handle *fwnode;
+	struct device *dev = atr->dev;
+
+	adap = atr->adapter[chan_id];
+	if (!adap)
+		return;
+
+	chan = adap->algo_data;
+	fwnode = dev_fwnode(&adap->dev);
+
+	dev_dbg(dev, "Removing ATR child bus %d\n", i2c_adapter_id(adap));
+
+	snprintf(symlink_name, sizeof(symlink_name), "channel-%u",
+		 chan->chan_id);
+	sysfs_remove_link(&dev->kobj, symlink_name);
+	sysfs_remove_link(&chan->adap.dev.kobj, "atr_device");
+
+	i2c_del_adapter(adap);
+
+	atr->adapter[chan_id] = NULL;
+
+	fwnode_handle_put(fwnode);
+	mutex_destroy(&chan->orig_addrs_lock);
+	kfree(chan->orig_addrs);
+	kfree(chan);
+}
+EXPORT_SYMBOL_NS_GPL(i2c_atr_del_adapter, I2C_ATR);
+
+void i2c_atr_set_driver_data(struct i2c_atr *atr, void *data)
+{
+	atr->priv = data;
+}
+EXPORT_SYMBOL_NS_GPL(i2c_atr_set_driver_data, I2C_ATR);
+
+void *i2c_atr_get_driver_data(struct i2c_atr *atr)
+{
+	return atr->priv;
+}
+EXPORT_SYMBOL_NS_GPL(i2c_atr_get_driver_data, I2C_ATR);
+
+MODULE_AUTHOR("Luca Ceresoli <luca.ceresoli@bootlin.com>");
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>");
+MODULE_DESCRIPTION("I2C Address Translator");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
--- a/drivers/i2c/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/i2c/Kconfig	2024-01-28 14:01:31.244353788 -0500
@@ -71,6 +71,15 @@
 
 source "drivers/i2c/muxes/Kconfig"
 
+config I2C_ATR
+	tristate "I2C Address Translator (ATR) support"
+	help
+	  Enable support for I2C Address Translator (ATR) chips.
+
+	  An ATR allows accessing multiple I2C busses from a single
+	  physical bus via address translation instead of bus selection as
+	  i2c-muxes do.
+
 config I2C_HELPER_AUTO
 	bool "Autoselect pertinent helper modules"
 	default y
diff -Naur --no-dereference a/drivers/i2c/Makefile b/drivers/i2c/Makefile
--- a/drivers/i2c/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/i2c/Makefile	2024-01-28 14:01:31.244353788 -0500
@@ -13,6 +13,7 @@
 obj-$(CONFIG_I2C_SMBUS)		+= i2c-smbus.o
 obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o
 obj-$(CONFIG_I2C_MUX)		+= i2c-mux.o
+obj-$(CONFIG_I2C_ATR)		+= i2c-atr.o
 obj-y				+= algos/ busses/ muxes/
 obj-$(CONFIG_I2C_STUB)		+= i2c-stub.o
 obj-$(CONFIG_I2C_SLAVE_EEPROM)	+= i2c-slave-eeprom.o
diff -Naur --no-dereference a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
--- a/drivers/iio/adc/ti_am335x_adc.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/iio/adc/ti_am335x_adc.c	2024-01-28 14:01:31.244353788 -0500
@@ -671,8 +671,10 @@
 	platform_set_drvdata(pdev, indio_dev);
 
 	err = tiadc_request_dma(pdev, adc_dev);
-	if (err && err == -EPROBE_DEFER)
+	if (err && err != -ENODEV) {
+		dev_err_probe(&pdev->dev, err, "DMA request failed\n");
 		goto err_dma;
+	}
 
 	return 0;
 
diff -Naur --no-dereference a/drivers/iio/buffer/industrialio-triggered-buffer.c b/drivers/iio/buffer/industrialio-triggered-buffer.c
--- a/drivers/iio/buffer/industrialio-triggered-buffer.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/iio/buffer/industrialio-triggered-buffer.c	2024-01-28 14:01:31.244353788 -0500
@@ -46,6 +46,16 @@
 	struct iio_buffer *buffer;
 	int ret;
 
+	/*
+	 * iio_triggered_buffer_cleanup() assumes that the buffer allocated here
+	 * is assigned to indio_dev->buffer but this is only the case if this
+	 * function is the first caller to iio_device_attach_buffer(). If
+	 * indio_dev->buffer is already set then we can't proceed otherwise the
+	 * cleanup function will try to free a buffer that was not allocated here.
+	 */
+	if (indio_dev->buffer)
+		return -EADDRINUSE;
+
 	buffer = iio_kfifo_allocate();
 	if (!buffer) {
 		ret = -ENOMEM;
diff -Naur --no-dereference a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
--- a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c	2024-01-28 14:01:31.244353788 -0500
@@ -15,8 +15,8 @@
 /* Conversion times in us */
 static const u16 ms_sensors_ht_t_conversion_time[] = { 50000, 25000,
 						       13000, 7000 };
-static const u16 ms_sensors_ht_h_conversion_time[] = { 16000, 3000,
-						       5000, 8000 };
+static const u16 ms_sensors_ht_h_conversion_time[] = { 16000, 5000,
+						       3000, 8000 };
 static const u16 ms_sensors_tp_conversion_time[] = { 500, 1100, 2100,
 						     4100, 8220, 16440 };
 
diff -Naur --no-dereference a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
--- a/drivers/iio/imu/adis16475.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/iio/imu/adis16475.c	2024-01-28 14:01:31.244353788 -0500
@@ -1243,50 +1243,6 @@
 	return 0;
 }
 
-static const struct of_device_id adis16475_of_match[] = {
-	{ .compatible = "adi,adis16470",
-		.data = &adis16475_chip_info[ADIS16470] },
-	{ .compatible = "adi,adis16475-1",
-		.data = &adis16475_chip_info[ADIS16475_1] },
-	{ .compatible = "adi,adis16475-2",
-		.data = &adis16475_chip_info[ADIS16475_2] },
-	{ .compatible = "adi,adis16475-3",
-		.data = &adis16475_chip_info[ADIS16475_3] },
-	{ .compatible = "adi,adis16477-1",
-		.data = &adis16475_chip_info[ADIS16477_1] },
-	{ .compatible = "adi,adis16477-2",
-		.data = &adis16475_chip_info[ADIS16477_2] },
-	{ .compatible = "adi,adis16477-3",
-		.data = &adis16475_chip_info[ADIS16477_3] },
-	{ .compatible = "adi,adis16465-1",
-		.data = &adis16475_chip_info[ADIS16465_1] },
-	{ .compatible = "adi,adis16465-2",
-		.data = &adis16475_chip_info[ADIS16465_2] },
-	{ .compatible = "adi,adis16465-3",
-		.data = &adis16475_chip_info[ADIS16465_3] },
-	{ .compatible = "adi,adis16467-1",
-		.data = &adis16475_chip_info[ADIS16467_1] },
-	{ .compatible = "adi,adis16467-2",
-		.data = &adis16475_chip_info[ADIS16467_2] },
-	{ .compatible = "adi,adis16467-3",
-		.data = &adis16475_chip_info[ADIS16467_3] },
-	{ .compatible = "adi,adis16500",
-		.data = &adis16475_chip_info[ADIS16500] },
-	{ .compatible = "adi,adis16505-1",
-		.data = &adis16475_chip_info[ADIS16505_1] },
-	{ .compatible = "adi,adis16505-2",
-		.data = &adis16475_chip_info[ADIS16505_2] },
-	{ .compatible = "adi,adis16505-3",
-		.data = &adis16475_chip_info[ADIS16505_3] },
-	{ .compatible = "adi,adis16507-1",
-		.data = &adis16475_chip_info[ADIS16507_1] },
-	{ .compatible = "adi,adis16507-2",
-		.data = &adis16475_chip_info[ADIS16507_2] },
-	{ .compatible = "adi,adis16507-3",
-		.data = &adis16475_chip_info[ADIS16507_3] },
-	{ },
-};
-MODULE_DEVICE_TABLE(of, adis16475_of_match);
 
 static int adis16475_probe(struct spi_device *spi)
 {
@@ -1300,7 +1256,7 @@
 
 	st = iio_priv(indio_dev);
 
-	st->info = device_get_match_data(&spi->dev);
+	st->info = spi_get_device_match_data(spi);
 	if (!st->info)
 		return -EINVAL;
 
@@ -1340,12 +1296,83 @@
 	return 0;
 }
 
+static const struct of_device_id adis16475_of_match[] = {
+	{ .compatible = "adi,adis16470",
+		.data = &adis16475_chip_info[ADIS16470] },
+	{ .compatible = "adi,adis16475-1",
+		.data = &adis16475_chip_info[ADIS16475_1] },
+	{ .compatible = "adi,adis16475-2",
+		.data = &adis16475_chip_info[ADIS16475_2] },
+	{ .compatible = "adi,adis16475-3",
+		.data = &adis16475_chip_info[ADIS16475_3] },
+	{ .compatible = "adi,adis16477-1",
+		.data = &adis16475_chip_info[ADIS16477_1] },
+	{ .compatible = "adi,adis16477-2",
+		.data = &adis16475_chip_info[ADIS16477_2] },
+	{ .compatible = "adi,adis16477-3",
+		.data = &adis16475_chip_info[ADIS16477_3] },
+	{ .compatible = "adi,adis16465-1",
+		.data = &adis16475_chip_info[ADIS16465_1] },
+	{ .compatible = "adi,adis16465-2",
+		.data = &adis16475_chip_info[ADIS16465_2] },
+	{ .compatible = "adi,adis16465-3",
+		.data = &adis16475_chip_info[ADIS16465_3] },
+	{ .compatible = "adi,adis16467-1",
+		.data = &adis16475_chip_info[ADIS16467_1] },
+	{ .compatible = "adi,adis16467-2",
+		.data = &adis16475_chip_info[ADIS16467_2] },
+	{ .compatible = "adi,adis16467-3",
+		.data = &adis16475_chip_info[ADIS16467_3] },
+	{ .compatible = "adi,adis16500",
+		.data = &adis16475_chip_info[ADIS16500] },
+	{ .compatible = "adi,adis16505-1",
+		.data = &adis16475_chip_info[ADIS16505_1] },
+	{ .compatible = "adi,adis16505-2",
+		.data = &adis16475_chip_info[ADIS16505_2] },
+	{ .compatible = "adi,adis16505-3",
+		.data = &adis16475_chip_info[ADIS16505_3] },
+	{ .compatible = "adi,adis16507-1",
+		.data = &adis16475_chip_info[ADIS16507_1] },
+	{ .compatible = "adi,adis16507-2",
+		.data = &adis16475_chip_info[ADIS16507_2] },
+	{ .compatible = "adi,adis16507-3",
+		.data = &adis16475_chip_info[ADIS16507_3] },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, adis16475_of_match);
+
+static const struct spi_device_id adis16475_ids[] = {
+	{ "adis16470", (kernel_ulong_t)&adis16475_chip_info[ADIS16470] },
+	{ "adis16475-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16475_1] },
+	{ "adis16475-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16475_2] },
+	{ "adis16475-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16475_3] },
+	{ "adis16477-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16477_1] },
+	{ "adis16477-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16477_2] },
+	{ "adis16477-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16477_3] },
+	{ "adis16465-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16465_1] },
+	{ "adis16465-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16465_2] },
+	{ "adis16465-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16465_3] },
+	{ "adis16467-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_1] },
+	{ "adis16467-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_2] },
+	{ "adis16467-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16467_3] },
+	{ "adis16500", (kernel_ulong_t)&adis16475_chip_info[ADIS16500] },
+	{ "adis16505-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_1] },
+	{ "adis16505-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_2] },
+	{ "adis16505-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16505_3] },
+	{ "adis16507-1", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_1] },
+	{ "adis16507-2", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_2] },
+	{ "adis16507-3", (kernel_ulong_t)&adis16475_chip_info[ADIS16507_3] },
+	{ }
+};
+MODULE_DEVICE_TABLE(spi, adis16475_ids);
+
 static struct spi_driver adis16475_driver = {
 	.driver = {
 		.name = "adis16475",
 		.of_match_table = adis16475_of_match,
 	},
 	.probe = adis16475_probe,
+	.id_table = adis16475_ids,
 };
 module_spi_driver(adis16475_driver);
 
diff -Naur --no-dereference a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c	2024-01-28 14:01:31.244353788 -0500
@@ -736,13 +736,13 @@
 			ret = inv_mpu6050_sensor_show(st, st->reg->gyro_offset,
 						chan->channel2, val);
 			mutex_unlock(&st->lock);
-			return IIO_VAL_INT;
+			return ret;
 		case IIO_ACCEL:
 			mutex_lock(&st->lock);
 			ret = inv_mpu6050_sensor_show(st, st->reg->accl_offset,
 						chan->channel2, val);
 			mutex_unlock(&st->lock);
-			return IIO_VAL_INT;
+			return ret;
 
 		default:
 			return -EINVAL;
diff -Naur --no-dereference a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
--- a/drivers/input/keyboard/gpio_keys.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/input/keyboard/gpio_keys.c	2024-01-28 14:01:31.244353788 -0500
@@ -45,7 +45,9 @@
 	unsigned int software_debounce;	/* in msecs, for GPIO-driven buttons */
 
 	unsigned int irq;
+	unsigned int wakeirq;
 	unsigned int wakeup_trigger_type;
+
 	spinlock_t lock;
 	bool disabled;
 	bool key_pressed;
@@ -511,6 +513,7 @@
 	struct gpio_button_data *bdata = &ddata->data[idx];
 	irq_handler_t isr;
 	unsigned long irqflags;
+	const char *wakedesc;
 	int irq;
 	int error;
 
@@ -578,6 +581,14 @@
 					!gpiod_cansleep(bdata->gpiod);
 		}
 
+		/*
+		 * If an interrupt was specified, use it instead of the gpio
+		 * interrupt and use the gpio for reading the state. A separate
+		 * interrupt may be used as the main button interrupt for
+		 * runtime PM to detect events also in deeper idle states. If a
+		 * dedicated wakeirq is used for system suspend only, see below
+		 * for bdata->wakeirq setup.
+		 */
 		if (button->irq) {
 			bdata->irq = button->irq;
 		} else {
@@ -675,6 +686,36 @@
 		return error;
 	}
 
+	if (!button->wakeirq)
+		return 0;
+
+	/* Use :wakeup suffix like drivers/base/power/wakeirq.c does */
+	wakedesc = devm_kasprintf(dev, GFP_KERNEL, "%s:wakeup", desc);
+	if (!wakedesc)
+		return -ENOMEM;
+
+	bdata->wakeirq = button->wakeirq;
+	irqflags |= IRQF_NO_SUSPEND;
+
+	/*
+	 * Wakeirq shares the handler with the main interrupt, it's only
+	 * active during system suspend. See gpio_keys_button_enable_wakeup()
+	 * and gpio_keys_button_disable_wakeup().
+	 */
+	error = devm_request_any_context_irq(dev, bdata->wakeirq, isr,
+					     irqflags, wakedesc, bdata);
+	if (error < 0) {
+		dev_err(dev, "Unable to claim wakeirq %d; error %d\n",
+			bdata->irq, error);
+		return error;
+	}
+
+	/*
+	 * Disable wakeirq until suspend. IRQF_NO_AUTOEN won't work if
+	 * IRQF_SHARED was set based on !button->can_disable.
+	 */
+	disable_irq_nosync(bdata->wakeirq);
+
 	return 0;
 }
 
@@ -731,7 +772,7 @@
 	struct gpio_keys_platform_data *pdata;
 	struct gpio_keys_button *button;
 	struct fwnode_handle *child;
-	int nbuttons;
+	int nbuttons, irq;
 
 	nbuttons = device_get_child_node_count(dev);
 	if (nbuttons == 0)
@@ -753,9 +794,19 @@
 	device_property_read_string(dev, "label", &pdata->name);
 
 	device_for_each_child_node(dev, child) {
-		if (is_of_node(child))
-			button->irq =
-				irq_of_parse_and_map(to_of_node(child), 0);
+		if (is_of_node(child)) {
+			irq = of_irq_get_byname(to_of_node(child), "irq");
+			if (irq > 0)
+				button->irq = irq;
+
+			irq = of_irq_get_byname(to_of_node(child), "wakeup");
+			if (irq > 0)
+				button->wakeirq = irq;
+
+			if (!button->irq && !button->wakeirq)
+				button->irq =
+					irq_of_parse_and_map(to_of_node(child), 0);
+		}
 
 		if (fwnode_property_read_u32(child, "linux,code",
 					     &button->code)) {
@@ -921,6 +972,11 @@
 		}
 	}
 
+	if (bdata->wakeirq) {
+		enable_irq(bdata->wakeirq);
+		disable_irq_nosync(bdata->irq);
+	}
+
 	return 0;
 }
 
@@ -929,6 +985,11 @@
 {
 	int error;
 
+	if (bdata->wakeirq) {
+		enable_irq(bdata->irq);
+		disable_irq_nosync(bdata->wakeirq);
+	}
+
 	/*
 	 * The trigger type is always both edges for gpio-based keys and we do
 	 * not support changing wakeup trigger for interrupt-based keys.
diff -Naur --no-dereference a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
--- a/drivers/input/misc/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/input/misc/Kconfig	2024-01-28 14:01:31.244353788 -0500
@@ -468,6 +468,16 @@
 	  To compile this driver as a module, choose M here. The module will
 	  be called tps65218-pwrbutton.
 
+config INPUT_TPS65219_PWRBUTTON
+	tristate "TPS65219 Power button driver"
+	depends on MFD_TPS65219
+	help
+	  Say Y here if you want to enable power button reporting for
+	  TPS65219 Power Management IC devices.
+
+	  To compile this driver as a module, choose M here. The module will
+	  be called tps65219-pwrbutton.
+
 config INPUT_AXP20X_PEK
 	tristate "X-Powers AXP20X power button driver"
 	depends on MFD_AXP20X
diff -Naur --no-dereference a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
--- a/drivers/input/misc/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/input/misc/Makefile	2024-01-28 14:01:31.244353788 -0500
@@ -80,6 +80,7 @@
 obj-$(CONFIG_INPUT_SPARCSPKR)		+= sparcspkr.o
 obj-$(CONFIG_INPUT_STPMIC1_ONKEY)  	+= stpmic1_onkey.o
 obj-$(CONFIG_INPUT_TPS65218_PWRBUTTON)	+= tps65218-pwrbutton.o
+obj-$(CONFIG_INPUT_TPS65219_PWRBUTTON)	+= tps65219-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON)	+= twl4030-pwrbutton.o
 obj-$(CONFIG_INPUT_TWL4030_VIBRA)	+= twl4030-vibra.o
 obj-$(CONFIG_INPUT_TWL6040_VIBRA)	+= twl6040-vibra.o
diff -Naur --no-dereference a/drivers/input/misc/tps65219-pwrbutton.c b/drivers/input/misc/tps65219-pwrbutton.c
--- a/drivers/input/misc/tps65219-pwrbutton.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/input/misc/tps65219-pwrbutton.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Driver for TPS65219 Push Button
+//
+// Copyright (C) 2022 BayLibre Incorporated - https://www.baylibre.com/
+
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/tps65219.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+struct tps65219_pwrbutton {
+	struct device *dev;
+	struct input_dev *idev;
+	char phys[32];
+};
+
+static irqreturn_t tps65219_pb_push_irq(int irq, void *_pwr)
+{
+	struct tps65219_pwrbutton *pwr = _pwr;
+
+	input_report_key(pwr->idev, KEY_POWER, 1);
+	pm_wakeup_event(pwr->dev, 0);
+	input_sync(pwr->idev);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t tps65219_pb_release_irq(int irq, void *_pwr)
+{
+	struct tps65219_pwrbutton *pwr = _pwr;
+
+	input_report_key(pwr->idev, KEY_POWER, 0);
+	input_sync(pwr->idev);
+
+	return IRQ_HANDLED;
+}
+
+static int tps65219_pb_probe(struct platform_device *pdev)
+{
+	struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent);
+	struct device *dev = &pdev->dev;
+	struct tps65219_pwrbutton *pwr;
+	struct input_dev *idev;
+	int error;
+	int push_irq;
+	int release_irq;
+
+	pwr = devm_kzalloc(dev, sizeof(*pwr), GFP_KERNEL);
+	if (!pwr)
+		return -ENOMEM;
+
+	idev = devm_input_allocate_device(dev);
+	if (!idev)
+		return -ENOMEM;
+
+	idev->name = pdev->name;
+	snprintf(pwr->phys, sizeof(pwr->phys), "%s/input0",
+		 pdev->name);
+	idev->phys = pwr->phys;
+	idev->id.bustype = BUS_I2C;
+
+	input_set_capability(idev, EV_KEY, KEY_POWER);
+
+	pwr->dev = dev;
+	pwr->idev = idev;
+	device_init_wakeup(dev, true);
+
+	push_irq = platform_get_irq(pdev, 0);
+	if (push_irq < 0)
+		return -EINVAL;
+
+	release_irq = platform_get_irq(pdev, 1);
+	if (release_irq < 0)
+		return -EINVAL;
+
+	error = devm_request_threaded_irq(dev, push_irq, NULL,
+					  tps65219_pb_push_irq,
+					  IRQF_ONESHOT,
+					  dev->init_name, pwr);
+	if (error) {
+		dev_err(dev, "failed to request push IRQ #%d: %d\n", push_irq,
+			error);
+		return error;
+	}
+
+	error = devm_request_threaded_irq(dev, release_irq, NULL,
+					  tps65219_pb_release_irq,
+					  IRQF_ONESHOT,
+					  dev->init_name, pwr);
+	if (error) {
+		dev_err(dev, "failed to request release IRQ #%d: %d\n",
+			release_irq, error);
+		return error;
+	}
+
+	error = input_register_device(idev);
+	if (error) {
+		dev_err(dev, "Can't register power button: %d\n", error);
+		return error;
+	}
+
+	/* Enable interrupts for the pushbutton */
+	regmap_clear_bits(tps->regmap, TPS65219_REG_MASK_CONFIG,
+			  TPS65219_REG_MASK_INT_FOR_PB_MASK);
+
+	/* Set PB/EN/VSENSE pin to be a pushbutton */
+	regmap_update_bits(tps->regmap, TPS65219_REG_MFP_2_CONFIG,
+			   TPS65219_MFP_2_EN_PB_VSENSE_MASK, TPS65219_MFP_2_PB);
+
+	return 0;
+}
+
+static int tps65219_pb_remove(struct platform_device *pdev)
+{
+	struct tps65219 *tps = dev_get_drvdata(pdev->dev.parent);
+
+	/* Disable interrupt for the pushbutton */
+	return regmap_update_bits(tps->regmap, TPS65219_REG_MASK_CONFIG,
+				  TPS65219_REG_MASK_INT_FOR_PB_MASK,
+				  TPS65219_REG_MASK_INT_FOR_PB_MASK);
+}
+
+static const struct platform_device_id tps65219_pwrbtn_id_table[] = {
+	{ "tps65219-pwrbutton", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, tps65219_pwrbtn_id_table);
+
+static struct platform_driver tps65219_pb_driver = {
+	.probe = tps65219_pb_probe,
+	.remove = tps65219_pb_remove,
+	.driver = {
+		.name = "tps65219_pwrbutton",
+	},
+	.id_table = tps65219_pwrbtn_id_table,
+};
+module_platform_driver(tps65219_pb_driver);
+
+MODULE_DESCRIPTION("TPS65219 Power Button");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Markus Schneider-Pargmann <msp@baylibre.com");
diff -Naur --no-dereference a/drivers/input/touchscreen/ar1021_i2c.c b/drivers/input/touchscreen/ar1021_i2c.c
--- a/drivers/input/touchscreen/ar1021_i2c.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/input/touchscreen/ar1021_i2c.c	2024-01-28 14:01:31.244353788 -0500
@@ -17,6 +17,7 @@
 
 #define AR1021_MAX_X	4095
 #define AR1021_MAX_Y	4095
+#define AR1021_MAX_PRESSURE 255
 
 #define AR1021_CMD	0x55
 
@@ -26,8 +27,29 @@
 	struct i2c_client *client;
 	struct input_dev *input;
 	u8 data[AR1021_TOUCH_PKG_SIZE];
+	bool invert_x;
+	bool invert_y;
+	bool swap_xy;
 };
 
+static bool ar1021_get_prop_u32(struct device *dev,
+				     const char *property,
+				     unsigned int default_value,
+				     unsigned int *value)
+{
+	u32 val;
+	int error;
+
+	error = device_property_read_u32(dev, property, &val);
+	if (error) {
+		*value = default_value;
+		return false;
+	}
+
+	*value = val;
+	return true;
+}
+
 static irqreturn_t ar1021_i2c_irq(int irq, void *dev_id)
 {
 	struct ar1021_i2c *ar1021 = dev_id;
@@ -49,9 +71,22 @@
 	x = ((data[2] & 0x1f) << 7) | (data[1] & 0x7f);
 	y = ((data[4] & 0x1f) << 7) | (data[3] & 0x7f);
 
-	input_report_abs(input, ABS_X, x);
-	input_report_abs(input, ABS_Y, y);
+	if (ar1021->invert_x)
+		x = AR1021_MAX_X - x;
+
+	if (ar1021->invert_y)
+		y = AR1021_MAX_Y - y;
+
+	if (ar1021->swap_xy) {
+		input_report_abs(input, ABS_X, y);
+		input_report_abs(input, ABS_Y, x);
+	} else {
+		input_report_abs(input, ABS_X, x);
+		input_report_abs(input, ABS_Y, y);
+	}
+
 	input_report_key(input, BTN_TOUCH, button);
+	input_report_abs(input, ABS_PRESSURE, AR1021_MAX_PRESSURE);
 	input_sync(input);
 
 out:
@@ -93,6 +128,8 @@
 	struct ar1021_i2c *ar1021;
 	struct input_dev *input;
 	int error;
+	unsigned int offset_x, offset_y;
+	bool data_present;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		dev_err(&client->dev, "i2c_check_functionality error\n");
@@ -116,10 +153,44 @@
 	input->open = ar1021_i2c_open;
 	input->close = ar1021_i2c_close;
 
+	ar1021->invert_x = device_property_read_bool(&client->dev, "touchscreen-inverted-x");
+	ar1021->invert_y = device_property_read_bool(&client->dev, "touchscreen-inverted-y");
+	ar1021->swap_xy = device_property_read_bool(&client->dev, "touchscreen-swapped-x-y");
+
+	data_present = ar1021_get_prop_u32(&client->dev,
+						"touchscreen-offset-x",
+						0,
+						&offset_x);
+
+	if (data_present)
+		dev_info(&client->dev, "touchscreen-offset-x: %d\n", offset_x);
+
+	data_present = ar1021_get_prop_u32(&client->dev,
+						"touchscreen-offset-y",
+						0,
+						&offset_y);
+
+	if (data_present)
+		dev_info(&client->dev, "touchscreen-offset-y: %d\n", offset_y);
+
 	__set_bit(INPUT_PROP_DIRECT, input->propbit);
-	input_set_capability(input, EV_KEY, BTN_TOUCH);
-	input_set_abs_params(input, ABS_X, 0, AR1021_MAX_X, 0, 0);
-	input_set_abs_params(input, ABS_Y, 0, AR1021_MAX_Y, 0, 0);
+	//input_set_capability(input, EV_KEY, BTN_TOUCH);
+
+	input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	if(ar1021->swap_xy)
+	{
+		input_set_abs_params(input, ABS_X, 0, AR1021_MAX_Y, 0, 0);
+		input_set_abs_params(input, ABS_Y, 0, AR1021_MAX_X, 0, 0);
+	}
+	else
+	{
+		input_set_abs_params(input, ABS_X, offset_x, AR1021_MAX_X-offset_x, 0, 0);
+		input_set_abs_params(input, ABS_Y, offset_y, AR1021_MAX_Y-offset_y, 0, 0);
+	}
+
+	input_set_abs_params(input, ABS_PRESSURE, 0, AR1021_MAX_PRESSURE, 0, 0);
 
 	input_set_drvdata(input, ar1021);
 
diff -Naur --no-dereference a/drivers/input/touchscreen/edt-ft5x06.c b/drivers/input/touchscreen/edt-ft5x06.c
--- a/drivers/input/touchscreen/edt-ft5x06.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/input/touchscreen/edt-ft5x06.c	2024-01-28 14:01:31.244353788 -0500
@@ -67,6 +67,7 @@
 #define TOUCH_EVENT_RESERVED		0x03
 
 #define EDT_NAME_LEN			23
+#define EDT_NAME_PREFIX_LEN		8
 #define EDT_SWITCH_MODE_RETRIES		10
 #define EDT_SWITCH_MODE_DELAY		5 /* msec */
 #define EDT_RAW_DATA_RETRIES		100
@@ -75,6 +76,10 @@
 #define EDT_DEFAULT_NUM_X		1024
 #define EDT_DEFAULT_NUM_Y		1024
 
+#define RESET_DELAY_MS			300	/* reset deassert to I2C */
+#define FIRST_POLL_DELAY_MS		300	/* in addition to the above */
+#define POLL_INTERVAL_MS		17	/* 17ms = 60fps */
+
 enum edt_pmode {
 	EDT_PMODE_NOT_SUPPORTED,
 	EDT_PMODE_HIBERNATE,
@@ -128,14 +133,19 @@
 	int offset_y;
 	int report_rate;
 	int max_support_points;
+	unsigned int known_ids;
 
-	char name[EDT_NAME_LEN];
+	char name[EDT_NAME_PREFIX_LEN + EDT_NAME_LEN];
 	char fw_version[EDT_NAME_LEN];
+	int init_td_status;
 
 	struct edt_reg_addr reg_addr;
 	enum edt_ver version;
 	unsigned int crc_errors;
 	unsigned int header_errors;
+
+	struct timer_list timer;
+	struct work_struct work_i2c_poll;
 };
 
 struct edt_i2c_chip_data {
@@ -203,6 +213,10 @@
 	int i, type, x, y, id;
 	int offset, tplen, datalen, crclen;
 	int error;
+	unsigned int active_ids = 0, known_ids = tsdata->known_ids;
+	long released_ids;
+	int b = 0;
+	unsigned int num_points;
 
 	switch (tsdata->version) {
 	case EDT_M06:
@@ -210,6 +224,7 @@
 		offset = 5; /* where the actual touch data starts */
 		tplen = 4;  /* data comes in so called frames */
 		crclen = 1; /* length of the crc data */
+		datalen = tplen * tsdata->max_support_points + offset + crclen;
 		break;
 
 	case EDT_M09:
@@ -220,6 +235,7 @@
 		offset = 3;
 		tplen = 6;
 		crclen = 0;
+		datalen = 3;
 		break;
 
 	default:
@@ -227,7 +243,6 @@
 	}
 
 	memset(rdbuf, 0, sizeof(rdbuf));
-	datalen = tplen * tsdata->max_support_points + offset + crclen;
 
 	error = edt_ft5x06_ts_readwrite(tsdata->client,
 					sizeof(cmd), &cmd,
@@ -251,9 +266,43 @@
 
 		if (!edt_ft5x06_ts_check_crc(tsdata, rdbuf, datalen))
 			goto out;
+		num_points = tsdata->max_support_points;
+	} else {
+		/* Register 2 is TD_STATUS, containing the number of touch
+		 * points.
+		 */
+		num_points = min(rdbuf[2] & 0xf, tsdata->max_support_points);
+
+		/* When polling FT5x06 without IRQ: initial register contents
+		 * could be stale or undefined; discard all readings until
+		 * TD_STATUS changes for the first time (or num_points is 0).
+		 */
+		if (tsdata->init_td_status) {
+			if (tsdata->init_td_status < 0)
+				tsdata->init_td_status = rdbuf[2];
+
+			if (num_points && rdbuf[2] == tsdata->init_td_status)
+				goto out;
+
+			tsdata->init_td_status = 0;
+		}
+
+		if (num_points) {
+			datalen = tplen * num_points + crclen;
+			cmd = offset;
+			error = edt_ft5x06_ts_readwrite(tsdata->client,
+							sizeof(cmd), &cmd,
+							datalen, &rdbuf[offset]);
+			if (error) {
+				dev_err_ratelimited(dev,
+						    "Unable to fetch data, error: %d\n",
+						    error);
+				goto out;
+			}
+		}
 	}
 
-	for (i = 0; i < tsdata->max_support_points; i++) {
+	for (i = 0; i < num_points; i++) {
 		u8 *buf = &rdbuf[i * tplen + offset];
 
 		type = buf[0] >> 6;
@@ -275,11 +324,26 @@
 
 		input_mt_slot(tsdata->input, id);
 		if (input_mt_report_slot_state(tsdata->input, MT_TOOL_FINGER,
-					       type != TOUCH_EVENT_UP))
+					       type != TOUCH_EVENT_UP)) {
 			touchscreen_report_pos(tsdata->input, &tsdata->prop,
 					       x, y, true);
+			active_ids |= BIT(id);
+		} else {
+			known_ids &= ~BIT(id);
+		}
 	}
 
+	/* One issue with the device is the TOUCH_UP message is not always
+	 * returned. Instead track which ids we know about and report when they
+	 * are no longer updated
+	 */
+	released_ids = known_ids & ~active_ids;
+	for_each_set_bit_from(b, &released_ids, tsdata->max_support_points) {
+		input_mt_slot(tsdata->input, b);
+		input_mt_report_slot_inactive(tsdata->input);
+	}
+	tsdata->known_ids = active_ids;
+
 	input_mt_report_pointer_emulation(tsdata->input, true);
 	input_sync(tsdata->input);
 
@@ -287,6 +351,22 @@
 	return IRQ_HANDLED;
 }
 
+static void edt_ft5x06_ts_irq_poll_timer(struct timer_list *t)
+{
+	struct edt_ft5x06_ts_data *tsdata = from_timer(tsdata, t, timer);
+
+	schedule_work(&tsdata->work_i2c_poll);
+	mod_timer(&tsdata->timer, jiffies + msecs_to_jiffies(POLL_INTERVAL_MS));
+}
+
+static void edt_ft5x06_ts_work_i2c_poll(struct work_struct *work)
+{
+	struct edt_ft5x06_ts_data *tsdata = container_of(work,
+			struct edt_ft5x06_ts_data, work_i2c_poll);
+
+	edt_ft5x06_ts_isr(0, tsdata);
+}
+
 static int edt_ft5x06_register_write(struct edt_ft5x06_ts_data *tsdata,
 				     u8 addr, u8 value)
 {
@@ -886,6 +966,9 @@
 	char *model_name = tsdata->name;
 	char *fw_version = tsdata->fw_version;
 
+	snprintf(model_name, EDT_NAME_PREFIX_LEN + 1, "%s ", dev_name(&client->dev));
+	model_name += strlen(model_name);
+
 	/* see what we find if we assume it is a M06 *
 	 * if we get less than EDT_NAME_LEN, we don't want
 	 * to have garbage in there
@@ -1239,7 +1322,7 @@
 	if (tsdata->reset_gpio) {
 		usleep_range(5000, 6000);
 		gpiod_set_value_cansleep(tsdata->reset_gpio, 0);
-		msleep(300);
+		msleep(RESET_DELAY_MS);
 	}
 
 	input = devm_input_allocate_device(&client->dev);
@@ -1314,17 +1397,28 @@
 
 	i2c_set_clientdata(client, tsdata);
 
-	irq_flags = irq_get_trigger_type(client->irq);
-	if (irq_flags == IRQF_TRIGGER_NONE)
-		irq_flags = IRQF_TRIGGER_FALLING;
-	irq_flags |= IRQF_ONESHOT;
-
-	error = devm_request_threaded_irq(&client->dev, client->irq,
-					NULL, edt_ft5x06_ts_isr, irq_flags,
-					client->name, tsdata);
-	if (error) {
-		dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
-		return error;
+	if (client->irq) {
+		irq_flags = irq_get_trigger_type(client->irq);
+		if (irq_flags == IRQF_TRIGGER_NONE)
+			irq_flags = IRQF_TRIGGER_FALLING;
+		irq_flags |= IRQF_ONESHOT;
+
+		error = devm_request_threaded_irq(&client->dev, client->irq,
+						  NULL, edt_ft5x06_ts_isr,
+						  irq_flags, client->name,
+						  tsdata);
+		if (error) {
+			dev_err(&client->dev, "Unable to request touchscreen IRQ.\n");
+			return error;
+		}
+	} else {
+		tsdata->init_td_status = -1; /* filter bogus initial data */
+		INIT_WORK(&tsdata->work_i2c_poll,
+			  edt_ft5x06_ts_work_i2c_poll);
+		timer_setup(&tsdata->timer, edt_ft5x06_ts_irq_poll_timer, 0);
+		tsdata->timer.expires =
+			jiffies + msecs_to_jiffies(FIRST_POLL_DELAY_MS);
+		add_timer(&tsdata->timer);
 	}
 
 	error = devm_device_add_group(&client->dev, &edt_ft5x06_attr_group);
@@ -1350,6 +1444,10 @@
 {
 	struct edt_ft5x06_ts_data *tsdata = i2c_get_clientdata(client);
 
+	if (!client->irq) {
+		del_timer(&tsdata->timer);
+		cancel_work_sync(&tsdata->work_i2c_poll);
+	}
 	edt_ft5x06_ts_teardown_debugfs(tsdata);
 }
 
diff -Naur --no-dereference a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c
--- a/drivers/input/touchscreen/ti_am335x_tsc.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/input/touchscreen/ti_am335x_tsc.c	2024-01-28 14:01:31.244353788 -0500
@@ -34,6 +34,7 @@
 #define ADCFSM_STEPID		0x10
 #define SEQ_SETTLE		275
 #define MAX_12BIT		((1 << 12) - 1)
+#define PRESSURE_MAX		1000
 
 #define TSC_IRQENB_MASK		(IRQENB_FIFO0THRES | IRQENB_EOS | IRQENB_HW_PEN)
 
@@ -242,6 +243,7 @@
 	for (i = 0; i < creads; i++) {
 		xvals[i] = titsc_readl(ts_dev, REG_FIFO0);
 		xvals[i] &= 0xfff;
+		pr_debug("i %d xval %d yval %d z1 %d z2 %d\n", i, xvals[i], yvals[i], *z1, *z2);
 	}
 
 	/*
@@ -320,13 +322,13 @@
 			 * Resistance(touch) = x plate resistance *
 			 * x position/4096 * ((z2 / z1) - 1)
 			 */
-			z = z1 - z2;
+			z = z2 - z1;
 			z *= x;
 			z *= ts_dev->x_plate_resistance;
-			z /= z2;
+			z /= z1;
 			z = (z + 2047) >> 12;
-
-			if (z <= MAX_12BIT) {
+			pr_debug("x %d y %d z1 %d z2 %d z %d\n", x, y, z1, z2, z);
+			if (z <= PRESSURE_MAX) {
 				input_report_abs(input_dev, ABS_X, x);
 				input_report_abs(input_dev, ABS_Y, y);
 				input_report_abs(input_dev, ABS_PRESSURE, z);
@@ -467,6 +469,7 @@
 	input_dev->name = "ti-tsc";
 	input_dev->dev.parent = &pdev->dev;
 
+	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
 	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
 	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
diff -Naur --no-dereference a/drivers/irqchip/irq-pruss-intc.c b/drivers/irqchip/irq-pruss-intc.c
--- a/drivers/irqchip/irq-pruss-intc.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/irqchip/irq-pruss-intc.c	2024-01-28 14:01:31.244353788 -0500
@@ -70,6 +70,8 @@
 #define MAX_PRU_SYS_EVENTS 160
 #define MAX_PRU_CHANNELS 20
 
+#define MAX_PRU_INT_EVENTS	64
+
 /**
  * struct pruss_intc_map_record - keeps track of actual mapping state
  * @value: The currently mapped value (channel or host)
@@ -85,10 +87,13 @@
  * @num_system_events: number of input system events handled by the PRUSS INTC
  * @num_host_events: number of host events (which is equal to number of
  *		     channels) supported by the PRUSS INTC
+ * @quirky_events: bitmask of events that need quirky IRQ handling (limited to
+ *		   (internal sources only for now, so 64 bits suffice)
  */
 struct pruss_intc_match_data {
 	u8 num_system_events;
 	u8 num_host_events;
+	u64 quirky_events;
 };
 
 /**
@@ -101,6 +106,7 @@
  * @soc_config: cached PRUSS INTC IP configuration data
  * @dev: PRUSS INTC device pointer
  * @lock: mutex to serialize interrupts mapping
+ * @irqs_reserved: bit-mask of reserved host interrupts
  */
 struct pruss_intc {
 	struct pruss_intc_map_record event_channel[MAX_PRU_SYS_EVENTS];
@@ -111,6 +117,7 @@
 	const struct pruss_intc_match_data *soc_config;
 	struct device *dev;
 	struct mutex lock; /* PRUSS INTC lock */
+	u8 irqs_reserved;
 };
 
 /**
@@ -178,6 +185,7 @@
 static void pruss_intc_map(struct pruss_intc *intc, unsigned long hwirq)
 {
 	struct device *dev = intc->dev;
+	bool enable_hwirq = false;
 	u8 ch, host, reg_idx;
 	u32 val;
 
@@ -187,6 +195,9 @@
 
 	ch = intc->event_channel[hwirq].value;
 	host = intc->channel_host[ch].value;
+	enable_hwirq = (host < FIRST_PRU_HOST_INT ||
+			host >= FIRST_PRU_HOST_INT + MAX_NUM_HOST_IRQS ||
+			intc->irqs_reserved & BIT(host - FIRST_PRU_HOST_INT));
 
 	pruss_intc_update_cmr(intc, hwirq, ch);
 
@@ -194,8 +205,10 @@
 	val = BIT(hwirq  % 32);
 
 	/* clear and enable system event */
-	pruss_intc_write_reg(intc, PRU_INTC_ESR(reg_idx), val);
 	pruss_intc_write_reg(intc, PRU_INTC_SECR(reg_idx), val);
+	/* unmask only events going to various PRU and other cores by default */
+	if (enable_hwirq)
+		pruss_intc_write_reg(intc, PRU_INTC_ESR(reg_idx), val);
 
 	if (++intc->channel_host[ch].ref_count == 1) {
 		pruss_intc_update_hmr(intc, ch, host);
@@ -204,7 +217,8 @@
 		pruss_intc_write_reg(intc, PRU_INTC_HIEISR, host);
 	}
 
-	dev_dbg(dev, "mapped system_event = %lu channel = %d host = %d",
+	dev_dbg(dev, "mapped%s system_event = %lu channel = %d host = %d",
+		enable_hwirq ? " and enabled" : "",
 		hwirq, ch, host);
 
 	mutex_unlock(&intc->lock);
@@ -268,11 +282,14 @@
 
 	/*
 	 * configure polarity (SIPR register) to active high and
-	 * type (SITR register) to level interrupt for all system events
+	 * type (SITR register) to level interrupt for all system events,
+	 * and disable and clear all the system events
 	 */
 	for (i = 0; i < num_event_type_regs; i++) {
 		pruss_intc_write_reg(intc, PRU_INTC_SIPR(i), 0xffffffff);
 		pruss_intc_write_reg(intc, PRU_INTC_SITR(i), 0);
+		pruss_intc_write_reg(intc, PRU_INTC_ECR(i), 0xffffffff);
+		pruss_intc_write_reg(intc, PRU_INTC_SECR(i), 0xffffffff);
 	}
 
 	/* clear all interrupt channel map registers, 4 events per register */
@@ -292,6 +309,10 @@
 	struct pruss_intc *intc = irq_data_get_irq_chip_data(data);
 	unsigned int hwirq = data->hwirq;
 
+	if (hwirq < MAX_PRU_INT_EVENTS &&
+	    intc->soc_config->quirky_events & BIT_ULL(hwirq))
+		return;
+
 	pruss_intc_write_reg(intc, PRU_INTC_SICR, hwirq);
 }
 
@@ -308,6 +329,9 @@
 	struct pruss_intc *intc = irq_data_get_irq_chip_data(data);
 	unsigned int hwirq = data->hwirq;
 
+	if (hwirq < MAX_PRU_INT_EVENTS &&
+	    intc->soc_config->quirky_events & BIT_ULL(hwirq))
+		pruss_intc_write_reg(intc, PRU_INTC_SICR, hwirq);
 	pruss_intc_write_reg(intc, PRU_INTC_EISR, hwirq);
 }
 
@@ -361,6 +385,14 @@
 	return 0;
 }
 
+static int pruss_intc_irq_irq_set_type(struct irq_data *data, unsigned int type)
+{
+	if (type != IRQ_TYPE_LEVEL_HIGH)
+		return -EINVAL;
+
+	return 0;
+}
+
 static struct irq_chip pruss_irqchip = {
 	.name			= "pruss-intc",
 	.irq_ack		= pruss_intc_irq_ack,
@@ -370,6 +402,7 @@
 	.irq_release_resources	= pruss_intc_irq_relres,
 	.irq_get_irqchip_state	= pruss_intc_irq_get_irqchip_state,
 	.irq_set_irqchip_state	= pruss_intc_irq_set_irqchip_state,
+	.irq_set_type		= pruss_intc_irq_irq_set_type,
 };
 
 static int pruss_intc_validate_mapping(struct pruss_intc *intc, int event,
@@ -521,7 +554,7 @@
 	struct pruss_intc *intc;
 	struct pruss_host_irq_data *host_data;
 	int i, irq, ret;
-	u8 max_system_events, irqs_reserved = 0;
+	u8 max_system_events;
 
 	data = of_device_get_match_data(dev);
 	if (!data)
@@ -542,7 +575,7 @@
 		return PTR_ERR(intc->base);
 
 	ret = of_property_read_u8(dev->of_node, "ti,irqs-reserved",
-				  &irqs_reserved);
+				  &intc->irqs_reserved);
 
 	/*
 	 * The irqs-reserved is used only for some SoC's therefore not having
@@ -561,7 +594,7 @@
 		return -ENOMEM;
 
 	for (i = 0; i < MAX_NUM_HOST_IRQS; i++) {
-		if (irqs_reserved & BIT(i))
+		if (intc->irqs_reserved & BIT(i))
 			continue;
 
 		irq = platform_get_irq_byname(pdev, irq_names[i]);
@@ -623,11 +656,13 @@
 static const struct pruss_intc_match_data pruss_intc_data = {
 	.num_system_events = 64,
 	.num_host_events = 10,
+	.quirky_events = BIT_ULL(7), /* IEP capture/compare event */
 };
 
 static const struct pruss_intc_match_data icssg_intc_data = {
 	.num_system_events = 160,
 	.num_host_events = 20,
+	.quirky_events = BIT_ULL(7) | BIT_ULL(56), /* IEP{0,1} capture/compare events */
 };
 
 static const struct of_device_id pruss_intc_of_match[] = {
diff -Naur --no-dereference a/drivers/irqchip/irq-ti-sci-inta.c b/drivers/irqchip/irq-ti-sci-inta.c
--- a/drivers/irqchip/irq-ti-sci-inta.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/irqchip/irq-ti-sci-inta.c	2024-01-28 14:01:31.244353788 -0500
@@ -64,6 +64,7 @@
  * @events:		Array of event descriptors assigned to this vint.
  * @parent_virq:	Linux IRQ number that gets attached to parent
  * @vint_id:		TISCI vint ID
+ * @affinity_managed:	flag to indicate VINT affinity is managed
  */
 struct ti_sci_inta_vint_desc {
 	struct irq_domain *domain;
@@ -72,6 +73,7 @@
 	struct ti_sci_inta_event_desc events[MAX_EVENTS_PER_VINT];
 	unsigned int parent_virq;
 	u16 vint_id;
+	bool affinity_managed;
 };
 
 /**
@@ -199,10 +201,12 @@
 /**
  * ti_sci_inta_alloc_parent_irq() - Allocate parent irq to Interrupt aggregator
  * @domain:	IRQ domain corresponding to Interrupt Aggregator
+ * @vint_id:	vint_id to which event is to be mapped to
  *
  * Return 0 if all went well else corresponding error value.
  */
-static struct ti_sci_inta_vint_desc *ti_sci_inta_alloc_parent_irq(struct irq_domain *domain)
+static struct ti_sci_inta_vint_desc *ti_sci_inta_alloc_parent_irq(struct irq_domain *domain,
+								  u16 vint_id)
 {
 	struct ti_sci_inta_irq_domain *inta = domain->host_data;
 	struct ti_sci_inta_vint_desc *vint_desc;
@@ -210,11 +214,6 @@
 	struct device_node *parent_node;
 	unsigned int parent_virq;
 	int p_hwirq, ret;
-	u16 vint_id;
-
-	vint_id = ti_sci_get_free_resource(inta->vint);
-	if (vint_id == TI_SCI_RESOURCE_NULL)
-		return ERR_PTR(-EINVAL);
 
 	p_hwirq = ti_sci_inta_xlate_irq(inta, vint_id);
 	if (p_hwirq < 0) {
@@ -328,29 +327,42 @@
 	struct ti_sci_inta_vint_desc *vint_desc = NULL;
 	struct ti_sci_inta_event_desc *event_desc;
 	u16 free_bit;
+	u16 vint_id;
 
 	mutex_lock(&inta->vint_mutex);
-	list_for_each_entry(vint_desc, &inta->vint_list, list) {
+	/*
+	 * Allocate new VINT each time until we runout, then start
+	 * aggregating
+	 */
+	vint_id = ti_sci_get_free_resource(inta->vint);
+	if (vint_id == TI_SCI_RESOURCE_NULL) {
+		list_for_each_entry(vint_desc, &inta->vint_list, list) {
+			if (vint_desc->affinity_managed)
+				continue;
+			free_bit = find_first_zero_bit(vint_desc->event_map,
+						       MAX_EVENTS_PER_VINT);
+			if (free_bit != MAX_EVENTS_PER_VINT) {
+				set_bit(free_bit, vint_desc->event_map);
+				break;
+			}
+		}
+	} else  {
+		vint_desc = ti_sci_inta_alloc_parent_irq(domain, vint_id);
+		if (IS_ERR(vint_desc)) {
+			event_desc = ERR_CAST(vint_desc);
+			goto unlock;
+		}
+
 		free_bit = find_first_zero_bit(vint_desc->event_map,
 					       MAX_EVENTS_PER_VINT);
-		if (free_bit != MAX_EVENTS_PER_VINT) {
-			set_bit(free_bit, vint_desc->event_map);
-			goto alloc_event;
-		}
+		set_bit(free_bit, vint_desc->event_map);
 	}
 
-	/* No free bits available. Allocate a new vint */
-	vint_desc = ti_sci_inta_alloc_parent_irq(domain);
-	if (IS_ERR(vint_desc)) {
-		event_desc = ERR_CAST(vint_desc);
+	if (free_bit == MAX_EVENTS_PER_VINT) {
+		event_desc = ERR_PTR(-EINVAL);
 		goto unlock;
 	}
 
-	free_bit = find_first_zero_bit(vint_desc->event_map,
-				       MAX_EVENTS_PER_VINT);
-	set_bit(free_bit, vint_desc->event_map);
-
-alloc_event:
 	event_desc = ti_sci_inta_alloc_event(vint_desc, free_bit, hwirq);
 	if (IS_ERR(event_desc))
 		clear_bit(free_bit, vint_desc->event_map);
@@ -429,6 +441,7 @@
 		return PTR_ERR(event_desc);
 
 	data->chip_data = event_desc;
+	irq_data_update_effective_affinity(data, cpu_online_mask);
 
 	return 0;
 }
@@ -499,11 +512,48 @@
 		ti_sci_inta_manage_event(data, VINT_STATUS_OFFSET);
 }
 
+#ifdef CONFIG_SMP
+static int ti_sci_inta_set_affinity(struct irq_data *d,
+				    const struct cpumask *mask_val, bool force)
+{
+	struct ti_sci_inta_event_desc *event_desc;
+	struct ti_sci_inta_vint_desc *vint_desc;
+	struct irq_data *parent_irq_data;
+
+	if (cpumask_equal(irq_data_get_effective_affinity_mask(d), mask_val))
+		return 0;
+
+	event_desc = irq_data_get_irq_chip_data(d);
+	if (event_desc) {
+		vint_desc = to_vint_desc(event_desc, event_desc->vint_bit);
+		parent_irq_data = irq_get_irq_data(vint_desc->parent_virq);
+
+		if (!parent_irq_data || !parent_irq_data->chip->irq_set_affinity)
+			return -EINVAL;
+
+		/*
+		 * Cannot set affinity if there is more than one event
+		 * mapped to same VINT
+		 */
+		if (bitmap_weight(vint_desc->event_map, MAX_EVENTS_PER_VINT) > 1)
+			return -EINVAL;
+
+		vint_desc->affinity_managed = true;
+
+		irq_data_update_effective_affinity(d, mask_val);
+
+		return parent_irq_data->chip->irq_set_affinity(parent_irq_data, mask_val, force);
+	}
+
+	return -EINVAL;
+}
+#else
 static int ti_sci_inta_set_affinity(struct irq_data *d,
 				    const struct cpumask *mask_val, bool force)
 {
 	return -EINVAL;
 }
+#endif
 
 /**
  * ti_sci_inta_set_type() - Update the trigger type of the irq.
diff -Naur --no-dereference a/drivers/Kconfig b/drivers/Kconfig
--- a/drivers/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/Kconfig	2024-01-28 14:01:31.240353775 -0500
@@ -169,6 +169,8 @@
 
 source "drivers/rpmsg/Kconfig"
 
+source "drivers/rpmsg-kdrv/Kconfig"
+
 source "drivers/soundwire/Kconfig"
 
 source "drivers/soc/Kconfig"
diff -Naur --no-dereference a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/Makefile	2024-01-28 14:01:31.240353775 -0500
@@ -155,6 +155,7 @@
 obj-$(CONFIG_HWSPINLOCK)	+= hwspinlock/
 obj-$(CONFIG_REMOTEPROC)	+= remoteproc/
 obj-$(CONFIG_RPMSG)		+= rpmsg/
+obj-$(CONFIG_RPMSG_KDRV)	+= rpmsg-kdrv/
 obj-$(CONFIG_SOUNDWIRE)		+= soundwire/
 
 # Virtualization drivers
diff -Naur --no-dereference a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c
--- a/drivers/media/i2c/ds90ub913.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/i2c/ds90ub913.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,906 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the Texas Instruments DS90UB913 video serializer
+ *
+ * Based on a driver from Luca Ceresoli <luca@lucaceresoli.net>
+ *
+ * Copyright (c) 2019 Luca Ceresoli <luca@lucaceresoli.net>
+ * Copyright (c) 2023 Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/fwnode.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c-atr.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+
+#include <media/i2c/ds90ub9xx.h>
+#include <media/v4l2-subdev.h>
+
+#define UB913_PAD_SINK			0
+#define UB913_PAD_SOURCE		1
+
+/*
+ * UB913 has 4 gpios, but gpios 3 and 4 are reserved for external oscillator
+ * mode. Thus we only support 2 gpios for now.
+ */
+#define UB913_NUM_GPIOS			2
+
+#define UB913_REG_RESET_CTL			0x01
+#define UB913_REG_RESET_CTL_DIGITAL_RESET_1	BIT(1)
+#define UB913_REG_RESET_CTL_DIGITAL_RESET_0	BIT(0)
+
+#define UB913_REG_GENERAL_CFG			0x03
+#define UB913_REG_GENERAL_CFG_CRC_ERR_RESET	BIT(5)
+#define UB913_REG_GENERAL_CFG_PCLK_RISING	BIT(0)
+
+#define UB913_REG_MODE_SEL			0x05
+#define UB913_REG_MODE_SEL_MODE_OVERRIDE	BIT(5)
+#define UB913_REG_MODE_SEL_MODE_UP_TO_DATE	BIT(4)
+#define UB913_REG_MODE_SEL_MODE_MASK		GENMASK(3, 0)
+
+#define UB913_REG_CRC_ERRORS_LSB		0x0a
+#define UB913_REG_CRC_ERRORS_MSB		0x0b
+
+#define UB913_REG_GENERAL_STATUS		0x0c
+
+#define UB913_REG_GPIO_CFG(n)			(0x0d + (n))
+#define UB913_REG_GPIO_CFG_ENABLE(n)		BIT(0 + (n) * 4)
+#define UB913_REG_GPIO_CFG_DIR_INPUT(n)		BIT(1 + (n) * 4)
+#define UB913_REG_GPIO_CFG_REMOTE_EN(n)		BIT(2 + (n) * 4)
+#define UB913_REG_GPIO_CFG_OUT_VAL(n)		BIT(3 + (n) * 4)
+#define UB913_REG_GPIO_CFG_MASK(n)		(0xf << ((n) * 4))
+
+#define UB913_REG_SCL_HIGH_TIME			0x11
+#define UB913_REG_SCL_LOW_TIME			0x12
+
+#define UB913_REG_PLL_OVR			0x35
+
+struct ub913_data {
+	struct i2c_client	*client;
+	struct regmap		*regmap;
+	struct clk		*clkin;
+
+	struct gpio_chip	gpio_chip;
+
+	struct v4l2_subdev	sd;
+	struct media_pad	pads[2];
+
+	struct v4l2_async_notifier	notifier;
+
+	struct v4l2_subdev	*source_sd;
+	u16			source_sd_pad;
+
+	u64			enabled_source_streams;
+
+	struct clk_hw		*clkout_clk_hw;
+
+	struct ds90ub9xx_platform_data *plat_data;
+
+	u32			pclk_polarity;
+};
+
+static inline struct ub913_data *sd_to_ub913(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ub913_data, sd);
+}
+
+struct ub913_format_info {
+	u32 incode;
+	u32 outcode;
+};
+
+static const struct ub913_format_info ub913_formats[] = {
+	/* Only RAW10 with 8-bit payload is supported at the moment */
+	{ .incode = MEDIA_BUS_FMT_YUYV8_2X8, .outcode = MEDIA_BUS_FMT_YUYV8_1X16 },
+	{ .incode = MEDIA_BUS_FMT_UYVY8_2X8, .outcode = MEDIA_BUS_FMT_UYVY8_1X16 },
+	{ .incode = MEDIA_BUS_FMT_VYUY8_2X8, .outcode = MEDIA_BUS_FMT_VYUY8_1X16 },
+	{ .incode = MEDIA_BUS_FMT_YVYU8_2X8, .outcode = MEDIA_BUS_FMT_YVYU8_1X16 },
+};
+
+static const struct ub913_format_info *ub913_find_format(u32 incode)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ub913_formats); i++) {
+		if (ub913_formats[i].incode == incode)
+			return &ub913_formats[i];
+	}
+
+	return NULL;
+}
+
+static int ub913_read(const struct ub913_data *priv, u8 reg, u8 *val)
+{
+	unsigned int v;
+	int ret;
+
+	ret = regmap_read(priv->regmap, reg, &v);
+	if (ret < 0) {
+		dev_err(&priv->client->dev,
+			"Cannot read register 0x%02x: %d!\n", reg, ret);
+		return ret;
+	}
+
+	*val = v;
+	return 0;
+}
+
+static int ub913_write(const struct ub913_data *priv, u8 reg, u8 val)
+{
+	int ret;
+
+	ret = regmap_write(priv->regmap, reg, val);
+	if (ret < 0)
+		dev_err(&priv->client->dev,
+			"Cannot write register 0x%02x: %d!\n", reg, ret);
+
+	return ret;
+}
+
+/*
+ * GPIO chip
+ */
+static int ub913_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+	return GPIO_LINE_DIRECTION_OUT;
+}
+
+static int ub913_gpio_direction_out(struct gpio_chip *gc, unsigned int offset,
+				    int value)
+{
+	struct ub913_data *priv = gpiochip_get_data(gc);
+	unsigned int reg_idx = offset / 2;
+	unsigned int field_idx = offset % 2;
+
+	return regmap_update_bits(priv->regmap, UB913_REG_GPIO_CFG(reg_idx),
+				  UB913_REG_GPIO_CFG_MASK(field_idx),
+				  UB913_REG_GPIO_CFG_ENABLE(field_idx) |
+					  (value ? UB913_REG_GPIO_CFG_OUT_VAL(field_idx) :
+						   0));
+}
+
+static void ub913_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
+{
+	ub913_gpio_direction_out(gc, offset, value);
+}
+
+static int ub913_gpio_of_xlate(struct gpio_chip *gc,
+			       const struct of_phandle_args *gpiospec,
+			       u32 *flags)
+{
+	if (flags)
+		*flags = gpiospec->args[1];
+
+	return gpiospec->args[0];
+}
+
+static int ub913_gpiochip_probe(struct ub913_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	struct gpio_chip *gc = &priv->gpio_chip;
+	int ret;
+
+	/* Initialize GPIOs 0 and 1 to local control, tri-state */
+	ub913_write(priv, UB913_REG_GPIO_CFG(0), 0);
+
+	gc->label = dev_name(dev);
+	gc->parent = dev;
+	gc->owner = THIS_MODULE;
+	gc->base = -1;
+	gc->can_sleep = true;
+	gc->ngpio = UB913_NUM_GPIOS;
+	gc->get_direction = ub913_gpio_get_direction;
+	gc->direction_output = ub913_gpio_direction_out;
+	gc->set = ub913_gpio_set;
+	gc->of_xlate = ub913_gpio_of_xlate;
+	gc->of_gpio_n_cells = 2;
+
+	ret = gpiochip_add_data(gc, priv);
+	if (ret) {
+		dev_err(dev, "Failed to add GPIOs: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void ub913_gpiochip_remove(struct ub913_data *priv)
+{
+	gpiochip_remove(&priv->gpio_chip);
+}
+
+static const struct regmap_config ub913_regmap_config = {
+	.name = "ds90ub913",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.reg_format_endian = REGMAP_ENDIAN_DEFAULT,
+	.val_format_endian = REGMAP_ENDIAN_DEFAULT,
+};
+
+/*
+ * V4L2
+ */
+
+static int ub913_enable_streams(struct v4l2_subdev *sd,
+				struct v4l2_subdev_state *state, u32 pad,
+				u64 streams_mask)
+{
+	struct ub913_data *priv = sd_to_ub913(sd);
+	u64 sink_streams;
+	int ret;
+
+	sink_streams = v4l2_subdev_state_xlate_streams(state, UB913_PAD_SOURCE,
+						       UB913_PAD_SINK,
+						       &streams_mask);
+
+	ret = v4l2_subdev_enable_streams(priv->source_sd, priv->source_sd_pad,
+					 sink_streams);
+	if (ret)
+		return ret;
+
+	priv->enabled_source_streams |= streams_mask;
+
+	return 0;
+}
+
+static int ub913_disable_streams(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_state *state, u32 pad,
+				 u64 streams_mask)
+{
+	struct ub913_data *priv = sd_to_ub913(sd);
+	u64 sink_streams;
+	int ret;
+
+	sink_streams = v4l2_subdev_state_xlate_streams(state, UB913_PAD_SOURCE,
+						       UB913_PAD_SINK,
+						       &streams_mask);
+
+	ret = v4l2_subdev_disable_streams(priv->source_sd, priv->source_sd_pad,
+					  sink_streams);
+	if (ret)
+		return ret;
+
+	priv->enabled_source_streams &= ~streams_mask;
+
+	return 0;
+}
+
+static int _ub913_set_routing(struct v4l2_subdev *sd,
+			      struct v4l2_subdev_state *state,
+			      struct v4l2_subdev_krouting *routing)
+{
+	static const struct v4l2_mbus_framefmt in_format = {
+		.width = 640,
+		.height = 480,
+		.code = MEDIA_BUS_FMT_UYVY8_2X8,
+		.field = V4L2_FIELD_NONE,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.ycbcr_enc = V4L2_YCBCR_ENC_601,
+		.quantization = V4L2_QUANTIZATION_LIM_RANGE,
+		.xfer_func = V4L2_XFER_FUNC_SRGB,
+	};
+	static const struct v4l2_mbus_framefmt out_format = {
+		.width = 640,
+		.height = 480,
+		.code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.field = V4L2_FIELD_NONE,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.ycbcr_enc = V4L2_YCBCR_ENC_601,
+		.quantization = V4L2_QUANTIZATION_LIM_RANGE,
+		.xfer_func = V4L2_XFER_FUNC_SRGB,
+	};
+	struct v4l2_subdev_stream_configs *stream_configs;
+	unsigned int i;
+	int ret;
+
+	/*
+	 * Note: we can only support up to V4L2_FRAME_DESC_ENTRY_MAX, until
+	 * frame desc is made dynamically allocated.
+	 */
+
+	if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX)
+		return -EINVAL;
+
+	ret = v4l2_subdev_routing_validate(sd, routing,
+					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
+	if (ret)
+		return ret;
+
+	ret = v4l2_subdev_set_routing(sd, state, routing);
+	if (ret)
+		return ret;
+
+	stream_configs = &state->stream_configs;
+
+	for (i = 0; i < stream_configs->num_configs; i++) {
+		if (stream_configs->configs[i].pad == UB913_PAD_SINK)
+			stream_configs->configs[i].fmt = in_format;
+		else
+			stream_configs->configs[i].fmt = out_format;
+	}
+
+	return 0;
+}
+
+static int ub913_set_routing(struct v4l2_subdev *sd,
+			     struct v4l2_subdev_state *state,
+			     enum v4l2_subdev_format_whence which,
+			     struct v4l2_subdev_krouting *routing)
+{
+	struct ub913_data *priv = sd_to_ub913(sd);
+
+	if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams)
+		return -EBUSY;
+
+	return _ub913_set_routing(sd, state, routing);
+}
+
+static int ub913_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+				struct v4l2_mbus_frame_desc *fd)
+{
+	struct ub913_data *priv = sd_to_ub913(sd);
+	const struct v4l2_subdev_krouting *routing;
+	struct v4l2_mbus_frame_desc source_fd;
+	struct v4l2_subdev_route *route;
+	struct v4l2_subdev_state *state;
+	int ret;
+
+	if (pad != UB913_PAD_SOURCE)
+		return -EINVAL;
+
+	ret = v4l2_subdev_call(priv->source_sd, pad, get_frame_desc,
+			       priv->source_sd_pad, &source_fd);
+	if (ret)
+		return ret;
+
+	memset(fd, 0, sizeof(*fd));
+
+	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL;
+
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	routing = &state->routing;
+
+	for_each_active_route(routing, route) {
+		unsigned int i;
+
+		if (route->source_pad != pad)
+			continue;
+
+		for (i = 0; i < source_fd.num_entries; i++) {
+			if (source_fd.entry[i].stream == route->sink_stream)
+				break;
+		}
+
+		if (i == source_fd.num_entries) {
+			dev_err(&priv->client->dev,
+				"Failed to find stream from source frame desc\n");
+			ret = -EPIPE;
+			goto out_unlock;
+		}
+
+		fd->entry[fd->num_entries].stream = route->source_stream;
+		fd->entry[fd->num_entries].flags = source_fd.entry[i].flags;
+		fd->entry[fd->num_entries].length = source_fd.entry[i].length;
+		fd->entry[fd->num_entries].pixelcode =
+			source_fd.entry[i].pixelcode;
+
+		fd->num_entries++;
+	}
+
+out_unlock:
+	v4l2_subdev_unlock_state(state);
+
+	return ret;
+}
+
+static int ub913_set_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_subdev_state *state,
+			 struct v4l2_subdev_format *format)
+{
+	struct ub913_data *priv = sd_to_ub913(sd);
+	struct v4l2_mbus_framefmt *fmt;
+	const struct ub913_format_info *finfo;
+
+	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
+	    priv->enabled_source_streams)
+		return -EBUSY;
+
+	/* Source format is fully defined by the sink format, so not settable */
+	if (format->pad == UB913_PAD_SOURCE)
+		return v4l2_subdev_get_fmt(sd, state, format);
+
+	finfo = ub913_find_format(format->format.code);
+	if (!finfo) {
+		finfo = &ub913_formats[0];
+		format->format.code = finfo->incode;
+	}
+
+	/* Set sink format */
+	fmt = v4l2_subdev_state_get_stream_format(state, format->pad,
+						  format->stream);
+	if (!fmt)
+		return -EINVAL;
+
+	*fmt = format->format;
+
+	/* Propagate to source format, and adjust the mbus code */
+	fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
+							   format->stream);
+	if (!fmt)
+		return -EINVAL;
+
+	format->format.code = finfo->outcode;
+
+	*fmt = format->format;
+
+	return 0;
+}
+
+static int ub913_init_cfg(struct v4l2_subdev *sd,
+			  struct v4l2_subdev_state *state)
+{
+	struct v4l2_subdev_route routes[] = {
+		{
+			.sink_pad = UB913_PAD_SINK,
+			.sink_stream = 0,
+			.source_pad = UB913_PAD_SOURCE,
+			.source_stream = 0,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+	};
+
+	struct v4l2_subdev_krouting routing = {
+		.num_routes = ARRAY_SIZE(routes),
+		.routes = routes,
+	};
+
+	return _ub913_set_routing(sd, state, &routing);
+}
+
+static int ub913_log_status(struct v4l2_subdev *sd)
+{
+	struct ub913_data *priv = sd_to_ub913(sd);
+	struct device *dev = &priv->client->dev;
+	u8 v, v1, v2;
+
+	ub913_read(priv, UB913_REG_MODE_SEL, &v);
+	dev_info(dev, "MODE_SEL %#02x\n", v);
+
+	ub913_read(priv, UB913_REG_CRC_ERRORS_LSB, &v1);
+	ub913_read(priv, UB913_REG_CRC_ERRORS_MSB, &v2);
+	dev_info(dev, "CRC errors %u\n", v1 | (v2 << 8));
+
+	/* clear CRC errors */
+	ub913_read(priv, UB913_REG_GENERAL_CFG, &v);
+	ub913_write(priv, UB913_REG_GENERAL_CFG,
+		    v | UB913_REG_GENERAL_CFG_CRC_ERR_RESET);
+	ub913_write(priv, UB913_REG_GENERAL_CFG, v);
+
+	ub913_read(priv, UB913_REG_GENERAL_STATUS, &v);
+	dev_info(dev, "GENERAL_STATUS %#02x\n", v);
+
+	ub913_read(priv, UB913_REG_PLL_OVR, &v);
+	dev_info(dev, "PLL_OVR %#02x\n", v);
+
+	return 0;
+}
+
+static const struct v4l2_subdev_core_ops ub913_subdev_core_ops = {
+	.log_status = ub913_log_status,
+};
+
+static const struct v4l2_subdev_pad_ops ub913_pad_ops = {
+	.enable_streams = ub913_enable_streams,
+	.disable_streams = ub913_disable_streams,
+	.set_routing = ub913_set_routing,
+	.get_frame_desc = ub913_get_frame_desc,
+	.get_fmt = v4l2_subdev_get_fmt,
+	.set_fmt = ub913_set_fmt,
+	.init_cfg = ub913_init_cfg,
+};
+
+static const struct v4l2_subdev_ops ub913_subdev_ops = {
+	.core = &ub913_subdev_core_ops,
+	.pad = &ub913_pad_ops,
+};
+
+static const struct media_entity_operations ub913_entity_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+static int ub913_notify_bound(struct v4l2_async_notifier *notifier,
+			      struct v4l2_subdev *source_subdev,
+			      struct v4l2_async_subdev *asd)
+{
+	struct ub913_data *priv = sd_to_ub913(notifier->sd);
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	ret = media_entity_get_fwnode_pad(&source_subdev->entity,
+					  source_subdev->fwnode,
+					  MEDIA_PAD_FL_SOURCE);
+	if (ret < 0) {
+		dev_err(dev, "Failed to find pad for %s\n",
+			source_subdev->name);
+		return ret;
+	}
+
+	priv->source_sd = source_subdev;
+	priv->source_sd_pad = ret;
+
+	ret = media_create_pad_link(&source_subdev->entity, priv->source_sd_pad,
+				    &priv->sd.entity, UB913_PAD_SINK,
+				    MEDIA_LNK_FL_ENABLED |
+					    MEDIA_LNK_FL_IMMUTABLE);
+	if (ret) {
+		dev_err(dev, "Unable to link %s:%u -> %s:0\n",
+			source_subdev->name, priv->source_sd_pad,
+			priv->sd.name);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_async_notifier_operations ub913_notify_ops = {
+	.bound = ub913_notify_bound,
+};
+
+static int ub913_v4l2_notifier_register(struct ub913_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	struct v4l2_async_subdev *asd;
+	struct fwnode_handle *ep_fwnode;
+	int ret;
+
+	ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
+						    UB913_PAD_SINK, 0, 0);
+	if (!ep_fwnode) {
+		dev_err(dev, "No graph endpoint\n");
+		return -ENODEV;
+	}
+
+	v4l2_async_nf_init(&priv->notifier);
+
+	asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep_fwnode,
+					      struct v4l2_async_subdev);
+
+	fwnode_handle_put(ep_fwnode);
+
+	if (IS_ERR(asd)) {
+		dev_err(dev, "Failed to add subdev: %ld", PTR_ERR(asd));
+		v4l2_async_nf_cleanup(&priv->notifier);
+		return PTR_ERR(asd);
+	}
+
+	priv->notifier.ops = &ub913_notify_ops;
+
+	ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier);
+	if (ret) {
+		dev_err(dev, "Failed to register subdev_notifier");
+		v4l2_async_nf_cleanup(&priv->notifier);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void ub913_v4l2_nf_unregister(struct ub913_data *priv)
+{
+	v4l2_async_nf_unregister(&priv->notifier);
+	v4l2_async_nf_cleanup(&priv->notifier);
+}
+
+static int ub913_register_clkout(struct ub913_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	const char *name;
+	int ret;
+
+	name = kasprintf(GFP_KERNEL, "ds90ub913.%s.clk_out", dev_name(dev));
+	if (!name)
+		return -ENOMEM;
+
+	priv->clkout_clk_hw = devm_clk_hw_register_fixed_factor(dev, name,
+		__clk_get_name(priv->clkin), 0, 1, 2);
+
+	kfree(name);
+
+	if (IS_ERR(priv->clkout_clk_hw))
+		return dev_err_probe(dev, PTR_ERR(priv->clkout_clk_hw),
+				     "Cannot register clkout hw\n");
+
+	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+					  priv->clkout_clk_hw);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Cannot add OF clock provider\n");
+
+	return 0;
+}
+
+static int ub913_i2c_master_init(struct ub913_data *priv)
+{
+	/* i2c fast mode */
+	u32 scl_high = 600 + 300; /* high period + rise time, ns */
+	u32 scl_low = 1300 + 300; /* low period + fall time, ns */
+	unsigned long ref;
+	int ret;
+
+	ref = clk_get_rate(priv->clkin) / 2;
+
+	scl_high = div64_u64((u64)scl_high * ref, 1000000000);
+	scl_low = div64_u64((u64)scl_low * ref, 1000000000);
+
+	ret = ub913_write(priv, UB913_REG_SCL_HIGH_TIME, scl_high);
+	if (ret)
+		return ret;
+
+	ret = ub913_write(priv, UB913_REG_SCL_LOW_TIME, scl_low);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int ub913_add_i2c_adapter(struct ub913_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	struct fwnode_handle *i2c_handle;
+	int ret;
+
+	i2c_handle = device_get_named_child_node(dev, "i2c");
+	if (!i2c_handle)
+		return 0;
+
+	ret = i2c_atr_add_adapter(priv->plat_data->atr, priv->plat_data->port,
+				  dev, i2c_handle);
+
+	fwnode_handle_put(i2c_handle);
+
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int ub913_parse_dt(struct ub913_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	struct fwnode_handle *ep_fwnode;
+	int ret;
+
+	ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
+						    UB913_PAD_SINK, 0, 0);
+	if (!ep_fwnode) {
+		dev_err_probe(dev, -ENOENT, "No sink endpoint\n");
+		return -ENOENT;
+	}
+
+	ret = fwnode_property_read_u32(ep_fwnode, "pclk-sample",
+				       &priv->pclk_polarity);
+
+	fwnode_handle_put(ep_fwnode);
+
+	if (ret) {
+		dev_err_probe(dev, ret, "failed to parse 'pclk-sample'\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ub913_hw_init(struct ub913_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	bool mode_override;
+	u8 mode;
+	int ret;
+	u8 v;
+
+	ret = ub913_read(priv, UB913_REG_MODE_SEL, &v);
+	if (ret)
+		return ret;
+
+	if (!(v & UB913_REG_MODE_SEL_MODE_UP_TO_DATE))
+		return dev_err_probe(dev, -ENODEV,
+				     "Mode value not stabilized\n");
+
+	mode_override = v & UB913_REG_MODE_SEL_MODE_OVERRIDE;
+	mode = v & UB913_REG_MODE_SEL_MODE_MASK;
+
+	dev_dbg(dev, "mode from %s: %#x\n",
+		mode_override ? "reg" : "deserializer", mode);
+
+	ret = ub913_i2c_master_init(priv);
+	if (ret)
+		return dev_err_probe(dev, ret, "i2c master init failed\n");
+
+	ub913_read(priv, UB913_REG_GENERAL_CFG, &v);
+	v &= ~UB913_REG_GENERAL_CFG_PCLK_RISING;
+	v |= priv->pclk_polarity ? UB913_REG_GENERAL_CFG_PCLK_RISING : 0;
+	ub913_write(priv, UB913_REG_GENERAL_CFG, v);
+
+	return 0;
+}
+
+static int ub913_subdev_init(struct ub913_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	v4l2_i2c_subdev_init(&priv->sd, priv->client, &ub913_subdev_ops);
+	priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
+	priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+	priv->sd.entity.ops = &ub913_entity_ops;
+
+	priv->pads[0].flags = MEDIA_PAD_FL_SINK;
+	priv->pads[1].flags = MEDIA_PAD_FL_SOURCE;
+
+	ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to init pads\n");
+
+	priv->sd.fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
+							  UB913_PAD_SOURCE, 0,
+							  0);
+
+	if (!priv->sd.fwnode) {
+		ret = -ENODEV;
+		dev_err_probe(dev, ret, "Missing TX endpoint\n");
+		goto err_entity_cleanup;
+	}
+
+	ret = v4l2_subdev_init_finalize(&priv->sd);
+	if (ret)
+		goto err_fwnode_put;
+
+	ret = ub913_v4l2_notifier_register(priv);
+	if (ret) {
+		dev_err_probe(dev, ret,
+			      "v4l2 subdev notifier register failed\n");
+		goto err_subdev_cleanup;
+	}
+
+	ret = v4l2_async_register_subdev(&priv->sd);
+	if (ret) {
+		dev_err_probe(dev, ret, "v4l2_async_register_subdev error\n");
+		goto err_unreg_notif;
+	}
+
+	return 0;
+
+err_unreg_notif:
+	ub913_v4l2_nf_unregister(priv);
+err_subdev_cleanup:
+	v4l2_subdev_cleanup(&priv->sd);
+err_fwnode_put:
+	fwnode_handle_put(priv->sd.fwnode);
+err_entity_cleanup:
+	media_entity_cleanup(&priv->sd.entity);
+
+	return ret;
+}
+
+static void ub913_subdev_uninit(struct ub913_data *priv)
+{
+	v4l2_async_unregister_subdev(&priv->sd);
+	ub913_v4l2_nf_unregister(priv);
+	v4l2_subdev_cleanup(&priv->sd);
+	fwnode_handle_put(priv->sd.fwnode);
+	media_entity_cleanup(&priv->sd.entity);
+}
+
+static int ub913_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	struct ub913_data *priv;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->client = client;
+
+	priv->plat_data = dev_get_platdata(&client->dev);
+	if (!priv->plat_data)
+		return dev_err_probe(dev, -ENODEV, "Platform data missing\n");
+
+	priv->regmap = devm_regmap_init_i2c(client, &ub913_regmap_config);
+	if (IS_ERR(priv->regmap))
+		return dev_err_probe(dev, PTR_ERR(priv->regmap),
+				     "Failed to init regmap\n");
+
+	/*
+	 * ub913 can also work without ext clock, but that is not supported by
+	 * the driver yet.
+	 */
+	priv->clkin = devm_clk_get(dev, "clkin");
+	if (IS_ERR(priv->clkin))
+		return dev_err_probe(dev, PTR_ERR(priv->clkin),
+				     "Cannot get CLKIN\n");
+
+	ret = ub913_parse_dt(priv);
+	if (ret)
+		return ret;
+
+	ret = ub913_hw_init(priv);
+	if (ret)
+		return ret;
+
+	ret = ub913_gpiochip_probe(priv);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to init gpiochip\n");
+
+	ret = ub913_register_clkout(priv);
+	if (ret) {
+		dev_err_probe(dev, ret, "Failed to register clkout\n");
+		goto err_gpiochip_remove;
+	}
+
+	ret = ub913_subdev_init(priv);
+	if (ret)
+		goto err_gpiochip_remove;
+
+	ret = ub913_add_i2c_adapter(priv);
+	if (ret) {
+		dev_err_probe(dev, ret, "failed to add remote i2c adapter\n");
+		goto err_subdev_uninit;
+	}
+
+	return 0;
+
+err_subdev_uninit:
+	ub913_subdev_uninit(priv);
+err_gpiochip_remove:
+	ub913_gpiochip_remove(priv);
+
+	return ret;
+}
+
+static void ub913_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ub913_data *priv = sd_to_ub913(sd);
+
+	i2c_atr_del_adapter(priv->plat_data->atr, priv->plat_data->port);
+
+	ub913_subdev_uninit(priv);
+
+	ub913_gpiochip_remove(priv);
+}
+
+static const struct i2c_device_id ub913_id[] = { { "ds90ub913a-q1", 0 }, {} };
+MODULE_DEVICE_TABLE(i2c, ub913_id);
+
+static const struct of_device_id ub913_dt_ids[] = {
+	{ .compatible = "ti,ds90ub913a-q1" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, ub913_dt_ids);
+
+static struct i2c_driver ds90ub913_driver = {
+	.probe_new	= ub913_probe,
+	.remove		= ub913_remove,
+	.id_table	= ub913_id,
+	.driver = {
+		.name	= "ds90ub913a",
+		.of_match_table = ub913_dt_ids,
+	},
+};
+module_i2c_driver(ds90ub913_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Texas Instruments DS90UB913 FPD-Link III Serializer Driver");
+MODULE_AUTHOR("Luca Ceresoli <luca@lucaceresoli.net>");
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>");
+MODULE_IMPORT_NS(I2C_ATR);
diff -Naur --no-dereference a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
--- a/drivers/media/i2c/ds90ub953.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/i2c/ds90ub953.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,1402 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the Texas Instruments DS90UB953 video serializer
+ *
+ * Based on a driver from Luca Ceresoli <luca@lucaceresoli.net>
+ *
+ * Copyright (c) 2019 Luca Ceresoli <luca@lucaceresoli.net>
+ * Copyright (c) 2023 Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/fwnode.h>
+#include <linux/gpio/driver.h>
+#include <linux/i2c-atr.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/rational.h>
+#include <linux/regmap.h>
+
+#include <media/i2c/ds90ub9xx.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-subdev.h>
+
+#define UB953_PAD_SINK			0
+#define UB953_PAD_SOURCE		1
+
+#define UB953_NUM_GPIOS			4
+
+#define UB953_REG_RESET_CTL			0x01
+#define UB953_REG_RESET_CTL_DIGITAL_RESET_1	BIT(1)
+#define UB953_REG_RESET_CTL_DIGITAL_RESET_0	BIT(0)
+
+#define UB953_REG_GENERAL_CFG			0x02
+#define UB953_REG_GENERAL_CFG_CONT_CLK_SHIFT	6
+#define UB953_REG_GENERAL_CFG_CSI_LANE_SEL_SHIFT	4
+#define UB953_REG_GENERAL_CFG_CSI_LANE_SEL_MASK	GENMASK(5, 4)
+#define UB953_REG_GENERAL_CFG_CRC_TX_GEN_ENABLE	BIT(1)
+#define UB953_REG_GENERAL_CFG_I2C_STRAP_MODE	BIT(0)
+
+#define UB953_REG_MODE_SEL			0x03
+#define UB953_REG_MODE_SEL_MODE_DONE		BIT(3)
+#define UB953_REG_MODE_SEL_MODE_OVERRIDE	BIT(4)
+#define UB953_REG_MODE_SEL_MODE_MASK		GENMASK(2, 0)
+
+#define UB953_REG_CLKOUT_CTRL0			0x06
+#define UB953_REG_CLKOUT_CTRL1			0x07
+
+#define UB953_REG_SCL_HIGH_TIME			0x0b
+#define UB953_REG_SCL_LOW_TIME			0x0c
+
+#define UB953_REG_LOCAL_GPIO_DATA		0x0d
+#define UB953_REG_LOCAL_GPIO_DATA_GPIO_RMTEN(n)		BIT(4 + (n))
+#define UB953_REG_LOCAL_GPIO_DATA_GPIO_OUT_SRC(n)	BIT(0 + (n))
+
+#define UB953_REG_GPIO_INPUT_CTRL		0x0e
+#define UB953_REG_GPIO_INPUT_CTRL_OUT_EN(n)	BIT(4 + (n))
+#define UB953_REG_GPIO_INPUT_CTRL_INPUT_EN(n)	BIT(0 + (n))
+
+#define UB953_REG_REV_MASK_ID			0x50
+#define UB953_REG_GENERAL_STATUS		0x52
+
+#define UB953_REG_GPIO_PIN_STS			0x53
+#define UB953_REG_GPIO_PIN_STS_GPIO_STS(n)	BIT(0 + (n))
+
+#define UB953_REG_BIST_ERR_CNT			0x54
+#define UB953_REG_CRC_ERR_CNT1			0x55
+#define UB953_REG_CRC_ERR_CNT2			0x56
+
+#define UB953_REG_CSI_ERR_CNT			0x5c
+#define UB953_REG_CSI_ERR_STATUS		0x5d
+#define UB953_REG_CSI_ERR_DLANE01		0x5e
+#define UB953_REG_CSI_ERR_DLANE23		0x5f
+#define UB953_REG_CSI_ERR_CLK_LANE		0x60
+#define UB953_REG_CSI_PKT_HDR_VC_ID		0x61
+#define UB953_REG_PKT_HDR_WC_LSB		0x62
+#define UB953_REG_PKT_HDR_WC_MSB		0x63
+#define UB953_REG_CSI_ECC			0x64
+
+#define UB953_REG_IND_ACC_CTL			0xb0
+#define UB953_REG_IND_ACC_ADDR			0xb1
+#define UB953_REG_IND_ACC_DATA			0xb2
+
+#define UB953_REG_FPD3_RX_ID(n)			(0xf0 + (n))
+#define UB953_REG_FPD3_RX_ID_LEN		6
+
+/* Indirect register blocks */
+#define UB953_IND_TARGET_PAT_GEN		0x00
+#define UB953_IND_TARGET_FPD3_TX		0x01
+#define UB953_IND_TARGET_DIE_ID			0x02
+
+#define UB953_IND_PGEN_CTL			0x01
+#define UB953_IND_PGEN_CTL_PGEN_ENABLE		BIT(0)
+#define UB953_IND_PGEN_CFG			0x02
+#define UB953_IND_PGEN_CSI_DI			0x03
+#define UB953_IND_PGEN_LINE_SIZE1		0x04
+#define UB953_IND_PGEN_LINE_SIZE0		0x05
+#define UB953_IND_PGEN_BAR_SIZE1		0x06
+#define UB953_IND_PGEN_BAR_SIZE0		0x07
+#define UB953_IND_PGEN_ACT_LPF1			0x08
+#define UB953_IND_PGEN_ACT_LPF0			0x09
+#define UB953_IND_PGEN_TOT_LPF1			0x0a
+#define UB953_IND_PGEN_TOT_LPF0			0x0b
+#define UB953_IND_PGEN_LINE_PD1			0x0c
+#define UB953_IND_PGEN_LINE_PD0			0x0d
+#define UB953_IND_PGEN_VBP			0x0e
+#define UB953_IND_PGEN_VFP			0x0f
+#define UB953_IND_PGEN_COLOR(n)			(0x10 + (n)) /* n <= 15 */
+
+/* Note: Only sync mode supported for now */
+enum ub953_mode {
+	/* FPD-Link III CSI-2 synchronous mode */
+	UB953_MODE_SYNC,
+	/* FPD-Link III CSI-2 non-synchronous mode, external ref clock */
+	UB953_MODE_NONSYNC_EXT,
+	/* FPD-Link III CSI-2 non-synchronous mode, internal ref clock */
+	UB953_MODE_NONSYNC_INT,
+	/* FPD-Link III DVP mode */
+	UB953_MODE_DVP,
+};
+
+struct ub953_hw_data {
+	const char *model;
+	bool is_ub971;
+};
+
+struct ub953_data {
+	const struct ub953_hw_data	*hw_data;
+
+	struct i2c_client	*client;
+	struct regmap		*regmap;
+
+	u32			num_data_lanes;
+	bool			clk_cont;
+
+	struct gpio_chip	gpio_chip;
+
+	struct v4l2_subdev	sd;
+	struct media_pad	pads[2];
+
+	struct v4l2_async_notifier	notifier;
+
+	struct v4l2_subdev	*source_sd;
+	u16			source_sd_pad;
+
+	u64			enabled_source_streams;
+
+	/* lock for register access */
+	struct mutex		reg_lock;
+
+	u8			current_indirect_target;
+
+	struct clk_hw		clkout_clk_hw;
+
+	enum ub953_mode		mode;
+
+	const struct ds90ub9xx_platform_data	*plat_data;
+};
+
+static inline struct ub953_data *sd_to_ub953(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ub953_data, sd);
+}
+
+/*
+ * HW Access
+ */
+
+static int ub953_read(struct ub953_data *priv, u8 reg, u8 *val)
+{
+	unsigned int v;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = regmap_read(priv->regmap, reg, &v);
+	if (ret) {
+		dev_err(&priv->client->dev, "Cannot read register 0x%02x: %d\n",
+			reg, ret);
+		goto out_unlock;
+	}
+
+	*val = v;
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub953_write(struct ub953_data *priv, u8 reg, u8 val)
+{
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = regmap_write(priv->regmap, reg, val);
+	if (ret)
+		dev_err(&priv->client->dev,
+			"Cannot write register 0x%02x: %d\n", reg, ret);
+
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub953_select_ind_reg_block(struct ub953_data *priv, u8 block)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	if (priv->current_indirect_target == block)
+		return 0;
+
+	ret = regmap_write(priv->regmap, UB953_REG_IND_ACC_CTL, block << 2);
+	if (ret) {
+		dev_err(dev, "%s: cannot select indirect target %u (%d)\n",
+			__func__, block, ret);
+		return ret;
+	}
+
+	priv->current_indirect_target = block;
+
+	return 0;
+}
+
+__maybe_unused
+static int ub953_read_ind(struct ub953_data *priv, u8 block, u8 reg, u8 *val)
+{
+	unsigned int v;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = ub953_select_ind_reg_block(priv, block);
+	if (ret)
+		goto out_unlock;
+
+	ret = regmap_write(priv->regmap, UB953_REG_IND_ACC_ADDR, reg);
+	if (ret) {
+		dev_err(&priv->client->dev,
+			"Write to IND_ACC_ADDR failed when reading %u:%x02x: %d\n",
+			block, reg, ret);
+		goto out_unlock;
+	}
+
+	ret = regmap_read(priv->regmap, UB953_REG_IND_ACC_DATA, &v);
+	if (ret) {
+		dev_err(&priv->client->dev,
+			"Write to IND_ACC_DATA failed when reading %u:%x02x: %d\n",
+			block, reg, ret);
+		goto out_unlock;
+	}
+
+	*val = v;
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+__maybe_unused
+static int ub953_write_ind(struct ub953_data *priv, u8 block, u8 reg, u8 val)
+{
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = ub953_select_ind_reg_block(priv, block);
+	if (ret)
+		goto out_unlock;
+
+	ret = regmap_write(priv->regmap, UB953_REG_IND_ACC_ADDR, reg);
+	if (ret) {
+		dev_err(&priv->client->dev,
+			"Write to IND_ACC_ADDR failed when writing %u:%x02x: %d\n",
+			block, reg, ret);
+		goto out_unlock;
+	}
+
+	ret = regmap_write(priv->regmap, UB953_REG_IND_ACC_DATA, val);
+	if (ret) {
+		dev_err(&priv->client->dev,
+			"Write to IND_ACC_DATA failed when writing %u:%x02x\n: %d\n",
+			block, reg, ret);
+	}
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+/*
+ * GPIO chip
+ */
+static int ub953_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+	struct ub953_data *priv = gpiochip_get_data(gc);
+	int ret;
+	u8 v;
+
+	ret = ub953_read(priv, UB953_REG_GPIO_INPUT_CTRL, &v);
+	if (ret)
+		return ret;
+
+	if (v & UB953_REG_GPIO_INPUT_CTRL_INPUT_EN(offset))
+		return GPIO_LINE_DIRECTION_IN;
+	else
+		return GPIO_LINE_DIRECTION_OUT;
+}
+
+static int ub953_gpio_direction_in(struct gpio_chip *gc, unsigned int offset)
+{
+	struct ub953_data *priv = gpiochip_get_data(gc);
+
+	return regmap_update_bits(priv->regmap, UB953_REG_GPIO_INPUT_CTRL,
+				  UB953_REG_GPIO_INPUT_CTRL_INPUT_EN(offset) |
+					  UB953_REG_GPIO_INPUT_CTRL_OUT_EN(offset),
+				  UB953_REG_GPIO_INPUT_CTRL_INPUT_EN(offset));
+}
+
+static int ub953_gpio_direction_out(struct gpio_chip *gc, unsigned int offset,
+				    int value)
+{
+	struct ub953_data *priv = gpiochip_get_data(gc);
+	int ret;
+
+	ret = regmap_update_bits(priv->regmap, UB953_REG_LOCAL_GPIO_DATA,
+				 UB953_REG_LOCAL_GPIO_DATA_GPIO_OUT_SRC(offset),
+				 value ? UB953_REG_LOCAL_GPIO_DATA_GPIO_OUT_SRC(offset) :
+					 0);
+
+	if (ret)
+		return ret;
+
+	return regmap_update_bits(priv->regmap, UB953_REG_GPIO_INPUT_CTRL,
+				  UB953_REG_GPIO_INPUT_CTRL_INPUT_EN(offset) |
+					  UB953_REG_GPIO_INPUT_CTRL_OUT_EN(offset),
+				  UB953_REG_GPIO_INPUT_CTRL_OUT_EN(offset));
+}
+
+static int ub953_gpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+	struct ub953_data *priv = gpiochip_get_data(gc);
+	int ret;
+	u8 v;
+
+	ret = ub953_read(priv, UB953_REG_GPIO_PIN_STS, &v);
+	if (ret)
+		return ret;
+
+	return !!(v & UB953_REG_GPIO_PIN_STS_GPIO_STS(offset));
+}
+
+static void ub953_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
+{
+	struct ub953_data *priv = gpiochip_get_data(gc);
+
+	regmap_update_bits(priv->regmap, UB953_REG_LOCAL_GPIO_DATA,
+			   UB953_REG_LOCAL_GPIO_DATA_GPIO_OUT_SRC(offset),
+			   value ? UB953_REG_LOCAL_GPIO_DATA_GPIO_OUT_SRC(offset) :
+				   0);
+}
+
+static int ub953_gpio_of_xlate(struct gpio_chip *gc,
+			       const struct of_phandle_args *gpiospec,
+			       u32 *flags)
+{
+	if (flags)
+		*flags = gpiospec->args[1];
+
+	return gpiospec->args[0];
+}
+
+static int ub953_gpiochip_probe(struct ub953_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	struct gpio_chip *gc = &priv->gpio_chip;
+	int ret;
+
+	/* Set all GPIOs to local input mode */
+	ub953_write(priv, UB953_REG_LOCAL_GPIO_DATA, 0);
+	ub953_write(priv, UB953_REG_GPIO_INPUT_CTRL, 0xf);
+
+	gc->label = dev_name(dev);
+	gc->parent = dev;
+	gc->owner = THIS_MODULE;
+	gc->base = -1;
+	gc->can_sleep = true;
+	gc->ngpio = UB953_NUM_GPIOS;
+	gc->get_direction = ub953_gpio_get_direction;
+	gc->direction_input = ub953_gpio_direction_in;
+	gc->direction_output = ub953_gpio_direction_out;
+	gc->get = ub953_gpio_get;
+	gc->set = ub953_gpio_set;
+	gc->of_xlate = ub953_gpio_of_xlate;
+	gc->of_gpio_n_cells = 2;
+
+	ret = gpiochip_add_data(gc, priv);
+	if (ret) {
+		dev_err(dev, "Failed to add GPIOs: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void ub953_gpiochip_remove(struct ub953_data *priv)
+{
+	gpiochip_remove(&priv->gpio_chip);
+}
+
+/*
+ * V4L2
+ */
+
+static int _ub953_set_routing(struct v4l2_subdev *sd,
+			      struct v4l2_subdev_state *state,
+			      struct v4l2_subdev_krouting *routing)
+{
+	static const struct v4l2_mbus_framefmt format = {
+		.width = 640,
+		.height = 480,
+		.code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.field = V4L2_FIELD_NONE,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.ycbcr_enc = V4L2_YCBCR_ENC_601,
+		.quantization = V4L2_QUANTIZATION_LIM_RANGE,
+		.xfer_func = V4L2_XFER_FUNC_SRGB,
+	};
+	int ret;
+
+	/*
+	 * Note: we can only support up to V4L2_FRAME_DESC_ENTRY_MAX, until
+	 * frame desc is made dynamically allocated.
+	 */
+
+	if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX)
+		return -EINVAL;
+
+	ret = v4l2_subdev_routing_validate(sd, routing,
+					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
+	if (ret)
+		return ret;
+
+	ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int ub953_set_routing(struct v4l2_subdev *sd,
+			     struct v4l2_subdev_state *state,
+			     enum v4l2_subdev_format_whence which,
+			     struct v4l2_subdev_krouting *routing)
+{
+	struct ub953_data *priv = sd_to_ub953(sd);
+
+	if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams)
+		return -EBUSY;
+
+	return _ub953_set_routing(sd, state, routing);
+}
+
+static int ub953_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+				struct v4l2_mbus_frame_desc *fd)
+{
+	struct ub953_data *priv = sd_to_ub953(sd);
+	struct v4l2_mbus_frame_desc source_fd;
+	struct v4l2_subdev_route *route;
+	struct v4l2_subdev_state *state;
+	int ret;
+
+	if (pad != UB953_PAD_SOURCE)
+		return -EINVAL;
+
+	ret = v4l2_subdev_call(priv->source_sd, pad, get_frame_desc,
+			       priv->source_sd_pad, &source_fd);
+	if (ret)
+		return ret;
+
+	memset(fd, 0, sizeof(*fd));
+
+	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
+
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	for_each_active_route(&state->routing, route) {
+		struct v4l2_mbus_frame_desc_entry *source_entry = NULL;
+		unsigned int i;
+
+		if (route->source_pad != pad)
+			continue;
+
+		for (i = 0; i < source_fd.num_entries; i++) {
+			if (source_fd.entry[i].stream == route->sink_stream) {
+				source_entry = &source_fd.entry[i];
+				break;
+			}
+		}
+
+		if (!source_entry) {
+			dev_err(&priv->client->dev,
+				"Failed to find stream from source frame desc\n");
+			ret = -EPIPE;
+			goto out_unlock;
+		}
+
+		fd->entry[fd->num_entries].stream = route->source_stream;
+		fd->entry[fd->num_entries].flags = source_entry->flags;
+		fd->entry[fd->num_entries].length = source_entry->length;
+		fd->entry[fd->num_entries].pixelcode = source_entry->pixelcode;
+		fd->entry[fd->num_entries].bus.csi2.vc =
+			source_entry->bus.csi2.vc;
+		fd->entry[fd->num_entries].bus.csi2.dt =
+			source_entry->bus.csi2.dt;
+
+		fd->num_entries++;
+	}
+
+out_unlock:
+	v4l2_subdev_unlock_state(state);
+
+	return ret;
+}
+
+static int ub953_set_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_subdev_state *state,
+			 struct v4l2_subdev_format *format)
+{
+	struct ub953_data *priv = sd_to_ub953(sd);
+	struct v4l2_mbus_framefmt *fmt;
+
+	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
+	    priv->enabled_source_streams)
+		return -EBUSY;
+
+	/* No transcoding, source and sink formats must match. */
+	if (format->pad == UB953_PAD_SOURCE)
+		return v4l2_subdev_get_fmt(sd, state, format);
+
+	/* Set sink format */
+	fmt = v4l2_subdev_state_get_stream_format(state, format->pad,
+						  format->stream);
+	if (!fmt)
+		return -EINVAL;
+
+	*fmt = format->format;
+
+	/* Propagate to source format */
+	fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
+							   format->stream);
+	if (!fmt)
+		return -EINVAL;
+
+	*fmt = format->format;
+
+	return 0;
+}
+
+static int ub953_init_cfg(struct v4l2_subdev *sd,
+			  struct v4l2_subdev_state *state)
+{
+	struct v4l2_subdev_route routes[] = {
+		{
+			.sink_pad = UB953_PAD_SINK,
+			.sink_stream = 0,
+			.source_pad = UB953_PAD_SOURCE,
+			.source_stream = 0,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+	};
+
+	struct v4l2_subdev_krouting routing = {
+		.num_routes = ARRAY_SIZE(routes),
+		.routes = routes,
+	};
+
+	return _ub953_set_routing(sd, state, &routing);
+}
+
+static int ub953_log_status(struct v4l2_subdev *sd)
+{
+	struct ub953_data *priv = sd_to_ub953(sd);
+	struct device *dev = &priv->client->dev;
+	u8 v = 0, v1 = 0, v2 = 0;
+	unsigned int i;
+	char id[UB953_REG_FPD3_RX_ID_LEN];
+	u8 gpio_local_data;
+	u8 gpio_input_ctrl;
+	u8 gpio_pin_sts;
+
+	for (i = 0; i < sizeof(id); i++)
+		ub953_read(priv, UB953_REG_FPD3_RX_ID(i), &id[i]);
+
+	dev_info(dev, "ID '%.*s'\n", (int)sizeof(id), id);
+
+	ub953_read(priv, UB953_REG_GENERAL_STATUS, &v);
+	dev_info(dev, "GENERAL_STATUS %#02x\n", v);
+
+	ub953_read(priv, UB953_REG_CRC_ERR_CNT1, &v1);
+	ub953_read(priv, UB953_REG_CRC_ERR_CNT2, &v2);
+	dev_info(dev, "CRC error count %u\n", v1 | (v2 << 8));
+
+	ub953_read(priv, UB953_REG_CSI_ERR_CNT, &v);
+	dev_info(dev, "CSI error count %u\n", v);
+
+	ub953_read(priv, UB953_REG_CSI_ERR_STATUS, &v);
+	dev_info(dev, "CSI_ERR_STATUS %#02x\n", v);
+
+	ub953_read(priv, UB953_REG_CSI_ERR_DLANE01, &v);
+	dev_info(dev, "CSI_ERR_DLANE01 %#02x\n", v);
+
+	ub953_read(priv, UB953_REG_CSI_ERR_DLANE23, &v);
+	dev_info(dev, "CSI_ERR_DLANE23 %#02x\n", v);
+
+	ub953_read(priv, UB953_REG_CSI_ERR_CLK_LANE, &v);
+	dev_info(dev, "CSI_ERR_CLK_LANE %#02x\n", v);
+
+	ub953_read(priv, UB953_REG_CSI_PKT_HDR_VC_ID, &v);
+	dev_info(dev, "CSI packet header VC %u ID %u\n", v >> 6, v & 0x3f);
+
+	ub953_read(priv, UB953_REG_PKT_HDR_WC_LSB, &v1);
+	ub953_read(priv, UB953_REG_PKT_HDR_WC_MSB, &v2);
+	dev_info(dev, "CSI packet header WC %u\n", (v2 << 8) | v1);
+
+	ub953_read(priv, UB953_REG_CSI_ECC, &v);
+	dev_info(dev, "CSI ECC %#02x\n", v);
+
+	ub953_read(priv, UB953_REG_LOCAL_GPIO_DATA, &gpio_local_data);
+	ub953_read(priv, UB953_REG_GPIO_INPUT_CTRL, &gpio_input_ctrl);
+	ub953_read(priv, UB953_REG_GPIO_PIN_STS, &gpio_pin_sts);
+
+	for (i = 0; i < UB953_NUM_GPIOS; i++) {
+		dev_info(dev,
+			 "GPIO%u: remote: %u is_input: %u is_output: %u val: %u sts: %u\n",
+			 i,
+			 !!(gpio_local_data & UB953_REG_LOCAL_GPIO_DATA_GPIO_RMTEN(i)),
+			 !!(gpio_input_ctrl & UB953_REG_GPIO_INPUT_CTRL_INPUT_EN(i)),
+			 !!(gpio_input_ctrl & UB953_REG_GPIO_INPUT_CTRL_OUT_EN(i)),
+			 !!(gpio_local_data & UB953_REG_LOCAL_GPIO_DATA_GPIO_OUT_SRC(i)),
+			 !!(gpio_pin_sts & UB953_REG_GPIO_PIN_STS_GPIO_STS(i)));
+	}
+
+	return 0;
+}
+
+static int ub953_enable_streams(struct v4l2_subdev *sd,
+				struct v4l2_subdev_state *state, u32 pad,
+				u64 streams_mask)
+{
+	struct ub953_data *priv = sd_to_ub953(sd);
+	u64 sink_streams;
+	int ret;
+
+	sink_streams = v4l2_subdev_state_xlate_streams(state, UB953_PAD_SOURCE,
+						       UB953_PAD_SINK,
+						       &streams_mask);
+
+	ret = v4l2_subdev_enable_streams(priv->source_sd, priv->source_sd_pad,
+					 sink_streams);
+	if (ret)
+		return ret;
+
+	priv->enabled_source_streams |= streams_mask;
+
+	return 0;
+}
+
+static int ub953_disable_streams(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_state *state, u32 pad,
+				 u64 streams_mask)
+{
+	struct ub953_data *priv = sd_to_ub953(sd);
+	u64 sink_streams;
+	int ret;
+
+	sink_streams = v4l2_subdev_state_xlate_streams(state, UB953_PAD_SOURCE,
+						       UB953_PAD_SINK,
+						       &streams_mask);
+
+	ret = v4l2_subdev_disable_streams(priv->source_sd, priv->source_sd_pad,
+					  sink_streams);
+	if (ret)
+		return ret;
+
+	priv->enabled_source_streams &= ~streams_mask;
+
+	return 0;
+}
+
+static const struct v4l2_subdev_pad_ops ub953_pad_ops = {
+	.enable_streams = ub953_enable_streams,
+	.disable_streams = ub953_disable_streams,
+	.set_routing = ub953_set_routing,
+	.get_frame_desc = ub953_get_frame_desc,
+	.get_fmt = v4l2_subdev_get_fmt,
+	.set_fmt = ub953_set_fmt,
+	.init_cfg = ub953_init_cfg,
+};
+
+static const struct v4l2_subdev_core_ops ub953_subdev_core_ops = {
+	.log_status = ub953_log_status,
+	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_ops ub953_subdev_ops = {
+	.core = &ub953_subdev_core_ops,
+	.pad = &ub953_pad_ops,
+};
+
+static const struct media_entity_operations ub953_entity_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+};
+
+static int ub953_notify_bound(struct v4l2_async_notifier *notifier,
+			      struct v4l2_subdev *source_subdev,
+			      struct v4l2_async_subdev *asd)
+{
+	struct ub953_data *priv = sd_to_ub953(notifier->sd);
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	ret = media_entity_get_fwnode_pad(&source_subdev->entity,
+					  source_subdev->fwnode,
+					  MEDIA_PAD_FL_SOURCE);
+	if (ret < 0) {
+		dev_err(dev, "Failed to find pad for %s\n",
+			source_subdev->name);
+		return ret;
+	}
+
+	priv->source_sd = source_subdev;
+	priv->source_sd_pad = ret;
+
+	ret = media_create_pad_link(&source_subdev->entity, priv->source_sd_pad,
+				    &priv->sd.entity, 0,
+				    MEDIA_LNK_FL_ENABLED |
+					    MEDIA_LNK_FL_IMMUTABLE);
+	if (ret) {
+		dev_err(dev, "Unable to link %s:%u -> %s:0\n",
+			source_subdev->name, priv->source_sd_pad,
+			priv->sd.name);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_async_notifier_operations ub953_notify_ops = {
+	.bound = ub953_notify_bound,
+};
+
+static int ub953_v4l2_notifier_register(struct ub953_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	struct v4l2_async_subdev *asd;
+	struct fwnode_handle *ep_fwnode;
+	int ret;
+
+	ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
+						    UB953_PAD_SINK, 0, 0);
+	if (!ep_fwnode) {
+		dev_err(dev, "No graph endpoint\n");
+		return -ENODEV;
+	}
+
+	v4l2_async_nf_init(&priv->notifier);
+
+	asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep_fwnode,
+					      struct v4l2_async_subdev);
+
+	fwnode_handle_put(ep_fwnode);
+
+	if (IS_ERR(asd)) {
+		dev_err(dev, "Failed to add subdev: %ld", PTR_ERR(asd));
+		v4l2_async_nf_cleanup(&priv->notifier);
+		return PTR_ERR(asd);
+	}
+
+	priv->notifier.ops = &ub953_notify_ops;
+
+	ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier);
+	if (ret) {
+		dev_err(dev, "Failed to register subdev_notifier");
+		v4l2_async_nf_cleanup(&priv->notifier);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void ub953_v4l2_notifier_unregister(struct ub953_data *priv)
+{
+	v4l2_async_nf_unregister(&priv->notifier);
+	v4l2_async_nf_cleanup(&priv->notifier);
+}
+
+/*
+ * Probing
+ */
+
+static int ub953_i2c_master_init(struct ub953_data *priv)
+{
+	/* i2c fast mode */
+	u32 ref = 26250000;
+	u32 scl_high = 915; /* ns */
+	u32 scl_low = 1641; /* ns */
+	int ret;
+
+	scl_high = div64_u64((u64)scl_high * ref, 1000000000) - 5;
+	scl_low = div64_u64((u64)scl_low * ref, 1000000000) - 5;
+
+	ret = ub953_write(priv, UB953_REG_SCL_HIGH_TIME, scl_high);
+	if (ret)
+		return ret;
+
+	ret = ub953_write(priv, UB953_REG_SCL_LOW_TIME, scl_low);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static u64 ub953_get_fc_rate(struct ub953_data *priv)
+{
+	if (priv->mode != UB953_MODE_SYNC) {
+		/* Not supported */
+		return 0;
+	}
+
+	if (priv->hw_data->is_ub971)
+		return priv->plat_data->bc_rate * 160ull;
+	else
+		return priv->plat_data->bc_rate / 2 * 160ull;
+}
+
+static unsigned long ub953_calc_clkout_ub953(struct ub953_data *priv,
+					     unsigned long target, u64 fc,
+					     u8 *hs_div, u8 *m, u8 *n)
+{
+	/*
+	 * We always use 4 as a pre-divider (HS_CLK_DIV = 2).
+	 *
+	 * According to the datasheet:
+	 * - "HS_CLK_DIV typically should be set to either 16, 8, or 4 (default)."
+	 * - "if it is not possible to have an integer ratio of N/M, it is best to
+	 *    select a smaller value for HS_CLK_DIV.
+	 *
+	 * For above reasons the default HS_CLK_DIV seems the best in the average
+	 * case. Use always that value to keep the code simple.
+	 */
+	static const unsigned long hs_clk_div = 4;
+
+	u64 fc_divided;
+	unsigned long mul, div;
+	unsigned long res;
+
+	/* clkout = fc / hs_clk_div * m / n */
+
+	fc_divided = div_u64(fc, hs_clk_div);
+
+	rational_best_approximation(target, fc_divided, (1 << 5) - 1,
+				    (1 << 8) - 1, &mul, &div);
+
+	res = div_u64(fc_divided * mul, div);
+
+	*hs_div = hs_clk_div;
+	*m = mul;
+	*n = div;
+
+	return res;
+}
+
+static unsigned long ub953_calc_clkout_ub971(struct ub953_data *priv,
+					     unsigned long target, u64 fc,
+					     u8 *m, u8 *n)
+{
+	u64 fc_divided;
+	unsigned long mul, div;
+	unsigned long res;
+
+	/* clkout = fc * m / (8 * n) */
+
+	fc_divided = div_u64(fc, 8);
+
+	rational_best_approximation(target, fc_divided, (1 << 5) - 1,
+				    (1 << 8) - 1, &mul, &div);
+
+	res = div_u64(fc_divided * mul, div);
+
+	*m = mul;
+	*n = div;
+
+	return res;
+}
+
+static unsigned long ub953_clkout_recalc_rate(struct clk_hw *hw,
+					      unsigned long parent_rate)
+{
+	struct ub953_data *priv = container_of(hw, struct ub953_data, clkout_clk_hw);
+	struct device *dev = &priv->client->dev;
+	u8 ctrl0, ctrl1;
+	u32 mul, div;
+	u64 fc_rate;
+	u32 hs_clk_div;
+	u64 rate;
+	int ret;
+
+	ret = ub953_read(priv, UB953_REG_CLKOUT_CTRL0, &ctrl0);
+	if (ret) {
+		dev_err(dev, "Failed to read CLKOUT_CTRL0: %d\n", ret);
+		return 0;
+	}
+
+	ret = ub953_read(priv, UB953_REG_CLKOUT_CTRL1, &ctrl1);
+	if (ret) {
+		dev_err(dev, "Failed to read CLKOUT_CTRL1: %d\n", ret);
+		return 0;
+	}
+
+	fc_rate = ub953_get_fc_rate(priv);
+
+	if (priv->hw_data->is_ub971) {
+		mul = ctrl0 & 0x1f;
+		div = ctrl1;
+
+		if (div == 0)
+			return 0;
+
+		rate = div_u64(fc_rate * mul, 8 * div);
+
+		dev_dbg(dev, "clkout: fc rate %llu, mul %u, div %u = %llu\n",
+			fc_rate, mul, div, rate);
+	} else {
+		mul = ctrl0 & 0x1f;
+		hs_clk_div = 1 << (ctrl0 >> 5);
+		div = ctrl1;
+
+		if (div == 0)
+			return 0;
+
+		rate = div_u64(div_u64(fc_rate, hs_clk_div) * mul, div);
+
+		dev_dbg(dev,
+			"clkout: fc rate %llu, hs_clk_div %u, mul %u, div %u = %llu\n",
+			fc_rate, hs_clk_div, mul, div, rate);
+	}
+
+	return rate;
+}
+
+static long ub953_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long *parent_rate)
+{
+	struct ub953_data *priv = container_of(hw, struct ub953_data, clkout_clk_hw);
+	struct device *dev = &priv->client->dev;
+	unsigned long res;
+	u64 fc_rate;
+	u8 hs_div, m, n;
+
+	fc_rate = ub953_get_fc_rate(priv);
+
+	if (priv->hw_data->is_ub971) {
+		res = ub953_calc_clkout_ub971(priv, rate, fc_rate, &m, &n);
+
+		dev_dbg(dev, "%s %llu * %u / (8 * %u) = %lu (requested %lu)",
+			__func__, fc_rate, m, n, res, rate);
+	} else {
+		res = ub953_calc_clkout_ub953(priv, rate, fc_rate, &hs_div, &m, &n);
+
+		dev_dbg(dev, "%s %llu / %u * %u / %u = %lu (requested %lu)",
+			__func__, fc_rate, hs_div, m, n, res, rate);
+	}
+
+	return res;
+}
+
+static int ub953_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
+				 unsigned long parent_rate)
+{
+	struct ub953_data *priv = container_of(hw, struct ub953_data, clkout_clk_hw);
+	u64 fc_rate;
+	u8 hs_div, m, n;
+	unsigned long res;
+
+	fc_rate = ub953_get_fc_rate(priv);
+
+	if (priv->hw_data->is_ub971) {
+		res = ub953_calc_clkout_ub971(priv, rate, fc_rate, &m, &n);
+
+		ub953_write(priv, UB953_REG_CLKOUT_CTRL0, m);
+		ub953_write(priv, UB953_REG_CLKOUT_CTRL1, n);
+	} else {
+		res = ub953_calc_clkout_ub953(priv, rate, fc_rate, &hs_div, &m, &n);
+
+		ub953_write(priv, UB953_REG_CLKOUT_CTRL0, (__ffs(hs_div) << 5) | m);
+		ub953_write(priv, UB953_REG_CLKOUT_CTRL1, n);
+	}
+
+	dev_dbg(&priv->client->dev, "%s %lu (requested %lu)\n", __func__, res,
+		rate);
+
+	return 0;
+}
+
+static const struct clk_ops ub953_clkout_ops = {
+	.recalc_rate	= ub953_clkout_recalc_rate,
+	.round_rate	= ub953_clkout_round_rate,
+	.set_rate	= ub953_clkout_set_rate,
+};
+
+static void ub953_init_clkout_ub953(struct ub953_data *priv)
+{
+	u64 fc_rate;
+	u8 hs_div, m, n;
+
+	fc_rate = ub953_get_fc_rate(priv);
+
+	ub953_calc_clkout_ub953(priv, 25000000, fc_rate, &hs_div, &m, &n);
+
+	ub953_write(priv, UB953_REG_CLKOUT_CTRL0, (__ffs(hs_div) << 5) | m);
+	ub953_write(priv, UB953_REG_CLKOUT_CTRL1, n);
+}
+
+static void ub953_init_clkout_ub971(struct ub953_data *priv)
+{
+	u64 fc_rate;
+	u8 m, n;
+
+	fc_rate = ub953_get_fc_rate(priv);
+
+	ub953_calc_clkout_ub971(priv, 25000000, fc_rate, &m, &n);
+
+	ub953_write(priv, UB953_REG_CLKOUT_CTRL0, m);
+	ub953_write(priv, UB953_REG_CLKOUT_CTRL1, n);
+}
+
+static int ub953_register_clkout(struct ub953_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	const struct clk_init_data init = {
+		.name = kasprintf(GFP_KERNEL, "ds90%s.%s.clk_out",
+				  priv->hw_data->model, dev_name(dev)),
+		.ops = &ub953_clkout_ops,
+	};
+	int ret;
+
+	if (!init.name)
+		return -ENOMEM;
+
+	/* Initialize clkout to 25MHz by default */
+	if (priv->hw_data->is_ub971)
+		ub953_init_clkout_ub971(priv);
+	else
+		ub953_init_clkout_ub953(priv);
+
+	priv->clkout_clk_hw.init = &init;
+
+	ret = devm_clk_hw_register(dev, &priv->clkout_clk_hw);
+	kfree(init.name);
+	if (ret)
+		return dev_err_probe(dev, ret, "Cannot register clock HW\n");
+
+	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
+					  &priv->clkout_clk_hw);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Cannot add OF clock provider\n");
+
+	return 0;
+}
+
+static int ub953_add_i2c_adapter(struct ub953_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	struct fwnode_handle *i2c_handle;
+	int ret;
+
+	i2c_handle = device_get_named_child_node(dev, "i2c");
+	if (!i2c_handle)
+		return 0;
+
+	ret = i2c_atr_add_adapter(priv->plat_data->atr, priv->plat_data->port,
+				  dev, i2c_handle);
+
+	fwnode_handle_put(i2c_handle);
+
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static const struct regmap_config ub953_regmap_config = {
+	.name = "ds90ub953",
+	.reg_bits = 8,
+	.val_bits = 8,
+	.reg_format_endian = REGMAP_ENDIAN_DEFAULT,
+	.val_format_endian = REGMAP_ENDIAN_DEFAULT,
+};
+
+static int ub953_parse_dt(struct ub953_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	struct fwnode_handle *ep_fwnode;
+	int ret;
+
+	ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
+						    UB953_PAD_SINK, 0, 0);
+	if (!ep_fwnode)
+		return dev_err_probe(dev, -ENOENT, "no endpoint found\n");
+
+	ret = fwnode_property_count_u32(ep_fwnode, "data-lanes");
+
+	if (ret < 0)
+		return dev_err_probe(dev, ret,
+				     "failed to parse property 'data-lanes'\n");
+
+	if (ret != 1 && ret != 2 && ret != 4)
+		return dev_err_probe(dev, -EINVAL,
+				     "bad number of data-lanes: %d\n", ret);
+
+	priv->num_data_lanes = ret;
+
+	priv->clk_cont = !fwnode_property_read_bool(ep_fwnode,
+						    "clock-noncontinuous");
+
+	fwnode_handle_put(ep_fwnode);
+	return 0;
+}
+
+static int ub953_hw_init(struct ub953_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	bool mode_override;
+	int ret;
+	u8 v;
+
+	ret = ub953_read(priv, UB953_REG_MODE_SEL, &v);
+	if (ret)
+		return ret;
+
+	if (!(v & UB953_REG_MODE_SEL_MODE_DONE))
+		return dev_err_probe(dev, -EIO, "Mode value not stabilized\n");
+
+	mode_override = v & UB953_REG_MODE_SEL_MODE_OVERRIDE;
+
+	switch (v & UB953_REG_MODE_SEL_MODE_MASK) {
+	case 0:
+		priv->mode = UB953_MODE_SYNC;
+		break;
+	case 2:
+		priv->mode = UB953_MODE_NONSYNC_EXT;
+		break;
+	case 3:
+		priv->mode = UB953_MODE_NONSYNC_INT;
+		break;
+	case 5:
+		priv->mode = UB953_MODE_DVP;
+		break;
+	default:
+		return dev_err_probe(dev, -EIO,
+				     "Invalid mode in mode register\n");
+	}
+
+	dev_dbg(dev, "mode from %s: %#x\n", mode_override ? "reg" : "strap",
+		priv->mode);
+
+	if (priv->mode != UB953_MODE_SYNC)
+		return dev_err_probe(dev, -ENODEV,
+				     "Only synchronous mode supported\n");
+
+	ret = ub953_read(priv, UB953_REG_REV_MASK_ID, &v);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to read revision");
+
+	dev_info(dev, "Found %s rev/mask %#04x\n", priv->hw_data->model, v);
+
+	ret = ub953_read(priv, UB953_REG_GENERAL_CFG, &v);
+	if (ret)
+		return ret;
+
+	dev_dbg(dev, "i2c strap setting %s V\n",
+		(v & UB953_REG_GENERAL_CFG_I2C_STRAP_MODE) ? "1.8" : "3.3");
+	ret = ub953_i2c_master_init(priv);
+	if (ret)
+		return dev_err_probe(dev, ret, "i2c init failed\n");
+
+	ub953_write(priv, UB953_REG_GENERAL_CFG,
+		    (priv->clk_cont << UB953_REG_GENERAL_CFG_CONT_CLK_SHIFT) |
+		    ((priv->num_data_lanes - 1) << UB953_REG_GENERAL_CFG_CSI_LANE_SEL_SHIFT) |
+		    UB953_REG_GENERAL_CFG_CRC_TX_GEN_ENABLE);
+
+	return 0;
+}
+
+static int ub953_subdev_init(struct ub953_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	v4l2_i2c_subdev_init(&priv->sd, priv->client, &ub953_subdev_ops);
+
+	priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+			  V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_STREAMS;
+	priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+	priv->sd.entity.ops = &ub953_entity_ops;
+
+	priv->pads[0].flags = MEDIA_PAD_FL_SINK;
+	priv->pads[1].flags = MEDIA_PAD_FL_SOURCE;
+
+	ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to init pads\n");
+
+	priv->sd.fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
+							  UB953_PAD_SOURCE, 0,
+							  0);
+	if (!priv->sd.fwnode) {
+		ret = -ENODEV;
+		dev_err_probe(dev, ret, "Missing TX endpoint\n");
+		goto err_entity_cleanup;
+	}
+
+	ret = v4l2_subdev_init_finalize(&priv->sd);
+	if (ret)
+		goto err_fwnode_put;
+
+	ret = ub953_v4l2_notifier_register(priv);
+	if (ret) {
+		dev_err_probe(dev, ret,
+			      "v4l2 subdev notifier register failed\n");
+		goto err_free_state;
+	}
+
+	ret = v4l2_async_register_subdev(&priv->sd);
+	if (ret) {
+		dev_err_probe(dev, ret, "v4l2_async_register_subdev error\n");
+		goto err_unreg_notif;
+	}
+
+	return 0;
+
+err_unreg_notif:
+	ub953_v4l2_notifier_unregister(priv);
+err_free_state:
+	v4l2_subdev_cleanup(&priv->sd);
+err_fwnode_put:
+	fwnode_handle_put(priv->sd.fwnode);
+err_entity_cleanup:
+	media_entity_cleanup(&priv->sd.entity);
+
+	return ret;
+}
+
+static void ub953_subdev_uninit(struct ub953_data *priv)
+{
+	v4l2_async_unregister_subdev(&priv->sd);
+	ub953_v4l2_notifier_unregister(priv);
+	v4l2_subdev_cleanup(&priv->sd);
+	fwnode_handle_put(priv->sd.fwnode);
+	media_entity_cleanup(&priv->sd.entity);
+}
+
+static int ub953_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	struct ub953_data *priv;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->client = client;
+
+	priv->hw_data = device_get_match_data(dev);
+
+	priv->plat_data = dev_get_platdata(&client->dev);
+	if (!priv->plat_data)
+		return dev_err_probe(dev, -ENODEV, "Platform data missing\n");
+
+	mutex_init(&priv->reg_lock);
+
+	/*
+	 * Initialize to invalid values so that the first reg writes will
+	 * configure the target.
+	 */
+	priv->current_indirect_target = 0xff;
+
+	priv->regmap = devm_regmap_init_i2c(client, &ub953_regmap_config);
+	if (IS_ERR(priv->regmap)) {
+		ret = PTR_ERR(priv->regmap);
+		dev_err_probe(dev, ret, "Failed to init regmap\n");
+		goto err_mutex_destroy;
+	}
+
+	ret = ub953_parse_dt(priv);
+	if (ret)
+		goto err_mutex_destroy;
+
+	ret = ub953_hw_init(priv);
+	if (ret)
+		goto err_mutex_destroy;
+
+	ret = ub953_gpiochip_probe(priv);
+	if (ret) {
+		dev_err_probe(dev, ret, "Failed to init gpiochip\n");
+		goto err_mutex_destroy;
+	}
+
+	ret = ub953_register_clkout(priv);
+	if (ret) {
+		dev_err_probe(dev, ret, "Failed to register clkout\n");
+		goto err_gpiochip_remove;
+	}
+
+	ret = ub953_subdev_init(priv);
+	if (ret)
+		goto err_gpiochip_remove;
+
+	ret = ub953_add_i2c_adapter(priv);
+	if (ret) {
+		dev_err_probe(dev, ret, "failed to add remote i2c adapter\n");
+		goto err_subdev_uninit;
+	}
+
+	return 0;
+
+err_subdev_uninit:
+	ub953_subdev_uninit(priv);
+err_gpiochip_remove:
+	ub953_gpiochip_remove(priv);
+err_mutex_destroy:
+	mutex_destroy(&priv->reg_lock);
+
+	return ret;
+}
+
+static void ub953_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ub953_data *priv = sd_to_ub953(sd);
+
+	i2c_atr_del_adapter(priv->plat_data->atr, priv->plat_data->port);
+
+	ub953_subdev_uninit(priv);
+
+	ub953_gpiochip_remove(priv);
+	mutex_destroy(&priv->reg_lock);
+}
+
+static const struct ub953_hw_data ds90ub953_hw = {
+	.model = "ub953",
+};
+
+static const struct ub953_hw_data ds90ub971_hw = {
+	.model = "ub971",
+	.is_ub971 = true,
+};
+
+static const struct i2c_device_id ub953_id[] = {
+	{ "ds90ub953-q1", (kernel_ulong_t)&ds90ub953_hw },
+	{ "ds90ub971-q1", (kernel_ulong_t)&ds90ub971_hw },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, ub953_id);
+
+static const struct of_device_id ub953_dt_ids[] = {
+	{ .compatible = "ti,ds90ub953-q1", .data = &ds90ub953_hw },
+	{ .compatible = "ti,ds90ub971-q1", .data = &ds90ub971_hw },
+	{}
+};
+MODULE_DEVICE_TABLE(of, ub953_dt_ids);
+
+static struct i2c_driver ds90ub953_driver = {
+	.probe_new	= ub953_probe,
+	.remove		= ub953_remove,
+	.id_table	= ub953_id,
+	.driver = {
+		.name	= "ds90ub953",
+		.owner = THIS_MODULE,
+		.of_match_table = ub953_dt_ids,
+	},
+};
+module_i2c_driver(ds90ub953_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Texas Instruments FPD-Link III/IV CSI-2 Serializers Driver");
+MODULE_AUTHOR("Luca Ceresoli <luca@lucaceresoli.net>");
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>");
+MODULE_IMPORT_NS(I2C_ATR);
diff -Naur --no-dereference a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
--- a/drivers/media/i2c/ds90ub960.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/i2c/ds90ub960.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,4062 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the Texas Instruments DS90UB960-Q1 video deserializer
+ *
+ * Copyright (c) 2019 Luca Ceresoli <luca@lucaceresoli.net>
+ * Copyright (c) 2023 Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+ */
+
+/*
+ * (Possible) TODOs:
+ *
+ * - PM for serializer and remote peripherals. We need to manage:
+ *   - VPOC
+ *     - Power domain? Regulator? Somehow any remote device should be able to
+ *       cause the VPOC to be turned on.
+ *   - Link between the deserializer and the serializer
+ *     - Related to VPOC management. We probably always want to turn on the VPOC
+ *       and then enable the link.
+ *   - Serializer's services: i2c, gpios, power
+ *     - The serializer needs to resume before the remote peripherals can
+ *       e.g. use the i2c.
+ *     - How to handle gpios? Reserving a gpio essentially keeps the provider
+ *       (serializer) always powered on.
+ * - Do we need a new bus for the FPD-Link? At the moment the serializers
+ *   are children of the same i2c-adapter where the deserializer resides.
+ * - i2c-atr could be made embeddable instead of allocatable.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/fwnode.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c-atr.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#include <media/i2c/ds90ub9xx.h>
+#include <media/mipi-csi2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fwnode.h>
+#include <media/v4l2-subdev.h>
+
+#define MHZ(v) ((u32)((v) * 1000000U))
+
+#define UB960_POLL_TIME_MS	500
+
+#define UB960_MAX_RX_NPORTS	4
+#define UB960_MAX_TX_NPORTS	2
+#define UB960_MAX_NPORTS	(UB960_MAX_RX_NPORTS + UB960_MAX_TX_NPORTS)
+#define UB960_MAX_VC		4
+
+#define UB960_MAX_PORT_ALIASES	8
+
+#define UB960_NUM_BC_GPIOS		4
+
+/*
+ * Register map
+ *
+ * 0x00-0x32   Shared (UB960_SR)
+ * 0x33-0x3a   CSI-2 TX (per-port paged on DS90UB960, shared on 954) (UB960_TR)
+ * 0x4c        Shared (UB960_SR)
+ * 0x4d-0x7f   FPD-Link RX, per-port paged (UB960_RR)
+ * 0xb0-0xbf   Shared (UB960_SR)
+ * 0xd0-0xdf   FPD-Link RX, per-port paged (UB960_RR)
+ * 0xf0-0xf5   Shared (UB960_SR)
+ * 0xf8-0xfb   Shared (UB960_SR)
+ * All others  Reserved
+ *
+ * Register prefixes:
+ * UB960_SR_* = Shared register
+ * UB960_RR_* = FPD-Link RX, per-port paged register
+ * UB960_TR_* = CSI-2 TX, per-port paged register
+ * UB960_XR_* = Reserved register
+ * UB960_IR_* = Indirect register
+ */
+
+#define UB960_SR_I2C_DEV_ID			0x00
+#define UB960_SR_RESET				0x01
+#define UB960_SR_RESET_DIGITAL_RESET1		BIT(1)
+#define UB960_SR_RESET_DIGITAL_RESET0		BIT(0)
+#define UB960_SR_RESET_GPIO_LOCK_RELEASE	BIT(5)
+
+#define UB960_SR_GEN_CONFIG			0x02
+#define UB960_SR_REV_MASK			0x03
+#define UB960_SR_DEVICE_STS			0x04
+#define UB960_SR_PAR_ERR_THOLD_HI		0x05
+#define UB960_SR_PAR_ERR_THOLD_LO		0x06
+#define UB960_SR_BCC_WDOG_CTL			0x07
+#define UB960_SR_I2C_CTL1			0x08
+#define UB960_SR_I2C_CTL2			0x09
+#define UB960_SR_SCL_HIGH_TIME			0x0a
+#define UB960_SR_SCL_LOW_TIME			0x0b
+#define UB960_SR_RX_PORT_CTL			0x0c
+#define UB960_SR_IO_CTL				0x0d
+#define UB960_SR_GPIO_PIN_STS			0x0e
+#define UB960_SR_GPIO_INPUT_CTL			0x0f
+#define UB960_SR_GPIO_PIN_CTL(n)		(0x10 + (n)) /* n < UB960_NUM_GPIOS */
+#define UB960_SR_GPIO_PIN_CTL_GPIO_OUT_SEL		5
+#define UB960_SR_GPIO_PIN_CTL_GPIO_OUT_SRC_SHIFT	2
+#define UB960_SR_GPIO_PIN_CTL_GPIO_OUT_EN		BIT(0)
+
+#define UB960_SR_FS_CTL				0x18
+#define UB960_SR_FS_HIGH_TIME_1			0x19
+#define UB960_SR_FS_HIGH_TIME_0			0x1a
+#define UB960_SR_FS_LOW_TIME_1			0x1b
+#define UB960_SR_FS_LOW_TIME_0			0x1c
+#define UB960_SR_MAX_FRM_HI			0x1d
+#define UB960_SR_MAX_FRM_LO			0x1e
+#define UB960_SR_CSI_PLL_CTL			0x1f
+
+#define UB960_SR_FWD_CTL1			0x20
+#define UB960_SR_FWD_CTL1_PORT_DIS(n)		BIT((n) + 4)
+
+#define UB960_SR_FWD_CTL2			0x21
+#define UB960_SR_FWD_STS			0x22
+
+#define UB960_SR_INTERRUPT_CTL			0x23
+#define UB960_SR_INTERRUPT_CTL_INT_EN		BIT(7)
+#define UB960_SR_INTERRUPT_CTL_IE_CSI_TX0	BIT(4)
+#define UB960_SR_INTERRUPT_CTL_IE_RX(n)		BIT((n)) /* rxport[n] IRQ */
+
+#define UB960_SR_INTERRUPT_STS			0x24
+#define UB960_SR_INTERRUPT_STS_INT		BIT(7)
+#define UB960_SR_INTERRUPT_STS_IS_CSI_TX(n)	BIT(4 + (n)) /* txport[n] IRQ */
+#define UB960_SR_INTERRUPT_STS_IS_RX(n)		BIT((n)) /* rxport[n] IRQ */
+
+#define UB960_SR_TS_CONFIG			0x25
+#define UB960_SR_TS_CONTROL			0x26
+#define UB960_SR_TS_LINE_HI			0x27
+#define UB960_SR_TS_LINE_LO			0x28
+#define UB960_SR_TS_STATUS			0x29
+#define UB960_SR_TIMESTAMP_P0_HI		0x2a
+#define UB960_SR_TIMESTAMP_P0_LO		0x2b
+#define UB960_SR_TIMESTAMP_P1_HI		0x2c
+#define UB960_SR_TIMESTAMP_P1_LO		0x2d
+
+#define UB960_SR_CSI_PORT_SEL			0x32
+
+#define UB960_TR_CSI_CTL			0x33
+#define UB960_TR_CSI_CTL_CSI_CAL_EN		BIT(6)
+#define UB960_TR_CSI_CTL_CSI_ENABLE		BIT(0)
+
+#define UB960_TR_CSI_CTL2			0x34
+#define UB960_TR_CSI_STS			0x35
+#define UB960_TR_CSI_TX_ICR			0x36
+
+#define UB960_TR_CSI_TX_ISR			0x37
+#define UB960_TR_CSI_TX_ISR_IS_CSI_SYNC_ERROR	BIT(3)
+#define UB960_TR_CSI_TX_ISR_IS_CSI_PASS_ERROR	BIT(1)
+
+#define UB960_TR_CSI_TEST_CTL			0x38
+#define UB960_TR_CSI_TEST_PATT_HI		0x39
+#define UB960_TR_CSI_TEST_PATT_LO		0x3a
+
+#define UB960_XR_SFILTER_CFG			0x41
+#define UB960_XR_SFILTER_CFG_SFILTER_MAX_SHIFT	4
+#define UB960_XR_SFILTER_CFG_SFILTER_MIN_SHIFT	0
+
+#define UB960_XR_AEQ_CTL1			0x42
+#define UB960_XR_AEQ_CTL1_AEQ_ERR_CTL_FPD_CLK	BIT(6)
+#define UB960_XR_AEQ_CTL1_AEQ_ERR_CTL_ENCODING	BIT(5)
+#define UB960_XR_AEQ_CTL1_AEQ_ERR_CTL_PARITY	BIT(4)
+#define UB960_XR_AEQ_CTL1_AEQ_ERR_CTL_MASK        \
+	(UB960_XR_AEQ_CTL1_AEQ_ERR_CTL_FPD_CLK |  \
+	 UB960_XR_AEQ_CTL1_AEQ_ERR_CTL_ENCODING | \
+	 UB960_XR_AEQ_CTL1_AEQ_ERR_CTL_PARITY)
+#define UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN	BIT(0)
+
+#define UB960_XR_AEQ_ERR_THOLD			0x43
+
+#define UB960_RR_BCC_ERR_CTL			0x46
+#define UB960_RR_BCC_STATUS			0x47
+#define UB960_RR_BCC_STATUS_SEQ_ERROR		BIT(5)
+#define UB960_RR_BCC_STATUS_MASTER_ERR		BIT(4)
+#define UB960_RR_BCC_STATUS_MASTER_TO		BIT(3)
+#define UB960_RR_BCC_STATUS_SLAVE_ERR		BIT(2)
+#define UB960_RR_BCC_STATUS_SLAVE_TO		BIT(1)
+#define UB960_RR_BCC_STATUS_RESP_ERR		BIT(0)
+#define UB960_RR_BCC_STATUS_ERROR_MASK                                    \
+	(UB960_RR_BCC_STATUS_SEQ_ERROR | UB960_RR_BCC_STATUS_MASTER_ERR | \
+	 UB960_RR_BCC_STATUS_MASTER_TO | UB960_RR_BCC_STATUS_SLAVE_ERR |  \
+	 UB960_RR_BCC_STATUS_SLAVE_TO | UB960_RR_BCC_STATUS_RESP_ERR)
+
+#define UB960_RR_FPD3_CAP			0x4a
+#define UB960_RR_RAW_EMBED_DTYPE		0x4b
+#define UB960_RR_RAW_EMBED_DTYPE_LINES_SHIFT	6
+
+#define UB960_SR_FPD3_PORT_SEL			0x4c
+
+#define UB960_RR_RX_PORT_STS1			0x4d
+#define UB960_RR_RX_PORT_STS1_BCC_CRC_ERROR	BIT(5)
+#define UB960_RR_RX_PORT_STS1_LOCK_STS_CHG	BIT(4)
+#define UB960_RR_RX_PORT_STS1_BCC_SEQ_ERROR	BIT(3)
+#define UB960_RR_RX_PORT_STS1_PARITY_ERROR	BIT(2)
+#define UB960_RR_RX_PORT_STS1_PORT_PASS		BIT(1)
+#define UB960_RR_RX_PORT_STS1_LOCK_STS		BIT(0)
+#define UB960_RR_RX_PORT_STS1_ERROR_MASK       \
+	(UB960_RR_RX_PORT_STS1_BCC_CRC_ERROR | \
+	 UB960_RR_RX_PORT_STS1_BCC_SEQ_ERROR | \
+	 UB960_RR_RX_PORT_STS1_PARITY_ERROR)
+
+#define UB960_RR_RX_PORT_STS2			0x4e
+#define UB960_RR_RX_PORT_STS2_LINE_LEN_UNSTABLE	BIT(7)
+#define UB960_RR_RX_PORT_STS2_LINE_LEN_CHG	BIT(6)
+#define UB960_RR_RX_PORT_STS2_FPD3_ENCODE_ERROR	BIT(5)
+#define UB960_RR_RX_PORT_STS2_BUFFER_ERROR	BIT(4)
+#define UB960_RR_RX_PORT_STS2_CSI_ERROR		BIT(3)
+#define UB960_RR_RX_PORT_STS2_FREQ_STABLE	BIT(2)
+#define UB960_RR_RX_PORT_STS2_CABLE_FAULT	BIT(1)
+#define UB960_RR_RX_PORT_STS2_LINE_CNT_CHG	BIT(0)
+#define UB960_RR_RX_PORT_STS2_ERROR_MASK       \
+	UB960_RR_RX_PORT_STS2_BUFFER_ERROR
+
+#define UB960_RR_RX_FREQ_HIGH			0x4f
+#define UB960_RR_RX_FREQ_LOW			0x50
+#define UB960_RR_SENSOR_STS_0			0x51
+#define UB960_RR_SENSOR_STS_1			0x52
+#define UB960_RR_SENSOR_STS_2			0x53
+#define UB960_RR_SENSOR_STS_3			0x54
+#define UB960_RR_RX_PAR_ERR_HI			0x55
+#define UB960_RR_RX_PAR_ERR_LO			0x56
+#define UB960_RR_BIST_ERR_COUNT			0x57
+
+#define UB960_RR_BCC_CONFIG			0x58
+#define UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH	BIT(6)
+#define UB960_RR_BCC_CONFIG_BC_FREQ_SEL_MASK	GENMASK(2, 0)
+
+#define UB960_RR_DATAPATH_CTL1			0x59
+#define UB960_RR_DATAPATH_CTL2			0x5a
+#define UB960_RR_SER_ID				0x5b
+#define UB960_RR_SER_ALIAS_ID			0x5c
+
+/* For these two register sets: n < UB960_MAX_PORT_ALIASES */
+#define UB960_RR_SLAVE_ID(n)			(0x5d + (n))
+#define UB960_RR_SLAVE_ALIAS(n)			(0x65 + (n))
+
+#define UB960_RR_PORT_CONFIG			0x6d
+#define UB960_RR_PORT_CONFIG_FPD3_MODE_MASK	GENMASK(1, 0)
+
+#define UB960_RR_BC_GPIO_CTL(n)			(0x6e + (n)) /* n < 2 */
+#define UB960_RR_RAW10_ID			0x70
+#define UB960_RR_RAW10_ID_VC_SHIFT		6
+#define UB960_RR_RAW10_ID_DT_SHIFT		0
+
+#define UB960_RR_RAW12_ID			0x71
+#define UB960_RR_CSI_VC_MAP			0x72
+#define UB960_RR_CSI_VC_MAP_SHIFT(x)		((x) * 2)
+
+#define UB960_RR_LINE_COUNT_HI			0x73
+#define UB960_RR_LINE_COUNT_LO			0x74
+#define UB960_RR_LINE_LEN_1			0x75
+#define UB960_RR_LINE_LEN_0			0x76
+#define UB960_RR_FREQ_DET_CTL			0x77
+#define UB960_RR_MAILBOX_1			0x78
+#define UB960_RR_MAILBOX_2			0x79
+
+#define UB960_RR_CSI_RX_STS			0x7a
+#define UB960_RR_CSI_RX_STS_LENGTH_ERR		BIT(3)
+#define UB960_RR_CSI_RX_STS_CKSUM_ERR		BIT(2)
+#define UB960_RR_CSI_RX_STS_ECC2_ERR		BIT(1)
+#define UB960_RR_CSI_RX_STS_ECC1_ERR		BIT(0)
+#define UB960_RR_CSI_RX_STS_ERROR_MASK                                    \
+	(UB960_RR_CSI_RX_STS_LENGTH_ERR | UB960_RR_CSI_RX_STS_CKSUM_ERR | \
+	 UB960_RR_CSI_RX_STS_ECC2_ERR | UB960_RR_CSI_RX_STS_ECC1_ERR)
+
+#define UB960_RR_CSI_ERR_COUNTER		0x7b
+#define UB960_RR_PORT_CONFIG2			0x7c
+#define UB960_RR_PORT_CONFIG2_RAW10_8BIT_CTL_MASK GENMASK(7, 6)
+#define UB960_RR_PORT_CONFIG2_RAW10_8BIT_CTL_SHIFT 6
+
+#define UB960_RR_PORT_CONFIG2_LV_POL_LOW	BIT(1)
+#define UB960_RR_PORT_CONFIG2_FV_POL_LOW	BIT(0)
+
+#define UB960_RR_PORT_PASS_CTL			0x7d
+#define UB960_RR_SEN_INT_RISE_CTL		0x7e
+#define UB960_RR_SEN_INT_FALL_CTL		0x7f
+
+#define UB960_SR_CSI_FRAME_COUNT_HI(n)		(0x90 + 8 * (n))
+#define UB960_SR_CSI_FRAME_COUNT_LO(n)		(0x91 + 8 * (n))
+#define UB960_SR_CSI_FRAME_ERR_COUNT_HI(n)	(0x92 + 8 * (n))
+#define UB960_SR_CSI_FRAME_ERR_COUNT_LO(n)	(0x93 + 8 * (n))
+#define UB960_SR_CSI_LINE_COUNT_HI(n)		(0x94 + 8 * (n))
+#define UB960_SR_CSI_LINE_COUNT_LO(n)		(0x95 + 8 * (n))
+#define UB960_SR_CSI_LINE_ERR_COUNT_HI(n)	(0x96 + 8 * (n))
+#define UB960_SR_CSI_LINE_ERR_COUNT_LO(n)	(0x97 + 8 * (n))
+
+#define UB960_XR_REFCLK_FREQ			0xa5	/* UB960 */
+
+#define UB960_RR_VC_ID_MAP(x)			(0xa0 + (x)) /* UB9702 */
+
+#define UB960_SR_IND_ACC_CTL			0xb0
+#define UB960_SR_IND_ACC_CTL_IA_AUTO_INC	BIT(1)
+
+#define UB960_SR_IND_ACC_ADDR			0xb1
+#define UB960_SR_IND_ACC_DATA			0xb2
+#define UB960_SR_BIST_CONTROL			0xb3
+#define UB960_SR_MODE_IDX_STS			0xb8
+#define UB960_SR_LINK_ERROR_COUNT		0xb9
+#define UB960_SR_FPD3_ENC_CTL			0xba
+#define UB960_SR_FV_MIN_TIME			0xbc
+#define UB960_SR_GPIO_PD_CTL			0xbe
+
+#define UB960_SR_FPD_RATE_CFG			0xc2	/* UB9702 */
+#define UB960_SR_CSI_PLL_DIV			0xc9	/* UB9702 */
+
+#define UB960_RR_PORT_DEBUG			0xd0
+#define UB960_RR_AEQ_CTL2			0xd2
+#define UB960_RR_AEQ_CTL2_SET_AEQ_FLOOR		BIT(2)
+
+#define UB960_RR_AEQ_STATUS			0xd3
+#define UB960_RR_AEQ_STATUS_STATUS_2		GENMASK(5, 3)
+#define UB960_RR_AEQ_STATUS_STATUS_1		GENMASK(2, 0)
+
+#define UB960_RR_AEQ_BYPASS			0xd4
+#define UB960_RR_AEQ_BYPASS_EQ_STAGE1_VALUE_SHIFT	5
+#define UB960_RR_AEQ_BYPASS_EQ_STAGE1_VALUE_MASK	GENMASK(7, 5)
+#define UB960_RR_AEQ_BYPASS_EQ_STAGE2_VALUE_SHIFT	1
+#define UB960_RR_AEQ_BYPASS_EQ_STAGE2_VALUE_MASK	GENMASK(3, 1)
+#define UB960_RR_AEQ_BYPASS_ENABLE			BIT(0)
+
+#define UB960_RR_AEQ_MIN_MAX			0xd5
+#define UB960_RR_AEQ_MIN_MAX_AEQ_MAX_SHIFT	4
+#define UB960_RR_AEQ_MIN_MAX_AEQ_FLOOR_SHIFT	0
+
+#define UB960_RR_SFILTER_STS_0			0xd6
+#define UB960_RR_SFILTER_STS_1			0xd7
+#define UB960_RR_PORT_ICR_HI			0xd8
+#define UB960_RR_PORT_ICR_LO			0xd9
+#define UB960_RR_PORT_ISR_HI			0xda
+#define UB960_RR_PORT_ISR_LO			0xdb
+#define UB960_RR_FC_GPIO_STS			0xdc
+#define UB960_RR_FC_GPIO_ICR			0xdd
+#define UB960_RR_SEN_INT_RISE_STS		0xde
+#define UB960_RR_SEN_INT_FALL_STS		0xdf
+
+#define UB960_RR_CHANNEL_MODE			0xe4	/* UB9702 */
+
+#define UB960_SR_FPD3_RX_ID(n)			(0xf0 + (n))
+#define UB960_SR_FPD3_RX_ID_LEN			6
+
+#define UB960_SR_I2C_RX_ID(n)			(0xf8 + (n)) /* < UB960_FPD_RX_NPORTS */
+
+/* Indirect register blocks */
+#define UB960_IND_TARGET_PAT_GEN		0x00
+#define UB960_IND_TARGET_RX_ANA(n)		(0x01 + (n))
+#define UB960_IND_TARGET_CSI_CSIPLL_REG_1	0x92	/* UB9702 */
+#define UB960_IND_TARGET_CSI_ANA		0x07
+
+/* UB960_IR_PGEN_*: Indirect Registers for Test Pattern Generator */
+
+#define UB960_IR_PGEN_CTL			0x01
+#define UB960_IR_PGEN_CTL_PGEN_ENABLE		BIT(0)
+
+#define UB960_IR_PGEN_CFG			0x02
+#define UB960_IR_PGEN_CSI_DI			0x03
+#define UB960_IR_PGEN_LINE_SIZE1		0x04
+#define UB960_IR_PGEN_LINE_SIZE0		0x05
+#define UB960_IR_PGEN_BAR_SIZE1			0x06
+#define UB960_IR_PGEN_BAR_SIZE0			0x07
+#define UB960_IR_PGEN_ACT_LPF1			0x08
+#define UB960_IR_PGEN_ACT_LPF0			0x09
+#define UB960_IR_PGEN_TOT_LPF1			0x0a
+#define UB960_IR_PGEN_TOT_LPF0			0x0b
+#define UB960_IR_PGEN_LINE_PD1			0x0c
+#define UB960_IR_PGEN_LINE_PD0			0x0d
+#define UB960_IR_PGEN_VBP			0x0e
+#define UB960_IR_PGEN_VFP			0x0f
+#define UB960_IR_PGEN_COLOR(n)			(0x10 + (n)) /* n < 15 */
+
+#define UB960_IR_RX_ANA_STROBE_SET_CLK		0x08
+#define UB960_IR_RX_ANA_STROBE_SET_CLK_NO_EXTRA_DELAY	BIT(3)
+#define UB960_IR_RX_ANA_STROBE_SET_CLK_DELAY_MASK	GENMASK(2, 0)
+
+#define UB960_IR_RX_ANA_STROBE_SET_DATA		0x09
+#define UB960_IR_RX_ANA_STROBE_SET_DATA_NO_EXTRA_DELAY	BIT(3)
+#define UB960_IR_RX_ANA_STROBE_SET_DATA_DELAY_MASK	GENMASK(2, 0)
+
+/* EQ related */
+
+#define UB960_MIN_AEQ_STROBE_POS -7
+#define UB960_MAX_AEQ_STROBE_POS  7
+
+#define UB960_MANUAL_STROBE_EXTRA_DELAY 6
+
+#define UB960_MIN_MANUAL_STROBE_POS -(7 + UB960_MANUAL_STROBE_EXTRA_DELAY)
+#define UB960_MAX_MANUAL_STROBE_POS  (7 + UB960_MANUAL_STROBE_EXTRA_DELAY)
+#define UB960_NUM_MANUAL_STROBE_POS  (UB960_MAX_MANUAL_STROBE_POS - UB960_MIN_MANUAL_STROBE_POS + 1)
+
+#define UB960_MIN_EQ_LEVEL  0
+#define UB960_MAX_EQ_LEVEL  14
+#define UB960_NUM_EQ_LEVELS (UB960_MAX_EQ_LEVEL - UB960_MIN_EQ_LEVEL + 1)
+
+struct ub960_hw_data {
+	const char *model;
+	u8 num_rxports;
+	u8 num_txports;
+	bool is_ub9702;
+	bool is_fpdlink4;
+	bool ignore_strobe_pos;
+};
+
+enum ub960_rxport_mode {
+	RXPORT_MODE_RAW10 = 0,
+	RXPORT_MODE_RAW12_HF = 1,
+	RXPORT_MODE_RAW12_LF = 2,
+	RXPORT_MODE_CSI2_SYNC = 3,
+	RXPORT_MODE_CSI2_ASYNC = 4,
+	RXPORT_MODE_LAST = RXPORT_MODE_CSI2_ASYNC,
+};
+
+enum ub960_rxport_cdr {
+	RXPORT_CDR_FPD3 = 0,
+	RXPORT_CDR_FPD4 = 1,
+	RXPORT_CDR_LAST = RXPORT_CDR_FPD4,
+};
+
+struct ub960_rxport {
+	struct ub960_data      *priv;
+	u8                      nport;	/* RX port number, and index in priv->rxport[] */
+
+	struct {
+		struct v4l2_subdev *sd;
+		u16 pad;
+		struct fwnode_handle *ep_fwnode;
+	} source;
+
+	/* Serializer */
+	struct {
+		struct fwnode_handle *fwnode;
+		struct i2c_client *client;
+		unsigned short alias; /* I2C alias (lower 7 bits) */
+		struct ds90ub9xx_platform_data pdata;
+	} ser;
+
+	enum ub960_rxport_mode  rx_mode;
+	enum ub960_rxport_cdr	cdr_mode;
+
+	u8			lv_fv_pol;	/* LV and FV polarities */
+
+	struct regulator	*vpoc;
+
+	/* EQ settings */
+	struct {
+		bool manual_eq;
+
+		s8 strobe_pos;
+
+		union {
+			struct {
+				u8 eq_level_min;
+				u8 eq_level_max;
+			} aeq;
+
+			struct {
+				u8 eq_level;
+			} manual;
+		};
+	} eq;
+
+	const struct i2c_client *aliased_clients[UB960_MAX_PORT_ALIASES];
+};
+
+struct ub960_asd {
+	struct v4l2_async_subdev base;
+	struct ub960_rxport *rxport;
+};
+
+static inline struct ub960_asd *to_ub960_asd(struct v4l2_async_subdev *asd)
+{
+	return container_of(asd, struct ub960_asd, base);
+}
+
+struct ub960_txport {
+	struct ub960_data      *priv;
+	u8                      nport;	/* TX port number, and index in priv->txport[] */
+
+	u32 num_data_lanes;
+};
+
+struct ub960_data {
+	const struct ub960_hw_data	*hw_data;
+	struct i2c_client	*client; /* for shared local registers */
+	struct regmap		*regmap;
+
+	/* lock for register access */
+	struct mutex		reg_lock;
+
+	struct clk		*refclk;
+
+	struct regulator	*vddio;
+
+	struct gpio_desc	*pd_gpio;
+	struct delayed_work	poll_work;
+	struct ub960_rxport	*rxports[UB960_MAX_RX_NPORTS];
+	struct ub960_txport	*txports[UB960_MAX_TX_NPORTS];
+
+	struct v4l2_subdev	sd;
+	struct media_pad	pads[UB960_MAX_NPORTS];
+
+	struct v4l2_ctrl_handler   ctrl_handler;
+	struct v4l2_async_notifier notifier;
+
+	u32 tx_data_rate;		/* Nominal data rate (Gb/s) */
+	s64 tx_link_freq[1];
+
+	struct i2c_atr *atr;
+
+	struct {
+		u8 rxport;
+		u8 txport;
+		u8 indirect_target;
+	} reg_current;
+
+	bool streaming;
+
+	u8 stored_fwd_ctl;
+
+	u64 stream_enable_mask[UB960_MAX_NPORTS];
+
+	/* These are common to all ports */
+	struct {
+		bool manual;
+
+		s8 min;
+		s8 max;
+	} strobe;
+};
+
+static inline struct ub960_data *sd_to_ub960(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ub960_data, sd);
+}
+
+static inline bool ub960_pad_is_sink(struct ub960_data *priv, u32 pad)
+{
+	return pad < priv->hw_data->num_rxports;
+}
+
+static inline bool ub960_pad_is_source(struct ub960_data *priv, u32 pad)
+{
+	return pad >= priv->hw_data->num_rxports;
+}
+
+static inline unsigned int ub960_pad_to_port(struct ub960_data *priv, u32 pad)
+{
+	if (ub960_pad_is_sink(priv, pad))
+		return pad;
+	else
+		return pad - priv->hw_data->num_rxports;
+}
+
+struct ub960_format_info {
+	u32 code;
+	u32 bpp;
+	u8 datatype;
+	bool meta;
+};
+
+static const struct ub960_format_info ub960_formats[] = {
+	{ .code = MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, .datatype = MIPI_CSI2_DT_YUV422_8B, },
+	{ .code = MEDIA_BUS_FMT_UYVY8_1X16, .bpp = 16, .datatype = MIPI_CSI2_DT_YUV422_8B, },
+	{ .code = MEDIA_BUS_FMT_VYUY8_1X16, .bpp = 16, .datatype = MIPI_CSI2_DT_YUV422_8B, },
+	{ .code = MEDIA_BUS_FMT_YVYU8_1X16, .bpp = 16, .datatype = MIPI_CSI2_DT_YUV422_8B, },
+
+	{ .code = MEDIA_BUS_FMT_SBGGR12_1X12, .bpp = 12, .datatype = MIPI_CSI2_DT_RAW12, },
+	{ .code = MEDIA_BUS_FMT_SGBRG12_1X12, .bpp = 12, .datatype = MIPI_CSI2_DT_RAW12, },
+	{ .code = MEDIA_BUS_FMT_SGRBG12_1X12, .bpp = 12, .datatype = MIPI_CSI2_DT_RAW12, },
+	{ .code = MEDIA_BUS_FMT_SRGGB12_1X12, .bpp = 12, .datatype = MIPI_CSI2_DT_RAW12, },
+
+	{ .code	= MEDIA_BUS_FMT_SRGGI10_1X10, .bpp = 10, .datatype = MIPI_CSI2_DT_RAW10, },
+	{ .code	= MEDIA_BUS_FMT_SGRIG10_1X10, .bpp = 10, .datatype = MIPI_CSI2_DT_RAW10, },
+	{ .code	= MEDIA_BUS_FMT_SBGGI10_1X10, .bpp = 10, .datatype = MIPI_CSI2_DT_RAW10, },
+	{ .code	= MEDIA_BUS_FMT_SGBIG10_1X10, .bpp = 10, .datatype = MIPI_CSI2_DT_RAW10, },
+	{ .code	= MEDIA_BUS_FMT_SGIRG10_1X10, .bpp = 10, .datatype = MIPI_CSI2_DT_RAW10, },
+	{ .code	= MEDIA_BUS_FMT_SIGGR10_1X10, .bpp = 10, .datatype = MIPI_CSI2_DT_RAW10, },
+	{ .code	= MEDIA_BUS_FMT_SGIBG10_1X10, .bpp = 10, .datatype = MIPI_CSI2_DT_RAW10, },
+	{ .code	= MEDIA_BUS_FMT_SIGGB10_1X10, .bpp = 10, .datatype = MIPI_CSI2_DT_RAW10, },
+};
+
+static const struct ub960_format_info *ub960_find_format(u32 code)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ub960_formats); i++) {
+		if (ub960_formats[i].code == code)
+			return &ub960_formats[i];
+	}
+
+	return NULL;
+}
+
+/* -----------------------------------------------------------------------------
+ * Basic device access
+ */
+
+static int ub960_read(struct ub960_data *priv, u8 reg, u8 *val)
+{
+	struct device *dev = &priv->client->dev;
+	unsigned int v;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = regmap_read(priv->regmap, reg, &v);
+	if (ret) {
+		dev_err(dev, "%s: cannot read register 0x%02x (%d)!\n",
+			__func__, reg, ret);
+		goto out_unlock;
+	}
+
+	*val = v;
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_write(struct ub960_data *priv, u8 reg, u8 val)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = regmap_write(priv->regmap, reg, val);
+	if (ret)
+		dev_err(dev, "%s: cannot write register 0x%02x (%d)!\n",
+			__func__, reg, ret);
+
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_update_bits(struct ub960_data *priv, u8 reg, u8 mask, u8 val)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = regmap_update_bits(priv->regmap, reg, mask, val);
+	if (ret)
+		dev_err(dev, "%s: cannot update register 0x%02x (%d)!\n",
+			__func__, reg, ret);
+
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_read16(struct ub960_data *priv, u8 reg, u16 *val)
+{
+	struct device *dev = &priv->client->dev;
+	__be16 __v;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = regmap_bulk_read(priv->regmap, reg, &__v, sizeof(__v));
+	if (ret) {
+		dev_err(dev, "%s: cannot read register 0x%02x (%d)!\n",
+			__func__, reg, ret);
+		goto out_unlock;
+	}
+
+	*val = be16_to_cpu(__v);
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_rxport_select(struct ub960_data *priv, u8 nport)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	lockdep_assert_held(&priv->reg_lock);
+
+	if (priv->reg_current.rxport == nport)
+		return 0;
+
+	ret = regmap_write(priv->regmap, UB960_SR_FPD3_PORT_SEL,
+			   (nport << 4) | BIT(nport));
+	if (ret) {
+		dev_err(dev, "%s: cannot select rxport %d (%d)!\n", __func__,
+			nport, ret);
+		return ret;
+	}
+
+	priv->reg_current.rxport = nport;
+
+	return 0;
+}
+
+static int ub960_rxport_read(struct ub960_data *priv, u8 nport, u8 reg, u8 *val)
+{
+	struct device *dev = &priv->client->dev;
+	unsigned int v;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = ub960_rxport_select(priv, nport);
+	if (ret)
+		goto out_unlock;
+
+	ret = regmap_read(priv->regmap, reg, &v);
+	if (ret) {
+		dev_err(dev, "%s: cannot read register 0x%02x (%d)!\n",
+			__func__, reg, ret);
+		goto out_unlock;
+	}
+
+	*val = v;
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_rxport_write(struct ub960_data *priv, u8 nport, u8 reg, u8 val)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = ub960_rxport_select(priv, nport);
+	if (ret)
+		goto out_unlock;
+
+	ret = regmap_write(priv->regmap, reg, val);
+	if (ret)
+		dev_err(dev, "%s: cannot write register 0x%02x (%d)!\n",
+			__func__, reg, ret);
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_rxport_update_bits(struct ub960_data *priv, u8 nport, u8 reg,
+				    u8 mask, u8 val)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = ub960_rxport_select(priv, nport);
+	if (ret)
+		goto out_unlock;
+
+	ret = regmap_update_bits(priv->regmap, reg, mask, val);
+	if (ret)
+		dev_err(dev, "%s: cannot update register 0x%02x (%d)!\n",
+			__func__, reg, ret);
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_rxport_read16(struct ub960_data *priv, u8 nport, u8 reg,
+			       u16 *val)
+{
+	struct device *dev = &priv->client->dev;
+	__be16 __v;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = ub960_rxport_select(priv, nport);
+	if (ret)
+		goto out_unlock;
+
+	ret = regmap_bulk_read(priv->regmap, reg, &__v, sizeof(__v));
+	if (ret) {
+		dev_err(dev, "%s: cannot read register 0x%02x (%d)!\n",
+			__func__, reg, ret);
+		goto out_unlock;
+	}
+
+	*val = be16_to_cpu(__v);
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_txport_select(struct ub960_data *priv, u8 nport)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	lockdep_assert_held(&priv->reg_lock);
+
+	if (priv->reg_current.txport == nport)
+		return 0;
+
+	ret = regmap_write(priv->regmap, UB960_SR_CSI_PORT_SEL,
+			   (nport << 4) | BIT(nport));
+	if (ret) {
+		dev_err(dev, "%s: cannot select tx port %d (%d)!\n", __func__,
+			nport, ret);
+		return ret;
+	}
+
+	priv->reg_current.txport = nport;
+
+	return 0;
+}
+
+static int ub960_txport_read(struct ub960_data *priv, u8 nport, u8 reg, u8 *val)
+{
+	struct device *dev = &priv->client->dev;
+	unsigned int v;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = ub960_txport_select(priv, nport);
+	if (ret)
+		goto out_unlock;
+
+	ret = regmap_read(priv->regmap, reg, &v);
+	if (ret) {
+		dev_err(dev, "%s: cannot read register 0x%02x (%d)!\n",
+			__func__, reg, ret);
+		goto out_unlock;
+	}
+
+	*val = v;
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_txport_write(struct ub960_data *priv, u8 nport, u8 reg, u8 val)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = ub960_txport_select(priv, nport);
+	if (ret)
+		goto out_unlock;
+
+	ret = regmap_write(priv->regmap, reg, val);
+	if (ret)
+		dev_err(dev, "%s: cannot write register 0x%02x (%d)!\n",
+			__func__, reg, ret);
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_txport_update_bits(struct ub960_data *priv, u8 nport, u8 reg,
+				    u8 mask, u8 val)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = ub960_txport_select(priv, nport);
+	if (ret)
+		goto out_unlock;
+
+	ret = regmap_update_bits(priv->regmap, reg, mask, val);
+	if (ret)
+		dev_err(dev, "%s: cannot update register 0x%02x (%d)!\n",
+			__func__, reg, ret);
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_select_ind_reg_block(struct ub960_data *priv, u8 block)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	lockdep_assert_held(&priv->reg_lock);
+
+	if (priv->reg_current.indirect_target == block)
+		return 0;
+
+	ret = regmap_write(priv->regmap, UB960_SR_IND_ACC_CTL, block << 2);
+	if (ret) {
+		dev_err(dev, "%s: cannot select indirect target %u (%d)!\n",
+			__func__, block, ret);
+		return ret;
+	}
+
+	priv->reg_current.indirect_target = block;
+
+	return 0;
+}
+
+static int ub960_read_ind(struct ub960_data *priv, u8 block, u8 reg, u8 *val)
+{
+	struct device *dev = &priv->client->dev;
+	unsigned int v;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = ub960_select_ind_reg_block(priv, block);
+	if (ret)
+		goto out_unlock;
+
+	ret = regmap_write(priv->regmap, UB960_SR_IND_ACC_ADDR, reg);
+	if (ret) {
+		dev_err(dev,
+			"Write to IND_ACC_ADDR failed when reading %u:%x02x: %d\n",
+			block, reg, ret);
+		goto out_unlock;
+	}
+
+	ret = regmap_read(priv->regmap, UB960_SR_IND_ACC_DATA, &v);
+	if (ret) {
+		dev_err(dev,
+			"Write to IND_ACC_DATA failed when reading %u:%x02x: %d\n",
+			block, reg, ret);
+		goto out_unlock;
+	}
+
+	*val = v;
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_write_ind(struct ub960_data *priv, u8 block, u8 reg, u8 val)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = ub960_select_ind_reg_block(priv, block);
+	if (ret)
+		goto out_unlock;
+
+	ret = regmap_write(priv->regmap, UB960_SR_IND_ACC_ADDR, reg);
+	if (ret) {
+		dev_err(dev,
+			"Write to IND_ACC_ADDR failed when writing %u:%x02x: %d\n",
+			block, reg, ret);
+		goto out_unlock;
+	}
+
+	ret = regmap_write(priv->regmap, UB960_SR_IND_ACC_DATA, val);
+	if (ret) {
+		dev_err(dev,
+			"Write to IND_ACC_DATA failed when writing %u:%x02x: %d\n",
+			block, reg, ret);
+		goto out_unlock;
+	}
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+static int ub960_ind_update_bits(struct ub960_data *priv, u8 block, u8 reg,
+				 u8 mask, u8 val)
+{
+	struct device *dev = &priv->client->dev;
+	int ret;
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = ub960_select_ind_reg_block(priv, block);
+	if (ret)
+		goto out_unlock;
+
+	ret = regmap_write(priv->regmap, UB960_SR_IND_ACC_ADDR, reg);
+	if (ret) {
+		dev_err(dev,
+			"Write to IND_ACC_ADDR failed when updating %u:%x02x: %d\n",
+			block, reg, ret);
+		goto out_unlock;
+	}
+
+	ret = regmap_update_bits(priv->regmap, UB960_SR_IND_ACC_DATA, mask,
+				 val);
+	if (ret) {
+		dev_err(dev,
+			"Write to IND_ACC_DATA failed when updating %u:%x02x: %d\n",
+			block, reg, ret);
+		goto out_unlock;
+	}
+
+out_unlock:
+	mutex_unlock(&priv->reg_lock);
+
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * I2C-ATR (address translator)
+ */
+
+static int ub960_atr_attach_client(struct i2c_atr *atr, u32 chan_id,
+				   const struct i2c_client *client, u16 alias)
+{
+	struct ub960_data *priv = i2c_atr_get_driver_data(atr);
+	struct ub960_rxport *rxport = priv->rxports[chan_id];
+	struct device *dev = &priv->client->dev;
+	unsigned int reg_idx;
+
+	for (reg_idx = 0; reg_idx < ARRAY_SIZE(rxport->aliased_clients); reg_idx++) {
+		if (!rxport->aliased_clients[reg_idx])
+			break;
+	}
+
+	if (reg_idx == ARRAY_SIZE(rxport->aliased_clients)) {
+		dev_err(dev, "rx%u: alias pool exhausted\n", rxport->nport);
+		return -EADDRNOTAVAIL;
+	}
+
+	rxport->aliased_clients[reg_idx] = client;
+
+	ub960_rxport_write(priv, chan_id, UB960_RR_SLAVE_ID(reg_idx),
+			   client->addr << 1);
+	ub960_rxport_write(priv, chan_id, UB960_RR_SLAVE_ALIAS(reg_idx),
+			   alias << 1);
+
+	dev_dbg(dev, "rx%u: client 0x%02x assigned alias 0x%02x at slot %u\n",
+		rxport->nport, client->addr, alias, reg_idx);
+
+	return 0;
+}
+
+static void ub960_atr_detach_client(struct i2c_atr *atr, u32 chan_id,
+				    const struct i2c_client *client)
+{
+	struct ub960_data *priv = i2c_atr_get_driver_data(atr);
+	struct ub960_rxport *rxport = priv->rxports[chan_id];
+	struct device *dev = &priv->client->dev;
+	unsigned int reg_idx;
+
+	for (reg_idx = 0; reg_idx < ARRAY_SIZE(rxport->aliased_clients); reg_idx++) {
+		if (rxport->aliased_clients[reg_idx] == client)
+			break;
+	}
+
+	if (reg_idx == ARRAY_SIZE(rxport->aliased_clients)) {
+		dev_err(dev, "rx%u: client 0x%02x is not mapped!\n",
+			rxport->nport, client->addr);
+		return;
+	}
+
+	rxport->aliased_clients[reg_idx] = NULL;
+
+	ub960_rxport_write(priv, chan_id, UB960_RR_SLAVE_ALIAS(reg_idx), 0);
+
+	dev_dbg(dev, "rx%u: client 0x%02x released at slot %u\n", rxport->nport,
+		client->addr, reg_idx);
+}
+
+static const struct i2c_atr_ops ub960_atr_ops = {
+	.attach_client = ub960_atr_attach_client,
+	.detach_client = ub960_atr_detach_client,
+};
+
+static int ub960_init_atr(struct ub960_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	struct i2c_adapter *parent_adap = priv->client->adapter;
+
+	priv->atr = i2c_atr_new(parent_adap, dev, &ub960_atr_ops,
+				priv->hw_data->num_rxports);
+	if (IS_ERR(priv->atr))
+		return PTR_ERR(priv->atr);
+
+	i2c_atr_set_driver_data(priv->atr, priv);
+
+	return 0;
+}
+
+static void ub960_uninit_atr(struct ub960_data *priv)
+{
+	i2c_atr_delete(priv->atr);
+	priv->atr = NULL;
+}
+
+/* -----------------------------------------------------------------------------
+ * TX ports
+ */
+
+static int ub960_parse_dt_txport(struct ub960_data *priv,
+				 struct fwnode_handle *ep_fwnode,
+				 u8 nport)
+{
+	struct device *dev = &priv->client->dev;
+	struct v4l2_fwnode_endpoint vep = {};
+	struct ub960_txport *txport;
+	int ret;
+
+	txport = kzalloc(sizeof(*txport), GFP_KERNEL);
+	if (!txport)
+		return -ENOMEM;
+
+	txport->priv = priv;
+	txport->nport = nport;
+
+	vep.bus_type = V4L2_MBUS_CSI2_DPHY;
+	ret = v4l2_fwnode_endpoint_alloc_parse(ep_fwnode, &vep);
+	if (ret) {
+		dev_err(dev, "tx%u: failed to parse endpoint data\n", nport);
+		goto err_free_txport;
+	}
+
+	txport->num_data_lanes = vep.bus.mipi_csi2.num_data_lanes;
+
+	if (vep.nr_of_link_frequencies != 1) {
+		ret = -EINVAL;
+		goto err_free_vep;
+	}
+
+	priv->tx_link_freq[0] = vep.link_frequencies[0];
+	priv->tx_data_rate = priv->tx_link_freq[0] * 2;
+
+	if (priv->tx_data_rate != MHZ(1600) &&
+	    priv->tx_data_rate != MHZ(1200) &&
+	    priv->tx_data_rate != MHZ(800) &&
+	    priv->tx_data_rate != MHZ(400)) {
+		dev_err(dev, "tx%u: invalid 'link-frequencies' value\n", nport);
+		ret = -EINVAL;
+		goto err_free_vep;
+	}
+
+	v4l2_fwnode_endpoint_free(&vep);
+
+	priv->txports[nport] = txport;
+
+	return 0;
+
+err_free_vep:
+	v4l2_fwnode_endpoint_free(&vep);
+err_free_txport:
+	kfree(txport);
+
+	return ret;
+}
+
+static void ub960_csi_handle_events(struct ub960_data *priv, u8 nport)
+{
+	struct device *dev = &priv->client->dev;
+	u8 csi_tx_isr;
+	int ret;
+
+	ret = ub960_txport_read(priv, nport, UB960_TR_CSI_TX_ISR, &csi_tx_isr);
+	if (ret)
+		return;
+
+	if (csi_tx_isr & UB960_TR_CSI_TX_ISR_IS_CSI_SYNC_ERROR)
+		dev_warn(dev, "TX%u: CSI_SYNC_ERROR\n", nport);
+
+	if (csi_tx_isr & UB960_TR_CSI_TX_ISR_IS_CSI_PASS_ERROR)
+		dev_warn(dev, "TX%u: CSI_PASS_ERROR\n", nport);
+}
+
+/* -----------------------------------------------------------------------------
+ * RX ports
+ */
+
+static int ub960_rxport_enable_vpocs(struct ub960_data *priv)
+{
+	unsigned int nport;
+	int ret;
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+		struct ub960_rxport *rxport = priv->rxports[nport];
+
+		if (!rxport || !rxport->vpoc)
+			continue;
+
+		ret = regulator_enable(rxport->vpoc);
+		if (ret)
+			goto err_disable_vpocs;
+	}
+
+	return 0;
+
+err_disable_vpocs:
+	while (nport--) {
+		struct ub960_rxport *rxport = priv->rxports[nport];
+
+		if (!rxport || !rxport->vpoc)
+			continue;
+
+		regulator_disable(rxport->vpoc);
+	}
+
+	return ret;
+}
+
+static void ub960_rxport_disable_vpocs(struct ub960_data *priv)
+{
+	unsigned int nport;
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+		struct ub960_rxport *rxport = priv->rxports[nport];
+
+		if (!rxport || !rxport->vpoc)
+			continue;
+
+		regulator_disable(rxport->vpoc);
+	}
+}
+
+static void ub960_rxport_clear_errors(struct ub960_data *priv,
+				      unsigned int nport)
+{
+	u8 v;
+
+	ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1, &v);
+	ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2, &v);
+	ub960_rxport_read(priv, nport, UB960_RR_CSI_RX_STS, &v);
+	ub960_rxport_read(priv, nport, UB960_RR_BCC_STATUS, &v);
+
+	ub960_rxport_read(priv, nport, UB960_RR_RX_PAR_ERR_HI, &v);
+	ub960_rxport_read(priv, nport, UB960_RR_RX_PAR_ERR_LO, &v);
+
+	ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER, &v);
+}
+
+static void ub960_clear_rx_errors(struct ub960_data *priv)
+{
+	unsigned int nport;
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++)
+		ub960_rxport_clear_errors(priv, nport);
+}
+
+static int ub960_rxport_get_strobe_pos(struct ub960_data *priv,
+				       unsigned int nport, s8 *strobe_pos)
+{
+	u8 v;
+	u8 clk_delay, data_delay;
+	int ret;
+
+	ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+		       UB960_IR_RX_ANA_STROBE_SET_CLK, &v);
+
+	clk_delay = (v & UB960_IR_RX_ANA_STROBE_SET_CLK_NO_EXTRA_DELAY) ?
+			    0 : UB960_MANUAL_STROBE_EXTRA_DELAY;
+
+	ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+		       UB960_IR_RX_ANA_STROBE_SET_DATA, &v);
+
+	data_delay = (v & UB960_IR_RX_ANA_STROBE_SET_DATA_NO_EXTRA_DELAY) ?
+			     0 : UB960_MANUAL_STROBE_EXTRA_DELAY;
+
+	ret = ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_0, &v);
+	if (ret)
+		return ret;
+
+	clk_delay += v & UB960_IR_RX_ANA_STROBE_SET_CLK_DELAY_MASK;
+
+	ub960_rxport_read(priv, nport, UB960_RR_SFILTER_STS_1, &v);
+	if (ret)
+		return ret;
+
+	data_delay += v & UB960_IR_RX_ANA_STROBE_SET_DATA_DELAY_MASK;
+
+	*strobe_pos = data_delay - clk_delay;
+
+	return 0;
+}
+
+static void ub960_rxport_set_strobe_pos(struct ub960_data *priv,
+					unsigned int nport, s8 strobe_pos)
+{
+	u8 clk_delay, data_delay;
+
+	clk_delay = UB960_IR_RX_ANA_STROBE_SET_CLK_NO_EXTRA_DELAY;
+	data_delay = UB960_IR_RX_ANA_STROBE_SET_DATA_NO_EXTRA_DELAY;
+
+	if (strobe_pos < UB960_MIN_AEQ_STROBE_POS)
+		clk_delay = abs(strobe_pos) - UB960_MANUAL_STROBE_EXTRA_DELAY;
+	else if (strobe_pos > UB960_MAX_AEQ_STROBE_POS)
+		data_delay = strobe_pos - UB960_MANUAL_STROBE_EXTRA_DELAY;
+	else if (strobe_pos < 0)
+		clk_delay = abs(strobe_pos) | UB960_IR_RX_ANA_STROBE_SET_CLK_NO_EXTRA_DELAY;
+	else if (strobe_pos > 0)
+		data_delay = strobe_pos | UB960_IR_RX_ANA_STROBE_SET_DATA_NO_EXTRA_DELAY;
+
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+			UB960_IR_RX_ANA_STROBE_SET_CLK, clk_delay);
+
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport),
+			UB960_IR_RX_ANA_STROBE_SET_DATA, data_delay);
+}
+
+static void ub960_rxport_set_strobe_range(struct ub960_data *priv,
+					  s8 strobe_min, s8 strobe_max)
+{
+	/* Convert the signed strobe pos to positive zero based value */
+	strobe_min -= UB960_MIN_AEQ_STROBE_POS;
+	strobe_max -= UB960_MIN_AEQ_STROBE_POS;
+
+	ub960_write(priv, UB960_XR_SFILTER_CFG,
+		    ((u8)strobe_min << UB960_XR_SFILTER_CFG_SFILTER_MIN_SHIFT) |
+		    ((u8)strobe_max << UB960_XR_SFILTER_CFG_SFILTER_MAX_SHIFT));
+}
+
+static int ub960_rxport_get_eq_level(struct ub960_data *priv,
+				     unsigned int nport, u8 *eq_level)
+{
+	int ret;
+	u8 v;
+
+	ret = ub960_rxport_read(priv, nport, UB960_RR_AEQ_STATUS, &v);
+	if (ret)
+		return ret;
+
+	*eq_level = (v & UB960_RR_AEQ_STATUS_STATUS_1) +
+		    (v & UB960_RR_AEQ_STATUS_STATUS_2);
+
+	return 0;
+}
+
+static void ub960_rxport_set_eq_level(struct ub960_data *priv,
+				      unsigned int nport, u8 eq_level)
+{
+	u8 eq_stage_1_select_value, eq_stage_2_select_value;
+	const unsigned int eq_stage_max = 7;
+	u8 v;
+
+	if (eq_level <= eq_stage_max) {
+		eq_stage_1_select_value = eq_level;
+		eq_stage_2_select_value = 0;
+	} else {
+		eq_stage_1_select_value = eq_stage_max;
+		eq_stage_2_select_value = eq_level - eq_stage_max;
+	}
+
+	ub960_rxport_read(priv, nport, UB960_RR_AEQ_BYPASS, &v);
+
+	v &= ~(UB960_RR_AEQ_BYPASS_EQ_STAGE1_VALUE_MASK |
+	       UB960_RR_AEQ_BYPASS_EQ_STAGE2_VALUE_MASK);
+	v |= eq_stage_1_select_value << UB960_RR_AEQ_BYPASS_EQ_STAGE1_VALUE_SHIFT;
+	v |= eq_stage_2_select_value << UB960_RR_AEQ_BYPASS_EQ_STAGE2_VALUE_SHIFT;
+	v |= UB960_RR_AEQ_BYPASS_ENABLE;
+
+	ub960_rxport_write(priv, nport, UB960_RR_AEQ_BYPASS, v);
+}
+
+static void ub960_rxport_set_eq_range(struct ub960_data *priv,
+				      unsigned int nport, u8 eq_min, u8 eq_max)
+{
+	ub960_rxport_write(priv, nport, UB960_RR_AEQ_MIN_MAX,
+			   (eq_min << UB960_RR_AEQ_MIN_MAX_AEQ_FLOOR_SHIFT) |
+			   (eq_max << UB960_RR_AEQ_MIN_MAX_AEQ_MAX_SHIFT));
+
+	/* Enable AEQ min setting */
+	ub960_rxport_update_bits(priv, nport, UB960_RR_AEQ_CTL2,
+				 UB960_RR_AEQ_CTL2_SET_AEQ_FLOOR,
+				 UB960_RR_AEQ_CTL2_SET_AEQ_FLOOR);
+}
+
+static void ub960_rxport_config_eq(struct ub960_data *priv, unsigned int nport)
+{
+	struct ub960_rxport *rxport = priv->rxports[nport];
+
+	/* We also set common settings here. Should be moved elsewhere. */
+
+	if (priv->strobe.manual) {
+		/* Disable AEQ_SFILTER_EN */
+		ub960_update_bits(priv, UB960_XR_AEQ_CTL1,
+				  UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN, 0);
+	} else {
+		/* Enable SFILTER and error control */
+		ub960_write(priv, UB960_XR_AEQ_CTL1,
+			    UB960_XR_AEQ_CTL1_AEQ_ERR_CTL_MASK |
+				    UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN);
+
+		/* Set AEQ strobe range */
+		ub960_rxport_set_strobe_range(priv, priv->strobe.min,
+					      priv->strobe.max);
+	}
+
+	/* The rest are port specific */
+
+	if (priv->strobe.manual)
+		ub960_rxport_set_strobe_pos(priv, nport, rxport->eq.strobe_pos);
+	else if (!priv->hw_data->ignore_strobe_pos)
+		ub960_rxport_set_strobe_pos(priv, nport, 0);
+
+	if (rxport->eq.manual_eq) {
+		ub960_rxport_set_eq_level(priv, nport,
+					  rxport->eq.manual.eq_level);
+
+		/* Enable AEQ Bypass */
+		ub960_rxport_update_bits(priv, nport, UB960_RR_AEQ_BYPASS,
+					 UB960_RR_AEQ_BYPASS_ENABLE,
+					 UB960_RR_AEQ_BYPASS_ENABLE);
+	} else {
+		ub960_rxport_set_eq_range(priv, nport,
+					  rxport->eq.aeq.eq_level_min,
+					  rxport->eq.aeq.eq_level_max);
+
+		/* Disable AEQ Bypass */
+		ub960_rxport_update_bits(priv, nport, UB960_RR_AEQ_BYPASS,
+					 UB960_RR_AEQ_BYPASS_ENABLE, 0);
+	}
+}
+
+static int ub960_rxport_link_ok(struct ub960_data *priv, unsigned int nport,
+				bool *ok)
+{
+	u8 rx_port_sts1, rx_port_sts2;
+	u16 parity_errors;
+	u8 csi_rx_sts;
+	u8 csi_err_cnt;
+	u8 bcc_sts;
+	int ret;
+	bool errors;
+
+	ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1,
+				&rx_port_sts1);
+	if (ret)
+		return ret;
+
+	if (!(rx_port_sts1 & UB960_RR_RX_PORT_STS1_LOCK_STS)) {
+		*ok = false;
+		return 0;
+	}
+
+	ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2,
+				&rx_port_sts2);
+	if (ret)
+		return ret;
+
+	ret = ub960_rxport_read(priv, nport, UB960_RR_CSI_RX_STS, &csi_rx_sts);
+	if (ret)
+		return ret;
+
+	ret = ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER,
+				&csi_err_cnt);
+	if (ret)
+		return ret;
+
+	ret = ub960_rxport_read(priv, nport, UB960_RR_BCC_STATUS, &bcc_sts);
+	if (ret)
+		return ret;
+
+	ret = ub960_rxport_read16(priv, nport, UB960_RR_RX_PAR_ERR_HI,
+				  &parity_errors);
+	if (ret)
+		return ret;
+
+	errors = (rx_port_sts1 & UB960_RR_RX_PORT_STS1_ERROR_MASK) ||
+		 (rx_port_sts2 & UB960_RR_RX_PORT_STS2_ERROR_MASK) ||
+		 (bcc_sts & UB960_RR_BCC_STATUS_ERROR_MASK) ||
+		 (csi_rx_sts & UB960_RR_CSI_RX_STS_ERROR_MASK) || csi_err_cnt ||
+		 parity_errors;
+
+	*ok = !errors;
+
+	return 0;
+}
+
+/*
+ * Wait for the RX ports to lock, have no errors and have stable strobe position
+ * and EQ level.
+ */
+static int ub960_rxport_wait_locks(struct ub960_data *priv,
+				   unsigned long port_mask,
+				   unsigned int *lock_mask)
+{
+	struct device *dev = &priv->client->dev;
+	unsigned long timeout;
+	unsigned int link_ok_mask;
+	unsigned int missing;
+	unsigned int loops;
+	u8 nport;
+	int ret;
+
+	if (port_mask == 0) {
+		if (lock_mask)
+			*lock_mask = 0;
+		return 0;
+	}
+
+	if (port_mask >= BIT(priv->hw_data->num_rxports))
+		return -EINVAL;
+
+	timeout = jiffies + msecs_to_jiffies(1000);
+	loops = 0;
+	link_ok_mask = 0;
+
+	while (time_before(jiffies, timeout)) {
+		missing = 0;
+
+		for_each_set_bit(nport, &port_mask,
+				 priv->hw_data->num_rxports) {
+			struct ub960_rxport *rxport = priv->rxports[nport];
+			bool ok;
+
+			if (!rxport)
+				continue;
+
+			ret = ub960_rxport_link_ok(priv, nport, &ok);
+			if (ret)
+				return ret;
+
+			/*
+			 * We want the link to be ok for two consecutive loops,
+			 * as a link could get established just before our test
+			 * and drop soon after.
+			 */
+			if (!ok || !(link_ok_mask & BIT(nport)))
+				missing++;
+
+			if (ok)
+				link_ok_mask |= BIT(nport);
+			else
+				link_ok_mask &= ~BIT(nport);
+		}
+
+		loops++;
+
+		if (missing == 0)
+			break;
+
+		msleep(50);
+	}
+
+	if (lock_mask)
+		*lock_mask = link_ok_mask;
+
+	dev_dbg(dev, "Wait locks done in %u loops\n", loops);
+	for_each_set_bit(nport, &port_mask, priv->hw_data->num_rxports) {
+		struct ub960_rxport *rxport = priv->rxports[nport];
+		s8 strobe_pos, eq_level;
+		u16 v;
+
+		if (!rxport)
+			continue;
+
+		if (!(link_ok_mask & BIT(nport))) {
+			dev_dbg(dev, "\trx%u: not locked\n", nport);
+			continue;
+		}
+
+		ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH, &v);
+
+		ret = ub960_rxport_get_strobe_pos(priv, nport, &strobe_pos);
+		if (ret)
+			return ret;
+
+		ret = ub960_rxport_get_eq_level(priv, nport, &eq_level);
+		if (ret)
+			return ret;
+
+		dev_dbg(dev, "\trx%u: locked, SP: %d, EQ: %u, freq %llu Hz\n",
+			nport, strobe_pos, eq_level, (v * 1000000ULL) >> 8);
+	}
+
+	return 0;
+}
+
+static unsigned long ub960_calc_bc_clk_rate_ub960(struct ub960_data *priv,
+						  struct ub960_rxport *rxport)
+{
+	unsigned int mult;
+	unsigned int div;
+
+	switch (rxport->rx_mode) {
+	case RXPORT_MODE_RAW10:
+	case RXPORT_MODE_RAW12_HF:
+	case RXPORT_MODE_RAW12_LF:
+		mult = 1;
+		div = 10;
+		break;
+
+	case RXPORT_MODE_CSI2_SYNC:
+		mult = 2;
+		div = 1;
+		break;
+
+	case RXPORT_MODE_CSI2_ASYNC:
+		mult = 2;
+		div = 5;
+		break;
+
+	default:
+		return 0;
+	}
+
+	return clk_get_rate(priv->refclk) * mult / div;
+}
+
+static unsigned long ub960_calc_bc_clk_rate_ub9702(struct ub960_data *priv,
+						   struct ub960_rxport *rxport)
+{
+	switch (rxport->rx_mode) {
+	case RXPORT_MODE_RAW10:
+	case RXPORT_MODE_RAW12_HF:
+	case RXPORT_MODE_RAW12_LF:
+		return 2359400;
+
+	case RXPORT_MODE_CSI2_SYNC:
+		return 47187500;
+
+	case RXPORT_MODE_CSI2_ASYNC:
+		return 9437500;
+
+	default:
+		return 0;
+	}
+}
+
+static int ub960_rxport_add_serializer(struct ub960_data *priv, u8 nport)
+{
+	struct ub960_rxport *rxport = priv->rxports[nport];
+	struct device *dev = &priv->client->dev;
+	struct ds90ub9xx_platform_data *ser_pdata = &rxport->ser.pdata;
+	struct i2c_board_info ser_info = {
+		.of_node = to_of_node(rxport->ser.fwnode),
+		.fwnode = rxport->ser.fwnode,
+		.platform_data = ser_pdata,
+	};
+
+	ser_pdata->port = nport;
+	ser_pdata->atr = priv->atr;
+	if (priv->hw_data->is_ub9702)
+		ser_pdata->bc_rate = ub960_calc_bc_clk_rate_ub9702(priv, rxport);
+	else
+		ser_pdata->bc_rate = ub960_calc_bc_clk_rate_ub960(priv, rxport);
+
+	/*
+	 * The serializer is added under the same i2c adapter as the
+	 * deserializer. This is not quite right, as the serializer is behind
+	 * the FPD-Link.
+	 */
+	ser_info.addr = rxport->ser.alias;
+	rxport->ser.client =
+		i2c_new_client_device(priv->client->adapter, &ser_info);
+	if (!rxport->ser.client) {
+		dev_err(dev, "rx%u: cannot add %s i2c device", nport,
+			ser_info.type);
+		return -EIO;
+	}
+
+	dev_dbg(dev, "rx%u: remote serializer at alias 0x%02x (%u-%04x)\n",
+		nport, rxport->ser.client->addr,
+		rxport->ser.client->adapter->nr, rxport->ser.client->addr);
+
+	return 0;
+}
+
+static void ub960_rxport_remove_serializer(struct ub960_data *priv, u8 nport)
+{
+	struct ub960_rxport *rxport = priv->rxports[nport];
+
+	i2c_unregister_device(rxport->ser.client);
+	rxport->ser.client = NULL;
+}
+
+/* Add serializer i2c devices for all initialized ports */
+static int ub960_rxport_add_serializers(struct ub960_data *priv)
+{
+	unsigned int nport;
+	int ret;
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+		struct ub960_rxport *rxport = priv->rxports[nport];
+
+		if (!rxport)
+			continue;
+
+		ret = ub960_rxport_add_serializer(priv, nport);
+		if (ret)
+			goto err_remove_sers;
+	}
+
+	return 0;
+
+err_remove_sers:
+	while (nport--) {
+		struct ub960_rxport *rxport = priv->rxports[nport];
+
+		if (!rxport)
+			continue;
+
+		ub960_rxport_remove_serializer(priv, nport);
+	}
+
+	return ret;
+}
+
+static void ub960_rxport_remove_serializers(struct ub960_data *priv)
+{
+	unsigned int nport;
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+		struct ub960_rxport *rxport = priv->rxports[nport];
+
+		if (!rxport)
+			continue;
+
+		ub960_rxport_remove_serializer(priv, nport);
+	}
+}
+
+static void ub960_init_tx_port(struct ub960_data *priv,
+			       struct ub960_txport *txport)
+{
+	unsigned int nport = txport->nport;
+	u8 csi_ctl = 0;
+
+	/*
+	 * From the datasheet: "initial CSI Skew-Calibration
+	 * sequence [...] should be set when operating at 1.6 Gbps"
+	 */
+	if (priv->tx_data_rate == MHZ(1600))
+		csi_ctl |= UB960_TR_CSI_CTL_CSI_CAL_EN;
+
+	csi_ctl |= (4 - txport->num_data_lanes) << 4;
+
+	ub960_txport_write(priv, nport, UB960_TR_CSI_CTL, csi_ctl);
+}
+
+static int ub960_init_tx_ports(struct ub960_data *priv)
+{
+	unsigned int nport;
+	u8 speed_select;
+	u8 pll_div;
+
+	/* TX ports */
+
+	switch (priv->tx_data_rate) {
+	case MHZ(1600):
+	default:
+		speed_select = 0;
+		pll_div = 0x10;
+		break;
+	case MHZ(1200):
+		speed_select = 1;
+		break;
+	case MHZ(800):
+		speed_select = 2;
+		pll_div = 0x10;
+		break;
+	case MHZ(400):
+		speed_select = 3;
+		pll_div = 0x10;
+		break;
+	}
+
+	ub960_write(priv, UB960_SR_CSI_PLL_CTL, speed_select);
+
+	if (priv->hw_data->is_ub9702) {
+		ub960_write(priv, UB960_SR_CSI_PLL_DIV, pll_div);
+
+		switch (priv->tx_data_rate) {
+		case MHZ(1600):
+		default:
+			ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92, 0x80);
+			ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b, 0x2a);
+			break;
+		case MHZ(800):
+			ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92, 0x90);
+			ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4f, 0x2a);
+			ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x4b, 0x2a);
+			break;
+		case MHZ(400):
+			ub960_write_ind(priv, UB960_IND_TARGET_CSI_ANA, 0x92, 0xa0);
+			break;
+		}
+	}
+
+	for (nport = 0; nport < priv->hw_data->num_txports; nport++) {
+		struct ub960_txport *txport = priv->txports[nport];
+
+		if (!txport)
+			continue;
+
+		ub960_init_tx_port(priv, txport);
+	}
+
+	return 0;
+}
+
+static void ub960_init_rx_port_ub960(struct ub960_data *priv,
+				     struct ub960_rxport *rxport)
+{
+	unsigned int nport = rxport->nport;
+	u32 bc_freq_val;
+
+	/*
+	 * Back channel frequency select.
+	 * Override FREQ_SELECT from the strap.
+	 * 0 - 2.5 Mbps (DS90UB913A-Q1 / DS90UB933-Q1)
+	 * 2 - 10 Mbps
+	 * 6 - 50 Mbps (DS90UB953-Q1)
+	 *
+	 * Note that changing this setting will result in some errors on the back
+	 * channel for a short period of time.
+	 */
+
+	switch (rxport->rx_mode) {
+	case RXPORT_MODE_RAW10:
+	case RXPORT_MODE_RAW12_HF:
+	case RXPORT_MODE_RAW12_LF:
+		bc_freq_val = 0;
+		break;
+
+	case RXPORT_MODE_CSI2_ASYNC:
+		bc_freq_val = 2;
+		break;
+
+	case RXPORT_MODE_CSI2_SYNC:
+		bc_freq_val = 6;
+		break;
+
+	default:
+		return;
+	}
+
+	ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
+				 UB960_RR_BCC_CONFIG_BC_FREQ_SEL_MASK,
+				 bc_freq_val);
+
+	switch (rxport->rx_mode) {
+	case RXPORT_MODE_RAW10:
+		/* FPD3_MODE = RAW10 Mode (DS90UB913A-Q1 / DS90UB933-Q1 compatible) */
+		ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG,
+					 UB960_RR_PORT_CONFIG_FPD3_MODE_MASK,
+					 0x3);
+
+		/*
+		 * RAW10_8BIT_CTL = 0b10 : 8-bit processing using upper 8 bits
+		 */
+		ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2,
+			UB960_RR_PORT_CONFIG2_RAW10_8BIT_CTL_MASK,
+			0x2 << UB960_RR_PORT_CONFIG2_RAW10_8BIT_CTL_SHIFT);
+
+		break;
+
+	case RXPORT_MODE_RAW12_HF:
+	case RXPORT_MODE_RAW12_LF:
+		/* Not implemented */
+		return;
+
+	case RXPORT_MODE_CSI2_SYNC:
+	case RXPORT_MODE_CSI2_ASYNC:
+		/* CSI-2 Mode (DS90UB953-Q1 compatible) */
+		ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG, 0x3,
+					 0x0);
+
+		break;
+	}
+
+	/* LV_POLARITY & FV_POLARITY */
+	ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2, 0x3,
+				 rxport->lv_fv_pol);
+
+	/* Enable all interrupt sources from this port */
+	ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_HI, 0x07);
+	ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_LO, 0x7f);
+
+	/* Enable I2C_PASS_THROUGH */
+	ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
+				 UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
+				 UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH);
+
+	/* Enable I2C communication to the serializer via the alias addr */
+	ub960_rxport_write(priv, nport, UB960_RR_SER_ALIAS_ID,
+			   rxport->ser.alias << 1);
+
+	/* Configure EQ related settings */
+	ub960_rxport_config_eq(priv, nport);
+
+	/* Enable RX port */
+	ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport));
+}
+
+static void ub960_init_rx_port_ub9702_fpd3(struct ub960_data *priv,
+					   struct ub960_rxport *rxport)
+{
+	unsigned int nport = rxport->nport;
+	u8 bc_freq_val;
+	u8 fpd_func_mode;
+
+	switch (rxport->rx_mode) {
+	case RXPORT_MODE_RAW10:
+		bc_freq_val = 0;
+		fpd_func_mode = 5;
+		break;
+
+	case RXPORT_MODE_RAW12_HF:
+		bc_freq_val = 0;
+		fpd_func_mode = 4;
+		break;
+
+	case RXPORT_MODE_RAW12_LF:
+		bc_freq_val = 0;
+		fpd_func_mode = 6;
+		break;
+
+	case RXPORT_MODE_CSI2_SYNC:
+		bc_freq_val = 6;
+		fpd_func_mode = 2;
+		break;
+
+	case RXPORT_MODE_CSI2_ASYNC:
+		bc_freq_val = 2;
+		fpd_func_mode = 2;
+		break;
+
+	default:
+		return;
+	}
+
+	ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, 0x7,
+				 bc_freq_val);
+	ub960_rxport_write(priv, nport, UB960_RR_CHANNEL_MODE, fpd_func_mode);
+
+	/* set serdes_eq_mode = 1 */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xa8, 0x80);
+
+	/* enable serdes driver */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x0d, 0x7f);
+
+	/* set serdes_eq_offset=4 */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x04);
+
+	/* init default serdes_eq_max in 0xa9 */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xa9, 0x23);
+
+	/* init serdes_eq_min in 0xaa */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xaa, 0);
+
+	/* serdes_driver_ctl2 control: DS90UB953-Q1/DS90UB933-Q1/DS90UB913A-Q1 */
+	ub960_ind_update_bits(priv, UB960_IND_TARGET_RX_ANA(nport), 0x1b,
+			      BIT(3), BIT(3));
+
+	/* RX port to half-rate */
+	ub960_update_bits(priv, UB960_SR_FPD_RATE_CFG, 0x3 << (nport * 2),
+			  BIT(nport * 2));
+}
+
+static void ub960_init_rx_port_ub9702_fpd4_aeq(struct ub960_data *priv,
+					       struct ub960_rxport *rxport)
+{
+	unsigned int nport = rxport->nport;
+	bool first_time_power_up = true;
+
+	if (first_time_power_up) {
+		u8 v;
+
+		/* AEQ init */
+		ub960_read_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2c, &v);
+
+		ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x27, v);
+		ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x28, v + 1);
+
+		ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x00);
+	}
+
+	/* enable serdes_eq_ctl2 */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x9e, 0x00);
+
+	/* enable serdes_eq_ctl1 */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x90, 0x40);
+
+	/* enable serdes_eq_en */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2e, 0x40);
+
+	/* disable serdes_eq_override */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0xf0, 0x00);
+
+	/* disable serdes_gain_override */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x71, 0x00);
+}
+
+static void ub960_init_rx_port_ub9702_fpd4(struct ub960_data *priv,
+					   struct ub960_rxport *rxport)
+{
+	unsigned int nport = rxport->nport;
+	u8 bc_freq_val;
+
+	switch (rxport->rx_mode) {
+	case RXPORT_MODE_RAW10:
+		bc_freq_val = 0;
+		break;
+
+	case RXPORT_MODE_RAW12_HF:
+		bc_freq_val = 0;
+		break;
+
+	case RXPORT_MODE_RAW12_LF:
+		bc_freq_val = 0;
+		break;
+
+	case RXPORT_MODE_CSI2_SYNC:
+		bc_freq_val = 6;
+		break;
+
+	case RXPORT_MODE_CSI2_ASYNC:
+		bc_freq_val = 2;
+		break;
+
+	default:
+		return;
+	}
+
+	ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG, 0x7,
+				 bc_freq_val);
+
+	/* FPD4 Sync Mode */
+	ub960_rxport_write(priv, nport, UB960_RR_CHANNEL_MODE, 0);
+
+	/* add serdes_eq_offset of 4 */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x2b, 0x04);
+
+	/* FPD4 serdes_start_eq in 0x27: assign default */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x27, 0x0);
+	/* FPD4 serdes_end_eq in 0x28: assign default */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x28, 0x23);
+
+	/* set serdes_driver_mode into FPD IV mode */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x04, 0x00);
+	/* set FPD PBC drv into FPD IV mode */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x1b, 0x00);
+
+	/* set serdes_system_init to 0x2f */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x21, 0x2f);
+	/* set serdes_system_rst in reset mode */
+	ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x25, 0xc1);
+
+	/* RX port to 7.55G mode */
+	ub960_update_bits(priv, UB960_SR_FPD_RATE_CFG, 0x3 << (nport * 2),
+			  0 << (nport * 2));
+
+	ub960_init_rx_port_ub9702_fpd4_aeq(priv, rxport);
+}
+
+static void ub960_init_rx_port_ub9702(struct ub960_data *priv,
+				      struct ub960_rxport *rxport)
+{
+	unsigned int nport = rxport->nport;
+
+	if (rxport->cdr_mode == RXPORT_CDR_FPD3)
+		ub960_init_rx_port_ub9702_fpd3(priv, rxport);
+	else /* RXPORT_CDR_FPD4 */
+		ub960_init_rx_port_ub9702_fpd4(priv, rxport);
+
+	switch (rxport->rx_mode) {
+	case RXPORT_MODE_RAW10:
+		/*
+		 * RAW10_8BIT_CTL = 0b11 : 8-bit processing using lower 8 bits
+		 * 0b10 : 8-bit processing using upper 8 bits
+		 */
+		ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2,
+					 0x3 << 6, 0x2 << 6);
+
+		break;
+
+	case RXPORT_MODE_RAW12_HF:
+	case RXPORT_MODE_RAW12_LF:
+		/* Not implemented */
+		return;
+
+	case RXPORT_MODE_CSI2_SYNC:
+	case RXPORT_MODE_CSI2_ASYNC:
+
+		break;
+	}
+
+	/* LV_POLARITY & FV_POLARITY */
+	ub960_rxport_update_bits(priv, nport, UB960_RR_PORT_CONFIG2, 0x3,
+				 rxport->lv_fv_pol);
+
+	/* Enable all interrupt sources from this port */
+	ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_HI, 0x07);
+	ub960_rxport_write(priv, nport, UB960_RR_PORT_ICR_LO, 0x7f);
+
+	/* Enable I2C_PASS_THROUGH */
+	ub960_rxport_update_bits(priv, nport, UB960_RR_BCC_CONFIG,
+				 UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH,
+				 UB960_RR_BCC_CONFIG_I2C_PASS_THROUGH);
+
+	/* Enable I2C communication to the serializer via the alias addr */
+	ub960_rxport_write(priv, nport, UB960_RR_SER_ALIAS_ID,
+			   rxport->ser.alias << 1);
+
+	/* Enable RX port */
+	ub960_update_bits(priv, UB960_SR_RX_PORT_CTL, BIT(nport), BIT(nport));
+
+	if (rxport->cdr_mode == RXPORT_CDR_FPD4) {
+		/* unreset 960 AEQ */
+		ub960_write_ind(priv, UB960_IND_TARGET_RX_ANA(nport), 0x25, 0x41);
+	}
+}
+
+static int ub960_init_rx_ports(struct ub960_data *priv)
+{
+	unsigned int nport;
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+		struct ub960_rxport *rxport = priv->rxports[nport];
+
+		if (!rxport)
+			continue;
+
+		if (priv->hw_data->is_ub9702)
+			ub960_init_rx_port_ub9702(priv, rxport);
+		else
+			ub960_init_rx_port_ub960(priv, rxport);
+	}
+
+	return 0;
+}
+
+static void ub960_rxport_handle_events(struct ub960_data *priv, u8 nport)
+{
+	struct device *dev = &priv->client->dev;
+	u8 rx_port_sts1;
+	u8 rx_port_sts2;
+	u8 csi_rx_sts;
+	u8 bcc_sts;
+	int ret = 0;
+
+	/* Read interrupts (also clears most of them) */
+	if (!ret)
+		ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1,
+					&rx_port_sts1);
+	if (!ret)
+		ret = ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2,
+					&rx_port_sts2);
+	if (!ret)
+		ret = ub960_rxport_read(priv, nport, UB960_RR_CSI_RX_STS,
+					&csi_rx_sts);
+	if (!ret)
+		ret = ub960_rxport_read(priv, nport, UB960_RR_BCC_STATUS,
+					&bcc_sts);
+
+	if (ret)
+		return;
+
+	if (rx_port_sts1 & UB960_RR_RX_PORT_STS1_PARITY_ERROR) {
+		u16 v;
+
+		ret = ub960_rxport_read16(priv, nport, UB960_RR_RX_PAR_ERR_HI,
+					  &v);
+		if (!ret)
+			dev_err(dev, "rx%u parity errors: %u\n", nport, v);
+	}
+
+	if (rx_port_sts1 & UB960_RR_RX_PORT_STS1_BCC_CRC_ERROR)
+		dev_err(dev, "rx%u BCC CRC error\n", nport);
+
+	if (rx_port_sts1 & UB960_RR_RX_PORT_STS1_BCC_SEQ_ERROR)
+		dev_err(dev, "rx%u BCC SEQ error\n", nport);
+
+	if (rx_port_sts2 & UB960_RR_RX_PORT_STS2_LINE_LEN_UNSTABLE)
+		dev_err(dev, "rx%u line length unstable\n", nport);
+
+	if (rx_port_sts2 & UB960_RR_RX_PORT_STS2_FPD3_ENCODE_ERROR)
+		dev_err(dev, "rx%u FPD3 encode error\n", nport);
+
+	if (rx_port_sts2 & UB960_RR_RX_PORT_STS2_BUFFER_ERROR)
+		dev_err(dev, "rx%u buffer error\n", nport);
+
+	if (csi_rx_sts)
+		dev_err(dev, "rx%u CSI error: %#02x\n", nport, csi_rx_sts);
+
+	if (csi_rx_sts & UB960_RR_CSI_RX_STS_ECC1_ERR)
+		dev_err(dev, "rx%u CSI ECC1 error\n", nport);
+
+	if (csi_rx_sts & UB960_RR_CSI_RX_STS_ECC2_ERR)
+		dev_err(dev, "rx%u CSI ECC2 error\n", nport);
+
+	if (csi_rx_sts & UB960_RR_CSI_RX_STS_CKSUM_ERR)
+		dev_err(dev, "rx%u CSI checksum error\n", nport);
+
+	if (csi_rx_sts & UB960_RR_CSI_RX_STS_LENGTH_ERR)
+		dev_err(dev, "rx%u CSI length error\n", nport);
+
+	if (bcc_sts)
+		dev_err(dev, "rx%u BCC error: %#02x\n", nport, bcc_sts);
+
+	if (bcc_sts & UB960_RR_BCC_STATUS_RESP_ERR)
+		dev_err(dev, "rx%u BCC response error", nport);
+
+	if (bcc_sts & UB960_RR_BCC_STATUS_SLAVE_TO)
+		dev_err(dev, "rx%u BCC slave timeout", nport);
+
+	if (bcc_sts & UB960_RR_BCC_STATUS_SLAVE_ERR)
+		dev_err(dev, "rx%u BCC slave error", nport);
+
+	if (bcc_sts & UB960_RR_BCC_STATUS_MASTER_TO)
+		dev_err(dev, "rx%u BCC master timeout", nport);
+
+	if (bcc_sts & UB960_RR_BCC_STATUS_MASTER_ERR)
+		dev_err(dev, "rx%u BCC master error", nport);
+
+	if (bcc_sts & UB960_RR_BCC_STATUS_SEQ_ERROR)
+		dev_err(dev, "rx%u BCC sequence error", nport);
+
+	if (rx_port_sts2 & UB960_RR_RX_PORT_STS2_LINE_LEN_CHG) {
+		u16 v;
+
+		ret = ub960_rxport_read16(priv, nport, UB960_RR_LINE_LEN_1, &v);
+		if (!ret)
+			dev_dbg(dev, "rx%u line len changed: %u\n", nport, v);
+	}
+
+	if (rx_port_sts2 & UB960_RR_RX_PORT_STS2_LINE_CNT_CHG) {
+		u16 v;
+
+		ret = ub960_rxport_read16(priv, nport, UB960_RR_LINE_COUNT_HI,
+					  &v);
+		if (!ret)
+			dev_dbg(dev, "rx%u line count changed: %u\n", nport, v);
+	}
+
+	if (rx_port_sts1 & UB960_RR_RX_PORT_STS1_LOCK_STS_CHG) {
+		dev_dbg(dev, "rx%u: %s, %s, %s, %s\n", nport,
+			(rx_port_sts1 & UB960_RR_RX_PORT_STS1_LOCK_STS) ?
+				"locked" :
+				"unlocked",
+			(rx_port_sts1 & UB960_RR_RX_PORT_STS1_PORT_PASS) ?
+				"passed" :
+				"not passed",
+			(rx_port_sts2 & UB960_RR_RX_PORT_STS2_CABLE_FAULT) ?
+				"no clock" :
+				"clock ok",
+			(rx_port_sts2 & UB960_RR_RX_PORT_STS2_FREQ_STABLE) ?
+				"stable freq" :
+				"unstable freq");
+	}
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2
+ */
+
+/*
+ * Map incoming streams with different virtual channels from 1-4 sensors to
+ * unique VCs on CSI TX0. Sensors using multiple VCs will work, but due to
+ * limited total channels (4) this will reduce the total number of sensors that
+ * can work simultaneously.
+ *
+ * The current implementation is limited to using a single CSI TX port (TX0),
+ * as that is the most common HW configuration found on boards with DS90UB960.
+ * For using both CSI TX0 & TX1 the below method will need significant changes.
+ *
+ * TODO: implement a more sophisticated VC mapping. As the driver cannot know
+ * what VCs the sinks expect (say, an FPGA with hardcoded VC routing), this
+ * probably needs to be somehow configurable. Device tree?
+ */
+static void ub960_get_vc_maps(struct ub960_data *priv, u8 *vc_map)
+{
+	struct device *dev = &priv->client->dev;
+	u8 nport, available_vc = 0;
+
+	for (nport = 0;
+	     nport < priv->hw_data->num_rxports && priv->rxports[nport];
+	     ++nport) {
+		struct v4l2_mbus_frame_desc source_fd;
+		bool used_vc[UB960_MAX_VC] = {false};
+		u8 vc, cur_vc = available_vc;
+		int j, ret;
+		u8 map;
+
+		ret = v4l2_subdev_call(priv->rxports[nport]->source.sd, pad,
+				       get_frame_desc,
+				       priv->rxports[nport]->source.pad,
+				       &source_fd);
+		/* Mark channels used in source in used_vc[] */
+		if (!ret) {
+			for (j = 0; j < source_fd.num_entries; ++j) {
+				u8 source_vc = source_fd.entry[j].bus.csi2.vc;
+
+				if (source_vc < UB960_MAX_VC)
+					used_vc[source_vc] = true;
+			}
+		} else if (ret == -ENOIOCTLCMD) {
+			/* assume VC=0 is used if sensor driver doesn't provide info */
+			used_vc[0] = true;
+		} else {
+			continue;
+		}
+
+		/* Start with all channels mapped to first free output */
+		map = (cur_vc << 6) | (cur_vc << 4) | (cur_vc << 2) |
+			(cur_vc << 0);
+
+		/* Map actually used to channels to distinct free outputs */
+		for (vc = 0; vc < UB960_MAX_VC; ++vc) {
+			if (used_vc[vc]) {
+				map &= ~(0x03 << (2 * vc));
+				map |= (cur_vc << (2 * vc));
+				++cur_vc;
+			}
+		}
+
+		/* Don't enable port if we ran out of available channels */
+		if (cur_vc > UB960_MAX_VC) {
+			dev_err(dev,
+				"No VCs available for RX port %d\n",
+				nport);
+			continue;
+		}
+
+		/* Enable port and update map */
+		vc_map[nport] = map;
+		available_vc = cur_vc;
+		dev_dbg(dev, "%s: VC map for port %d is 0x%02x",
+			__func__, nport, map);
+	}
+}
+
+static int ub960_enable_tx_port(struct ub960_data *priv, unsigned int nport)
+{
+	struct device *dev = &priv->client->dev;
+
+	dev_dbg(dev, "enable TX port %u\n", nport);
+
+	return ub960_txport_update_bits(priv, nport, UB960_TR_CSI_CTL,
+					UB960_TR_CSI_CTL_CSI_ENABLE,
+					UB960_TR_CSI_CTL_CSI_ENABLE);
+}
+
+static void ub960_disable_tx_port(struct ub960_data *priv, unsigned int nport)
+{
+	struct device *dev = &priv->client->dev;
+
+	dev_dbg(dev, "disable TX port %u\n", nport);
+
+	ub960_txport_update_bits(priv, nport, UB960_TR_CSI_CTL,
+				 UB960_TR_CSI_CTL_CSI_ENABLE, 0);
+}
+
+static int ub960_enable_rx_port(struct ub960_data *priv, unsigned int nport)
+{
+	struct device *dev = &priv->client->dev;
+
+	dev_dbg(dev, "enable RX port %u\n", nport);
+
+	/* Enable forwarding */
+	return ub960_update_bits(priv, UB960_SR_FWD_CTL1, BIT(4 + nport), 0);
+}
+
+static void ub960_disable_rx_port(struct ub960_data *priv, unsigned int nport)
+{
+	struct device *dev = &priv->client->dev;
+
+	dev_dbg(dev, "disable RX port %u\n", nport);
+
+	/* Disable forwarding */
+	ub960_update_bits(priv, UB960_SR_FWD_CTL1, BIT(4 + nport),
+			  BIT(4 + nport));
+}
+
+static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
+					       struct v4l2_subdev_state *state)
+{
+	u8 fwd_ctl;
+	struct {
+		u32 num_streams;
+		u8 pixel_dt;
+		u8 meta_dt;
+		u32 meta_lines;
+		u32 tx_port;
+	} rx_data[UB960_MAX_RX_NPORTS] = {};
+	u8 vc_map[UB960_MAX_RX_NPORTS] = {};
+	struct v4l2_subdev_route *route;
+	unsigned int nport;
+
+	ub960_get_vc_maps(priv, vc_map);
+
+	for_each_active_route(&state->routing, route) {
+		struct ub960_rxport *rxport;
+		struct ub960_txport *txport;
+		struct v4l2_mbus_framefmt *fmt;
+		const struct ub960_format_info *ub960_fmt;
+		unsigned int nport;
+
+		nport = ub960_pad_to_port(priv, route->sink_pad);
+
+		rxport = priv->rxports[nport];
+		if (!rxport)
+			return -EINVAL;
+
+		txport = priv->txports[ub960_pad_to_port(priv, route->source_pad)];
+		if (!txport)
+			return -EINVAL;
+
+		rx_data[nport].tx_port = ub960_pad_to_port(priv, route->source_pad);
+
+		rx_data[nport].num_streams++;
+
+		/* For the rest, we are only interested in parallel busses */
+		if (rxport->rx_mode == RXPORT_MODE_CSI2_SYNC ||
+		    rxport->rx_mode == RXPORT_MODE_CSI2_ASYNC)
+			continue;
+
+		if (rx_data[nport].num_streams > 2)
+			return -EPIPE;
+
+		fmt = v4l2_subdev_state_get_stream_format(state,
+							  route->sink_pad,
+							  route->sink_stream);
+		if (!fmt)
+			return -EPIPE;
+
+		ub960_fmt = ub960_find_format(fmt->code);
+		if (!ub960_fmt)
+			return -EPIPE;
+
+		if (ub960_fmt->meta) {
+			if (fmt->height > 3) {
+				dev_err(&priv->client->dev,
+					"rx%u: unsupported metadata height %u\n",
+					nport, fmt->height);
+				return -EPIPE;
+			}
+
+			rx_data[nport].meta_dt = ub960_fmt->datatype;
+			rx_data[nport].meta_lines = fmt->height;
+		} else {
+			rx_data[nport].pixel_dt = ub960_fmt->datatype;
+		}
+	}
+
+	/* Configure RX ports */
+
+	fwd_ctl = 0;
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+		struct ub960_rxport *rxport = priv->rxports[nport];
+
+		if (rx_data[nport].num_streams == 0)
+			continue;
+
+		switch (rxport->rx_mode) {
+		case RXPORT_MODE_RAW10:
+			ub960_rxport_write(priv, nport, UB960_RR_RAW10_ID,
+				rx_data[nport].pixel_dt | (nport << UB960_RR_RAW10_ID_VC_SHIFT));
+
+			ub960_rxport_write(priv, rxport->nport,
+				UB960_RR_RAW_EMBED_DTYPE,
+				(rx_data[nport].meta_lines << UB960_RR_RAW_EMBED_DTYPE_LINES_SHIFT) |
+					rx_data[nport].meta_dt);
+
+			break;
+
+		case RXPORT_MODE_RAW12_HF:
+		case RXPORT_MODE_RAW12_LF:
+			/* Not implemented */
+			break;
+
+		case RXPORT_MODE_CSI2_SYNC:
+		case RXPORT_MODE_CSI2_ASYNC:
+			if (!priv->hw_data->is_ub9702) {
+				ub960_rxport_write(priv, nport,
+						   UB960_RR_CSI_VC_MAP,
+						   vc_map[nport]);
+			} else {
+				unsigned int i;
+
+				/* Map all VCs from this port to VC(nport) */
+				for (i = 0; i < 8; i++)
+					ub960_rxport_write(priv, nport,
+							   UB960_RR_VC_ID_MAP(i),
+							   nport);
+			}
+
+			break;
+		}
+
+		/* Forwarding */
+
+		fwd_ctl |= BIT(4 + nport); /* forward disable */
+
+		if (rx_data[nport].tx_port == 1)
+			fwd_ctl |= BIT(nport); /* forward to TX1 */
+		else
+			fwd_ctl &= ~BIT(nport); /* forward to TX0 */
+	}
+
+	ub960_write(priv, UB960_SR_FWD_CTL1, fwd_ctl);
+
+	return 0;
+}
+
+static void ub960_update_streaming_status(struct ub960_data *priv)
+{
+	unsigned int i;
+
+	for (i = 0; i < UB960_MAX_NPORTS; i++) {
+		if (priv->stream_enable_mask[i])
+			break;
+	}
+
+	priv->streaming = i < UB960_MAX_NPORTS;
+}
+
+static int ub960_enable_streams(struct v4l2_subdev *sd,
+				struct v4l2_subdev_state *state, u32 source_pad,
+				u64 source_streams_mask)
+{
+	struct ub960_data *priv = sd_to_ub960(sd);
+	struct device *dev = &priv->client->dev;
+	u64 sink_streams[UB960_MAX_RX_NPORTS] = {};
+	struct v4l2_subdev_route *route;
+	unsigned int failed_port;
+	unsigned int nport;
+	int ret;
+
+	if (!priv->streaming) {
+		dev_dbg(dev, "Prepare for streaming\n");
+		ret = ub960_configure_ports_for_streaming(priv, state);
+		if (ret)
+			return ret;
+	}
+
+	/* Enable TX port if not yet enabled */
+	if (!priv->stream_enable_mask[source_pad]) {
+		ret = ub960_enable_tx_port(priv,
+					   ub960_pad_to_port(priv, source_pad));
+		if (ret)
+			return ret;
+	}
+
+	priv->stream_enable_mask[source_pad] |= source_streams_mask;
+
+	/* Collect sink streams per pad which we need to enable */
+	for_each_active_route(&state->routing, route) {
+		if (route->source_pad != source_pad)
+			continue;
+
+		if (!(source_streams_mask & BIT_ULL(route->source_stream)))
+			continue;
+
+		nport = ub960_pad_to_port(priv, route->sink_pad);
+
+		sink_streams[nport] |= BIT_ULL(route->sink_stream);
+	}
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+		if (!sink_streams[nport])
+			continue;
+
+		/* Enable the RX port if not yet enabled */
+		if (!priv->stream_enable_mask[nport]) {
+			ret = ub960_enable_rx_port(priv, nport);
+			if (ret) {
+				failed_port = nport;
+				goto err;
+			}
+		}
+
+		priv->stream_enable_mask[nport] |= sink_streams[nport];
+
+		dev_dbg(dev, "enable RX port %u streams %#llx\n", nport,
+			sink_streams[nport]);
+
+		ret = v4l2_subdev_enable_streams(
+			priv->rxports[nport]->source.sd,
+			priv->rxports[nport]->source.pad,
+			sink_streams[nport]);
+		if (ret) {
+			priv->stream_enable_mask[nport] &= ~sink_streams[nport];
+
+			if (!priv->stream_enable_mask[nport])
+				ub960_disable_rx_port(priv, nport);
+
+			failed_port = nport;
+			goto err;
+		}
+	}
+
+	priv->streaming = true;
+
+	return 0;
+
+err:
+	for (nport = 0; nport < failed_port; nport++) {
+		if (!sink_streams[nport])
+			continue;
+
+		dev_dbg(dev, "disable RX port %u streams %#llx\n", nport,
+			sink_streams[nport]);
+
+		ret = v4l2_subdev_disable_streams(
+			priv->rxports[nport]->source.sd,
+			priv->rxports[nport]->source.pad,
+			sink_streams[nport]);
+		if (ret)
+			dev_err(dev, "Failed to disable streams: %d\n", ret);
+
+		priv->stream_enable_mask[nport] &= ~sink_streams[nport];
+
+		/* Disable RX port if no active streams */
+		if (!priv->stream_enable_mask[nport])
+			ub960_disable_rx_port(priv, nport);
+	}
+
+	priv->stream_enable_mask[source_pad] &= ~source_streams_mask;
+
+	if (!priv->stream_enable_mask[source_pad])
+		ub960_disable_tx_port(priv,
+				      ub960_pad_to_port(priv, source_pad));
+
+	ub960_update_streaming_status(priv);
+
+	return ret;
+}
+
+static int ub960_disable_streams(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_state *state,
+				 u32 source_pad, u64 source_streams_mask)
+{
+	struct ub960_data *priv = sd_to_ub960(sd);
+	struct device *dev = &priv->client->dev;
+	u64 sink_streams[UB960_MAX_RX_NPORTS] = {};
+	struct v4l2_subdev_route *route;
+	unsigned int nport;
+	int ret;
+
+	/* Collect sink streams per pad which we need to disable */
+	for_each_active_route(&state->routing, route) {
+		if (route->source_pad != source_pad)
+			continue;
+
+		if (!(source_streams_mask & BIT_ULL(route->source_stream)))
+			continue;
+
+		nport = ub960_pad_to_port(priv, route->sink_pad);
+
+		sink_streams[nport] |= BIT_ULL(route->sink_stream);
+	}
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+		if (!sink_streams[nport])
+			continue;
+
+		dev_dbg(dev, "disable RX port %u streams %#llx\n", nport,
+			sink_streams[nport]);
+
+		ret = v4l2_subdev_disable_streams(
+			priv->rxports[nport]->source.sd,
+			priv->rxports[nport]->source.pad,
+			sink_streams[nport]);
+		if (ret)
+			dev_err(dev, "Failed to disable streams: %d\n", ret);
+
+		priv->stream_enable_mask[nport] &= ~sink_streams[nport];
+
+		/* Disable RX port if no active streams */
+		if (!priv->stream_enable_mask[nport])
+			ub960_disable_rx_port(priv, nport);
+	}
+
+	/* Disable TX port if no active streams */
+
+	priv->stream_enable_mask[source_pad] &= ~source_streams_mask;
+
+	if (!priv->stream_enable_mask[source_pad])
+		ub960_disable_tx_port(priv,
+				      ub960_pad_to_port(priv, source_pad));
+
+	ub960_update_streaming_status(priv);
+
+	return 0;
+}
+
+static int _ub960_set_routing(struct v4l2_subdev *sd,
+			      struct v4l2_subdev_state *state,
+			      struct v4l2_subdev_krouting *routing)
+{
+	static const struct v4l2_mbus_framefmt format = {
+		.width = 640,
+		.height = 480,
+		.code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.field = V4L2_FIELD_NONE,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.ycbcr_enc = V4L2_YCBCR_ENC_601,
+		.quantization = V4L2_QUANTIZATION_LIM_RANGE,
+		.xfer_func = V4L2_XFER_FUNC_SRGB,
+	};
+	int ret;
+
+	/*
+	 * Note: we can only support up to V4L2_FRAME_DESC_ENTRY_MAX, until
+	 * frame desc is made dynamically allocated.
+	 */
+
+	if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX)
+		return -E2BIG;
+
+	ret = v4l2_subdev_routing_validate(sd, routing,
+					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1 |
+					   V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX);
+	if (ret)
+		return ret;
+
+	ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int ub960_set_routing(struct v4l2_subdev *sd,
+			     struct v4l2_subdev_state *state,
+			     enum v4l2_subdev_format_whence which,
+			     struct v4l2_subdev_krouting *routing)
+{
+	struct ub960_data *priv = sd_to_ub960(sd);
+
+	if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->streaming)
+		return -EBUSY;
+
+	return _ub960_set_routing(sd, state, routing);
+}
+
+static inline u8 ub960_get_output_vc(u8 map, u8 input_vc)
+{
+	return (map >> (2 * input_vc)) & 0x03;
+}
+
+static int ub960_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+				struct v4l2_mbus_frame_desc *fd)
+{
+	struct ub960_data *priv = sd_to_ub960(sd);
+	struct v4l2_subdev_route *route;
+	struct v4l2_subdev_state *state;
+	int ret = 0;
+	struct device *dev = &priv->client->dev;
+	u8 vc_map[UB960_MAX_RX_NPORTS] = {};
+
+	if (!ub960_pad_is_source(priv, pad))
+		return -EINVAL;
+
+	memset(fd, 0, sizeof(*fd));
+
+	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
+
+	state = v4l2_subdev_lock_and_get_active_state(&priv->sd);
+
+	ub960_get_vc_maps(priv, vc_map);
+
+	for_each_active_route(&state->routing, route) {
+		struct v4l2_mbus_frame_desc_entry *source_entry = NULL;
+		struct v4l2_mbus_frame_desc source_fd;
+		unsigned int nport;
+		unsigned int i;
+
+		if (route->source_pad != pad)
+			continue;
+
+		nport = ub960_pad_to_port(priv, route->sink_pad);
+
+		ret = v4l2_subdev_call(priv->rxports[nport]->source.sd, pad,
+				       get_frame_desc,
+				       priv->rxports[nport]->source.pad,
+				       &source_fd);
+		if (ret) {
+			dev_err(dev,
+				"Failed to get source frame desc for pad %u\n",
+				route->sink_pad);
+			goto out_unlock;
+		}
+
+		for (i = 0; i < source_fd.num_entries; i++) {
+			if (source_fd.entry[i].stream == route->sink_stream) {
+				source_entry = &source_fd.entry[i];
+				break;
+			}
+		}
+
+		if (!source_entry) {
+			dev_err(dev,
+				"Failed to find stream from source frame desc\n");
+			ret = -EPIPE;
+			goto out_unlock;
+		}
+
+		fd->entry[fd->num_entries].stream = route->source_stream;
+		fd->entry[fd->num_entries].flags = source_entry->flags;
+		fd->entry[fd->num_entries].length = source_entry->length;
+		fd->entry[fd->num_entries].pixelcode = source_entry->pixelcode;
+
+		fd->entry[fd->num_entries].bus.csi2.vc =
+			ub960_get_output_vc(vc_map[nport],
+					    source_entry->bus.csi2.vc);
+		dev_dbg(dev, "Mapping sink %d/%d to output VC %d",
+			route->sink_pad, route->sink_stream,
+			fd->entry[fd->num_entries].bus.csi2.vc);
+
+		if (source_fd.type == V4L2_MBUS_FRAME_DESC_TYPE_CSI2) {
+			fd->entry[fd->num_entries].bus.csi2.dt =
+				source_entry->bus.csi2.dt;
+		} else {
+			const struct ub960_format_info *ub960_fmt;
+			struct v4l2_mbus_framefmt *fmt;
+
+			fmt = v4l2_subdev_state_get_stream_format(state, pad,
+								  route->source_stream);
+
+			if (!fmt) {
+				ret = -EINVAL;
+				goto out_unlock;
+			}
+
+			ub960_fmt = ub960_find_format(fmt->code);
+			if (!ub960_fmt) {
+				dev_err(dev, "Unable to find format\n");
+				ret = -EINVAL;
+				goto out_unlock;
+			}
+
+			fd->entry[fd->num_entries].bus.csi2.dt =
+				ub960_fmt->datatype;
+		}
+
+		fd->num_entries++;
+	}
+
+out_unlock:
+	v4l2_subdev_unlock_state(state);
+
+	return ret;
+}
+
+static int ub960_set_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_subdev_state *state,
+			 struct v4l2_subdev_format *format)
+{
+	struct ub960_data *priv = sd_to_ub960(sd);
+	struct v4l2_mbus_framefmt *fmt;
+
+	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->streaming)
+		return -EBUSY;
+
+	/* No transcoding, source and sink formats must match. */
+	if (ub960_pad_is_source(priv, format->pad))
+		return v4l2_subdev_get_fmt(sd, state, format);
+
+	/*
+	 * Default to the first format if the requested media bus code isn't
+	 * supported.
+	 */
+	if (!ub960_find_format(format->format.code))
+		format->format.code = ub960_formats[0].code;
+
+	fmt = v4l2_subdev_state_get_stream_format(state, format->pad,
+						  format->stream);
+	if (!fmt)
+		return -EINVAL;
+
+	*fmt = format->format;
+
+	fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
+							   format->stream);
+	if (!fmt)
+		return -EINVAL;
+
+	*fmt = format->format;
+
+	return 0;
+}
+
+static int ub960_init_cfg(struct v4l2_subdev *sd,
+			  struct v4l2_subdev_state *state)
+{
+	struct ub960_data *priv = sd_to_ub960(sd);
+
+	struct v4l2_subdev_route routes[] = {
+		{
+			.sink_pad = 0,
+			.sink_stream = 0,
+			.source_pad = priv->hw_data->num_rxports,
+			.source_stream = 0,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+	};
+
+	struct v4l2_subdev_krouting routing = {
+		.num_routes = ARRAY_SIZE(routes),
+		.routes = routes,
+	};
+
+	return _ub960_set_routing(sd, state, &routing);
+}
+
+static const struct v4l2_subdev_pad_ops ub960_pad_ops = {
+	.enable_streams = ub960_enable_streams,
+	.disable_streams = ub960_disable_streams,
+
+	.set_routing = ub960_set_routing,
+	.get_frame_desc = ub960_get_frame_desc,
+
+	.get_fmt = v4l2_subdev_get_fmt,
+	.set_fmt = ub960_set_fmt,
+
+	.init_cfg = ub960_init_cfg,
+};
+
+static int ub960_log_status(struct v4l2_subdev *sd)
+{
+	struct ub960_data *priv = sd_to_ub960(sd);
+	struct device *dev = &priv->client->dev;
+	struct v4l2_subdev_state *state;
+	unsigned int nport;
+	unsigned int i;
+	u16 v16 = 0;
+	u8 v = 0;
+	u8 id[UB960_SR_FPD3_RX_ID_LEN];
+
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	for (i = 0; i < sizeof(id); i++)
+		ub960_read(priv, UB960_SR_FPD3_RX_ID(i), &id[i]);
+
+	dev_info(dev, "ID '%.*s'\n", (int)sizeof(id), id);
+
+	for (nport = 0; nport < priv->hw_data->num_txports; nport++) {
+		struct ub960_txport *txport = priv->txports[nport];
+
+		dev_info(dev, "TX %u\n", nport);
+
+		if (!txport) {
+			dev_info(dev, "\tNot initialized\n");
+			continue;
+		}
+
+		ub960_txport_read(priv, nport, UB960_TR_CSI_STS, &v);
+		dev_info(dev, "\tsync %u, pass %u\n", v & (u8)BIT(1),
+			 v & (u8)BIT(0));
+
+		ub960_read16(priv, UB960_SR_CSI_FRAME_COUNT_HI(nport), &v16);
+		dev_info(dev, "\tframe counter %u\n", v16);
+
+		ub960_read16(priv, UB960_SR_CSI_FRAME_ERR_COUNT_HI(nport), &v16);
+		dev_info(dev, "\tframe error counter %u\n", v16);
+
+		ub960_read16(priv, UB960_SR_CSI_LINE_COUNT_HI(nport), &v16);
+		dev_info(dev, "\tline counter %u\n", v16);
+
+		ub960_read16(priv, UB960_SR_CSI_LINE_ERR_COUNT_HI(nport), &v16);
+		dev_info(dev, "\tline error counter %u\n", v16);
+	}
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+		struct ub960_rxport *rxport = priv->rxports[nport];
+		u8 eq_level;
+		s8 strobe_pos;
+		unsigned int i;
+
+		dev_info(dev, "RX %u\n", nport);
+
+		if (!rxport) {
+			dev_info(dev, "\tNot initialized\n");
+			continue;
+		}
+
+		ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS1, &v);
+
+		if (v & UB960_RR_RX_PORT_STS1_LOCK_STS)
+			dev_info(dev, "\tLocked\n");
+		else
+			dev_info(dev, "\tNot locked\n");
+
+		dev_info(dev, "\trx_port_sts1 %#02x\n", v);
+		ub960_rxport_read(priv, nport, UB960_RR_RX_PORT_STS2, &v);
+		dev_info(dev, "\trx_port_sts2 %#02x\n", v);
+
+		ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH, &v16);
+		dev_info(dev, "\tlink freq %llu Hz\n", (v16 * 1000000ULL) >> 8);
+
+		ub960_rxport_read16(priv, nport, UB960_RR_RX_PAR_ERR_HI, &v16);
+		dev_info(dev, "\tparity errors %u\n", v16);
+
+		ub960_rxport_read16(priv, nport, UB960_RR_LINE_COUNT_HI, &v16);
+		dev_info(dev, "\tlines per frame %u\n", v16);
+
+		ub960_rxport_read16(priv, nport, UB960_RR_LINE_LEN_1, &v16);
+		dev_info(dev, "\tbytes per line %u\n", v16);
+
+		ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER, &v);
+		dev_info(dev, "\tcsi_err_counter %u\n", v);
+
+		/* Strobe */
+
+		ub960_read(priv, UB960_XR_AEQ_CTL1, &v);
+
+		dev_info(dev, "\t%s strobe\n",
+			 (v & UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN) ? "Adaptive" :
+								  "Manual");
+
+		if (v & UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN) {
+			ub960_read(priv, UB960_XR_SFILTER_CFG, &v);
+
+			dev_info(dev, "\tStrobe range [%d, %d]\n",
+				 ((v >> UB960_XR_SFILTER_CFG_SFILTER_MIN_SHIFT) & 0xf) - 7,
+				 ((v >> UB960_XR_SFILTER_CFG_SFILTER_MAX_SHIFT) & 0xf) - 7);
+		}
+
+		ub960_rxport_get_strobe_pos(priv, nport, &strobe_pos);
+
+		dev_info(dev, "\tStrobe pos %d\n", strobe_pos);
+
+		/* EQ */
+
+		ub960_rxport_read(priv, nport, UB960_RR_AEQ_BYPASS, &v);
+
+		dev_info(dev, "\t%s EQ\n",
+			 (v & UB960_RR_AEQ_BYPASS_ENABLE) ? "Manual" :
+							    "Adaptive");
+
+		if (!(v & UB960_RR_AEQ_BYPASS_ENABLE)) {
+			ub960_rxport_read(priv, nport, UB960_RR_AEQ_MIN_MAX, &v);
+
+			dev_info(dev, "\tEQ range [%u, %u]\n",
+				 (v >> UB960_RR_AEQ_MIN_MAX_AEQ_FLOOR_SHIFT) & 0xf,
+				 (v >> UB960_RR_AEQ_MIN_MAX_AEQ_MAX_SHIFT) & 0xf);
+		}
+
+		if (ub960_rxport_get_eq_level(priv, nport, &eq_level) == 0)
+			dev_info(dev, "\tEQ level %u\n", eq_level);
+
+		/* GPIOs */
+		for (i = 0; i < UB960_NUM_BC_GPIOS; i++) {
+			u8 ctl_reg;
+			u8 ctl_shift;
+
+			ctl_reg = UB960_RR_BC_GPIO_CTL(i / 2);
+			ctl_shift = (i % 2) * 4;
+
+			ub960_rxport_read(priv, nport, ctl_reg, &v);
+
+			dev_info(dev, "\tGPIO%u: mode %u\n", i,
+				 (v >> ctl_shift) & 0xf);
+		}
+	}
+
+	v4l2_subdev_unlock_state(state);
+
+	return 0;
+}
+
+static const struct v4l2_subdev_core_ops ub960_subdev_core_ops = {
+	.log_status = ub960_log_status,
+	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
+	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
+};
+
+static const struct v4l2_subdev_ops ub960_subdev_ops = {
+	.core = &ub960_subdev_core_ops,
+	.pad = &ub960_pad_ops,
+};
+
+static const struct media_entity_operations ub960_entity_ops = {
+	.link_validate = v4l2_subdev_link_validate,
+	.has_pad_interdep = v4l2_subdev_has_pad_interdep,
+};
+
+/* -----------------------------------------------------------------------------
+ * Core
+ */
+
+static irqreturn_t ub960_handle_events(int irq, void *arg)
+{
+	struct ub960_data *priv = arg;
+	unsigned int i;
+	u8 int_sts;
+	u8 fwd_sts;
+	int ret;
+
+	ret = ub960_read(priv, UB960_SR_INTERRUPT_STS, &int_sts);
+	if (ret || !int_sts)
+		return IRQ_NONE;
+
+	dev_dbg(&priv->client->dev, "INTERRUPT_STS %x\n", int_sts);
+
+	ret = ub960_read(priv, UB960_SR_FWD_STS, &fwd_sts);
+	if (ret)
+		return IRQ_NONE;
+
+	dev_dbg(&priv->client->dev, "FWD_STS %#02x\n", fwd_sts);
+
+	for (i = 0; i < priv->hw_data->num_txports; i++) {
+		if (int_sts & UB960_SR_INTERRUPT_STS_IS_CSI_TX(i))
+			ub960_csi_handle_events(priv, i);
+	}
+
+	for (i = 0; i < priv->hw_data->num_rxports; i++) {
+		if (!priv->rxports[i])
+			continue;
+
+		if (int_sts & UB960_SR_INTERRUPT_STS_IS_RX(i))
+			ub960_rxport_handle_events(priv, i);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void ub960_handler_work(struct work_struct *work)
+{
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct ub960_data *priv =
+		container_of(dwork, struct ub960_data, poll_work);
+
+	ub960_handle_events(0, priv);
+
+	schedule_delayed_work(&priv->poll_work,
+			      msecs_to_jiffies(UB960_POLL_TIME_MS));
+}
+
+static void ub960_txport_free_ports(struct ub960_data *priv)
+{
+	unsigned int nport;
+
+	for (nport = 0; nport < priv->hw_data->num_txports; nport++) {
+		struct ub960_txport *txport = priv->txports[nport];
+
+		if (!txport)
+			continue;
+
+		kfree(txport);
+		priv->txports[nport] = NULL;
+	}
+}
+
+static void ub960_rxport_free_ports(struct ub960_data *priv)
+{
+	unsigned int nport;
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+		struct ub960_rxport *rxport = priv->rxports[nport];
+
+		if (!rxport)
+			continue;
+
+		fwnode_handle_put(rxport->source.ep_fwnode);
+		fwnode_handle_put(rxport->ser.fwnode);
+
+		kfree(rxport);
+		priv->rxports[nport] = NULL;
+	}
+}
+
+static int
+ub960_parse_dt_rxport_link_properties(struct ub960_data *priv,
+				      struct fwnode_handle *link_fwnode,
+				      struct ub960_rxport *rxport)
+{
+	struct device *dev = &priv->client->dev;
+	unsigned int nport = rxport->nport;
+	u32 rx_mode;
+	u32 cdr_mode;
+	s32 strobe_pos;
+	u32 eq_level;
+	u32 ser_i2c_alias;
+	int ret;
+
+	cdr_mode = RXPORT_CDR_FPD3;
+
+	ret = fwnode_property_read_u32(link_fwnode, "ti,cdr-mode", &cdr_mode);
+	if (ret < 0 && ret != -EINVAL) {
+		dev_err(dev, "rx%u: failed to read '%s': %d\n", nport,
+			"ti,cdr-mode", ret);
+		return ret;
+	}
+
+	if (cdr_mode > RXPORT_CDR_LAST) {
+		dev_err(dev, "rx%u: bad 'ti,cdr-mode' %u\n", nport, cdr_mode);
+		return -EINVAL;
+	}
+
+	if (!priv->hw_data->is_fpdlink4 && cdr_mode == RXPORT_CDR_FPD4) {
+		dev_err(dev, "rx%u: FPD-Link 4 CDR not supported\n", nport);
+		return -EINVAL;
+	}
+
+	rxport->cdr_mode = cdr_mode;
+
+	ret = fwnode_property_read_u32(link_fwnode, "ti,rx-mode", &rx_mode);
+	if (ret < 0) {
+		dev_err(dev, "rx%u: failed to read '%s': %d\n", nport,
+			"ti,rx-mode", ret);
+		return ret;
+	}
+
+	if (rx_mode > RXPORT_MODE_LAST) {
+		dev_err(dev, "rx%u: bad 'ti,rx-mode' %u\n", nport, rx_mode);
+		return -EINVAL;
+	}
+
+	switch (rx_mode) {
+	case RXPORT_MODE_RAW12_HF:
+	case RXPORT_MODE_RAW12_LF:
+	case RXPORT_MODE_CSI2_ASYNC:
+		dev_err(dev, "rx%u: unsupported 'ti,rx-mode' %u\n", nport,
+			rx_mode);
+		return -EINVAL;
+	default:
+		break;
+	}
+
+	rxport->rx_mode = rx_mode;
+
+	/* EQ & Strobe related */
+
+	/* Defaults */
+	rxport->eq.manual_eq = false;
+	rxport->eq.aeq.eq_level_min = UB960_MIN_EQ_LEVEL;
+	rxport->eq.aeq.eq_level_max = UB960_MAX_EQ_LEVEL;
+
+	ret = fwnode_property_read_u32(link_fwnode, "ti,strobe-pos",
+				       &strobe_pos);
+	if (ret) {
+		if (ret != -EINVAL) {
+			dev_err(dev, "rx%u: failed to read '%s': %d\n", nport,
+				"ti,strobe-pos", ret);
+			return ret;
+		}
+	} else {
+		if (strobe_pos < UB960_MIN_MANUAL_STROBE_POS ||
+		    strobe_pos > UB960_MAX_MANUAL_STROBE_POS) {
+			dev_err(dev, "rx%u: illegal 'strobe-pos' value: %d\n",
+				nport, strobe_pos);
+			return -EINVAL;
+		}
+
+		/* NOTE: ignored unless global manual strobe pos is also set */
+		rxport->eq.strobe_pos = strobe_pos;
+		if (!priv->strobe.manual)
+			dev_warn(dev,
+				 "rx%u: 'ti,strobe-pos' ignored as 'ti,manual-strobe' not set\n",
+				 nport);
+	}
+
+	ret = fwnode_property_read_u32(link_fwnode, "ti,eq-level", &eq_level);
+	if (ret) {
+		if (ret != -EINVAL) {
+			dev_err(dev, "rx%u: failed to read '%s': %d\n", nport,
+				"ti,eq-level", ret);
+			return ret;
+		}
+	} else {
+		if (eq_level > UB960_MAX_EQ_LEVEL) {
+			dev_err(dev, "rx%u: illegal 'ti,eq-level' value: %d\n",
+				nport, eq_level);
+			return -EINVAL;
+		}
+
+		rxport->eq.manual_eq = true;
+		rxport->eq.manual.eq_level = eq_level;
+	}
+
+	ret = fwnode_property_read_u32(link_fwnode, "i2c-alias",
+				       &ser_i2c_alias);
+	if (ret) {
+		dev_err(dev, "rx%u: failed to read '%s': %d\n", nport,
+			"i2c-alias", ret);
+		return ret;
+	}
+	rxport->ser.alias = ser_i2c_alias;
+
+	rxport->ser.fwnode = fwnode_get_named_child_node(link_fwnode, "serializer");
+	if (!rxport->ser.fwnode) {
+		dev_err(dev, "rx%u: missing 'serializer' node\n", nport);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ub960_parse_dt_rxport_ep_properties(struct ub960_data *priv,
+					       struct fwnode_handle *ep_fwnode,
+					       struct ub960_rxport *rxport)
+{
+	struct device *dev = &priv->client->dev;
+	struct v4l2_fwnode_endpoint vep = {};
+	unsigned int nport = rxport->nport;
+	bool hsync_hi;
+	bool vsync_hi;
+	int ret;
+
+	rxport->source.ep_fwnode = fwnode_graph_get_remote_endpoint(ep_fwnode);
+	if (!rxport->source.ep_fwnode) {
+		dev_err(dev, "rx%u: no remote endpoint\n", nport);
+		return -ENODEV;
+	}
+
+	/* We currently have properties only for RAW modes */
+
+	switch (rxport->rx_mode) {
+	case RXPORT_MODE_RAW10:
+	case RXPORT_MODE_RAW12_HF:
+	case RXPORT_MODE_RAW12_LF:
+		break;
+	default:
+		return 0;
+	}
+
+	vep.bus_type = V4L2_MBUS_PARALLEL;
+	ret = v4l2_fwnode_endpoint_parse(ep_fwnode, &vep);
+	if (ret) {
+		dev_err(dev, "rx%u: failed to parse endpoint data\n", nport);
+		goto err_put_source_ep_fwnode;
+	}
+
+	hsync_hi = !!(vep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH);
+	vsync_hi = !!(vep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH);
+
+	/* LineValid and FrameValid are inverse to the h/vsync active */
+	rxport->lv_fv_pol = (hsync_hi ? UB960_RR_PORT_CONFIG2_LV_POL_LOW : 0) |
+			    (vsync_hi ? UB960_RR_PORT_CONFIG2_FV_POL_LOW : 0);
+
+	return 0;
+
+err_put_source_ep_fwnode:
+	fwnode_handle_put(rxport->source.ep_fwnode);
+	return ret;
+}
+
+static int ub960_parse_dt_rxport(struct ub960_data *priv, unsigned int nport,
+				 struct fwnode_handle *link_fwnode,
+				 struct fwnode_handle *ep_fwnode)
+{
+	static const char *vpoc_names[UB960_MAX_RX_NPORTS] = {
+		"vpoc0", "vpoc1", "vpoc2", "vpoc3"
+	};
+	struct device *dev = &priv->client->dev;
+	struct ub960_rxport *rxport;
+	int ret;
+
+	rxport = kzalloc(sizeof(*rxport), GFP_KERNEL);
+	if (!rxport)
+		return -ENOMEM;
+
+	priv->rxports[nport] = rxport;
+
+	rxport->nport = nport;
+	rxport->priv = priv;
+
+	ret = ub960_parse_dt_rxport_link_properties(priv, link_fwnode, rxport);
+	if (ret)
+		goto err_free_rxport;
+
+	rxport->vpoc = devm_regulator_get_optional(dev, vpoc_names[nport]);
+	if (IS_ERR(rxport->vpoc)) {
+		ret = PTR_ERR(rxport->vpoc);
+		if (ret == -ENODEV) {
+			rxport->vpoc = NULL;
+		} else {
+			dev_err(dev, "rx%u: failed to get VPOC supply: %d\n",
+				nport, ret);
+			goto err_put_remote_fwnode;
+		}
+	}
+
+	ret = ub960_parse_dt_rxport_ep_properties(priv, ep_fwnode, rxport);
+	if (ret)
+		goto err_put_remote_fwnode;
+
+	return 0;
+
+err_put_remote_fwnode:
+	fwnode_handle_put(rxport->ser.fwnode);
+err_free_rxport:
+	priv->rxports[nport] = NULL;
+	kfree(rxport);
+	return ret;
+}
+
+static struct fwnode_handle *
+ub960_fwnode_get_link_by_regs(struct fwnode_handle *links_fwnode,
+			      unsigned int nport)
+{
+	struct fwnode_handle *link_fwnode;
+	int ret;
+
+	fwnode_for_each_child_node(links_fwnode, link_fwnode) {
+		u32 link_num;
+
+		if (!str_has_prefix(fwnode_get_name(link_fwnode), "link@"))
+			continue;
+
+		ret = fwnode_property_read_u32(link_fwnode, "reg", &link_num);
+		if (ret) {
+			fwnode_handle_put(link_fwnode);
+			return NULL;
+		}
+
+		if (nport == link_num)
+			return link_fwnode;
+	}
+
+	return NULL;
+}
+
+static int ub960_parse_dt_rxports(struct ub960_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	struct fwnode_handle *links_fwnode;
+	unsigned int nport;
+	int ret;
+
+	links_fwnode = fwnode_get_named_child_node(dev_fwnode(dev), "links");
+	if (!links_fwnode) {
+		dev_err(dev, "'links' node missing\n");
+		return -ENODEV;
+	}
+
+	/* Defaults, recommended by TI */
+	priv->strobe.min = 2;
+	priv->strobe.max = 3;
+
+	priv->strobe.manual = fwnode_property_read_bool(links_fwnode, "ti,manual-strobe");
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+		struct fwnode_handle *link_fwnode;
+		struct fwnode_handle *ep_fwnode;
+
+		link_fwnode = ub960_fwnode_get_link_by_regs(links_fwnode, nport);
+		if (!link_fwnode)
+			continue;
+
+		ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
+							    nport, 0, 0);
+		if (!ep_fwnode) {
+			fwnode_handle_put(link_fwnode);
+			continue;
+		}
+
+		ret = ub960_parse_dt_rxport(priv, nport, link_fwnode,
+					    ep_fwnode);
+
+		fwnode_handle_put(link_fwnode);
+		fwnode_handle_put(ep_fwnode);
+
+		if (ret) {
+			dev_err(dev, "rx%u: failed to parse RX port\n", nport);
+			goto err_put_links;
+		}
+	}
+
+	fwnode_handle_put(links_fwnode);
+
+	return 0;
+
+err_put_links:
+	fwnode_handle_put(links_fwnode);
+
+	return ret;
+}
+
+static int ub960_parse_dt_txports(struct ub960_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	u32 nport;
+	int ret;
+
+	for (nport = 0; nport < priv->hw_data->num_txports; nport++) {
+		unsigned int port = nport + priv->hw_data->num_rxports;
+		struct fwnode_handle *ep_fwnode;
+
+		ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
+							    port, 0, 0);
+		if (!ep_fwnode)
+			continue;
+
+		ret = ub960_parse_dt_txport(priv, ep_fwnode, nport);
+
+		fwnode_handle_put(ep_fwnode);
+
+		if (ret)
+			break;
+	}
+
+	return 0;
+}
+
+static int ub960_parse_dt(struct ub960_data *priv)
+{
+	int ret;
+
+	ret = ub960_parse_dt_rxports(priv);
+	if (ret)
+		return ret;
+
+	ret = ub960_parse_dt_txports(priv);
+	if (ret)
+		goto err_free_rxports;
+
+	return 0;
+
+err_free_rxports:
+	ub960_rxport_free_ports(priv);
+
+	return ret;
+}
+
+static int ub960_notify_bound(struct v4l2_async_notifier *notifier,
+			      struct v4l2_subdev *subdev,
+			      struct v4l2_async_subdev *asd)
+{
+	struct ub960_data *priv = sd_to_ub960(notifier->sd);
+	struct ub960_rxport *rxport = to_ub960_asd(asd)->rxport;
+	struct device *dev = &priv->client->dev;
+	u8 nport = rxport->nport;
+	unsigned int i;
+	int ret;
+
+	ret = media_entity_get_fwnode_pad(&subdev->entity,
+					  rxport->source.ep_fwnode,
+					  MEDIA_PAD_FL_SOURCE);
+	if (ret < 0) {
+		dev_err(dev, "Failed to find pad for %s\n", subdev->name);
+		return ret;
+	}
+
+	rxport->source.sd = subdev;
+	rxport->source.pad = ret;
+
+	ret = media_create_pad_link(&rxport->source.sd->entity,
+				    rxport->source.pad, &priv->sd.entity, nport,
+				    MEDIA_LNK_FL_ENABLED |
+					    MEDIA_LNK_FL_IMMUTABLE);
+	if (ret) {
+		dev_err(dev, "Unable to link %s:%u -> %s:%u\n",
+			rxport->source.sd->name, rxport->source.pad,
+			priv->sd.name, nport);
+		return ret;
+	}
+
+	for (i = 0; i < priv->hw_data->num_rxports; i++) {
+		if (priv->rxports[i] && !priv->rxports[i]->source.sd) {
+			dev_dbg(dev, "Waiting for more subdevs to be bound\n");
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+static void ub960_notify_unbind(struct v4l2_async_notifier *notifier,
+				struct v4l2_subdev *subdev,
+				struct v4l2_async_subdev *asd)
+{
+	struct ub960_rxport *rxport = to_ub960_asd(asd)->rxport;
+
+	rxport->source.sd = NULL;
+}
+
+static const struct v4l2_async_notifier_operations ub960_notify_ops = {
+	.bound = ub960_notify_bound,
+	.unbind = ub960_notify_unbind,
+};
+
+static int ub960_v4l2_notifier_register(struct ub960_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	unsigned int i;
+	int ret;
+
+	v4l2_async_nf_init(&priv->notifier);
+
+	for (i = 0; i < priv->hw_data->num_rxports; i++) {
+		struct ub960_rxport *rxport = priv->rxports[i];
+		struct ub960_asd *asd;
+
+		if (!rxport)
+			continue;
+
+		asd = v4l2_async_nf_add_fwnode(&priv->notifier,
+					       rxport->source.ep_fwnode,
+					       struct ub960_asd);
+		if (IS_ERR(asd)) {
+			dev_err(dev, "Failed to add subdev for source %u: %pe",
+				i, asd);
+			v4l2_async_nf_cleanup(&priv->notifier);
+			return PTR_ERR(asd);
+		}
+
+		asd->rxport = rxport;
+	}
+
+	priv->notifier.ops = &ub960_notify_ops;
+
+	ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier);
+	if (ret) {
+		dev_err(dev, "Failed to register subdev_notifier");
+		v4l2_async_nf_cleanup(&priv->notifier);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void ub960_v4l2_notifier_unregister(struct ub960_data *priv)
+{
+	v4l2_async_nf_unregister(&priv->notifier);
+	v4l2_async_nf_cleanup(&priv->notifier);
+}
+
+static int ub960_create_subdev(struct ub960_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	unsigned int i;
+	int ret;
+
+	v4l2_i2c_subdev_init(&priv->sd, priv->client, &ub960_subdev_ops);
+
+	v4l2_ctrl_handler_init(&priv->ctrl_handler, 1);
+	priv->sd.ctrl_handler = &priv->ctrl_handler;
+
+	v4l2_ctrl_new_int_menu(&priv->ctrl_handler, NULL, V4L2_CID_LINK_FREQ,
+			       ARRAY_SIZE(priv->tx_link_freq) - 1, 0,
+			       priv->tx_link_freq);
+
+	if (priv->ctrl_handler.error) {
+		ret = priv->ctrl_handler.error;
+		goto err_free_ctrl;
+	}
+
+	priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+			  V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_STREAMS;
+	priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+	priv->sd.entity.ops = &ub960_entity_ops;
+
+	for (i = 0; i < priv->hw_data->num_rxports + priv->hw_data->num_txports; i++) {
+		priv->pads[i].flags = ub960_pad_is_sink(priv, i) ?
+					      MEDIA_PAD_FL_SINK :
+					      MEDIA_PAD_FL_SOURCE;
+	}
+
+	ret = media_entity_pads_init(&priv->sd.entity,
+				     priv->hw_data->num_rxports +
+					     priv->hw_data->num_txports,
+				     priv->pads);
+	if (ret)
+		goto err_free_ctrl;
+
+	priv->sd.state_lock = priv->sd.ctrl_handler->lock;
+
+	ret = v4l2_subdev_init_finalize(&priv->sd);
+	if (ret)
+		goto err_entity_cleanup;
+
+	ret = ub960_v4l2_notifier_register(priv);
+	if (ret) {
+		dev_err(dev, "v4l2 subdev notifier register failed: %d\n", ret);
+		goto err_subdev_cleanup;
+	}
+
+	ret = v4l2_async_register_subdev(&priv->sd);
+	if (ret) {
+		dev_err(dev, "v4l2_async_register_subdev error: %d\n", ret);
+		goto err_unreg_notif;
+	}
+
+	return 0;
+
+err_unreg_notif:
+	ub960_v4l2_notifier_unregister(priv);
+err_subdev_cleanup:
+	v4l2_subdev_cleanup(&priv->sd);
+err_entity_cleanup:
+	media_entity_cleanup(&priv->sd.entity);
+err_free_ctrl:
+	v4l2_ctrl_handler_free(&priv->ctrl_handler);
+
+	return ret;
+}
+
+static void ub960_destroy_subdev(struct ub960_data *priv)
+{
+	ub960_v4l2_notifier_unregister(priv);
+	v4l2_async_unregister_subdev(&priv->sd);
+
+	v4l2_subdev_cleanup(&priv->sd);
+
+	media_entity_cleanup(&priv->sd.entity);
+	v4l2_ctrl_handler_free(&priv->ctrl_handler);
+}
+
+static const struct regmap_config ub960_regmap_config = {
+	.name = "ds90ub960",
+
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = 0xff,
+
+	/*
+	 * We do locking in the driver to cover the TX/RX port selection and the
+	 * indirect register access.
+	 */
+	.disable_locking = true,
+};
+
+static void ub960_reset(struct ub960_data *priv, bool reset_regs)
+{
+	struct device *dev = &priv->client->dev;
+	unsigned int v;
+	int ret;
+	u8 bit;
+
+	bit = reset_regs ? UB960_SR_RESET_DIGITAL_RESET1 :
+			   UB960_SR_RESET_DIGITAL_RESET0;
+
+	ub960_write(priv, UB960_SR_RESET, bit);
+
+	mutex_lock(&priv->reg_lock);
+
+	ret = regmap_read_poll_timeout(priv->regmap, UB960_SR_RESET, v,
+				       (v & bit) == 0, 2000, 100000);
+
+	mutex_unlock(&priv->reg_lock);
+
+	if (ret)
+		dev_err(dev, "reset failed: %d\n", ret);
+}
+
+static int ub960_get_hw_resources(struct ub960_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+
+	priv->regmap = devm_regmap_init_i2c(priv->client, &ub960_regmap_config);
+	if (IS_ERR(priv->regmap))
+		return PTR_ERR(priv->regmap);
+
+	priv->vddio = devm_regulator_get(dev, "vddio");
+	if (IS_ERR(priv->vddio))
+		return dev_err_probe(dev, PTR_ERR(priv->vddio),
+				     "cannot get VDDIO regulator\n");
+
+	/* get power-down pin from DT */
+	priv->pd_gpio =
+		devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH);
+	if (IS_ERR(priv->pd_gpio))
+		return dev_err_probe(dev, PTR_ERR(priv->pd_gpio),
+				     "Cannot get powerdown GPIO\n");
+
+	priv->refclk = devm_clk_get(dev, "refclk");
+	if (IS_ERR(priv->refclk))
+		return dev_err_probe(dev, PTR_ERR(priv->refclk),
+				     "Cannot get REFCLK\n");
+
+	return 0;
+}
+
+static int ub960_enable_core_hw(struct ub960_data *priv)
+{
+	struct device *dev = &priv->client->dev;
+	u8 rev_mask;
+	int ret;
+	u8 dev_sts;
+	u8 refclk_freq;
+
+	ret = regulator_enable(priv->vddio);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "failed to enable VDDIO regulator\n");
+
+	ret = clk_prepare_enable(priv->refclk);
+	if (ret) {
+		dev_err_probe(dev, ret, "Failed to enable refclk\n");
+		goto err_disable_vddio;
+	}
+
+	if (priv->pd_gpio) {
+		gpiod_set_value_cansleep(priv->pd_gpio, 1);
+		/* wait min 2 ms for reset to complete */
+		fsleep(2000);
+		gpiod_set_value_cansleep(priv->pd_gpio, 0);
+		/* wait min 2 ms for power up to finish */
+		fsleep(2000);
+	}
+
+	ub960_reset(priv, true);
+
+	/* Runtime check register accessibility */
+	ret = ub960_read(priv, UB960_SR_REV_MASK, &rev_mask);
+	if (ret) {
+		dev_err_probe(dev, ret, "Cannot read first register, abort\n");
+		goto err_pd_gpio;
+	}
+
+	dev_dbg(dev, "Found %s (rev/mask %#04x)\n", priv->hw_data->model,
+		rev_mask);
+
+	ret = ub960_read(priv, UB960_SR_DEVICE_STS, &dev_sts);
+	if (ret)
+		goto err_pd_gpio;
+
+	ret = ub960_read(priv, UB960_XR_REFCLK_FREQ, &refclk_freq);
+	if (ret)
+		goto err_pd_gpio;
+
+	dev_dbg(dev, "refclk valid %u freq %u MHz (clk fw freq %lu MHz)\n",
+		!!(dev_sts & BIT(4)), refclk_freq,
+		clk_get_rate(priv->refclk) / 1000000);
+
+	/* Disable all RX ports by default */
+	ret = ub960_write(priv, UB960_SR_RX_PORT_CTL, 0);
+	if (ret)
+		goto err_pd_gpio;
+
+	/* release GPIO lock */
+	if (priv->hw_data->is_ub9702) {
+		ret = ub960_update_bits(priv, UB960_SR_RESET,
+					UB960_SR_RESET_GPIO_LOCK_RELEASE,
+					UB960_SR_RESET_GPIO_LOCK_RELEASE);
+		if (ret)
+			goto err_pd_gpio;
+	}
+
+	return 0;
+
+err_pd_gpio:
+	gpiod_set_value_cansleep(priv->pd_gpio, 1);
+	clk_disable_unprepare(priv->refclk);
+err_disable_vddio:
+	regulator_disable(priv->vddio);
+
+	return ret;
+}
+
+static void ub960_disable_core_hw(struct ub960_data *priv)
+{
+	gpiod_set_value_cansleep(priv->pd_gpio, 1);
+	clk_disable_unprepare(priv->refclk);
+	regulator_disable(priv->vddio);
+}
+
+static int ub960_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	struct ub960_data *priv;
+	unsigned int port_lock_mask;
+	unsigned int port_mask;
+	unsigned int nport;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->client = client;
+
+	priv->hw_data = device_get_match_data(dev);
+
+	mutex_init(&priv->reg_lock);
+
+	INIT_DELAYED_WORK(&priv->poll_work, ub960_handler_work);
+
+	/*
+	 * Initialize these to invalid values so that the first reg writes will
+	 * configure the target.
+	 */
+	priv->reg_current.indirect_target = 0xff;
+	priv->reg_current.rxport = 0xff;
+	priv->reg_current.txport = 0xff;
+
+	ret = ub960_get_hw_resources(priv);
+	if (ret)
+		goto err_mutex_destroy;
+
+	ret = ub960_enable_core_hw(priv);
+	if (ret)
+		goto err_mutex_destroy;
+
+	ret = ub960_parse_dt(priv);
+	if (ret)
+		goto err_disable_core_hw;
+
+	ret = ub960_init_tx_ports(priv);
+	if (ret)
+		goto err_free_ports;
+
+	ret = ub960_rxport_enable_vpocs(priv);
+	if (ret)
+		goto err_free_ports;
+
+	ret = ub960_init_rx_ports(priv);
+	if (ret)
+		goto err_disable_vpocs;
+
+	ub960_reset(priv, false);
+
+	port_mask = 0;
+
+	for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
+		struct ub960_rxport *rxport = priv->rxports[nport];
+
+		if (!rxport)
+			continue;
+
+		port_mask |= BIT(nport);
+	}
+
+	ret = ub960_rxport_wait_locks(priv, port_mask, &port_lock_mask);
+	if (ret)
+		goto err_disable_vpocs;
+
+	if (port_mask != port_lock_mask) {
+		ret = -EIO;
+		dev_err_probe(dev, ret, "Failed to lock all RX ports\n");
+		goto err_disable_vpocs;
+	}
+
+	/*
+	 * Clear any errors caused by switching the RX port settings while
+	 * probing.
+	 */
+	ub960_clear_rx_errors(priv);
+
+	ret = ub960_init_atr(priv);
+	if (ret)
+		goto err_disable_vpocs;
+
+	ret = ub960_rxport_add_serializers(priv);
+	if (ret)
+		goto err_uninit_atr;
+
+	ret = ub960_create_subdev(priv);
+	if (ret)
+		goto err_free_sers;
+
+	if (client->irq)
+		dev_warn(dev, "irq support not implemented, using polling\n");
+
+	schedule_delayed_work(&priv->poll_work,
+			      msecs_to_jiffies(UB960_POLL_TIME_MS));
+
+	return 0;
+
+err_free_sers:
+	ub960_rxport_remove_serializers(priv);
+err_uninit_atr:
+	ub960_uninit_atr(priv);
+err_disable_vpocs:
+	ub960_rxport_disable_vpocs(priv);
+err_free_ports:
+	ub960_rxport_free_ports(priv);
+	ub960_txport_free_ports(priv);
+err_disable_core_hw:
+	ub960_disable_core_hw(priv);
+err_mutex_destroy:
+	mutex_destroy(&priv->reg_lock);
+	return ret;
+}
+
+static void ub960_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ub960_data *priv = sd_to_ub960(sd);
+
+	cancel_delayed_work_sync(&priv->poll_work);
+
+	ub960_destroy_subdev(priv);
+	ub960_rxport_remove_serializers(priv);
+	ub960_uninit_atr(priv);
+	ub960_rxport_disable_vpocs(priv);
+	ub960_rxport_free_ports(priv);
+	ub960_txport_free_ports(priv);
+	ub960_disable_core_hw(priv);
+	mutex_destroy(&priv->reg_lock);
+}
+
+static const struct ub960_hw_data ds90ub954_hw = {
+	.model = "ub954",
+	.num_rxports = 2,
+	.num_txports = 1,
+	.ignore_strobe_pos = true,
+};
+
+static const struct ub960_hw_data ds90ub960_hw = {
+	.model = "ub960",
+	.num_rxports = 4,
+	.num_txports = 2,
+};
+
+static const struct ub960_hw_data ds90ub9702_hw = {
+	.model = "ub9702",
+	.num_rxports = 4,
+	.num_txports = 2,
+	.is_ub9702 = true,
+	.is_fpdlink4 = true,
+};
+
+static const struct i2c_device_id ub960_id[] = {
+	{ "ds90ub954-q1", (kernel_ulong_t)&ds90ub954_hw },
+	{ "ds90ub960-q1", (kernel_ulong_t)&ds90ub960_hw },
+	{ "ds90ub9702-q1", (kernel_ulong_t)&ds90ub9702_hw },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, ub960_id);
+
+static const struct of_device_id ub960_dt_ids[] = {
+	{ .compatible = "ti,ds90ub954-q1", .data = &ds90ub954_hw },
+	{ .compatible = "ti,ds90ub960-q1", .data = &ds90ub960_hw },
+	{ .compatible = "ti,ds90ub9702-q1", .data = &ds90ub9702_hw },
+	{}
+};
+MODULE_DEVICE_TABLE(of, ub960_dt_ids);
+
+static struct i2c_driver ds90ub960_driver = {
+	.probe_new	= ub960_probe,
+	.remove		= ub960_remove,
+	.id_table	= ub960_id,
+	.driver = {
+		.name	= "ds90ub960",
+		.of_match_table = ub960_dt_ids,
+	},
+};
+module_i2c_driver(ds90ub960_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Texas Instruments FPD-Link III/IV Deserializers Driver");
+MODULE_AUTHOR("Luca Ceresoli <luca@lucaceresoli.net>");
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>");
+MODULE_IMPORT_NS(I2C_ATR);
diff -Naur --no-dereference a/drivers/media/i2c/imx390.c b/drivers/media/i2c/imx390.c
--- a/drivers/media/i2c/imx390.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/i2c/imx390.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,886 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Sony IMX390 CMOS Image Sensor Driver
+ *
+ * Copyright (c) 2021 Apurva Nandan <a-nandan@ti.com>
+ *
+ * Copyright (c) 2021 Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ctrls.h>
+
+#include "imx390.h"
+
+static inline struct imx390 *to_imx390(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct imx390, subdev);
+}
+
+static int imx390_read(struct imx390 *imx390, u16 addr, u32 *val, size_t nbytes)
+{
+	int ret;
+	__le32 val_le = 0;
+
+	ret = regmap_bulk_read(imx390->regmap, addr, &val_le, nbytes);
+	if (ret < 0) {
+		dev_err(imx390->dev, "%s: failed to read reg 0x%04x: %d\n",
+			__func__, addr, ret);
+		return ret;
+	}
+
+	*val = le32_to_cpu(val_le);
+	return 0;
+}
+
+static int imx390_write(struct imx390 *imx390, u16 addr, u32 val, size_t nbytes)
+{
+	int ret;
+	__le32 val_le = cpu_to_le32(val);
+
+	ret = regmap_bulk_write(imx390->regmap, addr, &val_le, nbytes);
+	if (ret < 0)
+		dev_err(imx390->dev, "%s: failed to write reg 0x%04x: %d\n",
+			__func__, addr, ret);
+	return ret;
+}
+
+static int imx390_update_bits(struct imx390 *imx390, u16 addr, u32 val,
+			      u32 mask, size_t nbytes)
+{
+	int ret;
+	u32 cfg;
+
+	ret = imx390_read(imx390, addr, &cfg, nbytes);
+	if (ret < 0)
+		return ret;
+
+	cfg = (val) ? (cfg | mask) : (cfg & (~mask));
+
+	return imx390_write(imx390, addr, cfg, nbytes);
+}
+
+static int imx390_write_table(struct imx390 *imx390,
+			      const struct reg_sequence *regs,
+			      unsigned int nr_regs)
+{
+	int ret;
+
+	ret = regmap_multi_reg_write(imx390->regmap, regs, nr_regs);
+	if (ret < 0)
+		dev_err(imx390->dev,
+			"%s: failed to write reg table (%d)!\n", __func__, ret);
+	return ret;
+}
+
+static void imx390_init_formats(struct v4l2_subdev_state *state)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	format = v4l2_subdev_state_get_stream_format(state, 0, 0);
+	format->code = imx390_mbus_formats[0];
+	format->width = imx390_framesizes[0].width;
+	format->height = imx390_framesizes[0].height;
+	format->field = V4L2_FIELD_NONE;
+	format->colorspace = V4L2_COLORSPACE_SMPTE170M;
+}
+
+static int _imx390_set_routing(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_state *state)
+{
+	struct v4l2_subdev_route routes[] = {
+		{
+			.source_pad = 0,
+			.source_stream = 0,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+		{
+			.source_pad = 0,
+			.source_stream = 1,
+		}
+	};
+
+	struct v4l2_subdev_krouting routing = {
+		.num_routes = ARRAY_SIZE(routes),
+		.routes = routes,
+	};
+
+	int ret;
+
+	ret = v4l2_subdev_set_routing(sd, state, &routing);
+	if (ret < 0)
+		return ret;
+
+	imx390_init_formats(state);
+
+	return 0;
+}
+
+static int imx390_init_cfg(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_state *state)
+{
+	int ret;
+
+	ret = _imx390_set_routing(sd, state);
+
+	return ret;
+}
+
+static int imx390_enum_mbus_code(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_state *state,
+				 struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index >= ARRAY_SIZE(imx390_mbus_formats))
+		return -EINVAL;
+
+	code->code = imx390_mbus_formats[code->index];
+
+	return 0;
+}
+
+static int imx390_enum_frame_sizes(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_state *state,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(imx390_mbus_formats); ++i) {
+		if (imx390_mbus_formats[i] == fse->code)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(imx390_mbus_formats))
+		return -EINVAL;
+
+	if (fse->index >= ARRAY_SIZE(imx390_framesizes))
+		return -EINVAL;
+
+	fse->min_width = imx390_framesizes[fse->index].width;
+	fse->max_width = fse->min_width;
+	fse->max_height = imx390_framesizes[fse->index].height;
+	fse->min_height = fse->max_height;
+
+	return 0;
+}
+
+static int imx390_set_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_subdev_state *state,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct imx390 *imx390 = to_imx390(sd);
+	struct v4l2_mbus_framefmt *format;
+	const struct v4l2_area *fsize;
+	unsigned int i;
+	u32 code;
+	int ret = 0;
+
+	if (fmt->pad != 0)
+		return -EINVAL;
+
+	if (fmt->stream != 0)
+		return -EINVAL;
+
+	/*
+	 * Validate the media bus code, defaulting to the first one if the
+	 * requested code isn't supported.
+	 */
+	for (i = 0; i < ARRAY_SIZE(imx390_mbus_formats); ++i) {
+		if (imx390_mbus_formats[i] == fmt->format.code) {
+			code = fmt->format.code;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(imx390_mbus_formats))
+		code = imx390_mbus_formats[0];
+
+	/* Find the nearest supported frame size. */
+	fsize = v4l2_find_nearest_size(imx390_framesizes,
+				       ARRAY_SIZE(imx390_framesizes), width,
+				       height, fmt->format.width,
+				       fmt->format.height);
+
+	v4l2_subdev_lock_state(state);
+
+	/* Update the stored format and return it. */
+	format = v4l2_subdev_state_get_stream_format(state, fmt->pad, fmt->stream);
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE && imx390->streaming) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	format->code = code;
+	format->width = fsize->width;
+	format->height = fsize->height;
+
+	fmt->format = *format;
+
+done:
+	v4l2_subdev_unlock_state(state);
+
+	return ret;
+}
+
+static int imx390_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+				 struct v4l2_mbus_frame_desc *fd)
+{
+	struct v4l2_subdev_state *state;
+	struct v4l2_mbus_framefmt *fmt;
+	u32 bpp;
+	int ret = 0;
+
+	if (pad != 0)
+		return -EINVAL;
+
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	fmt = v4l2_subdev_state_get_stream_format(state, 0, 0);
+	if (!fmt) {
+		ret = -EPIPE;
+		goto out;
+	}
+
+	memset(fd, 0, sizeof(*fd));
+
+	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
+
+	/* pixel stream */
+
+	bpp = 12;
+
+	fd->entry[fd->num_entries].stream = 0;
+
+	fd->entry[fd->num_entries].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
+	fd->entry[fd->num_entries].length = fmt->width * fmt->height * bpp / 8;
+	fd->entry[fd->num_entries].pixelcode = fmt->code;
+	fd->entry[fd->num_entries].bus.csi2.vc = 0;
+	fd->entry[fd->num_entries].bus.csi2.dt = 0x2c; /* SRGGB12 */
+
+	fd->num_entries++;
+
+out:
+	v4l2_subdev_unlock_state(state);
+
+	return ret;
+}
+
+static int imx390_set_routing(struct v4l2_subdev *sd,
+			      struct v4l2_subdev_state *state,
+			      enum v4l2_subdev_format_whence which,
+			      struct v4l2_subdev_krouting *routing)
+{
+	int ret;
+
+	if (routing->num_routes == 0 || routing->num_routes > 1)
+		return -EINVAL;
+
+	ret = _imx390_set_routing(sd, state);
+
+	return ret;
+}
+
+static int imx390_check_non_wdr_mode_fps(struct imx390 *imx390, bool enable)
+{
+	if (!enable && imx390->fps > IMX390_FRAMERATE_MAX_LINEAR) {
+		dev_err(imx390->dev,
+			"%s: failed, %dFPS unsupported in non-WDR mode\n",
+			__func__, imx390->fps);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int imx390_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct imx390 *imx390 = container_of(ctrl->handler,
+					     struct imx390, ctrl.handler);
+	int ret;
+
+	dev_dbg(imx390->dev,
+		"%s: %s, value: %d\n", __func__, ctrl->name, ctrl->val);
+
+	/* V4L2 controls values will be applied only when power is already up */
+	if (!pm_runtime_get_if_in_use(imx390->dev))
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_WIDE_DYNAMIC_RANGE:
+		ret = imx390_check_non_wdr_mode_fps(imx390, ctrl->val);
+		break;
+
+	case V4L2_CID_EXPOSURE:
+		ret = imx390_write(imx390, IMX390_REG_CAT0_SHS1,
+				   IMX390_EXPOSURE_SHS_VAL(ctrl->val,
+							   imx390->fps), 3);
+		break;
+
+	case V4L2_CID_ANALOGUE_GAIN:
+		ret = imx390_write(imx390, IMX390_REG_CAT0_AGAIN_SP1H,
+				   ctrl->val, 2);
+		if (ret < 0)
+			break;
+
+		ret = imx390_write(imx390, IMX390_REG_CAT0_AGAIN_SP1L,
+				   ctrl->val / IMX390_AGAIN_CONV_GAIN_RATIO, 2);
+		break;
+
+	case V4L2_CID_DIGITAL_GAIN:
+		ret = imx390_write(imx390, IMX390_REG_CAT0_PGA_GAIN,
+				   ctrl->val, 2);
+		break;
+
+	case V4L2_CID_RED_BALANCE:
+		ret = imx390_write(imx390, IMX390_REG_CAT0_WBGAIN_R,
+				   ctrl->val, 2);
+		break;
+
+	case V4L2_CID_BLUE_BALANCE:
+		ret = imx390_write(imx390, IMX390_REG_CAT0_WBGAIN_B,
+				   ctrl->val, 2);
+		break;
+
+	case V4L2_CID_HFLIP:
+		ret = imx390_update_bits(imx390, IMX390_REG_CAT0_V_H_REVERSE,
+					 ctrl->val, IMX390_H_REV_MASK, 1);
+		if (ret < 0)
+			break;
+
+		ret = imx390_update_bits(imx390, IMX390_REG_SM_CFG_REVERSE_APL,
+					 ctrl->val, IMX390_H_REV_APL_MASK, 1);
+		break;
+
+	case V4L2_CID_VFLIP:
+		ret = imx390_update_bits(imx390, IMX390_REG_CAT0_V_H_REVERSE,
+					 ctrl->val, IMX390_V_REV_MASK, 1);
+		if (ret < 0)
+			break;
+
+		ret = imx390_update_bits(imx390, IMX390_REG_SM_CFG_REVERSE_APL,
+					 ctrl->val, IMX390_V_REV_APL_MASK, 1);
+		break;
+
+	case V4L2_CID_TEST_PATTERN:
+		ret = imx390_write(imx390, IMX390_REG_CAT0_PGMODE_PGREGEN,
+				   imx390_pg_mode_reg_val[ctrl->val], 1);
+		if (ret < 0)
+			break;
+
+		ret = imx390_update_bits(imx390, IMX390_SM_CFG_SM_PGREGEN_APL,
+					 ctrl->val, IMX390_SM_PG_APL_MASK, 1);
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+
+	pm_runtime_put_noidle(imx390->dev);
+	return ret;
+}
+
+static int imx390_detect(struct imx390 *imx390)
+{
+	int ret;
+	u32 id;
+
+	ret = imx390_read(imx390, IMX390_REG_VERSION_ROM_VERSION, &id, 2);
+	if (ret < 0)
+		return ret;
+
+	if (id != IMX390_ROM_VERSION) {
+		dev_err(imx390->dev,
+			"%s: unknown chip ID 0x%04x\n", __func__, id);
+		return -ENODEV;
+	}
+
+	dev_dbg(imx390->dev, "%s: detected chip ID 0x%04x\n", __func__, id);
+	return 0;
+}
+
+static int imx390_power_on(struct imx390 *imx390)
+{
+	int ret;
+
+	ret = clk_prepare_enable(imx390->clk);
+	if (ret < 0)
+		return ret;
+
+	if (imx390->xclr_gpio) {
+		gpiod_set_value_cansleep(imx390->xclr_gpio, 1);
+		/* Keep the XCLR pin on Low for 100 us or longer */
+		usleep_range(100, 1000);
+		gpiod_set_value_cansleep(imx390->xclr_gpio, 0);
+		/* It takes max 30 ms for the sensor to be ready */
+		msleep(30);
+	}
+	return 0;
+}
+
+static void imx390_power_off(struct imx390 *imx390)
+{
+	if (imx390->xclr_gpio) {
+		gpiod_set_value_cansleep(imx390->xclr_gpio, 1);
+		/* Wait for the XCLR pin to be Low for at least 1 us */
+		usleep_range(1, 10);
+	}
+
+	clk_disable_unprepare(imx390->clk);
+}
+
+static int imx390_get_frame_interval(struct v4l2_subdev *sd,
+				     struct v4l2_subdev_frame_interval *fi)
+{
+	struct imx390 *imx390 = to_imx390(sd);
+
+	fi->interval.numerator = 1;
+	fi->interval.denominator = imx390->fps;
+	return 0;
+}
+
+static int imx390_set_frame_interval(struct v4l2_subdev *sd,
+				     struct v4l2_subdev_frame_interval *fi)
+{
+	struct imx390 *imx390 = to_imx390(sd);
+	struct v4l2_ctrl *ctrl = imx390->ctrl.exposure;
+	u32 req_fps;
+	int ret;
+
+	mutex_lock(&imx390->lock);
+
+	if (fi->interval.numerator == 0 || fi->interval.denominator == 0) {
+		fi->interval.denominator = IMX390_FRAMERATE_DEFAULT;
+		fi->interval.numerator = 1;
+	}
+
+	req_fps = clamp_val(DIV_ROUND_CLOSEST(fi->interval.denominator,
+					      fi->interval.numerator),
+			    IMX390_FRAMERATE_MIN, IMX390_FRAMERATE_MAX);
+
+	fi->interval.numerator = 1;
+	fi->interval.denominator = req_fps;
+
+	imx390->fps = req_fps;
+
+	ret = __v4l2_ctrl_modify_range(ctrl, 0, IMX390_EXPOSURE_MAX(req_fps), 1,
+				       IMX390_EXPOSURE_DEFAULT);
+	if (ret < 0) {
+		dev_err(imx390->dev,
+			"%s: exposure ctrl range update failed %d\n",
+			__func__, ret);
+	}
+
+	mutex_unlock(&imx390->lock);
+	dev_dbg(imx390->dev, "%s frame rate = %d\n", __func__, imx390->fps);
+
+	return ret;
+}
+
+static int imx390_start_stream(struct imx390 *imx390)
+{
+	int ret;
+
+	if (!imx390->ctrl.wdr->val &&
+	    imx390->fps <= IMX390_FRAMERATE_MAX_LINEAR)
+		ret = imx390_write_table(imx390, imx390_linear_1936x1096,
+					 ARRAY_SIZE(imx390_linear_1936x1096));
+	else
+		ret = imx390_write_table(imx390, imx390_wdr_1936x1096,
+					 ARRAY_SIZE(imx390_wdr_1936x1096));
+	if (ret < 0)
+		return ret;
+
+	msleep(100);
+
+	/* Restore the V4L2 control values into the registers */
+	ret =  __v4l2_ctrl_handler_setup(imx390->subdev.ctrl_handler);
+	if (ret < 0) {
+		dev_err(imx390->dev,
+			"%s: failed to apply v4l2 ctrls: %d\n", __func__, ret);
+		return ret;
+	}
+
+	ret = imx390_write(imx390, IMX390_REG_MODE_HMAX,
+			   (u32)IMX390_FPS_TO_MODE_HMAX(imx390->fps), 2);
+	if (ret < 0)
+		return ret;
+
+	/* Set active */
+	ret = imx390_write(imx390, IMX390_REG_CAT0_STANDBY, 0, 1);
+	if (ret < 0)
+		return ret;
+
+	/* No communication is possible for a while after exiting standby */
+	msleep(20);
+
+	return 0;
+}
+
+static int imx390_stop_stream(struct imx390 *imx390)
+{
+	int ret;
+
+	/* Set standby */
+	ret = imx390_write(imx390, IMX390_REG_CAT0_STANDBY, 1, 1);
+	if (ret < 0)
+		return ret;
+
+	/* No communication is possible for a while after entering standby */
+	usleep_range(10000, 20000);
+	return 0;
+}
+
+static int imx390_set_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct imx390 *imx390 = to_imx390(sd);
+	int ret;
+
+	mutex_lock(&imx390->lock);
+	if (imx390->streaming == enable) {
+		mutex_unlock(&imx390->lock);
+		return 0;
+	}
+
+	if (enable) {
+		ret = pm_runtime_get_sync(imx390->dev);
+		if (ret < 0) {
+			pm_runtime_put_noidle(imx390->dev);
+			goto err_unlock;
+		}
+
+		ret = imx390_start_stream(imx390);
+		if (ret < 0)
+			goto err_runtime_put;
+	} else {
+		ret = imx390_stop_stream(imx390);
+		if (ret < 0)
+			goto err_runtime_put;
+		pm_runtime_mark_last_busy(imx390->dev);
+		pm_runtime_put_autosuspend(imx390->dev);
+	}
+
+	imx390->streaming = enable;
+	/* WDR, HFLIP, VFLIP, TEST PATTERN cannot change during streaming */
+	__v4l2_ctrl_grab(imx390->ctrl.wdr, enable);
+	__v4l2_ctrl_grab(imx390->ctrl.h_flip, enable);
+	__v4l2_ctrl_grab(imx390->ctrl.v_flip, enable);
+	__v4l2_ctrl_grab(imx390->ctrl.pg_mode, enable);
+
+	mutex_unlock(&imx390->lock);
+	return 0;
+
+err_runtime_put:
+	pm_runtime_put(imx390->dev);
+
+err_unlock:
+	mutex_unlock(&imx390->lock);
+	dev_err(imx390->dev,
+		"%s: failed to setup streaming %d\n", __func__, ret);
+	return ret;
+}
+
+static const struct v4l2_subdev_video_ops imx390_subdev_video_ops = {
+	.g_frame_interval = imx390_get_frame_interval,
+	.s_frame_interval = imx390_set_frame_interval,
+	.s_stream = imx390_set_stream,
+};
+
+static const struct v4l2_subdev_pad_ops imx390_subdev_pad_ops = {
+	.init_cfg = imx390_init_cfg,
+	.enum_mbus_code	= imx390_enum_mbus_code,
+	.enum_frame_size = imx390_enum_frame_sizes,
+	.get_fmt = v4l2_subdev_get_fmt,
+	.set_fmt = imx390_set_fmt,
+	.set_routing = imx390_set_routing,
+	.get_frame_desc	= imx390_get_frame_desc,
+};
+
+static const struct v4l2_subdev_ops imx390_subdev_ops = {
+	.video	= &imx390_subdev_video_ops,
+	.pad	= &imx390_subdev_pad_ops,
+};
+
+static const struct v4l2_ctrl_ops imx390_ctrl_ops = {
+	.s_ctrl	= imx390_set_ctrl,
+};
+
+static int imx390_probe(struct i2c_client *client)
+{
+	struct imx390 *imx390;
+	struct v4l2_subdev *sd;
+	struct v4l2_ctrl_handler *ctrl_hdr;
+	int ret;
+
+	imx390 = devm_kzalloc(&client->dev, sizeof(*imx390), GFP_KERNEL);
+	if (!imx390)
+		return -ENOMEM;
+
+	imx390->dev = &client->dev;
+
+	imx390->regmap = devm_regmap_init_i2c(client, &imx390_regmap_config);
+	if (IS_ERR(imx390->regmap))
+		return PTR_ERR(imx390->regmap);
+
+	imx390->xclr_gpio = devm_gpiod_get_optional(imx390->dev,
+						    "xclr", GPIOD_OUT_LOW);
+	if (IS_ERR(imx390->xclr_gpio))
+		return PTR_ERR(imx390->xclr_gpio);
+
+	imx390->clk = devm_clk_get(imx390->dev, "inck");
+	if (IS_ERR(imx390->clk))
+		return PTR_ERR(imx390->clk);
+
+	imx390->clk_rate = clk_get_rate(imx390->clk);
+	dev_info(imx390->dev, "inck rate: %lu Hz\n", imx390->clk_rate);
+
+	if (imx390->clk_rate < 5900000 || imx390->clk_rate > 27100000)
+		return -EINVAL;
+
+	ret = imx390_power_on(imx390);
+	if (ret < 0)
+		return ret;
+
+	ret = imx390_detect(imx390);
+	if (ret < 0)
+		return ret;
+
+	/* Initialize the subdev and its controls. */
+	sd = &imx390->subdev;
+	v4l2_i2c_subdev_init(sd, client, &imx390_subdev_ops);
+
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+		     V4L2_SUBDEV_FL_HAS_EVENTS |
+		     V4L2_SUBDEV_FL_STREAMS;
+
+	/* Initialize the media entity. */
+	imx390->pad.flags = MEDIA_PAD_FL_SOURCE;
+	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
+	ret = media_entity_pads_init(&sd->entity, 1, &imx390->pad);
+	if (ret < 0) {
+		dev_err(imx390->dev,
+			"%s: media entity init failed %d\n", __func__, ret);
+		return ret;
+	}
+
+	/* Initialize controls */
+	ctrl_hdr = &imx390->ctrl.handler;
+	ret = v4l2_ctrl_handler_init(ctrl_hdr, 9);
+	if (ret < 0) {
+		dev_err(imx390->dev,
+			"%s: ctrl handler init failed: %d\n", __func__, ret);
+		goto err_media_cleanup;
+	}
+
+	mutex_init(&imx390->lock);
+	imx390->ctrl.handler.lock = &imx390->lock;
+	imx390->fps = IMX390_FRAMERATE_DEFAULT;
+
+	/* Add new controls */
+	imx390->ctrl.exposure = v4l2_ctrl_new_std(ctrl_hdr, &imx390_ctrl_ops,
+						  V4L2_CID_EXPOSURE, 0,
+						  IMX390_EXPOSURE_MAX(imx390->fps),
+						  1, IMX390_EXPOSURE_DEFAULT);
+
+	imx390->ctrl.again = v4l2_ctrl_new_std(ctrl_hdr, &imx390_ctrl_ops,
+					       V4L2_CID_ANALOGUE_GAIN, 0,
+					       IMX390_ANALOG_GAIN_MAX, 1,
+					       IMX390_ANALOG_GAIN_DEFAULT);
+
+	imx390->ctrl.dgain = v4l2_ctrl_new_std(ctrl_hdr, &imx390_ctrl_ops,
+					       V4L2_CID_DIGITAL_GAIN, 0,
+					       IMX390_DIGITAL_GAIN_MAX, 1,
+					       IMX390_DIGITAL_GAIN_DEFAULT);
+
+	imx390->ctrl.r_balance = v4l2_ctrl_new_std(ctrl_hdr, &imx390_ctrl_ops,
+						   V4L2_CID_RED_BALANCE, 0,
+						   IMX390_R_B_BALANCE_MAX, 1,
+						   IMX390_R_B_BALANCE_DEFAULT);
+
+	imx390->ctrl.b_balance = v4l2_ctrl_new_std(ctrl_hdr, &imx390_ctrl_ops,
+						   V4L2_CID_BLUE_BALANCE, 0,
+						   IMX390_R_B_BALANCE_MAX, 1,
+						   IMX390_R_B_BALANCE_DEFAULT);
+
+	imx390->ctrl.wdr = v4l2_ctrl_new_std(ctrl_hdr, &imx390_ctrl_ops,
+					     V4L2_CID_WIDE_DYNAMIC_RANGE,
+					     0, 1, 1, 1);
+
+	imx390->ctrl.h_flip = v4l2_ctrl_new_std(ctrl_hdr, &imx390_ctrl_ops,
+						V4L2_CID_HFLIP, 0, 1, 1, 0);
+
+	imx390->ctrl.v_flip = v4l2_ctrl_new_std(ctrl_hdr, &imx390_ctrl_ops,
+						V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+	imx390->ctrl.pg_mode = v4l2_ctrl_new_std_menu_items(ctrl_hdr,
+					&imx390_ctrl_ops, V4L2_CID_TEST_PATTERN,
+					ARRAY_SIZE(imx390_ctrl_pg_qmenu) - 1,
+					0, 0, imx390_ctrl_pg_qmenu);
+
+	imx390->subdev.ctrl_handler = ctrl_hdr;
+	if (imx390->ctrl.handler.error) {
+		ret = imx390->ctrl.handler.error;
+		dev_err(imx390->dev,
+			"%s: failed to add the ctrls: %d\n", __func__, ret);
+		goto err_ctrl_free;
+	}
+
+	pm_runtime_set_active(imx390->dev);
+	pm_runtime_enable(imx390->dev);
+	pm_runtime_set_autosuspend_delay(imx390->dev, IMX390_PM_IDLE_TIMEOUT);
+	pm_runtime_use_autosuspend(imx390->dev);
+	pm_runtime_get_noresume(imx390->dev);
+
+	ret = v4l2_subdev_init_finalize(sd);
+	if (ret < 0)
+		goto err_pm_disable;
+
+	/* Finally, register the subdev. */
+	ret = v4l2_async_register_subdev(sd);
+	if (ret < 0) {
+		dev_err(imx390->dev,
+			"%s: v4l2 subdev register failed %d\n", __func__, ret);
+		goto err_subdev_cleanup;
+	}
+
+	dev_info(imx390->dev, "imx390 probed\n");
+	pm_runtime_mark_last_busy(imx390->dev);
+	pm_runtime_put_autosuspend(imx390->dev);
+	return 0;
+
+err_subdev_cleanup:
+	v4l2_subdev_cleanup(&imx390->subdev);
+
+err_pm_disable:
+	pm_runtime_dont_use_autosuspend(imx390->dev);
+	pm_runtime_put_noidle(imx390->dev);
+	pm_runtime_disable(imx390->dev);
+
+err_ctrl_free:
+	v4l2_ctrl_handler_free(ctrl_hdr);
+	mutex_destroy(&imx390->lock);
+
+err_media_cleanup:
+	media_entity_cleanup(&imx390->subdev.entity);
+
+	return ret;
+}
+
+static int __maybe_unused imx390_runtime_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct imx390 *imx390 = to_imx390(sd);
+	int ret;
+
+	ret = imx390_power_on(imx390);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int __maybe_unused imx390_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct imx390 *imx390 = to_imx390(sd);
+
+	imx390_power_off(imx390);
+
+	return 0;
+}
+
+static int __maybe_unused imx390_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct imx390 *imx390 = to_imx390(sd);
+	int ret;
+
+	if (imx390->streaming)
+		imx390_stop_stream(imx390);
+
+	ret = pm_runtime_force_suspend(dev);
+	if (ret < 0)
+		dev_warn(dev, "%s: failed to suspend: %i\n", __func__, ret);
+
+	return 0;
+}
+
+static int __maybe_unused imx390_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct imx390 *imx390 = to_imx390(sd);
+	int ret;
+
+	ret = pm_runtime_force_resume(dev);
+	if (ret < 0)
+		dev_warn(dev, "%s: failed to resume: %i\n", __func__, ret);
+
+	if (imx390->streaming)
+		ret = imx390_start_stream(imx390);
+
+	if (ret < 0) {
+		imx390_stop_stream(imx390);
+		imx390->streaming = 0;
+		return ret;
+	}
+
+	return 0;
+}
+
+static void imx390_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct imx390 *imx390 = to_imx390(sd);
+
+	v4l2_async_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&imx390->ctrl.handler);
+	v4l2_subdev_cleanup(&imx390->subdev);
+	media_entity_cleanup(&sd->entity);
+	mutex_destroy(&imx390->lock);
+
+	pm_runtime_disable(imx390->dev);
+	pm_runtime_dont_use_autosuspend(imx390->dev);
+	pm_runtime_set_suspended(imx390->dev);
+}
+
+static const struct dev_pm_ops imx390_pm_ops = {
+	SET_RUNTIME_PM_OPS(imx390_runtime_suspend,
+			   imx390_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(imx390_suspend, imx390_resume)
+};
+
+static const struct of_device_id imx390_dt_id[] = {
+	{ .compatible = "sony,imx390" },
+	{ /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, imx390_dt_id);
+
+static struct i2c_driver imx390_i2c_driver = {
+	.driver = {
+		.name = "imx390",
+		.of_match_table = of_match_ptr(imx390_dt_id),
+		.pm = &imx390_pm_ops,
+	},
+	.probe_new = imx390_probe,
+	.remove = imx390_remove,
+};
+
+module_i2c_driver(imx390_i2c_driver);
+
+MODULE_DESCRIPTION("Camera Sensor Driver for Sony IMX390");
+MODULE_AUTHOR("Apurva Nandan <a-nandan@ti.com>");
+MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/media/i2c/imx390.h b/drivers/media/i2c/imx390.h
--- a/drivers/media/i2c/imx390.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/i2c/imx390.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,7158 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Sony IMX390 CMOS Image Sensor Driver
+ *
+ * Copyright (c) 2021 Apurva Nandan <a-nandan@ti.com>
+ *
+ * Copyright (c) 2021 Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+ */
+
+#include <linux/types.h>
+
+#define IMX390_ACTIVE_AREA_WIDTH	1936
+#define IMX390_ACTIVE_AREA_HEIGHT	1096
+
+/* SMPG cannot be disabled, and datatype is the same as the pixel data */
+#define IMX390_SMPG_HEIGHT		4
+
+#define IMX390_OUT_WIDTH	IMX390_ACTIVE_AREA_WIDTH
+#define IMX390_OUT_HEIGHT	(IMX390_ACTIVE_AREA_HEIGHT + IMX390_SMPG_HEIGHT)
+
+#define IMX390_FRAMERATE_DEFAULT	30
+#define IMX390_FRAMERATE_MIN		25
+#define IMX390_FRAMERATE_MAX		60
+#define IMX390_FRAMERATE_MAX_LINEAR	30
+
+#define IMX390_MODE_VMAX		0x465
+#define IMX390_MODE_HMAX_DEFAULT	0x1130
+#define IMX390_REG_MODE_HMAX		0x200C
+#define IMX390_FPS_TO_MODE_HMAX(_fps)		\
+	((IMX390_MODE_HMAX_DEFAULT * IMX390_FRAMERATE_DEFAULT) / (_fps))
+
+#define IMX390_REG_VERSION_ROM_VERSION	0x0330
+#define IMX390_ROM_VERSION		0x3815
+
+#define IMX390_REG_CAT0_STANDBY		0x0000
+
+/* Exposure control */
+#define IMX390_REG_CAT0_SHS1		0x000C
+#define IMX390_EXPOSURE_LINES_MAX	(IMX390_MODE_VMAX - 2)
+#define IMX390_EXPOSURE_MAX(_fps)		\
+	((IMX390_EXPOSURE_LINES_MAX * 1000000) / (IMX390_MODE_VMAX * (_fps)))
+
+#define IMX390_EXPOSURE_SHS_VAL(_exp, _fps)	\
+	(IMX390_MODE_VMAX - ((_exp) * (_fps) * IMX390_MODE_VMAX) / 1000000)
+
+#define IMX390_EXPOSURE_DEFAULT		11111
+
+/* Analog gain control */
+#define IMX390_REG_CAT0_AGAIN_SP1H	0x0018
+#define IMX390_REG_CAT0_AGAIN_SP1L	0x001A
+#define IMX390_ANALOG_GAIN_MAX		0x3FF
+#define IMX390_ANALOG_GAIN_DEFAULT	0x20
+#define IMX390_AGAIN_CONV_GAIN_RATIO	4
+
+/* Digital gain control */
+#define IMX390_REG_CAT0_PGA_GAIN	0x0024
+#define IMX390_DIGITAL_GAIN_MAX		0x1FF
+#define IMX390_DIGITAL_GAIN_DEFAULT	0x20
+
+/* White Balance control */
+#define IMX390_REG_CAT0_WBGAIN_R	0x0030
+#define IMX390_REG_CAT0_WBGAIN_B	0x0036
+#define IMX390_R_B_BALANCE_MAX		0xFFF
+#define IMX390_R_B_BALANCE_DEFAULT	0x200
+
+/* Vertical and Horizontal Flip control */
+#define IMX390_REG_CAT0_V_H_REVERSE	0x0074
+#define IMX390_V_REV_MASK		BIT(0)
+#define IMX390_H_REV_MASK		BIT(1)
+#define IMX390_REG_SM_CFG_REVERSE_APL	0x03C0
+#define IMX390_V_REV_APL_MASK		BIT(2)
+#define IMX390_H_REV_APL_MASK		BIT(3)
+
+/* Test Pattern control */
+#define IMX390_REG_CAT0_PGMODE_PGREGEN	0x01DB
+#define IMX390_SM_CFG_SM_PGREGEN_APL	0x03C0
+#define IMX390_SM_PG_APL_MASK		BIT(1)
+
+#define IMX390_PM_IDLE_TIMEOUT		1000
+
+struct imx390_ctrl {
+	struct v4l2_ctrl_handler handler;
+	struct v4l2_ctrl *wdr;
+	struct v4l2_ctrl *exposure;
+	struct v4l2_ctrl *again;
+	struct v4l2_ctrl *dgain;
+	struct v4l2_ctrl *r_balance;
+	struct v4l2_ctrl *b_balance;
+	struct v4l2_ctrl *h_flip;
+	struct v4l2_ctrl *v_flip;
+	struct v4l2_ctrl *pg_mode;
+};
+
+/*
+ * struct im390 - imx390 device structure
+ * @dev: Device handle
+ * @clk: Pointer to imx390 clock
+ * @client: Pointer to I2C client
+ * @regmap: Pointer to regmap structure
+ * @xclr_gpio: Pointer to XCLR gpio
+ * @subddev: V4L2 subdevice structure
+ * @format: V4L2 media bus frame format structure
+ *          (width and height are in sync with the compose rect)
+ * @pad: Media pad structure
+ * @ctrl: imx390 control structure
+ * @frame_interval: Time period of one frame in seconds
+ * @clk_rate: Frequency of imx390 clock
+ * @lock: Mutex structure for V4L2 ctrl handler
+ * @streaming: Flag to store the streaming on/off status
+ */
+struct imx390 {
+	struct device *dev;
+
+	struct clk *clk;
+	struct i2c_client *client;
+	struct regmap *regmap;
+	struct gpio_desc *xclr_gpio;
+
+	struct v4l2_subdev subdev;
+	struct v4l2_mbus_framefmt format;
+	struct media_pad pad;
+
+	struct imx390_ctrl ctrl;
+
+	unsigned long clk_rate;
+	u32 fps;
+
+	/* mutex for V4L2 ctrl handler */
+	struct mutex lock;
+	bool streaming;
+};
+
+static const struct v4l2_area imx390_framesizes[] = {
+	{
+		.width		= IMX390_OUT_WIDTH,
+		.height		= IMX390_OUT_HEIGHT,
+	},
+};
+
+static const u32 imx390_mbus_formats[] = {
+	MEDIA_BUS_FMT_SRGGB12_1X12,
+};
+
+static const struct regmap_config imx390_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+};
+
+static const u32 imx390_pg_mode_reg_val[] = {
+	0x00,
+	0x32,
+	0x33,
+	0x35,
+	0x3D,
+};
+
+static const char *const imx390_ctrl_pg_qmenu[] = {
+	"Disabled",
+	"Horizontal Color Bars",
+	"Vertical Color Bars",
+	"Gradation",
+	"Checker Pattern",
+};
+
+static const struct reg_sequence imx390_wdr_1936x1096[] = {
+	{ 0x000C, 0x7F },
+	{ 0x000D, 0x01 },
+	{ 0x000E, 0x00 },
+	{ 0x0010, 0x7F },
+	{ 0x0011, 0x01 },
+	{ 0x0012, 0x00 },
+	{ 0x0018, 0x20 },
+	{ 0x0019, 0x00 },
+	{ 0x001A, 0x0C },
+	{ 0x001B, 0x00 },
+	{ 0x0038, 0x00 },
+	{ 0x003C, 0x00 },
+	{ 0x003D, 0x00 },
+	{ 0x003E, 0x00 },
+	{ 0x0040, 0x00 },
+	{ 0x0041, 0x00 },
+	{ 0x0042, 0x00 },
+	{ 0x0044, 0x00 },
+	{ 0x0045, 0x00 },
+	{ 0x0046, 0x00 },
+	{ 0x0048, 0x00 },
+	{ 0x0049, 0x00 },
+	{ 0x004A, 0x00 },
+	{ 0x004C, 0x00 },
+	{ 0x004D, 0x00 },
+	{ 0x004E, 0x00 },
+	{ 0x0050, 0x00 },
+	{ 0x0051, 0x00 },
+	{ 0x0052, 0x00 },
+	{ 0x0054, 0x00 },
+	{ 0x0055, 0x00 },
+	{ 0x0056, 0x00 },
+	{ 0x0058, 0x00 },
+	{ 0x0059, 0x00 },
+	{ 0x005A, 0x00 },
+	{ 0x005C, 0x00 },
+	{ 0x005D, 0x00 },
+	{ 0x005E, 0x00 },
+	{ 0x0060, 0x00 },
+	{ 0x0061, 0x00 },
+	{ 0x0062, 0x00 },
+	{ 0x0064, 0x00 },
+	{ 0x0065, 0x00 },
+	{ 0x0066, 0x00 },
+	{ 0x0068, 0x00 },
+	{ 0x0069, 0x00 },
+	{ 0x006A, 0x00 },
+	{ 0x0078, 0x01 },
+	{ 0x007C, 0x08 },
+	{ 0x007D, 0x00 },
+	{ 0x0080, 0x08 },
+	{ 0x0081, 0x00 },
+	{ 0x0090, 0x00 },
+	{ 0x00F4, 0x1C },
+	{ 0x00F5, 0xF8 },
+	{ 0x00F6, 0x01 },
+	{ 0x00F8, 0x03 },
+	{ 0x00F9, 0x01 },
+	{ 0x00FA, 0x00 },
+	{ 0x00FB, 0x02 },
+	{ 0x0114, 0x00 },
+	{ 0x0115, 0x01 },
+	{ 0x0118, 0x20 },
+	{ 0x0119, 0x03 },
+	{ 0x011A, 0x00 },
+	{ 0x011B, 0x41 },
+	{ 0x011C, 0x80 },
+	{ 0x011D, 0x00 },
+	{ 0x0120, 0x20 },
+	{ 0x0121, 0x00 },
+	{ 0x0122, 0x00 },
+	{ 0x0123, 0x44 },
+	{ 0x0124, 0x00 },
+	{ 0x0125, 0x01 },
+	{ 0x0128, 0xAC },
+	{ 0x0129, 0x0D },
+	{ 0x012A, 0x00 },
+	{ 0x012B, 0xA4 },
+	{ 0x012C, 0x00 },
+	{ 0x012D, 0x01 },
+	{ 0x0130, 0xC4 },
+	{ 0x0131, 0x09 },
+	{ 0x0132, 0x00 },
+	{ 0x0133, 0xDA },
+	{ 0x0138, 0x00 }, /* DB_CMN_POST_PEDESTAL (0x0138: 0x0139) = 0 */
+	{ 0x0139, 0x00 }, /* DB_CMN_POST_PEDESTAL (0x0138: 0x0139) = 0 */
+	{ 0x013A, 0x00 },
+	{ 0x013B, 0x00 },
+	{ 0x013C, 0x00 },
+	{ 0x013D, 0x00 },
+	{ 0x013E, 0x00 },
+	{ 0x0140, 0x00 },
+	{ 0x0141, 0x00 },
+	{ 0x0142, 0x00 },
+	/* Start of PWL Registers */
+	{ 0x0144, 0x00 },	/* pwl_cp1_x 2048	*/
+	{ 0x0145, 0x08 },	/* pwl_cp1_x 2048	*/
+	{ 0x0146, 0x00 },	/* pwl_cp1_x 2048	*/
+	{ 0x0147, 0x00 },	/* pwl_cp1_x 2048	*/
+	{ 0x0148, 0x00 },	/* pwl_cp1_y 51		*/
+	{ 0x0149, 0x02 },	/* pwl_cp1_y 51		*/
+	{ 0x014A, 0x00 },	/* pwl_cp1_y 51		*/
+	{ 0x014B, 0x00 },	/* pwl_cp1_y 51		*/
+	{ 0x014C, 0x00 },	/* pwl_cp2_x 1638	*/
+	{ 0x014D, 0x40 },	/* pwl_cp2_x 1638	*/
+	{ 0x014E, 0x00 },	/* pwl_cp2_x 1638	*/
+	{ 0x014F, 0x00 },	/* pwl_cp2_x 1638	*/
+	{ 0x0150, 0x80 },	/* pwl_cp2_y 1408	*/
+	{ 0x0151, 0x05 },	/* pwl_cp2_y 1408	*/
+	{ 0x0152, 0x00 },	/* pwl_cp2_y 1408	*/
+	{ 0x0153, 0x00 },	/* pwl_cp2_y 1408	*/
+	{ 0x0154, 0x00 },	/* pwl_cp3_x 6553	*/
+	{ 0x0155, 0x00 },	/* pwl_cp3_x 6553	*/
+	{ 0x0156, 0x01 },	/* pwl_cp3_x 6553	*/
+	{ 0x0157, 0x00 },	/* pwl_cp3_x 6553	*/
+	{ 0x0158, 0x80 },	/* pwl_cp3_y 2176	*/
+	{ 0x0159, 0x08 },	/* pwl_cp3_y 2176	*/
+	{ 0x015A, 0x00 },	/* pwl_cp3_y 2176	*/
+	{ 0x015B, 0x00 },	/* pwl_cp3_y 2176	*/
+	{ 0x015C, 0x00 },	/* pwl_cp4_x 0x100000	*/
+	{ 0x015D, 0x00 },	/* pwl_cp4_x 0x100000	*/
+	{ 0x015E, 0x10 },	/* pwl_cp4_x 0x100000	*/
+	{ 0x015F, 0x00 },	/* pwl_cp4_x 0x100000	*/
+	{ 0x0160, 0x00 },	/* pwl_cp4_y 0x1000	*/
+	{ 0x0161, 0x10 },	/* pwl_cp4_y 0x1000	*/
+	{ 0x0162, 0x00 },	/* pwl_cp4_y 0x1000	*/
+	{ 0x0163, 0x00 },	/* pwl_cp4_y 0x1000	*/
+	{ 0x0164, 0x00 },	/* pwl_cp5_x 0x100000	*/
+	{ 0x0165, 0x00 },	/* pwl_cp5_x 0x100000	*/
+	{ 0x0166, 0x10 },	/* pwl_cp5_x 0x100000	*/
+	{ 0x0167, 0x00 },	/* pwl_cp5_x 0x100000	*/
+	{ 0x0168, 0x00 },	/* pwl_cp5_y 0x1000	*/
+	{ 0x0169, 0x10 },	/* pwl_cp5_y 0x1000	*/
+	{ 0x016A, 0x00 },	/* pwl_cp5_y 0x1000	*/
+	{ 0x016B, 0x00 },	/* pwl_cp5_y 0x1000	*/
+	{ 0x016C, 0x00 },	/* pwl_cp6_x 0x100000	*/
+	{ 0x016D, 0x00 },	/* pwl_cp6_x 0x100000	*/
+	{ 0x016E, 0x10 },	/* pwl_cp6_x 0x100000	*/
+	{ 0x016F, 0x00 },	/* pwl_cp6_x 0x100000	*/
+	{ 0x0170, 0x00 },	/* pwl_cp6_y 0x1000	*/
+	{ 0x0171, 0x10 },	/* pwl_cp6_y 0x1000	*/
+	{ 0x0172, 0x00 },	/* pwl_cp6_y 0x1000	*/
+	{ 0x0173, 0x00 },	/* pwl_cp6_y 0x1000	*/
+	{ 0x0174, 0x00 },	/* pwl_cp7_x 0x100000	*/
+	{ 0x0175, 0x00 },	/* pwl_cp7_x 0x100000	*/
+	{ 0x0176, 0x10 },	/* pwl_cp7_x 0x100000	*/
+	{ 0x0177, 0x00 },	/* pwl_cp7_x 0x100000	*/
+	{ 0x0178, 0x00 },	/* pwl_cp7_y 0x1000	*/
+	{ 0x0179, 0x10 },	/* pwl_cp7_y 0x1000	*/
+	{ 0x017A, 0x00 },	/* pwl_cp7_y 0x1000	*/
+	{ 0x017B, 0x00 },	/* pwl_cp7_y 0x1000	*/
+	{ 0x017C, 0x00 },	/* pwl_cp8_x 0x100000	*/
+	{ 0x017D, 0x00 },	/* pwl_cp8_x 0x100000	*/
+	{ 0x017E, 0x10 },	/* pwl_cp8_x 0x100000	*/
+	{ 0x017F, 0x00 },	/* pwl_cp8_x 0x100000	*/
+	{ 0x0180, 0x00 },	/* pwl_cp8_y 0x1000	*/
+	{ 0x0181, 0x10 },	/* pwl_cp8_y 0x1000	*/
+	{ 0x0182, 0x00 },	/* pwl_cp8_y 0x1000	*/
+	{ 0x0183, 0x00 },	/* pwl_cp8_y 0x1000	*/
+	{ 0x0184, 0x00 },	/* pwl_cp9_x 0x100000	*/
+	{ 0x0185, 0x00 },	/* pwl_cp9_x 0x100000	*/
+	{ 0x0186, 0x10 },	/* pwl_cp9_x 0x100000	*/
+	{ 0x0187, 0x00 },	/* pwl_cp9_x 0x100000	*/
+	{ 0x0188, 0x00 },	/* pwl_cp9_y 0x1000	*/
+	{ 0x0189, 0x10 },	/* pwl_cp9_y 0x1000	*/
+	{ 0x018A, 0x00 },	/* pwl_cp9_y 0x1000	*/
+	{ 0x018B, 0x00 },	/* pwl_cp9_y 0x1000	*/
+	{ 0x018C, 0x00 },	/* pwl_cp10_x 0x10000	*/
+	{ 0x018D, 0x00 },	/* pwl_cp10_x 0x10000	*/
+	{ 0x018E, 0x10 },	/* pwl_cp10_x 0x10000	*/
+	{ 0x018F, 0x00 },	/* pwl_cp10_x 0x10000	*/
+	{ 0x0190, 0x00 },	/* pwl_cp10_y 0x100	*/
+	{ 0x0191, 0x10 },	/* pwl_cp10_y 0x100	*/
+	{ 0x0192, 0x00 },	/* pwl_cp10_y 0x100	*/
+	{ 0x0193, 0x00 },	/* pwl_cp10_y 0x100	*/
+	{ 0x0198, 0x00 },	/* pwl gain0 0x040 0000	*/
+	{ 0x0199, 0x00 },
+	{ 0x019A, 0x40 },
+	{ 0x019B, 0x00 },
+	{ 0x019C, 0x00 },	/* pwl gain1 0x010 0000 */
+	{ 0x019D, 0x00 },
+	{ 0x019E, 0x10 },
+	{ 0x019F, 0x00 },
+	{ 0x01A0, 0x00 },	/* pwl gain2 0x004 0000 */
+	{ 0x01A1, 0x00 },
+	{ 0x01A2, 0x04 },
+	{ 0x01A3, 0x00 },
+	{ 0x01A4, 0x00 },	/* pwl gain3 0x000 8000 */
+	{ 0x01A5, 0x80 },
+	{ 0x01A6, 0x00 },
+	{ 0x01A7, 0x00 },
+	{ 0x01A8, 0x00 },
+	{ 0x01A9, 0x00 },
+	{ 0x01AA, 0x00 },
+	{ 0x01AB, 0x00 },
+	/* End of PWL Registers*/
+	{ 0x01AC, 0x00 },
+	{ 0x01AD, 0x00 },
+	{ 0x01AE, 0x00 },
+	{ 0x01AF, 0x00 },
+	{ 0x01B0, 0x00 },
+	{ 0x01B1, 0x00 },
+	{ 0x01B2, 0x00 },
+	{ 0x01B3, 0x00 },
+	{ 0x01B4, 0x00 },
+	{ 0x01B5, 0x00 },
+	{ 0x01B6, 0x00 },
+	{ 0x01B7, 0x00 },
+	{ 0x01B8, 0x00 },
+	{ 0x01B9, 0x00 },
+	{ 0x01BA, 0x00 },
+	{ 0x01BB, 0x00 },
+	{ 0x01BC, 0x00 },
+	{ 0x01BD, 0x00 },
+	{ 0x01BE, 0x00 },
+	{ 0x01BF, 0x00 },
+	{ 0x01C0, 0x00 },
+	{ 0x01C1, 0x00 },
+	{ 0x01C2, 0x00 },
+	{ 0x01C3, 0x00 },
+	{ 0x01C4, 0x00 },
+	{ 0x01C5, 0x00 },
+	{ 0x01CC, 0x01 },
+	{ 0x01D0, 0x09 },
+	{ 0x01D4, 0x01 },
+	{ 0x0332, 0x67 },
+	{ 0x0333, 0x02 },
+	{ 0x0390, 0x00 },
+	{ 0x0391, 0x00 },
+	{ 0x0392, 0x00 },
+	{ 0x03C0, 0x01 },
+	{ 0x2000, 0x55 },
+	{ 0x2001, 0x55 },
+	{ 0x2002, 0x55 },
+	{ 0x2003, 0x05 },
+	{ 0x2004, 0x02 },
+	{ 0x2008, 0x65 },
+	{ 0x2009, 0x04 },
+	{ 0x200A, 0x00 },
+	{ 0x200C, 0x98 },
+	{ 0x200D, 0x08 },
+	{ 0x2010, 0x04 },
+	{ 0x2014, 0x00 },
+	{ 0x2018, 0x02 },
+	{ 0x2019, 0x04 },
+	{ 0x201A, 0x00 },
+	{ 0x201C, 0x21 },
+	{ 0x201D, 0x11 },
+	{ 0x201E, 0x00 },
+	{ 0x201F, 0x00 },
+	{ 0x2020, 0xBC },
+	{ 0x2021, 0x00 },
+	{ 0x2022, 0x7F },
+	{ 0x2023, 0x00 },
+	{ 0x2024, 0xBA },
+	{ 0x2025, 0x00 },
+	{ 0x2026, 0x81 },
+	{ 0x2027, 0x00 },
+	{ 0x2028, 0x7D },
+	{ 0x2029, 0x90 },
+	{ 0x202A, 0x05 },
+	{ 0x202C, 0xFC },
+	{ 0x202D, 0x02 },
+	{ 0x202E, 0x25 },
+	{ 0x202F, 0x03 },
+	{ 0x2030, 0x05 },
+	{ 0x2031, 0x02 },
+	{ 0x2032, 0xCA },
+	{ 0x2033, 0x02 },
+	{ 0x2034, 0xFC },
+	{ 0x2035, 0x02 },
+	{ 0x2036, 0x25 },
+	{ 0x2037, 0x03 },
+	{ 0x2038, 0xF8 },
+	{ 0x2039, 0xE4 },
+	{ 0x203A, 0xE3 },
+	{ 0x203B, 0x01 },
+	{ 0x203C, 0xF5 },
+	{ 0x203D, 0x8E },
+	{ 0x203E, 0x0C },
+	{ 0x203F, 0x2D },
+	{ 0x2040, 0x69 },
+	{ 0x2041, 0x01 },
+	{ 0x2042, 0x8E },
+	{ 0x2043, 0x01 },
+	{ 0x2044, 0x0C },
+	{ 0x2045, 0x02 },
+	{ 0x2046, 0x31 },
+	{ 0x2047, 0x02 },
+	{ 0x2048, 0x6A },
+	{ 0x2049, 0x01 },
+	{ 0x204A, 0x8E },
+	{ 0x204B, 0x01 },
+	{ 0x204C, 0x0D },
+	{ 0x204D, 0x02 },
+	{ 0x204E, 0x31 },
+	{ 0x204F, 0x02 },
+	{ 0x2050, 0x7B },
+	{ 0x2051, 0x00 },
+	{ 0x2052, 0x7D },
+	{ 0x2053, 0x00 },
+	{ 0x2054, 0x95 },
+	{ 0x2055, 0x00 },
+	{ 0x2056, 0x97 },
+	{ 0x2057, 0x00 },
+	{ 0x2058, 0xAD },
+	{ 0x2059, 0x00 },
+	{ 0x205A, 0xAF },
+	{ 0x205B, 0x00 },
+	{ 0x205C, 0x92 },
+	{ 0x205D, 0x00 },
+	{ 0x205E, 0x94 },
+	{ 0x205F, 0x00 },
+	{ 0x2060, 0x8E },
+	{ 0x2061, 0x00 },
+	{ 0x2062, 0x90 },
+	{ 0x2063, 0x00 },
+	{ 0x2064, 0xB1 },
+	{ 0x2065, 0x00 },
+	{ 0x2066, 0xB3 },
+	{ 0x2067, 0x00 },
+	{ 0x2068, 0x08 },
+	{ 0x2069, 0x00 },
+	{ 0x206A, 0x04 },
+	{ 0x206B, 0x00 },
+	{ 0x206C, 0x84 },
+	{ 0x206D, 0x00 },
+	{ 0x206E, 0x80 },
+	{ 0x206F, 0x00 },
+	{ 0x2070, 0x04 },
+	{ 0x2071, 0x00 },
+	{ 0x2072, 0x46 },
+	{ 0x2073, 0x00 },
+	{ 0x2074, 0xE9 },
+	{ 0x2075, 0x01 },
+	{ 0x2076, 0x74 },
+	{ 0x2077, 0x02 },
+	{ 0x2078, 0x80 },
+	{ 0x2079, 0x00 },
+	{ 0x207A, 0xC1 },
+	{ 0x207B, 0x00 },
+	{ 0x207C, 0xFF },
+	{ 0x207D, 0x03 },
+	{ 0x207E, 0xFF },
+	{ 0x207F, 0x03 },
+	{ 0x2080, 0x78 },
+	{ 0x2081, 0x00 },
+	{ 0x2082, 0x6A },
+	{ 0x2083, 0x01 },
+	{ 0x2084, 0xE4 },
+	{ 0x2085, 0x01 },
+	{ 0x2086, 0x2B },
+	{ 0x2087, 0x03 },
+	{ 0x2088, 0x00 },
+	{ 0x2089, 0x00 },
+	{ 0x208A, 0xFF },
+	{ 0x208B, 0x03 },
+	{ 0x208C, 0xFF },
+	{ 0x208D, 0x03 },
+	{ 0x208E, 0xFF },
+	{ 0x208F, 0x03 },
+	{ 0x2090, 0x7D },
+	{ 0x2091, 0x00 },
+	{ 0x2092, 0x62 },
+	{ 0x2093, 0x01 },
+	{ 0x2094, 0xE9 },
+	{ 0x2095, 0x01 },
+	{ 0x2096, 0x00 },
+	{ 0x2097, 0x00 },
+	{ 0x2098, 0x7C },
+	{ 0x2099, 0x00 },
+	{ 0x209A, 0x21 },
+	{ 0x209B, 0x03 },
+	{ 0x209C, 0xE9 },
+	{ 0x209D, 0x01 },
+	{ 0x209E, 0x21 },
+	{ 0x209F, 0x03 },
+	{ 0x20A0, 0xFF },
+	{ 0x20A1, 0x03 },
+	{ 0x20A2, 0xFF },
+	{ 0x20A3, 0x03 },
+	{ 0x20A4, 0xFF },
+	{ 0x20A5, 0x03 },
+	{ 0x20A6, 0xFF },
+	{ 0x20A7, 0x03 },
+	{ 0x20A8, 0xFF },
+	{ 0x20A9, 0x03 },
+	{ 0x20AA, 0xFF },
+	{ 0x20AB, 0x03 },
+	{ 0x20AC, 0xFF },
+	{ 0x20AD, 0x03 },
+	{ 0x20AE, 0xFF },
+	{ 0x20AF, 0x03 },
+	{ 0x20B0, 0xFF },
+	{ 0x20B1, 0x03 },
+	{ 0x20B2, 0xFF },
+	{ 0x20B3, 0x03 },
+	{ 0x20B4, 0x87 },
+	{ 0x20B5, 0xCC },
+	{ 0x20B6, 0x87 },
+	{ 0x20B7, 0x08 },
+	{ 0x20B8, 0xF4 },
+	{ 0x20B9, 0xA5 },
+	{ 0x20BA, 0x07 },
+	{ 0x20BC, 0x1F },
+	{ 0x20BD, 0x01 },
+	{ 0x20BE, 0xF6 },
+	{ 0x20BF, 0x00 },
+	{ 0x20C0, 0x90 },
+	{ 0x20C1, 0x01 },
+	{ 0x20C2, 0x67 },
+	{ 0x20C3, 0x01 },
+	{ 0x20C4, 0xFF },
+	{ 0x20C5, 0x03 },
+	{ 0x20C6, 0xFF },
+	{ 0x20C7, 0x03 },
+	{ 0x20C8, 0x33 },
+	{ 0x20C9, 0x02 },
+	{ 0x20CA, 0x0A },
+	{ 0x20CB, 0x02 },
+	{ 0x20CC, 0x7F },
+	{ 0x20CD, 0x00 },
+	{ 0x20CE, 0xD2 },
+	{ 0x20CF, 0x00 },
+	{ 0x20D0, 0x81 },
+	{ 0x20D1, 0x00 },
+	{ 0x20D2, 0x87 },
+	{ 0x20D3, 0x00 },
+	{ 0x20D4, 0x09 },
+	{ 0x20D5, 0x00 },
+	{ 0x20D8, 0x7F },
+	{ 0x20D9, 0x00 },
+	{ 0x20DA, 0x62 },
+	{ 0x20DB, 0x01 },
+	{ 0x20DC, 0x7F },
+	{ 0x20DD, 0x00 },
+	{ 0x20DE, 0x62 },
+	{ 0x20DF, 0x01 },
+	{ 0x20E0, 0x65 },
+	{ 0x20E1, 0x00 },
+	{ 0x20E2, 0x75 },
+	{ 0x20E3, 0x00 },
+	{ 0x20E4, 0xE0 },
+	{ 0x20E5, 0x00 },
+	{ 0x20E6, 0xF0 },
+	{ 0x20E7, 0x00 },
+	{ 0x20E8, 0x4C },
+	{ 0x20E9, 0x01 },
+	{ 0x20EA, 0x5C },
+	{ 0x20EB, 0x01 },
+	{ 0x20EC, 0xD1 },
+	{ 0x20ED, 0x01 },
+	{ 0x20EE, 0xE1 },
+	{ 0x20EF, 0x01 },
+	{ 0x20F0, 0x93 },
+	{ 0x20F1, 0x02 },
+	{ 0x20F2, 0xA3 },
+	{ 0x20F3, 0x02 },
+	{ 0x20F4, 0x0D },
+	{ 0x20F5, 0x03 },
+	{ 0x20F6, 0x1D },
+	{ 0x20F7, 0x03 },
+	{ 0x20F8, 0x57 },
+	{ 0x20F9, 0x00 },
+	{ 0x20FA, 0x7B },
+	{ 0x20FB, 0x00 },
+	{ 0x20FC, 0xD2 },
+	{ 0x20FD, 0x00 },
+	{ 0x20FE, 0xF6 },
+	{ 0x20FF, 0x00 },
+	{ 0x2100, 0x3E },
+	{ 0x2101, 0x01 },
+	{ 0x2102, 0x60 },
+	{ 0x2103, 0x01 },
+	{ 0x2104, 0xC3 },
+	{ 0x2105, 0x01 },
+	{ 0x2106, 0xE5 },
+	{ 0x2107, 0x01 },
+	{ 0x2108, 0x85 },
+	{ 0x2109, 0x02 },
+	{ 0x210A, 0xA9 },
+	{ 0x210B, 0x02 },
+	{ 0x210C, 0xFF },
+	{ 0x210D, 0x02 },
+	{ 0x210E, 0x21 },
+	{ 0x210F, 0x03 },
+	{ 0x2110, 0xFF },
+	{ 0x2111, 0x03 },
+	{ 0x2112, 0x00 },
+	{ 0x2113, 0x00 },
+	{ 0x2114, 0xFF },
+	{ 0x2115, 0x03 },
+	{ 0x2116, 0xFF },
+	{ 0x2117, 0x03 },
+	{ 0x2118, 0xFF },
+	{ 0x2119, 0x03 },
+	{ 0x211A, 0xFF },
+	{ 0x211B, 0x03 },
+	{ 0x211C, 0xFF },
+	{ 0x211D, 0x03 },
+	{ 0x211E, 0xFF },
+	{ 0x211F, 0x03 },
+	{ 0x2120, 0xFF },
+	{ 0x2121, 0x03 },
+	{ 0x2122, 0xFF },
+	{ 0x2123, 0x03 },
+	{ 0x2124, 0xFF },
+	{ 0x2125, 0x03 },
+	{ 0x2126, 0xFF },
+	{ 0x2127, 0x03 },
+	{ 0x2128, 0x7D },
+	{ 0x2129, 0x90 },
+	{ 0x212A, 0xD5 },
+	{ 0x212B, 0x07 },
+	{ 0x212C, 0x64 },
+	{ 0x212D, 0x01 },
+	{ 0x2130, 0x5F },
+	{ 0x2131, 0x7D },
+	{ 0x2132, 0x05 },
+	{ 0x2134, 0x78 },
+	{ 0x2135, 0x00 },
+	{ 0x2136, 0x76 },
+	{ 0x2137, 0x00 },
+	{ 0x2138, 0xF3 },
+	{ 0x2139, 0x00 },
+	{ 0x213A, 0xF1 },
+	{ 0x213B, 0x00 },
+	{ 0x213C, 0xA6 },
+	{ 0x213D, 0x02 },
+	{ 0x213E, 0xA4 },
+	{ 0x213F, 0x02 },
+	{ 0x2140, 0x7D },
+	{ 0x2141, 0x00 },
+	{ 0x2142, 0x8D },
+	{ 0x2143, 0x00 },
+	{ 0x2144, 0xA1 },
+	{ 0x2145, 0x01 },
+	{ 0x2146, 0xB1 },
+	{ 0x2147, 0x01 },
+	{ 0x2148, 0xAB },
+	{ 0x2149, 0x02 },
+	{ 0x214A, 0xBB },
+	{ 0x214B, 0x02 },
+	{ 0x214C, 0x17 },
+	{ 0x214D, 0x5C },
+	{ 0x214E, 0x00 },
+	{ 0x2150, 0x00 },
+	{ 0x2151, 0x00 },
+	{ 0x2152, 0xF8 },
+	{ 0x2153, 0x00 },
+	{ 0x2154, 0xBE },
+	{ 0x2155, 0x00 },
+	{ 0x2156, 0x7D },
+	{ 0x2157, 0x00 },
+	{ 0x2158, 0x25 },
+	{ 0x2159, 0x00 },
+	{ 0x215A, 0x7D },
+	{ 0x215B, 0x00 },
+	{ 0x215C, 0x62 },
+	{ 0x215D, 0x01 },
+	{ 0x215E, 0xFF },
+	{ 0x215F, 0x03 },
+	{ 0x2160, 0x26 },
+	{ 0x2161, 0x00 },
+	{ 0x2162, 0x7D },
+	{ 0x2163, 0x00 },
+	{ 0x2164, 0x63 },
+	{ 0x2165, 0x01 },
+	{ 0x2166, 0xFF },
+	{ 0x2167, 0x03 },
+	{ 0x2168, 0xCB },
+	{ 0x2169, 0x02 },
+	{ 0x216A, 0xCF },
+	{ 0x216B, 0x02 },
+	{ 0x216C, 0xFF },
+	{ 0x216D, 0x03 },
+	{ 0x216E, 0xFF },
+	{ 0x216F, 0x03 },
+	{ 0x2170, 0xFF },
+	{ 0x2171, 0x03 },
+	{ 0x2172, 0xFF },
+	{ 0x2173, 0x03 },
+	{ 0x2174, 0xFF },
+	{ 0x2175, 0x03 },
+	{ 0x2176, 0xFF },
+	{ 0x2177, 0x03 },
+	{ 0x2178, 0x7E },
+	{ 0x2179, 0x00 },
+	{ 0x217A, 0xBD },
+	{ 0x217B, 0x00 },
+	{ 0x217C, 0xEC },
+	{ 0x217D, 0x01 },
+	{ 0x217E, 0x7B },
+	{ 0x217F, 0x02 },
+	{ 0x2180, 0xD1 },
+	{ 0x2181, 0x02 },
+	{ 0x2182, 0x25 },
+	{ 0x2183, 0x03 },
+	{ 0x2184, 0x7F },
+	{ 0x2185, 0x00 },
+	{ 0x2186, 0xBD },
+	{ 0x2187, 0x00 },
+	{ 0x2188, 0xED },
+	{ 0x2189, 0x01 },
+	{ 0x218A, 0x7B },
+	{ 0x218B, 0x02 },
+	{ 0x218C, 0xD2 },
+	{ 0x218D, 0x02 },
+	{ 0x218E, 0x25 },
+	{ 0x218F, 0x03 },
+	{ 0x2190, 0xFF },
+	{ 0x2191, 0x03 },
+	{ 0x2192, 0xFF },
+	{ 0x2193, 0x03 },
+	{ 0x2194, 0xE9 },
+	{ 0x2195, 0x01 },
+	{ 0x2196, 0x21 },
+	{ 0x2197, 0x03 },
+	{ 0x2198, 0x17 },
+	{ 0x2199, 0xFC },
+	{ 0x219A, 0x7F },
+	{ 0x219B, 0x01 },
+	{ 0x219C, 0xFF },
+	{ 0x219D, 0x03 },
+	{ 0x21A0, 0x1B },
+	{ 0x21A1, 0x1B },
+	{ 0x21A2, 0x1B },
+	{ 0x21A3, 0x1B },
+	{ 0x21A4, 0x2B },
+	{ 0x21A5, 0x80 },
+	{ 0x21A6, 0x00 },
+	{ 0x21A8, 0x04 },
+	{ 0x21A9, 0x98 },
+	{ 0x21AA, 0x60 },
+	{ 0x21AB, 0x03 },
+	{ 0x21AC, 0x7F },
+	{ 0x21AD, 0x80 },
+	{ 0x21AE, 0x09 },
+	{ 0x21B0, 0x1C },
+	{ 0x21B1, 0x00 },
+	{ 0x21B2, 0xA0 },
+	{ 0x21B3, 0x00 },
+	{ 0x21B4, 0x0C },
+	{ 0x21B5, 0x00 },
+	{ 0x21B6, 0x2D },
+	{ 0x21B7, 0x00 },
+	{ 0x21B8, 0x20 },
+	{ 0x21B9, 0x00 },
+	{ 0x21BA, 0x02 },
+	{ 0x21BB, 0x00 },
+	{ 0x21BC, 0xCC },
+	{ 0x21BD, 0x00 },
+	{ 0x21BE, 0x4A },
+	{ 0x21BF, 0x00 },
+	{ 0x21C0, 0xD0 },
+	{ 0x21C1, 0x00 },
+	{ 0x21C2, 0x44 },
+	{ 0x21C3, 0x00 },
+	{ 0x21C4, 0x00 },
+	{ 0x21C5, 0xE0 },
+	{ 0x21C6, 0x00 },
+	{ 0x21C8, 0x11 },
+	{ 0x21C9, 0x00 },
+	{ 0x21CA, 0x02 },
+	{ 0x21CC, 0x08 },
+	{ 0x21CD, 0xC0 },
+	{ 0x21CE, 0x0C },
+	{ 0x21D0, 0x44 },
+	{ 0x21D1, 0x00 },
+	{ 0x21D2, 0x02 },
+	{ 0x21D4, 0x02 },
+	{ 0x21D5, 0x20 },
+	{ 0x21D6, 0x2C },
+	{ 0x21D8, 0xFE },
+	{ 0x21D9, 0x9D },
+	{ 0x21DA, 0xDF },
+	{ 0x21DB, 0x03 },
+	{ 0x21DC, 0x62 },
+	{ 0x21DD, 0x01 },
+	{ 0x21DE, 0x7F },
+	{ 0x21DF, 0x00 },
+	{ 0x21E0, 0xB7 },
+	{ 0x21E1, 0x01 },
+	{ 0x21E2, 0xB5 },
+	{ 0x21E3, 0x01 },
+	{ 0x21E4, 0xC1 },
+	{ 0x21E5, 0x02 },
+	{ 0x21E6, 0xBF },
+	{ 0x21E7, 0x02 },
+	{ 0x21E8, 0xB3 },
+	{ 0x21E9, 0x0D },
+	{ 0x21EA, 0x00 },
+	{ 0x21EB, 0x04 },
+	{ 0x21EC, 0x90 },
+	{ 0x21ED, 0x07 },
+	{ 0x21EE, 0x58 },
+	{ 0x21EF, 0x04 },
+	{ 0x21F0, 0x54 },
+	{ 0x21F1, 0x04 },
+	{ 0x21F4, 0x02 },
+	{ 0x21F5, 0x00 },
+	{ 0x21F6, 0x00 },
+	{ 0x21F8, 0x3C },
+	{ 0x21F9, 0x00 },
+	{ 0x21FC, 0x28 },
+	{ 0x21FD, 0x00 },
+	{ 0x21FE, 0x3C },
+	{ 0x21FF, 0x00 },
+	{ 0x2200, 0x00 },
+	{ 0x2204, 0x4C },
+	{ 0x2205, 0x04 },
+	{ 0x2206, 0x65 },
+	{ 0x2207, 0x04 },
+	{ 0x2208, 0x0A },
+	{ 0x2209, 0x00 },
+	{ 0x220C, 0x57 },
+	{ 0x220D, 0x00 },
+	{ 0x220E, 0x37 },
+	{ 0x220F, 0x00 },
+	{ 0x2210, 0x1F },
+	{ 0x2211, 0x00 },
+	{ 0x2212, 0x1F },
+	{ 0x2213, 0x00 },
+	{ 0x2214, 0x1F },
+	{ 0x2215, 0x00 },
+	{ 0x2216, 0x77 },
+	{ 0x2217, 0x00 },
+	{ 0x2218, 0x1F },
+	{ 0x2219, 0x00 },
+	{ 0x221A, 0x17 },
+	{ 0x221B, 0x00 },
+	{ 0x221C, 0x03 },
+	{ 0x2220, 0x24 },
+	{ 0x2221, 0x00 },
+	{ 0x2222, 0x00 },
+	{ 0x2223, 0x00 },
+	{ 0x2224, 0xA7 },
+	{ 0x2225, 0xAA },
+	{ 0x2226, 0x80 },
+	{ 0x2227, 0x08 },
+	{ 0x2228, 0x01 },
+	{ 0x2260, 0xFF },
+	{ 0x2261, 0x1F },
+	{ 0x2262, 0x00 },
+	{ 0x2263, 0x00 },
+	{ 0x2264, 0x00 },
+	{ 0x2265, 0x00 },
+	{ 0x2266, 0xFF },
+	{ 0x2267, 0x1F },
+	{ 0x2268, 0x00 },
+	{ 0x2269, 0x00 },
+	{ 0x226A, 0xFF },
+	{ 0x226B, 0x1F },
+	{ 0x226C, 0x00 },
+	{ 0x226D, 0x00 },
+	{ 0x226E, 0xFF },
+	{ 0x226F, 0x1F },
+	{ 0x227C, 0xB2 },
+	{ 0x227D, 0x0C },
+	{ 0x227E, 0x6A },
+	{ 0x227F, 0x09 },
+	{ 0x2280, 0xD2 },
+	{ 0x2281, 0x0C },
+	{ 0x2282, 0x5A },
+	{ 0x2283, 0x09 },
+	{ 0x2284, 0xC4 },
+	{ 0x2285, 0x0C },
+	{ 0x2286, 0x54 },
+	{ 0x2287, 0x09 },
+	{ 0x22B2, 0x92 },
+	{ 0x22B4, 0x20 },
+	{ 0x22B5, 0x00 },
+	{ 0x22B6, 0x20 },
+	{ 0x22B7, 0x00 },
+	{ 0x22B8, 0x20 },
+	{ 0x22B9, 0x00 },
+	{ 0x22BA, 0x20 },
+	{ 0x22BB, 0x00 },
+	{ 0x22BC, 0x20 },
+	{ 0x22BD, 0x00 },
+	{ 0x22BE, 0x20 },
+	{ 0x22BF, 0x00 },
+	{ 0x22C0, 0x20 },
+	{ 0x22C1, 0x00 },
+	{ 0x22C2, 0x20 },
+	{ 0x22C3, 0x00 },
+	{ 0x22C4, 0x20 },
+	{ 0x22C5, 0x00 },
+	{ 0x22C6, 0x20 },
+	{ 0x22C7, 0x00 },
+	{ 0x22C8, 0x20 },
+	{ 0x22C9, 0x00 },
+	{ 0x22CA, 0x20 },
+	{ 0x22CB, 0x00 },
+	{ 0x22CC, 0x20 },
+	{ 0x22CD, 0x00 },
+	{ 0x22CE, 0x20 },
+	{ 0x22CF, 0x00 },
+	{ 0x22DA, 0x00 },
+	{ 0x22EF, 0x82 },
+	{ 0x2308, 0x01 },
+	{ 0x2310, 0x4B },
+	{ 0x2311, 0x09 },
+	{ 0x2318, 0x40 },
+	{ 0x2319, 0xCD },
+	{ 0x231A, 0x54 },
+	{ 0x2324, 0x20 },
+	{ 0x2325, 0x00 },
+	{ 0x2328, 0x00 },
+	{ 0x234A, 0x9F },
+	{ 0x234B, 0x07 },
+	{ 0x2354, 0x0C },
+	{ 0x23C0, 0x5D },
+	{ 0x244C, 0xFF },
+	{ 0x244D, 0x03 },
+	{ 0x244E, 0xFF },
+	{ 0x244F, 0x03 },
+	{ 0x24A0, 0x00 },
+	{ 0x24A4, 0x16 },
+	{ 0x24A5, 0x01 },
+	{ 0x24A6, 0xA6 },
+	{ 0x24A7, 0x02 },
+	{ 0x24A8, 0xD5 },
+	{ 0x24A9, 0x02 },
+	{ 0x24BC, 0x17 },
+	{ 0x24BD, 0x01 },
+	{ 0x24BE, 0xA7 },
+	{ 0x24BF, 0x02 },
+	{ 0x24C0, 0xD5 },
+	{ 0x24C1, 0x02 },
+	{ 0x24DA, 0x6F },
+	{ 0x24DB, 0x00 },
+	{ 0x24DC, 0x62 },
+	{ 0x24DD, 0x01 },
+	{ 0x24EA, 0x32 },
+	{ 0x24EB, 0x00 },
+	{ 0x24EC, 0xDC },
+	{ 0x24ED, 0x00 },
+	{ 0x24FA, 0x32 },
+	{ 0x24FB, 0x00 },
+	{ 0x24FC, 0xDD },
+	{ 0x24FD, 0x00 },
+	{ 0x254A, 0x15 },
+	{ 0x254B, 0x01 },
+	{ 0x255A, 0x15 },
+	{ 0x255B, 0x01 },
+	{ 0x2560, 0x01 },
+	{ 0x2561, 0x00 },
+	{ 0x2562, 0x2A },
+	{ 0x2563, 0x00 },
+	{ 0x2564, 0xF8 },
+	{ 0x2565, 0x00 },
+	{ 0x2566, 0x15 },
+	{ 0x2567, 0x01 },
+	{ 0x2568, 0x0C },
+	{ 0x2569, 0x02 },
+	{ 0x256A, 0x31 },
+	{ 0x256B, 0x02 },
+	{ 0x2578, 0x90 },
+	{ 0x2579, 0x01 },
+	{ 0x257A, 0x92 },
+	{ 0x257B, 0x01 },
+	{ 0x257C, 0xB8 },
+	{ 0x257D, 0x02 },
+	{ 0x257E, 0xBA },
+	{ 0x257F, 0x02 },
+	{ 0x2584, 0x90 },
+	{ 0x2585, 0x01 },
+	{ 0x2586, 0x92 },
+	{ 0x2587, 0x01 },
+	{ 0x2588, 0xB8 },
+	{ 0x2589, 0x02 },
+	{ 0x258A, 0xBA },
+	{ 0x258B, 0x02 },
+	{ 0x267A, 0xF8 },
+	{ 0x267B, 0x00 },
+	{ 0x267C, 0x16 },
+	{ 0x267D, 0x01 },
+	{ 0x267E, 0xA6 },
+	{ 0x267F, 0x02 },
+	{ 0x2680, 0xD5 },
+	{ 0x2681, 0x02 },
+	{ 0x2690, 0xF8 },
+	{ 0x2691, 0x00 },
+	{ 0x2694, 0xA6 },
+	{ 0x2695, 0x02 },
+	{ 0x2696, 0x16 },
+	{ 0x2697, 0x01 },
+	{ 0x269A, 0xD5 },
+	{ 0x269B, 0x02 },
+	{ 0x26B8, 0x10 },
+	{ 0x26B9, 0x00 },
+	{ 0x26BA, 0x33 },
+	{ 0x26BB, 0x00 },
+	{ 0x26BC, 0x89 },
+	{ 0x26BD, 0x00 },
+	{ 0x26BE, 0xB0 },
+	{ 0x26BF, 0x00 },
+	{ 0x26C4, 0x4E },
+	{ 0x26C5, 0x00 },
+	{ 0x26C8, 0xC9 },
+	{ 0x26C9, 0x00 },
+	{ 0x26CC, 0x35 },
+	{ 0x26CD, 0x01 },
+	{ 0x26D0, 0xBA },
+	{ 0x26D1, 0x01 },
+	{ 0x26D4, 0x7C },
+	{ 0x26D5, 0x02 },
+	{ 0x26D8, 0xF6 },
+	{ 0x26D9, 0x02 },
+	{ 0x26DE, 0x51 },
+	{ 0x26DF, 0x00 },
+	{ 0x26E0, 0x7F },
+	{ 0x26E1, 0x00 },
+	{ 0x26E2, 0xCC },
+	{ 0x26E3, 0x00 },
+	{ 0x26E4, 0xF8 },
+	{ 0x26E5, 0x00 },
+	{ 0x26E6, 0x38 },
+	{ 0x26E7, 0x01 },
+	{ 0x26E8, 0x65 },
+	{ 0x26E9, 0x01 },
+	{ 0x26EA, 0xBD },
+	{ 0x26EB, 0x01 },
+	{ 0x26EE, 0x7F },
+	{ 0x26EF, 0x02 },
+	{ 0x26F0, 0xAB },
+	{ 0x26F1, 0x02 },
+	{ 0x26F2, 0xF9 },
+	{ 0x26F3, 0x02 },
+	{ 0x2722, 0x59 },
+	{ 0x2723, 0x02 },
+	{ 0x2938, 0x55 },
+	{ 0x2939, 0x00 },
+	{ 0x293A, 0x17 },
+	{ 0x293B, 0x00 },
+	{ 0x293C, 0xD0 },
+	{ 0x293D, 0x00 },
+	{ 0x293E, 0x91 },
+	{ 0x293F, 0x00 },
+	{ 0x2940, 0x3C },
+	{ 0x2941, 0x01 },
+	{ 0x2942, 0x0C },
+	{ 0x2943, 0x01 },
+	{ 0x2944, 0xC1 },
+	{ 0x2945, 0x01 },
+	{ 0x2946, 0x76 },
+	{ 0x2947, 0x01 },
+	{ 0x2948, 0x83 },
+	{ 0x2949, 0x02 },
+	{ 0x294A, 0xFB },
+	{ 0x294B, 0x01 },
+	{ 0x294C, 0xFD },
+	{ 0x294D, 0x02 },
+	{ 0x294E, 0xBF },
+	{ 0x294F, 0x02 },
+	{ 0x2A06, 0x25 },
+	{ 0x2A07, 0x03 },
+	{ 0x2A0C, 0x45 },
+	{ 0x2A0D, 0x00 },
+	{ 0x2A0E, 0x00 },
+	{ 0x2A0F, 0x00 },
+	{ 0x2A20, 0x00 },
+	{ 0x2A21, 0x00 },
+	{ 0x2A22, 0x7D },
+	{ 0x2A23, 0x00 },
+	{ 0x2B11, 0x1A },
+	{ 0x2B13, 0x11 },
+	{ 0x2B14, 0x11 },
+	{ 0x2B15, 0x11 },
+	{ 0x2B16, 0x11 },
+	{ 0x2B17, 0x10 },
+	{ 0x2B18, 0x0F },
+	{ 0x2B19, 0x0E },
+	{ 0x2B1A, 0x0D },
+	{ 0x2B1B, 0x0C },
+	{ 0x2B1C, 0x0B },
+	{ 0x2B1D, 0x0B },
+	{ 0x2B1E, 0x0A },
+	{ 0x2B1F, 0x09 },
+	{ 0x2B20, 0x08 },
+	{ 0x2B21, 0x07 },
+	{ 0x2B22, 0x06 },
+	{ 0x2B23, 0x05 },
+	{ 0x2B24, 0x04 },
+	{ 0x2B25, 0x03 },
+	{ 0x2B26, 0x03 },
+	{ 0x2B38, 0x01 },
+	{ 0x2B45, 0xE3 },
+	{ 0x2B50, 0x01 },
+	{ 0x2B51, 0x00 },
+	{ 0x2B62, 0x66 },
+	{ 0x2B6D, 0x47 },
+	{ 0x2B70, 0x03 },
+	{ 0x2B71, 0x02 },
+	{ 0x2B72, 0x02 },
+	{ 0x2B7B, 0x42 },
+	{ 0x2B7F, 0x7F },
+	{ 0x2B80, 0x94 },
+	{ 0x2B81, 0x06 },
+	{ 0x2B87, 0x1B },
+	{ 0x2B88, 0x1A },
+	{ 0x2B89, 0x17 },
+	{ 0x2B8A, 0x17 },
+	{ 0x2B8B, 0x12 },
+	{ 0x2B8D, 0x2B },
+	{ 0x2B8E, 0x2B },
+	{ 0x2B8F, 0x2B },
+	{ 0x2B90, 0x7F },
+	{ 0x2B91, 0x0F },
+	{ 0x2B92, 0x31 },
+	{ 0x2B93, 0x07 },
+	{ 0x2B94, 0xFE },
+	{ 0x2B95, 0x26 },
+	{ 0x2B96, 0x84 },
+	{ 0x2B97, 0x0C },
+	{ 0x2B98, 0xFE },
+	{ 0x2B99, 0x56 },
+	{ 0x2B9B, 0x2A },
+	{ 0x2BA8, 0xBC },
+	{ 0x2BA9, 0x62 },
+	{ 0x2BC1, 0x70 },
+	{ 0x2BC5, 0x80 },
+	{ 0x2BD5, 0x30 },
+	{ 0x2BD6, 0xF0 },
+	{ 0x2BD8, 0xDB },
+	{ 0x2BD9, 0xF6 },
+	{ 0x2BDA, 0x21 },
+	{ 0x2BDB, 0x06 },
+	{ 0x2BDC, 0x57 },
+	{ 0x2BFE, 0x00 },
+	{ 0x2BFF, 0x00 },
+	{ 0x2C98, 0xE1 },
+	{ 0x2C99, 0x2E },
+	{ 0x2C9B, 0x80 },
+	{ 0x2CA9, 0x80 },
+	{ 0x2CAA, 0x01 },
+	{ 0x2CBF, 0x08 },
+	{ 0x2D39, 0x0E },
+	{ 0x2D50, 0x80 },
+	{ 0x2D54, 0x00 },
+	{ 0x2D5B, 0x58 },
+	{ 0x2DFD, 0x01 },
+	{ 0x2D64, 0x64 },
+	{ 0x2D65, 0x80 },
+	{ 0x3000, 0x00 },
+	{ 0x3001, 0x00 },
+	{ 0x3002, 0x23 },
+	{ 0x3003, 0xA1 },
+	{ 0x3004, 0x00 },
+	{ 0x3005, 0x20 },
+	{ 0x3006, 0x58 },
+	{ 0x3007, 0x00 },
+	{ 0x3008, 0x06 },
+	{ 0x3009, 0xB4 },
+	{ 0x300A, 0x1F },
+	{ 0x300B, 0x00 },
+	{ 0x300C, 0x00 },
+	{ 0x300D, 0x1B },
+	{ 0x300E, 0x90 },
+	{ 0x300F, 0x97 },
+	{ 0x3010, 0x00 },
+	{ 0x3011, 0x00 },
+	{ 0x3012, 0x20 },
+	{ 0x3013, 0x21 },
+	{ 0x3014, 0x00 },
+	{ 0x3015, 0x20 },
+	{ 0x3016, 0x84 },
+	{ 0x3017, 0x00 },
+	{ 0x3018, 0x30 },
+	{ 0x3019, 0x09 },
+	{ 0x301A, 0x46 },
+	{ 0x301B, 0x00 },
+	{ 0x3070, 0xC1 },
+	{ 0x3071, 0x81 },
+	{ 0x3072, 0x29 },
+	{ 0x3073, 0x81 },
+	{ 0x3080, 0xC4 },
+	{ 0x3081, 0x0C },
+	{ 0x3082, 0xD2 },
+	{ 0x3083, 0x0C },
+	{ 0x3084, 0x5C },
+	{ 0x3085, 0x00 },
+	{ 0x3086, 0x90 },
+	{ 0x3087, 0x00 },
+	{ 0x3088, 0x07 },
+	{ 0x3089, 0x0A },
+	{ 0x308A, 0x52 },
+	{ 0x308B, 0x09 },
+	{ 0x308C, 0x44 },
+	{ 0x308D, 0x03 },
+	{ 0x308E, 0x70 },
+	{ 0x308F, 0x03 },
+	{ 0x3090, 0x54 },
+	{ 0x3091, 0x09 },
+	{ 0x3092, 0x5A },
+	{ 0x3093, 0x09 },
+	{ 0x3094, 0x1C },
+	{ 0x3095, 0x00 },
+	{ 0x3096, 0x10 },
+	{ 0x3097, 0x00 },
+	{ 0x3098, 0x70 },
+	{ 0x3099, 0x03 },
+	{ 0x309A, 0xF8 },
+	{ 0x309B, 0x04 },
+	{ 0x309C, 0x74 },
+	{ 0x309D, 0x01 },
+	{ 0x309E, 0x60 },
+	{ 0x309F, 0x01 },
+	{ 0x3370, 0x01 },
+	{ 0x3374, 0xF0 },
+	{ 0x3375, 0x00 },
+	{ 0x3376, 0x01 },
+	{ 0x3377, 0x00 },
+	{ 0x3410, (IMX390_OUT_WIDTH & 0xFF) },
+	{ 0x3411, (IMX390_OUT_WIDTH >> 8) },
+	{ 0x3418, (IMX390_OUT_HEIGHT & 0xFF) },
+	{ 0x3419, (IMX390_OUT_HEIGHT >> 8) },
+	{ 0x34A0, 0x30 },
+	{ 0x34BE, 0x6A },
+	{ 0x34BF, 0x01 },
+	{ 0x34C0, 0x40 },
+	{ 0x34C1, 0x00 },
+	{ 0x34C2, 0x40 },
+	{ 0x34C3, 0x00 },
+	{ 0x34C4, 0x40 },
+	{ 0x34C5, 0x00 },
+	{ 0x34C6, 0x40 },
+	{ 0x34C7, 0x00 },
+	{ 0x34C8, 0x40 },
+	{ 0x34C9, 0x00 },
+	{ 0x34CA, 0x40 },
+	{ 0x34CB, 0x00 },
+	{ 0x34CC, 0x40 },
+	{ 0x34CD, 0x00 },
+	{ 0x34CE, 0x40 },
+	{ 0x34CF, 0x00 },
+	{ 0x3584, 0x00 },
+	{ 0x3586, 0x00 },
+	{ 0x3587, 0x01 },
+	{ 0x3588, 0xE6 },
+	{ 0x3589, 0x00 },
+	{ 0x3590, 0x00 },
+	{ 0x3591, 0x00 },
+	{ 0x3594, 0x40 },
+	{ 0x3598, 0x03 },
+	{ 0x3599, 0x00 },
+	{ 0x359A, 0x80 },
+	{ 0x359B, 0x00 },
+	{ 0x359C, 0x00 },
+	{ 0x359D, 0x01 },
+	{ 0x359E, 0x00 },
+	{ 0x359F, 0x02 },
+	{ 0x35A0, 0x00 },
+	{ 0x35A1, 0x04 },
+	{ 0x35A2, 0x20 },
+	{ 0x35A3, 0x00 },
+	{ 0x35A4, 0x40 },
+	{ 0x35A5, 0x00 },
+	{ 0x35A6, 0x80 },
+	{ 0x35A7, 0x00 },
+	{ 0x35A8, 0x00 },
+	{ 0x35A9, 0x01 },
+	{ 0x35AC, 0x80 },
+	{ 0x35AD, 0x00 },
+	{ 0x35AE, 0x00 },
+	{ 0x35AF, 0x01 },
+	{ 0x35B0, 0x00 },
+	{ 0x35B1, 0x02 },
+	{ 0x35B2, 0x00 },
+	{ 0x35B3, 0x04 },
+	{ 0x35B4, 0x02 },
+	{ 0x35B5, 0x00 },
+	{ 0x35B6, 0x04 },
+	{ 0x35B7, 0x00 },
+	{ 0x35B8, 0x08 },
+	{ 0x35B9, 0x00 },
+	{ 0x35BA, 0x10 },
+	{ 0x35BB, 0x00 },
+	{ 0x35C8, 0x00 },
+	{ 0x35C9, 0x01 },
+	{ 0x35CA, 0x00 },
+	{ 0x35CB, 0x04 },
+	{ 0x35CC, 0x00 },
+	{ 0x35CD, 0x10 },
+	{ 0x35CE, 0x00 },
+	{ 0x35CF, 0x40 },
+	{ 0x35D0, 0x00 },
+	{ 0x35D1, 0x0C },
+	{ 0x35D2, 0x00 },
+	{ 0x35D3, 0x0C },
+	{ 0x35D4, 0x00 },
+	{ 0x35D5, 0x0C },
+	{ 0x35D6, 0x00 },
+	{ 0x35D7, 0x0C },
+	{ 0x35D8, 0x00 },
+	{ 0x35D9, 0x00 },
+	{ 0x35DA, 0x08 },
+	{ 0x35DB, 0x00 },
+	{ 0x35DC, 0xD8 },
+	{ 0x35DD, 0x0E },
+	{ 0x35F0, 0x00 },
+	{ 0x35F1, 0x10 },
+	{ 0x35F2, 0x00 },
+	{ 0x35F3, 0x10 },
+	{ 0x35F4, 0x00 },
+	{ 0x35F5, 0x10 },
+	{ 0x35F6, 0x00 },
+	{ 0x35F7, 0x03 },
+	{ 0x35F8, 0x00 },
+	{ 0x35F9, 0x02 },
+	{ 0x35FA, 0x38 },
+	{ 0x35FB, 0x00 },
+	{ 0x35FC, 0xB3 },
+	{ 0x35FD, 0x01 },
+	{ 0x35FE, 0x00 },
+	{ 0x35FF, 0x00 },
+	{ 0x3600, 0x05 },
+	{ 0x3601, 0x06 },
+	{ 0x3604, 0x03 },
+	{ 0x3605, 0x00 },
+	{ 0x3608, 0x03 },
+	{ 0x3609, 0x00 },
+	{ 0x360C, 0x00 },
+	{ 0x360D, 0x00 },
+	{ 0x3610, 0x10 },
+	{ 0x3611, 0x01 },
+	{ 0x3612, 0x00 },
+	{ 0x3613, 0x00 },
+	{ 0x3614, 0x00 },
+	{ 0x3615, 0x00 },
+	{ 0x361C, 0x00 },
+	{ 0x361D, 0x01 },
+	{ 0x361E, 0x00 },
+	{ 0x361F, 0x01 },
+	{ 0x3620, 0x00 },
+	{ 0x3621, 0x00 },
+	{ 0x3622, 0xB0 },
+	{ 0x3623, 0x04 },
+	{ 0x3624, 0xDC },
+	{ 0x3625, 0x05 },
+	{ 0x3626, 0x00 },
+	{ 0x3627, 0x01 },
+	{ 0x3628, 0xFF },
+	{ 0x3629, 0x0F },
+	{ 0x362A, 0x00 },
+	{ 0x362B, 0x10 },
+	{ 0x362C, 0x00 },
+	{ 0x362D, 0x01 },
+	{ 0x3630, 0x41 },
+	{ 0x3631, 0x00 },
+	{ 0x3632, 0x41 },
+	{ 0x3633, 0x00 },
+	{ 0x3634, 0x41 },
+	{ 0x3635, 0x00 },
+	{ 0x3636, 0x41 },
+	{ 0x3637, 0x00 },
+	{ 0x3638, 0x44 },
+	{ 0x3639, 0x00 },
+	{ 0x363A, 0x47 },
+	{ 0x363B, 0x00 },
+	{ 0x363C, 0x47 },
+	{ 0x363D, 0x00 },
+	{ 0x363E, 0x44 },
+	{ 0x363F, 0x00 },
+	{ 0x36C4, 0xFF },
+	{ 0x36C5, 0x0F },
+	{ 0x36C6, 0xFF },
+	{ 0x36C7, 0x0F },
+	{ 0x36C8, 0xFF },
+	{ 0x36C9, 0x0F },
+	{ 0x36CC, 0x00 },
+	{ 0x36CD, 0x00 },
+	{ 0x36CE, 0x00 },
+	{ 0x36CF, 0x00 },
+	{ 0x36D0, 0x00 },
+	{ 0x36D1, 0x00 },
+	{ 0x36D4, 0xFF },
+	{ 0x36D5, 0x0F },
+	{ 0x36D6, 0xFF },
+	{ 0x36D7, 0x0F },
+	{ 0x36D8, 0xFF },
+	{ 0x36D9, 0x0F },
+	{ 0x36DC, 0xFF },
+	{ 0x36DD, 0x0F },
+	{ 0x36DE, 0xFF },
+	{ 0x36DF, 0x0F },
+	{ 0x36E0, 0xFF },
+	{ 0x36E1, 0x0F },
+	{ 0x36E4, 0xFF },
+	{ 0x36E5, 0x0F },
+	{ 0x36E6, 0xFF },
+	{ 0x36E7, 0x0F },
+	{ 0x36E8, 0xFF },
+	{ 0x36E9, 0x0F },
+	{ 0x36EE, 0x00 },
+	{ 0x36EF, 0x00 },
+	{ 0x36F0, 0x00 },
+	{ 0x36F1, 0x80 },
+	{ 0x36F8, 0x01 },
+	{ 0x3700, 0x03 },
+	{ 0x3701, 0x05 },
+	{ 0x3702, 0x03 },
+	{ 0x3703, 0x04 },
+	{ 0x3704, 0x08 },
+	{ 0x3705, 0x03 },
+	{ 0x3706, 0x03 },
+	{ 0x3707, 0x03 },
+	{ 0x3708, 0x03 },
+	{ 0x3709, 0x03 },
+	{ 0x370A, 0x03 },
+	{ 0x370B, 0x03 },
+	{ 0x370C, 0x03 },
+	{ 0x370D, 0x03 },
+	{ 0x370E, 0x0E },
+	{ 0x3718, 0x64 },
+	{ 0x3719, 0x47 },
+	{ 0x371A, 0x36 },
+	{ 0x371B, 0x1E },
+	{ 0x371C, 0x50 },
+	{ 0x371D, 0x41 },
+	{ 0x371E, 0x2F },
+	{ 0x371F, 0x1A },
+	{ 0x3720, 0x95 },
+	{ 0x3721, 0x9D },
+	{ 0x3722, 0xA5 },
+	{ 0x3723, 0xAD },
+	{ 0x3748, 0xA8 },
+	{ 0x3749, 0x9E },
+	{ 0x374A, 0x94 },
+	{ 0x374B, 0x80 },
+	{ 0x37C0, 0x00 },
+	{ 0x37C1, 0x00 },
+	{ 0x37C2, 0x00 },
+	{ 0x37C4, 0x00 },
+	{ 0x37C5, 0x00 },
+	{ 0x37C6, 0x00 },
+	{ 0x37C8, 0x00 },
+	{ 0x37C9, 0x00 },
+	{ 0x37CA, 0x00 },
+	{ 0x37CC, 0x00 },
+	{ 0x37CD, 0x00 },
+	{ 0x37CE, 0x00 },
+	{ 0x37D0, 0x00 },
+	{ 0x37D1, 0x00 },
+	{ 0x37D2, 0x00 },
+	{ 0x37D4, 0x00 },
+	{ 0x37D5, 0x00 },
+	{ 0x37D6, 0x00 },
+	{ 0x37D8, 0x00 },
+	{ 0x37D9, 0x00 },
+	{ 0x37DA, 0x00 },
+	{ 0x37DC, 0x00 },
+	{ 0x37DD, 0x00 },
+	{ 0x37DE, 0x00 },
+	{ 0x37E0, 0x00 },
+	{ 0x37E1, 0x00 },
+	{ 0x37E2, 0x00 },
+	{ 0x37E4, 0x00 },
+	{ 0x37E5, 0x00 },
+	{ 0x37E6, 0x00 },
+	{ 0x37E8, 0x00 },
+	{ 0x37E9, 0x00 },
+	{ 0x37EA, 0x00 },
+	{ 0x37EC, 0x00 },
+	{ 0x37ED, 0x00 },
+	{ 0x37EE, 0x00 },
+	{ 0x37F0, 0x00 },
+	{ 0x37F4, 0x00 },
+	{ 0x37F5, 0x1E },
+	{ 0x37F6, 0x34 },
+	{ 0x37F7, 0x00 },
+	{ 0x37F8, 0xFF },
+	{ 0x37F9, 0xFF },
+	{ 0x37FA, 0x03 },
+	{ 0x37FC, 0x00 },
+	{ 0x37FD, 0x00 },
+	{ 0x37FE, 0x04 },
+	{ 0x3800, 0xFF },
+	{ 0x3801, 0xFF },
+	{ 0x3802, 0x03 },
+	{ 0x3804, 0x00 },
+	{ 0x3805, 0x00 },
+	{ 0x3806, 0x04 },
+	{ 0x3808, 0x00 },
+	{ 0x3809, 0x00 },
+	{ 0x380A, 0x00 },
+	{ 0x380C, 0x00 },
+	{ 0x380D, 0x00 },
+	{ 0x380E, 0x00 },
+	{ 0x3810, 0x00 },
+	{ 0x3811, 0x00 },
+	{ 0x3812, 0x00 },
+	{ 0x3814, 0x00 },
+	{ 0x3815, 0x00 },
+	{ 0x3816, 0x00 },
+	{ 0x3818, 0x00 },
+	{ 0x3819, 0x00 },
+	{ 0x381A, 0x00 },
+	{ 0x381C, 0x00 },
+	{ 0x381D, 0x00 },
+	{ 0x381E, 0x00 },
+	{ 0x3820, 0x00 },
+	{ 0x3821, 0x00 },
+	{ 0x3822, 0x00 },
+	{ 0x3824, 0x00 },
+	{ 0x3825, 0x00 },
+	{ 0x3826, 0x00 },
+	{ 0x3828, 0x00 },
+	{ 0x3829, 0x00 },
+	{ 0x382A, 0x00 },
+	{ 0x382C, 0x00 },
+	{ 0x382D, 0x00 },
+	{ 0x382E, 0x00 },
+	{ 0x3830, 0x00 },
+	{ 0x3831, 0x00 },
+	{ 0x3832, 0x00 },
+	{ 0x3834, 0x00 },
+	{ 0x3835, 0x00 },
+	{ 0x3836, 0x00 },
+	{ 0x3838, 0x47 },
+	{ 0x3839, 0x00 },
+	{ 0x383A, 0x34 },
+	{ 0x383B, 0x00 },
+	{ 0x383C, 0x48 },
+	{ 0x383D, 0x00 },
+	{ 0x383E, 0x39 },
+	{ 0x383F, 0x00 },
+	{ 0x3840, 0x13 },
+	{ 0x3841, 0x00 },
+	{ 0x3842, 0x13 },
+	{ 0x3843, 0x00 },
+	{ 0x3844, 0x1D },
+	{ 0x3845, 0x00 },
+	{ 0x3846, 0x1D },
+	{ 0x3847, 0x00 },
+	{ 0x3848, 0x08 },
+	{ 0x3849, 0x00 },
+	{ 0x384A, 0x07 },
+	{ 0x384B, 0x00 },
+	{ 0x384C, 0x05 },
+	{ 0x384D, 0x00 },
+	{ 0x384E, 0x00 },
+	{ 0x384F, 0x00 },
+	{ 0x3850, 0xFF },
+	{ 0x3851, 0x0F },
+	{ 0x3852, 0x00 },
+	{ 0x3853, 0x10 },
+	{ 0x3854, 0xFF },
+	{ 0x3855, 0x0F },
+	{ 0x3856, 0x00 },
+	{ 0x3857, 0x10 },
+	{ 0x3858, 0xFF },
+	{ 0x3859, 0x0F },
+	{ 0x385A, 0x00 },
+	{ 0x385B, 0x10 },
+	{ 0x385C, 0x02 },
+	{ 0x385D, 0x00 },
+	{ 0x385E, 0x06 },
+	{ 0x385F, 0x00 },
+	{ 0x3860, 0x06 },
+	{ 0x3861, 0x00 },
+	{ 0x3862, 0x08 },
+	{ 0x3863, 0x00 },
+	{ 0x3864, 0x02 },
+	{ 0x3865, 0x00 },
+	{ 0x3870, 0x00 },
+	{ 0x3871, 0x01 },
+	{ 0x38A0, 0x01 },
+	{ 0x38A1, 0x01 },
+	{ 0x38A2, 0x00 },
+	{ 0x38A3, 0x01 },
+	{ 0x38A4, 0x07 },
+	{ 0x38A5, 0x00 },
+	{ 0x38A6, 0x04 },
+	{ 0x38A7, 0x04 },
+	{ 0x38A8, 0x00 },
+	{ 0x38A9, 0x00 },
+	{ 0x38AC, 0x00 },
+	{ 0x38AD, 0x00 },
+	{ 0x38AE, 0x01 },
+	{ 0x38B0, 0x02 },
+	{ 0x38B2, 0x43 },
+	{ 0x38B3, 0x00 },
+	{ 0x38B4, 0x10 },
+	{ 0x38B5, 0x00 },
+	{ 0x38B6, 0x09 },
+	{ 0x38B7, 0x00 },
+	{ 0x38B8, 0x09 },
+	{ 0x38B9, 0x00 },
+	{ 0x38BA, 0x47 },
+	{ 0x38BB, 0x00 },
+	{ 0x38BC, 0x16 },
+	{ 0x38BD, 0x00 },
+	{ 0x38BE, 0x0E },
+	{ 0x38BF, 0x00 },
+	{ 0x38C0, 0x0B },
+	{ 0x38C1, 0x00 },
+	{ 0x38C2, 0x4A },
+	{ 0x38C3, 0x00 },
+	{ 0x38C4, 0x1C },
+	{ 0x38C5, 0x00 },
+	{ 0x38C6, 0x12 },
+	{ 0x38C7, 0x00 },
+	{ 0x38C8, 0x0D },
+	{ 0x38C9, 0x00 },
+	{ 0x38CA, 0x51 },
+	{ 0x38CB, 0x00 },
+	{ 0x38CC, 0x24 },
+	{ 0x38CD, 0x00 },
+	{ 0x38CE, 0x19 },
+	{ 0x38CF, 0x00 },
+	{ 0x38D0, 0x10 },
+	{ 0x38D1, 0x00 },
+	{ 0x38D2, 0x5D },
+	{ 0x38D3, 0x00 },
+	{ 0x38D4, 0x30 },
+	{ 0x38D5, 0x00 },
+	{ 0x38D6, 0x23 },
+	{ 0x38D7, 0x00 },
+	{ 0x38D8, 0x17 },
+	{ 0x38D9, 0x00 },
+	{ 0x38DA, 0x72 },
+	{ 0x38DB, 0x00 },
+	{ 0x38DC, 0x43 },
+	{ 0x38DD, 0x00 },
+	{ 0x38DE, 0x31 },
+	{ 0x38DF, 0x00 },
+	{ 0x38E0, 0x20 },
+	{ 0x38E1, 0x00 },
+	{ 0x38E2, 0x96 },
+	{ 0x38E3, 0x00 },
+	{ 0x38E4, 0x5E },
+	{ 0x38E5, 0x00 },
+	{ 0x38E6, 0x46 },
+	{ 0x38E7, 0x00 },
+	{ 0x38E8, 0x2E },
+	{ 0x38E9, 0x00 },
+	{ 0x38EA, 0xD4 },
+	{ 0x38EB, 0x00 },
+	{ 0x38EC, 0x87 },
+	{ 0x38ED, 0x00 },
+	{ 0x38EE, 0x65 },
+	{ 0x38EF, 0x00 },
+	{ 0x38F0, 0x43 },
+	{ 0x38F1, 0x00 },
+	{ 0x38F2, 0x3F },
+	{ 0x38F3, 0x01 },
+	{ 0x38F4, 0xC4 },
+	{ 0x38F5, 0x00 },
+	{ 0x38F6, 0x94 },
+	{ 0x38F7, 0x00 },
+	{ 0x38F8, 0x64 },
+	{ 0x38F9, 0x00 },
+	{ 0x38FA, 0x00 },
+	{ 0x38FB, 0x01 },
+	{ 0x38FC, 0x00 },
+	{ 0x38FD, 0x01 },
+	{ 0x38FE, 0x00 },
+	{ 0x38FF, 0x01 },
+	{ 0x3900, 0x00 },
+	{ 0x3901, 0x01 },
+	{ 0x3902, 0x60 },
+	{ 0x3903, 0x00 },
+	{ 0x3904, 0x25 },
+	{ 0x3905, 0x00 },
+	{ 0x3906, 0x18 },
+	{ 0x3907, 0x00 },
+	{ 0x3908, 0x10 },
+	{ 0x3909, 0x00 },
+	{ 0x390A, 0xE6 },
+	{ 0x390B, 0x00 },
+	{ 0x390C, 0xD5 },
+	{ 0x390D, 0x00 },
+	{ 0x390E, 0xAA },
+	{ 0x390F, 0x00 },
+	{ 0x3910, 0x85 },
+	{ 0x3911, 0x00 },
+	{ 0x3912, 0xE6 },
+	{ 0x3913, 0x00 },
+	{ 0x3914, 0xD5 },
+	{ 0x3915, 0x00 },
+	{ 0x3916, 0xAA },
+	{ 0x3917, 0x00 },
+	{ 0x3918, 0x85 },
+	{ 0x3919, 0x00 },
+	{ 0x391A, 0xE6 },
+	{ 0x391B, 0x00 },
+	{ 0x391C, 0xD5 },
+	{ 0x391D, 0x00 },
+	{ 0x391E, 0xAA },
+	{ 0x391F, 0x00 },
+	{ 0x3920, 0x85 },
+	{ 0x3921, 0x00 },
+	{ 0x3922, 0x40 },
+	{ 0x3923, 0x00 },
+	{ 0x3924, 0x40 },
+	{ 0x3925, 0x00 },
+	{ 0x3926, 0x40 },
+	{ 0x3927, 0x00 },
+	{ 0x3928, 0x40 },
+	{ 0x3929, 0x00 },
+	{ 0x392A, 0x80 },
+	{ 0x392B, 0x00 },
+	{ 0x392C, 0x80 },
+	{ 0x392D, 0x00 },
+	{ 0x392E, 0x80 },
+	{ 0x392F, 0x00 },
+	{ 0x3930, 0x80 },
+	{ 0x3931, 0x00 },
+	{ 0x3932, 0x4C },
+	{ 0x3933, 0x4C },
+	{ 0x3934, 0x4C },
+	{ 0x3940, 0x01 },
+	{ 0x3941, 0x01 },
+	{ 0x3942, 0x00 },
+	{ 0x3943, 0x01 },
+	{ 0x3944, 0x07 },
+	{ 0x3945, 0x00 },
+	{ 0x3946, 0x04 },
+	{ 0x3947, 0x04 },
+	{ 0x3948, 0x00 },
+	{ 0x3949, 0x00 },
+	{ 0x394C, 0x00 },
+	{ 0x394D, 0x00 },
+	{ 0x394E, 0x01 },
+	{ 0x3950, 0x03 },
+	{ 0x3952, 0x1B },
+	{ 0x3953, 0x00 },
+	{ 0x3954, 0x0C },
+	{ 0x3955, 0x00 },
+	{ 0x3956, 0x09 },
+	{ 0x3957, 0x00 },
+	{ 0x3958, 0x07 },
+	{ 0x3959, 0x00 },
+	{ 0x395A, 0x1D },
+	{ 0x395B, 0x00 },
+	{ 0x395C, 0x0E },
+	{ 0x395D, 0x00 },
+	{ 0x395E, 0x0B },
+	{ 0x395F, 0x00 },
+	{ 0x3960, 0x08 },
+	{ 0x3961, 0x00 },
+	{ 0x3962, 0x1E },
+	{ 0x3963, 0x00 },
+	{ 0x3964, 0x10 },
+	{ 0x3965, 0x00 },
+	{ 0x3966, 0x0C },
+	{ 0x3967, 0x00 },
+	{ 0x3968, 0x09 },
+	{ 0x3969, 0x00 },
+	{ 0x396A, 0x21 },
+	{ 0x396B, 0x00 },
+	{ 0x396C, 0x13 },
+	{ 0x396D, 0x00 },
+	{ 0x396E, 0x0E },
+	{ 0x396F, 0x00 },
+	{ 0x3970, 0x0A },
+	{ 0x3971, 0x00 },
+	{ 0x3972, 0x25 },
+	{ 0x3973, 0x00 },
+	{ 0x3974, 0x19 },
+	{ 0x3975, 0x00 },
+	{ 0x3976, 0x12 },
+	{ 0x3977, 0x00 },
+	{ 0x3978, 0x0D },
+	{ 0x3979, 0x00 },
+	{ 0x397A, 0x2E },
+	{ 0x397B, 0x00 },
+	{ 0x397C, 0x21 },
+	{ 0x397D, 0x00 },
+	{ 0x397E, 0x19 },
+	{ 0x397F, 0x00 },
+	{ 0x3980, 0x11 },
+	{ 0x3981, 0x00 },
+	{ 0x3982, 0x3C },
+	{ 0x3983, 0x00 },
+	{ 0x3984, 0x2F },
+	{ 0x3985, 0x00 },
+	{ 0x3986, 0x23 },
+	{ 0x3987, 0x00 },
+	{ 0x3988, 0x19 },
+	{ 0x3989, 0x00 },
+	{ 0x398A, 0x56 },
+	{ 0x398B, 0x00 },
+	{ 0x398C, 0x44 },
+	{ 0x398D, 0x00 },
+	{ 0x398E, 0x35 },
+	{ 0x398F, 0x00 },
+	{ 0x3990, 0x27 },
+	{ 0x3991, 0x00 },
+	{ 0x3992, 0x84 },
+	{ 0x3993, 0x00 },
+	{ 0x3994, 0x68 },
+	{ 0x3995, 0x00 },
+	{ 0x3996, 0x53 },
+	{ 0x3997, 0x00 },
+	{ 0x3998, 0x40 },
+	{ 0x3999, 0x00 },
+	{ 0x399A, 0x00 },
+	{ 0x399B, 0x01 },
+	{ 0x399C, 0x00 },
+	{ 0x399D, 0x01 },
+	{ 0x399E, 0x00 },
+	{ 0x399F, 0x01 },
+	{ 0x39A0, 0x00 },
+	{ 0x39A1, 0x01 },
+	{ 0x39A2, 0x60 },
+	{ 0x39A3, 0x00 },
+	{ 0x39A4, 0x20 },
+	{ 0x39A5, 0x00 },
+	{ 0x39A6, 0x15 },
+	{ 0x39A7, 0x00 },
+	{ 0x39A8, 0x10 },
+	{ 0x39A9, 0x00 },
+	{ 0x39AA, 0xE6 },
+	{ 0x39AB, 0x00 },
+	{ 0x39AC, 0xD5 },
+	{ 0x39AD, 0x00 },
+	{ 0x39AE, 0xAA },
+	{ 0x39AF, 0x00 },
+	{ 0x39B0, 0x85 },
+	{ 0x39B1, 0x00 },
+	{ 0x39B2, 0xE6 },
+	{ 0x39B3, 0x00 },
+	{ 0x39B4, 0xD5 },
+	{ 0x39B5, 0x00 },
+	{ 0x39B6, 0xAA },
+	{ 0x39B7, 0x00 },
+	{ 0x39B8, 0x85 },
+	{ 0x39B9, 0x00 },
+	{ 0x39BA, 0xE6 },
+	{ 0x39BB, 0x00 },
+	{ 0x39BC, 0xD5 },
+	{ 0x39BD, 0x00 },
+	{ 0x39BE, 0xAA },
+	{ 0x39BF, 0x00 },
+	{ 0x39C0, 0x85 },
+	{ 0x39C1, 0x00 },
+	{ 0x39C2, 0x40 },
+	{ 0x39C3, 0x00 },
+	{ 0x39C4, 0x40 },
+	{ 0x39C5, 0x00 },
+	{ 0x39C6, 0x40 },
+	{ 0x39C7, 0x00 },
+	{ 0x39C8, 0x40 },
+	{ 0x39C9, 0x00 },
+	{ 0x39CA, 0x80 },
+	{ 0x39CB, 0x00 },
+	{ 0x39CC, 0x80 },
+	{ 0x39CD, 0x00 },
+	{ 0x39CE, 0x80 },
+	{ 0x39CF, 0x00 },
+	{ 0x39D0, 0x80 },
+	{ 0x39D1, 0x00 },
+	{ 0x39D2, 0x4C },
+	{ 0x39D3, 0x4C },
+	{ 0x39D4, 0x4C },
+	{ 0x39E0, 0x01 },
+	{ 0x39E1, 0x00 },
+	{ 0x39E4, 0x40 },
+	{ 0x39E5, 0x01 },
+	{ 0x39E6, 0x01 },
+	{ 0x39E8, 0x00 },
+	{ 0x39E9, 0x01 },
+	{ 0x39EA, 0x00 },
+	{ 0x39EB, 0x00 },
+	{ 0x39EC, 0x01 },
+	{ 0x39ED, 0x00 },
+	{ 0x39EE, 0x01 },
+	{ 0x39F0, 0x03 },
+	{ 0x39F1, 0x04 },
+	{ 0x39F2, 0x0E },
+	{ 0x39F4, 0x19 },
+	{ 0x39F5, 0x00 },
+	{ 0x39F6, 0x12 },
+	{ 0x39F7, 0x00 },
+	{ 0x39F8, 0x0D },
+	{ 0x39F9, 0x00 },
+	{ 0x39FA, 0x07 },
+	{ 0x39FB, 0x00 },
+	{ 0x39FC, 0x2B },
+	{ 0x39FD, 0x00 },
+	{ 0x39FE, 0x1B },
+	{ 0x39FF, 0x00 },
+	{ 0x3A00, 0x11 },
+	{ 0x3A01, 0x00 },
+	{ 0x3A02, 0x08 },
+	{ 0x3A03, 0x00 },
+	{ 0x3A04, 0x37 },
+	{ 0x3A05, 0x00 },
+	{ 0x3A06, 0x21 },
+	{ 0x3A07, 0x00 },
+	{ 0x3A08, 0x14 },
+	{ 0x3A09, 0x00 },
+	{ 0x3A0A, 0x09 },
+	{ 0x3A0B, 0x00 },
+	{ 0x3A0C, 0x4A },
+	{ 0x3A0D, 0x00 },
+	{ 0x3A0E, 0x2C },
+	{ 0x3A0F, 0x00 },
+	{ 0x3A10, 0x18 },
+	{ 0x3A11, 0x00 },
+	{ 0x3A12, 0x0B },
+	{ 0x3A13, 0x00 },
+	{ 0x3A14, 0x66 },
+	{ 0x3A15, 0x00 },
+	{ 0x3A16, 0x3B },
+	{ 0x3A17, 0x00 },
+	{ 0x3A18, 0x20 },
+	{ 0x3A19, 0x00 },
+	{ 0x3A1A, 0x0F },
+	{ 0x3A1B, 0x00 },
+	{ 0x3A1C, 0x8E },
+	{ 0x3A1D, 0x00 },
+	{ 0x3A1E, 0x51 },
+	{ 0x3A1F, 0x00 },
+	{ 0x3A20, 0x2B },
+	{ 0x3A21, 0x00 },
+	{ 0x3A22, 0x14 },
+	{ 0x3A23, 0x00 },
+	{ 0x3A24, 0xC8 },
+	{ 0x3A25, 0x00 },
+	{ 0x3A26, 0x72 },
+	{ 0x3A27, 0x00 },
+	{ 0x3A28, 0x3C },
+	{ 0x3A29, 0x00 },
+	{ 0x3A2A, 0x1B },
+	{ 0x3A2B, 0x00 },
+	{ 0x3A2C, 0x19 },
+	{ 0x3A2D, 0x01 },
+	{ 0x3A2E, 0xA0 },
+	{ 0x3A2F, 0x00 },
+	{ 0x3A30, 0x54 },
+	{ 0x3A31, 0x00 },
+	{ 0x3A32, 0x25 },
+	{ 0x3A33, 0x00 },
+	{ 0x3A34, 0x8D },
+	{ 0x3A35, 0x01 },
+	{ 0x3A36, 0xE1 },
+	{ 0x3A37, 0x00 },
+	{ 0x3A38, 0x76 },
+	{ 0x3A39, 0x00 },
+	{ 0x3A3A, 0x35 },
+	{ 0x3A3B, 0x00 },
+	{ 0x3A3C, 0x00 },
+	{ 0x3A3D, 0x01 },
+	{ 0x3A3E, 0x00 },
+	{ 0x3A3F, 0x01 },
+	{ 0x3A40, 0x00 },
+	{ 0x3A41, 0x01 },
+	{ 0x3A42, 0x00 },
+	{ 0x3A43, 0x01 },
+	{ 0x3A44, 0x70 },
+	{ 0x3A45, 0x00 },
+	{ 0x3A46, 0x25 },
+	{ 0x3A47, 0x00 },
+	{ 0x3A48, 0x18 },
+	{ 0x3A49, 0x00 },
+	{ 0x3A4A, 0x10 },
+	{ 0x3A4B, 0x00 },
+	{ 0x3A4C, 0xE6 },
+	{ 0x3A4D, 0x00 },
+	{ 0x3A4E, 0xD5 },
+	{ 0x3A4F, 0x00 },
+	{ 0x3A50, 0xAA },
+	{ 0x3A51, 0x00 },
+	{ 0x3A52, 0x85 },
+	{ 0x3A53, 0x00 },
+	{ 0x3A54, 0xE6 },
+	{ 0x3A55, 0x00 },
+	{ 0x3A56, 0xD5 },
+	{ 0x3A57, 0x00 },
+	{ 0x3A58, 0xAA },
+	{ 0x3A59, 0x00 },
+	{ 0x3A5A, 0x85 },
+	{ 0x3A5B, 0x00 },
+	{ 0x3A5C, 0xE6 },
+	{ 0x3A5D, 0x00 },
+	{ 0x3A5E, 0xD5 },
+	{ 0x3A5F, 0x00 },
+	{ 0x3A60, 0xAA },
+	{ 0x3A61, 0x00 },
+	{ 0x3A62, 0x85 },
+	{ 0x3A63, 0x00 },
+	{ 0x3A64, 0x19 },
+	{ 0x3A65, 0x00 },
+	{ 0x3A66, 0x12 },
+	{ 0x3A67, 0x00 },
+	{ 0x3A68, 0x0D },
+	{ 0x3A69, 0x00 },
+	{ 0x3A6A, 0x07 },
+	{ 0x3A6B, 0x00 },
+	{ 0x3A6C, 0x0C },
+	{ 0x3A6D, 0x00 },
+	{ 0x3A6E, 0x07 },
+	{ 0x3A6F, 0x00 },
+	{ 0x3A70, 0x05 },
+	{ 0x3A71, 0x00 },
+	{ 0x3A72, 0x04 },
+	{ 0x3A73, 0x00 },
+	{ 0x3A74, 0x1B },
+	{ 0x3A75, 0x00 },
+	{ 0x3A76, 0x15 },
+	{ 0x3A77, 0x00 },
+	{ 0x3A78, 0x0C },
+	{ 0x3A79, 0x00 },
+	{ 0x3A7A, 0x08 },
+	{ 0x3A7B, 0x00 },
+	{ 0x3A7C, 0x80 },
+	{ 0x3A7D, 0x00 },
+	{ 0x3A7E, 0x80 },
+	{ 0x3A7F, 0x00 },
+	{ 0x3A80, 0x80 },
+	{ 0x3A81, 0x00 },
+	{ 0x3A82, 0x80 },
+	{ 0x3A83, 0x00 },
+	{ 0x3A84, 0x09 },
+	{ 0x3A85, 0x00 },
+	{ 0x3A86, 0x06 },
+	{ 0x3A87, 0x00 },
+	{ 0x3A88, 0x04 },
+	{ 0x3A89, 0x00 },
+	{ 0x3A8A, 0x03 },
+	{ 0x3A8B, 0x00 },
+	{ 0x3A8C, 0xFA },
+	{ 0x3A8D, 0x00 },
+	{ 0x3A8E, 0xC8 },
+	{ 0x3A8F, 0x00 },
+	{ 0x3A90, 0x96 },
+	{ 0x3A91, 0x00 },
+	{ 0x3A92, 0x64 },
+	{ 0x3A93, 0x00 },
+	{ 0x3A94, 0xE1 },
+	{ 0x3A95, 0x00 },
+	{ 0x3A96, 0xC8 },
+	{ 0x3A97, 0x00 },
+	{ 0x3A98, 0x96 },
+	{ 0x3A99, 0x00 },
+	{ 0x3A9A, 0x64 },
+	{ 0x3A9B, 0x00 },
+	{ 0x3A9C, 0x08 },
+	{ 0x3A9D, 0x10 },
+	{ 0x3A9E, 0x4C },
+	{ 0x3A9F, 0x4C },
+	{ 0x3AA0, 0x4C },
+	{ 0x3AA1, 0x04 },
+	{ 0x3AA2, 0x04 },
+	{ 0x3AC0, 0x01 },
+	{ 0x3AC4, 0x81 },
+	{ 0x3AC5, 0x00 },
+	{ 0x3AC6, 0x00 },
+	{ 0x3AC7, 0x00 },
+	{ 0x3AC8, 0x00 },
+	{ 0x3AC9, 0x00 },
+	{ 0x3ACA, 0x00 },
+	{ 0x3ACB, 0x00 },
+	{ 0x3ACC, 0x02 },
+	{ 0x3ACD, 0x00 },
+	{ 0x3ACE, 0x81 },
+	{ 0x3ACF, 0x00 },
+	{ 0x3AD0, 0x00 },
+	{ 0x3AD1, 0x00 },
+	{ 0x3AD2, 0xFD },
+	{ 0x3AD3, 0x03 },
+	{ 0x3AD4, 0x02 },
+	{ 0x3AD5, 0x00 },
+	{ 0x3AD6, 0x00 },
+	{ 0x3AD7, 0x00 },
+	{ 0x3AD8, 0x81 },
+	{ 0x3AD9, 0x00 },
+	{ 0x3ADA, 0xFD },
+	{ 0x3ADB, 0x03 },
+	{ 0x3ADC, 0xFF },
+	{ 0x3ADD, 0x03 },
+	{ 0x3ADE, 0x01 },
+	{ 0x3ADF, 0x00 },
+	{ 0x3AE0, 0x01 },
+	{ 0x3AE1, 0x00 },
+	{ 0x3AE2, 0x7E },
+	{ 0x3AE3, 0x00 },
+	{ 0x3AF4, 0x00 },
+	{ 0x3AF6, 0x40 },
+	{ 0x3AF7, 0x1E },
+	{ 0x3AF8, 0x00 },
+	{ 0x3AFA, 0x00 },
+	{ 0x3AFB, 0x00 },
+	{ 0x3AFC, 0x00 },
+	{ 0x3AFD, 0x00 },
+	{ 0x3AFE, 0x00 },
+	{ 0x3AFF, 0x00 },
+	{ 0x3B00, 0x00 },
+	{ 0x3B01, 0x00 },
+	{ 0x3B02, 0x00 },
+	{ 0x3B03, 0x00 },
+	{ 0x3B04, 0x00 },
+	{ 0x3B05, 0x00 },
+	{ 0x3B06, 0x00 },
+	{ 0x3B07, 0x00 },
+	{ 0x3B08, 0x00 },
+	{ 0x3B09, 0x00 },
+	{ 0x3B0A, 0x00 },
+	{ 0x3B0B, 0x00 },
+	{ 0x3B0C, 0x00 },
+	{ 0x3B0D, 0x00 },
+	{ 0x3B0E, 0x00 },
+	{ 0x3B0F, 0x00 },
+	{ 0x3B10, 0x00 },
+	{ 0x3B11, 0x00 },
+	{ 0x3B12, 0x00 },
+	{ 0x3B13, 0x00 },
+	{ 0x3B14, 0x00 },
+	{ 0x3B15, 0x00 },
+	{ 0x3B16, 0x00 },
+	{ 0x3B17, 0x00 },
+	{ 0x3B18, 0x00 },
+	{ 0x3B19, 0x00 },
+	{ 0x3B1A, 0x00 },
+	{ 0x3B1B, 0x00 },
+	{ 0x3B1C, 0x00 },
+	{ 0x3B1D, 0x00 },
+	{ 0x3B1E, 0x00 },
+	{ 0x3B1F, 0x00 },
+	{ 0x3B20, 0x00 },
+	{ 0x3B21, 0x00 },
+	{ 0x3B22, 0x00 },
+	{ 0x3B23, 0x00 },
+	{ 0x3B24, 0x00 },
+	{ 0x3B25, 0x00 },
+	{ 0x3B26, 0x00 },
+	{ 0x3B27, 0x00 },
+	{ 0x3B28, 0x00 },
+	{ 0x3B29, 0x00 },
+	{ 0x3B2A, 0x00 },
+	{ 0x3B2C, 0x00 },
+	{ 0x3B2E, 0x00 },
+	{ 0x3B30, 0x00 },
+	{ 0x3B32, 0x0C },
+	{ 0x4000, 0xAF },
+	{ 0x4001, 0xA7 },
+	{ 0x4002, 0xA8 },
+	{ 0x4003, 0xA5 },
+	{ 0x4004, 0x98 },
+	{ 0x4005, 0x93 },
+	{ 0x4006, 0x94 },
+	{ 0x4007, 0x93 },
+	{ 0x4008, 0x8E },
+	{ 0x4009, 0x8C },
+	{ 0x400A, 0x8C },
+	{ 0x400B, 0x8C },
+	{ 0x400C, 0x89 },
+	{ 0x400D, 0x88 },
+	{ 0x400E, 0x89 },
+	{ 0x400F, 0x89 },
+	{ 0x4010, 0x87 },
+	{ 0x4011, 0x87 },
+	{ 0x4012, 0x87 },
+	{ 0x4013, 0x86 },
+	{ 0x4014, 0x88 },
+	{ 0x4015, 0x87 },
+	{ 0x4016, 0x87 },
+	{ 0x4017, 0x87 },
+	{ 0x4018, 0x8B },
+	{ 0x4019, 0x89 },
+	{ 0x401A, 0x89 },
+	{ 0x401B, 0x8A },
+	{ 0x401C, 0x92 },
+	{ 0x401D, 0x8F },
+	{ 0x401E, 0x8F },
+	{ 0x401F, 0x8F },
+	{ 0x4020, 0xA2 },
+	{ 0x4021, 0x9C },
+	{ 0x4022, 0x9B },
+	{ 0x4023, 0x9C },
+	{ 0x4024, 0xA1 },
+	{ 0x4025, 0x9A },
+	{ 0x4026, 0x9B },
+	{ 0x4027, 0x99 },
+	{ 0x4028, 0x94 },
+	{ 0x4029, 0x90 },
+	{ 0x402A, 0x90 },
+	{ 0x402B, 0x90 },
+	{ 0x402C, 0x8B },
+	{ 0x402D, 0x89 },
+	{ 0x402E, 0x89 },
+	{ 0x402F, 0x89 },
+	{ 0x4030, 0x86 },
+	{ 0x4031, 0x85 },
+	{ 0x4032, 0x86 },
+	{ 0x4033, 0x85 },
+	{ 0x4034, 0x84 },
+	{ 0x4035, 0x84 },
+	{ 0x4036, 0x84 },
+	{ 0x4037, 0x84 },
+	{ 0x4038, 0x85 },
+	{ 0x4039, 0x85 },
+	{ 0x403A, 0x85 },
+	{ 0x403B, 0x85 },
+	{ 0x403C, 0x88 },
+	{ 0x403D, 0x87 },
+	{ 0x403E, 0x87 },
+	{ 0x403F, 0x87 },
+	{ 0x4040, 0x8E },
+	{ 0x4041, 0x8C },
+	{ 0x4042, 0x8C },
+	{ 0x4043, 0x8C },
+	{ 0x4044, 0x98 },
+	{ 0x4045, 0x93 },
+	{ 0x4046, 0x93 },
+	{ 0x4047, 0x94 },
+	{ 0x4048, 0x9D },
+	{ 0x4049, 0x96 },
+	{ 0x404A, 0x97 },
+	{ 0x404B, 0x96 },
+	{ 0x404C, 0x91 },
+	{ 0x404D, 0x8C },
+	{ 0x404E, 0x8D },
+	{ 0x404F, 0x8C },
+	{ 0x4050, 0x89 },
+	{ 0x4051, 0x86 },
+	{ 0x4052, 0x87 },
+	{ 0x4053, 0x86 },
+	{ 0x4054, 0x83 },
+	{ 0x4055, 0x82 },
+	{ 0x4056, 0x82 },
+	{ 0x4057, 0x82 },
+	{ 0x4058, 0x80 },
+	{ 0x4059, 0x80 },
+	{ 0x405A, 0x80 },
+	{ 0x405B, 0x80 },
+	{ 0x405C, 0x82 },
+	{ 0x405D, 0x82 },
+	{ 0x405E, 0x82 },
+	{ 0x405F, 0x82 },
+	{ 0x4060, 0x86 },
+	{ 0x4061, 0x85 },
+	{ 0x4062, 0x85 },
+	{ 0x4063, 0x85 },
+	{ 0x4064, 0x8B },
+	{ 0x4065, 0x8A },
+	{ 0x4066, 0x89 },
+	{ 0x4067, 0x89 },
+	{ 0x4068, 0x94 },
+	{ 0x4069, 0x91 },
+	{ 0x406A, 0x90 },
+	{ 0x406B, 0x91 },
+	{ 0x406C, 0x9E },
+	{ 0x406D, 0x95 },
+	{ 0x406E, 0x96 },
+	{ 0x406F, 0x95 },
+	{ 0x4070, 0x91 },
+	{ 0x4071, 0x8C },
+	{ 0x4072, 0x8C },
+	{ 0x4073, 0x8C },
+	{ 0x4074, 0x89 },
+	{ 0x4075, 0x86 },
+	{ 0x4076, 0x86 },
+	{ 0x4077, 0x86 },
+	{ 0x4078, 0x83 },
+	{ 0x4079, 0x82 },
+	{ 0x407A, 0x82 },
+	{ 0x407B, 0x82 },
+	{ 0x407C, 0x80 },
+	{ 0x407D, 0x80 },
+	{ 0x407E, 0x80 },
+	{ 0x407F, 0x80 },
+	{ 0x4080, 0x82 },
+	{ 0x4081, 0x81 },
+	{ 0x4082, 0x81 },
+	{ 0x4083, 0x81 },
+	{ 0x4084, 0x85 },
+	{ 0x4085, 0x85 },
+	{ 0x4086, 0x85 },
+	{ 0x4087, 0x84 },
+	{ 0x4088, 0x8B },
+	{ 0x4089, 0x8A },
+	{ 0x408A, 0x89 },
+	{ 0x408B, 0x89 },
+	{ 0x408C, 0x93 },
+	{ 0x408D, 0x90 },
+	{ 0x408E, 0x8F },
+	{ 0x408F, 0x8F },
+	{ 0x4090, 0xA3 },
+	{ 0x4091, 0x99 },
+	{ 0x4092, 0x9A },
+	{ 0x4093, 0x99 },
+	{ 0x4094, 0x95 },
+	{ 0x4095, 0x8F },
+	{ 0x4096, 0x8F },
+	{ 0x4097, 0x8F },
+	{ 0x4098, 0x8B },
+	{ 0x4099, 0x87 },
+	{ 0x409A, 0x87 },
+	{ 0x409B, 0x87 },
+	{ 0x409C, 0x86 },
+	{ 0x409D, 0x84 },
+	{ 0x409E, 0x84 },
+	{ 0x409F, 0x84 },
+	{ 0x40A0, 0x84 },
+	{ 0x40A1, 0x83 },
+	{ 0x40A2, 0x83 },
+	{ 0x40A3, 0x82 },
+	{ 0x40A4, 0x84 },
+	{ 0x40A5, 0x84 },
+	{ 0x40A6, 0x83 },
+	{ 0x40A7, 0x83 },
+	{ 0x40A8, 0x88 },
+	{ 0x40A9, 0x87 },
+	{ 0x40AA, 0x86 },
+	{ 0x40AB, 0x86 },
+	{ 0x40AC, 0x8E },
+	{ 0x40AD, 0x8C },
+	{ 0x40AE, 0x8C },
+	{ 0x40AF, 0x8B },
+	{ 0x40B0, 0x9A },
+	{ 0x40B1, 0x96 },
+	{ 0x40B2, 0x96 },
+	{ 0x40B3, 0x95 },
+	{ 0x40B4, 0xBA },
+	{ 0x40B5, 0xAC },
+	{ 0x40B6, 0xAD },
+	{ 0x40B7, 0xAC },
+	{ 0x40B8, 0x99 },
+	{ 0x40B9, 0x90 },
+	{ 0x40BA, 0x91 },
+	{ 0x40BB, 0x90 },
+	{ 0x40BC, 0x90 },
+	{ 0x40BD, 0x8A },
+	{ 0x40BE, 0x8A },
+	{ 0x40BF, 0x8A },
+	{ 0x40C0, 0x89 },
+	{ 0x40C1, 0x86 },
+	{ 0x40C2, 0x86 },
+	{ 0x40C3, 0x87 },
+	{ 0x40C4, 0x87 },
+	{ 0x40C5, 0x85 },
+	{ 0x40C6, 0x85 },
+	{ 0x40C7, 0x85 },
+	{ 0x40C8, 0x87 },
+	{ 0x40C9, 0x86 },
+	{ 0x40CA, 0x85 },
+	{ 0x40CB, 0x85 },
+	{ 0x40CC, 0x8A },
+	{ 0x40CD, 0x88 },
+	{ 0x40CE, 0x88 },
+	{ 0x40CF, 0x87 },
+	{ 0x40D0, 0x92 },
+	{ 0x40D1, 0x8F },
+	{ 0x40D2, 0x8E },
+	{ 0x40D3, 0x8E },
+	{ 0x40D4, 0xA2 },
+	{ 0x40D5, 0x9D },
+	{ 0x40D6, 0x9D },
+	{ 0x40D7, 0x9B },
+	{ 0x4100, 0x80 },
+	{ 0x4101, 0x80 },
+	{ 0x4102, 0x80 },
+	{ 0x4103, 0x80 },
+	{ 0x4104, 0x80 },
+	{ 0x4105, 0x80 },
+	{ 0x4106, 0x80 },
+	{ 0x4107, 0x80 },
+	{ 0x4108, 0x80 },
+	{ 0x4109, 0x80 },
+	{ 0x410A, 0x80 },
+	{ 0x410B, 0x80 },
+	{ 0x410C, 0x80 },
+	{ 0x410D, 0x80 },
+	{ 0x410E, 0x80 },
+	{ 0x410F, 0x80 },
+	{ 0x4110, 0x80 },
+	{ 0x4111, 0x80 },
+	{ 0x4112, 0x80 },
+	{ 0x4113, 0x80 },
+	{ 0x4114, 0x80 },
+	{ 0x4115, 0x80 },
+	{ 0x4116, 0x80 },
+	{ 0x4117, 0x80 },
+	{ 0x4118, 0x80 },
+	{ 0x4119, 0x80 },
+	{ 0x411A, 0x80 },
+	{ 0x411B, 0x80 },
+	{ 0x411C, 0x80 },
+	{ 0x411D, 0x80 },
+	{ 0x411E, 0x80 },
+	{ 0x411F, 0x80 },
+	{ 0x4120, 0x80 },
+	{ 0x4121, 0x80 },
+	{ 0x4122, 0x80 },
+	{ 0x4123, 0x80 },
+	{ 0x4124, 0x80 },
+	{ 0x4125, 0x80 },
+	{ 0x4126, 0x80 },
+	{ 0x4127, 0x80 },
+	{ 0x4128, 0x80 },
+	{ 0x4129, 0x80 },
+	{ 0x412A, 0x80 },
+	{ 0x412B, 0x80 },
+	{ 0x412C, 0x80 },
+	{ 0x412D, 0x80 },
+	{ 0x412E, 0x80 },
+	{ 0x412F, 0x80 },
+	{ 0x4130, 0x80 },
+	{ 0x4131, 0x80 },
+	{ 0x4132, 0x80 },
+	{ 0x4133, 0x80 },
+	{ 0x4134, 0x80 },
+	{ 0x4135, 0x80 },
+	{ 0x4136, 0x80 },
+	{ 0x4137, 0x80 },
+	{ 0x4138, 0x80 },
+	{ 0x4139, 0x80 },
+	{ 0x413A, 0x80 },
+	{ 0x413B, 0x80 },
+	{ 0x413C, 0x80 },
+	{ 0x413D, 0x80 },
+	{ 0x413E, 0x80 },
+	{ 0x413F, 0x80 },
+	{ 0x4140, 0x80 },
+	{ 0x4141, 0x80 },
+	{ 0x4142, 0x80 },
+	{ 0x4143, 0x80 },
+	{ 0x4144, 0x80 },
+	{ 0x4145, 0x80 },
+	{ 0x4146, 0x80 },
+	{ 0x4147, 0x80 },
+	{ 0x4148, 0x80 },
+	{ 0x4149, 0x80 },
+	{ 0x414A, 0x80 },
+	{ 0x414B, 0x80 },
+	{ 0x414C, 0x80 },
+	{ 0x414D, 0x80 },
+	{ 0x414E, 0x80 },
+	{ 0x414F, 0x80 },
+	{ 0x4150, 0x80 },
+	{ 0x4151, 0x80 },
+	{ 0x4152, 0x80 },
+	{ 0x4153, 0x80 },
+	{ 0x4154, 0x80 },
+	{ 0x4155, 0x80 },
+	{ 0x4156, 0x80 },
+	{ 0x4157, 0x80 },
+	{ 0x4158, 0x80 },
+	{ 0x4159, 0x80 },
+	{ 0x415A, 0x80 },
+	{ 0x415B, 0x80 },
+	{ 0x415C, 0x80 },
+	{ 0x415D, 0x80 },
+	{ 0x415E, 0x80 },
+	{ 0x415F, 0x80 },
+	{ 0x4160, 0x80 },
+	{ 0x4161, 0x80 },
+	{ 0x4162, 0x80 },
+	{ 0x4163, 0x80 },
+	{ 0x4164, 0x80 },
+	{ 0x4165, 0x80 },
+	{ 0x4166, 0x80 },
+	{ 0x4167, 0x80 },
+	{ 0x4168, 0x80 },
+	{ 0x4169, 0x80 },
+	{ 0x416A, 0x80 },
+	{ 0x416B, 0x80 },
+	{ 0x416C, 0x80 },
+	{ 0x416D, 0x80 },
+	{ 0x416E, 0x80 },
+	{ 0x416F, 0x80 },
+	{ 0x4170, 0x80 },
+	{ 0x4171, 0x80 },
+	{ 0x4172, 0x80 },
+	{ 0x4173, 0x80 },
+	{ 0x4174, 0x80 },
+	{ 0x4175, 0x80 },
+	{ 0x4176, 0x80 },
+	{ 0x4177, 0x80 },
+	{ 0x4178, 0x80 },
+	{ 0x4179, 0x80 },
+	{ 0x417A, 0x80 },
+	{ 0x417B, 0x80 },
+	{ 0x417C, 0x80 },
+	{ 0x417D, 0x80 },
+	{ 0x417E, 0x80 },
+	{ 0x417F, 0x80 },
+	{ 0x4180, 0x80 },
+	{ 0x4181, 0x80 },
+	{ 0x4182, 0x80 },
+	{ 0x4183, 0x80 },
+	{ 0x4184, 0x80 },
+	{ 0x4185, 0x80 },
+	{ 0x4186, 0x80 },
+	{ 0x4187, 0x80 },
+	{ 0x4188, 0x80 },
+	{ 0x4189, 0x80 },
+	{ 0x418A, 0x80 },
+	{ 0x418B, 0x80 },
+	{ 0x418C, 0x80 },
+	{ 0x418D, 0x80 },
+	{ 0x418E, 0x80 },
+	{ 0x418F, 0x80 },
+	{ 0x4190, 0x80 },
+	{ 0x4191, 0x80 },
+	{ 0x4192, 0x80 },
+	{ 0x4193, 0x80 },
+	{ 0x4194, 0x80 },
+	{ 0x4195, 0x80 },
+	{ 0x4196, 0x80 },
+	{ 0x4197, 0x80 },
+	{ 0x4198, 0x80 },
+	{ 0x4199, 0x80 },
+	{ 0x419A, 0x80 },
+	{ 0x419B, 0x80 },
+	{ 0x419C, 0x80 },
+	{ 0x419D, 0x80 },
+	{ 0x419E, 0x80 },
+	{ 0x419F, 0x80 },
+	{ 0x41A0, 0x80 },
+	{ 0x41A1, 0x80 },
+	{ 0x41A2, 0x80 },
+	{ 0x41A3, 0x80 },
+	{ 0x41A4, 0x80 },
+	{ 0x41A5, 0x80 },
+	{ 0x41A6, 0x80 },
+	{ 0x41A7, 0x80 },
+	{ 0x41A8, 0x80 },
+	{ 0x41A9, 0x80 },
+	{ 0x41AA, 0x80 },
+	{ 0x41AB, 0x80 },
+	{ 0x41AC, 0x80 },
+	{ 0x41AD, 0x80 },
+	{ 0x41AE, 0x80 },
+	{ 0x41AF, 0x80 },
+	{ 0x41B0, 0x80 },
+	{ 0x41B1, 0x80 },
+	{ 0x41B2, 0x80 },
+	{ 0x41B3, 0x80 },
+	{ 0x41B4, 0x80 },
+	{ 0x41B5, 0x80 },
+	{ 0x41B6, 0x80 },
+	{ 0x41B7, 0x80 },
+	{ 0x41B8, 0x80 },
+	{ 0x41B9, 0x80 },
+	{ 0x41BA, 0x80 },
+	{ 0x41BB, 0x80 },
+	{ 0x41BC, 0x80 },
+	{ 0x41BD, 0x80 },
+	{ 0x41BE, 0x80 },
+	{ 0x41BF, 0x80 },
+	{ 0x41C0, 0x80 },
+	{ 0x41C1, 0x80 },
+	{ 0x41C2, 0x80 },
+	{ 0x41C3, 0x80 },
+	{ 0x41C4, 0x80 },
+	{ 0x41C5, 0x80 },
+	{ 0x41C6, 0x80 },
+	{ 0x41C7, 0x80 },
+	{ 0x41C8, 0x80 },
+	{ 0x41C9, 0x80 },
+	{ 0x41CA, 0x80 },
+	{ 0x41CB, 0x80 },
+	{ 0x41CC, 0x80 },
+	{ 0x41CD, 0x80 },
+	{ 0x41CE, 0x80 },
+	{ 0x41CF, 0x80 },
+	{ 0x41D0, 0x80 },
+	{ 0x41D1, 0x80 },
+	{ 0x41D2, 0x80 },
+	{ 0x41D3, 0x80 },
+	{ 0x41D4, 0x80 },
+	{ 0x41D5, 0x80 },
+	{ 0x41D6, 0x80 },
+	{ 0x41D7, 0x80 },
+	{ 0x4200, 0x80 },
+	{ 0x4201, 0x80 },
+	{ 0x4202, 0x80 },
+	{ 0x4203, 0x80 },
+	{ 0x4204, 0x80 },
+	{ 0x4205, 0x80 },
+	{ 0x4206, 0x80 },
+	{ 0x4207, 0x80 },
+	{ 0x4208, 0x80 },
+	{ 0x4209, 0x80 },
+	{ 0x420A, 0x80 },
+	{ 0x420B, 0x80 },
+	{ 0x420C, 0x80 },
+	{ 0x420D, 0x80 },
+	{ 0x420E, 0x80 },
+	{ 0x420F, 0x80 },
+	{ 0x4210, 0x80 },
+	{ 0x4211, 0x80 },
+	{ 0x4212, 0x80 },
+	{ 0x4213, 0x80 },
+	{ 0x4214, 0x80 },
+	{ 0x4215, 0x80 },
+	{ 0x4216, 0x80 },
+	{ 0x4217, 0x80 },
+	{ 0x4218, 0x80 },
+	{ 0x4219, 0x80 },
+	{ 0x421A, 0x80 },
+	{ 0x421B, 0x80 },
+	{ 0x421C, 0x80 },
+	{ 0x421D, 0x80 },
+	{ 0x421E, 0x80 },
+	{ 0x421F, 0x80 },
+	{ 0x4220, 0x80 },
+	{ 0x4221, 0x80 },
+	{ 0x4222, 0x80 },
+	{ 0x4223, 0x80 },
+	{ 0x4224, 0x80 },
+	{ 0x4225, 0x80 },
+	{ 0x4226, 0x80 },
+	{ 0x4227, 0x80 },
+	{ 0x4228, 0x80 },
+	{ 0x4229, 0x80 },
+	{ 0x422A, 0x80 },
+	{ 0x422B, 0x80 },
+	{ 0x422C, 0x80 },
+	{ 0x422D, 0x80 },
+	{ 0x422E, 0x80 },
+	{ 0x422F, 0x80 },
+	{ 0x4230, 0x80 },
+	{ 0x4231, 0x80 },
+	{ 0x4232, 0x80 },
+	{ 0x4233, 0x80 },
+	{ 0x4234, 0x80 },
+	{ 0x4235, 0x80 },
+	{ 0x4236, 0x80 },
+	{ 0x4237, 0x80 },
+	{ 0x4238, 0x80 },
+	{ 0x4239, 0x80 },
+	{ 0x423A, 0x80 },
+	{ 0x423B, 0x80 },
+	{ 0x423C, 0x80 },
+	{ 0x423D, 0x80 },
+	{ 0x423E, 0x80 },
+	{ 0x423F, 0x80 },
+	{ 0x4240, 0x80 },
+	{ 0x4241, 0x80 },
+	{ 0x4242, 0x80 },
+	{ 0x4243, 0x80 },
+	{ 0x4244, 0x80 },
+	{ 0x4245, 0x80 },
+	{ 0x4246, 0x80 },
+	{ 0x4247, 0x80 },
+	{ 0x4248, 0x80 },
+	{ 0x4249, 0x80 },
+	{ 0x424A, 0x80 },
+	{ 0x424B, 0x80 },
+	{ 0x424C, 0x80 },
+	{ 0x424D, 0x80 },
+	{ 0x424E, 0x80 },
+	{ 0x424F, 0x80 },
+	{ 0x4250, 0x80 },
+	{ 0x4251, 0x80 },
+	{ 0x4252, 0x80 },
+	{ 0x4253, 0x80 },
+	{ 0x4254, 0x80 },
+	{ 0x4255, 0x80 },
+	{ 0x4256, 0x80 },
+	{ 0x4257, 0x80 },
+	{ 0x4258, 0x80 },
+	{ 0x4259, 0x80 },
+	{ 0x425A, 0x80 },
+	{ 0x425B, 0x80 },
+	{ 0x425C, 0x80 },
+	{ 0x425D, 0x80 },
+	{ 0x425E, 0x80 },
+	{ 0x425F, 0x80 },
+	{ 0x4260, 0x80 },
+	{ 0x4261, 0x80 },
+	{ 0x4262, 0x80 },
+	{ 0x4263, 0x80 },
+	{ 0x4264, 0x80 },
+	{ 0x4265, 0x80 },
+	{ 0x4266, 0x80 },
+	{ 0x4267, 0x80 },
+	{ 0x4268, 0x80 },
+	{ 0x4269, 0x80 },
+	{ 0x426A, 0x80 },
+	{ 0x426B, 0x80 },
+	{ 0x426C, 0x80 },
+	{ 0x426D, 0x80 },
+	{ 0x426E, 0x80 },
+	{ 0x426F, 0x80 },
+	{ 0x4270, 0x80 },
+	{ 0x4271, 0x80 },
+	{ 0x4272, 0x80 },
+	{ 0x4273, 0x80 },
+	{ 0x4274, 0x80 },
+	{ 0x4275, 0x80 },
+	{ 0x4276, 0x80 },
+	{ 0x4277, 0x80 },
+	{ 0x4278, 0x80 },
+	{ 0x4279, 0x80 },
+	{ 0x427A, 0x80 },
+	{ 0x427B, 0x80 },
+	{ 0x427C, 0x80 },
+	{ 0x427D, 0x80 },
+	{ 0x427E, 0x80 },
+	{ 0x427F, 0x80 },
+	{ 0x4280, 0x80 },
+	{ 0x4281, 0x80 },
+	{ 0x4282, 0x80 },
+	{ 0x4283, 0x80 },
+	{ 0x4284, 0x80 },
+	{ 0x4285, 0x80 },
+	{ 0x4286, 0x80 },
+	{ 0x4287, 0x80 },
+	{ 0x4288, 0x80 },
+	{ 0x4289, 0x80 },
+	{ 0x428A, 0x80 },
+	{ 0x428B, 0x80 },
+	{ 0x428C, 0x80 },
+	{ 0x428D, 0x80 },
+	{ 0x428E, 0x80 },
+	{ 0x428F, 0x80 },
+	{ 0x4290, 0x80 },
+	{ 0x4291, 0x80 },
+	{ 0x4292, 0x80 },
+	{ 0x4293, 0x80 },
+	{ 0x4294, 0x80 },
+	{ 0x4295, 0x80 },
+	{ 0x4296, 0x80 },
+	{ 0x4297, 0x80 },
+	{ 0x4298, 0x80 },
+	{ 0x4299, 0x80 },
+	{ 0x429A, 0x80 },
+	{ 0x429B, 0x80 },
+	{ 0x429C, 0x80 },
+	{ 0x429D, 0x80 },
+	{ 0x429E, 0x80 },
+	{ 0x429F, 0x80 },
+	{ 0x42A0, 0x80 },
+	{ 0x42A1, 0x80 },
+	{ 0x42A2, 0x80 },
+	{ 0x42A3, 0x80 },
+	{ 0x42A4, 0x80 },
+	{ 0x42A5, 0x80 },
+	{ 0x42A6, 0x80 },
+	{ 0x42A7, 0x80 },
+	{ 0x42A8, 0x80 },
+	{ 0x42A9, 0x80 },
+	{ 0x42AA, 0x80 },
+	{ 0x42AB, 0x80 },
+	{ 0x42AC, 0x80 },
+	{ 0x42AD, 0x80 },
+	{ 0x42AE, 0x80 },
+	{ 0x42AF, 0x80 },
+	{ 0x42B0, 0x80 },
+	{ 0x42B1, 0x80 },
+	{ 0x42B2, 0x80 },
+	{ 0x42B3, 0x80 },
+	{ 0x42B4, 0x80 },
+	{ 0x42B5, 0x80 },
+	{ 0x42B6, 0x80 },
+	{ 0x42B7, 0x80 },
+	{ 0x42B8, 0x80 },
+	{ 0x42B9, 0x80 },
+	{ 0x42BA, 0x80 },
+	{ 0x42BB, 0x80 },
+	{ 0x42BC, 0x80 },
+	{ 0x42BD, 0x80 },
+	{ 0x42BE, 0x80 },
+	{ 0x42BF, 0x80 },
+	{ 0x42C0, 0x80 },
+	{ 0x42C1, 0x80 },
+	{ 0x42C2, 0x80 },
+	{ 0x42C3, 0x80 },
+	{ 0x42C4, 0x80 },
+	{ 0x42C5, 0x80 },
+	{ 0x42C6, 0x80 },
+	{ 0x42C7, 0x80 },
+	{ 0x42C8, 0x80 },
+	{ 0x42C9, 0x80 },
+	{ 0x42CA, 0x80 },
+	{ 0x42CB, 0x80 },
+	{ 0x42CC, 0x80 },
+	{ 0x42CD, 0x80 },
+	{ 0x42CE, 0x80 },
+	{ 0x42CF, 0x80 },
+	{ 0x42D0, 0x80 },
+	{ 0x42D1, 0x80 },
+	{ 0x42D2, 0x80 },
+	{ 0x42D3, 0x80 },
+	{ 0x42D4, 0x80 },
+	{ 0x42D5, 0x80 },
+	{ 0x42D6, 0x80 },
+	{ 0x42D7, 0x80 },
+	{ 0x42D8, 0x00 },
+	{ 0x42D9, 0x00 },
+	{ 0x4300, 0xA2 },
+	{ 0x4301, 0xAA },
+	{ 0x4302, 0xA7 },
+	{ 0x4303, 0xAD },
+	{ 0x4304, 0x8E },
+	{ 0x4305, 0x92 },
+	{ 0x4306, 0x90 },
+	{ 0x4307, 0x93 },
+	{ 0x4308, 0x86 },
+	{ 0x4309, 0x89 },
+	{ 0x430A, 0x87 },
+	{ 0x430B, 0x88 },
+	{ 0x430C, 0x82 },
+	{ 0x430D, 0x84 },
+	{ 0x430E, 0x83 },
+	{ 0x430F, 0x84 },
+	{ 0x4310, 0x80 },
+	{ 0x4311, 0x82 },
+	{ 0x4312, 0x82 },
+	{ 0x4313, 0x82 },
+	{ 0x4314, 0x83 },
+	{ 0x4315, 0x85 },
+	{ 0x4316, 0x84 },
+	{ 0x4317, 0x85 },
+	{ 0x4318, 0x8D },
+	{ 0x4319, 0x8D },
+	{ 0x431A, 0x8D },
+	{ 0x431B, 0x8D },
+	{ 0x431C, 0x99 },
+	{ 0x431D, 0x9A },
+	{ 0x431E, 0x9A },
+	{ 0x431F, 0x9A },
+	{ 0x4320, 0xAE },
+	{ 0x4321, 0xB4 },
+	{ 0x4322, 0xB4 },
+	{ 0x4323, 0xB5 },
+	{ 0x4324, 0x9A },
+	{ 0x4325, 0x9D },
+	{ 0x4326, 0x9B },
+	{ 0x4327, 0x9E },
+	{ 0x4328, 0x8C },
+	{ 0x4329, 0x8F },
+	{ 0x432A, 0x8D },
+	{ 0x432B, 0x8F },
+	{ 0x432C, 0x83 },
+	{ 0x432D, 0x85 },
+	{ 0x432E, 0x85 },
+	{ 0x432F, 0x85 },
+	{ 0x4330, 0x80 },
+	{ 0x4331, 0x81 },
+	{ 0x4332, 0x81 },
+	{ 0x4333, 0x81 },
+	{ 0x4334, 0x80 },
+	{ 0x4335, 0x80 },
+	{ 0x4336, 0x80 },
+	{ 0x4337, 0x81 },
+	{ 0x4338, 0x83 },
+	{ 0x4339, 0x83 },
+	{ 0x433A, 0x83 },
+	{ 0x433B, 0x83 },
+	{ 0x433C, 0x88 },
+	{ 0x433D, 0x88 },
+	{ 0x433E, 0x88 },
+	{ 0x433F, 0x88 },
+	{ 0x4340, 0x93 },
+	{ 0x4341, 0x93 },
+	{ 0x4342, 0x93 },
+	{ 0x4343, 0x93 },
+	{ 0x4344, 0xA2 },
+	{ 0x4345, 0xA4 },
+	{ 0x4346, 0xA4 },
+	{ 0x4347, 0xA4 },
+	{ 0x4348, 0x97 },
+	{ 0x4349, 0x99 },
+	{ 0x434A, 0x97 },
+	{ 0x434B, 0x97 },
+	{ 0x434C, 0x89 },
+	{ 0x434D, 0x8C },
+	{ 0x434E, 0x8B },
+	{ 0x434F, 0x8A },
+	{ 0x4350, 0x81 },
+	{ 0x4351, 0x83 },
+	{ 0x4352, 0x83 },
+	{ 0x4353, 0x83 },
+	{ 0x4354, 0x7F },
+	{ 0x4355, 0x80 },
+	{ 0x4356, 0x80 },
+	{ 0x4357, 0x80 },
+	{ 0x4358, 0x7F },
+	{ 0x4359, 0x7F },
+	{ 0x435A, 0x7F },
+	{ 0x435B, 0x7F },
+	{ 0x435C, 0x82 },
+	{ 0x435D, 0x81 },
+	{ 0x435E, 0x81 },
+	{ 0x435F, 0x82 },
+	{ 0x4360, 0x86 },
+	{ 0x4361, 0x86 },
+	{ 0x4362, 0x86 },
+	{ 0x4363, 0x87 },
+	{ 0x4364, 0x8F },
+	{ 0x4365, 0x8F },
+	{ 0x4366, 0x8F },
+	{ 0x4367, 0x90 },
+	{ 0x4368, 0x9E },
+	{ 0x4369, 0x9E },
+	{ 0x436A, 0x9E },
+	{ 0x436B, 0x9F },
+	{ 0x436C, 0x99 },
+	{ 0x436D, 0x9B },
+	{ 0x436E, 0x9A },
+	{ 0x436F, 0x98 },
+	{ 0x4370, 0x8B },
+	{ 0x4371, 0x8D },
+	{ 0x4372, 0x8D },
+	{ 0x4373, 0x8B },
+	{ 0x4374, 0x83 },
+	{ 0x4375, 0x84 },
+	{ 0x4376, 0x84 },
+	{ 0x4377, 0x83 },
+	{ 0x4378, 0x80 },
+	{ 0x4379, 0x81 },
+	{ 0x437A, 0x81 },
+	{ 0x437B, 0x80 },
+	{ 0x437C, 0x81 },
+	{ 0x437D, 0x80 },
+	{ 0x437E, 0x80 },
+	{ 0x437F, 0x80 },
+	{ 0x4380, 0x83 },
+	{ 0x4381, 0x83 },
+	{ 0x4382, 0x83 },
+	{ 0x4383, 0x83 },
+	{ 0x4384, 0x88 },
+	{ 0x4385, 0x87 },
+	{ 0x4386, 0x87 },
+	{ 0x4387, 0x88 },
+	{ 0x4388, 0x91 },
+	{ 0x4389, 0x90 },
+	{ 0x438A, 0x90 },
+	{ 0x438B, 0x91 },
+	{ 0x438C, 0x9E },
+	{ 0x438D, 0x9E },
+	{ 0x438E, 0x9E },
+	{ 0x438F, 0xA0 },
+	{ 0x4390, 0xA0 },
+	{ 0x4391, 0xA2 },
+	{ 0x4392, 0xA2 },
+	{ 0x4393, 0xA0 },
+	{ 0x4394, 0x92 },
+	{ 0x4395, 0x94 },
+	{ 0x4396, 0x94 },
+	{ 0x4397, 0x91 },
+	{ 0x4398, 0x89 },
+	{ 0x4399, 0x8A },
+	{ 0x439A, 0x89 },
+	{ 0x439B, 0x88 },
+	{ 0x439C, 0x85 },
+	{ 0x439D, 0x85 },
+	{ 0x439E, 0x85 },
+	{ 0x439F, 0x84 },
+	{ 0x43A0, 0x85 },
+	{ 0x43A1, 0x84 },
+	{ 0x43A2, 0x84 },
+	{ 0x43A3, 0x84 },
+	{ 0x43A4, 0x88 },
+	{ 0x43A5, 0x86 },
+	{ 0x43A6, 0x86 },
+	{ 0x43A7, 0x87 },
+	{ 0x43A8, 0x8E },
+	{ 0x43A9, 0x8B },
+	{ 0x43AA, 0x8B },
+	{ 0x43AB, 0x8D },
+	{ 0x43AC, 0x97 },
+	{ 0x43AD, 0x96 },
+	{ 0x43AE, 0x96 },
+	{ 0x43AF, 0x98 },
+	{ 0x43B0, 0xA5 },
+	{ 0x43B1, 0xA5 },
+	{ 0x43B2, 0xA5 },
+	{ 0x43B3, 0xA9 },
+	{ 0x43B4, 0xB7 },
+	{ 0x43B5, 0xBB },
+	{ 0x43B6, 0xBB },
+	{ 0x43B7, 0xB8 },
+	{ 0x43B8, 0x9C },
+	{ 0x43B9, 0x9C },
+	{ 0x43BA, 0x9C },
+	{ 0x43BB, 0x9A },
+	{ 0x43BC, 0x92 },
+	{ 0x43BD, 0x92 },
+	{ 0x43BE, 0x92 },
+	{ 0x43BF, 0x8F },
+	{ 0x43C0, 0x8B },
+	{ 0x43C1, 0x8B },
+	{ 0x43C2, 0x8B },
+	{ 0x43C3, 0x89 },
+	{ 0x43C4, 0x8A },
+	{ 0x43C5, 0x89 },
+	{ 0x43C6, 0x89 },
+	{ 0x43C7, 0x88 },
+	{ 0x43C8, 0x8D },
+	{ 0x43C9, 0x8B },
+	{ 0x43CA, 0x8B },
+	{ 0x43CB, 0x8C },
+	{ 0x43CC, 0x94 },
+	{ 0x43CD, 0x91 },
+	{ 0x43CE, 0x92 },
+	{ 0x43CF, 0x93 },
+	{ 0x43D0, 0x9E },
+	{ 0x43D1, 0x9D },
+	{ 0x43D2, 0x9D },
+	{ 0x43D3, 0xA1 },
+	{ 0x43D4, 0xB2 },
+	{ 0x43D5, 0xB4 },
+	{ 0x43D6, 0xB5 },
+	{ 0x43D7, 0xBD },
+	{ 0x4400, 0x80 },
+	{ 0x4401, 0x80 },
+	{ 0x4402, 0x80 },
+	{ 0x4403, 0x80 },
+	{ 0x4404, 0x80 },
+	{ 0x4405, 0x80 },
+	{ 0x4406, 0x80 },
+	{ 0x4407, 0x80 },
+	{ 0x4408, 0x80 },
+	{ 0x4409, 0x80 },
+	{ 0x440A, 0x80 },
+	{ 0x440B, 0x80 },
+	{ 0x440C, 0x80 },
+	{ 0x440D, 0x80 },
+	{ 0x440E, 0x80 },
+	{ 0x440F, 0x80 },
+	{ 0x4410, 0x80 },
+	{ 0x4411, 0x80 },
+	{ 0x4412, 0x80 },
+	{ 0x4413, 0x80 },
+	{ 0x4414, 0x80 },
+	{ 0x4415, 0x80 },
+	{ 0x4416, 0x80 },
+	{ 0x4417, 0x80 },
+	{ 0x4418, 0x80 },
+	{ 0x4419, 0x80 },
+	{ 0x441A, 0x80 },
+	{ 0x441B, 0x80 },
+	{ 0x441C, 0x80 },
+	{ 0x441D, 0x80 },
+	{ 0x441E, 0x80 },
+	{ 0x441F, 0x80 },
+	{ 0x4420, 0x80 },
+	{ 0x4421, 0x80 },
+	{ 0x4422, 0x80 },
+	{ 0x4423, 0x80 },
+	{ 0x4424, 0x80 },
+	{ 0x4425, 0x80 },
+	{ 0x4426, 0x80 },
+	{ 0x4427, 0x80 },
+	{ 0x4428, 0x80 },
+	{ 0x4429, 0x80 },
+	{ 0x442A, 0x80 },
+	{ 0x442B, 0x80 },
+	{ 0x442C, 0x80 },
+	{ 0x442D, 0x80 },
+	{ 0x442E, 0x80 },
+	{ 0x442F, 0x80 },
+	{ 0x4430, 0x80 },
+	{ 0x4431, 0x80 },
+	{ 0x4432, 0x80 },
+	{ 0x4433, 0x80 },
+	{ 0x4434, 0x80 },
+	{ 0x4435, 0x80 },
+	{ 0x4436, 0x80 },
+	{ 0x4437, 0x80 },
+	{ 0x4438, 0x80 },
+	{ 0x4439, 0x80 },
+	{ 0x443A, 0x80 },
+	{ 0x443B, 0x80 },
+	{ 0x443C, 0x80 },
+	{ 0x443D, 0x80 },
+	{ 0x443E, 0x80 },
+	{ 0x443F, 0x80 },
+	{ 0x4440, 0x80 },
+	{ 0x4441, 0x80 },
+	{ 0x4442, 0x80 },
+	{ 0x4443, 0x80 },
+	{ 0x4444, 0x80 },
+	{ 0x4445, 0x80 },
+	{ 0x4446, 0x80 },
+	{ 0x4447, 0x80 },
+	{ 0x4448, 0x80 },
+	{ 0x4449, 0x80 },
+	{ 0x444A, 0x80 },
+	{ 0x444B, 0x80 },
+	{ 0x444C, 0x80 },
+	{ 0x444D, 0x80 },
+	{ 0x444E, 0x80 },
+	{ 0x444F, 0x80 },
+	{ 0x4450, 0x80 },
+	{ 0x4451, 0x80 },
+	{ 0x4452, 0x80 },
+	{ 0x4453, 0x80 },
+	{ 0x4454, 0x80 },
+	{ 0x4455, 0x80 },
+	{ 0x4456, 0x80 },
+	{ 0x4457, 0x80 },
+	{ 0x4458, 0x80 },
+	{ 0x4459, 0x80 },
+	{ 0x445A, 0x80 },
+	{ 0x445B, 0x80 },
+	{ 0x445C, 0x80 },
+	{ 0x445D, 0x80 },
+	{ 0x445E, 0x80 },
+	{ 0x445F, 0x80 },
+	{ 0x4460, 0x80 },
+	{ 0x4461, 0x80 },
+	{ 0x4462, 0x80 },
+	{ 0x4463, 0x80 },
+	{ 0x4464, 0x80 },
+	{ 0x4465, 0x80 },
+	{ 0x4466, 0x80 },
+	{ 0x4467, 0x80 },
+	{ 0x4468, 0x80 },
+	{ 0x4469, 0x80 },
+	{ 0x446A, 0x80 },
+	{ 0x446B, 0x80 },
+	{ 0x446C, 0x80 },
+	{ 0x446D, 0x80 },
+	{ 0x446E, 0x80 },
+	{ 0x446F, 0x80 },
+	{ 0x4470, 0x80 },
+	{ 0x4471, 0x80 },
+	{ 0x4472, 0x80 },
+	{ 0x4473, 0x80 },
+	{ 0x4474, 0x80 },
+	{ 0x4475, 0x80 },
+	{ 0x4476, 0x80 },
+	{ 0x4477, 0x80 },
+	{ 0x4478, 0x80 },
+	{ 0x4479, 0x80 },
+	{ 0x447A, 0x80 },
+	{ 0x447B, 0x80 },
+	{ 0x447C, 0x80 },
+	{ 0x447D, 0x80 },
+	{ 0x447E, 0x80 },
+	{ 0x447F, 0x80 },
+	{ 0x4480, 0x80 },
+	{ 0x4481, 0x80 },
+	{ 0x4482, 0x80 },
+	{ 0x4483, 0x80 },
+	{ 0x4484, 0x80 },
+	{ 0x4485, 0x80 },
+	{ 0x4486, 0x80 },
+	{ 0x4487, 0x80 },
+	{ 0x4488, 0x80 },
+	{ 0x4489, 0x80 },
+	{ 0x448A, 0x80 },
+	{ 0x448B, 0x80 },
+	{ 0x448C, 0x80 },
+	{ 0x448D, 0x80 },
+	{ 0x448E, 0x80 },
+	{ 0x448F, 0x80 },
+	{ 0x4490, 0x80 },
+	{ 0x4491, 0x80 },
+	{ 0x4492, 0x80 },
+	{ 0x4493, 0x80 },
+	{ 0x4494, 0x80 },
+	{ 0x4495, 0x80 },
+	{ 0x4496, 0x80 },
+	{ 0x4497, 0x80 },
+	{ 0x4498, 0x80 },
+	{ 0x4499, 0x80 },
+	{ 0x449A, 0x80 },
+	{ 0x449B, 0x80 },
+	{ 0x449C, 0x80 },
+	{ 0x449D, 0x80 },
+	{ 0x449E, 0x80 },
+	{ 0x449F, 0x80 },
+	{ 0x44A0, 0x80 },
+	{ 0x44A1, 0x80 },
+	{ 0x44A2, 0x80 },
+	{ 0x44A3, 0x80 },
+	{ 0x44A4, 0x80 },
+	{ 0x44A5, 0x80 },
+	{ 0x44A6, 0x80 },
+	{ 0x44A7, 0x80 },
+	{ 0x44A8, 0x80 },
+	{ 0x44A9, 0x80 },
+	{ 0x44AA, 0x80 },
+	{ 0x44AB, 0x80 },
+	{ 0x44AC, 0x80 },
+	{ 0x44AD, 0x80 },
+	{ 0x44AE, 0x80 },
+	{ 0x44AF, 0x80 },
+	{ 0x44B0, 0x80 },
+	{ 0x44B1, 0x80 },
+	{ 0x44B2, 0x80 },
+	{ 0x44B3, 0x80 },
+	{ 0x44B4, 0x80 },
+	{ 0x44B5, 0x80 },
+	{ 0x44B6, 0x80 },
+	{ 0x44B7, 0x80 },
+	{ 0x44B8, 0x80 },
+	{ 0x44B9, 0x80 },
+	{ 0x44BA, 0x80 },
+	{ 0x44BB, 0x80 },
+	{ 0x44BC, 0x80 },
+	{ 0x44BD, 0x80 },
+	{ 0x44BE, 0x80 },
+	{ 0x44BF, 0x80 },
+	{ 0x44C0, 0x80 },
+	{ 0x44C1, 0x80 },
+	{ 0x44C2, 0x80 },
+	{ 0x44C3, 0x80 },
+	{ 0x44C4, 0x80 },
+	{ 0x44C5, 0x80 },
+	{ 0x44C6, 0x80 },
+	{ 0x44C7, 0x80 },
+	{ 0x44C8, 0x80 },
+	{ 0x44C9, 0x80 },
+	{ 0x44CA, 0x80 },
+	{ 0x44CB, 0x80 },
+	{ 0x44CC, 0x80 },
+	{ 0x44CD, 0x80 },
+	{ 0x44CE, 0x80 },
+	{ 0x44CF, 0x80 },
+	{ 0x44D0, 0x80 },
+	{ 0x44D1, 0x80 },
+	{ 0x44D2, 0x80 },
+	{ 0x44D3, 0x80 },
+	{ 0x44D4, 0x80 },
+	{ 0x44D5, 0x80 },
+	{ 0x44D6, 0x80 },
+	{ 0x44D7, 0x80 },
+	{ 0x4500, 0x80 },
+	{ 0x4501, 0x80 },
+	{ 0x4502, 0x80 },
+	{ 0x4503, 0x80 },
+	{ 0x4504, 0x80 },
+	{ 0x4505, 0x80 },
+	{ 0x4506, 0x80 },
+	{ 0x4507, 0x80 },
+	{ 0x4508, 0x80 },
+	{ 0x4509, 0x80 },
+	{ 0x450A, 0x80 },
+	{ 0x450B, 0x80 },
+	{ 0x450C, 0x80 },
+	{ 0x450D, 0x80 },
+	{ 0x450E, 0x80 },
+	{ 0x450F, 0x80 },
+	{ 0x4510, 0x80 },
+	{ 0x4511, 0x80 },
+	{ 0x4512, 0x80 },
+	{ 0x4513, 0x80 },
+	{ 0x4514, 0x80 },
+	{ 0x4515, 0x80 },
+	{ 0x4516, 0x80 },
+	{ 0x4517, 0x80 },
+	{ 0x4518, 0x80 },
+	{ 0x4519, 0x80 },
+	{ 0x451A, 0x80 },
+	{ 0x451B, 0x80 },
+	{ 0x451C, 0x80 },
+	{ 0x451D, 0x80 },
+	{ 0x451E, 0x80 },
+	{ 0x451F, 0x80 },
+	{ 0x4520, 0x80 },
+	{ 0x4521, 0x80 },
+	{ 0x4522, 0x80 },
+	{ 0x4523, 0x80 },
+	{ 0x4524, 0x80 },
+	{ 0x4525, 0x80 },
+	{ 0x4526, 0x80 },
+	{ 0x4527, 0x80 },
+	{ 0x4528, 0x80 },
+	{ 0x4529, 0x80 },
+	{ 0x452A, 0x80 },
+	{ 0x452B, 0x80 },
+	{ 0x452C, 0x80 },
+	{ 0x452D, 0x80 },
+	{ 0x452E, 0x80 },
+	{ 0x452F, 0x80 },
+	{ 0x4530, 0x80 },
+	{ 0x4531, 0x80 },
+	{ 0x4532, 0x80 },
+	{ 0x4533, 0x80 },
+	{ 0x4534, 0x80 },
+	{ 0x4535, 0x80 },
+	{ 0x4536, 0x80 },
+	{ 0x4537, 0x80 },
+	{ 0x4538, 0x80 },
+	{ 0x4539, 0x80 },
+	{ 0x453A, 0x80 },
+	{ 0x453B, 0x80 },
+	{ 0x453C, 0x80 },
+	{ 0x453D, 0x80 },
+	{ 0x453E, 0x80 },
+	{ 0x453F, 0x80 },
+	{ 0x4540, 0x80 },
+	{ 0x4541, 0x80 },
+	{ 0x4542, 0x80 },
+	{ 0x4543, 0x80 },
+	{ 0x4544, 0x80 },
+	{ 0x4545, 0x80 },
+	{ 0x4546, 0x80 },
+	{ 0x4547, 0x80 },
+	{ 0x4548, 0x80 },
+	{ 0x4549, 0x80 },
+	{ 0x454A, 0x80 },
+	{ 0x454B, 0x80 },
+	{ 0x454C, 0x80 },
+	{ 0x454D, 0x80 },
+	{ 0x454E, 0x80 },
+	{ 0x454F, 0x80 },
+	{ 0x4550, 0x80 },
+	{ 0x4551, 0x80 },
+	{ 0x4552, 0x80 },
+	{ 0x4553, 0x80 },
+	{ 0x4554, 0x80 },
+	{ 0x4555, 0x80 },
+	{ 0x4556, 0x80 },
+	{ 0x4557, 0x80 },
+	{ 0x4558, 0x80 },
+	{ 0x4559, 0x80 },
+	{ 0x455A, 0x80 },
+	{ 0x455B, 0x80 },
+	{ 0x455C, 0x80 },
+	{ 0x455D, 0x80 },
+	{ 0x455E, 0x80 },
+	{ 0x455F, 0x80 },
+	{ 0x4560, 0x80 },
+	{ 0x4561, 0x80 },
+	{ 0x4562, 0x80 },
+	{ 0x4563, 0x80 },
+	{ 0x4564, 0x80 },
+	{ 0x4565, 0x80 },
+	{ 0x4566, 0x80 },
+	{ 0x4567, 0x80 },
+	{ 0x4568, 0x80 },
+	{ 0x4569, 0x80 },
+	{ 0x456A, 0x80 },
+	{ 0x456B, 0x80 },
+	{ 0x456C, 0x80 },
+	{ 0x456D, 0x80 },
+	{ 0x456E, 0x80 },
+	{ 0x456F, 0x80 },
+	{ 0x4570, 0x80 },
+	{ 0x4571, 0x80 },
+	{ 0x4572, 0x80 },
+	{ 0x4573, 0x80 },
+	{ 0x4574, 0x80 },
+	{ 0x4575, 0x80 },
+	{ 0x4576, 0x80 },
+	{ 0x4577, 0x80 },
+	{ 0x4578, 0x80 },
+	{ 0x4579, 0x80 },
+	{ 0x457A, 0x80 },
+	{ 0x457B, 0x80 },
+	{ 0x457C, 0x80 },
+	{ 0x457D, 0x80 },
+	{ 0x457E, 0x80 },
+	{ 0x457F, 0x80 },
+	{ 0x4580, 0x80 },
+	{ 0x4581, 0x80 },
+	{ 0x4582, 0x80 },
+	{ 0x4583, 0x80 },
+	{ 0x4584, 0x80 },
+	{ 0x4585, 0x80 },
+	{ 0x4586, 0x80 },
+	{ 0x4587, 0x80 },
+	{ 0x4588, 0x80 },
+	{ 0x4589, 0x80 },
+	{ 0x458A, 0x80 },
+	{ 0x458B, 0x80 },
+	{ 0x458C, 0x80 },
+	{ 0x458D, 0x80 },
+	{ 0x458E, 0x80 },
+	{ 0x458F, 0x80 },
+	{ 0x4590, 0x80 },
+	{ 0x4591, 0x80 },
+	{ 0x4592, 0x80 },
+	{ 0x4593, 0x80 },
+	{ 0x4594, 0x80 },
+	{ 0x4595, 0x80 },
+	{ 0x4596, 0x80 },
+	{ 0x4597, 0x80 },
+	{ 0x4598, 0x80 },
+	{ 0x4599, 0x80 },
+	{ 0x459A, 0x80 },
+	{ 0x459B, 0x80 },
+	{ 0x459C, 0x80 },
+	{ 0x459D, 0x80 },
+	{ 0x459E, 0x80 },
+	{ 0x459F, 0x80 },
+	{ 0x45A0, 0x80 },
+	{ 0x45A1, 0x80 },
+	{ 0x45A2, 0x80 },
+	{ 0x45A3, 0x80 },
+	{ 0x45A4, 0x80 },
+	{ 0x45A5, 0x80 },
+	{ 0x45A6, 0x80 },
+	{ 0x45A7, 0x80 },
+	{ 0x45A8, 0x80 },
+	{ 0x45A9, 0x80 },
+	{ 0x45AA, 0x80 },
+	{ 0x45AB, 0x80 },
+	{ 0x45AC, 0x80 },
+	{ 0x45AD, 0x80 },
+	{ 0x45AE, 0x80 },
+	{ 0x45AF, 0x80 },
+	{ 0x45B0, 0x80 },
+	{ 0x45B1, 0x80 },
+	{ 0x45B2, 0x80 },
+	{ 0x45B3, 0x80 },
+	{ 0x45B4, 0x80 },
+	{ 0x45B5, 0x80 },
+	{ 0x45B6, 0x80 },
+	{ 0x45B7, 0x80 },
+	{ 0x45B8, 0x80 },
+	{ 0x45B9, 0x80 },
+	{ 0x45BA, 0x80 },
+	{ 0x45BB, 0x80 },
+	{ 0x45BC, 0x80 },
+	{ 0x45BD, 0x80 },
+	{ 0x45BE, 0x80 },
+	{ 0x45BF, 0x80 },
+	{ 0x45C0, 0x80 },
+	{ 0x45C1, 0x80 },
+	{ 0x45C2, 0x80 },
+	{ 0x45C3, 0x80 },
+	{ 0x45C4, 0x80 },
+	{ 0x45C5, 0x80 },
+	{ 0x45C6, 0x80 },
+	{ 0x45C7, 0x80 },
+	{ 0x45C8, 0x80 },
+	{ 0x45C9, 0x80 },
+	{ 0x45CA, 0x80 },
+	{ 0x45CB, 0x80 },
+	{ 0x45CC, 0x80 },
+	{ 0x45CD, 0x80 },
+	{ 0x45CE, 0x80 },
+	{ 0x45CF, 0x80 },
+	{ 0x45D0, 0x80 },
+	{ 0x45D1, 0x80 },
+	{ 0x45D2, 0x80 },
+	{ 0x45D3, 0x80 },
+	{ 0x45D4, 0x80 },
+	{ 0x45D5, 0x80 },
+	{ 0x45D6, 0x80 },
+	{ 0x45D7, 0x80 },
+	{ 0x7000, 0xAB },
+	{ 0x7001, 0xBA },
+	{ 0x7002, 0x40 },
+	{ 0x7003, 0x02 },
+	{ 0x7004, 0x00 },
+	{ 0x7005, 0x00 },
+	{ 0x7006, 0x00 },
+	{ 0x7007, 0x00 },
+	{ 0x7008, 0x00 },
+	{ 0x7009, 0x00 },
+	{ 0x700A, 0x00 },
+	{ 0x700B, 0x00 },
+	{ 0x700C, 0x00 },
+	{ 0x700D, 0x00 },
+	{ 0x700E, 0x00 },
+	{ 0x700F, 0x00 },
+	{ 0x7010, 0x55 },
+	{ 0x7011, 0x88 },
+	{ 0x7012, 0x40 },
+	{ 0x7013, 0x01 },
+	{ 0x7014, 0x72 },
+	{ 0x7015, 0xF1 },
+	{ 0x7016, 0x02 },
+	{ 0x7017, 0xF8 },
+	{ 0x7018, 0x00 },
+	{ 0x7019, 0x00 },
+	{ 0x701A, 0x00 },
+	{ 0x701B, 0x00 },
+	{ 0x701C, 0x00 },
+	{ 0x701D, 0x00 },
+	{ 0x701E, 0x00 },
+	{ 0x701F, 0x00 },
+	{ 0x7020, 0x00 },
+	{ 0x7021, 0x00 },
+	{ 0x7022, 0x00 },
+	{ 0x7023, 0x00 },
+	{ 0x7024, 0x00 },
+	{ 0x7025, 0x00 },
+	{ 0x7026, 0x00 },
+	{ 0x7027, 0x00 },
+	{ 0x7028, 0x00 },
+	{ 0x7029, 0x00 },
+	{ 0x702A, 0x00 },
+	{ 0x702B, 0x00 },
+	{ 0x702C, 0x00 },
+	{ 0x702D, 0x00 },
+	{ 0x702E, 0x00 },
+	{ 0x702F, 0x00 },
+	{ 0x7030, 0x00 },
+	{ 0x7031, 0x00 },
+	{ 0x7032, 0x00 },
+	{ 0x7033, 0x00 },
+	{ 0x7034, 0x00 },
+	{ 0x7035, 0x00 },
+	{ 0x7036, 0x00 },
+	{ 0x7037, 0x00 },
+	{ 0x7038, 0x00 },
+	{ 0x7039, 0x00 },
+	{ 0x703A, 0x00 },
+	{ 0x703B, 0x00 },
+	{ 0x703C, 0x00 },
+	{ 0x703D, 0x00 },
+	{ 0x703E, 0x00 },
+	{ 0x703F, 0x00 },
+	{ 0x7040, 0x00 },
+	{ 0x7041, 0x00 },
+	{ 0x7042, 0x00 },
+	{ 0x7043, 0x00 },
+	{ 0x7044, 0x00 },
+	{ 0x7045, 0x00 },
+	{ 0x7046, 0x00 },
+	{ 0x7047, 0x00 },
+	{ 0x7048, 0x00 },
+	{ 0x7049, 0x00 },
+	{ 0x704A, 0x00 },
+	{ 0x704B, 0x00 },
+	{ 0x704C, 0x00 },
+	{ 0x704D, 0x00 },
+	{ 0x704E, 0x00 },
+	{ 0x704F, 0x00 },
+	{ 0x7050, 0x00 },
+	{ 0x7051, 0x00 },
+	{ 0x7052, 0x00 },
+	{ 0x7053, 0x00 },
+	{ 0x7054, 0x00 },
+	{ 0x7055, 0x00 },
+	{ 0x7056, 0x00 },
+	{ 0x7057, 0x00 },
+	{ 0x7058, 0x00 },
+	{ 0x7059, 0x00 },
+	{ 0x705A, 0x00 },
+	{ 0x705B, 0x00 },
+	{ 0x705C, 0x00 },
+	{ 0x705D, 0x00 },
+	{ 0x705E, 0x00 },
+	{ 0x705F, 0x00 },
+	{ 0x7060, 0x00 },
+	{ 0x7061, 0x00 },
+	{ 0x7062, 0x00 },
+	{ 0x7063, 0x00 },
+	{ 0x7064, 0x00 },
+	{ 0x7065, 0x00 },
+	{ 0x7066, 0x00 },
+	{ 0x7067, 0x00 },
+	{ 0x7068, 0x00 },
+	{ 0x7069, 0x00 },
+	{ 0x706A, 0x00 },
+	{ 0x706B, 0x00 },
+	{ 0x706C, 0x00 },
+	{ 0x706D, 0x00 },
+	{ 0x706E, 0x00 },
+	{ 0x706F, 0x00 },
+	{ 0x7070, 0x00 },
+	{ 0x7071, 0x00 },
+	{ 0x7072, 0x00 },
+	{ 0x7073, 0x00 },
+	{ 0x7074, 0x00 },
+	{ 0x7075, 0x00 },
+	{ 0x7076, 0x00 },
+	{ 0x7077, 0x00 },
+	{ 0x7078, 0x00 },
+	{ 0x7079, 0x00 },
+	{ 0x707A, 0x00 },
+	{ 0x707B, 0x00 },
+	{ 0x707C, 0x00 },
+	{ 0x707D, 0x00 },
+	{ 0x707E, 0x00 },
+	{ 0x707F, 0x00 },
+	{ 0x7080, 0x00 },
+	{ 0x7081, 0x00 },
+	{ 0x7082, 0x00 },
+	{ 0x7083, 0x00 },
+	{ 0x7084, 0x00 },
+	{ 0x7085, 0x00 },
+	{ 0x7086, 0x00 },
+	{ 0x7087, 0x00 },
+	{ 0x7088, 0x00 },
+	{ 0x7089, 0x00 },
+	{ 0x708A, 0x00 },
+	{ 0x708B, 0x00 },
+	{ 0x708C, 0x00 },
+	{ 0x708D, 0x00 },
+	{ 0x708E, 0x00 },
+	{ 0x708F, 0x00 },
+	{ 0x7090, 0x00 },
+	{ 0x7091, 0xF0 },
+	{ 0x7092, 0x02 },
+	{ 0x7093, 0xF8 },
+	{ 0x7094, 0x8D },
+	{ 0x7095, 0xF6 },
+	{ 0x7096, 0xFA },
+	{ 0x7097, 0xFF },
+	{ 0x7098, 0xF0 },
+	{ 0x7099, 0xB5 },
+	{ 0x709A, 0x04 },
+	{ 0x709B, 0x46 },
+	{ 0x709C, 0x8F },
+	{ 0x709D, 0xB0 },
+	{ 0x709E, 0x5F },
+	{ 0x709F, 0x48 },
+	{ 0x70A0, 0x0C },
+	{ 0x70A1, 0x90 },
+	{ 0x70A2, 0x5F },
+	{ 0x70A3, 0x48 },
+	{ 0x70A4, 0x06 },
+	{ 0x70A5, 0x90 },
+	{ 0x70A6, 0x20 },
+	{ 0x70A7, 0x46 },
+	{ 0x70A8, 0x34 },
+	{ 0x70A9, 0x30 },
+	{ 0x70AA, 0x0B },
+	{ 0x70AB, 0x90 },
+	{ 0x70AC, 0x5B },
+	{ 0x70AD, 0x48 },
+	{ 0x70AE, 0x5A },
+	{ 0x70AF, 0x49 },
+	{ 0x70B0, 0x26 },
+	{ 0x70B1, 0x46 },
+	{ 0x70B2, 0x66 },
+	{ 0x70B3, 0x30 },
+	{ 0x70B4, 0x3A },
+	{ 0x70B5, 0x31 },
+	{ 0x70B6, 0x3C },
+	{ 0x70B7, 0x36 },
+	{ 0x70B8, 0x05 },
+	{ 0x70B9, 0x90 },
+	{ 0x70BA, 0x0A },
+	{ 0x70BB, 0x30 },
+	{ 0x70BC, 0x04 },
+	{ 0x70BD, 0x90 },
+	{ 0x70BE, 0x59 },
+	{ 0x70BF, 0x48 },
+	{ 0x70C0, 0x55 },
+	{ 0x70C1, 0x4A },
+	{ 0x70C2, 0x40 },
+	{ 0x70C3, 0x6E },
+	{ 0x70C4, 0xC0 },
+	{ 0x70C5, 0x07 },
+	{ 0x70C6, 0x7D },
+	{ 0x70C7, 0xD1 },
+	{ 0x70C8, 0x17 },
+	{ 0x70C9, 0x88 },
+	{ 0x70CA, 0x0A },
+	{ 0x70CB, 0x5E },
+	{ 0x70CC, 0x0D },
+	{ 0x70CD, 0x92 },
+	{ 0x70CE, 0x53 },
+	{ 0x70CF, 0x49 },
+	{ 0x70D0, 0x55 },
+	{ 0x70D1, 0x48 },
+	{ 0x70D2, 0x94 },
+	{ 0x70D3, 0x31 },
+	{ 0x70D4, 0x89 },
+	{ 0x70D5, 0x6B },
+	{ 0x70D6, 0x80 },
+	{ 0x70D7, 0x68 },
+	{ 0x70D8, 0x09 },
+	{ 0x70D9, 0x02 },
+	{ 0x70DA, 0x00 },
+	{ 0x70DB, 0x03 },
+	{ 0x70DC, 0x09 },
+	{ 0x70DD, 0x0E },
+	{ 0x70DE, 0x00 },
+	{ 0x70DF, 0x0B },
+	{ 0x70E0, 0x49 },
+	{ 0x70E1, 0x1C },
+	{ 0x70E2, 0x48 },
+	{ 0x70E3, 0x43 },
+	{ 0x70E4, 0x4D },
+	{ 0x70E5, 0x49 },
+	{ 0x70E6, 0x6C },
+	{ 0x70E7, 0x39 },
+	{ 0x70E8, 0x8A },
+	{ 0x70E9, 0x6A },
+	{ 0x70EA, 0x07 },
+	{ 0x70EB, 0x92 },
+	{ 0x70EC, 0xCA },
+	{ 0x70ED, 0x6A },
+	{ 0x70EE, 0x00 },
+	{ 0x70EF, 0x21 },
+	{ 0x70F0, 0xC9 },
+	{ 0x70F1, 0x43 },
+	{ 0x70F2, 0x03 },
+	{ 0x70F3, 0x92 },
+	{ 0x70F4, 0x00 },
+	{ 0x70F5, 0x22 },
+	{ 0x70F6, 0x00 },
+	{ 0x70F7, 0x91 },
+	{ 0x70F8, 0x01 },
+	{ 0x70F9, 0x92 },
+	{ 0x70FA, 0x39 },
+	{ 0x70FB, 0x46 },
+	{ 0x70FC, 0x8F },
+	{ 0x70FD, 0xF6 },
+	{ 0x70FE, 0xCE },
+	{ 0x70FF, 0xFB },
+	{ 0x7100, 0x01 },
+	{ 0x7101, 0x22 },
+	{ 0x7102, 0x00 },
+	{ 0x7103, 0x23 },
+	{ 0x7104, 0x8C },
+	{ 0x7105, 0xF6 },
+	{ 0x7106, 0x02 },
+	{ 0x7107, 0xFA },
+	{ 0x7108, 0x00 },
+	{ 0x7109, 0x21 },
+	{ 0x710A, 0x05 },
+	{ 0x710B, 0x46 },
+	{ 0x710C, 0x01 },
+	{ 0x710D, 0x91 },
+	{ 0x710E, 0x00 },
+	{ 0x710F, 0x90 },
+	{ 0x7110, 0x39 },
+	{ 0x7111, 0x46 },
+	{ 0x7112, 0x07 },
+	{ 0x7113, 0x98 },
+	{ 0x7114, 0x8F },
+	{ 0x7115, 0xF6 },
+	{ 0x7116, 0xC2 },
+	{ 0x7117, 0xFB },
+	{ 0x7118, 0x0D },
+	{ 0x7119, 0x9A },
+	{ 0x711A, 0xD3 },
+	{ 0x711B, 0x17 },
+	{ 0x711C, 0x80 },
+	{ 0x711D, 0x18 },
+	{ 0x711E, 0x59 },
+	{ 0x711F, 0x41 },
+	{ 0x7120, 0x01 },
+	{ 0x7121, 0x22 },
+	{ 0x7122, 0x00 },
+	{ 0x7123, 0x23 },
+	{ 0x7124, 0x8C },
+	{ 0x7125, 0xF6 },
+	{ 0x7126, 0xCD },
+	{ 0x7127, 0xF9 },
+	{ 0x7128, 0x07 },
+	{ 0x7129, 0x90 },
+	{ 0x712A, 0x00 },
+	{ 0x712B, 0x20 },
+	{ 0x712C, 0x01 },
+	{ 0x712D, 0x90 },
+	{ 0x712E, 0x00 },
+	{ 0x712F, 0x95 },
+	{ 0x7130, 0x39 },
+	{ 0x7131, 0x46 },
+	{ 0x7132, 0x03 },
+	{ 0x7133, 0x98 },
+	{ 0x7134, 0x8F },
+	{ 0x7135, 0xF6 },
+	{ 0x7136, 0xB2 },
+	{ 0x7137, 0xFB },
+	{ 0x7138, 0x01 },
+	{ 0x7139, 0x22 },
+	{ 0x713A, 0x00 },
+	{ 0x713B, 0x23 },
+	{ 0x713C, 0x8C },
+	{ 0x713D, 0xF6 },
+	{ 0x713E, 0xE6 },
+	{ 0x713F, 0xF9 },
+	{ 0x7140, 0x02 },
+	{ 0x7141, 0x46 },
+	{ 0x7142, 0x07 },
+	{ 0x7143, 0x98 },
+	{ 0x7144, 0x00 },
+	{ 0x7145, 0x23 },
+	{ 0x7146, 0x81 },
+	{ 0x7147, 0x0B },
+	{ 0x7148, 0x80 },
+	{ 0x7149, 0x04 },
+	{ 0x714A, 0x7A },
+	{ 0x714B, 0xF6 },
+	{ 0x714C, 0x54 },
+	{ 0x714D, 0xF8 },
+	{ 0x714E, 0x37 },
+	{ 0x714F, 0x4A },
+	{ 0x7150, 0x00 },
+	{ 0x7151, 0x23 },
+	{ 0x7152, 0x00 },
+	{ 0x7153, 0x92 },
+	{ 0x7154, 0x01 },
+	{ 0x7155, 0x93 },
+	{ 0x7156, 0x01 },
+	{ 0x7157, 0x22 },
+	{ 0x7158, 0x8C },
+	{ 0x7159, 0xF6 },
+	{ 0x715A, 0xD8 },
+	{ 0x715B, 0xF9 },
+	{ 0x715C, 0x05 },
+	{ 0x715D, 0x46 },
+	{ 0x715E, 0x60 },
+	{ 0x715F, 0x68 },
+	{ 0x7160, 0x00 },
+	{ 0x7161, 0x23 },
+	{ 0x7162, 0x01 },
+	{ 0x7163, 0x0C },
+	{ 0x7164, 0x00 },
+	{ 0x7165, 0x04 },
+	{ 0x7166, 0xE2 },
+	{ 0x7167, 0x68 },
+	{ 0x7168, 0x7A },
+	{ 0x7169, 0xF6 },
+	{ 0x716A, 0x45 },
+	{ 0x716B, 0xF8 },
+	{ 0x716C, 0x00 },
+	{ 0x716D, 0x22 },
+	{ 0x716E, 0xD2 },
+	{ 0x716F, 0x43 },
+	{ 0x7170, 0x00 },
+	{ 0x7171, 0x23 },
+	{ 0x7172, 0x00 },
+	{ 0x7173, 0x92 },
+	{ 0x7174, 0x01 },
+	{ 0x7175, 0x93 },
+	{ 0x7176, 0x1A },
+	{ 0x7177, 0x46 },
+	{ 0x7178, 0x8C },
+	{ 0x7179, 0xF6 },
+	{ 0x717A, 0xC8 },
+	{ 0x717B, 0xF9 },
+	{ 0x717C, 0x29 },
+	{ 0x717D, 0x46 },
+	{ 0x717E, 0x8F },
+	{ 0x717F, 0xF6 },
+	{ 0x7180, 0x8D },
+	{ 0x7181, 0xFB },
+	{ 0x7182, 0x8A },
+	{ 0x7183, 0x03 },
+	{ 0x7184, 0x80 },
+	{ 0x7185, 0x0C },
+	{ 0x7186, 0x10 },
+	{ 0x7187, 0x43 },
+	{ 0x7188, 0x00 },
+	{ 0x7189, 0x22 },
+	{ 0x718A, 0xD2 },
+	{ 0x718B, 0x43 },
+	{ 0x718C, 0x00 },
+	{ 0x718D, 0x23 },
+	{ 0x718E, 0x00 },
+	{ 0x718F, 0x92 },
+	{ 0x7190, 0x89 },
+	{ 0x7191, 0x0C },
+	{ 0x7192, 0x01 },
+	{ 0x7193, 0x93 },
+	{ 0x7194, 0x1A },
+	{ 0x7195, 0x46 },
+	{ 0x7196, 0x8C },
+	{ 0x7197, 0xF6 },
+	{ 0x7198, 0xB9 },
+	{ 0x7199, 0xF9 },
+	{ 0x719A, 0x00 },
+	{ 0x719B, 0x24 },
+	{ 0x719C, 0x03 },
+	{ 0x719D, 0x90 },
+	{ 0x719E, 0x0C },
+	{ 0x719F, 0x98 },
+	{ 0x71A0, 0x61 },
+	{ 0x71A1, 0x00 },
+	{ 0x71A2, 0x45 },
+	{ 0x71A3, 0x5A },
+	{ 0x71A4, 0x06 },
+	{ 0x71A5, 0x98 },
+	{ 0x71A6, 0x22 },
+	{ 0x71A7, 0x4A },
+	{ 0x71A8, 0x40 },
+	{ 0x71A9, 0x5A },
+	{ 0x71AA, 0x00 },
+	{ 0x71AB, 0x21 },
+	{ 0x71AC, 0x8C },
+	{ 0x71AD, 0xF6 },
+	{ 0x71AE, 0xBE },
+	{ 0x71AF, 0xF9 },
+	{ 0x71B0, 0x07 },
+	{ 0x71B1, 0x46 },
+	{ 0x71B2, 0x28 },
+	{ 0x71B3, 0x46 },
+	{ 0x71B4, 0x03 },
+	{ 0x71B5, 0x99 },
+	{ 0x71B6, 0x8F },
+	{ 0x71B7, 0xF6 },
+	{ 0x71B8, 0x71 },
+	{ 0x71B9, 0xFB },
+	{ 0x71BA, 0x3A },
+	{ 0x71BB, 0x46 },
+	{ 0x71BC, 0x00 },
+	{ 0x71BD, 0x23 },
+	{ 0x71BE, 0x79 },
+	{ 0x71BF, 0xF6 },
+	{ 0x71C0, 0xCA },
+	{ 0x71C1, 0xFF },
+	{ 0x71C2, 0x00 },
+	{ 0x71C3, 0xE0 },
+	{ 0x71C4, 0x0F },
+	{ 0x71C5, 0xE0 },
+	{ 0x71C6, 0x8A },
+	{ 0x71C7, 0x02 },
+	{ 0x71C8, 0x80 },
+	{ 0x71C9, 0x0D },
+	{ 0x71CA, 0x10 },
+	{ 0x71CB, 0x43 },
+	{ 0x71CC, 0x19 },
+	{ 0x71CD, 0x4A },
+	{ 0x71CE, 0x00 },
+	{ 0x71CF, 0x23 },
+	{ 0x71D0, 0x00 },
+	{ 0x71D1, 0x92 },
+	{ 0x71D2, 0x89 },
+	{ 0x71D3, 0x0D },
+	{ 0x71D4, 0x01 },
+	{ 0x71D5, 0x93 },
+	{ 0x71D6, 0x40 },
+	{ 0x71D7, 0x22 },
+	{ 0x71D8, 0x8C },
+	{ 0x71D9, 0xF6 },
+	{ 0x71DA, 0x98 },
+	{ 0x71DB, 0xF9 },
+	{ 0x71DC, 0xA1 },
+	{ 0x71DD, 0x00 },
+	{ 0x71DE, 0x64 },
+	{ 0x71DF, 0x1C },
+	{ 0x71E0, 0x70 },
+	{ 0x71E1, 0x50 },
+	{ 0x71E2, 0x04 },
+	{ 0x71E3, 0x2C },
+	{ 0x71E4, 0xDB },
+	{ 0x71E5, 0xD3 },
+	{ 0x71E6, 0x14 },
+	{ 0x71E7, 0x4D },
+	{ 0x71E8, 0x00 },
+	{ 0x71E9, 0x24 },
+	{ 0x71EA, 0x0B },
+	{ 0x71EB, 0x98 },
+	{ 0x71EC, 0x67 },
+	{ 0x71ED, 0x00 },
+	{ 0x71EE, 0xC0 },
+	{ 0x71EF, 0x5B },
+	{ 0x71F0, 0x2A },
+	{ 0x71F1, 0x46 },
+	{ 0x71F2, 0x40 },
+	{ 0x71F3, 0x21 },
+	{ 0x71F4, 0x8C },
+	{ 0x71F5, 0xF6 },
+	{ 0x71F6, 0x9A },
+	{ 0x71F7, 0xF9 },
+	{ 0x71F8, 0x05 },
+	{ 0x71F9, 0x99 },
+	{ 0x71FA, 0x0E },
+	{ 0x71FB, 0x4A },
+	{ 0x71FC, 0xC8 },
+	{ 0x71FD, 0x53 },
+	{ 0x71FE, 0xA7 },
+	{ 0x71FF, 0x00 },
+	{ 0x7200, 0xF0 },
+	{ 0x7201, 0x59 },
+	{ 0x7202, 0x40 },
+	{ 0x7203, 0x21 },
+	{ 0x7204, 0x8C },
+	{ 0x7205, 0xF6 },
+	{ 0x7206, 0x7B },
+	{ 0x7207, 0xF9 },
+	{ 0x7208, 0x04 },
+	{ 0x7209, 0x99 },
+	{ 0x720A, 0x64 },
+	{ 0x720B, 0x1C },
+	{ 0x720C, 0xC8 },
+	{ 0x720D, 0x51 },
+	{ 0x720E, 0x04 },
+	{ 0x720F, 0x2C },
+	{ 0x7210, 0xEB },
+	{ 0x7211, 0xD3 },
+	{ 0x7212, 0x0F },
+	{ 0x7213, 0xB0 },
+	{ 0x7214, 0xF0 },
+	{ 0x7215, 0xBD },
+	{ 0x7216, 0x00 },
+	{ 0x7217, 0x00 },
+	{ 0x7218, 0x76 },
+	{ 0x7219, 0x69 },
+	{ 0x721A, 0x18 },
+	{ 0x721B, 0x00 },
+	{ 0x721C, 0xEC },
+	{ 0x721D, 0x58 },
+	{ 0x721E, 0x18 },
+	{ 0x721F, 0x00 },
+	{ 0x7220, 0x38 },
+	{ 0x7221, 0x36 },
+	{ 0x7222, 0x18 },
+	{ 0x7223, 0x00 },
+	{ 0x7224, 0x00 },
+	{ 0x7225, 0x35 },
+	{ 0x7226, 0x18 },
+	{ 0x7227, 0x00 },
+	{ 0x7228, 0x00 },
+	{ 0x7229, 0x20 },
+	{ 0x722A, 0x18 },
+	{ 0x722B, 0x00 },
+	{ 0x722C, 0xFF },
+	{ 0x722D, 0xFF },
+	{ 0x722E, 0xFF },
+	{ 0x722F, 0x3F },
+	{ 0x7230, 0xFF },
+	{ 0x7231, 0x07 },
+	{ 0x7232, 0x00 },
+	{ 0x7233, 0x00 },
+	{ 0x7234, 0xFF },
+	{ 0x7235, 0xFF },
+	{ 0x7236, 0x07 },
+	{ 0x7237, 0x00 },
+	{ 0x7238, 0xFF },
+	{ 0x7239, 0x1F },
+	{ 0x723A, 0x00 },
+	{ 0x723B, 0x00 },
+	{ 0x723C, 0x01 },
+	{ 0x723D, 0xF6 },
+	{ 0x723E, 0x45 },
+	{ 0x723F, 0x12 },
+};
+
+static const struct reg_sequence imx390_linear_1936x1096[] = {
+	{ 0x000C, 0xF2 },
+	{ 0x000D, 0x02 },
+	{ 0x000E, 0x00 },
+	{ 0x0010, 0xF2 },
+	{ 0x0011, 0x02 },
+	{ 0x0012, 0x00 },
+	{ 0x0018, 0x0F },
+	{ 0x0019, 0x00 },
+	{ 0x001A, 0x0C },
+	{ 0x001B, 0x00 },
+	{ 0x0038, 0x00 },
+	{ 0x003C, 0x00 }, /* OBB_CLAMP_R_SP1H */
+	{ 0x003D, 0x00 }, /* OBB_CLAMP_R_SP1H */
+	{ 0x003E, 0x00 },
+	{ 0x0040, 0x00 }, /* OBB_CLAMP_GR_SP1H */
+	{ 0x0041, 0x00 }, /* OBB_CLAMP_GR_SP1H */
+	{ 0x0042, 0x00 },
+	{ 0x0044, 0x00 }, /* OBB_CLAMP_GB_SP1H */
+	{ 0x0045, 0x00 }, /* OBB_CLAMP_GB_SP1H */
+	{ 0x0046, 0x00 },
+	{ 0x0048, 0x00 },
+	{ 0x0049, 0x00 },
+	{ 0x004A, 0x00 },
+	{ 0x004C, 0x00 },
+	{ 0x004D, 0x00 },
+	{ 0x004E, 0x00 },
+	{ 0x0050, 0x00 },
+	{ 0x0051, 0x00 },
+	{ 0x0052, 0x00 },
+	{ 0x0054, 0x00 },
+	{ 0x0055, 0x00 },
+	{ 0x0056, 0x00 },
+	{ 0x0058, 0x00 },
+	{ 0x0059, 0x00 },
+	{ 0x005A, 0x00 },
+	{ 0x005C, 0x00 },
+	{ 0x005D, 0x00 },
+	{ 0x005E, 0x00 },
+	{ 0x0060, 0x00 },
+	{ 0x0061, 0x00 },
+	{ 0x0062, 0x00 },
+	{ 0x0064, 0x00 },
+	{ 0x0065, 0x00 },
+	{ 0x0066, 0x00 },
+	{ 0x0068, 0x00 },
+	{ 0x0069, 0x00 },
+	{ 0x006A, 0x00 },
+	{ 0x0074, 0x00 },
+	{ 0x0078, 0x00 },
+	{ 0x007C, 0x00 },
+	{ 0x007D, 0x00 },
+	{ 0x0080, 0x00 },
+	{ 0x0081, 0x00 },
+	{ 0x00F4, 0x1C },
+	{ 0x00F5, 0xF8 },
+	{ 0x00F6, 0x01 },
+	{ 0x00F8, 0x03 },
+	{ 0x00F9, 0x00 },
+	{ 0x00FA, 0x00 },
+	{ 0x00FB, 0x00 },
+	{ 0x0114, 0x00 },
+	{ 0x0115, 0x01 },
+	{ 0x0118, 0x20 },
+	{ 0x0119, 0x03 },
+	{ 0x011A, 0x00 },
+	{ 0x011B, 0x41 },
+	{ 0x011C, 0x80 },
+	{ 0x011D, 0x00 },
+	{ 0x0120, 0x20 },
+	{ 0x0121, 0x00 },
+	{ 0x0122, 0x00 },
+	{ 0x0123, 0x44 },
+	{ 0x0124, 0x00 },
+	{ 0x0125, 0x01 },
+	{ 0x0128, 0xAC },
+	{ 0x0129, 0x0D },
+	{ 0x012A, 0x00 },
+	{ 0x012B, 0xA4 },
+	{ 0x012C, 0x00 },
+	{ 0x012D, 0x01 },
+	{ 0x0130, 0xC4 },
+	{ 0x0131, 0x09 },
+	{ 0x0132, 0x00 },
+	{ 0x0133, 0xDA },
+	{ 0x013B, 0x01 },
+	{ 0x01C4, 0x00 },
+	{ 0x01C5, 0x00 },
+	{ 0x01CC, 0x01 },
+	{ 0x01D0, 0x09 },
+	{ 0x01D4, 0x01 },
+	{ 0x0232, 0x18 },
+	{ 0x0233, 0x00 },
+	{ 0x0390, 0x00 },
+	{ 0x0391, 0x00 },
+	{ 0x0392, 0x00 },
+	{ 0x03C0, 0x04 },
+	{ 0x2000, 0x55 },
+	{ 0x2001, 0x55 },
+	{ 0x2002, 0x55 },
+	{ 0x2003, 0x05 },
+	{ 0x2004, 0x02 },
+	{ 0x2008, 0x65 },
+	{ 0x2009, 0x04 },
+	{ 0x200A, 0x00 },
+	{ 0x200C, 0x30 },
+	{ 0x200D, 0x11 },
+	{ 0x2010, 0x04 },
+	{ 0x2014, 0x01 },
+	{ 0x2018, 0x02 },
+	{ 0x2019, 0x04 },
+	{ 0x201A, 0x00 },
+	{ 0x201C, 0x21 },
+	{ 0x201D, 0x11 },
+	{ 0x201E, 0x00 },
+	{ 0x201F, 0x00 },
+	{ 0x2020, 0xBC },
+	{ 0x2021, 0x00 },
+	{ 0x2022, 0x7F },
+	{ 0x2023, 0x00 },
+	{ 0x2024, 0xBA },
+	{ 0x2025, 0x00 },
+	{ 0x2026, 0x81 },
+	{ 0x2027, 0x00 },
+	{ 0x2028, 0x7D },
+	{ 0x2029, 0x90 },
+	{ 0x202A, 0x05 },
+	{ 0x202C, 0xFC },
+	{ 0x202D, 0x02 },
+	{ 0x202E, 0x25 },
+	{ 0x202F, 0x03 },
+	{ 0x2030, 0x05 },
+	{ 0x2031, 0x02 },
+	{ 0x2032, 0xCA },
+	{ 0x2033, 0x02 },
+	{ 0x2034, 0xFC },
+	{ 0x2035, 0x02 },
+	{ 0x2036, 0x25 },
+	{ 0x2037, 0x03 },
+	{ 0x2038, 0x25 },
+	{ 0x2039, 0x97 },
+	{ 0x203A, 0xEC },
+	{ 0x203B, 0x01 },
+	{ 0x203C, 0xF5 },
+	{ 0x203D, 0x8E },
+	{ 0x203E, 0x0C },
+	{ 0x203F, 0x2D },
+	{ 0x2040, 0x69 },
+	{ 0x2041, 0x01 },
+	{ 0x2042, 0x8E },
+	{ 0x2043, 0x01 },
+	{ 0x2044, 0x0C },
+	{ 0x2045, 0x02 },
+	{ 0x2046, 0x31 },
+	{ 0x2047, 0x02 },
+	{ 0x2048, 0x6A },
+	{ 0x2049, 0x01 },
+	{ 0x204A, 0x8E },
+	{ 0x204B, 0x01 },
+	{ 0x204C, 0x0D },
+	{ 0x204D, 0x02 },
+	{ 0x204E, 0x31 },
+	{ 0x204F, 0x02 },
+	{ 0x2050, 0x7B },
+	{ 0x2051, 0x00 },
+	{ 0x2052, 0x7D },
+	{ 0x2053, 0x00 },
+	{ 0x2054, 0x95 },
+	{ 0x2055, 0x00 },
+	{ 0x2056, 0x97 },
+	{ 0x2057, 0x00 },
+	{ 0x2058, 0xAD },
+	{ 0x2059, 0x00 },
+	{ 0x205A, 0xAF },
+	{ 0x205B, 0x00 },
+	{ 0x205C, 0x92 },
+	{ 0x205D, 0x00 },
+	{ 0x205E, 0x94 },
+	{ 0x205F, 0x00 },
+	{ 0x2060, 0x8E },
+	{ 0x2061, 0x00 },
+	{ 0x2062, 0x90 },
+	{ 0x2063, 0x00 },
+	{ 0x2064, 0xB1 },
+	{ 0x2065, 0x00 },
+	{ 0x2066, 0xB3 },
+	{ 0x2067, 0x00 },
+	{ 0x2068, 0x08 },
+	{ 0x2069, 0x00 },
+	{ 0x206A, 0x04 },
+	{ 0x206B, 0x00 },
+	{ 0x206C, 0x84 },
+	{ 0x206D, 0x00 },
+	{ 0x206E, 0x80 },
+	{ 0x206F, 0x00 },
+	{ 0x2070, 0x04 },
+	{ 0x2071, 0x00 },
+	{ 0x2072, 0x46 },
+	{ 0x2073, 0x00 },
+	{ 0x2074, 0xE9 },
+	{ 0x2075, 0x01 },
+	{ 0x2076, 0x74 },
+	{ 0x2077, 0x02 },
+	{ 0x2078, 0x80 },
+	{ 0x2079, 0x00 },
+	{ 0x207A, 0xC1 },
+	{ 0x207B, 0x00 },
+	{ 0x207C, 0xFF },
+	{ 0x207D, 0x03 },
+	{ 0x207E, 0xFF },
+	{ 0x207F, 0x03 },
+	{ 0x2080, 0x78 },
+	{ 0x2081, 0x00 },
+	{ 0x2082, 0x6A },
+	{ 0x2083, 0x01 },
+	{ 0x2084, 0xE4 },
+	{ 0x2085, 0x01 },
+	{ 0x2086, 0x2B },
+	{ 0x2087, 0x03 },
+	{ 0x2088, 0x00 },
+	{ 0x2089, 0x00 },
+	{ 0x208A, 0xFF },
+	{ 0x208B, 0x03 },
+	{ 0x208C, 0xFF },
+	{ 0x208D, 0x03 },
+	{ 0x208E, 0xFF },
+	{ 0x208F, 0x03 },
+	{ 0x2090, 0x7D },
+	{ 0x2091, 0x00 },
+	{ 0x2092, 0x62 },
+	{ 0x2093, 0x01 },
+	{ 0x2094, 0xE9 },
+	{ 0x2095, 0x01 },
+	{ 0x2096, 0x00 },
+	{ 0x2097, 0x00 },
+	{ 0x2098, 0x7C },
+	{ 0x2099, 0x00 },
+	{ 0x209A, 0x21 },
+	{ 0x209B, 0x03 },
+	{ 0x209C, 0xE9 },
+	{ 0x209D, 0x01 },
+	{ 0x209E, 0x21 },
+	{ 0x209F, 0x03 },
+	{ 0x20A0, 0xFF },
+	{ 0x20A1, 0x03 },
+	{ 0x20A2, 0xFF },
+	{ 0x20A3, 0x03 },
+	{ 0x20A4, 0xFF },
+	{ 0x20A5, 0x03 },
+	{ 0x20A6, 0xFF },
+	{ 0x20A7, 0x03 },
+	{ 0x20A8, 0xFF },
+	{ 0x20A9, 0x03 },
+	{ 0x20AA, 0xFF },
+	{ 0x20AB, 0x03 },
+	{ 0x20AC, 0xFF },
+	{ 0x20AD, 0x03 },
+	{ 0x20AE, 0xFF },
+	{ 0x20AF, 0x03 },
+	{ 0x20B0, 0xFF },
+	{ 0x20B1, 0x03 },
+	{ 0x20B2, 0xFF },
+	{ 0x20B3, 0x03 },
+	{ 0x20B4, 0x87 },
+	{ 0x20B5, 0xCC },
+	{ 0x20B6, 0x87 },
+	{ 0x20B7, 0x08 },
+	{ 0x20B8, 0xF4 },
+	{ 0x20B9, 0xA5 },
+	{ 0x20BA, 0x07 },
+	{ 0x20BC, 0x1F },
+	{ 0x20BD, 0x01 },
+	{ 0x20BE, 0xF6 },
+	{ 0x20BF, 0x00 },
+	{ 0x20C0, 0x90 },
+	{ 0x20C1, 0x01 },
+	{ 0x20C2, 0x67 },
+	{ 0x20C3, 0x01 },
+	{ 0x20C4, 0xFF },
+	{ 0x20C5, 0x03 },
+	{ 0x20C6, 0xFF },
+	{ 0x20C7, 0x03 },
+	{ 0x20C8, 0x33 },
+	{ 0x20C9, 0x02 },
+	{ 0x20CA, 0x0A },
+	{ 0x20CB, 0x02 },
+	{ 0x20CC, 0x7F },
+	{ 0x20CD, 0x00 },
+	{ 0x20CE, 0xD2 },
+	{ 0x20CF, 0x00 },
+	{ 0x20D0, 0x81 },
+	{ 0x20D1, 0x00 },
+	{ 0x20D2, 0x87 },
+	{ 0x20D3, 0x00 },
+	{ 0x20D4, 0x09 },
+	{ 0x20D5, 0x00 },
+	{ 0x20D8, 0x7F },
+	{ 0x20D9, 0x00 },
+	{ 0x20DA, 0x62 },
+	{ 0x20DB, 0x01 },
+	{ 0x20DC, 0x7F },
+	{ 0x20DD, 0x00 },
+	{ 0x20DE, 0x62 },
+	{ 0x20DF, 0x01 },
+	{ 0x20E0, 0x65 },
+	{ 0x20E1, 0x00 },
+	{ 0x20E2, 0x75 },
+	{ 0x20E3, 0x00 },
+	{ 0x20E4, 0xE0 },
+	{ 0x20E5, 0x00 },
+	{ 0x20E6, 0xF0 },
+	{ 0x20E7, 0x00 },
+	{ 0x20E8, 0x4C },
+	{ 0x20E9, 0x01 },
+	{ 0x20EA, 0x5C },
+	{ 0x20EB, 0x01 },
+	{ 0x20EC, 0xD1 },
+	{ 0x20ED, 0x01 },
+	{ 0x20EE, 0xE1 },
+	{ 0x20EF, 0x01 },
+	{ 0x20F0, 0x93 },
+	{ 0x20F1, 0x02 },
+	{ 0x20F2, 0xA3 },
+	{ 0x20F3, 0x02 },
+	{ 0x20F4, 0x0D },
+	{ 0x20F5, 0x03 },
+	{ 0x20F6, 0x1D },
+	{ 0x20F7, 0x03 },
+	{ 0x20F8, 0x57 },
+	{ 0x20F9, 0x00 },
+	{ 0x20FA, 0x7B },
+	{ 0x20FB, 0x00 },
+	{ 0x20FC, 0xD2 },
+	{ 0x20FD, 0x00 },
+	{ 0x20FE, 0xF6 },
+	{ 0x20FF, 0x00 },
+	{ 0x2100, 0x3E },
+	{ 0x2101, 0x01 },
+	{ 0x2102, 0x60 },
+	{ 0x2103, 0x01 },
+	{ 0x2104, 0xC3 },
+	{ 0x2105, 0x01 },
+	{ 0x2106, 0xE5 },
+	{ 0x2107, 0x01 },
+	{ 0x2108, 0x85 },
+	{ 0x2109, 0x02 },
+	{ 0x210A, 0xA9 },
+	{ 0x210B, 0x02 },
+	{ 0x210C, 0xFF },
+	{ 0x210D, 0x02 },
+	{ 0x210E, 0x21 },
+	{ 0x210F, 0x03 },
+	{ 0x2110, 0xFF },
+	{ 0x2111, 0x03 },
+	{ 0x2112, 0x00 },
+	{ 0x2113, 0x00 },
+	{ 0x2114, 0xFF },
+	{ 0x2115, 0x03 },
+	{ 0x2116, 0xFF },
+	{ 0x2117, 0x03 },
+	{ 0x2118, 0xFF },
+	{ 0x2119, 0x03 },
+	{ 0x211A, 0xFF },
+	{ 0x211B, 0x03 },
+	{ 0x211C, 0xFF },
+	{ 0x211D, 0x03 },
+	{ 0x211E, 0xFF },
+	{ 0x211F, 0x03 },
+	{ 0x2120, 0xFF },
+	{ 0x2121, 0x03 },
+	{ 0x2122, 0xFF },
+	{ 0x2123, 0x03 },
+	{ 0x2124, 0xFF },
+	{ 0x2125, 0x03 },
+	{ 0x2126, 0xFF },
+	{ 0x2127, 0x03 },
+	{ 0x2128, 0x7D },
+	{ 0x2129, 0x90 },
+	{ 0x212A, 0xD5 },
+	{ 0x212B, 0x07 },
+	{ 0x212C, 0x64 },
+	{ 0x212D, 0x01 },
+	{ 0x2130, 0x5F },
+	{ 0x2131, 0x7D },
+	{ 0x2132, 0x05 },
+	{ 0x2134, 0x78 },
+	{ 0x2135, 0x00 },
+	{ 0x2136, 0x76 },
+	{ 0x2137, 0x00 },
+	{ 0x2138, 0xF3 },
+	{ 0x2139, 0x00 },
+	{ 0x213A, 0xF1 },
+	{ 0x213B, 0x00 },
+	{ 0x213C, 0xA6 },
+	{ 0x213D, 0x02 },
+	{ 0x213E, 0xA4 },
+	{ 0x213F, 0x02 },
+	{ 0x2140, 0x7D },
+	{ 0x2141, 0x00 },
+	{ 0x2142, 0x8D },
+	{ 0x2143, 0x00 },
+	{ 0x2144, 0xA1 },
+	{ 0x2145, 0x01 },
+	{ 0x2146, 0xB1 },
+	{ 0x2147, 0x01 },
+	{ 0x2148, 0xAB },
+	{ 0x2149, 0x02 },
+	{ 0x214A, 0xBB },
+	{ 0x214B, 0x02 },
+	{ 0x214C, 0x17 },
+	{ 0x214D, 0x5C },
+	{ 0x214E, 0x00 },
+	{ 0x2150, 0x00 },
+	{ 0x2151, 0x00 },
+	{ 0x2152, 0xF8 },
+	{ 0x2153, 0x00 },
+	{ 0x2154, 0xBE },
+	{ 0x2155, 0x00 },
+	{ 0x2156, 0x7D },
+	{ 0x2157, 0x00 },
+	{ 0x2158, 0x25 },
+	{ 0x2159, 0x00 },
+	{ 0x215A, 0x7D },
+	{ 0x215B, 0x00 },
+	{ 0x215C, 0x62 },
+	{ 0x215D, 0x01 },
+	{ 0x215E, 0xFF },
+	{ 0x215F, 0x03 },
+	{ 0x2160, 0x26 },
+	{ 0x2161, 0x00 },
+	{ 0x2162, 0x7D },
+	{ 0x2163, 0x00 },
+	{ 0x2164, 0x63 },
+	{ 0x2165, 0x01 },
+	{ 0x2166, 0xFF },
+	{ 0x2167, 0x03 },
+	{ 0x2168, 0xCB },
+	{ 0x2169, 0x02 },
+	{ 0x216A, 0xCF },
+	{ 0x216B, 0x02 },
+	{ 0x216C, 0xFF },
+	{ 0x216D, 0x03 },
+	{ 0x216E, 0xFF },
+	{ 0x216F, 0x03 },
+	{ 0x2170, 0xFF },
+	{ 0x2171, 0x03 },
+	{ 0x2172, 0xFF },
+	{ 0x2173, 0x03 },
+	{ 0x2174, 0xFF },
+	{ 0x2175, 0x03 },
+	{ 0x2176, 0xFF },
+	{ 0x2177, 0x03 },
+	{ 0x2178, 0x7E },
+	{ 0x2179, 0x00 },
+	{ 0x217A, 0xBD },
+	{ 0x217B, 0x00 },
+	{ 0x217C, 0xEC },
+	{ 0x217D, 0x01 },
+	{ 0x217E, 0x7B },
+	{ 0x217F, 0x02 },
+	{ 0x2180, 0xD1 },
+	{ 0x2181, 0x02 },
+	{ 0x2182, 0x25 },
+	{ 0x2183, 0x03 },
+	{ 0x2184, 0x7F },
+	{ 0x2185, 0x00 },
+	{ 0x2186, 0xBD },
+	{ 0x2187, 0x00 },
+	{ 0x2188, 0xED },
+	{ 0x2189, 0x01 },
+	{ 0x218A, 0x7B },
+	{ 0x218B, 0x02 },
+	{ 0x218C, 0xD2 },
+	{ 0x218D, 0x02 },
+	{ 0x218E, 0x25 },
+	{ 0x218F, 0x03 },
+	{ 0x2190, 0xFF },
+	{ 0x2191, 0x03 },
+	{ 0x2192, 0xFF },
+	{ 0x2193, 0x03 },
+	{ 0x2194, 0xE9 },
+	{ 0x2195, 0x01 },
+	{ 0x2196, 0x21 },
+	{ 0x2197, 0x03 },
+	{ 0x2198, 0x17 },
+	{ 0x2199, 0xFC },
+	{ 0x219A, 0x7F },
+	{ 0x219B, 0x01 },
+	{ 0x219C, 0xFF },
+	{ 0x219D, 0x03 },
+	{ 0x21A0, 0x1B },
+	{ 0x21A1, 0x1B },
+	{ 0x21A2, 0x1B },
+	{ 0x21A3, 0x1B },
+	{ 0x21A4, 0x2E },
+	{ 0x21A5, 0x80 },
+	{ 0x21A6, 0x00 },
+	{ 0x21A8, 0x04 },
+	{ 0x21A9, 0x98 },
+	{ 0x21AA, 0x60 },
+	{ 0x21AB, 0x03 },
+	{ 0x21AC, 0x7F },
+	{ 0x21AD, 0x80 },
+	{ 0x21AE, 0x09 },
+	{ 0x21B0, 0x1C },
+	{ 0x21B1, 0x00 },
+	{ 0x21B2, 0xA0 },
+	{ 0x21B3, 0x00 },
+	{ 0x21B4, 0x0C },
+	{ 0x21B5, 0x00 },
+	{ 0x21B6, 0x2D },
+	{ 0x21B7, 0x00 },
+	{ 0x21B8, 0x20 },
+	{ 0x21B9, 0x00 },
+	{ 0x21BA, 0x02 },
+	{ 0x21BB, 0x00 },
+	{ 0x21BC, 0xCC },
+	{ 0x21BD, 0x00 },
+	{ 0x21BE, 0x4A },
+	{ 0x21BF, 0x00 },
+	{ 0x21C0, 0xD0 },
+	{ 0x21C1, 0x00 },
+	{ 0x21C2, 0x44 },
+	{ 0x21C3, 0x00 },
+	{ 0x21C4, 0x00 },
+	{ 0x21C5, 0xE0 },
+	{ 0x21C6, 0x00 },
+	{ 0x21C8, 0x11 },
+	{ 0x21C9, 0x00 },
+	{ 0x21CA, 0x02 },
+	{ 0x21CC, 0x08 },
+	{ 0x21CD, 0xC0 },
+	{ 0x21CE, 0x0C },
+	{ 0x21D0, 0x44 },
+	{ 0x21D1, 0x00 },
+	{ 0x21D2, 0x02 },
+	{ 0x21D4, 0x02 },
+	{ 0x21D5, 0x20 },
+	{ 0x21D6, 0x2C },
+	{ 0x21D8, 0xFE },
+	{ 0x21D9, 0x9D },
+	{ 0x21DA, 0xDF },
+	{ 0x21DB, 0x03 },
+	{ 0x21DC, 0x62 },
+	{ 0x21DD, 0x01 },
+	{ 0x21DE, 0x7F },
+	{ 0x21DF, 0x00 },
+	{ 0x21E0, 0xB7 },
+	{ 0x21E1, 0x01 },
+	{ 0x21E2, 0xB5 },
+	{ 0x21E3, 0x01 },
+	{ 0x21E4, 0xC1 },
+	{ 0x21E5, 0x02 },
+	{ 0x21E6, 0xBF },
+	{ 0x21E7, 0x02 },
+	{ 0x21E8, 0xB3 },
+	{ 0x21E9, 0x0D },
+	{ 0x21EA, 0x00 },
+	{ 0x21EB, 0x04 },
+	{ 0x21EC, 0x90 },
+	{ 0x21ED, 0x07 },
+	{ 0x21EE, 0x58 },
+	{ 0x21EF, 0x04 },
+	{ 0x21F0, 0x54 },
+	{ 0x21F1, 0x04 },
+	{ 0x21F4, 0x02 },
+	{ 0x21F5, 0x00 },
+	{ 0x21F6, 0x00 },
+	{ 0x21F8, 0x3C },
+	{ 0x21F9, 0x00 },
+	{ 0x21FC, 0x28 },
+	{ 0x21FD, 0x00 },
+	{ 0x21FE, 0x3C },
+	{ 0x21FF, 0x00 },
+	{ 0x2200, 0x00 },
+	{ 0x2204, 0x4C },
+	{ 0x2205, 0x04 },
+	{ 0x2206, 0x65 },
+	{ 0x2207, 0x04 },
+	{ 0x2208, 0x0A },
+	{ 0x2209, 0x00 },
+	{ 0x220C, 0x47 },
+	{ 0x220D, 0x00 },
+	{ 0x220E, 0x1F },
+	{ 0x220F, 0x00 },
+	{ 0x2210, 0x17 },
+	{ 0x2211, 0x00 },
+	{ 0x2212, 0x0F },
+	{ 0x2213, 0x00 },
+	{ 0x2214, 0x17 },
+	{ 0x2215, 0x00 },
+	{ 0x2216, 0x47 },
+	{ 0x2217, 0x00 },
+	{ 0x2218, 0x0F },
+	{ 0x2219, 0x00 },
+	{ 0x221A, 0x0F },
+	{ 0x221B, 0x00 },
+	{ 0x221C, 0x03 },
+	{ 0x2220, 0x20 },
+	{ 0x2221, 0x20 },
+	{ 0x2222, 0x22 },
+	{ 0x2223, 0x02 },
+	{ 0x2224, 0xA7 },
+	{ 0x2225, 0xAA },
+	{ 0x2226, 0x80 },
+	{ 0x2227, 0x08 },
+	{ 0x2228, 0x01 },
+	{ 0x22B2, 0x92 },
+	{ 0x22B4, 0x20 },
+	{ 0x22B5, 0x00 },
+	{ 0x22B6, 0x20 },
+	{ 0x22B7, 0x00 },
+	{ 0x22B8, 0x20 },
+	{ 0x22B9, 0x00 },
+	{ 0x22BA, 0x20 },
+	{ 0x22BB, 0x00 },
+	{ 0x22BC, 0x20 },
+	{ 0x22BD, 0x00 },
+	{ 0x22BE, 0x20 },
+	{ 0x22BF, 0x00 },
+	{ 0x22C0, 0x20 },
+	{ 0x22C1, 0x00 },
+	{ 0x22C2, 0x20 },
+	{ 0x22C3, 0x00 },
+	{ 0x22C4, 0x20 },
+	{ 0x22C5, 0x00 },
+	{ 0x22C6, 0x20 },
+	{ 0x22C7, 0x00 },
+	{ 0x22C8, 0x20 },
+	{ 0x22C9, 0x00 },
+	{ 0x22CA, 0x20 },
+	{ 0x22CB, 0x00 },
+	{ 0x22CC, 0x20 },
+	{ 0x22CD, 0x00 },
+	{ 0x22CE, 0x20 },
+	{ 0x22CF, 0x00 },
+	{ 0x22DA, 0x00 },
+	{ 0x2308, 0x01 },
+	{ 0x2311, 0x09 },
+	{ 0x2318, 0x40 },
+	{ 0x2319, 0xCD },
+	{ 0x231A, 0x54 },
+	{ 0x2324, 0x10 },
+	{ 0x2325, 0x00 },
+	{ 0x2328, 0x00 },
+	{ 0x2354, 0x0C },
+	{ 0x23C0, 0x5D },
+	{ 0x244C, 0x00 },
+	{ 0x244D, 0x02 },
+	{ 0x244E, 0x54 },
+	{ 0x244F, 0x02 },
+	{ 0x24A0, 0x00 },
+	{ 0x24DA, 0x6F },
+	{ 0x24DB, 0x00 },
+	{ 0x24DC, 0x62 },
+	{ 0x24DD, 0x01 },
+	{ 0x24EA, 0x32 },
+	{ 0x24EB, 0x00 },
+	{ 0x24EC, 0xDC },
+	{ 0x24ED, 0x00 },
+	{ 0x24FA, 0x32 },
+	{ 0x24FB, 0x00 },
+	{ 0x24FC, 0xDD },
+	{ 0x24FD, 0x00 },
+	{ 0x254A, 0x15 },
+	{ 0x254B, 0x01 },
+	{ 0x255A, 0x15 },
+	{ 0x255B, 0x01 },
+	{ 0x2560, 0x01 },
+	{ 0x2561, 0x00 },
+	{ 0x2562, 0x2A },
+	{ 0x2563, 0x00 },
+	{ 0x2564, 0xF8 },
+	{ 0x2565, 0x00 },
+	{ 0x2566, 0x15 },
+	{ 0x2567, 0x01 },
+	{ 0x2568, 0x0C },
+	{ 0x2569, 0x02 },
+	{ 0x256A, 0x31 },
+	{ 0x256B, 0x02 },
+	{ 0x2578, 0x90 },
+	{ 0x2579, 0x01 },
+	{ 0x257A, 0x92 },
+	{ 0x257B, 0x01 },
+	{ 0x257C, 0xB8 },
+	{ 0x257D, 0x02 },
+	{ 0x257E, 0xBA },
+	{ 0x257F, 0x02 },
+	{ 0x2584, 0x90 },
+	{ 0x2585, 0x01 },
+	{ 0x2586, 0x92 },
+	{ 0x2587, 0x01 },
+	{ 0x2588, 0xB8 },
+	{ 0x2589, 0x02 },
+	{ 0x258A, 0xBA },
+	{ 0x258B, 0x02 },
+	{ 0x26B8, 0x10 },
+	{ 0x26B9, 0x00 },
+	{ 0x26BA, 0x33 },
+	{ 0x26BB, 0x00 },
+	{ 0x26BC, 0x89 },
+	{ 0x26BD, 0x00 },
+	{ 0x26BE, 0xB0 },
+	{ 0x26BF, 0x00 },
+	{ 0x26C4, 0x4E },
+	{ 0x26C5, 0x00 },
+	{ 0x26C8, 0xC9 },
+	{ 0x26C9, 0x00 },
+	{ 0x26CC, 0x35 },
+	{ 0x26CD, 0x01 },
+	{ 0x26D0, 0xBA },
+	{ 0x26D1, 0x01 },
+	{ 0x26D4, 0x7C },
+	{ 0x26D5, 0x02 },
+	{ 0x26D8, 0xF6 },
+	{ 0x26D9, 0x02 },
+	{ 0x26DE, 0x51 },
+	{ 0x26DF, 0x00 },
+	{ 0x26E0, 0x7F },
+	{ 0x26E1, 0x00 },
+	{ 0x26E2, 0xCC },
+	{ 0x26E3, 0x00 },
+	{ 0x26E4, 0xF8 },
+	{ 0x26E5, 0x00 },
+	{ 0x26E6, 0x38 },
+	{ 0x26E7, 0x01 },
+	{ 0x26E8, 0x65 },
+	{ 0x26E9, 0x01 },
+	{ 0x26EA, 0xBD },
+	{ 0x26EB, 0x01 },
+	{ 0x26EE, 0x7F },
+	{ 0x26EF, 0x02 },
+	{ 0x26F0, 0xAB },
+	{ 0x26F1, 0x02 },
+	{ 0x26F2, 0xF9 },
+	{ 0x26F3, 0x02 },
+	{ 0x2722, 0x59 },
+	{ 0x2723, 0x02 },
+	{ 0x2938, 0x55 },
+	{ 0x2939, 0x00 },
+	{ 0x293A, 0x17 },
+	{ 0x293B, 0x00 },
+	{ 0x293C, 0xD0 },
+	{ 0x293D, 0x00 },
+	{ 0x293E, 0x91 },
+	{ 0x293F, 0x00 },
+	{ 0x2940, 0x3C },
+	{ 0x2941, 0x01 },
+	{ 0x2942, 0x0C },
+	{ 0x2943, 0x01 },
+	{ 0x2944, 0xC1 },
+	{ 0x2945, 0x01 },
+	{ 0x2946, 0x76 },
+	{ 0x2947, 0x01 },
+	{ 0x2948, 0x83 },
+	{ 0x2949, 0x02 },
+	{ 0x294A, 0xFB },
+	{ 0x294B, 0x01 },
+	{ 0x294C, 0xFD },
+	{ 0x294D, 0x02 },
+	{ 0x294E, 0xBF },
+	{ 0x294F, 0x02 },
+	{ 0x2A06, 0xFF },
+	{ 0x2A07, 0x03 },
+	{ 0x2A20, 0x00 },
+	{ 0x2A21, 0x00 },
+	{ 0x2A22, 0x7D },
+	{ 0x2A23, 0x00 },
+	{ 0x2B11, 0x19 },
+	{ 0x2B13, 0x15 },
+	{ 0x2B14, 0x14 },
+	{ 0x2B15, 0x13 },
+	{ 0x2B16, 0x12 },
+	{ 0x2B17, 0x11 },
+	{ 0x2B18, 0x10 },
+	{ 0x2B19, 0x0F },
+	{ 0x2B1A, 0x0E },
+	{ 0x2B1B, 0x0D },
+	{ 0x2B1C, 0x0C },
+	{ 0x2B1D, 0x0B },
+	{ 0x2B1E, 0x0A },
+	{ 0x2B1F, 0x09 },
+	{ 0x2B20, 0x08 },
+	{ 0x2B21, 0x07 },
+	{ 0x2B22, 0x06 },
+	{ 0x2B23, 0x05 },
+	{ 0x2B24, 0x04 },
+	{ 0x2B25, 0x03 },
+	{ 0x2B26, 0x03 },
+	{ 0x2B38, 0x01 },
+	{ 0x2B45, 0xE3 },
+	{ 0x2B50, 0x01 },
+	{ 0x2B51, 0x00 },
+	{ 0x2B6D, 0x47 },
+	{ 0x2B70, 0x02 },
+	{ 0x2B71, 0x02 },
+	{ 0x2B72, 0x02 },
+	{ 0x2B7F, 0x7F },
+	{ 0x2B80, 0x94 },
+	{ 0x2B81, 0x06 },
+	{ 0x2B87, 0x1B },
+	{ 0x2B88, 0x1B },
+	{ 0x2B89, 0x17 },
+	{ 0x2B8A, 0x12 },
+	{ 0x2B8B, 0x12 },
+	{ 0x2B8D, 0x2B },
+	{ 0x2B8E, 0x2B },
+	{ 0x2B8F, 0x2B },
+	{ 0x2B90, 0x7F },
+	{ 0x2B91, 0x1F },
+	{ 0x2B94, 0x7F },
+	{ 0x2B95, 0x27 },
+	{ 0x2B98, 0x7F },
+	{ 0x2B99, 0x57 },
+	{ 0x2BA8, 0xBC },
+	{ 0x2BA9, 0x62 },
+	{ 0x2BC1, 0x70 },
+	{ 0x2BC5, 0x80 },
+	{ 0x2BD5, 0x30 },
+	{ 0x2BD6, 0xF0 },
+	{ 0x2BD8, 0xDB },
+	{ 0x2BD9, 0xF6 },
+	{ 0x2BDA, 0x63 },
+	{ 0x2BDB, 0x0C },
+	{ 0x2BDC, 0x5C },
+	{ 0x2C98, 0xE1 },
+	{ 0x2C99, 0x2E },
+	{ 0x2C9B, 0x86 },
+	{ 0x2CA9, 0x80 },
+	{ 0x2CAA, 0x01 },
+	{ 0x2D39, 0x0E },
+	{ 0x2D54, 0x00 },
+	{ 0x2D5B, 0x58 },
+	{ 0x2D64, 0x64 },
+	{ 0x2D65, 0x80 },
+	{ 0x3000, 0x00 },
+	{ 0x3001, 0x00 },
+	{ 0x3002, 0x23 },
+	{ 0x3003, 0xA1 },
+	{ 0x3004, 0x00 },
+	{ 0x3005, 0x20 },
+	{ 0x3006, 0x84 },
+	{ 0x3007, 0x00 },
+	{ 0x3008, 0x06 },
+	{ 0x3009, 0xB4 },
+	{ 0x300A, 0x1F },
+	{ 0x300B, 0x00 },
+	{ 0x300C, 0x00 },
+	{ 0x300D, 0x1B },
+	{ 0x300E, 0x90 },
+	{ 0x300F, 0x97 },
+	{ 0x3010, 0x00 },
+	{ 0x3011, 0x00 },
+	{ 0x3012, 0x21 },
+	{ 0x3013, 0x21 },
+	{ 0x3014, 0x00 },
+	{ 0x3015, 0x20 },
+	{ 0x3016, 0x84 },
+	{ 0x3017, 0x00 },
+	{ 0x3018, 0x30 },
+	{ 0x3019, 0x09 },
+	{ 0x301A, 0x46 },
+	{ 0x301B, 0x00 },
+	{ 0x3070, 0xC1 },
+	{ 0x3071, 0x81 },
+	{ 0x3072, 0x29 },
+	{ 0x3073, 0x81 },
+	{ 0x3410, (IMX390_OUT_WIDTH & 0xFF) },
+	{ 0x3411, (IMX390_OUT_WIDTH >> 8) },
+	{ 0x3418, (IMX390_OUT_HEIGHT & 0xFF) },
+	{ 0x3419, (IMX390_OUT_HEIGHT >> 8) },
+	{ 0x34A0, 0x30 },
+	{ 0x34C0, 0xD3 },
+	{ 0x34C1, 0x00 },
+	{ 0x34C2, 0xD3 },
+	{ 0x34C3, 0x00 },
+	{ 0x34C4, 0xD3 },
+	{ 0x34C5, 0x00 },
+	{ 0x34C6, 0xD3 },
+	{ 0x34C7, 0x00 },
+	{ 0x34C8, 0xE2 },
+	{ 0x34C9, 0x21 },
+	{ 0x34CA, 0xE0 },
+	{ 0x34CB, 0x1F },
+	{ 0x34CC, 0x06 },
+	{ 0x34CD, 0x20 },
+	{ 0x34CE, 0x28 },
+	{ 0x34CF, 0x1F },
+	{ 0x3584, 0x00 },
+	{ 0x3586, 0x00 },
+	{ 0x3587, 0x01 },
+	{ 0x3588, 0xE6 },
+	{ 0x3589, 0x00 },
+	{ 0x3590, 0x00 },
+	{ 0x3591, 0x00 },
+	{ 0x3594, 0x40 },
+	{ 0x3598, 0x03 },
+	{ 0x3599, 0x00 },
+	{ 0x359A, 0x80 },
+	{ 0x359B, 0x00 },
+	{ 0x359C, 0x00 },
+	{ 0x359D, 0x01 },
+	{ 0x359E, 0x00 },
+	{ 0x359F, 0x02 },
+	{ 0x35A0, 0x00 },
+	{ 0x35A1, 0x04 },
+	{ 0x35A2, 0x20 },
+	{ 0x35A3, 0x00 },
+	{ 0x35A4, 0x40 },
+	{ 0x35A5, 0x00 },
+	{ 0x35A6, 0x80 },
+	{ 0x35A7, 0x00 },
+	{ 0x35A8, 0x00 },
+	{ 0x35A9, 0x01 },
+	{ 0x35AA, 0x3A },
+	{ 0x35AB, 0x00 },
+	{ 0x35AC, 0x80 },
+	{ 0x35AD, 0x00 },
+	{ 0x35AE, 0x00 },
+	{ 0x35AF, 0x01 },
+	{ 0x35B0, 0x00 },
+	{ 0x35B1, 0x02 },
+	{ 0x35B2, 0x00 },
+	{ 0x35B3, 0x04 },
+	{ 0x35B4, 0x02 },
+	{ 0x35B5, 0x00 },
+	{ 0x35B6, 0x04 },
+	{ 0x35B7, 0x00 },
+	{ 0x35B8, 0x08 },
+	{ 0x35B9, 0x00 },
+	{ 0x35BA, 0x10 },
+	{ 0x35BB, 0x00 },
+	{ 0x35BC, 0x03 },
+	{ 0x35BD, 0x00 },
+	{ 0x35C8, 0x00 },
+	{ 0x35C9, 0x01 },
+	{ 0x35CA, 0x00 },
+	{ 0x35CB, 0x04 },
+	{ 0x35CC, 0x00 },
+	{ 0x35CD, 0x10 },
+	{ 0x35CE, 0x00 },
+	{ 0x35CF, 0x40 },
+	{ 0x35D0, 0x00 },
+	{ 0x35D1, 0x0C },
+	{ 0x35D2, 0x00 },
+	{ 0x35D3, 0x0C },
+	{ 0x35D4, 0x00 },
+	{ 0x35D5, 0x0C },
+	{ 0x35D6, 0x00 },
+	{ 0x35D7, 0x0C },
+	{ 0x35D8, 0x00 },
+	{ 0x35D9, 0x00 },
+	{ 0x35DA, 0x08 },
+	{ 0x35DB, 0x00 },
+	{ 0x35DC, 0xD8 },
+	{ 0x35DD, 0x0E },
+	{ 0x35F0, 0x00 },
+	{ 0x35F1, 0x10 },
+	{ 0x35F2, 0x00 },
+	{ 0x35F3, 0x10 },
+	{ 0x35F4, 0x00 },
+	{ 0x35F5, 0x10 },
+	{ 0x35F6, 0x00 },
+	{ 0x35F7, 0x03 },
+	{ 0x35F8, 0x00 },
+	{ 0x35F9, 0x01 },
+	{ 0x35FA, 0x38 },
+	{ 0x35FB, 0x00 },
+	{ 0x35FC, 0xB3 },
+	{ 0x35FD, 0x01 },
+	{ 0x35FE, 0x00 },
+	{ 0x35FF, 0x00 },
+	{ 0x3600, 0x04 },
+	{ 0x3601, 0x06 },
+	{ 0x3604, 0x03 },
+	{ 0x3605, 0x00 },
+	{ 0x3608, 0x03 },
+	{ 0x3609, 0x00 },
+	{ 0x360C, 0x00 },
+	{ 0x360D, 0x00 },
+	{ 0x3610, 0x10 },
+	{ 0x3611, 0x01 },
+	{ 0x3612, 0x00 },
+	{ 0x3613, 0x00 },
+	{ 0x3614, 0x00 },
+	{ 0x3615, 0x00 },
+	{ 0x361C, 0x00 },
+	{ 0x361D, 0x01 },
+	{ 0x361E, 0x00 },
+	{ 0x361F, 0x01 },
+	{ 0x3620, 0x01 },
+	{ 0x3621, 0x00 },
+	{ 0x3622, 0xB0 },
+	{ 0x3623, 0x04 },
+	{ 0x3624, 0xDC },
+	{ 0x3625, 0x05 },
+	{ 0x3626, 0x00 },
+	{ 0x3627, 0x01 },
+	{ 0x3628, 0xFF },
+	{ 0x3629, 0x0F },
+	{ 0x362A, 0x00 },
+	{ 0x362B, 0x10 },
+	{ 0x362C, 0x00 },
+	{ 0x362D, 0x01 },
+	{ 0x3630, 0x40 },
+	{ 0x3631, 0x00 },
+	{ 0x3632, 0x40 },
+	{ 0x3633, 0x00 },
+	{ 0x3634, 0x40 },
+	{ 0x3635, 0x00 },
+	{ 0x3636, 0x40 },
+	{ 0x3637, 0x00 },
+	{ 0x3638, 0x40 },
+	{ 0x3639, 0x00 },
+	{ 0x363A, 0x40 },
+	{ 0x363B, 0x00 },
+	{ 0x363C, 0x40 },
+	{ 0x363D, 0x00 },
+	{ 0x363E, 0x40 },
+	{ 0x363F, 0x00 },
+	{ 0x36C4, 0x99 },
+	{ 0x36C5, 0x09 },
+	{ 0x36C6, 0x18 },
+	{ 0x36C7, 0x07 },
+	{ 0x36C8, 0x65 },
+	{ 0x36C9, 0x0E },
+	{ 0x36CC, 0x99 },
+	{ 0x36CD, 0x01 },
+	{ 0x36CE, 0x47 },
+	{ 0x36CF, 0x00 },
+	{ 0x36D0, 0x04 },
+	{ 0x36D1, 0x00 },
+	{ 0x36D4, 0x65 },
+	{ 0x36D5, 0x0E },
+	{ 0x36D6, 0xA4 },
+	{ 0x36D7, 0x0A },
+	{ 0x36D8, 0x65 },
+	{ 0x36D9, 0x0E },
+	{ 0x36DC, 0x65 },
+	{ 0x36DD, 0x0E },
+	{ 0x36DE, 0xA4 },
+	{ 0x36DF, 0x0A },
+	{ 0x36E0, 0x65 },
+	{ 0x36E1, 0x0E },
+	{ 0x36E4, 0x65 },
+	{ 0x36E5, 0x0E },
+	{ 0x36E6, 0xA4 },
+	{ 0x36E7, 0x0A },
+	{ 0x36E8, 0x65 },
+	{ 0x36E9, 0x0E },
+	{ 0x36EE, 0x00 },
+	{ 0x36EF, 0x00 },
+	{ 0x36F0, 0x00 },
+	{ 0x36F1, 0x80 },
+	{ 0x36F8, 0x00 },
+	{ 0x3702, 0x03 },
+	{ 0x3703, 0x04 },
+	{ 0x3704, 0x08 },
+	{ 0x370E, 0x0E },
+	{ 0x3718, 0x62 },
+	{ 0x3719, 0x4A },
+	{ 0x371A, 0x38 },
+	{ 0x371B, 0x20 },
+	{ 0x371C, 0x64 },
+	{ 0x371D, 0x42 },
+	{ 0x371E, 0x32 },
+	{ 0x371F, 0x1B },
+	{ 0x3720, 0x9C },
+	{ 0x3721, 0xA4 },
+	{ 0x3722, 0xAC },
+	{ 0x3723, 0xB4 },
+	{ 0x3748, 0xAA },
+	{ 0x3749, 0x96 },
+	{ 0x374A, 0x7D },
+	{ 0x374B, 0x69 },
+	{ 0x37C0, 0x00 },
+	{ 0x37C1, 0x00 },
+	{ 0x37C2, 0x00 },
+	{ 0x37C4, 0x00 },
+	{ 0x37C5, 0x00 },
+	{ 0x37C6, 0x00 },
+	{ 0x37C8, 0x00 },
+	{ 0x37C9, 0x00 },
+	{ 0x37CA, 0x00 },
+	{ 0x37CC, 0x00 },
+	{ 0x37CD, 0x00 },
+	{ 0x37CE, 0x00 },
+	{ 0x37D0, 0x00 },
+	{ 0x37D1, 0x00 },
+	{ 0x37D2, 0x00 },
+	{ 0x37D4, 0x00 },
+	{ 0x37D5, 0x00 },
+	{ 0x37D6, 0x00 },
+	{ 0x37D8, 0x00 },
+	{ 0x37D9, 0x00 },
+	{ 0x37DA, 0x00 },
+	{ 0x37DC, 0x00 },
+	{ 0x37DD, 0x00 },
+	{ 0x37DE, 0x00 },
+	{ 0x37E0, 0x00 },
+	{ 0x37E1, 0x00 },
+	{ 0x37E2, 0x00 },
+	{ 0x37E4, 0x00 },
+	{ 0x37E5, 0x00 },
+	{ 0x37E6, 0x00 },
+	{ 0x37E8, 0x00 },
+	{ 0x37E9, 0x00 },
+	{ 0x37EA, 0x00 },
+	{ 0x37EC, 0x00 },
+	{ 0x37ED, 0x00 },
+	{ 0x37EE, 0x00 },
+	{ 0x37F0, 0x00 },
+	{ 0x37F4, 0x00 },
+	{ 0x37F5, 0x1E },
+	{ 0x37F6, 0x34 },
+	{ 0x37F7, 0x00 },
+	{ 0x37F8, 0xFF },
+	{ 0x37F9, 0xFF },
+	{ 0x37FA, 0x03 },
+	{ 0x37FC, 0x00 },
+	{ 0x37FD, 0x00 },
+	{ 0x37FE, 0x04 },
+	{ 0x3800, 0xFF },
+	{ 0x3801, 0xFF },
+	{ 0x3802, 0x03 },
+	{ 0x3804, 0x00 },
+	{ 0x3805, 0x00 },
+	{ 0x3806, 0x04 },
+	{ 0x3808, 0x00 },
+	{ 0x3809, 0x00 },
+	{ 0x380A, 0x00 },
+	{ 0x380C, 0x00 },
+	{ 0x380D, 0x00 },
+	{ 0x380E, 0x00 },
+	{ 0x3810, 0x00 },
+	{ 0x3811, 0x00 },
+	{ 0x3812, 0x00 },
+	{ 0x3814, 0x00 },
+	{ 0x3815, 0x00 },
+	{ 0x3816, 0x00 },
+	{ 0x3818, 0x00 },
+	{ 0x3819, 0x00 },
+	{ 0x381A, 0x00 },
+	{ 0x381C, 0x00 },
+	{ 0x381D, 0x00 },
+	{ 0x381E, 0x00 },
+	{ 0x3820, 0x00 },
+	{ 0x3821, 0x00 },
+	{ 0x3822, 0x00 },
+	{ 0x3824, 0x00 },
+	{ 0x3825, 0x00 },
+	{ 0x3826, 0x00 },
+	{ 0x3828, 0x00 },
+	{ 0x3829, 0x00 },
+	{ 0x382A, 0x00 },
+	{ 0x382C, 0x00 },
+	{ 0x382D, 0x00 },
+	{ 0x382E, 0x00 },
+	{ 0x3830, 0x00 },
+	{ 0x3831, 0x00 },
+	{ 0x3832, 0x00 },
+	{ 0x3834, 0x00 },
+	{ 0x3835, 0x00 },
+	{ 0x3836, 0x00 },
+	{ 0x3838, 0x00 },
+	{ 0x3839, 0x00 },
+	{ 0x383A, 0x00 },
+	{ 0x383B, 0x00 },
+	{ 0x383C, 0x00 },
+	{ 0x383D, 0x00 },
+	{ 0x383E, 0x00 },
+	{ 0x383F, 0x00 },
+	{ 0x3840, 0x00 },
+	{ 0x3841, 0x00 },
+	{ 0x3842, 0x00 },
+	{ 0x3843, 0x00 },
+	{ 0x3844, 0x00 },
+	{ 0x3845, 0x00 },
+	{ 0x3846, 0x00 },
+	{ 0x3847, 0x00 },
+	{ 0x3848, 0x00 },
+	{ 0x3849, 0x00 },
+	{ 0x384A, 0x00 },
+	{ 0x384B, 0x00 },
+	{ 0x384C, 0x00 },
+	{ 0x384D, 0x00 },
+	{ 0x384E, 0x00 },
+	{ 0x384F, 0x00 },
+	{ 0x3850, 0xFF },
+	{ 0x3851, 0x0F },
+	{ 0x3852, 0x00 },
+	{ 0x3853, 0x10 },
+	{ 0x3854, 0xFF },
+	{ 0x3855, 0x0F },
+	{ 0x3856, 0x00 },
+	{ 0x3857, 0x10 },
+	{ 0x3858, 0xFF },
+	{ 0x3859, 0x0F },
+	{ 0x385A, 0x00 },
+	{ 0x385B, 0x10 },
+	{ 0x385C, 0x02 },
+	{ 0x385D, 0x00 },
+	{ 0x385E, 0x06 },
+	{ 0x385F, 0x00 },
+	{ 0x3860, 0x06 },
+	{ 0x3861, 0x00 },
+	{ 0x3862, 0x08 },
+	{ 0x3863, 0x00 },
+	{ 0x3864, 0x02 },
+	{ 0x3865, 0x00 },
+	{ 0x38A0, 0x01 },
+	{ 0x38A1, 0x01 },
+	{ 0x38A2, 0x00 },
+	{ 0x38A3, 0x01 },
+	{ 0x38A4, 0x07 },
+	{ 0x38A5, 0x00 },
+	{ 0x38A6, 0x04 },
+	{ 0x38A7, 0x05 },
+	{ 0x38A8, 0x00 },
+	{ 0x38A9, 0x00 },
+	{ 0x38AC, 0x00 },
+	{ 0x38AD, 0x00 },
+	{ 0x38AE, 0x01 },
+	{ 0x38B0, 0x02 },
+	{ 0x38B2, 0x22 },
+	{ 0x38B3, 0x00 },
+	{ 0x38B4, 0x17 },
+	{ 0x38B5, 0x00 },
+	{ 0x38B6, 0x11 },
+	{ 0x38B7, 0x00 },
+	{ 0x38B8, 0x0E },
+	{ 0x38B9, 0x00 },
+	{ 0x38BA, 0x2A },
+	{ 0x38BB, 0x00 },
+	{ 0x38BC, 0x1C },
+	{ 0x38BD, 0x00 },
+	{ 0x38BE, 0x14 },
+	{ 0x38BF, 0x00 },
+	{ 0x38C0, 0x10 },
+	{ 0x38C1, 0x00 },
+	{ 0x38C2, 0x31 },
+	{ 0x38C3, 0x00 },
+	{ 0x38C4, 0x21 },
+	{ 0x38C5, 0x00 },
+	{ 0x38C6, 0x18 },
+	{ 0x38C7, 0x00 },
+	{ 0x38C8, 0x12 },
+	{ 0x38C9, 0x00 },
+	{ 0x38CA, 0x3C },
+	{ 0x38CB, 0x00 },
+	{ 0x38CC, 0x29 },
+	{ 0x38CD, 0x00 },
+	{ 0x38CE, 0x1D },
+	{ 0x38CF, 0x00 },
+	{ 0x38D0, 0x15 },
+	{ 0x38D1, 0x00 },
+	{ 0x38D2, 0x4E },
+	{ 0x38D3, 0x00 },
+	{ 0x38D4, 0x35 },
+	{ 0x38D5, 0x00 },
+	{ 0x38D6, 0x26 },
+	{ 0x38D7, 0x00 },
+	{ 0x38D8, 0x1A },
+	{ 0x38D9, 0x00 },
+	{ 0x38DA, 0x69 },
+	{ 0x38DB, 0x00 },
+	{ 0x38DC, 0x48 },
+	{ 0x38DD, 0x00 },
+	{ 0x38DE, 0x33 },
+	{ 0x38DF, 0x00 },
+	{ 0x38E0, 0x22 },
+	{ 0x38E1, 0x00 },
+	{ 0x38E2, 0x93 },
+	{ 0x38E3, 0x00 },
+	{ 0x38E4, 0x64 },
+	{ 0x38E5, 0x00 },
+	{ 0x38E6, 0x48 },
+	{ 0x38E7, 0x00 },
+	{ 0x38E8, 0x30 },
+	{ 0x38E9, 0x00 },
+	{ 0x38EA, 0xD3 },
+	{ 0x38EB, 0x00 },
+	{ 0x38EC, 0x90 },
+	{ 0x38ED, 0x00 },
+	{ 0x38EE, 0x69 },
+	{ 0x38EF, 0x00 },
+	{ 0x38F0, 0x49 },
+	{ 0x38F1, 0x00 },
+	{ 0x38F2, 0x39 },
+	{ 0x38F3, 0x01 },
+	{ 0x38F4, 0xD5 },
+	{ 0x38F5, 0x00 },
+	{ 0x38F6, 0x9F },
+	{ 0x38F7, 0x00 },
+	{ 0x38F8, 0x75 },
+	{ 0x38F9, 0x00 },
+	{ 0x38FA, 0x00 },
+	{ 0x38FB, 0x01 },
+	{ 0x38FC, 0x00 },
+	{ 0x38FD, 0x01 },
+	{ 0x38FE, 0x00 },
+	{ 0x38FF, 0x01 },
+	{ 0x3900, 0x00 },
+	{ 0x3901, 0x01 },
+	{ 0x3902, 0x70 },
+	{ 0x3903, 0x00 },
+	{ 0x3904, 0x30 },
+	{ 0x3905, 0x00 },
+	{ 0x3906, 0x25 },
+	{ 0x3907, 0x00 },
+	{ 0x3908, 0x20 },
+	{ 0x3909, 0x00 },
+	{ 0x390A, 0xB2 },
+	{ 0x390B, 0x00 },
+	{ 0x390C, 0x80 },
+	{ 0x390D, 0x00 },
+	{ 0x390E, 0x70 },
+	{ 0x390F, 0x00 },
+	{ 0x3910, 0x50 },
+	{ 0x3911, 0x00 },
+	{ 0x3912, 0xB2 },
+	{ 0x3913, 0x00 },
+	{ 0x3914, 0x80 },
+	{ 0x3915, 0x00 },
+	{ 0x3916, 0x70 },
+	{ 0x3917, 0x00 },
+	{ 0x3918, 0x50 },
+	{ 0x3919, 0x00 },
+	{ 0x391A, 0xB2 },
+	{ 0x391B, 0x00 },
+	{ 0x391C, 0x80 },
+	{ 0x391D, 0x00 },
+	{ 0x391E, 0x70 },
+	{ 0x391F, 0x00 },
+	{ 0x3920, 0x50 },
+	{ 0x3921, 0x00 },
+	{ 0x3922, 0x40 },
+	{ 0x3923, 0x00 },
+	{ 0x3924, 0x40 },
+	{ 0x3925, 0x00 },
+	{ 0x3926, 0x40 },
+	{ 0x3927, 0x00 },
+	{ 0x3928, 0x40 },
+	{ 0x3929, 0x00 },
+	{ 0x392A, 0x80 },
+	{ 0x392B, 0x00 },
+	{ 0x392C, 0x80 },
+	{ 0x392D, 0x00 },
+	{ 0x392E, 0x80 },
+	{ 0x392F, 0x00 },
+	{ 0x3930, 0x80 },
+	{ 0x3931, 0x00 },
+	{ 0x3932, 0x80 },
+	{ 0x3933, 0x80 },
+	{ 0x3934, 0x80 },
+	{ 0x3940, 0x01 },
+	{ 0x3941, 0x01 },
+	{ 0x3942, 0x00 },
+	{ 0x3943, 0x01 },
+	{ 0x3944, 0x07 },
+	{ 0x3945, 0x00 },
+	{ 0x3946, 0x04 },
+	{ 0x3947, 0x05 },
+	{ 0x3948, 0x00 },
+	{ 0x3949, 0x00 },
+	{ 0x394C, 0x00 },
+	{ 0x394D, 0x00 },
+	{ 0x394E, 0x01 },
+	{ 0x3950, 0x03 },
+	{ 0x3952, 0x14 },
+	{ 0x3953, 0x00 },
+	{ 0x3954, 0x0F },
+	{ 0x3955, 0x00 },
+	{ 0x3956, 0x0E },
+	{ 0x3957, 0x00 },
+	{ 0x3958, 0x0E },
+	{ 0x3959, 0x00 },
+	{ 0x395A, 0x19 },
+	{ 0x395B, 0x00 },
+	{ 0x395C, 0x11 },
+	{ 0x395D, 0x00 },
+	{ 0x395E, 0x0F },
+	{ 0x395F, 0x00 },
+	{ 0x3960, 0x0E },
+	{ 0x3961, 0x00 },
+	{ 0x3962, 0x1C },
+	{ 0x3963, 0x00 },
+	{ 0x3964, 0x13 },
+	{ 0x3965, 0x00 },
+	{ 0x3966, 0x0F },
+	{ 0x3967, 0x00 },
+	{ 0x3968, 0x0E },
+	{ 0x3969, 0x00 },
+	{ 0x396A, 0x23 },
+	{ 0x396B, 0x00 },
+	{ 0x396C, 0x15 },
+	{ 0x396D, 0x00 },
+	{ 0x396E, 0x11 },
+	{ 0x396F, 0x00 },
+	{ 0x3970, 0x0E },
+	{ 0x3971, 0x00 },
+	{ 0x3972, 0x2E },
+	{ 0x3973, 0x00 },
+	{ 0x3974, 0x1A },
+	{ 0x3975, 0x00 },
+	{ 0x3976, 0x14 },
+	{ 0x3977, 0x00 },
+	{ 0x3978, 0x0F },
+	{ 0x3979, 0x00 },
+	{ 0x397A, 0x3E },
+	{ 0x397B, 0x00 },
+	{ 0x397C, 0x23 },
+	{ 0x397D, 0x00 },
+	{ 0x397E, 0x1A },
+	{ 0x397F, 0x00 },
+	{ 0x3980, 0x12 },
+	{ 0x3981, 0x00 },
+	{ 0x3982, 0x56 },
+	{ 0x3983, 0x00 },
+	{ 0x3984, 0x31 },
+	{ 0x3985, 0x00 },
+	{ 0x3986, 0x25 },
+	{ 0x3987, 0x00 },
+	{ 0x3988, 0x1A },
+	{ 0x3989, 0x00 },
+	{ 0x398A, 0x7B },
+	{ 0x398B, 0x00 },
+	{ 0x398C, 0x49 },
+	{ 0x398D, 0x00 },
+	{ 0x398E, 0x39 },
+	{ 0x398F, 0x00 },
+	{ 0x3990, 0x2C },
+	{ 0x3991, 0x00 },
+	{ 0x3992, 0xB4 },
+	{ 0x3993, 0x00 },
+	{ 0x3994, 0x75 },
+	{ 0x3995, 0x00 },
+	{ 0x3996, 0x61 },
+	{ 0x3997, 0x00 },
+	{ 0x3998, 0x53 },
+	{ 0x3999, 0x00 },
+	{ 0x399A, 0x00 },
+	{ 0x399B, 0x01 },
+	{ 0x399C, 0x00 },
+	{ 0x399D, 0x01 },
+	{ 0x399E, 0x00 },
+	{ 0x399F, 0x01 },
+	{ 0x39A0, 0x00 },
+	{ 0x39A1, 0x01 },
+	{ 0x39A2, 0x70 },
+	{ 0x39A3, 0x00 },
+	{ 0x39A4, 0x30 },
+	{ 0x39A5, 0x00 },
+	{ 0x39A6, 0x25 },
+	{ 0x39A7, 0x00 },
+	{ 0x39A8, 0x20 },
+	{ 0x39A9, 0x00 },
+	{ 0x39AA, 0xB2 },
+	{ 0x39AB, 0x00 },
+	{ 0x39AC, 0x80 },
+	{ 0x39AD, 0x00 },
+	{ 0x39AE, 0x70 },
+	{ 0x39AF, 0x00 },
+	{ 0x39B0, 0x80 },
+	{ 0x39B1, 0x00 },
+	{ 0x39B2, 0xB2 },
+	{ 0x39B3, 0x00 },
+	{ 0x39B4, 0x80 },
+	{ 0x39B5, 0x00 },
+	{ 0x39B6, 0x70 },
+	{ 0x39B7, 0x00 },
+	{ 0x39B8, 0x80 },
+	{ 0x39B9, 0x00 },
+	{ 0x39BA, 0xB2 },
+	{ 0x39BB, 0x00 },
+	{ 0x39BC, 0x80 },
+	{ 0x39BD, 0x00 },
+	{ 0x39BE, 0x70 },
+	{ 0x39BF, 0x00 },
+	{ 0x39C0, 0x80 },
+	{ 0x39C1, 0x00 },
+	{ 0x39C2, 0x40 },
+	{ 0x39C3, 0x00 },
+	{ 0x39C4, 0x40 },
+	{ 0x39C5, 0x00 },
+	{ 0x39C6, 0x40 },
+	{ 0x39C7, 0x00 },
+	{ 0x39C8, 0x40 },
+	{ 0x39C9, 0x00 },
+	{ 0x39CA, 0x80 },
+	{ 0x39CB, 0x00 },
+	{ 0x39CC, 0x80 },
+	{ 0x39CD, 0x00 },
+	{ 0x39CE, 0x80 },
+	{ 0x39CF, 0x00 },
+	{ 0x39D0, 0x80 },
+	{ 0x39D1, 0x00 },
+	{ 0x39D2, 0x80 },
+	{ 0x39D3, 0x80 },
+	{ 0x39D4, 0x80 },
+	{ 0x39E0, 0x01 },
+	{ 0x39E1, 0x00 },
+	{ 0x39E4, 0x40 },
+	{ 0x39E5, 0x01 },
+	{ 0x39E6, 0x01 },
+	{ 0x39E8, 0x00 },
+	{ 0x39E9, 0x01 },
+	{ 0x39EA, 0x00 },
+	{ 0x39EB, 0x00 },
+	{ 0x39EC, 0x01 },
+	{ 0x39ED, 0x00 },
+	{ 0x39EE, 0x01 },
+	{ 0x39F0, 0x03 },
+	{ 0x39F1, 0x04 },
+	{ 0x39F2, 0x0E },
+	{ 0x39F4, 0x1C },
+	{ 0x39F5, 0x00 },
+	{ 0x39F6, 0x13 },
+	{ 0x39F7, 0x00 },
+	{ 0x39F8, 0x0D },
+	{ 0x39F9, 0x00 },
+	{ 0x39FA, 0x07 },
+	{ 0x39FB, 0x00 },
+	{ 0x39FC, 0x38 },
+	{ 0x39FD, 0x00 },
+	{ 0x39FE, 0x1C },
+	{ 0x39FF, 0x00 },
+	{ 0x3A00, 0x11 },
+	{ 0x3A01, 0x00 },
+	{ 0x3A02, 0x08 },
+	{ 0x3A03, 0x00 },
+	{ 0x3A04, 0x4A },
+	{ 0x3A05, 0x00 },
+	{ 0x3A06, 0x23 },
+	{ 0x3A07, 0x00 },
+	{ 0x3A08, 0x15 },
+	{ 0x3A09, 0x00 },
+	{ 0x3A0A, 0x09 },
+	{ 0x3A0B, 0x00 },
+	{ 0x3A0C, 0x65 },
+	{ 0x3A0D, 0x00 },
+	{ 0x3A0E, 0x2D },
+	{ 0x3A0F, 0x00 },
+	{ 0x3A10, 0x1A },
+	{ 0x3A11, 0x00 },
+	{ 0x3A12, 0x0B },
+	{ 0x3A13, 0x00 },
+	{ 0x3A14, 0x8D },
+	{ 0x3A15, 0x00 },
+	{ 0x3A16, 0x3D },
+	{ 0x3A17, 0x00 },
+	{ 0x3A18, 0x23 },
+	{ 0x3A19, 0x00 },
+	{ 0x3A1A, 0x0E },
+	{ 0x3A1B, 0x00 },
+	{ 0x3A1C, 0xC5 },
+	{ 0x3A1D, 0x00 },
+	{ 0x3A1E, 0x55 },
+	{ 0x3A1F, 0x00 },
+	{ 0x3A20, 0x30 },
+	{ 0x3A21, 0x00 },
+	{ 0x3A22, 0x13 },
+	{ 0x3A23, 0x00 },
+	{ 0x3A24, 0x16 },
+	{ 0x3A25, 0x01 },
+	{ 0x3A26, 0x76 },
+	{ 0x3A27, 0x00 },
+	{ 0x3A28, 0x42 },
+	{ 0x3A29, 0x00 },
+	{ 0x3A2A, 0x1A },
+	{ 0x3A2B, 0x00 },
+	{ 0x3A2C, 0x88 },
+	{ 0x3A2D, 0x01 },
+	{ 0x3A2E, 0xA7 },
+	{ 0x3A2F, 0x00 },
+	{ 0x3A30, 0x5D },
+	{ 0x3A31, 0x00 },
+	{ 0x3A32, 0x24 },
+	{ 0x3A33, 0x00 },
+	{ 0x3A34, 0x2A },
+	{ 0x3A35, 0x02 },
+	{ 0x3A36, 0xEB },
+	{ 0x3A37, 0x00 },
+	{ 0x3A38, 0x83 },
+	{ 0x3A39, 0x00 },
+	{ 0x3A3A, 0x32 },
+	{ 0x3A3B, 0x00 },
+	{ 0x3A3C, 0x00 },
+	{ 0x3A3D, 0x01 },
+	{ 0x3A3E, 0x00 },
+	{ 0x3A3F, 0x01 },
+	{ 0x3A40, 0x00 },
+	{ 0x3A41, 0x01 },
+	{ 0x3A42, 0x00 },
+	{ 0x3A43, 0x01 },
+	{ 0x3A44, 0x80 },
+	{ 0x3A45, 0x00 },
+	{ 0x3A46, 0x50 },
+	{ 0x3A47, 0x00 },
+	{ 0x3A48, 0x30 },
+	{ 0x3A49, 0x00 },
+	{ 0x3A4A, 0x20 },
+	{ 0x3A4B, 0x00 },
+	{ 0x3A4C, 0x99 },
+	{ 0x3A4D, 0x00 },
+	{ 0x3A4E, 0x80 },
+	{ 0x3A4F, 0x00 },
+	{ 0x3A50, 0x80 },
+	{ 0x3A51, 0x00 },
+	{ 0x3A52, 0x80 },
+	{ 0x3A53, 0x00 },
+	{ 0x3A54, 0x99 },
+	{ 0x3A55, 0x00 },
+	{ 0x3A56, 0x80 },
+	{ 0x3A57, 0x00 },
+	{ 0x3A58, 0x80 },
+	{ 0x3A59, 0x00 },
+	{ 0x3A5A, 0x80 },
+	{ 0x3A5B, 0x00 },
+	{ 0x3A5C, 0x99 },
+	{ 0x3A5D, 0x00 },
+	{ 0x3A5E, 0x80 },
+	{ 0x3A5F, 0x00 },
+	{ 0x3A60, 0x80 },
+	{ 0x3A61, 0x00 },
+	{ 0x3A62, 0x80 },
+	{ 0x3A63, 0x00 },
+	{ 0x3A64, 0x1C },
+	{ 0x3A65, 0x00 },
+	{ 0x3A66, 0x13 },
+	{ 0x3A67, 0x00 },
+	{ 0x3A68, 0x0D },
+	{ 0x3A69, 0x00 },
+	{ 0x3A6A, 0x07 },
+	{ 0x3A6B, 0x00 },
+	{ 0x3A6C, 0x0C },
+	{ 0x3A6D, 0x00 },
+	{ 0x3A6E, 0x09 },
+	{ 0x3A6F, 0x00 },
+	{ 0x3A70, 0x06 },
+	{ 0x3A71, 0x00 },
+	{ 0x3A72, 0x03 },
+	{ 0x3A73, 0x00 },
+	{ 0x3A74, 0x1F },
+	{ 0x3A75, 0x00 },
+	{ 0x3A76, 0x1B },
+	{ 0x3A77, 0x00 },
+	{ 0x3A78, 0x0F },
+	{ 0x3A79, 0x00 },
+	{ 0x3A7A, 0x08 },
+	{ 0x3A7B, 0x00 },
+	{ 0x3A7C, 0x80 },
+	{ 0x3A7D, 0x00 },
+	{ 0x3A7E, 0x80 },
+	{ 0x3A7F, 0x00 },
+	{ 0x3A80, 0x80 },
+	{ 0x3A81, 0x00 },
+	{ 0x3A82, 0x80 },
+	{ 0x3A83, 0x00 },
+	{ 0x3A84, 0x09 },
+	{ 0x3A85, 0x00 },
+	{ 0x3A86, 0x04 },
+	{ 0x3A87, 0x00 },
+	{ 0x3A88, 0x03 },
+	{ 0x3A89, 0x00 },
+	{ 0x3A8A, 0x01 },
+	{ 0x3A8B, 0x00 },
+	{ 0x3A8C, 0x19 },
+	{ 0x3A8D, 0x01 },
+	{ 0x3A8E, 0xD2 },
+	{ 0x3A8F, 0x00 },
+	{ 0x3A90, 0x8C },
+	{ 0x3A91, 0x00 },
+	{ 0x3A92, 0x64 },
+	{ 0x3A93, 0x00 },
+	{ 0x3A94, 0xFF },
+	{ 0x3A95, 0x00 },
+	{ 0x3A96, 0xD2 },
+	{ 0x3A97, 0x00 },
+	{ 0x3A98, 0x8C },
+	{ 0x3A99, 0x00 },
+	{ 0x3A9A, 0x64 },
+	{ 0x3A9B, 0x00 },
+	{ 0x3A9C, 0x08 },
+	{ 0x3A9D, 0x10 },
+	{ 0x3A9E, 0x80 },
+	{ 0x3A9F, 0x80 },
+	{ 0x3AA0, 0x80 },
+	{ 0x3AA1, 0x04 },
+	{ 0x3AA2, 0x05 },
+	{ 0x3AC0, 0x01 },
+	{ 0x3AC4, 0x81 },
+	{ 0x3AC5, 0x00 },
+	{ 0x3AC6, 0x00 },
+	{ 0x3AC7, 0x00 },
+	{ 0x3AC8, 0x00 },
+	{ 0x3AC9, 0x00 },
+	{ 0x3ACA, 0x00 },
+	{ 0x3ACB, 0x00 },
+	{ 0x3ACC, 0x02 },
+	{ 0x3ACD, 0x00 },
+	{ 0x3ACE, 0x81 },
+	{ 0x3ACF, 0x00 },
+	{ 0x3AD0, 0x00 },
+	{ 0x3AD1, 0x00 },
+	{ 0x3AD2, 0xFD },
+	{ 0x3AD3, 0x03 },
+	{ 0x3AD4, 0x02 },
+	{ 0x3AD5, 0x00 },
+	{ 0x3AD6, 0x00 },
+	{ 0x3AD7, 0x00 },
+	{ 0x3AD8, 0x81 },
+	{ 0x3AD9, 0x00 },
+	{ 0x3ADA, 0xFD },
+	{ 0x3ADB, 0x03 },
+	{ 0x3ADC, 0xFF },
+	{ 0x3ADD, 0x03 },
+	{ 0x3ADE, 0x01 },
+	{ 0x3ADF, 0x00 },
+	{ 0x3AE0, 0x01 },
+	{ 0x3AE1, 0x00 },
+	{ 0x3AE2, 0x7E },
+	{ 0x3AE3, 0x00 },
+	{ 0x3AF4, 0x00 },
+	{ 0x3AF6, 0x40 },
+	{ 0x3AF7, 0x1E },
+	{ 0x3AF8, 0x01 },
+	{ 0x3AFA, 0x63 },
+	{ 0x3AFB, 0x09 },
+	{ 0x3AFC, 0x11 },
+	{ 0x3AFD, 0x09 },
+	{ 0x3AFE, 0x00 },
+	{ 0x3AFF, 0x00 },
+	{ 0x3B00, 0x00 },
+	{ 0x3B01, 0x00 },
+	{ 0x3B02, 0x84 },
+	{ 0x3B03, 0x06 },
+	{ 0x3B04, 0x30 },
+	{ 0x3B05, 0x06 },
+	{ 0x3B06, 0x00 },
+	{ 0x3B07, 0x00 },
+	{ 0x3B08, 0x00 },
+	{ 0x3B09, 0x00 },
+	{ 0x3B0A, 0x00 },
+	{ 0x3B0B, 0x00 },
+	{ 0x3B0C, 0x00 },
+	{ 0x3B0D, 0x00 },
+	{ 0x3B0E, 0x00 },
+	{ 0x3B0F, 0x00 },
+	{ 0x3B10, 0x00 },
+	{ 0x3B11, 0x00 },
+	{ 0x3B12, 0x00 },
+	{ 0x3B13, 0x00 },
+	{ 0x3B14, 0x00 },
+	{ 0x3B15, 0x00 },
+	{ 0x3B16, 0x00 },
+	{ 0x3B17, 0x00 },
+	{ 0x3B18, 0x00 },
+	{ 0x3B19, 0x00 },
+	{ 0x3B1A, 0x00 },
+	{ 0x3B1B, 0x00 },
+	{ 0x3B1C, 0x00 },
+	{ 0x3B1D, 0x00 },
+	{ 0x3B1E, 0x00 },
+	{ 0x3B1F, 0x00 },
+	{ 0x3B20, 0x00 },
+	{ 0x3B21, 0x00 },
+	{ 0x3B22, 0x00 },
+	{ 0x3B23, 0x00 },
+	{ 0x3B24, 0x00 },
+	{ 0x3B25, 0x00 },
+	{ 0x3B26, 0x00 },
+	{ 0x3B27, 0x00 },
+	{ 0x3B28, 0x00 },
+	{ 0x3B29, 0x00 },
+	{ 0x3B2A, 0x00 },
+	{ 0x3B2C, 0x00 },
+	{ 0x3B2E, 0x00 },
+	{ 0x3B30, 0x00 },
+	{ 0x3B32, 0x0C },
+	{ 0x4000, 0xD1 },
+	{ 0x4001, 0xC0 },
+	{ 0x4002, 0xC0 },
+	{ 0x4003, 0xB8 },
+	{ 0x4004, 0xC0 },
+	{ 0x4005, 0xB8 },
+	{ 0x4006, 0xB9 },
+	{ 0x4007, 0xB7 },
+	{ 0x4008, 0xB0 },
+	{ 0x4009, 0xAB },
+	{ 0x400A, 0xAC },
+	{ 0x400B, 0xAB },
+	{ 0x400C, 0xA8 },
+	{ 0x400D, 0xA6 },
+	{ 0x400E, 0xA6 },
+	{ 0x400F, 0xA5 },
+	{ 0x4010, 0xA2 },
+	{ 0x4011, 0xA0 },
+	{ 0x4012, 0xA0 },
+	{ 0x4013, 0x9F },
+	{ 0x4014, 0xA4 },
+	{ 0x4015, 0xA2 },
+	{ 0x4016, 0xA2 },
+	{ 0x4017, 0x9C },
+	{ 0x4018, 0xA8 },
+	{ 0x4019, 0xA6 },
+	{ 0x401A, 0xA8 },
+	{ 0x401B, 0xAA },
+	{ 0x401C, 0xB0 },
+	{ 0x401D, 0xAE },
+	{ 0x401E, 0xAE },
+	{ 0x401F, 0xAE },
+	{ 0x4020, 0xBA },
+	{ 0x4021, 0xAE },
+	{ 0x4022, 0xAF },
+	{ 0x4023, 0xAE },
+	{ 0x4024, 0xC6 },
+	{ 0x4025, 0xBD },
+	{ 0x4026, 0xBD },
+	{ 0x4027, 0xBA },
+	{ 0x4028, 0xB0 },
+	{ 0x4029, 0xA9 },
+	{ 0x402A, 0xAA },
+	{ 0x402B, 0xA8 },
+	{ 0x402C, 0x9F },
+	{ 0x402D, 0x9C },
+	{ 0x402E, 0x9C },
+	{ 0x402F, 0x9B },
+	{ 0x4030, 0x93 },
+	{ 0x4031, 0x91 },
+	{ 0x4032, 0x92 },
+	{ 0x4033, 0x91 },
+	{ 0x4034, 0x8D },
+	{ 0x4035, 0x8C },
+	{ 0x4036, 0x8C },
+	{ 0x4037, 0x8C },
+	{ 0x4038, 0x8F },
+	{ 0x4039, 0x8E },
+	{ 0x403A, 0x8E },
+	{ 0x403B, 0x8E },
+	{ 0x403C, 0x98 },
+	{ 0x403D, 0x96 },
+	{ 0x403E, 0x96 },
+	{ 0x403F, 0x95 },
+	{ 0x4040, 0xA4 },
+	{ 0x4041, 0xA0 },
+	{ 0x4042, 0xA0 },
+	{ 0x4043, 0x9E },
+	{ 0x4044, 0xB3 },
+	{ 0x4045, 0xAE },
+	{ 0x4046, 0xAF },
+	{ 0x4047, 0xAB },
+	{ 0x4048, 0xC2 },
+	{ 0x4049, 0xB7 },
+	{ 0x404A, 0xB8 },
+	{ 0x404B, 0xB5 },
+	{ 0x404C, 0xAB },
+	{ 0x404D, 0xA4 },
+	{ 0x404E, 0xA5 },
+	{ 0x404F, 0xA3 },
+	{ 0x4050, 0x99 },
+	{ 0x4051, 0x96 },
+	{ 0x4052, 0x96 },
+	{ 0x4053, 0x96 },
+	{ 0x4054, 0x8B },
+	{ 0x4055, 0x8A },
+	{ 0x4056, 0x8A },
+	{ 0x4057, 0x8A },
+	{ 0x4058, 0x82 },
+	{ 0x4059, 0x81 },
+	{ 0x405A, 0x81 },
+	{ 0x405B, 0x81 },
+	{ 0x405C, 0x85 },
+	{ 0x405D, 0x86 },
+	{ 0x405E, 0x85 },
+	{ 0x405F, 0x85 },
+	{ 0x4060, 0x90 },
+	{ 0x4061, 0x90 },
+	{ 0x4062, 0x8F },
+	{ 0x4063, 0x8F },
+	{ 0x4064, 0x9D },
+	{ 0x4065, 0x9B },
+	{ 0x4066, 0x9B },
+	{ 0x4067, 0x9A },
+	{ 0x4068, 0xAF },
+	{ 0x4069, 0xAA },
+	{ 0x406A, 0xAC },
+	{ 0x406B, 0xAA },
+	{ 0x406C, 0xC2 },
+	{ 0x406D, 0xB7 },
+	{ 0x406E, 0xB8 },
+	{ 0x406F, 0xB5 },
+	{ 0x4070, 0xAB },
+	{ 0x4071, 0xA4 },
+	{ 0x4072, 0xA4 },
+	{ 0x4073, 0xA3 },
+	{ 0x4074, 0x99 },
+	{ 0x4075, 0x96 },
+	{ 0x4076, 0x96 },
+	{ 0x4077, 0x96 },
+	{ 0x4078, 0x8B },
+	{ 0x4079, 0x8A },
+	{ 0x407A, 0x8A },
+	{ 0x407B, 0x8A },
+	{ 0x407C, 0x82 },
+	{ 0x407D, 0x82 },
+	{ 0x407E, 0x82 },
+	{ 0x407F, 0x82 },
+	{ 0x4080, 0x85 },
+	{ 0x4081, 0x86 },
+	{ 0x4082, 0x86 },
+	{ 0x4083, 0x86 },
+	{ 0x4084, 0x90 },
+	{ 0x4085, 0x90 },
+	{ 0x4086, 0x8F },
+	{ 0x4087, 0x8F },
+	{ 0x4088, 0x9D },
+	{ 0x4089, 0x9B },
+	{ 0x408A, 0x9B },
+	{ 0x408B, 0x99 },
+	{ 0x408C, 0xAE },
+	{ 0x408D, 0xAA },
+	{ 0x408E, 0xAA },
+	{ 0x408F, 0xA7 },
+	{ 0x4090, 0xC7 },
+	{ 0x4091, 0xBA },
+	{ 0x4092, 0xBC },
+	{ 0x4093, 0xB9 },
+	{ 0x4094, 0xB1 },
+	{ 0x4095, 0xA8 },
+	{ 0x4096, 0xA8 },
+	{ 0x4097, 0xA7 },
+	{ 0x4098, 0x9F },
+	{ 0x4099, 0x9B },
+	{ 0x409A, 0x9B },
+	{ 0x409B, 0x9B },
+	{ 0x409C, 0x93 },
+	{ 0x409D, 0x91 },
+	{ 0x409E, 0x91 },
+	{ 0x409F, 0x91 },
+	{ 0x40A0, 0x8D },
+	{ 0x40A1, 0x8C },
+	{ 0x40A2, 0x8C },
+	{ 0x40A3, 0x8C },
+	{ 0x40A4, 0x8E },
+	{ 0x40A5, 0x8E },
+	{ 0x40A6, 0x8D },
+	{ 0x40A7, 0x8D },
+	{ 0x40A8, 0x96 },
+	{ 0x40A9, 0x95 },
+	{ 0x40AA, 0x95 },
+	{ 0x40AB, 0x94 },
+	{ 0x40AC, 0xA2 },
+	{ 0x40AD, 0x9F },
+	{ 0x40AE, 0x9F },
+	{ 0x40AF, 0x9D },
+	{ 0x40B0, 0xB1 },
+	{ 0x40B1, 0xAC },
+	{ 0x40B2, 0xAB },
+	{ 0x40B3, 0xAA },
+	{ 0x40B4, 0xD3 },
+	{ 0x40B5, 0xBC },
+	{ 0x40B6, 0xBD },
+	{ 0x40B7, 0xBC },
+	{ 0x40B8, 0xC1 },
+	{ 0x40B9, 0xB7 },
+	{ 0x40BA, 0xB7 },
+	{ 0x40BB, 0xB5 },
+	{ 0x40BC, 0xB0 },
+	{ 0x40BD, 0xAA },
+	{ 0x40BE, 0xAA },
+	{ 0x40BF, 0xAA },
+	{ 0x40C0, 0xA8 },
+	{ 0x40C1, 0xA4 },
+	{ 0x40C2, 0xA4 },
+	{ 0x40C3, 0xA4 },
+	{ 0x40C4, 0xA2 },
+	{ 0x40C5, 0x9F },
+	{ 0x40C6, 0x9F },
+	{ 0x40C7, 0x9F },
+	{ 0x40C8, 0xA3 },
+	{ 0x40C9, 0xA0 },
+	{ 0x40CA, 0xA0 },
+	{ 0x40CB, 0xA0 },
+	{ 0x40CC, 0xA6 },
+	{ 0x40CD, 0xA3 },
+	{ 0x40CE, 0xA3 },
+	{ 0x40CF, 0xA2 },
+	{ 0x40D0, 0xAF },
+	{ 0x40D1, 0xAB },
+	{ 0x40D2, 0xAA },
+	{ 0x40D3, 0xA8 },
+	{ 0x40D4, 0xBA },
+	{ 0x40D5, 0xAE },
+	{ 0x40D6, 0xAE },
+	{ 0x40D7, 0xAB },
+	{ 0x4100, 0xBD },
+	{ 0x4101, 0xBA },
+	{ 0x4102, 0xBD },
+	{ 0x4103, 0xB7 },
+	{ 0x4104, 0xB7 },
+	{ 0x4105, 0xB7 },
+	{ 0x4106, 0xB8 },
+	{ 0x4107, 0xB5 },
+	{ 0x4108, 0xAB },
+	{ 0x4109, 0xAA },
+	{ 0x410A, 0xAC },
+	{ 0x410B, 0xAB },
+	{ 0x410C, 0xA4 },
+	{ 0x410D, 0xA5 },
+	{ 0x410E, 0xA5 },
+	{ 0x410F, 0xA4 },
+	{ 0x4110, 0x9F },
+	{ 0x4111, 0xA0 },
+	{ 0x4112, 0xA0 },
+	{ 0x4113, 0x9F },
+	{ 0x4114, 0xA0 },
+	{ 0x4115, 0xA0 },
+	{ 0x4116, 0xA0 },
+	{ 0x4117, 0x9F },
+	{ 0x4118, 0xA1 },
+	{ 0x4119, 0xA1 },
+	{ 0x411A, 0xA1 },
+	{ 0x411B, 0xA0 },
+	{ 0x411C, 0xA7 },
+	{ 0x411D, 0xA6 },
+	{ 0x411E, 0xA6 },
+	{ 0x411F, 0xA6 },
+	{ 0x4120, 0xA7 },
+	{ 0x4121, 0xA6 },
+	{ 0x4122, 0xA6 },
+	{ 0x4123, 0xA3 },
+	{ 0x4124, 0xB9 },
+	{ 0x4125, 0xB9 },
+	{ 0x4126, 0xBA },
+	{ 0x4127, 0xB8 },
+	{ 0x4128, 0xA6 },
+	{ 0x4129, 0xA7 },
+	{ 0x412A, 0xA7 },
+	{ 0x412B, 0xA6 },
+	{ 0x412C, 0x9B },
+	{ 0x412D, 0x9B },
+	{ 0x412E, 0x9B },
+	{ 0x412F, 0x9B },
+	{ 0x4130, 0x91 },
+	{ 0x4131, 0x92 },
+	{ 0x4132, 0x92 },
+	{ 0x4133, 0x91 },
+	{ 0x4134, 0x8C },
+	{ 0x4135, 0x8C },
+	{ 0x4136, 0x8C },
+	{ 0x4137, 0x8C },
+	{ 0x4138, 0x8D },
+	{ 0x4139, 0x8D },
+	{ 0x413A, 0x8D },
+	{ 0x413B, 0x8D },
+	{ 0x413C, 0x93 },
+	{ 0x413D, 0x93 },
+	{ 0x413E, 0x93 },
+	{ 0x413F, 0x92 },
+	{ 0x4140, 0x9A },
+	{ 0x4141, 0x9A },
+	{ 0x4142, 0x9A },
+	{ 0x4143, 0x99 },
+	{ 0x4144, 0xA7 },
+	{ 0x4145, 0xA5 },
+	{ 0x4146, 0xA6 },
+	{ 0x4147, 0xA6 },
+	{ 0x4148, 0xB8 },
+	{ 0x4149, 0xB4 },
+	{ 0x414A, 0xB4 },
+	{ 0x414B, 0xB3 },
+	{ 0x414C, 0xA3 },
+	{ 0x414D, 0xA2 },
+	{ 0x414E, 0xA3 },
+	{ 0x414F, 0xA2 },
+	{ 0x4150, 0x96 },
+	{ 0x4151, 0x96 },
+	{ 0x4152, 0x96 },
+	{ 0x4153, 0x96 },
+	{ 0x4154, 0x8A },
+	{ 0x4155, 0x8A },
+	{ 0x4156, 0x8A },
+	{ 0x4157, 0x8A },
+	{ 0x4158, 0x82 },
+	{ 0x4159, 0x82 },
+	{ 0x415A, 0x82 },
+	{ 0x415B, 0x82 },
+	{ 0x415C, 0x84 },
+	{ 0x415D, 0x85 },
+	{ 0x415E, 0x84 },
+	{ 0x415F, 0x84 },
+	{ 0x4160, 0x8D },
+	{ 0x4161, 0x8D },
+	{ 0x4162, 0x8D },
+	{ 0x4163, 0x8D },
+	{ 0x4164, 0x96 },
+	{ 0x4165, 0x96 },
+	{ 0x4166, 0x96 },
+	{ 0x4167, 0x95 },
+	{ 0x4168, 0xA5 },
+	{ 0x4169, 0xA2 },
+	{ 0x416A, 0xA3 },
+	{ 0x416B, 0xA2 },
+	{ 0x416C, 0xB7 },
+	{ 0x416D, 0xB3 },
+	{ 0x416E, 0xB5 },
+	{ 0x416F, 0xB4 },
+	{ 0x4170, 0xA4 },
+	{ 0x4171, 0xA2 },
+	{ 0x4172, 0xA3 },
+	{ 0x4173, 0xA2 },
+	{ 0x4174, 0x97 },
+	{ 0x4175, 0x96 },
+	{ 0x4176, 0x96 },
+	{ 0x4177, 0x96 },
+	{ 0x4178, 0x8B },
+	{ 0x4179, 0x8A },
+	{ 0x417A, 0x8A },
+	{ 0x417B, 0x8A },
+	{ 0x417C, 0x81 },
+	{ 0x417D, 0x81 },
+	{ 0x417E, 0x81 },
+	{ 0x417F, 0x81 },
+	{ 0x4180, 0x84 },
+	{ 0x4181, 0x84 },
+	{ 0x4182, 0x84 },
+	{ 0x4183, 0x84 },
+	{ 0x4184, 0x8C },
+	{ 0x4185, 0x8D },
+	{ 0x4186, 0x8D },
+	{ 0x4187, 0x8D },
+	{ 0x4188, 0x95 },
+	{ 0x4189, 0x96 },
+	{ 0x418A, 0x96 },
+	{ 0x418B, 0x95 },
+	{ 0x418C, 0xA1 },
+	{ 0x418D, 0xA1 },
+	{ 0x418E, 0xA1 },
+	{ 0x418F, 0xA0 },
+	{ 0x4190, 0xBC },
+	{ 0x4191, 0xB8 },
+	{ 0x4192, 0xB8 },
+	{ 0x4193, 0xB9 },
+	{ 0x4194, 0xA8 },
+	{ 0x4195, 0xA5 },
+	{ 0x4196, 0xA6 },
+	{ 0x4197, 0xA5 },
+	{ 0x4198, 0x9C },
+	{ 0x4199, 0x9A },
+	{ 0x419A, 0x9A },
+	{ 0x419B, 0x9A },
+	{ 0x419C, 0x91 },
+	{ 0x419D, 0x91 },
+	{ 0x419E, 0x91 },
+	{ 0x419F, 0x91 },
+	{ 0x41A0, 0x8B },
+	{ 0x41A1, 0x8B },
+	{ 0x41A2, 0x8B },
+	{ 0x41A3, 0x8B },
+	{ 0x41A4, 0x8C },
+	{ 0x41A5, 0x8C },
+	{ 0x41A6, 0x8C },
+	{ 0x41A7, 0x8C },
+	{ 0x41A8, 0x91 },
+	{ 0x41A9, 0x92 },
+	{ 0x41AA, 0x91 },
+	{ 0x41AB, 0x91 },
+	{ 0x41AC, 0x98 },
+	{ 0x41AD, 0x99 },
+	{ 0x41AE, 0x99 },
+	{ 0x41AF, 0x98 },
+	{ 0x41B0, 0xA3 },
+	{ 0x41B1, 0xA3 },
+	{ 0x41B2, 0xA3 },
+	{ 0x41B3, 0xA2 },
+	{ 0x41B4, 0xC1 },
+	{ 0x41B5, 0xB8 },
+	{ 0x41B6, 0xB9 },
+	{ 0x41B7, 0xBA },
+	{ 0x41B8, 0xB8 },
+	{ 0x41B9, 0xB4 },
+	{ 0x41BA, 0xB4 },
+	{ 0x41BB, 0xB4 },
+	{ 0x41BC, 0xAA },
+	{ 0x41BD, 0xA7 },
+	{ 0x41BE, 0xA7 },
+	{ 0x41BF, 0xA8 },
+	{ 0x41C0, 0xA4 },
+	{ 0x41C1, 0xA2 },
+	{ 0x41C2, 0xA2 },
+	{ 0x41C3, 0xA3 },
+	{ 0x41C4, 0x9E },
+	{ 0x41C5, 0x9D },
+	{ 0x41C6, 0x9D },
+	{ 0x41C7, 0x9D },
+	{ 0x41C8, 0x9E },
+	{ 0x41C9, 0x9D },
+	{ 0x41CA, 0x9D },
+	{ 0x41CB, 0x9D },
+	{ 0x41CC, 0x9E },
+	{ 0x41CD, 0x9E },
+	{ 0x41CE, 0x9E },
+	{ 0x41CF, 0x9E },
+	{ 0x41D0, 0xA3 },
+	{ 0x41D1, 0xA3 },
+	{ 0x41D2, 0xA2 },
+	{ 0x41D3, 0xA1 },
+	{ 0x41D4, 0xA7 },
+	{ 0x41D5, 0xA7 },
+	{ 0x41D6, 0xA7 },
+	{ 0x41D7, 0xA3 },
+	{ 0x4200, 0xCE },
+	{ 0x4201, 0xC0 },
+	{ 0x4202, 0xC1 },
+	{ 0x4203, 0xB9 },
+	{ 0x4204, 0xC3 },
+	{ 0x4205, 0xB9 },
+	{ 0x4206, 0xBC },
+	{ 0x4207, 0xBD },
+	{ 0x4208, 0xB3 },
+	{ 0x4209, 0xAE },
+	{ 0x420A, 0xAF },
+	{ 0x420B, 0xAE },
+	{ 0x420C, 0xAA },
+	{ 0x420D, 0xA8 },
+	{ 0x420E, 0xA8 },
+	{ 0x420F, 0xA6 },
+	{ 0x4210, 0xA4 },
+	{ 0x4211, 0xA2 },
+	{ 0x4212, 0xA2 },
+	{ 0x4213, 0xA0 },
+	{ 0x4214, 0xA4 },
+	{ 0x4215, 0xA3 },
+	{ 0x4216, 0xA2 },
+	{ 0x4217, 0xA0 },
+	{ 0x4218, 0xA7 },
+	{ 0x4219, 0xA5 },
+	{ 0x421A, 0xA3 },
+	{ 0x421B, 0xA1 },
+	{ 0x421C, 0xB0 },
+	{ 0x421D, 0xA8 },
+	{ 0x421E, 0xA8 },
+	{ 0x421F, 0xA6 },
+	{ 0x4220, 0xB4 },
+	{ 0x4221, 0xAA },
+	{ 0x4222, 0xA5 },
+	{ 0x4223, 0xA3 },
+	{ 0x4224, 0xC7 },
+	{ 0x4225, 0xBC },
+	{ 0x4226, 0xBE },
+	{ 0x4227, 0xBC },
+	{ 0x4228, 0xB0 },
+	{ 0x4229, 0xA9 },
+	{ 0x422A, 0xA9 },
+	{ 0x422B, 0xA8 },
+	{ 0x422C, 0xA0 },
+	{ 0x422D, 0x9D },
+	{ 0x422E, 0x9D },
+	{ 0x422F, 0x9C },
+	{ 0x4230, 0x94 },
+	{ 0x4231, 0x93 },
+	{ 0x4232, 0x93 },
+	{ 0x4233, 0x92 },
+	{ 0x4234, 0x8E },
+	{ 0x4235, 0x8D },
+	{ 0x4236, 0x8D },
+	{ 0x4237, 0x8C },
+	{ 0x4238, 0x8F },
+	{ 0x4239, 0x8E },
+	{ 0x423A, 0x8E },
+	{ 0x423B, 0x8D },
+	{ 0x423C, 0x96 },
+	{ 0x423D, 0x94 },
+	{ 0x423E, 0x94 },
+	{ 0x423F, 0x92 },
+	{ 0x4240, 0xA1 },
+	{ 0x4241, 0x9C },
+	{ 0x4242, 0x9C },
+	{ 0x4243, 0x99 },
+	{ 0x4244, 0xB0 },
+	{ 0x4245, 0xA8 },
+	{ 0x4246, 0xAB },
+	{ 0x4247, 0xA7 },
+	{ 0x4248, 0xC3 },
+	{ 0x4249, 0xB7 },
+	{ 0x424A, 0xB7 },
+	{ 0x424B, 0xBC },
+	{ 0x424C, 0xAB },
+	{ 0x424D, 0xA4 },
+	{ 0x424E, 0xA5 },
+	{ 0x424F, 0xA5 },
+	{ 0x4250, 0x9A },
+	{ 0x4251, 0x97 },
+	{ 0x4252, 0x97 },
+	{ 0x4253, 0x98 },
+	{ 0x4254, 0x8C },
+	{ 0x4255, 0x8B },
+	{ 0x4256, 0x8B },
+	{ 0x4257, 0x8B },
+	{ 0x4258, 0x82 },
+	{ 0x4259, 0x82 },
+	{ 0x425A, 0x82 },
+	{ 0x425B, 0x82 },
+	{ 0x425C, 0x85 },
+	{ 0x425D, 0x85 },
+	{ 0x425E, 0x85 },
+	{ 0x425F, 0x84 },
+	{ 0x4260, 0x8F },
+	{ 0x4261, 0x8E },
+	{ 0x4262, 0x8E },
+	{ 0x4263, 0x8D },
+	{ 0x4264, 0x9B },
+	{ 0x4265, 0x98 },
+	{ 0x4266, 0x98 },
+	{ 0x4267, 0x95 },
+	{ 0x4268, 0xAE },
+	{ 0x4269, 0xA5 },
+	{ 0x426A, 0xA7 },
+	{ 0x426B, 0xA2 },
+	{ 0x426C, 0xC2 },
+	{ 0x426D, 0xB7 },
+	{ 0x426E, 0xB8 },
+	{ 0x426F, 0xB9 },
+	{ 0x4270, 0xAA },
+	{ 0x4271, 0xA4 },
+	{ 0x4272, 0xA4 },
+	{ 0x4273, 0xA5 },
+	{ 0x4274, 0x99 },
+	{ 0x4275, 0x96 },
+	{ 0x4276, 0x97 },
+	{ 0x4277, 0x98 },
+	{ 0x4278, 0x8B },
+	{ 0x4279, 0x8A },
+	{ 0x427A, 0x8A },
+	{ 0x427B, 0x8B },
+	{ 0x427C, 0x81 },
+	{ 0x427D, 0x81 },
+	{ 0x427E, 0x81 },
+	{ 0x427F, 0x82 },
+	{ 0x4280, 0x84 },
+	{ 0x4281, 0x84 },
+	{ 0x4282, 0x84 },
+	{ 0x4283, 0x84 },
+	{ 0x4284, 0x8E },
+	{ 0x4285, 0x8E },
+	{ 0x4286, 0x8D },
+	{ 0x4287, 0x8C },
+	{ 0x4288, 0x9A },
+	{ 0x4289, 0x97 },
+	{ 0x428A, 0x97 },
+	{ 0x428B, 0x95 },
+	{ 0x428C, 0xAA },
+	{ 0x428D, 0xA3 },
+	{ 0x428E, 0xA3 },
+	{ 0x428F, 0xA2 },
+	{ 0x4290, 0xC7 },
+	{ 0x4291, 0xBA },
+	{ 0x4292, 0xC0 },
+	{ 0x4293, 0xC3 },
+	{ 0x4294, 0xB0 },
+	{ 0x4295, 0xA7 },
+	{ 0x4296, 0xA7 },
+	{ 0x4297, 0xA9 },
+	{ 0x4298, 0x9F },
+	{ 0x4299, 0x9B },
+	{ 0x429A, 0x9B },
+	{ 0x429B, 0x9D },
+	{ 0x429C, 0x93 },
+	{ 0x429D, 0x91 },
+	{ 0x429E, 0x91 },
+	{ 0x429F, 0x92 },
+	{ 0x42A0, 0x8C },
+	{ 0x42A1, 0x8B },
+	{ 0x42A2, 0x8B },
+	{ 0x42A3, 0x8C },
+	{ 0x42A4, 0x8D },
+	{ 0x42A5, 0x8C },
+	{ 0x42A6, 0x8C },
+	{ 0x42A7, 0x8C },
+	{ 0x42A8, 0x94 },
+	{ 0x42A9, 0x93 },
+	{ 0x42AA, 0x92 },
+	{ 0x42AB, 0x91 },
+	{ 0x42AC, 0x9E },
+	{ 0x42AD, 0x9B },
+	{ 0x42AE, 0x9B },
+	{ 0x42AF, 0x98 },
+	{ 0x42B0, 0xAC },
+	{ 0x42B1, 0xA6 },
+	{ 0x42B2, 0xA6 },
+	{ 0x42B3, 0xA2 },
+	{ 0x42B4, 0xCE },
+	{ 0x42B5, 0xBA },
+	{ 0x42B6, 0xBC },
+	{ 0x42B7, 0xB7 },
+	{ 0x42B8, 0xC5 },
+	{ 0x42B9, 0xB5 },
+	{ 0x42BA, 0xBA },
+	{ 0x42BB, 0xC0 },
+	{ 0x42BC, 0xB1 },
+	{ 0x42BD, 0xA8 },
+	{ 0x42BE, 0xAE },
+	{ 0x42BF, 0xAF },
+	{ 0x42C0, 0xA7 },
+	{ 0x42C1, 0xA3 },
+	{ 0x42C2, 0xA3 },
+	{ 0x42C3, 0xA5 },
+	{ 0x42C4, 0xA0 },
+	{ 0x42C5, 0x9D },
+	{ 0x42C6, 0x9D },
+	{ 0x42C7, 0x9F },
+	{ 0x42C8, 0xA0 },
+	{ 0x42C9, 0x9E },
+	{ 0x42CA, 0x9E },
+	{ 0x42CB, 0x9F },
+	{ 0x42CC, 0xA2 },
+	{ 0x42CD, 0xA0 },
+	{ 0x42CE, 0xA0 },
+	{ 0x42CF, 0xA0 },
+	{ 0x42D0, 0xA8 },
+	{ 0x42D1, 0xA5 },
+	{ 0x42D2, 0xA5 },
+	{ 0x42D3, 0xA2 },
+	{ 0x42D4, 0xB3 },
+	{ 0x42D5, 0xAA },
+	{ 0x42D6, 0xAB },
+	{ 0x42D7, 0xA3 },
+	{ 0x42D8, 0x00 },
+	{ 0x42D9, 0x00 },
+	{ 0x4300, 0xA2 },
+	{ 0x4301, 0xAE },
+	{ 0x4302, 0xAD },
+	{ 0x4303, 0xB5 },
+	{ 0x4304, 0x95 },
+	{ 0x4305, 0x9A },
+	{ 0x4306, 0x98 },
+	{ 0x4307, 0x9B },
+	{ 0x4308, 0x8D },
+	{ 0x4309, 0x90 },
+	{ 0x430A, 0x8F },
+	{ 0x430B, 0x91 },
+	{ 0x430C, 0x86 },
+	{ 0x430D, 0x88 },
+	{ 0x430E, 0x87 },
+	{ 0x430F, 0x89 },
+	{ 0x4310, 0x86 },
+	{ 0x4311, 0x87 },
+	{ 0x4312, 0x86 },
+	{ 0x4313, 0x88 },
+	{ 0x4314, 0x89 },
+	{ 0x4315, 0x88 },
+	{ 0x4316, 0x88 },
+	{ 0x4317, 0x8E },
+	{ 0x4318, 0x90 },
+	{ 0x4319, 0x8F },
+	{ 0x431A, 0x8C },
+	{ 0x431B, 0x8C },
+	{ 0x431C, 0x9C },
+	{ 0x431D, 0x99 },
+	{ 0x431E, 0x98 },
+	{ 0x431F, 0x99 },
+	{ 0x4320, 0xAB },
+	{ 0x4321, 0xB0 },
+	{ 0x4322, 0xAD },
+	{ 0x4323, 0xAF },
+	{ 0x4324, 0x9B },
+	{ 0x4325, 0x9F },
+	{ 0x4326, 0x9E },
+	{ 0x4327, 0xA1 },
+	{ 0x4328, 0x8E },
+	{ 0x4329, 0x91 },
+	{ 0x432A, 0x90 },
+	{ 0x432B, 0x93 },
+	{ 0x432C, 0x86 },
+	{ 0x432D, 0x88 },
+	{ 0x432E, 0x87 },
+	{ 0x432F, 0x89 },
+	{ 0x4330, 0x82 },
+	{ 0x4331, 0x84 },
+	{ 0x4332, 0x83 },
+	{ 0x4333, 0x84 },
+	{ 0x4334, 0x82 },
+	{ 0x4335, 0x82 },
+	{ 0x4336, 0x82 },
+	{ 0x4337, 0x83 },
+	{ 0x4338, 0x85 },
+	{ 0x4339, 0x84 },
+	{ 0x433A, 0x84 },
+	{ 0x433B, 0x85 },
+	{ 0x433C, 0x8A },
+	{ 0x433D, 0x89 },
+	{ 0x433E, 0x88 },
+	{ 0x433F, 0x89 },
+	{ 0x4340, 0x93 },
+	{ 0x4341, 0x91 },
+	{ 0x4342, 0x91 },
+	{ 0x4343, 0x93 },
+	{ 0x4344, 0xA0 },
+	{ 0x4345, 0x9E },
+	{ 0x4346, 0x9D },
+	{ 0x4347, 0xA1 },
+	{ 0x4348, 0x95 },
+	{ 0x4349, 0x9B },
+	{ 0x434A, 0x9A },
+	{ 0x434B, 0x9C },
+	{ 0x434C, 0x8A },
+	{ 0x434D, 0x8D },
+	{ 0x434E, 0x8C },
+	{ 0x434F, 0x8D },
+	{ 0x4350, 0x83 },
+	{ 0x4351, 0x85 },
+	{ 0x4352, 0x84 },
+	{ 0x4353, 0x85 },
+	{ 0x4354, 0x80 },
+	{ 0x4355, 0x81 },
+	{ 0x4356, 0x81 },
+	{ 0x4357, 0x81 },
+	{ 0x4358, 0x80 },
+	{ 0x4359, 0x80 },
+	{ 0x435A, 0x80 },
+	{ 0x435B, 0x80 },
+	{ 0x435C, 0x82 },
+	{ 0x435D, 0x81 },
+	{ 0x435E, 0x81 },
+	{ 0x435F, 0x81 },
+	{ 0x4360, 0x85 },
+	{ 0x4361, 0x84 },
+	{ 0x4362, 0x84 },
+	{ 0x4363, 0x85 },
+	{ 0x4364, 0x8D },
+	{ 0x4365, 0x8B },
+	{ 0x4366, 0x8B },
+	{ 0x4367, 0x8D },
+	{ 0x4368, 0x98 },
+	{ 0x4369, 0x98 },
+	{ 0x436A, 0x95 },
+	{ 0x436B, 0x98 },
+	{ 0x436C, 0x95 },
+	{ 0x436D, 0x9A },
+	{ 0x436E, 0x99 },
+	{ 0x436F, 0x9A },
+	{ 0x4370, 0x8A },
+	{ 0x4371, 0x8D },
+	{ 0x4372, 0x8C },
+	{ 0x4373, 0x8C },
+	{ 0x4374, 0x83 },
+	{ 0x4375, 0x85 },
+	{ 0x4376, 0x84 },
+	{ 0x4377, 0x84 },
+	{ 0x4378, 0x80 },
+	{ 0x4379, 0x80 },
+	{ 0x437A, 0x80 },
+	{ 0x437B, 0x80 },
+	{ 0x437C, 0x7F },
+	{ 0x437D, 0x7F },
+	{ 0x437E, 0x7F },
+	{ 0x437F, 0x7F },
+	{ 0x4380, 0x81 },
+	{ 0x4381, 0x80 },
+	{ 0x4382, 0x80 },
+	{ 0x4383, 0x81 },
+	{ 0x4384, 0x84 },
+	{ 0x4385, 0x83 },
+	{ 0x4386, 0x83 },
+	{ 0x4387, 0x84 },
+	{ 0x4388, 0x8B },
+	{ 0x4389, 0x8A },
+	{ 0x438A, 0x8A },
+	{ 0x438B, 0x8C },
+	{ 0x438C, 0x97 },
+	{ 0x438D, 0x96 },
+	{ 0x438E, 0x96 },
+	{ 0x438F, 0x99 },
+	{ 0x4390, 0x99 },
+	{ 0x4391, 0x9F },
+	{ 0x4392, 0x9E },
+	{ 0x4393, 0x9D },
+	{ 0x4394, 0x8D },
+	{ 0x4395, 0x90 },
+	{ 0x4396, 0x90 },
+	{ 0x4397, 0x8F },
+	{ 0x4398, 0x85 },
+	{ 0x4399, 0x87 },
+	{ 0x439A, 0x87 },
+	{ 0x439B, 0x86 },
+	{ 0x439C, 0x81 },
+	{ 0x439D, 0x83 },
+	{ 0x439E, 0x82 },
+	{ 0x439F, 0x82 },
+	{ 0x43A0, 0x80 },
+	{ 0x43A1, 0x81 },
+	{ 0x43A2, 0x81 },
+	{ 0x43A3, 0x81 },
+	{ 0x43A4, 0x82 },
+	{ 0x43A5, 0x82 },
+	{ 0x43A6, 0x82 },
+	{ 0x43A7, 0x82 },
+	{ 0x43A8, 0x86 },
+	{ 0x43A9, 0x85 },
+	{ 0x43AA, 0x85 },
+	{ 0x43AB, 0x87 },
+	{ 0x43AC, 0x8D },
+	{ 0x43AD, 0x8D },
+	{ 0x43AE, 0x8D },
+	{ 0x43AF, 0x90 },
+	{ 0x43B0, 0x9A },
+	{ 0x43B1, 0x9A },
+	{ 0x43B2, 0x9B },
+	{ 0x43B3, 0x9D },
+	{ 0x43B4, 0xA0 },
+	{ 0x43B5, 0xAD },
+	{ 0x43B6, 0xAC },
+	{ 0x43B7, 0xAA },
+	{ 0x43B8, 0x93 },
+	{ 0x43B9, 0x97 },
+	{ 0x43BA, 0x97 },
+	{ 0x43BB, 0x96 },
+	{ 0x43BC, 0x8B },
+	{ 0x43BD, 0x8E },
+	{ 0x43BE, 0x8E },
+	{ 0x43BF, 0x8C },
+	{ 0x43C0, 0x83 },
+	{ 0x43C1, 0x85 },
+	{ 0x43C2, 0x85 },
+	{ 0x43C3, 0x84 },
+	{ 0x43C4, 0x82 },
+	{ 0x43C5, 0x84 },
+	{ 0x43C6, 0x83 },
+	{ 0x43C7, 0x83 },
+	{ 0x43C8, 0x83 },
+	{ 0x43C9, 0x84 },
+	{ 0x43CA, 0x84 },
+	{ 0x43CB, 0x85 },
+	{ 0x43CC, 0x8A },
+	{ 0x43CD, 0x8A },
+	{ 0x43CE, 0x8A },
+	{ 0x43CF, 0x8C },
+	{ 0x43D0, 0x92 },
+	{ 0x43D1, 0x93 },
+	{ 0x43D2, 0x93 },
+	{ 0x43D3, 0x96 },
+	{ 0x43D4, 0x9F },
+	{ 0x43D5, 0xA6 },
+	{ 0x43D6, 0xA5 },
+	{ 0x43D7, 0xAA },
+	{ 0x4400, 0xA1 },
+	{ 0x4401, 0xAB },
+	{ 0x4402, 0xA7 },
+	{ 0x4403, 0xB0 },
+	{ 0x4404, 0x91 },
+	{ 0x4405, 0x96 },
+	{ 0x4406, 0x94 },
+	{ 0x4407, 0x99 },
+	{ 0x4408, 0x8A },
+	{ 0x4409, 0x8E },
+	{ 0x440A, 0x8C },
+	{ 0x440B, 0x8F },
+	{ 0x440C, 0x85 },
+	{ 0x440D, 0x86 },
+	{ 0x440E, 0x86 },
+	{ 0x440F, 0x88 },
+	{ 0x4410, 0x85 },
+	{ 0x4411, 0x86 },
+	{ 0x4412, 0x85 },
+	{ 0x4413, 0x87 },
+	{ 0x4414, 0x88 },
+	{ 0x4415, 0x87 },
+	{ 0x4416, 0x87 },
+	{ 0x4417, 0x89 },
+	{ 0x4418, 0x91 },
+	{ 0x4419, 0x8F },
+	{ 0x441A, 0x8F },
+	{ 0x441B, 0x90 },
+	{ 0x441C, 0x9C },
+	{ 0x441D, 0x9B },
+	{ 0x441E, 0x9A },
+	{ 0x441F, 0x9A },
+	{ 0x4420, 0xB3 },
+	{ 0x4421, 0xB1 },
+	{ 0x4422, 0xB0 },
+	{ 0x4423, 0xB2 },
+	{ 0x4424, 0x96 },
+	{ 0x4425, 0x9C },
+	{ 0x4426, 0x9A },
+	{ 0x4427, 0x9E },
+	{ 0x4428, 0x8B },
+	{ 0x4429, 0x8F },
+	{ 0x442A, 0x8E },
+	{ 0x442B, 0x91 },
+	{ 0x442C, 0x84 },
+	{ 0x442D, 0x87 },
+	{ 0x442E, 0x86 },
+	{ 0x442F, 0x88 },
+	{ 0x4430, 0x82 },
+	{ 0x4431, 0x83 },
+	{ 0x4432, 0x82 },
+	{ 0x4433, 0x84 },
+	{ 0x4434, 0x82 },
+	{ 0x4435, 0x82 },
+	{ 0x4436, 0x82 },
+	{ 0x4437, 0x83 },
+	{ 0x4438, 0x84 },
+	{ 0x4439, 0x84 },
+	{ 0x443A, 0x84 },
+	{ 0x443B, 0x84 },
+	{ 0x443C, 0x8B },
+	{ 0x443D, 0x89 },
+	{ 0x443E, 0x89 },
+	{ 0x443F, 0x89 },
+	{ 0x4440, 0x95 },
+	{ 0x4441, 0x93 },
+	{ 0x4442, 0x93 },
+	{ 0x4443, 0x93 },
+	{ 0x4444, 0xA2 },
+	{ 0x4445, 0xA2 },
+	{ 0x4446, 0xA1 },
+	{ 0x4447, 0xA0 },
+	{ 0x4448, 0x8F },
+	{ 0x4449, 0x97 },
+	{ 0x444A, 0x97 },
+	{ 0x444B, 0x98 },
+	{ 0x444C, 0x87 },
+	{ 0x444D, 0x8B },
+	{ 0x444E, 0x8A },
+	{ 0x444F, 0x8B },
+	{ 0x4450, 0x81 },
+	{ 0x4451, 0x83 },
+	{ 0x4452, 0x83 },
+	{ 0x4453, 0x84 },
+	{ 0x4454, 0x7F },
+	{ 0x4455, 0x80 },
+	{ 0x4456, 0x80 },
+	{ 0x4457, 0x81 },
+	{ 0x4458, 0x80 },
+	{ 0x4459, 0x80 },
+	{ 0x445A, 0x80 },
+	{ 0x445B, 0x80 },
+	{ 0x445C, 0x82 },
+	{ 0x445D, 0x81 },
+	{ 0x445E, 0x81 },
+	{ 0x445F, 0x81 },
+	{ 0x4460, 0x87 },
+	{ 0x4461, 0x85 },
+	{ 0x4462, 0x85 },
+	{ 0x4463, 0x86 },
+	{ 0x4464, 0x90 },
+	{ 0x4465, 0x8E },
+	{ 0x4466, 0x8E },
+	{ 0x4467, 0x8E },
+	{ 0x4468, 0x9B },
+	{ 0x4469, 0x9C },
+	{ 0x446A, 0x9A },
+	{ 0x446B, 0x9A },
+	{ 0x446C, 0x91 },
+	{ 0x446D, 0x97 },
+	{ 0x446E, 0x95 },
+	{ 0x446F, 0x95 },
+	{ 0x4470, 0x87 },
+	{ 0x4471, 0x8A },
+	{ 0x4472, 0x8A },
+	{ 0x4473, 0x89 },
+	{ 0x4474, 0x81 },
+	{ 0x4475, 0x83 },
+	{ 0x4476, 0x83 },
+	{ 0x4477, 0x83 },
+	{ 0x4478, 0x7F },
+	{ 0x4479, 0x80 },
+	{ 0x447A, 0x80 },
+	{ 0x447B, 0x80 },
+	{ 0x447C, 0x80 },
+	{ 0x447D, 0x80 },
+	{ 0x447E, 0x80 },
+	{ 0x447F, 0x7F },
+	{ 0x4480, 0x81 },
+	{ 0x4481, 0x81 },
+	{ 0x4482, 0x81 },
+	{ 0x4483, 0x81 },
+	{ 0x4484, 0x85 },
+	{ 0x4485, 0x85 },
+	{ 0x4486, 0x85 },
+	{ 0x4487, 0x85 },
+	{ 0x4488, 0x8E },
+	{ 0x4489, 0x8D },
+	{ 0x448A, 0x8D },
+	{ 0x448B, 0x8E },
+	{ 0x448C, 0x9D },
+	{ 0x448D, 0x9C },
+	{ 0x448E, 0x9C },
+	{ 0x448F, 0x9C },
+	{ 0x4490, 0x94 },
+	{ 0x4491, 0x9B },
+	{ 0x4492, 0x9A },
+	{ 0x4493, 0x97 },
+	{ 0x4494, 0x8A },
+	{ 0x4495, 0x8E },
+	{ 0x4496, 0x8E },
+	{ 0x4497, 0x8C },
+	{ 0x4498, 0x84 },
+	{ 0x4499, 0x86 },
+	{ 0x449A, 0x86 },
+	{ 0x449B, 0x84 },
+	{ 0x449C, 0x81 },
+	{ 0x449D, 0x83 },
+	{ 0x449E, 0x83 },
+	{ 0x449F, 0x81 },
+	{ 0x44A0, 0x81 },
+	{ 0x44A1, 0x82 },
+	{ 0x44A2, 0x82 },
+	{ 0x44A3, 0x81 },
+	{ 0x44A4, 0x83 },
+	{ 0x44A5, 0x83 },
+	{ 0x44A6, 0x83 },
+	{ 0x44A7, 0x83 },
+	{ 0x44A8, 0x88 },
+	{ 0x44A9, 0x88 },
+	{ 0x44AA, 0x88 },
+	{ 0x44AB, 0x88 },
+	{ 0x44AC, 0x91 },
+	{ 0x44AD, 0x91 },
+	{ 0x44AE, 0x91 },
+	{ 0x44AF, 0x92 },
+	{ 0x44B0, 0xA0 },
+	{ 0x44B1, 0xA0 },
+	{ 0x44B2, 0xA0 },
+	{ 0x44B3, 0xA0 },
+	{ 0x44B4, 0x9E },
+	{ 0x44B5, 0xA9 },
+	{ 0x44B6, 0xA8 },
+	{ 0x44B7, 0xA3 },
+	{ 0x44B8, 0x90 },
+	{ 0x44B9, 0x95 },
+	{ 0x44BA, 0x95 },
+	{ 0x44BB, 0x92 },
+	{ 0x44BC, 0x8A },
+	{ 0x44BD, 0x8E },
+	{ 0x44BE, 0x8E },
+	{ 0x44BF, 0x8B },
+	{ 0x44C0, 0x84 },
+	{ 0x44C1, 0x86 },
+	{ 0x44C2, 0x86 },
+	{ 0x44C3, 0x84 },
+	{ 0x44C4, 0x84 },
+	{ 0x44C5, 0x85 },
+	{ 0x44C6, 0x85 },
+	{ 0x44C7, 0x84 },
+	{ 0x44C8, 0x86 },
+	{ 0x44C9, 0x87 },
+	{ 0x44CA, 0x87 },
+	{ 0x44CB, 0x86 },
+	{ 0x44CC, 0x8D },
+	{ 0x44CD, 0x8E },
+	{ 0x44CE, 0x8E },
+	{ 0x44CF, 0x8D },
+	{ 0x44D0, 0x98 },
+	{ 0x44D1, 0x98 },
+	{ 0x44D2, 0x99 },
+	{ 0x44D3, 0x9A },
+	{ 0x44D4, 0xA9 },
+	{ 0x44D5, 0xAA },
+	{ 0x44D6, 0xAA },
+	{ 0x44D7, 0xAD },
+	{ 0x4500, 0x9F },
+	{ 0x4501, 0xA8 },
+	{ 0x4502, 0xA5 },
+	{ 0x4503, 0xAF },
+	{ 0x4504, 0x8F },
+	{ 0x4505, 0x96 },
+	{ 0x4506, 0x92 },
+	{ 0x4507, 0x94 },
+	{ 0x4508, 0x89 },
+	{ 0x4509, 0x8D },
+	{ 0x450A, 0x8A },
+	{ 0x450B, 0x8E },
+	{ 0x450C, 0x84 },
+	{ 0x450D, 0x85 },
+	{ 0x450E, 0x84 },
+	{ 0x450F, 0x87 },
+	{ 0x4510, 0x84 },
+	{ 0x4511, 0x85 },
+	{ 0x4512, 0x84 },
+	{ 0x4513, 0x86 },
+	{ 0x4514, 0x87 },
+	{ 0x4515, 0x86 },
+	{ 0x4516, 0x86 },
+	{ 0x4517, 0x88 },
+	{ 0x4518, 0x8F },
+	{ 0x4519, 0x8D },
+	{ 0x451A, 0x8D },
+	{ 0x451B, 0x8F },
+	{ 0x451C, 0x9A },
+	{ 0x451D, 0x9A },
+	{ 0x451E, 0x98 },
+	{ 0x451F, 0x9A },
+	{ 0x4520, 0xAF },
+	{ 0x4521, 0xAF },
+	{ 0x4522, 0xB2 },
+	{ 0x4523, 0xB1 },
+	{ 0x4524, 0x95 },
+	{ 0x4525, 0x9B },
+	{ 0x4526, 0x97 },
+	{ 0x4527, 0x9C },
+	{ 0x4528, 0x8A },
+	{ 0x4529, 0x8E },
+	{ 0x452A, 0x8D },
+	{ 0x452B, 0x90 },
+	{ 0x452C, 0x84 },
+	{ 0x452D, 0x86 },
+	{ 0x452E, 0x85 },
+	{ 0x452F, 0x87 },
+	{ 0x4530, 0x81 },
+	{ 0x4531, 0x82 },
+	{ 0x4532, 0x82 },
+	{ 0x4533, 0x83 },
+	{ 0x4534, 0x81 },
+	{ 0x4535, 0x81 },
+	{ 0x4536, 0x81 },
+	{ 0x4537, 0x82 },
+	{ 0x4538, 0x84 },
+	{ 0x4539, 0x83 },
+	{ 0x453A, 0x83 },
+	{ 0x453B, 0x84 },
+	{ 0x453C, 0x8A },
+	{ 0x453D, 0x88 },
+	{ 0x453E, 0x88 },
+	{ 0x453F, 0x89 },
+	{ 0x4540, 0x94 },
+	{ 0x4541, 0x92 },
+	{ 0x4542, 0x91 },
+	{ 0x4543, 0x92 },
+	{ 0x4544, 0xA1 },
+	{ 0x4545, 0xA0 },
+	{ 0x4546, 0x9C },
+	{ 0x4547, 0x9D },
+	{ 0x4548, 0x8F },
+	{ 0x4549, 0x96 },
+	{ 0x454A, 0x95 },
+	{ 0x454B, 0x92 },
+	{ 0x454C, 0x87 },
+	{ 0x454D, 0x8A },
+	{ 0x454E, 0x89 },
+	{ 0x454F, 0x8A },
+	{ 0x4550, 0x81 },
+	{ 0x4551, 0x83 },
+	{ 0x4552, 0x82 },
+	{ 0x4553, 0x83 },
+	{ 0x4554, 0x7F },
+	{ 0x4555, 0x80 },
+	{ 0x4556, 0x80 },
+	{ 0x4557, 0x81 },
+	{ 0x4558, 0x7F },
+	{ 0x4559, 0x80 },
+	{ 0x455A, 0x7F },
+	{ 0x455B, 0x80 },
+	{ 0x455C, 0x81 },
+	{ 0x455D, 0x81 },
+	{ 0x455E, 0x81 },
+	{ 0x455F, 0x81 },
+	{ 0x4560, 0x86 },
+	{ 0x4561, 0x85 },
+	{ 0x4562, 0x85 },
+	{ 0x4563, 0x85 },
+	{ 0x4564, 0x8F },
+	{ 0x4565, 0x8D },
+	{ 0x4566, 0x8D },
+	{ 0x4567, 0x8D },
+	{ 0x4568, 0x99 },
+	{ 0x4569, 0x9A },
+	{ 0x456A, 0x97 },
+	{ 0x456B, 0x99 },
+	{ 0x456C, 0x90 },
+	{ 0x456D, 0x95 },
+	{ 0x456E, 0x93 },
+	{ 0x456F, 0x92 },
+	{ 0x4570, 0x87 },
+	{ 0x4571, 0x8A },
+	{ 0x4572, 0x88 },
+	{ 0x4573, 0x87 },
+	{ 0x4574, 0x81 },
+	{ 0x4575, 0x83 },
+	{ 0x4576, 0x82 },
+	{ 0x4577, 0x82 },
+	{ 0x4578, 0x7F },
+	{ 0x4579, 0x80 },
+	{ 0x457A, 0x80 },
+	{ 0x457B, 0x80 },
+	{ 0x457C, 0x80 },
+	{ 0x457D, 0x80 },
+	{ 0x457E, 0x80 },
+	{ 0x457F, 0x80 },
+	{ 0x4580, 0x81 },
+	{ 0x4581, 0x81 },
+	{ 0x4582, 0x81 },
+	{ 0x4583, 0x81 },
+	{ 0x4584, 0x85 },
+	{ 0x4585, 0x85 },
+	{ 0x4586, 0x84 },
+	{ 0x4587, 0x85 },
+	{ 0x4588, 0x8E },
+	{ 0x4589, 0x8D },
+	{ 0x458A, 0x8C },
+	{ 0x458B, 0x8D },
+	{ 0x458C, 0x9B },
+	{ 0x458D, 0x9B },
+	{ 0x458E, 0x9A },
+	{ 0x458F, 0x98 },
+	{ 0x4590, 0x94 },
+	{ 0x4591, 0x9A },
+	{ 0x4592, 0x94 },
+	{ 0x4593, 0x90 },
+	{ 0x4594, 0x8A },
+	{ 0x4595, 0x8D },
+	{ 0x4596, 0x8C },
+	{ 0x4597, 0x89 },
+	{ 0x4598, 0x84 },
+	{ 0x4599, 0x86 },
+	{ 0x459A, 0x85 },
+	{ 0x459B, 0x83 },
+	{ 0x459C, 0x82 },
+	{ 0x459D, 0x83 },
+	{ 0x459E, 0x82 },
+	{ 0x459F, 0x80 },
+	{ 0x45A0, 0x81 },
+	{ 0x45A1, 0x82 },
+	{ 0x45A2, 0x81 },
+	{ 0x45A3, 0x80 },
+	{ 0x45A4, 0x83 },
+	{ 0x45A5, 0x83 },
+	{ 0x45A6, 0x83 },
+	{ 0x45A7, 0x83 },
+	{ 0x45A8, 0x88 },
+	{ 0x45A9, 0x87 },
+	{ 0x45AA, 0x87 },
+	{ 0x45AB, 0x88 },
+	{ 0x45AC, 0x91 },
+	{ 0x45AD, 0x90 },
+	{ 0x45AE, 0x90 },
+	{ 0x45AF, 0x91 },
+	{ 0x45B0, 0x9F },
+	{ 0x45B1, 0x9F },
+	{ 0x45B2, 0x9E },
+	{ 0x45B3, 0x9F },
+	{ 0x45B4, 0x9F },
+	{ 0x45B5, 0xA8 },
+	{ 0x45B6, 0xA6 },
+	{ 0x45B7, 0xA7 },
+	{ 0x45B8, 0x8D },
+	{ 0x45B9, 0x95 },
+	{ 0x45BA, 0x90 },
+	{ 0x45BB, 0x8A },
+	{ 0x45BC, 0x89 },
+	{ 0x45BD, 0x8D },
+	{ 0x45BE, 0x88 },
+	{ 0x45BF, 0x86 },
+	{ 0x45C0, 0x84 },
+	{ 0x45C1, 0x86 },
+	{ 0x45C2, 0x85 },
+	{ 0x45C3, 0x82 },
+	{ 0x45C4, 0x84 },
+	{ 0x45C5, 0x85 },
+	{ 0x45C6, 0x85 },
+	{ 0x45C7, 0x83 },
+	{ 0x45C8, 0x86 },
+	{ 0x45C9, 0x86 },
+	{ 0x45CA, 0x86 },
+	{ 0x45CB, 0x85 },
+	{ 0x45CC, 0x8E },
+	{ 0x45CD, 0x8D },
+	{ 0x45CE, 0x8D },
+	{ 0x45CF, 0x8C },
+	{ 0x45D0, 0x99 },
+	{ 0x45D1, 0x98 },
+	{ 0x45D2, 0x98 },
+	{ 0x45D3, 0x98 },
+	{ 0x45D4, 0xA6 },
+	{ 0x45D5, 0xA9 },
+	{ 0x45D6, 0xA7 },
+	{ 0x45D7, 0xAC },
+};
diff -Naur --no-dereference a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
--- a/drivers/media/i2c/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/i2c/Kconfig	2024-01-28 14:01:31.244353788 -0500
@@ -221,6 +221,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called imx355.
 
+config VIDEO_IMX390
+	tristate "Sony IMX390 sensor support"
+	depends on I2C && VIDEO_DEV
+	select MEDIA_CONTROLLER
+	select VIDEO_V4L2_SUBDEV_API
+	help
+	  This is a Video4Linux2 sensor driver for the Sony
+	  IMX390 camera.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called imx390.
+
 config VIDEO_IMX412
 	tristate "Sony IMX412 sensor support"
 	depends on OF_GPIO
@@ -391,6 +403,18 @@
 	  This is a Video4Linux2 sensor driver for the OmniVision
 	  OV13B10 camera.
 
+config VIDEO_OV2312
+	tristate "OmniVision OV2312 sensor support"
+	depends on I2C && VIDEO_DEV
+	select MEDIA_CONTROLLER
+	select VIDEO_V4L2_SUBDEV_API
+	help
+	  This is a Video4Linux2 sensor driver for the OmniVision
+	  OV2312 camera.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ov2312.
+
 config VIDEO_OV2640
 	tristate "OmniVision OV2640 sensor support"
 	depends on VIDEO_DEV && I2C
@@ -1602,4 +1626,51 @@
 
 endmenu
 
+#
+# Video serializers and deserializers (e.g. FPD-Link)
+#
+
+menu "Video serializers and deserializers"
+
+config VIDEO_DS90UB913
+	tristate "TI DS90UB913 FPD-Link III Serializer"
+	depends on OF && I2C && VIDEO_DEV
+	select I2C_ATR
+	select MEDIA_CONTROLLER
+	select OF_GPIO
+	select REGMAP_I2C
+	select V4L2_FWNODE
+	select VIDEO_V4L2_SUBDEV_API
+	help
+	  Device driver for the Texas Instruments DS90UB913
+	  FPD-Link III Serializer.
+
+config VIDEO_DS90UB953
+	tristate "TI FPD-Link III/IV CSI-2 Serializers"
+	depends on OF && I2C && VIDEO_DEV
+	select I2C_ATR
+	select MEDIA_CONTROLLER
+	select OF_GPIO
+	select REGMAP_I2C
+	select V4L2_FWNODE
+	select VIDEO_V4L2_SUBDEV_API
+	help
+	  Device driver for the Texas Instruments DS90UB953
+	  FPD-Link III Serializer and DS90UB971 FPD-Link IV Serializer.
+
+config VIDEO_DS90UB960
+	tristate "TI FPD-Link III/IV Deserializers"
+	depends on OF && I2C && VIDEO_DEV
+	select I2C_ATR
+	select MEDIA_CONTROLLER
+	select OF_GPIO
+	select REGMAP_I2C
+	select V4L2_FWNODE
+	select VIDEO_V4L2_SUBDEV_API
+	help
+	  Device driver for the Texas Instruments DS90UB960
+	  FPD-Link III Deserializer and DS90UB9702 FPD-Link IV Deserializer.
+
+endmenu
+
 endif # VIDEO_DEV
diff -Naur --no-dereference a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
--- a/drivers/media/i2c/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/i2c/Makefile	2024-01-28 14:01:31.244353788 -0500
@@ -29,6 +29,9 @@
 obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
 obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
 obj-$(CONFIG_VIDEO_CX25840) += cx25840/
+obj-$(CONFIG_VIDEO_DS90UB913) += ds90ub913.o
+obj-$(CONFIG_VIDEO_DS90UB953) += ds90ub953.o
+obj-$(CONFIG_VIDEO_DS90UB960) += ds90ub960.o
 obj-$(CONFIG_VIDEO_DW9714) += dw9714.o
 obj-$(CONFIG_VIDEO_DW9768) += dw9768.o
 obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o
@@ -47,6 +50,7 @@
 obj-$(CONFIG_VIDEO_IMX334) += imx334.o
 obj-$(CONFIG_VIDEO_IMX335) += imx335.o
 obj-$(CONFIG_VIDEO_IMX355) += imx355.o
+obj-$(CONFIG_VIDEO_IMX390) += imx390.o
 obj-$(CONFIG_VIDEO_IMX412) += imx412.o
 obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
 obj-$(CONFIG_VIDEO_ISL7998X) += isl7998x.o
@@ -74,6 +78,7 @@
 obj-$(CONFIG_VIDEO_OV08D10) += ov08d10.o
 obj-$(CONFIG_VIDEO_OV13858) += ov13858.o
 obj-$(CONFIG_VIDEO_OV13B10) += ov13b10.o
+obj-$(CONFIG_VIDEO_OV2312) += ov2312.o
 obj-$(CONFIG_VIDEO_OV2640) += ov2640.o
 obj-$(CONFIG_VIDEO_OV2659) += ov2659.o
 obj-$(CONFIG_VIDEO_OV2680) += ov2680.o
diff -Naur --no-dereference a/drivers/media/i2c/ov2312.c b/drivers/media/i2c/ov2312.c
--- a/drivers/media/i2c/ov2312.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/i2c/ov2312.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,781 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Omnivision OV2312 RGB-IR Image Sensor driver
+ *
+ * Copyright (c) 2022 Jai Luthra <j-luthra@ti.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-ctrls.h>
+
+#include "ov2312.h"
+
+struct ov2312 {
+	struct device *dev;
+
+	struct clk *clk;
+	unsigned long clk_rate;
+
+	struct i2c_client *client;
+	struct regmap *regmap;
+	struct gpio_desc *reset_gpio;
+
+	struct v4l2_subdev sd;
+	struct media_pad pad;
+	struct v4l2_mbus_framefmt format;
+
+	struct v4l2_ctrl_handler ctrls;
+	struct v4l2_ctrl *exposure;
+	struct v4l2_ctrl *again;
+	struct v4l2_ctrl *dgain;
+	struct v4l2_ctrl *h_flip;
+	struct v4l2_ctrl *v_flip;
+
+	u32 fps;
+
+	struct mutex lock; /* For streaming status */
+	bool streaming;
+};
+
+static inline struct ov2312 *to_ov2312(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ov2312, sd);
+}
+
+static int ov2312_read(struct ov2312 *ov2312, u16 addr, u32 *val, size_t nbytes)
+{
+	int ret;
+	__le32 val_le = 0;
+
+	ret = regmap_bulk_read(ov2312->regmap, addr, &val_le, nbytes);
+	if (ret < 0) {
+		dev_err(ov2312->dev, "%s: failed to read reg 0x%04x: %d\n",
+			__func__, addr, ret);
+		return ret;
+	}
+
+	*val = le32_to_cpu(val_le);
+	return 0;
+}
+
+static int ov2312_write(struct ov2312 *ov2312, u16 addr, u32 val, size_t nbytes)
+{
+	int ret;
+	__le32 val_le = cpu_to_le32(val);
+
+	ret = regmap_bulk_write(ov2312->regmap, addr, &val_le, nbytes);
+	if (ret < 0)
+		dev_err(ov2312->dev, "%s: failed to write reg 0x%04x: %d\n",
+			__func__, addr, ret);
+	return ret;
+}
+
+static int ov2312_write_table(struct ov2312 *ov2312,
+			      const struct reg_sequence *regs,
+			      unsigned int nr_regs)
+{
+	int ret, i;
+
+	for (i = 0; i < nr_regs; i++) {
+		ret = regmap_write(ov2312->regmap, regs[i].reg, regs[i].def);
+		if (ret < 0) {
+			dev_err(ov2312->dev,
+				"%s: failed to write reg[%d] 0x%04x = 0x%02x (%d)!\n",
+				__func__, i, regs[i].reg, regs[i].def, ret);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static void ov2312_init_formats(struct v4l2_subdev_state *state)
+{
+	struct v4l2_mbus_framefmt *format;
+	int i;
+
+	for (i = 0; i < 2; ++i) {
+		format = v4l2_subdev_state_get_stream_format(state, 0, i);
+		format->code = ov2312_mbus_formats[0];
+		format->width = ov2312_framesizes[0].width;
+		format->height = ov2312_framesizes[0].height;
+		format->field = V4L2_FIELD_NONE;
+		format->colorspace = V4L2_COLORSPACE_DEFAULT;
+	}
+}
+
+static int ov2312_set_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_subdev_state *state,
+			  struct v4l2_subdev_format *fmt)
+{
+	struct ov2312 *ov2312 = to_ov2312(sd);
+	struct v4l2_mbus_framefmt *format;
+	const struct v4l2_area *fsize;
+	u32 code;
+	int ret = 0;
+
+	if (fmt->pad != 0)
+		return -EINVAL;
+
+	if (fmt->stream != 0)
+		return -EINVAL;
+
+	/* Sensor only supports a single format. */
+	code = ov2312_mbus_formats[0];
+
+	/* Find the nearest supported frame size. */
+	fsize = v4l2_find_nearest_size(ov2312_framesizes,
+				       ARRAY_SIZE(ov2312_framesizes), width,
+				       height, fmt->format.width,
+				       fmt->format.height);
+
+	v4l2_subdev_lock_state(state);
+
+	/* Update the stored format and return it. */
+	format = v4l2_subdev_state_get_stream_format(state, fmt->pad, fmt->stream);
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE && ov2312->streaming) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	format->code = code;
+	format->width = fsize->width;
+	format->height = fsize->height;
+
+	fmt->format = *format;
+
+done:
+	v4l2_subdev_unlock_state(state);
+
+	return ret;
+}
+
+static int _ov2312_set_routing(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_state *state)
+{
+	struct v4l2_subdev_route routes[] = {
+		{
+			.source_pad = 0,
+			.source_stream = 0,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+		{
+			.source_pad = 0,
+			.source_stream = 1,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+	};
+
+	struct v4l2_subdev_krouting routing = {
+		.num_routes = ARRAY_SIZE(routes),
+		.routes = routes,
+	};
+
+	int ret;
+
+	ret = v4l2_subdev_set_routing(sd, state, &routing);
+	if (ret < 0)
+		return ret;
+
+	ov2312_init_formats(state);
+
+	return 0;
+}
+
+static int ov2312_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+				 struct v4l2_mbus_frame_desc *fd)
+{
+	struct v4l2_subdev_state *state;
+	struct v4l2_mbus_framefmt *fmt;
+	u32 bpp;
+	int ret = 0;
+	unsigned int i;
+
+	if (pad != 0)
+		return -EINVAL;
+
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	fmt = v4l2_subdev_state_get_stream_format(state, 0, 0);
+	if (!fmt) {
+		ret = -EPIPE;
+		goto out;
+	}
+
+	memset(fd, 0, sizeof(*fd));
+
+	fd->type = V4L2_MBUS_FRAME_DESC_TYPE_CSI2;
+
+	/* pixel stream - 2 virtual channels */
+
+	bpp = 10;
+
+	for (i = 0; i < 2; ++i) {
+		fd->entry[fd->num_entries].stream = i;
+
+		fd->entry[fd->num_entries].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
+		fd->entry[fd->num_entries].length = fmt->width * fmt->height * bpp / 8;
+		fd->entry[fd->num_entries].pixelcode = fmt->code;
+		fd->entry[fd->num_entries].bus.csi2.vc = i;
+		fd->entry[fd->num_entries].bus.csi2.dt = 0x2b; /* RAW10 */
+
+		fd->num_entries++;
+	}
+
+out:
+	v4l2_subdev_unlock_state(state);
+
+	return ret;
+}
+
+static int ov2312_set_routing(struct v4l2_subdev *sd,
+			      struct v4l2_subdev_state *state,
+			      enum v4l2_subdev_format_whence which,
+			      struct v4l2_subdev_krouting *routing)
+{
+	int ret;
+
+	if (routing->num_routes == 0 || routing->num_routes > 2)
+		return -EINVAL;
+
+	v4l2_subdev_lock_state(state);
+
+	ret = _ov2312_set_routing(sd, state);
+
+	v4l2_subdev_unlock_state(state);
+
+	return ret;
+}
+
+static int ov2312_init_cfg(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_state *state)
+{
+	int ret;
+
+	ret = _ov2312_set_routing(sd, state);
+
+	return ret;
+}
+
+static int ov2312_enum_mbus_code(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_state *state,
+				 struct v4l2_subdev_mbus_code_enum *code)
+{
+	if (code->index >= ARRAY_SIZE(ov2312_mbus_formats))
+		return -EINVAL;
+
+	code->code = ov2312_mbus_formats[code->index];
+
+	return 0;
+}
+
+static int ov2312_enum_frame_sizes(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_state *state,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(ov2312_mbus_formats); ++i) {
+		if (ov2312_mbus_formats[i] == fse->code)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(ov2312_mbus_formats))
+		return -EINVAL;
+
+	if (fse->index >= ARRAY_SIZE(ov2312_framesizes))
+		return -EINVAL;
+
+	fse->min_width = ov2312_framesizes[fse->index].width;
+	fse->max_width = fse->min_width;
+	fse->max_height = ov2312_framesizes[fse->index].height;
+	fse->min_height = fse->max_height;
+
+	return 0;
+}
+
+static int ov2312_get_frame_interval(struct v4l2_subdev *sd,
+				     struct v4l2_subdev_frame_interval *fi)
+{
+	struct ov2312 *ov2312 = to_ov2312(sd);
+
+	fi->interval.numerator = 1;
+	fi->interval.denominator = ov2312->fps / 2;
+
+	return 0;
+}
+
+static int ov2312_set_frame_interval(struct v4l2_subdev *sd,
+				     struct v4l2_subdev_frame_interval *fi)
+{
+	struct ov2312 *ov2312 = to_ov2312(sd);
+
+	dev_dbg(ov2312->dev, "%s: Set framerate %dfps\n", __func__,
+		fi->interval.denominator / fi->interval.numerator);
+	if ((fi->interval.denominator / fi->interval.numerator) != ov2312->fps) {
+		dev_err(ov2312->dev, "%s: Framerate can only be %dfps\n",
+			__func__, ov2312->fps);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int ov2312_detect(struct ov2312 *ov2312)
+{
+	int ret;
+	u32 id;
+
+	ret = ov2312_read(ov2312, OV2312_SC_CHIP_ID_HI, &id, 2);
+	if (ret < 0)
+		return ret;
+
+	id = cpu_to_be16(id);
+
+	if (id != OV2312_CHIP_ID) {
+		dev_err(ov2312->dev,
+			"%s: unknown chip ID 0x%04x\n", __func__, id);
+		return -ENODEV;
+	}
+
+	dev_dbg(ov2312->dev, "%s: detected chip ID 0x%04x\n", __func__, id);
+	return 0;
+}
+
+static int ov2312_set_AB_mode(struct ov2312 *ov2312)
+{
+	int i, ret;
+	u32 exposure = ov2312->exposure->val;
+	u32 again = ov2312->again->val;
+	u32 dgain = ov2312->dgain->val;
+	struct reg_sequence ov2312_groupB[] = {
+		{0x3208, 0x00},/* Group B (RGB Dominant VC1) */
+		{OV2312_AEC_PK_EXPO_HI, (exposure >> 8) & 0xff},
+		{OV2312_AEC_PK_EXPO_LO, exposure & 0xff},
+		{OV2312_AEC_PK_AGAIN_HI, (again >> 4) & 0xff},
+		{OV2312_AEC_PK_AGAIN_LO, (again & 0x0f) << 4},
+		{OV2312_AEC_PK_DGAIN_HI, (dgain >> 8) & 0xff},
+		{OV2312_AEC_PK_DGAIN_LO, dgain & 0xff},
+		{0x3920, 0x00},
+		{0x4813, 0x00},/* VC=0. This register takes effect from next frame */
+		{0x3208, 0x10},
+		{0x320D, 0x00},/* Auto mode switch between group0 and group1 ;setting to switch */
+		{0x320D, 0x31},
+		{0x3208, 0xA0},
+	};
+
+	for (i = 0; i < ARRAY_SIZE(ov2312_groupB); i++) {
+		ret = regmap_write(ov2312->regmap, ov2312_groupB[i].reg, ov2312_groupB[i].def);
+		if (ret < 0) {
+			dev_err(ov2312->dev,
+				"%s: failed to write reg[%d] 0x%04x = 0x%02x (%d)!\n",
+				__func__, i, ov2312_groupB[i].reg, ov2312_groupB[i].def, ret);
+			return ret;
+		}
+	}
+
+	msleep(33);
+	return 0;
+}
+
+static int ov2312_set_orientation(struct ov2312 *ov2312)
+{
+	bool v_flip = ov2312->v_flip->val;
+	bool h_flip = ov2312->h_flip->val;
+	u32 reg = (v_flip ? 0x4400 : 0) | (h_flip ? 0x0004 : 0);
+
+	return ov2312_write(ov2312, OV2312_TIMING_VFLIP, be16_to_cpu(reg), 2);
+}
+
+static int ov2312_set_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct ov2312 *ov2312 = container_of(ctrl->handler,
+					     struct ov2312, ctrls);
+	int ret;
+
+	dev_dbg(ov2312->dev, "%s: %s, value: %d\n", __func__,
+		ctrl->name, ctrl->val);
+
+	/*
+	 * If the device is not powered up by the host driver do
+	 * not apply any controls to H/W at this time. Instead
+	 * the controls will be restored right after power-up.
+	 */
+	if (pm_runtime_suspended(ov2312->dev))
+		return 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_EXPOSURE:
+	case V4L2_CID_ANALOGUE_GAIN:
+	case V4L2_CID_DIGITAL_GAIN:
+		ret = ov2312_set_AB_mode(ov2312);
+		break;
+
+	case V4L2_CID_HFLIP:
+	case V4L2_CID_VFLIP:
+		ret = ov2312_set_orientation(ov2312);
+		break;
+
+	default:
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int ov2312_power_on(struct ov2312 *ov2312)
+{
+	int ret;
+
+	ret = clk_prepare_enable(ov2312->clk);
+	if (ret < 0)
+		return ret;
+
+	if (ov2312->reset_gpio) {
+		gpiod_set_value_cansleep(ov2312->reset_gpio, 0);
+		msleep(10);
+		gpiod_set_value_cansleep(ov2312->reset_gpio, 1);
+		msleep(30);
+	}
+	return 0;
+}
+
+static int ov2312_power_off(struct ov2312 *ov2312)
+{
+	if (ov2312->reset_gpio) {
+		gpiod_set_value_cansleep(ov2312->reset_gpio, 0);
+		msleep(10);
+	}
+
+	clk_disable_unprepare(ov2312->clk);
+
+	return 0;
+}
+
+static int ov2312_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ov2312 *ov2312 = to_ov2312(sd);
+
+	return ov2312_power_on(ov2312);
+}
+
+static int ov2312_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ov2312 *ov2312 = to_ov2312(sd);
+
+	return ov2312_power_off(ov2312);
+}
+
+static int ov2312_start_stream(struct ov2312 *ov2312)
+{
+	int ret;
+
+	ret = ov2312_write_table(ov2312, ov2312_1600x1300_60fps_AB,
+				 ARRAY_SIZE(ov2312_1600x1300_60fps_AB));
+	if (ret < 0)
+		return ret;
+
+	/* Update controls on wake up */
+	ret = ov2312_set_orientation(ov2312);
+	if (ret < 0)
+		return ret;
+
+	ret = ov2312_set_AB_mode(ov2312);
+	if (ret < 0)
+		return ret;
+
+	msleep(100);
+
+	/* Set active */
+	ret = ov2312_write(ov2312, OV2312_SYS_MODE_SEL, 1, 1);
+	if (ret < 0)
+		return ret;
+
+	/* No communication is possible for a while after exiting standby */
+	msleep(20);
+	return 0;
+}
+
+static int ov2312_stop_stream(struct ov2312 *ov2312)
+{
+	int ret;
+
+	/* Set standby */
+	ret = ov2312_write(ov2312, OV2312_SYS_MODE_SEL, 0, 1);
+	if (ret < 0)
+		return ret;
+
+	/* No communication is possible for a while after entering standby */
+	usleep_range(10000, 20000);
+	return 0;
+}
+
+static int ov2312_set_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct ov2312 *ov2312 = to_ov2312(sd);
+	int ret;
+
+	mutex_lock(&ov2312->lock);
+	if (ov2312->streaming == enable) {
+		mutex_unlock(&ov2312->lock);
+		return 0;
+	}
+
+	if (enable) {
+		ret = pm_runtime_resume_and_get(ov2312->dev);
+		if (ret < 0)
+			goto err_unlock;
+
+		ret = ov2312_start_stream(ov2312);
+		if (ret < 0)
+			goto err_runtime_put;
+	} else {
+		ret = ov2312_stop_stream(ov2312);
+		if (ret < 0)
+			goto err_runtime_put;
+		pm_runtime_put(ov2312->dev);
+	}
+
+	ov2312->streaming = enable;
+	mutex_unlock(&ov2312->lock);
+	return 0;
+
+err_runtime_put:
+	pm_runtime_put(ov2312->dev);
+
+err_unlock:
+	mutex_unlock(&ov2312->lock);
+	dev_err(ov2312->dev,
+		"%s: failed to setup streaming %d\n", __func__, ret);
+	return ret;
+}
+
+static const struct v4l2_subdev_video_ops ov2312_subdev_video_ops = {
+	.s_stream = ov2312_set_stream,
+	.g_frame_interval = ov2312_get_frame_interval,
+	.s_frame_interval = ov2312_set_frame_interval,
+};
+
+static const struct v4l2_subdev_pad_ops ov2312_subdev_pad_ops = {
+	.init_cfg = ov2312_init_cfg,
+	.get_fmt = v4l2_subdev_get_fmt,
+	.set_fmt = ov2312_set_fmt,
+	.enum_mbus_code = ov2312_enum_mbus_code,
+	.enum_frame_size = ov2312_enum_frame_sizes,
+	.set_routing = ov2312_set_routing,
+	.get_frame_desc	= ov2312_get_frame_desc,
+};
+
+static const struct v4l2_subdev_ops ov2312_subdev_ops = {
+	.video	= &ov2312_subdev_video_ops,
+	.pad	= &ov2312_subdev_pad_ops,
+};
+
+static const struct v4l2_ctrl_ops ov2312_ctrl_ops = {
+	.s_ctrl	= ov2312_set_ctrl,
+};
+
+static const struct dev_pm_ops ov2312_pm_ops = {
+	SET_RUNTIME_PM_OPS(ov2312_suspend, ov2312_resume, NULL)
+};
+
+static int ov2312_probe(struct i2c_client *client)
+{
+	struct ov2312 *ov2312;
+	struct v4l2_subdev *sd;
+	struct v4l2_ctrl_handler *ctrl_hdr;
+	int ret;
+
+	/* Allocate internal struct */
+	ov2312 = devm_kzalloc(&client->dev, sizeof(*ov2312), GFP_KERNEL);
+	if (!ov2312)
+		return -ENOMEM;
+
+	ov2312->dev = &client->dev;
+	ov2312->client = client;
+
+	/* Initialize I2C Regmap */
+	ov2312->regmap = devm_regmap_init_i2c(client, &ov2312_regmap_config);
+	if (IS_ERR(ov2312->regmap))
+		return PTR_ERR(ov2312->regmap);
+
+	/* Initialize Shutdown GPIO */
+	ov2312->reset_gpio = devm_gpiod_get_optional(ov2312->dev, "reset",
+						     GPIOD_OUT_HIGH);
+	if (IS_ERR(ov2312->reset_gpio))
+		return PTR_ERR(ov2312->reset_gpio);
+
+	ov2312->clk = devm_clk_get(ov2312->dev, "xvclk");
+	if (IS_ERR(ov2312->clk))
+		return PTR_ERR(ov2312->clk);
+
+	ov2312->clk_rate = clk_get_rate(ov2312->clk);
+	dev_info(ov2312->dev, "xvclk rate: %lu Hz\n", ov2312->clk_rate);
+
+	if (ov2312->clk_rate < 6000000 || ov2312->clk_rate > 27000000)
+		return -EINVAL;
+
+	/* Power on */
+	ret = ov2312_power_on(ov2312);
+	if (ret < 0)
+		return ret;
+
+	/* Detect sensor */
+	ret = ov2312_detect(ov2312);
+	if (ret < 0)
+		return ret;
+
+	/* Initialize the subdev and its controls. */
+	sd = &ov2312->sd;
+	v4l2_i2c_subdev_init(sd, client, &ov2312_subdev_ops);
+
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+		     V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_STREAMS;
+
+	/* Initialize the media entity. */
+	ov2312->pad.flags = MEDIA_PAD_FL_SOURCE;
+	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
+	ret = media_entity_pads_init(&sd->entity, 1, &ov2312->pad);
+	if (ret < 0) {
+		dev_err(ov2312->dev,
+			"%s: media entity init failed %d\n", __func__, ret);
+		return ret;
+	}
+
+	ov2312->fps = OV2312_FRAMERATE_DEFAULT;
+	mutex_init(&ov2312->lock);
+
+	/* Initialize controls */
+	ctrl_hdr = &ov2312->ctrls;
+	ret = v4l2_ctrl_handler_init(ctrl_hdr, 5);
+	if (ret < 0) {
+		dev_err(ov2312->dev,
+			"%s: ctrl handler init failed: %d\n", __func__, ret);
+		goto err_media_cleanup;
+	}
+
+	ov2312->ctrls.lock = &ov2312->lock;
+
+	/* Add new controls */
+	ov2312->exposure = v4l2_ctrl_new_std(ctrl_hdr, &ov2312_ctrl_ops,
+					     V4L2_CID_EXPOSURE, 1,
+					     OV2312_EXPOSURE_MAX,
+					     1, OV2312_EXPOSURE_DEFAULT);
+
+	ov2312->again = v4l2_ctrl_new_std(ctrl_hdr, &ov2312_ctrl_ops,
+					  V4L2_CID_ANALOGUE_GAIN, 0,
+					  OV2312_AGAIN_MAX, 1,
+					  OV2312_AGAIN_DEFAULT);
+
+	ov2312->dgain = v4l2_ctrl_new_std(ctrl_hdr, &ov2312_ctrl_ops,
+					  V4L2_CID_DIGITAL_GAIN, 0,
+					  OV2312_DGAIN_MAX, 1,
+					  OV2312_DGAIN_DEFAULT);
+
+	ov2312->h_flip = v4l2_ctrl_new_std(ctrl_hdr, &ov2312_ctrl_ops,
+					   V4L2_CID_HFLIP, 0, 1, 1, 0);
+
+	ov2312->v_flip = v4l2_ctrl_new_std(ctrl_hdr, &ov2312_ctrl_ops,
+					   V4L2_CID_VFLIP, 0, 1, 1, 0);
+
+	ov2312->sd.ctrl_handler = ctrl_hdr;
+	if (ov2312->ctrls.error) {
+		ret = ov2312->ctrls.error;
+		dev_err(ov2312->dev,
+			"%s: failed to add the ctrls: %d\n", __func__, ret);
+		goto err_ctrl_free;
+	}
+
+	/* PM Runtime */
+	pm_runtime_enable(ov2312->dev);
+	pm_runtime_set_suspended(ov2312->dev);
+
+	ret = v4l2_subdev_init_finalize(sd);
+	if (ret < 0)
+		goto err_pm_disable;
+
+	/* Finally, register the subdev. */
+	ret = v4l2_async_register_subdev(sd);
+	if (ret < 0) {
+		dev_err(ov2312->dev,
+			"%s: v4l2 subdev register failed %d\n", __func__, ret);
+		goto err_subdev_cleanup;
+	}
+
+	dev_info(ov2312->dev, "ov2312 probed\n");
+	return 0;
+
+err_subdev_cleanup:
+	v4l2_subdev_cleanup(&ov2312->sd);
+
+err_pm_disable:
+	pm_runtime_disable(ov2312->dev);
+
+err_ctrl_free:
+	v4l2_ctrl_handler_free(ctrl_hdr);
+	mutex_destroy(&ov2312->lock);
+
+err_media_cleanup:
+	media_entity_cleanup(&ov2312->sd.entity);
+
+	return ret;
+}
+
+static void ov2312_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ov2312 *ov2312 = to_ov2312(sd);
+
+	v4l2_async_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&ov2312->ctrls);
+	v4l2_subdev_cleanup(&ov2312->sd);
+	media_entity_cleanup(&sd->entity);
+	mutex_destroy(&ov2312->lock);
+
+	pm_runtime_disable(ov2312->dev);
+}
+
+static const struct i2c_device_id ov2312_id[] = {
+	{ "ov2312", 0 },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(i2c, ov2312_id);
+
+#if IS_ENABLED(CONFIG_OF)
+static const struct of_device_id ov2312_of_match[] = {
+	{ .compatible = "ovti,ov2312", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, ov2312_of_match);
+#endif
+
+static struct i2c_driver ov2312_i2c_driver = {
+	.driver = {
+		.name	= "ov2312",
+		.pm	= &ov2312_pm_ops,
+		.of_match_table = of_match_ptr(ov2312_of_match),
+	},
+	.probe_new	= ov2312_probe,
+	.remove		= ov2312_remove,
+	.id_table	= ov2312_id,
+};
+
+module_i2c_driver(ov2312_i2c_driver);
+
+MODULE_AUTHOR("Jai Luthra <j-luthra@ti.com>");
+MODULE_DESCRIPTION("OV2312 RGB-IR Image Sensor driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/media/i2c/ov2312.h b/drivers/media/i2c/ov2312.h
--- a/drivers/media/i2c/ov2312.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/i2c/ov2312.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,267 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Omnivision OV2312 RGB-IR Image Sensor driver
+ *
+ * Copyright (c) 2022 Jai Luthra <j-luthra@ti.com>
+ */
+
+#include <linux/types.h>
+#include <linux/media-bus-format.h>
+
+#define OV2312_CHIP_ID	0x2311
+#define OV2312_FRAMERATE_DEFAULT 60
+
+#define OV2312_OUT_WIDTH	1600
+#define OV2312_OUT_HEIGHT	1300
+#define OV2312_VTS		0x0588
+
+#define OV2312_SYS_MODE_SEL	0x0100
+#define OV2312_SC_CHIP_ID_HI	0x300a
+#define OV2312_SC_CHIP_ID_LO	0x300b
+#define OV2312_AEC_PK_EXPO_HI	0x3501
+#define OV2312_AEC_PK_EXPO_LO	0x3502
+#define OV2312_AEC_PK_AGAIN_HI	0x3508
+#define OV2312_AEC_PK_AGAIN_LO	0x3509
+#define OV2312_AEC_PK_DGAIN_HI	0x350a
+#define OV2312_AEC_PK_DGAIN_LO	0x350b
+#define OV2312_TIMING_VFLIP	0x3820
+#define OV2312_TIMING_HFLIP	0x3821
+
+/* Exposure control */
+#define OV2312_EXPOSURE_MAX	(OV2312_VTS - 12)
+#define OV2312_EXPOSURE_DEFAULT 0x057c
+#define OV2312_IR_EXPOSURE	0x0090
+#define OV2312_IR_STROBE	OV2312_IR_EXPOSURE
+#define OV2312_IR_STROBE_START	(OV2312_VTS - OV2312_IR_EXPOSURE - 7)
+
+/* Analog gain control */
+#define OV2312_AGAIN_MAX	0x1FF
+#define OV2312_AGAIN_DEFAULT	0x010
+
+/* Digital gain control */
+#define OV2312_DGAIN_MAX	0x0FFF
+#define OV2312_DGAIN_DEFAULT	0x0100
+
+static const struct v4l2_area ov2312_framesizes[] = {
+	{
+		.width		= OV2312_OUT_WIDTH,
+		.height		= OV2312_OUT_HEIGHT,
+	},
+};
+
+static const u32 ov2312_mbus_formats[] = {
+	MEDIA_BUS_FMT_SBGGI10_1X10,
+};
+
+static const struct regmap_config ov2312_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+};
+
+static const struct reg_sequence ov2312_1600x1300_60fps_AB[] = {
+	{0x0103, 0x01},
+	{0x0100, 0x00},
+	{0x010c, 0x02},
+	{0x010b, 0x01},
+	{0x0300, 0x01},
+	{0x0302, 0x32},
+	{0x0303, 0x00},
+	{0x0304, 0x03},
+	{0x0305, 0x02},
+	{0x0306, 0x01},
+	{0x030d, 0x5a},
+	{0x030e, 0x04},
+	{0x3001, 0x02},
+	{0x3004, 0x00},
+	{0x3005, 0x00},
+	{0x3006, 0x0a},
+	{0x3011, 0x0d},
+	{0x3014, 0x04},
+	{0x301c, 0xf0},
+	{0x3020, 0x20},
+	{0x302c, 0x00},
+	{0x302d, 0x00},
+	{0x302e, 0x00},
+	{0x302f, 0x03},
+	{0x3030, 0x10},
+	{0x303f, 0x03},
+	{0x3103, 0x00},
+	{0x3106, 0x08},
+	{0x31ff, 0x01},
+	{0x3501, 0x05},
+	{0x3502, 0x7c},
+	{0x3506, 0x00},
+	{0x3507, 0x00},
+	{0x3620, 0x67},
+	{0x3633, 0x78},
+	{0x3662, 0x65},
+	{0x3664, 0xb0},
+	{0x3666, 0x70},
+	{0x3670, 0x68},
+	{0x3674, 0x10},
+	{0x3675, 0x00},
+	{0x367e, 0x90},
+	{0x3680, 0x84},
+	{0x36a2, 0x04},
+	{0x36a3, 0x80},
+	{0x36b0, 0x00},
+	{0x3700, 0x35},
+	{0x3704, 0x39},
+	{0x370a, 0x50},
+	{0x3712, 0x00},
+	{0x3713, 0x02},
+	{0x3778, 0x00},
+	{0x379b, 0x01},
+	{0x379c, 0x10},
+	{0x3800, 0x00},
+	{0x3801, 0x00},
+	{0x3802, 0x00},
+	{0x3803, 0x00},
+	{0x3804, 0x06},
+	{0x3805, 0x4f},
+	{0x3806, 0x05},
+	{0x3807, 0x23},
+	{0x3808, 0x06},
+	{0x3809, 0x40},
+	{0x380a, 0x05},
+	{0x380b, 0x14},
+	{0x380c, 0x03},
+	{0x380d, 0xa8},
+	{0x380e, (OV2312_VTS >> 8) & 0xff},
+	{0x380f, OV2312_VTS & 0xff},
+	{0x3810, 0x00},
+	{0x3811, 0x08},
+	{0x3812, 0x00},
+	{0x3813, 0x08},
+	{0x3814, 0x11},
+	{0x3815, 0x11},
+	{0x3816, 0x00},
+	{0x3817, 0x01},
+	{0x3818, 0x00},
+	{0x3819, 0x05},
+	{0x382b, 0x5a},
+	{0x382c, 0x0a},
+	{0x382d, 0xf8},
+	{0x3881, 0x44},
+	{0x3882, 0x02},
+	{0x3883, 0x8c},
+	{0x3885, 0x07},
+	{0x389d, 0x03},
+	{0x38a6, 0x00},
+	{0x38a7, 0x01},
+	{0x38b3, 0x07},
+	{0x38b1, 0x00},
+	{0x38e5, 0x02},
+	{0x38e7, 0x00},
+	{0x38e8, 0x00},
+	{0x3910, 0xff},
+	{0x3911, 0xff},
+	{0x3912, 0x08},
+	{0x3913, 0x00},
+	{0x3914, 0x00},
+	{0x3915, 0x00},
+	{0x391c, 0x00},
+	{0x3920, 0xff},
+	{0x3921, 0x80},
+	{0x3922, 0x00},
+	{0x3923, 0x00},
+	{0x3924, 0x05},
+	{0x3925, 0x00},
+	{0x3926, 0x00},
+	{0x3927, 0x00},
+	{0x3928, 0x1a},
+	{0x392d, 0x03},
+	{0x392e, 0xa8},
+	{0x392f, 0x08},
+	{0x4001, 0x00},
+	{0x4003, 0x40},
+	{0x4008, 0x04},
+	{0x4009, 0x1b},
+	{0x400c, 0x04},
+	{0x400d, 0x1b},
+	{0x4010, 0xf4},
+	{0x4011, 0x00},
+	{0x4016, 0x00},
+	{0x4017, 0x04},
+	{0x4042, 0x11},
+	{0x4043, 0x70},
+	{0x4045, 0x00},
+	{0x4409, 0x5f},
+	{0x4509, 0x00},
+	{0x450b, 0x00},
+	{0x4600, 0x00},
+	{0x4601, 0x80},
+	{0x4708, 0x09},
+	{0x470c, 0x81},
+	{0x4710, 0x06},
+	{0x4711, 0x00},
+	{0x4800, 0x00},
+	{0x481f, 0x30},
+	{0x4837, 0x14},
+	{0x4f00, 0x00},
+	{0x4f07, 0x00},
+	{0x4f08, 0x03},
+	{0x4f09, 0x08},
+	{0x4f0c, 0x05},
+	{0x4f0d, 0xb4},
+	{0x4f10, 0x00},
+	{0x4f11, 0x00},
+	{0x4f12, 0x07},
+	{0x4f13, 0xe2},
+	{0x5000, 0x9f},
+	{0x5001, 0x20},
+	{0x5026, 0x00},
+	{0x5c00, 0x00},
+	{0x5c01, 0x2c},
+	{0x5c02, 0x00},
+	{0x5c03, 0x7f},
+	{0x5e00, 0x00},
+	{0x5e01, 0x41},
+	{0x38b1, 0x02},
+	{0x0100, 0x01},
+	{0x3006, 0x08},/* Strobe control  */
+	{0x3004, 0x02},
+	{0x3007, 0x02},
+	{0x301c, 0x20},
+	{0x3020, 0x20},
+	{0x3025, 0x02},
+	{0x382c, 0x0a},
+	{0x382d, 0xf8},
+	{0x3920, 0xff},
+	{0x3921, 0x00},
+	{0x3923, 0x00},
+	{0x3924, 0x00},
+	{0x3925, 0x00},
+	{0x3926, 0x00},
+	{0x3927, 0x00},
+	{0x3928, 0x80},
+	{0x392b, 0x00},
+	{0x392c, 0x00},
+	{0x392d, 0x03},
+	{0x392e, 0xa8},
+	{0x392f, 0x0b},
+	{0x38b3, 0x07},
+	{0x3885, 0x07},
+	{0x382b, 0x3a},
+	{0x3670, 0x68},
+	{0x301C, 0xF0},/* AB mode - Group auto switch example setting */
+	{0x3209, 0x01},/* Stay in Group A for 1 Frame */
+	{0x320A, 0x01},/* Stay in Group B for 1 Frame */
+	{0x320B, 0x00},
+	{0x320C, 0x00},
+	{0x3208, 0x01},/* Group A (IR Dominant VC0) */
+	{OV2312_AEC_PK_EXPO_HI, (OV2312_IR_EXPOSURE >> 8) & 0xff},
+	{OV2312_AEC_PK_EXPO_LO, OV2312_IR_EXPOSURE & 0xff},
+	{OV2312_AEC_PK_AGAIN_HI, 0x01},
+	{OV2312_AEC_PK_AGAIN_LO, 0x00},
+	{OV2312_AEC_PK_DGAIN_HI, 0x01},
+	{OV2312_AEC_PK_DGAIN_LO, 0x00},
+	{0x3920, 0xff},/* IR Strobe duty cycle */
+	{0x3927, (OV2312_IR_STROBE >> 8) & 0xff},
+	{0x3928, OV2312_IR_STROBE & 0xff},
+	{0x3929, (OV2312_IR_STROBE_START >> 8) & 0xff},
+	{0x392a, OV2312_IR_STROBE_START & 0xff},
+	{0x4813, 0x01},/* VC=1. This register takes effect from next frame */
+	{0x3208, 0x11},
+
+};
diff -Naur --no-dereference a/drivers/media/i2c/ov5640.c b/drivers/media/i2c/ov5640.c
--- a/drivers/media/i2c/ov5640.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/i2c/ov5640.c	2024-01-28 14:01:31.244353788 -0500
@@ -178,8 +178,8 @@
 	248000000, 192000000, 192000000, 192000000, 96000000,
 };
 
-/* Link freq for default mode: UYVY 16 bpp, 2 data lanes. */
-#define OV5640_DEFAULT_LINK_FREQ	13
+/* Link freq for default mode: UYVY 640x480, 16 bpp, 2 data lanes. */
+#define OV5640_DEFAULT_LINK_FREQ	19
 
 enum ov5640_format_mux {
 	OV5640_FMT_MUX_YUV422 = 0,
@@ -521,7 +521,18 @@
  */
 /* YUV422 UYVY VGA@30fps */
 
-static const struct v4l2_mbus_framefmt ov5640_default_fmt = {
+static const struct v4l2_mbus_framefmt ov5640_csi2_default_fmt = {
+	.code = MEDIA_BUS_FMT_UYVY8_1X16,
+	.width = 640,
+	.height = 480,
+	.colorspace = V4L2_COLORSPACE_SRGB,
+	.ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SRGB),
+	.quantization = V4L2_QUANTIZATION_FULL_RANGE,
+	.xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SRGB),
+	.field = V4L2_FIELD_NONE,
+};
+
+static const struct v4l2_mbus_framefmt ov5640_dvp_default_fmt = {
 	.code = MEDIA_BUS_FMT_UYVY8_2X8,
 	.width = 640,
 	.height = 480,
@@ -2735,20 +2746,20 @@
 
 static int ov5640_try_frame_interval(struct ov5640_dev *sensor,
 				     struct v4l2_fract *fi,
-				     u32 width, u32 height)
+				     const struct ov5640_mode_info *mode_info)
 {
-	const struct ov5640_mode_info *mode;
+	const struct ov5640_mode_info *mode = mode_info;
 	enum ov5640_frame_rate rate = OV5640_15_FPS;
 	int minfps, maxfps, best_fps, fps;
 	int i;
 
 	minfps = ov5640_framerates[OV5640_15_FPS];
-	maxfps = ov5640_framerates[OV5640_60_FPS];
+	maxfps = ov5640_framerates[mode->max_fps];
 
 	if (fi->numerator == 0) {
 		fi->denominator = maxfps;
 		fi->numerator = 1;
-		rate = OV5640_60_FPS;
+		rate = mode->max_fps;
 		goto find_mode;
 	}
 
@@ -2769,7 +2780,7 @@
 	fi->denominator = best_fps;
 
 find_mode:
-	mode = ov5640_find_mode(sensor, width, height, false);
+	mode = ov5640_find_mode(sensor, mode->width, mode->height, false);
 	return mode ? rate : -EINVAL;
 }
 
@@ -3332,6 +3343,7 @@
 		break;
 	}
 
+	pm_runtime_mark_last_busy(&sensor->i2c_client->dev);
 	pm_runtime_put_autosuspend(&sensor->i2c_client->dev);
 
 	return 0;
@@ -3407,6 +3419,7 @@
 		break;
 	}
 
+	pm_runtime_mark_last_busy(&sensor->i2c_client->dev);
 	pm_runtime_put_autosuspend(&sensor->i2c_client->dev);
 
 	return ret;
@@ -3570,6 +3583,7 @@
 	struct v4l2_subdev_frame_interval_enum *fie)
 {
 	struct ov5640_dev *sensor = to_ov5640_dev(sd);
+	const struct ov5640_mode_info *mode;
 	struct v4l2_fract tpf;
 	int ret;
 
@@ -3578,11 +3592,14 @@
 	if (fie->index >= OV5640_NUM_FRAMERATES)
 		return -EINVAL;
 
+	mode = ov5640_find_mode(sensor, fie->width, fie->height, false);
+	if (!mode)
+		return -EINVAL;
+
 	tpf.numerator = 1;
 	tpf.denominator = ov5640_framerates[fie->index];
 
-	ret = ov5640_try_frame_interval(sensor, &tpf,
-					fie->width, fie->height);
+	ret = ov5640_try_frame_interval(sensor, &tpf, mode);
 	if (ret < 0)
 		return -EINVAL;
 
@@ -3621,9 +3638,7 @@
 
 	mode = sensor->current_mode;
 
-	frame_rate = ov5640_try_frame_interval(sensor, &fi->interval,
-					       mode->width,
-					       mode->height);
+	frame_rate = ov5640_try_frame_interval(sensor, &fi->interval, mode);
 	if (frame_rate < 0) {
 		/* Always return a valid frame interval value */
 		fi->interval = sensor->frame_interval;
@@ -3724,8 +3739,10 @@
 out:
 	mutex_unlock(&sensor->lock);
 
-	if (!enable || ret)
+	if (!enable || ret) {
+		pm_runtime_mark_last_busy(&sensor->i2c_client->dev);
 		pm_runtime_put_autosuspend(&sensor->i2c_client->dev);
+	}
 
 	return ret;
 }
@@ -3733,11 +3750,13 @@
 static int ov5640_init_cfg(struct v4l2_subdev *sd,
 			   struct v4l2_subdev_state *state)
 {
+	struct ov5640_dev *sensor = to_ov5640_dev(sd);
 	struct v4l2_mbus_framefmt *fmt =
 				v4l2_subdev_get_try_format(sd, state, 0);
 	struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, state, 0);
 
-	*fmt = ov5640_default_fmt;
+	*fmt = ov5640_is_csi2(sensor) ? ov5640_csi2_default_fmt :
+					ov5640_dvp_default_fmt;
 
 	crop->left = OV5640_PIXEL_ARRAY_LEFT;
 	crop->top = OV5640_PIXEL_ARRAY_TOP;
@@ -3826,7 +3845,6 @@
 	 * default init sequence initialize sensor to
 	 * YUV422 UYVY VGA@30fps
 	 */
-	sensor->fmt = ov5640_default_fmt;
 	sensor->frame_interval.numerator = 1;
 	sensor->frame_interval.denominator = ov5640_framerates[OV5640_30_FPS];
 	sensor->current_fr = OV5640_30_FPS;
@@ -3859,6 +3877,9 @@
 		return -EINVAL;
 	}
 
+	sensor->fmt = ov5640_is_csi2(sensor) ? ov5640_csi2_default_fmt :
+					       ov5640_dvp_default_fmt;
+
 	/* get system clock (xclk) */
 	sensor->xclk = devm_clk_get(dev, "xclk");
 	if (IS_ERR(sensor->xclk)) {
@@ -3924,8 +3945,9 @@
 	if (ret)
 		goto err_pm_runtime;
 
-	pm_runtime_set_autosuspend_delay(dev, 1000);
+	pm_runtime_set_autosuspend_delay(dev, -1);
 	pm_runtime_use_autosuspend(dev);
+	pm_runtime_mark_last_busy(dev);
 	pm_runtime_put_autosuspend(dev);
 
 	return 0;
diff -Naur --no-dereference a/drivers/media/platform/cadence/cdns-csi2rx.c b/drivers/media/platform/cadence/cdns-csi2rx.c
--- a/drivers/media/platform/cadence/cdns-csi2rx.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/cadence/cdns-csi2rx.c	2024-01-28 14:01:31.244353788 -0500
@@ -8,6 +8,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_graph.h>
@@ -30,14 +31,25 @@
 #define CSI2RX_STATIC_CFG_DLANE_MAP(llane, plane)	((plane) << (16 + (llane) * 4))
 #define CSI2RX_STATIC_CFG_LANES_MASK			GENMASK(11, 8)
 
+#define CSI2RX_DPHY_LANE_CTRL_REG		0x40
+#define CSI2RX_DPHY_CL_RST			BIT(16)
+#define CSI2RX_DPHY_DL_RST(i)			BIT((i) + 12)
+#define CSI2RX_DPHY_CL_EN			BIT(4)
+#define CSI2RX_DPHY_DL_EN(i)			BIT(i)
+
 #define CSI2RX_STREAM_BASE(n)		(((n) + 1) * 0x100)
 
 #define CSI2RX_STREAM_CTRL_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x000)
+#define CSI2RX_STREAM_CTRL_SOFT_RST			BIT(4)
+#define CSI2RX_STREAM_CTRL_STOP				BIT(1)
 #define CSI2RX_STREAM_CTRL_START			BIT(0)
 
+#define CSI2RX_STREAM_STATUS_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x004)
+#define CSI2RX_STREAM_STATUS_RDY			BIT(31)
+
 #define CSI2RX_STREAM_DATA_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x008)
-#define CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT		BIT(31)
 #define CSI2RX_STREAM_DATA_CFG_VC_SELECT(n)		BIT((n) + 16)
+#define CSI2RX_STREAM_DATA_CFG_VC_ALL			0
 
 #define CSI2RX_STREAM_CFG_REG(n)		(CSI2RX_STREAM_BASE(n) + 0x00c)
 #define CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF		(1 << 8)
@@ -54,6 +66,11 @@
 	CSI2RX_PAD_MAX,
 };
 
+struct csi2rx_fmt {
+	u32				code;
+	u8				bpp;
+};
+
 struct csi2rx_priv {
 	struct device			*dev;
 	unsigned int			count;
@@ -85,6 +102,131 @@
 	int				source_pad;
 };
 
+static const struct csi2rx_fmt formats[] = {
+	{
+		.code	= MEDIA_BUS_FMT_YUYV8_1X16,
+		.bpp	= 16,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_UYVY8_1X16,
+		.bpp	= 16,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_YVYU8_1X16,
+		.bpp	= 16,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_VYUY8_1X16,
+		.bpp	= 16,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.bpp	= 8,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGBRG8_1X8,
+		.bpp	= 8,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.bpp	= 8,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SRGGB8_1X8,
+		.bpp	= 8,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGBRG10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGRBG10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SRGGB10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SBGGR12_1X12,
+		.bpp	= 12,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGBRG12_1X12,
+		.bpp	= 12,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGRBG12_1X12,
+		.bpp	= 12,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SRGGB12_1X12,
+		.bpp	= 12,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SRGGI10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGRIG10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SBGGI10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGBIG10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGIRG10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SIGGR10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SGIBG10_1X10,
+		.bpp	= 10,
+	},
+	{
+		.code	= MEDIA_BUS_FMT_SIGGB10_1X10,
+		.bpp	= 10,
+	},
+};
+
+static const struct csi2rx_fmt *csi2rx_get_fmt_by_code(u32 code)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(formats); i++)
+		if (formats[i].code == code)
+			return &formats[i];
+
+	return NULL;
+}
+
+static int csi2rx_get_frame_desc_from_source(struct csi2rx_priv *csi2rx,
+					     struct v4l2_mbus_frame_desc *fd)
+{
+	struct media_pad *remote_pad;
+
+	remote_pad = media_entity_remote_source_pad_unique(&csi2rx->subdev.entity);
+	if (!remote_pad) {
+		dev_err(csi2rx->dev, "No remote pad found for sink\n");
+		return -ENODEV;
+	}
+
+	return v4l2_subdev_call(csi2rx->source_subdev, pad, get_frame_desc,
+				remote_pad->index, fd);
+}
+
 static inline
 struct csi2rx_priv *v4l2_subdev_to_csi2rx(struct v4l2_subdev *subdev)
 {
@@ -93,12 +235,63 @@
 
 static void csi2rx_reset(struct csi2rx_priv *csi2rx)
 {
+	unsigned int i;
+
 	writel(CSI2RX_SOFT_RESET_PROTOCOL | CSI2RX_SOFT_RESET_FRONT,
 	       csi2rx->base + CSI2RX_SOFT_RESET_REG);
 
 	udelay(10);
 
 	writel(0, csi2rx->base + CSI2RX_SOFT_RESET_REG);
+
+	/* Reset individual streams. */
+	for (i = 0; i < csi2rx->max_streams; i++) {
+		writel(CSI2RX_STREAM_CTRL_SOFT_RST,
+		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+		usleep_range(10, 20);
+		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+	}
+}
+
+static int csi2rx_configure_external_dphy(struct csi2rx_priv *csi2rx)
+{
+	union phy_configure_opts opts = { };
+	struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
+	struct v4l2_mbus_framefmt *framefmt;
+	struct v4l2_subdev_state *state;
+	const struct csi2rx_fmt *fmt;
+	s64 link_freq;
+	int ret;
+
+	state = v4l2_subdev_get_locked_active_state(&csi2rx->subdev);
+	framefmt = v4l2_subdev_state_get_stream_format(state, CSI2RX_PAD_SINK, 0);
+
+	if (framefmt) {
+		fmt = csi2rx_get_fmt_by_code(framefmt->code);
+	} else {
+		dev_err(csi2rx->dev, "Did not find active sink format\n");
+		fmt = &formats[0];
+	}
+
+	link_freq = v4l2_get_link_freq(csi2rx->source_subdev->ctrl_handler,
+				       fmt->bpp, 2 * csi2rx->num_lanes);
+	if (link_freq < 0)
+		return link_freq;
+
+	ret = phy_mipi_dphy_get_default_config_for_hsclk(link_freq,
+							 csi2rx->num_lanes, cfg);
+	if (ret)
+		return ret;
+
+	ret = phy_power_on(csi2rx->dphy);
+	if (ret)
+		return ret;
+
+	ret = phy_configure(csi2rx->dphy, &opts);
+	if (ret)
+		phy_power_off(csi2rx->dphy);
+
+	return ret;
 }
 
 static int csi2rx_start(struct csi2rx_priv *csi2rx)
@@ -135,9 +328,23 @@
 
 	writel(reg, csi2rx->base + CSI2RX_STATIC_CFG_REG);
 
-	ret = v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, true);
-	if (ret)
-		goto err_disable_pclk;
+	/* Enable DPHY clk and data lanes. */
+	if (csi2rx->dphy) {
+		reg = CSI2RX_DPHY_CL_EN | CSI2RX_DPHY_CL_RST;
+		for (i = 0; i < csi2rx->num_lanes; i++) {
+			reg |= CSI2RX_DPHY_DL_EN(csi2rx->lanes[i] - 1);
+			reg |= CSI2RX_DPHY_DL_RST(csi2rx->lanes[i] - 1);
+		}
+
+		writel(reg, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG);
+
+		ret = csi2rx_configure_external_dphy(csi2rx);
+		if (ret) {
+			dev_err(csi2rx->dev,
+				"Failed to configure external DPHY: %d\n", ret);
+			goto err_disable_pclk;
+		}
+	}
 
 	/*
 	 * Create a static mapping between the CSI virtual channels
@@ -157,8 +364,8 @@
 		writel(CSI2RX_STREAM_CFG_FIFO_MODE_LARGE_BUF,
 		       csi2rx->base + CSI2RX_STREAM_CFG_REG(i));
 
-		writel(CSI2RX_STREAM_DATA_CFG_EN_VC_SELECT |
-		       CSI2RX_STREAM_DATA_CFG_VC_SELECT(i),
+		/* Let all virtual channels through. */
+		writel(CSI2RX_STREAM_DATA_CFG_VC_ALL,
 		       csi2rx->base + CSI2RX_STREAM_DATA_CFG_REG(i));
 
 		writel(CSI2RX_STREAM_CTRL_START,
@@ -177,6 +384,10 @@
 	for (; i > 0; i--)
 		clk_disable_unprepare(csi2rx->pixel_clk[i - 1]);
 
+	if (csi2rx->dphy) {
+		writel(0, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG);
+		phy_power_off(csi2rx->dphy);
+	}
 err_disable_pclk:
 	clk_disable_unprepare(csi2rx->p_clk);
 
@@ -186,62 +397,259 @@
 static void csi2rx_stop(struct csi2rx_priv *csi2rx)
 {
 	unsigned int i;
+	u32 val;
+	int ret;
 
 	clk_prepare_enable(csi2rx->p_clk);
 	clk_disable_unprepare(csi2rx->sys_clk);
 
 	for (i = 0; i < csi2rx->max_streams; i++) {
-		writel(0, csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+		writel(CSI2RX_STREAM_CTRL_STOP,
+		       csi2rx->base + CSI2RX_STREAM_CTRL_REG(i));
+
+		ret = readl_relaxed_poll_timeout(csi2rx->base +
+						 CSI2RX_STREAM_STATUS_REG(i),
+						 val,
+						 !(val & CSI2RX_STREAM_STATUS_RDY),
+						 10, 10000);
+		if (ret)
+			dev_warn(csi2rx->dev, "Failed to stop stream%u\n", i);
 
 		clk_disable_unprepare(csi2rx->pixel_clk[i]);
 	}
 
 	clk_disable_unprepare(csi2rx->p_clk);
 
-	if (v4l2_subdev_call(csi2rx->source_subdev, video, s_stream, false))
-		dev_warn(csi2rx->dev, "Couldn't disable our subdev\n");
+	if (csi2rx->dphy) {
+		writel(0, csi2rx->base + CSI2RX_DPHY_LANE_CTRL_REG);
+
+		if (phy_power_off(csi2rx->dphy))
+			dev_warn(csi2rx->dev, "Couldn't power off DPHY\n");
+	}
 }
 
-static int csi2rx_s_stream(struct v4l2_subdev *subdev, int enable)
+static int csi2rx_enable_streams(struct v4l2_subdev *subdev,
+				 struct v4l2_subdev_state *state, u32 pad,
+				 u64 streams_mask)
 {
 	struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev);
-	int ret = 0;
+	struct media_pad *remote_pad;
+	u64 sink_streams;
+	int ret;
 
-	mutex_lock(&csi2rx->lock);
+	remote_pad = media_pad_remote_pad_first(&csi2rx->pads[CSI2RX_PAD_SINK]);
+	if (!remote_pad) {
+		dev_err(csi2rx->dev,
+			"Failed to find connected source\n");
+		return -ENODEV;
+	}
 
-	if (enable) {
-		/*
-		 * If we're not the first users, there's no need to
-		 * enable the whole controller.
-		 */
-		if (!csi2rx->count) {
-			ret = csi2rx_start(csi2rx);
-			if (ret)
-				goto out;
-		}
+	ret = pm_runtime_resume_and_get(csi2rx->dev);
+	if (ret < 0)
+		return ret;
 
-		csi2rx->count++;
-	} else {
-		csi2rx->count--;
+	sink_streams = v4l2_subdev_state_xlate_streams(state,
+						       CSI2RX_PAD_SOURCE_STREAM0,
+						       CSI2RX_PAD_SINK,
+						       &streams_mask);
+
+	mutex_lock(&csi2rx->lock);
+	/*
+	 * If we're not the first users, there's no need to
+	 * enable the whole controller.
+	 */
+	if (!csi2rx->count) {
+		ret = csi2rx_start(csi2rx);
+		if (ret)
+			goto err_stream_start;
+	}
 
-		/*
-		 * Let the last user turn off the lights.
-		 */
-		if (!csi2rx->count)
-			csi2rx_stop(csi2rx);
+	/* Start streaming on the source */
+	ret = v4l2_subdev_enable_streams(csi2rx->source_subdev, remote_pad->index,
+					 sink_streams);
+	if (ret) {
+		dev_err(csi2rx->dev,
+			"Failed to start streams %#llx on subdev\n",
+			sink_streams);
+		goto err_subdev_enable;
 	}
 
-out:
+	csi2rx->count++;
+	mutex_unlock(&csi2rx->lock);
+
+	return 0;
+
+err_subdev_enable:
+	if (!csi2rx->count)
+		csi2rx_stop(csi2rx);
+err_stream_start:
 	mutex_unlock(&csi2rx->lock);
+	pm_runtime_put(csi2rx->dev);
 	return ret;
 }
 
-static const struct v4l2_subdev_video_ops csi2rx_video_ops = {
-	.s_stream	= csi2rx_s_stream,
+static int csi2rx_disable_streams(struct v4l2_subdev *subdev,
+				  struct v4l2_subdev_state *state, u32 pad,
+				  u64 streams_mask)
+{
+	struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev);
+	struct media_pad *remote_pad;
+	u64 sink_streams;
+
+	sink_streams = v4l2_subdev_state_xlate_streams(state,
+						       CSI2RX_PAD_SOURCE_STREAM0,
+						       CSI2RX_PAD_SINK,
+						       &streams_mask);
+
+	remote_pad = media_pad_remote_pad_first(&csi2rx->pads[CSI2RX_PAD_SINK]);
+	if (!remote_pad ||
+	    v4l2_subdev_disable_streams(csi2rx->source_subdev,
+					remote_pad->index, sink_streams)) {
+		dev_err(csi2rx->dev, "Couldn't disable our subdev\n");
+	}
+
+	mutex_lock(&csi2rx->lock);
+	csi2rx->count--;
+	/*
+	 * Let the last user turn off the lights.
+	 */
+	if (!csi2rx->count)
+		csi2rx_stop(csi2rx);
+	mutex_unlock(&csi2rx->lock);
+
+	pm_runtime_put(csi2rx->dev);
+
+	return 0;
+}
+
+static int _csi2rx_set_routing(struct v4l2_subdev *subdev,
+			       struct v4l2_subdev_state *state,
+			       struct v4l2_subdev_krouting *routing)
+{
+	static const struct v4l2_mbus_framefmt format = {
+		.width = 640,
+		.height = 480,
+		.code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.field = V4L2_FIELD_NONE,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.ycbcr_enc = V4L2_YCBCR_ENC_601,
+		.quantization = V4L2_QUANTIZATION_LIM_RANGE,
+		.xfer_func = V4L2_XFER_FUNC_SRGB,
+	};
+	int ret;
+
+	if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX)
+		return -EINVAL;
+
+	ret = v4l2_subdev_routing_validate(subdev, routing,
+					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
+	if (ret)
+		return ret;
+
+	ret = v4l2_subdev_set_routing_with_fmt(subdev, state, routing, &format);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int csi2rx_set_routing(struct v4l2_subdev *subdev,
+			      struct v4l2_subdev_state *state,
+			      enum v4l2_subdev_format_whence which,
+			      struct v4l2_subdev_krouting *routing)
+{
+	struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev);
+
+	if (which == V4L2_SUBDEV_FORMAT_ACTIVE && csi2rx->count)
+		return -EBUSY;
+
+	return _csi2rx_set_routing(subdev, state, routing);
+}
+
+static int csi2rx_set_fmt(struct v4l2_subdev *subdev,
+			  struct v4l2_subdev_state *state,
+			  struct v4l2_subdev_format *format)
+{
+	struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev);
+	struct v4l2_mbus_framefmt *fmt;
+
+	if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE && csi2rx->count)
+		return -EBUSY;
+
+	/* No transcoding, source and sink formats must match. */
+	if (format->pad >= CSI2RX_PAD_SOURCE_STREAM0)
+		return v4l2_subdev_get_fmt(subdev, state, format);
+	/*
+	 * Default to the first format if the requested media bus code isn't
+	 * supported.
+	 */
+	if (!csi2rx_get_fmt_by_code(format->format.code))
+		format->format.code = formats[0].code;
+
+	/* Set sink format */
+	fmt = v4l2_subdev_state_get_stream_format(state, format->pad,
+						  format->stream);
+	if (!fmt)
+		return -EINVAL;
+
+	*fmt = format->format;
+
+	/* Propagate to source format */
+	fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
+							   format->stream);
+	if (!fmt)
+		return -EINVAL;
+
+	*fmt = format->format;
+
+	return 0;
+}
+
+static int csi2rx_init_cfg(struct v4l2_subdev *subdev,
+			   struct v4l2_subdev_state *state)
+{
+	struct v4l2_subdev_route routes[] = {
+		{
+			.sink_pad = CSI2RX_PAD_SINK,
+			.sink_stream = 0,
+			.source_pad = CSI2RX_PAD_SOURCE_STREAM0,
+			.source_stream = 0,
+			.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+		},
+	};
+
+	struct v4l2_subdev_krouting routing = {
+		.num_routes = ARRAY_SIZE(routes),
+		.routes = routes,
+	};
+
+	return _csi2rx_set_routing(subdev, state, &routing);
+}
+
+static int csi2rx_get_frame_desc(struct v4l2_subdev *subdev, unsigned int pad,
+				 struct v4l2_mbus_frame_desc *fd)
+{
+	struct csi2rx_priv *csi2rx = v4l2_subdev_to_csi2rx(subdev);
+
+	return csi2rx_get_frame_desc_from_source(csi2rx, fd);
+}
+
+static const struct v4l2_subdev_pad_ops csi2rx_pad_ops = {
+	.get_fmt		= v4l2_subdev_get_fmt,
+	.set_fmt		= csi2rx_set_fmt,
+	.init_cfg		= csi2rx_init_cfg,
+	.get_frame_desc		= csi2rx_get_frame_desc,
+	.set_routing		= csi2rx_set_routing,
+	.enable_streams		= csi2rx_enable_streams,
+	.disable_streams	= csi2rx_disable_streams,
 };
 
 static const struct v4l2_subdev_ops csi2rx_subdev_ops = {
-	.video		= &csi2rx_video_ops,
+	.pad		= &csi2rx_pad_ops,
+};
+
+static const struct media_entity_operations csi2rx_media_ops = {
+	.link_validate = v4l2_subdev_link_validate,
 };
 
 static int csi2rx_async_bound(struct v4l2_async_notifier *notifier,
@@ -305,15 +713,6 @@
 		return PTR_ERR(csi2rx->dphy);
 	}
 
-	/*
-	 * FIXME: Once we'll have external D-PHY support, the check
-	 * will need to be removed.
-	 */
-	if (csi2rx->dphy) {
-		dev_err(&pdev->dev, "External D-PHY not supported yet\n");
-		return -EINVAL;
-	}
-
 	ret = clk_prepare_enable(csi2rx->p_clk);
 	if (ret) {
 		dev_err(&pdev->dev, "Couldn't prepare and enable P clock\n");
@@ -343,7 +742,7 @@
 	 * FIXME: Once we'll have internal D-PHY support, the check
 	 * will need to be removed.
 	 */
-	if (csi2rx->has_internal_dphy) {
+	if (!csi2rx->dphy && csi2rx->has_internal_dphy) {
 		dev_err(&pdev->dev, "Internal D-PHY not supported yet\n");
 		return -EINVAL;
 	}
@@ -418,6 +817,29 @@
 	return ret;
 }
 
+static int csi2rx_suspend(struct device *dev)
+{
+	struct csi2rx_priv *csi2rx = dev_get_drvdata(dev);
+
+	mutex_lock(&csi2rx->lock);
+	if (csi2rx->count)
+		csi2rx_stop(csi2rx);
+	mutex_unlock(&csi2rx->lock);
+
+	return 0;
+}
+
+static int csi2rx_resume(struct device *dev)
+{
+	struct csi2rx_priv *csi2rx = dev_get_drvdata(dev);
+
+	mutex_lock(&csi2rx->lock);
+	if (csi2rx->count)
+		csi2rx_start(csi2rx);
+	mutex_unlock(&csi2rx->lock);
+	return 0;
+}
+
 static int csi2rx_probe(struct platform_device *pdev)
 {
 	struct csi2rx_priv *csi2rx;
@@ -451,26 +873,39 @@
 	csi2rx->pads[CSI2RX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
 	for (i = CSI2RX_PAD_SOURCE_STREAM0; i < CSI2RX_PAD_MAX; i++)
 		csi2rx->pads[i].flags = MEDIA_PAD_FL_SOURCE;
+	csi2rx->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+		V4L2_SUBDEV_FL_STREAMS;
+	csi2rx->subdev.entity.ops = &csi2rx_media_ops;
 
 	ret = media_entity_pads_init(&csi2rx->subdev.entity, CSI2RX_PAD_MAX,
 				     csi2rx->pads);
 	if (ret)
 		goto err_cleanup;
 
+	ret = v4l2_subdev_init_finalize(&csi2rx->subdev);
+	if (ret)
+		goto err_cleanup;
+
+	pm_runtime_enable(csi2rx->dev);
 	ret = v4l2_async_register_subdev(&csi2rx->subdev);
 	if (ret < 0)
-		goto err_cleanup;
+		goto err_free_subdev;
 
 	dev_info(&pdev->dev,
 		 "Probed CSI2RX with %u/%u lanes, %u streams, %s D-PHY\n",
 		 csi2rx->num_lanes, csi2rx->max_lanes, csi2rx->max_streams,
+		 csi2rx->dphy ? "external" :
 		 csi2rx->has_internal_dphy ? "internal" : "no");
 
 	return 0;
 
+err_free_subdev:
+	pm_runtime_disable(csi2rx->dev);
+	v4l2_subdev_cleanup(&csi2rx->subdev);
 err_cleanup:
 	v4l2_async_nf_unregister(&csi2rx->notifier);
 	v4l2_async_nf_cleanup(&csi2rx->notifier);
+	media_entity_cleanup(&csi2rx->subdev.entity);
 err_free_priv:
 	kfree(csi2rx);
 	return ret;
@@ -483,11 +918,18 @@
 	v4l2_async_nf_unregister(&csi2rx->notifier);
 	v4l2_async_nf_cleanup(&csi2rx->notifier);
 	v4l2_async_unregister_subdev(&csi2rx->subdev);
+	v4l2_subdev_cleanup(&csi2rx->subdev);
+	media_entity_cleanup(&csi2rx->subdev.entity);
+	pm_runtime_disable(csi2rx->dev);
 	kfree(csi2rx);
 
 	return 0;
 }
 
+static const struct dev_pm_ops csi2rx_pm_ops = {
+	SET_RUNTIME_PM_OPS(csi2rx_suspend, csi2rx_resume, NULL)
+};
+
 static const struct of_device_id csi2rx_of_table[] = {
 	{ .compatible = "cdns,csi2rx" },
 	{ },
@@ -501,6 +943,7 @@
 	.driver	= {
 		.name		= "cdns-csi2rx",
 		.of_match_table	= csi2rx_of_table,
+		.pm		= &csi2rx_pm_ops,
 	},
 };
 module_platform_driver(csi2rx_driver);
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-bit.c b/drivers/media/platform/chips-media/coda/coda-bit.c
--- a/drivers/media/platform/chips-media/coda/coda-bit.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/coda-bit.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,2666 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Coda multi-standard codec IP - BIT processor functions
+ *
+ * Copyright (C) 2012 Vista Silicon S.L.
+ *    Javier Martin, <javier.martin@vista-silicon.com>
+ *    Xavier Duret
+ * Copyright (C) 2012-2014 Philipp Zabel, Pengutronix
+ */
+
+#include <linux/clk.h>
+#include <linux/irqreturn.h>
+#include <linux/kernel.h>
+#include <linux/log2.h>
+#include <linux/platform_device.h>
+#include <linux/ratelimit.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-vmalloc.h>
+
+#include "coda.h"
+#include "imx-vdoa.h"
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+#define CODA_PARA_BUF_SIZE	(10 * 1024)
+#define CODA7_PS_BUF_SIZE	0x28000
+#define CODA9_PS_SAVE_SIZE	(512 * 1024)
+
+#define CODA_DEFAULT_GAMMA	4096
+#define CODA9_DEFAULT_GAMMA	24576	/* 0.75 * 32768 */
+
+static void coda_free_bitstream_buffer(struct coda_ctx *ctx);
+
+static inline int coda_is_initialized(struct coda_dev *dev)
+{
+	return coda_read(dev, CODA_REG_BIT_CUR_PC) != 0;
+}
+
+static inline unsigned long coda_isbusy(struct coda_dev *dev)
+{
+	return coda_read(dev, CODA_REG_BIT_BUSY);
+}
+
+static int coda_wait_timeout(struct coda_dev *dev)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+
+	while (coda_isbusy(dev)) {
+		if (time_after(jiffies, timeout))
+			return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static void coda_command_async(struct coda_ctx *ctx, int cmd)
+{
+	struct coda_dev *dev = ctx->dev;
+
+	if (dev->devtype->product == CODA_HX4 ||
+	    dev->devtype->product == CODA_7541 ||
+	    dev->devtype->product == CODA_960) {
+		/* Restore context related registers to CODA */
+		coda_write(dev, ctx->bit_stream_param,
+				CODA_REG_BIT_BIT_STREAM_PARAM);
+		coda_write(dev, ctx->frm_dis_flg,
+				CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
+		coda_write(dev, ctx->frame_mem_ctrl,
+				CODA_REG_BIT_FRAME_MEM_CTRL);
+		coda_write(dev, ctx->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR);
+	}
+
+	if (dev->devtype->product == CODA_960) {
+		coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR);
+		coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
+	}
+
+	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
+
+	coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX);
+	coda_write(dev, ctx->params.codec_mode, CODA_REG_BIT_RUN_COD_STD);
+	coda_write(dev, ctx->params.codec_mode_aux, CODA7_REG_BIT_RUN_AUX_STD);
+
+	trace_coda_bit_run(ctx, cmd);
+
+	coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND);
+}
+
+static int coda_command_sync(struct coda_ctx *ctx, int cmd)
+{
+	struct coda_dev *dev = ctx->dev;
+	int ret;
+
+	lockdep_assert_held(&dev->coda_mutex);
+
+	coda_command_async(ctx, cmd);
+	ret = coda_wait_timeout(dev);
+	trace_coda_bit_done(ctx);
+
+	return ret;
+}
+
+int coda_hw_reset(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	unsigned long timeout;
+	unsigned int idx;
+	int ret;
+
+	lockdep_assert_held(&dev->coda_mutex);
+
+	if (!dev->rstc)
+		return -ENOENT;
+
+	idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX);
+
+	if (dev->devtype->product == CODA_960) {
+		timeout = jiffies + msecs_to_jiffies(100);
+		coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL);
+		while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) {
+			if (time_after(jiffies, timeout))
+				return -ETIME;
+			cpu_relax();
+		}
+	}
+
+	ret = reset_control_reset(dev->rstc);
+	if (ret < 0)
+		return ret;
+
+	if (dev->devtype->product == CODA_960)
+		coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL);
+	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
+	coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN);
+	ret = coda_wait_timeout(dev);
+	coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX);
+
+	return ret;
+}
+
+static void coda_kfifo_sync_from_device(struct coda_ctx *ctx)
+{
+	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
+	struct coda_dev *dev = ctx->dev;
+	u32 rd_ptr;
+
+	rd_ptr = coda_read(dev, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
+	kfifo->out = (kfifo->in & ~kfifo->mask) |
+		      (rd_ptr - ctx->bitstream.paddr);
+	if (kfifo->out > kfifo->in)
+		kfifo->out -= kfifo->mask + 1;
+}
+
+static void coda_kfifo_sync_to_device_full(struct coda_ctx *ctx)
+{
+	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
+	struct coda_dev *dev = ctx->dev;
+	u32 rd_ptr, wr_ptr;
+
+	rd_ptr = ctx->bitstream.paddr + (kfifo->out & kfifo->mask);
+	coda_write(dev, rd_ptr, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
+	wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask);
+	coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
+}
+
+static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx)
+{
+	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
+	struct coda_dev *dev = ctx->dev;
+	u32 wr_ptr;
+
+	wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask);
+	coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
+}
+
+static int coda_h264_bitstream_pad(struct coda_ctx *ctx, u32 size)
+{
+	unsigned char *buf;
+	u32 n;
+
+	if (size < 6)
+		size = 6;
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	coda_h264_filler_nal(size, buf);
+	n = kfifo_in(&ctx->bitstream_fifo, buf, size);
+	kfree(buf);
+
+	return (n < size) ? -ENOSPC : 0;
+}
+
+int coda_bitstream_flush(struct coda_ctx *ctx)
+{
+	int ret;
+
+	if (ctx->inst_type != CODA_INST_DECODER || !ctx->use_bit)
+		return 0;
+
+	ret = coda_command_sync(ctx, CODA_COMMAND_DEC_BUF_FLUSH);
+	if (ret < 0) {
+		v4l2_err(&ctx->dev->v4l2_dev, "failed to flush bitstream\n");
+		return ret;
+	}
+
+	kfifo_init(&ctx->bitstream_fifo, ctx->bitstream.vaddr,
+		   ctx->bitstream.size);
+	coda_kfifo_sync_to_device_full(ctx);
+
+	return 0;
+}
+
+static int coda_bitstream_queue(struct coda_ctx *ctx, const u8 *buf, u32 size)
+{
+	u32 n = kfifo_in(&ctx->bitstream_fifo, buf, size);
+
+	return (n < size) ? -ENOSPC : 0;
+}
+
+static u32 coda_buffer_parse_headers(struct coda_ctx *ctx,
+				     struct vb2_v4l2_buffer *src_buf,
+				     u32 payload)
+{
+	u8 *vaddr = vb2_plane_vaddr(&src_buf->vb2_buf, 0);
+	u32 size = 0;
+
+	switch (ctx->codec->src_fourcc) {
+	case V4L2_PIX_FMT_MPEG2:
+		size = coda_mpeg2_parse_headers(ctx, vaddr, payload);
+		break;
+	case V4L2_PIX_FMT_MPEG4:
+		size = coda_mpeg4_parse_headers(ctx, vaddr, payload);
+		break;
+	default:
+		break;
+	}
+
+	return size;
+}
+
+static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
+				     struct vb2_v4l2_buffer *src_buf)
+{
+	unsigned long payload = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
+	u8 *vaddr = vb2_plane_vaddr(&src_buf->vb2_buf, 0);
+	int ret;
+	int i;
+
+	if (coda_get_bitstream_payload(ctx) + payload + 512 >=
+	    ctx->bitstream.size)
+		return false;
+
+	if (!vaddr) {
+		v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty buffer\n");
+		return true;
+	}
+
+	if (ctx->qsequence == 0 && payload < 512) {
+		/*
+		 * Add padding after the first buffer, if it is too small to be
+		 * fetched by the CODA, by repeating the headers. Without
+		 * repeated headers, or the first frame already queued, decoder
+		 * sequence initialization fails with error code 0x2000 on i.MX6
+		 * or error code 0x1 on i.MX51.
+		 */
+		u32 header_size = coda_buffer_parse_headers(ctx, src_buf,
+							    payload);
+
+		if (header_size) {
+			coda_dbg(1, ctx, "pad with %u-byte header\n",
+				 header_size);
+			for (i = payload; i < 512; i += header_size) {
+				ret = coda_bitstream_queue(ctx, vaddr,
+							   header_size);
+				if (ret < 0) {
+					v4l2_err(&ctx->dev->v4l2_dev,
+						 "bitstream buffer overflow\n");
+					return false;
+				}
+				if (ctx->dev->devtype->product == CODA_960)
+					break;
+			}
+		} else {
+			coda_dbg(1, ctx,
+				 "could not parse header, sequence initialization might fail\n");
+		}
+
+		/* Add padding before the first buffer, if it is too small */
+		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264)
+			coda_h264_bitstream_pad(ctx, 512 - payload);
+	}
+
+	ret = coda_bitstream_queue(ctx, vaddr, payload);
+	if (ret < 0) {
+		v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer overflow\n");
+		return false;
+	}
+
+	src_buf->sequence = ctx->qsequence++;
+
+	/* Sync read pointer to device */
+	if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev))
+		coda_kfifo_sync_to_device_write(ctx);
+
+	/* Set the stream-end flag after the last buffer is queued */
+	if (src_buf->flags & V4L2_BUF_FLAG_LAST)
+		coda_bit_stream_end_flag(ctx);
+	ctx->hold = false;
+
+	return true;
+}
+
+void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list)
+{
+	struct vb2_v4l2_buffer *src_buf;
+	struct coda_buffer_meta *meta;
+	u32 start;
+
+	lockdep_assert_held(&ctx->bitstream_mutex);
+
+	if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG)
+		return;
+
+	while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) {
+		/*
+		 * Only queue two JPEGs into the bitstream buffer to keep
+		 * latency low. We need at least one complete buffer and the
+		 * header of another buffer (for prescan) in the bitstream.
+		 */
+		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
+		    ctx->num_metas > 1)
+			break;
+
+		if (ctx->num_internal_frames &&
+		    ctx->num_metas >= ctx->num_internal_frames) {
+			meta = list_first_entry(&ctx->buffer_meta_list,
+						struct coda_buffer_meta, list);
+
+			/*
+			 * If we managed to fill in at least a full reorder
+			 * window of buffers (num_internal_frames is a
+			 * conservative estimate for this) and the bitstream
+			 * prefetcher has at least 2 256 bytes periods beyond
+			 * the first buffer to fetch, we can safely stop queuing
+			 * in order to limit the decoder drain latency.
+			 */
+			if (coda_bitstream_can_fetch_past(ctx, meta->end))
+				break;
+		}
+
+		src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+
+		/* Drop frames that do not start/end with a SOI/EOI markers */
+		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
+		    !coda_jpeg_check_buffer(ctx, &src_buf->vb2_buf)) {
+			v4l2_err(&ctx->dev->v4l2_dev,
+				 "dropping invalid JPEG frame %d\n",
+				 ctx->qsequence);
+			src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+			if (buffer_list) {
+				struct v4l2_m2m_buffer *m2m_buf;
+
+				m2m_buf = container_of(src_buf,
+						       struct v4l2_m2m_buffer,
+						       vb);
+				list_add_tail(&m2m_buf->list, buffer_list);
+			} else {
+				v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+			}
+			continue;
+		}
+
+		/* Dump empty buffers */
+		if (!vb2_get_plane_payload(&src_buf->vb2_buf, 0)) {
+			src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+			continue;
+		}
+
+		/* Buffer start position */
+		start = ctx->bitstream_fifo.kfifo.in;
+
+		if (coda_bitstream_try_queue(ctx, src_buf)) {
+			/*
+			 * Source buffer is queued in the bitstream ringbuffer;
+			 * queue the timestamp and mark source buffer as done
+			 */
+			src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+
+			meta = kmalloc(sizeof(*meta), GFP_KERNEL);
+			if (meta) {
+				meta->sequence = src_buf->sequence;
+				meta->timecode = src_buf->timecode;
+				meta->timestamp = src_buf->vb2_buf.timestamp;
+				meta->start = start;
+				meta->end = ctx->bitstream_fifo.kfifo.in;
+				meta->last = src_buf->flags & V4L2_BUF_FLAG_LAST;
+				if (meta->last)
+					coda_dbg(1, ctx, "marking last meta");
+				spin_lock(&ctx->buffer_meta_lock);
+				list_add_tail(&meta->list,
+					      &ctx->buffer_meta_list);
+				ctx->num_metas++;
+				spin_unlock(&ctx->buffer_meta_lock);
+
+				trace_coda_bit_queue(ctx, src_buf, meta);
+			}
+
+			if (buffer_list) {
+				struct v4l2_m2m_buffer *m2m_buf;
+
+				m2m_buf = container_of(src_buf,
+						       struct v4l2_m2m_buffer,
+						       vb);
+				list_add_tail(&m2m_buf->list, buffer_list);
+			} else {
+				v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+			}
+		} else {
+			break;
+		}
+	}
+}
+
+void coda_bit_stream_end_flag(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+
+	ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
+
+	/* If this context is currently running, update the hardware flag */
+	if ((dev->devtype->product == CODA_960) &&
+	    coda_isbusy(dev) &&
+	    (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) {
+		coda_write(dev, ctx->bit_stream_param,
+			   CODA_REG_BIT_BIT_STREAM_PARAM);
+	}
+}
+
+static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value)
+{
+	struct coda_dev *dev = ctx->dev;
+	u32 *p = ctx->parabuf.vaddr;
+
+	if (dev->devtype->product == CODA_DX6)
+		p[index] = value;
+	else
+		p[index ^ 1] = value;
+}
+
+static inline int coda_alloc_context_buf(struct coda_ctx *ctx,
+					 struct coda_aux_buf *buf, size_t size,
+					 const char *name)
+{
+	return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx->debugfs_entry);
+}
+
+
+static void coda_free_framebuffers(struct coda_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++)
+		coda_free_aux_buf(ctx->dev, &ctx->internal_frames[i].buf);
+}
+
+static int coda_alloc_framebuffers(struct coda_ctx *ctx,
+				   struct coda_q_data *q_data, u32 fourcc)
+{
+	struct coda_dev *dev = ctx->dev;
+	unsigned int ysize, ycbcr_size;
+	int ret;
+	int i;
+
+	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 ||
+	    ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264 ||
+	    ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 ||
+	    ctx->codec->dst_fourcc == V4L2_PIX_FMT_MPEG4)
+		ysize = round_up(q_data->rect.width, 16) *
+			round_up(q_data->rect.height, 16);
+	else
+		ysize = round_up(q_data->rect.width, 8) * q_data->rect.height;
+
+	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
+		ycbcr_size = round_up(ysize, 4096) + ysize / 2;
+	else
+		ycbcr_size = ysize + ysize / 2;
+
+	/* Allocate frame buffers */
+	for (i = 0; i < ctx->num_internal_frames; i++) {
+		size_t size = ycbcr_size;
+		char *name;
+
+		/* Add space for mvcol buffers */
+		if (dev->devtype->product != CODA_DX6 &&
+		    (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 ||
+		     (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 && i == 0)))
+			size += ysize / 4;
+		name = kasprintf(GFP_KERNEL, "fb%d", i);
+		if (!name) {
+			coda_free_framebuffers(ctx);
+			return -ENOMEM;
+		}
+		ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i].buf,
+					     size, name);
+		kfree(name);
+		if (ret < 0) {
+			coda_free_framebuffers(ctx);
+			return ret;
+		}
+	}
+
+	/* Register frame buffers in the parameter buffer */
+	for (i = 0; i < ctx->num_internal_frames; i++) {
+		u32 y, cb, cr, mvcol;
+
+		/* Start addresses of Y, Cb, Cr planes */
+		y = ctx->internal_frames[i].buf.paddr;
+		cb = y + ysize;
+		cr = y + ysize + ysize/4;
+		mvcol = y + ysize + ysize/4 + ysize/4;
+		if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) {
+			cb = round_up(cb, 4096);
+			mvcol = cb + ysize/2;
+			cr = 0;
+			/* Packed 20-bit MSB of base addresses */
+			/* YYYYYCCC, CCyyyyyc, cccc.... */
+			y = (y & 0xfffff000) | cb >> 20;
+			cb = (cb & 0x000ff000) << 12;
+		}
+		coda_parabuf_write(ctx, i * 3 + 0, y);
+		coda_parabuf_write(ctx, i * 3 + 1, cb);
+		coda_parabuf_write(ctx, i * 3 + 2, cr);
+
+		if (dev->devtype->product == CODA_DX6)
+			continue;
+
+		/* mvcol buffer for h.264 and mpeg4 */
+		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264)
+			coda_parabuf_write(ctx, 96 + i, mvcol);
+		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 && i == 0)
+			coda_parabuf_write(ctx, 97, mvcol);
+	}
+
+	return 0;
+}
+
+static void coda_free_context_buffers(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+
+	coda_free_aux_buf(dev, &ctx->slicebuf);
+	coda_free_aux_buf(dev, &ctx->psbuf);
+	if (dev->devtype->product != CODA_DX6)
+		coda_free_aux_buf(dev, &ctx->workbuf);
+	coda_free_aux_buf(dev, &ctx->parabuf);
+}
+
+static int coda_alloc_context_buffers(struct coda_ctx *ctx,
+				      struct coda_q_data *q_data)
+{
+	struct coda_dev *dev = ctx->dev;
+	size_t size;
+	int ret;
+
+	if (!ctx->parabuf.vaddr) {
+		ret = coda_alloc_context_buf(ctx, &ctx->parabuf,
+					     CODA_PARA_BUF_SIZE, "parabuf");
+		if (ret < 0)
+			return ret;
+	}
+
+	if (dev->devtype->product == CODA_DX6)
+		return 0;
+
+	if (!ctx->slicebuf.vaddr && q_data->fourcc == V4L2_PIX_FMT_H264) {
+		/* worst case slice size */
+		size = (DIV_ROUND_UP(q_data->rect.width, 16) *
+			DIV_ROUND_UP(q_data->rect.height, 16)) * 3200 / 8 + 512;
+		ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size,
+					     "slicebuf");
+		if (ret < 0)
+			goto err;
+	}
+
+	if (!ctx->psbuf.vaddr && (dev->devtype->product == CODA_HX4 ||
+				  dev->devtype->product == CODA_7541)) {
+		ret = coda_alloc_context_buf(ctx, &ctx->psbuf,
+					     CODA7_PS_BUF_SIZE, "psbuf");
+		if (ret < 0)
+			goto err;
+	}
+
+	if (!ctx->workbuf.vaddr) {
+		size = dev->devtype->workbuf_size;
+		if (dev->devtype->product == CODA_960 &&
+		    q_data->fourcc == V4L2_PIX_FMT_H264)
+			size += CODA9_PS_SAVE_SIZE;
+		ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size,
+					     "workbuf");
+		if (ret < 0)
+			goto err;
+	}
+
+	return 0;
+
+err:
+	coda_free_context_buffers(ctx);
+	return ret;
+}
+
+static int coda_encode_header(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
+			      int header_code, u8 *header, int *size)
+{
+	struct vb2_buffer *vb = &buf->vb2_buf;
+	struct coda_dev *dev = ctx->dev;
+	struct coda_q_data *q_data_src;
+	struct v4l2_rect *r;
+	size_t bufsize;
+	int ret;
+	int i;
+
+	if (dev->devtype->product == CODA_960)
+		memset(vb2_plane_vaddr(vb, 0), 0, 64);
+
+	coda_write(dev, vb2_dma_contig_plane_dma_addr(vb, 0),
+		   CODA_CMD_ENC_HEADER_BB_START);
+	bufsize = vb2_plane_size(vb, 0);
+	if (dev->devtype->product == CODA_960)
+		bufsize /= 1024;
+	coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE);
+	if (dev->devtype->product == CODA_960 &&
+	    ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264 &&
+	    header_code == CODA_HEADER_H264_SPS) {
+		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+		r = &q_data_src->rect;
+
+		if (r->width % 16 || r->height % 16) {
+			u32 crop_right = round_up(r->width, 16) -  r->width;
+			u32 crop_bottom = round_up(r->height, 16) - r->height;
+
+			coda_write(dev, crop_right,
+				   CODA9_CMD_ENC_HEADER_FRAME_CROP_H);
+			coda_write(dev, crop_bottom,
+				   CODA9_CMD_ENC_HEADER_FRAME_CROP_V);
+			header_code |= CODA9_HEADER_FRAME_CROP;
+		}
+	}
+	coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE);
+	ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER);
+	if (ret < 0) {
+		v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n");
+		return ret;
+	}
+
+	if (dev->devtype->product == CODA_960) {
+		for (i = 63; i > 0; i--)
+			if (((char *)vb2_plane_vaddr(vb, 0))[i] != 0)
+				break;
+		*size = i + 1;
+	} else {
+		*size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) -
+			coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
+	}
+	memcpy(header, vb2_plane_vaddr(vb, 0), *size);
+
+	return 0;
+}
+
+static u32 coda_slice_mode(struct coda_ctx *ctx)
+{
+	int size, unit;
+
+	switch (ctx->params.slice_mode) {
+	case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE:
+	default:
+		return 0;
+	case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB:
+		size = ctx->params.slice_max_mb;
+		unit = 1;
+		break;
+	case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES:
+		size = ctx->params.slice_max_bits;
+		unit = 0;
+		break;
+	}
+
+	return ((size & CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET) |
+	       ((unit & CODA_SLICING_UNIT_MASK) << CODA_SLICING_UNIT_OFFSET) |
+	       ((1 & CODA_SLICING_MODE_MASK) << CODA_SLICING_MODE_OFFSET);
+}
+
+static int coda_enc_param_change(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	u32 change_enable = 0;
+	u32 success;
+	int ret;
+
+	if (ctx->params.gop_size_changed) {
+		change_enable |= CODA_PARAM_CHANGE_RC_GOP;
+		coda_write(dev, ctx->params.gop_size,
+			   CODA_CMD_ENC_PARAM_RC_GOP);
+		ctx->gopcounter = ctx->params.gop_size - 1;
+		ctx->params.gop_size_changed = false;
+	}
+	if (ctx->params.h264_intra_qp_changed) {
+		coda_dbg(1, ctx, "parameter change: intra Qp %u\n",
+			 ctx->params.h264_intra_qp);
+
+		if (ctx->params.bitrate) {
+			change_enable |= CODA_PARAM_CHANGE_RC_INTRA_QP;
+			coda_write(dev, ctx->params.h264_intra_qp,
+				   CODA_CMD_ENC_PARAM_RC_INTRA_QP);
+		}
+		ctx->params.h264_intra_qp_changed = false;
+	}
+	if (ctx->params.bitrate_changed) {
+		coda_dbg(1, ctx, "parameter change: bitrate %u kbit/s\n",
+			 ctx->params.bitrate);
+		change_enable |= CODA_PARAM_CHANGE_RC_BITRATE;
+		coda_write(dev, ctx->params.bitrate,
+			   CODA_CMD_ENC_PARAM_RC_BITRATE);
+		ctx->params.bitrate_changed = false;
+	}
+	if (ctx->params.framerate_changed) {
+		coda_dbg(1, ctx, "parameter change: frame rate %u/%u Hz\n",
+			 ctx->params.framerate & 0xffff,
+			 (ctx->params.framerate >> 16) + 1);
+		change_enable |= CODA_PARAM_CHANGE_RC_FRAME_RATE;
+		coda_write(dev, ctx->params.framerate,
+			   CODA_CMD_ENC_PARAM_RC_FRAME_RATE);
+		ctx->params.framerate_changed = false;
+	}
+	if (ctx->params.intra_refresh_changed) {
+		coda_dbg(1, ctx, "parameter change: intra refresh MBs %u\n",
+			 ctx->params.intra_refresh);
+		change_enable |= CODA_PARAM_CHANGE_INTRA_MB_NUM;
+		coda_write(dev, ctx->params.intra_refresh,
+			   CODA_CMD_ENC_PARAM_INTRA_MB_NUM);
+		ctx->params.intra_refresh_changed = false;
+	}
+	if (ctx->params.slice_mode_changed) {
+		change_enable |= CODA_PARAM_CHANGE_SLICE_MODE;
+		coda_write(dev, coda_slice_mode(ctx),
+			   CODA_CMD_ENC_PARAM_SLICE_MODE);
+		ctx->params.slice_mode_changed = false;
+	}
+
+	if (!change_enable)
+		return 0;
+
+	coda_write(dev, change_enable, CODA_CMD_ENC_PARAM_CHANGE_ENABLE);
+
+	ret = coda_command_sync(ctx, CODA_COMMAND_RC_CHANGE_PARAMETER);
+	if (ret < 0)
+		return ret;
+
+	success = coda_read(dev, CODA_RET_ENC_PARAM_CHANGE_SUCCESS);
+	if (success != 1)
+		coda_dbg(1, ctx, "parameter change failed: %u\n", success);
+
+	return 0;
+}
+
+static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t size)
+{
+	phys_addr_t ret;
+
+	size = round_up(size, 1024);
+	if (size > iram->remaining)
+		return 0;
+	iram->remaining -= size;
+
+	ret = iram->next_paddr;
+	iram->next_paddr += size;
+
+	return ret;
+}
+
+static void coda_setup_iram(struct coda_ctx *ctx)
+{
+	struct coda_iram_info *iram_info = &ctx->iram_info;
+	struct coda_dev *dev = ctx->dev;
+	int w64, w128;
+	int mb_width;
+	int dbk_bits;
+	int bit_bits;
+	int ip_bits;
+	int me_bits;
+
+	memset(iram_info, 0, sizeof(*iram_info));
+	iram_info->next_paddr = dev->iram.paddr;
+	iram_info->remaining = dev->iram.size;
+
+	if (!dev->iram.vaddr)
+		return;
+
+	switch (dev->devtype->product) {
+	case CODA_HX4:
+		dbk_bits = CODA7_USE_HOST_DBK_ENABLE;
+		bit_bits = CODA7_USE_HOST_BIT_ENABLE;
+		ip_bits = CODA7_USE_HOST_IP_ENABLE;
+		me_bits = CODA7_USE_HOST_ME_ENABLE;
+		break;
+	case CODA_7541:
+		dbk_bits = CODA7_USE_HOST_DBK_ENABLE | CODA7_USE_DBK_ENABLE;
+		bit_bits = CODA7_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE;
+		ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
+		me_bits = CODA7_USE_HOST_ME_ENABLE | CODA7_USE_ME_ENABLE;
+		break;
+	case CODA_960:
+		dbk_bits = CODA9_USE_HOST_DBK_ENABLE | CODA9_USE_DBK_ENABLE;
+		bit_bits = CODA9_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE;
+		ip_bits = CODA9_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
+		me_bits = 0;
+		break;
+	default: /* CODA_DX6 */
+		return;
+	}
+
+	if (ctx->inst_type == CODA_INST_ENCODER) {
+		struct coda_q_data *q_data_src;
+
+		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+		mb_width = DIV_ROUND_UP(q_data_src->rect.width, 16);
+		w128 = mb_width * 128;
+		w64 = mb_width * 64;
+
+		/* Prioritize in case IRAM is too small for everything */
+		if (dev->devtype->product == CODA_HX4 ||
+		    dev->devtype->product == CODA_7541) {
+			iram_info->search_ram_size = round_up(mb_width * 16 *
+							      36 + 2048, 1024);
+			iram_info->search_ram_paddr = coda_iram_alloc(iram_info,
+						iram_info->search_ram_size);
+			if (!iram_info->search_ram_paddr) {
+				pr_err("IRAM is smaller than the search ram size\n");
+				goto out;
+			}
+			iram_info->axi_sram_use |= me_bits;
+		}
+
+		/* Only H.264BP and H.263P3 are considered */
+		iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w64);
+		iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w64);
+		if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use)
+			goto out;
+		iram_info->axi_sram_use |= dbk_bits;
+
+		iram_info->buf_bit_use = coda_iram_alloc(iram_info, w128);
+		if (!iram_info->buf_bit_use)
+			goto out;
+		iram_info->axi_sram_use |= bit_bits;
+
+		iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, w128);
+		if (!iram_info->buf_ip_ac_dc_use)
+			goto out;
+		iram_info->axi_sram_use |= ip_bits;
+
+		/* OVL and BTP disabled for encoder */
+	} else if (ctx->inst_type == CODA_INST_DECODER) {
+		struct coda_q_data *q_data_dst;
+
+		q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		mb_width = DIV_ROUND_UP(q_data_dst->width, 16);
+		w128 = mb_width * 128;
+
+		iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w128);
+		iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w128);
+		if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use)
+			goto out;
+		iram_info->axi_sram_use |= dbk_bits;
+
+		iram_info->buf_bit_use = coda_iram_alloc(iram_info, w128);
+		if (!iram_info->buf_bit_use)
+			goto out;
+		iram_info->axi_sram_use |= bit_bits;
+
+		iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, w128);
+		if (!iram_info->buf_ip_ac_dc_use)
+			goto out;
+		iram_info->axi_sram_use |= ip_bits;
+
+		/* OVL and BTP unused as there is no VC1 support yet */
+	}
+
+out:
+	if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE))
+		coda_dbg(1, ctx, "IRAM smaller than needed\n");
+
+	if (dev->devtype->product == CODA_HX4 ||
+	    dev->devtype->product == CODA_7541) {
+		/* TODO - Enabling these causes picture errors on CODA7541 */
+		if (ctx->inst_type == CODA_INST_DECODER) {
+			/* fw 1.4.50 */
+			iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE |
+						     CODA7_USE_IP_ENABLE);
+		} else {
+			/* fw 13.4.29 */
+			iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE |
+						     CODA7_USE_HOST_DBK_ENABLE |
+						     CODA7_USE_IP_ENABLE |
+						     CODA7_USE_DBK_ENABLE);
+		}
+	}
+}
+
+static u32 coda_supported_firmwares[] = {
+	CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5),
+	CODA_FIRMWARE_VERNUM(CODA_HX4, 1, 4, 50),
+	CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50),
+	CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 5),
+	CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 9),
+	CODA_FIRMWARE_VERNUM(CODA_960, 2, 3, 10),
+	CODA_FIRMWARE_VERNUM(CODA_960, 3, 1, 1),
+};
+
+static bool coda_firmware_supported(u32 vernum)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(coda_supported_firmwares); i++)
+		if (vernum == coda_supported_firmwares[i])
+			return true;
+	return false;
+}
+
+int coda_check_firmware(struct coda_dev *dev)
+{
+	u16 product, major, minor, release;
+	u32 data;
+	int ret;
+
+	ret = clk_prepare_enable(dev->clk_per);
+	if (ret)
+		goto err_clk_per;
+
+	ret = clk_prepare_enable(dev->clk_ahb);
+	if (ret)
+		goto err_clk_ahb;
+
+	coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM);
+	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
+	coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX);
+	coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD);
+	coda_write(dev, CODA_COMMAND_FIRMWARE_GET, CODA_REG_BIT_RUN_COMMAND);
+	if (coda_wait_timeout(dev)) {
+		v4l2_err(&dev->v4l2_dev, "firmware get command error\n");
+		ret = -EIO;
+		goto err_run_cmd;
+	}
+
+	if (dev->devtype->product == CODA_960) {
+		data = coda_read(dev, CODA9_CMD_FIRMWARE_CODE_REV);
+		v4l2_info(&dev->v4l2_dev, "Firmware code revision: %d\n",
+			  data);
+	}
+
+	/* Check we are compatible with the loaded firmware */
+	data = coda_read(dev, CODA_CMD_FIRMWARE_VERNUM);
+	product = CODA_FIRMWARE_PRODUCT(data);
+	major = CODA_FIRMWARE_MAJOR(data);
+	minor = CODA_FIRMWARE_MINOR(data);
+	release = CODA_FIRMWARE_RELEASE(data);
+
+	clk_disable_unprepare(dev->clk_per);
+	clk_disable_unprepare(dev->clk_ahb);
+
+	if (product != dev->devtype->product) {
+		v4l2_err(&dev->v4l2_dev,
+			 "Wrong firmware. Hw: %s, Fw: %s, Version: %u.%u.%u\n",
+			 coda_product_name(dev->devtype->product),
+			 coda_product_name(product), major, minor, release);
+		return -EINVAL;
+	}
+
+	v4l2_info(&dev->v4l2_dev, "Initialized %s.\n",
+		  coda_product_name(product));
+
+	if (coda_firmware_supported(data)) {
+		v4l2_info(&dev->v4l2_dev, "Firmware version: %u.%u.%u\n",
+			  major, minor, release);
+	} else {
+		v4l2_warn(&dev->v4l2_dev,
+			  "Unsupported firmware version: %u.%u.%u\n",
+			  major, minor, release);
+	}
+
+	return 0;
+
+err_run_cmd:
+	clk_disable_unprepare(dev->clk_ahb);
+err_clk_ahb:
+	clk_disable_unprepare(dev->clk_per);
+err_clk_per:
+	return ret;
+}
+
+static void coda9_set_frame_cache(struct coda_ctx *ctx, u32 fourcc)
+{
+	u32 cache_size, cache_config;
+
+	if (ctx->tiled_map_type == GDI_LINEAR_FRAME_MAP) {
+		/* Luma 2x0 page, 2x6 cache, chroma 2x0 page, 2x4 cache size */
+		cache_size = 0x20262024;
+		cache_config = 2 << CODA9_CACHE_PAGEMERGE_OFFSET;
+	} else {
+		/* Luma 0x2 page, 4x4 cache, chroma 0x2 page, 4x3 cache size */
+		cache_size = 0x02440243;
+		cache_config = 1 << CODA9_CACHE_PAGEMERGE_OFFSET;
+	}
+	coda_write(ctx->dev, cache_size, CODA9_CMD_SET_FRAME_CACHE_SIZE);
+	if (fourcc == V4L2_PIX_FMT_NV12 || fourcc == V4L2_PIX_FMT_YUYV) {
+		cache_config |= 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
+				16 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET |
+				0 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET;
+	} else {
+		cache_config |= 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
+				8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET |
+				8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET;
+	}
+	coda_write(ctx->dev, cache_config, CODA9_CMD_SET_FRAME_CACHE_CONFIG);
+}
+
+/*
+ * Encoder context operations
+ */
+
+static int coda_encoder_reqbufs(struct coda_ctx *ctx,
+				struct v4l2_requestbuffers *rb)
+{
+	struct coda_q_data *q_data_src;
+	int ret;
+
+	if (rb->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		return 0;
+
+	if (rb->count) {
+		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+		ret = coda_alloc_context_buffers(ctx, q_data_src);
+		if (ret < 0)
+			return ret;
+	} else {
+		coda_free_context_buffers(ctx);
+	}
+
+	return 0;
+}
+
+static int coda_start_encoding(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
+	struct coda_q_data *q_data_src, *q_data_dst;
+	u32 bitstream_buf, bitstream_size;
+	struct vb2_v4l2_buffer *buf;
+	int gamma, ret, value;
+	u32 dst_fourcc;
+	int num_fb;
+	u32 stride;
+
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	dst_fourcc = q_data_dst->fourcc;
+
+	buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+	bitstream_buf = vb2_dma_contig_plane_dma_addr(&buf->vb2_buf, 0);
+	bitstream_size = q_data_dst->sizeimage;
+
+	if (!coda_is_initialized(dev)) {
+		v4l2_err(v4l2_dev, "coda is not initialized.\n");
+		return -EFAULT;
+	}
+
+	if (dst_fourcc == V4L2_PIX_FMT_JPEG) {
+		if (!ctx->params.jpeg_qmat_tab[0]) {
+			ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL);
+			if (!ctx->params.jpeg_qmat_tab[0])
+				return -ENOMEM;
+		}
+		if (!ctx->params.jpeg_qmat_tab[1]) {
+			ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL);
+			if (!ctx->params.jpeg_qmat_tab[1])
+				return -ENOMEM;
+		}
+		coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality);
+	}
+
+	mutex_lock(&dev->coda_mutex);
+
+	coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
+	coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
+	coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
+	switch (dev->devtype->product) {
+	case CODA_DX6:
+		coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN |
+			CODADX6_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL);
+		break;
+	case CODA_960:
+		coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
+		fallthrough;
+	case CODA_HX4:
+	case CODA_7541:
+		coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN |
+			CODA7_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL);
+		break;
+	}
+
+	ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) |
+				 CODA9_FRAME_TILED2LINEAR);
+	if (q_data_src->fourcc == V4L2_PIX_FMT_NV12)
+		ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
+	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
+		ctx->frame_mem_ctrl |= (0x3 << 9) | CODA9_FRAME_TILED2LINEAR;
+	coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL);
+
+	if (dev->devtype->product == CODA_DX6) {
+		/* Configure the coda */
+		coda_write(dev, dev->iram.paddr,
+			   CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR);
+	}
+
+	/* Could set rotation here if needed */
+	value = 0;
+	switch (dev->devtype->product) {
+	case CODA_DX6:
+		value = (q_data_src->rect.width & CODADX6_PICWIDTH_MASK)
+			<< CODADX6_PICWIDTH_OFFSET;
+		value |= (q_data_src->rect.height & CODADX6_PICHEIGHT_MASK)
+			 << CODA_PICHEIGHT_OFFSET;
+		break;
+	case CODA_HX4:
+	case CODA_7541:
+		if (dst_fourcc == V4L2_PIX_FMT_H264) {
+			value = (round_up(q_data_src->rect.width, 16) &
+				 CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET;
+			value |= (round_up(q_data_src->rect.height, 16) &
+				 CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET;
+			break;
+		}
+		fallthrough;
+	case CODA_960:
+		value = (q_data_src->rect.width & CODA7_PICWIDTH_MASK)
+			<< CODA7_PICWIDTH_OFFSET;
+		value |= (q_data_src->rect.height & CODA7_PICHEIGHT_MASK)
+			 << CODA_PICHEIGHT_OFFSET;
+	}
+	coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE);
+	if (dst_fourcc == V4L2_PIX_FMT_JPEG)
+		ctx->params.framerate = 0;
+	coda_write(dev, ctx->params.framerate,
+		   CODA_CMD_ENC_SEQ_SRC_F_RATE);
+
+	ctx->params.codec_mode = ctx->codec->mode;
+	switch (dst_fourcc) {
+	case V4L2_PIX_FMT_MPEG4:
+		if (dev->devtype->product == CODA_960)
+			coda_write(dev, CODA9_STD_MPEG4,
+				   CODA_CMD_ENC_SEQ_COD_STD);
+		else
+			coda_write(dev, CODA_STD_MPEG4,
+				   CODA_CMD_ENC_SEQ_COD_STD);
+		coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA);
+		break;
+	case V4L2_PIX_FMT_H264:
+		if (dev->devtype->product == CODA_960)
+			coda_write(dev, CODA9_STD_H264,
+				   CODA_CMD_ENC_SEQ_COD_STD);
+		else
+			coda_write(dev, CODA_STD_H264,
+				   CODA_CMD_ENC_SEQ_COD_STD);
+		value = ((ctx->params.h264_disable_deblocking_filter_idc &
+			  CODA_264PARAM_DISABLEDEBLK_MASK) <<
+			 CODA_264PARAM_DISABLEDEBLK_OFFSET) |
+			((ctx->params.h264_slice_alpha_c0_offset_div2 &
+			  CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK) <<
+			 CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) |
+			((ctx->params.h264_slice_beta_offset_div2 &
+			  CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK) <<
+			 CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET) |
+			(ctx->params.h264_constrained_intra_pred_flag <<
+			 CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_OFFSET) |
+			(ctx->params.h264_chroma_qp_index_offset &
+			 CODA_264PARAM_CHROMAQPOFFSET_MASK);
+		coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA);
+		break;
+	case V4L2_PIX_FMT_JPEG:
+		coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_PARA);
+		coda_write(dev, ctx->params.jpeg_restart_interval,
+				CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL);
+		coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_EN);
+		coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE);
+		coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET);
+
+		coda_jpeg_write_tables(ctx);
+		break;
+	default:
+		v4l2_err(v4l2_dev,
+			 "dst format (0x%08x) invalid.\n", dst_fourcc);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/*
+	 * slice mode and GOP size registers are used for thumb size/offset
+	 * in JPEG mode
+	 */
+	if (dst_fourcc != V4L2_PIX_FMT_JPEG) {
+		value = coda_slice_mode(ctx);
+		coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE);
+		value = ctx->params.gop_size;
+		coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE);
+	}
+
+	if (ctx->params.bitrate && (ctx->params.frame_rc_enable ||
+				    ctx->params.mb_rc_enable)) {
+		ctx->params.bitrate_changed = false;
+		ctx->params.h264_intra_qp_changed = false;
+
+		/* Rate control enabled */
+		value = (ctx->params.bitrate & CODA_RATECONTROL_BITRATE_MASK)
+			<< CODA_RATECONTROL_BITRATE_OFFSET;
+		value |=  1 & CODA_RATECONTROL_ENABLE_MASK;
+		value |= (ctx->params.vbv_delay &
+			  CODA_RATECONTROL_INITIALDELAY_MASK)
+			 << CODA_RATECONTROL_INITIALDELAY_OFFSET;
+		if (dev->devtype->product == CODA_960)
+			value |= BIT(31); /* disable autoskip */
+	} else {
+		value = 0;
+	}
+	coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA);
+
+	coda_write(dev, ctx->params.vbv_size, CODA_CMD_ENC_SEQ_RC_BUF_SIZE);
+	coda_write(dev, ctx->params.intra_refresh,
+		   CODA_CMD_ENC_SEQ_INTRA_REFRESH);
+
+	coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START);
+	coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE);
+
+
+	value = 0;
+	if (dev->devtype->product == CODA_960)
+		gamma = CODA9_DEFAULT_GAMMA;
+	else
+		gamma = CODA_DEFAULT_GAMMA;
+	if (gamma > 0) {
+		coda_write(dev, (gamma & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET,
+			   CODA_CMD_ENC_SEQ_RC_GAMMA);
+	}
+
+	if (ctx->params.h264_min_qp || ctx->params.h264_max_qp) {
+		coda_write(dev,
+			   ctx->params.h264_min_qp << CODA_QPMIN_OFFSET |
+			   ctx->params.h264_max_qp << CODA_QPMAX_OFFSET,
+			   CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX);
+	}
+	if (dev->devtype->product == CODA_960) {
+		if (ctx->params.h264_max_qp)
+			value |= 1 << CODA9_OPTION_RCQPMAX_OFFSET;
+		if (CODA_DEFAULT_GAMMA > 0)
+			value |= 1 << CODA9_OPTION_GAMMA_OFFSET;
+	} else {
+		if (CODA_DEFAULT_GAMMA > 0) {
+			if (dev->devtype->product == CODA_DX6)
+				value |= 1 << CODADX6_OPTION_GAMMA_OFFSET;
+			else
+				value |= 1 << CODA7_OPTION_GAMMA_OFFSET;
+		}
+		if (ctx->params.h264_min_qp)
+			value |= 1 << CODA7_OPTION_RCQPMIN_OFFSET;
+		if (ctx->params.h264_max_qp)
+			value |= 1 << CODA7_OPTION_RCQPMAX_OFFSET;
+	}
+	coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION);
+
+	if (ctx->params.frame_rc_enable && !ctx->params.mb_rc_enable)
+		value = 1;
+	else
+		value = 0;
+	coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE);
+
+	coda_setup_iram(ctx);
+
+	if (dst_fourcc == V4L2_PIX_FMT_H264) {
+		switch (dev->devtype->product) {
+		case CODA_DX6:
+			value = FMO_SLICE_SAVE_BUF_SIZE << 7;
+			coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO);
+			break;
+		case CODA_HX4:
+		case CODA_7541:
+			coda_write(dev, ctx->iram_info.search_ram_paddr,
+					CODA7_CMD_ENC_SEQ_SEARCH_BASE);
+			coda_write(dev, ctx->iram_info.search_ram_size,
+					CODA7_CMD_ENC_SEQ_SEARCH_SIZE);
+			break;
+		case CODA_960:
+			coda_write(dev, 0, CODA9_CMD_ENC_SEQ_ME_OPTION);
+			coda_write(dev, 0, CODA9_CMD_ENC_SEQ_INTRA_WEIGHT);
+		}
+	}
+
+	ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n");
+		goto out;
+	}
+
+	if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) {
+		v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT failed\n");
+		ret = -EFAULT;
+		goto out;
+	}
+	ctx->initialized = 1;
+
+	if (dst_fourcc != V4L2_PIX_FMT_JPEG) {
+		if (dev->devtype->product == CODA_960)
+			ctx->num_internal_frames = 4;
+		else
+			ctx->num_internal_frames = 2;
+		ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc);
+		if (ret < 0) {
+			v4l2_err(v4l2_dev, "failed to allocate framebuffers\n");
+			goto out;
+		}
+		num_fb = 2;
+		stride = q_data_src->bytesperline;
+	} else {
+		ctx->num_internal_frames = 0;
+		num_fb = 0;
+		stride = 0;
+	}
+	coda_write(dev, num_fb, CODA_CMD_SET_FRAME_BUF_NUM);
+	coda_write(dev, stride, CODA_CMD_SET_FRAME_BUF_STRIDE);
+
+	if (dev->devtype->product == CODA_HX4 ||
+	    dev->devtype->product == CODA_7541) {
+		coda_write(dev, q_data_src->bytesperline,
+				CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE);
+	}
+	if (dev->devtype->product != CODA_DX6) {
+		coda_write(dev, ctx->iram_info.buf_bit_use,
+				CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
+		coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use,
+				CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR);
+		coda_write(dev, ctx->iram_info.buf_dbk_y_use,
+				CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR);
+		coda_write(dev, ctx->iram_info.buf_dbk_c_use,
+				CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
+		coda_write(dev, ctx->iram_info.buf_ovl_use,
+				CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
+		if (dev->devtype->product == CODA_960) {
+			coda_write(dev, ctx->iram_info.buf_btp_use,
+					CODA9_CMD_SET_FRAME_AXI_BTP_ADDR);
+
+			coda9_set_frame_cache(ctx, q_data_src->fourcc);
+
+			/* FIXME */
+			coda_write(dev, ctx->internal_frames[2].buf.paddr,
+				   CODA9_CMD_SET_FRAME_SUBSAMP_A);
+			coda_write(dev, ctx->internal_frames[3].buf.paddr,
+				   CODA9_CMD_SET_FRAME_SUBSAMP_B);
+		}
+	}
+
+	ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF);
+	if (ret < 0) {
+		v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n");
+		goto out;
+	}
+
+	coda_dbg(1, ctx, "start encoding %dx%d %4.4s->%4.4s @ %d/%d Hz\n",
+		 q_data_src->rect.width, q_data_src->rect.height,
+		 (char *)&ctx->codec->src_fourcc, (char *)&dst_fourcc,
+		 ctx->params.framerate & 0xffff,
+		 (ctx->params.framerate >> 16) + 1);
+
+	/* Save stream headers */
+	buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+	switch (dst_fourcc) {
+	case V4L2_PIX_FMT_H264:
+		/*
+		 * Get SPS in the first frame and copy it to an
+		 * intermediate buffer.
+		 */
+		ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_SPS,
+					 &ctx->vpu_header[0][0],
+					 &ctx->vpu_header_size[0]);
+		if (ret < 0)
+			goto out;
+
+		/*
+		 * If visible width or height are not aligned to macroblock
+		 * size, the crop_right and crop_bottom SPS fields must be set
+		 * to the difference between visible and coded size.  This is
+		 * only supported by CODA960 firmware. All others do not allow
+		 * writing frame cropping parameters, so we have to manually
+		 * fix up the SPS RBSP (Sequence Parameter Set Raw Byte
+		 * Sequence Payload) ourselves.
+		 */
+		if (ctx->dev->devtype->product != CODA_960 &&
+		    ((q_data_src->rect.width % 16) ||
+		     (q_data_src->rect.height % 16))) {
+			ret = coda_h264_sps_fixup(ctx, q_data_src->rect.width,
+						  q_data_src->rect.height,
+						  &ctx->vpu_header[0][0],
+						  &ctx->vpu_header_size[0],
+						  sizeof(ctx->vpu_header[0]));
+			if (ret < 0)
+				goto out;
+		}
+
+		/*
+		 * Get PPS in the first frame and copy it to an
+		 * intermediate buffer.
+		 */
+		ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_PPS,
+					 &ctx->vpu_header[1][0],
+					 &ctx->vpu_header_size[1]);
+		if (ret < 0)
+			goto out;
+
+		/*
+		 * Length of H.264 headers is variable and thus it might not be
+		 * aligned for the coda to append the encoded frame. In that is
+		 * the case a filler NAL must be added to header 2.
+		 */
+		ctx->vpu_header_size[2] = coda_h264_padding(
+					(ctx->vpu_header_size[0] +
+					 ctx->vpu_header_size[1]),
+					 ctx->vpu_header[2]);
+		break;
+	case V4L2_PIX_FMT_MPEG4:
+		/*
+		 * Get VOS in the first frame and copy it to an
+		 * intermediate buffer
+		 */
+		ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOS,
+					 &ctx->vpu_header[0][0],
+					 &ctx->vpu_header_size[0]);
+		if (ret < 0)
+			goto out;
+
+		ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VIS,
+					 &ctx->vpu_header[1][0],
+					 &ctx->vpu_header_size[1]);
+		if (ret < 0)
+			goto out;
+
+		ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOL,
+					 &ctx->vpu_header[2][0],
+					 &ctx->vpu_header_size[2]);
+		if (ret < 0)
+			goto out;
+		break;
+	default:
+		/* No more formats need to save headers at the moment */
+		break;
+	}
+
+out:
+	mutex_unlock(&dev->coda_mutex);
+	return ret;
+}
+
+static int coda_prepare_encode(struct coda_ctx *ctx)
+{
+	struct coda_q_data *q_data_src, *q_data_dst;
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	struct coda_dev *dev = ctx->dev;
+	int force_ipicture;
+	int quant_param = 0;
+	u32 pic_stream_buffer_addr, pic_stream_buffer_size;
+	u32 rot_mode = 0;
+	u32 dst_fourcc;
+	u32 reg;
+	int ret;
+
+	ret = coda_enc_param_change(ctx);
+	if (ret < 0) {
+		v4l2_warn(&ctx->dev->v4l2_dev, "parameter change failed: %d\n",
+			  ret);
+	}
+
+	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	dst_fourcc = q_data_dst->fourcc;
+
+	src_buf->sequence = ctx->osequence;
+	dst_buf->sequence = ctx->osequence;
+	ctx->osequence++;
+
+	force_ipicture = ctx->params.force_ipicture;
+	if (force_ipicture)
+		ctx->params.force_ipicture = false;
+	else if (ctx->params.gop_size != 0 &&
+		 (src_buf->sequence % ctx->params.gop_size) == 0)
+		force_ipicture = 1;
+
+	/*
+	 * Workaround coda firmware BUG that only marks the first
+	 * frame as IDR. This is a problem for some decoders that can't
+	 * recover when a frame is lost.
+	 */
+	if (!force_ipicture) {
+		src_buf->flags |= V4L2_BUF_FLAG_PFRAME;
+		src_buf->flags &= ~V4L2_BUF_FLAG_KEYFRAME;
+	} else {
+		src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
+		src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME;
+	}
+
+	if (dev->devtype->product == CODA_960)
+		coda_set_gdi_regs(ctx);
+
+	/*
+	 * Copy headers in front of the first frame and forced I frames for
+	 * H.264 only. In MPEG4 they are already copied by the CODA.
+	 */
+	if (src_buf->sequence == 0 || force_ipicture) {
+		pic_stream_buffer_addr =
+			vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0) +
+			ctx->vpu_header_size[0] +
+			ctx->vpu_header_size[1] +
+			ctx->vpu_header_size[2];
+		pic_stream_buffer_size = q_data_dst->sizeimage -
+			ctx->vpu_header_size[0] -
+			ctx->vpu_header_size[1] -
+			ctx->vpu_header_size[2];
+		memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0),
+		       &ctx->vpu_header[0][0], ctx->vpu_header_size[0]);
+		memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0)
+			+ ctx->vpu_header_size[0], &ctx->vpu_header[1][0],
+			ctx->vpu_header_size[1]);
+		memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0)
+			+ ctx->vpu_header_size[0] + ctx->vpu_header_size[1],
+			&ctx->vpu_header[2][0], ctx->vpu_header_size[2]);
+	} else {
+		pic_stream_buffer_addr =
+			vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
+		pic_stream_buffer_size = q_data_dst->sizeimage;
+	}
+
+	if (force_ipicture) {
+		switch (dst_fourcc) {
+		case V4L2_PIX_FMT_H264:
+			quant_param = ctx->params.h264_intra_qp;
+			break;
+		case V4L2_PIX_FMT_MPEG4:
+			quant_param = ctx->params.mpeg4_intra_qp;
+			break;
+		case V4L2_PIX_FMT_JPEG:
+			quant_param = 30;
+			break;
+		default:
+			v4l2_warn(&ctx->dev->v4l2_dev,
+				"cannot set intra qp, fmt not supported\n");
+			break;
+		}
+	} else {
+		switch (dst_fourcc) {
+		case V4L2_PIX_FMT_H264:
+			quant_param = ctx->params.h264_inter_qp;
+			break;
+		case V4L2_PIX_FMT_MPEG4:
+			quant_param = ctx->params.mpeg4_inter_qp;
+			break;
+		default:
+			v4l2_warn(&ctx->dev->v4l2_dev,
+				"cannot set inter qp, fmt not supported\n");
+			break;
+		}
+	}
+
+	/* submit */
+	if (ctx->params.rot_mode)
+		rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode;
+	coda_write(dev, rot_mode, CODA_CMD_ENC_PIC_ROT_MODE);
+	coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS);
+
+	if (dev->devtype->product == CODA_960) {
+		coda_write(dev, 4/*FIXME: 0*/, CODA9_CMD_ENC_PIC_SRC_INDEX);
+		coda_write(dev, q_data_src->bytesperline,
+			   CODA9_CMD_ENC_PIC_SRC_STRIDE);
+		coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC);
+
+		reg = CODA9_CMD_ENC_PIC_SRC_ADDR_Y;
+	} else {
+		reg = CODA_CMD_ENC_PIC_SRC_ADDR_Y;
+	}
+	coda_write_base(ctx, q_data_src, src_buf, reg);
+
+	coda_write(dev, force_ipicture << 1 & 0x2,
+		   CODA_CMD_ENC_PIC_OPTION);
+
+	coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START);
+	coda_write(dev, pic_stream_buffer_size / 1024,
+		   CODA_CMD_ENC_PIC_BB_SIZE);
+
+	if (!ctx->streamon_out) {
+		/* After streamoff on the output side, set stream end flag */
+		ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
+		coda_write(dev, ctx->bit_stream_param,
+			   CODA_REG_BIT_BIT_STREAM_PARAM);
+	}
+
+	if (dev->devtype->product != CODA_DX6)
+		coda_write(dev, ctx->iram_info.axi_sram_use,
+				CODA7_REG_BIT_AXI_SRAM_USE);
+
+	trace_coda_enc_pic_run(ctx, src_buf);
+
+	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
+
+	return 0;
+}
+
+static char coda_frame_type_char(u32 flags)
+{
+	return (flags & V4L2_BUF_FLAG_KEYFRAME) ? 'I' :
+	       (flags & V4L2_BUF_FLAG_PFRAME) ? 'P' :
+	       (flags & V4L2_BUF_FLAG_BFRAME) ? 'B' : '?';
+}
+
+static void coda_finish_encode(struct coda_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	struct coda_dev *dev = ctx->dev;
+	u32 wr_ptr, start_ptr;
+
+	if (ctx->aborting)
+		return;
+
+	/*
+	 * Lock to make sure that an encoder stop command running in parallel
+	 * will either already have marked src_buf as last, or it will wake up
+	 * the capture queue after the buffers are returned.
+	 */
+	mutex_lock(&ctx->wakeup_mutex);
+	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+
+	trace_coda_enc_pic_done(ctx, dst_buf);
+
+	/* Get results from the coda */
+	start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START);
+	wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
+
+	/* Calculate bytesused field */
+	if (dst_buf->sequence == 0 ||
+	    src_buf->flags & V4L2_BUF_FLAG_KEYFRAME) {
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr +
+					ctx->vpu_header_size[0] +
+					ctx->vpu_header_size[1] +
+					ctx->vpu_header_size[2]);
+	} else {
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr);
+	}
+
+	coda_dbg(1, ctx, "frame size = %u\n", wr_ptr - start_ptr);
+
+	coda_read(dev, CODA_RET_ENC_PIC_SLICE_NUM);
+	coda_read(dev, CODA_RET_ENC_PIC_FLAG);
+
+	dst_buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+			    V4L2_BUF_FLAG_PFRAME |
+			    V4L2_BUF_FLAG_LAST);
+	if (coda_read(dev, CODA_RET_ENC_PIC_TYPE) == 0)
+		dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
+	else
+		dst_buf->flags |= V4L2_BUF_FLAG_PFRAME;
+	dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST;
+
+	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
+
+	v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+
+	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+	coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_DONE);
+	mutex_unlock(&ctx->wakeup_mutex);
+
+	ctx->gopcounter--;
+	if (ctx->gopcounter < 0)
+		ctx->gopcounter = ctx->params.gop_size - 1;
+
+	coda_dbg(1, ctx, "job finished: encoded %c frame (%d)%s\n",
+		 coda_frame_type_char(dst_buf->flags), dst_buf->sequence,
+		 (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : "");
+}
+
+static void coda_seq_end_work(struct work_struct *work)
+{
+	struct coda_ctx *ctx = container_of(work, struct coda_ctx, seq_end_work);
+	struct coda_dev *dev = ctx->dev;
+
+	mutex_lock(&ctx->buffer_mutex);
+	mutex_lock(&dev->coda_mutex);
+
+	if (ctx->initialized == 0)
+		goto out;
+
+	coda_dbg(1, ctx, "%s: sent command 'SEQ_END' to coda\n", __func__);
+	if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
+		v4l2_err(&dev->v4l2_dev,
+			 "CODA_COMMAND_SEQ_END failed\n");
+	}
+
+	/*
+	 * FIXME: Sometimes h.264 encoding fails with 8-byte sequences missing
+	 * from the output stream after the h.264 decoder has run. Resetting the
+	 * hardware after the decoder has finished seems to help.
+	 */
+	if (dev->devtype->product == CODA_960)
+		coda_hw_reset(ctx);
+
+	kfifo_init(&ctx->bitstream_fifo,
+		ctx->bitstream.vaddr, ctx->bitstream.size);
+
+	coda_free_framebuffers(ctx);
+
+	ctx->initialized = 0;
+
+out:
+	mutex_unlock(&dev->coda_mutex);
+	mutex_unlock(&ctx->buffer_mutex);
+}
+
+static void coda_bit_release(struct coda_ctx *ctx)
+{
+	mutex_lock(&ctx->buffer_mutex);
+	coda_free_framebuffers(ctx);
+	coda_free_context_buffers(ctx);
+	coda_free_bitstream_buffer(ctx);
+	mutex_unlock(&ctx->buffer_mutex);
+}
+
+const struct coda_context_ops coda_bit_encode_ops = {
+	.queue_init = coda_encoder_queue_init,
+	.reqbufs = coda_encoder_reqbufs,
+	.start_streaming = coda_start_encoding,
+	.prepare_run = coda_prepare_encode,
+	.finish_run = coda_finish_encode,
+	.seq_end_work = coda_seq_end_work,
+	.release = coda_bit_release,
+};
+
+/*
+ * Decoder context operations
+ */
+
+static int coda_alloc_bitstream_buffer(struct coda_ctx *ctx,
+				       struct coda_q_data *q_data)
+{
+	if (ctx->bitstream.vaddr)
+		return 0;
+
+	ctx->bitstream.size = roundup_pow_of_two(q_data->sizeimage * 2);
+	ctx->bitstream.vaddr = dma_alloc_wc(ctx->dev->dev, ctx->bitstream.size,
+					    &ctx->bitstream.paddr, GFP_KERNEL);
+	if (!ctx->bitstream.vaddr) {
+		v4l2_err(&ctx->dev->v4l2_dev,
+			 "failed to allocate bitstream ringbuffer");
+		return -ENOMEM;
+	}
+	kfifo_init(&ctx->bitstream_fifo,
+		   ctx->bitstream.vaddr, ctx->bitstream.size);
+
+	return 0;
+}
+
+static void coda_free_bitstream_buffer(struct coda_ctx *ctx)
+{
+	if (ctx->bitstream.vaddr == NULL)
+		return;
+
+	dma_free_wc(ctx->dev->dev, ctx->bitstream.size, ctx->bitstream.vaddr,
+		    ctx->bitstream.paddr);
+	ctx->bitstream.vaddr = NULL;
+	kfifo_init(&ctx->bitstream_fifo, NULL, 0);
+}
+
+static int coda_decoder_reqbufs(struct coda_ctx *ctx,
+				struct v4l2_requestbuffers *rb)
+{
+	struct coda_q_data *q_data_src;
+	int ret;
+
+	if (rb->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		return 0;
+
+	if (rb->count) {
+		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+		ret = coda_alloc_context_buffers(ctx, q_data_src);
+		if (ret < 0)
+			return ret;
+		ret = coda_alloc_bitstream_buffer(ctx, q_data_src);
+		if (ret < 0) {
+			coda_free_context_buffers(ctx);
+			return ret;
+		}
+	} else {
+		coda_free_bitstream_buffer(ctx);
+		coda_free_context_buffers(ctx);
+	}
+
+	return 0;
+}
+
+static bool coda_reorder_enable(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	int profile;
+
+	if (dev->devtype->product != CODA_HX4 &&
+	    dev->devtype->product != CODA_7541 &&
+	    dev->devtype->product != CODA_960)
+		return false;
+
+	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG)
+		return false;
+
+	if (ctx->codec->src_fourcc != V4L2_PIX_FMT_H264)
+		return true;
+
+	profile = coda_h264_profile(ctx->params.h264_profile_idc);
+	if (profile < 0)
+		v4l2_warn(&dev->v4l2_dev, "Unknown H264 Profile: %u\n",
+			  ctx->params.h264_profile_idc);
+
+	/* Baseline profile does not support reordering */
+	return profile > V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
+}
+
+static void coda_decoder_drop_used_metas(struct coda_ctx *ctx)
+{
+	struct coda_buffer_meta *meta, *tmp;
+
+	/*
+	 * All metas that end at or before the RD pointer (fifo out),
+	 * are now consumed by the VPU and should be released.
+	 */
+	spin_lock(&ctx->buffer_meta_lock);
+	list_for_each_entry_safe(meta, tmp, &ctx->buffer_meta_list, list) {
+		if (ctx->bitstream_fifo.kfifo.out >= meta->end) {
+			coda_dbg(2, ctx, "releasing meta: seq=%d start=%d end=%d\n",
+				 meta->sequence, meta->start, meta->end);
+
+			list_del(&meta->list);
+			ctx->num_metas--;
+			ctx->first_frame_sequence++;
+			kfree(meta);
+		}
+	}
+	spin_unlock(&ctx->buffer_meta_lock);
+}
+
+static int __coda_decoder_seq_init(struct coda_ctx *ctx)
+{
+	struct coda_q_data *q_data_src, *q_data_dst;
+	u32 bitstream_buf, bitstream_size;
+	struct coda_dev *dev = ctx->dev;
+	int width, height;
+	u32 src_fourcc, dst_fourcc;
+	u32 val;
+	int ret;
+
+	lockdep_assert_held(&dev->coda_mutex);
+
+	coda_dbg(1, ctx, "Video Data Order Adapter: %s\n",
+		 ctx->use_vdoa ? "Enabled" : "Disabled");
+
+	/* Start decoding */
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	bitstream_buf = ctx->bitstream.paddr;
+	bitstream_size = ctx->bitstream.size;
+	src_fourcc = q_data_src->fourcc;
+	dst_fourcc = q_data_dst->fourcc;
+
+	/* Update coda bitstream read and write pointers from kfifo */
+	coda_kfifo_sync_to_device_full(ctx);
+
+	ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) |
+				 CODA9_FRAME_TILED2LINEAR);
+	if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV)
+		ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
+	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
+		ctx->frame_mem_ctrl |= (0x3 << 9) |
+			((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR);
+	coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL);
+
+	ctx->display_idx = -1;
+	ctx->frm_dis_flg = 0;
+	coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
+
+	coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START);
+	coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE);
+	val = 0;
+	if (coda_reorder_enable(ctx))
+		val |= CODA_REORDER_ENABLE;
+	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG)
+		val |= CODA_NO_INT_ENABLE;
+	coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION);
+
+	ctx->params.codec_mode = ctx->codec->mode;
+	if (dev->devtype->product == CODA_960 &&
+	    src_fourcc == V4L2_PIX_FMT_MPEG4)
+		ctx->params.codec_mode_aux = CODA_MP4_AUX_MPEG4;
+	else
+		ctx->params.codec_mode_aux = 0;
+	if (src_fourcc == V4L2_PIX_FMT_MPEG4) {
+		coda_write(dev, CODA_MP4_CLASS_MPEG4,
+			   CODA_CMD_DEC_SEQ_MP4_ASP_CLASS);
+	}
+	if (src_fourcc == V4L2_PIX_FMT_H264) {
+		if (dev->devtype->product == CODA_HX4 ||
+		    dev->devtype->product == CODA_7541) {
+			coda_write(dev, ctx->psbuf.paddr,
+					CODA_CMD_DEC_SEQ_PS_BB_START);
+			coda_write(dev, (CODA7_PS_BUF_SIZE / 1024),
+					CODA_CMD_DEC_SEQ_PS_BB_SIZE);
+		}
+		if (dev->devtype->product == CODA_960) {
+			coda_write(dev, 0, CODA_CMD_DEC_SEQ_X264_MV_EN);
+			coda_write(dev, 512, CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE);
+		}
+	}
+	if (src_fourcc == V4L2_PIX_FMT_JPEG)
+		coda_write(dev, 0, CODA_CMD_DEC_SEQ_JPG_THUMB_EN);
+	if (dev->devtype->product != CODA_960)
+		coda_write(dev, 0, CODA_CMD_DEC_SEQ_SRC_SIZE);
+
+	ctx->bit_stream_param = CODA_BIT_DEC_SEQ_INIT_ESCAPE;
+	ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT);
+	ctx->bit_stream_param = 0;
+	if (ret) {
+		v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n");
+		return ret;
+	}
+	ctx->sequence_offset = ~0U;
+	ctx->initialized = 1;
+	ctx->first_frame_sequence = 0;
+
+	/* Update kfifo out pointer from coda bitstream read pointer */
+	coda_kfifo_sync_from_device(ctx);
+
+	/*
+	 * After updating the read pointer, we need to check if
+	 * any metas are consumed and should be released.
+	 */
+	coda_decoder_drop_used_metas(ctx);
+
+	if (coda_read(dev, CODA_RET_DEC_SEQ_SUCCESS) == 0) {
+		v4l2_err(&dev->v4l2_dev,
+			"CODA_COMMAND_SEQ_INIT failed, error code = 0x%x\n",
+			coda_read(dev, CODA_RET_DEC_SEQ_ERR_REASON));
+		return -EAGAIN;
+	}
+
+	val = coda_read(dev, CODA_RET_DEC_SEQ_SRC_SIZE);
+	if (dev->devtype->product == CODA_DX6) {
+		width = (val >> CODADX6_PICWIDTH_OFFSET) & CODADX6_PICWIDTH_MASK;
+		height = val & CODADX6_PICHEIGHT_MASK;
+	} else {
+		width = (val >> CODA7_PICWIDTH_OFFSET) & CODA7_PICWIDTH_MASK;
+		height = val & CODA7_PICHEIGHT_MASK;
+	}
+
+	if (width > q_data_dst->bytesperline || height > q_data_dst->height) {
+		v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n",
+			 width, height, q_data_dst->bytesperline,
+			 q_data_dst->height);
+		return -EINVAL;
+	}
+
+	width = round_up(width, 16);
+	height = round_up(height, 16);
+
+	coda_dbg(1, ctx, "start decoding: %dx%d\n", width, height);
+
+	ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED);
+	/*
+	 * If the VDOA is used, the decoder needs one additional frame,
+	 * because the frames are freed when the next frame is decoded.
+	 * Otherwise there are visible errors in the decoded frames (green
+	 * regions in displayed frames) and a broken order of frames (earlier
+	 * frames are sporadically displayed after later frames).
+	 */
+	if (ctx->use_vdoa)
+		ctx->num_internal_frames += 1;
+	if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) {
+		v4l2_err(&dev->v4l2_dev,
+			 "not enough framebuffers to decode (%d < %d)\n",
+			 CODA_MAX_FRAMEBUFFERS, ctx->num_internal_frames);
+		return -EINVAL;
+	}
+
+	if (src_fourcc == V4L2_PIX_FMT_H264) {
+		u32 left_right;
+		u32 top_bottom;
+
+		left_right = coda_read(dev, CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT);
+		top_bottom = coda_read(dev, CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM);
+
+		q_data_dst->rect.left = (left_right >> 10) & 0x3ff;
+		q_data_dst->rect.top = (top_bottom >> 10) & 0x3ff;
+		q_data_dst->rect.width = width - q_data_dst->rect.left -
+					 (left_right & 0x3ff);
+		q_data_dst->rect.height = height - q_data_dst->rect.top -
+					  (top_bottom & 0x3ff);
+	}
+
+	if (dev->devtype->product != CODA_DX6) {
+		u8 profile, level;
+
+		val = coda_read(dev, CODA7_RET_DEC_SEQ_HEADER_REPORT);
+		profile = val & 0xff;
+		level = (val >> 8) & 0x7f;
+
+		if (profile || level)
+			coda_update_profile_level_ctrls(ctx, profile, level);
+	}
+
+	return 0;
+}
+
+static void coda_dec_seq_init_work(struct work_struct *work)
+{
+	struct coda_ctx *ctx = container_of(work,
+					    struct coda_ctx, seq_init_work);
+	struct coda_dev *dev = ctx->dev;
+
+	mutex_lock(&ctx->buffer_mutex);
+	mutex_lock(&dev->coda_mutex);
+
+	if (!ctx->initialized)
+		__coda_decoder_seq_init(ctx);
+
+	mutex_unlock(&dev->coda_mutex);
+	mutex_unlock(&ctx->buffer_mutex);
+}
+
+static int __coda_start_decoding(struct coda_ctx *ctx)
+{
+	struct coda_q_data *q_data_src, *q_data_dst;
+	struct coda_dev *dev = ctx->dev;
+	u32 src_fourcc, dst_fourcc;
+	int ret;
+
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	src_fourcc = q_data_src->fourcc;
+	dst_fourcc = q_data_dst->fourcc;
+
+	if (!ctx->initialized) {
+		ret = __coda_decoder_seq_init(ctx);
+		if (ret < 0)
+			return ret;
+	} else {
+		ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) |
+					 CODA9_FRAME_TILED2LINEAR);
+		if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV)
+			ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
+		if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
+			ctx->frame_mem_ctrl |= (0x3 << 9) |
+				((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR);
+	}
+
+	coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
+
+	ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc);
+	if (ret < 0) {
+		v4l2_err(&dev->v4l2_dev, "failed to allocate framebuffers\n");
+		return ret;
+	}
+
+	/* Tell the decoder how many frame buffers we allocated. */
+	coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
+	coda_write(dev, round_up(q_data_dst->rect.width, 16),
+		   CODA_CMD_SET_FRAME_BUF_STRIDE);
+
+	if (dev->devtype->product != CODA_DX6) {
+		/* Set secondary AXI IRAM */
+		coda_setup_iram(ctx);
+
+		coda_write(dev, ctx->iram_info.buf_bit_use,
+				CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
+		coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use,
+				CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR);
+		coda_write(dev, ctx->iram_info.buf_dbk_y_use,
+				CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR);
+		coda_write(dev, ctx->iram_info.buf_dbk_c_use,
+				CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
+		coda_write(dev, ctx->iram_info.buf_ovl_use,
+				CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
+		if (dev->devtype->product == CODA_960) {
+			coda_write(dev, ctx->iram_info.buf_btp_use,
+					CODA9_CMD_SET_FRAME_AXI_BTP_ADDR);
+
+			coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY);
+			coda9_set_frame_cache(ctx, dst_fourcc);
+		}
+	}
+
+	if (src_fourcc == V4L2_PIX_FMT_H264) {
+		coda_write(dev, ctx->slicebuf.paddr,
+				CODA_CMD_SET_FRAME_SLICE_BB_START);
+		coda_write(dev, ctx->slicebuf.size / 1024,
+				CODA_CMD_SET_FRAME_SLICE_BB_SIZE);
+	}
+
+	if (dev->devtype->product == CODA_HX4 ||
+	    dev->devtype->product == CODA_7541) {
+		int max_mb_x = 1920 / 16;
+		int max_mb_y = 1088 / 16;
+		int max_mb_num = max_mb_x * max_mb_y;
+
+		coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y,
+				CODA7_CMD_SET_FRAME_MAX_DEC_SIZE);
+	} else if (dev->devtype->product == CODA_960) {
+		int max_mb_x = 1920 / 16;
+		int max_mb_y = 1088 / 16;
+		int max_mb_num = max_mb_x * max_mb_y;
+
+		coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y,
+				CODA9_CMD_SET_FRAME_MAX_DEC_SIZE);
+	}
+
+	if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) {
+		v4l2_err(&ctx->dev->v4l2_dev,
+			 "CODA_COMMAND_SET_FRAME_BUF timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+static int coda_start_decoding(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	int ret;
+
+	mutex_lock(&dev->coda_mutex);
+	ret = __coda_start_decoding(ctx);
+	mutex_unlock(&dev->coda_mutex);
+
+	return ret;
+}
+
+static int coda_prepare_decode(struct coda_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *dst_buf;
+	struct coda_dev *dev = ctx->dev;
+	struct coda_q_data *q_data_dst;
+	struct coda_buffer_meta *meta;
+	u32 rot_mode = 0;
+	u32 reg_addr, reg_stride;
+
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
+	/* Try to copy source buffer contents into the bitstream ringbuffer */
+	mutex_lock(&ctx->bitstream_mutex);
+	coda_fill_bitstream(ctx, NULL);
+	mutex_unlock(&ctx->bitstream_mutex);
+
+	if (coda_get_bitstream_payload(ctx) < 512 &&
+	    (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
+		coda_dbg(1, ctx, "bitstream payload: %d, skipping\n",
+			 coda_get_bitstream_payload(ctx));
+		return -EAGAIN;
+	}
+
+	/* Run coda_start_decoding (again) if not yet initialized */
+	if (!ctx->initialized) {
+		int ret = __coda_start_decoding(ctx);
+
+		if (ret < 0) {
+			v4l2_err(&dev->v4l2_dev, "failed to start decoding\n");
+			return -EAGAIN;
+		} else {
+			ctx->initialized = 1;
+		}
+	}
+
+	if (dev->devtype->product == CODA_960)
+		coda_set_gdi_regs(ctx);
+
+	if (ctx->use_vdoa &&
+	    ctx->display_idx >= 0 &&
+	    ctx->display_idx < ctx->num_internal_frames) {
+		vdoa_device_run(ctx->vdoa,
+				vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0),
+				ctx->internal_frames[ctx->display_idx].buf.paddr);
+	} else {
+		if (dev->devtype->product == CODA_960) {
+			/*
+			 * It was previously assumed that the CODA960 has an
+			 * internal list of 64 buffer entries that contains
+			 * both the registered internal frame buffers as well
+			 * as the rotator buffer output, and that the ROT_INDEX
+			 * register must be set to a value between the last
+			 * internal frame buffers' index and 64.
+			 * At least on firmware version 3.1.1 it turns out that
+			 * setting ROT_INDEX to any value >= 32 causes CODA
+			 * hangups that it can not recover from with the SRC VPU
+			 * reset.
+			 * It does appear to work however, to just set it to a
+			 * fixed value in the [ctx->num_internal_frames, 31]
+			 * range, for example CODA_MAX_FRAMEBUFFERS.
+			 */
+			coda_write(dev, CODA_MAX_FRAMEBUFFERS,
+				   CODA9_CMD_DEC_PIC_ROT_INDEX);
+
+			reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y;
+			reg_stride = CODA9_CMD_DEC_PIC_ROT_STRIDE;
+		} else {
+			reg_addr = CODA_CMD_DEC_PIC_ROT_ADDR_Y;
+			reg_stride = CODA_CMD_DEC_PIC_ROT_STRIDE;
+		}
+		coda_write_base(ctx, q_data_dst, dst_buf, reg_addr);
+		coda_write(dev, q_data_dst->bytesperline, reg_stride);
+
+		rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode;
+	}
+
+	coda_write(dev, rot_mode, CODA_CMD_DEC_PIC_ROT_MODE);
+
+	switch (dev->devtype->product) {
+	case CODA_DX6:
+		/* TBD */
+	case CODA_HX4:
+	case CODA_7541:
+		coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION);
+		break;
+	case CODA_960:
+		/* 'hardcode to use interrupt disable mode'? */
+		coda_write(dev, (1 << 10), CODA_CMD_DEC_PIC_OPTION);
+		break;
+	}
+
+	coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM);
+
+	coda_write(dev, 0, CODA_CMD_DEC_PIC_BB_START);
+	coda_write(dev, 0, CODA_CMD_DEC_PIC_START_BYTE);
+
+	if (dev->devtype->product != CODA_DX6)
+		coda_write(dev, ctx->iram_info.axi_sram_use,
+				CODA7_REG_BIT_AXI_SRAM_USE);
+
+	spin_lock(&ctx->buffer_meta_lock);
+	meta = list_first_entry_or_null(&ctx->buffer_meta_list,
+					struct coda_buffer_meta, list);
+
+	if (meta && ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) {
+
+		/* If this is the last buffer in the bitstream, add padding */
+		if (meta->end == ctx->bitstream_fifo.kfifo.in) {
+			static unsigned char buf[512];
+			unsigned int pad;
+
+			/* Pad to multiple of 256 and then add 256 more */
+			pad = ((0 - meta->end) & 0xff) + 256;
+
+			memset(buf, 0xff, sizeof(buf));
+
+			kfifo_in(&ctx->bitstream_fifo, buf, pad);
+		}
+	}
+	spin_unlock(&ctx->buffer_meta_lock);
+
+	coda_kfifo_sync_to_device_full(ctx);
+
+	/* Clear decode success flag */
+	coda_write(dev, 0, CODA_RET_DEC_PIC_SUCCESS);
+
+	/* Clear error return value */
+	coda_write(dev, 0, CODA_RET_DEC_PIC_ERR_MB);
+
+	trace_coda_dec_pic_run(ctx, meta);
+
+	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
+
+	return 0;
+}
+
+static void coda_finish_decode(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	struct coda_q_data *q_data_src;
+	struct coda_q_data *q_data_dst;
+	struct vb2_v4l2_buffer *dst_buf;
+	struct coda_buffer_meta *meta;
+	int width, height;
+	int decoded_idx;
+	int display_idx;
+	struct coda_internal_frame *decoded_frame = NULL;
+	u32 src_fourcc;
+	int success;
+	u32 err_mb;
+	int err_vdoa = 0;
+	u32 val;
+
+	if (ctx->aborting)
+		return;
+
+	/* Update kfifo out pointer from coda bitstream read pointer */
+	coda_kfifo_sync_from_device(ctx);
+
+	/*
+	 * in stream-end mode, the read pointer can overshoot the write pointer
+	 * by up to 512 bytes
+	 */
+	if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) {
+		if (coda_get_bitstream_payload(ctx) >= ctx->bitstream.size - 512)
+			kfifo_init(&ctx->bitstream_fifo,
+				ctx->bitstream.vaddr, ctx->bitstream.size);
+	}
+
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	src_fourcc = q_data_src->fourcc;
+
+	val = coda_read(dev, CODA_RET_DEC_PIC_SUCCESS);
+	if (val != 1)
+		pr_err("DEC_PIC_SUCCESS = %d\n", val);
+
+	success = val & 0x1;
+	if (!success)
+		v4l2_err(&dev->v4l2_dev, "decode failed\n");
+
+	if (src_fourcc == V4L2_PIX_FMT_H264) {
+		if (val & (1 << 3))
+			v4l2_err(&dev->v4l2_dev,
+				 "insufficient PS buffer space (%d bytes)\n",
+				 ctx->psbuf.size);
+		if (val & (1 << 2))
+			v4l2_err(&dev->v4l2_dev,
+				 "insufficient slice buffer space (%d bytes)\n",
+				 ctx->slicebuf.size);
+	}
+
+	val = coda_read(dev, CODA_RET_DEC_PIC_SIZE);
+	width = (val >> 16) & 0xffff;
+	height = val & 0xffff;
+
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
+	/* frame crop information */
+	if (src_fourcc == V4L2_PIX_FMT_H264) {
+		u32 left_right;
+		u32 top_bottom;
+
+		left_right = coda_read(dev, CODA_RET_DEC_PIC_CROP_LEFT_RIGHT);
+		top_bottom = coda_read(dev, CODA_RET_DEC_PIC_CROP_TOP_BOTTOM);
+
+		if (left_right == 0xffffffff && top_bottom == 0xffffffff) {
+			/* Keep current crop information */
+		} else {
+			struct v4l2_rect *rect = &q_data_dst->rect;
+
+			rect->left = left_right >> 16 & 0xffff;
+			rect->top = top_bottom >> 16 & 0xffff;
+			rect->width = width - rect->left -
+				      (left_right & 0xffff);
+			rect->height = height - rect->top -
+				       (top_bottom & 0xffff);
+		}
+	} else {
+		/* no cropping */
+	}
+
+	err_mb = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB);
+	if (err_mb > 0) {
+		if (__ratelimit(&dev->mb_err_rs))
+			coda_dbg(1, ctx, "errors in %d macroblocks\n", err_mb);
+		v4l2_ctrl_s_ctrl(ctx->mb_err_cnt_ctrl,
+				 v4l2_ctrl_g_ctrl(ctx->mb_err_cnt_ctrl) + err_mb);
+	}
+
+	if (dev->devtype->product == CODA_HX4 ||
+	    dev->devtype->product == CODA_7541) {
+		val = coda_read(dev, CODA_RET_DEC_PIC_OPTION);
+		if (val == 0) {
+			/* not enough bitstream data */
+			coda_dbg(1, ctx, "prescan failed: %d\n", val);
+			ctx->hold = true;
+			return;
+		}
+	}
+
+	/* Wait until the VDOA finished writing the previous display frame */
+	if (ctx->use_vdoa &&
+	    ctx->display_idx >= 0 &&
+	    ctx->display_idx < ctx->num_internal_frames) {
+		err_vdoa = vdoa_wait_for_completion(ctx->vdoa);
+	}
+
+	ctx->frm_dis_flg = coda_read(dev,
+				     CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
+
+	/* The previous display frame was copied out and can be overwritten */
+	if (ctx->display_idx >= 0 &&
+	    ctx->display_idx < ctx->num_internal_frames) {
+		ctx->frm_dis_flg &= ~(1 << ctx->display_idx);
+		coda_write(dev, ctx->frm_dis_flg,
+				CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
+	}
+
+	/*
+	 * The index of the last decoded frame, not necessarily in
+	 * display order, and the index of the next display frame.
+	 * The latter could have been decoded in a previous run.
+	 */
+	decoded_idx = coda_read(dev, CODA_RET_DEC_PIC_CUR_IDX);
+	display_idx = coda_read(dev, CODA_RET_DEC_PIC_FRAME_IDX);
+
+	if (decoded_idx == -1) {
+		/* no frame was decoded, but we might have a display frame */
+		if (display_idx >= 0 && display_idx < ctx->num_internal_frames)
+			ctx->sequence_offset++;
+		else if (ctx->display_idx < 0)
+			ctx->hold = true;
+	} else if (decoded_idx == -2) {
+		if (ctx->display_idx >= 0 &&
+		    ctx->display_idx < ctx->num_internal_frames)
+			ctx->sequence_offset++;
+		/* no frame was decoded, we still return remaining buffers */
+	} else if (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) {
+		v4l2_err(&dev->v4l2_dev,
+			 "decoded frame index out of range: %d\n", decoded_idx);
+	} else {
+		int sequence;
+
+		decoded_frame = &ctx->internal_frames[decoded_idx];
+
+		val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM);
+		if (ctx->sequence_offset == -1)
+			ctx->sequence_offset = val;
+
+		sequence = val + ctx->first_frame_sequence
+			       - ctx->sequence_offset;
+		spin_lock(&ctx->buffer_meta_lock);
+		if (!list_empty(&ctx->buffer_meta_list)) {
+			meta = list_first_entry(&ctx->buffer_meta_list,
+					      struct coda_buffer_meta, list);
+			list_del(&meta->list);
+			ctx->num_metas--;
+			spin_unlock(&ctx->buffer_meta_lock);
+			/*
+			 * Clamp counters to 16 bits for comparison, as the HW
+			 * counter rolls over at this point for h.264. This
+			 * may be different for other formats, but using 16 bits
+			 * should be enough to detect most errors and saves us
+			 * from doing different things based on the format.
+			 */
+			if ((sequence & 0xffff) != (meta->sequence & 0xffff)) {
+				v4l2_err(&dev->v4l2_dev,
+					 "sequence number mismatch (%d(%d) != %d)\n",
+					 sequence, ctx->sequence_offset,
+					 meta->sequence);
+			}
+			decoded_frame->meta = *meta;
+			kfree(meta);
+		} else {
+			spin_unlock(&ctx->buffer_meta_lock);
+			v4l2_err(&dev->v4l2_dev, "empty timestamp list!\n");
+			memset(&decoded_frame->meta, 0,
+			       sizeof(struct coda_buffer_meta));
+			decoded_frame->meta.sequence = sequence;
+			decoded_frame->meta.last = false;
+			ctx->sequence_offset++;
+		}
+
+		trace_coda_dec_pic_done(ctx, &decoded_frame->meta);
+
+		val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7;
+		decoded_frame->type = (val == 0) ? V4L2_BUF_FLAG_KEYFRAME :
+				      (val == 1) ? V4L2_BUF_FLAG_PFRAME :
+						   V4L2_BUF_FLAG_BFRAME;
+
+		decoded_frame->error = err_mb;
+	}
+
+	if (display_idx == -1) {
+		/*
+		 * no more frames to be decoded, but there could still
+		 * be rotator output to dequeue
+		 */
+		ctx->hold = true;
+	} else if (display_idx == -3) {
+		/* possibly prescan failure */
+	} else if (display_idx < 0 || display_idx >= ctx->num_internal_frames) {
+		v4l2_err(&dev->v4l2_dev,
+			 "presentation frame index out of range: %d\n",
+			 display_idx);
+	}
+
+	/* If a frame was copied out, return it */
+	if (ctx->display_idx >= 0 &&
+	    ctx->display_idx < ctx->num_internal_frames) {
+		struct coda_internal_frame *ready_frame;
+
+		ready_frame = &ctx->internal_frames[ctx->display_idx];
+
+		dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+		dst_buf->sequence = ctx->osequence++;
+
+		dst_buf->field = V4L2_FIELD_NONE;
+		dst_buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+					     V4L2_BUF_FLAG_PFRAME |
+					     V4L2_BUF_FLAG_BFRAME);
+		dst_buf->flags |= ready_frame->type;
+		meta = &ready_frame->meta;
+		if (meta->last && !coda_reorder_enable(ctx)) {
+			/*
+			 * If this was the last decoded frame, and reordering
+			 * is disabled, this will be the last display frame.
+			 */
+			coda_dbg(1, ctx, "last meta, marking as last frame\n");
+			dst_buf->flags |= V4L2_BUF_FLAG_LAST;
+		} else if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG &&
+			   display_idx == -1) {
+			/*
+			 * If there is no designated presentation frame anymore,
+			 * this frame has to be the last one.
+			 */
+			coda_dbg(1, ctx,
+				 "no more frames to return, marking as last frame\n");
+			dst_buf->flags |= V4L2_BUF_FLAG_LAST;
+		}
+		dst_buf->timecode = meta->timecode;
+		dst_buf->vb2_buf.timestamp = meta->timestamp;
+
+		trace_coda_dec_rot_done(ctx, dst_buf, meta);
+
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
+				      q_data_dst->sizeimage);
+
+		if (ready_frame->error || err_vdoa)
+			coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_ERROR);
+		else
+			coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_DONE);
+
+		if (decoded_frame) {
+			coda_dbg(1, ctx, "job finished: decoded %c frame %u, returned %c frame %u (%u/%u)%s\n",
+				 coda_frame_type_char(decoded_frame->type),
+				 decoded_frame->meta.sequence,
+				 coda_frame_type_char(dst_buf->flags),
+				 ready_frame->meta.sequence,
+				 dst_buf->sequence, ctx->qsequence,
+				 (dst_buf->flags & V4L2_BUF_FLAG_LAST) ?
+				 " (last)" : "");
+		} else {
+			coda_dbg(1, ctx, "job finished: no frame decoded (%d), returned %c frame %u (%u/%u)%s\n",
+				 decoded_idx,
+				 coda_frame_type_char(dst_buf->flags),
+				 ready_frame->meta.sequence,
+				 dst_buf->sequence, ctx->qsequence,
+				 (dst_buf->flags & V4L2_BUF_FLAG_LAST) ?
+				 " (last)" : "");
+		}
+	} else {
+		if (decoded_frame) {
+			coda_dbg(1, ctx, "job finished: decoded %c frame %u, no frame returned (%d)\n",
+				 coda_frame_type_char(decoded_frame->type),
+				 decoded_frame->meta.sequence,
+				 ctx->display_idx);
+		} else {
+			coda_dbg(1, ctx, "job finished: no frame decoded (%d) or returned (%d)\n",
+				 decoded_idx, ctx->display_idx);
+		}
+	}
+
+	/* The rotator will copy the current display frame next time */
+	ctx->display_idx = display_idx;
+
+	/*
+	 * The current decode run might have brought the bitstream fill level
+	 * below the size where we can start the next decode run. As userspace
+	 * might have filled the output queue completely and might thus be
+	 * blocked, we can't rely on the next qbuf to trigger the bitstream
+	 * refill. Check if we have data to refill the bitstream now.
+	 */
+	mutex_lock(&ctx->bitstream_mutex);
+	coda_fill_bitstream(ctx, NULL);
+	mutex_unlock(&ctx->bitstream_mutex);
+}
+
+static void coda_decode_timeout(struct coda_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *dst_buf;
+
+	/*
+	 * For now this only handles the case where we would deadlock with
+	 * userspace, i.e. userspace issued DEC_CMD_STOP and waits for EOS,
+	 * but after a failed decode run we would hold the context and wait for
+	 * userspace to queue more buffers.
+	 */
+	if (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))
+		return;
+
+	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+	dst_buf->sequence = ctx->qsequence - 1;
+
+	coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_ERROR);
+}
+
+const struct coda_context_ops coda_bit_decode_ops = {
+	.queue_init = coda_decoder_queue_init,
+	.reqbufs = coda_decoder_reqbufs,
+	.start_streaming = coda_start_decoding,
+	.prepare_run = coda_prepare_decode,
+	.finish_run = coda_finish_decode,
+	.run_timeout = coda_decode_timeout,
+	.seq_init_work = coda_dec_seq_init_work,
+	.seq_end_work = coda_seq_end_work,
+	.release = coda_bit_release,
+};
+
+irqreturn_t coda_irq_handler(int irq, void *data)
+{
+	struct coda_dev *dev = data;
+	struct coda_ctx *ctx;
+
+	/* read status register to attend the IRQ */
+	coda_read(dev, CODA_REG_BIT_INT_STATUS);
+	coda_write(dev, 0, CODA_REG_BIT_INT_REASON);
+	coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET,
+		      CODA_REG_BIT_INT_CLEAR);
+
+	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
+	if (ctx == NULL) {
+		v4l2_err(&dev->v4l2_dev,
+			 "Instance released before the end of transaction\n");
+		return IRQ_HANDLED;
+	}
+
+	trace_coda_bit_done(ctx);
+
+	if (ctx->aborting) {
+		coda_dbg(1, ctx, "task has been aborted\n");
+	}
+
+	if (coda_isbusy(ctx->dev)) {
+		coda_dbg(1, ctx, "coda is still busy!!!!\n");
+		return IRQ_NONE;
+	}
+
+	complete(&ctx->completion);
+
+	return IRQ_HANDLED;
+}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-common.c b/drivers/media/platform/chips-media/coda/coda-common.c
--- a/drivers/media/platform/chips-media/coda/coda-common.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/coda-common.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,3362 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Coda multi-standard codec IP
+ *
+ * Copyright (C) 2012 Vista Silicon S.L.
+ *    Javier Martin, <javier.martin@vista-silicon.com>
+ *    Xavier Duret
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/gcd.h>
+#include <linux/genalloc.h>
+#include <linux/idr.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kfifo.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/of.h>
+#include <linux/ratelimit.h>
+#include <linux/reset.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-vmalloc.h>
+
+#include "coda.h"
+#include "imx-vdoa.h"
+
+#define CODA_NAME		"coda"
+
+#define CODADX6_MAX_INSTANCES	4
+#define CODA_MAX_FORMATS	5
+
+#define CODA_ISRAM_SIZE	(2048 * 2)
+
+#define MIN_W 48
+#define MIN_H 16
+
+#define S_ALIGN		1 /* multiple of 2 */
+#define W_ALIGN		1 /* multiple of 2 */
+#define H_ALIGN		1 /* multiple of 2 */
+
+#define fh_to_ctx(__fh)	container_of(__fh, struct coda_ctx, fh)
+
+int coda_debug;
+module_param(coda_debug, int, 0644);
+MODULE_PARM_DESC(coda_debug, "Debug level (0-2)");
+
+static int disable_tiling;
+module_param(disable_tiling, int, 0644);
+MODULE_PARM_DESC(disable_tiling, "Disable tiled frame buffers");
+
+static int disable_vdoa;
+module_param(disable_vdoa, int, 0644);
+MODULE_PARM_DESC(disable_vdoa, "Disable Video Data Order Adapter tiled to raster-scan conversion");
+
+static int enable_bwb = 0;
+module_param(enable_bwb, int, 0644);
+MODULE_PARM_DESC(enable_bwb, "Enable BWB unit for decoding, may crash on certain streams");
+
+void coda_write(struct coda_dev *dev, u32 data, u32 reg)
+{
+	v4l2_dbg(3, coda_debug, &dev->v4l2_dev,
+		 "%s: data=0x%x, reg=0x%x\n", __func__, data, reg);
+	writel(data, dev->regs_base + reg);
+}
+
+unsigned int coda_read(struct coda_dev *dev, u32 reg)
+{
+	u32 data;
+
+	data = readl(dev->regs_base + reg);
+	v4l2_dbg(3, coda_debug, &dev->v4l2_dev,
+		 "%s: data=0x%x, reg=0x%x\n", __func__, data, reg);
+	return data;
+}
+
+void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
+		     struct vb2_v4l2_buffer *buf, unsigned int reg_y)
+{
+	u32 base_y = vb2_dma_contig_plane_dma_addr(&buf->vb2_buf, 0);
+	u32 base_cb, base_cr;
+
+	switch (q_data->fourcc) {
+	case V4L2_PIX_FMT_YUYV:
+		/* Fallthrough: IN -H264-> CODA -NV12 MB-> VDOA -YUYV-> OUT */
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_YUV420:
+	default:
+		base_cb = base_y + q_data->bytesperline * q_data->height;
+		base_cr = base_cb + q_data->bytesperline * q_data->height / 4;
+		break;
+	case V4L2_PIX_FMT_YVU420:
+		/* Switch Cb and Cr for YVU420 format */
+		base_cr = base_y + q_data->bytesperline * q_data->height;
+		base_cb = base_cr + q_data->bytesperline * q_data->height / 4;
+		break;
+	case V4L2_PIX_FMT_YUV422P:
+		base_cb = base_y + q_data->bytesperline * q_data->height;
+		base_cr = base_cb + q_data->bytesperline * q_data->height / 2;
+	}
+
+	coda_write(ctx->dev, base_y, reg_y);
+	coda_write(ctx->dev, base_cb, reg_y + 4);
+	coda_write(ctx->dev, base_cr, reg_y + 8);
+}
+
+#define CODA_CODEC(mode, src_fourcc, dst_fourcc, max_w, max_h) \
+	{ mode, src_fourcc, dst_fourcc, max_w, max_h }
+
+/*
+ * Arrays of codecs supported by each given version of Coda:
+ *  i.MX27 -> codadx6
+ *  i.MX51 -> codahx4
+ *  i.MX53 -> coda7
+ *  i.MX6  -> coda960
+ * Use V4L2_PIX_FMT_YUV420 as placeholder for all supported YUV 4:2:0 variants
+ */
+static const struct coda_codec codadx6_codecs[] = {
+	CODA_CODEC(CODADX6_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264,  720, 576),
+	CODA_CODEC(CODADX6_MODE_ENCODE_MP4,  V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 720, 576),
+};
+
+static const struct coda_codec codahx4_codecs[] = {
+	CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264,   720, 576),
+	CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264,   V4L2_PIX_FMT_YUV420, 1920, 1088),
+	CODA_CODEC(CODA7_MODE_DECODE_MP2,  V4L2_PIX_FMT_MPEG2,  V4L2_PIX_FMT_YUV420, 1920, 1088),
+	CODA_CODEC(CODA7_MODE_DECODE_MP4,  V4L2_PIX_FMT_MPEG4,  V4L2_PIX_FMT_YUV420, 1280, 720),
+};
+
+static const struct coda_codec coda7_codecs[] = {
+	CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264,   1280, 720),
+	CODA_CODEC(CODA7_MODE_ENCODE_MP4,  V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4,  1280, 720),
+	CODA_CODEC(CODA7_MODE_ENCODE_MJPG, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_JPEG,   8192, 8192),
+	CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264,   V4L2_PIX_FMT_YUV420, 1920, 1088),
+	CODA_CODEC(CODA7_MODE_DECODE_MP2,  V4L2_PIX_FMT_MPEG2,  V4L2_PIX_FMT_YUV420, 1920, 1088),
+	CODA_CODEC(CODA7_MODE_DECODE_MP4,  V4L2_PIX_FMT_MPEG4,  V4L2_PIX_FMT_YUV420, 1920, 1088),
+	CODA_CODEC(CODA7_MODE_DECODE_MJPG, V4L2_PIX_FMT_JPEG,   V4L2_PIX_FMT_YUV420, 8192, 8192),
+};
+
+static const struct coda_codec coda9_codecs[] = {
+	CODA_CODEC(CODA9_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264,   1920, 1088),
+	CODA_CODEC(CODA9_MODE_ENCODE_MP4,  V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4,  1920, 1088),
+	CODA_CODEC(CODA9_MODE_ENCODE_MJPG, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_JPEG,   8192, 8192),
+	CODA_CODEC(CODA9_MODE_DECODE_H264, V4L2_PIX_FMT_H264,   V4L2_PIX_FMT_YUV420, 1920, 1088),
+	CODA_CODEC(CODA9_MODE_DECODE_MP2,  V4L2_PIX_FMT_MPEG2,  V4L2_PIX_FMT_YUV420, 1920, 1088),
+	CODA_CODEC(CODA9_MODE_DECODE_MP4,  V4L2_PIX_FMT_MPEG4,  V4L2_PIX_FMT_YUV420, 1920, 1088),
+	CODA_CODEC(CODA9_MODE_DECODE_MJPG, V4L2_PIX_FMT_JPEG,	V4L2_PIX_FMT_YUV420, 8192, 8192),
+};
+
+struct coda_video_device {
+	const char *name;
+	enum coda_inst_type type;
+	const struct coda_context_ops *ops;
+	bool direct;
+	u32 src_formats[CODA_MAX_FORMATS];
+	u32 dst_formats[CODA_MAX_FORMATS];
+};
+
+static const struct coda_video_device coda_bit_encoder = {
+	.name = "coda-video-encoder",
+	.type = CODA_INST_ENCODER,
+	.ops = &coda_bit_encode_ops,
+	.src_formats = {
+		V4L2_PIX_FMT_NV12,
+		V4L2_PIX_FMT_YUV420,
+		V4L2_PIX_FMT_YVU420,
+	},
+	.dst_formats = {
+		V4L2_PIX_FMT_H264,
+		V4L2_PIX_FMT_MPEG4,
+	},
+};
+
+static const struct coda_video_device coda_bit_jpeg_encoder = {
+	.name = "coda-jpeg-encoder",
+	.type = CODA_INST_ENCODER,
+	.ops = &coda_bit_encode_ops,
+	.src_formats = {
+		V4L2_PIX_FMT_NV12,
+		V4L2_PIX_FMT_YUV420,
+		V4L2_PIX_FMT_YVU420,
+		V4L2_PIX_FMT_YUV422P,
+	},
+	.dst_formats = {
+		V4L2_PIX_FMT_JPEG,
+	},
+};
+
+static const struct coda_video_device coda_bit_decoder = {
+	.name = "coda-video-decoder",
+	.type = CODA_INST_DECODER,
+	.ops = &coda_bit_decode_ops,
+	.src_formats = {
+		V4L2_PIX_FMT_H264,
+		V4L2_PIX_FMT_MPEG2,
+		V4L2_PIX_FMT_MPEG4,
+	},
+	.dst_formats = {
+		V4L2_PIX_FMT_NV12,
+		V4L2_PIX_FMT_YUV420,
+		V4L2_PIX_FMT_YVU420,
+		/*
+		 * If V4L2_PIX_FMT_YUYV should be default,
+		 * set_default_params() must be adjusted.
+		 */
+		V4L2_PIX_FMT_YUYV,
+	},
+};
+
+static const struct coda_video_device coda_bit_jpeg_decoder = {
+	.name = "coda-jpeg-decoder",
+	.type = CODA_INST_DECODER,
+	.ops = &coda_bit_decode_ops,
+	.src_formats = {
+		V4L2_PIX_FMT_JPEG,
+	},
+	.dst_formats = {
+		V4L2_PIX_FMT_NV12,
+		V4L2_PIX_FMT_YUV420,
+		V4L2_PIX_FMT_YVU420,
+		V4L2_PIX_FMT_YUV422P,
+	},
+};
+
+static const struct coda_video_device coda9_jpeg_encoder = {
+	.name = "coda-jpeg-encoder",
+	.type = CODA_INST_ENCODER,
+	.ops = &coda9_jpeg_encode_ops,
+	.direct = true,
+	.src_formats = {
+		V4L2_PIX_FMT_NV12,
+		V4L2_PIX_FMT_YUV420,
+		V4L2_PIX_FMT_YVU420,
+		V4L2_PIX_FMT_YUV422P,
+		V4L2_PIX_FMT_GREY,
+	},
+	.dst_formats = {
+		V4L2_PIX_FMT_JPEG,
+	},
+};
+
+static const struct coda_video_device coda9_jpeg_decoder = {
+	.name = "coda-jpeg-decoder",
+	.type = CODA_INST_DECODER,
+	.ops = &coda9_jpeg_decode_ops,
+	.direct = true,
+	.src_formats = {
+		V4L2_PIX_FMT_JPEG,
+	},
+	.dst_formats = {
+		V4L2_PIX_FMT_NV12,
+		V4L2_PIX_FMT_YUV420,
+		V4L2_PIX_FMT_YVU420,
+		V4L2_PIX_FMT_YUV422P,
+	},
+};
+
+static const struct coda_video_device *codadx6_video_devices[] = {
+	&coda_bit_encoder,
+};
+
+static const struct coda_video_device *codahx4_video_devices[] = {
+	&coda_bit_encoder,
+	&coda_bit_decoder,
+};
+
+static const struct coda_video_device *coda7_video_devices[] = {
+	&coda_bit_jpeg_encoder,
+	&coda_bit_jpeg_decoder,
+	&coda_bit_encoder,
+	&coda_bit_decoder,
+};
+
+static const struct coda_video_device *coda9_video_devices[] = {
+	&coda9_jpeg_encoder,
+	&coda9_jpeg_decoder,
+	&coda_bit_encoder,
+	&coda_bit_decoder,
+};
+
+/*
+ * Normalize all supported YUV 4:2:0 formats to the value used in the codec
+ * tables.
+ */
+static u32 coda_format_normalize_yuv(u32 fourcc)
+{
+	switch (fourcc) {
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+	case V4L2_PIX_FMT_YUV422P:
+	case V4L2_PIX_FMT_YUYV:
+		return V4L2_PIX_FMT_YUV420;
+	default:
+		return fourcc;
+	}
+}
+
+static const struct coda_codec *coda_find_codec(struct coda_dev *dev,
+						int src_fourcc, int dst_fourcc)
+{
+	const struct coda_codec *codecs = dev->devtype->codecs;
+	int num_codecs = dev->devtype->num_codecs;
+	int k;
+
+	src_fourcc = coda_format_normalize_yuv(src_fourcc);
+	dst_fourcc = coda_format_normalize_yuv(dst_fourcc);
+	if (src_fourcc == dst_fourcc)
+		return NULL;
+
+	for (k = 0; k < num_codecs; k++) {
+		if (codecs[k].src_fourcc == src_fourcc &&
+		    codecs[k].dst_fourcc == dst_fourcc)
+			break;
+	}
+
+	if (k == num_codecs)
+		return NULL;
+
+	return &codecs[k];
+}
+
+static void coda_get_max_dimensions(struct coda_dev *dev,
+				    const struct coda_codec *codec,
+				    int *max_w, int *max_h)
+{
+	const struct coda_codec *codecs = dev->devtype->codecs;
+	int num_codecs = dev->devtype->num_codecs;
+	unsigned int w, h;
+	int k;
+
+	if (codec) {
+		w = codec->max_w;
+		h = codec->max_h;
+	} else {
+		for (k = 0, w = 0, h = 0; k < num_codecs; k++) {
+			w = max(w, codecs[k].max_w);
+			h = max(h, codecs[k].max_h);
+		}
+	}
+
+	if (max_w)
+		*max_w = w;
+	if (max_h)
+		*max_h = h;
+}
+
+static const struct coda_video_device *to_coda_video_device(struct video_device
+							    *vdev)
+{
+	struct coda_dev *dev = video_get_drvdata(vdev);
+	unsigned int i = vdev - dev->vfd;
+
+	if (i >= dev->devtype->num_vdevs)
+		return NULL;
+
+	return dev->devtype->vdevs[i];
+}
+
+const char *coda_product_name(int product)
+{
+	static char buf[9];
+
+	switch (product) {
+	case CODA_DX6:
+		return "CodaDx6";
+	case CODA_HX4:
+		return "CodaHx4";
+	case CODA_7541:
+		return "CODA7541";
+	case CODA_960:
+		return "CODA960";
+	default:
+		snprintf(buf, sizeof(buf), "(0x%04x)", product);
+		return buf;
+	}
+}
+
+static struct vdoa_data *coda_get_vdoa_data(void)
+{
+	struct device_node *vdoa_node;
+	struct platform_device *vdoa_pdev;
+	struct vdoa_data *vdoa_data = NULL;
+
+	vdoa_node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-vdoa");
+	if (!vdoa_node)
+		return NULL;
+
+	vdoa_pdev = of_find_device_by_node(vdoa_node);
+	if (!vdoa_pdev)
+		goto out;
+
+	vdoa_data = platform_get_drvdata(vdoa_pdev);
+	if (!vdoa_data)
+		vdoa_data = ERR_PTR(-EPROBE_DEFER);
+
+	put_device(&vdoa_pdev->dev);
+out:
+	of_node_put(vdoa_node);
+
+	return vdoa_data;
+}
+
+/*
+ * V4L2 ioctl() operations.
+ */
+static int coda_querycap(struct file *file, void *priv,
+			 struct v4l2_capability *cap)
+{
+	struct coda_ctx *ctx = fh_to_ctx(priv);
+
+	strscpy(cap->driver, CODA_NAME, sizeof(cap->driver));
+	strscpy(cap->card, coda_product_name(ctx->dev->devtype->product),
+		sizeof(cap->card));
+	strscpy(cap->bus_info, "platform:" CODA_NAME, sizeof(cap->bus_info));
+	return 0;
+}
+
+static const u32 coda_formats_420[CODA_MAX_FORMATS] = {
+		V4L2_PIX_FMT_NV12,
+		V4L2_PIX_FMT_YUV420,
+		V4L2_PIX_FMT_YVU420,
+};
+
+static int coda_enum_fmt(struct file *file, void *priv,
+			 struct v4l2_fmtdesc *f)
+{
+	struct video_device *vdev = video_devdata(file);
+	const struct coda_video_device *cvd = to_coda_video_device(vdev);
+	struct coda_ctx *ctx = fh_to_ctx(priv);
+	const u32 *formats;
+
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		formats = cvd->src_formats;
+	else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		struct coda_q_data *q_data_src;
+		struct vb2_queue *src_vq;
+
+		formats = cvd->dst_formats;
+
+		/*
+		 * If the source format is already fixed, only allow the same
+		 * chroma subsampling.
+		 */
+		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+		src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
+					 V4L2_BUF_TYPE_VIDEO_OUTPUT);
+		if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
+		    vb2_is_streaming(src_vq)) {
+			if (ctx->params.jpeg_chroma_subsampling ==
+			    V4L2_JPEG_CHROMA_SUBSAMPLING_420) {
+				formats = coda_formats_420;
+			} else if (ctx->params.jpeg_chroma_subsampling ==
+				   V4L2_JPEG_CHROMA_SUBSAMPLING_422) {
+				f->pixelformat = V4L2_PIX_FMT_YUV422P;
+				return f->index ? -EINVAL : 0;
+			}
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	if (f->index >= CODA_MAX_FORMATS || formats[f->index] == 0)
+		return -EINVAL;
+
+	/* Skip YUYV if the vdoa is not available */
+	if (!ctx->vdoa && f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+	    formats[f->index] == V4L2_PIX_FMT_YUYV)
+		return -EINVAL;
+
+	f->pixelformat = formats[f->index];
+
+	return 0;
+}
+
+static int coda_g_fmt(struct file *file, void *priv,
+		      struct v4l2_format *f)
+{
+	struct coda_q_data *q_data;
+	struct coda_ctx *ctx = fh_to_ctx(priv);
+
+	q_data = get_q_data(ctx, f->type);
+	if (!q_data)
+		return -EINVAL;
+
+	f->fmt.pix.field	= V4L2_FIELD_NONE;
+	f->fmt.pix.pixelformat	= q_data->fourcc;
+	f->fmt.pix.width	= q_data->width;
+	f->fmt.pix.height	= q_data->height;
+	f->fmt.pix.bytesperline = q_data->bytesperline;
+
+	f->fmt.pix.sizeimage	= q_data->sizeimage;
+	f->fmt.pix.colorspace	= ctx->colorspace;
+	f->fmt.pix.xfer_func	= ctx->xfer_func;
+	f->fmt.pix.ycbcr_enc	= ctx->ycbcr_enc;
+	f->fmt.pix.quantization	= ctx->quantization;
+
+	return 0;
+}
+
+static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f)
+{
+	struct coda_q_data *q_data;
+	const u32 *formats;
+	int i;
+
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		formats = ctx->cvd->src_formats;
+	else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		formats = ctx->cvd->dst_formats;
+	else
+		return -EINVAL;
+
+	for (i = 0; i < CODA_MAX_FORMATS; i++) {
+		/* Skip YUYV if the vdoa is not available */
+		if (!ctx->vdoa && f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+		    formats[i] == V4L2_PIX_FMT_YUYV)
+			continue;
+
+		if (formats[i] == f->fmt.pix.pixelformat) {
+			f->fmt.pix.pixelformat = formats[i];
+			return 0;
+		}
+	}
+
+	/* Fall back to currently set pixelformat */
+	q_data = get_q_data(ctx, f->type);
+	f->fmt.pix.pixelformat = q_data->fourcc;
+
+	return 0;
+}
+
+static int coda_try_fmt_vdoa(struct coda_ctx *ctx, struct v4l2_format *f,
+			     bool *use_vdoa)
+{
+	int err;
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (!use_vdoa)
+		return -EINVAL;
+
+	if (!ctx->vdoa) {
+		*use_vdoa = false;
+		return 0;
+	}
+
+	err = vdoa_context_configure(NULL, round_up(f->fmt.pix.width, 16),
+				     f->fmt.pix.height, f->fmt.pix.pixelformat);
+	if (err) {
+		*use_vdoa = false;
+		return 0;
+	}
+
+	*use_vdoa = true;
+	return 0;
+}
+
+static unsigned int coda_estimate_sizeimage(struct coda_ctx *ctx, u32 sizeimage,
+					    u32 width, u32 height)
+{
+	/*
+	 * This is a rough estimate for sensible compressed buffer
+	 * sizes (between 1 and 16 bits per pixel). This could be
+	 * improved by better format specific worst case estimates.
+	 */
+	return round_up(clamp(sizeimage, width * height / 8,
+					 width * height * 2), PAGE_SIZE);
+}
+
+static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
+			struct v4l2_format *f)
+{
+	struct coda_dev *dev = ctx->dev;
+	unsigned int max_w, max_h;
+	enum v4l2_field field;
+
+	field = f->fmt.pix.field;
+	if (field == V4L2_FIELD_ANY)
+		field = V4L2_FIELD_NONE;
+	else if (V4L2_FIELD_NONE != field)
+		return -EINVAL;
+
+	/* V4L2 specification suggests the driver corrects the format struct
+	 * if any of the dimensions is unsupported */
+	f->fmt.pix.field = field;
+
+	coda_get_max_dimensions(dev, codec, &max_w, &max_h);
+	v4l_bound_align_image(&f->fmt.pix.width, MIN_W, max_w, W_ALIGN,
+			      &f->fmt.pix.height, MIN_H, max_h, H_ALIGN,
+			      S_ALIGN);
+
+	switch (f->fmt.pix.pixelformat) {
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+		/*
+		 * Frame stride must be at least multiple of 8,
+		 * but multiple of 16 for h.264 or JPEG 4:2:x
+		 */
+		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
+		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+					f->fmt.pix.height * 3 / 2;
+		break;
+	case V4L2_PIX_FMT_YUYV:
+		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16) * 2;
+		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+					f->fmt.pix.height;
+		break;
+	case V4L2_PIX_FMT_YUV422P:
+		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
+		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+					f->fmt.pix.height * 2;
+		break;
+	case V4L2_PIX_FMT_GREY:
+		/* keep 16 pixel alignment of 8-bit pixel data */
+		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
+		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
+		break;
+	case V4L2_PIX_FMT_JPEG:
+	case V4L2_PIX_FMT_H264:
+	case V4L2_PIX_FMT_MPEG4:
+	case V4L2_PIX_FMT_MPEG2:
+		f->fmt.pix.bytesperline = 0;
+		f->fmt.pix.sizeimage = coda_estimate_sizeimage(ctx,
+							f->fmt.pix.sizeimage,
+							f->fmt.pix.width,
+							f->fmt.pix.height);
+		break;
+	default:
+		BUG();
+	}
+
+	return 0;
+}
+
+static int coda_try_fmt_vid_cap(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct coda_ctx *ctx = fh_to_ctx(priv);
+	const struct coda_q_data *q_data_src;
+	const struct coda_codec *codec;
+	struct vb2_queue *src_vq;
+	int hscale = 0;
+	int vscale = 0;
+	int ret;
+	bool use_vdoa;
+
+	ret = coda_try_pixelformat(ctx, f);
+	if (ret < 0)
+		return ret;
+
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+
+	/*
+	 * If the source format is already fixed, only allow the same output
+	 * resolution. When decoding JPEG images, we also have to make sure to
+	 * use the same chroma subsampling.
+	 */
+	src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	if (vb2_is_streaming(src_vq)) {
+		if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
+		    ctx->dev->devtype->product == CODA_960) {
+			hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width);
+			vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height);
+		}
+		f->fmt.pix.width = q_data_src->width >> hscale;
+		f->fmt.pix.height = q_data_src->height >> vscale;
+
+		if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) {
+			if (ctx->params.jpeg_chroma_subsampling ==
+			    V4L2_JPEG_CHROMA_SUBSAMPLING_420 &&
+			    f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
+				f->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
+			else if (ctx->params.jpeg_chroma_subsampling ==
+				 V4L2_JPEG_CHROMA_SUBSAMPLING_422)
+				f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
+		}
+	}
+
+	f->fmt.pix.colorspace = ctx->colorspace;
+	f->fmt.pix.xfer_func = ctx->xfer_func;
+	f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc;
+	f->fmt.pix.quantization = ctx->quantization;
+
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
+				f->fmt.pix.pixelformat);
+	if (!codec)
+		return -EINVAL;
+
+	ret = coda_try_fmt(ctx, codec, f);
+	if (ret < 0)
+		return ret;
+
+	/* The decoders always write complete macroblocks or MCUs */
+	if (ctx->inst_type == CODA_INST_DECODER) {
+		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16 >> hscale);
+		f->fmt.pix.height = round_up(f->fmt.pix.height, 16 >> vscale);
+		if (codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
+		    f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {
+			f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+					       f->fmt.pix.height * 2;
+		} else {
+			f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+					       f->fmt.pix.height * 3 / 2;
+		}
+
+		ret = coda_try_fmt_vdoa(ctx, f, &use_vdoa);
+		if (ret < 0)
+			return ret;
+
+		if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
+			if (!use_vdoa)
+				return -EINVAL;
+
+			f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16) * 2;
+			f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
+				f->fmt.pix.height;
+		}
+	}
+
+	return 0;
+}
+
+static void coda_set_default_colorspace(struct v4l2_pix_format *fmt)
+{
+	enum v4l2_colorspace colorspace;
+
+	if (fmt->pixelformat == V4L2_PIX_FMT_JPEG)
+		colorspace = V4L2_COLORSPACE_JPEG;
+	else if (fmt->width <= 720 && fmt->height <= 576)
+		colorspace = V4L2_COLORSPACE_SMPTE170M;
+	else
+		colorspace = V4L2_COLORSPACE_REC709;
+
+	fmt->colorspace = colorspace;
+	fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+	fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	fmt->quantization = V4L2_QUANTIZATION_DEFAULT;
+}
+
+static int coda_try_fmt_vid_out(struct file *file, void *priv,
+				struct v4l2_format *f)
+{
+	struct coda_ctx *ctx = fh_to_ctx(priv);
+	struct coda_dev *dev = ctx->dev;
+	const struct coda_q_data *q_data_dst;
+	const struct coda_codec *codec;
+	int ret;
+
+	ret = coda_try_pixelformat(ctx, f);
+	if (ret < 0)
+		return ret;
+
+	if (f->fmt.pix.colorspace == V4L2_COLORSPACE_DEFAULT)
+		coda_set_default_colorspace(&f->fmt.pix);
+
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	codec = coda_find_codec(dev, f->fmt.pix.pixelformat, q_data_dst->fourcc);
+
+	return coda_try_fmt(ctx, codec, f);
+}
+
+static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f,
+		      struct v4l2_rect *r)
+{
+	struct coda_q_data *q_data;
+	struct vb2_queue *vq;
+
+	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+	if (!vq)
+		return -EINVAL;
+
+	q_data = get_q_data(ctx, f->type);
+	if (!q_data)
+		return -EINVAL;
+
+	if (vb2_is_busy(vq)) {
+		v4l2_err(&ctx->dev->v4l2_dev, "%s: %s queue busy: %d\n",
+			 __func__, v4l2_type_names[f->type], vq->num_buffers);
+		return -EBUSY;
+	}
+
+	q_data->fourcc = f->fmt.pix.pixelformat;
+	q_data->width = f->fmt.pix.width;
+	q_data->height = f->fmt.pix.height;
+	q_data->bytesperline = f->fmt.pix.bytesperline;
+	q_data->sizeimage = f->fmt.pix.sizeimage;
+	if (r) {
+		q_data->rect = *r;
+	} else {
+		q_data->rect.left = 0;
+		q_data->rect.top = 0;
+		q_data->rect.width = f->fmt.pix.width;
+		q_data->rect.height = f->fmt.pix.height;
+	}
+
+	switch (f->fmt.pix.pixelformat) {
+	case V4L2_PIX_FMT_YUYV:
+		ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
+		break;
+	case V4L2_PIX_FMT_NV12:
+		if (!disable_tiling && ctx->use_bit &&
+		    ctx->dev->devtype->product == CODA_960) {
+			ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
+			break;
+		}
+		fallthrough;
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_YVU420:
+	case V4L2_PIX_FMT_YUV422P:
+		ctx->tiled_map_type = GDI_LINEAR_FRAME_MAP;
+		break;
+	default:
+		break;
+	}
+
+	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP &&
+	    !coda_try_fmt_vdoa(ctx, f, &ctx->use_vdoa) &&
+	    ctx->use_vdoa)
+		vdoa_context_configure(ctx->vdoa,
+				       round_up(f->fmt.pix.width, 16),
+				       f->fmt.pix.height,
+				       f->fmt.pix.pixelformat);
+	else
+		ctx->use_vdoa = false;
+
+	coda_dbg(1, ctx, "Setting %s format, wxh: %dx%d, fmt: %4.4s %c\n",
+		 v4l2_type_names[f->type], q_data->width, q_data->height,
+		 (char *)&q_data->fourcc,
+		 (ctx->tiled_map_type == GDI_LINEAR_FRAME_MAP) ? 'L' : 'T');
+
+	return 0;
+}
+
+static int coda_s_fmt_vid_cap(struct file *file, void *priv,
+			      struct v4l2_format *f)
+{
+	struct coda_ctx *ctx = fh_to_ctx(priv);
+	struct coda_q_data *q_data_src;
+	const struct coda_codec *codec;
+	struct v4l2_rect r;
+	int hscale = 0;
+	int vscale = 0;
+	int ret;
+
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+
+	if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
+	    ctx->dev->devtype->product == CODA_960) {
+		hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width);
+		vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height);
+	}
+
+	ret = coda_try_fmt_vid_cap(file, priv, f);
+	if (ret)
+		return ret;
+
+	r.left = 0;
+	r.top = 0;
+	r.width = q_data_src->width >> hscale;
+	r.height = q_data_src->height >> vscale;
+
+	ret = coda_s_fmt(ctx, f, &r);
+	if (ret)
+		return ret;
+
+	if (ctx->inst_type != CODA_INST_ENCODER)
+		return 0;
+
+	/* Setting the coded format determines the selected codec */
+	codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
+				f->fmt.pix.pixelformat);
+	if (!codec) {
+		v4l2_err(&ctx->dev->v4l2_dev, "failed to determine codec\n");
+		return -EINVAL;
+	}
+	ctx->codec = codec;
+
+	ctx->colorspace = f->fmt.pix.colorspace;
+	ctx->xfer_func = f->fmt.pix.xfer_func;
+	ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
+	ctx->quantization = f->fmt.pix.quantization;
+
+	return 0;
+}
+
+static int coda_s_fmt_vid_out(struct file *file, void *priv,
+			      struct v4l2_format *f)
+{
+	struct coda_ctx *ctx = fh_to_ctx(priv);
+	const struct coda_codec *codec;
+	struct v4l2_format f_cap;
+	struct vb2_queue *dst_vq;
+	int ret;
+
+	ret = coda_try_fmt_vid_out(file, priv, f);
+	if (ret)
+		return ret;
+
+	ret = coda_s_fmt(ctx, f, NULL);
+	if (ret)
+		return ret;
+
+	ctx->colorspace = f->fmt.pix.colorspace;
+	ctx->xfer_func = f->fmt.pix.xfer_func;
+	ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
+	ctx->quantization = f->fmt.pix.quantization;
+
+	if (ctx->inst_type != CODA_INST_DECODER)
+		return 0;
+
+	/* Setting the coded format determines the selected codec */
+	codec = coda_find_codec(ctx->dev, f->fmt.pix.pixelformat,
+				V4L2_PIX_FMT_YUV420);
+	if (!codec) {
+		v4l2_err(&ctx->dev->v4l2_dev, "failed to determine codec\n");
+		return -EINVAL;
+	}
+	ctx->codec = codec;
+
+	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	if (!dst_vq)
+		return -EINVAL;
+
+	/*
+	 * Setting the capture queue format is not possible while the capture
+	 * queue is still busy. This is not an error, but the user will have to
+	 * make sure themselves that the capture format is set correctly before
+	 * starting the output queue again.
+	 */
+	if (vb2_is_busy(dst_vq))
+		return 0;
+
+	memset(&f_cap, 0, sizeof(f_cap));
+	f_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	coda_g_fmt(file, priv, &f_cap);
+	f_cap.fmt.pix.width = f->fmt.pix.width;
+	f_cap.fmt.pix.height = f->fmt.pix.height;
+
+	return coda_s_fmt_vid_cap(file, priv, &f_cap);
+}
+
+static int coda_reqbufs(struct file *file, void *priv,
+			struct v4l2_requestbuffers *rb)
+{
+	struct coda_ctx *ctx = fh_to_ctx(priv);
+	int ret;
+
+	ret = v4l2_m2m_reqbufs(file, ctx->fh.m2m_ctx, rb);
+	if (ret)
+		return ret;
+
+	/*
+	 * Allow to allocate instance specific per-context buffers, such as
+	 * bitstream ringbuffer, slice buffer, work buffer, etc. if needed.
+	 */
+	if (rb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && ctx->ops->reqbufs)
+		return ctx->ops->reqbufs(ctx, rb);
+
+	return 0;
+}
+
+static int coda_qbuf(struct file *file, void *priv,
+		     struct v4l2_buffer *buf)
+{
+	struct coda_ctx *ctx = fh_to_ctx(priv);
+
+	if (ctx->inst_type == CODA_INST_DECODER &&
+	    buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		buf->flags &= ~V4L2_BUF_FLAG_LAST;
+
+	return v4l2_m2m_qbuf(file, ctx->fh.m2m_ctx, buf);
+}
+
+static int coda_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+	struct coda_ctx *ctx = fh_to_ctx(priv);
+	int ret;
+
+	ret = v4l2_m2m_dqbuf(file, ctx->fh.m2m_ctx, buf);
+
+	if (ctx->inst_type == CODA_INST_DECODER &&
+	    buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		buf->flags &= ~V4L2_BUF_FLAG_LAST;
+
+	return ret;
+}
+
+void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
+		       enum vb2_buffer_state state)
+{
+	const struct v4l2_event eos_event = {
+		.type = V4L2_EVENT_EOS
+	};
+
+	if (buf->flags & V4L2_BUF_FLAG_LAST)
+		v4l2_event_queue_fh(&ctx->fh, &eos_event);
+
+	v4l2_m2m_buf_done(buf, state);
+}
+
+static int coda_g_selection(struct file *file, void *fh,
+			    struct v4l2_selection *s)
+{
+	struct coda_ctx *ctx = fh_to_ctx(fh);
+	struct coda_q_data *q_data;
+	struct v4l2_rect r, *rsel;
+
+	q_data = get_q_data(ctx, s->type);
+	if (!q_data)
+		return -EINVAL;
+
+	r.left = 0;
+	r.top = 0;
+	r.width = q_data->width;
+	r.height = q_data->height;
+	rsel = &q_data->rect;
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+		rsel = &r;
+		fallthrough;
+	case V4L2_SEL_TGT_CROP:
+		if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+		    ctx->inst_type == CODA_INST_DECODER)
+			return -EINVAL;
+		break;
+	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+	case V4L2_SEL_TGT_COMPOSE_PADDED:
+		rsel = &r;
+		fallthrough;
+	case V4L2_SEL_TGT_COMPOSE:
+	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+		if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+		    ctx->inst_type == CODA_INST_ENCODER)
+			return -EINVAL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	s->r = *rsel;
+
+	return 0;
+}
+
+static int coda_s_selection(struct file *file, void *fh,
+			    struct v4l2_selection *s)
+{
+	struct coda_ctx *ctx = fh_to_ctx(fh);
+	struct coda_q_data *q_data;
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_CROP:
+		if (ctx->inst_type == CODA_INST_ENCODER &&
+		    s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+			q_data = get_q_data(ctx, s->type);
+			if (!q_data)
+				return -EINVAL;
+
+			s->r.left = 0;
+			s->r.top = 0;
+			s->r.width = clamp(s->r.width, 2U, q_data->width);
+			s->r.height = clamp(s->r.height, 2U, q_data->height);
+
+			if (s->flags & V4L2_SEL_FLAG_LE) {
+				s->r.width = round_up(s->r.width, 2);
+				s->r.height = round_up(s->r.height, 2);
+			} else {
+				s->r.width = round_down(s->r.width, 2);
+				s->r.height = round_down(s->r.height, 2);
+			}
+
+			q_data->rect = s->r;
+
+			coda_dbg(1, ctx, "Setting crop rectangle: %dx%d\n",
+				 s->r.width, s->r.height);
+
+			return 0;
+		}
+		fallthrough;
+	case V4L2_SEL_TGT_NATIVE_SIZE:
+	case V4L2_SEL_TGT_COMPOSE:
+		return coda_g_selection(file, fh, s);
+	default:
+		/* v4l2-compliance expects this to fail for read-only targets */
+		return -EINVAL;
+	}
+}
+
+static void coda_wake_up_capture_queue(struct coda_ctx *ctx)
+{
+	struct vb2_queue *dst_vq;
+
+	coda_dbg(1, ctx, "waking up capture queue\n");
+
+	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	dst_vq->last_buffer_dequeued = true;
+	wake_up(&dst_vq->done_wq);
+}
+
+static int coda_encoder_cmd(struct file *file, void *fh,
+			    struct v4l2_encoder_cmd *ec)
+{
+	struct coda_ctx *ctx = fh_to_ctx(fh);
+	struct vb2_v4l2_buffer *buf;
+	int ret;
+
+	ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec);
+	if (ret < 0)
+		return ret;
+
+	mutex_lock(&ctx->wakeup_mutex);
+	buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
+	if (buf) {
+		/*
+		 * If the last output buffer is still on the queue, make sure
+		 * that decoder finish_run will see the last flag and report it
+		 * to userspace.
+		 */
+		buf->flags |= V4L2_BUF_FLAG_LAST;
+	} else {
+		/* Set the stream-end flag on this context */
+		ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
+
+		/*
+		 * If the last output buffer has already been taken from the
+		 * queue, wake up the capture queue and signal end of stream
+		 * via the -EPIPE mechanism.
+		 */
+		coda_wake_up_capture_queue(ctx);
+	}
+	mutex_unlock(&ctx->wakeup_mutex);
+
+	return 0;
+}
+
+static bool coda_mark_last_meta(struct coda_ctx *ctx)
+{
+	struct coda_buffer_meta *meta;
+
+	coda_dbg(1, ctx, "marking last meta\n");
+
+	spin_lock(&ctx->buffer_meta_lock);
+	if (list_empty(&ctx->buffer_meta_list)) {
+		spin_unlock(&ctx->buffer_meta_lock);
+		return false;
+	}
+
+	meta = list_last_entry(&ctx->buffer_meta_list, struct coda_buffer_meta,
+			       list);
+	meta->last = true;
+
+	spin_unlock(&ctx->buffer_meta_lock);
+	return true;
+}
+
+static bool coda_mark_last_dst_buf(struct coda_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *buf;
+	struct vb2_buffer *dst_vb;
+	struct vb2_queue *dst_vq;
+	unsigned long flags;
+
+	coda_dbg(1, ctx, "marking last capture buffer\n");
+
+	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	spin_lock_irqsave(&dst_vq->done_lock, flags);
+	if (list_empty(&dst_vq->done_list)) {
+		spin_unlock_irqrestore(&dst_vq->done_lock, flags);
+		return false;
+	}
+
+	dst_vb = list_last_entry(&dst_vq->done_list, struct vb2_buffer,
+				 done_entry);
+	buf = to_vb2_v4l2_buffer(dst_vb);
+	buf->flags |= V4L2_BUF_FLAG_LAST;
+
+	spin_unlock_irqrestore(&dst_vq->done_lock, flags);
+	return true;
+}
+
+static int coda_decoder_cmd(struct file *file, void *fh,
+			    struct v4l2_decoder_cmd *dc)
+{
+	struct coda_ctx *ctx = fh_to_ctx(fh);
+	struct coda_dev *dev = ctx->dev;
+	struct vb2_v4l2_buffer *buf;
+	struct vb2_queue *dst_vq;
+	bool stream_end;
+	bool wakeup;
+	int ret;
+
+	ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc);
+	if (ret < 0)
+		return ret;
+
+	switch (dc->cmd) {
+	case V4L2_DEC_CMD_START:
+		mutex_lock(&dev->coda_mutex);
+		mutex_lock(&ctx->bitstream_mutex);
+		coda_bitstream_flush(ctx);
+		dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
+					 V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		vb2_clear_last_buffer_dequeued(dst_vq);
+		ctx->bit_stream_param &= ~CODA_BIT_STREAM_END_FLAG;
+		coda_fill_bitstream(ctx, NULL);
+		mutex_unlock(&ctx->bitstream_mutex);
+		mutex_unlock(&dev->coda_mutex);
+		break;
+	case V4L2_DEC_CMD_STOP:
+		stream_end = false;
+		wakeup = false;
+
+		mutex_lock(&ctx->wakeup_mutex);
+
+		buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
+		if (buf) {
+			coda_dbg(1, ctx, "marking last pending buffer\n");
+
+			/* Mark last buffer */
+			buf->flags |= V4L2_BUF_FLAG_LAST;
+
+			if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) == 0) {
+				coda_dbg(1, ctx, "all remaining buffers queued\n");
+				stream_end = true;
+			}
+		} else {
+			if (ctx->use_bit)
+				if (coda_mark_last_meta(ctx))
+					stream_end = true;
+				else
+					wakeup = true;
+			else
+				if (!coda_mark_last_dst_buf(ctx))
+					wakeup = true;
+		}
+
+		if (stream_end) {
+			coda_dbg(1, ctx, "all remaining buffers queued\n");
+
+			/* Set the stream-end flag on this context */
+			coda_bit_stream_end_flag(ctx);
+			ctx->hold = false;
+			v4l2_m2m_try_schedule(ctx->fh.m2m_ctx);
+		}
+
+		if (wakeup) {
+			/* If there is no buffer in flight, wake up */
+			coda_wake_up_capture_queue(ctx);
+		}
+
+		mutex_unlock(&ctx->wakeup_mutex);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int coda_enum_framesizes(struct file *file, void *fh,
+				struct v4l2_frmsizeenum *fsize)
+{
+	struct coda_ctx *ctx = fh_to_ctx(fh);
+	struct coda_q_data *q_data_dst;
+	const struct coda_codec *codec;
+
+	if (fsize->index)
+		return -EINVAL;
+
+	if (coda_format_normalize_yuv(fsize->pixel_format) ==
+	    V4L2_PIX_FMT_YUV420) {
+		q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		codec = coda_find_codec(ctx->dev, fsize->pixel_format,
+					q_data_dst->fourcc);
+	} else {
+		codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420,
+					fsize->pixel_format);
+	}
+	if (!codec)
+		return -EINVAL;
+
+	fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
+	fsize->stepwise.min_width = MIN_W;
+	fsize->stepwise.max_width = codec->max_w;
+	fsize->stepwise.step_width = 1;
+	fsize->stepwise.min_height = MIN_H;
+	fsize->stepwise.max_height = codec->max_h;
+	fsize->stepwise.step_height = 1;
+
+	return 0;
+}
+
+static int coda_enum_frameintervals(struct file *file, void *fh,
+				    struct v4l2_frmivalenum *f)
+{
+	struct coda_ctx *ctx = fh_to_ctx(fh);
+	struct coda_q_data *q_data;
+	const struct coda_codec *codec;
+
+	if (f->index)
+		return -EINVAL;
+
+	/* Disallow YUYV if the vdoa is not available */
+	if (!ctx->vdoa && f->pixel_format == V4L2_PIX_FMT_YUYV)
+		return -EINVAL;
+
+	if (coda_format_normalize_yuv(f->pixel_format) == V4L2_PIX_FMT_YUV420) {
+		q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+		codec = coda_find_codec(ctx->dev, f->pixel_format,
+					q_data->fourcc);
+	} else {
+		codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420,
+					f->pixel_format);
+	}
+	if (!codec)
+		return -EINVAL;
+
+	if (f->width < MIN_W || f->width > codec->max_w ||
+	    f->height < MIN_H || f->height > codec->max_h)
+		return -EINVAL;
+
+	f->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
+	f->stepwise.min.numerator = 1;
+	f->stepwise.min.denominator = 65535;
+	f->stepwise.max.numerator = 65536;
+	f->stepwise.max.denominator = 1;
+	f->stepwise.step.numerator = 1;
+	f->stepwise.step.denominator = 1;
+
+	return 0;
+}
+
+static int coda_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct coda_ctx *ctx = fh_to_ctx(fh);
+	struct v4l2_fract *tpf;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		return -EINVAL;
+
+	a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+	tpf = &a->parm.output.timeperframe;
+	tpf->denominator = ctx->params.framerate & CODA_FRATE_RES_MASK;
+	tpf->numerator = 1 + (ctx->params.framerate >>
+			      CODA_FRATE_DIV_OFFSET);
+
+	return 0;
+}
+
+/*
+ * Approximate timeperframe v4l2_fract with values that can be written
+ * into the 16-bit CODA_FRATE_DIV and CODA_FRATE_RES fields.
+ */
+static void coda_approximate_timeperframe(struct v4l2_fract *timeperframe)
+{
+	struct v4l2_fract s = *timeperframe;
+	struct v4l2_fract f0;
+	struct v4l2_fract f1 = { 1, 0 };
+	struct v4l2_fract f2 = { 0, 1 };
+	unsigned int i, div, s_denominator;
+
+	/* Lower bound is 1/65535 */
+	if (s.numerator == 0 || s.denominator / s.numerator > 65535) {
+		timeperframe->numerator = 1;
+		timeperframe->denominator = 65535;
+		return;
+	}
+
+	/* Upper bound is 65536/1 */
+	if (s.denominator == 0 || s.numerator / s.denominator > 65536) {
+		timeperframe->numerator = 65536;
+		timeperframe->denominator = 1;
+		return;
+	}
+
+	/* Reduce fraction to lowest terms */
+	div = gcd(s.numerator, s.denominator);
+	if (div > 1) {
+		s.numerator /= div;
+		s.denominator /= div;
+	}
+
+	if (s.numerator <= 65536 && s.denominator < 65536) {
+		*timeperframe = s;
+		return;
+	}
+
+	/* Find successive convergents from continued fraction expansion */
+	while (f2.numerator <= 65536 && f2.denominator < 65536) {
+		f0 = f1;
+		f1 = f2;
+
+		/* Stop when f2 exactly equals timeperframe */
+		if (s.numerator == 0)
+			break;
+
+		i = s.denominator / s.numerator;
+
+		f2.numerator = f0.numerator + i * f1.numerator;
+		f2.denominator = f0.denominator + i * f2.denominator;
+
+		s_denominator = s.numerator;
+		s.numerator = s.denominator % s.numerator;
+		s.denominator = s_denominator;
+	}
+
+	*timeperframe = f1;
+}
+
+static uint32_t coda_timeperframe_to_frate(struct v4l2_fract *timeperframe)
+{
+	return ((timeperframe->numerator - 1) << CODA_FRATE_DIV_OFFSET) |
+		timeperframe->denominator;
+}
+
+static int coda_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct coda_ctx *ctx = fh_to_ctx(fh);
+	struct v4l2_fract *tpf;
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		return -EINVAL;
+
+	a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+	tpf = &a->parm.output.timeperframe;
+	coda_approximate_timeperframe(tpf);
+	ctx->params.framerate = coda_timeperframe_to_frate(tpf);
+	ctx->params.framerate_changed = true;
+
+	return 0;
+}
+
+static int coda_subscribe_event(struct v4l2_fh *fh,
+				const struct v4l2_event_subscription *sub)
+{
+	struct coda_ctx *ctx = fh_to_ctx(fh);
+
+	switch (sub->type) {
+	case V4L2_EVENT_EOS:
+		return v4l2_event_subscribe(fh, sub, 0, NULL);
+	case V4L2_EVENT_SOURCE_CHANGE:
+		if (ctx->inst_type == CODA_INST_DECODER)
+			return v4l2_event_subscribe(fh, sub, 0, NULL);
+		else
+			return -EINVAL;
+	default:
+		return v4l2_ctrl_subscribe_event(fh, sub);
+	}
+}
+
+static const struct v4l2_ioctl_ops coda_ioctl_ops = {
+	.vidioc_querycap	= coda_querycap,
+
+	.vidioc_enum_fmt_vid_cap = coda_enum_fmt,
+	.vidioc_g_fmt_vid_cap	= coda_g_fmt,
+	.vidioc_try_fmt_vid_cap	= coda_try_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap	= coda_s_fmt_vid_cap,
+
+	.vidioc_enum_fmt_vid_out = coda_enum_fmt,
+	.vidioc_g_fmt_vid_out	= coda_g_fmt,
+	.vidioc_try_fmt_vid_out	= coda_try_fmt_vid_out,
+	.vidioc_s_fmt_vid_out	= coda_s_fmt_vid_out,
+
+	.vidioc_reqbufs		= coda_reqbufs,
+	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
+
+	.vidioc_qbuf		= coda_qbuf,
+	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
+	.vidioc_dqbuf		= coda_dqbuf,
+	.vidioc_create_bufs	= v4l2_m2m_ioctl_create_bufs,
+	.vidioc_prepare_buf	= v4l2_m2m_ioctl_prepare_buf,
+
+	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff	= v4l2_m2m_ioctl_streamoff,
+
+	.vidioc_g_selection	= coda_g_selection,
+	.vidioc_s_selection	= coda_s_selection,
+
+	.vidioc_try_encoder_cmd	= v4l2_m2m_ioctl_try_encoder_cmd,
+	.vidioc_encoder_cmd	= coda_encoder_cmd,
+	.vidioc_try_decoder_cmd	= v4l2_m2m_ioctl_try_decoder_cmd,
+	.vidioc_decoder_cmd	= coda_decoder_cmd,
+
+	.vidioc_g_parm		= coda_g_parm,
+	.vidioc_s_parm		= coda_s_parm,
+
+	.vidioc_enum_framesizes	= coda_enum_framesizes,
+	.vidioc_enum_frameintervals = coda_enum_frameintervals,
+
+	.vidioc_subscribe_event = coda_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+/*
+ * Mem-to-mem operations.
+ */
+
+static void coda_device_run(void *m2m_priv)
+{
+	struct coda_ctx *ctx = m2m_priv;
+	struct coda_dev *dev = ctx->dev;
+
+	queue_work(dev->workqueue, &ctx->pic_run_work);
+}
+
+static void coda_pic_run_work(struct work_struct *work)
+{
+	struct coda_ctx *ctx = container_of(work, struct coda_ctx, pic_run_work);
+	struct coda_dev *dev = ctx->dev;
+	int ret;
+
+	mutex_lock(&ctx->buffer_mutex);
+	mutex_lock(&dev->coda_mutex);
+
+	ret = ctx->ops->prepare_run(ctx);
+	if (ret < 0 && ctx->inst_type == CODA_INST_DECODER)
+		goto out;
+
+	if (!wait_for_completion_timeout(&ctx->completion,
+					 msecs_to_jiffies(1000))) {
+		if (ctx->use_bit) {
+			dev_err(dev->dev, "CODA PIC_RUN timeout\n");
+
+			ctx->hold = true;
+
+			coda_hw_reset(ctx);
+		}
+
+		if (ctx->ops->run_timeout)
+			ctx->ops->run_timeout(ctx);
+	} else {
+		ctx->ops->finish_run(ctx);
+	}
+
+	if ((ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) &&
+	    ctx->ops->seq_end_work)
+		queue_work(dev->workqueue, &ctx->seq_end_work);
+
+out:
+	mutex_unlock(&dev->coda_mutex);
+	mutex_unlock(&ctx->buffer_mutex);
+
+	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
+}
+
+static int coda_job_ready(void *m2m_priv)
+{
+	struct coda_ctx *ctx = m2m_priv;
+	int src_bufs = v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx);
+
+	/*
+	 * For both 'P' and 'key' frame cases 1 picture
+	 * and 1 frame are needed. In the decoder case,
+	 * the compressed frame can be in the bitstream.
+	 */
+	if (!src_bufs && ctx->inst_type != CODA_INST_DECODER) {
+		coda_dbg(1, ctx, "not ready: not enough vid-out buffers.\n");
+		return 0;
+	}
+
+	if (!v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) {
+		coda_dbg(1, ctx, "not ready: not enough vid-cap buffers.\n");
+		return 0;
+	}
+
+	if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) {
+		bool stream_end = ctx->bit_stream_param &
+				  CODA_BIT_STREAM_END_FLAG;
+		int num_metas = ctx->num_metas;
+		struct coda_buffer_meta *meta;
+		unsigned int count;
+
+		count = hweight32(ctx->frm_dis_flg);
+		if (ctx->use_vdoa && count >= (ctx->num_internal_frames - 1)) {
+			coda_dbg(1, ctx,
+				 "not ready: all internal buffers in use: %d/%d (0x%x)",
+				 count, ctx->num_internal_frames,
+				 ctx->frm_dis_flg);
+			return 0;
+		}
+
+		if (ctx->hold && !src_bufs) {
+			coda_dbg(1, ctx,
+				 "not ready: on hold for more buffers.\n");
+			return 0;
+		}
+
+		if (!stream_end && (num_metas + src_bufs) < 2) {
+			coda_dbg(1, ctx,
+				 "not ready: need 2 buffers available (queue:%d + bitstream:%d)\n",
+				 num_metas, src_bufs);
+			return 0;
+		}
+
+		meta = list_first_entry(&ctx->buffer_meta_list,
+					struct coda_buffer_meta, list);
+		if (!coda_bitstream_can_fetch_past(ctx, meta->end) &&
+		    !stream_end) {
+			coda_dbg(1, ctx,
+				 "not ready: not enough bitstream data to read past %u (%u)\n",
+				 meta->end, ctx->bitstream_fifo.kfifo.in);
+			return 0;
+		}
+	}
+
+	if (ctx->aborting) {
+		coda_dbg(1, ctx, "not ready: aborting\n");
+		return 0;
+	}
+
+	coda_dbg(2, ctx, "job ready\n");
+
+	return 1;
+}
+
+static void coda_job_abort(void *priv)
+{
+	struct coda_ctx *ctx = priv;
+
+	ctx->aborting = 1;
+
+	coda_dbg(1, ctx, "job abort\n");
+}
+
+static const struct v4l2_m2m_ops coda_m2m_ops = {
+	.device_run	= coda_device_run,
+	.job_ready	= coda_job_ready,
+	.job_abort	= coda_job_abort,
+};
+
+static void set_default_params(struct coda_ctx *ctx)
+{
+	unsigned int max_w, max_h, usize, csize;
+
+	ctx->codec = coda_find_codec(ctx->dev, ctx->cvd->src_formats[0],
+				     ctx->cvd->dst_formats[0]);
+	max_w = min(ctx->codec->max_w, 1920U);
+	max_h = min(ctx->codec->max_h, 1088U);
+	usize = max_w * max_h * 3 / 2;
+	csize = coda_estimate_sizeimage(ctx, usize, max_w, max_h);
+
+	ctx->params.codec_mode = ctx->codec->mode;
+	if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_JPEG ||
+	    ctx->cvd->dst_formats[0] == V4L2_PIX_FMT_JPEG) {
+		ctx->colorspace = V4L2_COLORSPACE_SRGB;
+		ctx->xfer_func = V4L2_XFER_FUNC_SRGB;
+		ctx->ycbcr_enc = V4L2_YCBCR_ENC_601;
+		ctx->quantization = V4L2_QUANTIZATION_FULL_RANGE;
+	} else {
+		ctx->colorspace = V4L2_COLORSPACE_REC709;
+		ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+		ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+		ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
+	}
+	ctx->params.framerate = 30;
+
+	/* Default formats for output and input queues */
+	ctx->q_data[V4L2_M2M_SRC].fourcc = ctx->cvd->src_formats[0];
+	ctx->q_data[V4L2_M2M_DST].fourcc = ctx->cvd->dst_formats[0];
+	ctx->q_data[V4L2_M2M_SRC].width = max_w;
+	ctx->q_data[V4L2_M2M_SRC].height = max_h;
+	ctx->q_data[V4L2_M2M_DST].width = max_w;
+	ctx->q_data[V4L2_M2M_DST].height = max_h;
+	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_YUV420) {
+		ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w;
+		ctx->q_data[V4L2_M2M_SRC].sizeimage = usize;
+		ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
+		ctx->q_data[V4L2_M2M_DST].sizeimage = csize;
+	} else {
+		ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
+		ctx->q_data[V4L2_M2M_SRC].sizeimage = csize;
+		ctx->q_data[V4L2_M2M_DST].bytesperline = max_w;
+		ctx->q_data[V4L2_M2M_DST].sizeimage = usize;
+	}
+	ctx->q_data[V4L2_M2M_SRC].rect.width = max_w;
+	ctx->q_data[V4L2_M2M_SRC].rect.height = max_h;
+	ctx->q_data[V4L2_M2M_DST].rect.width = max_w;
+	ctx->q_data[V4L2_M2M_DST].rect.height = max_h;
+
+	/*
+	 * Since the RBC2AXI logic only supports a single chroma plane,
+	 * macroblock tiling only works for to NV12 pixel format.
+	 */
+	ctx->tiled_map_type = GDI_LINEAR_FRAME_MAP;
+}
+
+/*
+ * Queue operations
+ */
+static int coda_queue_setup(struct vb2_queue *vq,
+				unsigned int *nbuffers, unsigned int *nplanes,
+				unsigned int sizes[], struct device *alloc_devs[])
+{
+	struct coda_ctx *ctx = vb2_get_drv_priv(vq);
+	struct coda_q_data *q_data;
+	unsigned int size;
+
+	q_data = get_q_data(ctx, vq->type);
+	size = q_data->sizeimage;
+
+	if (*nplanes)
+		return sizes[0] < size ? -EINVAL : 0;
+
+	*nplanes = 1;
+	sizes[0] = size;
+
+	coda_dbg(1, ctx, "get %d buffer(s) of size %d each.\n", *nbuffers,
+		 size);
+
+	return 0;
+}
+
+static int coda_buf_prepare(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct coda_q_data *q_data;
+
+	q_data = get_q_data(ctx, vb->vb2_queue->type);
+	if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+		if (vbuf->field == V4L2_FIELD_ANY)
+			vbuf->field = V4L2_FIELD_NONE;
+		if (vbuf->field != V4L2_FIELD_NONE) {
+			v4l2_warn(&ctx->dev->v4l2_dev,
+				  "%s field isn't supported\n", __func__);
+			return -EINVAL;
+		}
+	}
+
+	if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
+		v4l2_warn(&ctx->dev->v4l2_dev,
+			  "%s data will not fit into plane (%lu < %lu)\n",
+			  __func__, vb2_plane_size(vb, 0),
+			  (long)q_data->sizeimage);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void coda_update_menu_ctrl(struct v4l2_ctrl *ctrl, int value)
+{
+	if (!ctrl)
+		return;
+
+	v4l2_ctrl_lock(ctrl);
+
+	/*
+	 * Extend the control range if the parsed stream contains a known but
+	 * unsupported value or level.
+	 */
+	if (value > ctrl->maximum) {
+		__v4l2_ctrl_modify_range(ctrl, ctrl->minimum, value,
+			ctrl->menu_skip_mask & ~(1 << value),
+			ctrl->default_value);
+	} else if (value < ctrl->minimum) {
+		__v4l2_ctrl_modify_range(ctrl, value, ctrl->maximum,
+			ctrl->menu_skip_mask & ~(1 << value),
+			ctrl->default_value);
+	}
+
+	__v4l2_ctrl_s_ctrl(ctrl, value);
+
+	v4l2_ctrl_unlock(ctrl);
+}
+
+void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc,
+				     u8 level_idc)
+{
+	const char * const *profile_names;
+	const char * const *level_names;
+	struct v4l2_ctrl *profile_ctrl;
+	struct v4l2_ctrl *level_ctrl;
+	const char *codec_name;
+	u32 profile_cid;
+	u32 level_cid;
+	int profile;
+	int level;
+
+	switch (ctx->codec->src_fourcc) {
+	case V4L2_PIX_FMT_H264:
+		codec_name = "H264";
+		profile_cid = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
+		level_cid = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
+		profile_ctrl = ctx->h264_profile_ctrl;
+		level_ctrl = ctx->h264_level_ctrl;
+		profile = coda_h264_profile(profile_idc);
+		level = coda_h264_level(level_idc);
+		break;
+	case V4L2_PIX_FMT_MPEG2:
+		codec_name = "MPEG-2";
+		profile_cid = V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE;
+		level_cid = V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL;
+		profile_ctrl = ctx->mpeg2_profile_ctrl;
+		level_ctrl = ctx->mpeg2_level_ctrl;
+		profile = coda_mpeg2_profile(profile_idc);
+		level = coda_mpeg2_level(level_idc);
+		break;
+	case V4L2_PIX_FMT_MPEG4:
+		codec_name = "MPEG-4";
+		profile_cid = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE;
+		level_cid = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL;
+		profile_ctrl = ctx->mpeg4_profile_ctrl;
+		level_ctrl = ctx->mpeg4_level_ctrl;
+		profile = coda_mpeg4_profile(profile_idc);
+		level = coda_mpeg4_level(level_idc);
+		break;
+	default:
+		return;
+	}
+
+	profile_names = v4l2_ctrl_get_menu(profile_cid);
+	level_names = v4l2_ctrl_get_menu(level_cid);
+
+	if (profile < 0) {
+		v4l2_warn(&ctx->dev->v4l2_dev, "Invalid %s profile: %u\n",
+			  codec_name, profile_idc);
+	} else {
+		coda_dbg(1, ctx, "Parsed %s profile: %s\n", codec_name,
+			 profile_names[profile]);
+		coda_update_menu_ctrl(profile_ctrl, profile);
+	}
+
+	if (level < 0) {
+		v4l2_warn(&ctx->dev->v4l2_dev, "Invalid %s level: %u\n",
+			  codec_name, level_idc);
+	} else {
+		coda_dbg(1, ctx, "Parsed %s level: %s\n", codec_name,
+			 level_names[level]);
+		coda_update_menu_ctrl(level_ctrl, level);
+	}
+}
+
+static void coda_queue_source_change_event(struct coda_ctx *ctx)
+{
+	static const struct v4l2_event source_change_event = {
+		.type = V4L2_EVENT_SOURCE_CHANGE,
+		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
+	};
+
+	v4l2_event_queue_fh(&ctx->fh, &source_change_event);
+}
+
+static void coda_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct coda_q_data *q_data;
+
+	q_data = get_q_data(ctx, vb->vb2_queue->type);
+
+	/*
+	 * In the decoder case, immediately try to copy the buffer into the
+	 * bitstream ringbuffer and mark it as ready to be dequeued.
+	 */
+	if (ctx->bitstream.size && vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+		/*
+		 * For backwards compatibility, queuing an empty buffer marks
+		 * the stream end
+		 */
+		if (vb2_get_plane_payload(vb, 0) == 0)
+			coda_bit_stream_end_flag(ctx);
+
+		if (q_data->fourcc == V4L2_PIX_FMT_H264) {
+			/*
+			 * Unless already done, try to obtain profile_idc and
+			 * level_idc from the SPS header. This allows to decide
+			 * whether to enable reordering during sequence
+			 * initialization.
+			 */
+			if (!ctx->params.h264_profile_idc) {
+				coda_sps_parse_profile(ctx, vb);
+				coda_update_profile_level_ctrls(ctx,
+						ctx->params.h264_profile_idc,
+						ctx->params.h264_level_idc);
+			}
+		}
+
+		mutex_lock(&ctx->bitstream_mutex);
+		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+		if (vb2_is_streaming(vb->vb2_queue))
+			/* This set buf->sequence = ctx->qsequence++ */
+			coda_fill_bitstream(ctx, NULL);
+		mutex_unlock(&ctx->bitstream_mutex);
+
+		if (!ctx->initialized) {
+			/*
+			 * Run sequence initialization in case the queued
+			 * buffer contained headers.
+			 */
+			if (vb2_is_streaming(vb->vb2_queue) &&
+			    ctx->ops->seq_init_work) {
+				queue_work(ctx->dev->workqueue,
+					   &ctx->seq_init_work);
+				flush_work(&ctx->seq_init_work);
+			}
+
+			if (ctx->initialized)
+				coda_queue_source_change_event(ctx);
+		}
+	} else {
+		if ((ctx->inst_type == CODA_INST_ENCODER || !ctx->use_bit) &&
+		    vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+			vbuf->sequence = ctx->qsequence++;
+		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+	}
+}
+
+int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf,
+		       size_t size, const char *name, struct dentry *parent)
+{
+	buf->vaddr = dma_alloc_coherent(dev->dev, size, &buf->paddr,
+					GFP_KERNEL);
+	if (!buf->vaddr) {
+		v4l2_err(&dev->v4l2_dev,
+			 "Failed to allocate %s buffer of size %zu\n",
+			 name, size);
+		return -ENOMEM;
+	}
+
+	buf->size = size;
+
+	if (name && parent) {
+		buf->blob.data = buf->vaddr;
+		buf->blob.size = size;
+		buf->dentry = debugfs_create_blob(name, 0444, parent,
+						  &buf->blob);
+	}
+
+	return 0;
+}
+
+void coda_free_aux_buf(struct coda_dev *dev,
+		       struct coda_aux_buf *buf)
+{
+	if (buf->vaddr) {
+		dma_free_coherent(dev->dev, buf->size, buf->vaddr, buf->paddr);
+		buf->vaddr = NULL;
+		buf->size = 0;
+		debugfs_remove(buf->dentry);
+		buf->dentry = NULL;
+	}
+}
+
+static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct coda_ctx *ctx = vb2_get_drv_priv(q);
+	struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev;
+	struct coda_q_data *q_data_src, *q_data_dst;
+	struct v4l2_m2m_buffer *m2m_buf, *tmp;
+	struct vb2_v4l2_buffer *buf;
+	struct list_head list;
+	int ret = 0;
+
+	if (count < 1)
+		return -EINVAL;
+
+	coda_dbg(1, ctx, "start streaming %s\n", v4l2_type_names[q->type]);
+
+	INIT_LIST_HEAD(&list);
+
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+		if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) {
+			/* copy the buffers that were queued before streamon */
+			mutex_lock(&ctx->bitstream_mutex);
+			coda_fill_bitstream(ctx, &list);
+			mutex_unlock(&ctx->bitstream_mutex);
+
+			if (ctx->dev->devtype->product != CODA_960 &&
+			    coda_get_bitstream_payload(ctx) < 512) {
+				v4l2_err(v4l2_dev, "start payload < 512\n");
+				ret = -EINVAL;
+				goto err;
+			}
+
+			if (!ctx->initialized) {
+				/* Run sequence initialization */
+				if (ctx->ops->seq_init_work) {
+					queue_work(ctx->dev->workqueue,
+						   &ctx->seq_init_work);
+					flush_work(&ctx->seq_init_work);
+				}
+			}
+		}
+
+		/*
+		 * Check the first input JPEG buffer to determine chroma
+		 * subsampling.
+		 */
+		if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) {
+			buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+			coda_jpeg_decode_header(ctx, &buf->vb2_buf);
+			/*
+			 * We have to start streaming even if the first buffer
+			 * does not contain a valid JPEG image. The error will
+			 * be caught during device run and will be signalled
+			 * via the capture buffer error flag.
+			 */
+
+			q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+			q_data_dst->width = round_up(q_data_src->width, 16);
+			q_data_dst->height = round_up(q_data_src->height, 16);
+			q_data_dst->bytesperline = q_data_dst->width;
+			if (ctx->params.jpeg_chroma_subsampling ==
+			    V4L2_JPEG_CHROMA_SUBSAMPLING_420) {
+				q_data_dst->sizeimage =
+						q_data_dst->bytesperline *
+						q_data_dst->height * 3 / 2;
+				if (q_data_dst->fourcc != V4L2_PIX_FMT_YUV420)
+					q_data_dst->fourcc = V4L2_PIX_FMT_NV12;
+			} else {
+				q_data_dst->sizeimage =
+						q_data_dst->bytesperline *
+						q_data_dst->height * 2;
+				q_data_dst->fourcc = V4L2_PIX_FMT_YUV422P;
+			}
+			q_data_dst->rect.left = 0;
+			q_data_dst->rect.top = 0;
+			q_data_dst->rect.width = q_data_src->width;
+			q_data_dst->rect.height = q_data_src->height;
+		}
+		ctx->streamon_out = 1;
+	} else {
+		ctx->streamon_cap = 1;
+	}
+
+	/* Don't start the coda unless both queues are on */
+	if (!(ctx->streamon_out && ctx->streamon_cap))
+		goto out;
+
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	if ((q_data_src->rect.width != q_data_dst->width &&
+	     round_up(q_data_src->rect.width, 16) != q_data_dst->width) ||
+	    (q_data_src->rect.height != q_data_dst->height &&
+	     round_up(q_data_src->rect.height, 16) != q_data_dst->height)) {
+		v4l2_err(v4l2_dev, "can't convert %dx%d to %dx%d\n",
+			 q_data_src->rect.width, q_data_src->rect.height,
+			 q_data_dst->width, q_data_dst->height);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	/* Allow BIT decoder device_run with no new buffers queued */
+	if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit)
+		v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
+
+	ctx->gopcounter = ctx->params.gop_size - 1;
+
+	if (q_data_dst->fourcc == V4L2_PIX_FMT_JPEG)
+		ctx->params.gop_size = 1;
+	ctx->gopcounter = ctx->params.gop_size - 1;
+	/* Only decoders have this control */
+	if (ctx->mb_err_cnt_ctrl)
+		v4l2_ctrl_s_ctrl(ctx->mb_err_cnt_ctrl, 0);
+
+	ret = ctx->ops->start_streaming(ctx);
+	if (ctx->inst_type == CODA_INST_DECODER) {
+		if (ret == -EAGAIN)
+			goto out;
+	}
+	if (ret < 0)
+		goto err;
+
+out:
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+		list_for_each_entry_safe(m2m_buf, tmp, &list, list) {
+			list_del(&m2m_buf->list);
+			v4l2_m2m_buf_done(&m2m_buf->vb, VB2_BUF_STATE_DONE);
+		}
+	}
+	return 0;
+
+err:
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+		list_for_each_entry_safe(m2m_buf, tmp, &list, list) {
+			list_del(&m2m_buf->list);
+			v4l2_m2m_buf_done(&m2m_buf->vb, VB2_BUF_STATE_QUEUED);
+		}
+		while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
+			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED);
+	} else {
+		while ((buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx)))
+			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED);
+	}
+	return ret;
+}
+
+static void coda_stop_streaming(struct vb2_queue *q)
+{
+	struct coda_ctx *ctx = vb2_get_drv_priv(q);
+	struct coda_dev *dev = ctx->dev;
+	struct vb2_v4l2_buffer *buf;
+	bool stop;
+
+	stop = ctx->streamon_out && ctx->streamon_cap;
+
+	coda_dbg(1, ctx, "stop streaming %s\n", v4l2_type_names[q->type]);
+
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+		ctx->streamon_out = 0;
+
+		coda_bit_stream_end_flag(ctx);
+
+		ctx->qsequence = 0;
+
+		while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
+			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
+	} else {
+		ctx->streamon_cap = 0;
+
+		ctx->osequence = 0;
+		ctx->sequence_offset = 0;
+
+		while ((buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx)))
+			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
+	}
+
+	if (stop) {
+		struct coda_buffer_meta *meta;
+
+		if (ctx->ops->seq_end_work) {
+			queue_work(dev->workqueue, &ctx->seq_end_work);
+			flush_work(&ctx->seq_end_work);
+		}
+		spin_lock(&ctx->buffer_meta_lock);
+		while (!list_empty(&ctx->buffer_meta_list)) {
+			meta = list_first_entry(&ctx->buffer_meta_list,
+						struct coda_buffer_meta, list);
+			list_del(&meta->list);
+			kfree(meta);
+		}
+		ctx->num_metas = 0;
+		spin_unlock(&ctx->buffer_meta_lock);
+		kfifo_init(&ctx->bitstream_fifo,
+			ctx->bitstream.vaddr, ctx->bitstream.size);
+		ctx->runcounter = 0;
+		ctx->aborting = 0;
+		ctx->hold = false;
+	}
+
+	if (!ctx->streamon_out && !ctx->streamon_cap)
+		ctx->bit_stream_param &= ~CODA_BIT_STREAM_END_FLAG;
+}
+
+static const struct vb2_ops coda_qops = {
+	.queue_setup		= coda_queue_setup,
+	.buf_prepare		= coda_buf_prepare,
+	.buf_queue		= coda_buf_queue,
+	.start_streaming	= coda_start_streaming,
+	.stop_streaming		= coda_stop_streaming,
+	.wait_prepare		= vb2_ops_wait_prepare,
+	.wait_finish		= vb2_ops_wait_finish,
+};
+
+static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	const char * const *val_names = v4l2_ctrl_get_menu(ctrl->id);
+	struct coda_ctx *ctx =
+			container_of(ctrl->handler, struct coda_ctx, ctrls);
+
+	if (val_names)
+		coda_dbg(2, ctx, "s_ctrl: id = 0x%x, name = \"%s\", val = %d (\"%s\")\n",
+			 ctrl->id, ctrl->name, ctrl->val, val_names[ctrl->val]);
+	else
+		coda_dbg(2, ctx, "s_ctrl: id = 0x%x, name = \"%s\", val = %d\n",
+			 ctrl->id, ctrl->name, ctrl->val);
+
+	switch (ctrl->id) {
+	case V4L2_CID_HFLIP:
+		if (ctrl->val)
+			ctx->params.rot_mode |= CODA_MIR_HOR;
+		else
+			ctx->params.rot_mode &= ~CODA_MIR_HOR;
+		break;
+	case V4L2_CID_VFLIP:
+		if (ctrl->val)
+			ctx->params.rot_mode |= CODA_MIR_VER;
+		else
+			ctx->params.rot_mode &= ~CODA_MIR_VER;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		ctx->params.bitrate = ctrl->val / 1000;
+		ctx->params.bitrate_changed = true;
+		break;
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		ctx->params.gop_size = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+		ctx->params.h264_intra_qp = ctrl->val;
+		ctx->params.h264_intra_qp_changed = true;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+		ctx->params.h264_inter_qp = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+		ctx->params.h264_min_qp = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+		ctx->params.h264_max_qp = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
+		ctx->params.h264_slice_alpha_c0_offset_div2 = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
+		ctx->params.h264_slice_beta_offset_div2 = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
+		ctx->params.h264_disable_deblocking_filter_idc = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION:
+		ctx->params.h264_constrained_intra_pred_flag = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
+		ctx->params.frame_rc_enable = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
+		ctx->params.mb_rc_enable = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET:
+		ctx->params.h264_chroma_qp_index_offset = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+		/* TODO: switch between baseline and constrained baseline */
+		if (ctx->inst_type == CODA_INST_ENCODER)
+			ctx->params.h264_profile_idc = 66;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+		/* nothing to do, this is set by the encoder */
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+		ctx->params.mpeg4_intra_qp = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+		ctx->params.mpeg4_inter_qp = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE:
+	case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
+	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
+		/* nothing to do, these are fixed */
+		break;
+	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
+		ctx->params.slice_mode = ctrl->val;
+		ctx->params.slice_mode_changed = true;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
+		ctx->params.slice_max_mb = ctrl->val;
+		ctx->params.slice_mode_changed = true;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
+		ctx->params.slice_max_bits = ctrl->val * 8;
+		ctx->params.slice_mode_changed = true;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+		break;
+	case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
+		ctx->params.intra_refresh = ctrl->val;
+		ctx->params.intra_refresh_changed = true;
+		break;
+	case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:
+		ctx->params.force_ipicture = true;
+		break;
+	case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+		coda_set_jpeg_compression_quality(ctx, ctrl->val);
+		break;
+	case V4L2_CID_JPEG_RESTART_INTERVAL:
+		ctx->params.jpeg_restart_interval = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_VBV_DELAY:
+		ctx->params.vbv_delay = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_VBV_SIZE:
+		ctx->params.vbv_size = min(ctrl->val * 8192, 0x7fffffff);
+		break;
+	default:
+		coda_dbg(1, ctx, "Invalid control, id=%d, val=%d\n",
+			 ctrl->id, ctrl->val);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops coda_ctrl_ops = {
+	.s_ctrl = coda_s_ctrl,
+};
+
+static void coda_encode_ctrls(struct coda_ctx *ctx)
+{
+	int max_gop_size = (ctx->dev->devtype->product == CODA_DX6) ? 60 : 99;
+
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_BITRATE, 0, 32767000, 1000, 0);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, max_gop_size, 1, 16);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 0, 51, 1, 25);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 0, 51, 1, 25);
+	if (ctx->dev->devtype->product != CODA_960) {
+		v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+			V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 51, 1, 12);
+	}
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 0, 51, 1, 51);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, -6, 6, 1, 0);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, -6, 6, 1, 0);
+	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
+		V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY,
+		0x0, V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION, 0, 1, 1,
+		0);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, 0, 1, 1, 1);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE, 0, 1, 1, 1);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET, -12, 12, 1, 0);
+	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+		V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE, 0x0,
+		V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE);
+	if (ctx->dev->devtype->product == CODA_HX4 ||
+	    ctx->dev->devtype->product == CODA_7541) {
+		v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+			V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+			V4L2_MPEG_VIDEO_H264_LEVEL_3_1,
+			~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1)),
+			V4L2_MPEG_VIDEO_H264_LEVEL_3_1);
+	}
+	if (ctx->dev->devtype->product == CODA_960) {
+		v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+			V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+			V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
+			~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
+			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_2)),
+			V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
+	}
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP, 1, 31, 1, 2);
+	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
+		V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE, 0x0,
+		V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE);
+	if (ctx->dev->devtype->product == CODA_HX4 ||
+	    ctx->dev->devtype->product == CODA_7541 ||
+	    ctx->dev->devtype->product == CODA_960) {
+		v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+			V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
+			V4L2_MPEG_VIDEO_MPEG4_LEVEL_5,
+			~(1 << V4L2_MPEG_VIDEO_MPEG4_LEVEL_5),
+			V4L2_MPEG_VIDEO_MPEG4_LEVEL_5);
+	}
+	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
+		V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES, 0x0,
+		V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, 1, 0x3fffffff, 1, 1);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, 1, 0x3fffffff, 1,
+		500);
+	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_HEADER_MODE,
+		V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+		(1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE),
+		V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, 0,
+		1920 * 1088 / 256, 1, 0);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_VBV_DELAY, 0, 0x7fff, 1, 0);
+	/*
+	 * The maximum VBV size value is 0x7fffffff bits,
+	 * one bit less than 262144 KiB
+	 */
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_MPEG_VIDEO_VBV_SIZE, 0, 262144, 1, 0);
+}
+
+static void coda_jpeg_encode_ctrls(struct coda_ctx *ctx)
+{
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_JPEG_COMPRESSION_QUALITY, 5, 100, 1, 50);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_JPEG_RESTART_INTERVAL, 0, 100, 1, 0);
+}
+
+static void coda_decode_ctrls(struct coda_ctx *ctx)
+{
+	u8 max;
+
+	ctx->h264_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
+		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+		V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+		~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
+		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
+		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
+		V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
+	if (ctx->h264_profile_ctrl)
+		ctx->h264_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+	if (ctx->dev->devtype->product == CODA_HX4 ||
+	    ctx->dev->devtype->product == CODA_7541)
+		max = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
+	else if (ctx->dev->devtype->product == CODA_960)
+		max = V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
+	else
+		return;
+	ctx->h264_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
+		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_LEVEL, max, 0, max);
+	if (ctx->h264_level_ctrl)
+		ctx->h264_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+	ctx->mpeg2_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
+		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE,
+		V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH, 0,
+		V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH);
+	if (ctx->mpeg2_profile_ctrl)
+		ctx->mpeg2_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+	ctx->mpeg2_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
+		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL,
+		V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH, 0,
+		V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH);
+	if (ctx->mpeg2_level_ctrl)
+		ctx->mpeg2_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+	ctx->mpeg4_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
+		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
+		V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY, 0,
+		V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY);
+	if (ctx->mpeg4_profile_ctrl)
+		ctx->mpeg4_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
+	ctx->mpeg4_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
+		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
+		V4L2_MPEG_VIDEO_MPEG4_LEVEL_5, 0,
+		V4L2_MPEG_VIDEO_MPEG4_LEVEL_5);
+	if (ctx->mpeg4_level_ctrl)
+		ctx->mpeg4_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+}
+
+static const struct v4l2_ctrl_config coda_mb_err_cnt_ctrl_config = {
+	.id	= V4L2_CID_CODA_MB_ERR_CNT,
+	.name	= "Macroblocks Error Count",
+	.type	= V4L2_CTRL_TYPE_INTEGER,
+	.min	= 0,
+	.max	= 0x7fffffff,
+	.step	= 1,
+};
+
+static int coda_ctrls_setup(struct coda_ctx *ctx)
+{
+	v4l2_ctrl_handler_init(&ctx->ctrls, 2);
+
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_HFLIP, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+		V4L2_CID_VFLIP, 0, 1, 1, 0);
+	if (ctx->inst_type == CODA_INST_ENCODER) {
+		v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+				  V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
+				  1, 1, 1, 1);
+		if (ctx->cvd->dst_formats[0] == V4L2_PIX_FMT_JPEG)
+			coda_jpeg_encode_ctrls(ctx);
+		else
+			coda_encode_ctrls(ctx);
+	} else {
+		v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+				  V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
+				  1, 1, 1, 1);
+		if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_H264)
+			coda_decode_ctrls(ctx);
+
+		ctx->mb_err_cnt_ctrl = v4l2_ctrl_new_custom(&ctx->ctrls,
+						&coda_mb_err_cnt_ctrl_config,
+						NULL);
+		if (ctx->mb_err_cnt_ctrl)
+			ctx->mb_err_cnt_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+	}
+
+	if (ctx->ctrls.error) {
+		v4l2_err(&ctx->dev->v4l2_dev,
+			"control initialization error (%d)",
+			ctx->ctrls.error);
+		return -EINVAL;
+	}
+
+	return v4l2_ctrl_handler_setup(&ctx->ctrls);
+}
+
+static int coda_queue_init(struct coda_ctx *ctx, struct vb2_queue *vq)
+{
+	vq->drv_priv = ctx;
+	vq->ops = &coda_qops;
+	vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	vq->lock = &ctx->dev->dev_mutex;
+	/* One way to indicate end-of-stream for coda is to set the
+	 * bytesused == 0. However by default videobuf2 handles bytesused
+	 * equal to 0 as a special case and changes its value to the size
+	 * of the buffer. Set the allow_zero_bytesused flag, so
+	 * that videobuf2 will keep the value of bytesused intact.
+	 */
+	vq->allow_zero_bytesused = 1;
+	/*
+	 * We might be fine with no buffers on some of the queues, but that
+	 * would need to be reflected in job_ready(). Currently we expect all
+	 * queues to have at least one buffer queued.
+	 */
+	vq->min_buffers_needed = 1;
+	vq->dev = ctx->dev->dev;
+
+	return vb2_queue_init(vq);
+}
+
+int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq,
+			    struct vb2_queue *dst_vq)
+{
+	int ret;
+
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	src_vq->io_modes = VB2_DMABUF | VB2_MMAP;
+	src_vq->mem_ops = &vb2_dma_contig_memops;
+
+	ret = coda_queue_init(priv, src_vq);
+	if (ret)
+		return ret;
+
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	dst_vq->io_modes = VB2_DMABUF | VB2_MMAP;
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+
+	return coda_queue_init(priv, dst_vq);
+}
+
+int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq,
+			    struct vb2_queue *dst_vq)
+{
+	int ret;
+
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	src_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR;
+	src_vq->mem_ops = &vb2_vmalloc_memops;
+
+	ret = coda_queue_init(priv, src_vq);
+	if (ret)
+		return ret;
+
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	dst_vq->io_modes = VB2_DMABUF | VB2_MMAP;
+	dst_vq->dma_attrs = DMA_ATTR_NO_KERNEL_MAPPING;
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+
+	return coda_queue_init(priv, dst_vq);
+}
+
+/*
+ * File operations
+ */
+
+static int coda_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct coda_dev *dev = video_get_drvdata(vdev);
+	struct coda_ctx *ctx;
+	unsigned int max = ~0;
+	char *name;
+	int ret;
+	int idx;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	if (dev->devtype->product == CODA_DX6)
+		max = CODADX6_MAX_INSTANCES - 1;
+	idx = ida_alloc_max(&dev->ida, max, GFP_KERNEL);
+	if (idx < 0) {
+		ret = idx;
+		goto err_coda_max;
+	}
+
+	name = kasprintf(GFP_KERNEL, "context%d", idx);
+	if (!name) {
+		ret = -ENOMEM;
+		goto err_coda_name_init;
+	}
+
+	ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root);
+	kfree(name);
+
+	ctx->cvd = to_coda_video_device(vdev);
+	ctx->inst_type = ctx->cvd->type;
+	ctx->ops = ctx->cvd->ops;
+	ctx->use_bit = !ctx->cvd->direct;
+	init_completion(&ctx->completion);
+	INIT_WORK(&ctx->pic_run_work, coda_pic_run_work);
+	if (ctx->ops->seq_init_work)
+		INIT_WORK(&ctx->seq_init_work, ctx->ops->seq_init_work);
+	if (ctx->ops->seq_end_work)
+		INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work);
+	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	file->private_data = &ctx->fh;
+	v4l2_fh_add(&ctx->fh);
+	ctx->dev = dev;
+	ctx->idx = idx;
+
+	coda_dbg(1, ctx, "open instance (%p)\n", ctx);
+
+	switch (dev->devtype->product) {
+	case CODA_960:
+		/*
+		 * Enabling the BWB when decoding can hang the firmware with
+		 * certain streams. The issue was tracked as ENGR00293425 by
+		 * Freescale. As a workaround, disable BWB for all decoders.
+		 * The enable_bwb module parameter allows to override this.
+		 */
+		if (enable_bwb || ctx->inst_type == CODA_INST_ENCODER)
+			ctx->frame_mem_ctrl = CODA9_FRAME_ENABLE_BWB;
+		fallthrough;
+	case CODA_HX4:
+	case CODA_7541:
+		ctx->reg_idx = 0;
+		break;
+	default:
+		ctx->reg_idx = idx;
+	}
+	if (ctx->dev->vdoa && !disable_vdoa) {
+		ctx->vdoa = vdoa_context_create(dev->vdoa);
+		if (!ctx->vdoa)
+			v4l2_warn(&dev->v4l2_dev,
+				  "Failed to create vdoa context: not using vdoa");
+	}
+	ctx->use_vdoa = false;
+
+	/* Power up and upload firmware if necessary */
+	ret = pm_runtime_resume_and_get(dev->dev);
+	if (ret < 0) {
+		v4l2_err(&dev->v4l2_dev, "failed to power up: %d\n", ret);
+		goto err_pm_get;
+	}
+
+	ret = clk_prepare_enable(dev->clk_per);
+	if (ret)
+		goto err_clk_enable;
+
+	ret = clk_prepare_enable(dev->clk_ahb);
+	if (ret)
+		goto err_clk_ahb;
+
+	set_default_params(ctx);
+	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
+					    ctx->ops->queue_init);
+	if (IS_ERR(ctx->fh.m2m_ctx)) {
+		ret = PTR_ERR(ctx->fh.m2m_ctx);
+
+		v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n",
+			 __func__, ret);
+		goto err_ctx_init;
+	}
+
+	ret = coda_ctrls_setup(ctx);
+	if (ret) {
+		v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n");
+		goto err_ctrls_setup;
+	}
+
+	ctx->fh.ctrl_handler = &ctx->ctrls;
+
+	mutex_init(&ctx->bitstream_mutex);
+	mutex_init(&ctx->buffer_mutex);
+	mutex_init(&ctx->wakeup_mutex);
+	INIT_LIST_HEAD(&ctx->buffer_meta_list);
+	spin_lock_init(&ctx->buffer_meta_lock);
+
+	return 0;
+
+err_ctrls_setup:
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+err_ctx_init:
+	clk_disable_unprepare(dev->clk_ahb);
+err_clk_ahb:
+	clk_disable_unprepare(dev->clk_per);
+err_clk_enable:
+	pm_runtime_put_sync(dev->dev);
+err_pm_get:
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+err_coda_name_init:
+	ida_free(&dev->ida, ctx->idx);
+err_coda_max:
+	kfree(ctx);
+	return ret;
+}
+
+static int coda_release(struct file *file)
+{
+	struct coda_dev *dev = video_drvdata(file);
+	struct coda_ctx *ctx = fh_to_ctx(file->private_data);
+
+	coda_dbg(1, ctx, "release instance (%p)\n", ctx);
+
+	if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit)
+		coda_bit_stream_end_flag(ctx);
+
+	/* If this instance is running, call .job_abort and wait for it to end */
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+
+	if (ctx->vdoa)
+		vdoa_context_destroy(ctx->vdoa);
+
+	/* In case the instance was not running, we still need to call SEQ_END */
+	if (ctx->ops->seq_end_work) {
+		queue_work(dev->workqueue, &ctx->seq_end_work);
+		flush_work(&ctx->seq_end_work);
+	}
+
+	if (ctx->dev->devtype->product == CODA_DX6)
+		coda_free_aux_buf(dev, &ctx->workbuf);
+
+	v4l2_ctrl_handler_free(&ctx->ctrls);
+	clk_disable_unprepare(dev->clk_ahb);
+	clk_disable_unprepare(dev->clk_per);
+	pm_runtime_put_sync(dev->dev);
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	ida_free(&dev->ida, ctx->idx);
+	if (ctx->ops->release)
+		ctx->ops->release(ctx);
+	debugfs_remove_recursive(ctx->debugfs_entry);
+	kfree(ctx);
+
+	return 0;
+}
+
+static const struct v4l2_file_operations coda_fops = {
+	.owner		= THIS_MODULE,
+	.open		= coda_open,
+	.release	= coda_release,
+	.poll		= v4l2_m2m_fop_poll,
+	.unlocked_ioctl	= video_ioctl2,
+	.mmap		= v4l2_m2m_fop_mmap,
+};
+
+static int coda_hw_init(struct coda_dev *dev)
+{
+	u32 data;
+	u16 *p;
+	int i, ret;
+
+	ret = clk_prepare_enable(dev->clk_per);
+	if (ret)
+		goto err_clk_per;
+
+	ret = clk_prepare_enable(dev->clk_ahb);
+	if (ret)
+		goto err_clk_ahb;
+
+	reset_control_reset(dev->rstc);
+
+	/*
+	 * Copy the first CODA_ISRAM_SIZE in the internal SRAM.
+	 * The 16-bit chars in the code buffer are in memory access
+	 * order, re-sort them to CODA order for register download.
+	 * Data in this SRAM survives a reboot.
+	 */
+	p = (u16 *)dev->codebuf.vaddr;
+	if (dev->devtype->product == CODA_DX6) {
+		for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++)  {
+			data = CODA_DOWN_ADDRESS_SET(i) |
+				CODA_DOWN_DATA_SET(p[i ^ 1]);
+			coda_write(dev, data, CODA_REG_BIT_CODE_DOWN);
+		}
+	} else {
+		for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++) {
+			data = CODA_DOWN_ADDRESS_SET(i) |
+				CODA_DOWN_DATA_SET(p[round_down(i, 4) +
+							3 - (i % 4)]);
+			coda_write(dev, data, CODA_REG_BIT_CODE_DOWN);
+		}
+	}
+
+	/* Clear registers */
+	for (i = 0; i < 64; i++)
+		coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4);
+
+	/* Tell the BIT where to find everything it needs */
+	if (dev->devtype->product == CODA_960 ||
+	    dev->devtype->product == CODA_7541 ||
+	    dev->devtype->product == CODA_HX4) {
+		coda_write(dev, dev->tempbuf.paddr,
+				CODA_REG_BIT_TEMP_BUF_ADDR);
+		coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
+	} else {
+		coda_write(dev, dev->workbuf.paddr,
+			      CODA_REG_BIT_WORK_BUF_ADDR);
+	}
+	coda_write(dev, dev->codebuf.paddr,
+		      CODA_REG_BIT_CODE_BUF_ADDR);
+	coda_write(dev, 0, CODA_REG_BIT_CODE_RUN);
+
+	/* Set default values */
+	switch (dev->devtype->product) {
+	case CODA_DX6:
+		coda_write(dev, CODADX6_STREAM_BUF_PIC_FLUSH,
+			   CODA_REG_BIT_STREAM_CTRL);
+		break;
+	default:
+		coda_write(dev, CODA7_STREAM_BUF_PIC_FLUSH,
+			   CODA_REG_BIT_STREAM_CTRL);
+	}
+	if (dev->devtype->product == CODA_960)
+		coda_write(dev, CODA9_FRAME_ENABLE_BWB,
+				CODA_REG_BIT_FRAME_MEM_CTRL);
+	else
+		coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL);
+
+	if (dev->devtype->product != CODA_DX6)
+		coda_write(dev, 0, CODA7_REG_BIT_AXI_SRAM_USE);
+
+	coda_write(dev, CODA_INT_INTERRUPT_ENABLE,
+		      CODA_REG_BIT_INT_ENABLE);
+
+	/* Reset VPU and start processor */
+	data = coda_read(dev, CODA_REG_BIT_CODE_RESET);
+	data |= CODA_REG_RESET_ENABLE;
+	coda_write(dev, data, CODA_REG_BIT_CODE_RESET);
+	udelay(10);
+	data &= ~CODA_REG_RESET_ENABLE;
+	coda_write(dev, data, CODA_REG_BIT_CODE_RESET);
+	coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN);
+
+	clk_disable_unprepare(dev->clk_ahb);
+	clk_disable_unprepare(dev->clk_per);
+
+	return 0;
+
+err_clk_ahb:
+	clk_disable_unprepare(dev->clk_per);
+err_clk_per:
+	return ret;
+}
+
+static int coda_register_device(struct coda_dev *dev, int i)
+{
+	struct video_device *vfd = &dev->vfd[i];
+	const char *name;
+	int ret;
+
+	if (i >= dev->devtype->num_vdevs)
+		return -EINVAL;
+	name = dev->devtype->vdevs[i]->name;
+
+	strscpy(vfd->name, dev->devtype->vdevs[i]->name, sizeof(vfd->name));
+	vfd->fops	= &coda_fops;
+	vfd->ioctl_ops	= &coda_ioctl_ops;
+	vfd->release	= video_device_release_empty;
+	vfd->lock	= &dev->dev_mutex;
+	vfd->v4l2_dev	= &dev->v4l2_dev;
+	vfd->vfl_dir	= VFL_DIR_M2M;
+	vfd->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
+	video_set_drvdata(vfd, dev);
+
+	/* Not applicable, use the selection API instead */
+	v4l2_disable_ioctl(vfd, VIDIOC_CROPCAP);
+	v4l2_disable_ioctl(vfd, VIDIOC_G_CROP);
+	v4l2_disable_ioctl(vfd, VIDIOC_S_CROP);
+
+	if (dev->devtype->vdevs[i]->type == CODA_INST_ENCODER) {
+		v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
+		v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
+		if (dev->devtype->vdevs[i]->dst_formats[0] == V4L2_PIX_FMT_JPEG) {
+			v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMEINTERVALS);
+			v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
+			v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
+		}
+	} else {
+		v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
+		v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
+		v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMESIZES);
+		v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMEINTERVALS);
+		v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
+		v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
+	}
+
+	ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
+	if (!ret)
+		v4l2_info(&dev->v4l2_dev, "%s registered as %s\n",
+			  name, video_device_node_name(vfd));
+	return ret;
+}
+
+static void coda_copy_firmware(struct coda_dev *dev, const u8 * const buf,
+			       size_t size)
+{
+	u32 *src = (u32 *)buf;
+
+	/* Check if the firmware has a 16-byte Freescale header, skip it */
+	if (buf[0] == 'M' && buf[1] == 'X')
+		src += 4;
+	/*
+	 * Check whether the firmware is in native order or pre-reordered for
+	 * memory access. The first instruction opcode always is 0xe40e.
+	 */
+	if (__le16_to_cpup((__le16 *)src) == 0xe40e) {
+		u32 *dst = dev->codebuf.vaddr;
+		int i;
+
+		/* Firmware in native order, reorder while copying */
+		if (dev->devtype->product == CODA_DX6) {
+			for (i = 0; i < (size - 16) / 4; i++)
+				dst[i] = (src[i] << 16) | (src[i] >> 16);
+		} else {
+			for (i = 0; i < (size - 16) / 4; i += 2) {
+				dst[i] = (src[i + 1] << 16) | (src[i + 1] >> 16);
+				dst[i + 1] = (src[i] << 16) | (src[i] >> 16);
+			}
+		}
+	} else {
+		/* Copy the already reordered firmware image */
+		memcpy(dev->codebuf.vaddr, src, size);
+	}
+}
+
+static void coda_fw_callback(const struct firmware *fw, void *context);
+
+static int coda_firmware_request(struct coda_dev *dev)
+{
+	char *fw;
+
+	if (dev->firmware >= ARRAY_SIZE(dev->devtype->firmware))
+		return -EINVAL;
+
+	fw = dev->devtype->firmware[dev->firmware];
+
+	dev_dbg(dev->dev, "requesting firmware '%s' for %s\n", fw,
+		coda_product_name(dev->devtype->product));
+
+	return request_firmware_nowait(THIS_MODULE, true, fw, dev->dev,
+				       GFP_KERNEL, dev, coda_fw_callback);
+}
+
+static void coda_fw_callback(const struct firmware *fw, void *context)
+{
+	struct coda_dev *dev = context;
+	int i, ret;
+
+	if (!fw) {
+		dev->firmware++;
+		ret = coda_firmware_request(dev);
+		if (ret < 0) {
+			v4l2_err(&dev->v4l2_dev, "firmware request failed\n");
+			goto put_pm;
+		}
+		return;
+	}
+	if (dev->firmware > 0) {
+		/*
+		 * Since we can't suppress warnings for failed asynchronous
+		 * firmware requests, report that the fallback firmware was
+		 * found.
+		 */
+		dev_info(dev->dev, "Using fallback firmware %s\n",
+			 dev->devtype->firmware[dev->firmware]);
+	}
+
+	/* allocate auxiliary per-device code buffer for the BIT processor */
+	ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size, "codebuf",
+				 dev->debugfs_root);
+	if (ret < 0)
+		goto put_pm;
+
+	coda_copy_firmware(dev, fw->data, fw->size);
+	release_firmware(fw);
+
+	ret = coda_hw_init(dev);
+	if (ret < 0) {
+		v4l2_err(&dev->v4l2_dev, "HW initialization failed\n");
+		goto put_pm;
+	}
+
+	ret = coda_check_firmware(dev);
+	if (ret < 0)
+		goto put_pm;
+
+	dev->m2m_dev = v4l2_m2m_init(&coda_m2m_ops);
+	if (IS_ERR(dev->m2m_dev)) {
+		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
+		goto put_pm;
+	}
+
+	for (i = 0; i < dev->devtype->num_vdevs; i++) {
+		ret = coda_register_device(dev, i);
+		if (ret) {
+			v4l2_err(&dev->v4l2_dev,
+				 "Failed to register %s video device: %d\n",
+				 dev->devtype->vdevs[i]->name, ret);
+			goto rel_vfd;
+		}
+	}
+
+	pm_runtime_put_sync(dev->dev);
+	return;
+
+rel_vfd:
+	while (--i >= 0)
+		video_unregister_device(&dev->vfd[i]);
+	v4l2_m2m_release(dev->m2m_dev);
+put_pm:
+	pm_runtime_put_sync(dev->dev);
+}
+
+enum coda_platform {
+	CODA_IMX27,
+	CODA_IMX51,
+	CODA_IMX53,
+	CODA_IMX6Q,
+	CODA_IMX6DL,
+};
+
+static const struct coda_devtype coda_devdata[] = {
+	[CODA_IMX27] = {
+		.firmware     = {
+			"vpu_fw_imx27_TO2.bin",
+			"vpu/vpu_fw_imx27_TO2.bin",
+			"v4l-codadx6-imx27.bin"
+		},
+		.product      = CODA_DX6,
+		.codecs       = codadx6_codecs,
+		.num_codecs   = ARRAY_SIZE(codadx6_codecs),
+		.vdevs        = codadx6_video_devices,
+		.num_vdevs    = ARRAY_SIZE(codadx6_video_devices),
+		.workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024,
+		.iram_size    = 0xb000,
+	},
+	[CODA_IMX51] = {
+		.firmware     = {
+			"vpu_fw_imx51.bin",
+			"vpu/vpu_fw_imx51.bin",
+			"v4l-codahx4-imx51.bin"
+		},
+		.product      = CODA_HX4,
+		.codecs       = codahx4_codecs,
+		.num_codecs   = ARRAY_SIZE(codahx4_codecs),
+		.vdevs        = codahx4_video_devices,
+		.num_vdevs    = ARRAY_SIZE(codahx4_video_devices),
+		.workbuf_size = 128 * 1024,
+		.tempbuf_size = 304 * 1024,
+		.iram_size    = 0x14000,
+	},
+	[CODA_IMX53] = {
+		.firmware     = {
+			"vpu_fw_imx53.bin",
+			"vpu/vpu_fw_imx53.bin",
+			"v4l-coda7541-imx53.bin"
+		},
+		.product      = CODA_7541,
+		.codecs       = coda7_codecs,
+		.num_codecs   = ARRAY_SIZE(coda7_codecs),
+		.vdevs        = coda7_video_devices,
+		.num_vdevs    = ARRAY_SIZE(coda7_video_devices),
+		.workbuf_size = 128 * 1024,
+		.tempbuf_size = 304 * 1024,
+		.iram_size    = 0x14000,
+	},
+	[CODA_IMX6Q] = {
+		.firmware     = {
+			"vpu_fw_imx6q.bin",
+			"vpu/vpu_fw_imx6q.bin",
+			"v4l-coda960-imx6q.bin"
+		},
+		.product      = CODA_960,
+		.codecs       = coda9_codecs,
+		.num_codecs   = ARRAY_SIZE(coda9_codecs),
+		.vdevs        = coda9_video_devices,
+		.num_vdevs    = ARRAY_SIZE(coda9_video_devices),
+		.workbuf_size = 80 * 1024,
+		.tempbuf_size = 204 * 1024,
+		.iram_size    = 0x21000,
+	},
+	[CODA_IMX6DL] = {
+		.firmware     = {
+			"vpu_fw_imx6d.bin",
+			"vpu/vpu_fw_imx6d.bin",
+			"v4l-coda960-imx6dl.bin"
+		},
+		.product      = CODA_960,
+		.codecs       = coda9_codecs,
+		.num_codecs   = ARRAY_SIZE(coda9_codecs),
+		.vdevs        = coda9_video_devices,
+		.num_vdevs    = ARRAY_SIZE(coda9_video_devices),
+		.workbuf_size = 80 * 1024,
+		.tempbuf_size = 204 * 1024,
+		.iram_size    = 0x1f000, /* leave 4k for suspend code */
+	},
+};
+
+static const struct of_device_id coda_dt_ids[] = {
+	{ .compatible = "fsl,imx27-vpu", .data = &coda_devdata[CODA_IMX27] },
+	{ .compatible = "fsl,imx51-vpu", .data = &coda_devdata[CODA_IMX51] },
+	{ .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] },
+	{ .compatible = "fsl,imx6q-vpu", .data = &coda_devdata[CODA_IMX6Q] },
+	{ .compatible = "fsl,imx6dl-vpu", .data = &coda_devdata[CODA_IMX6DL] },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, coda_dt_ids);
+
+static int coda_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct gen_pool *pool;
+	struct coda_dev *dev;
+	int ret, irq;
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->devtype = of_device_get_match_data(&pdev->dev);
+
+	dev->dev = &pdev->dev;
+	dev->clk_per = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(dev->clk_per)) {
+		dev_err(&pdev->dev, "Could not get per clock\n");
+		return PTR_ERR(dev->clk_per);
+	}
+
+	dev->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
+	if (IS_ERR(dev->clk_ahb)) {
+		dev_err(&pdev->dev, "Could not get ahb clock\n");
+		return PTR_ERR(dev->clk_ahb);
+	}
+
+	/* Get  memory for physical registers */
+	dev->regs_base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(dev->regs_base))
+		return PTR_ERR(dev->regs_base);
+
+	/* IRQ */
+	irq = platform_get_irq_byname(pdev, "bit");
+	if (irq < 0)
+		irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	ret = devm_request_irq(&pdev->dev, irq, coda_irq_handler, 0,
+			       CODA_NAME "-video", dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to request irq: %d\n", ret);
+		return ret;
+	}
+
+	/* JPEG IRQ */
+	if (dev->devtype->product == CODA_960) {
+		irq = platform_get_irq_byname(pdev, "jpeg");
+		if (irq < 0)
+			return irq;
+
+		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+						coda9_jpeg_irq_handler,
+						IRQF_ONESHOT, CODA_NAME "-jpeg",
+						dev);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "failed to request jpeg irq\n");
+			return ret;
+		}
+	}
+
+	dev->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev,
+							      NULL);
+	if (IS_ERR(dev->rstc)) {
+		ret = PTR_ERR(dev->rstc);
+		dev_err(&pdev->dev, "failed get reset control: %d\n", ret);
+		return ret;
+	}
+
+	/* Get IRAM pool from device tree */
+	pool = of_gen_pool_get(np, "iram", 0);
+	if (!pool) {
+		dev_err(&pdev->dev, "iram pool not available\n");
+		return -ENOMEM;
+	}
+	dev->iram_pool = pool;
+
+	/* Get vdoa_data if supported by the platform */
+	dev->vdoa = coda_get_vdoa_data();
+	if (PTR_ERR(dev->vdoa) == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+
+	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+	if (ret)
+		return ret;
+
+	ratelimit_default_init(&dev->mb_err_rs);
+	mutex_init(&dev->dev_mutex);
+	mutex_init(&dev->coda_mutex);
+	ida_init(&dev->ida);
+
+	dev->debugfs_root = debugfs_create_dir("coda", NULL);
+
+	/* allocate auxiliary per-device buffers for the BIT processor */
+	if (dev->devtype->product == CODA_DX6) {
+		ret = coda_alloc_aux_buf(dev, &dev->workbuf,
+					 dev->devtype->workbuf_size, "workbuf",
+					 dev->debugfs_root);
+		if (ret < 0)
+			goto err_v4l2_register;
+	}
+
+	if (dev->devtype->tempbuf_size) {
+		ret = coda_alloc_aux_buf(dev, &dev->tempbuf,
+					 dev->devtype->tempbuf_size, "tempbuf",
+					 dev->debugfs_root);
+		if (ret < 0)
+			goto err_v4l2_register;
+	}
+
+	dev->iram.size = dev->devtype->iram_size;
+	dev->iram.vaddr = gen_pool_dma_alloc(dev->iram_pool, dev->iram.size,
+					     &dev->iram.paddr);
+	if (!dev->iram.vaddr) {
+		dev_warn(&pdev->dev, "unable to alloc iram\n");
+	} else {
+		memset(dev->iram.vaddr, 0, dev->iram.size);
+		dev->iram.blob.data = dev->iram.vaddr;
+		dev->iram.blob.size = dev->iram.size;
+		dev->iram.dentry = debugfs_create_blob("iram", 0444,
+						       dev->debugfs_root,
+						       &dev->iram.blob);
+	}
+
+	dev->workqueue = alloc_workqueue("coda", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+	if (!dev->workqueue) {
+		dev_err(&pdev->dev, "unable to alloc workqueue\n");
+		ret = -ENOMEM;
+		goto err_v4l2_register;
+	}
+
+	platform_set_drvdata(pdev, dev);
+
+	/*
+	 * Start activated so we can directly call coda_hw_init in
+	 * coda_fw_callback regardless of whether CONFIG_PM is
+	 * enabled or whether the device is associated with a PM domain.
+	 */
+	pm_runtime_get_noresume(&pdev->dev);
+	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_enable(&pdev->dev);
+
+	ret = coda_firmware_request(dev);
+	if (ret)
+		goto err_alloc_workqueue;
+	return 0;
+
+err_alloc_workqueue:
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
+	destroy_workqueue(dev->workqueue);
+err_v4l2_register:
+	v4l2_device_unregister(&dev->v4l2_dev);
+	return ret;
+}
+
+static int coda_remove(struct platform_device *pdev)
+{
+	struct coda_dev *dev = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dev->vfd); i++) {
+		if (video_get_drvdata(&dev->vfd[i]))
+			video_unregister_device(&dev->vfd[i]);
+	}
+	if (dev->m2m_dev)
+		v4l2_m2m_release(dev->m2m_dev);
+	pm_runtime_disable(&pdev->dev);
+	v4l2_device_unregister(&dev->v4l2_dev);
+	destroy_workqueue(dev->workqueue);
+	if (dev->iram.vaddr)
+		gen_pool_free(dev->iram_pool, (unsigned long)dev->iram.vaddr,
+			      dev->iram.size);
+	coda_free_aux_buf(dev, &dev->codebuf);
+	coda_free_aux_buf(dev, &dev->tempbuf);
+	coda_free_aux_buf(dev, &dev->workbuf);
+	debugfs_remove_recursive(dev->debugfs_root);
+	ida_destroy(&dev->ida);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int coda_runtime_resume(struct device *dev)
+{
+	struct coda_dev *cdev = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (dev->pm_domain && cdev->codebuf.vaddr) {
+		ret = coda_hw_init(cdev);
+		if (ret)
+			v4l2_err(&cdev->v4l2_dev, "HW initialization failed\n");
+	}
+
+	return ret;
+}
+#endif
+
+static const struct dev_pm_ops coda_pm_ops = {
+	SET_RUNTIME_PM_OPS(NULL, coda_runtime_resume, NULL)
+};
+
+static struct platform_driver coda_driver = {
+	.probe	= coda_probe,
+	.remove	= coda_remove,
+	.driver	= {
+		.name	= CODA_NAME,
+		.of_match_table = coda_dt_ids,
+		.pm	= &coda_pm_ops,
+	},
+};
+
+module_platform_driver(coda_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
+MODULE_DESCRIPTION("Coda multi-standard codec V4L2 driver");
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-gdi.c b/drivers/media/platform/chips-media/coda/coda-gdi.c
--- a/drivers/media/platform/chips-media/coda/coda-gdi.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/coda-gdi.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Coda multi-standard codec IP
+ *
+ * Copyright (C) 2014 Philipp Zabel, Pengutronix
+ */
+
+#include <linux/bitops.h>
+#include "coda.h"
+
+#define XY2_INVERT	BIT(7)
+#define XY2_ZERO	BIT(6)
+#define XY2_TB_XOR	BIT(5)
+#define XY2_XYSEL	BIT(4)
+#define XY2_Y		(1 << 4)
+#define XY2_X		(0 << 4)
+
+#define XY2(luma_sel, luma_bit, chroma_sel, chroma_bit) \
+	(((XY2_##luma_sel) | (luma_bit)) << 8 | \
+	 (XY2_##chroma_sel) | (chroma_bit))
+
+static const u16 xy2ca_zero_map[16] = {
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+};
+
+static const u16 xy2ca_tiled_map[16] = {
+	XY2(Y,    0, Y,    0),
+	XY2(Y,    1, Y,    1),
+	XY2(Y,    2, Y,    2),
+	XY2(Y,    3, X,    3),
+	XY2(X,    3, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+	XY2(ZERO, 0, ZERO, 0),
+};
+
+/*
+ * RA[15:0], CA[15:8] are hardwired to contain the 24-bit macroblock
+ * start offset (macroblock size is 16x16 for luma, 16x8 for chroma).
+ * Bits CA[4:0] are set using XY2CA above. BA[3:0] seems to be unused.
+ */
+
+#define RBC_CA		(0 << 4)
+#define RBC_BA		(1 << 4)
+#define RBC_RA		(2 << 4)
+#define RBC_ZERO	(3 << 4)
+
+#define RBC(luma_sel, luma_bit, chroma_sel, chroma_bit) \
+	(((RBC_##luma_sel) | (luma_bit)) << 6 | \
+	 (RBC_##chroma_sel) | (chroma_bit))
+
+static const u16 rbc2axi_tiled_map[32] = {
+	RBC(ZERO, 0, ZERO, 0),
+	RBC(ZERO, 0, ZERO, 0),
+	RBC(ZERO, 0, ZERO, 0),
+	RBC(CA,   0, CA,   0),
+	RBC(CA,   1, CA,   1),
+	RBC(CA,   2, CA,   2),
+	RBC(CA,   3, CA,   3),
+	RBC(CA,   4, CA,   8),
+	RBC(CA,   8, CA,   9),
+	RBC(CA,   9, CA,  10),
+	RBC(CA,  10, CA,  11),
+	RBC(CA,  11, CA,  12),
+	RBC(CA,  12, CA,  13),
+	RBC(CA,  13, CA,  14),
+	RBC(CA,  14, CA,  15),
+	RBC(CA,  15, RA,   0),
+	RBC(RA,   0, RA,   1),
+	RBC(RA,   1, RA,   2),
+	RBC(RA,   2, RA,   3),
+	RBC(RA,   3, RA,   4),
+	RBC(RA,   4, RA,   5),
+	RBC(RA,   5, RA,   6),
+	RBC(RA,   6, RA,   7),
+	RBC(RA,   7, RA,   8),
+	RBC(RA,   8, RA,   9),
+	RBC(RA,   9, RA,  10),
+	RBC(RA,  10, RA,  11),
+	RBC(RA,  11, RA,  12),
+	RBC(RA,  12, RA,  13),
+	RBC(RA,  13, RA,  14),
+	RBC(RA,  14, RA,  15),
+	RBC(RA,  15, ZERO, 0),
+};
+
+void coda_set_gdi_regs(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	const u16 *xy2ca_map;
+	u32 xy2rbc_config;
+	int i;
+
+	switch (ctx->tiled_map_type) {
+	case GDI_LINEAR_FRAME_MAP:
+	default:
+		xy2ca_map = xy2ca_zero_map;
+		xy2rbc_config = 0;
+		break;
+	case GDI_TILED_FRAME_MB_RASTER_MAP:
+		xy2ca_map = xy2ca_tiled_map;
+		xy2rbc_config = CODA9_XY2RBC_TILED_MAP |
+				CODA9_XY2RBC_CA_INC_HOR |
+				(16 - 1) << 12 | (8 - 1) << 4;
+		break;
+	}
+
+	for (i = 0; i < 16; i++)
+		coda_write(dev, xy2ca_map[i],
+				CODA9_GDI_XY2_CAS_0 + 4 * i);
+	for (i = 0; i < 4; i++)
+		coda_write(dev, XY2(ZERO, 0, ZERO, 0),
+				CODA9_GDI_XY2_BA_0 + 4 * i);
+	for (i = 0; i < 16; i++)
+		coda_write(dev, XY2(ZERO, 0, ZERO, 0),
+				CODA9_GDI_XY2_RAS_0 + 4 * i);
+	coda_write(dev, xy2rbc_config, CODA9_GDI_XY2_RBC_CONFIG);
+	if (xy2rbc_config) {
+		for (i = 0; i < 32; i++)
+			coda_write(dev, rbc2axi_tiled_map[i],
+					CODA9_GDI_RBC2_AXI_0 + 4 * i);
+	}
+}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda.h b/drivers/media/platform/chips-media/coda/coda.h
--- a/drivers/media/platform/chips-media/coda/coda.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/coda.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,403 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Coda multi-standard codec IP
+ *
+ * Copyright (C) 2012 Vista Silicon S.L.
+ *    Javier Martin, <javier.martin@vista-silicon.com>
+ *    Xavier Duret
+ * Copyright (C) 2012-2014 Philipp Zabel, Pengutronix
+ */
+
+#ifndef __CODA_H__
+#define __CODA_H__
+
+#include <linux/debugfs.h>
+#include <linux/idr.h>
+#include <linux/irqreturn.h>
+#include <linux/mutex.h>
+#include <linux/kfifo.h>
+#include <linux/videodev2.h>
+#include <linux/ratelimit.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/videobuf2-v4l2.h>
+
+#include "coda_regs.h"
+
+#define CODA_MAX_FRAMEBUFFERS	19
+#define FMO_SLICE_SAVE_BUF_SIZE	(32)
+
+/*
+ * This control allows applications to read the per-stream
+ * (i.e. per-context) Macroblocks Error Count. This value
+ * is CODA specific.
+ */
+#define V4L2_CID_CODA_MB_ERR_CNT (V4L2_CID_USER_CODA_BASE + 0)
+
+enum {
+	V4L2_M2M_SRC = 0,
+	V4L2_M2M_DST = 1,
+};
+
+enum coda_inst_type {
+	CODA_INST_ENCODER,
+	CODA_INST_DECODER,
+};
+
+enum coda_product {
+	CODA_DX6 = 0xf001,
+	CODA_HX4 = 0xf00a,
+	CODA_7541 = 0xf012,
+	CODA_960 = 0xf020,
+};
+
+struct coda_video_device;
+
+struct coda_devtype {
+	char			*firmware[3];
+	enum coda_product	product;
+	const struct coda_codec	*codecs;
+	unsigned int		num_codecs;
+	const struct coda_video_device **vdevs;
+	unsigned int		num_vdevs;
+	size_t			workbuf_size;
+	size_t			tempbuf_size;
+	size_t			iram_size;
+};
+
+struct coda_aux_buf {
+	void			*vaddr;
+	dma_addr_t		paddr;
+	u32			size;
+	struct debugfs_blob_wrapper blob;
+	struct dentry		*dentry;
+};
+
+struct coda_dev {
+	struct v4l2_device	v4l2_dev;
+	struct video_device	vfd[6];
+	struct device		*dev;
+	const struct coda_devtype *devtype;
+	int			firmware;
+	struct vdoa_data	*vdoa;
+
+	void __iomem		*regs_base;
+	struct clk		*clk_per;
+	struct clk		*clk_ahb;
+	struct reset_control	*rstc;
+
+	struct coda_aux_buf	codebuf;
+	struct coda_aux_buf	tempbuf;
+	struct coda_aux_buf	workbuf;
+	struct gen_pool		*iram_pool;
+	struct coda_aux_buf	iram;
+
+	struct mutex		dev_mutex;
+	struct mutex		coda_mutex;
+	struct workqueue_struct	*workqueue;
+	struct v4l2_m2m_dev	*m2m_dev;
+	struct ida		ida;
+	struct dentry		*debugfs_root;
+	struct ratelimit_state	mb_err_rs;
+};
+
+struct coda_codec {
+	u32 mode;
+	u32 src_fourcc;
+	u32 dst_fourcc;
+	u32 max_w;
+	u32 max_h;
+};
+
+struct coda_huff_tab;
+
+struct coda_params {
+	u8			rot_mode;
+	u8			h264_intra_qp;
+	u8			h264_inter_qp;
+	u8			h264_min_qp;
+	u8			h264_max_qp;
+	u8			h264_disable_deblocking_filter_idc;
+	s8			h264_slice_alpha_c0_offset_div2;
+	s8			h264_slice_beta_offset_div2;
+	bool			h264_constrained_intra_pred_flag;
+	s8			h264_chroma_qp_index_offset;
+	u8			h264_profile_idc;
+	u8			h264_level_idc;
+	u8			mpeg2_profile_idc;
+	u8			mpeg2_level_idc;
+	u8			mpeg4_intra_qp;
+	u8			mpeg4_inter_qp;
+	u8			gop_size;
+	int			intra_refresh;
+	enum v4l2_jpeg_chroma_subsampling jpeg_chroma_subsampling;
+	u8			jpeg_quality;
+	u8			jpeg_restart_interval;
+	u8			*jpeg_qmat_tab[3];
+	int			jpeg_qmat_index[3];
+	int			jpeg_huff_dc_index[3];
+	int			jpeg_huff_ac_index[3];
+	u32			*jpeg_huff_data;
+	struct coda_huff_tab	*jpeg_huff_tab;
+	int			codec_mode;
+	int			codec_mode_aux;
+	enum v4l2_mpeg_video_multi_slice_mode slice_mode;
+	u32			framerate;
+	u16			bitrate;
+	u16			vbv_delay;
+	u32			vbv_size;
+	u32			slice_max_bits;
+	u32			slice_max_mb;
+	bool			force_ipicture;
+	bool			gop_size_changed;
+	bool			bitrate_changed;
+	bool			framerate_changed;
+	bool			h264_intra_qp_changed;
+	bool			intra_refresh_changed;
+	bool			slice_mode_changed;
+	bool			frame_rc_enable;
+	bool			mb_rc_enable;
+};
+
+struct coda_buffer_meta {
+	struct list_head	list;
+	u32			sequence;
+	struct v4l2_timecode	timecode;
+	u64			timestamp;
+	unsigned int		start;
+	unsigned int		end;
+	bool			last;
+};
+
+/* Per-queue, driver-specific private data */
+struct coda_q_data {
+	unsigned int		width;
+	unsigned int		height;
+	unsigned int		bytesperline;
+	unsigned int		sizeimage;
+	unsigned int		fourcc;
+	struct v4l2_rect	rect;
+};
+
+struct coda_iram_info {
+	u32		axi_sram_use;
+	phys_addr_t	buf_bit_use;
+	phys_addr_t	buf_ip_ac_dc_use;
+	phys_addr_t	buf_dbk_y_use;
+	phys_addr_t	buf_dbk_c_use;
+	phys_addr_t	buf_ovl_use;
+	phys_addr_t	buf_btp_use;
+	phys_addr_t	search_ram_paddr;
+	int		search_ram_size;
+	int		remaining;
+	phys_addr_t	next_paddr;
+};
+
+#define GDI_LINEAR_FRAME_MAP 0
+#define GDI_TILED_FRAME_MB_RASTER_MAP 1
+
+struct coda_ctx;
+
+struct coda_context_ops {
+	int (*queue_init)(void *priv, struct vb2_queue *src_vq,
+			  struct vb2_queue *dst_vq);
+	int (*reqbufs)(struct coda_ctx *ctx, struct v4l2_requestbuffers *rb);
+	int (*start_streaming)(struct coda_ctx *ctx);
+	int (*prepare_run)(struct coda_ctx *ctx);
+	void (*finish_run)(struct coda_ctx *ctx);
+	void (*run_timeout)(struct coda_ctx *ctx);
+	void (*seq_init_work)(struct work_struct *work);
+	void (*seq_end_work)(struct work_struct *work);
+	void (*release)(struct coda_ctx *ctx);
+};
+
+struct coda_internal_frame {
+	struct coda_aux_buf		buf;
+	struct coda_buffer_meta		meta;
+	u32				type;
+	u32				error;
+};
+
+struct coda_ctx {
+	struct coda_dev			*dev;
+	struct mutex			buffer_mutex;
+	struct work_struct		pic_run_work;
+	struct work_struct		seq_init_work;
+	struct work_struct		seq_end_work;
+	struct completion		completion;
+	const struct coda_video_device	*cvd;
+	const struct coda_context_ops	*ops;
+	int				aborting;
+	int				initialized;
+	int				streamon_out;
+	int				streamon_cap;
+	u32				qsequence;
+	u32				osequence;
+	u32				sequence_offset;
+	struct coda_q_data		q_data[2];
+	enum coda_inst_type		inst_type;
+	const struct coda_codec		*codec;
+	enum v4l2_colorspace		colorspace;
+	enum v4l2_xfer_func		xfer_func;
+	enum v4l2_ycbcr_encoding	ycbcr_enc;
+	enum v4l2_quantization		quantization;
+	struct coda_params		params;
+	struct v4l2_ctrl_handler	ctrls;
+	struct v4l2_ctrl		*h264_profile_ctrl;
+	struct v4l2_ctrl		*h264_level_ctrl;
+	struct v4l2_ctrl		*mpeg2_profile_ctrl;
+	struct v4l2_ctrl		*mpeg2_level_ctrl;
+	struct v4l2_ctrl		*mpeg4_profile_ctrl;
+	struct v4l2_ctrl		*mpeg4_level_ctrl;
+	struct v4l2_ctrl		*mb_err_cnt_ctrl;
+	struct v4l2_fh			fh;
+	int				gopcounter;
+	int				runcounter;
+	int				jpeg_ecs_offset;
+	char				vpu_header[3][64];
+	int				vpu_header_size[3];
+	struct kfifo			bitstream_fifo;
+	struct mutex			bitstream_mutex;
+	struct coda_aux_buf		bitstream;
+	bool				hold;
+	struct coda_aux_buf		parabuf;
+	struct coda_aux_buf		psbuf;
+	struct coda_aux_buf		slicebuf;
+	struct coda_internal_frame	internal_frames[CODA_MAX_FRAMEBUFFERS];
+	struct list_head		buffer_meta_list;
+	spinlock_t			buffer_meta_lock;
+	int				num_metas;
+	unsigned int			first_frame_sequence;
+	struct coda_aux_buf		workbuf;
+	int				num_internal_frames;
+	int				idx;
+	int				reg_idx;
+	struct coda_iram_info		iram_info;
+	int				tiled_map_type;
+	u32				bit_stream_param;
+	u32				frm_dis_flg;
+	u32				frame_mem_ctrl;
+	u32				para_change;
+	int				display_idx;
+	struct dentry			*debugfs_entry;
+	bool				use_bit;
+	bool				use_vdoa;
+	struct vdoa_ctx			*vdoa;
+	/*
+	 * wakeup mutex used to serialize encoder stop command and finish_run,
+	 * ensures that finish_run always either flags the last returned buffer
+	 * or wakes up the capture queue to signal EOS afterwards.
+	 */
+	struct mutex			wakeup_mutex;
+};
+
+extern int coda_debug;
+
+#define coda_dbg(level, ctx, fmt, arg...)				\
+	do {								\
+		if (coda_debug >= (level))				\
+			v4l2_dbg((level), coda_debug, &(ctx)->dev->v4l2_dev, \
+			 "%u: " fmt, (ctx)->idx, ##arg);		\
+	} while (0)
+
+void coda_write(struct coda_dev *dev, u32 data, u32 reg);
+unsigned int coda_read(struct coda_dev *dev, u32 reg);
+void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
+		     struct vb2_v4l2_buffer *buf, unsigned int reg_y);
+
+int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf,
+		       size_t size, const char *name, struct dentry *parent);
+void coda_free_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf);
+
+int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq,
+			    struct vb2_queue *dst_vq);
+int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq,
+			    struct vb2_queue *dst_vq);
+
+int coda_hw_reset(struct coda_ctx *ctx);
+
+void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list);
+
+void coda_set_gdi_regs(struct coda_ctx *ctx);
+
+static inline struct coda_q_data *get_q_data(struct coda_ctx *ctx,
+					     enum v4l2_buf_type type)
+{
+	switch (type) {
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+		return &(ctx->q_data[V4L2_M2M_SRC]);
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		return &(ctx->q_data[V4L2_M2M_DST]);
+	default:
+		return NULL;
+	}
+}
+
+const char *coda_product_name(int product);
+
+int coda_check_firmware(struct coda_dev *dev);
+
+static inline unsigned int coda_get_bitstream_payload(struct coda_ctx *ctx)
+{
+	return kfifo_len(&ctx->bitstream_fifo);
+}
+
+/*
+ * The bitstream prefetcher needs to read at least 2 256 byte periods past
+ * the desired bitstream position for all data to reach the decoder.
+ */
+static inline bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx,
+						 unsigned int pos)
+{
+	return (int)(ctx->bitstream_fifo.kfifo.in - ALIGN(pos, 256)) > 512;
+}
+
+bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx, unsigned int pos);
+int coda_bitstream_flush(struct coda_ctx *ctx);
+
+void coda_bit_stream_end_flag(struct coda_ctx *ctx);
+
+void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
+		       enum vb2_buffer_state state);
+
+int coda_h264_filler_nal(int size, char *p);
+int coda_h264_padding(int size, char *p);
+int coda_h264_profile(int profile_idc);
+int coda_h264_level(int level_idc);
+int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb);
+int coda_h264_sps_fixup(struct coda_ctx *ctx, int width, int height, char *buf,
+			int *size, int max_size);
+
+int coda_mpeg2_profile(int profile_idc);
+int coda_mpeg2_level(int level_idc);
+u32 coda_mpeg2_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size);
+int coda_mpeg4_profile(int profile_idc);
+int coda_mpeg4_level(int level_idc);
+u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size);
+
+void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc,
+				     u8 level_idc);
+
+static inline int coda_jpeg_scale(int src, int dst)
+{
+	return (dst <= src / 8) ? 3 :
+	       (dst <= src / 4) ? 2 :
+	       (dst <= src / 2) ? 1 : 0;
+}
+
+bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb);
+int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb);
+int coda_jpeg_write_tables(struct coda_ctx *ctx);
+void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality);
+
+extern const struct coda_context_ops coda_bit_encode_ops;
+extern const struct coda_context_ops coda_bit_decode_ops;
+extern const struct coda_context_ops coda9_jpeg_encode_ops;
+extern const struct coda_context_ops coda9_jpeg_decode_ops;
+
+irqreturn_t coda_irq_handler(int irq, void *data);
+irqreturn_t coda9_jpeg_irq_handler(int irq, void *data);
+
+#endif /* __CODA_H__ */
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-h264.c b/drivers/media/platform/chips-media/coda/coda-h264.c
--- a/drivers/media/platform/chips-media/coda/coda-h264.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/coda-h264.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,429 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Coda multi-standard codec IP - H.264 helper functions
+ *
+ * Copyright (C) 2012 Vista Silicon S.L.
+ *    Javier Martin, <javier.martin@vista-silicon.com>
+ *    Xavier Duret
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/videodev2.h>
+
+#include "coda.h"
+
+static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 };
+
+static const u8 *coda_find_nal_header(const u8 *buf, const u8 *end)
+{
+	u32 val = 0xffffffff;
+
+	do {
+		val = val << 8 | *buf++;
+		if (buf >= end)
+			return NULL;
+	} while (val != 0x00000001);
+
+	return buf;
+}
+
+int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb)
+{
+	const u8 *buf = vb2_plane_vaddr(vb, 0);
+	const u8 *end = buf + vb2_get_plane_payload(vb, 0);
+
+	/* Find SPS header */
+	do {
+		buf = coda_find_nal_header(buf, end);
+		if (!buf)
+			return -EINVAL;
+	} while ((*buf++ & 0x1f) != 0x7);
+
+	ctx->params.h264_profile_idc = buf[0];
+	ctx->params.h264_level_idc = buf[2];
+
+	return 0;
+}
+
+int coda_h264_filler_nal(int size, char *p)
+{
+	if (size < 6)
+		return -EINVAL;
+
+	p[0] = 0x00;
+	p[1] = 0x00;
+	p[2] = 0x00;
+	p[3] = 0x01;
+	p[4] = 0x0c;
+	memset(p + 5, 0xff, size - 6);
+	/* Add rbsp stop bit and trailing at the end */
+	p[size - 1] = 0x80;
+
+	return 0;
+}
+
+int coda_h264_padding(int size, char *p)
+{
+	int nal_size;
+	int diff;
+
+	diff = size - (size & ~0x7);
+	if (diff == 0)
+		return 0;
+
+	nal_size = coda_filler_size[diff];
+	coda_h264_filler_nal(nal_size, p);
+
+	return nal_size;
+}
+
+int coda_h264_profile(int profile_idc)
+{
+	switch (profile_idc) {
+	case 66: return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
+	case 77: return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
+	case 88: return V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED;
+	case 100: return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
+	default: return -EINVAL;
+	}
+}
+
+int coda_h264_level(int level_idc)
+{
+	switch (level_idc) {
+	case 10: return V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
+	case 9:  return V4L2_MPEG_VIDEO_H264_LEVEL_1B;
+	case 11: return V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
+	case 12: return V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
+	case 13: return V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
+	case 20: return V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
+	case 21: return V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
+	case 22: return V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
+	case 30: return V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
+	case 31: return V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
+	case 32: return V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
+	case 40: return V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
+	case 41: return V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
+	case 42: return V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
+	case 50: return V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
+	case 51: return V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
+	default: return -EINVAL;
+	}
+}
+
+struct rbsp {
+	char *buf;
+	int size;
+	int pos;
+};
+
+static inline int rbsp_read_bit(struct rbsp *rbsp)
+{
+	int shift = 7 - (rbsp->pos % 8);
+	int ofs = rbsp->pos++ / 8;
+
+	if (ofs >= rbsp->size)
+		return -EINVAL;
+
+	return (rbsp->buf[ofs] >> shift) & 1;
+}
+
+static inline int rbsp_write_bit(struct rbsp *rbsp, int bit)
+{
+	int shift = 7 - (rbsp->pos % 8);
+	int ofs = rbsp->pos++ / 8;
+
+	if (ofs >= rbsp->size)
+		return -EINVAL;
+
+	rbsp->buf[ofs] &= ~(1 << shift);
+	rbsp->buf[ofs] |= bit << shift;
+
+	return 0;
+}
+
+static inline int rbsp_read_bits(struct rbsp *rbsp, int num, int *val)
+{
+	int i, ret;
+	int tmp = 0;
+
+	if (num > 32)
+		return -EINVAL;
+
+	for (i = 0; i < num; i++) {
+		ret = rbsp_read_bit(rbsp);
+		if (ret < 0)
+			return ret;
+		tmp |= ret << (num - i - 1);
+	}
+
+	if (val)
+		*val = tmp;
+
+	return 0;
+}
+
+static int rbsp_write_bits(struct rbsp *rbsp, int num, int value)
+{
+	int ret;
+
+	while (num--) {
+		ret = rbsp_write_bit(rbsp, (value >> num) & 1);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int rbsp_read_uev(struct rbsp *rbsp, unsigned int *val)
+{
+	int leading_zero_bits = 0;
+	unsigned int tmp = 0;
+	int ret;
+
+	while ((ret = rbsp_read_bit(rbsp)) == 0)
+		leading_zero_bits++;
+	if (ret < 0)
+		return ret;
+
+	if (leading_zero_bits > 0) {
+		ret = rbsp_read_bits(rbsp, leading_zero_bits, &tmp);
+		if (ret)
+			return ret;
+	}
+
+	if (val)
+		*val = (1 << leading_zero_bits) - 1 + tmp;
+
+	return 0;
+}
+
+static int rbsp_write_uev(struct rbsp *rbsp, unsigned int value)
+{
+	int i;
+	int ret;
+	int tmp = value + 1;
+	int leading_zero_bits = fls(tmp) - 1;
+
+	for (i = 0; i < leading_zero_bits; i++) {
+		ret = rbsp_write_bit(rbsp, 0);
+		if (ret)
+			return ret;
+	}
+
+	return rbsp_write_bits(rbsp, leading_zero_bits + 1, tmp);
+}
+
+static int rbsp_read_sev(struct rbsp *rbsp, int *val)
+{
+	unsigned int tmp;
+	int ret;
+
+	ret = rbsp_read_uev(rbsp, &tmp);
+	if (ret)
+		return ret;
+
+	if (val) {
+		if (tmp & 1)
+			*val = (tmp + 1) / 2;
+		else
+			*val = -(tmp / 2);
+	}
+
+	return 0;
+}
+
+/**
+ * coda_h264_sps_fixup - fixes frame cropping values in h.264 SPS
+ * @ctx: encoder context
+ * @width: visible width
+ * @height: visible height
+ * @buf: buffer containing h.264 SPS RBSP, starting with NAL header
+ * @size: modified RBSP size return value
+ * @max_size: available size in buf
+ *
+ * Rewrites the frame cropping values in an h.264 SPS RBSP correctly for the
+ * given visible width and height.
+ */
+int coda_h264_sps_fixup(struct coda_ctx *ctx, int width, int height, char *buf,
+			int *size, int max_size)
+{
+	int profile_idc;
+	unsigned int pic_order_cnt_type;
+	int pic_width_in_mbs_minus1, pic_height_in_map_units_minus1;
+	int frame_mbs_only_flag, frame_cropping_flag;
+	int vui_parameters_present_flag;
+	unsigned int crop_right, crop_bottom;
+	struct rbsp sps;
+	int pos;
+	int ret;
+
+	if (*size < 8 || *size >= max_size)
+		return -EINVAL;
+
+	sps.buf = buf + 5; /* Skip NAL header */
+	sps.size = *size - 5;
+
+	profile_idc = sps.buf[0];
+	/* Skip constraint_set[0-5]_flag, reserved_zero_2bits */
+	/* Skip level_idc */
+	sps.pos = 24;
+
+	/* seq_parameter_set_id */
+	ret = rbsp_read_uev(&sps, NULL);
+	if (ret)
+		return ret;
+
+	if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 ||
+	    profile_idc == 244 || profile_idc == 44 || profile_idc == 83 ||
+	    profile_idc == 86 || profile_idc == 118 || profile_idc == 128 ||
+	    profile_idc == 138 || profile_idc == 139 || profile_idc == 134 ||
+	    profile_idc == 135) {
+		dev_err(ctx->fh.vdev->dev_parent,
+			"%s: Handling profile_idc %d not implemented\n",
+			__func__, profile_idc);
+		return -EINVAL;
+	}
+
+	/* log2_max_frame_num_minus4 */
+	ret = rbsp_read_uev(&sps, NULL);
+	if (ret)
+		return ret;
+
+	ret = rbsp_read_uev(&sps, &pic_order_cnt_type);
+	if (ret)
+		return ret;
+
+	if (pic_order_cnt_type == 0) {
+		/* log2_max_pic_order_cnt_lsb_minus4 */
+		ret = rbsp_read_uev(&sps, NULL);
+		if (ret)
+			return ret;
+	} else if (pic_order_cnt_type == 1) {
+		unsigned int i, num_ref_frames_in_pic_order_cnt_cycle;
+
+		/* delta_pic_order_always_zero_flag */
+		ret = rbsp_read_bit(&sps);
+		if (ret < 0)
+			return ret;
+		/* offset_for_non_ref_pic */
+		ret = rbsp_read_sev(&sps, NULL);
+		if (ret)
+			return ret;
+		/* offset_for_top_to_bottom_field */
+		ret = rbsp_read_sev(&sps, NULL);
+		if (ret)
+			return ret;
+
+		ret = rbsp_read_uev(&sps,
+				    &num_ref_frames_in_pic_order_cnt_cycle);
+		if (ret)
+			return ret;
+		for (i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
+			/* offset_for_ref_frame */
+			ret = rbsp_read_sev(&sps, NULL);
+			if (ret)
+				return ret;
+		}
+	}
+
+	/* max_num_ref_frames */
+	ret = rbsp_read_uev(&sps, NULL);
+	if (ret)
+		return ret;
+
+	/* gaps_in_frame_num_value_allowed_flag */
+	ret = rbsp_read_bit(&sps);
+	if (ret < 0)
+		return ret;
+	ret = rbsp_read_uev(&sps, &pic_width_in_mbs_minus1);
+	if (ret)
+		return ret;
+	ret = rbsp_read_uev(&sps, &pic_height_in_map_units_minus1);
+	if (ret)
+		return ret;
+	frame_mbs_only_flag = ret = rbsp_read_bit(&sps);
+	if (ret < 0)
+		return ret;
+	if (!frame_mbs_only_flag) {
+		/* mb_adaptive_frame_field_flag */
+		ret = rbsp_read_bit(&sps);
+		if (ret < 0)
+			return ret;
+	}
+	/* direct_8x8_inference_flag */
+	ret = rbsp_read_bit(&sps);
+	if (ret < 0)
+		return ret;
+
+	/* Mark position of the frame cropping flag */
+	pos = sps.pos;
+	frame_cropping_flag = ret = rbsp_read_bit(&sps);
+	if (ret < 0)
+		return ret;
+	if (frame_cropping_flag) {
+		unsigned int crop_left, crop_top;
+
+		ret = rbsp_read_uev(&sps, &crop_left);
+		if (ret)
+			return ret;
+		ret = rbsp_read_uev(&sps, &crop_right);
+		if (ret)
+			return ret;
+		ret = rbsp_read_uev(&sps, &crop_top);
+		if (ret)
+			return ret;
+		ret = rbsp_read_uev(&sps, &crop_bottom);
+		if (ret)
+			return ret;
+	}
+	vui_parameters_present_flag = ret = rbsp_read_bit(&sps);
+	if (ret < 0)
+		return ret;
+	if (vui_parameters_present_flag) {
+		dev_err(ctx->fh.vdev->dev_parent,
+			"%s: Handling vui_parameters not implemented\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	crop_right = round_up(width, 16) - width;
+	crop_bottom = round_up(height, 16) - height;
+	crop_right /= 2;
+	if (frame_mbs_only_flag)
+		crop_bottom /= 2;
+	else
+		crop_bottom /= 4;
+
+
+	sps.size = max_size - 5;
+	sps.pos = pos;
+	frame_cropping_flag = 1;
+	ret = rbsp_write_bit(&sps, frame_cropping_flag);
+	if (ret)
+		return ret;
+	ret = rbsp_write_uev(&sps, 0); /* crop_left */
+	if (ret)
+		return ret;
+	ret = rbsp_write_uev(&sps, crop_right);
+	if (ret)
+		return ret;
+	ret = rbsp_write_uev(&sps, 0); /* crop_top */
+	if (ret)
+		return ret;
+	ret = rbsp_write_uev(&sps, crop_bottom);
+	if (ret)
+		return ret;
+	ret = rbsp_write_bit(&sps, 0); /* vui_parameters_present_flag */
+	if (ret)
+		return ret;
+	ret = rbsp_write_bit(&sps, 1);
+	if (ret)
+		return ret;
+
+	*size = 5 + DIV_ROUND_UP(sps.pos, 8);
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-jpeg.c b/drivers/media/platform/chips-media/coda/coda-jpeg.c
--- a/drivers/media/platform/chips-media/coda/coda-jpeg.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/coda-jpeg.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,1547 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Coda multi-standard codec IP - JPEG support functions
+ *
+ * Copyright (C) 2014 Philipp Zabel, Pengutronix
+ */
+
+#include <asm/unaligned.h>
+#include <linux/irqreturn.h>
+#include <linux/kernel.h>
+#include <linux/ktime.h>
+#include <linux/slab.h>
+#include <linux/swab.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-jpeg.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "coda.h"
+#include "trace.h"
+
+#define SOI_MARKER	0xffd8
+#define APP9_MARKER	0xffe9
+#define DRI_MARKER	0xffdd
+#define DQT_MARKER	0xffdb
+#define DHT_MARKER	0xffc4
+#define SOF_MARKER	0xffc0
+#define SOS_MARKER	0xffda
+#define EOI_MARKER	0xffd9
+
+enum {
+	CODA9_JPEG_FORMAT_420,
+	CODA9_JPEG_FORMAT_422,
+	CODA9_JPEG_FORMAT_224,
+	CODA9_JPEG_FORMAT_444,
+	CODA9_JPEG_FORMAT_400,
+};
+
+struct coda_huff_tab {
+	u8 luma_dc[16 + 12];
+	u8 chroma_dc[16 + 12];
+	u8 luma_ac[16 + 162];
+	u8 chroma_ac[16 + 162];
+
+	/* DC Luma, DC Chroma, AC Luma, AC Chroma */
+	s16	min[4 * 16];
+	s16	max[4 * 16];
+	s8	ptr[4 * 16];
+};
+
+#define CODA9_JPEG_ENC_HUFF_DATA_SIZE	(256 + 256 + 16 + 16)
+
+/*
+ * Typical Huffman tables for 8-bit precision luminance and
+ * chrominance from JPEG ITU-T.81 (ISO/IEC 10918-1) Annex K.3
+ */
+
+static const unsigned char luma_dc[16 + 12] = {
+	/* bits */
+	0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* values */
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b,
+};
+
+static const unsigned char chroma_dc[16 + 12] = {
+	/* bits */
+	0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+	/* values */
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b,
+};
+
+static const unsigned char luma_ac[16 + 162 + 2] = {
+	/* bits */
+	0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
+	0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
+	/* values */
+	0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+	0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+	0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+	0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+	0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+	0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+	0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+	0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+	0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+	0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+	0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+	0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+	0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+	0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+	0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+	0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+	0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+	0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+	0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+	0xf9, 0xfa, /* padded to 32-bit */
+};
+
+static const unsigned char chroma_ac[16 + 162 + 2] = {
+	/* bits */
+	0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+	0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
+	/* values */
+	0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+	0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+	0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+	0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+	0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+	0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+	0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+	0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+	0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+	0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+	0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+	0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+	0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+	0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+	0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+	0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+	0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+	0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+	0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+	0xf9, 0xfa, /* padded to 32-bit */
+};
+
+/*
+ * Quantization tables for luminance and chrominance components in
+ * zig-zag scan order from the Freescale i.MX VPU libraries
+ */
+
+static unsigned char luma_q[64] = {
+	0x06, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x05,
+	0x05, 0x06, 0x09, 0x06, 0x05, 0x06, 0x09, 0x0b,
+	0x08, 0x06, 0x06, 0x08, 0x0b, 0x0c, 0x0a, 0x0a,
+	0x0b, 0x0a, 0x0a, 0x0c, 0x10, 0x0c, 0x0c, 0x0c,
+	0x0c, 0x0c, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, 0x0c,
+	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+};
+
+static unsigned char chroma_q[64] = {
+	0x07, 0x07, 0x07, 0x0d, 0x0c, 0x0d, 0x18, 0x10,
+	0x10, 0x18, 0x14, 0x0e, 0x0e, 0x0e, 0x14, 0x14,
+	0x0e, 0x0e, 0x0e, 0x0e, 0x14, 0x11, 0x0c, 0x0c,
+	0x0c, 0x0c, 0x0c, 0x11, 0x11, 0x0c, 0x0c, 0x0c,
+	0x0c, 0x0c, 0x0c, 0x11, 0x0c, 0x0c, 0x0c, 0x0c,
+	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+};
+
+static const unsigned char width_align[] = {
+	[CODA9_JPEG_FORMAT_420] = 16,
+	[CODA9_JPEG_FORMAT_422] = 16,
+	[CODA9_JPEG_FORMAT_224] = 8,
+	[CODA9_JPEG_FORMAT_444] = 8,
+	[CODA9_JPEG_FORMAT_400] = 8,
+};
+
+static const unsigned char height_align[] = {
+	[CODA9_JPEG_FORMAT_420] = 16,
+	[CODA9_JPEG_FORMAT_422] = 8,
+	[CODA9_JPEG_FORMAT_224] = 16,
+	[CODA9_JPEG_FORMAT_444] = 8,
+	[CODA9_JPEG_FORMAT_400] = 8,
+};
+
+static int coda9_jpeg_chroma_format(u32 pixfmt)
+{
+	switch (pixfmt) {
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_NV12:
+		return CODA9_JPEG_FORMAT_420;
+	case V4L2_PIX_FMT_YUV422P:
+		return CODA9_JPEG_FORMAT_422;
+	case V4L2_PIX_FMT_YUV444:
+		return CODA9_JPEG_FORMAT_444;
+	case V4L2_PIX_FMT_GREY:
+		return CODA9_JPEG_FORMAT_400;
+	}
+	return -EINVAL;
+}
+
+struct coda_memcpy_desc {
+	int offset;
+	const void *src;
+	size_t len;
+};
+
+static void coda_memcpy_parabuf(void *parabuf,
+				const struct coda_memcpy_desc *desc)
+{
+	u32 *dst = parabuf + desc->offset;
+	const u32 *src = desc->src;
+	int len = desc->len / 4;
+	int i;
+
+	for (i = 0; i < len; i += 2) {
+		dst[i + 1] = swab32(src[i]);
+		dst[i] = swab32(src[i + 1]);
+	}
+}
+
+int coda_jpeg_write_tables(struct coda_ctx *ctx)
+{
+	int i;
+	static const struct coda_memcpy_desc huff[8] = {
+		{ 0,   luma_dc,    sizeof(luma_dc)    },
+		{ 32,  luma_ac,    sizeof(luma_ac)    },
+		{ 216, chroma_dc,  sizeof(chroma_dc)  },
+		{ 248, chroma_ac,  sizeof(chroma_ac)  },
+	};
+	struct coda_memcpy_desc qmat[3] = {
+		{ 512, ctx->params.jpeg_qmat_tab[0], 64 },
+		{ 576, ctx->params.jpeg_qmat_tab[1], 64 },
+		{ 640, ctx->params.jpeg_qmat_tab[1], 64 },
+	};
+
+	/* Write huffman tables to parameter memory */
+	for (i = 0; i < ARRAY_SIZE(huff); i++)
+		coda_memcpy_parabuf(ctx->parabuf.vaddr, huff + i);
+
+	/* Write Q-matrix to parameter memory */
+	for (i = 0; i < ARRAY_SIZE(qmat); i++)
+		coda_memcpy_parabuf(ctx->parabuf.vaddr, qmat + i);
+
+	return 0;
+}
+
+bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb)
+{
+	void *vaddr = vb2_plane_vaddr(vb, 0);
+	u16 soi, eoi;
+	int len, i;
+
+	soi = be16_to_cpup((__be16 *)vaddr);
+	if (soi != SOI_MARKER)
+		return false;
+
+	len = vb2_get_plane_payload(vb, 0);
+	vaddr += len - 2;
+	for (i = 0; i < 32; i++) {
+		eoi = be16_to_cpup((__be16 *)(vaddr - i));
+		if (eoi == EOI_MARKER) {
+			if (i > 0)
+				vb2_set_plane_payload(vb, 0, len - i);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num);
+
+int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb)
+{
+	struct coda_dev *dev = ctx->dev;
+	u8 *buf = vb2_plane_vaddr(vb, 0);
+	size_t len = vb2_get_plane_payload(vb, 0);
+	struct v4l2_jpeg_scan_header scan_header;
+	struct v4l2_jpeg_reference quantization_tables[4] = { };
+	struct v4l2_jpeg_reference huffman_tables[4] = { };
+	struct v4l2_jpeg_header header = {
+		.scan = &scan_header,
+		.quantization_tables = quantization_tables,
+		.huffman_tables = huffman_tables,
+	};
+	struct coda_q_data *q_data_src;
+	struct coda_huff_tab *huff_tab;
+	int i, j, ret;
+
+	ret = v4l2_jpeg_parse_header(buf, len, &header);
+	if (ret < 0) {
+		v4l2_err(&dev->v4l2_dev, "failed to parse JPEG header: %pe\n",
+			 ERR_PTR(ret));
+		return ret;
+	}
+
+	ctx->params.jpeg_restart_interval = header.restart_interval;
+
+	/* check frame header */
+	if (header.frame.height > ctx->codec->max_h ||
+	    header.frame.width > ctx->codec->max_w) {
+		v4l2_err(&dev->v4l2_dev, "invalid dimensions: %dx%d\n",
+			 header.frame.width, header.frame.height);
+		return -EINVAL;
+	}
+
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	if (header.frame.height != q_data_src->height ||
+	    header.frame.width != q_data_src->width) {
+		v4l2_err(&dev->v4l2_dev,
+			 "dimensions don't match format: %dx%d\n",
+			 header.frame.width, header.frame.height);
+		return -EINVAL;
+	}
+
+	if (header.frame.num_components != 3) {
+		v4l2_err(&dev->v4l2_dev,
+			 "unsupported number of components: %d\n",
+			 header.frame.num_components);
+		return -EINVAL;
+	}
+
+	/* install quantization tables */
+	if (quantization_tables[3].start) {
+		v4l2_err(&dev->v4l2_dev,
+			 "only 3 quantization tables supported\n");
+		return -EINVAL;
+	}
+	for (i = 0; i < 3; i++) {
+		if (!quantization_tables[i].start)
+			continue;
+		if (quantization_tables[i].length != 64) {
+			v4l2_err(&dev->v4l2_dev,
+				 "only 8-bit quantization tables supported\n");
+			continue;
+		}
+		if (!ctx->params.jpeg_qmat_tab[i]) {
+			ctx->params.jpeg_qmat_tab[i] = kmalloc(64, GFP_KERNEL);
+			if (!ctx->params.jpeg_qmat_tab[i])
+				return -ENOMEM;
+		}
+		memcpy(ctx->params.jpeg_qmat_tab[i],
+		       quantization_tables[i].start, 64);
+	}
+
+	/* install Huffman tables */
+	for (i = 0; i < 4; i++) {
+		if (!huffman_tables[i].start) {
+			v4l2_err(&dev->v4l2_dev, "missing Huffman table\n");
+			return -EINVAL;
+		}
+		/* AC tables should be between 17 -> 178, DC between 17 -> 28 */
+		if (huffman_tables[i].length < 17 ||
+		    huffman_tables[i].length > 178 ||
+		    ((i & 2) == 0 && huffman_tables[i].length > 28)) {
+			v4l2_err(&dev->v4l2_dev,
+				 "invalid Huffman table %d length: %zu\n",
+				 i, huffman_tables[i].length);
+			return -EINVAL;
+		}
+	}
+	huff_tab = ctx->params.jpeg_huff_tab;
+	if (!huff_tab) {
+		huff_tab = kzalloc(sizeof(struct coda_huff_tab), GFP_KERNEL);
+		if (!huff_tab)
+			return -ENOMEM;
+		ctx->params.jpeg_huff_tab = huff_tab;
+	}
+
+	memset(huff_tab, 0, sizeof(*huff_tab));
+	memcpy(huff_tab->luma_dc, huffman_tables[0].start, huffman_tables[0].length);
+	memcpy(huff_tab->chroma_dc, huffman_tables[1].start, huffman_tables[1].length);
+	memcpy(huff_tab->luma_ac, huffman_tables[2].start, huffman_tables[2].length);
+	memcpy(huff_tab->chroma_ac, huffman_tables[3].start, huffman_tables[3].length);
+
+	/* check scan header */
+	for (i = 0; i < scan_header.num_components; i++) {
+		struct v4l2_jpeg_scan_component_spec *scan_component;
+
+		scan_component = &scan_header.component[i];
+		for (j = 0; j < header.frame.num_components; j++) {
+			if (header.frame.component[j].component_identifier ==
+			    scan_component->component_selector)
+				break;
+		}
+		if (j == header.frame.num_components)
+			continue;
+
+		ctx->params.jpeg_huff_dc_index[j] =
+			scan_component->dc_entropy_coding_table_selector;
+		ctx->params.jpeg_huff_ac_index[j] =
+			scan_component->ac_entropy_coding_table_selector;
+	}
+
+	/* Generate Huffman table information */
+	for (i = 0; i < 4; i++)
+		coda9_jpeg_gen_dec_huff_tab(ctx, i);
+
+	/* start of entropy coded segment */
+	ctx->jpeg_ecs_offset = header.ecs_offset;
+
+	switch (header.frame.subsampling) {
+	case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+	case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
+		ctx->params.jpeg_chroma_subsampling = header.frame.subsampling;
+		break;
+	default:
+		v4l2_err(&dev->v4l2_dev, "chroma subsampling not supported: %d",
+			 header.frame.subsampling);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static inline void coda9_jpeg_write_huff_values(struct coda_dev *dev, u8 *bits,
+						int num_values)
+{
+	s8 *values = (s8 *)(bits + 16);
+	int huff_length, i;
+
+	for (huff_length = 0, i = 0; i < 16; i++)
+		huff_length += bits[i];
+	for (i = huff_length; i < num_values; i++)
+		values[i] = -1;
+	for (i = 0; i < num_values; i++)
+		coda_write(dev, (s32)values[i], CODA9_REG_JPEG_HUFF_DATA);
+}
+
+static void coda9_jpeg_dec_huff_setup(struct coda_ctx *ctx)
+{
+	struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab;
+	struct coda_dev *dev = ctx->dev;
+	s16 *huff_min = huff_tab->min;
+	s16 *huff_max = huff_tab->max;
+	s8 *huff_ptr = huff_tab->ptr;
+	int i;
+
+	/* MIN Tables */
+	coda_write(dev, 0x003, CODA9_REG_JPEG_HUFF_CTRL);
+	coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_ADDR);
+	for (i = 0; i < 4 * 16; i++)
+		coda_write(dev, (s32)huff_min[i], CODA9_REG_JPEG_HUFF_DATA);
+
+	/* MAX Tables */
+	coda_write(dev, 0x403, CODA9_REG_JPEG_HUFF_CTRL);
+	coda_write(dev, 0x440, CODA9_REG_JPEG_HUFF_ADDR);
+	for (i = 0; i < 4 * 16; i++)
+		coda_write(dev, (s32)huff_max[i], CODA9_REG_JPEG_HUFF_DATA);
+
+	/* PTR Tables */
+	coda_write(dev, 0x803, CODA9_REG_JPEG_HUFF_CTRL);
+	coda_write(dev, 0x880, CODA9_REG_JPEG_HUFF_ADDR);
+	for (i = 0; i < 4 * 16; i++)
+		coda_write(dev, (s32)huff_ptr[i], CODA9_REG_JPEG_HUFF_DATA);
+
+	/* VAL Tables: DC Luma, DC Chroma, AC Luma, AC Chroma */
+	coda_write(dev, 0xc03, CODA9_REG_JPEG_HUFF_CTRL);
+	coda9_jpeg_write_huff_values(dev, huff_tab->luma_dc, 12);
+	coda9_jpeg_write_huff_values(dev, huff_tab->chroma_dc, 12);
+	coda9_jpeg_write_huff_values(dev, huff_tab->luma_ac, 162);
+	coda9_jpeg_write_huff_values(dev, huff_tab->chroma_ac, 162);
+	coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_CTRL);
+}
+
+static inline void coda9_jpeg_write_qmat_tab(struct coda_dev *dev,
+					     u8 *qmat, int index)
+{
+	int i;
+
+	coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL);
+	for (i = 0; i < 64; i++)
+		coda_write(dev, qmat[i], CODA9_REG_JPEG_QMAT_DATA);
+	coda_write(dev, 0, CODA9_REG_JPEG_QMAT_CTRL);
+}
+
+static void coda9_jpeg_qmat_setup(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	int *qmat_index = ctx->params.jpeg_qmat_index;
+	u8 **qmat_tab = ctx->params.jpeg_qmat_tab;
+
+	coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[0]], 0x00);
+	coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[1]], 0x40);
+	coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[2]], 0x80);
+}
+
+static void coda9_jpeg_dec_bbc_gbu_setup(struct coda_ctx *ctx,
+					 struct vb2_buffer *buf, u32 ecs_offset)
+{
+	struct coda_dev *dev = ctx->dev;
+	int page_ptr, word_ptr, bit_ptr;
+	u32 bbc_base_addr, end_addr;
+	int bbc_cur_pos;
+	int ret, val;
+
+	bbc_base_addr = vb2_dma_contig_plane_dma_addr(buf, 0);
+	end_addr = bbc_base_addr + vb2_get_plane_payload(buf, 0);
+
+	page_ptr = ecs_offset / 256;
+	word_ptr = (ecs_offset % 256) / 4;
+	if (page_ptr & 1)
+		word_ptr += 64;
+	bit_ptr = (ecs_offset % 4) * 8;
+	if (word_ptr & 1)
+		bit_ptr += 32;
+	word_ptr &= ~0x1;
+
+	coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_WR_PTR);
+	coda_write(dev, bbc_base_addr, CODA9_REG_JPEG_BBC_BAS_ADDR);
+
+	/* Leave 3 256-byte page margin to avoid a BBC interrupt */
+	coda_write(dev, end_addr + 256 * 3 + 256, CODA9_REG_JPEG_BBC_END_ADDR);
+	val = DIV_ROUND_UP(vb2_plane_size(buf, 0), 256) + 3;
+	coda_write(dev, BIT(31) | val, CODA9_REG_JPEG_BBC_STRM_CTRL);
+
+	bbc_cur_pos = page_ptr;
+	coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS);
+	coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8),
+			CODA9_REG_JPEG_BBC_EXT_ADDR);
+	coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR);
+	coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT);
+	coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND);
+	do {
+		ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY);
+	} while (ret == 1);
+
+	bbc_cur_pos++;
+	coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS);
+	coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8),
+			CODA9_REG_JPEG_BBC_EXT_ADDR);
+	coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR);
+	coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT);
+	coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND);
+	do {
+		ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY);
+	} while (ret == 1);
+
+	bbc_cur_pos++;
+	coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS);
+	coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL);
+
+	coda_write(dev, 0, CODA9_REG_JPEG_GBU_TT_CNT);
+	coda_write(dev, word_ptr, CODA9_REG_JPEG_GBU_WD_PTR);
+	coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR);
+	coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER);
+	if (page_ptr & 1) {
+		coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBIR);
+		coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBHR);
+	} else {
+		coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR);
+		coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR);
+	}
+	coda_write(dev, 4, CODA9_REG_JPEG_GBU_CTRL);
+	coda_write(dev, bit_ptr, CODA9_REG_JPEG_GBU_FF_RPTR);
+	coda_write(dev, 3, CODA9_REG_JPEG_GBU_CTRL);
+}
+
+static const int bus_req_num[] = {
+	[CODA9_JPEG_FORMAT_420] = 2,
+	[CODA9_JPEG_FORMAT_422] = 3,
+	[CODA9_JPEG_FORMAT_224] = 3,
+	[CODA9_JPEG_FORMAT_444] = 4,
+	[CODA9_JPEG_FORMAT_400] = 4,
+};
+
+#define MCU_INFO(mcu_block_num, comp_num, comp0_info, comp1_info, comp2_info) \
+	(((mcu_block_num) << CODA9_JPEG_MCU_BLOCK_NUM_OFFSET) | \
+	 ((comp_num) << CODA9_JPEG_COMP_NUM_OFFSET) | \
+	 ((comp0_info) << CODA9_JPEG_COMP0_INFO_OFFSET) | \
+	 ((comp1_info) << CODA9_JPEG_COMP1_INFO_OFFSET) | \
+	 ((comp2_info) << CODA9_JPEG_COMP2_INFO_OFFSET))
+
+static const u32 mcu_info[] = {
+	[CODA9_JPEG_FORMAT_420] = MCU_INFO(6, 3, 10, 5, 5),
+	[CODA9_JPEG_FORMAT_422] = MCU_INFO(4, 3, 9, 5, 5),
+	[CODA9_JPEG_FORMAT_224] = MCU_INFO(4, 3, 6, 5, 5),
+	[CODA9_JPEG_FORMAT_444] = MCU_INFO(3, 3, 5, 5, 5),
+	[CODA9_JPEG_FORMAT_400] = MCU_INFO(1, 1, 5, 0, 0),
+};
+
+/*
+ * Convert Huffman table specifcations to tables of codes and code lengths.
+ * For reference, see JPEG ITU-T.81 (ISO/IEC 10918-1) [1]
+ *
+ * [1] https://www.w3.org/Graphics/JPEG/itu-t81.pdf
+ */
+static int coda9_jpeg_gen_enc_huff_tab(struct coda_ctx *ctx, int tab_num,
+				       int *ehufsi, int *ehufco)
+{
+	int i, j, k, lastk, si, code, maxsymbol;
+	const u8 *bits, *huffval;
+	struct {
+		int size[256];
+		int code[256];
+	} *huff;
+	static const unsigned char *huff_tabs[4] = {
+		luma_dc, luma_ac, chroma_dc, chroma_ac,
+	};
+	int ret = -EINVAL;
+
+	huff = kzalloc(sizeof(*huff), GFP_KERNEL);
+	if (!huff)
+		return -ENOMEM;
+
+	bits = huff_tabs[tab_num];
+	huffval = huff_tabs[tab_num] + 16;
+
+	maxsymbol = tab_num & 1 ? 256 : 16;
+
+	/* Figure C.1 - Generation of table of Huffman code sizes */
+	k = 0;
+	for (i = 1; i <= 16; i++) {
+		j = bits[i - 1];
+		if (k + j > maxsymbol)
+			goto out;
+		while (j--)
+			huff->size[k++] = i;
+	}
+	lastk = k;
+
+	/* Figure C.2 - Generation of table of Huffman codes */
+	k = 0;
+	code = 0;
+	si = huff->size[0];
+	while (k < lastk) {
+		while (huff->size[k] == si) {
+			huff->code[k++] = code;
+			code++;
+		}
+		if (code >= (1 << si))
+			goto out;
+		code <<= 1;
+		si++;
+	}
+
+	/* Figure C.3 - Ordering procedure for encoding procedure code tables */
+	for (k = 0; k < lastk; k++) {
+		i = huffval[k];
+		if (i >= maxsymbol || ehufsi[i])
+			goto out;
+		ehufco[i] = huff->code[k];
+		ehufsi[i] = huff->size[k];
+	}
+
+	ret = 0;
+out:
+	kfree(huff);
+	return ret;
+}
+
+#define DC_TABLE_INDEX0		    0
+#define AC_TABLE_INDEX0		    1
+#define DC_TABLE_INDEX1		    2
+#define AC_TABLE_INDEX1		    3
+
+static u8 *coda9_jpeg_get_huff_bits(struct coda_ctx *ctx, int tab_num)
+{
+	struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab;
+
+	if (!huff_tab)
+		return NULL;
+
+	switch (tab_num) {
+	case DC_TABLE_INDEX0: return huff_tab->luma_dc;
+	case AC_TABLE_INDEX0: return huff_tab->luma_ac;
+	case DC_TABLE_INDEX1: return huff_tab->chroma_dc;
+	case AC_TABLE_INDEX1: return huff_tab->chroma_ac;
+	}
+
+	return NULL;
+}
+
+static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num)
+{
+	int ptr_cnt = 0, huff_code = 0, zero_flag = 0, data_flag = 0;
+	u8 *huff_bits;
+	s16 *huff_max;
+	s16 *huff_min;
+	s8 *huff_ptr;
+	int ofs;
+	int i;
+
+	huff_bits = coda9_jpeg_get_huff_bits(ctx, tab_num);
+	if (!huff_bits)
+		return -EINVAL;
+
+	/* DC/AC Luma, DC/AC Chroma -> DC Luma/Chroma, AC Luma/Chroma */
+	ofs = ((tab_num & 1) << 1) | ((tab_num >> 1) & 1);
+	ofs *= 16;
+
+	huff_ptr = ctx->params.jpeg_huff_tab->ptr + ofs;
+	huff_max = ctx->params.jpeg_huff_tab->max + ofs;
+	huff_min = ctx->params.jpeg_huff_tab->min + ofs;
+
+	for (i = 0; i < 16; i++) {
+		if (huff_bits[i]) {
+			huff_ptr[i] = ptr_cnt;
+			ptr_cnt += huff_bits[i];
+			huff_min[i] = huff_code;
+			huff_max[i] = huff_code + (huff_bits[i] - 1);
+			data_flag = 1;
+			zero_flag = 0;
+		} else {
+			huff_ptr[i] = -1;
+			huff_min[i] = -1;
+			huff_max[i] = -1;
+			zero_flag = 1;
+		}
+
+		if (data_flag == 1) {
+			if (zero_flag == 1)
+				huff_code <<= 1;
+			else
+				huff_code = (huff_max[i] + 1) << 1;
+		}
+	}
+
+	return 0;
+}
+
+static int coda9_jpeg_load_huff_tab(struct coda_ctx *ctx)
+{
+	struct {
+		int size[4][256];
+		int code[4][256];
+	} *huff;
+	u32 *huff_data;
+	int i, j;
+	int ret;
+
+	huff = kzalloc(sizeof(*huff), GFP_KERNEL);
+	if (!huff)
+		return -ENOMEM;
+
+	/* Generate all four (luma/chroma DC/AC) code/size lookup tables */
+	for (i = 0; i < 4; i++) {
+		ret = coda9_jpeg_gen_enc_huff_tab(ctx, i, huff->size[i],
+						  huff->code[i]);
+		if (ret)
+			goto out;
+	}
+
+	if (!ctx->params.jpeg_huff_data) {
+		ctx->params.jpeg_huff_data =
+			kzalloc(sizeof(u32) * CODA9_JPEG_ENC_HUFF_DATA_SIZE,
+				GFP_KERNEL);
+		if (!ctx->params.jpeg_huff_data) {
+			ret = -ENOMEM;
+			goto out;
+		}
+	}
+	huff_data = ctx->params.jpeg_huff_data;
+
+	for (j = 0; j < 4; j++) {
+		/* Store Huffman lookup tables in AC0, AC1, DC0, DC1 order */
+		int t = (j == 0) ? AC_TABLE_INDEX0 :
+			(j == 1) ? AC_TABLE_INDEX1 :
+			(j == 2) ? DC_TABLE_INDEX0 :
+				   DC_TABLE_INDEX1;
+		/* DC tables only have 16 entries */
+		int len = (j < 2) ? 256 : 16;
+
+		for (i = 0; i < len; i++) {
+			if (huff->size[t][i] == 0 && huff->code[t][i] == 0)
+				*(huff_data++) = 0;
+			else
+				*(huff_data++) =
+					((huff->size[t][i] - 1) << 16) |
+					huff->code[t][i];
+		}
+	}
+
+	ret = 0;
+out:
+	kfree(huff);
+	return ret;
+}
+
+static void coda9_jpeg_write_huff_tab(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	u32 *huff_data = ctx->params.jpeg_huff_data;
+	int i;
+
+	/* Write Huffman size/code lookup tables in AC0, AC1, DC0, DC1 order */
+	coda_write(dev, 0x3, CODA9_REG_JPEG_HUFF_CTRL);
+	for (i = 0; i < CODA9_JPEG_ENC_HUFF_DATA_SIZE; i++)
+		coda_write(dev, *(huff_data++), CODA9_REG_JPEG_HUFF_DATA);
+	coda_write(dev, 0x0, CODA9_REG_JPEG_HUFF_CTRL);
+}
+
+static inline void coda9_jpeg_write_qmat_quotients(struct coda_dev *dev,
+						   u8 *qmat, int index)
+{
+	int i;
+
+	coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL);
+	for (i = 0; i < 64; i++)
+		coda_write(dev, 0x80000 / qmat[i], CODA9_REG_JPEG_QMAT_DATA);
+	coda_write(dev, index, CODA9_REG_JPEG_QMAT_CTRL);
+}
+
+static void coda9_jpeg_load_qmat_tab(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	u8 *luma_tab;
+	u8 *chroma_tab;
+
+	luma_tab = ctx->params.jpeg_qmat_tab[0];
+	if (!luma_tab)
+		luma_tab = luma_q;
+
+	chroma_tab = ctx->params.jpeg_qmat_tab[1];
+	if (!chroma_tab)
+		chroma_tab = chroma_q;
+
+	coda9_jpeg_write_qmat_quotients(dev, luma_tab, 0x00);
+	coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x40);
+	coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x80);
+}
+
+struct coda_jpeg_stream {
+	u8 *curr;
+	u8 *end;
+};
+
+static inline int coda_jpeg_put_byte(u8 byte, struct coda_jpeg_stream *stream)
+{
+	if (stream->curr >= stream->end)
+		return -EINVAL;
+
+	*stream->curr++ = byte;
+
+	return 0;
+}
+
+static inline int coda_jpeg_put_word(u16 word, struct coda_jpeg_stream *stream)
+{
+	if (stream->curr + sizeof(__be16) > stream->end)
+		return -EINVAL;
+
+	put_unaligned_be16(word, stream->curr);
+	stream->curr += sizeof(__be16);
+
+	return 0;
+}
+
+static int coda_jpeg_put_table(u16 marker, u8 index, const u8 *table,
+			       size_t len, struct coda_jpeg_stream *stream)
+{
+	int i, ret;
+
+	ret = coda_jpeg_put_word(marker, stream);
+	if (ret < 0)
+		return ret;
+	ret = coda_jpeg_put_word(3 + len, stream);
+	if (ret < 0)
+		return ret;
+	ret = coda_jpeg_put_byte(index, stream);
+	for (i = 0; i < len && ret == 0; i++)
+		ret = coda_jpeg_put_byte(table[i], stream);
+
+	return ret;
+}
+
+static int coda_jpeg_define_quantization_table(struct coda_ctx *ctx, u8 index,
+					       struct coda_jpeg_stream *stream)
+{
+	return coda_jpeg_put_table(DQT_MARKER, index,
+				   ctx->params.jpeg_qmat_tab[index], 64,
+				   stream);
+}
+
+static int coda_jpeg_define_huffman_table(u8 index, const u8 *table, size_t len,
+					  struct coda_jpeg_stream *stream)
+{
+	return coda_jpeg_put_table(DHT_MARKER, index, table, len, stream);
+}
+
+static int coda9_jpeg_encode_header(struct coda_ctx *ctx, int len, u8 *buf)
+{
+	struct coda_jpeg_stream stream = { buf, buf + len };
+	struct coda_q_data *q_data_src;
+	int chroma_format, comp_num;
+	int i, ret, pad;
+
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc);
+	if (chroma_format < 0)
+		return 0;
+
+	/* Start Of Image */
+	ret = coda_jpeg_put_word(SOI_MARKER, &stream);
+	if (ret < 0)
+		return ret;
+
+	/* Define Restart Interval */
+	if (ctx->params.jpeg_restart_interval) {
+		ret = coda_jpeg_put_word(DRI_MARKER, &stream);
+		if (ret < 0)
+			return ret;
+		ret = coda_jpeg_put_word(4, &stream);
+		if (ret < 0)
+			return ret;
+		ret = coda_jpeg_put_word(ctx->params.jpeg_restart_interval,
+					 &stream);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Define Quantization Tables */
+	ret = coda_jpeg_define_quantization_table(ctx, 0x00, &stream);
+	if (ret < 0)
+		return ret;
+	if (chroma_format != CODA9_JPEG_FORMAT_400) {
+		ret = coda_jpeg_define_quantization_table(ctx, 0x01, &stream);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Define Huffman Tables */
+	ret = coda_jpeg_define_huffman_table(0x00, luma_dc, 16 + 12, &stream);
+	if (ret < 0)
+		return ret;
+	ret = coda_jpeg_define_huffman_table(0x10, luma_ac, 16 + 162, &stream);
+	if (ret < 0)
+		return ret;
+	if (chroma_format != CODA9_JPEG_FORMAT_400) {
+		ret = coda_jpeg_define_huffman_table(0x01, chroma_dc, 16 + 12,
+						     &stream);
+		if (ret < 0)
+			return ret;
+		ret = coda_jpeg_define_huffman_table(0x11, chroma_ac, 16 + 162,
+						     &stream);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Start Of Frame */
+	ret = coda_jpeg_put_word(SOF_MARKER, &stream);
+	if (ret < 0)
+		return ret;
+	comp_num = (chroma_format == CODA9_JPEG_FORMAT_400) ? 1 : 3;
+	ret = coda_jpeg_put_word(8 + comp_num * 3, &stream);
+	if (ret < 0)
+		return ret;
+	ret = coda_jpeg_put_byte(0x08, &stream);
+	if (ret < 0)
+		return ret;
+	ret = coda_jpeg_put_word(q_data_src->height, &stream);
+	if (ret < 0)
+		return ret;
+	ret = coda_jpeg_put_word(q_data_src->width, &stream);
+	if (ret < 0)
+		return ret;
+	ret = coda_jpeg_put_byte(comp_num, &stream);
+	if (ret < 0)
+		return ret;
+	for (i = 0; i < comp_num; i++) {
+		static unsigned char subsampling[5][3] = {
+			[CODA9_JPEG_FORMAT_420] = { 0x22, 0x11, 0x11 },
+			[CODA9_JPEG_FORMAT_422] = { 0x21, 0x11, 0x11 },
+			[CODA9_JPEG_FORMAT_224] = { 0x12, 0x11, 0x11 },
+			[CODA9_JPEG_FORMAT_444] = { 0x11, 0x11, 0x11 },
+			[CODA9_JPEG_FORMAT_400] = { 0x11 },
+		};
+
+		/* Component identifier, matches SOS */
+		ret = coda_jpeg_put_byte(i + 1, &stream);
+		if (ret < 0)
+			return ret;
+		ret = coda_jpeg_put_byte(subsampling[chroma_format][i],
+					 &stream);
+		if (ret < 0)
+			return ret;
+		/* Chroma table index */
+		ret = coda_jpeg_put_byte((i == 0) ? 0 : 1, &stream);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* Pad to multiple of 8 bytes */
+	pad = (stream.curr - buf) % 8;
+	if (pad) {
+		pad = 8 - pad;
+		while (pad--) {
+			ret = coda_jpeg_put_byte(0x00, &stream);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	return stream.curr - buf;
+}
+
+/*
+ * Scale quantization table using nonlinear scaling factor
+ * u8 qtab[64], scale [50,190]
+ */
+static void coda_scale_quant_table(u8 *q_tab, int scale)
+{
+	unsigned int temp;
+	int i;
+
+	for (i = 0; i < 64; i++) {
+		temp = DIV_ROUND_CLOSEST((unsigned int)q_tab[i] * scale, 100);
+		if (temp <= 0)
+			temp = 1;
+		if (temp > 255)
+			temp = 255;
+		q_tab[i] = (unsigned char)temp;
+	}
+}
+
+void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality)
+{
+	unsigned int scale;
+
+	ctx->params.jpeg_quality = quality;
+
+	/* Clip quality setting to [5,100] interval */
+	if (quality > 100)
+		quality = 100;
+	if (quality < 5)
+		quality = 5;
+
+	/*
+	 * Non-linear scaling factor:
+	 * [5,50] -> [1000..100], [51,100] -> [98..0]
+	 */
+	if (quality < 50)
+		scale = 5000 / quality;
+	else
+		scale = 200 - 2 * quality;
+
+	if (ctx->params.jpeg_qmat_tab[0]) {
+		memcpy(ctx->params.jpeg_qmat_tab[0], luma_q, 64);
+		coda_scale_quant_table(ctx->params.jpeg_qmat_tab[0], scale);
+	}
+	if (ctx->params.jpeg_qmat_tab[1]) {
+		memcpy(ctx->params.jpeg_qmat_tab[1], chroma_q, 64);
+		coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale);
+	}
+}
+
+/*
+ * Encoder context operations
+ */
+
+static int coda9_jpeg_start_encoding(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	int ret;
+
+	ret = coda9_jpeg_load_huff_tab(ctx);
+	if (ret < 0) {
+		v4l2_err(&dev->v4l2_dev, "error loading Huffman tables\n");
+		return ret;
+	}
+	if (!ctx->params.jpeg_qmat_tab[0]) {
+		ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL);
+		if (!ctx->params.jpeg_qmat_tab[0])
+			return -ENOMEM;
+	}
+	if (!ctx->params.jpeg_qmat_tab[1]) {
+		ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL);
+		if (!ctx->params.jpeg_qmat_tab[1])
+			return -ENOMEM;
+	}
+	coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality);
+
+	return 0;
+}
+
+static int coda9_jpeg_prepare_encode(struct coda_ctx *ctx)
+{
+	struct coda_q_data *q_data_src;
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	struct coda_dev *dev = ctx->dev;
+	u32 start_addr, end_addr;
+	u16 aligned_width, aligned_height;
+	bool chroma_interleave;
+	int chroma_format;
+	int header_len;
+	int ret;
+	ktime_t timeout;
+
+	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+
+	if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0)
+		vb2_set_plane_payload(&src_buf->vb2_buf, 0,
+				      vb2_plane_size(&src_buf->vb2_buf, 0));
+
+	src_buf->sequence = ctx->osequence;
+	dst_buf->sequence = ctx->osequence;
+	ctx->osequence++;
+
+	src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
+	src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME;
+
+	coda_set_gdi_regs(ctx);
+
+	start_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
+	end_addr = start_addr + vb2_plane_size(&dst_buf->vb2_buf, 0);
+
+	chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc);
+	if (chroma_format < 0)
+		return chroma_format;
+
+	/* Round image dimensions to multiple of MCU size */
+	aligned_width = round_up(q_data_src->width, width_align[chroma_format]);
+	aligned_height = round_up(q_data_src->height,
+				  height_align[chroma_format]);
+	if (aligned_width != q_data_src->bytesperline) {
+		v4l2_err(&dev->v4l2_dev, "wrong stride: %d instead of %d\n",
+			 aligned_width, q_data_src->bytesperline);
+	}
+
+	header_len =
+		coda9_jpeg_encode_header(ctx,
+					 vb2_plane_size(&dst_buf->vb2_buf, 0),
+					 vb2_plane_vaddr(&dst_buf->vb2_buf, 0));
+	if (header_len < 0)
+		return header_len;
+
+	coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_BAS_ADDR);
+	coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_END_ADDR);
+	coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_WR_PTR);
+	coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_RD_PTR);
+	coda_write(dev, 0, CODA9_REG_JPEG_BBC_CUR_POS);
+	/* 64 words per 256-byte page */
+	coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT);
+	coda_write(dev, start_addr, CODA9_REG_JPEG_BBC_EXT_ADDR);
+	coda_write(dev, 0, CODA9_REG_JPEG_BBC_INT_ADDR);
+
+	coda_write(dev, 0, CODA9_REG_JPEG_GBU_BT_PTR);
+	coda_write(dev, 0, CODA9_REG_JPEG_GBU_WD_PTR);
+	coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR);
+	coda_write(dev, BIT(31) | ((end_addr - start_addr - header_len) / 256),
+		   CODA9_REG_JPEG_BBC_STRM_CTRL);
+	coda_write(dev, 0, CODA9_REG_JPEG_GBU_CTRL);
+	coda_write(dev, 0, CODA9_REG_JPEG_GBU_FF_RPTR);
+	coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER);
+	coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR);
+	coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR);
+
+	chroma_interleave = (q_data_src->fourcc == V4L2_PIX_FMT_NV12);
+	coda_write(dev, CODA9_JPEG_PIC_CTRL_TC_DIRECTION |
+		   CODA9_JPEG_PIC_CTRL_ENCODER_EN, CODA9_REG_JPEG_PIC_CTRL);
+	coda_write(dev, 0, CODA9_REG_JPEG_SCL_INFO);
+	coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG);
+	coda_write(dev, ctx->params.jpeg_restart_interval,
+		   CODA9_REG_JPEG_RST_INTVAL);
+	coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL);
+
+	coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO);
+
+	coda9_jpeg_write_huff_tab(ctx);
+	coda9_jpeg_load_qmat_tab(ctx);
+
+	if (ctx->params.rot_mode & CODA_ROT_90) {
+		aligned_width = aligned_height;
+		aligned_height = q_data_src->bytesperline;
+		if (chroma_format == CODA9_JPEG_FORMAT_422)
+			chroma_format = CODA9_JPEG_FORMAT_224;
+		else if (chroma_format == CODA9_JPEG_FORMAT_224)
+			chroma_format = CODA9_JPEG_FORMAT_422;
+	}
+	/* These need to be multiples of MCU size */
+	coda_write(dev, aligned_width << 16 | aligned_height,
+		   CODA9_REG_JPEG_PIC_SIZE);
+	coda_write(dev, ctx->params.rot_mode ?
+		   (CODA_ROT_MIR_ENABLE | ctx->params.rot_mode) : 0,
+		   CODA9_REG_JPEG_ROT_INFO);
+
+	coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO);
+
+	coda_write(dev, 1, CODA9_GDI_CONTROL);
+	timeout = ktime_add_us(ktime_get(), 100000);
+	do {
+		ret = coda_read(dev, CODA9_GDI_STATUS);
+		if (ktime_compare(ktime_get(), timeout) > 0) {
+			v4l2_err(&dev->v4l2_dev, "timeout waiting for GDI\n");
+			return -ETIMEDOUT;
+		}
+	} while (!ret);
+
+	coda_write(dev, (chroma_format << 17) | (chroma_interleave << 16) |
+		   q_data_src->bytesperline, CODA9_GDI_INFO_CONTROL);
+	/* The content of this register seems to be irrelevant: */
+	coda_write(dev, aligned_width << 16 | aligned_height,
+		   CODA9_GDI_INFO_PIC_SIZE);
+
+	coda_write_base(ctx, q_data_src, src_buf, CODA9_GDI_INFO_BASE_Y);
+
+	coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00);
+	coda_write(dev, 0, CODA9_GDI_CONTROL);
+	coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST);
+
+	coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR);
+	coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
+
+	trace_coda_jpeg_run(ctx, src_buf);
+
+	coda_write(dev, 1, CODA9_REG_JPEG_PIC_START);
+
+	return 0;
+}
+
+static void coda9_jpeg_finish_encode(struct coda_ctx *ctx)
+{
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	struct coda_dev *dev = ctx->dev;
+	u32 wr_ptr, start_ptr;
+	u32 err_mb;
+
+	if (ctx->aborting) {
+		coda_write(ctx->dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD);
+		return;
+	}
+
+	/*
+	 * Lock to make sure that an encoder stop command running in parallel
+	 * will either already have marked src_buf as last, or it will wake up
+	 * the capture queue after the buffers are returned.
+	 */
+	mutex_lock(&ctx->wakeup_mutex);
+	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+	trace_coda_jpeg_done(ctx, dst_buf);
+
+	/*
+	 * Set plane payload to the number of bytes written out
+	 * by the JPEG processing unit
+	 */
+	start_ptr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
+	wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR);
+	vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr);
+
+	err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB);
+	if (err_mb)
+		coda_dbg(1, ctx, "ERRMB: 0x%x\n", err_mb);
+
+	coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD);
+
+	dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST);
+	dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
+	dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST;
+
+	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
+
+	v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+	coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR :
+						 VB2_BUF_STATE_DONE);
+	mutex_unlock(&ctx->wakeup_mutex);
+
+	coda_dbg(1, ctx, "job finished: encoded frame (%u)%s\n",
+		 dst_buf->sequence,
+		 (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : "");
+
+	/*
+	 * Reset JPEG processing unit after each encode run to work
+	 * around hangups when switching context between encoder and
+	 * decoder.
+	 */
+	coda_hw_reset(ctx);
+}
+
+static void coda9_jpeg_encode_timeout(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	u32 end_addr, wr_ptr;
+
+	/* Handle missing BBC overflow interrupt via timeout */
+	end_addr = coda_read(dev, CODA9_REG_JPEG_BBC_END_ADDR);
+	wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR);
+	if (wr_ptr >= end_addr - 256) {
+		v4l2_err(&dev->v4l2_dev, "JPEG too large for capture buffer\n");
+		coda9_jpeg_finish_encode(ctx);
+		return;
+	}
+
+	coda_hw_reset(ctx);
+}
+
+static void coda9_jpeg_release(struct coda_ctx *ctx)
+{
+	int i;
+
+	if (ctx->params.jpeg_qmat_tab[0] == luma_q)
+		ctx->params.jpeg_qmat_tab[0] = NULL;
+	if (ctx->params.jpeg_qmat_tab[1] == chroma_q)
+		ctx->params.jpeg_qmat_tab[1] = NULL;
+	for (i = 0; i < 3; i++)
+		kfree(ctx->params.jpeg_qmat_tab[i]);
+	kfree(ctx->params.jpeg_huff_data);
+	kfree(ctx->params.jpeg_huff_tab);
+}
+
+const struct coda_context_ops coda9_jpeg_encode_ops = {
+	.queue_init = coda_encoder_queue_init,
+	.start_streaming = coda9_jpeg_start_encoding,
+	.prepare_run = coda9_jpeg_prepare_encode,
+	.finish_run = coda9_jpeg_finish_encode,
+	.run_timeout = coda9_jpeg_encode_timeout,
+	.release = coda9_jpeg_release,
+};
+
+/*
+ * Decoder context operations
+ */
+
+static int coda9_jpeg_start_decoding(struct coda_ctx *ctx)
+{
+	ctx->params.jpeg_qmat_index[0] = 0;
+	ctx->params.jpeg_qmat_index[1] = 1;
+	ctx->params.jpeg_qmat_index[2] = 1;
+	ctx->params.jpeg_qmat_tab[0] = luma_q;
+	ctx->params.jpeg_qmat_tab[1] = chroma_q;
+	/* nothing more to do here */
+
+	/* TODO: we could already scan the first header to get the chroma
+	 * format.
+	 */
+
+	return 0;
+}
+
+static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	int aligned_width, aligned_height;
+	int chroma_format;
+	int ret;
+	u32 val, dst_fourcc;
+	struct coda_q_data *q_data_src, *q_data_dst;
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	int chroma_interleave;
+	int scl_hor_mode, scl_ver_mode;
+
+	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	dst_fourcc = q_data_dst->fourcc;
+
+	scl_hor_mode = coda_jpeg_scale(q_data_src->width, q_data_dst->width);
+	scl_ver_mode = coda_jpeg_scale(q_data_src->height, q_data_dst->height);
+
+	if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0)
+		vb2_set_plane_payload(&src_buf->vb2_buf, 0,
+				      vb2_plane_size(&src_buf->vb2_buf, 0));
+
+	chroma_format = coda9_jpeg_chroma_format(q_data_dst->fourcc);
+	if (chroma_format < 0)
+		return chroma_format;
+
+	ret = coda_jpeg_decode_header(ctx, &src_buf->vb2_buf);
+	if (ret < 0) {
+		src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+		dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
+
+		return ret;
+	}
+
+	/* Round image dimensions to multiple of MCU size */
+	aligned_width = round_up(q_data_src->width, width_align[chroma_format]);
+	aligned_height = round_up(q_data_src->height, height_align[chroma_format]);
+	if (aligned_width != q_data_dst->bytesperline) {
+		v4l2_err(&dev->v4l2_dev, "stride mismatch: %d != %d\n",
+			 aligned_width, q_data_dst->bytesperline);
+	}
+
+	coda_set_gdi_regs(ctx);
+
+	val = ctx->params.jpeg_huff_ac_index[0] << 12 |
+	      ctx->params.jpeg_huff_ac_index[1] << 11 |
+	      ctx->params.jpeg_huff_ac_index[2] << 10 |
+	      ctx->params.jpeg_huff_dc_index[0] << 9 |
+	      ctx->params.jpeg_huff_dc_index[1] << 8 |
+	      ctx->params.jpeg_huff_dc_index[2] << 7;
+	if (ctx->params.jpeg_huff_tab)
+		val |= CODA9_JPEG_PIC_CTRL_USER_HUFFMAN_EN;
+	coda_write(dev, val, CODA9_REG_JPEG_PIC_CTRL);
+
+	coda_write(dev, aligned_width << 16 | aligned_height,
+			CODA9_REG_JPEG_PIC_SIZE);
+
+	chroma_interleave = (dst_fourcc == V4L2_PIX_FMT_NV12);
+	coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO);
+	coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO);
+	coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO);
+	if (scl_hor_mode || scl_ver_mode)
+		val = CODA9_JPEG_SCL_ENABLE | (scl_hor_mode << 2) | scl_ver_mode;
+	else
+		val = 0;
+	coda_write(dev, val, CODA9_REG_JPEG_SCL_INFO);
+	coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG);
+	coda_write(dev, ctx->params.jpeg_restart_interval,
+			CODA9_REG_JPEG_RST_INTVAL);
+
+	if (ctx->params.jpeg_huff_tab)
+		coda9_jpeg_dec_huff_setup(ctx);
+
+	coda9_jpeg_qmat_setup(ctx);
+
+	coda9_jpeg_dec_bbc_gbu_setup(ctx, &src_buf->vb2_buf,
+				     ctx->jpeg_ecs_offset);
+
+	coda_write(dev, 0, CODA9_REG_JPEG_RST_INDEX);
+	coda_write(dev, 0, CODA9_REG_JPEG_RST_COUNT);
+
+	coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_Y);
+	coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CB);
+	coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CR);
+
+	coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO);
+
+	coda_write(dev, 1, CODA9_GDI_CONTROL);
+	do {
+		ret = coda_read(dev, CODA9_GDI_STATUS);
+	} while (!ret);
+
+	val = (chroma_format << 17) | (chroma_interleave << 16) |
+	      q_data_dst->bytesperline;
+	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
+		val |= 3 << 20;
+	coda_write(dev, val, CODA9_GDI_INFO_CONTROL);
+
+	coda_write(dev, aligned_width << 16 | aligned_height,
+			CODA9_GDI_INFO_PIC_SIZE);
+
+	coda_write_base(ctx, q_data_dst, dst_buf, CODA9_GDI_INFO_BASE_Y);
+
+	coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00);
+	coda_write(dev, 0, CODA9_GDI_CONTROL);
+	coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST);
+
+	trace_coda_jpeg_run(ctx, src_buf);
+
+	coda_write(dev, 1, CODA9_REG_JPEG_PIC_START);
+
+	return 0;
+}
+
+static void coda9_jpeg_finish_decode(struct coda_ctx *ctx)
+{
+	struct coda_dev *dev = ctx->dev;
+	struct vb2_v4l2_buffer *dst_buf, *src_buf;
+	struct coda_q_data *q_data_dst;
+	u32 err_mb;
+
+	err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB);
+	if (err_mb)
+		v4l2_err(&dev->v4l2_dev, "ERRMB: 0x%x\n", err_mb);
+
+	coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD);
+
+	/*
+	 * Lock to make sure that a decoder stop command running in parallel
+	 * will either already have marked src_buf as last, or it will wake up
+	 * the capture queue after the buffers are returned.
+	 */
+	mutex_lock(&ctx->wakeup_mutex);
+	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+	dst_buf->sequence = ctx->osequence++;
+
+	trace_coda_jpeg_done(ctx, dst_buf);
+
+	dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST);
+	dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
+	dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST;
+
+	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
+
+	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	vb2_set_plane_payload(&dst_buf->vb2_buf, 0, q_data_dst->sizeimage);
+
+	v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+	coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR :
+						 VB2_BUF_STATE_DONE);
+
+	mutex_unlock(&ctx->wakeup_mutex);
+
+	coda_dbg(1, ctx, "job finished: decoded frame (%u)%s\n",
+		 dst_buf->sequence,
+		 (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : "");
+
+	/*
+	 * Reset JPEG processing unit after each decode run to work
+	 * around hangups when switching context between encoder and
+	 * decoder.
+	 */
+	coda_hw_reset(ctx);
+}
+
+const struct coda_context_ops coda9_jpeg_decode_ops = {
+	.queue_init = coda_encoder_queue_init, /* non-bitstream operation */
+	.start_streaming = coda9_jpeg_start_decoding,
+	.prepare_run = coda9_jpeg_prepare_decode,
+	.finish_run = coda9_jpeg_finish_decode,
+	.release = coda9_jpeg_release,
+};
+
+irqreturn_t coda9_jpeg_irq_handler(int irq, void *data)
+{
+	struct coda_dev *dev = data;
+	struct coda_ctx *ctx;
+	int status;
+	int err_mb;
+
+	status = coda_read(dev, CODA9_REG_JPEG_PIC_STATUS);
+	if (status == 0)
+		return IRQ_HANDLED;
+	coda_write(dev, status, CODA9_REG_JPEG_PIC_STATUS);
+
+	if (status & CODA9_JPEG_STATUS_OVERFLOW)
+		v4l2_err(&dev->v4l2_dev, "JPEG overflow\n");
+
+	if (status & CODA9_JPEG_STATUS_BBC_INT)
+		v4l2_err(&dev->v4l2_dev, "JPEG BBC interrupt\n");
+
+	if (status & CODA9_JPEG_STATUS_ERROR) {
+		v4l2_err(&dev->v4l2_dev, "JPEG error\n");
+
+		err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB);
+		if (err_mb) {
+			v4l2_err(&dev->v4l2_dev,
+				 "ERRMB: 0x%x: rst idx %d, mcu pos (%d,%d)\n",
+				 err_mb, err_mb >> 24, (err_mb >> 12) & 0xfff,
+				 err_mb & 0xfff);
+		}
+	}
+
+	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
+	if (!ctx) {
+		v4l2_err(&dev->v4l2_dev,
+			 "Instance released before the end of transaction\n");
+		mutex_unlock(&dev->coda_mutex);
+		return IRQ_HANDLED;
+	}
+
+	complete(&ctx->completion);
+
+	return IRQ_HANDLED;
+}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-mpeg2.c b/drivers/media/platform/chips-media/coda/coda-mpeg2.c
--- a/drivers/media/platform/chips-media/coda/coda-mpeg2.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/coda-mpeg2.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Coda multi-standard codec IP - MPEG-2 helper functions
+ *
+ * Copyright (C) 2019 Pengutronix, Philipp Zabel
+ */
+
+#include <linux/kernel.h>
+#include <linux/videodev2.h>
+#include "coda.h"
+
+int coda_mpeg2_profile(int profile_idc)
+{
+	switch (profile_idc) {
+	case 5:
+		return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SIMPLE;
+	case 4:
+		return V4L2_MPEG_VIDEO_MPEG2_PROFILE_MAIN;
+	case 3:
+		return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SNR_SCALABLE;
+	case 2:
+		return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SPATIALLY_SCALABLE;
+	case 1:
+		return V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH;
+	default:
+		return -EINVAL;
+	}
+}
+
+int coda_mpeg2_level(int level_idc)
+{
+	switch (level_idc) {
+	case 10:
+		return V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW;
+	case 8:
+		return V4L2_MPEG_VIDEO_MPEG2_LEVEL_MAIN;
+	case 6:
+		return V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH_1440;
+	case 4:
+		return V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH;
+	default:
+		return -EINVAL;
+	}
+}
+
+/*
+ * Check if the buffer starts with the MPEG-2 sequence header (with or without
+ * quantization matrix) and extension header, for example:
+ *
+ *   00 00 01 b3 2d 01 e0 34 08 8b a3 81
+ *               10 11 11 12 12 12 13 13 13 13 14 14 14 14 14 15
+ *               15 15 15 15 15 16 16 16 16 16 16 16 17 17 17 17
+ *               17 17 17 17 18 18 18 19 18 18 18 19 1a 1a 1a 1a
+ *               19 1b 1b 1b 1b 1b 1c 1c 1c 1c 1e 1e 1e 1f 1f 21
+ *   00 00 01 b5 14 8a 00 01 00 00
+ *
+ * or:
+ *
+ *   00 00 01 b3 08 00 40 15 ff ff e0 28
+ *   00 00 01 b5 14 8a 00 01 00 00
+ *
+ * Returns the detected header size in bytes or 0.
+ */
+u32 coda_mpeg2_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size)
+{
+	static const u8 sequence_header_start[4] = { 0x00, 0x00, 0x01, 0xb3 };
+	static const union {
+		u8 extension_start[4];
+		u8 start_code_prefix[3];
+	} u = { { 0x00, 0x00, 0x01, 0xb5 } };
+
+	if (size < 22 ||
+	    memcmp(buf, sequence_header_start, 4) != 0)
+		return 0;
+
+	if ((size == 22 ||
+	     (size >= 25 && memcmp(buf + 22, u.start_code_prefix, 3) == 0)) &&
+	    memcmp(buf + 12, u.extension_start, 4) == 0)
+		return 22;
+
+	if ((size == 86 ||
+	     (size > 89 && memcmp(buf + 86, u.start_code_prefix, 3) == 0)) &&
+	    memcmp(buf + 76, u.extension_start, 4) == 0)
+		return 86;
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda-mpeg4.c b/drivers/media/platform/chips-media/coda/coda-mpeg4.c
--- a/drivers/media/platform/chips-media/coda/coda-mpeg4.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/coda-mpeg4.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Coda multi-standard codec IP - MPEG-4 helper functions
+ *
+ * Copyright (C) 2019 Pengutronix, Philipp Zabel
+ */
+
+#include <linux/kernel.h>
+#include <linux/videodev2.h>
+
+#include "coda.h"
+
+int coda_mpeg4_profile(int profile_idc)
+{
+	switch (profile_idc) {
+	case 0:
+		return V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE;
+	case 15:
+		return V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE;
+	case 2:
+		return V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE;
+	case 1:
+		return V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE;
+	case 11:
+		return V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY;
+	default:
+		return -EINVAL;
+	}
+}
+
+int coda_mpeg4_level(int level_idc)
+{
+	switch (level_idc) {
+	case 0:
+		return V4L2_MPEG_VIDEO_MPEG4_LEVEL_0;
+	case 1:
+		return V4L2_MPEG_VIDEO_MPEG4_LEVEL_1;
+	case 2:
+		return V4L2_MPEG_VIDEO_MPEG4_LEVEL_2;
+	case 3:
+		return V4L2_MPEG_VIDEO_MPEG4_LEVEL_3;
+	case 4:
+		return V4L2_MPEG_VIDEO_MPEG4_LEVEL_4;
+	case 5:
+		return V4L2_MPEG_VIDEO_MPEG4_LEVEL_5;
+	default:
+		return -EINVAL;
+	}
+}
+
+/*
+ * Check if the buffer starts with the MPEG-4 visual object sequence and visual
+ * object headers, for example:
+ *
+ *   00 00 01 b0 f1
+ *   00 00 01 b5 a9 13 00 00 01 00 00 00 01 20 08
+ *               d4 8d 88 00 f5 04 04 08 14 30 3f
+ *
+ * Returns the detected header size in bytes or 0.
+ */
+u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size)
+{
+	static const u8 vos_start[4] = { 0x00, 0x00, 0x01, 0xb0 };
+	static const union {
+		u8 vo_start[4];
+		u8 start_code_prefix[3];
+	} u = { { 0x00, 0x00, 0x01, 0xb5 } };
+
+	if (size < 30 ||
+	    memcmp(buf, vos_start, 4) != 0 ||
+	    memcmp(buf + 5, u.vo_start, 4) != 0)
+		return 0;
+
+	if (size == 30 ||
+	    (size >= 33 && memcmp(buf + 30, u.start_code_prefix, 3) == 0))
+		return 30;
+
+	if (size == 31 ||
+	    (size >= 34 && memcmp(buf + 31, u.start_code_prefix, 3) == 0))
+		return 31;
+
+	if (size == 32 ||
+	    (size >= 35 && memcmp(buf + 32, u.start_code_prefix, 3) == 0))
+		return 32;
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/coda_regs.h b/drivers/media/platform/chips-media/coda/coda_regs.h
--- a/drivers/media/platform/chips-media/coda/coda_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/coda_regs.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,563 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * linux/drivers/media/platform/chips-media/coda_regs.h
+ *
+ * Copyright (C) 2012 Vista Silicon SL
+ *    Javier Martin <javier.martin@vista-silicon.com>
+ *    Xavier Duret
+ */
+
+#ifndef _REGS_CODA_H_
+#define _REGS_CODA_H_
+
+/* HW registers */
+#define CODA_REG_BIT_CODE_RUN			0x000
+#define		CODA_REG_RUN_ENABLE		(1 << 0)
+#define CODA_REG_BIT_CODE_DOWN			0x004
+#define		CODA_DOWN_ADDRESS_SET(x)	(((x) & 0xffff) << 16)
+#define		CODA_DOWN_DATA_SET(x)		((x) & 0xffff)
+#define CODA_REG_BIT_HOST_IN_REQ		0x008
+#define CODA_REG_BIT_INT_CLEAR			0x00c
+#define		CODA_REG_BIT_INT_CLEAR_SET	0x1
+#define CODA_REG_BIT_INT_STATUS		0x010
+#define CODA_REG_BIT_CODE_RESET		0x014
+#define		CODA_REG_RESET_ENABLE		(1 << 0)
+#define CODA_REG_BIT_CUR_PC			0x018
+#define CODA9_REG_BIT_SW_RESET			0x024
+#define		CODA9_SW_RESET_BPU_CORE   0x008
+#define		CODA9_SW_RESET_BPU_BUS    0x010
+#define		CODA9_SW_RESET_VCE_CORE   0x020
+#define		CODA9_SW_RESET_VCE_BUS    0x040
+#define		CODA9_SW_RESET_GDI_CORE   0x080
+#define		CODA9_SW_RESET_GDI_BUS    0x100
+#define CODA9_REG_BIT_SW_RESET_STATUS		0x034
+
+/* Static SW registers */
+#define CODA_REG_BIT_CODE_BUF_ADDR		0x100
+#define CODA_REG_BIT_WORK_BUF_ADDR		0x104
+#define CODA_REG_BIT_PARA_BUF_ADDR		0x108
+#define CODA_REG_BIT_STREAM_CTRL		0x10c
+#define		CODA7_STREAM_BUF_PIC_RESET	(1 << 4)
+#define		CODADX6_STREAM_BUF_PIC_RESET	(1 << 3)
+#define		CODA7_STREAM_BUF_PIC_FLUSH	(1 << 3)
+#define		CODADX6_STREAM_BUF_PIC_FLUSH	(1 << 2)
+#define		CODA7_STREAM_BUF_DYNALLOC_EN	(1 << 5)
+#define		CODADX6_STREAM_BUF_DYNALLOC_EN	(1 << 4)
+#define		CODADX6_STREAM_CHKDIS_OFFSET	(1 << 1)
+#define		CODA7_STREAM_SEL_64BITS_ENDIAN	(1 << 1)
+#define		CODA_STREAM_ENDIAN_SELECT	(1 << 0)
+#define CODA_REG_BIT_FRAME_MEM_CTRL		0x110
+#define		CODA9_FRAME_ENABLE_BWB		(1 << 12)
+#define		CODA9_FRAME_TILED2LINEAR	(1 << 11)
+#define		CODA_FRAME_CHROMA_INTERLEAVE	(1 << 2)
+#define		CODA_IMAGE_ENDIAN_SELECT	(1 << 0)
+#define CODA_REG_BIT_BIT_STREAM_PARAM		0x114
+#define		CODA_BIT_STREAM_END_FLAG	(1 << 2)
+#define		CODA_BIT_DEC_SEQ_INIT_ESCAPE	(1 << 0)
+#define CODA_REG_BIT_TEMP_BUF_ADDR		0x118
+#define CODA_REG_BIT_RD_PTR(x)			(0x120 + 8 * (x))
+#define CODA_REG_BIT_WR_PTR(x)			(0x124 + 8 * (x))
+#define CODA_REG_BIT_FRM_DIS_FLG(x)		(0x150 + 4 * (x))
+#define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR	0x140
+#define CODA7_REG_BIT_AXI_SRAM_USE		0x140
+#define		CODA9_USE_HOST_BTP_ENABLE	(1 << 13)
+#define		CODA9_USE_HOST_OVL_ENABLE	(1 << 12)
+#define		CODA7_USE_HOST_ME_ENABLE	(1 << 11)
+#define		CODA9_USE_HOST_DBK_ENABLE	(3 << 10)
+#define		CODA7_USE_HOST_OVL_ENABLE	(1 << 10)
+#define		CODA7_USE_HOST_DBK_ENABLE	(1 << 9)
+#define		CODA9_USE_HOST_IP_ENABLE	(1 << 9)
+#define		CODA7_USE_HOST_IP_ENABLE	(1 << 8)
+#define		CODA9_USE_HOST_BIT_ENABLE	(1 << 8)
+#define		CODA7_USE_HOST_BIT_ENABLE	(1 << 7)
+#define		CODA9_USE_BTP_ENABLE		(1 << 5)
+#define		CODA7_USE_ME_ENABLE		(1 << 4)
+#define		CODA9_USE_OVL_ENABLE		(1 << 4)
+#define		CODA7_USE_OVL_ENABLE		(1 << 3)
+#define		CODA9_USE_DBK_ENABLE		(3 << 2)
+#define		CODA7_USE_DBK_ENABLE		(1 << 2)
+#define		CODA7_USE_IP_ENABLE		(1 << 1)
+#define		CODA7_USE_BIT_ENABLE		(1 << 0)
+
+#define CODA_REG_BIT_BUSY			0x160
+#define		CODA_REG_BIT_BUSY_FLAG		1
+#define CODA_REG_BIT_RUN_COMMAND		0x164
+#define		CODA_COMMAND_SEQ_INIT		1
+#define		CODA_COMMAND_SEQ_END		2
+#define		CODA_COMMAND_PIC_RUN		3
+#define		CODA_COMMAND_SET_FRAME_BUF	4
+#define		CODA_COMMAND_ENCODE_HEADER	5
+#define		CODA_COMMAND_ENC_PARA_SET	6
+#define		CODA_COMMAND_DEC_PARA_SET	7
+#define		CODA_COMMAND_DEC_BUF_FLUSH	8
+#define		CODA_COMMAND_RC_CHANGE_PARAMETER 9
+#define		CODA_COMMAND_FIRMWARE_GET	0xf
+#define CODA_REG_BIT_RUN_INDEX			0x168
+#define		CODA_INDEX_SET(x)		((x) & 0x3)
+#define CODA_REG_BIT_RUN_COD_STD		0x16c
+#define		CODADX6_MODE_DECODE_MP4		0
+#define		CODADX6_MODE_ENCODE_MP4		1
+#define		CODADX6_MODE_DECODE_H264	2
+#define		CODADX6_MODE_ENCODE_H264	3
+#define		CODA7_MODE_DECODE_H264		0
+#define		CODA7_MODE_DECODE_VC1		1
+#define		CODA7_MODE_DECODE_MP2		2
+#define		CODA7_MODE_DECODE_MP4		3
+#define		CODA7_MODE_DECODE_DV3		3
+#define		CODA7_MODE_DECODE_RV		4
+#define		CODA7_MODE_DECODE_MJPG		5
+#define		CODA7_MODE_ENCODE_H264		8
+#define		CODA7_MODE_ENCODE_MP4		11
+#define		CODA7_MODE_ENCODE_MJPG		13
+#define		CODA9_MODE_DECODE_H264		0
+#define		CODA9_MODE_DECODE_VC1		1
+#define		CODA9_MODE_DECODE_MP2		2
+#define		CODA9_MODE_DECODE_MP4		3
+#define		CODA9_MODE_DECODE_DV3		3
+#define		CODA9_MODE_DECODE_RV		4
+#define		CODA9_MODE_DECODE_AVS		5
+#define		CODA9_MODE_DECODE_MJPG		6
+#define		CODA9_MODE_DECODE_VPX		7
+#define		CODA9_MODE_ENCODE_H264		8
+#define		CODA9_MODE_ENCODE_MP4		11
+#define		CODA9_MODE_ENCODE_MJPG		13
+#define		CODA_MODE_INVALID		0xffff
+#define CODA_REG_BIT_INT_ENABLE		0x170
+#define		CODA_INT_INTERRUPT_ENABLE	(1 << 3)
+#define CODA_REG_BIT_INT_REASON			0x174
+#define CODA7_REG_BIT_RUN_AUX_STD		0x178
+#define		CODA_MP4_AUX_MPEG4		0
+#define		CODA_MP4_AUX_DIVX3		1
+#define		CODA_VPX_AUX_THO		0
+#define		CODA_VPX_AUX_VP6		1
+#define		CODA_VPX_AUX_VP8		2
+#define		CODA_H264_AUX_AVC		0
+#define		CODA_H264_AUX_MVC		1
+
+/*
+ * Commands' mailbox:
+ * registers with offsets in the range 0x180-0x1d0
+ * have different meaning depending on the command being
+ * issued.
+ */
+
+/* Decoder Sequence Initialization */
+#define CODA_CMD_DEC_SEQ_BB_START		0x180
+#define CODA_CMD_DEC_SEQ_BB_SIZE		0x184
+#define CODA_CMD_DEC_SEQ_OPTION			0x188
+#define		CODA_NO_INT_ENABLE			(1 << 10)
+#define		CODA_REORDER_ENABLE			(1 << 1)
+#define		CODADX6_QP_REPORT			(1 << 0)
+#define		CODA7_MP4_DEBLK_ENABLE			(1 << 0)
+#define CODA_CMD_DEC_SEQ_SRC_SIZE		0x18c
+#define CODA_CMD_DEC_SEQ_START_BYTE		0x190
+#define CODA_CMD_DEC_SEQ_PS_BB_START		0x194
+#define CODA_CMD_DEC_SEQ_PS_BB_SIZE		0x198
+#define CODA_CMD_DEC_SEQ_JPG_THUMB_EN		0x19c
+#define CODA_CMD_DEC_SEQ_MP4_ASP_CLASS		0x19c
+#define		CODA_MP4_CLASS_MPEG4			0
+#define CODA_CMD_DEC_SEQ_X264_MV_EN		0x19c
+#define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE		0x1a0
+
+#define CODA7_RET_DEC_SEQ_ASPECT		0x1b0
+#define CODA9_RET_DEC_SEQ_BITRATE		0x1b4
+#define CODA_RET_DEC_SEQ_SUCCESS		0x1c0
+#define CODA_RET_DEC_SEQ_SRC_FMT		0x1c4 /* SRC_SIZE on CODA7 */
+#define CODA_RET_DEC_SEQ_SRC_SIZE		0x1c4
+#define CODA_RET_DEC_SEQ_SRC_F_RATE		0x1c8
+#define CODA9_RET_DEC_SEQ_ASPECT		0x1c8
+#define CODA_RET_DEC_SEQ_FRAME_NEED		0x1cc
+#define CODA_RET_DEC_SEQ_FRAME_DELAY		0x1d0
+#define CODA_RET_DEC_SEQ_INFO			0x1d4
+#define CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT	0x1d8
+#define CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM	0x1dc
+#define CODA_RET_DEC_SEQ_NEXT_FRAME_NUM		0x1e0
+#define CODA_RET_DEC_SEQ_ERR_REASON		0x1e0
+#define CODA_RET_DEC_SEQ_FRATE_NR		0x1e4
+#define CODA_RET_DEC_SEQ_FRATE_DR		0x1e8
+#define CODA_RET_DEC_SEQ_JPG_PARA		0x1e4
+#define CODA_RET_DEC_SEQ_JPG_THUMB_IND		0x1e8
+#define CODA7_RET_DEC_SEQ_HEADER_REPORT		0x1ec
+
+/* Decoder Picture Run */
+#define CODA_CMD_DEC_PIC_ROT_MODE		0x180
+#define CODA_CMD_DEC_PIC_ROT_ADDR_Y		0x184
+#define CODA9_CMD_DEC_PIC_ROT_INDEX		0x184
+#define CODA_CMD_DEC_PIC_ROT_ADDR_CB		0x188
+#define CODA9_CMD_DEC_PIC_ROT_ADDR_Y		0x188
+#define CODA_CMD_DEC_PIC_ROT_ADDR_CR		0x18c
+#define CODA9_CMD_DEC_PIC_ROT_ADDR_CB		0x18c
+#define CODA_CMD_DEC_PIC_ROT_STRIDE		0x190
+#define CODA9_CMD_DEC_PIC_ROT_ADDR_CR		0x190
+#define CODA9_CMD_DEC_PIC_ROT_STRIDE		0x1b8
+
+#define CODA_CMD_DEC_PIC_OPTION			0x194
+#define		CODA_PRE_SCAN_EN			(1 << 0)
+#define		CODA_PRE_SCAN_MODE_DECODE		(0 << 1)
+#define		CODA_PRE_SCAN_MODE_RETURN		(1 << 1)
+#define		CODA_IFRAME_SEARCH_EN			(1 << 2)
+#define		CODA_SKIP_FRAME_MODE			(0x3 << 3)
+#define CODA_CMD_DEC_PIC_SKIP_NUM		0x198
+#define CODA_CMD_DEC_PIC_CHUNK_SIZE		0x19c
+#define CODA_CMD_DEC_PIC_BB_START		0x1a0
+#define CODA_CMD_DEC_PIC_START_BYTE		0x1a4
+#define CODA_RET_DEC_PIC_SIZE			0x1bc
+#define CODA_RET_DEC_PIC_FRAME_NUM		0x1c0
+#define CODA_RET_DEC_PIC_FRAME_IDX		0x1c4
+#define CODA_RET_DEC_PIC_ERR_MB			0x1c8
+#define CODA_RET_DEC_PIC_TYPE			0x1cc
+#define		CODA_PIC_TYPE_MASK			0x7
+#define		CODA_PIC_TYPE_MASK_VC1			0x3f
+#define		CODA9_PIC_TYPE_FIRST_MASK		(0x7 << 3)
+#define		CODA9_PIC_TYPE_IDR_MASK			(0x3 << 6)
+#define		CODA7_PIC_TYPE_H264_NPF_MASK		(0x3 << 16)
+#define		CODA7_PIC_TYPE_INTERLACED		(1 << 18)
+#define CODA_RET_DEC_PIC_POST			0x1d0
+#define CODA_RET_DEC_PIC_MVC_REPORT		0x1d0
+#define CODA_RET_DEC_PIC_OPTION			0x1d4
+#define CODA_RET_DEC_PIC_SUCCESS		0x1d8
+#define CODA_RET_DEC_PIC_CUR_IDX		0x1dc
+#define CODA_RET_DEC_PIC_CROP_LEFT_RIGHT	0x1e0
+#define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM	0x1e4
+#define CODA_RET_DEC_PIC_FRAME_NEED		0x1ec
+
+#define CODA9_RET_DEC_PIC_VP8_PIC_REPORT	0x1e8
+#define CODA9_RET_DEC_PIC_ASPECT		0x1f0
+#define CODA9_RET_DEC_PIC_VP8_SCALE_INFO	0x1f0
+#define CODA9_RET_DEC_PIC_FRATE_NR		0x1f4
+#define CODA9_RET_DEC_PIC_FRATE_DR		0x1f8
+
+/* Encoder Sequence Initialization */
+#define CODA_CMD_ENC_SEQ_BB_START				0x180
+#define CODA_CMD_ENC_SEQ_BB_SIZE				0x184
+#define CODA_CMD_ENC_SEQ_OPTION				0x188
+#define		CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET		9
+#define		CODA9_OPTION_MVC_PREFIX_NAL_OFFSET		9
+#define		CODA7_OPTION_GAMMA_OFFSET			8
+#define		CODA9_OPTION_MVC_PARASET_REFRESH_OFFSET		8
+#define		CODA7_OPTION_RCQPMAX_OFFSET			7
+#define		CODA9_OPTION_GAMMA_OFFSET			7
+#define		CODADX6_OPTION_GAMMA_OFFSET			7
+#define		CODA7_OPTION_RCQPMIN_OFFSET			6
+#define		CODA9_OPTION_RCQPMAX_OFFSET			6
+#define		CODA_OPTION_LIMITQP_OFFSET			6
+#define		CODA_OPTION_RCINTRAQP_OFFSET			5
+#define		CODA_OPTION_FMO_OFFSET				4
+#define		CODA9_OPTION_MVC_INTERVIEW_OFFSET		4
+#define		CODA_OPTION_AVC_AUD_OFFSET			2
+#define		CODA_OPTION_SLICEREPORT_OFFSET			1
+#define CODA_CMD_ENC_SEQ_COD_STD				0x18c
+#define		CODA_STD_MPEG4					0
+#define		CODA9_STD_H264					0
+#define		CODA_STD_H263					1
+#define		CODA_STD_H264					2
+#define		CODA9_STD_MPEG4					3
+
+#define CODA_CMD_ENC_SEQ_SRC_SIZE				0x190
+#define		CODA7_PICWIDTH_OFFSET				16
+#define		CODA7_PICWIDTH_MASK				0xffff
+#define		CODADX6_PICWIDTH_OFFSET				10
+#define		CODADX6_PICWIDTH_MASK				0x3ff
+#define		CODA_PICHEIGHT_OFFSET				0
+#define		CODADX6_PICHEIGHT_MASK				0x3ff
+#define		CODA7_PICHEIGHT_MASK				0xffff
+#define CODA_CMD_ENC_SEQ_SRC_F_RATE				0x194
+#define		CODA_FRATE_RES_OFFSET				0
+#define		CODA_FRATE_RES_MASK				0xffff
+#define		CODA_FRATE_DIV_OFFSET				16
+#define		CODA_FRATE_DIV_MASK				0xffff
+#define CODA_CMD_ENC_SEQ_MP4_PARA				0x198
+#define		CODA_MP4PARAM_VERID_OFFSET			6
+#define		CODA_MP4PARAM_VERID_MASK			0x01
+#define		CODA_MP4PARAM_INTRADCVLCTHR_OFFSET		2
+#define		CODA_MP4PARAM_INTRADCVLCTHR_MASK		0x07
+#define		CODA_MP4PARAM_REVERSIBLEVLCENABLE_OFFSET	1
+#define		CODA_MP4PARAM_REVERSIBLEVLCENABLE_MASK		0x01
+#define		CODA_MP4PARAM_DATAPARTITIONENABLE_OFFSET	0
+#define		CODA_MP4PARAM_DATAPARTITIONENABLE_MASK		0x01
+#define CODA_CMD_ENC_SEQ_263_PARA				0x19c
+#define		CODA_263PARAM_ANNEXJENABLE_OFFSET		2
+#define		CODA_263PARAM_ANNEXJENABLE_MASK		0x01
+#define		CODA_263PARAM_ANNEXKENABLE_OFFSET		1
+#define		CODA_263PARAM_ANNEXKENABLE_MASK		0x01
+#define		CODA_263PARAM_ANNEXTENABLE_OFFSET		0
+#define		CODA_263PARAM_ANNEXTENABLE_MASK		0x01
+#define CODA_CMD_ENC_SEQ_264_PARA				0x1a0
+#define		CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET	12
+#define		CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK	0x0f
+#define		CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET	8
+#define		CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK	0x0f
+#define		CODA_264PARAM_DISABLEDEBLK_OFFSET		6
+#define		CODA_264PARAM_DISABLEDEBLK_MASK		0x03
+#define		CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_OFFSET	5
+#define		CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_MASK	0x01
+#define		CODA_264PARAM_CHROMAQPOFFSET_OFFSET		0
+#define		CODA_264PARAM_CHROMAQPOFFSET_MASK		0x1f
+#define CODA_CMD_ENC_SEQ_SLICE_MODE				0x1a4
+#define		CODA_SLICING_SIZE_OFFSET			2
+#define		CODA_SLICING_SIZE_MASK				0x3fffffff
+#define		CODA_SLICING_UNIT_OFFSET			1
+#define		CODA_SLICING_UNIT_MASK				0x01
+#define		CODA_SLICING_MODE_OFFSET			0
+#define		CODA_SLICING_MODE_MASK				0x01
+#define CODA_CMD_ENC_SEQ_GOP_SIZE				0x1a8
+#define		CODA_GOP_SIZE_OFFSET				0
+#define		CODA_GOP_SIZE_MASK				0x3f
+#define CODA_CMD_ENC_SEQ_RC_PARA				0x1ac
+#define		CODA_RATECONTROL_AUTOSKIP_OFFSET		31
+#define		CODA_RATECONTROL_AUTOSKIP_MASK			0x01
+#define		CODA_RATECONTROL_INITIALDELAY_OFFSET		16
+#define		CODA_RATECONTROL_INITIALDELAY_MASK		0x7fff
+#define		CODA_RATECONTROL_BITRATE_OFFSET		1
+#define		CODA_RATECONTROL_BITRATE_MASK			0x7fff
+#define		CODA_RATECONTROL_ENABLE_OFFSET			0
+#define		CODA_RATECONTROL_ENABLE_MASK			0x01
+#define CODA_CMD_ENC_SEQ_RC_BUF_SIZE				0x1b0
+#define CODA_CMD_ENC_SEQ_INTRA_REFRESH				0x1b4
+#define CODADX6_CMD_ENC_SEQ_FMO					0x1b8
+#define		CODA_FMOPARAM_TYPE_OFFSET			4
+#define		CODA_FMOPARAM_TYPE_MASK				1
+#define		CODA_FMOPARAM_SLICENUM_OFFSET			0
+#define		CODA_FMOPARAM_SLICENUM_MASK			0x0f
+#define CODADX6_CMD_ENC_SEQ_INTRA_QP				0x1bc
+#define CODA7_CMD_ENC_SEQ_SEARCH_BASE				0x1b8
+#define CODA7_CMD_ENC_SEQ_SEARCH_SIZE				0x1bc
+#define CODA7_CMD_ENC_SEQ_INTRA_QP				0x1c4
+#define CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX				0x1c8
+#define		CODA_QPMIN_OFFSET				8
+#define		CODA_QPMIN_MASK					0x3f
+#define		CODA_QPMAX_OFFSET				0
+#define		CODA_QPMAX_MASK					0x3f
+#define CODA_CMD_ENC_SEQ_RC_GAMMA				0x1cc
+#define		CODA_GAMMA_OFFSET				0
+#define		CODA_GAMMA_MASK					0xffff
+#define CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE			0x1d0
+#define CODA9_CMD_ENC_SEQ_INTRA_WEIGHT				0x1d4
+#define CODA9_CMD_ENC_SEQ_ME_OPTION				0x1d8
+#define CODA_RET_ENC_SEQ_SUCCESS				0x1c0
+
+#define CODA_CMD_ENC_SEQ_JPG_PARA				0x198
+#define CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL			0x19C
+#define CODA_CMD_ENC_SEQ_JPG_THUMB_EN				0x1a0
+#define CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE				0x1a4
+#define CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET			0x1a8
+
+/* Encoder Parameter Change */
+#define CODA_CMD_ENC_PARAM_CHANGE_ENABLE	0x180
+#define		CODA_PARAM_CHANGE_RC_GOP			BIT(0)
+#define		CODA_PARAM_CHANGE_RC_INTRA_QP			BIT(1)
+#define		CODA_PARAM_CHANGE_RC_BITRATE			BIT(2)
+#define		CODA_PARAM_CHANGE_RC_FRAME_RATE			BIT(3)
+#define		CODA_PARAM_CHANGE_INTRA_MB_NUM			BIT(4)
+#define		CODA_PARAM_CHANGE_SLICE_MODE			BIT(5)
+#define		CODA_PARAM_CHANGE_HEC_MODE			BIT(6)
+#define CODA_CMD_ENC_PARAM_RC_GOP		0x184
+#define CODA_CMD_ENC_PARAM_RC_INTRA_QP		0x188
+#define CODA_CMD_ENC_PARAM_RC_BITRATE		0x18c
+#define CODA_CMD_ENC_PARAM_RC_FRAME_RATE	0x190
+#define CODA_CMD_ENC_PARAM_INTRA_MB_NUM		0x194
+#define CODA_CMD_ENC_PARAM_SLICE_MODE		0x198
+#define CODA_CMD_ENC_PARAM_HEC_MODE		0x19c
+#define CODA_RET_ENC_PARAM_CHANGE_SUCCESS	0x1c0
+
+/* Encoder Picture Run */
+#define CODA9_CMD_ENC_PIC_SRC_INDEX		0x180
+#define CODA9_CMD_ENC_PIC_SRC_STRIDE		0x184
+#define CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC	0x1a4
+#define CODA9_CMD_ENC_PIC_SRC_ADDR_Y		0x1a8
+#define CODA9_CMD_ENC_PIC_SRC_ADDR_CB		0x1ac
+#define CODA9_CMD_ENC_PIC_SRC_ADDR_CR		0x1b0
+#define CODA_CMD_ENC_PIC_SRC_ADDR_Y	0x180
+#define CODA_CMD_ENC_PIC_SRC_ADDR_CB	0x184
+#define CODA_CMD_ENC_PIC_SRC_ADDR_CR	0x188
+#define CODA_CMD_ENC_PIC_QS		0x18c
+#define CODA_CMD_ENC_PIC_ROT_MODE	0x190
+#define		CODA_ROT_MIR_ENABLE				(1 << 4)
+#define		CODA_ROT_0					(0x0 << 0)
+#define		CODA_ROT_90					(0x1 << 0)
+#define		CODA_ROT_180					(0x2 << 0)
+#define		CODA_ROT_270					(0x3 << 0)
+#define		CODA_MIR_NONE					(0x0 << 2)
+#define		CODA_MIR_VER					(0x1 << 2)
+#define		CODA_MIR_HOR					(0x2 << 2)
+#define		CODA_MIR_VER_HOR				(0x3 << 2)
+#define CODA_CMD_ENC_PIC_OPTION		0x194
+#define		CODA_FORCE_IPICTURE				BIT(1)
+#define		CODA_REPORT_MB_INFO				BIT(3)
+#define		CODA_REPORT_MV_INFO				BIT(4)
+#define		CODA_REPORT_SLICE_INFO				BIT(5)
+#define CODA_CMD_ENC_PIC_BB_START	0x198
+#define CODA_CMD_ENC_PIC_BB_SIZE	0x19c
+#define CODA_RET_ENC_FRAME_NUM		0x1c0
+#define CODA_RET_ENC_PIC_TYPE		0x1c4
+#define CODA_RET_ENC_PIC_FRAME_IDX	0x1c8
+#define CODA_RET_ENC_PIC_SLICE_NUM	0x1cc
+#define CODA_RET_ENC_PIC_FLAG		0x1d0
+#define CODA_RET_ENC_PIC_SUCCESS	0x1d8
+
+/* Set Frame Buffer */
+#define CODA_CMD_SET_FRAME_BUF_NUM		0x180
+#define CODA_CMD_SET_FRAME_BUF_STRIDE		0x184
+#define CODA_CMD_SET_FRAME_SLICE_BB_START	0x188
+#define CODA_CMD_SET_FRAME_SLICE_BB_SIZE	0x18c
+#define CODA9_CMD_SET_FRAME_SUBSAMP_A		0x188
+#define CODA9_CMD_SET_FRAME_SUBSAMP_B		0x18c
+#define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR	0x190
+#define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR	0x194
+#define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR	0x198
+#define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR	0x19c
+#define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR	0x1a0
+#define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE	0x1a4
+#define CODA9_CMD_SET_FRAME_AXI_BTP_ADDR	0x1a4
+#define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE	0x1a8
+#define CODA9_CMD_SET_FRAME_CACHE_SIZE		0x1a8
+#define CODA9_CMD_SET_FRAME_CACHE_CONFIG	0x1ac
+#define		CODA9_CACHE_BYPASS_OFFSET		28
+#define		CODA9_CACHE_DUALCONF_OFFSET		26
+#define		CODA9_CACHE_PAGEMERGE_OFFSET		24
+#define		CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET	16
+#define		CODA9_CACHE_CB_BUFFER_SIZE_OFFSET	8
+#define		CODA9_CACHE_CR_BUFFER_SIZE_OFFSET	0
+#define CODA9_CMD_SET_FRAME_SUBSAMP_A_MVC	0x1b0
+#define CODA9_CMD_SET_FRAME_SUBSAMP_B_MVC	0x1b4
+#define CODA9_CMD_SET_FRAME_DP_BUF_BASE		0x1b0
+#define CODA9_CMD_SET_FRAME_DP_BUF_SIZE		0x1b4
+#define CODA9_CMD_SET_FRAME_MAX_DEC_SIZE	0x1b8
+#define CODA9_CMD_SET_FRAME_DELAY		0x1bc
+
+/* Encoder Header */
+#define CODA_CMD_ENC_HEADER_CODE	0x180
+#define		CODA_GAMMA_OFFSET	0
+#define		CODA_HEADER_H264_SPS	0
+#define		CODA_HEADER_H264_PPS	1
+#define		CODA_HEADER_MP4V_VOL	0
+#define		CODA_HEADER_MP4V_VOS	1
+#define		CODA_HEADER_MP4V_VIS	2
+#define		CODA9_HEADER_FRAME_CROP	(1 << 3)
+#define CODA_CMD_ENC_HEADER_BB_START	0x184
+#define CODA_CMD_ENC_HEADER_BB_SIZE	0x188
+#define CODA9_CMD_ENC_HEADER_FRAME_CROP_H	0x18c
+#define CODA9_CMD_ENC_HEADER_FRAME_CROP_V	0x190
+
+/* Get Version */
+#define CODA_CMD_FIRMWARE_VERNUM		0x1c0
+#define		CODA_FIRMWARE_PRODUCT(x)	(((x) >> 16) & 0xffff)
+#define		CODA_FIRMWARE_MAJOR(x)		(((x) >> 12) & 0x0f)
+#define		CODA_FIRMWARE_MINOR(x)		(((x) >> 8) & 0x0f)
+#define		CODA_FIRMWARE_RELEASE(x)	((x) & 0xff)
+#define		CODA_FIRMWARE_VERNUM(product, major, minor, release)	\
+			((product) << 16 | ((major) << 12) |		\
+			((minor) << 8) | (release))
+#define CODA9_CMD_FIRMWARE_CODE_REV		0x1c4
+
+#define CODA9_GDMA_BASE				0x1000
+#define CODA9_GDI_CONTROL			(CODA9_GDMA_BASE + 0x034)
+#define CODA9_GDI_PIC_INIT_HOST			(CODA9_GDMA_BASE + 0x038)
+#define CODA9_GDI_STATUS			(CODA9_GDMA_BASE + 0x080)
+#define CODA9_GDI_WPROT_ERR_CLR			(CODA9_GDMA_BASE + 0x0a0)
+#define CODA9_GDI_WPROT_RGN_EN			(CODA9_GDMA_BASE + 0x0ac)
+
+#define CODA9_GDI_BUS_CTRL			(CODA9_GDMA_BASE + 0x0f0)
+#define CODA9_GDI_BUS_STATUS			(CODA9_GDMA_BASE + 0x0f4)
+
+#define CODA9_GDI_INFO_CONTROL			(CODA9_GDMA_BASE + 0x400)
+#define CODA9_GDI_INFO_PIC_SIZE			(CODA9_GDMA_BASE + 0x404)
+#define CODA9_GDI_INFO_BASE_Y			(CODA9_GDMA_BASE + 0x408)
+#define CODA9_GDI_INFO_BASE_CB			(CODA9_GDMA_BASE + 0x40c)
+#define CODA9_GDI_INFO_BASE_CR			(CODA9_GDMA_BASE + 0x410)
+
+#define CODA9_GDI_XY2_CAS_0			(CODA9_GDMA_BASE + 0x800)
+#define CODA9_GDI_XY2_CAS_F			(CODA9_GDMA_BASE + 0x83c)
+
+#define CODA9_GDI_XY2_BA_0			(CODA9_GDMA_BASE + 0x840)
+#define CODA9_GDI_XY2_BA_1			(CODA9_GDMA_BASE + 0x844)
+#define CODA9_GDI_XY2_BA_2			(CODA9_GDMA_BASE + 0x848)
+#define CODA9_GDI_XY2_BA_3			(CODA9_GDMA_BASE + 0x84c)
+
+#define CODA9_GDI_XY2_RAS_0			(CODA9_GDMA_BASE + 0x850)
+#define CODA9_GDI_XY2_RAS_F			(CODA9_GDMA_BASE + 0x88c)
+
+#define CODA9_GDI_XY2_RBC_CONFIG		(CODA9_GDMA_BASE + 0x890)
+#define		CODA9_XY2RBC_SEPARATE_MAP		BIT(19)
+#define		CODA9_XY2RBC_TOP_BOT_SPLIT		BIT(18)
+#define		CODA9_XY2RBC_TILED_MAP			BIT(17)
+#define		CODA9_XY2RBC_CA_INC_HOR			BIT(16)
+#define CODA9_GDI_RBC2_AXI_0			(CODA9_GDMA_BASE + 0x8a0)
+#define CODA9_GDI_RBC2_AXI_1F			(CODA9_GDMA_BASE + 0x91c)
+#define	CODA9_GDI_TILEDBUF_BASE			(CODA9_GDMA_BASE + 0x920)
+
+#define CODA9_JPEG_BASE				0x3000
+#define CODA9_REG_JPEG_PIC_START		(CODA9_JPEG_BASE + 0x000)
+#define CODA9_REG_JPEG_PIC_STATUS		(CODA9_JPEG_BASE + 0x004)
+#define		CODA9_JPEG_STATUS_OVERFLOW		BIT(3)
+#define		CODA9_JPEG_STATUS_BBC_INT		BIT(2)
+#define		CODA9_JPEG_STATUS_ERROR			BIT(1)
+#define		CODA9_JPEG_STATUS_DONE			BIT(0)
+#define CODA9_REG_JPEG_PIC_ERRMB		(CODA9_JPEG_BASE + 0x008)
+#define		CODA9_JPEG_ERRMB_RESTART_IDX_MASK	(0xf << 24)
+#define		CODA9_JPEG_ERRMB_MCU_POS_X_MASK		(0xfff << 12)
+#define		CODA9_JPEG_ERRMB_MCU_POS_Y_MASK		0xfff
+#define CODA9_REG_JPEG_PIC_CTRL			(CODA9_JPEG_BASE + 0x010)
+#define		CODA9_JPEG_PIC_CTRL_USER_HUFFMAN_EN	BIT(6)
+#define		CODA9_JPEG_PIC_CTRL_TC_DIRECTION	BIT(4)
+#define		CODA9_JPEG_PIC_CTRL_ENCODER_EN		BIT(3)
+#define CODA9_REG_JPEG_PIC_SIZE			(CODA9_JPEG_BASE + 0x014)
+#define CODA9_REG_JPEG_MCU_INFO			(CODA9_JPEG_BASE + 0x018)
+#define		CODA9_JPEG_MCU_BLOCK_NUM_OFFSET		16
+#define		CODA9_JPEG_COMP_NUM_OFFSET		12
+#define		CODA9_JPEG_COMP0_INFO_OFFSET		8
+#define		CODA9_JPEG_COMP1_INFO_OFFSET		4
+#define		CODA9_JPEG_COMP2_INFO_OFFSET		0
+#define CODA9_REG_JPEG_ROT_INFO			(CODA9_JPEG_BASE + 0x01c)
+#define		CODA9_JPEG_ROT_MIR_ENABLE		BIT(4)
+#define		CODA9_JPEG_ROT_MIR_MODE_MASK		0xf
+#define CODA9_REG_JPEG_SCL_INFO			(CODA9_JPEG_BASE + 0x020)
+#define		CODA9_JPEG_SCL_ENABLE			BIT(4)
+#define		CODA9_JPEG_SCL_HOR_MODE_MASK		(0x3 << 2)
+#define		CODA9_JPEG_SCL_VER_MODE_MASK		(0x3 << 0)
+#define CODA9_REG_JPEG_IF_INFO			(CODA9_JPEG_BASE + 0x024)
+#define		CODA9_JPEG_SENS_IF_CLR			BIT(1)
+#define		CODA9_JPEG_DISP_IF_CLR			BIT(0)
+#define CODA9_REG_JPEG_OP_INFO			(CODA9_JPEG_BASE + 0x02c)
+#define		CODA9_JPEG_BUS_REQ_NUM_OFFSET		0
+#define		CODA9_JPEG_BUS_REQ_NUM_MASK		0x7
+#define CODA9_REG_JPEG_DPB_CONFIG		(CODA9_JPEG_BASE + 0x030)
+#define CODA9_REG_JPEG_DPB_BASE00		(CODA9_JPEG_BASE + 0x040)
+#define CODA9_REG_JPEG_HUFF_CTRL		(CODA9_JPEG_BASE + 0x080)
+#define CODA9_REG_JPEG_HUFF_ADDR		(CODA9_JPEG_BASE + 0x084)
+#define CODA9_REG_JPEG_HUFF_DATA		(CODA9_JPEG_BASE + 0x088)
+#define CODA9_REG_JPEG_QMAT_CTRL		(CODA9_JPEG_BASE + 0x090)
+#define CODA9_REG_JPEG_QMAT_ADDR		(CODA9_JPEG_BASE + 0x094)
+#define CODA9_REG_JPEG_QMAT_DATA		(CODA9_JPEG_BASE + 0x098)
+#define CODA9_REG_JPEG_RST_INTVAL		(CODA9_JPEG_BASE + 0x0b0)
+#define CODA9_REG_JPEG_RST_INDEX		(CODA9_JPEG_BASE + 0x0b4)
+#define CODA9_REG_JPEG_RST_COUNT		(CODA9_JPEG_BASE + 0x0b8)
+#define CODA9_REG_JPEG_DPCM_DIFF_Y		(CODA9_JPEG_BASE + 0x0f0)
+#define CODA9_REG_JPEG_DPCM_DIFF_CB		(CODA9_JPEG_BASE + 0x0f4)
+#define CODA9_REG_JPEG_DPCM_DIFF_CR		(CODA9_JPEG_BASE + 0x0f8)
+#define CODA9_REG_JPEG_GBU_CTRL			(CODA9_JPEG_BASE + 0x100)
+#define CODA9_REG_JPEG_GBU_BT_PTR		(CODA9_JPEG_BASE + 0x110)
+#define CODA9_REG_JPEG_GBU_WD_PTR		(CODA9_JPEG_BASE + 0x114)
+#define CODA9_REG_JPEG_GBU_TT_CNT		(CODA9_JPEG_BASE + 0x118)
+#define CODA9_REG_JPEG_GBU_BBSR			(CODA9_JPEG_BASE + 0x140)
+#define CODA9_REG_JPEG_GBU_BBER			(CODA9_JPEG_BASE + 0x144)
+#define CODA9_REG_JPEG_GBU_BBIR			(CODA9_JPEG_BASE + 0x148)
+#define CODA9_REG_JPEG_GBU_BBHR			(CODA9_JPEG_BASE + 0x14c)
+#define CODA9_REG_JPEG_GBU_BCNT			(CODA9_JPEG_BASE + 0x158)
+#define CODA9_REG_JPEG_GBU_FF_RPTR		(CODA9_JPEG_BASE + 0x160)
+#define CODA9_REG_JPEG_GBU_FF_WPTR		(CODA9_JPEG_BASE + 0x164)
+#define CODA9_REG_JPEG_BBC_END_ADDR		(CODA9_JPEG_BASE + 0x208)
+#define CODA9_REG_JPEG_BBC_WR_PTR		(CODA9_JPEG_BASE + 0x20c)
+#define CODA9_REG_JPEG_BBC_RD_PTR		(CODA9_JPEG_BASE + 0x210)
+#define CODA9_REG_JPEG_BBC_EXT_ADDR		(CODA9_JPEG_BASE + 0x214)
+#define CODA9_REG_JPEG_BBC_INT_ADDR		(CODA9_JPEG_BASE + 0x218)
+#define CODA9_REG_JPEG_BBC_DATA_CNT		(CODA9_JPEG_BASE + 0x21c)
+#define CODA9_REG_JPEG_BBC_COMMAND		(CODA9_JPEG_BASE + 0x220)
+#define CODA9_REG_JPEG_BBC_BUSY			(CODA9_JPEG_BASE + 0x224)
+#define CODA9_REG_JPEG_BBC_CTRL			(CODA9_JPEG_BASE + 0x228)
+#define CODA9_REG_JPEG_BBC_CUR_POS		(CODA9_JPEG_BASE + 0x22c)
+#define CODA9_REG_JPEG_BBC_BAS_ADDR		(CODA9_JPEG_BASE + 0x230)
+#define CODA9_REG_JPEG_BBC_STRM_CTRL		(CODA9_JPEG_BASE + 0x234)
+#define CODA9_REG_JPEG_BBC_FLUSH_CMD		(CODA9_JPEG_BASE + 0x238)
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/imx-vdoa.c b/drivers/media/platform/chips-media/coda/imx-vdoa.c
--- a/drivers/media/platform/chips-media/coda/imx-vdoa.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/imx-vdoa.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * i.MX6 Video Data Order Adapter (VDOA)
+ *
+ * Copyright (C) 2014 Philipp Zabel
+ * Copyright (C) 2016 Pengutronix, Michael Tretter <kernel@pengutronix.de>
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+
+#include "imx-vdoa.h"
+
+#define VDOA_NAME "imx-vdoa"
+
+#define VDOAC		0x00
+#define VDOASRR		0x04
+#define VDOAIE		0x08
+#define VDOAIST		0x0c
+#define VDOAFP		0x10
+#define VDOAIEBA00	0x14
+#define VDOAIEBA01	0x18
+#define VDOAIEBA02	0x1c
+#define VDOAIEBA10	0x20
+#define VDOAIEBA11	0x24
+#define VDOAIEBA12	0x28
+#define VDOASL		0x2c
+#define VDOAIUBO	0x30
+#define VDOAVEBA0	0x34
+#define VDOAVEBA1	0x38
+#define VDOAVEBA2	0x3c
+#define VDOAVUBO	0x40
+#define VDOASR		0x44
+
+#define VDOAC_ISEL		BIT(6)
+#define VDOAC_PFS		BIT(5)
+#define VDOAC_SO		BIT(4)
+#define VDOAC_SYNC		BIT(3)
+#define VDOAC_NF		BIT(2)
+#define VDOAC_BNDM_MASK		0x3
+#define VDOAC_BAND_HEIGHT_8	0x0
+#define VDOAC_BAND_HEIGHT_16	0x1
+#define VDOAC_BAND_HEIGHT_32	0x2
+
+#define VDOASRR_START		BIT(1)
+#define VDOASRR_SWRST		BIT(0)
+
+#define VDOAIE_EITERR		BIT(1)
+#define VDOAIE_EIEOT		BIT(0)
+
+#define VDOAIST_TERR		BIT(1)
+#define VDOAIST_EOT		BIT(0)
+
+#define VDOAFP_FH_MASK		(0x1fff << 16)
+#define VDOAFP_FW_MASK		(0x3fff)
+
+#define VDOASL_VSLY_MASK	(0x3fff << 16)
+#define VDOASL_ISLY_MASK	(0x7fff)
+
+#define VDOASR_ERRW		BIT(4)
+#define VDOASR_EOB		BIT(3)
+#define VDOASR_CURRENT_FRAME	(0x3 << 1)
+#define VDOASR_CURRENT_BUFFER	BIT(1)
+
+enum {
+	V4L2_M2M_SRC = 0,
+	V4L2_M2M_DST = 1,
+};
+
+struct vdoa_data {
+	struct vdoa_ctx		*curr_ctx;
+	struct device		*dev;
+	struct clk		*vdoa_clk;
+	void __iomem		*regs;
+};
+
+struct vdoa_q_data {
+	unsigned int	width;
+	unsigned int	height;
+	unsigned int	bytesperline;
+	unsigned int	sizeimage;
+	u32		pixelformat;
+};
+
+struct vdoa_ctx {
+	struct vdoa_data	*vdoa;
+	struct completion	completion;
+	struct vdoa_q_data	q_data[2];
+	unsigned int		submitted_job;
+	unsigned int		completed_job;
+};
+
+static irqreturn_t vdoa_irq_handler(int irq, void *data)
+{
+	struct vdoa_data *vdoa = data;
+	struct vdoa_ctx *curr_ctx;
+	u32 val;
+
+	/* Disable interrupts */
+	writel(0, vdoa->regs + VDOAIE);
+
+	curr_ctx = vdoa->curr_ctx;
+	if (!curr_ctx) {
+		dev_warn(vdoa->dev,
+			"Instance released before the end of transaction\n");
+		return IRQ_HANDLED;
+	}
+
+	val = readl(vdoa->regs + VDOAIST);
+	writel(val, vdoa->regs + VDOAIST);
+	if (val & VDOAIST_TERR) {
+		val = readl(vdoa->regs + VDOASR) & VDOASR_ERRW;
+		dev_err(vdoa->dev, "AXI %s error\n", val ? "write" : "read");
+	} else if (!(val & VDOAIST_EOT)) {
+		dev_warn(vdoa->dev, "Spurious interrupt\n");
+	}
+	curr_ctx->completed_job++;
+	complete(&curr_ctx->completion);
+
+	return IRQ_HANDLED;
+}
+
+int vdoa_wait_for_completion(struct vdoa_ctx *ctx)
+{
+	struct vdoa_data *vdoa = ctx->vdoa;
+
+	if (ctx->submitted_job == ctx->completed_job)
+		return 0;
+
+	if (!wait_for_completion_timeout(&ctx->completion,
+					 msecs_to_jiffies(300))) {
+		dev_err(vdoa->dev,
+			"Timeout waiting for transfer result\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(vdoa_wait_for_completion);
+
+void vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src)
+{
+	struct vdoa_q_data *src_q_data, *dst_q_data;
+	struct vdoa_data *vdoa = ctx->vdoa;
+	u32 val;
+
+	if (vdoa->curr_ctx)
+		vdoa_wait_for_completion(vdoa->curr_ctx);
+
+	vdoa->curr_ctx = ctx;
+
+	reinit_completion(&ctx->completion);
+	ctx->submitted_job++;
+
+	src_q_data = &ctx->q_data[V4L2_M2M_SRC];
+	dst_q_data = &ctx->q_data[V4L2_M2M_DST];
+
+	/* Progressive, no sync, 1 frame per run */
+	if (dst_q_data->pixelformat == V4L2_PIX_FMT_YUYV)
+		val = VDOAC_PFS;
+	else
+		val = 0;
+	writel(val, vdoa->regs + VDOAC);
+
+	writel(dst_q_data->height << 16 | dst_q_data->width,
+	       vdoa->regs + VDOAFP);
+
+	val = dst;
+	writel(val, vdoa->regs + VDOAIEBA00);
+
+	writel(src_q_data->bytesperline << 16 | dst_q_data->bytesperline,
+	       vdoa->regs + VDOASL);
+
+	if (dst_q_data->pixelformat == V4L2_PIX_FMT_NV12 ||
+	    dst_q_data->pixelformat == V4L2_PIX_FMT_NV21)
+		val = dst_q_data->bytesperline * dst_q_data->height;
+	else
+		val = 0;
+	writel(val, vdoa->regs + VDOAIUBO);
+
+	val = src;
+	writel(val, vdoa->regs + VDOAVEBA0);
+	val = round_up(src_q_data->bytesperline * src_q_data->height, 4096);
+	writel(val, vdoa->regs + VDOAVUBO);
+
+	/* Enable interrupts and start transfer */
+	writel(VDOAIE_EITERR | VDOAIE_EIEOT, vdoa->regs + VDOAIE);
+	writel(VDOASRR_START, vdoa->regs + VDOASRR);
+}
+EXPORT_SYMBOL(vdoa_device_run);
+
+struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa)
+{
+	struct vdoa_ctx *ctx;
+	int err;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return NULL;
+
+	err = clk_prepare_enable(vdoa->vdoa_clk);
+	if (err) {
+		kfree(ctx);
+		return NULL;
+	}
+
+	init_completion(&ctx->completion);
+	ctx->vdoa = vdoa;
+
+	return ctx;
+}
+EXPORT_SYMBOL(vdoa_context_create);
+
+void vdoa_context_destroy(struct vdoa_ctx *ctx)
+{
+	struct vdoa_data *vdoa = ctx->vdoa;
+
+	if (vdoa->curr_ctx == ctx) {
+		vdoa_wait_for_completion(vdoa->curr_ctx);
+		vdoa->curr_ctx = NULL;
+	}
+
+	clk_disable_unprepare(vdoa->vdoa_clk);
+	kfree(ctx);
+}
+EXPORT_SYMBOL(vdoa_context_destroy);
+
+int vdoa_context_configure(struct vdoa_ctx *ctx,
+			   unsigned int width, unsigned int height,
+			   u32 pixelformat)
+{
+	struct vdoa_q_data *src_q_data;
+	struct vdoa_q_data *dst_q_data;
+
+	if (width < 16 || width  > 8192 || width % 16 != 0 ||
+	    height < 16 || height > 4096 || height % 16 != 0)
+		return -EINVAL;
+
+	if (pixelformat != V4L2_PIX_FMT_YUYV &&
+	    pixelformat != V4L2_PIX_FMT_NV12)
+		return -EINVAL;
+
+	/* If no context is passed, only check if the format is valid */
+	if (!ctx)
+		return 0;
+
+	src_q_data = &ctx->q_data[V4L2_M2M_SRC];
+	dst_q_data = &ctx->q_data[V4L2_M2M_DST];
+
+	src_q_data->width = width;
+	src_q_data->height = height;
+	src_q_data->bytesperline = width;
+	src_q_data->sizeimage =
+		round_up(src_q_data->bytesperline * height, 4096) +
+		src_q_data->bytesperline * height / 2;
+
+	dst_q_data->width = width;
+	dst_q_data->height = height;
+	dst_q_data->pixelformat = pixelformat;
+	switch (pixelformat) {
+	case V4L2_PIX_FMT_YUYV:
+		dst_q_data->bytesperline = width * 2;
+		dst_q_data->sizeimage = dst_q_data->bytesperline * height;
+		break;
+	case V4L2_PIX_FMT_NV12:
+	default:
+		dst_q_data->bytesperline = width;
+		dst_q_data->sizeimage =
+			dst_q_data->bytesperline * height * 3 / 2;
+		break;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(vdoa_context_configure);
+
+static int vdoa_probe(struct platform_device *pdev)
+{
+	struct vdoa_data *vdoa;
+	int ret;
+
+	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_err(&pdev->dev, "DMA enable failed\n");
+		return ret;
+	}
+
+	vdoa = devm_kzalloc(&pdev->dev, sizeof(*vdoa), GFP_KERNEL);
+	if (!vdoa)
+		return -ENOMEM;
+
+	vdoa->dev = &pdev->dev;
+
+	vdoa->vdoa_clk = devm_clk_get(vdoa->dev, NULL);
+	if (IS_ERR(vdoa->vdoa_clk)) {
+		dev_err(vdoa->dev, "Failed to get clock\n");
+		return PTR_ERR(vdoa->vdoa_clk);
+	}
+
+	vdoa->regs = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(vdoa->regs))
+		return PTR_ERR(vdoa->regs);
+
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		return ret;
+	ret = devm_request_threaded_irq(&pdev->dev, ret, NULL,
+					vdoa_irq_handler, IRQF_ONESHOT,
+					"vdoa", vdoa);
+	if (ret < 0) {
+		dev_err(vdoa->dev, "Failed to get irq\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, vdoa);
+
+	return 0;
+}
+
+static int vdoa_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id vdoa_dt_ids[] = {
+	{ .compatible = "fsl,imx6q-vdoa" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, vdoa_dt_ids);
+
+static struct platform_driver vdoa_driver = {
+	.probe		= vdoa_probe,
+	.remove		= vdoa_remove,
+	.driver		= {
+		.name	= VDOA_NAME,
+		.of_match_table = vdoa_dt_ids,
+	},
+};
+
+module_platform_driver(vdoa_driver);
+
+MODULE_DESCRIPTION("Video Data Order Adapter");
+MODULE_AUTHOR("Philipp Zabel <philipp.zabel@gmail.com>");
+MODULE_ALIAS("platform:imx-vdoa");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/imx-vdoa.h b/drivers/media/platform/chips-media/coda/imx-vdoa.h
--- a/drivers/media/platform/chips-media/coda/imx-vdoa.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/imx-vdoa.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2016 Pengutronix
+ */
+
+#ifndef IMX_VDOA_H
+#define IMX_VDOA_H
+
+struct vdoa_data;
+struct vdoa_ctx;
+
+#if (defined CONFIG_VIDEO_IMX_VDOA || defined CONFIG_VIDEO_IMX_VDOA_MODULE)
+
+struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa);
+int vdoa_context_configure(struct vdoa_ctx *ctx,
+			   unsigned int width, unsigned int height,
+			   u32 pixelformat);
+void vdoa_context_destroy(struct vdoa_ctx *ctx);
+
+void vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src);
+int vdoa_wait_for_completion(struct vdoa_ctx *ctx);
+
+#else
+
+static inline struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa)
+{
+	return NULL;
+}
+
+static inline int vdoa_context_configure(struct vdoa_ctx *ctx,
+					 unsigned int width,
+					 unsigned int height,
+					 u32 pixelformat)
+{
+	return 0;
+}
+
+static inline void vdoa_context_destroy(struct vdoa_ctx *ctx) { };
+
+static inline void vdoa_device_run(struct vdoa_ctx *ctx,
+				   dma_addr_t dst, dma_addr_t src) { };
+
+static inline int vdoa_wait_for_completion(struct vdoa_ctx *ctx)
+{
+	return 0;
+};
+
+#endif
+
+#endif /* IMX_VDOA_H */
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/Kconfig b/drivers/media/platform/chips-media/coda/Kconfig
--- a/drivers/media/platform/chips-media/coda/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/Kconfig	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+config VIDEO_CODA
+	tristate "Chips&Media Coda multi-standard codec IP"
+	depends on V4L_MEM2MEM_DRIVERS
+	depends on VIDEO_DEV && OF && (ARCH_MXC || COMPILE_TEST)
+	select SRAM
+	select VIDEOBUF2_DMA_CONTIG
+	select VIDEOBUF2_VMALLOC
+	select V4L2_JPEG_HELPER
+	select V4L2_MEM2MEM_DEV
+	select GENERIC_ALLOCATOR
+	help
+	   Coda is a range of video codec IPs that supports
+	   H.264, MPEG-4, and other video formats.
+
+config VIDEO_IMX_VDOA
+	def_tristate VIDEO_CODA if SOC_IMX6Q || COMPILE_TEST
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/Makefile b/drivers/media/platform/chips-media/coda/Makefile
--- a/drivers/media/platform/chips-media/coda/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/Makefile	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+coda-vpu-objs := coda-common.o coda-bit.o coda-gdi.o coda-h264.o coda-mpeg2.o coda-mpeg4.o coda-jpeg.o
+
+obj-$(CONFIG_VIDEO_CODA) += coda-vpu.o
+obj-$(CONFIG_VIDEO_IMX_VDOA) += imx-vdoa.o
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda/trace.h b/drivers/media/platform/chips-media/coda/trace.h
--- a/drivers/media/platform/chips-media/coda/trace.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda/trace.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM coda
+
+#if !defined(__CODA_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
+#define __CODA_TRACE_H__
+
+#include <linux/tracepoint.h>
+#include <media/videobuf2-v4l2.h>
+
+#include "coda.h"
+
+TRACE_EVENT(coda_bit_run,
+	TP_PROTO(struct coda_ctx *ctx, int cmd),
+
+	TP_ARGS(ctx, cmd),
+
+	TP_STRUCT__entry(
+		__field(int, minor)
+		__field(int, ctx)
+		__field(int, cmd)
+	),
+
+	TP_fast_assign(
+		__entry->minor = ctx->fh.vdev->minor;
+		__entry->ctx = ctx->idx;
+		__entry->cmd = cmd;
+	),
+
+	TP_printk("minor = %d, ctx = %d, cmd = %d",
+		  __entry->minor, __entry->ctx, __entry->cmd)
+);
+
+TRACE_EVENT(coda_bit_done,
+	TP_PROTO(struct coda_ctx *ctx),
+
+	TP_ARGS(ctx),
+
+	TP_STRUCT__entry(
+		__field(int, minor)
+		__field(int, ctx)
+	),
+
+	TP_fast_assign(
+		__entry->minor = ctx->fh.vdev->minor;
+		__entry->ctx = ctx->idx;
+	),
+
+	TP_printk("minor = %d, ctx = %d", __entry->minor, __entry->ctx)
+);
+
+DECLARE_EVENT_CLASS(coda_buf_class,
+	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
+
+	TP_ARGS(ctx, buf),
+
+	TP_STRUCT__entry(
+		__field(int, minor)
+		__field(int, index)
+		__field(int, ctx)
+	),
+
+	TP_fast_assign(
+		__entry->minor = ctx->fh.vdev->minor;
+		__entry->index = buf->vb2_buf.index;
+		__entry->ctx = ctx->idx;
+	),
+
+	TP_printk("minor = %d, index = %d, ctx = %d",
+		  __entry->minor, __entry->index, __entry->ctx)
+);
+
+DEFINE_EVENT(coda_buf_class, coda_enc_pic_run,
+	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
+	TP_ARGS(ctx, buf)
+);
+
+DEFINE_EVENT(coda_buf_class, coda_enc_pic_done,
+	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
+	TP_ARGS(ctx, buf)
+);
+
+DECLARE_EVENT_CLASS(coda_buf_meta_class,
+	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
+		 struct coda_buffer_meta *meta),
+
+	TP_ARGS(ctx, buf, meta),
+
+	TP_STRUCT__entry(
+		__field(int, minor)
+		__field(int, index)
+		__field(int, start)
+		__field(int, end)
+		__field(int, ctx)
+	),
+
+	TP_fast_assign(
+		__entry->minor = ctx->fh.vdev->minor;
+		__entry->index = buf->vb2_buf.index;
+		__entry->start = meta->start & ctx->bitstream_fifo.kfifo.mask;
+		__entry->end = meta->end & ctx->bitstream_fifo.kfifo.mask;
+		__entry->ctx = ctx->idx;
+	),
+
+	TP_printk("minor = %d, index = %d, start = 0x%x, end = 0x%x, ctx = %d",
+		  __entry->minor, __entry->index, __entry->start, __entry->end,
+		  __entry->ctx)
+);
+
+DEFINE_EVENT(coda_buf_meta_class, coda_bit_queue,
+	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
+		 struct coda_buffer_meta *meta),
+	TP_ARGS(ctx, buf, meta)
+);
+
+DECLARE_EVENT_CLASS(coda_meta_class,
+	TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta),
+
+	TP_ARGS(ctx, meta),
+
+	TP_STRUCT__entry(
+		__field(int, minor)
+		__field(int, start)
+		__field(int, end)
+		__field(int, ctx)
+	),
+
+	TP_fast_assign(
+		__entry->minor = ctx->fh.vdev->minor;
+		__entry->start = meta ? (meta->start &
+					 ctx->bitstream_fifo.kfifo.mask) : 0;
+		__entry->end = meta ? (meta->end &
+				       ctx->bitstream_fifo.kfifo.mask) : 0;
+		__entry->ctx = ctx->idx;
+	),
+
+	TP_printk("minor = %d, start = 0x%x, end = 0x%x, ctx = %d",
+		  __entry->minor, __entry->start, __entry->end, __entry->ctx)
+);
+
+DEFINE_EVENT(coda_meta_class, coda_dec_pic_run,
+	TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta),
+	TP_ARGS(ctx, meta)
+);
+
+DEFINE_EVENT(coda_meta_class, coda_dec_pic_done,
+	TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta),
+	TP_ARGS(ctx, meta)
+);
+
+DEFINE_EVENT(coda_buf_meta_class, coda_dec_rot_done,
+	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
+		 struct coda_buffer_meta *meta),
+	TP_ARGS(ctx, buf, meta)
+);
+
+DEFINE_EVENT(coda_buf_class, coda_jpeg_run,
+	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
+	TP_ARGS(ctx, buf)
+);
+
+DEFINE_EVENT(coda_buf_class, coda_jpeg_done,
+	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
+	TP_ARGS(ctx, buf)
+);
+
+#endif /* __CODA_TRACE_H__ */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH ../../drivers/media/platform/chips-media
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-bit.c b/drivers/media/platform/chips-media/coda-bit.c
--- a/drivers/media/platform/chips-media/coda-bit.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda-bit.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2666 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Coda multi-standard codec IP - BIT processor functions
- *
- * Copyright (C) 2012 Vista Silicon S.L.
- *    Javier Martin, <javier.martin@vista-silicon.com>
- *    Xavier Duret
- * Copyright (C) 2012-2014 Philipp Zabel, Pengutronix
- */
-
-#include <linux/clk.h>
-#include <linux/irqreturn.h>
-#include <linux/kernel.h>
-#include <linux/log2.h>
-#include <linux/platform_device.h>
-#include <linux/ratelimit.h>
-#include <linux/reset.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-v4l2.h>
-#include <media/videobuf2-dma-contig.h>
-#include <media/videobuf2-vmalloc.h>
-
-#include "coda.h"
-#include "imx-vdoa.h"
-#define CREATE_TRACE_POINTS
-#include "trace.h"
-
-#define CODA_PARA_BUF_SIZE	(10 * 1024)
-#define CODA7_PS_BUF_SIZE	0x28000
-#define CODA9_PS_SAVE_SIZE	(512 * 1024)
-
-#define CODA_DEFAULT_GAMMA	4096
-#define CODA9_DEFAULT_GAMMA	24576	/* 0.75 * 32768 */
-
-static void coda_free_bitstream_buffer(struct coda_ctx *ctx);
-
-static inline int coda_is_initialized(struct coda_dev *dev)
-{
-	return coda_read(dev, CODA_REG_BIT_CUR_PC) != 0;
-}
-
-static inline unsigned long coda_isbusy(struct coda_dev *dev)
-{
-	return coda_read(dev, CODA_REG_BIT_BUSY);
-}
-
-static int coda_wait_timeout(struct coda_dev *dev)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-
-	while (coda_isbusy(dev)) {
-		if (time_after(jiffies, timeout))
-			return -ETIMEDOUT;
-	}
-	return 0;
-}
-
-static void coda_command_async(struct coda_ctx *ctx, int cmd)
-{
-	struct coda_dev *dev = ctx->dev;
-
-	if (dev->devtype->product == CODA_HX4 ||
-	    dev->devtype->product == CODA_7541 ||
-	    dev->devtype->product == CODA_960) {
-		/* Restore context related registers to CODA */
-		coda_write(dev, ctx->bit_stream_param,
-				CODA_REG_BIT_BIT_STREAM_PARAM);
-		coda_write(dev, ctx->frm_dis_flg,
-				CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
-		coda_write(dev, ctx->frame_mem_ctrl,
-				CODA_REG_BIT_FRAME_MEM_CTRL);
-		coda_write(dev, ctx->workbuf.paddr, CODA_REG_BIT_WORK_BUF_ADDR);
-	}
-
-	if (dev->devtype->product == CODA_960) {
-		coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR);
-		coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
-	}
-
-	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
-
-	coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX);
-	coda_write(dev, ctx->params.codec_mode, CODA_REG_BIT_RUN_COD_STD);
-	coda_write(dev, ctx->params.codec_mode_aux, CODA7_REG_BIT_RUN_AUX_STD);
-
-	trace_coda_bit_run(ctx, cmd);
-
-	coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND);
-}
-
-static int coda_command_sync(struct coda_ctx *ctx, int cmd)
-{
-	struct coda_dev *dev = ctx->dev;
-	int ret;
-
-	lockdep_assert_held(&dev->coda_mutex);
-
-	coda_command_async(ctx, cmd);
-	ret = coda_wait_timeout(dev);
-	trace_coda_bit_done(ctx);
-
-	return ret;
-}
-
-int coda_hw_reset(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	unsigned long timeout;
-	unsigned int idx;
-	int ret;
-
-	lockdep_assert_held(&dev->coda_mutex);
-
-	if (!dev->rstc)
-		return -ENOENT;
-
-	idx = coda_read(dev, CODA_REG_BIT_RUN_INDEX);
-
-	if (dev->devtype->product == CODA_960) {
-		timeout = jiffies + msecs_to_jiffies(100);
-		coda_write(dev, 0x11, CODA9_GDI_BUS_CTRL);
-		while (coda_read(dev, CODA9_GDI_BUS_STATUS) != 0x77) {
-			if (time_after(jiffies, timeout))
-				return -ETIME;
-			cpu_relax();
-		}
-	}
-
-	ret = reset_control_reset(dev->rstc);
-	if (ret < 0)
-		return ret;
-
-	if (dev->devtype->product == CODA_960)
-		coda_write(dev, 0x00, CODA9_GDI_BUS_CTRL);
-	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
-	coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN);
-	ret = coda_wait_timeout(dev);
-	coda_write(dev, idx, CODA_REG_BIT_RUN_INDEX);
-
-	return ret;
-}
-
-static void coda_kfifo_sync_from_device(struct coda_ctx *ctx)
-{
-	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
-	struct coda_dev *dev = ctx->dev;
-	u32 rd_ptr;
-
-	rd_ptr = coda_read(dev, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
-	kfifo->out = (kfifo->in & ~kfifo->mask) |
-		      (rd_ptr - ctx->bitstream.paddr);
-	if (kfifo->out > kfifo->in)
-		kfifo->out -= kfifo->mask + 1;
-}
-
-static void coda_kfifo_sync_to_device_full(struct coda_ctx *ctx)
-{
-	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
-	struct coda_dev *dev = ctx->dev;
-	u32 rd_ptr, wr_ptr;
-
-	rd_ptr = ctx->bitstream.paddr + (kfifo->out & kfifo->mask);
-	coda_write(dev, rd_ptr, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
-	wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask);
-	coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
-}
-
-static void coda_kfifo_sync_to_device_write(struct coda_ctx *ctx)
-{
-	struct __kfifo *kfifo = &ctx->bitstream_fifo.kfifo;
-	struct coda_dev *dev = ctx->dev;
-	u32 wr_ptr;
-
-	wr_ptr = ctx->bitstream.paddr + (kfifo->in & kfifo->mask);
-	coda_write(dev, wr_ptr, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
-}
-
-static int coda_h264_bitstream_pad(struct coda_ctx *ctx, u32 size)
-{
-	unsigned char *buf;
-	u32 n;
-
-	if (size < 6)
-		size = 6;
-
-	buf = kmalloc(size, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	coda_h264_filler_nal(size, buf);
-	n = kfifo_in(&ctx->bitstream_fifo, buf, size);
-	kfree(buf);
-
-	return (n < size) ? -ENOSPC : 0;
-}
-
-int coda_bitstream_flush(struct coda_ctx *ctx)
-{
-	int ret;
-
-	if (ctx->inst_type != CODA_INST_DECODER || !ctx->use_bit)
-		return 0;
-
-	ret = coda_command_sync(ctx, CODA_COMMAND_DEC_BUF_FLUSH);
-	if (ret < 0) {
-		v4l2_err(&ctx->dev->v4l2_dev, "failed to flush bitstream\n");
-		return ret;
-	}
-
-	kfifo_init(&ctx->bitstream_fifo, ctx->bitstream.vaddr,
-		   ctx->bitstream.size);
-	coda_kfifo_sync_to_device_full(ctx);
-
-	return 0;
-}
-
-static int coda_bitstream_queue(struct coda_ctx *ctx, const u8 *buf, u32 size)
-{
-	u32 n = kfifo_in(&ctx->bitstream_fifo, buf, size);
-
-	return (n < size) ? -ENOSPC : 0;
-}
-
-static u32 coda_buffer_parse_headers(struct coda_ctx *ctx,
-				     struct vb2_v4l2_buffer *src_buf,
-				     u32 payload)
-{
-	u8 *vaddr = vb2_plane_vaddr(&src_buf->vb2_buf, 0);
-	u32 size = 0;
-
-	switch (ctx->codec->src_fourcc) {
-	case V4L2_PIX_FMT_MPEG2:
-		size = coda_mpeg2_parse_headers(ctx, vaddr, payload);
-		break;
-	case V4L2_PIX_FMT_MPEG4:
-		size = coda_mpeg4_parse_headers(ctx, vaddr, payload);
-		break;
-	default:
-		break;
-	}
-
-	return size;
-}
-
-static bool coda_bitstream_try_queue(struct coda_ctx *ctx,
-				     struct vb2_v4l2_buffer *src_buf)
-{
-	unsigned long payload = vb2_get_plane_payload(&src_buf->vb2_buf, 0);
-	u8 *vaddr = vb2_plane_vaddr(&src_buf->vb2_buf, 0);
-	int ret;
-	int i;
-
-	if (coda_get_bitstream_payload(ctx) + payload + 512 >=
-	    ctx->bitstream.size)
-		return false;
-
-	if (!vaddr) {
-		v4l2_err(&ctx->dev->v4l2_dev, "trying to queue empty buffer\n");
-		return true;
-	}
-
-	if (ctx->qsequence == 0 && payload < 512) {
-		/*
-		 * Add padding after the first buffer, if it is too small to be
-		 * fetched by the CODA, by repeating the headers. Without
-		 * repeated headers, or the first frame already queued, decoder
-		 * sequence initialization fails with error code 0x2000 on i.MX6
-		 * or error code 0x1 on i.MX51.
-		 */
-		u32 header_size = coda_buffer_parse_headers(ctx, src_buf,
-							    payload);
-
-		if (header_size) {
-			coda_dbg(1, ctx, "pad with %u-byte header\n",
-				 header_size);
-			for (i = payload; i < 512; i += header_size) {
-				ret = coda_bitstream_queue(ctx, vaddr,
-							   header_size);
-				if (ret < 0) {
-					v4l2_err(&ctx->dev->v4l2_dev,
-						 "bitstream buffer overflow\n");
-					return false;
-				}
-				if (ctx->dev->devtype->product == CODA_960)
-					break;
-			}
-		} else {
-			coda_dbg(1, ctx,
-				 "could not parse header, sequence initialization might fail\n");
-		}
-
-		/* Add padding before the first buffer, if it is too small */
-		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264)
-			coda_h264_bitstream_pad(ctx, 512 - payload);
-	}
-
-	ret = coda_bitstream_queue(ctx, vaddr, payload);
-	if (ret < 0) {
-		v4l2_err(&ctx->dev->v4l2_dev, "bitstream buffer overflow\n");
-		return false;
-	}
-
-	src_buf->sequence = ctx->qsequence++;
-
-	/* Sync read pointer to device */
-	if (ctx == v4l2_m2m_get_curr_priv(ctx->dev->m2m_dev))
-		coda_kfifo_sync_to_device_write(ctx);
-
-	/* Set the stream-end flag after the last buffer is queued */
-	if (src_buf->flags & V4L2_BUF_FLAG_LAST)
-		coda_bit_stream_end_flag(ctx);
-	ctx->hold = false;
-
-	return true;
-}
-
-void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list)
-{
-	struct vb2_v4l2_buffer *src_buf;
-	struct coda_buffer_meta *meta;
-	u32 start;
-
-	lockdep_assert_held(&ctx->bitstream_mutex);
-
-	if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG)
-		return;
-
-	while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) {
-		/*
-		 * Only queue two JPEGs into the bitstream buffer to keep
-		 * latency low. We need at least one complete buffer and the
-		 * header of another buffer (for prescan) in the bitstream.
-		 */
-		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
-		    ctx->num_metas > 1)
-			break;
-
-		if (ctx->num_internal_frames &&
-		    ctx->num_metas >= ctx->num_internal_frames) {
-			meta = list_first_entry(&ctx->buffer_meta_list,
-						struct coda_buffer_meta, list);
-
-			/*
-			 * If we managed to fill in at least a full reorder
-			 * window of buffers (num_internal_frames is a
-			 * conservative estimate for this) and the bitstream
-			 * prefetcher has at least 2 256 bytes periods beyond
-			 * the first buffer to fetch, we can safely stop queuing
-			 * in order to limit the decoder drain latency.
-			 */
-			if (coda_bitstream_can_fetch_past(ctx, meta->end))
-				break;
-		}
-
-		src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-
-		/* Drop frames that do not start/end with a SOI/EOI markers */
-		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
-		    !coda_jpeg_check_buffer(ctx, &src_buf->vb2_buf)) {
-			v4l2_err(&ctx->dev->v4l2_dev,
-				 "dropping invalid JPEG frame %d\n",
-				 ctx->qsequence);
-			src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-			if (buffer_list) {
-				struct v4l2_m2m_buffer *m2m_buf;
-
-				m2m_buf = container_of(src_buf,
-						       struct v4l2_m2m_buffer,
-						       vb);
-				list_add_tail(&m2m_buf->list, buffer_list);
-			} else {
-				v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
-			}
-			continue;
-		}
-
-		/* Dump empty buffers */
-		if (!vb2_get_plane_payload(&src_buf->vb2_buf, 0)) {
-			src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
-			continue;
-		}
-
-		/* Buffer start position */
-		start = ctx->bitstream_fifo.kfifo.in;
-
-		if (coda_bitstream_try_queue(ctx, src_buf)) {
-			/*
-			 * Source buffer is queued in the bitstream ringbuffer;
-			 * queue the timestamp and mark source buffer as done
-			 */
-			src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-
-			meta = kmalloc(sizeof(*meta), GFP_KERNEL);
-			if (meta) {
-				meta->sequence = src_buf->sequence;
-				meta->timecode = src_buf->timecode;
-				meta->timestamp = src_buf->vb2_buf.timestamp;
-				meta->start = start;
-				meta->end = ctx->bitstream_fifo.kfifo.in;
-				meta->last = src_buf->flags & V4L2_BUF_FLAG_LAST;
-				if (meta->last)
-					coda_dbg(1, ctx, "marking last meta");
-				spin_lock(&ctx->buffer_meta_lock);
-				list_add_tail(&meta->list,
-					      &ctx->buffer_meta_list);
-				ctx->num_metas++;
-				spin_unlock(&ctx->buffer_meta_lock);
-
-				trace_coda_bit_queue(ctx, src_buf, meta);
-			}
-
-			if (buffer_list) {
-				struct v4l2_m2m_buffer *m2m_buf;
-
-				m2m_buf = container_of(src_buf,
-						       struct v4l2_m2m_buffer,
-						       vb);
-				list_add_tail(&m2m_buf->list, buffer_list);
-			} else {
-				v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
-			}
-		} else {
-			break;
-		}
-	}
-}
-
-void coda_bit_stream_end_flag(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-
-	ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
-
-	/* If this context is currently running, update the hardware flag */
-	if ((dev->devtype->product == CODA_960) &&
-	    coda_isbusy(dev) &&
-	    (ctx->idx == coda_read(dev, CODA_REG_BIT_RUN_INDEX))) {
-		coda_write(dev, ctx->bit_stream_param,
-			   CODA_REG_BIT_BIT_STREAM_PARAM);
-	}
-}
-
-static void coda_parabuf_write(struct coda_ctx *ctx, int index, u32 value)
-{
-	struct coda_dev *dev = ctx->dev;
-	u32 *p = ctx->parabuf.vaddr;
-
-	if (dev->devtype->product == CODA_DX6)
-		p[index] = value;
-	else
-		p[index ^ 1] = value;
-}
-
-static inline int coda_alloc_context_buf(struct coda_ctx *ctx,
-					 struct coda_aux_buf *buf, size_t size,
-					 const char *name)
-{
-	return coda_alloc_aux_buf(ctx->dev, buf, size, name, ctx->debugfs_entry);
-}
-
-
-static void coda_free_framebuffers(struct coda_ctx *ctx)
-{
-	int i;
-
-	for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++)
-		coda_free_aux_buf(ctx->dev, &ctx->internal_frames[i].buf);
-}
-
-static int coda_alloc_framebuffers(struct coda_ctx *ctx,
-				   struct coda_q_data *q_data, u32 fourcc)
-{
-	struct coda_dev *dev = ctx->dev;
-	unsigned int ysize, ycbcr_size;
-	int ret;
-	int i;
-
-	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 ||
-	    ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264 ||
-	    ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 ||
-	    ctx->codec->dst_fourcc == V4L2_PIX_FMT_MPEG4)
-		ysize = round_up(q_data->rect.width, 16) *
-			round_up(q_data->rect.height, 16);
-	else
-		ysize = round_up(q_data->rect.width, 8) * q_data->rect.height;
-
-	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
-		ycbcr_size = round_up(ysize, 4096) + ysize / 2;
-	else
-		ycbcr_size = ysize + ysize / 2;
-
-	/* Allocate frame buffers */
-	for (i = 0; i < ctx->num_internal_frames; i++) {
-		size_t size = ycbcr_size;
-		char *name;
-
-		/* Add space for mvcol buffers */
-		if (dev->devtype->product != CODA_DX6 &&
-		    (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 ||
-		     (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 && i == 0)))
-			size += ysize / 4;
-		name = kasprintf(GFP_KERNEL, "fb%d", i);
-		if (!name) {
-			coda_free_framebuffers(ctx);
-			return -ENOMEM;
-		}
-		ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i].buf,
-					     size, name);
-		kfree(name);
-		if (ret < 0) {
-			coda_free_framebuffers(ctx);
-			return ret;
-		}
-	}
-
-	/* Register frame buffers in the parameter buffer */
-	for (i = 0; i < ctx->num_internal_frames; i++) {
-		u32 y, cb, cr, mvcol;
-
-		/* Start addresses of Y, Cb, Cr planes */
-		y = ctx->internal_frames[i].buf.paddr;
-		cb = y + ysize;
-		cr = y + ysize + ysize/4;
-		mvcol = y + ysize + ysize/4 + ysize/4;
-		if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP) {
-			cb = round_up(cb, 4096);
-			mvcol = cb + ysize/2;
-			cr = 0;
-			/* Packed 20-bit MSB of base addresses */
-			/* YYYYYCCC, CCyyyyyc, cccc.... */
-			y = (y & 0xfffff000) | cb >> 20;
-			cb = (cb & 0x000ff000) << 12;
-		}
-		coda_parabuf_write(ctx, i * 3 + 0, y);
-		coda_parabuf_write(ctx, i * 3 + 1, cb);
-		coda_parabuf_write(ctx, i * 3 + 2, cr);
-
-		if (dev->devtype->product == CODA_DX6)
-			continue;
-
-		/* mvcol buffer for h.264 and mpeg4 */
-		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264)
-			coda_parabuf_write(ctx, 96 + i, mvcol);
-		if (ctx->codec->src_fourcc == V4L2_PIX_FMT_MPEG4 && i == 0)
-			coda_parabuf_write(ctx, 97, mvcol);
-	}
-
-	return 0;
-}
-
-static void coda_free_context_buffers(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-
-	coda_free_aux_buf(dev, &ctx->slicebuf);
-	coda_free_aux_buf(dev, &ctx->psbuf);
-	if (dev->devtype->product != CODA_DX6)
-		coda_free_aux_buf(dev, &ctx->workbuf);
-	coda_free_aux_buf(dev, &ctx->parabuf);
-}
-
-static int coda_alloc_context_buffers(struct coda_ctx *ctx,
-				      struct coda_q_data *q_data)
-{
-	struct coda_dev *dev = ctx->dev;
-	size_t size;
-	int ret;
-
-	if (!ctx->parabuf.vaddr) {
-		ret = coda_alloc_context_buf(ctx, &ctx->parabuf,
-					     CODA_PARA_BUF_SIZE, "parabuf");
-		if (ret < 0)
-			return ret;
-	}
-
-	if (dev->devtype->product == CODA_DX6)
-		return 0;
-
-	if (!ctx->slicebuf.vaddr && q_data->fourcc == V4L2_PIX_FMT_H264) {
-		/* worst case slice size */
-		size = (DIV_ROUND_UP(q_data->rect.width, 16) *
-			DIV_ROUND_UP(q_data->rect.height, 16)) * 3200 / 8 + 512;
-		ret = coda_alloc_context_buf(ctx, &ctx->slicebuf, size,
-					     "slicebuf");
-		if (ret < 0)
-			goto err;
-	}
-
-	if (!ctx->psbuf.vaddr && (dev->devtype->product == CODA_HX4 ||
-				  dev->devtype->product == CODA_7541)) {
-		ret = coda_alloc_context_buf(ctx, &ctx->psbuf,
-					     CODA7_PS_BUF_SIZE, "psbuf");
-		if (ret < 0)
-			goto err;
-	}
-
-	if (!ctx->workbuf.vaddr) {
-		size = dev->devtype->workbuf_size;
-		if (dev->devtype->product == CODA_960 &&
-		    q_data->fourcc == V4L2_PIX_FMT_H264)
-			size += CODA9_PS_SAVE_SIZE;
-		ret = coda_alloc_context_buf(ctx, &ctx->workbuf, size,
-					     "workbuf");
-		if (ret < 0)
-			goto err;
-	}
-
-	return 0;
-
-err:
-	coda_free_context_buffers(ctx);
-	return ret;
-}
-
-static int coda_encode_header(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
-			      int header_code, u8 *header, int *size)
-{
-	struct vb2_buffer *vb = &buf->vb2_buf;
-	struct coda_dev *dev = ctx->dev;
-	struct coda_q_data *q_data_src;
-	struct v4l2_rect *r;
-	size_t bufsize;
-	int ret;
-	int i;
-
-	if (dev->devtype->product == CODA_960)
-		memset(vb2_plane_vaddr(vb, 0), 0, 64);
-
-	coda_write(dev, vb2_dma_contig_plane_dma_addr(vb, 0),
-		   CODA_CMD_ENC_HEADER_BB_START);
-	bufsize = vb2_plane_size(vb, 0);
-	if (dev->devtype->product == CODA_960)
-		bufsize /= 1024;
-	coda_write(dev, bufsize, CODA_CMD_ENC_HEADER_BB_SIZE);
-	if (dev->devtype->product == CODA_960 &&
-	    ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264 &&
-	    header_code == CODA_HEADER_H264_SPS) {
-		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-		r = &q_data_src->rect;
-
-		if (r->width % 16 || r->height % 16) {
-			u32 crop_right = round_up(r->width, 16) -  r->width;
-			u32 crop_bottom = round_up(r->height, 16) - r->height;
-
-			coda_write(dev, crop_right,
-				   CODA9_CMD_ENC_HEADER_FRAME_CROP_H);
-			coda_write(dev, crop_bottom,
-				   CODA9_CMD_ENC_HEADER_FRAME_CROP_V);
-			header_code |= CODA9_HEADER_FRAME_CROP;
-		}
-	}
-	coda_write(dev, header_code, CODA_CMD_ENC_HEADER_CODE);
-	ret = coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER);
-	if (ret < 0) {
-		v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n");
-		return ret;
-	}
-
-	if (dev->devtype->product == CODA_960) {
-		for (i = 63; i > 0; i--)
-			if (((char *)vb2_plane_vaddr(vb, 0))[i] != 0)
-				break;
-		*size = i + 1;
-	} else {
-		*size = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx)) -
-			coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
-	}
-	memcpy(header, vb2_plane_vaddr(vb, 0), *size);
-
-	return 0;
-}
-
-static u32 coda_slice_mode(struct coda_ctx *ctx)
-{
-	int size, unit;
-
-	switch (ctx->params.slice_mode) {
-	case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE:
-	default:
-		return 0;
-	case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB:
-		size = ctx->params.slice_max_mb;
-		unit = 1;
-		break;
-	case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES:
-		size = ctx->params.slice_max_bits;
-		unit = 0;
-		break;
-	}
-
-	return ((size & CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET) |
-	       ((unit & CODA_SLICING_UNIT_MASK) << CODA_SLICING_UNIT_OFFSET) |
-	       ((1 & CODA_SLICING_MODE_MASK) << CODA_SLICING_MODE_OFFSET);
-}
-
-static int coda_enc_param_change(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	u32 change_enable = 0;
-	u32 success;
-	int ret;
-
-	if (ctx->params.gop_size_changed) {
-		change_enable |= CODA_PARAM_CHANGE_RC_GOP;
-		coda_write(dev, ctx->params.gop_size,
-			   CODA_CMD_ENC_PARAM_RC_GOP);
-		ctx->gopcounter = ctx->params.gop_size - 1;
-		ctx->params.gop_size_changed = false;
-	}
-	if (ctx->params.h264_intra_qp_changed) {
-		coda_dbg(1, ctx, "parameter change: intra Qp %u\n",
-			 ctx->params.h264_intra_qp);
-
-		if (ctx->params.bitrate) {
-			change_enable |= CODA_PARAM_CHANGE_RC_INTRA_QP;
-			coda_write(dev, ctx->params.h264_intra_qp,
-				   CODA_CMD_ENC_PARAM_RC_INTRA_QP);
-		}
-		ctx->params.h264_intra_qp_changed = false;
-	}
-	if (ctx->params.bitrate_changed) {
-		coda_dbg(1, ctx, "parameter change: bitrate %u kbit/s\n",
-			 ctx->params.bitrate);
-		change_enable |= CODA_PARAM_CHANGE_RC_BITRATE;
-		coda_write(dev, ctx->params.bitrate,
-			   CODA_CMD_ENC_PARAM_RC_BITRATE);
-		ctx->params.bitrate_changed = false;
-	}
-	if (ctx->params.framerate_changed) {
-		coda_dbg(1, ctx, "parameter change: frame rate %u/%u Hz\n",
-			 ctx->params.framerate & 0xffff,
-			 (ctx->params.framerate >> 16) + 1);
-		change_enable |= CODA_PARAM_CHANGE_RC_FRAME_RATE;
-		coda_write(dev, ctx->params.framerate,
-			   CODA_CMD_ENC_PARAM_RC_FRAME_RATE);
-		ctx->params.framerate_changed = false;
-	}
-	if (ctx->params.intra_refresh_changed) {
-		coda_dbg(1, ctx, "parameter change: intra refresh MBs %u\n",
-			 ctx->params.intra_refresh);
-		change_enable |= CODA_PARAM_CHANGE_INTRA_MB_NUM;
-		coda_write(dev, ctx->params.intra_refresh,
-			   CODA_CMD_ENC_PARAM_INTRA_MB_NUM);
-		ctx->params.intra_refresh_changed = false;
-	}
-	if (ctx->params.slice_mode_changed) {
-		change_enable |= CODA_PARAM_CHANGE_SLICE_MODE;
-		coda_write(dev, coda_slice_mode(ctx),
-			   CODA_CMD_ENC_PARAM_SLICE_MODE);
-		ctx->params.slice_mode_changed = false;
-	}
-
-	if (!change_enable)
-		return 0;
-
-	coda_write(dev, change_enable, CODA_CMD_ENC_PARAM_CHANGE_ENABLE);
-
-	ret = coda_command_sync(ctx, CODA_COMMAND_RC_CHANGE_PARAMETER);
-	if (ret < 0)
-		return ret;
-
-	success = coda_read(dev, CODA_RET_ENC_PARAM_CHANGE_SUCCESS);
-	if (success != 1)
-		coda_dbg(1, ctx, "parameter change failed: %u\n", success);
-
-	return 0;
-}
-
-static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t size)
-{
-	phys_addr_t ret;
-
-	size = round_up(size, 1024);
-	if (size > iram->remaining)
-		return 0;
-	iram->remaining -= size;
-
-	ret = iram->next_paddr;
-	iram->next_paddr += size;
-
-	return ret;
-}
-
-static void coda_setup_iram(struct coda_ctx *ctx)
-{
-	struct coda_iram_info *iram_info = &ctx->iram_info;
-	struct coda_dev *dev = ctx->dev;
-	int w64, w128;
-	int mb_width;
-	int dbk_bits;
-	int bit_bits;
-	int ip_bits;
-	int me_bits;
-
-	memset(iram_info, 0, sizeof(*iram_info));
-	iram_info->next_paddr = dev->iram.paddr;
-	iram_info->remaining = dev->iram.size;
-
-	if (!dev->iram.vaddr)
-		return;
-
-	switch (dev->devtype->product) {
-	case CODA_HX4:
-		dbk_bits = CODA7_USE_HOST_DBK_ENABLE;
-		bit_bits = CODA7_USE_HOST_BIT_ENABLE;
-		ip_bits = CODA7_USE_HOST_IP_ENABLE;
-		me_bits = CODA7_USE_HOST_ME_ENABLE;
-		break;
-	case CODA_7541:
-		dbk_bits = CODA7_USE_HOST_DBK_ENABLE | CODA7_USE_DBK_ENABLE;
-		bit_bits = CODA7_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE;
-		ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
-		me_bits = CODA7_USE_HOST_ME_ENABLE | CODA7_USE_ME_ENABLE;
-		break;
-	case CODA_960:
-		dbk_bits = CODA9_USE_HOST_DBK_ENABLE | CODA9_USE_DBK_ENABLE;
-		bit_bits = CODA9_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE;
-		ip_bits = CODA9_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
-		me_bits = 0;
-		break;
-	default: /* CODA_DX6 */
-		return;
-	}
-
-	if (ctx->inst_type == CODA_INST_ENCODER) {
-		struct coda_q_data *q_data_src;
-
-		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-		mb_width = DIV_ROUND_UP(q_data_src->rect.width, 16);
-		w128 = mb_width * 128;
-		w64 = mb_width * 64;
-
-		/* Prioritize in case IRAM is too small for everything */
-		if (dev->devtype->product == CODA_HX4 ||
-		    dev->devtype->product == CODA_7541) {
-			iram_info->search_ram_size = round_up(mb_width * 16 *
-							      36 + 2048, 1024);
-			iram_info->search_ram_paddr = coda_iram_alloc(iram_info,
-						iram_info->search_ram_size);
-			if (!iram_info->search_ram_paddr) {
-				pr_err("IRAM is smaller than the search ram size\n");
-				goto out;
-			}
-			iram_info->axi_sram_use |= me_bits;
-		}
-
-		/* Only H.264BP and H.263P3 are considered */
-		iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w64);
-		iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w64);
-		if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use)
-			goto out;
-		iram_info->axi_sram_use |= dbk_bits;
-
-		iram_info->buf_bit_use = coda_iram_alloc(iram_info, w128);
-		if (!iram_info->buf_bit_use)
-			goto out;
-		iram_info->axi_sram_use |= bit_bits;
-
-		iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, w128);
-		if (!iram_info->buf_ip_ac_dc_use)
-			goto out;
-		iram_info->axi_sram_use |= ip_bits;
-
-		/* OVL and BTP disabled for encoder */
-	} else if (ctx->inst_type == CODA_INST_DECODER) {
-		struct coda_q_data *q_data_dst;
-
-		q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-		mb_width = DIV_ROUND_UP(q_data_dst->width, 16);
-		w128 = mb_width * 128;
-
-		iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, w128);
-		iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, w128);
-		if (!iram_info->buf_dbk_y_use || !iram_info->buf_dbk_c_use)
-			goto out;
-		iram_info->axi_sram_use |= dbk_bits;
-
-		iram_info->buf_bit_use = coda_iram_alloc(iram_info, w128);
-		if (!iram_info->buf_bit_use)
-			goto out;
-		iram_info->axi_sram_use |= bit_bits;
-
-		iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, w128);
-		if (!iram_info->buf_ip_ac_dc_use)
-			goto out;
-		iram_info->axi_sram_use |= ip_bits;
-
-		/* OVL and BTP unused as there is no VC1 support yet */
-	}
-
-out:
-	if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE))
-		coda_dbg(1, ctx, "IRAM smaller than needed\n");
-
-	if (dev->devtype->product == CODA_HX4 ||
-	    dev->devtype->product == CODA_7541) {
-		/* TODO - Enabling these causes picture errors on CODA7541 */
-		if (ctx->inst_type == CODA_INST_DECODER) {
-			/* fw 1.4.50 */
-			iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE |
-						     CODA7_USE_IP_ENABLE);
-		} else {
-			/* fw 13.4.29 */
-			iram_info->axi_sram_use &= ~(CODA7_USE_HOST_IP_ENABLE |
-						     CODA7_USE_HOST_DBK_ENABLE |
-						     CODA7_USE_IP_ENABLE |
-						     CODA7_USE_DBK_ENABLE);
-		}
-	}
-}
-
-static u32 coda_supported_firmwares[] = {
-	CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5),
-	CODA_FIRMWARE_VERNUM(CODA_HX4, 1, 4, 50),
-	CODA_FIRMWARE_VERNUM(CODA_7541, 1, 4, 50),
-	CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 5),
-	CODA_FIRMWARE_VERNUM(CODA_960, 2, 1, 9),
-	CODA_FIRMWARE_VERNUM(CODA_960, 2, 3, 10),
-	CODA_FIRMWARE_VERNUM(CODA_960, 3, 1, 1),
-};
-
-static bool coda_firmware_supported(u32 vernum)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(coda_supported_firmwares); i++)
-		if (vernum == coda_supported_firmwares[i])
-			return true;
-	return false;
-}
-
-int coda_check_firmware(struct coda_dev *dev)
-{
-	u16 product, major, minor, release;
-	u32 data;
-	int ret;
-
-	ret = clk_prepare_enable(dev->clk_per);
-	if (ret)
-		goto err_clk_per;
-
-	ret = clk_prepare_enable(dev->clk_ahb);
-	if (ret)
-		goto err_clk_ahb;
-
-	coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM);
-	coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
-	coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX);
-	coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD);
-	coda_write(dev, CODA_COMMAND_FIRMWARE_GET, CODA_REG_BIT_RUN_COMMAND);
-	if (coda_wait_timeout(dev)) {
-		v4l2_err(&dev->v4l2_dev, "firmware get command error\n");
-		ret = -EIO;
-		goto err_run_cmd;
-	}
-
-	if (dev->devtype->product == CODA_960) {
-		data = coda_read(dev, CODA9_CMD_FIRMWARE_CODE_REV);
-		v4l2_info(&dev->v4l2_dev, "Firmware code revision: %d\n",
-			  data);
-	}
-
-	/* Check we are compatible with the loaded firmware */
-	data = coda_read(dev, CODA_CMD_FIRMWARE_VERNUM);
-	product = CODA_FIRMWARE_PRODUCT(data);
-	major = CODA_FIRMWARE_MAJOR(data);
-	minor = CODA_FIRMWARE_MINOR(data);
-	release = CODA_FIRMWARE_RELEASE(data);
-
-	clk_disable_unprepare(dev->clk_per);
-	clk_disable_unprepare(dev->clk_ahb);
-
-	if (product != dev->devtype->product) {
-		v4l2_err(&dev->v4l2_dev,
-			 "Wrong firmware. Hw: %s, Fw: %s, Version: %u.%u.%u\n",
-			 coda_product_name(dev->devtype->product),
-			 coda_product_name(product), major, minor, release);
-		return -EINVAL;
-	}
-
-	v4l2_info(&dev->v4l2_dev, "Initialized %s.\n",
-		  coda_product_name(product));
-
-	if (coda_firmware_supported(data)) {
-		v4l2_info(&dev->v4l2_dev, "Firmware version: %u.%u.%u\n",
-			  major, minor, release);
-	} else {
-		v4l2_warn(&dev->v4l2_dev,
-			  "Unsupported firmware version: %u.%u.%u\n",
-			  major, minor, release);
-	}
-
-	return 0;
-
-err_run_cmd:
-	clk_disable_unprepare(dev->clk_ahb);
-err_clk_ahb:
-	clk_disable_unprepare(dev->clk_per);
-err_clk_per:
-	return ret;
-}
-
-static void coda9_set_frame_cache(struct coda_ctx *ctx, u32 fourcc)
-{
-	u32 cache_size, cache_config;
-
-	if (ctx->tiled_map_type == GDI_LINEAR_FRAME_MAP) {
-		/* Luma 2x0 page, 2x6 cache, chroma 2x0 page, 2x4 cache size */
-		cache_size = 0x20262024;
-		cache_config = 2 << CODA9_CACHE_PAGEMERGE_OFFSET;
-	} else {
-		/* Luma 0x2 page, 4x4 cache, chroma 0x2 page, 4x3 cache size */
-		cache_size = 0x02440243;
-		cache_config = 1 << CODA9_CACHE_PAGEMERGE_OFFSET;
-	}
-	coda_write(ctx->dev, cache_size, CODA9_CMD_SET_FRAME_CACHE_SIZE);
-	if (fourcc == V4L2_PIX_FMT_NV12 || fourcc == V4L2_PIX_FMT_YUYV) {
-		cache_config |= 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
-				16 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET |
-				0 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET;
-	} else {
-		cache_config |= 32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
-				8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET |
-				8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET;
-	}
-	coda_write(ctx->dev, cache_config, CODA9_CMD_SET_FRAME_CACHE_CONFIG);
-}
-
-/*
- * Encoder context operations
- */
-
-static int coda_encoder_reqbufs(struct coda_ctx *ctx,
-				struct v4l2_requestbuffers *rb)
-{
-	struct coda_q_data *q_data_src;
-	int ret;
-
-	if (rb->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		return 0;
-
-	if (rb->count) {
-		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-		ret = coda_alloc_context_buffers(ctx, q_data_src);
-		if (ret < 0)
-			return ret;
-	} else {
-		coda_free_context_buffers(ctx);
-	}
-
-	return 0;
-}
-
-static int coda_start_encoding(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
-	struct coda_q_data *q_data_src, *q_data_dst;
-	u32 bitstream_buf, bitstream_size;
-	struct vb2_v4l2_buffer *buf;
-	int gamma, ret, value;
-	u32 dst_fourcc;
-	int num_fb;
-	u32 stride;
-
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	dst_fourcc = q_data_dst->fourcc;
-
-	buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-	bitstream_buf = vb2_dma_contig_plane_dma_addr(&buf->vb2_buf, 0);
-	bitstream_size = q_data_dst->sizeimage;
-
-	if (!coda_is_initialized(dev)) {
-		v4l2_err(v4l2_dev, "coda is not initialized.\n");
-		return -EFAULT;
-	}
-
-	if (dst_fourcc == V4L2_PIX_FMT_JPEG) {
-		if (!ctx->params.jpeg_qmat_tab[0]) {
-			ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL);
-			if (!ctx->params.jpeg_qmat_tab[0])
-				return -ENOMEM;
-		}
-		if (!ctx->params.jpeg_qmat_tab[1]) {
-			ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL);
-			if (!ctx->params.jpeg_qmat_tab[1])
-				return -ENOMEM;
-		}
-		coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality);
-	}
-
-	mutex_lock(&dev->coda_mutex);
-
-	coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
-	coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->reg_idx));
-	coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
-	switch (dev->devtype->product) {
-	case CODA_DX6:
-		coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN |
-			CODADX6_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL);
-		break;
-	case CODA_960:
-		coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
-		fallthrough;
-	case CODA_HX4:
-	case CODA_7541:
-		coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN |
-			CODA7_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL);
-		break;
-	}
-
-	ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) |
-				 CODA9_FRAME_TILED2LINEAR);
-	if (q_data_src->fourcc == V4L2_PIX_FMT_NV12)
-		ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
-	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
-		ctx->frame_mem_ctrl |= (0x3 << 9) | CODA9_FRAME_TILED2LINEAR;
-	coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL);
-
-	if (dev->devtype->product == CODA_DX6) {
-		/* Configure the coda */
-		coda_write(dev, dev->iram.paddr,
-			   CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR);
-	}
-
-	/* Could set rotation here if needed */
-	value = 0;
-	switch (dev->devtype->product) {
-	case CODA_DX6:
-		value = (q_data_src->rect.width & CODADX6_PICWIDTH_MASK)
-			<< CODADX6_PICWIDTH_OFFSET;
-		value |= (q_data_src->rect.height & CODADX6_PICHEIGHT_MASK)
-			 << CODA_PICHEIGHT_OFFSET;
-		break;
-	case CODA_HX4:
-	case CODA_7541:
-		if (dst_fourcc == V4L2_PIX_FMT_H264) {
-			value = (round_up(q_data_src->rect.width, 16) &
-				 CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET;
-			value |= (round_up(q_data_src->rect.height, 16) &
-				 CODA7_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET;
-			break;
-		}
-		fallthrough;
-	case CODA_960:
-		value = (q_data_src->rect.width & CODA7_PICWIDTH_MASK)
-			<< CODA7_PICWIDTH_OFFSET;
-		value |= (q_data_src->rect.height & CODA7_PICHEIGHT_MASK)
-			 << CODA_PICHEIGHT_OFFSET;
-	}
-	coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE);
-	if (dst_fourcc == V4L2_PIX_FMT_JPEG)
-		ctx->params.framerate = 0;
-	coda_write(dev, ctx->params.framerate,
-		   CODA_CMD_ENC_SEQ_SRC_F_RATE);
-
-	ctx->params.codec_mode = ctx->codec->mode;
-	switch (dst_fourcc) {
-	case V4L2_PIX_FMT_MPEG4:
-		if (dev->devtype->product == CODA_960)
-			coda_write(dev, CODA9_STD_MPEG4,
-				   CODA_CMD_ENC_SEQ_COD_STD);
-		else
-			coda_write(dev, CODA_STD_MPEG4,
-				   CODA_CMD_ENC_SEQ_COD_STD);
-		coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA);
-		break;
-	case V4L2_PIX_FMT_H264:
-		if (dev->devtype->product == CODA_960)
-			coda_write(dev, CODA9_STD_H264,
-				   CODA_CMD_ENC_SEQ_COD_STD);
-		else
-			coda_write(dev, CODA_STD_H264,
-				   CODA_CMD_ENC_SEQ_COD_STD);
-		value = ((ctx->params.h264_disable_deblocking_filter_idc &
-			  CODA_264PARAM_DISABLEDEBLK_MASK) <<
-			 CODA_264PARAM_DISABLEDEBLK_OFFSET) |
-			((ctx->params.h264_slice_alpha_c0_offset_div2 &
-			  CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK) <<
-			 CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET) |
-			((ctx->params.h264_slice_beta_offset_div2 &
-			  CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK) <<
-			 CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET) |
-			(ctx->params.h264_constrained_intra_pred_flag <<
-			 CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_OFFSET) |
-			(ctx->params.h264_chroma_qp_index_offset &
-			 CODA_264PARAM_CHROMAQPOFFSET_MASK);
-		coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA);
-		break;
-	case V4L2_PIX_FMT_JPEG:
-		coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_PARA);
-		coda_write(dev, ctx->params.jpeg_restart_interval,
-				CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL);
-		coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_EN);
-		coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE);
-		coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET);
-
-		coda_jpeg_write_tables(ctx);
-		break;
-	default:
-		v4l2_err(v4l2_dev,
-			 "dst format (0x%08x) invalid.\n", dst_fourcc);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/*
-	 * slice mode and GOP size registers are used for thumb size/offset
-	 * in JPEG mode
-	 */
-	if (dst_fourcc != V4L2_PIX_FMT_JPEG) {
-		value = coda_slice_mode(ctx);
-		coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE);
-		value = ctx->params.gop_size;
-		coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE);
-	}
-
-	if (ctx->params.bitrate && (ctx->params.frame_rc_enable ||
-				    ctx->params.mb_rc_enable)) {
-		ctx->params.bitrate_changed = false;
-		ctx->params.h264_intra_qp_changed = false;
-
-		/* Rate control enabled */
-		value = (ctx->params.bitrate & CODA_RATECONTROL_BITRATE_MASK)
-			<< CODA_RATECONTROL_BITRATE_OFFSET;
-		value |=  1 & CODA_RATECONTROL_ENABLE_MASK;
-		value |= (ctx->params.vbv_delay &
-			  CODA_RATECONTROL_INITIALDELAY_MASK)
-			 << CODA_RATECONTROL_INITIALDELAY_OFFSET;
-		if (dev->devtype->product == CODA_960)
-			value |= BIT(31); /* disable autoskip */
-	} else {
-		value = 0;
-	}
-	coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA);
-
-	coda_write(dev, ctx->params.vbv_size, CODA_CMD_ENC_SEQ_RC_BUF_SIZE);
-	coda_write(dev, ctx->params.intra_refresh,
-		   CODA_CMD_ENC_SEQ_INTRA_REFRESH);
-
-	coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START);
-	coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE);
-
-
-	value = 0;
-	if (dev->devtype->product == CODA_960)
-		gamma = CODA9_DEFAULT_GAMMA;
-	else
-		gamma = CODA_DEFAULT_GAMMA;
-	if (gamma > 0) {
-		coda_write(dev, (gamma & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET,
-			   CODA_CMD_ENC_SEQ_RC_GAMMA);
-	}
-
-	if (ctx->params.h264_min_qp || ctx->params.h264_max_qp) {
-		coda_write(dev,
-			   ctx->params.h264_min_qp << CODA_QPMIN_OFFSET |
-			   ctx->params.h264_max_qp << CODA_QPMAX_OFFSET,
-			   CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX);
-	}
-	if (dev->devtype->product == CODA_960) {
-		if (ctx->params.h264_max_qp)
-			value |= 1 << CODA9_OPTION_RCQPMAX_OFFSET;
-		if (CODA_DEFAULT_GAMMA > 0)
-			value |= 1 << CODA9_OPTION_GAMMA_OFFSET;
-	} else {
-		if (CODA_DEFAULT_GAMMA > 0) {
-			if (dev->devtype->product == CODA_DX6)
-				value |= 1 << CODADX6_OPTION_GAMMA_OFFSET;
-			else
-				value |= 1 << CODA7_OPTION_GAMMA_OFFSET;
-		}
-		if (ctx->params.h264_min_qp)
-			value |= 1 << CODA7_OPTION_RCQPMIN_OFFSET;
-		if (ctx->params.h264_max_qp)
-			value |= 1 << CODA7_OPTION_RCQPMAX_OFFSET;
-	}
-	coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION);
-
-	if (ctx->params.frame_rc_enable && !ctx->params.mb_rc_enable)
-		value = 1;
-	else
-		value = 0;
-	coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE);
-
-	coda_setup_iram(ctx);
-
-	if (dst_fourcc == V4L2_PIX_FMT_H264) {
-		switch (dev->devtype->product) {
-		case CODA_DX6:
-			value = FMO_SLICE_SAVE_BUF_SIZE << 7;
-			coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO);
-			break;
-		case CODA_HX4:
-		case CODA_7541:
-			coda_write(dev, ctx->iram_info.search_ram_paddr,
-					CODA7_CMD_ENC_SEQ_SEARCH_BASE);
-			coda_write(dev, ctx->iram_info.search_ram_size,
-					CODA7_CMD_ENC_SEQ_SEARCH_SIZE);
-			break;
-		case CODA_960:
-			coda_write(dev, 0, CODA9_CMD_ENC_SEQ_ME_OPTION);
-			coda_write(dev, 0, CODA9_CMD_ENC_SEQ_INTRA_WEIGHT);
-		}
-	}
-
-	ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT);
-	if (ret < 0) {
-		v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n");
-		goto out;
-	}
-
-	if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0) {
-		v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT failed\n");
-		ret = -EFAULT;
-		goto out;
-	}
-	ctx->initialized = 1;
-
-	if (dst_fourcc != V4L2_PIX_FMT_JPEG) {
-		if (dev->devtype->product == CODA_960)
-			ctx->num_internal_frames = 4;
-		else
-			ctx->num_internal_frames = 2;
-		ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc);
-		if (ret < 0) {
-			v4l2_err(v4l2_dev, "failed to allocate framebuffers\n");
-			goto out;
-		}
-		num_fb = 2;
-		stride = q_data_src->bytesperline;
-	} else {
-		ctx->num_internal_frames = 0;
-		num_fb = 0;
-		stride = 0;
-	}
-	coda_write(dev, num_fb, CODA_CMD_SET_FRAME_BUF_NUM);
-	coda_write(dev, stride, CODA_CMD_SET_FRAME_BUF_STRIDE);
-
-	if (dev->devtype->product == CODA_HX4 ||
-	    dev->devtype->product == CODA_7541) {
-		coda_write(dev, q_data_src->bytesperline,
-				CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE);
-	}
-	if (dev->devtype->product != CODA_DX6) {
-		coda_write(dev, ctx->iram_info.buf_bit_use,
-				CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
-		coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use,
-				CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR);
-		coda_write(dev, ctx->iram_info.buf_dbk_y_use,
-				CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR);
-		coda_write(dev, ctx->iram_info.buf_dbk_c_use,
-				CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
-		coda_write(dev, ctx->iram_info.buf_ovl_use,
-				CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
-		if (dev->devtype->product == CODA_960) {
-			coda_write(dev, ctx->iram_info.buf_btp_use,
-					CODA9_CMD_SET_FRAME_AXI_BTP_ADDR);
-
-			coda9_set_frame_cache(ctx, q_data_src->fourcc);
-
-			/* FIXME */
-			coda_write(dev, ctx->internal_frames[2].buf.paddr,
-				   CODA9_CMD_SET_FRAME_SUBSAMP_A);
-			coda_write(dev, ctx->internal_frames[3].buf.paddr,
-				   CODA9_CMD_SET_FRAME_SUBSAMP_B);
-		}
-	}
-
-	ret = coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF);
-	if (ret < 0) {
-		v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n");
-		goto out;
-	}
-
-	coda_dbg(1, ctx, "start encoding %dx%d %4.4s->%4.4s @ %d/%d Hz\n",
-		 q_data_src->rect.width, q_data_src->rect.height,
-		 (char *)&ctx->codec->src_fourcc, (char *)&dst_fourcc,
-		 ctx->params.framerate & 0xffff,
-		 (ctx->params.framerate >> 16) + 1);
-
-	/* Save stream headers */
-	buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-	switch (dst_fourcc) {
-	case V4L2_PIX_FMT_H264:
-		/*
-		 * Get SPS in the first frame and copy it to an
-		 * intermediate buffer.
-		 */
-		ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_SPS,
-					 &ctx->vpu_header[0][0],
-					 &ctx->vpu_header_size[0]);
-		if (ret < 0)
-			goto out;
-
-		/*
-		 * If visible width or height are not aligned to macroblock
-		 * size, the crop_right and crop_bottom SPS fields must be set
-		 * to the difference between visible and coded size.  This is
-		 * only supported by CODA960 firmware. All others do not allow
-		 * writing frame cropping parameters, so we have to manually
-		 * fix up the SPS RBSP (Sequence Parameter Set Raw Byte
-		 * Sequence Payload) ourselves.
-		 */
-		if (ctx->dev->devtype->product != CODA_960 &&
-		    ((q_data_src->rect.width % 16) ||
-		     (q_data_src->rect.height % 16))) {
-			ret = coda_h264_sps_fixup(ctx, q_data_src->rect.width,
-						  q_data_src->rect.height,
-						  &ctx->vpu_header[0][0],
-						  &ctx->vpu_header_size[0],
-						  sizeof(ctx->vpu_header[0]));
-			if (ret < 0)
-				goto out;
-		}
-
-		/*
-		 * Get PPS in the first frame and copy it to an
-		 * intermediate buffer.
-		 */
-		ret = coda_encode_header(ctx, buf, CODA_HEADER_H264_PPS,
-					 &ctx->vpu_header[1][0],
-					 &ctx->vpu_header_size[1]);
-		if (ret < 0)
-			goto out;
-
-		/*
-		 * Length of H.264 headers is variable and thus it might not be
-		 * aligned for the coda to append the encoded frame. In that is
-		 * the case a filler NAL must be added to header 2.
-		 */
-		ctx->vpu_header_size[2] = coda_h264_padding(
-					(ctx->vpu_header_size[0] +
-					 ctx->vpu_header_size[1]),
-					 ctx->vpu_header[2]);
-		break;
-	case V4L2_PIX_FMT_MPEG4:
-		/*
-		 * Get VOS in the first frame and copy it to an
-		 * intermediate buffer
-		 */
-		ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOS,
-					 &ctx->vpu_header[0][0],
-					 &ctx->vpu_header_size[0]);
-		if (ret < 0)
-			goto out;
-
-		ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VIS,
-					 &ctx->vpu_header[1][0],
-					 &ctx->vpu_header_size[1]);
-		if (ret < 0)
-			goto out;
-
-		ret = coda_encode_header(ctx, buf, CODA_HEADER_MP4V_VOL,
-					 &ctx->vpu_header[2][0],
-					 &ctx->vpu_header_size[2]);
-		if (ret < 0)
-			goto out;
-		break;
-	default:
-		/* No more formats need to save headers at the moment */
-		break;
-	}
-
-out:
-	mutex_unlock(&dev->coda_mutex);
-	return ret;
-}
-
-static int coda_prepare_encode(struct coda_ctx *ctx)
-{
-	struct coda_q_data *q_data_src, *q_data_dst;
-	struct vb2_v4l2_buffer *src_buf, *dst_buf;
-	struct coda_dev *dev = ctx->dev;
-	int force_ipicture;
-	int quant_param = 0;
-	u32 pic_stream_buffer_addr, pic_stream_buffer_size;
-	u32 rot_mode = 0;
-	u32 dst_fourcc;
-	u32 reg;
-	int ret;
-
-	ret = coda_enc_param_change(ctx);
-	if (ret < 0) {
-		v4l2_warn(&ctx->dev->v4l2_dev, "parameter change failed: %d\n",
-			  ret);
-	}
-
-	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	dst_fourcc = q_data_dst->fourcc;
-
-	src_buf->sequence = ctx->osequence;
-	dst_buf->sequence = ctx->osequence;
-	ctx->osequence++;
-
-	force_ipicture = ctx->params.force_ipicture;
-	if (force_ipicture)
-		ctx->params.force_ipicture = false;
-	else if (ctx->params.gop_size != 0 &&
-		 (src_buf->sequence % ctx->params.gop_size) == 0)
-		force_ipicture = 1;
-
-	/*
-	 * Workaround coda firmware BUG that only marks the first
-	 * frame as IDR. This is a problem for some decoders that can't
-	 * recover when a frame is lost.
-	 */
-	if (!force_ipicture) {
-		src_buf->flags |= V4L2_BUF_FLAG_PFRAME;
-		src_buf->flags &= ~V4L2_BUF_FLAG_KEYFRAME;
-	} else {
-		src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
-		src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME;
-	}
-
-	if (dev->devtype->product == CODA_960)
-		coda_set_gdi_regs(ctx);
-
-	/*
-	 * Copy headers in front of the first frame and forced I frames for
-	 * H.264 only. In MPEG4 they are already copied by the CODA.
-	 */
-	if (src_buf->sequence == 0 || force_ipicture) {
-		pic_stream_buffer_addr =
-			vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0) +
-			ctx->vpu_header_size[0] +
-			ctx->vpu_header_size[1] +
-			ctx->vpu_header_size[2];
-		pic_stream_buffer_size = q_data_dst->sizeimage -
-			ctx->vpu_header_size[0] -
-			ctx->vpu_header_size[1] -
-			ctx->vpu_header_size[2];
-		memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0),
-		       &ctx->vpu_header[0][0], ctx->vpu_header_size[0]);
-		memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0)
-			+ ctx->vpu_header_size[0], &ctx->vpu_header[1][0],
-			ctx->vpu_header_size[1]);
-		memcpy(vb2_plane_vaddr(&dst_buf->vb2_buf, 0)
-			+ ctx->vpu_header_size[0] + ctx->vpu_header_size[1],
-			&ctx->vpu_header[2][0], ctx->vpu_header_size[2]);
-	} else {
-		pic_stream_buffer_addr =
-			vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
-		pic_stream_buffer_size = q_data_dst->sizeimage;
-	}
-
-	if (force_ipicture) {
-		switch (dst_fourcc) {
-		case V4L2_PIX_FMT_H264:
-			quant_param = ctx->params.h264_intra_qp;
-			break;
-		case V4L2_PIX_FMT_MPEG4:
-			quant_param = ctx->params.mpeg4_intra_qp;
-			break;
-		case V4L2_PIX_FMT_JPEG:
-			quant_param = 30;
-			break;
-		default:
-			v4l2_warn(&ctx->dev->v4l2_dev,
-				"cannot set intra qp, fmt not supported\n");
-			break;
-		}
-	} else {
-		switch (dst_fourcc) {
-		case V4L2_PIX_FMT_H264:
-			quant_param = ctx->params.h264_inter_qp;
-			break;
-		case V4L2_PIX_FMT_MPEG4:
-			quant_param = ctx->params.mpeg4_inter_qp;
-			break;
-		default:
-			v4l2_warn(&ctx->dev->v4l2_dev,
-				"cannot set inter qp, fmt not supported\n");
-			break;
-		}
-	}
-
-	/* submit */
-	if (ctx->params.rot_mode)
-		rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode;
-	coda_write(dev, rot_mode, CODA_CMD_ENC_PIC_ROT_MODE);
-	coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS);
-
-	if (dev->devtype->product == CODA_960) {
-		coda_write(dev, 4/*FIXME: 0*/, CODA9_CMD_ENC_PIC_SRC_INDEX);
-		coda_write(dev, q_data_src->bytesperline,
-			   CODA9_CMD_ENC_PIC_SRC_STRIDE);
-		coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC);
-
-		reg = CODA9_CMD_ENC_PIC_SRC_ADDR_Y;
-	} else {
-		reg = CODA_CMD_ENC_PIC_SRC_ADDR_Y;
-	}
-	coda_write_base(ctx, q_data_src, src_buf, reg);
-
-	coda_write(dev, force_ipicture << 1 & 0x2,
-		   CODA_CMD_ENC_PIC_OPTION);
-
-	coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START);
-	coda_write(dev, pic_stream_buffer_size / 1024,
-		   CODA_CMD_ENC_PIC_BB_SIZE);
-
-	if (!ctx->streamon_out) {
-		/* After streamoff on the output side, set stream end flag */
-		ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
-		coda_write(dev, ctx->bit_stream_param,
-			   CODA_REG_BIT_BIT_STREAM_PARAM);
-	}
-
-	if (dev->devtype->product != CODA_DX6)
-		coda_write(dev, ctx->iram_info.axi_sram_use,
-				CODA7_REG_BIT_AXI_SRAM_USE);
-
-	trace_coda_enc_pic_run(ctx, src_buf);
-
-	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
-
-	return 0;
-}
-
-static char coda_frame_type_char(u32 flags)
-{
-	return (flags & V4L2_BUF_FLAG_KEYFRAME) ? 'I' :
-	       (flags & V4L2_BUF_FLAG_PFRAME) ? 'P' :
-	       (flags & V4L2_BUF_FLAG_BFRAME) ? 'B' : '?';
-}
-
-static void coda_finish_encode(struct coda_ctx *ctx)
-{
-	struct vb2_v4l2_buffer *src_buf, *dst_buf;
-	struct coda_dev *dev = ctx->dev;
-	u32 wr_ptr, start_ptr;
-
-	if (ctx->aborting)
-		return;
-
-	/*
-	 * Lock to make sure that an encoder stop command running in parallel
-	 * will either already have marked src_buf as last, or it will wake up
-	 * the capture queue after the buffers are returned.
-	 */
-	mutex_lock(&ctx->wakeup_mutex);
-	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-
-	trace_coda_enc_pic_done(ctx, dst_buf);
-
-	/* Get results from the coda */
-	start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START);
-	wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->reg_idx));
-
-	/* Calculate bytesused field */
-	if (dst_buf->sequence == 0 ||
-	    src_buf->flags & V4L2_BUF_FLAG_KEYFRAME) {
-		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr +
-					ctx->vpu_header_size[0] +
-					ctx->vpu_header_size[1] +
-					ctx->vpu_header_size[2]);
-	} else {
-		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr);
-	}
-
-	coda_dbg(1, ctx, "frame size = %u\n", wr_ptr - start_ptr);
-
-	coda_read(dev, CODA_RET_ENC_PIC_SLICE_NUM);
-	coda_read(dev, CODA_RET_ENC_PIC_FLAG);
-
-	dst_buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
-			    V4L2_BUF_FLAG_PFRAME |
-			    V4L2_BUF_FLAG_LAST);
-	if (coda_read(dev, CODA_RET_ENC_PIC_TYPE) == 0)
-		dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
-	else
-		dst_buf->flags |= V4L2_BUF_FLAG_PFRAME;
-	dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST;
-
-	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
-
-	v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
-
-	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-	coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_DONE);
-	mutex_unlock(&ctx->wakeup_mutex);
-
-	ctx->gopcounter--;
-	if (ctx->gopcounter < 0)
-		ctx->gopcounter = ctx->params.gop_size - 1;
-
-	coda_dbg(1, ctx, "job finished: encoded %c frame (%d)%s\n",
-		 coda_frame_type_char(dst_buf->flags), dst_buf->sequence,
-		 (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : "");
-}
-
-static void coda_seq_end_work(struct work_struct *work)
-{
-	struct coda_ctx *ctx = container_of(work, struct coda_ctx, seq_end_work);
-	struct coda_dev *dev = ctx->dev;
-
-	mutex_lock(&ctx->buffer_mutex);
-	mutex_lock(&dev->coda_mutex);
-
-	if (ctx->initialized == 0)
-		goto out;
-
-	coda_dbg(1, ctx, "%s: sent command 'SEQ_END' to coda\n", __func__);
-	if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
-		v4l2_err(&dev->v4l2_dev,
-			 "CODA_COMMAND_SEQ_END failed\n");
-	}
-
-	/*
-	 * FIXME: Sometimes h.264 encoding fails with 8-byte sequences missing
-	 * from the output stream after the h.264 decoder has run. Resetting the
-	 * hardware after the decoder has finished seems to help.
-	 */
-	if (dev->devtype->product == CODA_960)
-		coda_hw_reset(ctx);
-
-	kfifo_init(&ctx->bitstream_fifo,
-		ctx->bitstream.vaddr, ctx->bitstream.size);
-
-	coda_free_framebuffers(ctx);
-
-	ctx->initialized = 0;
-
-out:
-	mutex_unlock(&dev->coda_mutex);
-	mutex_unlock(&ctx->buffer_mutex);
-}
-
-static void coda_bit_release(struct coda_ctx *ctx)
-{
-	mutex_lock(&ctx->buffer_mutex);
-	coda_free_framebuffers(ctx);
-	coda_free_context_buffers(ctx);
-	coda_free_bitstream_buffer(ctx);
-	mutex_unlock(&ctx->buffer_mutex);
-}
-
-const struct coda_context_ops coda_bit_encode_ops = {
-	.queue_init = coda_encoder_queue_init,
-	.reqbufs = coda_encoder_reqbufs,
-	.start_streaming = coda_start_encoding,
-	.prepare_run = coda_prepare_encode,
-	.finish_run = coda_finish_encode,
-	.seq_end_work = coda_seq_end_work,
-	.release = coda_bit_release,
-};
-
-/*
- * Decoder context operations
- */
-
-static int coda_alloc_bitstream_buffer(struct coda_ctx *ctx,
-				       struct coda_q_data *q_data)
-{
-	if (ctx->bitstream.vaddr)
-		return 0;
-
-	ctx->bitstream.size = roundup_pow_of_two(q_data->sizeimage * 2);
-	ctx->bitstream.vaddr = dma_alloc_wc(ctx->dev->dev, ctx->bitstream.size,
-					    &ctx->bitstream.paddr, GFP_KERNEL);
-	if (!ctx->bitstream.vaddr) {
-		v4l2_err(&ctx->dev->v4l2_dev,
-			 "failed to allocate bitstream ringbuffer");
-		return -ENOMEM;
-	}
-	kfifo_init(&ctx->bitstream_fifo,
-		   ctx->bitstream.vaddr, ctx->bitstream.size);
-
-	return 0;
-}
-
-static void coda_free_bitstream_buffer(struct coda_ctx *ctx)
-{
-	if (ctx->bitstream.vaddr == NULL)
-		return;
-
-	dma_free_wc(ctx->dev->dev, ctx->bitstream.size, ctx->bitstream.vaddr,
-		    ctx->bitstream.paddr);
-	ctx->bitstream.vaddr = NULL;
-	kfifo_init(&ctx->bitstream_fifo, NULL, 0);
-}
-
-static int coda_decoder_reqbufs(struct coda_ctx *ctx,
-				struct v4l2_requestbuffers *rb)
-{
-	struct coda_q_data *q_data_src;
-	int ret;
-
-	if (rb->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		return 0;
-
-	if (rb->count) {
-		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-		ret = coda_alloc_context_buffers(ctx, q_data_src);
-		if (ret < 0)
-			return ret;
-		ret = coda_alloc_bitstream_buffer(ctx, q_data_src);
-		if (ret < 0) {
-			coda_free_context_buffers(ctx);
-			return ret;
-		}
-	} else {
-		coda_free_bitstream_buffer(ctx);
-		coda_free_context_buffers(ctx);
-	}
-
-	return 0;
-}
-
-static bool coda_reorder_enable(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	int profile;
-
-	if (dev->devtype->product != CODA_HX4 &&
-	    dev->devtype->product != CODA_7541 &&
-	    dev->devtype->product != CODA_960)
-		return false;
-
-	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG)
-		return false;
-
-	if (ctx->codec->src_fourcc != V4L2_PIX_FMT_H264)
-		return true;
-
-	profile = coda_h264_profile(ctx->params.h264_profile_idc);
-	if (profile < 0)
-		v4l2_warn(&dev->v4l2_dev, "Unknown H264 Profile: %u\n",
-			  ctx->params.h264_profile_idc);
-
-	/* Baseline profile does not support reordering */
-	return profile > V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
-}
-
-static void coda_decoder_drop_used_metas(struct coda_ctx *ctx)
-{
-	struct coda_buffer_meta *meta, *tmp;
-
-	/*
-	 * All metas that end at or before the RD pointer (fifo out),
-	 * are now consumed by the VPU and should be released.
-	 */
-	spin_lock(&ctx->buffer_meta_lock);
-	list_for_each_entry_safe(meta, tmp, &ctx->buffer_meta_list, list) {
-		if (ctx->bitstream_fifo.kfifo.out >= meta->end) {
-			coda_dbg(2, ctx, "releasing meta: seq=%d start=%d end=%d\n",
-				 meta->sequence, meta->start, meta->end);
-
-			list_del(&meta->list);
-			ctx->num_metas--;
-			ctx->first_frame_sequence++;
-			kfree(meta);
-		}
-	}
-	spin_unlock(&ctx->buffer_meta_lock);
-}
-
-static int __coda_decoder_seq_init(struct coda_ctx *ctx)
-{
-	struct coda_q_data *q_data_src, *q_data_dst;
-	u32 bitstream_buf, bitstream_size;
-	struct coda_dev *dev = ctx->dev;
-	int width, height;
-	u32 src_fourcc, dst_fourcc;
-	u32 val;
-	int ret;
-
-	lockdep_assert_held(&dev->coda_mutex);
-
-	coda_dbg(1, ctx, "Video Data Order Adapter: %s\n",
-		 ctx->use_vdoa ? "Enabled" : "Disabled");
-
-	/* Start decoding */
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	bitstream_buf = ctx->bitstream.paddr;
-	bitstream_size = ctx->bitstream.size;
-	src_fourcc = q_data_src->fourcc;
-	dst_fourcc = q_data_dst->fourcc;
-
-	/* Update coda bitstream read and write pointers from kfifo */
-	coda_kfifo_sync_to_device_full(ctx);
-
-	ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) |
-				 CODA9_FRAME_TILED2LINEAR);
-	if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV)
-		ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
-	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
-		ctx->frame_mem_ctrl |= (0x3 << 9) |
-			((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR);
-	coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL);
-
-	ctx->display_idx = -1;
-	ctx->frm_dis_flg = 0;
-	coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
-
-	coda_write(dev, bitstream_buf, CODA_CMD_DEC_SEQ_BB_START);
-	coda_write(dev, bitstream_size / 1024, CODA_CMD_DEC_SEQ_BB_SIZE);
-	val = 0;
-	if (coda_reorder_enable(ctx))
-		val |= CODA_REORDER_ENABLE;
-	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG)
-		val |= CODA_NO_INT_ENABLE;
-	coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION);
-
-	ctx->params.codec_mode = ctx->codec->mode;
-	if (dev->devtype->product == CODA_960 &&
-	    src_fourcc == V4L2_PIX_FMT_MPEG4)
-		ctx->params.codec_mode_aux = CODA_MP4_AUX_MPEG4;
-	else
-		ctx->params.codec_mode_aux = 0;
-	if (src_fourcc == V4L2_PIX_FMT_MPEG4) {
-		coda_write(dev, CODA_MP4_CLASS_MPEG4,
-			   CODA_CMD_DEC_SEQ_MP4_ASP_CLASS);
-	}
-	if (src_fourcc == V4L2_PIX_FMT_H264) {
-		if (dev->devtype->product == CODA_HX4 ||
-		    dev->devtype->product == CODA_7541) {
-			coda_write(dev, ctx->psbuf.paddr,
-					CODA_CMD_DEC_SEQ_PS_BB_START);
-			coda_write(dev, (CODA7_PS_BUF_SIZE / 1024),
-					CODA_CMD_DEC_SEQ_PS_BB_SIZE);
-		}
-		if (dev->devtype->product == CODA_960) {
-			coda_write(dev, 0, CODA_CMD_DEC_SEQ_X264_MV_EN);
-			coda_write(dev, 512, CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE);
-		}
-	}
-	if (src_fourcc == V4L2_PIX_FMT_JPEG)
-		coda_write(dev, 0, CODA_CMD_DEC_SEQ_JPG_THUMB_EN);
-	if (dev->devtype->product != CODA_960)
-		coda_write(dev, 0, CODA_CMD_DEC_SEQ_SRC_SIZE);
-
-	ctx->bit_stream_param = CODA_BIT_DEC_SEQ_INIT_ESCAPE;
-	ret = coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT);
-	ctx->bit_stream_param = 0;
-	if (ret) {
-		v4l2_err(&dev->v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n");
-		return ret;
-	}
-	ctx->sequence_offset = ~0U;
-	ctx->initialized = 1;
-	ctx->first_frame_sequence = 0;
-
-	/* Update kfifo out pointer from coda bitstream read pointer */
-	coda_kfifo_sync_from_device(ctx);
-
-	/*
-	 * After updating the read pointer, we need to check if
-	 * any metas are consumed and should be released.
-	 */
-	coda_decoder_drop_used_metas(ctx);
-
-	if (coda_read(dev, CODA_RET_DEC_SEQ_SUCCESS) == 0) {
-		v4l2_err(&dev->v4l2_dev,
-			"CODA_COMMAND_SEQ_INIT failed, error code = 0x%x\n",
-			coda_read(dev, CODA_RET_DEC_SEQ_ERR_REASON));
-		return -EAGAIN;
-	}
-
-	val = coda_read(dev, CODA_RET_DEC_SEQ_SRC_SIZE);
-	if (dev->devtype->product == CODA_DX6) {
-		width = (val >> CODADX6_PICWIDTH_OFFSET) & CODADX6_PICWIDTH_MASK;
-		height = val & CODADX6_PICHEIGHT_MASK;
-	} else {
-		width = (val >> CODA7_PICWIDTH_OFFSET) & CODA7_PICWIDTH_MASK;
-		height = val & CODA7_PICHEIGHT_MASK;
-	}
-
-	if (width > q_data_dst->bytesperline || height > q_data_dst->height) {
-		v4l2_err(&dev->v4l2_dev, "stream is %dx%d, not %dx%d\n",
-			 width, height, q_data_dst->bytesperline,
-			 q_data_dst->height);
-		return -EINVAL;
-	}
-
-	width = round_up(width, 16);
-	height = round_up(height, 16);
-
-	coda_dbg(1, ctx, "start decoding: %dx%d\n", width, height);
-
-	ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED);
-	/*
-	 * If the VDOA is used, the decoder needs one additional frame,
-	 * because the frames are freed when the next frame is decoded.
-	 * Otherwise there are visible errors in the decoded frames (green
-	 * regions in displayed frames) and a broken order of frames (earlier
-	 * frames are sporadically displayed after later frames).
-	 */
-	if (ctx->use_vdoa)
-		ctx->num_internal_frames += 1;
-	if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) {
-		v4l2_err(&dev->v4l2_dev,
-			 "not enough framebuffers to decode (%d < %d)\n",
-			 CODA_MAX_FRAMEBUFFERS, ctx->num_internal_frames);
-		return -EINVAL;
-	}
-
-	if (src_fourcc == V4L2_PIX_FMT_H264) {
-		u32 left_right;
-		u32 top_bottom;
-
-		left_right = coda_read(dev, CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT);
-		top_bottom = coda_read(dev, CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM);
-
-		q_data_dst->rect.left = (left_right >> 10) & 0x3ff;
-		q_data_dst->rect.top = (top_bottom >> 10) & 0x3ff;
-		q_data_dst->rect.width = width - q_data_dst->rect.left -
-					 (left_right & 0x3ff);
-		q_data_dst->rect.height = height - q_data_dst->rect.top -
-					  (top_bottom & 0x3ff);
-	}
-
-	if (dev->devtype->product != CODA_DX6) {
-		u8 profile, level;
-
-		val = coda_read(dev, CODA7_RET_DEC_SEQ_HEADER_REPORT);
-		profile = val & 0xff;
-		level = (val >> 8) & 0x7f;
-
-		if (profile || level)
-			coda_update_profile_level_ctrls(ctx, profile, level);
-	}
-
-	return 0;
-}
-
-static void coda_dec_seq_init_work(struct work_struct *work)
-{
-	struct coda_ctx *ctx = container_of(work,
-					    struct coda_ctx, seq_init_work);
-	struct coda_dev *dev = ctx->dev;
-
-	mutex_lock(&ctx->buffer_mutex);
-	mutex_lock(&dev->coda_mutex);
-
-	if (!ctx->initialized)
-		__coda_decoder_seq_init(ctx);
-
-	mutex_unlock(&dev->coda_mutex);
-	mutex_unlock(&ctx->buffer_mutex);
-}
-
-static int __coda_start_decoding(struct coda_ctx *ctx)
-{
-	struct coda_q_data *q_data_src, *q_data_dst;
-	struct coda_dev *dev = ctx->dev;
-	u32 src_fourcc, dst_fourcc;
-	int ret;
-
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	src_fourcc = q_data_src->fourcc;
-	dst_fourcc = q_data_dst->fourcc;
-
-	if (!ctx->initialized) {
-		ret = __coda_decoder_seq_init(ctx);
-		if (ret < 0)
-			return ret;
-	} else {
-		ctx->frame_mem_ctrl &= ~(CODA_FRAME_CHROMA_INTERLEAVE | (0x3 << 9) |
-					 CODA9_FRAME_TILED2LINEAR);
-		if (dst_fourcc == V4L2_PIX_FMT_NV12 || dst_fourcc == V4L2_PIX_FMT_YUYV)
-			ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
-		if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
-			ctx->frame_mem_ctrl |= (0x3 << 9) |
-				((ctx->use_vdoa) ? 0 : CODA9_FRAME_TILED2LINEAR);
-	}
-
-	coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
-
-	ret = coda_alloc_framebuffers(ctx, q_data_dst, src_fourcc);
-	if (ret < 0) {
-		v4l2_err(&dev->v4l2_dev, "failed to allocate framebuffers\n");
-		return ret;
-	}
-
-	/* Tell the decoder how many frame buffers we allocated. */
-	coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
-	coda_write(dev, round_up(q_data_dst->rect.width, 16),
-		   CODA_CMD_SET_FRAME_BUF_STRIDE);
-
-	if (dev->devtype->product != CODA_DX6) {
-		/* Set secondary AXI IRAM */
-		coda_setup_iram(ctx);
-
-		coda_write(dev, ctx->iram_info.buf_bit_use,
-				CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
-		coda_write(dev, ctx->iram_info.buf_ip_ac_dc_use,
-				CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR);
-		coda_write(dev, ctx->iram_info.buf_dbk_y_use,
-				CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR);
-		coda_write(dev, ctx->iram_info.buf_dbk_c_use,
-				CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
-		coda_write(dev, ctx->iram_info.buf_ovl_use,
-				CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
-		if (dev->devtype->product == CODA_960) {
-			coda_write(dev, ctx->iram_info.buf_btp_use,
-					CODA9_CMD_SET_FRAME_AXI_BTP_ADDR);
-
-			coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY);
-			coda9_set_frame_cache(ctx, dst_fourcc);
-		}
-	}
-
-	if (src_fourcc == V4L2_PIX_FMT_H264) {
-		coda_write(dev, ctx->slicebuf.paddr,
-				CODA_CMD_SET_FRAME_SLICE_BB_START);
-		coda_write(dev, ctx->slicebuf.size / 1024,
-				CODA_CMD_SET_FRAME_SLICE_BB_SIZE);
-	}
-
-	if (dev->devtype->product == CODA_HX4 ||
-	    dev->devtype->product == CODA_7541) {
-		int max_mb_x = 1920 / 16;
-		int max_mb_y = 1088 / 16;
-		int max_mb_num = max_mb_x * max_mb_y;
-
-		coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y,
-				CODA7_CMD_SET_FRAME_MAX_DEC_SIZE);
-	} else if (dev->devtype->product == CODA_960) {
-		int max_mb_x = 1920 / 16;
-		int max_mb_y = 1088 / 16;
-		int max_mb_num = max_mb_x * max_mb_y;
-
-		coda_write(dev, max_mb_num << 16 | max_mb_x << 8 | max_mb_y,
-				CODA9_CMD_SET_FRAME_MAX_DEC_SIZE);
-	}
-
-	if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) {
-		v4l2_err(&ctx->dev->v4l2_dev,
-			 "CODA_COMMAND_SET_FRAME_BUF timeout\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-
-static int coda_start_decoding(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	int ret;
-
-	mutex_lock(&dev->coda_mutex);
-	ret = __coda_start_decoding(ctx);
-	mutex_unlock(&dev->coda_mutex);
-
-	return ret;
-}
-
-static int coda_prepare_decode(struct coda_ctx *ctx)
-{
-	struct vb2_v4l2_buffer *dst_buf;
-	struct coda_dev *dev = ctx->dev;
-	struct coda_q_data *q_data_dst;
-	struct coda_buffer_meta *meta;
-	u32 rot_mode = 0;
-	u32 reg_addr, reg_stride;
-
-	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-
-	/* Try to copy source buffer contents into the bitstream ringbuffer */
-	mutex_lock(&ctx->bitstream_mutex);
-	coda_fill_bitstream(ctx, NULL);
-	mutex_unlock(&ctx->bitstream_mutex);
-
-	if (coda_get_bitstream_payload(ctx) < 512 &&
-	    (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
-		coda_dbg(1, ctx, "bitstream payload: %d, skipping\n",
-			 coda_get_bitstream_payload(ctx));
-		return -EAGAIN;
-	}
-
-	/* Run coda_start_decoding (again) if not yet initialized */
-	if (!ctx->initialized) {
-		int ret = __coda_start_decoding(ctx);
-
-		if (ret < 0) {
-			v4l2_err(&dev->v4l2_dev, "failed to start decoding\n");
-			return -EAGAIN;
-		} else {
-			ctx->initialized = 1;
-		}
-	}
-
-	if (dev->devtype->product == CODA_960)
-		coda_set_gdi_regs(ctx);
-
-	if (ctx->use_vdoa &&
-	    ctx->display_idx >= 0 &&
-	    ctx->display_idx < ctx->num_internal_frames) {
-		vdoa_device_run(ctx->vdoa,
-				vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0),
-				ctx->internal_frames[ctx->display_idx].buf.paddr);
-	} else {
-		if (dev->devtype->product == CODA_960) {
-			/*
-			 * It was previously assumed that the CODA960 has an
-			 * internal list of 64 buffer entries that contains
-			 * both the registered internal frame buffers as well
-			 * as the rotator buffer output, and that the ROT_INDEX
-			 * register must be set to a value between the last
-			 * internal frame buffers' index and 64.
-			 * At least on firmware version 3.1.1 it turns out that
-			 * setting ROT_INDEX to any value >= 32 causes CODA
-			 * hangups that it can not recover from with the SRC VPU
-			 * reset.
-			 * It does appear to work however, to just set it to a
-			 * fixed value in the [ctx->num_internal_frames, 31]
-			 * range, for example CODA_MAX_FRAMEBUFFERS.
-			 */
-			coda_write(dev, CODA_MAX_FRAMEBUFFERS,
-				   CODA9_CMD_DEC_PIC_ROT_INDEX);
-
-			reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y;
-			reg_stride = CODA9_CMD_DEC_PIC_ROT_STRIDE;
-		} else {
-			reg_addr = CODA_CMD_DEC_PIC_ROT_ADDR_Y;
-			reg_stride = CODA_CMD_DEC_PIC_ROT_STRIDE;
-		}
-		coda_write_base(ctx, q_data_dst, dst_buf, reg_addr);
-		coda_write(dev, q_data_dst->bytesperline, reg_stride);
-
-		rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode;
-	}
-
-	coda_write(dev, rot_mode, CODA_CMD_DEC_PIC_ROT_MODE);
-
-	switch (dev->devtype->product) {
-	case CODA_DX6:
-		/* TBD */
-	case CODA_HX4:
-	case CODA_7541:
-		coda_write(dev, CODA_PRE_SCAN_EN, CODA_CMD_DEC_PIC_OPTION);
-		break;
-	case CODA_960:
-		/* 'hardcode to use interrupt disable mode'? */
-		coda_write(dev, (1 << 10), CODA_CMD_DEC_PIC_OPTION);
-		break;
-	}
-
-	coda_write(dev, 0, CODA_CMD_DEC_PIC_SKIP_NUM);
-
-	coda_write(dev, 0, CODA_CMD_DEC_PIC_BB_START);
-	coda_write(dev, 0, CODA_CMD_DEC_PIC_START_BYTE);
-
-	if (dev->devtype->product != CODA_DX6)
-		coda_write(dev, ctx->iram_info.axi_sram_use,
-				CODA7_REG_BIT_AXI_SRAM_USE);
-
-	spin_lock(&ctx->buffer_meta_lock);
-	meta = list_first_entry_or_null(&ctx->buffer_meta_list,
-					struct coda_buffer_meta, list);
-
-	if (meta && ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) {
-
-		/* If this is the last buffer in the bitstream, add padding */
-		if (meta->end == ctx->bitstream_fifo.kfifo.in) {
-			static unsigned char buf[512];
-			unsigned int pad;
-
-			/* Pad to multiple of 256 and then add 256 more */
-			pad = ((0 - meta->end) & 0xff) + 256;
-
-			memset(buf, 0xff, sizeof(buf));
-
-			kfifo_in(&ctx->bitstream_fifo, buf, pad);
-		}
-	}
-	spin_unlock(&ctx->buffer_meta_lock);
-
-	coda_kfifo_sync_to_device_full(ctx);
-
-	/* Clear decode success flag */
-	coda_write(dev, 0, CODA_RET_DEC_PIC_SUCCESS);
-
-	/* Clear error return value */
-	coda_write(dev, 0, CODA_RET_DEC_PIC_ERR_MB);
-
-	trace_coda_dec_pic_run(ctx, meta);
-
-	coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
-
-	return 0;
-}
-
-static void coda_finish_decode(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	struct coda_q_data *q_data_src;
-	struct coda_q_data *q_data_dst;
-	struct vb2_v4l2_buffer *dst_buf;
-	struct coda_buffer_meta *meta;
-	int width, height;
-	int decoded_idx;
-	int display_idx;
-	struct coda_internal_frame *decoded_frame = NULL;
-	u32 src_fourcc;
-	int success;
-	u32 err_mb;
-	int err_vdoa = 0;
-	u32 val;
-
-	if (ctx->aborting)
-		return;
-
-	/* Update kfifo out pointer from coda bitstream read pointer */
-	coda_kfifo_sync_from_device(ctx);
-
-	/*
-	 * in stream-end mode, the read pointer can overshoot the write pointer
-	 * by up to 512 bytes
-	 */
-	if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG) {
-		if (coda_get_bitstream_payload(ctx) >= ctx->bitstream.size - 512)
-			kfifo_init(&ctx->bitstream_fifo,
-				ctx->bitstream.vaddr, ctx->bitstream.size);
-	}
-
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	src_fourcc = q_data_src->fourcc;
-
-	val = coda_read(dev, CODA_RET_DEC_PIC_SUCCESS);
-	if (val != 1)
-		pr_err("DEC_PIC_SUCCESS = %d\n", val);
-
-	success = val & 0x1;
-	if (!success)
-		v4l2_err(&dev->v4l2_dev, "decode failed\n");
-
-	if (src_fourcc == V4L2_PIX_FMT_H264) {
-		if (val & (1 << 3))
-			v4l2_err(&dev->v4l2_dev,
-				 "insufficient PS buffer space (%d bytes)\n",
-				 ctx->psbuf.size);
-		if (val & (1 << 2))
-			v4l2_err(&dev->v4l2_dev,
-				 "insufficient slice buffer space (%d bytes)\n",
-				 ctx->slicebuf.size);
-	}
-
-	val = coda_read(dev, CODA_RET_DEC_PIC_SIZE);
-	width = (val >> 16) & 0xffff;
-	height = val & 0xffff;
-
-	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-
-	/* frame crop information */
-	if (src_fourcc == V4L2_PIX_FMT_H264) {
-		u32 left_right;
-		u32 top_bottom;
-
-		left_right = coda_read(dev, CODA_RET_DEC_PIC_CROP_LEFT_RIGHT);
-		top_bottom = coda_read(dev, CODA_RET_DEC_PIC_CROP_TOP_BOTTOM);
-
-		if (left_right == 0xffffffff && top_bottom == 0xffffffff) {
-			/* Keep current crop information */
-		} else {
-			struct v4l2_rect *rect = &q_data_dst->rect;
-
-			rect->left = left_right >> 16 & 0xffff;
-			rect->top = top_bottom >> 16 & 0xffff;
-			rect->width = width - rect->left -
-				      (left_right & 0xffff);
-			rect->height = height - rect->top -
-				       (top_bottom & 0xffff);
-		}
-	} else {
-		/* no cropping */
-	}
-
-	err_mb = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB);
-	if (err_mb > 0) {
-		if (__ratelimit(&dev->mb_err_rs))
-			coda_dbg(1, ctx, "errors in %d macroblocks\n", err_mb);
-		v4l2_ctrl_s_ctrl(ctx->mb_err_cnt_ctrl,
-				 v4l2_ctrl_g_ctrl(ctx->mb_err_cnt_ctrl) + err_mb);
-	}
-
-	if (dev->devtype->product == CODA_HX4 ||
-	    dev->devtype->product == CODA_7541) {
-		val = coda_read(dev, CODA_RET_DEC_PIC_OPTION);
-		if (val == 0) {
-			/* not enough bitstream data */
-			coda_dbg(1, ctx, "prescan failed: %d\n", val);
-			ctx->hold = true;
-			return;
-		}
-	}
-
-	/* Wait until the VDOA finished writing the previous display frame */
-	if (ctx->use_vdoa &&
-	    ctx->display_idx >= 0 &&
-	    ctx->display_idx < ctx->num_internal_frames) {
-		err_vdoa = vdoa_wait_for_completion(ctx->vdoa);
-	}
-
-	ctx->frm_dis_flg = coda_read(dev,
-				     CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
-
-	/* The previous display frame was copied out and can be overwritten */
-	if (ctx->display_idx >= 0 &&
-	    ctx->display_idx < ctx->num_internal_frames) {
-		ctx->frm_dis_flg &= ~(1 << ctx->display_idx);
-		coda_write(dev, ctx->frm_dis_flg,
-				CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
-	}
-
-	/*
-	 * The index of the last decoded frame, not necessarily in
-	 * display order, and the index of the next display frame.
-	 * The latter could have been decoded in a previous run.
-	 */
-	decoded_idx = coda_read(dev, CODA_RET_DEC_PIC_CUR_IDX);
-	display_idx = coda_read(dev, CODA_RET_DEC_PIC_FRAME_IDX);
-
-	if (decoded_idx == -1) {
-		/* no frame was decoded, but we might have a display frame */
-		if (display_idx >= 0 && display_idx < ctx->num_internal_frames)
-			ctx->sequence_offset++;
-		else if (ctx->display_idx < 0)
-			ctx->hold = true;
-	} else if (decoded_idx == -2) {
-		if (ctx->display_idx >= 0 &&
-		    ctx->display_idx < ctx->num_internal_frames)
-			ctx->sequence_offset++;
-		/* no frame was decoded, we still return remaining buffers */
-	} else if (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) {
-		v4l2_err(&dev->v4l2_dev,
-			 "decoded frame index out of range: %d\n", decoded_idx);
-	} else {
-		int sequence;
-
-		decoded_frame = &ctx->internal_frames[decoded_idx];
-
-		val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM);
-		if (ctx->sequence_offset == -1)
-			ctx->sequence_offset = val;
-
-		sequence = val + ctx->first_frame_sequence
-			       - ctx->sequence_offset;
-		spin_lock(&ctx->buffer_meta_lock);
-		if (!list_empty(&ctx->buffer_meta_list)) {
-			meta = list_first_entry(&ctx->buffer_meta_list,
-					      struct coda_buffer_meta, list);
-			list_del(&meta->list);
-			ctx->num_metas--;
-			spin_unlock(&ctx->buffer_meta_lock);
-			/*
-			 * Clamp counters to 16 bits for comparison, as the HW
-			 * counter rolls over at this point for h.264. This
-			 * may be different for other formats, but using 16 bits
-			 * should be enough to detect most errors and saves us
-			 * from doing different things based on the format.
-			 */
-			if ((sequence & 0xffff) != (meta->sequence & 0xffff)) {
-				v4l2_err(&dev->v4l2_dev,
-					 "sequence number mismatch (%d(%d) != %d)\n",
-					 sequence, ctx->sequence_offset,
-					 meta->sequence);
-			}
-			decoded_frame->meta = *meta;
-			kfree(meta);
-		} else {
-			spin_unlock(&ctx->buffer_meta_lock);
-			v4l2_err(&dev->v4l2_dev, "empty timestamp list!\n");
-			memset(&decoded_frame->meta, 0,
-			       sizeof(struct coda_buffer_meta));
-			decoded_frame->meta.sequence = sequence;
-			decoded_frame->meta.last = false;
-			ctx->sequence_offset++;
-		}
-
-		trace_coda_dec_pic_done(ctx, &decoded_frame->meta);
-
-		val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7;
-		decoded_frame->type = (val == 0) ? V4L2_BUF_FLAG_KEYFRAME :
-				      (val == 1) ? V4L2_BUF_FLAG_PFRAME :
-						   V4L2_BUF_FLAG_BFRAME;
-
-		decoded_frame->error = err_mb;
-	}
-
-	if (display_idx == -1) {
-		/*
-		 * no more frames to be decoded, but there could still
-		 * be rotator output to dequeue
-		 */
-		ctx->hold = true;
-	} else if (display_idx == -3) {
-		/* possibly prescan failure */
-	} else if (display_idx < 0 || display_idx >= ctx->num_internal_frames) {
-		v4l2_err(&dev->v4l2_dev,
-			 "presentation frame index out of range: %d\n",
-			 display_idx);
-	}
-
-	/* If a frame was copied out, return it */
-	if (ctx->display_idx >= 0 &&
-	    ctx->display_idx < ctx->num_internal_frames) {
-		struct coda_internal_frame *ready_frame;
-
-		ready_frame = &ctx->internal_frames[ctx->display_idx];
-
-		dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-		dst_buf->sequence = ctx->osequence++;
-
-		dst_buf->field = V4L2_FIELD_NONE;
-		dst_buf->flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
-					     V4L2_BUF_FLAG_PFRAME |
-					     V4L2_BUF_FLAG_BFRAME);
-		dst_buf->flags |= ready_frame->type;
-		meta = &ready_frame->meta;
-		if (meta->last && !coda_reorder_enable(ctx)) {
-			/*
-			 * If this was the last decoded frame, and reordering
-			 * is disabled, this will be the last display frame.
-			 */
-			coda_dbg(1, ctx, "last meta, marking as last frame\n");
-			dst_buf->flags |= V4L2_BUF_FLAG_LAST;
-		} else if (ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG &&
-			   display_idx == -1) {
-			/*
-			 * If there is no designated presentation frame anymore,
-			 * this frame has to be the last one.
-			 */
-			coda_dbg(1, ctx,
-				 "no more frames to return, marking as last frame\n");
-			dst_buf->flags |= V4L2_BUF_FLAG_LAST;
-		}
-		dst_buf->timecode = meta->timecode;
-		dst_buf->vb2_buf.timestamp = meta->timestamp;
-
-		trace_coda_dec_rot_done(ctx, dst_buf, meta);
-
-		vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
-				      q_data_dst->sizeimage);
-
-		if (ready_frame->error || err_vdoa)
-			coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_ERROR);
-		else
-			coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_DONE);
-
-		if (decoded_frame) {
-			coda_dbg(1, ctx, "job finished: decoded %c frame %u, returned %c frame %u (%u/%u)%s\n",
-				 coda_frame_type_char(decoded_frame->type),
-				 decoded_frame->meta.sequence,
-				 coda_frame_type_char(dst_buf->flags),
-				 ready_frame->meta.sequence,
-				 dst_buf->sequence, ctx->qsequence,
-				 (dst_buf->flags & V4L2_BUF_FLAG_LAST) ?
-				 " (last)" : "");
-		} else {
-			coda_dbg(1, ctx, "job finished: no frame decoded (%d), returned %c frame %u (%u/%u)%s\n",
-				 decoded_idx,
-				 coda_frame_type_char(dst_buf->flags),
-				 ready_frame->meta.sequence,
-				 dst_buf->sequence, ctx->qsequence,
-				 (dst_buf->flags & V4L2_BUF_FLAG_LAST) ?
-				 " (last)" : "");
-		}
-	} else {
-		if (decoded_frame) {
-			coda_dbg(1, ctx, "job finished: decoded %c frame %u, no frame returned (%d)\n",
-				 coda_frame_type_char(decoded_frame->type),
-				 decoded_frame->meta.sequence,
-				 ctx->display_idx);
-		} else {
-			coda_dbg(1, ctx, "job finished: no frame decoded (%d) or returned (%d)\n",
-				 decoded_idx, ctx->display_idx);
-		}
-	}
-
-	/* The rotator will copy the current display frame next time */
-	ctx->display_idx = display_idx;
-
-	/*
-	 * The current decode run might have brought the bitstream fill level
-	 * below the size where we can start the next decode run. As userspace
-	 * might have filled the output queue completely and might thus be
-	 * blocked, we can't rely on the next qbuf to trigger the bitstream
-	 * refill. Check if we have data to refill the bitstream now.
-	 */
-	mutex_lock(&ctx->bitstream_mutex);
-	coda_fill_bitstream(ctx, NULL);
-	mutex_unlock(&ctx->bitstream_mutex);
-}
-
-static void coda_decode_timeout(struct coda_ctx *ctx)
-{
-	struct vb2_v4l2_buffer *dst_buf;
-
-	/*
-	 * For now this only handles the case where we would deadlock with
-	 * userspace, i.e. userspace issued DEC_CMD_STOP and waits for EOS,
-	 * but after a failed decode run we would hold the context and wait for
-	 * userspace to queue more buffers.
-	 */
-	if (!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))
-		return;
-
-	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-	dst_buf->sequence = ctx->qsequence - 1;
-
-	coda_m2m_buf_done(ctx, dst_buf, VB2_BUF_STATE_ERROR);
-}
-
-const struct coda_context_ops coda_bit_decode_ops = {
-	.queue_init = coda_decoder_queue_init,
-	.reqbufs = coda_decoder_reqbufs,
-	.start_streaming = coda_start_decoding,
-	.prepare_run = coda_prepare_decode,
-	.finish_run = coda_finish_decode,
-	.run_timeout = coda_decode_timeout,
-	.seq_init_work = coda_dec_seq_init_work,
-	.seq_end_work = coda_seq_end_work,
-	.release = coda_bit_release,
-};
-
-irqreturn_t coda_irq_handler(int irq, void *data)
-{
-	struct coda_dev *dev = data;
-	struct coda_ctx *ctx;
-
-	/* read status register to attend the IRQ */
-	coda_read(dev, CODA_REG_BIT_INT_STATUS);
-	coda_write(dev, 0, CODA_REG_BIT_INT_REASON);
-	coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET,
-		      CODA_REG_BIT_INT_CLEAR);
-
-	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
-	if (ctx == NULL) {
-		v4l2_err(&dev->v4l2_dev,
-			 "Instance released before the end of transaction\n");
-		return IRQ_HANDLED;
-	}
-
-	trace_coda_bit_done(ctx);
-
-	if (ctx->aborting) {
-		coda_dbg(1, ctx, "task has been aborted\n");
-	}
-
-	if (coda_isbusy(ctx->dev)) {
-		coda_dbg(1, ctx, "coda is still busy!!!!\n");
-		return IRQ_NONE;
-	}
-
-	complete(&ctx->completion);
-
-	return IRQ_HANDLED;
-}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-common.c b/drivers/media/platform/chips-media/coda-common.c
--- a/drivers/media/platform/chips-media/coda-common.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda-common.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3362 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Coda multi-standard codec IP
- *
- * Copyright (C) 2012 Vista Silicon S.L.
- *    Javier Martin, <javier.martin@vista-silicon.com>
- *    Xavier Duret
- */
-
-#include <linux/clk.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/gcd.h>
-#include <linux/genalloc.h>
-#include <linux/idr.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/kfifo.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-#include <linux/videodev2.h>
-#include <linux/of.h>
-#include <linux/ratelimit.h>
-#include <linux/reset.h>
-
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-event.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-v4l2.h>
-#include <media/videobuf2-dma-contig.h>
-#include <media/videobuf2-vmalloc.h>
-
-#include "coda.h"
-#include "imx-vdoa.h"
-
-#define CODA_NAME		"coda"
-
-#define CODADX6_MAX_INSTANCES	4
-#define CODA_MAX_FORMATS	5
-
-#define CODA_ISRAM_SIZE	(2048 * 2)
-
-#define MIN_W 48
-#define MIN_H 16
-
-#define S_ALIGN		1 /* multiple of 2 */
-#define W_ALIGN		1 /* multiple of 2 */
-#define H_ALIGN		1 /* multiple of 2 */
-
-#define fh_to_ctx(__fh)	container_of(__fh, struct coda_ctx, fh)
-
-int coda_debug;
-module_param(coda_debug, int, 0644);
-MODULE_PARM_DESC(coda_debug, "Debug level (0-2)");
-
-static int disable_tiling;
-module_param(disable_tiling, int, 0644);
-MODULE_PARM_DESC(disable_tiling, "Disable tiled frame buffers");
-
-static int disable_vdoa;
-module_param(disable_vdoa, int, 0644);
-MODULE_PARM_DESC(disable_vdoa, "Disable Video Data Order Adapter tiled to raster-scan conversion");
-
-static int enable_bwb = 0;
-module_param(enable_bwb, int, 0644);
-MODULE_PARM_DESC(enable_bwb, "Enable BWB unit for decoding, may crash on certain streams");
-
-void coda_write(struct coda_dev *dev, u32 data, u32 reg)
-{
-	v4l2_dbg(3, coda_debug, &dev->v4l2_dev,
-		 "%s: data=0x%x, reg=0x%x\n", __func__, data, reg);
-	writel(data, dev->regs_base + reg);
-}
-
-unsigned int coda_read(struct coda_dev *dev, u32 reg)
-{
-	u32 data;
-
-	data = readl(dev->regs_base + reg);
-	v4l2_dbg(3, coda_debug, &dev->v4l2_dev,
-		 "%s: data=0x%x, reg=0x%x\n", __func__, data, reg);
-	return data;
-}
-
-void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
-		     struct vb2_v4l2_buffer *buf, unsigned int reg_y)
-{
-	u32 base_y = vb2_dma_contig_plane_dma_addr(&buf->vb2_buf, 0);
-	u32 base_cb, base_cr;
-
-	switch (q_data->fourcc) {
-	case V4L2_PIX_FMT_YUYV:
-		/* Fallthrough: IN -H264-> CODA -NV12 MB-> VDOA -YUYV-> OUT */
-	case V4L2_PIX_FMT_NV12:
-	case V4L2_PIX_FMT_YUV420:
-	default:
-		base_cb = base_y + q_data->bytesperline * q_data->height;
-		base_cr = base_cb + q_data->bytesperline * q_data->height / 4;
-		break;
-	case V4L2_PIX_FMT_YVU420:
-		/* Switch Cb and Cr for YVU420 format */
-		base_cr = base_y + q_data->bytesperline * q_data->height;
-		base_cb = base_cr + q_data->bytesperline * q_data->height / 4;
-		break;
-	case V4L2_PIX_FMT_YUV422P:
-		base_cb = base_y + q_data->bytesperline * q_data->height;
-		base_cr = base_cb + q_data->bytesperline * q_data->height / 2;
-	}
-
-	coda_write(ctx->dev, base_y, reg_y);
-	coda_write(ctx->dev, base_cb, reg_y + 4);
-	coda_write(ctx->dev, base_cr, reg_y + 8);
-}
-
-#define CODA_CODEC(mode, src_fourcc, dst_fourcc, max_w, max_h) \
-	{ mode, src_fourcc, dst_fourcc, max_w, max_h }
-
-/*
- * Arrays of codecs supported by each given version of Coda:
- *  i.MX27 -> codadx6
- *  i.MX51 -> codahx4
- *  i.MX53 -> coda7
- *  i.MX6  -> coda960
- * Use V4L2_PIX_FMT_YUV420 as placeholder for all supported YUV 4:2:0 variants
- */
-static const struct coda_codec codadx6_codecs[] = {
-	CODA_CODEC(CODADX6_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264,  720, 576),
-	CODA_CODEC(CODADX6_MODE_ENCODE_MP4,  V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 720, 576),
-};
-
-static const struct coda_codec codahx4_codecs[] = {
-	CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264,   720, 576),
-	CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264,   V4L2_PIX_FMT_YUV420, 1920, 1088),
-	CODA_CODEC(CODA7_MODE_DECODE_MP2,  V4L2_PIX_FMT_MPEG2,  V4L2_PIX_FMT_YUV420, 1920, 1088),
-	CODA_CODEC(CODA7_MODE_DECODE_MP4,  V4L2_PIX_FMT_MPEG4,  V4L2_PIX_FMT_YUV420, 1280, 720),
-};
-
-static const struct coda_codec coda7_codecs[] = {
-	CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264,   1280, 720),
-	CODA_CODEC(CODA7_MODE_ENCODE_MP4,  V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4,  1280, 720),
-	CODA_CODEC(CODA7_MODE_ENCODE_MJPG, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_JPEG,   8192, 8192),
-	CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264,   V4L2_PIX_FMT_YUV420, 1920, 1088),
-	CODA_CODEC(CODA7_MODE_DECODE_MP2,  V4L2_PIX_FMT_MPEG2,  V4L2_PIX_FMT_YUV420, 1920, 1088),
-	CODA_CODEC(CODA7_MODE_DECODE_MP4,  V4L2_PIX_FMT_MPEG4,  V4L2_PIX_FMT_YUV420, 1920, 1088),
-	CODA_CODEC(CODA7_MODE_DECODE_MJPG, V4L2_PIX_FMT_JPEG,   V4L2_PIX_FMT_YUV420, 8192, 8192),
-};
-
-static const struct coda_codec coda9_codecs[] = {
-	CODA_CODEC(CODA9_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264,   1920, 1088),
-	CODA_CODEC(CODA9_MODE_ENCODE_MP4,  V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4,  1920, 1088),
-	CODA_CODEC(CODA9_MODE_ENCODE_MJPG, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_JPEG,   8192, 8192),
-	CODA_CODEC(CODA9_MODE_DECODE_H264, V4L2_PIX_FMT_H264,   V4L2_PIX_FMT_YUV420, 1920, 1088),
-	CODA_CODEC(CODA9_MODE_DECODE_MP2,  V4L2_PIX_FMT_MPEG2,  V4L2_PIX_FMT_YUV420, 1920, 1088),
-	CODA_CODEC(CODA9_MODE_DECODE_MP4,  V4L2_PIX_FMT_MPEG4,  V4L2_PIX_FMT_YUV420, 1920, 1088),
-	CODA_CODEC(CODA9_MODE_DECODE_MJPG, V4L2_PIX_FMT_JPEG,	V4L2_PIX_FMT_YUV420, 8192, 8192),
-};
-
-struct coda_video_device {
-	const char *name;
-	enum coda_inst_type type;
-	const struct coda_context_ops *ops;
-	bool direct;
-	u32 src_formats[CODA_MAX_FORMATS];
-	u32 dst_formats[CODA_MAX_FORMATS];
-};
-
-static const struct coda_video_device coda_bit_encoder = {
-	.name = "coda-video-encoder",
-	.type = CODA_INST_ENCODER,
-	.ops = &coda_bit_encode_ops,
-	.src_formats = {
-		V4L2_PIX_FMT_NV12,
-		V4L2_PIX_FMT_YUV420,
-		V4L2_PIX_FMT_YVU420,
-	},
-	.dst_formats = {
-		V4L2_PIX_FMT_H264,
-		V4L2_PIX_FMT_MPEG4,
-	},
-};
-
-static const struct coda_video_device coda_bit_jpeg_encoder = {
-	.name = "coda-jpeg-encoder",
-	.type = CODA_INST_ENCODER,
-	.ops = &coda_bit_encode_ops,
-	.src_formats = {
-		V4L2_PIX_FMT_NV12,
-		V4L2_PIX_FMT_YUV420,
-		V4L2_PIX_FMT_YVU420,
-		V4L2_PIX_FMT_YUV422P,
-	},
-	.dst_formats = {
-		V4L2_PIX_FMT_JPEG,
-	},
-};
-
-static const struct coda_video_device coda_bit_decoder = {
-	.name = "coda-video-decoder",
-	.type = CODA_INST_DECODER,
-	.ops = &coda_bit_decode_ops,
-	.src_formats = {
-		V4L2_PIX_FMT_H264,
-		V4L2_PIX_FMT_MPEG2,
-		V4L2_PIX_FMT_MPEG4,
-	},
-	.dst_formats = {
-		V4L2_PIX_FMT_NV12,
-		V4L2_PIX_FMT_YUV420,
-		V4L2_PIX_FMT_YVU420,
-		/*
-		 * If V4L2_PIX_FMT_YUYV should be default,
-		 * set_default_params() must be adjusted.
-		 */
-		V4L2_PIX_FMT_YUYV,
-	},
-};
-
-static const struct coda_video_device coda_bit_jpeg_decoder = {
-	.name = "coda-jpeg-decoder",
-	.type = CODA_INST_DECODER,
-	.ops = &coda_bit_decode_ops,
-	.src_formats = {
-		V4L2_PIX_FMT_JPEG,
-	},
-	.dst_formats = {
-		V4L2_PIX_FMT_NV12,
-		V4L2_PIX_FMT_YUV420,
-		V4L2_PIX_FMT_YVU420,
-		V4L2_PIX_FMT_YUV422P,
-	},
-};
-
-static const struct coda_video_device coda9_jpeg_encoder = {
-	.name = "coda-jpeg-encoder",
-	.type = CODA_INST_ENCODER,
-	.ops = &coda9_jpeg_encode_ops,
-	.direct = true,
-	.src_formats = {
-		V4L2_PIX_FMT_NV12,
-		V4L2_PIX_FMT_YUV420,
-		V4L2_PIX_FMT_YVU420,
-		V4L2_PIX_FMT_YUV422P,
-		V4L2_PIX_FMT_GREY,
-	},
-	.dst_formats = {
-		V4L2_PIX_FMT_JPEG,
-	},
-};
-
-static const struct coda_video_device coda9_jpeg_decoder = {
-	.name = "coda-jpeg-decoder",
-	.type = CODA_INST_DECODER,
-	.ops = &coda9_jpeg_decode_ops,
-	.direct = true,
-	.src_formats = {
-		V4L2_PIX_FMT_JPEG,
-	},
-	.dst_formats = {
-		V4L2_PIX_FMT_NV12,
-		V4L2_PIX_FMT_YUV420,
-		V4L2_PIX_FMT_YVU420,
-		V4L2_PIX_FMT_YUV422P,
-	},
-};
-
-static const struct coda_video_device *codadx6_video_devices[] = {
-	&coda_bit_encoder,
-};
-
-static const struct coda_video_device *codahx4_video_devices[] = {
-	&coda_bit_encoder,
-	&coda_bit_decoder,
-};
-
-static const struct coda_video_device *coda7_video_devices[] = {
-	&coda_bit_jpeg_encoder,
-	&coda_bit_jpeg_decoder,
-	&coda_bit_encoder,
-	&coda_bit_decoder,
-};
-
-static const struct coda_video_device *coda9_video_devices[] = {
-	&coda9_jpeg_encoder,
-	&coda9_jpeg_decoder,
-	&coda_bit_encoder,
-	&coda_bit_decoder,
-};
-
-/*
- * Normalize all supported YUV 4:2:0 formats to the value used in the codec
- * tables.
- */
-static u32 coda_format_normalize_yuv(u32 fourcc)
-{
-	switch (fourcc) {
-	case V4L2_PIX_FMT_NV12:
-	case V4L2_PIX_FMT_YUV420:
-	case V4L2_PIX_FMT_YVU420:
-	case V4L2_PIX_FMT_YUV422P:
-	case V4L2_PIX_FMT_YUYV:
-		return V4L2_PIX_FMT_YUV420;
-	default:
-		return fourcc;
-	}
-}
-
-static const struct coda_codec *coda_find_codec(struct coda_dev *dev,
-						int src_fourcc, int dst_fourcc)
-{
-	const struct coda_codec *codecs = dev->devtype->codecs;
-	int num_codecs = dev->devtype->num_codecs;
-	int k;
-
-	src_fourcc = coda_format_normalize_yuv(src_fourcc);
-	dst_fourcc = coda_format_normalize_yuv(dst_fourcc);
-	if (src_fourcc == dst_fourcc)
-		return NULL;
-
-	for (k = 0; k < num_codecs; k++) {
-		if (codecs[k].src_fourcc == src_fourcc &&
-		    codecs[k].dst_fourcc == dst_fourcc)
-			break;
-	}
-
-	if (k == num_codecs)
-		return NULL;
-
-	return &codecs[k];
-}
-
-static void coda_get_max_dimensions(struct coda_dev *dev,
-				    const struct coda_codec *codec,
-				    int *max_w, int *max_h)
-{
-	const struct coda_codec *codecs = dev->devtype->codecs;
-	int num_codecs = dev->devtype->num_codecs;
-	unsigned int w, h;
-	int k;
-
-	if (codec) {
-		w = codec->max_w;
-		h = codec->max_h;
-	} else {
-		for (k = 0, w = 0, h = 0; k < num_codecs; k++) {
-			w = max(w, codecs[k].max_w);
-			h = max(h, codecs[k].max_h);
-		}
-	}
-
-	if (max_w)
-		*max_w = w;
-	if (max_h)
-		*max_h = h;
-}
-
-static const struct coda_video_device *to_coda_video_device(struct video_device
-							    *vdev)
-{
-	struct coda_dev *dev = video_get_drvdata(vdev);
-	unsigned int i = vdev - dev->vfd;
-
-	if (i >= dev->devtype->num_vdevs)
-		return NULL;
-
-	return dev->devtype->vdevs[i];
-}
-
-const char *coda_product_name(int product)
-{
-	static char buf[9];
-
-	switch (product) {
-	case CODA_DX6:
-		return "CodaDx6";
-	case CODA_HX4:
-		return "CodaHx4";
-	case CODA_7541:
-		return "CODA7541";
-	case CODA_960:
-		return "CODA960";
-	default:
-		snprintf(buf, sizeof(buf), "(0x%04x)", product);
-		return buf;
-	}
-}
-
-static struct vdoa_data *coda_get_vdoa_data(void)
-{
-	struct device_node *vdoa_node;
-	struct platform_device *vdoa_pdev;
-	struct vdoa_data *vdoa_data = NULL;
-
-	vdoa_node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-vdoa");
-	if (!vdoa_node)
-		return NULL;
-
-	vdoa_pdev = of_find_device_by_node(vdoa_node);
-	if (!vdoa_pdev)
-		goto out;
-
-	vdoa_data = platform_get_drvdata(vdoa_pdev);
-	if (!vdoa_data)
-		vdoa_data = ERR_PTR(-EPROBE_DEFER);
-
-	put_device(&vdoa_pdev->dev);
-out:
-	of_node_put(vdoa_node);
-
-	return vdoa_data;
-}
-
-/*
- * V4L2 ioctl() operations.
- */
-static int coda_querycap(struct file *file, void *priv,
-			 struct v4l2_capability *cap)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-
-	strscpy(cap->driver, CODA_NAME, sizeof(cap->driver));
-	strscpy(cap->card, coda_product_name(ctx->dev->devtype->product),
-		sizeof(cap->card));
-	strscpy(cap->bus_info, "platform:" CODA_NAME, sizeof(cap->bus_info));
-	return 0;
-}
-
-static const u32 coda_formats_420[CODA_MAX_FORMATS] = {
-		V4L2_PIX_FMT_NV12,
-		V4L2_PIX_FMT_YUV420,
-		V4L2_PIX_FMT_YVU420,
-};
-
-static int coda_enum_fmt(struct file *file, void *priv,
-			 struct v4l2_fmtdesc *f)
-{
-	struct video_device *vdev = video_devdata(file);
-	const struct coda_video_device *cvd = to_coda_video_device(vdev);
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-	const u32 *formats;
-
-	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		formats = cvd->src_formats;
-	else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		struct coda_q_data *q_data_src;
-		struct vb2_queue *src_vq;
-
-		formats = cvd->dst_formats;
-
-		/*
-		 * If the source format is already fixed, only allow the same
-		 * chroma subsampling.
-		 */
-		q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-		src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
-					 V4L2_BUF_TYPE_VIDEO_OUTPUT);
-		if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
-		    vb2_is_streaming(src_vq)) {
-			if (ctx->params.jpeg_chroma_subsampling ==
-			    V4L2_JPEG_CHROMA_SUBSAMPLING_420) {
-				formats = coda_formats_420;
-			} else if (ctx->params.jpeg_chroma_subsampling ==
-				   V4L2_JPEG_CHROMA_SUBSAMPLING_422) {
-				f->pixelformat = V4L2_PIX_FMT_YUV422P;
-				return f->index ? -EINVAL : 0;
-			}
-		}
-	} else {
-		return -EINVAL;
-	}
-
-	if (f->index >= CODA_MAX_FORMATS || formats[f->index] == 0)
-		return -EINVAL;
-
-	/* Skip YUYV if the vdoa is not available */
-	if (!ctx->vdoa && f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-	    formats[f->index] == V4L2_PIX_FMT_YUYV)
-		return -EINVAL;
-
-	f->pixelformat = formats[f->index];
-
-	return 0;
-}
-
-static int coda_g_fmt(struct file *file, void *priv,
-		      struct v4l2_format *f)
-{
-	struct coda_q_data *q_data;
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-
-	q_data = get_q_data(ctx, f->type);
-	if (!q_data)
-		return -EINVAL;
-
-	f->fmt.pix.field	= V4L2_FIELD_NONE;
-	f->fmt.pix.pixelformat	= q_data->fourcc;
-	f->fmt.pix.width	= q_data->width;
-	f->fmt.pix.height	= q_data->height;
-	f->fmt.pix.bytesperline = q_data->bytesperline;
-
-	f->fmt.pix.sizeimage	= q_data->sizeimage;
-	f->fmt.pix.colorspace	= ctx->colorspace;
-	f->fmt.pix.xfer_func	= ctx->xfer_func;
-	f->fmt.pix.ycbcr_enc	= ctx->ycbcr_enc;
-	f->fmt.pix.quantization	= ctx->quantization;
-
-	return 0;
-}
-
-static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f)
-{
-	struct coda_q_data *q_data;
-	const u32 *formats;
-	int i;
-
-	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		formats = ctx->cvd->src_formats;
-	else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		formats = ctx->cvd->dst_formats;
-	else
-		return -EINVAL;
-
-	for (i = 0; i < CODA_MAX_FORMATS; i++) {
-		/* Skip YUYV if the vdoa is not available */
-		if (!ctx->vdoa && f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
-		    formats[i] == V4L2_PIX_FMT_YUYV)
-			continue;
-
-		if (formats[i] == f->fmt.pix.pixelformat) {
-			f->fmt.pix.pixelformat = formats[i];
-			return 0;
-		}
-	}
-
-	/* Fall back to currently set pixelformat */
-	q_data = get_q_data(ctx, f->type);
-	f->fmt.pix.pixelformat = q_data->fourcc;
-
-	return 0;
-}
-
-static int coda_try_fmt_vdoa(struct coda_ctx *ctx, struct v4l2_format *f,
-			     bool *use_vdoa)
-{
-	int err;
-
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-
-	if (!use_vdoa)
-		return -EINVAL;
-
-	if (!ctx->vdoa) {
-		*use_vdoa = false;
-		return 0;
-	}
-
-	err = vdoa_context_configure(NULL, round_up(f->fmt.pix.width, 16),
-				     f->fmt.pix.height, f->fmt.pix.pixelformat);
-	if (err) {
-		*use_vdoa = false;
-		return 0;
-	}
-
-	*use_vdoa = true;
-	return 0;
-}
-
-static unsigned int coda_estimate_sizeimage(struct coda_ctx *ctx, u32 sizeimage,
-					    u32 width, u32 height)
-{
-	/*
-	 * This is a rough estimate for sensible compressed buffer
-	 * sizes (between 1 and 16 bits per pixel). This could be
-	 * improved by better format specific worst case estimates.
-	 */
-	return round_up(clamp(sizeimage, width * height / 8,
-					 width * height * 2), PAGE_SIZE);
-}
-
-static int coda_try_fmt(struct coda_ctx *ctx, const struct coda_codec *codec,
-			struct v4l2_format *f)
-{
-	struct coda_dev *dev = ctx->dev;
-	unsigned int max_w, max_h;
-	enum v4l2_field field;
-
-	field = f->fmt.pix.field;
-	if (field == V4L2_FIELD_ANY)
-		field = V4L2_FIELD_NONE;
-	else if (V4L2_FIELD_NONE != field)
-		return -EINVAL;
-
-	/* V4L2 specification suggests the driver corrects the format struct
-	 * if any of the dimensions is unsupported */
-	f->fmt.pix.field = field;
-
-	coda_get_max_dimensions(dev, codec, &max_w, &max_h);
-	v4l_bound_align_image(&f->fmt.pix.width, MIN_W, max_w, W_ALIGN,
-			      &f->fmt.pix.height, MIN_H, max_h, H_ALIGN,
-			      S_ALIGN);
-
-	switch (f->fmt.pix.pixelformat) {
-	case V4L2_PIX_FMT_NV12:
-	case V4L2_PIX_FMT_YUV420:
-	case V4L2_PIX_FMT_YVU420:
-		/*
-		 * Frame stride must be at least multiple of 8,
-		 * but multiple of 16 for h.264 or JPEG 4:2:x
-		 */
-		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
-		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
-					f->fmt.pix.height * 3 / 2;
-		break;
-	case V4L2_PIX_FMT_YUYV:
-		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16) * 2;
-		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
-					f->fmt.pix.height;
-		break;
-	case V4L2_PIX_FMT_YUV422P:
-		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
-		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
-					f->fmt.pix.height * 2;
-		break;
-	case V4L2_PIX_FMT_GREY:
-		/* keep 16 pixel alignment of 8-bit pixel data */
-		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
-		f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
-		break;
-	case V4L2_PIX_FMT_JPEG:
-	case V4L2_PIX_FMT_H264:
-	case V4L2_PIX_FMT_MPEG4:
-	case V4L2_PIX_FMT_MPEG2:
-		f->fmt.pix.bytesperline = 0;
-		f->fmt.pix.sizeimage = coda_estimate_sizeimage(ctx,
-							f->fmt.pix.sizeimage,
-							f->fmt.pix.width,
-							f->fmt.pix.height);
-		break;
-	default:
-		BUG();
-	}
-
-	return 0;
-}
-
-static int coda_try_fmt_vid_cap(struct file *file, void *priv,
-				struct v4l2_format *f)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-	const struct coda_q_data *q_data_src;
-	const struct coda_codec *codec;
-	struct vb2_queue *src_vq;
-	int hscale = 0;
-	int vscale = 0;
-	int ret;
-	bool use_vdoa;
-
-	ret = coda_try_pixelformat(ctx, f);
-	if (ret < 0)
-		return ret;
-
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-
-	/*
-	 * If the source format is already fixed, only allow the same output
-	 * resolution. When decoding JPEG images, we also have to make sure to
-	 * use the same chroma subsampling.
-	 */
-	src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	if (vb2_is_streaming(src_vq)) {
-		if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
-		    ctx->dev->devtype->product == CODA_960) {
-			hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width);
-			vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height);
-		}
-		f->fmt.pix.width = q_data_src->width >> hscale;
-		f->fmt.pix.height = q_data_src->height >> vscale;
-
-		if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) {
-			if (ctx->params.jpeg_chroma_subsampling ==
-			    V4L2_JPEG_CHROMA_SUBSAMPLING_420 &&
-			    f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P)
-				f->fmt.pix.pixelformat = V4L2_PIX_FMT_NV12;
-			else if (ctx->params.jpeg_chroma_subsampling ==
-				 V4L2_JPEG_CHROMA_SUBSAMPLING_422)
-				f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
-		}
-	}
-
-	f->fmt.pix.colorspace = ctx->colorspace;
-	f->fmt.pix.xfer_func = ctx->xfer_func;
-	f->fmt.pix.ycbcr_enc = ctx->ycbcr_enc;
-	f->fmt.pix.quantization = ctx->quantization;
-
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
-				f->fmt.pix.pixelformat);
-	if (!codec)
-		return -EINVAL;
-
-	ret = coda_try_fmt(ctx, codec, f);
-	if (ret < 0)
-		return ret;
-
-	/* The decoders always write complete macroblocks or MCUs */
-	if (ctx->inst_type == CODA_INST_DECODER) {
-		f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16 >> hscale);
-		f->fmt.pix.height = round_up(f->fmt.pix.height, 16 >> vscale);
-		if (codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
-		    f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV422P) {
-			f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
-					       f->fmt.pix.height * 2;
-		} else {
-			f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
-					       f->fmt.pix.height * 3 / 2;
-		}
-
-		ret = coda_try_fmt_vdoa(ctx, f, &use_vdoa);
-		if (ret < 0)
-			return ret;
-
-		if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
-			if (!use_vdoa)
-				return -EINVAL;
-
-			f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16) * 2;
-			f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
-				f->fmt.pix.height;
-		}
-	}
-
-	return 0;
-}
-
-static void coda_set_default_colorspace(struct v4l2_pix_format *fmt)
-{
-	enum v4l2_colorspace colorspace;
-
-	if (fmt->pixelformat == V4L2_PIX_FMT_JPEG)
-		colorspace = V4L2_COLORSPACE_JPEG;
-	else if (fmt->width <= 720 && fmt->height <= 576)
-		colorspace = V4L2_COLORSPACE_SMPTE170M;
-	else
-		colorspace = V4L2_COLORSPACE_REC709;
-
-	fmt->colorspace = colorspace;
-	fmt->xfer_func = V4L2_XFER_FUNC_DEFAULT;
-	fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
-	fmt->quantization = V4L2_QUANTIZATION_DEFAULT;
-}
-
-static int coda_try_fmt_vid_out(struct file *file, void *priv,
-				struct v4l2_format *f)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-	struct coda_dev *dev = ctx->dev;
-	const struct coda_q_data *q_data_dst;
-	const struct coda_codec *codec;
-	int ret;
-
-	ret = coda_try_pixelformat(ctx, f);
-	if (ret < 0)
-		return ret;
-
-	if (f->fmt.pix.colorspace == V4L2_COLORSPACE_DEFAULT)
-		coda_set_default_colorspace(&f->fmt.pix);
-
-	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	codec = coda_find_codec(dev, f->fmt.pix.pixelformat, q_data_dst->fourcc);
-
-	return coda_try_fmt(ctx, codec, f);
-}
-
-static int coda_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f,
-		      struct v4l2_rect *r)
-{
-	struct coda_q_data *q_data;
-	struct vb2_queue *vq;
-
-	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
-	if (!vq)
-		return -EINVAL;
-
-	q_data = get_q_data(ctx, f->type);
-	if (!q_data)
-		return -EINVAL;
-
-	if (vb2_is_busy(vq)) {
-		v4l2_err(&ctx->dev->v4l2_dev, "%s: %s queue busy: %d\n",
-			 __func__, v4l2_type_names[f->type], vq->num_buffers);
-		return -EBUSY;
-	}
-
-	q_data->fourcc = f->fmt.pix.pixelformat;
-	q_data->width = f->fmt.pix.width;
-	q_data->height = f->fmt.pix.height;
-	q_data->bytesperline = f->fmt.pix.bytesperline;
-	q_data->sizeimage = f->fmt.pix.sizeimage;
-	if (r) {
-		q_data->rect = *r;
-	} else {
-		q_data->rect.left = 0;
-		q_data->rect.top = 0;
-		q_data->rect.width = f->fmt.pix.width;
-		q_data->rect.height = f->fmt.pix.height;
-	}
-
-	switch (f->fmt.pix.pixelformat) {
-	case V4L2_PIX_FMT_YUYV:
-		ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
-		break;
-	case V4L2_PIX_FMT_NV12:
-		if (!disable_tiling && ctx->use_bit &&
-		    ctx->dev->devtype->product == CODA_960) {
-			ctx->tiled_map_type = GDI_TILED_FRAME_MB_RASTER_MAP;
-			break;
-		}
-		fallthrough;
-	case V4L2_PIX_FMT_YUV420:
-	case V4L2_PIX_FMT_YVU420:
-	case V4L2_PIX_FMT_YUV422P:
-		ctx->tiled_map_type = GDI_LINEAR_FRAME_MAP;
-		break;
-	default:
-		break;
-	}
-
-	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP &&
-	    !coda_try_fmt_vdoa(ctx, f, &ctx->use_vdoa) &&
-	    ctx->use_vdoa)
-		vdoa_context_configure(ctx->vdoa,
-				       round_up(f->fmt.pix.width, 16),
-				       f->fmt.pix.height,
-				       f->fmt.pix.pixelformat);
-	else
-		ctx->use_vdoa = false;
-
-	coda_dbg(1, ctx, "Setting %s format, wxh: %dx%d, fmt: %4.4s %c\n",
-		 v4l2_type_names[f->type], q_data->width, q_data->height,
-		 (char *)&q_data->fourcc,
-		 (ctx->tiled_map_type == GDI_LINEAR_FRAME_MAP) ? 'L' : 'T');
-
-	return 0;
-}
-
-static int coda_s_fmt_vid_cap(struct file *file, void *priv,
-			      struct v4l2_format *f)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-	struct coda_q_data *q_data_src;
-	const struct coda_codec *codec;
-	struct v4l2_rect r;
-	int hscale = 0;
-	int vscale = 0;
-	int ret;
-
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-
-	if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
-	    ctx->dev->devtype->product == CODA_960) {
-		hscale = coda_jpeg_scale(q_data_src->width, f->fmt.pix.width);
-		vscale = coda_jpeg_scale(q_data_src->height, f->fmt.pix.height);
-	}
-
-	ret = coda_try_fmt_vid_cap(file, priv, f);
-	if (ret)
-		return ret;
-
-	r.left = 0;
-	r.top = 0;
-	r.width = q_data_src->width >> hscale;
-	r.height = q_data_src->height >> vscale;
-
-	ret = coda_s_fmt(ctx, f, &r);
-	if (ret)
-		return ret;
-
-	if (ctx->inst_type != CODA_INST_ENCODER)
-		return 0;
-
-	/* Setting the coded format determines the selected codec */
-	codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
-				f->fmt.pix.pixelformat);
-	if (!codec) {
-		v4l2_err(&ctx->dev->v4l2_dev, "failed to determine codec\n");
-		return -EINVAL;
-	}
-	ctx->codec = codec;
-
-	ctx->colorspace = f->fmt.pix.colorspace;
-	ctx->xfer_func = f->fmt.pix.xfer_func;
-	ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
-	ctx->quantization = f->fmt.pix.quantization;
-
-	return 0;
-}
-
-static int coda_s_fmt_vid_out(struct file *file, void *priv,
-			      struct v4l2_format *f)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-	const struct coda_codec *codec;
-	struct v4l2_format f_cap;
-	struct vb2_queue *dst_vq;
-	int ret;
-
-	ret = coda_try_fmt_vid_out(file, priv, f);
-	if (ret)
-		return ret;
-
-	ret = coda_s_fmt(ctx, f, NULL);
-	if (ret)
-		return ret;
-
-	ctx->colorspace = f->fmt.pix.colorspace;
-	ctx->xfer_func = f->fmt.pix.xfer_func;
-	ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc;
-	ctx->quantization = f->fmt.pix.quantization;
-
-	if (ctx->inst_type != CODA_INST_DECODER)
-		return 0;
-
-	/* Setting the coded format determines the selected codec */
-	codec = coda_find_codec(ctx->dev, f->fmt.pix.pixelformat,
-				V4L2_PIX_FMT_YUV420);
-	if (!codec) {
-		v4l2_err(&ctx->dev->v4l2_dev, "failed to determine codec\n");
-		return -EINVAL;
-	}
-	ctx->codec = codec;
-
-	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	if (!dst_vq)
-		return -EINVAL;
-
-	/*
-	 * Setting the capture queue format is not possible while the capture
-	 * queue is still busy. This is not an error, but the user will have to
-	 * make sure themselves that the capture format is set correctly before
-	 * starting the output queue again.
-	 */
-	if (vb2_is_busy(dst_vq))
-		return 0;
-
-	memset(&f_cap, 0, sizeof(f_cap));
-	f_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	coda_g_fmt(file, priv, &f_cap);
-	f_cap.fmt.pix.width = f->fmt.pix.width;
-	f_cap.fmt.pix.height = f->fmt.pix.height;
-
-	return coda_s_fmt_vid_cap(file, priv, &f_cap);
-}
-
-static int coda_reqbufs(struct file *file, void *priv,
-			struct v4l2_requestbuffers *rb)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-	int ret;
-
-	ret = v4l2_m2m_reqbufs(file, ctx->fh.m2m_ctx, rb);
-	if (ret)
-		return ret;
-
-	/*
-	 * Allow to allocate instance specific per-context buffers, such as
-	 * bitstream ringbuffer, slice buffer, work buffer, etc. if needed.
-	 */
-	if (rb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && ctx->ops->reqbufs)
-		return ctx->ops->reqbufs(ctx, rb);
-
-	return 0;
-}
-
-static int coda_qbuf(struct file *file, void *priv,
-		     struct v4l2_buffer *buf)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-
-	if (ctx->inst_type == CODA_INST_DECODER &&
-	    buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		buf->flags &= ~V4L2_BUF_FLAG_LAST;
-
-	return v4l2_m2m_qbuf(file, ctx->fh.m2m_ctx, buf);
-}
-
-static int coda_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
-{
-	struct coda_ctx *ctx = fh_to_ctx(priv);
-	int ret;
-
-	ret = v4l2_m2m_dqbuf(file, ctx->fh.m2m_ctx, buf);
-
-	if (ctx->inst_type == CODA_INST_DECODER &&
-	    buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		buf->flags &= ~V4L2_BUF_FLAG_LAST;
-
-	return ret;
-}
-
-void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
-		       enum vb2_buffer_state state)
-{
-	const struct v4l2_event eos_event = {
-		.type = V4L2_EVENT_EOS
-	};
-
-	if (buf->flags & V4L2_BUF_FLAG_LAST)
-		v4l2_event_queue_fh(&ctx->fh, &eos_event);
-
-	v4l2_m2m_buf_done(buf, state);
-}
-
-static int coda_g_selection(struct file *file, void *fh,
-			    struct v4l2_selection *s)
-{
-	struct coda_ctx *ctx = fh_to_ctx(fh);
-	struct coda_q_data *q_data;
-	struct v4l2_rect r, *rsel;
-
-	q_data = get_q_data(ctx, s->type);
-	if (!q_data)
-		return -EINVAL;
-
-	r.left = 0;
-	r.top = 0;
-	r.width = q_data->width;
-	r.height = q_data->height;
-	rsel = &q_data->rect;
-
-	switch (s->target) {
-	case V4L2_SEL_TGT_CROP_DEFAULT:
-	case V4L2_SEL_TGT_CROP_BOUNDS:
-		rsel = &r;
-		fallthrough;
-	case V4L2_SEL_TGT_CROP:
-		if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
-		    ctx->inst_type == CODA_INST_DECODER)
-			return -EINVAL;
-		break;
-	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
-	case V4L2_SEL_TGT_COMPOSE_PADDED:
-		rsel = &r;
-		fallthrough;
-	case V4L2_SEL_TGT_COMPOSE:
-	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
-		if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
-		    ctx->inst_type == CODA_INST_ENCODER)
-			return -EINVAL;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	s->r = *rsel;
-
-	return 0;
-}
-
-static int coda_s_selection(struct file *file, void *fh,
-			    struct v4l2_selection *s)
-{
-	struct coda_ctx *ctx = fh_to_ctx(fh);
-	struct coda_q_data *q_data;
-
-	switch (s->target) {
-	case V4L2_SEL_TGT_CROP:
-		if (ctx->inst_type == CODA_INST_ENCODER &&
-		    s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-			q_data = get_q_data(ctx, s->type);
-			if (!q_data)
-				return -EINVAL;
-
-			s->r.left = 0;
-			s->r.top = 0;
-			s->r.width = clamp(s->r.width, 2U, q_data->width);
-			s->r.height = clamp(s->r.height, 2U, q_data->height);
-
-			if (s->flags & V4L2_SEL_FLAG_LE) {
-				s->r.width = round_up(s->r.width, 2);
-				s->r.height = round_up(s->r.height, 2);
-			} else {
-				s->r.width = round_down(s->r.width, 2);
-				s->r.height = round_down(s->r.height, 2);
-			}
-
-			q_data->rect = s->r;
-
-			coda_dbg(1, ctx, "Setting crop rectangle: %dx%d\n",
-				 s->r.width, s->r.height);
-
-			return 0;
-		}
-		fallthrough;
-	case V4L2_SEL_TGT_NATIVE_SIZE:
-	case V4L2_SEL_TGT_COMPOSE:
-		return coda_g_selection(file, fh, s);
-	default:
-		/* v4l2-compliance expects this to fail for read-only targets */
-		return -EINVAL;
-	}
-}
-
-static void coda_wake_up_capture_queue(struct coda_ctx *ctx)
-{
-	struct vb2_queue *dst_vq;
-
-	coda_dbg(1, ctx, "waking up capture queue\n");
-
-	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	dst_vq->last_buffer_dequeued = true;
-	wake_up(&dst_vq->done_wq);
-}
-
-static int coda_encoder_cmd(struct file *file, void *fh,
-			    struct v4l2_encoder_cmd *ec)
-{
-	struct coda_ctx *ctx = fh_to_ctx(fh);
-	struct vb2_v4l2_buffer *buf;
-	int ret;
-
-	ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec);
-	if (ret < 0)
-		return ret;
-
-	mutex_lock(&ctx->wakeup_mutex);
-	buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
-	if (buf) {
-		/*
-		 * If the last output buffer is still on the queue, make sure
-		 * that decoder finish_run will see the last flag and report it
-		 * to userspace.
-		 */
-		buf->flags |= V4L2_BUF_FLAG_LAST;
-	} else {
-		/* Set the stream-end flag on this context */
-		ctx->bit_stream_param |= CODA_BIT_STREAM_END_FLAG;
-
-		/*
-		 * If the last output buffer has already been taken from the
-		 * queue, wake up the capture queue and signal end of stream
-		 * via the -EPIPE mechanism.
-		 */
-		coda_wake_up_capture_queue(ctx);
-	}
-	mutex_unlock(&ctx->wakeup_mutex);
-
-	return 0;
-}
-
-static bool coda_mark_last_meta(struct coda_ctx *ctx)
-{
-	struct coda_buffer_meta *meta;
-
-	coda_dbg(1, ctx, "marking last meta\n");
-
-	spin_lock(&ctx->buffer_meta_lock);
-	if (list_empty(&ctx->buffer_meta_list)) {
-		spin_unlock(&ctx->buffer_meta_lock);
-		return false;
-	}
-
-	meta = list_last_entry(&ctx->buffer_meta_list, struct coda_buffer_meta,
-			       list);
-	meta->last = true;
-
-	spin_unlock(&ctx->buffer_meta_lock);
-	return true;
-}
-
-static bool coda_mark_last_dst_buf(struct coda_ctx *ctx)
-{
-	struct vb2_v4l2_buffer *buf;
-	struct vb2_buffer *dst_vb;
-	struct vb2_queue *dst_vq;
-	unsigned long flags;
-
-	coda_dbg(1, ctx, "marking last capture buffer\n");
-
-	dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	spin_lock_irqsave(&dst_vq->done_lock, flags);
-	if (list_empty(&dst_vq->done_list)) {
-		spin_unlock_irqrestore(&dst_vq->done_lock, flags);
-		return false;
-	}
-
-	dst_vb = list_last_entry(&dst_vq->done_list, struct vb2_buffer,
-				 done_entry);
-	buf = to_vb2_v4l2_buffer(dst_vb);
-	buf->flags |= V4L2_BUF_FLAG_LAST;
-
-	spin_unlock_irqrestore(&dst_vq->done_lock, flags);
-	return true;
-}
-
-static int coda_decoder_cmd(struct file *file, void *fh,
-			    struct v4l2_decoder_cmd *dc)
-{
-	struct coda_ctx *ctx = fh_to_ctx(fh);
-	struct coda_dev *dev = ctx->dev;
-	struct vb2_v4l2_buffer *buf;
-	struct vb2_queue *dst_vq;
-	bool stream_end;
-	bool wakeup;
-	int ret;
-
-	ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc);
-	if (ret < 0)
-		return ret;
-
-	switch (dc->cmd) {
-	case V4L2_DEC_CMD_START:
-		mutex_lock(&dev->coda_mutex);
-		mutex_lock(&ctx->bitstream_mutex);
-		coda_bitstream_flush(ctx);
-		dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx,
-					 V4L2_BUF_TYPE_VIDEO_CAPTURE);
-		vb2_clear_last_buffer_dequeued(dst_vq);
-		ctx->bit_stream_param &= ~CODA_BIT_STREAM_END_FLAG;
-		coda_fill_bitstream(ctx, NULL);
-		mutex_unlock(&ctx->bitstream_mutex);
-		mutex_unlock(&dev->coda_mutex);
-		break;
-	case V4L2_DEC_CMD_STOP:
-		stream_end = false;
-		wakeup = false;
-
-		mutex_lock(&ctx->wakeup_mutex);
-
-		buf = v4l2_m2m_last_src_buf(ctx->fh.m2m_ctx);
-		if (buf) {
-			coda_dbg(1, ctx, "marking last pending buffer\n");
-
-			/* Mark last buffer */
-			buf->flags |= V4L2_BUF_FLAG_LAST;
-
-			if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) == 0) {
-				coda_dbg(1, ctx, "all remaining buffers queued\n");
-				stream_end = true;
-			}
-		} else {
-			if (ctx->use_bit)
-				if (coda_mark_last_meta(ctx))
-					stream_end = true;
-				else
-					wakeup = true;
-			else
-				if (!coda_mark_last_dst_buf(ctx))
-					wakeup = true;
-		}
-
-		if (stream_end) {
-			coda_dbg(1, ctx, "all remaining buffers queued\n");
-
-			/* Set the stream-end flag on this context */
-			coda_bit_stream_end_flag(ctx);
-			ctx->hold = false;
-			v4l2_m2m_try_schedule(ctx->fh.m2m_ctx);
-		}
-
-		if (wakeup) {
-			/* If there is no buffer in flight, wake up */
-			coda_wake_up_capture_queue(ctx);
-		}
-
-		mutex_unlock(&ctx->wakeup_mutex);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int coda_enum_framesizes(struct file *file, void *fh,
-				struct v4l2_frmsizeenum *fsize)
-{
-	struct coda_ctx *ctx = fh_to_ctx(fh);
-	struct coda_q_data *q_data_dst;
-	const struct coda_codec *codec;
-
-	if (fsize->index)
-		return -EINVAL;
-
-	if (coda_format_normalize_yuv(fsize->pixel_format) ==
-	    V4L2_PIX_FMT_YUV420) {
-		q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-		codec = coda_find_codec(ctx->dev, fsize->pixel_format,
-					q_data_dst->fourcc);
-	} else {
-		codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420,
-					fsize->pixel_format);
-	}
-	if (!codec)
-		return -EINVAL;
-
-	fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
-	fsize->stepwise.min_width = MIN_W;
-	fsize->stepwise.max_width = codec->max_w;
-	fsize->stepwise.step_width = 1;
-	fsize->stepwise.min_height = MIN_H;
-	fsize->stepwise.max_height = codec->max_h;
-	fsize->stepwise.step_height = 1;
-
-	return 0;
-}
-
-static int coda_enum_frameintervals(struct file *file, void *fh,
-				    struct v4l2_frmivalenum *f)
-{
-	struct coda_ctx *ctx = fh_to_ctx(fh);
-	struct coda_q_data *q_data;
-	const struct coda_codec *codec;
-
-	if (f->index)
-		return -EINVAL;
-
-	/* Disallow YUYV if the vdoa is not available */
-	if (!ctx->vdoa && f->pixel_format == V4L2_PIX_FMT_YUYV)
-		return -EINVAL;
-
-	if (coda_format_normalize_yuv(f->pixel_format) == V4L2_PIX_FMT_YUV420) {
-		q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-		codec = coda_find_codec(ctx->dev, f->pixel_format,
-					q_data->fourcc);
-	} else {
-		codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420,
-					f->pixel_format);
-	}
-	if (!codec)
-		return -EINVAL;
-
-	if (f->width < MIN_W || f->width > codec->max_w ||
-	    f->height < MIN_H || f->height > codec->max_h)
-		return -EINVAL;
-
-	f->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
-	f->stepwise.min.numerator = 1;
-	f->stepwise.min.denominator = 65535;
-	f->stepwise.max.numerator = 65536;
-	f->stepwise.max.denominator = 1;
-	f->stepwise.step.numerator = 1;
-	f->stepwise.step.denominator = 1;
-
-	return 0;
-}
-
-static int coda_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
-{
-	struct coda_ctx *ctx = fh_to_ctx(fh);
-	struct v4l2_fract *tpf;
-
-	if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		return -EINVAL;
-
-	a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
-	tpf = &a->parm.output.timeperframe;
-	tpf->denominator = ctx->params.framerate & CODA_FRATE_RES_MASK;
-	tpf->numerator = 1 + (ctx->params.framerate >>
-			      CODA_FRATE_DIV_OFFSET);
-
-	return 0;
-}
-
-/*
- * Approximate timeperframe v4l2_fract with values that can be written
- * into the 16-bit CODA_FRATE_DIV and CODA_FRATE_RES fields.
- */
-static void coda_approximate_timeperframe(struct v4l2_fract *timeperframe)
-{
-	struct v4l2_fract s = *timeperframe;
-	struct v4l2_fract f0;
-	struct v4l2_fract f1 = { 1, 0 };
-	struct v4l2_fract f2 = { 0, 1 };
-	unsigned int i, div, s_denominator;
-
-	/* Lower bound is 1/65535 */
-	if (s.numerator == 0 || s.denominator / s.numerator > 65535) {
-		timeperframe->numerator = 1;
-		timeperframe->denominator = 65535;
-		return;
-	}
-
-	/* Upper bound is 65536/1 */
-	if (s.denominator == 0 || s.numerator / s.denominator > 65536) {
-		timeperframe->numerator = 65536;
-		timeperframe->denominator = 1;
-		return;
-	}
-
-	/* Reduce fraction to lowest terms */
-	div = gcd(s.numerator, s.denominator);
-	if (div > 1) {
-		s.numerator /= div;
-		s.denominator /= div;
-	}
-
-	if (s.numerator <= 65536 && s.denominator < 65536) {
-		*timeperframe = s;
-		return;
-	}
-
-	/* Find successive convergents from continued fraction expansion */
-	while (f2.numerator <= 65536 && f2.denominator < 65536) {
-		f0 = f1;
-		f1 = f2;
-
-		/* Stop when f2 exactly equals timeperframe */
-		if (s.numerator == 0)
-			break;
-
-		i = s.denominator / s.numerator;
-
-		f2.numerator = f0.numerator + i * f1.numerator;
-		f2.denominator = f0.denominator + i * f2.denominator;
-
-		s_denominator = s.numerator;
-		s.numerator = s.denominator % s.numerator;
-		s.denominator = s_denominator;
-	}
-
-	*timeperframe = f1;
-}
-
-static uint32_t coda_timeperframe_to_frate(struct v4l2_fract *timeperframe)
-{
-	return ((timeperframe->numerator - 1) << CODA_FRATE_DIV_OFFSET) |
-		timeperframe->denominator;
-}
-
-static int coda_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
-{
-	struct coda_ctx *ctx = fh_to_ctx(fh);
-	struct v4l2_fract *tpf;
-
-	if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
-		return -EINVAL;
-
-	a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
-	tpf = &a->parm.output.timeperframe;
-	coda_approximate_timeperframe(tpf);
-	ctx->params.framerate = coda_timeperframe_to_frate(tpf);
-	ctx->params.framerate_changed = true;
-
-	return 0;
-}
-
-static int coda_subscribe_event(struct v4l2_fh *fh,
-				const struct v4l2_event_subscription *sub)
-{
-	struct coda_ctx *ctx = fh_to_ctx(fh);
-
-	switch (sub->type) {
-	case V4L2_EVENT_EOS:
-		return v4l2_event_subscribe(fh, sub, 0, NULL);
-	case V4L2_EVENT_SOURCE_CHANGE:
-		if (ctx->inst_type == CODA_INST_DECODER)
-			return v4l2_event_subscribe(fh, sub, 0, NULL);
-		else
-			return -EINVAL;
-	default:
-		return v4l2_ctrl_subscribe_event(fh, sub);
-	}
-}
-
-static const struct v4l2_ioctl_ops coda_ioctl_ops = {
-	.vidioc_querycap	= coda_querycap,
-
-	.vidioc_enum_fmt_vid_cap = coda_enum_fmt,
-	.vidioc_g_fmt_vid_cap	= coda_g_fmt,
-	.vidioc_try_fmt_vid_cap	= coda_try_fmt_vid_cap,
-	.vidioc_s_fmt_vid_cap	= coda_s_fmt_vid_cap,
-
-	.vidioc_enum_fmt_vid_out = coda_enum_fmt,
-	.vidioc_g_fmt_vid_out	= coda_g_fmt,
-	.vidioc_try_fmt_vid_out	= coda_try_fmt_vid_out,
-	.vidioc_s_fmt_vid_out	= coda_s_fmt_vid_out,
-
-	.vidioc_reqbufs		= coda_reqbufs,
-	.vidioc_querybuf	= v4l2_m2m_ioctl_querybuf,
-
-	.vidioc_qbuf		= coda_qbuf,
-	.vidioc_expbuf		= v4l2_m2m_ioctl_expbuf,
-	.vidioc_dqbuf		= coda_dqbuf,
-	.vidioc_create_bufs	= v4l2_m2m_ioctl_create_bufs,
-	.vidioc_prepare_buf	= v4l2_m2m_ioctl_prepare_buf,
-
-	.vidioc_streamon	= v4l2_m2m_ioctl_streamon,
-	.vidioc_streamoff	= v4l2_m2m_ioctl_streamoff,
-
-	.vidioc_g_selection	= coda_g_selection,
-	.vidioc_s_selection	= coda_s_selection,
-
-	.vidioc_try_encoder_cmd	= v4l2_m2m_ioctl_try_encoder_cmd,
-	.vidioc_encoder_cmd	= coda_encoder_cmd,
-	.vidioc_try_decoder_cmd	= v4l2_m2m_ioctl_try_decoder_cmd,
-	.vidioc_decoder_cmd	= coda_decoder_cmd,
-
-	.vidioc_g_parm		= coda_g_parm,
-	.vidioc_s_parm		= coda_s_parm,
-
-	.vidioc_enum_framesizes	= coda_enum_framesizes,
-	.vidioc_enum_frameintervals = coda_enum_frameintervals,
-
-	.vidioc_subscribe_event = coda_subscribe_event,
-	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
-};
-
-/*
- * Mem-to-mem operations.
- */
-
-static void coda_device_run(void *m2m_priv)
-{
-	struct coda_ctx *ctx = m2m_priv;
-	struct coda_dev *dev = ctx->dev;
-
-	queue_work(dev->workqueue, &ctx->pic_run_work);
-}
-
-static void coda_pic_run_work(struct work_struct *work)
-{
-	struct coda_ctx *ctx = container_of(work, struct coda_ctx, pic_run_work);
-	struct coda_dev *dev = ctx->dev;
-	int ret;
-
-	mutex_lock(&ctx->buffer_mutex);
-	mutex_lock(&dev->coda_mutex);
-
-	ret = ctx->ops->prepare_run(ctx);
-	if (ret < 0 && ctx->inst_type == CODA_INST_DECODER)
-		goto out;
-
-	if (!wait_for_completion_timeout(&ctx->completion,
-					 msecs_to_jiffies(1000))) {
-		if (ctx->use_bit) {
-			dev_err(dev->dev, "CODA PIC_RUN timeout\n");
-
-			ctx->hold = true;
-
-			coda_hw_reset(ctx);
-		}
-
-		if (ctx->ops->run_timeout)
-			ctx->ops->run_timeout(ctx);
-	} else {
-		ctx->ops->finish_run(ctx);
-	}
-
-	if ((ctx->aborting || (!ctx->streamon_cap && !ctx->streamon_out)) &&
-	    ctx->ops->seq_end_work)
-		queue_work(dev->workqueue, &ctx->seq_end_work);
-
-out:
-	mutex_unlock(&dev->coda_mutex);
-	mutex_unlock(&ctx->buffer_mutex);
-
-	v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
-}
-
-static int coda_job_ready(void *m2m_priv)
-{
-	struct coda_ctx *ctx = m2m_priv;
-	int src_bufs = v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx);
-
-	/*
-	 * For both 'P' and 'key' frame cases 1 picture
-	 * and 1 frame are needed. In the decoder case,
-	 * the compressed frame can be in the bitstream.
-	 */
-	if (!src_bufs && ctx->inst_type != CODA_INST_DECODER) {
-		coda_dbg(1, ctx, "not ready: not enough vid-out buffers.\n");
-		return 0;
-	}
-
-	if (!v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) {
-		coda_dbg(1, ctx, "not ready: not enough vid-cap buffers.\n");
-		return 0;
-	}
-
-	if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) {
-		bool stream_end = ctx->bit_stream_param &
-				  CODA_BIT_STREAM_END_FLAG;
-		int num_metas = ctx->num_metas;
-		struct coda_buffer_meta *meta;
-		unsigned int count;
-
-		count = hweight32(ctx->frm_dis_flg);
-		if (ctx->use_vdoa && count >= (ctx->num_internal_frames - 1)) {
-			coda_dbg(1, ctx,
-				 "not ready: all internal buffers in use: %d/%d (0x%x)",
-				 count, ctx->num_internal_frames,
-				 ctx->frm_dis_flg);
-			return 0;
-		}
-
-		if (ctx->hold && !src_bufs) {
-			coda_dbg(1, ctx,
-				 "not ready: on hold for more buffers.\n");
-			return 0;
-		}
-
-		if (!stream_end && (num_metas + src_bufs) < 2) {
-			coda_dbg(1, ctx,
-				 "not ready: need 2 buffers available (queue:%d + bitstream:%d)\n",
-				 num_metas, src_bufs);
-			return 0;
-		}
-
-		meta = list_first_entry(&ctx->buffer_meta_list,
-					struct coda_buffer_meta, list);
-		if (!coda_bitstream_can_fetch_past(ctx, meta->end) &&
-		    !stream_end) {
-			coda_dbg(1, ctx,
-				 "not ready: not enough bitstream data to read past %u (%u)\n",
-				 meta->end, ctx->bitstream_fifo.kfifo.in);
-			return 0;
-		}
-	}
-
-	if (ctx->aborting) {
-		coda_dbg(1, ctx, "not ready: aborting\n");
-		return 0;
-	}
-
-	coda_dbg(2, ctx, "job ready\n");
-
-	return 1;
-}
-
-static void coda_job_abort(void *priv)
-{
-	struct coda_ctx *ctx = priv;
-
-	ctx->aborting = 1;
-
-	coda_dbg(1, ctx, "job abort\n");
-}
-
-static const struct v4l2_m2m_ops coda_m2m_ops = {
-	.device_run	= coda_device_run,
-	.job_ready	= coda_job_ready,
-	.job_abort	= coda_job_abort,
-};
-
-static void set_default_params(struct coda_ctx *ctx)
-{
-	unsigned int max_w, max_h, usize, csize;
-
-	ctx->codec = coda_find_codec(ctx->dev, ctx->cvd->src_formats[0],
-				     ctx->cvd->dst_formats[0]);
-	max_w = min(ctx->codec->max_w, 1920U);
-	max_h = min(ctx->codec->max_h, 1088U);
-	usize = max_w * max_h * 3 / 2;
-	csize = coda_estimate_sizeimage(ctx, usize, max_w, max_h);
-
-	ctx->params.codec_mode = ctx->codec->mode;
-	if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_JPEG ||
-	    ctx->cvd->dst_formats[0] == V4L2_PIX_FMT_JPEG) {
-		ctx->colorspace = V4L2_COLORSPACE_SRGB;
-		ctx->xfer_func = V4L2_XFER_FUNC_SRGB;
-		ctx->ycbcr_enc = V4L2_YCBCR_ENC_601;
-		ctx->quantization = V4L2_QUANTIZATION_FULL_RANGE;
-	} else {
-		ctx->colorspace = V4L2_COLORSPACE_REC709;
-		ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
-		ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
-		ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
-	}
-	ctx->params.framerate = 30;
-
-	/* Default formats for output and input queues */
-	ctx->q_data[V4L2_M2M_SRC].fourcc = ctx->cvd->src_formats[0];
-	ctx->q_data[V4L2_M2M_DST].fourcc = ctx->cvd->dst_formats[0];
-	ctx->q_data[V4L2_M2M_SRC].width = max_w;
-	ctx->q_data[V4L2_M2M_SRC].height = max_h;
-	ctx->q_data[V4L2_M2M_DST].width = max_w;
-	ctx->q_data[V4L2_M2M_DST].height = max_h;
-	if (ctx->codec->src_fourcc == V4L2_PIX_FMT_YUV420) {
-		ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w;
-		ctx->q_data[V4L2_M2M_SRC].sizeimage = usize;
-		ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
-		ctx->q_data[V4L2_M2M_DST].sizeimage = csize;
-	} else {
-		ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
-		ctx->q_data[V4L2_M2M_SRC].sizeimage = csize;
-		ctx->q_data[V4L2_M2M_DST].bytesperline = max_w;
-		ctx->q_data[V4L2_M2M_DST].sizeimage = usize;
-	}
-	ctx->q_data[V4L2_M2M_SRC].rect.width = max_w;
-	ctx->q_data[V4L2_M2M_SRC].rect.height = max_h;
-	ctx->q_data[V4L2_M2M_DST].rect.width = max_w;
-	ctx->q_data[V4L2_M2M_DST].rect.height = max_h;
-
-	/*
-	 * Since the RBC2AXI logic only supports a single chroma plane,
-	 * macroblock tiling only works for to NV12 pixel format.
-	 */
-	ctx->tiled_map_type = GDI_LINEAR_FRAME_MAP;
-}
-
-/*
- * Queue operations
- */
-static int coda_queue_setup(struct vb2_queue *vq,
-				unsigned int *nbuffers, unsigned int *nplanes,
-				unsigned int sizes[], struct device *alloc_devs[])
-{
-	struct coda_ctx *ctx = vb2_get_drv_priv(vq);
-	struct coda_q_data *q_data;
-	unsigned int size;
-
-	q_data = get_q_data(ctx, vq->type);
-	size = q_data->sizeimage;
-
-	if (*nplanes)
-		return sizes[0] < size ? -EINVAL : 0;
-
-	*nplanes = 1;
-	sizes[0] = size;
-
-	coda_dbg(1, ctx, "get %d buffer(s) of size %d each.\n", *nbuffers,
-		 size);
-
-	return 0;
-}
-
-static int coda_buf_prepare(struct vb2_buffer *vb)
-{
-	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-	struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-	struct coda_q_data *q_data;
-
-	q_data = get_q_data(ctx, vb->vb2_queue->type);
-	if (V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
-		if (vbuf->field == V4L2_FIELD_ANY)
-			vbuf->field = V4L2_FIELD_NONE;
-		if (vbuf->field != V4L2_FIELD_NONE) {
-			v4l2_warn(&ctx->dev->v4l2_dev,
-				  "%s field isn't supported\n", __func__);
-			return -EINVAL;
-		}
-	}
-
-	if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
-		v4l2_warn(&ctx->dev->v4l2_dev,
-			  "%s data will not fit into plane (%lu < %lu)\n",
-			  __func__, vb2_plane_size(vb, 0),
-			  (long)q_data->sizeimage);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static void coda_update_menu_ctrl(struct v4l2_ctrl *ctrl, int value)
-{
-	if (!ctrl)
-		return;
-
-	v4l2_ctrl_lock(ctrl);
-
-	/*
-	 * Extend the control range if the parsed stream contains a known but
-	 * unsupported value or level.
-	 */
-	if (value > ctrl->maximum) {
-		__v4l2_ctrl_modify_range(ctrl, ctrl->minimum, value,
-			ctrl->menu_skip_mask & ~(1 << value),
-			ctrl->default_value);
-	} else if (value < ctrl->minimum) {
-		__v4l2_ctrl_modify_range(ctrl, value, ctrl->maximum,
-			ctrl->menu_skip_mask & ~(1 << value),
-			ctrl->default_value);
-	}
-
-	__v4l2_ctrl_s_ctrl(ctrl, value);
-
-	v4l2_ctrl_unlock(ctrl);
-}
-
-void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc,
-				     u8 level_idc)
-{
-	const char * const *profile_names;
-	const char * const *level_names;
-	struct v4l2_ctrl *profile_ctrl;
-	struct v4l2_ctrl *level_ctrl;
-	const char *codec_name;
-	u32 profile_cid;
-	u32 level_cid;
-	int profile;
-	int level;
-
-	switch (ctx->codec->src_fourcc) {
-	case V4L2_PIX_FMT_H264:
-		codec_name = "H264";
-		profile_cid = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
-		level_cid = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
-		profile_ctrl = ctx->h264_profile_ctrl;
-		level_ctrl = ctx->h264_level_ctrl;
-		profile = coda_h264_profile(profile_idc);
-		level = coda_h264_level(level_idc);
-		break;
-	case V4L2_PIX_FMT_MPEG2:
-		codec_name = "MPEG-2";
-		profile_cid = V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE;
-		level_cid = V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL;
-		profile_ctrl = ctx->mpeg2_profile_ctrl;
-		level_ctrl = ctx->mpeg2_level_ctrl;
-		profile = coda_mpeg2_profile(profile_idc);
-		level = coda_mpeg2_level(level_idc);
-		break;
-	case V4L2_PIX_FMT_MPEG4:
-		codec_name = "MPEG-4";
-		profile_cid = V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE;
-		level_cid = V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL;
-		profile_ctrl = ctx->mpeg4_profile_ctrl;
-		level_ctrl = ctx->mpeg4_level_ctrl;
-		profile = coda_mpeg4_profile(profile_idc);
-		level = coda_mpeg4_level(level_idc);
-		break;
-	default:
-		return;
-	}
-
-	profile_names = v4l2_ctrl_get_menu(profile_cid);
-	level_names = v4l2_ctrl_get_menu(level_cid);
-
-	if (profile < 0) {
-		v4l2_warn(&ctx->dev->v4l2_dev, "Invalid %s profile: %u\n",
-			  codec_name, profile_idc);
-	} else {
-		coda_dbg(1, ctx, "Parsed %s profile: %s\n", codec_name,
-			 profile_names[profile]);
-		coda_update_menu_ctrl(profile_ctrl, profile);
-	}
-
-	if (level < 0) {
-		v4l2_warn(&ctx->dev->v4l2_dev, "Invalid %s level: %u\n",
-			  codec_name, level_idc);
-	} else {
-		coda_dbg(1, ctx, "Parsed %s level: %s\n", codec_name,
-			 level_names[level]);
-		coda_update_menu_ctrl(level_ctrl, level);
-	}
-}
-
-static void coda_queue_source_change_event(struct coda_ctx *ctx)
-{
-	static const struct v4l2_event source_change_event = {
-		.type = V4L2_EVENT_SOURCE_CHANGE,
-		.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
-	};
-
-	v4l2_event_queue_fh(&ctx->fh, &source_change_event);
-}
-
-static void coda_buf_queue(struct vb2_buffer *vb)
-{
-	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
-	struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
-	struct vb2_queue *vq = vb->vb2_queue;
-	struct coda_q_data *q_data;
-
-	q_data = get_q_data(ctx, vb->vb2_queue->type);
-
-	/*
-	 * In the decoder case, immediately try to copy the buffer into the
-	 * bitstream ringbuffer and mark it as ready to be dequeued.
-	 */
-	if (ctx->bitstream.size && vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-		/*
-		 * For backwards compatibility, queuing an empty buffer marks
-		 * the stream end
-		 */
-		if (vb2_get_plane_payload(vb, 0) == 0)
-			coda_bit_stream_end_flag(ctx);
-
-		if (q_data->fourcc == V4L2_PIX_FMT_H264) {
-			/*
-			 * Unless already done, try to obtain profile_idc and
-			 * level_idc from the SPS header. This allows to decide
-			 * whether to enable reordering during sequence
-			 * initialization.
-			 */
-			if (!ctx->params.h264_profile_idc) {
-				coda_sps_parse_profile(ctx, vb);
-				coda_update_profile_level_ctrls(ctx,
-						ctx->params.h264_profile_idc,
-						ctx->params.h264_level_idc);
-			}
-		}
-
-		mutex_lock(&ctx->bitstream_mutex);
-		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
-		if (vb2_is_streaming(vb->vb2_queue))
-			/* This set buf->sequence = ctx->qsequence++ */
-			coda_fill_bitstream(ctx, NULL);
-		mutex_unlock(&ctx->bitstream_mutex);
-
-		if (!ctx->initialized) {
-			/*
-			 * Run sequence initialization in case the queued
-			 * buffer contained headers.
-			 */
-			if (vb2_is_streaming(vb->vb2_queue) &&
-			    ctx->ops->seq_init_work) {
-				queue_work(ctx->dev->workqueue,
-					   &ctx->seq_init_work);
-				flush_work(&ctx->seq_init_work);
-			}
-
-			if (ctx->initialized)
-				coda_queue_source_change_event(ctx);
-		}
-	} else {
-		if ((ctx->inst_type == CODA_INST_ENCODER || !ctx->use_bit) &&
-		    vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-			vbuf->sequence = ctx->qsequence++;
-		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
-	}
-}
-
-int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf,
-		       size_t size, const char *name, struct dentry *parent)
-{
-	buf->vaddr = dma_alloc_coherent(dev->dev, size, &buf->paddr,
-					GFP_KERNEL);
-	if (!buf->vaddr) {
-		v4l2_err(&dev->v4l2_dev,
-			 "Failed to allocate %s buffer of size %zu\n",
-			 name, size);
-		return -ENOMEM;
-	}
-
-	buf->size = size;
-
-	if (name && parent) {
-		buf->blob.data = buf->vaddr;
-		buf->blob.size = size;
-		buf->dentry = debugfs_create_blob(name, 0444, parent,
-						  &buf->blob);
-	}
-
-	return 0;
-}
-
-void coda_free_aux_buf(struct coda_dev *dev,
-		       struct coda_aux_buf *buf)
-{
-	if (buf->vaddr) {
-		dma_free_coherent(dev->dev, buf->size, buf->vaddr, buf->paddr);
-		buf->vaddr = NULL;
-		buf->size = 0;
-		debugfs_remove(buf->dentry);
-		buf->dentry = NULL;
-	}
-}
-
-static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
-{
-	struct coda_ctx *ctx = vb2_get_drv_priv(q);
-	struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev;
-	struct coda_q_data *q_data_src, *q_data_dst;
-	struct v4l2_m2m_buffer *m2m_buf, *tmp;
-	struct vb2_v4l2_buffer *buf;
-	struct list_head list;
-	int ret = 0;
-
-	if (count < 1)
-		return -EINVAL;
-
-	coda_dbg(1, ctx, "start streaming %s\n", v4l2_type_names[q->type]);
-
-	INIT_LIST_HEAD(&list);
-
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-		if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit) {
-			/* copy the buffers that were queued before streamon */
-			mutex_lock(&ctx->bitstream_mutex);
-			coda_fill_bitstream(ctx, &list);
-			mutex_unlock(&ctx->bitstream_mutex);
-
-			if (ctx->dev->devtype->product != CODA_960 &&
-			    coda_get_bitstream_payload(ctx) < 512) {
-				v4l2_err(v4l2_dev, "start payload < 512\n");
-				ret = -EINVAL;
-				goto err;
-			}
-
-			if (!ctx->initialized) {
-				/* Run sequence initialization */
-				if (ctx->ops->seq_init_work) {
-					queue_work(ctx->dev->workqueue,
-						   &ctx->seq_init_work);
-					flush_work(&ctx->seq_init_work);
-				}
-			}
-		}
-
-		/*
-		 * Check the first input JPEG buffer to determine chroma
-		 * subsampling.
-		 */
-		if (q_data_src->fourcc == V4L2_PIX_FMT_JPEG) {
-			buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-			coda_jpeg_decode_header(ctx, &buf->vb2_buf);
-			/*
-			 * We have to start streaming even if the first buffer
-			 * does not contain a valid JPEG image. The error will
-			 * be caught during device run and will be signalled
-			 * via the capture buffer error flag.
-			 */
-
-			q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-			q_data_dst->width = round_up(q_data_src->width, 16);
-			q_data_dst->height = round_up(q_data_src->height, 16);
-			q_data_dst->bytesperline = q_data_dst->width;
-			if (ctx->params.jpeg_chroma_subsampling ==
-			    V4L2_JPEG_CHROMA_SUBSAMPLING_420) {
-				q_data_dst->sizeimage =
-						q_data_dst->bytesperline *
-						q_data_dst->height * 3 / 2;
-				if (q_data_dst->fourcc != V4L2_PIX_FMT_YUV420)
-					q_data_dst->fourcc = V4L2_PIX_FMT_NV12;
-			} else {
-				q_data_dst->sizeimage =
-						q_data_dst->bytesperline *
-						q_data_dst->height * 2;
-				q_data_dst->fourcc = V4L2_PIX_FMT_YUV422P;
-			}
-			q_data_dst->rect.left = 0;
-			q_data_dst->rect.top = 0;
-			q_data_dst->rect.width = q_data_src->width;
-			q_data_dst->rect.height = q_data_src->height;
-		}
-		ctx->streamon_out = 1;
-	} else {
-		ctx->streamon_cap = 1;
-	}
-
-	/* Don't start the coda unless both queues are on */
-	if (!(ctx->streamon_out && ctx->streamon_cap))
-		goto out;
-
-	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	if ((q_data_src->rect.width != q_data_dst->width &&
-	     round_up(q_data_src->rect.width, 16) != q_data_dst->width) ||
-	    (q_data_src->rect.height != q_data_dst->height &&
-	     round_up(q_data_src->rect.height, 16) != q_data_dst->height)) {
-		v4l2_err(v4l2_dev, "can't convert %dx%d to %dx%d\n",
-			 q_data_src->rect.width, q_data_src->rect.height,
-			 q_data_dst->width, q_data_dst->height);
-		ret = -EINVAL;
-		goto err;
-	}
-
-	/* Allow BIT decoder device_run with no new buffers queued */
-	if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit)
-		v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
-
-	ctx->gopcounter = ctx->params.gop_size - 1;
-
-	if (q_data_dst->fourcc == V4L2_PIX_FMT_JPEG)
-		ctx->params.gop_size = 1;
-	ctx->gopcounter = ctx->params.gop_size - 1;
-	/* Only decoders have this control */
-	if (ctx->mb_err_cnt_ctrl)
-		v4l2_ctrl_s_ctrl(ctx->mb_err_cnt_ctrl, 0);
-
-	ret = ctx->ops->start_streaming(ctx);
-	if (ctx->inst_type == CODA_INST_DECODER) {
-		if (ret == -EAGAIN)
-			goto out;
-	}
-	if (ret < 0)
-		goto err;
-
-out:
-	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-		list_for_each_entry_safe(m2m_buf, tmp, &list, list) {
-			list_del(&m2m_buf->list);
-			v4l2_m2m_buf_done(&m2m_buf->vb, VB2_BUF_STATE_DONE);
-		}
-	}
-	return 0;
-
-err:
-	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-		list_for_each_entry_safe(m2m_buf, tmp, &list, list) {
-			list_del(&m2m_buf->list);
-			v4l2_m2m_buf_done(&m2m_buf->vb, VB2_BUF_STATE_QUEUED);
-		}
-		while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
-			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED);
-	} else {
-		while ((buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx)))
-			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED);
-	}
-	return ret;
-}
-
-static void coda_stop_streaming(struct vb2_queue *q)
-{
-	struct coda_ctx *ctx = vb2_get_drv_priv(q);
-	struct coda_dev *dev = ctx->dev;
-	struct vb2_v4l2_buffer *buf;
-	bool stop;
-
-	stop = ctx->streamon_out && ctx->streamon_cap;
-
-	coda_dbg(1, ctx, "stop streaming %s\n", v4l2_type_names[q->type]);
-
-	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-		ctx->streamon_out = 0;
-
-		coda_bit_stream_end_flag(ctx);
-
-		ctx->qsequence = 0;
-
-		while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
-			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
-	} else {
-		ctx->streamon_cap = 0;
-
-		ctx->osequence = 0;
-		ctx->sequence_offset = 0;
-
-		while ((buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx)))
-			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
-	}
-
-	if (stop) {
-		struct coda_buffer_meta *meta;
-
-		if (ctx->ops->seq_end_work) {
-			queue_work(dev->workqueue, &ctx->seq_end_work);
-			flush_work(&ctx->seq_end_work);
-		}
-		spin_lock(&ctx->buffer_meta_lock);
-		while (!list_empty(&ctx->buffer_meta_list)) {
-			meta = list_first_entry(&ctx->buffer_meta_list,
-						struct coda_buffer_meta, list);
-			list_del(&meta->list);
-			kfree(meta);
-		}
-		ctx->num_metas = 0;
-		spin_unlock(&ctx->buffer_meta_lock);
-		kfifo_init(&ctx->bitstream_fifo,
-			ctx->bitstream.vaddr, ctx->bitstream.size);
-		ctx->runcounter = 0;
-		ctx->aborting = 0;
-		ctx->hold = false;
-	}
-
-	if (!ctx->streamon_out && !ctx->streamon_cap)
-		ctx->bit_stream_param &= ~CODA_BIT_STREAM_END_FLAG;
-}
-
-static const struct vb2_ops coda_qops = {
-	.queue_setup		= coda_queue_setup,
-	.buf_prepare		= coda_buf_prepare,
-	.buf_queue		= coda_buf_queue,
-	.start_streaming	= coda_start_streaming,
-	.stop_streaming		= coda_stop_streaming,
-	.wait_prepare		= vb2_ops_wait_prepare,
-	.wait_finish		= vb2_ops_wait_finish,
-};
-
-static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
-{
-	const char * const *val_names = v4l2_ctrl_get_menu(ctrl->id);
-	struct coda_ctx *ctx =
-			container_of(ctrl->handler, struct coda_ctx, ctrls);
-
-	if (val_names)
-		coda_dbg(2, ctx, "s_ctrl: id = 0x%x, name = \"%s\", val = %d (\"%s\")\n",
-			 ctrl->id, ctrl->name, ctrl->val, val_names[ctrl->val]);
-	else
-		coda_dbg(2, ctx, "s_ctrl: id = 0x%x, name = \"%s\", val = %d\n",
-			 ctrl->id, ctrl->name, ctrl->val);
-
-	switch (ctrl->id) {
-	case V4L2_CID_HFLIP:
-		if (ctrl->val)
-			ctx->params.rot_mode |= CODA_MIR_HOR;
-		else
-			ctx->params.rot_mode &= ~CODA_MIR_HOR;
-		break;
-	case V4L2_CID_VFLIP:
-		if (ctrl->val)
-			ctx->params.rot_mode |= CODA_MIR_VER;
-		else
-			ctx->params.rot_mode &= ~CODA_MIR_VER;
-		break;
-	case V4L2_CID_MPEG_VIDEO_BITRATE:
-		ctx->params.bitrate = ctrl->val / 1000;
-		ctx->params.bitrate_changed = true;
-		break;
-	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
-		ctx->params.gop_size = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
-		ctx->params.h264_intra_qp = ctrl->val;
-		ctx->params.h264_intra_qp_changed = true;
-		break;
-	case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
-		ctx->params.h264_inter_qp = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
-		ctx->params.h264_min_qp = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
-		ctx->params.h264_max_qp = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
-		ctx->params.h264_slice_alpha_c0_offset_div2 = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
-		ctx->params.h264_slice_beta_offset_div2 = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
-		ctx->params.h264_disable_deblocking_filter_idc = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION:
-		ctx->params.h264_constrained_intra_pred_flag = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
-		ctx->params.frame_rc_enable = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
-		ctx->params.mb_rc_enable = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET:
-		ctx->params.h264_chroma_qp_index_offset = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
-		/* TODO: switch between baseline and constrained baseline */
-		if (ctx->inst_type == CODA_INST_ENCODER)
-			ctx->params.h264_profile_idc = 66;
-		break;
-	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
-		/* nothing to do, this is set by the encoder */
-		break;
-	case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
-		ctx->params.mpeg4_intra_qp = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
-		ctx->params.mpeg4_inter_qp = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE:
-	case V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL:
-	case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
-	case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
-		/* nothing to do, these are fixed */
-		break;
-	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
-		ctx->params.slice_mode = ctrl->val;
-		ctx->params.slice_mode_changed = true;
-		break;
-	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
-		ctx->params.slice_max_mb = ctrl->val;
-		ctx->params.slice_mode_changed = true;
-		break;
-	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
-		ctx->params.slice_max_bits = ctrl->val * 8;
-		ctx->params.slice_mode_changed = true;
-		break;
-	case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
-		break;
-	case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
-		ctx->params.intra_refresh = ctrl->val;
-		ctx->params.intra_refresh_changed = true;
-		break;
-	case V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME:
-		ctx->params.force_ipicture = true;
-		break;
-	case V4L2_CID_JPEG_COMPRESSION_QUALITY:
-		coda_set_jpeg_compression_quality(ctx, ctrl->val);
-		break;
-	case V4L2_CID_JPEG_RESTART_INTERVAL:
-		ctx->params.jpeg_restart_interval = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_VBV_DELAY:
-		ctx->params.vbv_delay = ctrl->val;
-		break;
-	case V4L2_CID_MPEG_VIDEO_VBV_SIZE:
-		ctx->params.vbv_size = min(ctrl->val * 8192, 0x7fffffff);
-		break;
-	default:
-		coda_dbg(1, ctx, "Invalid control, id=%d, val=%d\n",
-			 ctrl->id, ctrl->val);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static const struct v4l2_ctrl_ops coda_ctrl_ops = {
-	.s_ctrl = coda_s_ctrl,
-};
-
-static void coda_encode_ctrls(struct coda_ctx *ctx)
-{
-	int max_gop_size = (ctx->dev->devtype->product == CODA_DX6) ? 60 : 99;
-
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_BITRATE, 0, 32767000, 1000, 0);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, max_gop_size, 1, 16);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 0, 51, 1, 25);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 0, 51, 1, 25);
-	if (ctx->dev->devtype->product != CODA_960) {
-		v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-			V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 51, 1, 12);
-	}
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 0, 51, 1, 51);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA, -6, 6, 1, 0);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA, -6, 6, 1, 0);
-	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
-		V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY,
-		0x0, V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION, 0, 1, 1,
-		0);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE, 0, 1, 1, 1);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE, 0, 1, 1, 1);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET, -12, 12, 1, 0);
-	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_H264_PROFILE,
-		V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE, 0x0,
-		V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE);
-	if (ctx->dev->devtype->product == CODA_HX4 ||
-	    ctx->dev->devtype->product == CODA_7541) {
-		v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
-			V4L2_CID_MPEG_VIDEO_H264_LEVEL,
-			V4L2_MPEG_VIDEO_H264_LEVEL_3_1,
-			~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
-			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
-			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1)),
-			V4L2_MPEG_VIDEO_H264_LEVEL_3_1);
-	}
-	if (ctx->dev->devtype->product == CODA_960) {
-		v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
-			V4L2_CID_MPEG_VIDEO_H264_LEVEL,
-			V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
-			~((1 << V4L2_MPEG_VIDEO_H264_LEVEL_1_0) |
-			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_2_0) |
-			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_0) |
-			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_1) |
-			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_3_2) |
-			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_0) |
-			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_1) |
-			  (1 << V4L2_MPEG_VIDEO_H264_LEVEL_4_2)),
-			V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
-	}
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP, 1, 31, 1, 2);
-	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
-		V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE, 0x0,
-		V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE);
-	if (ctx->dev->devtype->product == CODA_HX4 ||
-	    ctx->dev->devtype->product == CODA_7541 ||
-	    ctx->dev->devtype->product == CODA_960) {
-		v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
-			V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
-			V4L2_MPEG_VIDEO_MPEG4_LEVEL_5,
-			~(1 << V4L2_MPEG_VIDEO_MPEG4_LEVEL_5),
-			V4L2_MPEG_VIDEO_MPEG4_LEVEL_5);
-	}
-	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
-		V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_BYTES, 0x0,
-		V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, 1, 0x3fffffff, 1, 1);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, 1, 0x3fffffff, 1,
-		500);
-	v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_HEADER_MODE,
-		V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
-		(1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE),
-		V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, 0,
-		1920 * 1088 / 256, 1, 0);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_VBV_DELAY, 0, 0x7fff, 1, 0);
-	/*
-	 * The maximum VBV size value is 0x7fffffff bits,
-	 * one bit less than 262144 KiB
-	 */
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_MPEG_VIDEO_VBV_SIZE, 0, 262144, 1, 0);
-}
-
-static void coda_jpeg_encode_ctrls(struct coda_ctx *ctx)
-{
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_JPEG_COMPRESSION_QUALITY, 5, 100, 1, 50);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_JPEG_RESTART_INTERVAL, 0, 100, 1, 0);
-}
-
-static void coda_decode_ctrls(struct coda_ctx *ctx)
-{
-	u8 max;
-
-	ctx->h264_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
-		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_PROFILE,
-		V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
-		~((1 << V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) |
-		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) |
-		  (1 << V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)),
-		V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
-	if (ctx->h264_profile_ctrl)
-		ctx->h264_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-
-	if (ctx->dev->devtype->product == CODA_HX4 ||
-	    ctx->dev->devtype->product == CODA_7541)
-		max = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
-	else if (ctx->dev->devtype->product == CODA_960)
-		max = V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
-	else
-		return;
-	ctx->h264_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
-		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_H264_LEVEL, max, 0, max);
-	if (ctx->h264_level_ctrl)
-		ctx->h264_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-
-	ctx->mpeg2_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
-		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE,
-		V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH, 0,
-		V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH);
-	if (ctx->mpeg2_profile_ctrl)
-		ctx->mpeg2_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-
-	ctx->mpeg2_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
-		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL,
-		V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH, 0,
-		V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH);
-	if (ctx->mpeg2_level_ctrl)
-		ctx->mpeg2_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-
-	ctx->mpeg4_profile_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
-		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE,
-		V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY, 0,
-		V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY);
-	if (ctx->mpeg4_profile_ctrl)
-		ctx->mpeg4_profile_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-
-	ctx->mpeg4_level_ctrl = v4l2_ctrl_new_std_menu(&ctx->ctrls,
-		&coda_ctrl_ops, V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL,
-		V4L2_MPEG_VIDEO_MPEG4_LEVEL_5, 0,
-		V4L2_MPEG_VIDEO_MPEG4_LEVEL_5);
-	if (ctx->mpeg4_level_ctrl)
-		ctx->mpeg4_level_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-}
-
-static const struct v4l2_ctrl_config coda_mb_err_cnt_ctrl_config = {
-	.id	= V4L2_CID_CODA_MB_ERR_CNT,
-	.name	= "Macroblocks Error Count",
-	.type	= V4L2_CTRL_TYPE_INTEGER,
-	.min	= 0,
-	.max	= 0x7fffffff,
-	.step	= 1,
-};
-
-static int coda_ctrls_setup(struct coda_ctx *ctx)
-{
-	v4l2_ctrl_handler_init(&ctx->ctrls, 2);
-
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_HFLIP, 0, 1, 1, 0);
-	v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-		V4L2_CID_VFLIP, 0, 1, 1, 0);
-	if (ctx->inst_type == CODA_INST_ENCODER) {
-		v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-				  V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
-				  1, 1, 1, 1);
-		if (ctx->cvd->dst_formats[0] == V4L2_PIX_FMT_JPEG)
-			coda_jpeg_encode_ctrls(ctx);
-		else
-			coda_encode_ctrls(ctx);
-	} else {
-		v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
-				  V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
-				  1, 1, 1, 1);
-		if (ctx->cvd->src_formats[0] == V4L2_PIX_FMT_H264)
-			coda_decode_ctrls(ctx);
-
-		ctx->mb_err_cnt_ctrl = v4l2_ctrl_new_custom(&ctx->ctrls,
-						&coda_mb_err_cnt_ctrl_config,
-						NULL);
-		if (ctx->mb_err_cnt_ctrl)
-			ctx->mb_err_cnt_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
-	}
-
-	if (ctx->ctrls.error) {
-		v4l2_err(&ctx->dev->v4l2_dev,
-			"control initialization error (%d)",
-			ctx->ctrls.error);
-		return -EINVAL;
-	}
-
-	return v4l2_ctrl_handler_setup(&ctx->ctrls);
-}
-
-static int coda_queue_init(struct coda_ctx *ctx, struct vb2_queue *vq)
-{
-	vq->drv_priv = ctx;
-	vq->ops = &coda_qops;
-	vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
-	vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
-	vq->lock = &ctx->dev->dev_mutex;
-	/* One way to indicate end-of-stream for coda is to set the
-	 * bytesused == 0. However by default videobuf2 handles bytesused
-	 * equal to 0 as a special case and changes its value to the size
-	 * of the buffer. Set the allow_zero_bytesused flag, so
-	 * that videobuf2 will keep the value of bytesused intact.
-	 */
-	vq->allow_zero_bytesused = 1;
-	/*
-	 * We might be fine with no buffers on some of the queues, but that
-	 * would need to be reflected in job_ready(). Currently we expect all
-	 * queues to have at least one buffer queued.
-	 */
-	vq->min_buffers_needed = 1;
-	vq->dev = ctx->dev->dev;
-
-	return vb2_queue_init(vq);
-}
-
-int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq,
-			    struct vb2_queue *dst_vq)
-{
-	int ret;
-
-	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-	src_vq->io_modes = VB2_DMABUF | VB2_MMAP;
-	src_vq->mem_ops = &vb2_dma_contig_memops;
-
-	ret = coda_queue_init(priv, src_vq);
-	if (ret)
-		return ret;
-
-	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	dst_vq->io_modes = VB2_DMABUF | VB2_MMAP;
-	dst_vq->mem_ops = &vb2_dma_contig_memops;
-
-	return coda_queue_init(priv, dst_vq);
-}
-
-int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq,
-			    struct vb2_queue *dst_vq)
-{
-	int ret;
-
-	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
-	src_vq->io_modes = VB2_DMABUF | VB2_MMAP | VB2_USERPTR;
-	src_vq->mem_ops = &vb2_vmalloc_memops;
-
-	ret = coda_queue_init(priv, src_vq);
-	if (ret)
-		return ret;
-
-	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-	dst_vq->io_modes = VB2_DMABUF | VB2_MMAP;
-	dst_vq->dma_attrs = DMA_ATTR_NO_KERNEL_MAPPING;
-	dst_vq->mem_ops = &vb2_dma_contig_memops;
-
-	return coda_queue_init(priv, dst_vq);
-}
-
-/*
- * File operations
- */
-
-static int coda_open(struct file *file)
-{
-	struct video_device *vdev = video_devdata(file);
-	struct coda_dev *dev = video_get_drvdata(vdev);
-	struct coda_ctx *ctx;
-	unsigned int max = ~0;
-	char *name;
-	int ret;
-	int idx;
-
-	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-	if (!ctx)
-		return -ENOMEM;
-
-	if (dev->devtype->product == CODA_DX6)
-		max = CODADX6_MAX_INSTANCES - 1;
-	idx = ida_alloc_max(&dev->ida, max, GFP_KERNEL);
-	if (idx < 0) {
-		ret = idx;
-		goto err_coda_max;
-	}
-
-	name = kasprintf(GFP_KERNEL, "context%d", idx);
-	if (!name) {
-		ret = -ENOMEM;
-		goto err_coda_name_init;
-	}
-
-	ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root);
-	kfree(name);
-
-	ctx->cvd = to_coda_video_device(vdev);
-	ctx->inst_type = ctx->cvd->type;
-	ctx->ops = ctx->cvd->ops;
-	ctx->use_bit = !ctx->cvd->direct;
-	init_completion(&ctx->completion);
-	INIT_WORK(&ctx->pic_run_work, coda_pic_run_work);
-	if (ctx->ops->seq_init_work)
-		INIT_WORK(&ctx->seq_init_work, ctx->ops->seq_init_work);
-	if (ctx->ops->seq_end_work)
-		INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work);
-	v4l2_fh_init(&ctx->fh, video_devdata(file));
-	file->private_data = &ctx->fh;
-	v4l2_fh_add(&ctx->fh);
-	ctx->dev = dev;
-	ctx->idx = idx;
-
-	coda_dbg(1, ctx, "open instance (%p)\n", ctx);
-
-	switch (dev->devtype->product) {
-	case CODA_960:
-		/*
-		 * Enabling the BWB when decoding can hang the firmware with
-		 * certain streams. The issue was tracked as ENGR00293425 by
-		 * Freescale. As a workaround, disable BWB for all decoders.
-		 * The enable_bwb module parameter allows to override this.
-		 */
-		if (enable_bwb || ctx->inst_type == CODA_INST_ENCODER)
-			ctx->frame_mem_ctrl = CODA9_FRAME_ENABLE_BWB;
-		fallthrough;
-	case CODA_HX4:
-	case CODA_7541:
-		ctx->reg_idx = 0;
-		break;
-	default:
-		ctx->reg_idx = idx;
-	}
-	if (ctx->dev->vdoa && !disable_vdoa) {
-		ctx->vdoa = vdoa_context_create(dev->vdoa);
-		if (!ctx->vdoa)
-			v4l2_warn(&dev->v4l2_dev,
-				  "Failed to create vdoa context: not using vdoa");
-	}
-	ctx->use_vdoa = false;
-
-	/* Power up and upload firmware if necessary */
-	ret = pm_runtime_resume_and_get(dev->dev);
-	if (ret < 0) {
-		v4l2_err(&dev->v4l2_dev, "failed to power up: %d\n", ret);
-		goto err_pm_get;
-	}
-
-	ret = clk_prepare_enable(dev->clk_per);
-	if (ret)
-		goto err_clk_enable;
-
-	ret = clk_prepare_enable(dev->clk_ahb);
-	if (ret)
-		goto err_clk_ahb;
-
-	set_default_params(ctx);
-	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
-					    ctx->ops->queue_init);
-	if (IS_ERR(ctx->fh.m2m_ctx)) {
-		ret = PTR_ERR(ctx->fh.m2m_ctx);
-
-		v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n",
-			 __func__, ret);
-		goto err_ctx_init;
-	}
-
-	ret = coda_ctrls_setup(ctx);
-	if (ret) {
-		v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n");
-		goto err_ctrls_setup;
-	}
-
-	ctx->fh.ctrl_handler = &ctx->ctrls;
-
-	mutex_init(&ctx->bitstream_mutex);
-	mutex_init(&ctx->buffer_mutex);
-	mutex_init(&ctx->wakeup_mutex);
-	INIT_LIST_HEAD(&ctx->buffer_meta_list);
-	spin_lock_init(&ctx->buffer_meta_lock);
-
-	return 0;
-
-err_ctrls_setup:
-	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
-err_ctx_init:
-	clk_disable_unprepare(dev->clk_ahb);
-err_clk_ahb:
-	clk_disable_unprepare(dev->clk_per);
-err_clk_enable:
-	pm_runtime_put_sync(dev->dev);
-err_pm_get:
-	v4l2_fh_del(&ctx->fh);
-	v4l2_fh_exit(&ctx->fh);
-err_coda_name_init:
-	ida_free(&dev->ida, ctx->idx);
-err_coda_max:
-	kfree(ctx);
-	return ret;
-}
-
-static int coda_release(struct file *file)
-{
-	struct coda_dev *dev = video_drvdata(file);
-	struct coda_ctx *ctx = fh_to_ctx(file->private_data);
-
-	coda_dbg(1, ctx, "release instance (%p)\n", ctx);
-
-	if (ctx->inst_type == CODA_INST_DECODER && ctx->use_bit)
-		coda_bit_stream_end_flag(ctx);
-
-	/* If this instance is running, call .job_abort and wait for it to end */
-	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
-
-	if (ctx->vdoa)
-		vdoa_context_destroy(ctx->vdoa);
-
-	/* In case the instance was not running, we still need to call SEQ_END */
-	if (ctx->ops->seq_end_work) {
-		queue_work(dev->workqueue, &ctx->seq_end_work);
-		flush_work(&ctx->seq_end_work);
-	}
-
-	if (ctx->dev->devtype->product == CODA_DX6)
-		coda_free_aux_buf(dev, &ctx->workbuf);
-
-	v4l2_ctrl_handler_free(&ctx->ctrls);
-	clk_disable_unprepare(dev->clk_ahb);
-	clk_disable_unprepare(dev->clk_per);
-	pm_runtime_put_sync(dev->dev);
-	v4l2_fh_del(&ctx->fh);
-	v4l2_fh_exit(&ctx->fh);
-	ida_free(&dev->ida, ctx->idx);
-	if (ctx->ops->release)
-		ctx->ops->release(ctx);
-	debugfs_remove_recursive(ctx->debugfs_entry);
-	kfree(ctx);
-
-	return 0;
-}
-
-static const struct v4l2_file_operations coda_fops = {
-	.owner		= THIS_MODULE,
-	.open		= coda_open,
-	.release	= coda_release,
-	.poll		= v4l2_m2m_fop_poll,
-	.unlocked_ioctl	= video_ioctl2,
-	.mmap		= v4l2_m2m_fop_mmap,
-};
-
-static int coda_hw_init(struct coda_dev *dev)
-{
-	u32 data;
-	u16 *p;
-	int i, ret;
-
-	ret = clk_prepare_enable(dev->clk_per);
-	if (ret)
-		goto err_clk_per;
-
-	ret = clk_prepare_enable(dev->clk_ahb);
-	if (ret)
-		goto err_clk_ahb;
-
-	reset_control_reset(dev->rstc);
-
-	/*
-	 * Copy the first CODA_ISRAM_SIZE in the internal SRAM.
-	 * The 16-bit chars in the code buffer are in memory access
-	 * order, re-sort them to CODA order for register download.
-	 * Data in this SRAM survives a reboot.
-	 */
-	p = (u16 *)dev->codebuf.vaddr;
-	if (dev->devtype->product == CODA_DX6) {
-		for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++)  {
-			data = CODA_DOWN_ADDRESS_SET(i) |
-				CODA_DOWN_DATA_SET(p[i ^ 1]);
-			coda_write(dev, data, CODA_REG_BIT_CODE_DOWN);
-		}
-	} else {
-		for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++) {
-			data = CODA_DOWN_ADDRESS_SET(i) |
-				CODA_DOWN_DATA_SET(p[round_down(i, 4) +
-							3 - (i % 4)]);
-			coda_write(dev, data, CODA_REG_BIT_CODE_DOWN);
-		}
-	}
-
-	/* Clear registers */
-	for (i = 0; i < 64; i++)
-		coda_write(dev, 0, CODA_REG_BIT_CODE_BUF_ADDR + i * 4);
-
-	/* Tell the BIT where to find everything it needs */
-	if (dev->devtype->product == CODA_960 ||
-	    dev->devtype->product == CODA_7541 ||
-	    dev->devtype->product == CODA_HX4) {
-		coda_write(dev, dev->tempbuf.paddr,
-				CODA_REG_BIT_TEMP_BUF_ADDR);
-		coda_write(dev, 0, CODA_REG_BIT_BIT_STREAM_PARAM);
-	} else {
-		coda_write(dev, dev->workbuf.paddr,
-			      CODA_REG_BIT_WORK_BUF_ADDR);
-	}
-	coda_write(dev, dev->codebuf.paddr,
-		      CODA_REG_BIT_CODE_BUF_ADDR);
-	coda_write(dev, 0, CODA_REG_BIT_CODE_RUN);
-
-	/* Set default values */
-	switch (dev->devtype->product) {
-	case CODA_DX6:
-		coda_write(dev, CODADX6_STREAM_BUF_PIC_FLUSH,
-			   CODA_REG_BIT_STREAM_CTRL);
-		break;
-	default:
-		coda_write(dev, CODA7_STREAM_BUF_PIC_FLUSH,
-			   CODA_REG_BIT_STREAM_CTRL);
-	}
-	if (dev->devtype->product == CODA_960)
-		coda_write(dev, CODA9_FRAME_ENABLE_BWB,
-				CODA_REG_BIT_FRAME_MEM_CTRL);
-	else
-		coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL);
-
-	if (dev->devtype->product != CODA_DX6)
-		coda_write(dev, 0, CODA7_REG_BIT_AXI_SRAM_USE);
-
-	coda_write(dev, CODA_INT_INTERRUPT_ENABLE,
-		      CODA_REG_BIT_INT_ENABLE);
-
-	/* Reset VPU and start processor */
-	data = coda_read(dev, CODA_REG_BIT_CODE_RESET);
-	data |= CODA_REG_RESET_ENABLE;
-	coda_write(dev, data, CODA_REG_BIT_CODE_RESET);
-	udelay(10);
-	data &= ~CODA_REG_RESET_ENABLE;
-	coda_write(dev, data, CODA_REG_BIT_CODE_RESET);
-	coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN);
-
-	clk_disable_unprepare(dev->clk_ahb);
-	clk_disable_unprepare(dev->clk_per);
-
-	return 0;
-
-err_clk_ahb:
-	clk_disable_unprepare(dev->clk_per);
-err_clk_per:
-	return ret;
-}
-
-static int coda_register_device(struct coda_dev *dev, int i)
-{
-	struct video_device *vfd = &dev->vfd[i];
-	const char *name;
-	int ret;
-
-	if (i >= dev->devtype->num_vdevs)
-		return -EINVAL;
-	name = dev->devtype->vdevs[i]->name;
-
-	strscpy(vfd->name, dev->devtype->vdevs[i]->name, sizeof(vfd->name));
-	vfd->fops	= &coda_fops;
-	vfd->ioctl_ops	= &coda_ioctl_ops;
-	vfd->release	= video_device_release_empty;
-	vfd->lock	= &dev->dev_mutex;
-	vfd->v4l2_dev	= &dev->v4l2_dev;
-	vfd->vfl_dir	= VFL_DIR_M2M;
-	vfd->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
-	video_set_drvdata(vfd, dev);
-
-	/* Not applicable, use the selection API instead */
-	v4l2_disable_ioctl(vfd, VIDIOC_CROPCAP);
-	v4l2_disable_ioctl(vfd, VIDIOC_G_CROP);
-	v4l2_disable_ioctl(vfd, VIDIOC_S_CROP);
-
-	if (dev->devtype->vdevs[i]->type == CODA_INST_ENCODER) {
-		v4l2_disable_ioctl(vfd, VIDIOC_DECODER_CMD);
-		v4l2_disable_ioctl(vfd, VIDIOC_TRY_DECODER_CMD);
-		if (dev->devtype->vdevs[i]->dst_formats[0] == V4L2_PIX_FMT_JPEG) {
-			v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMEINTERVALS);
-			v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
-			v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
-		}
-	} else {
-		v4l2_disable_ioctl(vfd, VIDIOC_ENCODER_CMD);
-		v4l2_disable_ioctl(vfd, VIDIOC_TRY_ENCODER_CMD);
-		v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMESIZES);
-		v4l2_disable_ioctl(vfd, VIDIOC_ENUM_FRAMEINTERVALS);
-		v4l2_disable_ioctl(vfd, VIDIOC_G_PARM);
-		v4l2_disable_ioctl(vfd, VIDIOC_S_PARM);
-	}
-
-	ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
-	if (!ret)
-		v4l2_info(&dev->v4l2_dev, "%s registered as %s\n",
-			  name, video_device_node_name(vfd));
-	return ret;
-}
-
-static void coda_copy_firmware(struct coda_dev *dev, const u8 * const buf,
-			       size_t size)
-{
-	u32 *src = (u32 *)buf;
-
-	/* Check if the firmware has a 16-byte Freescale header, skip it */
-	if (buf[0] == 'M' && buf[1] == 'X')
-		src += 4;
-	/*
-	 * Check whether the firmware is in native order or pre-reordered for
-	 * memory access. The first instruction opcode always is 0xe40e.
-	 */
-	if (__le16_to_cpup((__le16 *)src) == 0xe40e) {
-		u32 *dst = dev->codebuf.vaddr;
-		int i;
-
-		/* Firmware in native order, reorder while copying */
-		if (dev->devtype->product == CODA_DX6) {
-			for (i = 0; i < (size - 16) / 4; i++)
-				dst[i] = (src[i] << 16) | (src[i] >> 16);
-		} else {
-			for (i = 0; i < (size - 16) / 4; i += 2) {
-				dst[i] = (src[i + 1] << 16) | (src[i + 1] >> 16);
-				dst[i + 1] = (src[i] << 16) | (src[i] >> 16);
-			}
-		}
-	} else {
-		/* Copy the already reordered firmware image */
-		memcpy(dev->codebuf.vaddr, src, size);
-	}
-}
-
-static void coda_fw_callback(const struct firmware *fw, void *context);
-
-static int coda_firmware_request(struct coda_dev *dev)
-{
-	char *fw;
-
-	if (dev->firmware >= ARRAY_SIZE(dev->devtype->firmware))
-		return -EINVAL;
-
-	fw = dev->devtype->firmware[dev->firmware];
-
-	dev_dbg(dev->dev, "requesting firmware '%s' for %s\n", fw,
-		coda_product_name(dev->devtype->product));
-
-	return request_firmware_nowait(THIS_MODULE, true, fw, dev->dev,
-				       GFP_KERNEL, dev, coda_fw_callback);
-}
-
-static void coda_fw_callback(const struct firmware *fw, void *context)
-{
-	struct coda_dev *dev = context;
-	int i, ret;
-
-	if (!fw) {
-		dev->firmware++;
-		ret = coda_firmware_request(dev);
-		if (ret < 0) {
-			v4l2_err(&dev->v4l2_dev, "firmware request failed\n");
-			goto put_pm;
-		}
-		return;
-	}
-	if (dev->firmware > 0) {
-		/*
-		 * Since we can't suppress warnings for failed asynchronous
-		 * firmware requests, report that the fallback firmware was
-		 * found.
-		 */
-		dev_info(dev->dev, "Using fallback firmware %s\n",
-			 dev->devtype->firmware[dev->firmware]);
-	}
-
-	/* allocate auxiliary per-device code buffer for the BIT processor */
-	ret = coda_alloc_aux_buf(dev, &dev->codebuf, fw->size, "codebuf",
-				 dev->debugfs_root);
-	if (ret < 0)
-		goto put_pm;
-
-	coda_copy_firmware(dev, fw->data, fw->size);
-	release_firmware(fw);
-
-	ret = coda_hw_init(dev);
-	if (ret < 0) {
-		v4l2_err(&dev->v4l2_dev, "HW initialization failed\n");
-		goto put_pm;
-	}
-
-	ret = coda_check_firmware(dev);
-	if (ret < 0)
-		goto put_pm;
-
-	dev->m2m_dev = v4l2_m2m_init(&coda_m2m_ops);
-	if (IS_ERR(dev->m2m_dev)) {
-		v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
-		goto put_pm;
-	}
-
-	for (i = 0; i < dev->devtype->num_vdevs; i++) {
-		ret = coda_register_device(dev, i);
-		if (ret) {
-			v4l2_err(&dev->v4l2_dev,
-				 "Failed to register %s video device: %d\n",
-				 dev->devtype->vdevs[i]->name, ret);
-			goto rel_vfd;
-		}
-	}
-
-	pm_runtime_put_sync(dev->dev);
-	return;
-
-rel_vfd:
-	while (--i >= 0)
-		video_unregister_device(&dev->vfd[i]);
-	v4l2_m2m_release(dev->m2m_dev);
-put_pm:
-	pm_runtime_put_sync(dev->dev);
-}
-
-enum coda_platform {
-	CODA_IMX27,
-	CODA_IMX51,
-	CODA_IMX53,
-	CODA_IMX6Q,
-	CODA_IMX6DL,
-};
-
-static const struct coda_devtype coda_devdata[] = {
-	[CODA_IMX27] = {
-		.firmware     = {
-			"vpu_fw_imx27_TO2.bin",
-			"vpu/vpu_fw_imx27_TO2.bin",
-			"v4l-codadx6-imx27.bin"
-		},
-		.product      = CODA_DX6,
-		.codecs       = codadx6_codecs,
-		.num_codecs   = ARRAY_SIZE(codadx6_codecs),
-		.vdevs        = codadx6_video_devices,
-		.num_vdevs    = ARRAY_SIZE(codadx6_video_devices),
-		.workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024,
-		.iram_size    = 0xb000,
-	},
-	[CODA_IMX51] = {
-		.firmware     = {
-			"vpu_fw_imx51.bin",
-			"vpu/vpu_fw_imx51.bin",
-			"v4l-codahx4-imx51.bin"
-		},
-		.product      = CODA_HX4,
-		.codecs       = codahx4_codecs,
-		.num_codecs   = ARRAY_SIZE(codahx4_codecs),
-		.vdevs        = codahx4_video_devices,
-		.num_vdevs    = ARRAY_SIZE(codahx4_video_devices),
-		.workbuf_size = 128 * 1024,
-		.tempbuf_size = 304 * 1024,
-		.iram_size    = 0x14000,
-	},
-	[CODA_IMX53] = {
-		.firmware     = {
-			"vpu_fw_imx53.bin",
-			"vpu/vpu_fw_imx53.bin",
-			"v4l-coda7541-imx53.bin"
-		},
-		.product      = CODA_7541,
-		.codecs       = coda7_codecs,
-		.num_codecs   = ARRAY_SIZE(coda7_codecs),
-		.vdevs        = coda7_video_devices,
-		.num_vdevs    = ARRAY_SIZE(coda7_video_devices),
-		.workbuf_size = 128 * 1024,
-		.tempbuf_size = 304 * 1024,
-		.iram_size    = 0x14000,
-	},
-	[CODA_IMX6Q] = {
-		.firmware     = {
-			"vpu_fw_imx6q.bin",
-			"vpu/vpu_fw_imx6q.bin",
-			"v4l-coda960-imx6q.bin"
-		},
-		.product      = CODA_960,
-		.codecs       = coda9_codecs,
-		.num_codecs   = ARRAY_SIZE(coda9_codecs),
-		.vdevs        = coda9_video_devices,
-		.num_vdevs    = ARRAY_SIZE(coda9_video_devices),
-		.workbuf_size = 80 * 1024,
-		.tempbuf_size = 204 * 1024,
-		.iram_size    = 0x21000,
-	},
-	[CODA_IMX6DL] = {
-		.firmware     = {
-			"vpu_fw_imx6d.bin",
-			"vpu/vpu_fw_imx6d.bin",
-			"v4l-coda960-imx6dl.bin"
-		},
-		.product      = CODA_960,
-		.codecs       = coda9_codecs,
-		.num_codecs   = ARRAY_SIZE(coda9_codecs),
-		.vdevs        = coda9_video_devices,
-		.num_vdevs    = ARRAY_SIZE(coda9_video_devices),
-		.workbuf_size = 80 * 1024,
-		.tempbuf_size = 204 * 1024,
-		.iram_size    = 0x1f000, /* leave 4k for suspend code */
-	},
-};
-
-static const struct of_device_id coda_dt_ids[] = {
-	{ .compatible = "fsl,imx27-vpu", .data = &coda_devdata[CODA_IMX27] },
-	{ .compatible = "fsl,imx51-vpu", .data = &coda_devdata[CODA_IMX51] },
-	{ .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] },
-	{ .compatible = "fsl,imx6q-vpu", .data = &coda_devdata[CODA_IMX6Q] },
-	{ .compatible = "fsl,imx6dl-vpu", .data = &coda_devdata[CODA_IMX6DL] },
-	{ /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, coda_dt_ids);
-
-static int coda_probe(struct platform_device *pdev)
-{
-	struct device_node *np = pdev->dev.of_node;
-	struct gen_pool *pool;
-	struct coda_dev *dev;
-	int ret, irq;
-
-	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return -ENOMEM;
-
-	dev->devtype = of_device_get_match_data(&pdev->dev);
-
-	dev->dev = &pdev->dev;
-	dev->clk_per = devm_clk_get(&pdev->dev, "per");
-	if (IS_ERR(dev->clk_per)) {
-		dev_err(&pdev->dev, "Could not get per clock\n");
-		return PTR_ERR(dev->clk_per);
-	}
-
-	dev->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
-	if (IS_ERR(dev->clk_ahb)) {
-		dev_err(&pdev->dev, "Could not get ahb clock\n");
-		return PTR_ERR(dev->clk_ahb);
-	}
-
-	/* Get  memory for physical registers */
-	dev->regs_base = devm_platform_ioremap_resource(pdev, 0);
-	if (IS_ERR(dev->regs_base))
-		return PTR_ERR(dev->regs_base);
-
-	/* IRQ */
-	irq = platform_get_irq_byname(pdev, "bit");
-	if (irq < 0)
-		irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	ret = devm_request_irq(&pdev->dev, irq, coda_irq_handler, 0,
-			       CODA_NAME "-video", dev);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "failed to request irq: %d\n", ret);
-		return ret;
-	}
-
-	/* JPEG IRQ */
-	if (dev->devtype->product == CODA_960) {
-		irq = platform_get_irq_byname(pdev, "jpeg");
-		if (irq < 0)
-			return irq;
-
-		ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
-						coda9_jpeg_irq_handler,
-						IRQF_ONESHOT, CODA_NAME "-jpeg",
-						dev);
-		if (ret < 0) {
-			dev_err(&pdev->dev, "failed to request jpeg irq\n");
-			return ret;
-		}
-	}
-
-	dev->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev,
-							      NULL);
-	if (IS_ERR(dev->rstc)) {
-		ret = PTR_ERR(dev->rstc);
-		dev_err(&pdev->dev, "failed get reset control: %d\n", ret);
-		return ret;
-	}
-
-	/* Get IRAM pool from device tree */
-	pool = of_gen_pool_get(np, "iram", 0);
-	if (!pool) {
-		dev_err(&pdev->dev, "iram pool not available\n");
-		return -ENOMEM;
-	}
-	dev->iram_pool = pool;
-
-	/* Get vdoa_data if supported by the platform */
-	dev->vdoa = coda_get_vdoa_data();
-	if (PTR_ERR(dev->vdoa) == -EPROBE_DEFER)
-		return -EPROBE_DEFER;
-
-	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
-	if (ret)
-		return ret;
-
-	ratelimit_default_init(&dev->mb_err_rs);
-	mutex_init(&dev->dev_mutex);
-	mutex_init(&dev->coda_mutex);
-	ida_init(&dev->ida);
-
-	dev->debugfs_root = debugfs_create_dir("coda", NULL);
-
-	/* allocate auxiliary per-device buffers for the BIT processor */
-	if (dev->devtype->product == CODA_DX6) {
-		ret = coda_alloc_aux_buf(dev, &dev->workbuf,
-					 dev->devtype->workbuf_size, "workbuf",
-					 dev->debugfs_root);
-		if (ret < 0)
-			goto err_v4l2_register;
-	}
-
-	if (dev->devtype->tempbuf_size) {
-		ret = coda_alloc_aux_buf(dev, &dev->tempbuf,
-					 dev->devtype->tempbuf_size, "tempbuf",
-					 dev->debugfs_root);
-		if (ret < 0)
-			goto err_v4l2_register;
-	}
-
-	dev->iram.size = dev->devtype->iram_size;
-	dev->iram.vaddr = gen_pool_dma_alloc(dev->iram_pool, dev->iram.size,
-					     &dev->iram.paddr);
-	if (!dev->iram.vaddr) {
-		dev_warn(&pdev->dev, "unable to alloc iram\n");
-	} else {
-		memset(dev->iram.vaddr, 0, dev->iram.size);
-		dev->iram.blob.data = dev->iram.vaddr;
-		dev->iram.blob.size = dev->iram.size;
-		dev->iram.dentry = debugfs_create_blob("iram", 0444,
-						       dev->debugfs_root,
-						       &dev->iram.blob);
-	}
-
-	dev->workqueue = alloc_workqueue("coda", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
-	if (!dev->workqueue) {
-		dev_err(&pdev->dev, "unable to alloc workqueue\n");
-		ret = -ENOMEM;
-		goto err_v4l2_register;
-	}
-
-	platform_set_drvdata(pdev, dev);
-
-	/*
-	 * Start activated so we can directly call coda_hw_init in
-	 * coda_fw_callback regardless of whether CONFIG_PM is
-	 * enabled or whether the device is associated with a PM domain.
-	 */
-	pm_runtime_get_noresume(&pdev->dev);
-	pm_runtime_set_active(&pdev->dev);
-	pm_runtime_enable(&pdev->dev);
-
-	ret = coda_firmware_request(dev);
-	if (ret)
-		goto err_alloc_workqueue;
-	return 0;
-
-err_alloc_workqueue:
-	pm_runtime_disable(&pdev->dev);
-	pm_runtime_put_noidle(&pdev->dev);
-	destroy_workqueue(dev->workqueue);
-err_v4l2_register:
-	v4l2_device_unregister(&dev->v4l2_dev);
-	return ret;
-}
-
-static int coda_remove(struct platform_device *pdev)
-{
-	struct coda_dev *dev = platform_get_drvdata(pdev);
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(dev->vfd); i++) {
-		if (video_get_drvdata(&dev->vfd[i]))
-			video_unregister_device(&dev->vfd[i]);
-	}
-	if (dev->m2m_dev)
-		v4l2_m2m_release(dev->m2m_dev);
-	pm_runtime_disable(&pdev->dev);
-	v4l2_device_unregister(&dev->v4l2_dev);
-	destroy_workqueue(dev->workqueue);
-	if (dev->iram.vaddr)
-		gen_pool_free(dev->iram_pool, (unsigned long)dev->iram.vaddr,
-			      dev->iram.size);
-	coda_free_aux_buf(dev, &dev->codebuf);
-	coda_free_aux_buf(dev, &dev->tempbuf);
-	coda_free_aux_buf(dev, &dev->workbuf);
-	debugfs_remove_recursive(dev->debugfs_root);
-	ida_destroy(&dev->ida);
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int coda_runtime_resume(struct device *dev)
-{
-	struct coda_dev *cdev = dev_get_drvdata(dev);
-	int ret = 0;
-
-	if (dev->pm_domain && cdev->codebuf.vaddr) {
-		ret = coda_hw_init(cdev);
-		if (ret)
-			v4l2_err(&cdev->v4l2_dev, "HW initialization failed\n");
-	}
-
-	return ret;
-}
-#endif
-
-static const struct dev_pm_ops coda_pm_ops = {
-	SET_RUNTIME_PM_OPS(NULL, coda_runtime_resume, NULL)
-};
-
-static struct platform_driver coda_driver = {
-	.probe	= coda_probe,
-	.remove	= coda_remove,
-	.driver	= {
-		.name	= CODA_NAME,
-		.of_match_table = coda_dt_ids,
-		.pm	= &coda_pm_ops,
-	},
-};
-
-module_platform_driver(coda_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
-MODULE_DESCRIPTION("Coda multi-standard codec V4L2 driver");
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-gdi.c b/drivers/media/platform/chips-media/coda-gdi.c
--- a/drivers/media/platform/chips-media/coda-gdi.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda-gdi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,146 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Coda multi-standard codec IP
- *
- * Copyright (C) 2014 Philipp Zabel, Pengutronix
- */
-
-#include <linux/bitops.h>
-#include "coda.h"
-
-#define XY2_INVERT	BIT(7)
-#define XY2_ZERO	BIT(6)
-#define XY2_TB_XOR	BIT(5)
-#define XY2_XYSEL	BIT(4)
-#define XY2_Y		(1 << 4)
-#define XY2_X		(0 << 4)
-
-#define XY2(luma_sel, luma_bit, chroma_sel, chroma_bit) \
-	(((XY2_##luma_sel) | (luma_bit)) << 8 | \
-	 (XY2_##chroma_sel) | (chroma_bit))
-
-static const u16 xy2ca_zero_map[16] = {
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-};
-
-static const u16 xy2ca_tiled_map[16] = {
-	XY2(Y,    0, Y,    0),
-	XY2(Y,    1, Y,    1),
-	XY2(Y,    2, Y,    2),
-	XY2(Y,    3, X,    3),
-	XY2(X,    3, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-	XY2(ZERO, 0, ZERO, 0),
-};
-
-/*
- * RA[15:0], CA[15:8] are hardwired to contain the 24-bit macroblock
- * start offset (macroblock size is 16x16 for luma, 16x8 for chroma).
- * Bits CA[4:0] are set using XY2CA above. BA[3:0] seems to be unused.
- */
-
-#define RBC_CA		(0 << 4)
-#define RBC_BA		(1 << 4)
-#define RBC_RA		(2 << 4)
-#define RBC_ZERO	(3 << 4)
-
-#define RBC(luma_sel, luma_bit, chroma_sel, chroma_bit) \
-	(((RBC_##luma_sel) | (luma_bit)) << 6 | \
-	 (RBC_##chroma_sel) | (chroma_bit))
-
-static const u16 rbc2axi_tiled_map[32] = {
-	RBC(ZERO, 0, ZERO, 0),
-	RBC(ZERO, 0, ZERO, 0),
-	RBC(ZERO, 0, ZERO, 0),
-	RBC(CA,   0, CA,   0),
-	RBC(CA,   1, CA,   1),
-	RBC(CA,   2, CA,   2),
-	RBC(CA,   3, CA,   3),
-	RBC(CA,   4, CA,   8),
-	RBC(CA,   8, CA,   9),
-	RBC(CA,   9, CA,  10),
-	RBC(CA,  10, CA,  11),
-	RBC(CA,  11, CA,  12),
-	RBC(CA,  12, CA,  13),
-	RBC(CA,  13, CA,  14),
-	RBC(CA,  14, CA,  15),
-	RBC(CA,  15, RA,   0),
-	RBC(RA,   0, RA,   1),
-	RBC(RA,   1, RA,   2),
-	RBC(RA,   2, RA,   3),
-	RBC(RA,   3, RA,   4),
-	RBC(RA,   4, RA,   5),
-	RBC(RA,   5, RA,   6),
-	RBC(RA,   6, RA,   7),
-	RBC(RA,   7, RA,   8),
-	RBC(RA,   8, RA,   9),
-	RBC(RA,   9, RA,  10),
-	RBC(RA,  10, RA,  11),
-	RBC(RA,  11, RA,  12),
-	RBC(RA,  12, RA,  13),
-	RBC(RA,  13, RA,  14),
-	RBC(RA,  14, RA,  15),
-	RBC(RA,  15, ZERO, 0),
-};
-
-void coda_set_gdi_regs(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	const u16 *xy2ca_map;
-	u32 xy2rbc_config;
-	int i;
-
-	switch (ctx->tiled_map_type) {
-	case GDI_LINEAR_FRAME_MAP:
-	default:
-		xy2ca_map = xy2ca_zero_map;
-		xy2rbc_config = 0;
-		break;
-	case GDI_TILED_FRAME_MB_RASTER_MAP:
-		xy2ca_map = xy2ca_tiled_map;
-		xy2rbc_config = CODA9_XY2RBC_TILED_MAP |
-				CODA9_XY2RBC_CA_INC_HOR |
-				(16 - 1) << 12 | (8 - 1) << 4;
-		break;
-	}
-
-	for (i = 0; i < 16; i++)
-		coda_write(dev, xy2ca_map[i],
-				CODA9_GDI_XY2_CAS_0 + 4 * i);
-	for (i = 0; i < 4; i++)
-		coda_write(dev, XY2(ZERO, 0, ZERO, 0),
-				CODA9_GDI_XY2_BA_0 + 4 * i);
-	for (i = 0; i < 16; i++)
-		coda_write(dev, XY2(ZERO, 0, ZERO, 0),
-				CODA9_GDI_XY2_RAS_0 + 4 * i);
-	coda_write(dev, xy2rbc_config, CODA9_GDI_XY2_RBC_CONFIG);
-	if (xy2rbc_config) {
-		for (i = 0; i < 32; i++)
-			coda_write(dev, rbc2axi_tiled_map[i],
-					CODA9_GDI_RBC2_AXI_0 + 4 * i);
-	}
-}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda.h b/drivers/media/platform/chips-media/coda.h
--- a/drivers/media/platform/chips-media/coda.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,403 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Coda multi-standard codec IP
- *
- * Copyright (C) 2012 Vista Silicon S.L.
- *    Javier Martin, <javier.martin@vista-silicon.com>
- *    Xavier Duret
- * Copyright (C) 2012-2014 Philipp Zabel, Pengutronix
- */
-
-#ifndef __CODA_H__
-#define __CODA_H__
-
-#include <linux/debugfs.h>
-#include <linux/idr.h>
-#include <linux/irqreturn.h>
-#include <linux/mutex.h>
-#include <linux/kfifo.h>
-#include <linux/videodev2.h>
-#include <linux/ratelimit.h>
-
-#include <media/v4l2-ctrls.h>
-#include <media/v4l2-device.h>
-#include <media/v4l2-fh.h>
-#include <media/videobuf2-v4l2.h>
-
-#include "coda_regs.h"
-
-#define CODA_MAX_FRAMEBUFFERS	19
-#define FMO_SLICE_SAVE_BUF_SIZE	(32)
-
-/*
- * This control allows applications to read the per-stream
- * (i.e. per-context) Macroblocks Error Count. This value
- * is CODA specific.
- */
-#define V4L2_CID_CODA_MB_ERR_CNT (V4L2_CID_USER_CODA_BASE + 0)
-
-enum {
-	V4L2_M2M_SRC = 0,
-	V4L2_M2M_DST = 1,
-};
-
-enum coda_inst_type {
-	CODA_INST_ENCODER,
-	CODA_INST_DECODER,
-};
-
-enum coda_product {
-	CODA_DX6 = 0xf001,
-	CODA_HX4 = 0xf00a,
-	CODA_7541 = 0xf012,
-	CODA_960 = 0xf020,
-};
-
-struct coda_video_device;
-
-struct coda_devtype {
-	char			*firmware[3];
-	enum coda_product	product;
-	const struct coda_codec	*codecs;
-	unsigned int		num_codecs;
-	const struct coda_video_device **vdevs;
-	unsigned int		num_vdevs;
-	size_t			workbuf_size;
-	size_t			tempbuf_size;
-	size_t			iram_size;
-};
-
-struct coda_aux_buf {
-	void			*vaddr;
-	dma_addr_t		paddr;
-	u32			size;
-	struct debugfs_blob_wrapper blob;
-	struct dentry		*dentry;
-};
-
-struct coda_dev {
-	struct v4l2_device	v4l2_dev;
-	struct video_device	vfd[6];
-	struct device		*dev;
-	const struct coda_devtype *devtype;
-	int			firmware;
-	struct vdoa_data	*vdoa;
-
-	void __iomem		*regs_base;
-	struct clk		*clk_per;
-	struct clk		*clk_ahb;
-	struct reset_control	*rstc;
-
-	struct coda_aux_buf	codebuf;
-	struct coda_aux_buf	tempbuf;
-	struct coda_aux_buf	workbuf;
-	struct gen_pool		*iram_pool;
-	struct coda_aux_buf	iram;
-
-	struct mutex		dev_mutex;
-	struct mutex		coda_mutex;
-	struct workqueue_struct	*workqueue;
-	struct v4l2_m2m_dev	*m2m_dev;
-	struct ida		ida;
-	struct dentry		*debugfs_root;
-	struct ratelimit_state	mb_err_rs;
-};
-
-struct coda_codec {
-	u32 mode;
-	u32 src_fourcc;
-	u32 dst_fourcc;
-	u32 max_w;
-	u32 max_h;
-};
-
-struct coda_huff_tab;
-
-struct coda_params {
-	u8			rot_mode;
-	u8			h264_intra_qp;
-	u8			h264_inter_qp;
-	u8			h264_min_qp;
-	u8			h264_max_qp;
-	u8			h264_disable_deblocking_filter_idc;
-	s8			h264_slice_alpha_c0_offset_div2;
-	s8			h264_slice_beta_offset_div2;
-	bool			h264_constrained_intra_pred_flag;
-	s8			h264_chroma_qp_index_offset;
-	u8			h264_profile_idc;
-	u8			h264_level_idc;
-	u8			mpeg2_profile_idc;
-	u8			mpeg2_level_idc;
-	u8			mpeg4_intra_qp;
-	u8			mpeg4_inter_qp;
-	u8			gop_size;
-	int			intra_refresh;
-	enum v4l2_jpeg_chroma_subsampling jpeg_chroma_subsampling;
-	u8			jpeg_quality;
-	u8			jpeg_restart_interval;
-	u8			*jpeg_qmat_tab[3];
-	int			jpeg_qmat_index[3];
-	int			jpeg_huff_dc_index[3];
-	int			jpeg_huff_ac_index[3];
-	u32			*jpeg_huff_data;
-	struct coda_huff_tab	*jpeg_huff_tab;
-	int			codec_mode;
-	int			codec_mode_aux;
-	enum v4l2_mpeg_video_multi_slice_mode slice_mode;
-	u32			framerate;
-	u16			bitrate;
-	u16			vbv_delay;
-	u32			vbv_size;
-	u32			slice_max_bits;
-	u32			slice_max_mb;
-	bool			force_ipicture;
-	bool			gop_size_changed;
-	bool			bitrate_changed;
-	bool			framerate_changed;
-	bool			h264_intra_qp_changed;
-	bool			intra_refresh_changed;
-	bool			slice_mode_changed;
-	bool			frame_rc_enable;
-	bool			mb_rc_enable;
-};
-
-struct coda_buffer_meta {
-	struct list_head	list;
-	u32			sequence;
-	struct v4l2_timecode	timecode;
-	u64			timestamp;
-	unsigned int		start;
-	unsigned int		end;
-	bool			last;
-};
-
-/* Per-queue, driver-specific private data */
-struct coda_q_data {
-	unsigned int		width;
-	unsigned int		height;
-	unsigned int		bytesperline;
-	unsigned int		sizeimage;
-	unsigned int		fourcc;
-	struct v4l2_rect	rect;
-};
-
-struct coda_iram_info {
-	u32		axi_sram_use;
-	phys_addr_t	buf_bit_use;
-	phys_addr_t	buf_ip_ac_dc_use;
-	phys_addr_t	buf_dbk_y_use;
-	phys_addr_t	buf_dbk_c_use;
-	phys_addr_t	buf_ovl_use;
-	phys_addr_t	buf_btp_use;
-	phys_addr_t	search_ram_paddr;
-	int		search_ram_size;
-	int		remaining;
-	phys_addr_t	next_paddr;
-};
-
-#define GDI_LINEAR_FRAME_MAP 0
-#define GDI_TILED_FRAME_MB_RASTER_MAP 1
-
-struct coda_ctx;
-
-struct coda_context_ops {
-	int (*queue_init)(void *priv, struct vb2_queue *src_vq,
-			  struct vb2_queue *dst_vq);
-	int (*reqbufs)(struct coda_ctx *ctx, struct v4l2_requestbuffers *rb);
-	int (*start_streaming)(struct coda_ctx *ctx);
-	int (*prepare_run)(struct coda_ctx *ctx);
-	void (*finish_run)(struct coda_ctx *ctx);
-	void (*run_timeout)(struct coda_ctx *ctx);
-	void (*seq_init_work)(struct work_struct *work);
-	void (*seq_end_work)(struct work_struct *work);
-	void (*release)(struct coda_ctx *ctx);
-};
-
-struct coda_internal_frame {
-	struct coda_aux_buf		buf;
-	struct coda_buffer_meta		meta;
-	u32				type;
-	u32				error;
-};
-
-struct coda_ctx {
-	struct coda_dev			*dev;
-	struct mutex			buffer_mutex;
-	struct work_struct		pic_run_work;
-	struct work_struct		seq_init_work;
-	struct work_struct		seq_end_work;
-	struct completion		completion;
-	const struct coda_video_device	*cvd;
-	const struct coda_context_ops	*ops;
-	int				aborting;
-	int				initialized;
-	int				streamon_out;
-	int				streamon_cap;
-	u32				qsequence;
-	u32				osequence;
-	u32				sequence_offset;
-	struct coda_q_data		q_data[2];
-	enum coda_inst_type		inst_type;
-	const struct coda_codec		*codec;
-	enum v4l2_colorspace		colorspace;
-	enum v4l2_xfer_func		xfer_func;
-	enum v4l2_ycbcr_encoding	ycbcr_enc;
-	enum v4l2_quantization		quantization;
-	struct coda_params		params;
-	struct v4l2_ctrl_handler	ctrls;
-	struct v4l2_ctrl		*h264_profile_ctrl;
-	struct v4l2_ctrl		*h264_level_ctrl;
-	struct v4l2_ctrl		*mpeg2_profile_ctrl;
-	struct v4l2_ctrl		*mpeg2_level_ctrl;
-	struct v4l2_ctrl		*mpeg4_profile_ctrl;
-	struct v4l2_ctrl		*mpeg4_level_ctrl;
-	struct v4l2_ctrl		*mb_err_cnt_ctrl;
-	struct v4l2_fh			fh;
-	int				gopcounter;
-	int				runcounter;
-	int				jpeg_ecs_offset;
-	char				vpu_header[3][64];
-	int				vpu_header_size[3];
-	struct kfifo			bitstream_fifo;
-	struct mutex			bitstream_mutex;
-	struct coda_aux_buf		bitstream;
-	bool				hold;
-	struct coda_aux_buf		parabuf;
-	struct coda_aux_buf		psbuf;
-	struct coda_aux_buf		slicebuf;
-	struct coda_internal_frame	internal_frames[CODA_MAX_FRAMEBUFFERS];
-	struct list_head		buffer_meta_list;
-	spinlock_t			buffer_meta_lock;
-	int				num_metas;
-	unsigned int			first_frame_sequence;
-	struct coda_aux_buf		workbuf;
-	int				num_internal_frames;
-	int				idx;
-	int				reg_idx;
-	struct coda_iram_info		iram_info;
-	int				tiled_map_type;
-	u32				bit_stream_param;
-	u32				frm_dis_flg;
-	u32				frame_mem_ctrl;
-	u32				para_change;
-	int				display_idx;
-	struct dentry			*debugfs_entry;
-	bool				use_bit;
-	bool				use_vdoa;
-	struct vdoa_ctx			*vdoa;
-	/*
-	 * wakeup mutex used to serialize encoder stop command and finish_run,
-	 * ensures that finish_run always either flags the last returned buffer
-	 * or wakes up the capture queue to signal EOS afterwards.
-	 */
-	struct mutex			wakeup_mutex;
-};
-
-extern int coda_debug;
-
-#define coda_dbg(level, ctx, fmt, arg...)				\
-	do {								\
-		if (coda_debug >= (level))				\
-			v4l2_dbg((level), coda_debug, &(ctx)->dev->v4l2_dev, \
-			 "%u: " fmt, (ctx)->idx, ##arg);		\
-	} while (0)
-
-void coda_write(struct coda_dev *dev, u32 data, u32 reg);
-unsigned int coda_read(struct coda_dev *dev, u32 reg);
-void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
-		     struct vb2_v4l2_buffer *buf, unsigned int reg_y);
-
-int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf,
-		       size_t size, const char *name, struct dentry *parent);
-void coda_free_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf);
-
-int coda_encoder_queue_init(void *priv, struct vb2_queue *src_vq,
-			    struct vb2_queue *dst_vq);
-int coda_decoder_queue_init(void *priv, struct vb2_queue *src_vq,
-			    struct vb2_queue *dst_vq);
-
-int coda_hw_reset(struct coda_ctx *ctx);
-
-void coda_fill_bitstream(struct coda_ctx *ctx, struct list_head *buffer_list);
-
-void coda_set_gdi_regs(struct coda_ctx *ctx);
-
-static inline struct coda_q_data *get_q_data(struct coda_ctx *ctx,
-					     enum v4l2_buf_type type)
-{
-	switch (type) {
-	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-		return &(ctx->q_data[V4L2_M2M_SRC]);
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		return &(ctx->q_data[V4L2_M2M_DST]);
-	default:
-		return NULL;
-	}
-}
-
-const char *coda_product_name(int product);
-
-int coda_check_firmware(struct coda_dev *dev);
-
-static inline unsigned int coda_get_bitstream_payload(struct coda_ctx *ctx)
-{
-	return kfifo_len(&ctx->bitstream_fifo);
-}
-
-/*
- * The bitstream prefetcher needs to read at least 2 256 byte periods past
- * the desired bitstream position for all data to reach the decoder.
- */
-static inline bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx,
-						 unsigned int pos)
-{
-	return (int)(ctx->bitstream_fifo.kfifo.in - ALIGN(pos, 256)) > 512;
-}
-
-bool coda_bitstream_can_fetch_past(struct coda_ctx *ctx, unsigned int pos);
-int coda_bitstream_flush(struct coda_ctx *ctx);
-
-void coda_bit_stream_end_flag(struct coda_ctx *ctx);
-
-void coda_m2m_buf_done(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
-		       enum vb2_buffer_state state);
-
-int coda_h264_filler_nal(int size, char *p);
-int coda_h264_padding(int size, char *p);
-int coda_h264_profile(int profile_idc);
-int coda_h264_level(int level_idc);
-int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb);
-int coda_h264_sps_fixup(struct coda_ctx *ctx, int width, int height, char *buf,
-			int *size, int max_size);
-
-int coda_mpeg2_profile(int profile_idc);
-int coda_mpeg2_level(int level_idc);
-u32 coda_mpeg2_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size);
-int coda_mpeg4_profile(int profile_idc);
-int coda_mpeg4_level(int level_idc);
-u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size);
-
-void coda_update_profile_level_ctrls(struct coda_ctx *ctx, u8 profile_idc,
-				     u8 level_idc);
-
-static inline int coda_jpeg_scale(int src, int dst)
-{
-	return (dst <= src / 8) ? 3 :
-	       (dst <= src / 4) ? 2 :
-	       (dst <= src / 2) ? 1 : 0;
-}
-
-bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb);
-int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb);
-int coda_jpeg_write_tables(struct coda_ctx *ctx);
-void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality);
-
-extern const struct coda_context_ops coda_bit_encode_ops;
-extern const struct coda_context_ops coda_bit_decode_ops;
-extern const struct coda_context_ops coda9_jpeg_encode_ops;
-extern const struct coda_context_ops coda9_jpeg_decode_ops;
-
-irqreturn_t coda_irq_handler(int irq, void *data);
-irqreturn_t coda9_jpeg_irq_handler(int irq, void *data);
-
-#endif /* __CODA_H__ */
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-h264.c b/drivers/media/platform/chips-media/coda-h264.c
--- a/drivers/media/platform/chips-media/coda-h264.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda-h264.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,429 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Coda multi-standard codec IP - H.264 helper functions
- *
- * Copyright (C) 2012 Vista Silicon S.L.
- *    Javier Martin, <javier.martin@vista-silicon.com>
- *    Xavier Duret
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/videodev2.h>
-
-#include "coda.h"
-
-static const u8 coda_filler_size[8] = { 0, 7, 14, 13, 12, 11, 10, 9 };
-
-static const u8 *coda_find_nal_header(const u8 *buf, const u8 *end)
-{
-	u32 val = 0xffffffff;
-
-	do {
-		val = val << 8 | *buf++;
-		if (buf >= end)
-			return NULL;
-	} while (val != 0x00000001);
-
-	return buf;
-}
-
-int coda_sps_parse_profile(struct coda_ctx *ctx, struct vb2_buffer *vb)
-{
-	const u8 *buf = vb2_plane_vaddr(vb, 0);
-	const u8 *end = buf + vb2_get_plane_payload(vb, 0);
-
-	/* Find SPS header */
-	do {
-		buf = coda_find_nal_header(buf, end);
-		if (!buf)
-			return -EINVAL;
-	} while ((*buf++ & 0x1f) != 0x7);
-
-	ctx->params.h264_profile_idc = buf[0];
-	ctx->params.h264_level_idc = buf[2];
-
-	return 0;
-}
-
-int coda_h264_filler_nal(int size, char *p)
-{
-	if (size < 6)
-		return -EINVAL;
-
-	p[0] = 0x00;
-	p[1] = 0x00;
-	p[2] = 0x00;
-	p[3] = 0x01;
-	p[4] = 0x0c;
-	memset(p + 5, 0xff, size - 6);
-	/* Add rbsp stop bit and trailing at the end */
-	p[size - 1] = 0x80;
-
-	return 0;
-}
-
-int coda_h264_padding(int size, char *p)
-{
-	int nal_size;
-	int diff;
-
-	diff = size - (size & ~0x7);
-	if (diff == 0)
-		return 0;
-
-	nal_size = coda_filler_size[diff];
-	coda_h264_filler_nal(nal_size, p);
-
-	return nal_size;
-}
-
-int coda_h264_profile(int profile_idc)
-{
-	switch (profile_idc) {
-	case 66: return V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
-	case 77: return V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
-	case 88: return V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED;
-	case 100: return V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
-	default: return -EINVAL;
-	}
-}
-
-int coda_h264_level(int level_idc)
-{
-	switch (level_idc) {
-	case 10: return V4L2_MPEG_VIDEO_H264_LEVEL_1_0;
-	case 9:  return V4L2_MPEG_VIDEO_H264_LEVEL_1B;
-	case 11: return V4L2_MPEG_VIDEO_H264_LEVEL_1_1;
-	case 12: return V4L2_MPEG_VIDEO_H264_LEVEL_1_2;
-	case 13: return V4L2_MPEG_VIDEO_H264_LEVEL_1_3;
-	case 20: return V4L2_MPEG_VIDEO_H264_LEVEL_2_0;
-	case 21: return V4L2_MPEG_VIDEO_H264_LEVEL_2_1;
-	case 22: return V4L2_MPEG_VIDEO_H264_LEVEL_2_2;
-	case 30: return V4L2_MPEG_VIDEO_H264_LEVEL_3_0;
-	case 31: return V4L2_MPEG_VIDEO_H264_LEVEL_3_1;
-	case 32: return V4L2_MPEG_VIDEO_H264_LEVEL_3_2;
-	case 40: return V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
-	case 41: return V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
-	case 42: return V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
-	case 50: return V4L2_MPEG_VIDEO_H264_LEVEL_5_0;
-	case 51: return V4L2_MPEG_VIDEO_H264_LEVEL_5_1;
-	default: return -EINVAL;
-	}
-}
-
-struct rbsp {
-	char *buf;
-	int size;
-	int pos;
-};
-
-static inline int rbsp_read_bit(struct rbsp *rbsp)
-{
-	int shift = 7 - (rbsp->pos % 8);
-	int ofs = rbsp->pos++ / 8;
-
-	if (ofs >= rbsp->size)
-		return -EINVAL;
-
-	return (rbsp->buf[ofs] >> shift) & 1;
-}
-
-static inline int rbsp_write_bit(struct rbsp *rbsp, int bit)
-{
-	int shift = 7 - (rbsp->pos % 8);
-	int ofs = rbsp->pos++ / 8;
-
-	if (ofs >= rbsp->size)
-		return -EINVAL;
-
-	rbsp->buf[ofs] &= ~(1 << shift);
-	rbsp->buf[ofs] |= bit << shift;
-
-	return 0;
-}
-
-static inline int rbsp_read_bits(struct rbsp *rbsp, int num, int *val)
-{
-	int i, ret;
-	int tmp = 0;
-
-	if (num > 32)
-		return -EINVAL;
-
-	for (i = 0; i < num; i++) {
-		ret = rbsp_read_bit(rbsp);
-		if (ret < 0)
-			return ret;
-		tmp |= ret << (num - i - 1);
-	}
-
-	if (val)
-		*val = tmp;
-
-	return 0;
-}
-
-static int rbsp_write_bits(struct rbsp *rbsp, int num, int value)
-{
-	int ret;
-
-	while (num--) {
-		ret = rbsp_write_bit(rbsp, (value >> num) & 1);
-		if (ret)
-			return ret;
-	}
-
-	return 0;
-}
-
-static int rbsp_read_uev(struct rbsp *rbsp, unsigned int *val)
-{
-	int leading_zero_bits = 0;
-	unsigned int tmp = 0;
-	int ret;
-
-	while ((ret = rbsp_read_bit(rbsp)) == 0)
-		leading_zero_bits++;
-	if (ret < 0)
-		return ret;
-
-	if (leading_zero_bits > 0) {
-		ret = rbsp_read_bits(rbsp, leading_zero_bits, &tmp);
-		if (ret)
-			return ret;
-	}
-
-	if (val)
-		*val = (1 << leading_zero_bits) - 1 + tmp;
-
-	return 0;
-}
-
-static int rbsp_write_uev(struct rbsp *rbsp, unsigned int value)
-{
-	int i;
-	int ret;
-	int tmp = value + 1;
-	int leading_zero_bits = fls(tmp) - 1;
-
-	for (i = 0; i < leading_zero_bits; i++) {
-		ret = rbsp_write_bit(rbsp, 0);
-		if (ret)
-			return ret;
-	}
-
-	return rbsp_write_bits(rbsp, leading_zero_bits + 1, tmp);
-}
-
-static int rbsp_read_sev(struct rbsp *rbsp, int *val)
-{
-	unsigned int tmp;
-	int ret;
-
-	ret = rbsp_read_uev(rbsp, &tmp);
-	if (ret)
-		return ret;
-
-	if (val) {
-		if (tmp & 1)
-			*val = (tmp + 1) / 2;
-		else
-			*val = -(tmp / 2);
-	}
-
-	return 0;
-}
-
-/**
- * coda_h264_sps_fixup - fixes frame cropping values in h.264 SPS
- * @ctx: encoder context
- * @width: visible width
- * @height: visible height
- * @buf: buffer containing h.264 SPS RBSP, starting with NAL header
- * @size: modified RBSP size return value
- * @max_size: available size in buf
- *
- * Rewrites the frame cropping values in an h.264 SPS RBSP correctly for the
- * given visible width and height.
- */
-int coda_h264_sps_fixup(struct coda_ctx *ctx, int width, int height, char *buf,
-			int *size, int max_size)
-{
-	int profile_idc;
-	unsigned int pic_order_cnt_type;
-	int pic_width_in_mbs_minus1, pic_height_in_map_units_minus1;
-	int frame_mbs_only_flag, frame_cropping_flag;
-	int vui_parameters_present_flag;
-	unsigned int crop_right, crop_bottom;
-	struct rbsp sps;
-	int pos;
-	int ret;
-
-	if (*size < 8 || *size >= max_size)
-		return -EINVAL;
-
-	sps.buf = buf + 5; /* Skip NAL header */
-	sps.size = *size - 5;
-
-	profile_idc = sps.buf[0];
-	/* Skip constraint_set[0-5]_flag, reserved_zero_2bits */
-	/* Skip level_idc */
-	sps.pos = 24;
-
-	/* seq_parameter_set_id */
-	ret = rbsp_read_uev(&sps, NULL);
-	if (ret)
-		return ret;
-
-	if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 ||
-	    profile_idc == 244 || profile_idc == 44 || profile_idc == 83 ||
-	    profile_idc == 86 || profile_idc == 118 || profile_idc == 128 ||
-	    profile_idc == 138 || profile_idc == 139 || profile_idc == 134 ||
-	    profile_idc == 135) {
-		dev_err(ctx->fh.vdev->dev_parent,
-			"%s: Handling profile_idc %d not implemented\n",
-			__func__, profile_idc);
-		return -EINVAL;
-	}
-
-	/* log2_max_frame_num_minus4 */
-	ret = rbsp_read_uev(&sps, NULL);
-	if (ret)
-		return ret;
-
-	ret = rbsp_read_uev(&sps, &pic_order_cnt_type);
-	if (ret)
-		return ret;
-
-	if (pic_order_cnt_type == 0) {
-		/* log2_max_pic_order_cnt_lsb_minus4 */
-		ret = rbsp_read_uev(&sps, NULL);
-		if (ret)
-			return ret;
-	} else if (pic_order_cnt_type == 1) {
-		unsigned int i, num_ref_frames_in_pic_order_cnt_cycle;
-
-		/* delta_pic_order_always_zero_flag */
-		ret = rbsp_read_bit(&sps);
-		if (ret < 0)
-			return ret;
-		/* offset_for_non_ref_pic */
-		ret = rbsp_read_sev(&sps, NULL);
-		if (ret)
-			return ret;
-		/* offset_for_top_to_bottom_field */
-		ret = rbsp_read_sev(&sps, NULL);
-		if (ret)
-			return ret;
-
-		ret = rbsp_read_uev(&sps,
-				    &num_ref_frames_in_pic_order_cnt_cycle);
-		if (ret)
-			return ret;
-		for (i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
-			/* offset_for_ref_frame */
-			ret = rbsp_read_sev(&sps, NULL);
-			if (ret)
-				return ret;
-		}
-	}
-
-	/* max_num_ref_frames */
-	ret = rbsp_read_uev(&sps, NULL);
-	if (ret)
-		return ret;
-
-	/* gaps_in_frame_num_value_allowed_flag */
-	ret = rbsp_read_bit(&sps);
-	if (ret < 0)
-		return ret;
-	ret = rbsp_read_uev(&sps, &pic_width_in_mbs_minus1);
-	if (ret)
-		return ret;
-	ret = rbsp_read_uev(&sps, &pic_height_in_map_units_minus1);
-	if (ret)
-		return ret;
-	frame_mbs_only_flag = ret = rbsp_read_bit(&sps);
-	if (ret < 0)
-		return ret;
-	if (!frame_mbs_only_flag) {
-		/* mb_adaptive_frame_field_flag */
-		ret = rbsp_read_bit(&sps);
-		if (ret < 0)
-			return ret;
-	}
-	/* direct_8x8_inference_flag */
-	ret = rbsp_read_bit(&sps);
-	if (ret < 0)
-		return ret;
-
-	/* Mark position of the frame cropping flag */
-	pos = sps.pos;
-	frame_cropping_flag = ret = rbsp_read_bit(&sps);
-	if (ret < 0)
-		return ret;
-	if (frame_cropping_flag) {
-		unsigned int crop_left, crop_top;
-
-		ret = rbsp_read_uev(&sps, &crop_left);
-		if (ret)
-			return ret;
-		ret = rbsp_read_uev(&sps, &crop_right);
-		if (ret)
-			return ret;
-		ret = rbsp_read_uev(&sps, &crop_top);
-		if (ret)
-			return ret;
-		ret = rbsp_read_uev(&sps, &crop_bottom);
-		if (ret)
-			return ret;
-	}
-	vui_parameters_present_flag = ret = rbsp_read_bit(&sps);
-	if (ret < 0)
-		return ret;
-	if (vui_parameters_present_flag) {
-		dev_err(ctx->fh.vdev->dev_parent,
-			"%s: Handling vui_parameters not implemented\n",
-			__func__);
-		return -EINVAL;
-	}
-
-	crop_right = round_up(width, 16) - width;
-	crop_bottom = round_up(height, 16) - height;
-	crop_right /= 2;
-	if (frame_mbs_only_flag)
-		crop_bottom /= 2;
-	else
-		crop_bottom /= 4;
-
-
-	sps.size = max_size - 5;
-	sps.pos = pos;
-	frame_cropping_flag = 1;
-	ret = rbsp_write_bit(&sps, frame_cropping_flag);
-	if (ret)
-		return ret;
-	ret = rbsp_write_uev(&sps, 0); /* crop_left */
-	if (ret)
-		return ret;
-	ret = rbsp_write_uev(&sps, crop_right);
-	if (ret)
-		return ret;
-	ret = rbsp_write_uev(&sps, 0); /* crop_top */
-	if (ret)
-		return ret;
-	ret = rbsp_write_uev(&sps, crop_bottom);
-	if (ret)
-		return ret;
-	ret = rbsp_write_bit(&sps, 0); /* vui_parameters_present_flag */
-	if (ret)
-		return ret;
-	ret = rbsp_write_bit(&sps, 1);
-	if (ret)
-		return ret;
-
-	*size = 5 + DIV_ROUND_UP(sps.pos, 8);
-
-	return 0;
-}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-jpeg.c b/drivers/media/platform/chips-media/coda-jpeg.c
--- a/drivers/media/platform/chips-media/coda-jpeg.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda-jpeg.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1547 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Coda multi-standard codec IP - JPEG support functions
- *
- * Copyright (C) 2014 Philipp Zabel, Pengutronix
- */
-
-#include <asm/unaligned.h>
-#include <linux/irqreturn.h>
-#include <linux/kernel.h>
-#include <linux/ktime.h>
-#include <linux/slab.h>
-#include <linux/swab.h>
-#include <linux/videodev2.h>
-
-#include <media/v4l2-common.h>
-#include <media/v4l2-fh.h>
-#include <media/v4l2-jpeg.h>
-#include <media/v4l2-mem2mem.h>
-#include <media/videobuf2-core.h>
-#include <media/videobuf2-dma-contig.h>
-
-#include "coda.h"
-#include "trace.h"
-
-#define SOI_MARKER	0xffd8
-#define APP9_MARKER	0xffe9
-#define DRI_MARKER	0xffdd
-#define DQT_MARKER	0xffdb
-#define DHT_MARKER	0xffc4
-#define SOF_MARKER	0xffc0
-#define SOS_MARKER	0xffda
-#define EOI_MARKER	0xffd9
-
-enum {
-	CODA9_JPEG_FORMAT_420,
-	CODA9_JPEG_FORMAT_422,
-	CODA9_JPEG_FORMAT_224,
-	CODA9_JPEG_FORMAT_444,
-	CODA9_JPEG_FORMAT_400,
-};
-
-struct coda_huff_tab {
-	u8 luma_dc[16 + 12];
-	u8 chroma_dc[16 + 12];
-	u8 luma_ac[16 + 162];
-	u8 chroma_ac[16 + 162];
-
-	/* DC Luma, DC Chroma, AC Luma, AC Chroma */
-	s16	min[4 * 16];
-	s16	max[4 * 16];
-	s8	ptr[4 * 16];
-};
-
-#define CODA9_JPEG_ENC_HUFF_DATA_SIZE	(256 + 256 + 16 + 16)
-
-/*
- * Typical Huffman tables for 8-bit precision luminance and
- * chrominance from JPEG ITU-T.81 (ISO/IEC 10918-1) Annex K.3
- */
-
-static const unsigned char luma_dc[16 + 12] = {
-	/* bits */
-	0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* values */
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b,
-};
-
-static const unsigned char chroma_dc[16 + 12] = {
-	/* bits */
-	0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* values */
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b,
-};
-
-static const unsigned char luma_ac[16 + 162 + 2] = {
-	/* bits */
-	0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
-	0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
-	/* values */
-	0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
-	0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
-	0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
-	0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
-	0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
-	0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
-	0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
-	0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
-	0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
-	0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
-	0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
-	0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
-	0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
-	0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-	0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
-	0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
-	0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
-	0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
-	0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
-	0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-	0xf9, 0xfa, /* padded to 32-bit */
-};
-
-static const unsigned char chroma_ac[16 + 162 + 2] = {
-	/* bits */
-	0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
-	0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
-	/* values */
-	0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
-	0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
-	0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
-	0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
-	0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
-	0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
-	0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
-	0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
-	0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
-	0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
-	0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
-	0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
-	0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
-	0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
-	0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
-	0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
-	0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
-	0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
-	0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
-	0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
-	0xf9, 0xfa, /* padded to 32-bit */
-};
-
-/*
- * Quantization tables for luminance and chrominance components in
- * zig-zag scan order from the Freescale i.MX VPU libraries
- */
-
-static unsigned char luma_q[64] = {
-	0x06, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x05,
-	0x05, 0x06, 0x09, 0x06, 0x05, 0x06, 0x09, 0x0b,
-	0x08, 0x06, 0x06, 0x08, 0x0b, 0x0c, 0x0a, 0x0a,
-	0x0b, 0x0a, 0x0a, 0x0c, 0x10, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-};
-
-static unsigned char chroma_q[64] = {
-	0x07, 0x07, 0x07, 0x0d, 0x0c, 0x0d, 0x18, 0x10,
-	0x10, 0x18, 0x14, 0x0e, 0x0e, 0x0e, 0x14, 0x14,
-	0x0e, 0x0e, 0x0e, 0x0e, 0x14, 0x11, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x11, 0x11, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x11, 0x0c, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-};
-
-static const unsigned char width_align[] = {
-	[CODA9_JPEG_FORMAT_420] = 16,
-	[CODA9_JPEG_FORMAT_422] = 16,
-	[CODA9_JPEG_FORMAT_224] = 8,
-	[CODA9_JPEG_FORMAT_444] = 8,
-	[CODA9_JPEG_FORMAT_400] = 8,
-};
-
-static const unsigned char height_align[] = {
-	[CODA9_JPEG_FORMAT_420] = 16,
-	[CODA9_JPEG_FORMAT_422] = 8,
-	[CODA9_JPEG_FORMAT_224] = 16,
-	[CODA9_JPEG_FORMAT_444] = 8,
-	[CODA9_JPEG_FORMAT_400] = 8,
-};
-
-static int coda9_jpeg_chroma_format(u32 pixfmt)
-{
-	switch (pixfmt) {
-	case V4L2_PIX_FMT_YUV420:
-	case V4L2_PIX_FMT_NV12:
-		return CODA9_JPEG_FORMAT_420;
-	case V4L2_PIX_FMT_YUV422P:
-		return CODA9_JPEG_FORMAT_422;
-	case V4L2_PIX_FMT_YUV444:
-		return CODA9_JPEG_FORMAT_444;
-	case V4L2_PIX_FMT_GREY:
-		return CODA9_JPEG_FORMAT_400;
-	}
-	return -EINVAL;
-}
-
-struct coda_memcpy_desc {
-	int offset;
-	const void *src;
-	size_t len;
-};
-
-static void coda_memcpy_parabuf(void *parabuf,
-				const struct coda_memcpy_desc *desc)
-{
-	u32 *dst = parabuf + desc->offset;
-	const u32 *src = desc->src;
-	int len = desc->len / 4;
-	int i;
-
-	for (i = 0; i < len; i += 2) {
-		dst[i + 1] = swab32(src[i]);
-		dst[i] = swab32(src[i + 1]);
-	}
-}
-
-int coda_jpeg_write_tables(struct coda_ctx *ctx)
-{
-	int i;
-	static const struct coda_memcpy_desc huff[8] = {
-		{ 0,   luma_dc,    sizeof(luma_dc)    },
-		{ 32,  luma_ac,    sizeof(luma_ac)    },
-		{ 216, chroma_dc,  sizeof(chroma_dc)  },
-		{ 248, chroma_ac,  sizeof(chroma_ac)  },
-	};
-	struct coda_memcpy_desc qmat[3] = {
-		{ 512, ctx->params.jpeg_qmat_tab[0], 64 },
-		{ 576, ctx->params.jpeg_qmat_tab[1], 64 },
-		{ 640, ctx->params.jpeg_qmat_tab[1], 64 },
-	};
-
-	/* Write huffman tables to parameter memory */
-	for (i = 0; i < ARRAY_SIZE(huff); i++)
-		coda_memcpy_parabuf(ctx->parabuf.vaddr, huff + i);
-
-	/* Write Q-matrix to parameter memory */
-	for (i = 0; i < ARRAY_SIZE(qmat); i++)
-		coda_memcpy_parabuf(ctx->parabuf.vaddr, qmat + i);
-
-	return 0;
-}
-
-bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb)
-{
-	void *vaddr = vb2_plane_vaddr(vb, 0);
-	u16 soi, eoi;
-	int len, i;
-
-	soi = be16_to_cpup((__be16 *)vaddr);
-	if (soi != SOI_MARKER)
-		return false;
-
-	len = vb2_get_plane_payload(vb, 0);
-	vaddr += len - 2;
-	for (i = 0; i < 32; i++) {
-		eoi = be16_to_cpup((__be16 *)(vaddr - i));
-		if (eoi == EOI_MARKER) {
-			if (i > 0)
-				vb2_set_plane_payload(vb, 0, len - i);
-			return true;
-		}
-	}
-
-	return false;
-}
-
-static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num);
-
-int coda_jpeg_decode_header(struct coda_ctx *ctx, struct vb2_buffer *vb)
-{
-	struct coda_dev *dev = ctx->dev;
-	u8 *buf = vb2_plane_vaddr(vb, 0);
-	size_t len = vb2_get_plane_payload(vb, 0);
-	struct v4l2_jpeg_scan_header scan_header;
-	struct v4l2_jpeg_reference quantization_tables[4] = { };
-	struct v4l2_jpeg_reference huffman_tables[4] = { };
-	struct v4l2_jpeg_header header = {
-		.scan = &scan_header,
-		.quantization_tables = quantization_tables,
-		.huffman_tables = huffman_tables,
-	};
-	struct coda_q_data *q_data_src;
-	struct coda_huff_tab *huff_tab;
-	int i, j, ret;
-
-	ret = v4l2_jpeg_parse_header(buf, len, &header);
-	if (ret < 0) {
-		v4l2_err(&dev->v4l2_dev, "failed to parse JPEG header: %pe\n",
-			 ERR_PTR(ret));
-		return ret;
-	}
-
-	ctx->params.jpeg_restart_interval = header.restart_interval;
-
-	/* check frame header */
-	if (header.frame.height > ctx->codec->max_h ||
-	    header.frame.width > ctx->codec->max_w) {
-		v4l2_err(&dev->v4l2_dev, "invalid dimensions: %dx%d\n",
-			 header.frame.width, header.frame.height);
-		return -EINVAL;
-	}
-
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	if (header.frame.height != q_data_src->height ||
-	    header.frame.width != q_data_src->width) {
-		v4l2_err(&dev->v4l2_dev,
-			 "dimensions don't match format: %dx%d\n",
-			 header.frame.width, header.frame.height);
-		return -EINVAL;
-	}
-
-	if (header.frame.num_components != 3) {
-		v4l2_err(&dev->v4l2_dev,
-			 "unsupported number of components: %d\n",
-			 header.frame.num_components);
-		return -EINVAL;
-	}
-
-	/* install quantization tables */
-	if (quantization_tables[3].start) {
-		v4l2_err(&dev->v4l2_dev,
-			 "only 3 quantization tables supported\n");
-		return -EINVAL;
-	}
-	for (i = 0; i < 3; i++) {
-		if (!quantization_tables[i].start)
-			continue;
-		if (quantization_tables[i].length != 64) {
-			v4l2_err(&dev->v4l2_dev,
-				 "only 8-bit quantization tables supported\n");
-			continue;
-		}
-		if (!ctx->params.jpeg_qmat_tab[i]) {
-			ctx->params.jpeg_qmat_tab[i] = kmalloc(64, GFP_KERNEL);
-			if (!ctx->params.jpeg_qmat_tab[i])
-				return -ENOMEM;
-		}
-		memcpy(ctx->params.jpeg_qmat_tab[i],
-		       quantization_tables[i].start, 64);
-	}
-
-	/* install Huffman tables */
-	for (i = 0; i < 4; i++) {
-		if (!huffman_tables[i].start) {
-			v4l2_err(&dev->v4l2_dev, "missing Huffman table\n");
-			return -EINVAL;
-		}
-		/* AC tables should be between 17 -> 178, DC between 17 -> 28 */
-		if (huffman_tables[i].length < 17 ||
-		    huffman_tables[i].length > 178 ||
-		    ((i & 2) == 0 && huffman_tables[i].length > 28)) {
-			v4l2_err(&dev->v4l2_dev,
-				 "invalid Huffman table %d length: %zu\n",
-				 i, huffman_tables[i].length);
-			return -EINVAL;
-		}
-	}
-	huff_tab = ctx->params.jpeg_huff_tab;
-	if (!huff_tab) {
-		huff_tab = kzalloc(sizeof(struct coda_huff_tab), GFP_KERNEL);
-		if (!huff_tab)
-			return -ENOMEM;
-		ctx->params.jpeg_huff_tab = huff_tab;
-	}
-
-	memset(huff_tab, 0, sizeof(*huff_tab));
-	memcpy(huff_tab->luma_dc, huffman_tables[0].start, huffman_tables[0].length);
-	memcpy(huff_tab->chroma_dc, huffman_tables[1].start, huffman_tables[1].length);
-	memcpy(huff_tab->luma_ac, huffman_tables[2].start, huffman_tables[2].length);
-	memcpy(huff_tab->chroma_ac, huffman_tables[3].start, huffman_tables[3].length);
-
-	/* check scan header */
-	for (i = 0; i < scan_header.num_components; i++) {
-		struct v4l2_jpeg_scan_component_spec *scan_component;
-
-		scan_component = &scan_header.component[i];
-		for (j = 0; j < header.frame.num_components; j++) {
-			if (header.frame.component[j].component_identifier ==
-			    scan_component->component_selector)
-				break;
-		}
-		if (j == header.frame.num_components)
-			continue;
-
-		ctx->params.jpeg_huff_dc_index[j] =
-			scan_component->dc_entropy_coding_table_selector;
-		ctx->params.jpeg_huff_ac_index[j] =
-			scan_component->ac_entropy_coding_table_selector;
-	}
-
-	/* Generate Huffman table information */
-	for (i = 0; i < 4; i++)
-		coda9_jpeg_gen_dec_huff_tab(ctx, i);
-
-	/* start of entropy coded segment */
-	ctx->jpeg_ecs_offset = header.ecs_offset;
-
-	switch (header.frame.subsampling) {
-	case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
-	case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
-		ctx->params.jpeg_chroma_subsampling = header.frame.subsampling;
-		break;
-	default:
-		v4l2_err(&dev->v4l2_dev, "chroma subsampling not supported: %d",
-			 header.frame.subsampling);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static inline void coda9_jpeg_write_huff_values(struct coda_dev *dev, u8 *bits,
-						int num_values)
-{
-	s8 *values = (s8 *)(bits + 16);
-	int huff_length, i;
-
-	for (huff_length = 0, i = 0; i < 16; i++)
-		huff_length += bits[i];
-	for (i = huff_length; i < num_values; i++)
-		values[i] = -1;
-	for (i = 0; i < num_values; i++)
-		coda_write(dev, (s32)values[i], CODA9_REG_JPEG_HUFF_DATA);
-}
-
-static void coda9_jpeg_dec_huff_setup(struct coda_ctx *ctx)
-{
-	struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab;
-	struct coda_dev *dev = ctx->dev;
-	s16 *huff_min = huff_tab->min;
-	s16 *huff_max = huff_tab->max;
-	s8 *huff_ptr = huff_tab->ptr;
-	int i;
-
-	/* MIN Tables */
-	coda_write(dev, 0x003, CODA9_REG_JPEG_HUFF_CTRL);
-	coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_ADDR);
-	for (i = 0; i < 4 * 16; i++)
-		coda_write(dev, (s32)huff_min[i], CODA9_REG_JPEG_HUFF_DATA);
-
-	/* MAX Tables */
-	coda_write(dev, 0x403, CODA9_REG_JPEG_HUFF_CTRL);
-	coda_write(dev, 0x440, CODA9_REG_JPEG_HUFF_ADDR);
-	for (i = 0; i < 4 * 16; i++)
-		coda_write(dev, (s32)huff_max[i], CODA9_REG_JPEG_HUFF_DATA);
-
-	/* PTR Tables */
-	coda_write(dev, 0x803, CODA9_REG_JPEG_HUFF_CTRL);
-	coda_write(dev, 0x880, CODA9_REG_JPEG_HUFF_ADDR);
-	for (i = 0; i < 4 * 16; i++)
-		coda_write(dev, (s32)huff_ptr[i], CODA9_REG_JPEG_HUFF_DATA);
-
-	/* VAL Tables: DC Luma, DC Chroma, AC Luma, AC Chroma */
-	coda_write(dev, 0xc03, CODA9_REG_JPEG_HUFF_CTRL);
-	coda9_jpeg_write_huff_values(dev, huff_tab->luma_dc, 12);
-	coda9_jpeg_write_huff_values(dev, huff_tab->chroma_dc, 12);
-	coda9_jpeg_write_huff_values(dev, huff_tab->luma_ac, 162);
-	coda9_jpeg_write_huff_values(dev, huff_tab->chroma_ac, 162);
-	coda_write(dev, 0x000, CODA9_REG_JPEG_HUFF_CTRL);
-}
-
-static inline void coda9_jpeg_write_qmat_tab(struct coda_dev *dev,
-					     u8 *qmat, int index)
-{
-	int i;
-
-	coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL);
-	for (i = 0; i < 64; i++)
-		coda_write(dev, qmat[i], CODA9_REG_JPEG_QMAT_DATA);
-	coda_write(dev, 0, CODA9_REG_JPEG_QMAT_CTRL);
-}
-
-static void coda9_jpeg_qmat_setup(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	int *qmat_index = ctx->params.jpeg_qmat_index;
-	u8 **qmat_tab = ctx->params.jpeg_qmat_tab;
-
-	coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[0]], 0x00);
-	coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[1]], 0x40);
-	coda9_jpeg_write_qmat_tab(dev, qmat_tab[qmat_index[2]], 0x80);
-}
-
-static void coda9_jpeg_dec_bbc_gbu_setup(struct coda_ctx *ctx,
-					 struct vb2_buffer *buf, u32 ecs_offset)
-{
-	struct coda_dev *dev = ctx->dev;
-	int page_ptr, word_ptr, bit_ptr;
-	u32 bbc_base_addr, end_addr;
-	int bbc_cur_pos;
-	int ret, val;
-
-	bbc_base_addr = vb2_dma_contig_plane_dma_addr(buf, 0);
-	end_addr = bbc_base_addr + vb2_get_plane_payload(buf, 0);
-
-	page_ptr = ecs_offset / 256;
-	word_ptr = (ecs_offset % 256) / 4;
-	if (page_ptr & 1)
-		word_ptr += 64;
-	bit_ptr = (ecs_offset % 4) * 8;
-	if (word_ptr & 1)
-		bit_ptr += 32;
-	word_ptr &= ~0x1;
-
-	coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_WR_PTR);
-	coda_write(dev, bbc_base_addr, CODA9_REG_JPEG_BBC_BAS_ADDR);
-
-	/* Leave 3 256-byte page margin to avoid a BBC interrupt */
-	coda_write(dev, end_addr + 256 * 3 + 256, CODA9_REG_JPEG_BBC_END_ADDR);
-	val = DIV_ROUND_UP(vb2_plane_size(buf, 0), 256) + 3;
-	coda_write(dev, BIT(31) | val, CODA9_REG_JPEG_BBC_STRM_CTRL);
-
-	bbc_cur_pos = page_ptr;
-	coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS);
-	coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8),
-			CODA9_REG_JPEG_BBC_EXT_ADDR);
-	coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR);
-	coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT);
-	coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND);
-	do {
-		ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY);
-	} while (ret == 1);
-
-	bbc_cur_pos++;
-	coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS);
-	coda_write(dev, bbc_base_addr + (bbc_cur_pos << 8),
-			CODA9_REG_JPEG_BBC_EXT_ADDR);
-	coda_write(dev, (bbc_cur_pos & 1) << 6, CODA9_REG_JPEG_BBC_INT_ADDR);
-	coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT);
-	coda_write(dev, 0, CODA9_REG_JPEG_BBC_COMMAND);
-	do {
-		ret = coda_read(dev, CODA9_REG_JPEG_BBC_BUSY);
-	} while (ret == 1);
-
-	bbc_cur_pos++;
-	coda_write(dev, bbc_cur_pos, CODA9_REG_JPEG_BBC_CUR_POS);
-	coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL);
-
-	coda_write(dev, 0, CODA9_REG_JPEG_GBU_TT_CNT);
-	coda_write(dev, word_ptr, CODA9_REG_JPEG_GBU_WD_PTR);
-	coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR);
-	coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER);
-	if (page_ptr & 1) {
-		coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBIR);
-		coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBHR);
-	} else {
-		coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR);
-		coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR);
-	}
-	coda_write(dev, 4, CODA9_REG_JPEG_GBU_CTRL);
-	coda_write(dev, bit_ptr, CODA9_REG_JPEG_GBU_FF_RPTR);
-	coda_write(dev, 3, CODA9_REG_JPEG_GBU_CTRL);
-}
-
-static const int bus_req_num[] = {
-	[CODA9_JPEG_FORMAT_420] = 2,
-	[CODA9_JPEG_FORMAT_422] = 3,
-	[CODA9_JPEG_FORMAT_224] = 3,
-	[CODA9_JPEG_FORMAT_444] = 4,
-	[CODA9_JPEG_FORMAT_400] = 4,
-};
-
-#define MCU_INFO(mcu_block_num, comp_num, comp0_info, comp1_info, comp2_info) \
-	(((mcu_block_num) << CODA9_JPEG_MCU_BLOCK_NUM_OFFSET) | \
-	 ((comp_num) << CODA9_JPEG_COMP_NUM_OFFSET) | \
-	 ((comp0_info) << CODA9_JPEG_COMP0_INFO_OFFSET) | \
-	 ((comp1_info) << CODA9_JPEG_COMP1_INFO_OFFSET) | \
-	 ((comp2_info) << CODA9_JPEG_COMP2_INFO_OFFSET))
-
-static const u32 mcu_info[] = {
-	[CODA9_JPEG_FORMAT_420] = MCU_INFO(6, 3, 10, 5, 5),
-	[CODA9_JPEG_FORMAT_422] = MCU_INFO(4, 3, 9, 5, 5),
-	[CODA9_JPEG_FORMAT_224] = MCU_INFO(4, 3, 6, 5, 5),
-	[CODA9_JPEG_FORMAT_444] = MCU_INFO(3, 3, 5, 5, 5),
-	[CODA9_JPEG_FORMAT_400] = MCU_INFO(1, 1, 5, 0, 0),
-};
-
-/*
- * Convert Huffman table specifcations to tables of codes and code lengths.
- * For reference, see JPEG ITU-T.81 (ISO/IEC 10918-1) [1]
- *
- * [1] https://www.w3.org/Graphics/JPEG/itu-t81.pdf
- */
-static int coda9_jpeg_gen_enc_huff_tab(struct coda_ctx *ctx, int tab_num,
-				       int *ehufsi, int *ehufco)
-{
-	int i, j, k, lastk, si, code, maxsymbol;
-	const u8 *bits, *huffval;
-	struct {
-		int size[256];
-		int code[256];
-	} *huff;
-	static const unsigned char *huff_tabs[4] = {
-		luma_dc, luma_ac, chroma_dc, chroma_ac,
-	};
-	int ret = -EINVAL;
-
-	huff = kzalloc(sizeof(*huff), GFP_KERNEL);
-	if (!huff)
-		return -ENOMEM;
-
-	bits = huff_tabs[tab_num];
-	huffval = huff_tabs[tab_num] + 16;
-
-	maxsymbol = tab_num & 1 ? 256 : 16;
-
-	/* Figure C.1 - Generation of table of Huffman code sizes */
-	k = 0;
-	for (i = 1; i <= 16; i++) {
-		j = bits[i - 1];
-		if (k + j > maxsymbol)
-			goto out;
-		while (j--)
-			huff->size[k++] = i;
-	}
-	lastk = k;
-
-	/* Figure C.2 - Generation of table of Huffman codes */
-	k = 0;
-	code = 0;
-	si = huff->size[0];
-	while (k < lastk) {
-		while (huff->size[k] == si) {
-			huff->code[k++] = code;
-			code++;
-		}
-		if (code >= (1 << si))
-			goto out;
-		code <<= 1;
-		si++;
-	}
-
-	/* Figure C.3 - Ordering procedure for encoding procedure code tables */
-	for (k = 0; k < lastk; k++) {
-		i = huffval[k];
-		if (i >= maxsymbol || ehufsi[i])
-			goto out;
-		ehufco[i] = huff->code[k];
-		ehufsi[i] = huff->size[k];
-	}
-
-	ret = 0;
-out:
-	kfree(huff);
-	return ret;
-}
-
-#define DC_TABLE_INDEX0		    0
-#define AC_TABLE_INDEX0		    1
-#define DC_TABLE_INDEX1		    2
-#define AC_TABLE_INDEX1		    3
-
-static u8 *coda9_jpeg_get_huff_bits(struct coda_ctx *ctx, int tab_num)
-{
-	struct coda_huff_tab *huff_tab = ctx->params.jpeg_huff_tab;
-
-	if (!huff_tab)
-		return NULL;
-
-	switch (tab_num) {
-	case DC_TABLE_INDEX0: return huff_tab->luma_dc;
-	case AC_TABLE_INDEX0: return huff_tab->luma_ac;
-	case DC_TABLE_INDEX1: return huff_tab->chroma_dc;
-	case AC_TABLE_INDEX1: return huff_tab->chroma_ac;
-	}
-
-	return NULL;
-}
-
-static int coda9_jpeg_gen_dec_huff_tab(struct coda_ctx *ctx, int tab_num)
-{
-	int ptr_cnt = 0, huff_code = 0, zero_flag = 0, data_flag = 0;
-	u8 *huff_bits;
-	s16 *huff_max;
-	s16 *huff_min;
-	s8 *huff_ptr;
-	int ofs;
-	int i;
-
-	huff_bits = coda9_jpeg_get_huff_bits(ctx, tab_num);
-	if (!huff_bits)
-		return -EINVAL;
-
-	/* DC/AC Luma, DC/AC Chroma -> DC Luma/Chroma, AC Luma/Chroma */
-	ofs = ((tab_num & 1) << 1) | ((tab_num >> 1) & 1);
-	ofs *= 16;
-
-	huff_ptr = ctx->params.jpeg_huff_tab->ptr + ofs;
-	huff_max = ctx->params.jpeg_huff_tab->max + ofs;
-	huff_min = ctx->params.jpeg_huff_tab->min + ofs;
-
-	for (i = 0; i < 16; i++) {
-		if (huff_bits[i]) {
-			huff_ptr[i] = ptr_cnt;
-			ptr_cnt += huff_bits[i];
-			huff_min[i] = huff_code;
-			huff_max[i] = huff_code + (huff_bits[i] - 1);
-			data_flag = 1;
-			zero_flag = 0;
-		} else {
-			huff_ptr[i] = -1;
-			huff_min[i] = -1;
-			huff_max[i] = -1;
-			zero_flag = 1;
-		}
-
-		if (data_flag == 1) {
-			if (zero_flag == 1)
-				huff_code <<= 1;
-			else
-				huff_code = (huff_max[i] + 1) << 1;
-		}
-	}
-
-	return 0;
-}
-
-static int coda9_jpeg_load_huff_tab(struct coda_ctx *ctx)
-{
-	struct {
-		int size[4][256];
-		int code[4][256];
-	} *huff;
-	u32 *huff_data;
-	int i, j;
-	int ret;
-
-	huff = kzalloc(sizeof(*huff), GFP_KERNEL);
-	if (!huff)
-		return -ENOMEM;
-
-	/* Generate all four (luma/chroma DC/AC) code/size lookup tables */
-	for (i = 0; i < 4; i++) {
-		ret = coda9_jpeg_gen_enc_huff_tab(ctx, i, huff->size[i],
-						  huff->code[i]);
-		if (ret)
-			goto out;
-	}
-
-	if (!ctx->params.jpeg_huff_data) {
-		ctx->params.jpeg_huff_data =
-			kzalloc(sizeof(u32) * CODA9_JPEG_ENC_HUFF_DATA_SIZE,
-				GFP_KERNEL);
-		if (!ctx->params.jpeg_huff_data) {
-			ret = -ENOMEM;
-			goto out;
-		}
-	}
-	huff_data = ctx->params.jpeg_huff_data;
-
-	for (j = 0; j < 4; j++) {
-		/* Store Huffman lookup tables in AC0, AC1, DC0, DC1 order */
-		int t = (j == 0) ? AC_TABLE_INDEX0 :
-			(j == 1) ? AC_TABLE_INDEX1 :
-			(j == 2) ? DC_TABLE_INDEX0 :
-				   DC_TABLE_INDEX1;
-		/* DC tables only have 16 entries */
-		int len = (j < 2) ? 256 : 16;
-
-		for (i = 0; i < len; i++) {
-			if (huff->size[t][i] == 0 && huff->code[t][i] == 0)
-				*(huff_data++) = 0;
-			else
-				*(huff_data++) =
-					((huff->size[t][i] - 1) << 16) |
-					huff->code[t][i];
-		}
-	}
-
-	ret = 0;
-out:
-	kfree(huff);
-	return ret;
-}
-
-static void coda9_jpeg_write_huff_tab(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	u32 *huff_data = ctx->params.jpeg_huff_data;
-	int i;
-
-	/* Write Huffman size/code lookup tables in AC0, AC1, DC0, DC1 order */
-	coda_write(dev, 0x3, CODA9_REG_JPEG_HUFF_CTRL);
-	for (i = 0; i < CODA9_JPEG_ENC_HUFF_DATA_SIZE; i++)
-		coda_write(dev, *(huff_data++), CODA9_REG_JPEG_HUFF_DATA);
-	coda_write(dev, 0x0, CODA9_REG_JPEG_HUFF_CTRL);
-}
-
-static inline void coda9_jpeg_write_qmat_quotients(struct coda_dev *dev,
-						   u8 *qmat, int index)
-{
-	int i;
-
-	coda_write(dev, index | 0x3, CODA9_REG_JPEG_QMAT_CTRL);
-	for (i = 0; i < 64; i++)
-		coda_write(dev, 0x80000 / qmat[i], CODA9_REG_JPEG_QMAT_DATA);
-	coda_write(dev, index, CODA9_REG_JPEG_QMAT_CTRL);
-}
-
-static void coda9_jpeg_load_qmat_tab(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	u8 *luma_tab;
-	u8 *chroma_tab;
-
-	luma_tab = ctx->params.jpeg_qmat_tab[0];
-	if (!luma_tab)
-		luma_tab = luma_q;
-
-	chroma_tab = ctx->params.jpeg_qmat_tab[1];
-	if (!chroma_tab)
-		chroma_tab = chroma_q;
-
-	coda9_jpeg_write_qmat_quotients(dev, luma_tab, 0x00);
-	coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x40);
-	coda9_jpeg_write_qmat_quotients(dev, chroma_tab, 0x80);
-}
-
-struct coda_jpeg_stream {
-	u8 *curr;
-	u8 *end;
-};
-
-static inline int coda_jpeg_put_byte(u8 byte, struct coda_jpeg_stream *stream)
-{
-	if (stream->curr >= stream->end)
-		return -EINVAL;
-
-	*stream->curr++ = byte;
-
-	return 0;
-}
-
-static inline int coda_jpeg_put_word(u16 word, struct coda_jpeg_stream *stream)
-{
-	if (stream->curr + sizeof(__be16) > stream->end)
-		return -EINVAL;
-
-	put_unaligned_be16(word, stream->curr);
-	stream->curr += sizeof(__be16);
-
-	return 0;
-}
-
-static int coda_jpeg_put_table(u16 marker, u8 index, const u8 *table,
-			       size_t len, struct coda_jpeg_stream *stream)
-{
-	int i, ret;
-
-	ret = coda_jpeg_put_word(marker, stream);
-	if (ret < 0)
-		return ret;
-	ret = coda_jpeg_put_word(3 + len, stream);
-	if (ret < 0)
-		return ret;
-	ret = coda_jpeg_put_byte(index, stream);
-	for (i = 0; i < len && ret == 0; i++)
-		ret = coda_jpeg_put_byte(table[i], stream);
-
-	return ret;
-}
-
-static int coda_jpeg_define_quantization_table(struct coda_ctx *ctx, u8 index,
-					       struct coda_jpeg_stream *stream)
-{
-	return coda_jpeg_put_table(DQT_MARKER, index,
-				   ctx->params.jpeg_qmat_tab[index], 64,
-				   stream);
-}
-
-static int coda_jpeg_define_huffman_table(u8 index, const u8 *table, size_t len,
-					  struct coda_jpeg_stream *stream)
-{
-	return coda_jpeg_put_table(DHT_MARKER, index, table, len, stream);
-}
-
-static int coda9_jpeg_encode_header(struct coda_ctx *ctx, int len, u8 *buf)
-{
-	struct coda_jpeg_stream stream = { buf, buf + len };
-	struct coda_q_data *q_data_src;
-	int chroma_format, comp_num;
-	int i, ret, pad;
-
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc);
-	if (chroma_format < 0)
-		return 0;
-
-	/* Start Of Image */
-	ret = coda_jpeg_put_word(SOI_MARKER, &stream);
-	if (ret < 0)
-		return ret;
-
-	/* Define Restart Interval */
-	if (ctx->params.jpeg_restart_interval) {
-		ret = coda_jpeg_put_word(DRI_MARKER, &stream);
-		if (ret < 0)
-			return ret;
-		ret = coda_jpeg_put_word(4, &stream);
-		if (ret < 0)
-			return ret;
-		ret = coda_jpeg_put_word(ctx->params.jpeg_restart_interval,
-					 &stream);
-		if (ret < 0)
-			return ret;
-	}
-
-	/* Define Quantization Tables */
-	ret = coda_jpeg_define_quantization_table(ctx, 0x00, &stream);
-	if (ret < 0)
-		return ret;
-	if (chroma_format != CODA9_JPEG_FORMAT_400) {
-		ret = coda_jpeg_define_quantization_table(ctx, 0x01, &stream);
-		if (ret < 0)
-			return ret;
-	}
-
-	/* Define Huffman Tables */
-	ret = coda_jpeg_define_huffman_table(0x00, luma_dc, 16 + 12, &stream);
-	if (ret < 0)
-		return ret;
-	ret = coda_jpeg_define_huffman_table(0x10, luma_ac, 16 + 162, &stream);
-	if (ret < 0)
-		return ret;
-	if (chroma_format != CODA9_JPEG_FORMAT_400) {
-		ret = coda_jpeg_define_huffman_table(0x01, chroma_dc, 16 + 12,
-						     &stream);
-		if (ret < 0)
-			return ret;
-		ret = coda_jpeg_define_huffman_table(0x11, chroma_ac, 16 + 162,
-						     &stream);
-		if (ret < 0)
-			return ret;
-	}
-
-	/* Start Of Frame */
-	ret = coda_jpeg_put_word(SOF_MARKER, &stream);
-	if (ret < 0)
-		return ret;
-	comp_num = (chroma_format == CODA9_JPEG_FORMAT_400) ? 1 : 3;
-	ret = coda_jpeg_put_word(8 + comp_num * 3, &stream);
-	if (ret < 0)
-		return ret;
-	ret = coda_jpeg_put_byte(0x08, &stream);
-	if (ret < 0)
-		return ret;
-	ret = coda_jpeg_put_word(q_data_src->height, &stream);
-	if (ret < 0)
-		return ret;
-	ret = coda_jpeg_put_word(q_data_src->width, &stream);
-	if (ret < 0)
-		return ret;
-	ret = coda_jpeg_put_byte(comp_num, &stream);
-	if (ret < 0)
-		return ret;
-	for (i = 0; i < comp_num; i++) {
-		static unsigned char subsampling[5][3] = {
-			[CODA9_JPEG_FORMAT_420] = { 0x22, 0x11, 0x11 },
-			[CODA9_JPEG_FORMAT_422] = { 0x21, 0x11, 0x11 },
-			[CODA9_JPEG_FORMAT_224] = { 0x12, 0x11, 0x11 },
-			[CODA9_JPEG_FORMAT_444] = { 0x11, 0x11, 0x11 },
-			[CODA9_JPEG_FORMAT_400] = { 0x11 },
-		};
-
-		/* Component identifier, matches SOS */
-		ret = coda_jpeg_put_byte(i + 1, &stream);
-		if (ret < 0)
-			return ret;
-		ret = coda_jpeg_put_byte(subsampling[chroma_format][i],
-					 &stream);
-		if (ret < 0)
-			return ret;
-		/* Chroma table index */
-		ret = coda_jpeg_put_byte((i == 0) ? 0 : 1, &stream);
-		if (ret < 0)
-			return ret;
-	}
-
-	/* Pad to multiple of 8 bytes */
-	pad = (stream.curr - buf) % 8;
-	if (pad) {
-		pad = 8 - pad;
-		while (pad--) {
-			ret = coda_jpeg_put_byte(0x00, &stream);
-			if (ret < 0)
-				return ret;
-		}
-	}
-
-	return stream.curr - buf;
-}
-
-/*
- * Scale quantization table using nonlinear scaling factor
- * u8 qtab[64], scale [50,190]
- */
-static void coda_scale_quant_table(u8 *q_tab, int scale)
-{
-	unsigned int temp;
-	int i;
-
-	for (i = 0; i < 64; i++) {
-		temp = DIV_ROUND_CLOSEST((unsigned int)q_tab[i] * scale, 100);
-		if (temp <= 0)
-			temp = 1;
-		if (temp > 255)
-			temp = 255;
-		q_tab[i] = (unsigned char)temp;
-	}
-}
-
-void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality)
-{
-	unsigned int scale;
-
-	ctx->params.jpeg_quality = quality;
-
-	/* Clip quality setting to [5,100] interval */
-	if (quality > 100)
-		quality = 100;
-	if (quality < 5)
-		quality = 5;
-
-	/*
-	 * Non-linear scaling factor:
-	 * [5,50] -> [1000..100], [51,100] -> [98..0]
-	 */
-	if (quality < 50)
-		scale = 5000 / quality;
-	else
-		scale = 200 - 2 * quality;
-
-	if (ctx->params.jpeg_qmat_tab[0]) {
-		memcpy(ctx->params.jpeg_qmat_tab[0], luma_q, 64);
-		coda_scale_quant_table(ctx->params.jpeg_qmat_tab[0], scale);
-	}
-	if (ctx->params.jpeg_qmat_tab[1]) {
-		memcpy(ctx->params.jpeg_qmat_tab[1], chroma_q, 64);
-		coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale);
-	}
-}
-
-/*
- * Encoder context operations
- */
-
-static int coda9_jpeg_start_encoding(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	int ret;
-
-	ret = coda9_jpeg_load_huff_tab(ctx);
-	if (ret < 0) {
-		v4l2_err(&dev->v4l2_dev, "error loading Huffman tables\n");
-		return ret;
-	}
-	if (!ctx->params.jpeg_qmat_tab[0]) {
-		ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL);
-		if (!ctx->params.jpeg_qmat_tab[0])
-			return -ENOMEM;
-	}
-	if (!ctx->params.jpeg_qmat_tab[1]) {
-		ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL);
-		if (!ctx->params.jpeg_qmat_tab[1])
-			return -ENOMEM;
-	}
-	coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality);
-
-	return 0;
-}
-
-static int coda9_jpeg_prepare_encode(struct coda_ctx *ctx)
-{
-	struct coda_q_data *q_data_src;
-	struct vb2_v4l2_buffer *src_buf, *dst_buf;
-	struct coda_dev *dev = ctx->dev;
-	u32 start_addr, end_addr;
-	u16 aligned_width, aligned_height;
-	bool chroma_interleave;
-	int chroma_format;
-	int header_len;
-	int ret;
-	ktime_t timeout;
-
-	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-
-	if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0)
-		vb2_set_plane_payload(&src_buf->vb2_buf, 0,
-				      vb2_plane_size(&src_buf->vb2_buf, 0));
-
-	src_buf->sequence = ctx->osequence;
-	dst_buf->sequence = ctx->osequence;
-	ctx->osequence++;
-
-	src_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
-	src_buf->flags &= ~V4L2_BUF_FLAG_PFRAME;
-
-	coda_set_gdi_regs(ctx);
-
-	start_addr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
-	end_addr = start_addr + vb2_plane_size(&dst_buf->vb2_buf, 0);
-
-	chroma_format = coda9_jpeg_chroma_format(q_data_src->fourcc);
-	if (chroma_format < 0)
-		return chroma_format;
-
-	/* Round image dimensions to multiple of MCU size */
-	aligned_width = round_up(q_data_src->width, width_align[chroma_format]);
-	aligned_height = round_up(q_data_src->height,
-				  height_align[chroma_format]);
-	if (aligned_width != q_data_src->bytesperline) {
-		v4l2_err(&dev->v4l2_dev, "wrong stride: %d instead of %d\n",
-			 aligned_width, q_data_src->bytesperline);
-	}
-
-	header_len =
-		coda9_jpeg_encode_header(ctx,
-					 vb2_plane_size(&dst_buf->vb2_buf, 0),
-					 vb2_plane_vaddr(&dst_buf->vb2_buf, 0));
-	if (header_len < 0)
-		return header_len;
-
-	coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_BAS_ADDR);
-	coda_write(dev, end_addr, CODA9_REG_JPEG_BBC_END_ADDR);
-	coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_WR_PTR);
-	coda_write(dev, start_addr + header_len, CODA9_REG_JPEG_BBC_RD_PTR);
-	coda_write(dev, 0, CODA9_REG_JPEG_BBC_CUR_POS);
-	/* 64 words per 256-byte page */
-	coda_write(dev, 64, CODA9_REG_JPEG_BBC_DATA_CNT);
-	coda_write(dev, start_addr, CODA9_REG_JPEG_BBC_EXT_ADDR);
-	coda_write(dev, 0, CODA9_REG_JPEG_BBC_INT_ADDR);
-
-	coda_write(dev, 0, CODA9_REG_JPEG_GBU_BT_PTR);
-	coda_write(dev, 0, CODA9_REG_JPEG_GBU_WD_PTR);
-	coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR);
-	coda_write(dev, BIT(31) | ((end_addr - start_addr - header_len) / 256),
-		   CODA9_REG_JPEG_BBC_STRM_CTRL);
-	coda_write(dev, 0, CODA9_REG_JPEG_GBU_CTRL);
-	coda_write(dev, 0, CODA9_REG_JPEG_GBU_FF_RPTR);
-	coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER);
-	coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBIR);
-	coda_write(dev, 64, CODA9_REG_JPEG_GBU_BBHR);
-
-	chroma_interleave = (q_data_src->fourcc == V4L2_PIX_FMT_NV12);
-	coda_write(dev, CODA9_JPEG_PIC_CTRL_TC_DIRECTION |
-		   CODA9_JPEG_PIC_CTRL_ENCODER_EN, CODA9_REG_JPEG_PIC_CTRL);
-	coda_write(dev, 0, CODA9_REG_JPEG_SCL_INFO);
-	coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG);
-	coda_write(dev, ctx->params.jpeg_restart_interval,
-		   CODA9_REG_JPEG_RST_INTVAL);
-	coda_write(dev, 1, CODA9_REG_JPEG_BBC_CTRL);
-
-	coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO);
-
-	coda9_jpeg_write_huff_tab(ctx);
-	coda9_jpeg_load_qmat_tab(ctx);
-
-	if (ctx->params.rot_mode & CODA_ROT_90) {
-		aligned_width = aligned_height;
-		aligned_height = q_data_src->bytesperline;
-		if (chroma_format == CODA9_JPEG_FORMAT_422)
-			chroma_format = CODA9_JPEG_FORMAT_224;
-		else if (chroma_format == CODA9_JPEG_FORMAT_224)
-			chroma_format = CODA9_JPEG_FORMAT_422;
-	}
-	/* These need to be multiples of MCU size */
-	coda_write(dev, aligned_width << 16 | aligned_height,
-		   CODA9_REG_JPEG_PIC_SIZE);
-	coda_write(dev, ctx->params.rot_mode ?
-		   (CODA_ROT_MIR_ENABLE | ctx->params.rot_mode) : 0,
-		   CODA9_REG_JPEG_ROT_INFO);
-
-	coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO);
-
-	coda_write(dev, 1, CODA9_GDI_CONTROL);
-	timeout = ktime_add_us(ktime_get(), 100000);
-	do {
-		ret = coda_read(dev, CODA9_GDI_STATUS);
-		if (ktime_compare(ktime_get(), timeout) > 0) {
-			v4l2_err(&dev->v4l2_dev, "timeout waiting for GDI\n");
-			return -ETIMEDOUT;
-		}
-	} while (!ret);
-
-	coda_write(dev, (chroma_format << 17) | (chroma_interleave << 16) |
-		   q_data_src->bytesperline, CODA9_GDI_INFO_CONTROL);
-	/* The content of this register seems to be irrelevant: */
-	coda_write(dev, aligned_width << 16 | aligned_height,
-		   CODA9_GDI_INFO_PIC_SIZE);
-
-	coda_write_base(ctx, q_data_src, src_buf, CODA9_GDI_INFO_BASE_Y);
-
-	coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00);
-	coda_write(dev, 0, CODA9_GDI_CONTROL);
-	coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST);
-
-	coda_write(dev, 1, CODA9_GDI_WPROT_ERR_CLR);
-	coda_write(dev, 0, CODA9_GDI_WPROT_RGN_EN);
-
-	trace_coda_jpeg_run(ctx, src_buf);
-
-	coda_write(dev, 1, CODA9_REG_JPEG_PIC_START);
-
-	return 0;
-}
-
-static void coda9_jpeg_finish_encode(struct coda_ctx *ctx)
-{
-	struct vb2_v4l2_buffer *src_buf, *dst_buf;
-	struct coda_dev *dev = ctx->dev;
-	u32 wr_ptr, start_ptr;
-	u32 err_mb;
-
-	if (ctx->aborting) {
-		coda_write(ctx->dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD);
-		return;
-	}
-
-	/*
-	 * Lock to make sure that an encoder stop command running in parallel
-	 * will either already have marked src_buf as last, or it will wake up
-	 * the capture queue after the buffers are returned.
-	 */
-	mutex_lock(&ctx->wakeup_mutex);
-	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-
-	trace_coda_jpeg_done(ctx, dst_buf);
-
-	/*
-	 * Set plane payload to the number of bytes written out
-	 * by the JPEG processing unit
-	 */
-	start_ptr = vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
-	wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR);
-	vb2_set_plane_payload(&dst_buf->vb2_buf, 0, wr_ptr - start_ptr);
-
-	err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB);
-	if (err_mb)
-		coda_dbg(1, ctx, "ERRMB: 0x%x\n", err_mb);
-
-	coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD);
-
-	dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST);
-	dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
-	dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST;
-
-	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
-
-	v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
-	coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR :
-						 VB2_BUF_STATE_DONE);
-	mutex_unlock(&ctx->wakeup_mutex);
-
-	coda_dbg(1, ctx, "job finished: encoded frame (%u)%s\n",
-		 dst_buf->sequence,
-		 (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : "");
-
-	/*
-	 * Reset JPEG processing unit after each encode run to work
-	 * around hangups when switching context between encoder and
-	 * decoder.
-	 */
-	coda_hw_reset(ctx);
-}
-
-static void coda9_jpeg_encode_timeout(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	u32 end_addr, wr_ptr;
-
-	/* Handle missing BBC overflow interrupt via timeout */
-	end_addr = coda_read(dev, CODA9_REG_JPEG_BBC_END_ADDR);
-	wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR);
-	if (wr_ptr >= end_addr - 256) {
-		v4l2_err(&dev->v4l2_dev, "JPEG too large for capture buffer\n");
-		coda9_jpeg_finish_encode(ctx);
-		return;
-	}
-
-	coda_hw_reset(ctx);
-}
-
-static void coda9_jpeg_release(struct coda_ctx *ctx)
-{
-	int i;
-
-	if (ctx->params.jpeg_qmat_tab[0] == luma_q)
-		ctx->params.jpeg_qmat_tab[0] = NULL;
-	if (ctx->params.jpeg_qmat_tab[1] == chroma_q)
-		ctx->params.jpeg_qmat_tab[1] = NULL;
-	for (i = 0; i < 3; i++)
-		kfree(ctx->params.jpeg_qmat_tab[i]);
-	kfree(ctx->params.jpeg_huff_data);
-	kfree(ctx->params.jpeg_huff_tab);
-}
-
-const struct coda_context_ops coda9_jpeg_encode_ops = {
-	.queue_init = coda_encoder_queue_init,
-	.start_streaming = coda9_jpeg_start_encoding,
-	.prepare_run = coda9_jpeg_prepare_encode,
-	.finish_run = coda9_jpeg_finish_encode,
-	.run_timeout = coda9_jpeg_encode_timeout,
-	.release = coda9_jpeg_release,
-};
-
-/*
- * Decoder context operations
- */
-
-static int coda9_jpeg_start_decoding(struct coda_ctx *ctx)
-{
-	ctx->params.jpeg_qmat_index[0] = 0;
-	ctx->params.jpeg_qmat_index[1] = 1;
-	ctx->params.jpeg_qmat_index[2] = 1;
-	ctx->params.jpeg_qmat_tab[0] = luma_q;
-	ctx->params.jpeg_qmat_tab[1] = chroma_q;
-	/* nothing more to do here */
-
-	/* TODO: we could already scan the first header to get the chroma
-	 * format.
-	 */
-
-	return 0;
-}
-
-static int coda9_jpeg_prepare_decode(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	int aligned_width, aligned_height;
-	int chroma_format;
-	int ret;
-	u32 val, dst_fourcc;
-	struct coda_q_data *q_data_src, *q_data_dst;
-	struct vb2_v4l2_buffer *src_buf, *dst_buf;
-	int chroma_interleave;
-	int scl_hor_mode, scl_ver_mode;
-
-	src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
-	dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
-	q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	dst_fourcc = q_data_dst->fourcc;
-
-	scl_hor_mode = coda_jpeg_scale(q_data_src->width, q_data_dst->width);
-	scl_ver_mode = coda_jpeg_scale(q_data_src->height, q_data_dst->height);
-
-	if (vb2_get_plane_payload(&src_buf->vb2_buf, 0) == 0)
-		vb2_set_plane_payload(&src_buf->vb2_buf, 0,
-				      vb2_plane_size(&src_buf->vb2_buf, 0));
-
-	chroma_format = coda9_jpeg_chroma_format(q_data_dst->fourcc);
-	if (chroma_format < 0)
-		return chroma_format;
-
-	ret = coda_jpeg_decode_header(ctx, &src_buf->vb2_buf);
-	if (ret < 0) {
-		src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-		dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
-		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
-
-		return ret;
-	}
-
-	/* Round image dimensions to multiple of MCU size */
-	aligned_width = round_up(q_data_src->width, width_align[chroma_format]);
-	aligned_height = round_up(q_data_src->height, height_align[chroma_format]);
-	if (aligned_width != q_data_dst->bytesperline) {
-		v4l2_err(&dev->v4l2_dev, "stride mismatch: %d != %d\n",
-			 aligned_width, q_data_dst->bytesperline);
-	}
-
-	coda_set_gdi_regs(ctx);
-
-	val = ctx->params.jpeg_huff_ac_index[0] << 12 |
-	      ctx->params.jpeg_huff_ac_index[1] << 11 |
-	      ctx->params.jpeg_huff_ac_index[2] << 10 |
-	      ctx->params.jpeg_huff_dc_index[0] << 9 |
-	      ctx->params.jpeg_huff_dc_index[1] << 8 |
-	      ctx->params.jpeg_huff_dc_index[2] << 7;
-	if (ctx->params.jpeg_huff_tab)
-		val |= CODA9_JPEG_PIC_CTRL_USER_HUFFMAN_EN;
-	coda_write(dev, val, CODA9_REG_JPEG_PIC_CTRL);
-
-	coda_write(dev, aligned_width << 16 | aligned_height,
-			CODA9_REG_JPEG_PIC_SIZE);
-
-	chroma_interleave = (dst_fourcc == V4L2_PIX_FMT_NV12);
-	coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO);
-	coda_write(dev, bus_req_num[chroma_format], CODA9_REG_JPEG_OP_INFO);
-	coda_write(dev, mcu_info[chroma_format], CODA9_REG_JPEG_MCU_INFO);
-	if (scl_hor_mode || scl_ver_mode)
-		val = CODA9_JPEG_SCL_ENABLE | (scl_hor_mode << 2) | scl_ver_mode;
-	else
-		val = 0;
-	coda_write(dev, val, CODA9_REG_JPEG_SCL_INFO);
-	coda_write(dev, chroma_interleave, CODA9_REG_JPEG_DPB_CONFIG);
-	coda_write(dev, ctx->params.jpeg_restart_interval,
-			CODA9_REG_JPEG_RST_INTVAL);
-
-	if (ctx->params.jpeg_huff_tab)
-		coda9_jpeg_dec_huff_setup(ctx);
-
-	coda9_jpeg_qmat_setup(ctx);
-
-	coda9_jpeg_dec_bbc_gbu_setup(ctx, &src_buf->vb2_buf,
-				     ctx->jpeg_ecs_offset);
-
-	coda_write(dev, 0, CODA9_REG_JPEG_RST_INDEX);
-	coda_write(dev, 0, CODA9_REG_JPEG_RST_COUNT);
-
-	coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_Y);
-	coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CB);
-	coda_write(dev, 0, CODA9_REG_JPEG_DPCM_DIFF_CR);
-
-	coda_write(dev, 0, CODA9_REG_JPEG_ROT_INFO);
-
-	coda_write(dev, 1, CODA9_GDI_CONTROL);
-	do {
-		ret = coda_read(dev, CODA9_GDI_STATUS);
-	} while (!ret);
-
-	val = (chroma_format << 17) | (chroma_interleave << 16) |
-	      q_data_dst->bytesperline;
-	if (ctx->tiled_map_type == GDI_TILED_FRAME_MB_RASTER_MAP)
-		val |= 3 << 20;
-	coda_write(dev, val, CODA9_GDI_INFO_CONTROL);
-
-	coda_write(dev, aligned_width << 16 | aligned_height,
-			CODA9_GDI_INFO_PIC_SIZE);
-
-	coda_write_base(ctx, q_data_dst, dst_buf, CODA9_GDI_INFO_BASE_Y);
-
-	coda_write(dev, 0, CODA9_REG_JPEG_DPB_BASE00);
-	coda_write(dev, 0, CODA9_GDI_CONTROL);
-	coda_write(dev, 1, CODA9_GDI_PIC_INIT_HOST);
-
-	trace_coda_jpeg_run(ctx, src_buf);
-
-	coda_write(dev, 1, CODA9_REG_JPEG_PIC_START);
-
-	return 0;
-}
-
-static void coda9_jpeg_finish_decode(struct coda_ctx *ctx)
-{
-	struct coda_dev *dev = ctx->dev;
-	struct vb2_v4l2_buffer *dst_buf, *src_buf;
-	struct coda_q_data *q_data_dst;
-	u32 err_mb;
-
-	err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB);
-	if (err_mb)
-		v4l2_err(&dev->v4l2_dev, "ERRMB: 0x%x\n", err_mb);
-
-	coda_write(dev, 0, CODA9_REG_JPEG_BBC_FLUSH_CMD);
-
-	/*
-	 * Lock to make sure that a decoder stop command running in parallel
-	 * will either already have marked src_buf as last, or it will wake up
-	 * the capture queue after the buffers are returned.
-	 */
-	mutex_lock(&ctx->wakeup_mutex);
-	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
-	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
-	dst_buf->sequence = ctx->osequence++;
-
-	trace_coda_jpeg_done(ctx, dst_buf);
-
-	dst_buf->flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_LAST);
-	dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
-	dst_buf->flags |= src_buf->flags & V4L2_BUF_FLAG_LAST;
-
-	v4l2_m2m_buf_copy_metadata(src_buf, dst_buf, false);
-
-	q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	vb2_set_plane_payload(&dst_buf->vb2_buf, 0, q_data_dst->sizeimage);
-
-	v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
-	coda_m2m_buf_done(ctx, dst_buf, err_mb ? VB2_BUF_STATE_ERROR :
-						 VB2_BUF_STATE_DONE);
-
-	mutex_unlock(&ctx->wakeup_mutex);
-
-	coda_dbg(1, ctx, "job finished: decoded frame (%u)%s\n",
-		 dst_buf->sequence,
-		 (dst_buf->flags & V4L2_BUF_FLAG_LAST) ? " (last)" : "");
-
-	/*
-	 * Reset JPEG processing unit after each decode run to work
-	 * around hangups when switching context between encoder and
-	 * decoder.
-	 */
-	coda_hw_reset(ctx);
-}
-
-const struct coda_context_ops coda9_jpeg_decode_ops = {
-	.queue_init = coda_encoder_queue_init, /* non-bitstream operation */
-	.start_streaming = coda9_jpeg_start_decoding,
-	.prepare_run = coda9_jpeg_prepare_decode,
-	.finish_run = coda9_jpeg_finish_decode,
-	.release = coda9_jpeg_release,
-};
-
-irqreturn_t coda9_jpeg_irq_handler(int irq, void *data)
-{
-	struct coda_dev *dev = data;
-	struct coda_ctx *ctx;
-	int status;
-	int err_mb;
-
-	status = coda_read(dev, CODA9_REG_JPEG_PIC_STATUS);
-	if (status == 0)
-		return IRQ_HANDLED;
-	coda_write(dev, status, CODA9_REG_JPEG_PIC_STATUS);
-
-	if (status & CODA9_JPEG_STATUS_OVERFLOW)
-		v4l2_err(&dev->v4l2_dev, "JPEG overflow\n");
-
-	if (status & CODA9_JPEG_STATUS_BBC_INT)
-		v4l2_err(&dev->v4l2_dev, "JPEG BBC interrupt\n");
-
-	if (status & CODA9_JPEG_STATUS_ERROR) {
-		v4l2_err(&dev->v4l2_dev, "JPEG error\n");
-
-		err_mb = coda_read(dev, CODA9_REG_JPEG_PIC_ERRMB);
-		if (err_mb) {
-			v4l2_err(&dev->v4l2_dev,
-				 "ERRMB: 0x%x: rst idx %d, mcu pos (%d,%d)\n",
-				 err_mb, err_mb >> 24, (err_mb >> 12) & 0xfff,
-				 err_mb & 0xfff);
-		}
-	}
-
-	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
-	if (!ctx) {
-		v4l2_err(&dev->v4l2_dev,
-			 "Instance released before the end of transaction\n");
-		mutex_unlock(&dev->coda_mutex);
-		return IRQ_HANDLED;
-	}
-
-	complete(&ctx->completion);
-
-	return IRQ_HANDLED;
-}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-mpeg2.c b/drivers/media/platform/chips-media/coda-mpeg2.c
--- a/drivers/media/platform/chips-media/coda-mpeg2.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda-mpeg2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,87 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Coda multi-standard codec IP - MPEG-2 helper functions
- *
- * Copyright (C) 2019 Pengutronix, Philipp Zabel
- */
-
-#include <linux/kernel.h>
-#include <linux/videodev2.h>
-#include "coda.h"
-
-int coda_mpeg2_profile(int profile_idc)
-{
-	switch (profile_idc) {
-	case 5:
-		return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SIMPLE;
-	case 4:
-		return V4L2_MPEG_VIDEO_MPEG2_PROFILE_MAIN;
-	case 3:
-		return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SNR_SCALABLE;
-	case 2:
-		return V4L2_MPEG_VIDEO_MPEG2_PROFILE_SPATIALLY_SCALABLE;
-	case 1:
-		return V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH;
-	default:
-		return -EINVAL;
-	}
-}
-
-int coda_mpeg2_level(int level_idc)
-{
-	switch (level_idc) {
-	case 10:
-		return V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW;
-	case 8:
-		return V4L2_MPEG_VIDEO_MPEG2_LEVEL_MAIN;
-	case 6:
-		return V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH_1440;
-	case 4:
-		return V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH;
-	default:
-		return -EINVAL;
-	}
-}
-
-/*
- * Check if the buffer starts with the MPEG-2 sequence header (with or without
- * quantization matrix) and extension header, for example:
- *
- *   00 00 01 b3 2d 01 e0 34 08 8b a3 81
- *               10 11 11 12 12 12 13 13 13 13 14 14 14 14 14 15
- *               15 15 15 15 15 16 16 16 16 16 16 16 17 17 17 17
- *               17 17 17 17 18 18 18 19 18 18 18 19 1a 1a 1a 1a
- *               19 1b 1b 1b 1b 1b 1c 1c 1c 1c 1e 1e 1e 1f 1f 21
- *   00 00 01 b5 14 8a 00 01 00 00
- *
- * or:
- *
- *   00 00 01 b3 08 00 40 15 ff ff e0 28
- *   00 00 01 b5 14 8a 00 01 00 00
- *
- * Returns the detected header size in bytes or 0.
- */
-u32 coda_mpeg2_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size)
-{
-	static const u8 sequence_header_start[4] = { 0x00, 0x00, 0x01, 0xb3 };
-	static const union {
-		u8 extension_start[4];
-		u8 start_code_prefix[3];
-	} u = { { 0x00, 0x00, 0x01, 0xb5 } };
-
-	if (size < 22 ||
-	    memcmp(buf, sequence_header_start, 4) != 0)
-		return 0;
-
-	if ((size == 22 ||
-	     (size >= 25 && memcmp(buf + 22, u.start_code_prefix, 3) == 0)) &&
-	    memcmp(buf + 12, u.extension_start, 4) == 0)
-		return 22;
-
-	if ((size == 86 ||
-	     (size > 89 && memcmp(buf + 86, u.start_code_prefix, 3) == 0)) &&
-	    memcmp(buf + 76, u.extension_start, 4) == 0)
-		return 86;
-
-	return 0;
-}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda-mpeg4.c b/drivers/media/platform/chips-media/coda-mpeg4.c
--- a/drivers/media/platform/chips-media/coda-mpeg4.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda-mpeg4.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,87 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Coda multi-standard codec IP - MPEG-4 helper functions
- *
- * Copyright (C) 2019 Pengutronix, Philipp Zabel
- */
-
-#include <linux/kernel.h>
-#include <linux/videodev2.h>
-
-#include "coda.h"
-
-int coda_mpeg4_profile(int profile_idc)
-{
-	switch (profile_idc) {
-	case 0:
-		return V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE;
-	case 15:
-		return V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE;
-	case 2:
-		return V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE;
-	case 1:
-		return V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE;
-	case 11:
-		return V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY;
-	default:
-		return -EINVAL;
-	}
-}
-
-int coda_mpeg4_level(int level_idc)
-{
-	switch (level_idc) {
-	case 0:
-		return V4L2_MPEG_VIDEO_MPEG4_LEVEL_0;
-	case 1:
-		return V4L2_MPEG_VIDEO_MPEG4_LEVEL_1;
-	case 2:
-		return V4L2_MPEG_VIDEO_MPEG4_LEVEL_2;
-	case 3:
-		return V4L2_MPEG_VIDEO_MPEG4_LEVEL_3;
-	case 4:
-		return V4L2_MPEG_VIDEO_MPEG4_LEVEL_4;
-	case 5:
-		return V4L2_MPEG_VIDEO_MPEG4_LEVEL_5;
-	default:
-		return -EINVAL;
-	}
-}
-
-/*
- * Check if the buffer starts with the MPEG-4 visual object sequence and visual
- * object headers, for example:
- *
- *   00 00 01 b0 f1
- *   00 00 01 b5 a9 13 00 00 01 00 00 00 01 20 08
- *               d4 8d 88 00 f5 04 04 08 14 30 3f
- *
- * Returns the detected header size in bytes or 0.
- */
-u32 coda_mpeg4_parse_headers(struct coda_ctx *ctx, u8 *buf, u32 size)
-{
-	static const u8 vos_start[4] = { 0x00, 0x00, 0x01, 0xb0 };
-	static const union {
-		u8 vo_start[4];
-		u8 start_code_prefix[3];
-	} u = { { 0x00, 0x00, 0x01, 0xb5 } };
-
-	if (size < 30 ||
-	    memcmp(buf, vos_start, 4) != 0 ||
-	    memcmp(buf + 5, u.vo_start, 4) != 0)
-		return 0;
-
-	if (size == 30 ||
-	    (size >= 33 && memcmp(buf + 30, u.start_code_prefix, 3) == 0))
-		return 30;
-
-	if (size == 31 ||
-	    (size >= 34 && memcmp(buf + 31, u.start_code_prefix, 3) == 0))
-		return 31;
-
-	if (size == 32 ||
-	    (size >= 35 && memcmp(buf + 32, u.start_code_prefix, 3) == 0))
-		return 32;
-
-	return 0;
-}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/coda_regs.h b/drivers/media/platform/chips-media/coda_regs.h
--- a/drivers/media/platform/chips-media/coda_regs.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/coda_regs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,563 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * linux/drivers/media/platform/chips-media/coda_regs.h
- *
- * Copyright (C) 2012 Vista Silicon SL
- *    Javier Martin <javier.martin@vista-silicon.com>
- *    Xavier Duret
- */
-
-#ifndef _REGS_CODA_H_
-#define _REGS_CODA_H_
-
-/* HW registers */
-#define CODA_REG_BIT_CODE_RUN			0x000
-#define		CODA_REG_RUN_ENABLE		(1 << 0)
-#define CODA_REG_BIT_CODE_DOWN			0x004
-#define		CODA_DOWN_ADDRESS_SET(x)	(((x) & 0xffff) << 16)
-#define		CODA_DOWN_DATA_SET(x)		((x) & 0xffff)
-#define CODA_REG_BIT_HOST_IN_REQ		0x008
-#define CODA_REG_BIT_INT_CLEAR			0x00c
-#define		CODA_REG_BIT_INT_CLEAR_SET	0x1
-#define CODA_REG_BIT_INT_STATUS		0x010
-#define CODA_REG_BIT_CODE_RESET		0x014
-#define		CODA_REG_RESET_ENABLE		(1 << 0)
-#define CODA_REG_BIT_CUR_PC			0x018
-#define CODA9_REG_BIT_SW_RESET			0x024
-#define		CODA9_SW_RESET_BPU_CORE   0x008
-#define		CODA9_SW_RESET_BPU_BUS    0x010
-#define		CODA9_SW_RESET_VCE_CORE   0x020
-#define		CODA9_SW_RESET_VCE_BUS    0x040
-#define		CODA9_SW_RESET_GDI_CORE   0x080
-#define		CODA9_SW_RESET_GDI_BUS    0x100
-#define CODA9_REG_BIT_SW_RESET_STATUS		0x034
-
-/* Static SW registers */
-#define CODA_REG_BIT_CODE_BUF_ADDR		0x100
-#define CODA_REG_BIT_WORK_BUF_ADDR		0x104
-#define CODA_REG_BIT_PARA_BUF_ADDR		0x108
-#define CODA_REG_BIT_STREAM_CTRL		0x10c
-#define		CODA7_STREAM_BUF_PIC_RESET	(1 << 4)
-#define		CODADX6_STREAM_BUF_PIC_RESET	(1 << 3)
-#define		CODA7_STREAM_BUF_PIC_FLUSH	(1 << 3)
-#define		CODADX6_STREAM_BUF_PIC_FLUSH	(1 << 2)
-#define		CODA7_STREAM_BUF_DYNALLOC_EN	(1 << 5)
-#define		CODADX6_STREAM_BUF_DYNALLOC_EN	(1 << 4)
-#define		CODADX6_STREAM_CHKDIS_OFFSET	(1 << 1)
-#define		CODA7_STREAM_SEL_64BITS_ENDIAN	(1 << 1)
-#define		CODA_STREAM_ENDIAN_SELECT	(1 << 0)
-#define CODA_REG_BIT_FRAME_MEM_CTRL		0x110
-#define		CODA9_FRAME_ENABLE_BWB		(1 << 12)
-#define		CODA9_FRAME_TILED2LINEAR	(1 << 11)
-#define		CODA_FRAME_CHROMA_INTERLEAVE	(1 << 2)
-#define		CODA_IMAGE_ENDIAN_SELECT	(1 << 0)
-#define CODA_REG_BIT_BIT_STREAM_PARAM		0x114
-#define		CODA_BIT_STREAM_END_FLAG	(1 << 2)
-#define		CODA_BIT_DEC_SEQ_INIT_ESCAPE	(1 << 0)
-#define CODA_REG_BIT_TEMP_BUF_ADDR		0x118
-#define CODA_REG_BIT_RD_PTR(x)			(0x120 + 8 * (x))
-#define CODA_REG_BIT_WR_PTR(x)			(0x124 + 8 * (x))
-#define CODA_REG_BIT_FRM_DIS_FLG(x)		(0x150 + 4 * (x))
-#define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR	0x140
-#define CODA7_REG_BIT_AXI_SRAM_USE		0x140
-#define		CODA9_USE_HOST_BTP_ENABLE	(1 << 13)
-#define		CODA9_USE_HOST_OVL_ENABLE	(1 << 12)
-#define		CODA7_USE_HOST_ME_ENABLE	(1 << 11)
-#define		CODA9_USE_HOST_DBK_ENABLE	(3 << 10)
-#define		CODA7_USE_HOST_OVL_ENABLE	(1 << 10)
-#define		CODA7_USE_HOST_DBK_ENABLE	(1 << 9)
-#define		CODA9_USE_HOST_IP_ENABLE	(1 << 9)
-#define		CODA7_USE_HOST_IP_ENABLE	(1 << 8)
-#define		CODA9_USE_HOST_BIT_ENABLE	(1 << 8)
-#define		CODA7_USE_HOST_BIT_ENABLE	(1 << 7)
-#define		CODA9_USE_BTP_ENABLE		(1 << 5)
-#define		CODA7_USE_ME_ENABLE		(1 << 4)
-#define		CODA9_USE_OVL_ENABLE		(1 << 4)
-#define		CODA7_USE_OVL_ENABLE		(1 << 3)
-#define		CODA9_USE_DBK_ENABLE		(3 << 2)
-#define		CODA7_USE_DBK_ENABLE		(1 << 2)
-#define		CODA7_USE_IP_ENABLE		(1 << 1)
-#define		CODA7_USE_BIT_ENABLE		(1 << 0)
-
-#define CODA_REG_BIT_BUSY			0x160
-#define		CODA_REG_BIT_BUSY_FLAG		1
-#define CODA_REG_BIT_RUN_COMMAND		0x164
-#define		CODA_COMMAND_SEQ_INIT		1
-#define		CODA_COMMAND_SEQ_END		2
-#define		CODA_COMMAND_PIC_RUN		3
-#define		CODA_COMMAND_SET_FRAME_BUF	4
-#define		CODA_COMMAND_ENCODE_HEADER	5
-#define		CODA_COMMAND_ENC_PARA_SET	6
-#define		CODA_COMMAND_DEC_PARA_SET	7
-#define		CODA_COMMAND_DEC_BUF_FLUSH	8
-#define		CODA_COMMAND_RC_CHANGE_PARAMETER 9
-#define		CODA_COMMAND_FIRMWARE_GET	0xf
-#define CODA_REG_BIT_RUN_INDEX			0x168
-#define		CODA_INDEX_SET(x)		((x) & 0x3)
-#define CODA_REG_BIT_RUN_COD_STD		0x16c
-#define		CODADX6_MODE_DECODE_MP4		0
-#define		CODADX6_MODE_ENCODE_MP4		1
-#define		CODADX6_MODE_DECODE_H264	2
-#define		CODADX6_MODE_ENCODE_H264	3
-#define		CODA7_MODE_DECODE_H264		0
-#define		CODA7_MODE_DECODE_VC1		1
-#define		CODA7_MODE_DECODE_MP2		2
-#define		CODA7_MODE_DECODE_MP4		3
-#define		CODA7_MODE_DECODE_DV3		3
-#define		CODA7_MODE_DECODE_RV		4
-#define		CODA7_MODE_DECODE_MJPG		5
-#define		CODA7_MODE_ENCODE_H264		8
-#define		CODA7_MODE_ENCODE_MP4		11
-#define		CODA7_MODE_ENCODE_MJPG		13
-#define		CODA9_MODE_DECODE_H264		0
-#define		CODA9_MODE_DECODE_VC1		1
-#define		CODA9_MODE_DECODE_MP2		2
-#define		CODA9_MODE_DECODE_MP4		3
-#define		CODA9_MODE_DECODE_DV3		3
-#define		CODA9_MODE_DECODE_RV		4
-#define		CODA9_MODE_DECODE_AVS		5
-#define		CODA9_MODE_DECODE_MJPG		6
-#define		CODA9_MODE_DECODE_VPX		7
-#define		CODA9_MODE_ENCODE_H264		8
-#define		CODA9_MODE_ENCODE_MP4		11
-#define		CODA9_MODE_ENCODE_MJPG		13
-#define		CODA_MODE_INVALID		0xffff
-#define CODA_REG_BIT_INT_ENABLE		0x170
-#define		CODA_INT_INTERRUPT_ENABLE	(1 << 3)
-#define CODA_REG_BIT_INT_REASON			0x174
-#define CODA7_REG_BIT_RUN_AUX_STD		0x178
-#define		CODA_MP4_AUX_MPEG4		0
-#define		CODA_MP4_AUX_DIVX3		1
-#define		CODA_VPX_AUX_THO		0
-#define		CODA_VPX_AUX_VP6		1
-#define		CODA_VPX_AUX_VP8		2
-#define		CODA_H264_AUX_AVC		0
-#define		CODA_H264_AUX_MVC		1
-
-/*
- * Commands' mailbox:
- * registers with offsets in the range 0x180-0x1d0
- * have different meaning depending on the command being
- * issued.
- */
-
-/* Decoder Sequence Initialization */
-#define CODA_CMD_DEC_SEQ_BB_START		0x180
-#define CODA_CMD_DEC_SEQ_BB_SIZE		0x184
-#define CODA_CMD_DEC_SEQ_OPTION			0x188
-#define		CODA_NO_INT_ENABLE			(1 << 10)
-#define		CODA_REORDER_ENABLE			(1 << 1)
-#define		CODADX6_QP_REPORT			(1 << 0)
-#define		CODA7_MP4_DEBLK_ENABLE			(1 << 0)
-#define CODA_CMD_DEC_SEQ_SRC_SIZE		0x18c
-#define CODA_CMD_DEC_SEQ_START_BYTE		0x190
-#define CODA_CMD_DEC_SEQ_PS_BB_START		0x194
-#define CODA_CMD_DEC_SEQ_PS_BB_SIZE		0x198
-#define CODA_CMD_DEC_SEQ_JPG_THUMB_EN		0x19c
-#define CODA_CMD_DEC_SEQ_MP4_ASP_CLASS		0x19c
-#define		CODA_MP4_CLASS_MPEG4			0
-#define CODA_CMD_DEC_SEQ_X264_MV_EN		0x19c
-#define CODA_CMD_DEC_SEQ_SPP_CHUNK_SIZE		0x1a0
-
-#define CODA7_RET_DEC_SEQ_ASPECT		0x1b0
-#define CODA9_RET_DEC_SEQ_BITRATE		0x1b4
-#define CODA_RET_DEC_SEQ_SUCCESS		0x1c0
-#define CODA_RET_DEC_SEQ_SRC_FMT		0x1c4 /* SRC_SIZE on CODA7 */
-#define CODA_RET_DEC_SEQ_SRC_SIZE		0x1c4
-#define CODA_RET_DEC_SEQ_SRC_F_RATE		0x1c8
-#define CODA9_RET_DEC_SEQ_ASPECT		0x1c8
-#define CODA_RET_DEC_SEQ_FRAME_NEED		0x1cc
-#define CODA_RET_DEC_SEQ_FRAME_DELAY		0x1d0
-#define CODA_RET_DEC_SEQ_INFO			0x1d4
-#define CODA_RET_DEC_SEQ_CROP_LEFT_RIGHT	0x1d8
-#define CODA_RET_DEC_SEQ_CROP_TOP_BOTTOM	0x1dc
-#define CODA_RET_DEC_SEQ_NEXT_FRAME_NUM		0x1e0
-#define CODA_RET_DEC_SEQ_ERR_REASON		0x1e0
-#define CODA_RET_DEC_SEQ_FRATE_NR		0x1e4
-#define CODA_RET_DEC_SEQ_FRATE_DR		0x1e8
-#define CODA_RET_DEC_SEQ_JPG_PARA		0x1e4
-#define CODA_RET_DEC_SEQ_JPG_THUMB_IND		0x1e8
-#define CODA7_RET_DEC_SEQ_HEADER_REPORT		0x1ec
-
-/* Decoder Picture Run */
-#define CODA_CMD_DEC_PIC_ROT_MODE		0x180
-#define CODA_CMD_DEC_PIC_ROT_ADDR_Y		0x184
-#define CODA9_CMD_DEC_PIC_ROT_INDEX		0x184
-#define CODA_CMD_DEC_PIC_ROT_ADDR_CB		0x188
-#define CODA9_CMD_DEC_PIC_ROT_ADDR_Y		0x188
-#define CODA_CMD_DEC_PIC_ROT_ADDR_CR		0x18c
-#define CODA9_CMD_DEC_PIC_ROT_ADDR_CB		0x18c
-#define CODA_CMD_DEC_PIC_ROT_STRIDE		0x190
-#define CODA9_CMD_DEC_PIC_ROT_ADDR_CR		0x190
-#define CODA9_CMD_DEC_PIC_ROT_STRIDE		0x1b8
-
-#define CODA_CMD_DEC_PIC_OPTION			0x194
-#define		CODA_PRE_SCAN_EN			(1 << 0)
-#define		CODA_PRE_SCAN_MODE_DECODE		(0 << 1)
-#define		CODA_PRE_SCAN_MODE_RETURN		(1 << 1)
-#define		CODA_IFRAME_SEARCH_EN			(1 << 2)
-#define		CODA_SKIP_FRAME_MODE			(0x3 << 3)
-#define CODA_CMD_DEC_PIC_SKIP_NUM		0x198
-#define CODA_CMD_DEC_PIC_CHUNK_SIZE		0x19c
-#define CODA_CMD_DEC_PIC_BB_START		0x1a0
-#define CODA_CMD_DEC_PIC_START_BYTE		0x1a4
-#define CODA_RET_DEC_PIC_SIZE			0x1bc
-#define CODA_RET_DEC_PIC_FRAME_NUM		0x1c0
-#define CODA_RET_DEC_PIC_FRAME_IDX		0x1c4
-#define CODA_RET_DEC_PIC_ERR_MB			0x1c8
-#define CODA_RET_DEC_PIC_TYPE			0x1cc
-#define		CODA_PIC_TYPE_MASK			0x7
-#define		CODA_PIC_TYPE_MASK_VC1			0x3f
-#define		CODA9_PIC_TYPE_FIRST_MASK		(0x7 << 3)
-#define		CODA9_PIC_TYPE_IDR_MASK			(0x3 << 6)
-#define		CODA7_PIC_TYPE_H264_NPF_MASK		(0x3 << 16)
-#define		CODA7_PIC_TYPE_INTERLACED		(1 << 18)
-#define CODA_RET_DEC_PIC_POST			0x1d0
-#define CODA_RET_DEC_PIC_MVC_REPORT		0x1d0
-#define CODA_RET_DEC_PIC_OPTION			0x1d4
-#define CODA_RET_DEC_PIC_SUCCESS		0x1d8
-#define CODA_RET_DEC_PIC_CUR_IDX		0x1dc
-#define CODA_RET_DEC_PIC_CROP_LEFT_RIGHT	0x1e0
-#define CODA_RET_DEC_PIC_CROP_TOP_BOTTOM	0x1e4
-#define CODA_RET_DEC_PIC_FRAME_NEED		0x1ec
-
-#define CODA9_RET_DEC_PIC_VP8_PIC_REPORT	0x1e8
-#define CODA9_RET_DEC_PIC_ASPECT		0x1f0
-#define CODA9_RET_DEC_PIC_VP8_SCALE_INFO	0x1f0
-#define CODA9_RET_DEC_PIC_FRATE_NR		0x1f4
-#define CODA9_RET_DEC_PIC_FRATE_DR		0x1f8
-
-/* Encoder Sequence Initialization */
-#define CODA_CMD_ENC_SEQ_BB_START				0x180
-#define CODA_CMD_ENC_SEQ_BB_SIZE				0x184
-#define CODA_CMD_ENC_SEQ_OPTION				0x188
-#define		CODA7_OPTION_AVCINTRA16X16ONLY_OFFSET		9
-#define		CODA9_OPTION_MVC_PREFIX_NAL_OFFSET		9
-#define		CODA7_OPTION_GAMMA_OFFSET			8
-#define		CODA9_OPTION_MVC_PARASET_REFRESH_OFFSET		8
-#define		CODA7_OPTION_RCQPMAX_OFFSET			7
-#define		CODA9_OPTION_GAMMA_OFFSET			7
-#define		CODADX6_OPTION_GAMMA_OFFSET			7
-#define		CODA7_OPTION_RCQPMIN_OFFSET			6
-#define		CODA9_OPTION_RCQPMAX_OFFSET			6
-#define		CODA_OPTION_LIMITQP_OFFSET			6
-#define		CODA_OPTION_RCINTRAQP_OFFSET			5
-#define		CODA_OPTION_FMO_OFFSET				4
-#define		CODA9_OPTION_MVC_INTERVIEW_OFFSET		4
-#define		CODA_OPTION_AVC_AUD_OFFSET			2
-#define		CODA_OPTION_SLICEREPORT_OFFSET			1
-#define CODA_CMD_ENC_SEQ_COD_STD				0x18c
-#define		CODA_STD_MPEG4					0
-#define		CODA9_STD_H264					0
-#define		CODA_STD_H263					1
-#define		CODA_STD_H264					2
-#define		CODA9_STD_MPEG4					3
-
-#define CODA_CMD_ENC_SEQ_SRC_SIZE				0x190
-#define		CODA7_PICWIDTH_OFFSET				16
-#define		CODA7_PICWIDTH_MASK				0xffff
-#define		CODADX6_PICWIDTH_OFFSET				10
-#define		CODADX6_PICWIDTH_MASK				0x3ff
-#define		CODA_PICHEIGHT_OFFSET				0
-#define		CODADX6_PICHEIGHT_MASK				0x3ff
-#define		CODA7_PICHEIGHT_MASK				0xffff
-#define CODA_CMD_ENC_SEQ_SRC_F_RATE				0x194
-#define		CODA_FRATE_RES_OFFSET				0
-#define		CODA_FRATE_RES_MASK				0xffff
-#define		CODA_FRATE_DIV_OFFSET				16
-#define		CODA_FRATE_DIV_MASK				0xffff
-#define CODA_CMD_ENC_SEQ_MP4_PARA				0x198
-#define		CODA_MP4PARAM_VERID_OFFSET			6
-#define		CODA_MP4PARAM_VERID_MASK			0x01
-#define		CODA_MP4PARAM_INTRADCVLCTHR_OFFSET		2
-#define		CODA_MP4PARAM_INTRADCVLCTHR_MASK		0x07
-#define		CODA_MP4PARAM_REVERSIBLEVLCENABLE_OFFSET	1
-#define		CODA_MP4PARAM_REVERSIBLEVLCENABLE_MASK		0x01
-#define		CODA_MP4PARAM_DATAPARTITIONENABLE_OFFSET	0
-#define		CODA_MP4PARAM_DATAPARTITIONENABLE_MASK		0x01
-#define CODA_CMD_ENC_SEQ_263_PARA				0x19c
-#define		CODA_263PARAM_ANNEXJENABLE_OFFSET		2
-#define		CODA_263PARAM_ANNEXJENABLE_MASK		0x01
-#define		CODA_263PARAM_ANNEXKENABLE_OFFSET		1
-#define		CODA_263PARAM_ANNEXKENABLE_MASK		0x01
-#define		CODA_263PARAM_ANNEXTENABLE_OFFSET		0
-#define		CODA_263PARAM_ANNEXTENABLE_MASK		0x01
-#define CODA_CMD_ENC_SEQ_264_PARA				0x1a0
-#define		CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET	12
-#define		CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK	0x0f
-#define		CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET	8
-#define		CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK	0x0f
-#define		CODA_264PARAM_DISABLEDEBLK_OFFSET		6
-#define		CODA_264PARAM_DISABLEDEBLK_MASK		0x03
-#define		CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_OFFSET	5
-#define		CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_MASK	0x01
-#define		CODA_264PARAM_CHROMAQPOFFSET_OFFSET		0
-#define		CODA_264PARAM_CHROMAQPOFFSET_MASK		0x1f
-#define CODA_CMD_ENC_SEQ_SLICE_MODE				0x1a4
-#define		CODA_SLICING_SIZE_OFFSET			2
-#define		CODA_SLICING_SIZE_MASK				0x3fffffff
-#define		CODA_SLICING_UNIT_OFFSET			1
-#define		CODA_SLICING_UNIT_MASK				0x01
-#define		CODA_SLICING_MODE_OFFSET			0
-#define		CODA_SLICING_MODE_MASK				0x01
-#define CODA_CMD_ENC_SEQ_GOP_SIZE				0x1a8
-#define		CODA_GOP_SIZE_OFFSET				0
-#define		CODA_GOP_SIZE_MASK				0x3f
-#define CODA_CMD_ENC_SEQ_RC_PARA				0x1ac
-#define		CODA_RATECONTROL_AUTOSKIP_OFFSET		31
-#define		CODA_RATECONTROL_AUTOSKIP_MASK			0x01
-#define		CODA_RATECONTROL_INITIALDELAY_OFFSET		16
-#define		CODA_RATECONTROL_INITIALDELAY_MASK		0x7fff
-#define		CODA_RATECONTROL_BITRATE_OFFSET		1
-#define		CODA_RATECONTROL_BITRATE_MASK			0x7fff
-#define		CODA_RATECONTROL_ENABLE_OFFSET			0
-#define		CODA_RATECONTROL_ENABLE_MASK			0x01
-#define CODA_CMD_ENC_SEQ_RC_BUF_SIZE				0x1b0
-#define CODA_CMD_ENC_SEQ_INTRA_REFRESH				0x1b4
-#define CODADX6_CMD_ENC_SEQ_FMO					0x1b8
-#define		CODA_FMOPARAM_TYPE_OFFSET			4
-#define		CODA_FMOPARAM_TYPE_MASK				1
-#define		CODA_FMOPARAM_SLICENUM_OFFSET			0
-#define		CODA_FMOPARAM_SLICENUM_MASK			0x0f
-#define CODADX6_CMD_ENC_SEQ_INTRA_QP				0x1bc
-#define CODA7_CMD_ENC_SEQ_SEARCH_BASE				0x1b8
-#define CODA7_CMD_ENC_SEQ_SEARCH_SIZE				0x1bc
-#define CODA7_CMD_ENC_SEQ_INTRA_QP				0x1c4
-#define CODA_CMD_ENC_SEQ_RC_QP_MIN_MAX				0x1c8
-#define		CODA_QPMIN_OFFSET				8
-#define		CODA_QPMIN_MASK					0x3f
-#define		CODA_QPMAX_OFFSET				0
-#define		CODA_QPMAX_MASK					0x3f
-#define CODA_CMD_ENC_SEQ_RC_GAMMA				0x1cc
-#define		CODA_GAMMA_OFFSET				0
-#define		CODA_GAMMA_MASK					0xffff
-#define CODA_CMD_ENC_SEQ_RC_INTERVAL_MODE			0x1d0
-#define CODA9_CMD_ENC_SEQ_INTRA_WEIGHT				0x1d4
-#define CODA9_CMD_ENC_SEQ_ME_OPTION				0x1d8
-#define CODA_RET_ENC_SEQ_SUCCESS				0x1c0
-
-#define CODA_CMD_ENC_SEQ_JPG_PARA				0x198
-#define CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL			0x19C
-#define CODA_CMD_ENC_SEQ_JPG_THUMB_EN				0x1a0
-#define CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE				0x1a4
-#define CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET			0x1a8
-
-/* Encoder Parameter Change */
-#define CODA_CMD_ENC_PARAM_CHANGE_ENABLE	0x180
-#define		CODA_PARAM_CHANGE_RC_GOP			BIT(0)
-#define		CODA_PARAM_CHANGE_RC_INTRA_QP			BIT(1)
-#define		CODA_PARAM_CHANGE_RC_BITRATE			BIT(2)
-#define		CODA_PARAM_CHANGE_RC_FRAME_RATE			BIT(3)
-#define		CODA_PARAM_CHANGE_INTRA_MB_NUM			BIT(4)
-#define		CODA_PARAM_CHANGE_SLICE_MODE			BIT(5)
-#define		CODA_PARAM_CHANGE_HEC_MODE			BIT(6)
-#define CODA_CMD_ENC_PARAM_RC_GOP		0x184
-#define CODA_CMD_ENC_PARAM_RC_INTRA_QP		0x188
-#define CODA_CMD_ENC_PARAM_RC_BITRATE		0x18c
-#define CODA_CMD_ENC_PARAM_RC_FRAME_RATE	0x190
-#define CODA_CMD_ENC_PARAM_INTRA_MB_NUM		0x194
-#define CODA_CMD_ENC_PARAM_SLICE_MODE		0x198
-#define CODA_CMD_ENC_PARAM_HEC_MODE		0x19c
-#define CODA_RET_ENC_PARAM_CHANGE_SUCCESS	0x1c0
-
-/* Encoder Picture Run */
-#define CODA9_CMD_ENC_PIC_SRC_INDEX		0x180
-#define CODA9_CMD_ENC_PIC_SRC_STRIDE		0x184
-#define CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC	0x1a4
-#define CODA9_CMD_ENC_PIC_SRC_ADDR_Y		0x1a8
-#define CODA9_CMD_ENC_PIC_SRC_ADDR_CB		0x1ac
-#define CODA9_CMD_ENC_PIC_SRC_ADDR_CR		0x1b0
-#define CODA_CMD_ENC_PIC_SRC_ADDR_Y	0x180
-#define CODA_CMD_ENC_PIC_SRC_ADDR_CB	0x184
-#define CODA_CMD_ENC_PIC_SRC_ADDR_CR	0x188
-#define CODA_CMD_ENC_PIC_QS		0x18c
-#define CODA_CMD_ENC_PIC_ROT_MODE	0x190
-#define		CODA_ROT_MIR_ENABLE				(1 << 4)
-#define		CODA_ROT_0					(0x0 << 0)
-#define		CODA_ROT_90					(0x1 << 0)
-#define		CODA_ROT_180					(0x2 << 0)
-#define		CODA_ROT_270					(0x3 << 0)
-#define		CODA_MIR_NONE					(0x0 << 2)
-#define		CODA_MIR_VER					(0x1 << 2)
-#define		CODA_MIR_HOR					(0x2 << 2)
-#define		CODA_MIR_VER_HOR				(0x3 << 2)
-#define CODA_CMD_ENC_PIC_OPTION		0x194
-#define		CODA_FORCE_IPICTURE				BIT(1)
-#define		CODA_REPORT_MB_INFO				BIT(3)
-#define		CODA_REPORT_MV_INFO				BIT(4)
-#define		CODA_REPORT_SLICE_INFO				BIT(5)
-#define CODA_CMD_ENC_PIC_BB_START	0x198
-#define CODA_CMD_ENC_PIC_BB_SIZE	0x19c
-#define CODA_RET_ENC_FRAME_NUM		0x1c0
-#define CODA_RET_ENC_PIC_TYPE		0x1c4
-#define CODA_RET_ENC_PIC_FRAME_IDX	0x1c8
-#define CODA_RET_ENC_PIC_SLICE_NUM	0x1cc
-#define CODA_RET_ENC_PIC_FLAG		0x1d0
-#define CODA_RET_ENC_PIC_SUCCESS	0x1d8
-
-/* Set Frame Buffer */
-#define CODA_CMD_SET_FRAME_BUF_NUM		0x180
-#define CODA_CMD_SET_FRAME_BUF_STRIDE		0x184
-#define CODA_CMD_SET_FRAME_SLICE_BB_START	0x188
-#define CODA_CMD_SET_FRAME_SLICE_BB_SIZE	0x18c
-#define CODA9_CMD_SET_FRAME_SUBSAMP_A		0x188
-#define CODA9_CMD_SET_FRAME_SUBSAMP_B		0x18c
-#define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR	0x190
-#define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR	0x194
-#define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR	0x198
-#define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR	0x19c
-#define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR	0x1a0
-#define CODA7_CMD_SET_FRAME_MAX_DEC_SIZE	0x1a4
-#define CODA9_CMD_SET_FRAME_AXI_BTP_ADDR	0x1a4
-#define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE	0x1a8
-#define CODA9_CMD_SET_FRAME_CACHE_SIZE		0x1a8
-#define CODA9_CMD_SET_FRAME_CACHE_CONFIG	0x1ac
-#define		CODA9_CACHE_BYPASS_OFFSET		28
-#define		CODA9_CACHE_DUALCONF_OFFSET		26
-#define		CODA9_CACHE_PAGEMERGE_OFFSET		24
-#define		CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET	16
-#define		CODA9_CACHE_CB_BUFFER_SIZE_OFFSET	8
-#define		CODA9_CACHE_CR_BUFFER_SIZE_OFFSET	0
-#define CODA9_CMD_SET_FRAME_SUBSAMP_A_MVC	0x1b0
-#define CODA9_CMD_SET_FRAME_SUBSAMP_B_MVC	0x1b4
-#define CODA9_CMD_SET_FRAME_DP_BUF_BASE		0x1b0
-#define CODA9_CMD_SET_FRAME_DP_BUF_SIZE		0x1b4
-#define CODA9_CMD_SET_FRAME_MAX_DEC_SIZE	0x1b8
-#define CODA9_CMD_SET_FRAME_DELAY		0x1bc
-
-/* Encoder Header */
-#define CODA_CMD_ENC_HEADER_CODE	0x180
-#define		CODA_GAMMA_OFFSET	0
-#define		CODA_HEADER_H264_SPS	0
-#define		CODA_HEADER_H264_PPS	1
-#define		CODA_HEADER_MP4V_VOL	0
-#define		CODA_HEADER_MP4V_VOS	1
-#define		CODA_HEADER_MP4V_VIS	2
-#define		CODA9_HEADER_FRAME_CROP	(1 << 3)
-#define CODA_CMD_ENC_HEADER_BB_START	0x184
-#define CODA_CMD_ENC_HEADER_BB_SIZE	0x188
-#define CODA9_CMD_ENC_HEADER_FRAME_CROP_H	0x18c
-#define CODA9_CMD_ENC_HEADER_FRAME_CROP_V	0x190
-
-/* Get Version */
-#define CODA_CMD_FIRMWARE_VERNUM		0x1c0
-#define		CODA_FIRMWARE_PRODUCT(x)	(((x) >> 16) & 0xffff)
-#define		CODA_FIRMWARE_MAJOR(x)		(((x) >> 12) & 0x0f)
-#define		CODA_FIRMWARE_MINOR(x)		(((x) >> 8) & 0x0f)
-#define		CODA_FIRMWARE_RELEASE(x)	((x) & 0xff)
-#define		CODA_FIRMWARE_VERNUM(product, major, minor, release)	\
-			((product) << 16 | ((major) << 12) |		\
-			((minor) << 8) | (release))
-#define CODA9_CMD_FIRMWARE_CODE_REV		0x1c4
-
-#define CODA9_GDMA_BASE				0x1000
-#define CODA9_GDI_CONTROL			(CODA9_GDMA_BASE + 0x034)
-#define CODA9_GDI_PIC_INIT_HOST			(CODA9_GDMA_BASE + 0x038)
-#define CODA9_GDI_STATUS			(CODA9_GDMA_BASE + 0x080)
-#define CODA9_GDI_WPROT_ERR_CLR			(CODA9_GDMA_BASE + 0x0a0)
-#define CODA9_GDI_WPROT_RGN_EN			(CODA9_GDMA_BASE + 0x0ac)
-
-#define CODA9_GDI_BUS_CTRL			(CODA9_GDMA_BASE + 0x0f0)
-#define CODA9_GDI_BUS_STATUS			(CODA9_GDMA_BASE + 0x0f4)
-
-#define CODA9_GDI_INFO_CONTROL			(CODA9_GDMA_BASE + 0x400)
-#define CODA9_GDI_INFO_PIC_SIZE			(CODA9_GDMA_BASE + 0x404)
-#define CODA9_GDI_INFO_BASE_Y			(CODA9_GDMA_BASE + 0x408)
-#define CODA9_GDI_INFO_BASE_CB			(CODA9_GDMA_BASE + 0x40c)
-#define CODA9_GDI_INFO_BASE_CR			(CODA9_GDMA_BASE + 0x410)
-
-#define CODA9_GDI_XY2_CAS_0			(CODA9_GDMA_BASE + 0x800)
-#define CODA9_GDI_XY2_CAS_F			(CODA9_GDMA_BASE + 0x83c)
-
-#define CODA9_GDI_XY2_BA_0			(CODA9_GDMA_BASE + 0x840)
-#define CODA9_GDI_XY2_BA_1			(CODA9_GDMA_BASE + 0x844)
-#define CODA9_GDI_XY2_BA_2			(CODA9_GDMA_BASE + 0x848)
-#define CODA9_GDI_XY2_BA_3			(CODA9_GDMA_BASE + 0x84c)
-
-#define CODA9_GDI_XY2_RAS_0			(CODA9_GDMA_BASE + 0x850)
-#define CODA9_GDI_XY2_RAS_F			(CODA9_GDMA_BASE + 0x88c)
-
-#define CODA9_GDI_XY2_RBC_CONFIG		(CODA9_GDMA_BASE + 0x890)
-#define		CODA9_XY2RBC_SEPARATE_MAP		BIT(19)
-#define		CODA9_XY2RBC_TOP_BOT_SPLIT		BIT(18)
-#define		CODA9_XY2RBC_TILED_MAP			BIT(17)
-#define		CODA9_XY2RBC_CA_INC_HOR			BIT(16)
-#define CODA9_GDI_RBC2_AXI_0			(CODA9_GDMA_BASE + 0x8a0)
-#define CODA9_GDI_RBC2_AXI_1F			(CODA9_GDMA_BASE + 0x91c)
-#define	CODA9_GDI_TILEDBUF_BASE			(CODA9_GDMA_BASE + 0x920)
-
-#define CODA9_JPEG_BASE				0x3000
-#define CODA9_REG_JPEG_PIC_START		(CODA9_JPEG_BASE + 0x000)
-#define CODA9_REG_JPEG_PIC_STATUS		(CODA9_JPEG_BASE + 0x004)
-#define		CODA9_JPEG_STATUS_OVERFLOW		BIT(3)
-#define		CODA9_JPEG_STATUS_BBC_INT		BIT(2)
-#define		CODA9_JPEG_STATUS_ERROR			BIT(1)
-#define		CODA9_JPEG_STATUS_DONE			BIT(0)
-#define CODA9_REG_JPEG_PIC_ERRMB		(CODA9_JPEG_BASE + 0x008)
-#define		CODA9_JPEG_ERRMB_RESTART_IDX_MASK	(0xf << 24)
-#define		CODA9_JPEG_ERRMB_MCU_POS_X_MASK		(0xfff << 12)
-#define		CODA9_JPEG_ERRMB_MCU_POS_Y_MASK		0xfff
-#define CODA9_REG_JPEG_PIC_CTRL			(CODA9_JPEG_BASE + 0x010)
-#define		CODA9_JPEG_PIC_CTRL_USER_HUFFMAN_EN	BIT(6)
-#define		CODA9_JPEG_PIC_CTRL_TC_DIRECTION	BIT(4)
-#define		CODA9_JPEG_PIC_CTRL_ENCODER_EN		BIT(3)
-#define CODA9_REG_JPEG_PIC_SIZE			(CODA9_JPEG_BASE + 0x014)
-#define CODA9_REG_JPEG_MCU_INFO			(CODA9_JPEG_BASE + 0x018)
-#define		CODA9_JPEG_MCU_BLOCK_NUM_OFFSET		16
-#define		CODA9_JPEG_COMP_NUM_OFFSET		12
-#define		CODA9_JPEG_COMP0_INFO_OFFSET		8
-#define		CODA9_JPEG_COMP1_INFO_OFFSET		4
-#define		CODA9_JPEG_COMP2_INFO_OFFSET		0
-#define CODA9_REG_JPEG_ROT_INFO			(CODA9_JPEG_BASE + 0x01c)
-#define		CODA9_JPEG_ROT_MIR_ENABLE		BIT(4)
-#define		CODA9_JPEG_ROT_MIR_MODE_MASK		0xf
-#define CODA9_REG_JPEG_SCL_INFO			(CODA9_JPEG_BASE + 0x020)
-#define		CODA9_JPEG_SCL_ENABLE			BIT(4)
-#define		CODA9_JPEG_SCL_HOR_MODE_MASK		(0x3 << 2)
-#define		CODA9_JPEG_SCL_VER_MODE_MASK		(0x3 << 0)
-#define CODA9_REG_JPEG_IF_INFO			(CODA9_JPEG_BASE + 0x024)
-#define		CODA9_JPEG_SENS_IF_CLR			BIT(1)
-#define		CODA9_JPEG_DISP_IF_CLR			BIT(0)
-#define CODA9_REG_JPEG_OP_INFO			(CODA9_JPEG_BASE + 0x02c)
-#define		CODA9_JPEG_BUS_REQ_NUM_OFFSET		0
-#define		CODA9_JPEG_BUS_REQ_NUM_MASK		0x7
-#define CODA9_REG_JPEG_DPB_CONFIG		(CODA9_JPEG_BASE + 0x030)
-#define CODA9_REG_JPEG_DPB_BASE00		(CODA9_JPEG_BASE + 0x040)
-#define CODA9_REG_JPEG_HUFF_CTRL		(CODA9_JPEG_BASE + 0x080)
-#define CODA9_REG_JPEG_HUFF_ADDR		(CODA9_JPEG_BASE + 0x084)
-#define CODA9_REG_JPEG_HUFF_DATA		(CODA9_JPEG_BASE + 0x088)
-#define CODA9_REG_JPEG_QMAT_CTRL		(CODA9_JPEG_BASE + 0x090)
-#define CODA9_REG_JPEG_QMAT_ADDR		(CODA9_JPEG_BASE + 0x094)
-#define CODA9_REG_JPEG_QMAT_DATA		(CODA9_JPEG_BASE + 0x098)
-#define CODA9_REG_JPEG_RST_INTVAL		(CODA9_JPEG_BASE + 0x0b0)
-#define CODA9_REG_JPEG_RST_INDEX		(CODA9_JPEG_BASE + 0x0b4)
-#define CODA9_REG_JPEG_RST_COUNT		(CODA9_JPEG_BASE + 0x0b8)
-#define CODA9_REG_JPEG_DPCM_DIFF_Y		(CODA9_JPEG_BASE + 0x0f0)
-#define CODA9_REG_JPEG_DPCM_DIFF_CB		(CODA9_JPEG_BASE + 0x0f4)
-#define CODA9_REG_JPEG_DPCM_DIFF_CR		(CODA9_JPEG_BASE + 0x0f8)
-#define CODA9_REG_JPEG_GBU_CTRL			(CODA9_JPEG_BASE + 0x100)
-#define CODA9_REG_JPEG_GBU_BT_PTR		(CODA9_JPEG_BASE + 0x110)
-#define CODA9_REG_JPEG_GBU_WD_PTR		(CODA9_JPEG_BASE + 0x114)
-#define CODA9_REG_JPEG_GBU_TT_CNT		(CODA9_JPEG_BASE + 0x118)
-#define CODA9_REG_JPEG_GBU_BBSR			(CODA9_JPEG_BASE + 0x140)
-#define CODA9_REG_JPEG_GBU_BBER			(CODA9_JPEG_BASE + 0x144)
-#define CODA9_REG_JPEG_GBU_BBIR			(CODA9_JPEG_BASE + 0x148)
-#define CODA9_REG_JPEG_GBU_BBHR			(CODA9_JPEG_BASE + 0x14c)
-#define CODA9_REG_JPEG_GBU_BCNT			(CODA9_JPEG_BASE + 0x158)
-#define CODA9_REG_JPEG_GBU_FF_RPTR		(CODA9_JPEG_BASE + 0x160)
-#define CODA9_REG_JPEG_GBU_FF_WPTR		(CODA9_JPEG_BASE + 0x164)
-#define CODA9_REG_JPEG_BBC_END_ADDR		(CODA9_JPEG_BASE + 0x208)
-#define CODA9_REG_JPEG_BBC_WR_PTR		(CODA9_JPEG_BASE + 0x20c)
-#define CODA9_REG_JPEG_BBC_RD_PTR		(CODA9_JPEG_BASE + 0x210)
-#define CODA9_REG_JPEG_BBC_EXT_ADDR		(CODA9_JPEG_BASE + 0x214)
-#define CODA9_REG_JPEG_BBC_INT_ADDR		(CODA9_JPEG_BASE + 0x218)
-#define CODA9_REG_JPEG_BBC_DATA_CNT		(CODA9_JPEG_BASE + 0x21c)
-#define CODA9_REG_JPEG_BBC_COMMAND		(CODA9_JPEG_BASE + 0x220)
-#define CODA9_REG_JPEG_BBC_BUSY			(CODA9_JPEG_BASE + 0x224)
-#define CODA9_REG_JPEG_BBC_CTRL			(CODA9_JPEG_BASE + 0x228)
-#define CODA9_REG_JPEG_BBC_CUR_POS		(CODA9_JPEG_BASE + 0x22c)
-#define CODA9_REG_JPEG_BBC_BAS_ADDR		(CODA9_JPEG_BASE + 0x230)
-#define CODA9_REG_JPEG_BBC_STRM_CTRL		(CODA9_JPEG_BASE + 0x234)
-#define CODA9_REG_JPEG_BBC_FLUSH_CMD		(CODA9_JPEG_BASE + 0x238)
-
-#endif
diff -Naur --no-dereference a/drivers/media/platform/chips-media/imx-vdoa.c b/drivers/media/platform/chips-media/imx-vdoa.c
--- a/drivers/media/platform/chips-media/imx-vdoa.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/imx-vdoa.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,352 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * i.MX6 Video Data Order Adapter (VDOA)
- *
- * Copyright (C) 2014 Philipp Zabel
- * Copyright (C) 2016 Pengutronix, Michael Tretter <kernel@pengutronix.de>
- */
-
-#include <linux/clk.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/mod_devicetable.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/videodev2.h>
-#include <linux/slab.h>
-
-#include "imx-vdoa.h"
-
-#define VDOA_NAME "imx-vdoa"
-
-#define VDOAC		0x00
-#define VDOASRR		0x04
-#define VDOAIE		0x08
-#define VDOAIST		0x0c
-#define VDOAFP		0x10
-#define VDOAIEBA00	0x14
-#define VDOAIEBA01	0x18
-#define VDOAIEBA02	0x1c
-#define VDOAIEBA10	0x20
-#define VDOAIEBA11	0x24
-#define VDOAIEBA12	0x28
-#define VDOASL		0x2c
-#define VDOAIUBO	0x30
-#define VDOAVEBA0	0x34
-#define VDOAVEBA1	0x38
-#define VDOAVEBA2	0x3c
-#define VDOAVUBO	0x40
-#define VDOASR		0x44
-
-#define VDOAC_ISEL		BIT(6)
-#define VDOAC_PFS		BIT(5)
-#define VDOAC_SO		BIT(4)
-#define VDOAC_SYNC		BIT(3)
-#define VDOAC_NF		BIT(2)
-#define VDOAC_BNDM_MASK		0x3
-#define VDOAC_BAND_HEIGHT_8	0x0
-#define VDOAC_BAND_HEIGHT_16	0x1
-#define VDOAC_BAND_HEIGHT_32	0x2
-
-#define VDOASRR_START		BIT(1)
-#define VDOASRR_SWRST		BIT(0)
-
-#define VDOAIE_EITERR		BIT(1)
-#define VDOAIE_EIEOT		BIT(0)
-
-#define VDOAIST_TERR		BIT(1)
-#define VDOAIST_EOT		BIT(0)
-
-#define VDOAFP_FH_MASK		(0x1fff << 16)
-#define VDOAFP_FW_MASK		(0x3fff)
-
-#define VDOASL_VSLY_MASK	(0x3fff << 16)
-#define VDOASL_ISLY_MASK	(0x7fff)
-
-#define VDOASR_ERRW		BIT(4)
-#define VDOASR_EOB		BIT(3)
-#define VDOASR_CURRENT_FRAME	(0x3 << 1)
-#define VDOASR_CURRENT_BUFFER	BIT(1)
-
-enum {
-	V4L2_M2M_SRC = 0,
-	V4L2_M2M_DST = 1,
-};
-
-struct vdoa_data {
-	struct vdoa_ctx		*curr_ctx;
-	struct device		*dev;
-	struct clk		*vdoa_clk;
-	void __iomem		*regs;
-};
-
-struct vdoa_q_data {
-	unsigned int	width;
-	unsigned int	height;
-	unsigned int	bytesperline;
-	unsigned int	sizeimage;
-	u32		pixelformat;
-};
-
-struct vdoa_ctx {
-	struct vdoa_data	*vdoa;
-	struct completion	completion;
-	struct vdoa_q_data	q_data[2];
-	unsigned int		submitted_job;
-	unsigned int		completed_job;
-};
-
-static irqreturn_t vdoa_irq_handler(int irq, void *data)
-{
-	struct vdoa_data *vdoa = data;
-	struct vdoa_ctx *curr_ctx;
-	u32 val;
-
-	/* Disable interrupts */
-	writel(0, vdoa->regs + VDOAIE);
-
-	curr_ctx = vdoa->curr_ctx;
-	if (!curr_ctx) {
-		dev_warn(vdoa->dev,
-			"Instance released before the end of transaction\n");
-		return IRQ_HANDLED;
-	}
-
-	val = readl(vdoa->regs + VDOAIST);
-	writel(val, vdoa->regs + VDOAIST);
-	if (val & VDOAIST_TERR) {
-		val = readl(vdoa->regs + VDOASR) & VDOASR_ERRW;
-		dev_err(vdoa->dev, "AXI %s error\n", val ? "write" : "read");
-	} else if (!(val & VDOAIST_EOT)) {
-		dev_warn(vdoa->dev, "Spurious interrupt\n");
-	}
-	curr_ctx->completed_job++;
-	complete(&curr_ctx->completion);
-
-	return IRQ_HANDLED;
-}
-
-int vdoa_wait_for_completion(struct vdoa_ctx *ctx)
-{
-	struct vdoa_data *vdoa = ctx->vdoa;
-
-	if (ctx->submitted_job == ctx->completed_job)
-		return 0;
-
-	if (!wait_for_completion_timeout(&ctx->completion,
-					 msecs_to_jiffies(300))) {
-		dev_err(vdoa->dev,
-			"Timeout waiting for transfer result\n");
-		return -ETIMEDOUT;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(vdoa_wait_for_completion);
-
-void vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src)
-{
-	struct vdoa_q_data *src_q_data, *dst_q_data;
-	struct vdoa_data *vdoa = ctx->vdoa;
-	u32 val;
-
-	if (vdoa->curr_ctx)
-		vdoa_wait_for_completion(vdoa->curr_ctx);
-
-	vdoa->curr_ctx = ctx;
-
-	reinit_completion(&ctx->completion);
-	ctx->submitted_job++;
-
-	src_q_data = &ctx->q_data[V4L2_M2M_SRC];
-	dst_q_data = &ctx->q_data[V4L2_M2M_DST];
-
-	/* Progressive, no sync, 1 frame per run */
-	if (dst_q_data->pixelformat == V4L2_PIX_FMT_YUYV)
-		val = VDOAC_PFS;
-	else
-		val = 0;
-	writel(val, vdoa->regs + VDOAC);
-
-	writel(dst_q_data->height << 16 | dst_q_data->width,
-	       vdoa->regs + VDOAFP);
-
-	val = dst;
-	writel(val, vdoa->regs + VDOAIEBA00);
-
-	writel(src_q_data->bytesperline << 16 | dst_q_data->bytesperline,
-	       vdoa->regs + VDOASL);
-
-	if (dst_q_data->pixelformat == V4L2_PIX_FMT_NV12 ||
-	    dst_q_data->pixelformat == V4L2_PIX_FMT_NV21)
-		val = dst_q_data->bytesperline * dst_q_data->height;
-	else
-		val = 0;
-	writel(val, vdoa->regs + VDOAIUBO);
-
-	val = src;
-	writel(val, vdoa->regs + VDOAVEBA0);
-	val = round_up(src_q_data->bytesperline * src_q_data->height, 4096);
-	writel(val, vdoa->regs + VDOAVUBO);
-
-	/* Enable interrupts and start transfer */
-	writel(VDOAIE_EITERR | VDOAIE_EIEOT, vdoa->regs + VDOAIE);
-	writel(VDOASRR_START, vdoa->regs + VDOASRR);
-}
-EXPORT_SYMBOL(vdoa_device_run);
-
-struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa)
-{
-	struct vdoa_ctx *ctx;
-	int err;
-
-	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-	if (!ctx)
-		return NULL;
-
-	err = clk_prepare_enable(vdoa->vdoa_clk);
-	if (err) {
-		kfree(ctx);
-		return NULL;
-	}
-
-	init_completion(&ctx->completion);
-	ctx->vdoa = vdoa;
-
-	return ctx;
-}
-EXPORT_SYMBOL(vdoa_context_create);
-
-void vdoa_context_destroy(struct vdoa_ctx *ctx)
-{
-	struct vdoa_data *vdoa = ctx->vdoa;
-
-	if (vdoa->curr_ctx == ctx) {
-		vdoa_wait_for_completion(vdoa->curr_ctx);
-		vdoa->curr_ctx = NULL;
-	}
-
-	clk_disable_unprepare(vdoa->vdoa_clk);
-	kfree(ctx);
-}
-EXPORT_SYMBOL(vdoa_context_destroy);
-
-int vdoa_context_configure(struct vdoa_ctx *ctx,
-			   unsigned int width, unsigned int height,
-			   u32 pixelformat)
-{
-	struct vdoa_q_data *src_q_data;
-	struct vdoa_q_data *dst_q_data;
-
-	if (width < 16 || width  > 8192 || width % 16 != 0 ||
-	    height < 16 || height > 4096 || height % 16 != 0)
-		return -EINVAL;
-
-	if (pixelformat != V4L2_PIX_FMT_YUYV &&
-	    pixelformat != V4L2_PIX_FMT_NV12)
-		return -EINVAL;
-
-	/* If no context is passed, only check if the format is valid */
-	if (!ctx)
-		return 0;
-
-	src_q_data = &ctx->q_data[V4L2_M2M_SRC];
-	dst_q_data = &ctx->q_data[V4L2_M2M_DST];
-
-	src_q_data->width = width;
-	src_q_data->height = height;
-	src_q_data->bytesperline = width;
-	src_q_data->sizeimage =
-		round_up(src_q_data->bytesperline * height, 4096) +
-		src_q_data->bytesperline * height / 2;
-
-	dst_q_data->width = width;
-	dst_q_data->height = height;
-	dst_q_data->pixelformat = pixelformat;
-	switch (pixelformat) {
-	case V4L2_PIX_FMT_YUYV:
-		dst_q_data->bytesperline = width * 2;
-		dst_q_data->sizeimage = dst_q_data->bytesperline * height;
-		break;
-	case V4L2_PIX_FMT_NV12:
-	default:
-		dst_q_data->bytesperline = width;
-		dst_q_data->sizeimage =
-			dst_q_data->bytesperline * height * 3 / 2;
-		break;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(vdoa_context_configure);
-
-static int vdoa_probe(struct platform_device *pdev)
-{
-	struct vdoa_data *vdoa;
-	int ret;
-
-	ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-	if (ret) {
-		dev_err(&pdev->dev, "DMA enable failed\n");
-		return ret;
-	}
-
-	vdoa = devm_kzalloc(&pdev->dev, sizeof(*vdoa), GFP_KERNEL);
-	if (!vdoa)
-		return -ENOMEM;
-
-	vdoa->dev = &pdev->dev;
-
-	vdoa->vdoa_clk = devm_clk_get(vdoa->dev, NULL);
-	if (IS_ERR(vdoa->vdoa_clk)) {
-		dev_err(vdoa->dev, "Failed to get clock\n");
-		return PTR_ERR(vdoa->vdoa_clk);
-	}
-
-	vdoa->regs = devm_platform_ioremap_resource(pdev, 0);
-	if (IS_ERR(vdoa->regs))
-		return PTR_ERR(vdoa->regs);
-
-	ret = platform_get_irq(pdev, 0);
-	if (ret < 0)
-		return ret;
-	ret = devm_request_threaded_irq(&pdev->dev, ret, NULL,
-					vdoa_irq_handler, IRQF_ONESHOT,
-					"vdoa", vdoa);
-	if (ret < 0) {
-		dev_err(vdoa->dev, "Failed to get irq\n");
-		return ret;
-	}
-
-	platform_set_drvdata(pdev, vdoa);
-
-	return 0;
-}
-
-static int vdoa_remove(struct platform_device *pdev)
-{
-	return 0;
-}
-
-static const struct of_device_id vdoa_dt_ids[] = {
-	{ .compatible = "fsl,imx6q-vdoa" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, vdoa_dt_ids);
-
-static struct platform_driver vdoa_driver = {
-	.probe		= vdoa_probe,
-	.remove		= vdoa_remove,
-	.driver		= {
-		.name	= VDOA_NAME,
-		.of_match_table = vdoa_dt_ids,
-	},
-};
-
-module_platform_driver(vdoa_driver);
-
-MODULE_DESCRIPTION("Video Data Order Adapter");
-MODULE_AUTHOR("Philipp Zabel <philipp.zabel@gmail.com>");
-MODULE_ALIAS("platform:imx-vdoa");
-MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/media/platform/chips-media/imx-vdoa.h b/drivers/media/platform/chips-media/imx-vdoa.h
--- a/drivers/media/platform/chips-media/imx-vdoa.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/imx-vdoa.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2016 Pengutronix
- */
-
-#ifndef IMX_VDOA_H
-#define IMX_VDOA_H
-
-struct vdoa_data;
-struct vdoa_ctx;
-
-#if (defined CONFIG_VIDEO_IMX_VDOA || defined CONFIG_VIDEO_IMX_VDOA_MODULE)
-
-struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa);
-int vdoa_context_configure(struct vdoa_ctx *ctx,
-			   unsigned int width, unsigned int height,
-			   u32 pixelformat);
-void vdoa_context_destroy(struct vdoa_ctx *ctx);
-
-void vdoa_device_run(struct vdoa_ctx *ctx, dma_addr_t dst, dma_addr_t src);
-int vdoa_wait_for_completion(struct vdoa_ctx *ctx);
-
-#else
-
-static inline struct vdoa_ctx *vdoa_context_create(struct vdoa_data *vdoa)
-{
-	return NULL;
-}
-
-static inline int vdoa_context_configure(struct vdoa_ctx *ctx,
-					 unsigned int width,
-					 unsigned int height,
-					 u32 pixelformat)
-{
-	return 0;
-}
-
-static inline void vdoa_context_destroy(struct vdoa_ctx *ctx) { };
-
-static inline void vdoa_device_run(struct vdoa_ctx *ctx,
-				   dma_addr_t dst, dma_addr_t src) { };
-
-static inline int vdoa_wait_for_completion(struct vdoa_ctx *ctx)
-{
-	return 0;
-};
-
-#endif
-
-#endif /* IMX_VDOA_H */
diff -Naur --no-dereference a/drivers/media/platform/chips-media/Kconfig b/drivers/media/platform/chips-media/Kconfig
--- a/drivers/media/platform/chips-media/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/Kconfig	2024-01-28 14:01:31.244353788 -0500
@@ -2,19 +2,5 @@
 
 comment "Chips&Media media platform drivers"
 
-config VIDEO_CODA
-	tristate "Chips&Media Coda multi-standard codec IP"
-	depends on V4L_MEM2MEM_DRIVERS
-	depends on VIDEO_DEV && OF && (ARCH_MXC || COMPILE_TEST)
-	select SRAM
-	select VIDEOBUF2_DMA_CONTIG
-	select VIDEOBUF2_VMALLOC
-	select V4L2_JPEG_HELPER
-	select V4L2_MEM2MEM_DEV
-	select GENERIC_ALLOCATOR
-	help
-	   Coda is a range of video codec IPs that supports
-	   H.264, MPEG-4, and other video formats.
-
-config VIDEO_IMX_VDOA
-	def_tristate VIDEO_CODA if SOC_IMX6Q || COMPILE_TEST
+source "drivers/media/platform/chips-media/coda/Kconfig"
+source "drivers/media/platform/chips-media/wave5/Kconfig"
diff -Naur --no-dereference a/drivers/media/platform/chips-media/Makefile b/drivers/media/platform/chips-media/Makefile
--- a/drivers/media/platform/chips-media/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/Makefile	2024-01-28 14:01:31.244353788 -0500
@@ -1,6 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
-coda-vpu-objs := coda-common.o coda-bit.o coda-gdi.o coda-h264.o coda-mpeg2.o coda-mpeg4.o coda-jpeg.o
-
-obj-$(CONFIG_VIDEO_CODA) += coda-vpu.o
-obj-$(CONFIG_VIDEO_IMX_VDOA) += imx-vdoa.o
+obj-y += coda/
+obj-y += wave5/
diff -Naur --no-dereference a/drivers/media/platform/chips-media/trace.h b/drivers/media/platform/chips-media/trace.h
--- a/drivers/media/platform/chips-media/trace.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/chips-media/trace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,175 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM coda
-
-#if !defined(__CODA_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
-#define __CODA_TRACE_H__
-
-#include <linux/tracepoint.h>
-#include <media/videobuf2-v4l2.h>
-
-#include "coda.h"
-
-TRACE_EVENT(coda_bit_run,
-	TP_PROTO(struct coda_ctx *ctx, int cmd),
-
-	TP_ARGS(ctx, cmd),
-
-	TP_STRUCT__entry(
-		__field(int, minor)
-		__field(int, ctx)
-		__field(int, cmd)
-	),
-
-	TP_fast_assign(
-		__entry->minor = ctx->fh.vdev->minor;
-		__entry->ctx = ctx->idx;
-		__entry->cmd = cmd;
-	),
-
-	TP_printk("minor = %d, ctx = %d, cmd = %d",
-		  __entry->minor, __entry->ctx, __entry->cmd)
-);
-
-TRACE_EVENT(coda_bit_done,
-	TP_PROTO(struct coda_ctx *ctx),
-
-	TP_ARGS(ctx),
-
-	TP_STRUCT__entry(
-		__field(int, minor)
-		__field(int, ctx)
-	),
-
-	TP_fast_assign(
-		__entry->minor = ctx->fh.vdev->minor;
-		__entry->ctx = ctx->idx;
-	),
-
-	TP_printk("minor = %d, ctx = %d", __entry->minor, __entry->ctx)
-);
-
-DECLARE_EVENT_CLASS(coda_buf_class,
-	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
-
-	TP_ARGS(ctx, buf),
-
-	TP_STRUCT__entry(
-		__field(int, minor)
-		__field(int, index)
-		__field(int, ctx)
-	),
-
-	TP_fast_assign(
-		__entry->minor = ctx->fh.vdev->minor;
-		__entry->index = buf->vb2_buf.index;
-		__entry->ctx = ctx->idx;
-	),
-
-	TP_printk("minor = %d, index = %d, ctx = %d",
-		  __entry->minor, __entry->index, __entry->ctx)
-);
-
-DEFINE_EVENT(coda_buf_class, coda_enc_pic_run,
-	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
-	TP_ARGS(ctx, buf)
-);
-
-DEFINE_EVENT(coda_buf_class, coda_enc_pic_done,
-	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
-	TP_ARGS(ctx, buf)
-);
-
-DECLARE_EVENT_CLASS(coda_buf_meta_class,
-	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
-		 struct coda_buffer_meta *meta),
-
-	TP_ARGS(ctx, buf, meta),
-
-	TP_STRUCT__entry(
-		__field(int, minor)
-		__field(int, index)
-		__field(int, start)
-		__field(int, end)
-		__field(int, ctx)
-	),
-
-	TP_fast_assign(
-		__entry->minor = ctx->fh.vdev->minor;
-		__entry->index = buf->vb2_buf.index;
-		__entry->start = meta->start & ctx->bitstream_fifo.kfifo.mask;
-		__entry->end = meta->end & ctx->bitstream_fifo.kfifo.mask;
-		__entry->ctx = ctx->idx;
-	),
-
-	TP_printk("minor = %d, index = %d, start = 0x%x, end = 0x%x, ctx = %d",
-		  __entry->minor, __entry->index, __entry->start, __entry->end,
-		  __entry->ctx)
-);
-
-DEFINE_EVENT(coda_buf_meta_class, coda_bit_queue,
-	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
-		 struct coda_buffer_meta *meta),
-	TP_ARGS(ctx, buf, meta)
-);
-
-DECLARE_EVENT_CLASS(coda_meta_class,
-	TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta),
-
-	TP_ARGS(ctx, meta),
-
-	TP_STRUCT__entry(
-		__field(int, minor)
-		__field(int, start)
-		__field(int, end)
-		__field(int, ctx)
-	),
-
-	TP_fast_assign(
-		__entry->minor = ctx->fh.vdev->minor;
-		__entry->start = meta ? (meta->start &
-					 ctx->bitstream_fifo.kfifo.mask) : 0;
-		__entry->end = meta ? (meta->end &
-				       ctx->bitstream_fifo.kfifo.mask) : 0;
-		__entry->ctx = ctx->idx;
-	),
-
-	TP_printk("minor = %d, start = 0x%x, end = 0x%x, ctx = %d",
-		  __entry->minor, __entry->start, __entry->end, __entry->ctx)
-);
-
-DEFINE_EVENT(coda_meta_class, coda_dec_pic_run,
-	TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta),
-	TP_ARGS(ctx, meta)
-);
-
-DEFINE_EVENT(coda_meta_class, coda_dec_pic_done,
-	TP_PROTO(struct coda_ctx *ctx, struct coda_buffer_meta *meta),
-	TP_ARGS(ctx, meta)
-);
-
-DEFINE_EVENT(coda_buf_meta_class, coda_dec_rot_done,
-	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf,
-		 struct coda_buffer_meta *meta),
-	TP_ARGS(ctx, buf, meta)
-);
-
-DEFINE_EVENT(coda_buf_class, coda_jpeg_run,
-	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
-	TP_ARGS(ctx, buf)
-);
-
-DEFINE_EVENT(coda_buf_class, coda_jpeg_done,
-	TP_PROTO(struct coda_ctx *ctx, struct vb2_v4l2_buffer *buf),
-	TP_ARGS(ctx, buf)
-);
-
-#endif /* __CODA_TRACE_H__ */
-
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH ../../drivers/media/platform/chips-media
-#undef TRACE_INCLUDE_FILE
-#define TRACE_INCLUDE_FILE trace
-
-/* This part must be outside protection */
-#include <trace/define_trace.h>
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/Kconfig b/drivers/media/platform/chips-media/wave5/Kconfig
--- a/drivers/media/platform/chips-media/wave5/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/Kconfig	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+config VIDEO_WAVE_VPU
+	tristate "Chips&Media Wave Codec Driver"
+	depends on VIDEO_DEV
+	select VIDEOBUF2_DMA_CONTIG
+	select VIDEOBUF2_VMALLOC
+	select V4L2_MEM2MEM_DEV
+	help
+	  Chips&Media stateful encoder and decoder driver.
+	  The driver supports HEVC and H264 formats.
+	  To compile this driver as modules, choose M here: the
+	  modules will be called wave5.
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/Makefile b/drivers/media/platform/chips-media/wave5/Makefile
--- a/drivers/media/platform/chips-media/wave5/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/Makefile	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_VIDEO_WAVE_VPU) += wave5.o
+wave5-objs +=  	wave5-hw.o \
+		wave5-vpuapi.o \
+		wave5-vdi.o \
+		wave5-vpu-dec.o \
+		wave5-vpu.o \
+		wave5-vpu-enc.o \
+		wave5-helper.o
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/TODO b/drivers/media/platform/chips-media/wave5/TODO
--- a/drivers/media/platform/chips-media/wave5/TODO	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/TODO	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,18 @@
+* Handle interrupts better
+
+Currently the interrupt handling uses an unusual design employing a kfifo to
+transfer irq status to irq thread. This was done as a work around for dropped
+interrupts seen with IRQF_ONESHOT based handling.
+
+This needs further investigation and fixing properly, with the aid of
+C&M.
+
+* power management handling - add (runtime_)suspen/resume cb where the clock is enabled
+
+* revise logic of wave5_vpu_(dec/enc)_register_framebuffer
+
+* check if the  normal kernel endianness/__swab32 routines are sufficient. (instead of the ones
+  implemented in the driver)
+
+* Adjust STREAMON routine for the stateful decoder to adhere to the API, which
+  declares that STREAMON can be called before source buffers have been queued.
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5.h b/drivers/media/platform/chips-media/wave5/wave5.h
--- a/drivers/media/platform/chips-media/wave5/wave5.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave5 series multi-standard codec IP - wave5 backend definitions
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+
+#ifndef __WAVE5_FUNCTION_H__
+#define __WAVE5_FUNCTION_H__
+
+#define WAVE5_SUBSAMPLED_ONE_SIZE(_w, _h)	(ALIGN((_w) / 4, 16) * ALIGN((_h) / 4, 8))
+#define WAVE5_SUBSAMPLED_ONE_SIZE_AVC(_w, _h)	(ALIGN((_w) / 4, 32) * ALIGN((_h) / 4, 4))
+
+#define BSOPTION_ENABLE_EXPLICIT_END        BIT(0)
+
+#define WTL_RIGHT_JUSTIFIED          0
+#define WTL_LEFT_JUSTIFIED           1
+#define WTL_PIXEL_8BIT               0
+#define WTL_PIXEL_16BIT              1
+#define WTL_PIXEL_32BIT              2
+
+/* Mirror & rotation modes of the PRP (pre-processing) module */
+#define NONE_ROTATE		0x0
+#define ROT_CLOCKWISE_90	0x3
+#define ROT_CLOCKWISE_180	0x5
+#define ROT_CLOCKWISE_270	0x7
+#define MIR_HOR_FLIP		0x11
+#define MIR_VER_FLIP		0x9
+#define MIR_HOR_VER_FLIP	(MIR_HOR_FLIP | MIR_VER_FLIP)
+
+bool wave5_vpu_is_init(struct vpu_device *vpu_dev);
+
+unsigned int wave5_vpu_get_product_id(struct vpu_device *vpu_dev);
+
+void wave5_bit_issue_command(struct vpu_instance *inst, u32 cmd);
+
+int wave5_vpu_get_version(struct vpu_device *vpu_dev, u32 *revision);
+
+int wave5_vpu_init(struct device *dev, u8 *fw, size_t size);
+
+int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uint16_t *code,
+				size_t size);
+
+int wave5_vpu_reset(struct device *dev, enum sw_reset_mode reset_mode);
+
+int wave5_vpu_build_up_dec_param(struct vpu_instance *inst, struct dec_open_param *param);
+
+int wave5_vpu_dec_set_bitstream_flag(struct vpu_instance *inst, bool eos);
+
+int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst,
+				       struct frame_buffer *fb_arr, enum tiled_map_type map_type,
+				       unsigned int count);
+
+int wave5_vpu_re_init(struct device *dev, u8 *fw, size_t size);
+
+int wave5_vpu_dec_init_seq(struct vpu_instance *inst);
+
+int wave5_vpu_dec_get_seq_info(struct vpu_instance *inst, struct dec_initial_info *info);
+
+int wave5_vpu_decode(struct vpu_instance *inst, struct dec_param *option, u32 *fail_res);
+
+int wave5_vpu_dec_get_result(struct vpu_instance *inst, struct dec_output_info *result);
+
+int wave5_vpu_dec_finish_seq(struct vpu_instance *inst, u32 *fail_res);
+
+int wave5_dec_clr_disp_flag(struct vpu_instance *inst, unsigned int index);
+
+int wave5_dec_set_disp_flag(struct vpu_instance *inst, unsigned int index);
+
+int wave5_vpu_clear_interrupt(struct vpu_instance *inst, u32 flags);
+
+dma_addr_t wave5_vpu_dec_get_rd_ptr(struct vpu_instance *inst);
+
+int wave5_dec_set_rd_ptr(struct vpu_instance *inst, dma_addr_t addr);
+
+/***< WAVE5 encoder >******/
+
+int wave5_vpu_build_up_enc_param(struct device *dev, struct vpu_instance *inst,
+				 struct enc_open_param *open_param);
+
+int wave5_vpu_enc_init_seq(struct vpu_instance *inst);
+
+int wave5_vpu_enc_get_seq_info(struct vpu_instance *inst, struct enc_initial_info *info);
+
+int wave5_vpu_enc_register_framebuffer(struct device *dev, struct vpu_instance *inst,
+				       struct frame_buffer *fb_arr, enum tiled_map_type map_type,
+				       unsigned int count);
+
+int wave5_vpu_encode(struct vpu_instance *inst, struct enc_param *option, u32 *fail_res);
+
+int wave5_vpu_enc_get_result(struct vpu_instance *inst, struct enc_output_info *result);
+
+int wave5_vpu_enc_finish_seq(struct vpu_instance *inst, u32 *fail_res);
+
+int wave5_vpu_enc_check_open_param(struct vpu_instance *inst, struct enc_open_param *open_param);
+
+#endif /* __WAVE5_FUNCTION_H__ */
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-helper.c b/drivers/media/platform/chips-media/wave5/wave5-helper.c
--- a/drivers/media/platform/chips-media/wave5/wave5-helper.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-helper.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Wave5 series multi-standard codec IP - decoder interface
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+
+#include <linux/pm_opp.h>
+#include <linux/pm_runtime.h>
+#include "wave5-helper.h"
+
+void wave5_cleanup_instance(struct vpu_instance *inst)
+{
+	int i;
+
+	if (list_is_singular(&inst->list))
+		wave5_vdi_free_sram(inst->dev);
+
+	for (i = 0; i < inst->dst_buf_count; i++)
+		wave5_vdi_free_dma_memory(inst->dev, &inst->frame_vbuf[i]);
+
+	wave5_vdi_free_dma_memory(inst->dev, &inst->bitstream_vbuf);
+	v4l2_ctrl_handler_free(&inst->v4l2_ctrl_hdl);
+	if (inst->v4l2_m2m_dev != NULL)
+		v4l2_m2m_release(inst->v4l2_m2m_dev);
+	if (inst->v4l2_fh.vdev != NULL) {
+		v4l2_fh_del(&inst->v4l2_fh);
+		v4l2_fh_exit(&inst->v4l2_fh);
+	}
+	list_del_init(&inst->list);
+	kfifo_free(&inst->irq_status);
+	ida_free(&inst->dev->inst_ida, inst->id);
+	kfree(inst->map_index);
+	kfree(inst->mapped_dma_addr);
+	kfree(inst->inst_lock);
+	kfree(inst);
+}
+
+int wave5_vpu_release_device(struct file *filp,
+			     int (*close_func)(struct vpu_instance *inst, u32 *fail_res),
+			     char *name)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(filp->private_data);
+	struct vpu_device *dev = inst->dev;
+	int ret = 0;
+
+	v4l2_m2m_ctx_release(inst->v4l2_fh.m2m_ctx);
+	if (inst->state != VPU_INST_STATE_NONE) {
+		u32 fail_res;
+		int retry_count = 10;
+
+		do {
+			fail_res = 0;
+			ret = close_func(inst, &fail_res);
+			if (ret && ret != -EIO)
+				break;
+			if (fail_res != WAVE5_SYSERR_VPU_STILL_RUNNING)
+				break;
+			if (!wave5_vpu_wait_interrupt(inst, VPU_DEC_TIMEOUT))
+				break;
+		} while (--retry_count);
+
+		if (fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING) {
+			dev_err(inst->dev->dev, "%s close failed, device is still running\n",
+				 name);
+			return -EBUSY;
+		}
+		if (ret && ret != -EIO) {
+			dev_err(inst->dev->dev, "%s close, fail: %d\n", name, ret);
+			return ret;
+		}
+		wave5_instance_reset_clk(inst);
+	}
+
+	wave5_cleanup_instance(inst);
+	if (dev->irq < 0) {
+		ret = mutex_lock_interruptible(&dev->dev_lock);
+		if (ret)
+			return ret;
+
+		if (list_empty(&dev->instances)) {
+			dev_dbg(dev->dev, "Disabling the hrtimer\n");
+			hrtimer_cancel(&dev->hrtimer);
+		}
+
+		mutex_unlock(&dev->dev_lock);
+	}
+
+	if (!pm_runtime_suspended(dev->dev))
+		pm_runtime_put_sync(dev->dev);
+
+	return ret;
+}
+
+int wave5_vpu_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq,
+			 const struct vb2_ops *ops)
+{
+	struct vpu_instance *inst = priv;
+	int ret;
+
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	src_vq->mem_ops = &vb2_dma_contig_memops;
+	src_vq->ops = ops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->buf_struct_size = sizeof(struct vpu_buffer);
+	src_vq->drv_priv = inst;
+	src_vq->lock = &inst->dev->dev_lock;
+	src_vq->dev = inst->dev->v4l2_dev.dev;
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+	dst_vq->ops = ops;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->buf_struct_size = sizeof(struct vpu_buffer);
+	dst_vq->drv_priv = inst;
+	dst_vq->lock = &inst->dev->dev_lock;
+	dst_vq->dev = inst->dev->v4l2_dev.dev;
+	ret = vb2_queue_init(dst_vq);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	bool is_decoder = inst->type == VPU_INST_TYPE_DEC;
+
+	dev_dbg(inst->dev->dev, "%s: [%s] type: %u id: %u | flags: %u\n", __func__,
+		is_decoder ? "decoder" : "encoder", sub->type, sub->id, sub->flags);
+
+	switch (sub->type) {
+	case V4L2_EVENT_EOS:
+		return v4l2_event_subscribe(fh, sub, 0, NULL);
+	case V4L2_EVENT_SOURCE_CHANGE:
+		if (is_decoder)
+			return v4l2_src_change_event_subscribe(fh, sub);
+		return -EINVAL;
+	case V4L2_EVENT_CTRL:
+		return v4l2_ctrl_subscribe_event(fh, sub);
+	default:
+		return -EINVAL;
+	}
+}
+
+int wave5_vpu_g_fmt_out(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	int i;
+
+	f->fmt.pix_mp.width = inst->src_fmt.width;
+	f->fmt.pix_mp.height = inst->src_fmt.height;
+	f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat;
+	f->fmt.pix_mp.field = inst->src_fmt.field;
+	f->fmt.pix_mp.flags = inst->src_fmt.flags;
+	f->fmt.pix_mp.num_planes = inst->src_fmt.num_planes;
+	for (i = 0; i < f->fmt.pix_mp.num_planes; i++) {
+		f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->src_fmt.plane_fmt[i].bytesperline;
+		f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->src_fmt.plane_fmt[i].sizeimage;
+	}
+
+	f->fmt.pix_mp.colorspace = inst->colorspace;
+	f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc;
+	f->fmt.pix_mp.hsv_enc = inst->hsv_enc;
+	f->fmt.pix_mp.quantization = inst->quantization;
+	f->fmt.pix_mp.xfer_func = inst->xfer_func;
+
+	return 0;
+}
+
+const struct vpu_format *wave5_find_vpu_fmt(unsigned int v4l2_pix_fmt,
+					    const struct vpu_format fmt_list[MAX_FMTS])
+{
+	unsigned int index;
+
+	for (index = 0; index < MAX_FMTS; index++) {
+		if (fmt_list[index].v4l2_pix_fmt == v4l2_pix_fmt)
+			return &fmt_list[index];
+	}
+
+	return NULL;
+}
+
+const struct vpu_format *wave5_find_vpu_fmt_by_idx(unsigned int idx,
+						   const struct vpu_format fmt_list[MAX_FMTS])
+{
+	if (idx >= MAX_FMTS)
+		return NULL;
+
+	if (!fmt_list[idx].v4l2_pix_fmt)
+		return NULL;
+
+	return &fmt_list[idx];
+}
+
+int wave5_set_dev_clk(struct vpu_instance *inst)
+{
+	struct dev_pm_opp *opp;
+	unsigned long calc_pixel_rate, req_freq, acq_freq, pixel_rate;
+	int ret;
+
+	pixel_rate = inst->dev->opp_pixel_rate;
+	calc_pixel_rate = pixel_rate*(uint)(MAX_OP_HZ);
+	req_freq = (calc_pixel_rate / MAX_PIXEL_RATE) + 1;
+	opp = dev_pm_opp_find_freq_ceil(inst->dev->dev, &req_freq);
+	if (IS_ERR(opp)) {
+		opp = dev_pm_opp_find_freq_floor(inst->dev->dev, &req_freq);
+		if (IS_ERR(opp)) {
+			dev_err(inst->dev->dev, "Failed to get floor value\n");
+			return -EINVAL;
+		}
+
+	}
+
+	dev_pm_opp_put(opp);
+	acq_freq = dev_pm_opp_get_freq(opp);
+	if (acq_freq != inst->dev->opp_freq) {
+		inst->dev->opp_freq = acq_freq;
+		ret = dev_pm_opp_set_rate(inst->dev->dev, acq_freq);
+		if (ret) {
+			dev_err(inst->dev->dev, "Error setting the clock");
+			return ret;
+		}
+	}
+	return ret;
+}
+
+int wave5_instance_reset_clk(struct vpu_instance *inst)
+{
+	if (inst->dev->opp_pixel_rate < inst->pixel_rate)
+		goto err;
+	inst->dev->opp_pixel_rate -= inst->pixel_rate;
+	wave5_set_dev_clk(inst);
+err:
+	return -EINVAL;
+}
+
+
+int wave5_instance_set_clk(struct vpu_instance *inst)
+{
+	int width, height, framerate;
+	unsigned int pixel_rate;
+	int ret;
+
+	width = inst->src_fmt.width;
+	height = inst->src_fmt.height;
+	framerate = inst->frame_rate;
+	pixel_rate = (width*height*framerate);
+
+	if (!pixel_rate)
+		pixel_rate = MAX_PIXEL_RATE;
+
+	inst->pixel_rate = pixel_rate;
+	inst->dev->opp_pixel_rate += inst->pixel_rate;
+	ret = wave5_set_dev_clk(inst);
+	return ret;
+}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-helper.h b/drivers/media/platform/chips-media/wave5/wave5-helper.h
--- a/drivers/media/platform/chips-media/wave5/wave5-helper.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-helper.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave5 series multi-standard codec IP - basic types
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+
+#ifndef __WAVE_HELPER_H__
+#define __WAVE_HELPER_H__
+
+#include "wave5-vpu.h"
+
+#define FMT_TYPES	2
+#define MAX_FMTS	12
+#define MAX_OP_HZ	500000000
+#define MAX_PIXEL_RATE 497664000      /* 480 MPix/s at 500MHz */
+
+void wave5_cleanup_instance(struct vpu_instance *inst);
+int wave5_vpu_release_device(struct file *filp,
+			     int (*close_func)(struct vpu_instance *inst, u32 *fail_res),
+			     char *name);
+int wave5_vpu_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq,
+			 const struct vb2_ops *ops);
+int wave5_vpu_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub);
+int wave5_vpu_g_fmt_out(struct file *file, void *fh, struct v4l2_format *f);
+const struct vpu_format *wave5_find_vpu_fmt(unsigned int v4l2_pix_fmt,
+					    const struct vpu_format fmt_list[MAX_FMTS]);
+const struct vpu_format *wave5_find_vpu_fmt_by_idx(unsigned int idx,
+						   const struct vpu_format fmt_list[MAX_FMTS]);
+int wave5_instance_set_clk(struct vpu_instance *inst);
+int wave5_instance_reset_clk(struct vpu_instance *inst);
+int wave5_set_dev_clk(struct vpu_instance *inst);
+#endif
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-hw.c b/drivers/media/platform/chips-media/wave5/wave5-hw.c
--- a/drivers/media/platform/chips-media/wave5/wave5-hw.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-hw.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,3373 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Wave5 series multi-standard codec IP - wave5 backend logic
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+
+#include <linux/iopoll.h>
+#include "wave5-vpu.h"
+#include "wave5.h"
+#include "wave5-regdefine.h"
+
+#define FIO_TIMEOUT			10000000
+#define FIO_CTRL_READY			BIT(31)
+#define FIO_CTRL_WRITE			BIT(16)
+#define VPU_BUSY_CHECK_TIMEOUT		10000000
+#define QUEUE_REPORT_MASK		0xffff
+
+static void wave5_print_reg_err(struct vpu_device *vpu_dev, u32 reg_fail_reason)
+{
+	char *caller = __builtin_return_address(0);
+	struct device *dev = vpu_dev->dev;
+	u32 reg_val;
+
+	switch (reg_fail_reason) {
+	case WAVE5_SYSERR_QUEUEING_FAIL:
+		reg_val = vpu_read_reg(vpu_dev, W5_RET_QUEUE_FAIL_REASON);
+		dev_dbg(dev, "%s: queueing failure: 0x%x\n", caller, reg_val);
+		break;
+	case WAVE5_SYSERR_RESULT_NOT_READY:
+		dev_err(dev, "%s: result not ready: 0x%x\n", caller, reg_fail_reason);
+		break;
+	case WAVE5_SYSERR_ACCESS_VIOLATION_HW:
+		dev_err(dev, "%s: access violation: 0x%x\n", caller, reg_fail_reason);
+		break;
+	case WAVE5_SYSERR_WATCHDOG_TIMEOUT:
+		dev_err(dev, "%s: watchdog timeout: 0x%x\n", caller, reg_fail_reason);
+		break;
+	case WAVE5_SYSERR_BUS_ERROR:
+		dev_err(dev, "%s: bus error: 0x%x\n", caller, reg_fail_reason);
+		break;
+	case WAVE5_SYSERR_DOUBLE_FAULT:
+		dev_err(dev, "%s: double fault: 0x%x\n", caller, reg_fail_reason);
+		break;
+	case WAVE5_SYSERR_VPU_STILL_RUNNING:
+		dev_err(dev, "%s: still running: 0x%x\n", caller, reg_fail_reason);
+		break;
+	case WAVE5_SYSERR_VLC_BUF_FULL:
+		dev_err(dev, "%s: vlc buf full: 0x%x\n", caller, reg_fail_reason);
+		break;
+	default:
+		dev_err(dev, "%s: failure:: 0x%x\n", caller, reg_fail_reason);
+		break;
+	}
+}
+
+static int wave5_wait_fio_readl(struct vpu_device *vpu_dev, u32 addr, u32 val)
+{
+	u32 ctrl;
+	int ret;
+
+	ctrl = addr & 0xffff;
+	wave5_vdi_write_register(vpu_dev, W5_VPU_FIO_CTRL_ADDR, ctrl);
+	ret = read_poll_timeout(wave5_vdi_readl, ctrl, ctrl & FIO_CTRL_READY,
+				0, FIO_TIMEOUT, false, vpu_dev, W5_VPU_FIO_CTRL_ADDR);
+	if (ret)
+		return ret;
+	if (wave5_vdi_readl(vpu_dev, W5_VPU_FIO_DATA) != val)
+		return -ETIMEDOUT;
+	return 0;
+}
+
+static void wave5_fio_writel(struct vpu_device *vpu_dev, unsigned int addr, unsigned int data)
+{
+	int ret;
+	unsigned int ctrl;
+
+	wave5_vdi_write_register(vpu_dev, W5_VPU_FIO_DATA, data);
+	ctrl = FIO_CTRL_WRITE | (addr & 0xffff);
+	wave5_vdi_write_register(vpu_dev, W5_VPU_FIO_CTRL_ADDR, ctrl);
+	ret = read_poll_timeout(wave5_vdi_readl, ctrl, ctrl & FIO_CTRL_READY, 0, FIO_TIMEOUT,
+				false, vpu_dev, W5_VPU_FIO_CTRL_ADDR);
+	if (ret) {
+		dev_dbg_ratelimited(vpu_dev->dev, "FIO write timeout: addr=0x%x data=%x\n",
+				    ctrl, data);
+	}
+}
+
+static int wave5_wait_bus_busy(struct vpu_device *vpu_dev, unsigned int addr)
+{
+	u32 gdi_status_check_value = 0x3f;
+
+	if (vpu_dev->product_code == WAVE521C_CODE ||
+	    vpu_dev->product_code == WAVE521_CODE ||
+	    vpu_dev->product_code == WAVE521E1_CODE)
+		gdi_status_check_value = 0x00ff1f3f;
+
+	return wave5_wait_fio_readl(vpu_dev, addr, gdi_status_check_value);
+}
+
+static int wave5_wait_vpu_busy(struct vpu_device *vpu_dev, unsigned int addr)
+{
+	u32 data;
+
+	return read_poll_timeout(wave5_vdi_readl, data, data == 0,
+				 0, VPU_BUSY_CHECK_TIMEOUT, false, vpu_dev, addr);
+}
+
+static int wave5_wait_vcpu_bus_busy(struct vpu_device *vpu_dev, unsigned int addr)
+{
+	return wave5_wait_fio_readl(vpu_dev, addr, 0);
+}
+
+static dma_addr_t wave5_read_reg_for_mem_addr(struct vpu_instance *inst,
+					      unsigned int reg_addr)
+{
+	dma_addr_t addr;
+	dma_addr_t high_addr = inst->dev->ext_addr;
+	u32 val;
+
+	val = vpu_read_reg(inst->dev, reg_addr);
+	addr = ((high_addr << 32) | val);
+
+	return addr;
+}
+
+bool wave5_vpu_is_init(struct vpu_device *vpu_dev)
+{
+	return vpu_read_reg(vpu_dev, W5_VCPU_CUR_PC) != 0;
+}
+
+unsigned int wave5_vpu_get_product_id(struct vpu_device *vpu_dev)
+{
+	unsigned int product_id = PRODUCT_ID_NONE;
+	u32 val;
+
+	val = vpu_read_reg(vpu_dev, W5_PRODUCT_NUMBER);
+
+	switch (val) {
+	case WAVE521_CODE:
+	case WAVE521C_CODE:
+	case WAVE521C_DUAL_CODE:
+	case WAVE521E1_CODE:
+		product_id = PRODUCT_ID_521;
+		break;
+	case WAVE511_CODE:
+		product_id = PRODUCT_ID_511;
+		break;
+	case WAVE517_CODE:
+	case WAVE537_CODE:
+		product_id = PRODUCT_ID_517;
+		break;
+	default:
+		dev_err(vpu_dev->dev, "Invalid product id (%x)\n", val);
+		break;
+	}
+	return product_id;
+}
+
+void wave5_bit_issue_command(struct vpu_instance *inst, u32 cmd)
+{
+	u32 instance_index = inst->id;
+	u32 codec_mode = inst->std;
+
+	vpu_write_reg(inst->dev, W5_CMD_INSTANCE_INFO, (codec_mode << 16) |
+			(instance_index & 0xffff));
+	vpu_write_reg(inst->dev, W5_VPU_BUSY_STATUS, 1);
+	vpu_write_reg(inst->dev, W5_COMMAND, cmd);
+
+	dev_dbg(inst->dev->dev, "%s: cmd=0x%x\n", __func__, cmd);
+
+	vpu_write_reg(inst->dev, W5_VPU_HOST_INT_REQ, 1);
+}
+
+static int wave5_send_query(struct vpu_instance *inst, enum QUERY_OPT query_opt)
+{
+	int ret;
+
+	vpu_write_reg(inst->dev, W5_QUERY_OPTION, query_opt);
+	vpu_write_reg(inst->dev, W5_VPU_BUSY_STATUS, 1);
+	wave5_bit_issue_command(inst, W5_QUERY);
+
+	ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);
+	if (ret) {
+		dev_warn(inst->dev->dev, "command: 'W5_QUERY', timed out opt=0x%x\n", query_opt);
+		return ret;
+	}
+
+	if (!vpu_read_reg(inst->dev, W5_RET_SUCCESS))
+		return -EIO;
+
+	return 0;
+}
+
+static int setup_wave5_properties(struct device *dev)
+{
+	struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+	struct vpu_attr *p_attr = &vpu_dev->attr;
+	u32 reg_val;
+	u8 *str;
+	int ret;
+	u32 hw_config_def0, hw_config_def1, hw_config_feature, hw_config_rev;
+
+	vpu_write_reg(vpu_dev, W5_QUERY_OPTION, GET_VPU_INFO);
+	vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
+	vpu_write_reg(vpu_dev, W5_COMMAND, W5_QUERY);
+	vpu_write_reg(vpu_dev, W5_VPU_HOST_INT_REQ, 1);
+	ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);
+	if (ret)
+		return ret;
+
+	if (!vpu_read_reg(vpu_dev, W5_RET_SUCCESS))
+		return -EIO;
+
+	reg_val = vpu_read_reg(vpu_dev, W5_RET_PRODUCT_NAME);
+	str = (u8 *)&reg_val;
+	p_attr->product_name[0] = str[3];
+	p_attr->product_name[1] = str[2];
+	p_attr->product_name[2] = str[1];
+	p_attr->product_name[3] = str[0];
+	p_attr->product_name[4] = 0;
+
+	p_attr->product_id = wave5_vpu_get_product_id(vpu_dev);
+	p_attr->product_version = vpu_read_reg(vpu_dev, W5_RET_PRODUCT_VERSION);
+	p_attr->fw_version = vpu_read_reg(vpu_dev, W5_RET_FW_VERSION);
+	p_attr->customer_id = vpu_read_reg(vpu_dev, W5_RET_CUSTOMER_ID);
+	hw_config_def0 = vpu_read_reg(vpu_dev, W5_RET_STD_DEF0);
+	hw_config_def1 = vpu_read_reg(vpu_dev, W5_RET_STD_DEF1);
+	hw_config_feature = vpu_read_reg(vpu_dev, W5_RET_CONF_FEATURE);
+	hw_config_rev = vpu_read_reg(vpu_dev, W5_RET_CONF_REVISION);
+
+	p_attr->support_hevc10bit_enc = (hw_config_feature >> 3) & 1;
+	if (hw_config_rev > 167455) //20190321
+		p_attr->support_avc10bit_enc = (hw_config_feature >> 11) & 1;
+	else
+		p_attr->support_avc10bit_enc = p_attr->support_hevc10bit_enc;
+
+	p_attr->support_decoders = 0;
+	p_attr->support_encoders = 0;
+	if (p_attr->product_id == PRODUCT_ID_521) {
+		p_attr->support_dual_core = ((hw_config_def1 >> 26) & 0x01);
+		if (p_attr->support_dual_core || hw_config_rev < 206116) {
+			p_attr->support_decoders = BIT(STD_AVC);
+			p_attr->support_decoders |= BIT(STD_HEVC);
+			p_attr->support_encoders = BIT(STD_AVC);
+			p_attr->support_encoders |= BIT(STD_HEVC);
+		} else {
+			p_attr->support_decoders |= (((hw_config_def1 >> 3) & 0x01) << STD_AVC);
+			p_attr->support_decoders |= (((hw_config_def1 >> 2) & 0x01) << STD_HEVC);
+			p_attr->support_encoders = (((hw_config_def1 >> 1) & 0x01) << STD_AVC);
+			p_attr->support_encoders |= ((hw_config_def1 & 0x01) << STD_HEVC);
+		}
+	} else if (p_attr->product_id == PRODUCT_ID_511) {
+		p_attr->support_decoders = BIT(STD_HEVC);
+		p_attr->support_decoders |= BIT(STD_AVC);
+	} else if (p_attr->product_id == PRODUCT_ID_517) {
+		p_attr->support_decoders = (((hw_config_def1 >> 4) & 0x01) << STD_AV1);
+		p_attr->support_decoders |= (((hw_config_def1 >> 3) & 0x01) << STD_AVS2);
+		p_attr->support_decoders |= (((hw_config_def1 >> 2) & 0x01) << STD_AVC);
+		p_attr->support_decoders |= (((hw_config_def1 >> 1) & 0x01) << STD_VP9);
+		p_attr->support_decoders |= ((hw_config_def1 & 0x01) << STD_HEVC);
+	}
+
+	p_attr->support_backbone = (hw_config_def0 >> 16) & 0x01;
+	p_attr->support_vcpu_backbone = (hw_config_def0 >> 28) & 0x01;
+	p_attr->support_vcore_backbone = (hw_config_def0 >> 22) & 0x01;
+	p_attr->support_dual_core = (hw_config_def1 >> 26) & 0x01;
+	p_attr->support_endian_mask = BIT(VDI_LITTLE_ENDIAN) |
+				      BIT(VDI_BIG_ENDIAN) |
+				      BIT(VDI_32BIT_LITTLE_ENDIAN) |
+				      BIT(VDI_32BIT_BIG_ENDIAN) |
+				      (0xffffUL << 16);
+	p_attr->support_bitstream_mode = BIT(BS_MODE_INTERRUPT) |
+		BIT(BS_MODE_PIC_END);
+
+	return 0;
+}
+
+int wave5_vpu_get_version(struct vpu_device *vpu_dev, u32 *revision)
+{
+	u32 reg_val;
+	int ret;
+
+	vpu_write_reg(vpu_dev, W5_QUERY_OPTION, GET_VPU_INFO);
+	vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
+	vpu_write_reg(vpu_dev, W5_COMMAND, W5_QUERY);
+	vpu_write_reg(vpu_dev, W5_VPU_HOST_INT_REQ, 1);
+	ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);
+	if (ret) {
+		dev_err(vpu_dev->dev, "%s: timeout\n", __func__);
+		return ret;
+	}
+
+	if (!vpu_read_reg(vpu_dev, W5_RET_SUCCESS)) {
+		dev_err(vpu_dev->dev, "%s: failed\n", __func__);
+		return -EIO;
+	}
+
+	reg_val = vpu_read_reg(vpu_dev, W5_RET_FW_VERSION);
+	if (revision)
+		*revision = reg_val;
+
+	return 0;
+}
+
+static void remap_page(struct vpu_device *vpu_dev, dma_addr_t code_base, u32 index)
+{
+	u32 remap_size = (W5_REMAP_MAX_SIZE >> 12) & 0x1ff;
+	u32 reg_val = 0x80000000 | (WAVE5_UPPER_PROC_AXI_ID << 20) | (index << 12) | BIT(11)
+		| remap_size;
+
+	vpu_write_reg(vpu_dev, W5_VPU_REMAP_CTRL, reg_val);
+	vpu_write_reg(vpu_dev, W5_VPU_REMAP_VADDR, index * W5_REMAP_MAX_SIZE);
+	vpu_write_reg(vpu_dev, W5_VPU_REMAP_PADDR, code_base + index * W5_REMAP_MAX_SIZE);
+}
+
+int wave5_vpu_init(struct device *dev, u8 *fw, size_t size)
+{
+	struct vpu_buf *common_vb;
+	dma_addr_t code_base, temp_base;
+	u32 code_size, temp_size;
+	u32 i, reg_val;
+	int ret;
+	struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+
+	common_vb = &vpu_dev->common_mem;
+
+	code_base = common_vb->daddr;
+	/* ALIGN TO 4KB */
+	code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff);
+	if (code_size < size * 2)
+		return -EINVAL;
+
+	temp_base = common_vb->daddr + WAVE5_TEMPBUF_OFFSET;
+	temp_size = WAVE5_TEMPBUF_SIZE;
+
+	ret = wave5_vdi_write_memory(vpu_dev, common_vb, 0, fw, size, VDI_128BIT_LITTLE_ENDIAN);
+	if (ret < 0) {
+		dev_err(vpu_dev->dev, "VPU init, Writing firmware to common buffer, fail: %d\n",
+			ret);
+		return ret;
+	}
+
+	vpu_write_reg(vpu_dev, W5_PO_CONF, 0);
+
+	/* clear registers */
+
+	for (i = W5_CMD_REG_BASE; i < W5_CMD_REG_END; i += 4)
+		vpu_write_reg(vpu_dev, i, 0x00);
+
+	remap_page(vpu_dev, code_base, W5_REMAP_INDEX0);
+	remap_page(vpu_dev, code_base, W5_REMAP_INDEX1);
+
+	vpu_write_reg(vpu_dev, W5_ADDR_CODE_BASE, code_base);
+	vpu_write_reg(vpu_dev, W5_CODE_SIZE, code_size);
+	vpu_write_reg(vpu_dev, W5_CODE_PARAM, (WAVE5_UPPER_PROC_AXI_ID << 4) | 0);
+	vpu_write_reg(vpu_dev, W5_ADDR_TEMP_BASE, temp_base);
+	vpu_write_reg(vpu_dev, W5_TEMP_SIZE, temp_size);
+
+	vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);
+
+	reg_val = (vpu_dev->ext_addr & 0xFFFF);
+	wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, reg_val);
+	reg_val = ((WAVE5_PROC_AXI_AXPROT & 0x7) << 4) |
+		(WAVE5_PROC_AXI_AXCACHE & 0xF);
+	wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, reg_val);
+	reg_val = ((WAVE5_SEC_AXI_AXPROT & 0x7) << 20) |
+		((WAVE5_SEC_AXI_AXCACHE & 0xF) << 16) |
+		(WAVE5_SEC_AXI_EXT_ADDR & 0xFFFF);
+	vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, reg_val);
+
+	/* interrupt */
+	// encoder
+	reg_val = BIT(INT_WAVE5_ENC_SET_PARAM);
+	reg_val |= BIT(INT_WAVE5_ENC_PIC);
+	reg_val |= BIT(INT_WAVE5_BSBUF_FULL);
+	// decoder
+	reg_val |= BIT(INT_WAVE5_INIT_SEQ);
+	reg_val |= BIT(INT_WAVE5_DEC_PIC);
+	reg_val |= BIT(INT_WAVE5_BSBUF_EMPTY);
+	vpu_write_reg(vpu_dev, W5_VPU_VINT_ENABLE, reg_val);
+
+	reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);
+	if ((reg_val >> 16) & 1) {
+		reg_val = ((WAVE5_PROC_AXI_ID << 28) |
+			   (WAVE5_PRP_AXI_ID << 24) |
+			   (WAVE5_FBD_Y_AXI_ID << 20) |
+			   (WAVE5_FBC_Y_AXI_ID << 16) |
+			   (WAVE5_FBD_C_AXI_ID << 12) |
+			   (WAVE5_FBC_C_AXI_ID << 8) |
+			   (WAVE5_PRI_AXI_ID << 4) |
+			   WAVE5_SEC_AXI_ID);
+		wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);
+	}
+
+	vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
+	vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU);
+	vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1);
+	ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);
+	if (ret) {
+		dev_err(vpu_dev->dev, "VPU init(W5_VPU_REMAP_CORE_START) timeout\n");
+		return ret;
+	}
+
+	reg_val = vpu_read_reg(vpu_dev, W5_RET_SUCCESS);
+	if (!reg_val) {
+		u32 reason_code = vpu_read_reg(vpu_dev, W5_RET_FAIL_REASON);
+
+		wave5_print_reg_err(vpu_dev, reason_code);
+		return -EIO;
+	}
+
+	return setup_wave5_properties(dev);
+}
+
+int wave5_vpu_build_up_dec_param(struct vpu_instance *inst,
+				 struct dec_open_param *param)
+{
+	int ret;
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	u32 bs_endian;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	p_dec_info->cycle_per_tick = 256;
+	if (vpu_dev->sram_buf.size) {
+		p_dec_info->sec_axi_info.use_bit_enable = 1;
+		p_dec_info->sec_axi_info.use_ip_enable = 1;
+		p_dec_info->sec_axi_info.use_lf_row_enable = 1;
+	}
+
+	switch (inst->std) {
+	case W_HEVC_DEC:
+		p_dec_info->seq_change_mask = SEQ_CHANGE_ENABLE_ALL_HEVC;
+		break;
+	case W_VP9_DEC:
+		p_dec_info->seq_change_mask = SEQ_CHANGE_ENABLE_ALL_VP9;
+		break;
+	case W_AVS2_DEC:
+		p_dec_info->seq_change_mask = SEQ_CHANGE_ENABLE_ALL_AVS2;
+		break;
+	case W_AVC_DEC:
+		p_dec_info->seq_change_mask = SEQ_CHANGE_ENABLE_ALL_AVC;
+		break;
+	case W_AV1_DEC:
+		p_dec_info->seq_change_mask = SEQ_CHANGE_ENABLE_ALL_AV1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (vpu_dev->product == PRODUCT_ID_517)
+		p_dec_info->vb_work.size = WAVE517_WORKBUF_SIZE;
+	else if (vpu_dev->product == PRODUCT_ID_521)
+		p_dec_info->vb_work.size = WAVE521DEC_WORKBUF_SIZE;
+	else if (vpu_dev->product == PRODUCT_ID_511)
+		p_dec_info->vb_work.size = WAVE521DEC_WORKBUF_SIZE;
+
+	ret = wave5_vdi_allocate_dma_memory(inst->dev, &p_dec_info->vb_work);
+	if (ret)
+		return ret;
+
+	vpu_write_reg(inst->dev, W5_CMD_DEC_VCORE_INFO, 1);
+
+	wave5_vdi_clear_memory(inst->dev, &p_dec_info->vb_work);
+
+	vpu_write_reg(inst->dev, W5_ADDR_WORK_BASE, p_dec_info->vb_work.daddr);
+	vpu_write_reg(inst->dev, W5_WORK_SIZE, p_dec_info->vb_work.size);
+
+	vpu_write_reg(inst->dev, W5_CMD_ADDR_SEC_AXI, vpu_dev->sram_buf.daddr);
+	vpu_write_reg(inst->dev, W5_CMD_SEC_AXI_SIZE, vpu_dev->sram_buf.size);
+
+	vpu_write_reg(inst->dev, W5_CMD_DEC_BS_START_ADDR, p_dec_info->stream_buf_start_addr);
+	vpu_write_reg(inst->dev, W5_CMD_DEC_BS_SIZE, p_dec_info->stream_buf_size);
+
+	/* NOTE: when endian mode is 0, SDMA reads MSB first */
+	bs_endian = wave5_vdi_convert_endian(inst->dev, param->stream_endian);
+	bs_endian = (~bs_endian & VDI_128BIT_ENDIAN_MASK);
+	vpu_write_reg(inst->dev, W5_CMD_BS_PARAM, bs_endian);
+	vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, (param->pri_axprot << 20) |
+			(param->pri_axcache << 16) | inst->dev->ext_addr);
+	vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1, (COMMAND_QUEUE_DEPTH - 1));
+	vpu_write_reg(inst->dev, W5_CMD_ERR_CONCEAL, (param->error_conceal_unit << 2) |
+			(param->error_conceal_mode));
+
+	wave5_bit_issue_command(inst, W5_CREATE_INSTANCE);
+	// check QUEUE_DONE
+	ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);
+	if (ret) {
+		dev_warn(inst->dev->dev, "command: 'W5_CREATE_INSTANCE' timed out\n");
+		goto free_vb_work;
+	}
+
+	// Check if we were able to add the parameters into the VCPU QUEUE
+	if (!vpu_read_reg(inst->dev, W5_RET_SUCCESS)) {
+		ret = -EIO;
+		goto free_vb_work;
+	}
+
+	p_dec_info->product_code = vpu_read_reg(inst->dev, W5_PRODUCT_NUMBER);
+
+	return 0;
+free_vb_work:
+	wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_work);
+	return ret;
+}
+
+int wave5_vpu_dec_init_seq(struct vpu_instance *inst)
+{
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	u32 cmd_option = INIT_SEQ_NORMAL;
+	u32 reg_val, bs_option;
+	int ret;
+
+	if (!inst->codec_info)
+		return -EINVAL;
+
+	if (p_dec_info->thumbnail_mode)
+		cmd_option = INIT_SEQ_W_THUMBNAIL;
+
+	/* set attributes of bitstream buffer controller */
+	switch (p_dec_info->open_param.bitstream_mode) {
+	case BS_MODE_INTERRUPT:
+		bs_option = BSOPTION_ENABLE_EXPLICIT_END;
+		break;
+	case BS_MODE_PIC_END:
+		bs_option = BSOPTION_ENABLE_EXPLICIT_END;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	vpu_write_reg(inst->dev, W5_BS_RD_PTR, p_dec_info->stream_rd_ptr);
+	vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr);
+
+	if (p_dec_info->stream_endflag)
+		bs_option = 3;
+	if (inst->std == W_AV1_DEC)
+		bs_option |= ((p_dec_info->open_param.av1_format) << 2);
+	vpu_write_reg(inst->dev, W5_BS_OPTION, BIT(31) | bs_option);
+
+	vpu_write_reg(inst->dev, W5_COMMAND_OPTION, cmd_option);
+	vpu_write_reg(inst->dev, W5_CMD_DEC_USER_MASK, p_dec_info->user_data_enable);
+
+	wave5_bit_issue_command(inst, W5_INIT_SEQ);
+
+	// check QUEUE_DONE
+	ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);
+	if (ret) {
+		dev_warn(inst->dev->dev, "command: 'W5_INIT_SEQ', timed out\n");
+		return ret;
+	}
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS);
+
+	p_dec_info->instance_queue_count = (reg_val >> 16) & 0xff;
+	p_dec_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);
+
+	// Check if we were able to add a command into VCPU QUEUE
+	if (!vpu_read_reg(inst->dev, W5_RET_SUCCESS)) {
+		reg_val = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+		wave5_print_reg_err(inst->dev, reg_val);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void wave5_get_dec_seq_result(struct vpu_instance *inst, struct dec_initial_info *info)
+{
+	u32 reg_val, sub_layer_info;
+	u32 profile_compatibility_flag;
+	u32 output_bit_depth_minus8;
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+
+	p_dec_info->stream_rd_ptr = wave5_vpu_dec_get_rd_ptr(inst);
+	info->rd_ptr = p_dec_info->stream_rd_ptr;
+
+	p_dec_info->frame_display_flag = vpu_read_reg(inst->dev, W5_RET_DEC_DISP_IDC);
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_SIZE);
+	info->pic_width = ((reg_val >> 16) & 0xffff);
+	info->pic_height = (reg_val & 0xffff);
+	info->min_frame_buffer_count = vpu_read_reg(inst->dev, W5_RET_DEC_NUM_REQUIRED_FB);
+	info->frame_buf_delay = vpu_read_reg(inst->dev, W5_RET_DEC_NUM_REORDER_DELAY);
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_CROP_LEFT_RIGHT);
+	info->pic_crop_rect.left = (reg_val >> 16) & 0xffff;
+	info->pic_crop_rect.right = reg_val & 0xffff;
+	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_CROP_TOP_BOTTOM);
+	info->pic_crop_rect.top = (reg_val >> 16) & 0xffff;
+	info->pic_crop_rect.bottom = reg_val & 0xffff;
+
+	info->f_rate_numerator = vpu_read_reg(inst->dev, W5_RET_DEC_FRAME_RATE_NR);
+	info->f_rate_denominator = vpu_read_reg(inst->dev, W5_RET_DEC_FRAME_RATE_DR);
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_COLOR_SAMPLE_INFO);
+	info->luma_bitdepth = reg_val & 0xf;
+	info->chroma_bitdepth = (reg_val >> 4) & 0xf;
+	info->chroma_format_idc = (reg_val >> 8) & 0xf;
+	info->aspect_rate_info = (reg_val >> 16) & 0xff;
+	info->is_ext_sar = ((info->aspect_rate_info == 255) ? true : false);
+	/* [0:15] - vertical size, [16:31] - horizontal size */
+	if (info->is_ext_sar)
+		info->aspect_rate_info = vpu_read_reg(inst->dev, W5_RET_DEC_ASPECT_RATIO);
+	info->bit_rate = vpu_read_reg(inst->dev, W5_RET_DEC_BIT_RATE);
+
+	sub_layer_info = vpu_read_reg(inst->dev, W5_RET_DEC_SUB_LAYER_INFO);
+	info->max_temporal_layers = (sub_layer_info >> 8) & 0x7;
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_SEQ_PARAM);
+	info->level = reg_val & 0xff;
+	profile_compatibility_flag = (reg_val >> 12) & 0xff;
+	info->profile = (reg_val >> 24) & 0x1f;
+	info->tier = (reg_val >> 29) & 0x01;
+	output_bit_depth_minus8 = (reg_val >> 30) & 0x03;
+
+	if (inst->std == W_HEVC_DEC) {
+		/* guessing profile */
+		if (!info->profile) {
+			if ((profile_compatibility_flag & 0x06) == 0x06)
+				info->profile = HEVC_PROFILE_MAIN; /* main profile */
+			else if ((profile_compatibility_flag & 0x04) == 0x04)
+				info->profile = HEVC_PROFILE_MAIN10; /* main10 profile */
+			else if ((profile_compatibility_flag & 0x08) == 0x08)
+				/* main still picture profile */
+				info->profile = HEVC_PROFILE_STILLPICTURE;
+			else
+				info->profile = HEVC_PROFILE_MAIN; /* for old version HM */
+		}
+
+	} else if (inst->std == W_AVS2_DEC) {
+		if (info->luma_bitdepth == 10 && output_bit_depth_minus8 == 2)
+			info->output_bit_depth = 10;
+		else
+			info->output_bit_depth = 8;
+
+	} else if (inst->std == W_AVC_DEC) {
+		info->profile = (reg_val >> 24) & 0x7f;
+	}
+
+	info->vlc_buf_size = vpu_read_reg(inst->dev, W5_RET_VLC_BUF_SIZE);
+	info->param_buf_size = vpu_read_reg(inst->dev, W5_RET_PARAM_BUF_SIZE);
+	p_dec_info->vlc_buf_size = info->vlc_buf_size;
+	p_dec_info->param_buf_size = info->param_buf_size;
+}
+
+int wave5_vpu_dec_get_seq_info(struct vpu_instance *inst, struct dec_initial_info *info)
+{
+	int ret;
+	u32 reg_val;
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+
+	vpu_write_reg(inst->dev, W5_CMD_DEC_ADDR_REPORT_BASE, p_dec_info->user_data_buf_addr);
+	vpu_write_reg(inst->dev, W5_CMD_DEC_REPORT_SIZE, p_dec_info->user_data_buf_size);
+	vpu_write_reg(inst->dev, W5_CMD_DEC_REPORT_PARAM,
+		      VPU_USER_DATA_ENDIAN & VDI_128BIT_ENDIAN_MASK);
+
+	// send QUERY cmd
+	ret = wave5_send_query(inst, GET_RESULT);
+	if (ret) {
+		if (ret == -EIO) {
+			reg_val = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+			wave5_print_reg_err(inst->dev, reg_val);
+		}
+		return ret;
+	}
+
+	dev_dbg(inst->dev->dev, "%s: init seq complete\n", __func__);
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS);
+
+	p_dec_info->instance_queue_count = (reg_val >> 16) & 0xff;
+	p_dec_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);
+
+	/* this is not a fatal error, set ret to -EIO but don't return immediately */
+	if (vpu_read_reg(inst->dev, W5_RET_DEC_DECODING_SUCCESS) != 1) {
+		info->seq_init_err_reason = vpu_read_reg(inst->dev, W5_RET_DEC_ERR_INFO);
+		ret = -EIO;
+	} else {
+		info->warn_info = vpu_read_reg(inst->dev, W5_RET_DEC_WARN_INFO);
+	}
+
+	// get sequence info
+	info->user_data_size = 0;
+	info->user_data_buf_full = false;
+	info->user_data_header = vpu_read_reg(inst->dev, W5_RET_DEC_USERDATA_IDC);
+	if (info->user_data_header) {
+		if (info->user_data_header & BIT(USERDATA_FLAG_BUFF_FULL))
+			info->user_data_buf_full = true;
+		info->user_data_size = p_dec_info->user_data_buf_size;
+	}
+
+	wave5_get_dec_seq_result(inst, info);
+
+	return ret;
+}
+
+static u32 calculate_table_size(u32 bit_depth, u32 frame_width, u32 frame_height, u32 ot_bg_width)
+{
+	u32 bgs_width = ((bit_depth > 8) ? 256 : 512);
+	u32 comp_frame_width = ALIGN(ALIGN(frame_width, 16) + 16, 16);
+	u32 ot_frame_width = ALIGN(comp_frame_width, ot_bg_width);
+
+	// sizeof_offset_table()
+	u32 ot_bg_height = 32;
+	u32 bgs_height = BIT(14) / bgs_width / ((bit_depth > 8) ? 2 : 1);
+	u32 comp_frame_height = ALIGN(ALIGN(frame_height, 4) + 4, bgs_height);
+	u32 ot_frame_height = ALIGN(comp_frame_height, ot_bg_height);
+
+	return (ot_frame_width / 16) * (ot_frame_height / 4) * 2;
+}
+
+int wave5_vpu_dec_register_framebuffer(struct vpu_instance *inst, struct frame_buffer *fb_arr,
+				       enum tiled_map_type map_type, unsigned int count)
+{
+	int ret;
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	struct dec_initial_info *init_info = &p_dec_info->initial_info;
+	size_t remain, idx, j, i, cnt_8_chunk;
+	u32 start_no, end_no;
+	u32 reg_val, cbcr_interleave, nv21, pic_size;
+	u32 endian;
+	u32 addr_y, addr_cb, addr_cr;
+	u32 table_width = init_info->pic_width;
+	u32 table_height = init_info->pic_height;
+	u32 mv_col_size, frame_width, frame_height, fbc_y_tbl_size, fbc_c_tbl_size;
+	struct vpu_buf vb_buf;
+	bool justified = WTL_RIGHT_JUSTIFIED;
+	u32 format_no = WTL_PIXEL_8BIT;
+	u32 color_format = 0;
+	u32 pixel_order = 1;
+	u32 bwb_flag = (map_type == LINEAR_FRAME_MAP) ? 1 : 0;
+
+	cbcr_interleave = inst->cbcr_interleave;
+	nv21 = inst->nv21;
+	mv_col_size = 0;
+	fbc_y_tbl_size = 0;
+	fbc_c_tbl_size = 0;
+
+	if (map_type >= COMPRESSED_FRAME_MAP) {
+		cbcr_interleave = 0;
+		nv21 = 0;
+
+		switch (inst->std) {
+		case W_HEVC_DEC:
+			mv_col_size = WAVE5_DEC_HEVC_BUF_SIZE(init_info->pic_width,
+							      init_info->pic_height);
+			break;
+		case W_VP9_DEC:
+			mv_col_size = WAVE5_DEC_VP9_BUF_SIZE(init_info->pic_width,
+							     init_info->pic_height);
+			table_width = ALIGN(table_width, 64);
+			table_height = ALIGN(table_height, 64);
+			break;
+		case W_AVS2_DEC:
+			mv_col_size = WAVE5_DEC_AVS2_BUF_SIZE(init_info->pic_width,
+							      init_info->pic_height);
+			break;
+		case W_AVC_DEC:
+			mv_col_size = WAVE5_DEC_AVC_BUF_SIZE(init_info->pic_width,
+							     init_info->pic_height);
+			break;
+		case W_AV1_DEC:
+			mv_col_size = WAVE5_DEC_AV1_BUF_SZ_1(init_info->pic_width,
+							     init_info->pic_height) +
+				WAVE5_DEC_AV1_BUF_SZ_2(init_info->pic_width, init_info->pic_width,
+						       init_info->pic_height);
+			table_width = ALIGN(table_width, 16);
+			table_height = ALIGN(table_height, 8);
+			break;
+		default:
+			return -EINVAL;
+		}
+
+		mv_col_size = ALIGN(mv_col_size, 16);
+		vb_buf.daddr = 0;
+		if (inst->std == W_HEVC_DEC || inst->std == W_AVS2_DEC || inst->std ==
+				W_VP9_DEC || inst->std == W_AVC_DEC || inst->std ==
+				W_AV1_DEC) {
+			vb_buf.size = ALIGN(mv_col_size, BUFFER_MARGIN) + BUFFER_MARGIN;
+
+			for (i = 0 ; i < count ; i++) {
+				if (p_dec_info->vb_mv[i].size == 0) {
+					ret = wave5_vdi_allocate_dma_memory(inst->dev, &vb_buf);
+					if (ret)
+						goto free_mv_buffers;
+					p_dec_info->vb_mv[i] = vb_buf;
+				}
+			}
+		}
+
+		frame_width = ALIGN(init_info->pic_width, 16);
+		frame_height = ALIGN(init_info->pic_height, 16);
+		if (p_dec_info->product_code == WAVE521C_DUAL_CODE) {
+			// Use a offset table BG width of 1024 for all decoders
+			fbc_y_tbl_size = calculate_table_size(init_info->luma_bitdepth,
+							      frame_width, frame_height, 1024);
+		} else {
+			fbc_y_tbl_size = ALIGN(WAVE5_FBC_LUMA_TABLE_SIZE(table_width,
+									 table_height), 16);
+		}
+
+		vb_buf.daddr = 0;
+		vb_buf.size = ALIGN(fbc_y_tbl_size, BUFFER_MARGIN) + BUFFER_MARGIN;
+		for (i = 0 ; i < count ; i++) {
+			if (p_dec_info->vb_fbc_y_tbl[i].size == 0) {
+				ret = wave5_vdi_allocate_dma_memory(inst->dev, &vb_buf);
+				if (ret)
+					goto free_fbc_y_tbl_buffers;
+				p_dec_info->vb_fbc_y_tbl[i] = vb_buf;
+			}
+		}
+
+		if (p_dec_info->product_code == WAVE521C_DUAL_CODE) {
+			// Use a offset table BG width of 1024 for all decoders
+			fbc_c_tbl_size = calculate_table_size(init_info->chroma_bitdepth,
+							      frame_width / 2, frame_height, 1024);
+		} else {
+			fbc_c_tbl_size = ALIGN(WAVE5_FBC_CHROMA_TABLE_SIZE(table_width,
+									   table_height), 16);
+		}
+
+		vb_buf.daddr = 0;
+		vb_buf.size = ALIGN(fbc_c_tbl_size, BUFFER_MARGIN) + BUFFER_MARGIN;
+		for (i = 0 ; i < count ; i++) {
+			if (p_dec_info->vb_fbc_c_tbl[i].size == 0) {
+				ret = wave5_vdi_allocate_dma_memory(inst->dev, &vb_buf);
+				if (ret)
+					goto free_fbc_c_tbl_buffers;
+				p_dec_info->vb_fbc_c_tbl[i] = vb_buf;
+			}
+		}
+		pic_size = (init_info->pic_width << 16) | (init_info->pic_height);
+
+		// allocate task_buffer
+		vb_buf.size = (p_dec_info->vlc_buf_size * VLC_BUF_NUM) +
+				(p_dec_info->param_buf_size * COMMAND_QUEUE_DEPTH);
+		vb_buf.daddr = 0;
+		ret = wave5_vdi_allocate_dma_memory(inst->dev, &vb_buf);
+		if (ret)
+			goto free_fbc_c_tbl_buffers;
+
+		p_dec_info->vb_task = vb_buf;
+
+		vpu_write_reg(inst->dev, W5_CMD_SET_FB_ADDR_TASK_BUF,
+			      p_dec_info->vb_task.daddr);
+		vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE, vb_buf.size);
+	} else {
+		pic_size = (init_info->pic_width << 16) | (init_info->pic_height);
+
+		if (inst->output_format == FORMAT_422)
+			color_format = 1;
+		else
+			color_format = 0;
+	}
+	endian = wave5_vdi_convert_endian(inst->dev, fb_arr[0].endian);
+	vpu_write_reg(inst->dev, W5_PIC_SIZE, pic_size);
+
+	reg_val = (bwb_flag << 28) |
+		  (pixel_order << 23) |
+		  (justified << 22) |
+		  (format_no << 20) |
+		  (color_format << 19) |
+		  (nv21 << 17) |
+		  (cbcr_interleave << 16) |
+		  (fb_arr[0].stride);
+	vpu_write_reg(inst->dev, W5_COMMON_PIC_INFO, reg_val);
+
+	remain = count;
+	cnt_8_chunk = ALIGN(count, 8) / 8;
+	idx = 0;
+	for (j = 0; j < cnt_8_chunk; j++) {
+		reg_val = (endian << 16) | (j == cnt_8_chunk - 1) << 4 | ((j == 0) << 3);
+		reg_val |= (p_dec_info->open_param.enable_non_ref_fbc_write << 26);
+		vpu_write_reg(inst->dev, W5_SFB_OPTION, reg_val);
+		start_no = j * 8;
+		end_no = start_no + ((remain >= 8) ? 8 : remain) - 1;
+
+		vpu_write_reg(inst->dev, W5_SET_FB_NUM, (start_no << 8) | end_no);
+
+		for (i = 0; i < 8 && i < remain; i++) {
+			if (map_type == LINEAR_FRAME_MAP && p_dec_info->open_param.cbcr_order ==
+					CBCR_ORDER_REVERSED) {
+				addr_y = fb_arr[i + start_no].buf_y;
+				addr_cb = fb_arr[i + start_no].buf_cr;
+				addr_cr = fb_arr[i + start_no].buf_cb;
+			} else {
+				addr_y = fb_arr[i + start_no].buf_y;
+				addr_cb = fb_arr[i + start_no].buf_cb;
+				addr_cr = fb_arr[i + start_no].buf_cr;
+			}
+			vpu_write_reg(inst->dev, W5_ADDR_LUMA_BASE0 + (i << 4), addr_y);
+			vpu_write_reg(inst->dev, W5_ADDR_CB_BASE0 + (i << 4), addr_cb);
+			if (map_type >= COMPRESSED_FRAME_MAP) {
+				/* luma FBC offset table */
+				vpu_write_reg(inst->dev, W5_ADDR_FBC_Y_OFFSET0 + (i << 4),
+					      p_dec_info->vb_fbc_y_tbl[idx].daddr);
+				/* chroma FBC offset table */
+				vpu_write_reg(inst->dev, W5_ADDR_FBC_C_OFFSET0 + (i << 4),
+					      p_dec_info->vb_fbc_c_tbl[idx].daddr);
+				vpu_write_reg(inst->dev, W5_ADDR_MV_COL0 + (i << 2),
+					      p_dec_info->vb_mv[idx].daddr);
+			} else {
+				vpu_write_reg(inst->dev, W5_ADDR_CR_BASE0 + (i << 4), addr_cr);
+				vpu_write_reg(inst->dev, W5_ADDR_FBC_C_OFFSET0 + (i << 4), 0);
+				vpu_write_reg(inst->dev, W5_ADDR_MV_COL0 + (i << 2), 0);
+			}
+			idx++;
+		}
+		remain -= i;
+
+		wave5_bit_issue_command(inst, W5_SET_FB);
+		ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);
+		if (ret)
+			goto free_buffers;
+	}
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_SUCCESS);
+	if (!reg_val) {
+		ret = -EIO;
+		goto free_buffers;
+	}
+
+	return 0;
+
+free_buffers:
+	wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_task);
+free_fbc_c_tbl_buffers:
+	for (i = 0; i < count; i++)
+		wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_fbc_c_tbl[i]);
+free_fbc_y_tbl_buffers:
+	for (i = 0; i < count; i++)
+		wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_fbc_y_tbl[i]);
+free_mv_buffers:
+	for (i = 0; i < count; i++)
+		wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_mv[i]);
+	return ret;
+}
+
+int wave5_vpu_decode(struct vpu_instance *inst, struct dec_param *option, u32 *fail_res)
+{
+	u32 mode_option = DEC_PIC_NORMAL, bs_option, reg_val;
+	u32 force_latency = 0;
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	struct dec_open_param *p_open_param = &p_dec_info->open_param;
+	int ret;
+
+	if (p_dec_info->thumbnail_mode) {
+		mode_option = DEC_PIC_W_THUMBNAIL;
+	} else if (option->skipframe_mode) {
+		switch (option->skipframe_mode) {
+		case WAVE_SKIPMODE_NON_IRAP:
+			mode_option = SKIP_NON_IRAP;
+			force_latency = 1;
+			break;
+		case WAVE_SKIPMODE_NON_REF:
+			mode_option = SKIP_NON_REF_PIC;
+			break;
+		default:
+			// skip mode off
+			break;
+		}
+	}
+
+	// set disable reorder
+	if (!p_dec_info->reorder_enable)
+		force_latency = 1;
+
+	/* set attributes of bitstream buffer controller */
+	bs_option = 0;
+	switch (p_open_param->bitstream_mode) {
+	case BS_MODE_INTERRUPT:
+		bs_option = BSOPTION_ENABLE_EXPLICIT_END;
+		break;
+	case BS_MODE_PIC_END:
+		bs_option = BSOPTION_ENABLE_EXPLICIT_END;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	vpu_write_reg(inst->dev, W5_BS_RD_PTR, p_dec_info->stream_rd_ptr);
+	vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr);
+	bs_option = (p_dec_info->stream_endflag << 1) | BS_EXPLICIT_END_MODE_ON;
+	if (p_open_param->bitstream_mode == BS_MODE_PIC_END)
+		bs_option |= BIT(31);
+	if (inst->std == W_AV1_DEC)
+		bs_option |= ((p_open_param->av1_format) << 2);
+	vpu_write_reg(inst->dev, W5_BS_OPTION, bs_option);
+
+	/* secondary AXI */
+	reg_val = p_dec_info->sec_axi_info.use_bit_enable |
+		(p_dec_info->sec_axi_info.use_ip_enable << 9) |
+		(p_dec_info->sec_axi_info.use_lf_row_enable << 15);
+	vpu_write_reg(inst->dev, W5_USE_SEC_AXI, reg_val);
+
+	/* set attributes of user buffer */
+	vpu_write_reg(inst->dev, W5_CMD_DEC_USER_MASK, p_dec_info->user_data_enable);
+
+	vpu_write_reg(inst->dev, W5_COMMAND_OPTION,
+		      ((option->disable_film_grain << 6) | (option->cra_as_bla_flag << 5) |
+		      mode_option));
+	vpu_write_reg(inst->dev, W5_CMD_DEC_TEMPORAL_ID_PLUS1,
+		      (p_dec_info->target_spatial_id << 9) |
+		      (p_dec_info->temp_id_select_mode << 8) | p_dec_info->target_temp_id);
+	vpu_write_reg(inst->dev, W5_CMD_SEQ_CHANGE_ENABLE_FLAG, p_dec_info->seq_change_mask);
+	vpu_write_reg(inst->dev, W5_CMD_DEC_FORCE_FB_LATENCY_PLUS1, force_latency);
+
+	wave5_bit_issue_command(inst, W5_DEC_PIC);
+	// check QUEUE_DONE
+	ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);
+	if (ret) {
+		dev_warn(inst->dev->dev, "command: 'W5_DEC_PIC', timed out\n");
+		return -ETIMEDOUT;
+	}
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS);
+
+	p_dec_info->instance_queue_count = (reg_val >> 16) & 0xff;
+	p_dec_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);
+	// Check if we were able to add a command into the VCPU QUEUE
+	if (!vpu_read_reg(inst->dev, W5_RET_SUCCESS)) {
+		*fail_res = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+		wave5_print_reg_err(inst->dev, *fail_res);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int wave5_vpu_dec_get_result(struct vpu_instance *inst, struct dec_output_info *result)
+{
+	int ret;
+	u32 index, nal_unit_type, reg_val, sub_layer_info;
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	vpu_write_reg(inst->dev, W5_CMD_DEC_ADDR_REPORT_BASE, p_dec_info->user_data_buf_addr);
+	vpu_write_reg(inst->dev, W5_CMD_DEC_REPORT_SIZE, p_dec_info->user_data_buf_size);
+	vpu_write_reg(inst->dev, W5_CMD_DEC_REPORT_PARAM,
+		      VPU_USER_DATA_ENDIAN & VDI_128BIT_ENDIAN_MASK);
+
+	// send QUERY cmd
+	ret = wave5_send_query(inst, GET_RESULT);
+	if (ret) {
+		if (ret == -EIO) {
+			reg_val = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+			wave5_print_reg_err(inst->dev, reg_val);
+		}
+
+		return ret;
+	}
+
+	dev_dbg(inst->dev->dev, "%s: dec pic complete\n", __func__);
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS);
+
+	p_dec_info->instance_queue_count = (reg_val >> 16) & 0xff;
+	p_dec_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_TYPE);
+
+	nal_unit_type = (reg_val >> 4) & 0x3f;
+
+	if (inst->std == W_VP9_DEC) {
+		if (reg_val & 0x01)
+			result->pic_type = PIC_TYPE_I;
+		else if (reg_val & 0x02)
+			result->pic_type = PIC_TYPE_P;
+		else if (reg_val & 0x04)
+			result->pic_type = PIC_TYPE_REPEAT;
+		else
+			result->pic_type = PIC_TYPE_MAX;
+	} else if (inst->std == W_HEVC_DEC) {
+		if (reg_val & 0x04)
+			result->pic_type = PIC_TYPE_B;
+		else if (reg_val & 0x02)
+			result->pic_type = PIC_TYPE_P;
+		else if (reg_val & 0x01)
+			result->pic_type = PIC_TYPE_I;
+		else
+			result->pic_type = PIC_TYPE_MAX;
+		if ((nal_unit_type == 19 || nal_unit_type == 20) && result->pic_type == PIC_TYPE_I)
+			/* IDR_W_RADL, IDR_N_LP */
+			result->pic_type = PIC_TYPE_IDR;
+	} else if (inst->std == W_AVC_DEC) {
+		if (reg_val & 0x04)
+			result->pic_type = PIC_TYPE_B;
+		else if (reg_val & 0x02)
+			result->pic_type = PIC_TYPE_P;
+		else if (reg_val & 0x01)
+			result->pic_type = PIC_TYPE_I;
+		else
+			result->pic_type = PIC_TYPE_MAX;
+		if (nal_unit_type == 5 && result->pic_type == PIC_TYPE_I)
+			result->pic_type = PIC_TYPE_IDR;
+	} else if (inst->std == W_AV1_DEC) {
+		switch (reg_val & 0x07) {
+		case 0:
+			result->pic_type = PIC_TYPE_KEY;
+			break;
+		case 1:
+			result->pic_type = PIC_TYPE_INTER;
+			break;
+		case 2:
+			result->pic_type = PIC_TYPE_AV1_INTRA;
+			break;
+		case 3:
+			result->pic_type = PIC_TYPE_AV1_SWITCH;
+			break;
+		default:
+			result->pic_type = PIC_TYPE_MAX;
+			break;
+		}
+	} else { // AVS2
+		switch (reg_val & 0x07) {
+		case 0:
+			result->pic_type = PIC_TYPE_I;
+			break;
+		case 1:
+			result->pic_type = PIC_TYPE_P;
+			break;
+		case 2:
+			result->pic_type = PIC_TYPE_B;
+			break;
+		case 3:
+			result->pic_type = PIC_TYPE_AVS2_F;
+			break;
+		case 4:
+			result->pic_type = PIC_TYPE_AVS2_S;
+			break;
+		case 5:
+			result->pic_type = PIC_TYPE_AVS2_G;
+			break;
+		case 6:
+			result->pic_type = PIC_TYPE_AVS2_GB;
+			break;
+		default:
+			result->pic_type = PIC_TYPE_MAX;
+			break;
+		}
+	}
+	index = vpu_read_reg(inst->dev, W5_RET_DEC_DISPLAY_INDEX);
+	result->index_frame_display = index;
+	index = vpu_read_reg(inst->dev, W5_RET_DEC_DECODED_INDEX);
+	result->index_frame_decoded = index;
+	result->index_frame_decoded_for_tiled = index;
+
+	sub_layer_info = vpu_read_reg(inst->dev, W5_RET_DEC_SUB_LAYER_INFO);
+	result->temporal_id = sub_layer_info & 0x7;
+
+	if (inst->std == W_HEVC_DEC) {
+		result->decoded_poc = -1;
+		if (result->index_frame_decoded >= 0 ||
+		    result->index_frame_decoded == DECODED_IDX_FLAG_SKIP)
+			result->decoded_poc = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_POC);
+	} else if (inst->std == W_AVS2_DEC) {
+		result->avs2_info.decoded_poi = -1;
+		result->avs2_info.display_poi = -1;
+		if (result->index_frame_decoded >= 0)
+			result->avs2_info.decoded_poi =
+				vpu_read_reg(inst->dev, W5_RET_DEC_PIC_POC);
+	} else if (inst->std == W_AVC_DEC) {
+		result->decoded_poc = -1;
+		if (result->index_frame_decoded >= 0 ||
+		    result->index_frame_decoded == DECODED_IDX_FLAG_SKIP)
+			result->decoded_poc = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_POC);
+	} else if (inst->std == W_AV1_DEC) {
+		result->decoded_poc = -1;
+		if (result->index_frame_decoded >= 0 ||
+		    result->index_frame_decoded == DECODED_IDX_FLAG_SKIP)
+			result->decoded_poc = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_POC);
+	}
+
+	result->sequence_changed = vpu_read_reg(inst->dev, W5_RET_DEC_NOTIFICATION);
+	reg_val = vpu_read_reg(inst->dev, W5_RET_DEC_PIC_SIZE);
+	result->dec_pic_width = reg_val >> 16;
+	result->dec_pic_height = reg_val & 0xffff;
+
+	if (result->sequence_changed) {
+		memcpy((void *)&p_dec_info->new_seq_info, (void *)&p_dec_info->initial_info,
+		       sizeof(struct dec_initial_info));
+		wave5_get_dec_seq_result(inst, &p_dec_info->new_seq_info);
+	}
+
+	result->dec_host_cmd_tick = vpu_read_reg(inst->dev, W5_RET_DEC_HOST_CMD_TICK);
+	result->dec_decode_end_tick = vpu_read_reg(inst->dev, W5_RET_DEC_DECODING_ENC_TICK);
+
+	if (!p_dec_info->first_cycle_check) {
+		result->frame_cycle =
+			(result->dec_decode_end_tick - result->dec_host_cmd_tick) *
+			p_dec_info->cycle_per_tick;
+		vpu_dev->last_performance_cycles = result->dec_decode_end_tick;
+		p_dec_info->first_cycle_check = true;
+	} else if (result->index_frame_decoded_for_tiled != -1) {
+		result->frame_cycle =
+			(result->dec_decode_end_tick - vpu_dev->last_performance_cycles) *
+			p_dec_info->cycle_per_tick;
+		vpu_dev->last_performance_cycles = result->dec_decode_end_tick;
+		if (vpu_dev->last_performance_cycles < result->dec_host_cmd_tick)
+			result->frame_cycle =
+				(result->dec_decode_end_tick - result->dec_host_cmd_tick) *
+				p_dec_info->cycle_per_tick;
+	}
+
+	// no remaining command. reset frame cycle.
+	if (p_dec_info->instance_queue_count == 0 && p_dec_info->report_queue_count == 0)
+		p_dec_info->first_cycle_check = false;
+
+	return 0;
+}
+
+int wave5_vpu_re_init(struct device *dev, u8 *fw, size_t size)
+{
+	struct vpu_buf *common_vb;
+	dma_addr_t code_base, temp_base;
+	dma_addr_t old_code_base, temp_size;
+	u32 code_size;
+	u32 reg_val;
+	struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+
+	common_vb = &vpu_dev->common_mem;
+
+	code_base = common_vb->daddr;
+	/* ALIGN TO 4KB */
+	code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff);
+	if (code_size < size * 2)
+		return -EINVAL;
+	temp_base = common_vb->daddr + WAVE5_TEMPBUF_OFFSET;
+	temp_size = WAVE5_TEMPBUF_SIZE;
+
+	old_code_base = vpu_read_reg(vpu_dev, W5_VPU_REMAP_PADDR);
+
+	if (old_code_base != code_base + W5_REMAP_INDEX1 * W5_REMAP_MAX_SIZE) {
+		int ret;
+
+		ret = wave5_vdi_write_memory(vpu_dev, common_vb, 0, fw, size,
+					     VDI_128BIT_LITTLE_ENDIAN);
+		if (ret < 0) {
+			dev_err(vpu_dev->dev,
+				"VPU init, Writing firmware to common buffer, fail: %d\n", ret);
+			return ret;
+		}
+
+		vpu_write_reg(vpu_dev, W5_PO_CONF, 0);
+
+		ret = wave5_vpu_reset(dev, SW_RESET_ON_BOOT);
+		if (ret < 0) {
+			dev_err(vpu_dev->dev, "VPU init, Resetting the VPU, fail: %d\n", ret);
+			return ret;
+		}
+
+		remap_page(vpu_dev, code_base, W5_REMAP_INDEX0);
+		remap_page(vpu_dev, code_base, W5_REMAP_INDEX1);
+
+		vpu_write_reg(vpu_dev, W5_ADDR_CODE_BASE, code_base);
+		vpu_write_reg(vpu_dev, W5_CODE_SIZE, code_size);
+		vpu_write_reg(vpu_dev, W5_CODE_PARAM, (WAVE5_UPPER_PROC_AXI_ID << 4) | 0);
+		vpu_write_reg(vpu_dev, W5_ADDR_TEMP_BASE, temp_base);
+		vpu_write_reg(vpu_dev, W5_TEMP_SIZE, temp_size);
+
+		vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);
+
+		reg_val = (vpu_dev->ext_addr & 0xFFFF);
+		wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, reg_val);
+		reg_val = ((WAVE5_PROC_AXI_AXPROT & 0x7) << 4) |
+			(WAVE5_PROC_AXI_AXCACHE & 0xF);
+		wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, reg_val);
+		reg_val = ((WAVE5_SEC_AXI_AXPROT & 0x7) << 20) |
+			((WAVE5_SEC_AXI_AXCACHE & 0xF) << 16) |
+			(WAVE5_SEC_AXI_EXT_ADDR & 0xFFFF);
+		vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, reg_val);
+
+		/* interrupt */
+		// encoder
+		reg_val = BIT(INT_WAVE5_ENC_SET_PARAM);
+		reg_val |= BIT(INT_WAVE5_ENC_PIC);
+		reg_val |= BIT(INT_WAVE5_BSBUF_FULL);
+		// decoder
+		reg_val |= BIT(INT_WAVE5_INIT_SEQ);
+		reg_val |= BIT(INT_WAVE5_DEC_PIC);
+		reg_val |= BIT(INT_WAVE5_BSBUF_EMPTY);
+		vpu_write_reg(vpu_dev, W5_VPU_VINT_ENABLE, reg_val);
+
+		reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);
+		if ((reg_val >> 16) & 1) {
+			reg_val = ((WAVE5_PROC_AXI_ID << 28) |
+					(WAVE5_PRP_AXI_ID << 24) |
+					(WAVE5_FBD_Y_AXI_ID << 20) |
+					(WAVE5_FBC_Y_AXI_ID << 16) |
+					(WAVE5_FBD_C_AXI_ID << 12) |
+					(WAVE5_FBC_C_AXI_ID << 8) |
+					(WAVE5_PRI_AXI_ID << 4) |
+					WAVE5_SEC_AXI_ID);
+			wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);
+		}
+
+		vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
+		vpu_write_reg(vpu_dev, W5_COMMAND, W5_INIT_VPU);
+		vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1);
+
+		ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);
+		if (ret) {
+			dev_err(vpu_dev->dev, "VPU reinit(W5_VPU_REMAP_CORE_START) timeout\n");
+			return ret;
+		}
+
+		reg_val = vpu_read_reg(vpu_dev, W5_RET_SUCCESS);
+		if (!reg_val) {
+			u32 reason_code = vpu_read_reg(vpu_dev, W5_RET_FAIL_REASON);
+
+			wave5_print_reg_err(vpu_dev, reason_code);
+			return -EIO;
+		}
+	}
+
+	return setup_wave5_properties(dev);
+}
+
+int wave5_vpu_sleep_wake(struct device *dev, bool i_sleep_wake, const uint16_t *code,
+				size_t size)
+{
+	u32 reg_val;
+	struct vpu_buf *common_vb;
+	dma_addr_t code_base;
+	u32 code_size;
+	struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+	int ret;
+
+	if (i_sleep_wake) {
+		ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);
+		if (ret)
+			return ret;
+
+		/*
+		 * Declare who has ownership for the host interface access
+		 * 1 = VPU
+		 * 0 = Host processer
+		 */
+		vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
+		vpu_write_reg(vpu_dev, W5_COMMAND, W5_SLEEP_VPU);
+		/* Send an interrupt named HOST to the VPU */
+		vpu_write_reg(vpu_dev, W5_VPU_HOST_INT_REQ, 1);
+
+		ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);
+		if (ret)
+			return ret;
+
+		if (!vpu_read_reg(vpu_dev, W5_RET_SUCCESS)) {
+			u32 reason = vpu_read_reg(vpu_dev, W5_RET_FAIL_REASON);
+
+			wave5_print_reg_err(vpu_dev, reason);
+			return -EIO;
+		}
+	} else { /* restore */
+		common_vb = &vpu_dev->common_mem;
+
+		code_base = common_vb->daddr;
+		/* ALIGN TO 4KB */
+		code_size = (WAVE5_MAX_CODE_BUF_SIZE & ~0xfff);
+		if (code_size < size * 2) {
+			dev_err(dev, "size too small\n");
+			return -EINVAL;
+		}
+
+		/* Power on without DEBUG mode */
+		vpu_write_reg(vpu_dev, W5_PO_CONF, 0);
+
+		remap_page(vpu_dev, code_base, W5_REMAP_INDEX0);
+		remap_page(vpu_dev, code_base, W5_REMAP_INDEX1);
+
+		vpu_write_reg(vpu_dev, W5_ADDR_CODE_BASE, code_base);
+		vpu_write_reg(vpu_dev, W5_CODE_SIZE, code_size);
+		vpu_write_reg(vpu_dev, W5_CODE_PARAM, (WAVE5_UPPER_PROC_AXI_ID << 4) | 0);
+
+		vpu_write_reg(vpu_dev, W5_HW_OPTION, 0);
+
+		reg_val = (vpu_dev->ext_addr & 0xFFFF);
+		wave5_fio_writel(vpu_dev, W5_BACKBONE_PROC_EXT_ADDR, reg_val);
+		reg_val = ((WAVE5_PROC_AXI_AXPROT & 0x7) << 4) |
+			(WAVE5_PROC_AXI_AXCACHE & 0xF);
+		wave5_fio_writel(vpu_dev, W5_BACKBONE_AXI_PARAM, reg_val);
+		reg_val = ((WAVE5_SEC_AXI_AXPROT & 0x7) << 20) |
+			((WAVE5_SEC_AXI_AXCACHE & 0xF) << 16) |
+			(WAVE5_SEC_AXI_EXT_ADDR & 0xFFFF);
+		vpu_write_reg(vpu_dev, W5_SEC_AXI_PARAM, reg_val);
+
+		/* interrupt */
+		// encoder
+		reg_val = BIT(INT_WAVE5_ENC_SET_PARAM);
+		reg_val |= BIT(INT_WAVE5_ENC_PIC);
+		reg_val |= BIT(INT_WAVE5_BSBUF_FULL);
+		// decoder
+		reg_val |= BIT(INT_WAVE5_INIT_SEQ);
+		reg_val |= BIT(INT_WAVE5_DEC_PIC);
+		reg_val |= BIT(INT_WAVE5_BSBUF_EMPTY);
+		vpu_write_reg(vpu_dev, W5_VPU_VINT_ENABLE, reg_val);
+
+		reg_val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);
+		if ((reg_val >> 16) & 1) {
+			reg_val = ((WAVE5_PROC_AXI_ID << 28) |
+					(WAVE5_PRP_AXI_ID << 24) |
+					(WAVE5_FBD_Y_AXI_ID << 20) |
+					(WAVE5_FBC_Y_AXI_ID << 16) |
+					(WAVE5_FBD_C_AXI_ID << 12) |
+					(WAVE5_FBC_C_AXI_ID << 8) |
+					(WAVE5_PRI_AXI_ID << 4) |
+					WAVE5_SEC_AXI_ID);
+			wave5_fio_writel(vpu_dev, W5_BACKBONE_PROG_AXI_ID, reg_val);
+		}
+
+		vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 1);
+		vpu_write_reg(vpu_dev, W5_COMMAND, W5_WAKEUP_VPU);
+		/* Start VPU after settings */
+		vpu_write_reg(vpu_dev, W5_VPU_REMAP_CORE_START, 1);
+
+		ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_BUSY_STATUS);
+		if (ret) {
+			dev_err(vpu_dev->dev, "VPU wakeup(W5_VPU_REMAP_CORE_START) timeout\n");
+			return ret;
+		}
+
+		reg_val = vpu_read_reg(vpu_dev, W5_RET_SUCCESS);
+		if (!reg_val) {
+			u32 reason_code = vpu_read_reg(vpu_dev, W5_RET_FAIL_REASON);
+
+			wave5_print_reg_err(vpu_dev, reason_code);
+			return -EIO;
+		}
+	}
+
+	return 0;
+}
+
+int wave5_vpu_reset(struct device *dev, enum sw_reset_mode reset_mode)
+{
+	u32 val = 0;
+	int ret = 0;
+	struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+	struct vpu_attr *p_attr = &vpu_dev->attr;
+	// VPU doesn't send response. force to set BUSY flag to 0.
+	vpu_write_reg(vpu_dev, W5_VPU_BUSY_STATUS, 0);
+
+	if (reset_mode == SW_RESET_SAFETY) {
+		ret = wave5_vpu_sleep_wake(dev, true, NULL, 0);
+		if (ret)
+			return ret;
+	}
+
+	val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG0);
+	if ((val >> 16) & 0x1)
+		p_attr->support_backbone = true;
+	if ((val >> 22) & 0x1)
+		p_attr->support_vcore_backbone = true;
+	if ((val >> 28) & 0x1)
+		p_attr->support_vcpu_backbone = true;
+
+	val = vpu_read_reg(vpu_dev, W5_VPU_RET_VPU_CONFIG1);
+	if ((val >> 26) & 0x1)
+		p_attr->support_dual_core = true;
+
+	// waiting for completion of bus transaction
+	if (p_attr->support_backbone) {
+		dev_dbg(dev, "%s: backbone supported\n", __func__);
+
+		if (p_attr->support_dual_core) {
+			// check CORE0
+			wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE0, 0x7);
+
+			ret = wave5_wait_bus_busy(vpu_dev, W5_BACKBONE_BUS_STATUS_VCORE0);
+			if (ret) {
+				wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE0, 0x00);
+				return ret;
+			}
+
+			// check CORE1
+			wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE1, 0x7);
+
+			ret = wave5_wait_bus_busy(vpu_dev, W5_BACKBONE_BUS_STATUS_VCORE1);
+			if (ret) {
+				wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE1, 0x00);
+				return ret;
+			}
+
+		} else if (p_attr->support_vcore_backbone) {
+			if (p_attr->support_vcpu_backbone) {
+				// step1 : disable request
+				wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCPU, 0xFF);
+
+				// step2 : waiting for completion of bus transaction
+				ret = wave5_wait_vcpu_bus_busy(vpu_dev,
+							       W5_BACKBONE_BUS_STATUS_VCPU);
+				if (ret) {
+					wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCPU, 0x00);
+					return ret;
+				}
+			}
+			// step1 : disable request
+			wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE0, 0x7);
+
+			// step2 : waiting for completion of bus transaction
+			if (wave5_wait_bus_busy(vpu_dev, W5_BACKBONE_BUS_STATUS_VCORE0)) {
+				wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE0, 0x00);
+				return -EBUSY;
+			}
+		} else {
+			// step1 : disable request
+			wave5_fio_writel(vpu_dev, W5_COMBINED_BACKBONE_BUS_CTRL, 0x7);
+
+			// step2 : waiting for completion of bus transaction
+			if (wave5_wait_bus_busy(vpu_dev, W5_COMBINED_BACKBONE_BUS_STATUS)) {
+				wave5_fio_writel(vpu_dev, W5_COMBINED_BACKBONE_BUS_CTRL, 0x00);
+				return -EBUSY;
+			}
+		}
+	} else {
+		dev_dbg(dev, "%s: backbone NOT supported\n", __func__);
+		// step1 : disable request
+		wave5_fio_writel(vpu_dev, W5_GDI_BUS_CTRL, 0x100);
+
+		// step2 : waiting for completion of bus transaction
+		ret = wave5_wait_bus_busy(vpu_dev, W5_GDI_BUS_STATUS);
+		if (ret) {
+			wave5_fio_writel(vpu_dev, W5_GDI_BUS_CTRL, 0x00);
+			return ret;
+		}
+	}
+
+	switch (reset_mode) {
+	case SW_RESET_ON_BOOT:
+	case SW_RESET_FORCE:
+	case SW_RESET_SAFETY:
+		val = W5_RST_BLOCK_ALL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (val) {
+		vpu_write_reg(vpu_dev, W5_VPU_RESET_REQ, val);
+
+		ret = wave5_wait_vpu_busy(vpu_dev, W5_VPU_RESET_STATUS);
+		if (ret) {
+			vpu_write_reg(vpu_dev, W5_VPU_RESET_REQ, 0);
+			return ret;
+		}
+		vpu_write_reg(vpu_dev, W5_VPU_RESET_REQ, 0);
+	}
+	// step3 : must clear GDI_BUS_CTRL after done SW_RESET
+	if (p_attr->support_backbone) {
+		if (p_attr->support_dual_core) {
+			wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE0, 0x00);
+			wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE1, 0x00);
+		} else if (p_attr->support_vcore_backbone) {
+			if (p_attr->support_vcpu_backbone)
+				wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCPU, 0x00);
+			wave5_fio_writel(vpu_dev, W5_BACKBONE_BUS_CTRL_VCORE0, 0x00);
+		} else {
+			wave5_fio_writel(vpu_dev, W5_COMBINED_BACKBONE_BUS_CTRL, 0x00);
+		}
+	} else {
+		wave5_fio_writel(vpu_dev, W5_GDI_BUS_CTRL, 0x00);
+	}
+	if (reset_mode == SW_RESET_SAFETY || reset_mode == SW_RESET_FORCE)
+		ret = wave5_vpu_sleep_wake(dev, false, NULL, 0);
+
+	return ret;
+}
+
+int wave5_vpu_dec_finish_seq(struct vpu_instance *inst, u32 *fail_res)
+{
+	int ret;
+
+	wave5_bit_issue_command(inst, W5_DESTROY_INSTANCE);
+	ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);
+	if (ret)
+		return -ETIMEDOUT;
+
+	if (!vpu_read_reg(inst->dev, W5_RET_SUCCESS)) {
+		*fail_res = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+		wave5_print_reg_err(inst->dev, *fail_res);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int wave5_vpu_dec_set_bitstream_flag(struct vpu_instance *inst, bool eos)
+{
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	enum bit_stream_mode bs_mode = (enum bit_stream_mode)p_dec_info->open_param.bitstream_mode;
+
+	p_dec_info->stream_endflag = eos ? 1 : 0;
+
+	if (bs_mode == BS_MODE_INTERRUPT) {
+		int ret;
+
+		vpu_write_reg(inst->dev, W5_BS_OPTION, (p_dec_info->stream_endflag << 1) |
+			      p_dec_info->stream_endflag);
+		vpu_write_reg(inst->dev, W5_BS_WR_PTR, p_dec_info->stream_wr_ptr);
+
+		wave5_bit_issue_command(inst, W5_UPDATE_BS);
+		ret = wave5_wait_vpu_busy(inst->dev,
+					  W5_VPU_BUSY_STATUS);
+		if (ret)
+			return ret;
+
+		if (!vpu_read_reg(inst->dev, W5_RET_SUCCESS))
+			return -EIO;
+	}
+
+	return 0;
+}
+
+int wave5_dec_clr_disp_flag(struct vpu_instance *inst, unsigned int index)
+{
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	int ret;
+
+	vpu_write_reg(inst->dev, W5_CMD_DEC_CLR_DISP_IDC, BIT(index));
+	vpu_write_reg(inst->dev, W5_CMD_DEC_SET_DISP_IDC, 0);
+	ret = wave5_send_query(inst, UPDATE_DISP_FLAG);
+
+	if (ret) {
+		if (ret == -EIO) {
+			u32 reg_val = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+
+			wave5_print_reg_err(inst->dev, reg_val);
+		}
+		return ret;
+	}
+
+	p_dec_info->frame_display_flag = vpu_read_reg(inst->dev, W5_RET_DEC_DISP_IDC);
+
+	return 0;
+}
+
+int wave5_dec_set_disp_flag(struct vpu_instance *inst, unsigned int index)
+{
+	int ret;
+
+	vpu_write_reg(inst->dev, W5_CMD_DEC_CLR_DISP_IDC, 0);
+	vpu_write_reg(inst->dev, W5_CMD_DEC_SET_DISP_IDC, BIT(index));
+	ret = wave5_send_query(inst, UPDATE_DISP_FLAG);
+
+	if (ret) {
+		if (ret == -EIO) {
+			u32 reg_val = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+
+			wave5_print_reg_err(inst->dev, reg_val);
+		}
+		return ret;
+	}
+
+	return 0;
+}
+
+int wave5_vpu_clear_interrupt(struct vpu_instance *inst, u32 flags)
+{
+	u32 interrupt_reason;
+
+	interrupt_reason = vpu_read_reg(inst->dev, W5_VPU_VINT_REASON_USR);
+	interrupt_reason &= ~flags;
+	vpu_write_reg(inst->dev, W5_VPU_VINT_REASON_USR, interrupt_reason);
+
+	return 0;
+}
+
+dma_addr_t wave5_vpu_dec_get_rd_ptr(struct vpu_instance *inst)
+{
+	int ret;
+
+	ret = wave5_send_query(inst, GET_BS_RD_PTR);
+
+	if (ret)
+		return inst->codec_info->dec_info.stream_rd_ptr;
+
+	return wave5_read_reg_for_mem_addr(inst, W5_RET_QUERY_DEC_BS_RD_PTR);
+}
+
+int wave5_dec_set_rd_ptr(struct vpu_instance *inst, dma_addr_t addr)
+{
+	int ret;
+
+	vpu_write_reg(inst->dev, W5_RET_QUERY_DEC_SET_BS_RD_PTR, addr);
+
+	ret = wave5_send_query(inst, SET_BS_RD_PTR);
+
+	return ret;
+}
+
+/************************************************************************/
+/* ENCODER functions */
+/************************************************************************/
+
+int wave5_vpu_build_up_enc_param(struct device *dev, struct vpu_instance *inst,
+				 struct enc_open_param *open_param)
+{
+	int ret;
+	struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+	u32 reg_val;
+	u32 bs_endian;
+	struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+	dma_addr_t buffer_addr;
+	size_t buffer_size;
+
+	p_enc_info->cycle_per_tick = 256;
+	if (vpu_dev->sram_buf.size) {
+		p_enc_info->sec_axi_info.use_enc_rdo_enable = 1;
+		p_enc_info->sec_axi_info.use_enc_lf_enable = 1;
+	}
+
+	if (vpu_dev->product == PRODUCT_ID_521)
+		p_enc_info->vb_work.size = WAVE521ENC_WORKBUF_SIZE;
+
+	ret = wave5_vdi_allocate_dma_memory(vpu_dev, &p_enc_info->vb_work);
+	if (ret) {
+		memset(&p_enc_info->vb_work, 0, sizeof(p_enc_info->vb_work));
+		return ret;
+	}
+
+	wave5_vdi_clear_memory(vpu_dev, &p_enc_info->vb_work);
+
+	vpu_write_reg(inst->dev, W5_ADDR_WORK_BASE, p_enc_info->vb_work.daddr);
+	vpu_write_reg(inst->dev, W5_WORK_SIZE, p_enc_info->vb_work.size);
+
+	vpu_write_reg(inst->dev, W5_CMD_ADDR_SEC_AXI, vpu_dev->sram_buf.daddr);
+	vpu_write_reg(inst->dev, W5_CMD_SEC_AXI_SIZE, vpu_dev->sram_buf.size);
+
+	reg_val = wave5_vdi_convert_endian(vpu_dev, open_param->stream_endian);
+	bs_endian = (~reg_val & VDI_128BIT_ENDIAN_MASK);
+
+	reg_val = (open_param->line_buf_int_en << 6) | bs_endian;
+	vpu_write_reg(inst->dev, W5_CMD_BS_PARAM, reg_val);
+	vpu_write_reg(inst->dev, W5_CMD_EXT_ADDR, (open_param->pri_axprot << 20) |
+			(open_param->pri_axcache << 16) | inst->dev->ext_addr);
+	vpu_write_reg(inst->dev, W5_CMD_NUM_CQ_DEPTH_M1, (COMMAND_QUEUE_DEPTH - 1));
+
+	reg_val = 0;
+	if (vpu_dev->product == PRODUCT_ID_521)
+		reg_val |= (open_param->sub_frame_sync_enable |
+			    open_param->sub_frame_sync_mode << 1);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SRC_OPTIONS, reg_val);
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_VCORE_INFO, 1);
+
+	wave5_bit_issue_command(inst, W5_CREATE_INSTANCE);
+	// check QUEUE_DONE
+	ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);
+	if (ret) {
+		dev_warn(inst->dev->dev, "command: 'W5_CREATE_INSTANCE' timed out\n");
+		goto free_vb_work;
+	}
+
+	// Check if we were able to add the parameters into the VCPU QUEUE
+	if (!vpu_read_reg(inst->dev, W5_RET_SUCCESS)) {
+		reg_val = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+		wave5_print_reg_err(inst->dev, reg_val);
+		ret = -EIO;
+		goto free_vb_work;
+	}
+
+	buffer_addr = open_param->bitstream_buffer;
+	buffer_size = open_param->bitstream_buffer_size;
+	p_enc_info->sub_frame_sync_config.sub_frame_sync_mode = open_param->sub_frame_sync_mode;
+	p_enc_info->sub_frame_sync_config.sub_frame_sync_on = open_param->sub_frame_sync_enable;
+	p_enc_info->stream_rd_ptr = buffer_addr;
+	p_enc_info->stream_wr_ptr = buffer_addr;
+	p_enc_info->line_buf_int_en = open_param->line_buf_int_en;
+	p_enc_info->stream_buf_start_addr = buffer_addr;
+	p_enc_info->stream_buf_size = buffer_size;
+	p_enc_info->stream_buf_end_addr = buffer_addr + buffer_size;
+	p_enc_info->stride = 0;
+	p_enc_info->initial_info_obtained = false;
+	p_enc_info->product_code = vpu_read_reg(inst->dev, W5_PRODUCT_NUMBER);
+
+	return 0;
+free_vb_work:
+	wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_work);
+	return ret;
+}
+
+static void wave5_set_enc_crop_info(u32 codec, struct enc_wave_param *param, int rot_mode,
+				    int src_width, int src_height)
+{
+	int aligned_width = (codec == W_HEVC_ENC) ? ALIGN(src_width, 32) : ALIGN(src_width, 16);
+	int aligned_height = (codec == W_HEVC_ENC) ? ALIGN(src_height, 32) : ALIGN(src_height, 16);
+	int pad_right, pad_bot;
+	int crop_right, crop_left, crop_top, crop_bot;
+	int prp_mode = rot_mode >> 1; // remove prp_enable bit
+
+	if (codec == W_HEVC_ENC &&
+	    (!rot_mode || prp_mode == 14)) // prp_mode 14 : hor_mir && ver_mir && rot_180
+		return;
+
+	pad_right = aligned_width - src_width;
+	pad_bot = aligned_height - src_height;
+
+	if (param->conf_win_right > 0)
+		crop_right = param->conf_win_right + pad_right;
+	else
+		crop_right = pad_right;
+
+	if (param->conf_win_bot > 0)
+		crop_bot = param->conf_win_bot + pad_bot;
+	else
+		crop_bot = pad_bot;
+
+	crop_top = param->conf_win_top;
+	crop_left = param->conf_win_left;
+
+	param->conf_win_top = crop_top;
+	param->conf_win_left = crop_left;
+	param->conf_win_bot = crop_bot;
+	param->conf_win_right = crop_right;
+
+	if (prp_mode == 1 || prp_mode == 15) {
+		param->conf_win_top = crop_right;
+		param->conf_win_left = crop_top;
+		param->conf_win_bot = crop_left;
+		param->conf_win_right = crop_bot;
+	} else if (prp_mode == 2 || prp_mode == 12) {
+		param->conf_win_top = crop_bot;
+		param->conf_win_left = crop_right;
+		param->conf_win_bot = crop_top;
+		param->conf_win_right = crop_left;
+	} else if (prp_mode == 3 || prp_mode == 13) {
+		param->conf_win_top = crop_left;
+		param->conf_win_left = crop_bot;
+		param->conf_win_bot = crop_right;
+		param->conf_win_right = crop_top;
+	} else if (prp_mode == 4 || prp_mode == 10) {
+		param->conf_win_top = crop_bot;
+		param->conf_win_bot = crop_top;
+	} else if (prp_mode == 8 || prp_mode == 6) {
+		param->conf_win_left = crop_right;
+		param->conf_win_right = crop_left;
+	} else if (prp_mode == 5 || prp_mode == 11) {
+		param->conf_win_top = crop_left;
+		param->conf_win_left = crop_top;
+		param->conf_win_bot = crop_right;
+		param->conf_win_right = crop_bot;
+	} else if (prp_mode == 7 || prp_mode == 9) {
+		param->conf_win_top = crop_right;
+		param->conf_win_left = crop_bot;
+		param->conf_win_bot = crop_left;
+		param->conf_win_right = crop_top;
+	}
+}
+
+int wave5_vpu_enc_init_seq(struct vpu_instance *inst)
+{
+	u32 reg_val = 0, rot_mir_mode, fixed_cu_size_mode = 0x7;
+	struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+	struct enc_open_param *p_open_param = &p_enc_info->open_param;
+	struct enc_wave_param *p_param = &p_open_param->wave_param;
+	int ret;
+
+	if (inst->dev->product != PRODUCT_ID_521)
+		return -EINVAL;
+
+	/*==============================================*/
+	/* OPT_CUSTOM_GOP */
+	/*==============================================*/
+	/*
+	 * SET_PARAM + CUSTOM_GOP
+	 * only when gop_preset_idx == custom_gop, custom_gop related registers should be set
+	 */
+	if (p_param->gop_preset_idx == PRESET_IDX_CUSTOM_GOP) {
+		int i = 0, j = 0;
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_CUSTOM_GOP_PARAM,
+			      p_param->gop_param.custom_gop_size);
+		for (i = 0; i < p_param->gop_param.custom_gop_size; i++) {
+			vpu_write_reg(inst->dev, W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_0 + (i * 4),
+				      p_param->gop_param.pic_param[i].pic_type |
+				      (p_param->gop_param.pic_param[i].poc_offset << 2) |
+				      (p_param->gop_param.pic_param[i].pic_qp << 6) |
+				      (p_param->gop_param.pic_param[i].use_multi_ref_p << 13) |
+				      ((p_param->gop_param.pic_param[i].ref_poc_l0 & 0x1F) << 14) |
+				      ((p_param->gop_param.pic_param[i].ref_poc_l1 & 0x1F) << 19) |
+				      (p_param->gop_param.pic_param[i].temporal_id << 24));
+		}
+
+		for (j = i; j < MAX_GOP_NUM; j++)
+			vpu_write_reg(inst->dev,
+				      W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_0 + (j * 4), 0);
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_SET_PARAM_OPTION, OPT_CUSTOM_GOP);
+		wave5_bit_issue_command(inst, W5_ENC_SET_PARAM);
+
+		ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);
+		if (ret) {
+			dev_warn(inst->dev->dev, "command: 'W5_ENC_SET_PARAM', timed out op=0x%x\n",
+				 OPT_CUSTOM_GOP);
+			return ret;
+		}
+	}
+
+	/*======================================================================*/
+	/* OPT_COMMON:								*/
+	/*	the last SET_PARAM command should be called with OPT_COMMON	*/
+	/*======================================================================*/
+	rot_mir_mode = 0;
+	if (p_enc_info->rotation_enable) {
+		switch (p_enc_info->rotation_angle) {
+		case 0:
+			rot_mir_mode |= NONE_ROTATE;
+			break;
+		case 90:
+			rot_mir_mode |= ROT_CLOCKWISE_90;
+			break;
+		case 180:
+			rot_mir_mode |= ROT_CLOCKWISE_180;
+			break;
+		case 270:
+			rot_mir_mode |= ROT_CLOCKWISE_270;
+			break;
+		}
+	}
+
+	if (p_enc_info->mirror_enable) {
+		switch (p_enc_info->mirror_direction) {
+		case MIRDIR_NONE:
+			rot_mir_mode |= NONE_ROTATE;
+			break;
+		case MIRDIR_VER:
+			rot_mir_mode |= MIR_VER_FLIP;
+			break;
+		case MIRDIR_HOR:
+			rot_mir_mode |= MIR_HOR_FLIP;
+			break;
+		case MIRDIR_HOR_VER:
+			rot_mir_mode |= MIR_HOR_VER_FLIP;
+			break;
+		}
+	}
+
+	wave5_set_enc_crop_info(inst->std, p_param, rot_mir_mode, p_open_param->pic_width,
+				p_open_param->pic_height);
+
+	/* SET_PARAM + COMMON */
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_SET_PARAM_OPTION, OPT_COMMON);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_SRC_SIZE, p_open_param->pic_height << 16
+			| p_open_param->pic_width);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MAP_ENDIAN, VDI_LITTLE_ENDIAN);
+
+	if (inst->std == W_AVC_ENC) {
+		reg_val = p_param->profile | (p_param->level << 3) |
+			(p_param->internal_bit_depth << 14) | (p_param->use_long_term << 21);
+		if (p_param->scaling_list_enable == 2) {
+			reg_val |= BIT(22) | BIT(23); // [23]=USE_DEFAULT_SCALING_LIST
+		} else { // 0 or 1
+			reg_val |= (p_param->scaling_list_enable << 22);
+		}
+	} else { // HEVC enc
+		reg_val = p_param->profile |
+			(p_param->level << 3) |
+			(p_param->tier << 12) |
+			(p_param->internal_bit_depth << 14) |
+			(p_param->use_long_term << 21) |
+			(p_param->tmvp_enable << 23) |
+			(p_param->sao_enable << 24) |
+			(p_param->skip_intra_trans << 25) |
+			(p_param->strong_intra_smooth_enable << 27) |
+			(p_param->en_still_picture << 30);
+		if (p_param->scaling_list_enable == 2)
+			reg_val |= BIT(22) | BIT(31); // [31]=USE_DEFAULT_SCALING_LIST
+		else
+			reg_val |= (p_param->scaling_list_enable << 22);
+	}
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_SPS_PARAM, reg_val);
+
+	reg_val = (p_param->lossless_enable) |
+		(p_param->const_intra_pred_flag << 1) |
+		(p_param->lf_cross_slice_boundary_enable << 2) |
+		(p_param->weight_pred_enable << 3) |
+		(p_param->wpp_enable << 4) |
+		(p_param->disable_deblk << 5) |
+		((p_param->beta_offset_div2 & 0xF) << 6) |
+		((p_param->tc_offset_div2 & 0xF) << 10) |
+		((p_param->chroma_cb_qp_offset & 0x1F) << 14) |
+		((p_param->chroma_cr_qp_offset & 0x1F) << 19) |
+		(p_param->transform8x8_enable << 29) |
+		(p_param->entropy_coding_mode << 30);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_PPS_PARAM, reg_val);
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_GOP_PARAM, p_param->gop_preset_idx);
+
+	if (inst->std == W_AVC_ENC)
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_PARAM, p_param->intra_qp |
+				((p_param->intra_period & 0x7ff) << 6) |
+				((p_param->avc_idr_period & 0x7ff) << 17) |
+				((p_param->forced_idr_header_enable & 3) << 28));
+	else
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_PARAM,
+			      p_param->decoding_refresh_type | (p_param->intra_qp << 3) |
+				(p_param->forced_idr_header_enable << 9) |
+				(p_param->intra_period << 16));
+
+	reg_val = (p_param->use_recommend_enc_param) |
+		(p_param->rdo_skip << 2) |
+		(p_param->lambda_scaling_enable << 3) |
+		(p_param->coef_clear_disable << 4) |
+		(fixed_cu_size_mode << 5) |
+		(p_param->intra_nx_n_enable << 8) |
+		(p_param->max_num_merge << 18) |
+		(p_param->custom_md_enable << 20) |
+		(p_param->custom_lambda_enable << 21) |
+		(p_param->monochrome_enable << 22);
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RDO_PARAM, reg_val);
+
+	if (inst->std == W_AVC_ENC)
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_REFRESH,
+			      p_param->intra_mb_refresh_arg << 16 | p_param->intra_mb_refresh_mode);
+	else
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INTRA_REFRESH,
+			      p_param->intra_refresh_arg << 16 | p_param->intra_refresh_mode);
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_FRAME_RATE, p_open_param->frame_rate_info);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_TARGET_RATE, p_open_param->bit_rate);
+
+	if (inst->std == W_AVC_ENC)
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_PARAM,
+			      p_open_param->rc_enable | (p_param->mb_level_rc_enable << 1) |
+			      (p_param->hvs_qp_enable << 2) | (p_param->hvs_qp_scale << 4) |
+			      (p_param->bit_alloc_mode << 8) | (p_param->roi_enable << 13) |
+			      ((p_param->initial_rc_qp & 0x3F) << 14) |
+			      (p_open_param->vbv_buffer_size << 20));
+	else
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_PARAM,
+			      p_open_param->rc_enable | (p_param->cu_level_rc_enable << 1) |
+			      (p_param->hvs_qp_enable << 2) | (p_param->hvs_qp_scale << 4) |
+			      (p_param->bit_alloc_mode << 8) | (p_param->roi_enable << 13) |
+			      ((p_param->initial_rc_qp & 0x3F) << 14) |
+			      (p_open_param->vbv_buffer_size << 20));
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_WEIGHT_PARAM,
+		      p_param->rc_weight_buf << 8 | p_param->rc_weight_param);
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_MIN_MAX_QP, p_param->min_qp_i |
+		      (p_param->max_qp_i << 6) | (p_param->hvs_max_delta_qp << 12));
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_INTER_MIN_MAX_QP, p_param->min_qp_p |
+		      (p_param->max_qp_p << 6) | (p_param->min_qp_b << 12) |
+		      (p_param->max_qp_b << 18));
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_BIT_RATIO_LAYER_0_3,
+		      (u32)p_param->fixed_bit_ratio[0] |
+		      ((u32)p_param->fixed_bit_ratio[1] << 8) |
+		      ((u32)p_param->fixed_bit_ratio[2] << 16) |
+		      ((u32)p_param->fixed_bit_ratio[3] << 24));
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_RC_BIT_RATIO_LAYER_4_7,
+		      (u32)p_param->fixed_bit_ratio[4] |
+		      ((u32)p_param->fixed_bit_ratio[5] << 8) |
+		      ((u32)p_param->fixed_bit_ratio[6] << 16) |
+		      ((u32)p_param->fixed_bit_ratio[7] << 24));
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_ROT_PARAM, rot_mir_mode);
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_BG_PARAM, (p_param->bg_detect_enable) |
+		      (p_param->bg_thr_diff << 1) | (p_param->bg_thr_mean_diff << 10) |
+		      (p_param->bg_lambda_qp << 18) | ((p_param->bg_delta_qp & 0x1F) << 24) |
+		      ((inst->std == W_AVC_ENC) ? p_param->s2fme_disable << 29 : 0));
+
+	if (inst->std == W_HEVC_ENC || inst->std == W_AVC_ENC) {
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_LAMBDA_ADDR,
+			      p_param->custom_lambda_addr);
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CONF_WIN_TOP_BOT,
+			      p_param->conf_win_bot << 16 | p_param->conf_win_top);
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CONF_WIN_LEFT_RIGHT,
+			      p_param->conf_win_right << 16 | p_param->conf_win_left);
+
+		if (inst->std == W_AVC_ENC)
+			vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INDEPENDENT_SLICE,
+				      p_param->avc_slice_arg << 16 | p_param->avc_slice_mode);
+		else
+			vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_INDEPENDENT_SLICE,
+				      p_param->independ_slice_mode_arg << 16 |
+				      p_param->independ_slice_mode);
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_USER_SCALING_LIST_ADDR,
+			      p_param->user_scaling_list_addr);
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_NUM_UNITS_IN_TICK,
+			      p_param->num_units_in_tick);
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_TIME_SCALE, p_param->time_scale);
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_NUM_TICKS_POC_DIFF_ONE,
+			      p_param->num_ticks_poc_diff_one);
+	}
+
+	if (inst->std == W_HEVC_ENC) {
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_PU04,
+			      (p_param->pu04_delta_rate & 0xFF) |
+			      ((p_param->pu04_intra_planar_delta_rate & 0xFF) << 8) |
+			      ((p_param->pu04_intra_dc_delta_rate & 0xFF) << 16) |
+			      ((p_param->pu04_intra_angle_delta_rate & 0xFF) << 24));
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_PU08,
+			      (p_param->pu08_delta_rate & 0xFF) |
+			      ((p_param->pu08_intra_planar_delta_rate & 0xFF) << 8) |
+			      ((p_param->pu08_intra_dc_delta_rate & 0xFF) << 16) |
+			      ((p_param->pu08_intra_angle_delta_rate & 0xFF) << 24));
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_PU16,
+			      (p_param->pu16_delta_rate & 0xFF) |
+			      ((p_param->pu16_intra_planar_delta_rate & 0xFF) << 8) |
+			      ((p_param->pu16_intra_dc_delta_rate & 0xFF) << 16) |
+			      ((p_param->pu16_intra_angle_delta_rate & 0xFF) << 24));
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_PU32,
+			      (p_param->pu32_delta_rate & 0xFF) |
+			      ((p_param->pu32_intra_planar_delta_rate & 0xFF) << 8) |
+			      ((p_param->pu32_intra_dc_delta_rate & 0xFF) << 16) |
+			      ((p_param->pu32_intra_angle_delta_rate & 0xFF) << 24));
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_CU08,
+			      (p_param->cu08_intra_delta_rate & 0xFF) |
+			      ((p_param->cu08_inter_delta_rate & 0xFF) << 8) |
+			      ((p_param->cu08_merge_delta_rate & 0xFF) << 16));
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_CU16,
+			      (p_param->cu16_intra_delta_rate & 0xFF) |
+			      ((p_param->cu16_inter_delta_rate & 0xFF) << 8) |
+			      ((p_param->cu16_merge_delta_rate & 0xFF) << 16));
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_CUSTOM_MD_CU32,
+			      (p_param->cu32_intra_delta_rate & 0xFF) |
+			      ((p_param->cu32_inter_delta_rate & 0xFF) << 8) |
+			      ((p_param->cu32_merge_delta_rate & 0xFF) << 16));
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_DEPENDENT_SLICE,
+			      p_param->depend_slice_mode_arg << 16 | p_param->depend_slice_mode);
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_NR_PARAM, p_param->nr_y_enable |
+			      (p_param->nr_cb_enable << 1) | (p_param->nr_cr_enable << 2) |
+			      (p_param->nr_noise_est_enable << 3) |
+			      (p_param->nr_noise_sigma_y << 4) |
+			      (p_param->nr_noise_sigma_cb << 12) |
+			      (p_param->nr_noise_sigma_cr << 20));
+
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_NR_WEIGHT,
+			      p_param->nr_intra_weight_y |
+			      (p_param->nr_intra_weight_cb << 5) |
+			      (p_param->nr_intra_weight_cr << 10) |
+			      (p_param->nr_inter_weight_y << 15) |
+			      (p_param->nr_inter_weight_cb << 20) |
+			      (p_param->nr_inter_weight_cr << 25));
+	}
+	if (p_enc_info->open_param.encode_vui_rbsp || p_enc_info->open_param.enc_hrd_rbsp_in_vps) {
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_VUI_HRD_PARAM,
+			      (p_enc_info->open_param.hrd_rbsp_data_size << 18) |
+			      (p_enc_info->open_param.vui_rbsp_data_size << 4) |
+			      (p_enc_info->open_param.enc_hrd_rbsp_in_vps << 2) |
+			      (p_enc_info->open_param.encode_vui_rbsp));
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_VUI_RBSP_ADDR,
+			      p_enc_info->open_param.vui_rbsp_data_addr);
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_HRD_RBSP_ADDR,
+			      p_enc_info->open_param.hrd_rbsp_data_addr);
+	} else {
+		vpu_write_reg(inst->dev, W5_CMD_ENC_SEQ_VUI_HRD_PARAM, 0);
+	}
+
+	wave5_bit_issue_command(inst, W5_ENC_SET_PARAM);
+
+	ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);
+	if (ret) {
+		dev_warn(inst->dev->dev, "command: 'W5_ENC_SET_PARAM', timed out\n");
+		return ret;
+	}
+
+	if (!vpu_read_reg(inst->dev, W5_RET_SUCCESS)) {
+		reg_val = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+		wave5_print_reg_err(inst->dev, reg_val);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int wave5_vpu_enc_get_seq_info(struct vpu_instance *inst, struct enc_initial_info *info)
+{
+	int ret;
+	u32 reg_val;
+	struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+
+	if (inst->dev->product != PRODUCT_ID_521)
+		return -EINVAL;
+
+	// send QUERY cmd
+	ret = wave5_send_query(inst, GET_RESULT);
+	if (ret) {
+		if (ret == -EIO) {
+			reg_val = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+			wave5_print_reg_err(inst->dev, reg_val);
+		}
+		return ret;
+	}
+
+	dev_dbg(inst->dev->dev, "%s: init seq\n", __func__);
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS);
+
+	p_enc_info->instance_queue_count = (reg_val >> 16) & 0xff;
+	p_enc_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);
+
+	if (vpu_read_reg(inst->dev, W5_RET_ENC_ENCODING_SUCCESS) != 1) {
+		info->seq_init_err_reason = vpu_read_reg(inst->dev, W5_RET_ENC_ERR_INFO);
+		ret = -EIO;
+	} else {
+		info->warn_info = vpu_read_reg(inst->dev, W5_RET_ENC_WARN_INFO);
+	}
+
+	info->min_frame_buffer_count = vpu_read_reg(inst->dev, W5_RET_ENC_NUM_REQUIRED_FB);
+	info->min_src_frame_count = vpu_read_reg(inst->dev, W5_RET_ENC_MIN_SRC_BUF_NUM);
+	info->max_latency_pictures = vpu_read_reg(inst->dev, W5_RET_ENC_PIC_MAX_LATENCY_PICS);
+	info->vlc_buf_size = vpu_read_reg(inst->dev, W5_RET_VLC_BUF_SIZE);
+	info->param_buf_size = vpu_read_reg(inst->dev, W5_RET_PARAM_BUF_SIZE);
+	p_enc_info->vlc_buf_size = info->vlc_buf_size;
+	p_enc_info->param_buf_size = info->param_buf_size;
+
+	return ret;
+}
+
+static u32 calculate_luma_stride(u32 width, u32 bit_depth)
+{
+	return ALIGN(ALIGN(width, 16) * ((bit_depth > 8) ? 5 : 4), 32);
+}
+
+static u32 calculate_chroma_stride(u32 width, u32 bit_depth)
+{
+	return ALIGN(ALIGN(width / 2, 16) * ((bit_depth > 8) ? 5 : 4), 32);
+}
+
+int wave5_vpu_enc_register_framebuffer(struct device *dev, struct vpu_instance *inst,
+				       struct frame_buffer *fb_arr, enum tiled_map_type map_type,
+				       unsigned int count)
+{
+	struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+	int ret = 0;
+	u32 stride;
+	u32 start_no, end_no;
+	size_t remain, idx, j, i, cnt_8_chunk;
+	u32 reg_val = 0, pic_size = 0, mv_col_size, fbc_y_tbl_size, fbc_c_tbl_size;
+	u32 sub_sampled_size = 0;
+	u32 endian, luma_stride, chroma_stride, frame_width, frame_height;
+	u32 buf_height = 0, buf_width = 0;
+	u32 bit_depth;
+	bool avc_encoding = (inst->std == W_AVC_ENC);
+	struct vpu_buf vb_mv = {0};
+	struct vpu_buf vb_fbc_y_tbl = {0};
+	struct vpu_buf vb_fbc_c_tbl = {0};
+	struct vpu_buf vb_sub_sam_buf = {0};
+	struct vpu_buf vb_task = {0};
+	struct enc_open_param *p_open_param;
+	struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+
+	p_open_param = &p_enc_info->open_param;
+	mv_col_size = 0;
+	fbc_y_tbl_size = 0;
+	fbc_c_tbl_size = 0;
+	stride = p_enc_info->stride;
+	bit_depth = p_open_param->wave_param.internal_bit_depth;
+
+	if (avc_encoding) {
+		buf_width = ALIGN(p_open_param->pic_width, 16);
+		buf_height = ALIGN(p_open_param->pic_height, 16);
+
+		if ((p_enc_info->rotation_angle || p_enc_info->mirror_direction) &&
+		    !(p_enc_info->rotation_angle == 180 &&
+					p_enc_info->mirror_direction == MIRDIR_HOR_VER)) {
+			buf_width = ALIGN(p_open_param->pic_width, 16);
+			buf_height = ALIGN(p_open_param->pic_height, 16);
+		}
+
+		if (p_enc_info->rotation_angle == 90 || p_enc_info->rotation_angle == 270) {
+			buf_width = ALIGN(p_open_param->pic_height, 16);
+			buf_height = ALIGN(p_open_param->pic_width, 16);
+		}
+	} else {
+		buf_width = ALIGN(p_open_param->pic_width, 8);
+		buf_height = ALIGN(p_open_param->pic_height, 8);
+
+		if ((p_enc_info->rotation_angle || p_enc_info->mirror_direction) &&
+		    !(p_enc_info->rotation_angle == 180 &&
+					p_enc_info->mirror_direction == MIRDIR_HOR_VER)) {
+			buf_width = ALIGN(p_open_param->pic_width, 32);
+			buf_height = ALIGN(p_open_param->pic_height, 32);
+		}
+
+		if (p_enc_info->rotation_angle == 90 || p_enc_info->rotation_angle == 270) {
+			buf_width = ALIGN(p_open_param->pic_height, 32);
+			buf_height = ALIGN(p_open_param->pic_width, 32);
+		}
+	}
+
+	pic_size = (buf_width << 16) | buf_height;
+
+	if (avc_encoding) {
+		mv_col_size = WAVE5_ENC_AVC_BUF_SIZE(buf_width, buf_height);
+		vb_mv.daddr = 0;
+		vb_mv.size = ALIGN(mv_col_size * count, BUFFER_MARGIN) + BUFFER_MARGIN;
+	} else {
+		mv_col_size = WAVE5_ENC_HEVC_BUF_SIZE(buf_width, buf_height);
+		mv_col_size = ALIGN(mv_col_size, 16);
+		vb_mv.daddr = 0;
+		vb_mv.size = ALIGN(mv_col_size * count, BUFFER_MARGIN) + BUFFER_MARGIN;
+	}
+
+	ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_mv);
+	if (ret)
+		return ret;
+
+	p_enc_info->vb_mv = vb_mv;
+
+	frame_width = ALIGN(buf_width, 16);
+	frame_height = ALIGN(buf_height, 16);
+	if (p_enc_info->product_code == WAVE521C_DUAL_CODE) {
+		// Use 1024 for H264(AVC) and 512 for H265(HEVC)
+		fbc_y_tbl_size = calculate_table_size(bit_depth, frame_width, frame_height,
+						      (avc_encoding ? 1024 : 512));
+	} else {
+		fbc_y_tbl_size = WAVE5_FBC_LUMA_TABLE_SIZE(buf_width, buf_height);
+		fbc_y_tbl_size = ALIGN(fbc_y_tbl_size, 16);
+	}
+
+	vb_fbc_y_tbl.daddr = 0;
+	vb_fbc_y_tbl.size = ALIGN(fbc_y_tbl_size * count, BUFFER_MARGIN) + BUFFER_MARGIN;
+	ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_fbc_y_tbl);
+	if (ret)
+		goto free_vb_fbc_y_tbl;
+
+	p_enc_info->vb_fbc_y_tbl = vb_fbc_y_tbl;
+
+	if (p_enc_info->product_code == WAVE521C_DUAL_CODE) {
+		// Use 1024 for H264(AVC) and 512 for HEVC
+		fbc_c_tbl_size = calculate_table_size(bit_depth, frame_width, frame_height,
+						      (avc_encoding ? 1024 : 512));
+	} else {
+		fbc_c_tbl_size = WAVE5_FBC_CHROMA_TABLE_SIZE(buf_width, buf_height);
+		fbc_c_tbl_size = ALIGN(fbc_c_tbl_size, 16);
+	}
+
+	vb_fbc_c_tbl.daddr = 0;
+	vb_fbc_c_tbl.size = ALIGN(fbc_c_tbl_size * count, BUFFER_MARGIN) + BUFFER_MARGIN;
+	ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_fbc_c_tbl);
+	if (ret)
+		goto free_vb_fbc_c_tbl;
+
+	p_enc_info->vb_fbc_c_tbl = vb_fbc_c_tbl;
+
+	if (avc_encoding)
+		sub_sampled_size = WAVE5_SUBSAMPLED_ONE_SIZE_AVC(buf_width, buf_height);
+	else
+		sub_sampled_size = WAVE5_SUBSAMPLED_ONE_SIZE(buf_width, buf_height);
+	vb_sub_sam_buf.size = ALIGN(sub_sampled_size * count, BUFFER_MARGIN) + BUFFER_MARGIN;
+	vb_sub_sam_buf.daddr = 0;
+	ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_sub_sam_buf);
+	if (ret)
+		goto free_vb_sam_buf;
+
+	p_enc_info->vb_sub_sam_buf = vb_sub_sam_buf;
+
+	vb_task.size = (p_enc_info->vlc_buf_size * VLC_BUF_NUM) +
+			(p_enc_info->param_buf_size * COMMAND_QUEUE_DEPTH);
+	vb_task.daddr = 0;
+	if (p_enc_info->vb_task.size == 0) {
+		ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vb_task);
+		if (ret)
+			goto free_vb_task;
+
+		p_enc_info->vb_task = vb_task;
+
+		vpu_write_reg(inst->dev, W5_CMD_SET_FB_ADDR_TASK_BUF,
+			      p_enc_info->vb_task.daddr);
+		vpu_write_reg(inst->dev, W5_CMD_SET_FB_TASK_BUF_SIZE, vb_task.size);
+	}
+
+	// set sub-sampled buffer base addr
+	vpu_write_reg(inst->dev, W5_ADDR_SUB_SAMPLED_FB_BASE, vb_sub_sam_buf.daddr);
+	// set sub-sampled buffer size for one frame
+	vpu_write_reg(inst->dev, W5_SUB_SAMPLED_ONE_FB_SIZE, sub_sampled_size);
+
+	endian = wave5_vdi_convert_endian(vpu_dev, fb_arr[0].endian);
+
+	vpu_write_reg(inst->dev, W5_PIC_SIZE, pic_size);
+
+	// set stride of luma/chroma for compressed buffer
+	if ((p_enc_info->rotation_angle || p_enc_info->mirror_direction) &&
+	    !(p_enc_info->rotation_angle == 180 &&
+	    p_enc_info->mirror_direction == MIRDIR_HOR_VER)) {
+		luma_stride = calculate_luma_stride(buf_width, bit_depth);
+		chroma_stride = calculate_chroma_stride(buf_width / 2, bit_depth);
+	} else {
+		luma_stride = calculate_luma_stride(p_open_param->pic_width, bit_depth);
+		chroma_stride = calculate_chroma_stride(p_open_param->pic_width / 2, bit_depth);
+	}
+
+	vpu_write_reg(inst->dev, W5_FBC_STRIDE, luma_stride << 16 | chroma_stride);
+	vpu_write_reg(inst->dev, W5_COMMON_PIC_INFO, stride);
+
+	remain = count;
+	cnt_8_chunk = ALIGN(count, 8) / 8;
+	idx = 0;
+	for (j = 0; j < cnt_8_chunk; j++) {
+		reg_val = (endian << 16) | (j == cnt_8_chunk - 1) << 4 | ((j == 0) << 3);
+		reg_val |= (p_open_param->enable_non_ref_fbc_write << 26);
+		vpu_write_reg(inst->dev, W5_SFB_OPTION, reg_val);
+		start_no = j * 8;
+		end_no = start_no + ((remain >= 8) ? 8 : remain) - 1;
+
+		vpu_write_reg(inst->dev, W5_SET_FB_NUM, (start_no << 8) | end_no);
+
+		for (i = 0; i < 8 && i < remain; i++) {
+			vpu_write_reg(inst->dev, W5_ADDR_LUMA_BASE0 + (i << 4), fb_arr[i +
+					start_no].buf_y);
+			vpu_write_reg(inst->dev, W5_ADDR_CB_BASE0 + (i << 4),
+				      fb_arr[i + start_no].buf_cb);
+			/* luma FBC offset table */
+			vpu_write_reg(inst->dev, W5_ADDR_FBC_Y_OFFSET0 + (i << 4),
+				      vb_fbc_y_tbl.daddr + idx * fbc_y_tbl_size);
+			/* chroma FBC offset table */
+			vpu_write_reg(inst->dev, W5_ADDR_FBC_C_OFFSET0 + (i << 4),
+				      vb_fbc_c_tbl.daddr + idx * fbc_c_tbl_size);
+
+			vpu_write_reg(inst->dev, W5_ADDR_MV_COL0 + (i << 2),
+				      vb_mv.daddr + idx * mv_col_size);
+			idx++;
+		}
+		remain -= i;
+
+		wave5_bit_issue_command(inst, W5_SET_FB);
+		ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);
+		if (ret)
+			goto free_vb_mem;
+	}
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_SUCCESS);
+	if (!reg_val) {
+		ret = -EIO;
+		goto free_vb_mem;
+	}
+
+	return ret;
+
+free_vb_mem:
+	wave5_vdi_free_dma_memory(vpu_dev, &vb_task);
+free_vb_task:
+	wave5_vdi_free_dma_memory(vpu_dev, &vb_sub_sam_buf);
+free_vb_sam_buf:
+	wave5_vdi_free_dma_memory(vpu_dev, &vb_fbc_c_tbl);
+free_vb_fbc_c_tbl:
+	wave5_vdi_free_dma_memory(vpu_dev, &vb_fbc_y_tbl);
+free_vb_fbc_y_tbl:
+	wave5_vdi_free_dma_memory(vpu_dev, &vb_mv);
+	return ret;
+}
+
+int wave5_vpu_encode(struct vpu_instance *inst, struct enc_param *option, u32 *fail_res)
+{
+	u32 src_frame_format;
+	u32 reg_val = 0, bs_endian;
+	u32 src_stride_c = 0;
+	struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+	struct frame_buffer *p_src_frame = option->source_frame;
+	struct enc_open_param *p_open_param = &p_enc_info->open_param;
+	bool justified = WTL_RIGHT_JUSTIFIED;
+	u32 format_no = WTL_PIXEL_8BIT;
+	int ret;
+
+	if (inst->dev->product != PRODUCT_ID_521)
+		return -EINVAL;
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_BS_START_ADDR, option->pic_stream_buffer_addr);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_BS_SIZE, option->pic_stream_buffer_size);
+	p_enc_info->stream_buf_start_addr = option->pic_stream_buffer_addr;
+	p_enc_info->stream_buf_size = option->pic_stream_buffer_size;
+	p_enc_info->stream_buf_end_addr =
+		option->pic_stream_buffer_addr + option->pic_stream_buffer_size;
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_AXI_SEL, DEFAULT_SRC_AXI);
+	/* secondary AXI */
+	reg_val = (p_enc_info->sec_axi_info.use_enc_rdo_enable << 11) |
+		(p_enc_info->sec_axi_info.use_enc_lf_enable << 15);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_USE_SEC_AXI, reg_val);
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_REPORT_PARAM, 0);
+
+	/*
+	 * CODEOPT_ENC_VCL is used to implicitly encode header/headers to generate bitstream.
+	 * (use ENC_PUT_VIDEO_HEADER for give_command to encode only a header)
+	 */
+	if (option->code_option.implicit_header_encode)
+		vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_CODE_OPTION,
+			      CODEOPT_ENC_HEADER_IMPLICIT | CODEOPT_ENC_VCL |
+			      (option->code_option.encode_aud << 5) |
+			      (option->code_option.encode_eos << 6) |
+			      (option->code_option.encode_eob << 7));
+	else
+		vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_CODE_OPTION,
+			      option->code_option.implicit_header_encode |
+			      (option->code_option.encode_vcl << 1) |
+			      (option->code_option.encode_vps << 2) |
+			      (option->code_option.encode_sps << 3) |
+			      (option->code_option.encode_pps << 4) |
+			      (option->code_option.encode_aud << 5) |
+			      (option->code_option.encode_eos << 6) |
+			      (option->code_option.encode_eob << 7));
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_PIC_PARAM, option->skip_picture |
+		      (option->force_pic_qp_enable << 1) | (option->force_pic_qp_i << 2) |
+		      (option->force_pic_qp_p << 8) | (option->force_pic_qp_b << 14) |
+		      (option->force_pic_type_enable << 20) | (option->force_pic_type << 21) |
+		      (option->force_all_ctu_coef_drop_enable << 24));
+
+	if (option->src_end_flag)
+		// no more source images.
+		vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_PIC_IDX, 0xFFFFFFFF);
+	else
+		vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_PIC_IDX, option->src_idx);
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_ADDR_Y, p_src_frame->buf_y);
+	if (p_open_param->cbcr_order == CBCR_ORDER_NORMAL) {
+		vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_ADDR_U, p_src_frame->buf_cb);
+		vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_ADDR_V, p_src_frame->buf_cr);
+	} else {
+		vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_ADDR_U, p_src_frame->buf_cr);
+		vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_ADDR_V, p_src_frame->buf_cb);
+	}
+
+	switch (p_open_param->src_format) {
+	case FORMAT_420:
+	case FORMAT_422:
+	case FORMAT_YUYV:
+	case FORMAT_YVYU:
+	case FORMAT_UYVY:
+	case FORMAT_VYUY:
+		justified = WTL_LEFT_JUSTIFIED;
+		format_no = WTL_PIXEL_8BIT;
+		src_stride_c = inst->cbcr_interleave ? p_src_frame->stride :
+			(p_src_frame->stride / 2);
+		src_stride_c = (p_open_param->src_format == FORMAT_422) ? src_stride_c * 2 :
+			src_stride_c;
+		break;
+	case FORMAT_420_P10_16BIT_MSB:
+	case FORMAT_422_P10_16BIT_MSB:
+	case FORMAT_YUYV_P10_16BIT_MSB:
+	case FORMAT_YVYU_P10_16BIT_MSB:
+	case FORMAT_UYVY_P10_16BIT_MSB:
+	case FORMAT_VYUY_P10_16BIT_MSB:
+		justified = WTL_RIGHT_JUSTIFIED;
+		format_no = WTL_PIXEL_16BIT;
+		src_stride_c = inst->cbcr_interleave ? p_src_frame->stride :
+			(p_src_frame->stride / 2);
+		src_stride_c = (p_open_param->src_format ==
+				FORMAT_422_P10_16BIT_MSB) ? src_stride_c * 2 : src_stride_c;
+		break;
+	case FORMAT_420_P10_16BIT_LSB:
+	case FORMAT_422_P10_16BIT_LSB:
+	case FORMAT_YUYV_P10_16BIT_LSB:
+	case FORMAT_YVYU_P10_16BIT_LSB:
+	case FORMAT_UYVY_P10_16BIT_LSB:
+	case FORMAT_VYUY_P10_16BIT_LSB:
+		justified = WTL_LEFT_JUSTIFIED;
+		format_no = WTL_PIXEL_16BIT;
+		src_stride_c = inst->cbcr_interleave ? p_src_frame->stride :
+			(p_src_frame->stride / 2);
+		src_stride_c = (p_open_param->src_format ==
+				FORMAT_422_P10_16BIT_LSB) ? src_stride_c * 2 : src_stride_c;
+		break;
+	case FORMAT_420_P10_32BIT_MSB:
+	case FORMAT_422_P10_32BIT_MSB:
+	case FORMAT_YUYV_P10_32BIT_MSB:
+	case FORMAT_YVYU_P10_32BIT_MSB:
+	case FORMAT_UYVY_P10_32BIT_MSB:
+	case FORMAT_VYUY_P10_32BIT_MSB:
+		justified = WTL_RIGHT_JUSTIFIED;
+		format_no = WTL_PIXEL_32BIT;
+		src_stride_c = inst->cbcr_interleave ? p_src_frame->stride :
+			ALIGN(p_src_frame->stride / 2, 16) * BIT(inst->cbcr_interleave);
+		src_stride_c = (p_open_param->src_format ==
+				FORMAT_422_P10_32BIT_MSB) ? src_stride_c * 2 : src_stride_c;
+		break;
+	case FORMAT_420_P10_32BIT_LSB:
+	case FORMAT_422_P10_32BIT_LSB:
+	case FORMAT_YUYV_P10_32BIT_LSB:
+	case FORMAT_YVYU_P10_32BIT_LSB:
+	case FORMAT_UYVY_P10_32BIT_LSB:
+	case FORMAT_VYUY_P10_32BIT_LSB:
+		justified = WTL_LEFT_JUSTIFIED;
+		format_no = WTL_PIXEL_32BIT;
+		src_stride_c = inst->cbcr_interleave ? p_src_frame->stride :
+			ALIGN(p_src_frame->stride / 2, 16) * BIT(inst->cbcr_interleave);
+		src_stride_c = (p_open_param->src_format ==
+				FORMAT_422_P10_32BIT_LSB) ? src_stride_c * 2 : src_stride_c;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	src_frame_format = (inst->cbcr_interleave << 1) | (inst->nv21);
+	switch (p_open_param->packed_format) {
+	case PACKED_YUYV:
+		src_frame_format = 4;
+		break;
+	case PACKED_YVYU:
+		src_frame_format = 5;
+		break;
+	case PACKED_UYVY:
+		src_frame_format = 6;
+		break;
+	case PACKED_VYUY:
+		src_frame_format = 7;
+		break;
+	default:
+		break;
+	}
+
+	reg_val = wave5_vdi_convert_endian(inst->dev, p_open_param->source_endian);
+	bs_endian = (~reg_val & VDI_128BIT_ENDIAN_MASK);
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_STRIDE,
+		      (p_src_frame->stride << 16) | src_stride_c);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SRC_FORMAT, src_frame_format |
+		      (format_no << 3) | (justified << 5) | (bs_endian << 6));
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_CUSTOM_MAP_OPTION_ADDR,
+		      option->custom_map_opt.addr_custom_map);
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_CUSTOM_MAP_OPTION_PARAM,
+		      option->custom_map_opt.custom_roi_map_enable |
+		      (option->custom_map_opt.roi_avg_qp << 1) |
+		      (option->custom_map_opt.custom_lambda_map_enable << 8) |
+		      (option->custom_map_opt.custom_mode_map_enable << 9) |
+		      (option->custom_map_opt.custom_coef_drop_enable << 10));
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_LONGTERM_PIC,
+		      option->use_cur_src_as_longterm_pic | (option->use_longterm_ref << 1));
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_WP_PIXEL_SIGMA_Y, option->wp_pix_sigma_y);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_WP_PIXEL_SIGMA_C,
+		      (option->wp_pix_sigma_cr << 16) | option->wp_pix_sigma_cb);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_WP_PIXEL_MEAN_Y, option->wp_pix_mean_y);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_WP_PIXEL_MEAN_C,
+		      (option->wp_pix_mean_cr << 16) | (option->wp_pix_mean_cb));
+
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_PREFIX_SEI_INFO, 0);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_PREFIX_SEI_NAL_ADDR, 0);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SUFFIX_SEI_INFO, 0);
+	vpu_write_reg(inst->dev, W5_CMD_ENC_PIC_SUFFIX_SEI_NAL_ADDR, 0);
+
+	wave5_bit_issue_command(inst, W5_ENC_PIC);
+
+	// check QUEUE_DONE
+	ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);
+	if (ret) {
+		dev_warn(inst->dev->dev, "command: 'W5_ENC_PIC', timed out\n");
+		return -ETIMEDOUT;
+	}
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS);
+
+	p_enc_info->instance_queue_count = (reg_val >> 16) & 0xff;
+	p_enc_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);
+
+	// Check if we were able to add a command into the VCPU QUEUE
+	if (!vpu_read_reg(inst->dev, W5_RET_SUCCESS)) {
+		*fail_res = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+		wave5_print_reg_err(inst->dev, *fail_res);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int wave5_vpu_enc_get_result(struct vpu_instance *inst, struct enc_output_info *result)
+{
+	int ret;
+	u32 encoding_success;
+	u32 reg_val;
+	struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	if (vpu_dev->product != PRODUCT_ID_521)
+		return -EINVAL;
+
+	ret = wave5_send_query(inst, GET_RESULT);
+	if (ret) {
+		if (ret == -EIO) {
+			reg_val = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+			wave5_print_reg_err(inst->dev, reg_val);
+		}
+		return ret;
+	}
+	dev_dbg(inst->dev->dev, "%s: enc pic complete\n", __func__);
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_QUEUE_STATUS);
+
+	p_enc_info->instance_queue_count = (reg_val >> 16) & 0xff;
+	p_enc_info->report_queue_count = (reg_val & QUEUE_REPORT_MASK);
+
+	encoding_success = vpu_read_reg(inst->dev, W5_RET_ENC_ENCODING_SUCCESS);
+	if (!encoding_success) {
+		result->error_reason = vpu_read_reg(inst->dev, W5_RET_ENC_ERR_INFO);
+		return -EIO;
+	}
+
+	result->warn_info = vpu_read_reg(inst->dev, W5_RET_ENC_WARN_INFO);
+
+	reg_val = vpu_read_reg(inst->dev, W5_RET_ENC_PIC_TYPE);
+	result->pic_type = reg_val & 0xFFFF;
+
+	result->enc_vcl_nut = vpu_read_reg(inst->dev, W5_RET_ENC_VCL_NUT);
+	/*
+	 * To get the reconstructed frame use the following index on
+	 * inst->frame_buf
+	 */
+	result->recon_frame_index = vpu_read_reg(inst->dev, W5_RET_ENC_PIC_IDX);
+	result->enc_pic_byte = vpu_read_reg(inst->dev, W5_RET_ENC_PIC_BYTE);
+	result->enc_src_idx = vpu_read_reg(inst->dev, W5_RET_ENC_USED_SRC_IDX);
+	p_enc_info->stream_wr_ptr = wave5_read_reg_for_mem_addr(inst, W5_RET_ENC_WR_PTR);
+	p_enc_info->stream_rd_ptr = wave5_read_reg_for_mem_addr(inst, W5_RET_ENC_RD_PTR);
+
+	result->bitstream_buffer = wave5_read_reg_for_mem_addr(inst, W5_RET_ENC_RD_PTR);
+	result->rd_ptr = p_enc_info->stream_rd_ptr;
+	result->wr_ptr = p_enc_info->stream_wr_ptr;
+
+	//result for header only(no vcl) encoding
+	if (result->recon_frame_index == RECON_IDX_FLAG_HEADER_ONLY)
+		result->bitstream_size = result->enc_pic_byte;
+	else if (result->recon_frame_index < 0)
+		result->bitstream_size = 0;
+	else
+		result->bitstream_size = result->enc_pic_byte;
+
+	result->enc_host_cmd_tick = vpu_read_reg(inst->dev, W5_RET_ENC_HOST_CMD_TICK);
+	result->enc_encode_end_tick = vpu_read_reg(inst->dev, W5_RET_ENC_ENCODING_END_TICK);
+
+	if (!p_enc_info->first_cycle_check) {
+		result->frame_cycle = (result->enc_encode_end_tick - result->enc_host_cmd_tick) *
+			p_enc_info->cycle_per_tick;
+		p_enc_info->first_cycle_check = true;
+	} else {
+		result->frame_cycle =
+			(result->enc_encode_end_tick - vpu_dev->last_performance_cycles) *
+			p_enc_info->cycle_per_tick;
+		if (vpu_dev->last_performance_cycles < result->enc_host_cmd_tick)
+			result->frame_cycle = (result->enc_encode_end_tick -
+					result->enc_host_cmd_tick) * p_enc_info->cycle_per_tick;
+	}
+	vpu_dev->last_performance_cycles = result->enc_encode_end_tick;
+
+	return 0;
+}
+
+int wave5_vpu_enc_finish_seq(struct vpu_instance *inst, u32 *fail_res)
+{
+	int ret;
+
+	if (inst->dev->product != PRODUCT_ID_521)
+		return -EINVAL;
+
+	wave5_bit_issue_command(inst, W5_DESTROY_INSTANCE);
+	ret = wave5_wait_vpu_busy(inst->dev, W5_VPU_BUSY_STATUS);
+	if (ret)
+		return -ETIMEDOUT;
+
+	if (!vpu_read_reg(inst->dev, W5_RET_SUCCESS)) {
+		*fail_res = vpu_read_reg(inst->dev, W5_RET_FAIL_REASON);
+		wave5_print_reg_err(inst->dev, *fail_res);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int wave5_vpu_enc_check_common_param_valid(struct vpu_instance *inst,
+						  struct enc_open_param *open_param)
+{
+	int i = 0;
+	bool low_delay = true;
+	struct enc_wave_param *param = &open_param->wave_param;
+	struct vpu_device *vpu_dev = inst->dev;
+	struct device *dev = vpu_dev->dev;
+	u32 num_ctu_row = (open_param->pic_height + 64 - 1) / 64;
+	u32 num_ctu_col = (open_param->pic_width + 64 - 1) / 64;
+	u32 ctu_sz = num_ctu_col * num_ctu_row;
+
+	// check low-delay gop structure
+	if (param->gop_preset_idx == PRESET_IDX_CUSTOM_GOP) { /* common gop */
+		if (param->gop_param.custom_gop_size > 1) {
+			s32 min_val = param->gop_param.pic_param[0].poc_offset;
+
+			for (i = 1; i < param->gop_param.custom_gop_size; i++) {
+				if (min_val > param->gop_param.pic_param[i].poc_offset) {
+					low_delay = false;
+					break;
+				}
+				min_val = param->gop_param.pic_param[i].poc_offset;
+			}
+		}
+	}
+
+	if (inst->std == W_HEVC_ENC && low_delay &&
+	    param->decoding_refresh_type == DEC_REFRESH_TYPE_CRA) {
+		dev_warn(dev,
+			 "dec_refresh_type(CRA) shouldn't be used together with low delay GOP\n");
+		dev_warn(dev, "Suggested configuration parameter: decoding refresh type (IDR)\n");
+		param->decoding_refresh_type = 2;
+	}
+
+	if (param->gop_preset_idx == PRESET_IDX_CUSTOM_GOP) {
+		for (i = 0; i < param->gop_param.custom_gop_size; i++) {
+			if (param->gop_param.pic_param[i].temporal_id >= MAX_NUM_TEMPORAL_LAYER) {
+				dev_err(dev, "temporal_id: %d exceeds MAX_NUM_TEMPORAL_LAYER (%u)\n",
+					param->gop_param.pic_param[i].temporal_id,
+					MAX_NUM_TEMPORAL_LAYER);
+				return -EINVAL;
+			}
+
+			if (param->gop_param.pic_param[i].temporal_id < 0) {
+				dev_err(dev, "temporal_id: %d must be greater or equal to 0\n",
+					param->gop_param.pic_param[i].temporal_id);
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (param->wpp_enable && param->independ_slice_mode) {
+		unsigned int num_ctb_in_width = ALIGN(open_param->pic_width, 64) >> 6;
+
+		if (param->independ_slice_mode_arg % num_ctb_in_width) {
+			dev_err(dev, "independ_slice_mode_arg %u must be a multiple of %u\n",
+				param->independ_slice_mode_arg, num_ctb_in_width);
+			return -EINVAL;
+		}
+	}
+
+	// multi-slice & wpp
+	if (param->wpp_enable && param->depend_slice_mode) {
+		dev_err(dev, "wpp_enable && depend_slice_mode cannot be used simultaneously\n");
+		return -EINVAL;
+	}
+
+	if (!param->independ_slice_mode && param->depend_slice_mode) {
+		dev_err(dev, "depend_slice_mode requires independ_slice_mode\n");
+		return -EINVAL;
+	} else if (param->independ_slice_mode &&
+		   param->depend_slice_mode == DEPEND_SLICE_MODE_RECOMMENDED &&
+		   param->independ_slice_mode_arg < param->depend_slice_mode_arg) {
+		dev_err(dev, "independ_slice_mode_arg: %u must be smaller than %u\n",
+			param->independ_slice_mode_arg, param->depend_slice_mode_arg);
+		return -EINVAL;
+	}
+
+	if (param->independ_slice_mode && param->independ_slice_mode_arg > 65535) {
+		dev_err(dev, "independ_slice_mode_arg: %u must be smaller than 65535\n",
+			param->independ_slice_mode_arg);
+		return -EINVAL;
+	}
+
+	if (param->depend_slice_mode && param->depend_slice_mode_arg > 65535) {
+		dev_err(dev, "depend_slice_mode_arg: %u must be smaller than 65535\n",
+			param->depend_slice_mode_arg);
+		return -EINVAL;
+	}
+
+	if (param->conf_win_top % 2) {
+		dev_err(dev, "conf_win_top: %u, must be a multiple of 2\n", param->conf_win_top);
+		return -EINVAL;
+	}
+
+	if (param->conf_win_bot % 2) {
+		dev_err(dev, "conf_win_bot: %u, must be a multiple of 2\n", param->conf_win_bot);
+		return -EINVAL;
+	}
+
+	if (param->conf_win_left % 2) {
+		dev_err(dev, "conf_win_left: %u, must be a multiple of 2\n", param->conf_win_left);
+		return -EINVAL;
+	}
+
+	if (param->conf_win_right % 2) {
+		dev_err(dev, "conf_win_right: %u, Must be a multiple of 2\n",
+			param->conf_win_right);
+		return -EINVAL;
+	}
+
+	if (param->lossless_enable && (param->nr_y_enable || param->nr_cb_enable ||
+				       param->nr_cr_enable)) {
+		/* Noise reduction => en_nr_y, en_nr_cb, en_nr_cr */
+		dev_err(dev, "option noise_reduction cannot be used with lossless_coding\n");
+		return -EINVAL;
+	}
+
+	if (param->lossless_enable && param->bg_detect_enable) {
+		dev_err(dev, "option bg_detect cannot be used with lossless_coding\n");
+		return -EINVAL;
+	}
+
+	if (param->lossless_enable && open_param->rc_enable) {
+		dev_err(dev, "option rate_control cannot be used with lossless_coding\n");
+		return -EINVAL;
+	}
+
+	if (param->lossless_enable && param->roi_enable) {
+		dev_err(dev, "option roi cannot be used with lossless_coding\n");
+		return -EINVAL;
+	}
+
+	if (param->lossless_enable && !param->skip_intra_trans) {
+		dev_err(dev, "option intra_trans_skip must be enabled with lossless_coding\n");
+		return -EINVAL;
+	}
+
+	// intra refresh
+	if (param->intra_refresh_mode && param->intra_refresh_arg == 0) {
+		dev_err(dev, "Invalid refresh argument, mode: %u, refresh: %u must be > 0\n",
+			param->intra_refresh_mode, param->intra_refresh_arg);
+		return -EINVAL;
+	}
+	switch (param->intra_refresh_mode) {
+	case REFRESH_MODE_CTU_ROWS:
+		if (param->intra_mb_refresh_arg > num_ctu_row)
+			goto invalid_refresh_argument;
+		break;
+	case REFRESH_MODE_CTU_COLUMNS:
+		if (param->intra_refresh_arg > num_ctu_col)
+			goto invalid_refresh_argument;
+		break;
+	case REFRESH_MODE_CTU_STEP_SIZE:
+		if (param->intra_refresh_arg > ctu_sz)
+			goto invalid_refresh_argument;
+		break;
+	case REFRESH_MODE_CTUS:
+		if (param->intra_refresh_arg > ctu_sz)
+			goto invalid_refresh_argument;
+		if (param->lossless_enable) {
+			dev_err(dev, "mode: %u cannot be used lossless_enable",
+				param->intra_refresh_mode);
+			return -EINVAL;
+		}
+		if (param->roi_enable) {
+			dev_err(dev, "mode: %u cannot be used and roi_enable",
+				param->intra_refresh_mode);
+			return -EINVAL;
+		}
+	};
+	return 0;
+
+invalid_refresh_argument:
+	dev_err(dev, "Invalid refresh argument, mode: %u, refresh: %u > W(%u)xH(%u)\n",
+		param->intra_refresh_mode, param->intra_refresh_arg,
+		num_ctu_row, num_ctu_col);
+	return -EINVAL;
+}
+
+static int wave5_vpu_enc_check_param_valid(struct vpu_device *vpu_dev,
+					   struct enc_open_param *open_param)
+{
+	struct enc_wave_param *param = &open_param->wave_param;
+
+	if (open_param->rc_enable) {
+		if (param->min_qp_i > param->max_qp_i || param->min_qp_p > param->max_qp_p ||
+		    param->min_qp_b > param->max_qp_b) {
+			dev_err(vpu_dev->dev, "Configuration failed because min_qp is greater than max_qp\n");
+			dev_err(vpu_dev->dev, "Suggested configuration parameters: min_qp = max_qp\n");
+			return -EINVAL;
+		}
+
+		if (open_param->bit_rate <= (int)open_param->frame_rate_info) {
+			dev_err(vpu_dev->dev,
+				"enc_bit_rate: %u must be greater than the frame_rate: %u\n",
+				open_param->bit_rate, (int)open_param->frame_rate_info);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int wave5_vpu_enc_check_custom_gop(struct vpu_device *vpu_dev,
+					  struct enc_open_param *open_param)
+{
+	struct custom_gop_param *gop_param;
+	struct custom_gop_pic_param *gop_pic_param;
+	struct custom_gop_pic_param new_gop[MAX_GOP_NUM * 2 + 1];
+
+	unsigned int i, ei, gi;
+	u32 gop_size;
+	s32 curr_poc, ref_poc;
+	s32 enc_tid[MAX_GOP_NUM * 2 + 1];
+
+	gop_param = &open_param->wave_param.gop_param;
+	gop_size = gop_param->custom_gop_size;
+
+	new_gop[0].poc_offset = 0;
+	new_gop[0].temporal_id = 0;
+	new_gop[0].pic_type = PIC_TYPE_I;
+	new_gop[0].use_multi_ref_p = 0;
+	enc_tid[0] = 0;
+
+	for (i = 0; i < gop_size * 2; i++) {
+		ei = i % gop_size;
+		gi = i / gop_size;
+		gop_pic_param = &gop_param->pic_param[ei];
+
+		curr_poc = gi * gop_size + gop_pic_param->poc_offset;
+		new_gop[i + 1].poc_offset = curr_poc;
+		new_gop[i + 1].temporal_id = gop_pic_param->temporal_id;
+		new_gop[i + 1].pic_type = gop_pic_param->pic_type;
+		new_gop[i + 1].ref_poc_l0 = gop_pic_param->ref_poc_l0 + gi * gop_size;
+		new_gop[i + 1].ref_poc_l1 = gop_pic_param->ref_poc_l1 + gi * gop_size;
+		new_gop[i + 1].use_multi_ref_p = gop_pic_param->use_multi_ref_p;
+		enc_tid[i + 1] = -1;
+	}
+
+	for (i = 0; i < gop_size; i++) {
+		gop_pic_param = &gop_param->pic_param[i];
+
+		if (gop_pic_param->poc_offset <= 0) {
+			dev_err(vpu_dev->dev, "POC of the %u-th pic not greater then -1\n", i + 1);
+			return -EINVAL;
+		}
+		if (gop_pic_param->poc_offset > gop_size) {
+			dev_err(vpu_dev->dev, "POC of %uth pic bigger than gop_size\n", i + 1);
+			return -EINVAL;
+		}
+		if (gop_pic_param->temporal_id < 0) {
+			dev_err(vpu_dev->dev, "temporal_id of the %d-th  < 0\n", i + 1);
+			return -EINVAL;
+		}
+	}
+
+	for (ei = 1; ei < gop_size * 2 + 1; ei++) {
+		struct custom_gop_pic_param *cur_pic = &new_gop[ei];
+
+		if (ei <= gop_size) {
+			enc_tid[cur_pic->poc_offset] = cur_pic->temporal_id;
+			continue;
+		}
+
+		if (new_gop[ei].pic_type != PIC_TYPE_I) {
+			ref_poc = cur_pic->ref_poc_l0;
+
+			/* reference picture is not encoded yet */
+			if (enc_tid[ref_poc] < 0) {
+				dev_err(vpu_dev->dev, "1st ref pic can't be ref of pic (POC: %u)\n",
+					cur_pic->poc_offset - gop_size);
+				return -EINVAL;
+			}
+			if (enc_tid[ref_poc] > cur_pic->temporal_id) {
+				dev_err(vpu_dev->dev, "wrong temporal_id of pic (POC: %u)\n",
+					cur_pic->poc_offset - gop_size);
+				return -EINVAL;
+			}
+			if (ref_poc >= cur_pic->poc_offset) {
+				dev_err(vpu_dev->dev, "POC of 1st ref pic of %u-th pic is wrong\n",
+					cur_pic->poc_offset - gop_size);
+				return -EINVAL;
+			}
+		}
+		if (new_gop[ei].pic_type != PIC_TYPE_P) {
+			ref_poc = cur_pic->ref_poc_l1;
+
+			/* reference picture is not encoded yet */
+			if (enc_tid[ref_poc] < 0) {
+				dev_err(vpu_dev->dev, "2nd ref pic can't be ref of pic (POC: %u)\n"
+						, cur_pic->poc_offset - gop_size);
+				return -EINVAL;
+			}
+			if (enc_tid[ref_poc] > cur_pic->temporal_id) {
+				dev_err(vpu_dev->dev,  "temporal_id of %u-th picture is wrong\n",
+					cur_pic->poc_offset - gop_size);
+				return -EINVAL;
+			}
+			if (new_gop[ei].pic_type == PIC_TYPE_P && new_gop[ei].use_multi_ref_p > 0) {
+				if (ref_poc >= cur_pic->poc_offset) {
+					dev_err(vpu_dev->dev,  "bad POC of 2nd ref pic of %uth pic\n",
+						cur_pic->poc_offset - gop_size);
+					return -EINVAL;
+				}
+			} else if (ref_poc == cur_pic->poc_offset) {
+				/* HOST_PIC_TYPE_B */
+				dev_err(vpu_dev->dev,  "POC of 2nd ref pic of %uth pic is wrong\n",
+					cur_pic->poc_offset - gop_size);
+				return -EINVAL;
+			}
+		}
+		curr_poc = cur_pic->poc_offset;
+		enc_tid[curr_poc] = cur_pic->temporal_id;
+	}
+	return 0;
+}
+
+int wave5_vpu_enc_check_open_param(struct vpu_instance *inst, struct enc_open_param *open_param)
+{
+	u32 pic_width;
+	u32 pic_height;
+	s32 product_id = inst->dev->product;
+	struct vpu_attr *p_attr = &inst->dev->attr;
+	struct enc_wave_param *param;
+
+	if (!open_param)
+		return -EINVAL;
+
+	param = &open_param->wave_param;
+	pic_width = open_param->pic_width;
+	pic_height = open_param->pic_height;
+
+	if (inst->id >= MAX_NUM_INSTANCE) {
+		dev_err(inst->dev->dev, "Too many simultaneous instances: %d (max: %u)\n",
+			inst->id, MAX_NUM_INSTANCE);
+		return -EOPNOTSUPP;
+	}
+
+	if (inst->std != W_HEVC_ENC &&
+	    !(inst->std == W_AVC_ENC && product_id == PRODUCT_ID_521)) {
+		dev_err(inst->dev->dev, "Unsupported encoder-codec & product combination\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (param->internal_bit_depth == 10) {
+		if (inst->std == W_HEVC_ENC && !p_attr->support_hevc10bit_enc) {
+			dev_err(inst->dev->dev,
+				"Flag support_hevc10bit_enc must be set to encode 10bit HEVC\n");
+			return -EOPNOTSUPP;
+		} else if (inst->std == W_AVC_ENC && !p_attr->support_avc10bit_enc) {
+			dev_err(inst->dev->dev,
+				"Flag support_avc10bit_enc must be set to encode 10bit AVC\n");
+			return -EOPNOTSUPP;
+		}
+	}
+
+	if (open_param->ring_buffer_enable) {
+		if (open_param->bitstream_buffer % 8) {
+			dev_err(inst->dev->dev,
+				"Bitstream buffer must be aligned to a multiple of 8\n");
+			return -EINVAL;
+		}
+		if (open_param->bitstream_buffer_size % 1024 ||
+		    open_param->bitstream_buffer_size < MIN_BITSTREAM_BUFFER_SIZE) {
+			dev_err(inst->dev->dev,
+				"Bitstream buffer size must be aligned to a multiple of 1024 and have a minimum size of %u\n",
+				MIN_BITSTREAM_BUFFER_SIZE);
+			return -EINVAL;
+		}
+		if (product_id == PRODUCT_ID_521) {
+			if (open_param->bitstream_buffer % 16) {
+				dev_err(inst->dev->dev,
+					"Bitstream buffer must be aligned to a multiple of 16\n");
+				return -EINVAL;
+			}
+			if (open_param->bitstream_buffer_size < MIN_BITSTREAM_BUFFER_SIZE_WAVE521) {
+				dev_err(inst->dev->dev,
+					"Bitstream buffer too small: %u (minimum: %u)\n",
+					open_param->bitstream_buffer_size,
+					MIN_BITSTREAM_BUFFER_SIZE_WAVE521);
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (!open_param->frame_rate_info)
+		return -EINVAL;
+	if (open_param->bit_rate > MAX_BIT_RATE) {
+		dev_err(inst->dev->dev, "Invalid encoding bit-rate: %u (valid: 0-%u)\n",
+			open_param->bit_rate, MAX_BIT_RATE);
+		return -EINVAL;
+	}
+
+	if (pic_width < W5_MIN_ENC_PIC_WIDTH || pic_width > W5_MAX_ENC_PIC_WIDTH ||
+	    pic_height < W5_MIN_ENC_PIC_HEIGHT || pic_height > W5_MAX_ENC_PIC_HEIGHT) {
+		dev_err(inst->dev->dev, "Invalid encoding dimension: %ux%u\n",
+			pic_width, pic_height);
+		return -EINVAL;
+	}
+
+	if (param->profile) {
+		if (inst->std == W_HEVC_ENC) {
+			if ((param->profile != HEVC_PROFILE_MAIN ||
+			     (param->profile == HEVC_PROFILE_MAIN &&
+			      param->internal_bit_depth > 8)) &&
+			    (param->profile != HEVC_PROFILE_MAIN10 ||
+			     (param->profile == HEVC_PROFILE_MAIN10 &&
+			      param->internal_bit_depth < 10)) &&
+			    param->profile != HEVC_PROFILE_STILLPICTURE) {
+				dev_err(inst->dev->dev,
+					"Invalid HEVC encoding profile: %u (bit-depth: %u)\n",
+					param->profile, param->internal_bit_depth);
+				return -EINVAL;
+			}
+		} else if (inst->std == W_AVC_ENC) {
+			if ((param->internal_bit_depth > 8 &&
+			     param->profile != H264_PROFILE_HIGH10)) {
+				dev_err(inst->dev->dev,
+					"Invalid AVC encoding profile: %u (bit-depth: %u)\n",
+					param->profile, param->internal_bit_depth);
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (param->decoding_refresh_type > DEC_REFRESH_TYPE_IDR) {
+		dev_err(inst->dev->dev, "Invalid decoding refresh type: %u (valid: 0-2)\n",
+			param->decoding_refresh_type);
+		return -EINVAL;
+	}
+
+	if (param->gop_preset_idx == PRESET_IDX_CUSTOM_GOP) {
+		if (param->gop_param.custom_gop_size < 1 ||
+		    param->gop_param.custom_gop_size > MAX_GOP_NUM) {
+			dev_err(inst->dev->dev,
+				"Invalid custom group of pictures size: %u (valid: 1-%u)\n",
+				param->gop_param.custom_gop_size, MAX_GOP_NUM);
+			return -EINVAL;
+		}
+	}
+
+	if (inst->std == W_AVC_ENC && param->custom_lambda_enable) {
+		dev_err(inst->dev->dev,
+			"Cannot combine AVC encoding with the custom lambda option\n");
+		return -EINVAL;
+	}
+	if (param->intra_refresh_mode > REFRESH_MODE_CTUS) {
+		dev_err(inst->dev->dev, "Invalid intra refresh mode: %d (valid: 0-4)\n",
+			param->intra_refresh_mode);
+		return -EINVAL;
+	}
+
+	if (inst->std == W_HEVC_ENC && param->independ_slice_mode &&
+	    param->depend_slice_mode > DEPEND_SLICE_MODE_BOOST) {
+		dev_err(inst->dev->dev,
+			"Can't combine slice modes: independent and fast dependent for HEVC\n");
+		return -EINVAL;
+	}
+
+	if (param->scaling_list_enable > 2) {
+		dev_err(inst->dev->dev, "Invalid scaling_list_enable: %u (valid: 0-2)\n",
+			param->scaling_list_enable);
+		return -EINVAL;
+	}
+
+	if (!param->disable_deblk) {
+		if (param->beta_offset_div2 < -6 || param->beta_offset_div2 > 6) {
+			dev_err(inst->dev->dev, "Invalid beta offset: %d (valid: -6-6)\n",
+				param->beta_offset_div2);
+			return -EINVAL;
+		}
+
+		if (param->tc_offset_div2 < -6 || param->tc_offset_div2 > 6) {
+			dev_err(inst->dev->dev, "Invalid tc offset: %d (valid: -6-6)\n",
+				param->tc_offset_div2);
+			return -EINVAL;
+		}
+	}
+
+	if (param->intra_qp > MAX_INTRA_QP) {
+		dev_err(inst->dev->dev,
+			"Invalid intra quantization parameter: %u (valid: 0-%u)\n",
+			param->intra_qp, MAX_INTRA_QP);
+		return -EINVAL;
+	}
+
+	if (open_param->rc_enable) {
+		if (param->min_qp_i > MAX_INTRA_QP || param->max_qp_i > MAX_INTRA_QP ||
+		    param->min_qp_p > MAX_INTRA_QP || param->max_qp_p > MAX_INTRA_QP ||
+		    param->min_qp_b > MAX_INTRA_QP || param->max_qp_b > MAX_INTRA_QP) {
+			dev_err(inst->dev->dev,
+				"Invalid quantization parameter min/max values: "
+				"I: %u-%u, P: %u-%u, B: %u-%u (valid for each: 0-%u)\n",
+				param->min_qp_i, param->max_qp_i, param->min_qp_p, param->max_qp_p,
+				param->min_qp_b, param->max_qp_b, MAX_INTRA_QP);
+			return -EINVAL;
+		}
+
+		if (param->hvs_qp_enable && param->hvs_max_delta_qp > MAX_HVS_MAX_DELTA_QP) {
+			dev_err(inst->dev->dev,
+				"Invalid HVS max delta quantization parameter: %u (valid: 0-%u)\n",
+				param->hvs_max_delta_qp, MAX_HVS_MAX_DELTA_QP);
+			return -EINVAL;
+		}
+
+		if (param->bit_alloc_mode > BIT_ALLOC_MODE_FIXED_RATIO) {
+			dev_err(inst->dev->dev, "Invalid bit alloc mode: %u (valid: 0-2)\n",
+				param->bit_alloc_mode);
+			return -EINVAL;
+		}
+
+		if (open_param->vbv_buffer_size < MIN_VBV_BUFFER_SIZE ||
+		    open_param->vbv_buffer_size > MAX_VBV_BUFFER_SIZE) {
+			dev_err(inst->dev->dev, "VBV buffer size: %u (valid: %u-%u)\n",
+				open_param->vbv_buffer_size, MIN_VBV_BUFFER_SIZE,
+				MAX_VBV_BUFFER_SIZE);
+			return -EINVAL;
+		}
+	}
+
+	if (wave5_vpu_enc_check_common_param_valid(inst, open_param))
+		return -EINVAL;
+
+	if (wave5_vpu_enc_check_param_valid(inst->dev, open_param))
+		return -EINVAL;
+
+	if (param->gop_preset_idx == PRESET_IDX_CUSTOM_GOP) {
+		if (wave5_vpu_enc_check_custom_gop(inst->dev, open_param))
+			return -EINVAL;
+	}
+
+	if (param->chroma_cb_qp_offset < -12 || param->chroma_cb_qp_offset > 12) {
+		dev_err(inst->dev->dev,
+			"Invalid chroma Cb quantization parameter offset: %d (valid: -12-12)\n",
+			param->chroma_cb_qp_offset);
+		return -EINVAL;
+	}
+
+	if (param->chroma_cr_qp_offset < -12 || param->chroma_cr_qp_offset > 12) {
+		dev_err(inst->dev->dev,
+			"Invalid chroma Cr quantization parameter offset: %d (valid: -12-12)\n",
+			param->chroma_cr_qp_offset);
+		return -EINVAL;
+	}
+
+	if (param->intra_refresh_mode == REFRESH_MODE_CTU_STEP_SIZE && !param->intra_refresh_arg) {
+		dev_err(inst->dev->dev,
+			"Intra refresh mode CTU step-size requires an argument\n");
+		return -EINVAL;
+	}
+
+	if (inst->std == W_HEVC_ENC) {
+		if (param->nr_noise_sigma_y > MAX_NOISE_SIGMA ||
+		    param->nr_noise_sigma_cb > MAX_NOISE_SIGMA ||
+		    param->nr_noise_sigma_cr > MAX_NOISE_SIGMA) {
+			dev_err(inst->dev->dev,
+				"Invalid noise sigma Y(%u) Cb(%u) Cr(%u) (valid: %u)\n",
+				param->nr_noise_sigma_y, param->nr_noise_sigma_cb,
+				param->nr_noise_sigma_cr, MAX_NOISE_SIGMA);
+			return -EINVAL;
+		}
+
+		if (param->nr_intra_weight_y > MAX_INTRA_WEIGHT ||
+		    param->nr_intra_weight_cb > MAX_INTRA_WEIGHT ||
+		    param->nr_intra_weight_cr > MAX_INTRA_WEIGHT) {
+			dev_err(inst->dev->dev,
+				"Invalid intra weight Y(%u) Cb(%u) Cr(%u) (valid: %u)\n",
+				param->nr_intra_weight_y, param->nr_intra_weight_cb,
+				param->nr_intra_weight_cr, MAX_INTRA_WEIGHT);
+			return -EINVAL;
+		}
+
+		if (param->nr_inter_weight_y > MAX_INTER_WEIGHT ||
+		    param->nr_inter_weight_cb > MAX_INTER_WEIGHT ||
+		    param->nr_inter_weight_cr > MAX_INTER_WEIGHT) {
+			dev_err(inst->dev->dev,
+				"Invalid inter weight Y(%u) Cb(%u) Cr(%u) (valid: %u)\n",
+				param->nr_inter_weight_y, param->nr_inter_weight_cb,
+				param->nr_inter_weight_cr, MAX_INTER_WEIGHT);
+			return -EINVAL;
+		}
+
+		if ((param->nr_y_enable || param->nr_cb_enable || param->nr_cr_enable) &&
+		    param->lossless_enable) {
+			dev_err(inst->dev->dev,
+				"Can't enable lossless mode with either nr_y, nr_cb or nr_cr\n");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-regdefine.h b/drivers/media/platform/chips-media/wave5/wave5-regdefine.h
--- a/drivers/media/platform/chips-media/wave5/wave5-regdefine.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-regdefine.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,743 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave5 series multi-standard codec IP - wave5 register definitions
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+
+#ifndef __WAVE5_REGISTER_DEFINE_H__
+#define __WAVE5_REGISTER_DEFINE_H__
+
+enum W5_VPU_COMMAND {
+	W5_INIT_VPU        = 0x0001,
+	W5_WAKEUP_VPU      = 0x0002,
+	W5_SLEEP_VPU       = 0x0004,
+	W5_CREATE_INSTANCE = 0x0008,            /* queuing command */
+	W5_FLUSH_INSTANCE  = 0x0010,
+	W5_DESTROY_INSTANCE = 0x0020,            /* queuing command */
+	W5_INIT_SEQ        = 0x0040,            /* queuing command */
+	W5_SET_FB          = 0x0080,
+	W5_DEC_PIC         = 0x0100,            /* queuing command */
+	W5_ENC_PIC         = 0x0100,            /* queuing command */
+	W5_ENC_SET_PARAM   = 0x0200,            /* queuing command */
+	W5_QUERY           = 0x4000,
+	W5_UPDATE_BS       = 0x8000,
+	W5_MAX_VPU_COMD	   = 0x10000,
+};
+
+enum QUERY_OPT {
+	GET_VPU_INFO        = 0,
+	SET_WRITE_PROT      = 1,
+	GET_RESULT          = 2,
+	UPDATE_DISP_FLAG    = 3,
+	GET_BW_REPORT       = 4,
+	GET_BS_RD_PTR       = 5,    // for decoder
+	GET_BS_WR_PTR       = 6,    // for encoder
+	GET_SRC_BUF_FLAG    = 7,    // for encoder
+	SET_BS_RD_PTR       = 8,    // for decoder
+	GET_DEBUG_INFO      = 0x61,
+};
+
+/*
+ * A flag of user data buffer full.
+ * User data buffer full flag equal to 1 specifies that de-
+ * coded frame has more user data size than VPU internal
+ * buffer. VPU only dumps the internal buffer size of us-
+ * er data to USER_DATA_BUF_BASE buffer. In other
+ * words, VPU is unable to report the rest of the user data to
+ * USER_DATA_BUF_BASE buffer after the internal buffer
+ * fullness happens.
+ */
+#define USERDATA_FLAG_BUFF_FULL		1
+
+#define W5_REG_BASE                     0x00000000
+#define W5_CMD_REG_BASE                 0x00000100
+#define W5_CMD_REG_END                  0x00000200
+
+/*
+ * common
+ */
+/* power on configuration
+ * PO_DEBUG_MODE    [0]     1 - power on with debug mode
+ * USE_PO_CONF      [3]     1 - use power-on-configuration
+ */
+#define W5_PO_CONF                     (W5_REG_BASE + 0x0000)
+#define W5_VCPU_CUR_PC                 (W5_REG_BASE + 0x0004)
+#define W5_VCPU_CUR_LR                 (W5_REG_BASE + 0x0008)
+#define W5_VPU_PDBG_STEP_MASK_V        (W5_REG_BASE + 0x000C)
+#define W5_VPU_PDBG_CTRL               (W5_REG_BASE + 0x0010) // v_cpu debugger ctrl register
+#define W5_VPU_PDBG_IDX_REG            (W5_REG_BASE + 0x0014) // v_cpu debugger index register
+#define W5_VPU_PDBG_WDATA_REG          (W5_REG_BASE + 0x0018) // v_cpu debugger write data register
+#define W5_VPU_PDBG_RDATA_REG          (W5_REG_BASE + 0x001C) // v_cpu debugger read data register
+
+#define W5_VPU_FIO_CTRL_ADDR           (W5_REG_BASE + 0x0020)
+#define W5_VPU_FIO_DATA                (W5_REG_BASE + 0x0024)
+#define W5_VPU_VINT_REASON_USR         (W5_REG_BASE + 0x0030)
+#define W5_VPU_VINT_REASON_CLR         (W5_REG_BASE + 0x0034)
+#define W5_VPU_HOST_INT_REQ            (W5_REG_BASE + 0x0038)
+#define W5_VPU_VINT_CLEAR              (W5_REG_BASE + 0x003C)
+#define W5_VPU_HINT_CLEAR              (W5_REG_BASE + 0x0040)
+#define W5_VPU_VPU_INT_STS             (W5_REG_BASE + 0x0044)
+#define W5_VPU_VINT_ENABLE             (W5_REG_BASE + 0x0048)
+#define W5_VPU_VINT_REASON             (W5_REG_BASE + 0x004C)
+#define W5_VPU_RESET_REQ               (W5_REG_BASE + 0x0050)
+#define W5_RST_BLOCK_CCLK(_core)       BIT((_core))
+#define W5_RST_BLOCK_CCLK_ALL          (0xff)
+#define W5_RST_BLOCK_BCLK(_core)       (0x100 << (_core))
+#define W5_RST_BLOCK_BCLK_ALL          (0xff00)
+#define W5_RST_BLOCK_ACLK(_core)       (0x10000 << (_core))
+#define W5_RST_BLOCK_ACLK_ALL          (0xff0000)
+#define W5_RST_BLOCK_VCPU_ALL          (0x3f000000)
+#define W5_RST_BLOCK_ALL               (0x3fffffff)
+#define W5_VPU_RESET_STATUS            (W5_REG_BASE + 0x0054)
+
+#define W5_VCPU_RESTART                (W5_REG_BASE + 0x0058)
+#define W5_VPU_CLK_MASK                (W5_REG_BASE + 0x005C)
+
+/* REMAP_CTRL
+ * PAGE SIZE:   [8:0]   0x001 - 4K
+ *                      0x002 - 8K
+ *                      0x004 - 16K
+ *                      ...
+ *                      0x100 - 1M
+ * REGION ATTR1 [10]    0     - normal
+ *                      1     - make bus error for the region
+ * REGION ATTR2 [11]    0     - normal
+ *                      1     - bypass region
+ * REMAP INDEX  [15:12]       - 0 ~ 3
+ * ENDIAN       [19:16]       - see endian_mode in vdi.h
+ * AXI-ID       [23:20]       - upper AXI-ID
+ * BUS_ERROR    [29]    0     - bypass
+ *                      1     - make BUS_ERROR for unmapped region
+ * BYPASS_ALL   [30]    1     - bypass all
+ * ENABLE       [31]    1     - update control register[30:16]
+ */
+#define W5_VPU_REMAP_CTRL                       (W5_REG_BASE + 0x0060)
+#define W5_VPU_REMAP_VADDR                      (W5_REG_BASE + 0x0064)
+#define W5_VPU_REMAP_PADDR                      (W5_REG_BASE + 0x0068)
+#define W5_VPU_REMAP_CORE_START                 (W5_REG_BASE + 0x006C)
+#define W5_VPU_BUSY_STATUS                      (W5_REG_BASE + 0x0070)
+#define W5_VPU_HALT_STATUS                      (W5_REG_BASE + 0x0074)
+#define W5_VPU_VCPU_STATUS                      (W5_REG_BASE + 0x0078)
+#define W5_VPU_RET_PRODUCT_VERSION              (W5_REG_BASE + 0x0094)
+/*
+ * assign vpu_config0          = {conf_map_converter_reg,      // [31]
+ * conf_map_converter_sig,         // [30]
+ * 8'd0,                        // [29:22]
+ * conf_std_switch_en,          // [21]
+ * conf_bg_detect,              // [20]
+ * conf_3dnr_en,                // [19]
+ * conf_one_axi_en,             // [18]
+ * conf_sec_axi_en,             // [17]
+ * conf_bus_info,               // [16]
+ * conf_afbc_en,                // [15]
+ * conf_afbc_version_id,        // [14:12]
+ * conf_fbc_en,                 // [11]
+ * conf_fbc_version_id,         // [10:08]
+ * conf_scaler_en,              // [07]
+ * conf_scaler_version_id,      // [06:04]
+ * conf_bwb_en,                 // [03]
+ * 3'd0};                       // [02:00]
+ */
+#define W5_VPU_RET_VPU_CONFIG0                  (W5_REG_BASE + 0x0098)
+/*
+ * assign vpu_config1          = {4'd0,                        // [31:28]
+ * conf_perf_timer_en,          // [27]
+ * conf_multi_core_en,          // [26]
+ * conf_gcu_en,                 // [25]
+ * conf_cu_report,              // [24]
+ * 4'd0,                        // [23:20]
+ * conf_vcore_id_3,             // [19]
+ * conf_vcore_id_2,             // [18]
+ * conf_vcore_id_1,             // [17]
+ * conf_vcore_id_0,             // [16]
+ * conf_bwb_opt,                // [15]
+ * 7'd0,                        // [14:08]
+ * conf_cod_std_en_reserved_7,  // [7]
+ * conf_cod_std_en_reserved_6,  // [6]
+ * conf_cod_std_en_reserved_5,  // [5]
+ * conf_cod_std_en_reserved_4,  // [4]
+ * conf_cod_std_en_reserved_3,  // [3]
+ * conf_cod_std_en_reserved_2,  // [2]
+ * conf_cod_std_en_vp9,         // [1]
+ * conf_cod_std_en_hevc};       // [0]
+ * }
+ */
+#define W5_VPU_RET_VPU_CONFIG1                  (W5_REG_BASE + 0x009C)
+
+#define W5_VPU_DBG_REG0							(W5_REG_BASE + 0x00f0)
+#define W5_VPU_DBG_REG1							(W5_REG_BASE + 0x00f4)
+#define W5_VPU_DBG_REG2							(W5_REG_BASE + 0x00f8)
+#define W5_VPU_DBG_REG3							(W5_REG_BASE + 0x00fc)
+
+/************************************************************************/
+/* PRODUCT INFORMATION                                                  */
+/************************************************************************/
+#define W5_PRODUCT_NAME                        (W5_REG_BASE + 0x1040)
+#define W5_PRODUCT_NUMBER                      (W5_REG_BASE + 0x1044)
+
+/************************************************************************/
+/* DECODER/ENCODER COMMON                                               */
+/************************************************************************/
+#define W5_COMMAND                              (W5_REG_BASE + 0x0100)
+#define W5_COMMAND_OPTION                       (W5_REG_BASE + 0x0104)
+#define W5_QUERY_OPTION                         (W5_REG_BASE + 0x0104)
+#define W5_RET_SUCCESS                          (W5_REG_BASE + 0x0108)
+#define W5_RET_FAIL_REASON                      (W5_REG_BASE + 0x010C)
+#define W5_RET_QUEUE_FAIL_REASON                (W5_REG_BASE + 0x0110)
+#define W5_CMD_INSTANCE_INFO                    (W5_REG_BASE + 0x0110)
+
+#define W5_RET_QUEUE_STATUS                     (W5_REG_BASE + 0x01E0)
+#define W5_RET_BS_EMPTY_INST                    (W5_REG_BASE + 0x01E4)
+#define W5_RET_QUEUE_CMD_DONE_INST              (W5_REG_BASE + 0x01E8)
+#define W5_RET_STAGE0_INSTANCE_INFO             (W5_REG_BASE + 0x01EC)
+#define W5_RET_STAGE1_INSTANCE_INFO             (W5_REG_BASE + 0x01F0)
+#define W5_RET_STAGE2_INSTANCE_INFO             (W5_REG_BASE + 0x01F4)
+
+#define W5_RET_SEQ_DONE_INSTANCE_INFO           (W5_REG_BASE + 0x01FC)
+
+#define W5_BS_OPTION                            (W5_REG_BASE + 0x0120)
+
+// return info when QUERY (GET_RESULT) for en/decoder
+#define W5_RET_VLC_BUF_SIZE                     (W5_REG_BASE + 0x01B0)
+// return info when QUERY (GET_RESULT) for en/decoder
+#define W5_RET_PARAM_BUF_SIZE                   (W5_REG_BASE + 0x01B4)
+
+// set when SET_FB for en/decoder
+#define W5_CMD_SET_FB_ADDR_TASK_BUF             (W5_REG_BASE + 0x01D4)
+#define W5_CMD_SET_FB_TASK_BUF_SIZE             (W5_REG_BASE + 0x01D8)
+/************************************************************************/
+/* INIT_VPU - COMMON                                                    */
+/************************************************************************/
+/* note: W5_ADDR_CODE_BASE should be aligned to 4KB */
+#define W5_ADDR_CODE_BASE                       (W5_REG_BASE + 0x0110)
+#define W5_CODE_SIZE                            (W5_REG_BASE + 0x0114)
+#define W5_CODE_PARAM                           (W5_REG_BASE + 0x0118)
+#define W5_ADDR_TEMP_BASE                       (W5_REG_BASE + 0x011C)
+#define W5_TEMP_SIZE                            (W5_REG_BASE + 0x0120)
+#define W5_HW_OPTION                            (W5_REG_BASE + 0x012C)
+#define W5_SEC_AXI_PARAM                        (W5_REG_BASE + 0x0180)
+
+/************************************************************************/
+/* CREATE_INSTANCE - COMMON                                             */
+/************************************************************************/
+#define W5_ADDR_WORK_BASE                       (W5_REG_BASE + 0x0114)
+#define W5_WORK_SIZE                            (W5_REG_BASE + 0x0118)
+#define W5_CMD_DEC_BS_START_ADDR                (W5_REG_BASE + 0x011C)
+#define W5_CMD_DEC_BS_SIZE                      (W5_REG_BASE + 0x0120)
+#define W5_CMD_BS_PARAM                         (W5_REG_BASE + 0x0124)
+#define W5_CMD_ADDR_SEC_AXI                     (W5_REG_BASE + 0x0130)
+#define W5_CMD_SEC_AXI_SIZE                     (W5_REG_BASE + 0x0134)
+#define W5_CMD_EXT_ADDR                         (W5_REG_BASE + 0x0138)
+#define W5_CMD_NUM_CQ_DEPTH_M1                  (W5_REG_BASE + 0x013C)
+#define W5_CMD_ERR_CONCEAL                      (W5_REG_BASE + 0x0140)
+
+/************************************************************************/
+/* DECODER - INIT_SEQ                                                   */
+/************************************************************************/
+#define W5_BS_RD_PTR                            (W5_REG_BASE + 0x0118)
+#define W5_BS_WR_PTR                            (W5_REG_BASE + 0x011C)
+/************************************************************************/
+/* SET_FRAME_BUF                                                        */
+/************************************************************************/
+/* SET_FB_OPTION 0x00       REGISTER FRAMEBUFFERS
+ * 0x01       UPDATE FRAMEBUFFER, just one framebuffer(linear, fbc and mvcol)
+ */
+#define W5_SFB_OPTION                           (W5_REG_BASE + 0x0104)
+#define W5_COMMON_PIC_INFO                      (W5_REG_BASE + 0x0118)
+#define W5_PIC_SIZE                             (W5_REG_BASE + 0x011C)
+#define W5_SET_FB_NUM                           (W5_REG_BASE + 0x0120)
+#define W5_EXTRA_PIC_INFO                       (W5_REG_BASE + 0x0124)
+
+#define W5_ADDR_LUMA_BASE0                      (W5_REG_BASE + 0x0134)
+#define W5_ADDR_CB_BASE0                        (W5_REG_BASE + 0x0138)
+#define W5_ADDR_CR_BASE0                        (W5_REG_BASE + 0x013C)
+// compression offset table for luma
+#define W5_ADDR_FBC_Y_OFFSET0                   (W5_REG_BASE + 0x013C)
+// compression offset table for chroma
+#define W5_ADDR_FBC_C_OFFSET0                   (W5_REG_BASE + 0x0140)
+#define W5_ADDR_LUMA_BASE1                      (W5_REG_BASE + 0x0144)
+#define W5_ADDR_CB_ADDR1                        (W5_REG_BASE + 0x0148)
+#define W5_ADDR_CR_ADDR1                        (W5_REG_BASE + 0x014C)
+// compression offset table for luma
+#define W5_ADDR_FBC_Y_OFFSET1                   (W5_REG_BASE + 0x014C)
+// compression offset table for chroma
+#define W5_ADDR_FBC_C_OFFSET1                   (W5_REG_BASE + 0x0150)
+#define W5_ADDR_LUMA_BASE2                      (W5_REG_BASE + 0x0154)
+#define W5_ADDR_CB_ADDR2                        (W5_REG_BASE + 0x0158)
+#define W5_ADDR_CR_ADDR2                        (W5_REG_BASE + 0x015C)
+// compression offset table for luma
+#define W5_ADDR_FBC_Y_OFFSET2                   (W5_REG_BASE + 0x015C)
+// compression offset table for chroma
+#define W5_ADDR_FBC_C_OFFSET2                   (W5_REG_BASE + 0x0160)
+#define W5_ADDR_LUMA_BASE3                      (W5_REG_BASE + 0x0164)
+#define W5_ADDR_CB_ADDR3                        (W5_REG_BASE + 0x0168)
+#define W5_ADDR_CR_ADDR3                        (W5_REG_BASE + 0x016C)
+// compression offset table for luma
+#define W5_ADDR_FBC_Y_OFFSET3                   (W5_REG_BASE + 0x016C)
+// compression offset table for chroma
+#define W5_ADDR_FBC_C_OFFSET3                   (W5_REG_BASE + 0x0170)
+#define W5_ADDR_LUMA_BASE4                      (W5_REG_BASE + 0x0174)
+#define W5_ADDR_CB_ADDR4                        (W5_REG_BASE + 0x0178)
+#define W5_ADDR_CR_ADDR4                        (W5_REG_BASE + 0x017C)
+// compression offset table for luma
+#define W5_ADDR_FBC_Y_OFFSET4                   (W5_REG_BASE + 0x017C)
+// compression offset table for chroma
+#define W5_ADDR_FBC_C_OFFSET4                   (W5_REG_BASE + 0x0180)
+#define W5_ADDR_LUMA_BASE5                      (W5_REG_BASE + 0x0184)
+#define W5_ADDR_CB_ADDR5                        (W5_REG_BASE + 0x0188)
+#define W5_ADDR_CR_ADDR5                        (W5_REG_BASE + 0x018C)
+// compression offset table for luma
+#define W5_ADDR_FBC_Y_OFFSET5                   (W5_REG_BASE + 0x018C)
+// compression offset table for chroma
+#define W5_ADDR_FBC_C_OFFSET5                   (W5_REG_BASE + 0x0190)
+#define W5_ADDR_LUMA_BASE6                      (W5_REG_BASE + 0x0194)
+#define W5_ADDR_CB_ADDR6                        (W5_REG_BASE + 0x0198)
+#define W5_ADDR_CR_ADDR6                        (W5_REG_BASE + 0x019C)
+// compression offset table for luma
+#define W5_ADDR_FBC_Y_OFFSET6                   (W5_REG_BASE + 0x019C)
+// compression offset table for chroma
+#define W5_ADDR_FBC_C_OFFSET6                   (W5_REG_BASE + 0x01A0)
+#define W5_ADDR_LUMA_BASE7                      (W5_REG_BASE + 0x01A4)
+#define W5_ADDR_CB_ADDR7                        (W5_REG_BASE + 0x01A8)
+#define W5_ADDR_CR_ADDR7                        (W5_REG_BASE + 0x01AC)
+// compression offset table for luma
+#define W5_ADDR_FBC_Y_OFFSET7                   (W5_REG_BASE + 0x01AC)
+// compression offset table for chroma
+#define W5_ADDR_FBC_C_OFFSET7                   (W5_REG_BASE + 0x01B0)
+#define W5_ADDR_MV_COL0                         (W5_REG_BASE + 0x01B4)
+#define W5_ADDR_MV_COL1                         (W5_REG_BASE + 0x01B8)
+#define W5_ADDR_MV_COL2                         (W5_REG_BASE + 0x01BC)
+#define W5_ADDR_MV_COL3                         (W5_REG_BASE + 0x01C0)
+#define W5_ADDR_MV_COL4                         (W5_REG_BASE + 0x01C4)
+#define W5_ADDR_MV_COL5                         (W5_REG_BASE + 0x01C8)
+#define W5_ADDR_MV_COL6                         (W5_REG_BASE + 0x01CC)
+#define W5_ADDR_MV_COL7                         (W5_REG_BASE + 0x01D0)
+
+/* UPDATE_FB */
+/* CMD_SET_FB_STRIDE [15:0]     - FBC framebuffer stride
+ * [31:15]    - linear framebuffer stride
+ */
+#define W5_CMD_SET_FB_STRIDE                    (W5_REG_BASE + 0x0118)
+#define W5_CMD_SET_FB_INDEX                     (W5_REG_BASE + 0x0120)
+#define W5_ADDR_LUMA_BASE                       (W5_REG_BASE + 0x0134)
+#define W5_ADDR_CB_BASE                         (W5_REG_BASE + 0x0138)
+#define W5_ADDR_CR_BASE                         (W5_REG_BASE + 0x013C)
+#define W5_ADDR_MV_COL                          (W5_REG_BASE + 0x0140)
+#define W5_ADDR_FBC_Y_BASE                      (W5_REG_BASE + 0x0144)
+#define W5_ADDR_FBC_C_BASE                      (W5_REG_BASE + 0x0148)
+#define W5_ADDR_FBC_Y_OFFSET                    (W5_REG_BASE + 0x014C)
+#define W5_ADDR_FBC_C_OFFSET                    (W5_REG_BASE + 0x0150)
+
+/************************************************************************/
+/* DECODER - DEC_PIC                                                    */
+/************************************************************************/
+#define W5_CMD_DEC_VCORE_INFO                   (W5_REG_BASE + 0x0194)
+/* sequence change enable mask register
+ * CMD_SEQ_CHANGE_ENABLE_FLAG [5]   profile_idc
+ *                            [16]  pic_width/height_in_luma_sample
+ *                            [19]  sps_max_dec_pic_buffering, max_num_reorder, max_latency_increase
+ */
+#define W5_CMD_SEQ_CHANGE_ENABLE_FLAG           (W5_REG_BASE + 0x0128)
+#define W5_CMD_DEC_USER_MASK                    (W5_REG_BASE + 0x012C)
+#define W5_CMD_DEC_TEMPORAL_ID_PLUS1            (W5_REG_BASE + 0x0130)
+#define W5_CMD_DEC_FORCE_FB_LATENCY_PLUS1       (W5_REG_BASE + 0x0134)
+#define W5_USE_SEC_AXI                          (W5_REG_BASE + 0x0150)
+
+/************************************************************************/
+/* DECODER - QUERY : GET_VPU_INFO                                       */
+/************************************************************************/
+#define W5_RET_FW_VERSION                       (W5_REG_BASE + 0x0118)
+#define W5_RET_PRODUCT_NAME                     (W5_REG_BASE + 0x011C)
+#define W5_RET_PRODUCT_VERSION                  (W5_REG_BASE + 0x0120)
+#define W5_RET_STD_DEF0                         (W5_REG_BASE + 0x0124)
+#define W5_RET_STD_DEF1                         (W5_REG_BASE + 0x0128)
+#define W5_RET_CONF_FEATURE                     (W5_REG_BASE + 0x012C)
+#define W5_RET_CONF_DATE                        (W5_REG_BASE + 0x0130)
+#define W5_RET_CONF_REVISION                    (W5_REG_BASE + 0x0134)
+#define W5_RET_CONF_TYPE                        (W5_REG_BASE + 0x0138)
+#define W5_RET_PRODUCT_ID                       (W5_REG_BASE + 0x013C)
+#define W5_RET_CUSTOMER_ID                      (W5_REG_BASE + 0x0140)
+
+/************************************************************************/
+/* DECODER - QUERY : GET_RESULT                                         */
+/************************************************************************/
+#define W5_CMD_DEC_ADDR_REPORT_BASE         (W5_REG_BASE + 0x0114)
+#define W5_CMD_DEC_REPORT_SIZE              (W5_REG_BASE + 0x0118)
+#define W5_CMD_DEC_REPORT_PARAM             (W5_REG_BASE + 0x011C)
+
+#define W5_RET_DEC_BS_RD_PTR                (W5_REG_BASE + 0x011C)
+#define W5_RET_DEC_SEQ_PARAM                (W5_REG_BASE + 0x0120)
+#define W5_RET_DEC_COLOR_SAMPLE_INFO        (W5_REG_BASE + 0x0124)
+#define W5_RET_DEC_ASPECT_RATIO             (W5_REG_BASE + 0x0128)
+#define W5_RET_DEC_BIT_RATE                 (W5_REG_BASE + 0x012C)
+#define W5_RET_DEC_FRAME_RATE_NR            (W5_REG_BASE + 0x0130)
+#define W5_RET_DEC_FRAME_RATE_DR            (W5_REG_BASE + 0x0134)
+#define W5_RET_DEC_NUM_REQUIRED_FB          (W5_REG_BASE + 0x0138)
+#define W5_RET_DEC_NUM_REORDER_DELAY        (W5_REG_BASE + 0x013C)
+#define W5_RET_DEC_SUB_LAYER_INFO           (W5_REG_BASE + 0x0140)
+#define W5_RET_DEC_NOTIFICATION             (W5_REG_BASE + 0x0144)
+/*
+ * USER_DATA_FLAGS for HEVC/H264 only.
+ * Bits:
+ * [1] - User data buffer full boolean
+ * [2] - VUI parameter flag
+ * [4] - Pic_timing SEI flag
+ * [5] - 1st user_data_registed_itu_t_t35 prefix SEI flag
+ * [6] - user_data_unregistered prefix SEI flag
+ * [7] - 1st user_data_registed_itu_t_t35 suffix SEI flag
+ * [8] - user_data_unregistered suffix SEI flag
+ * [10]- mastering_display_color_volume prefix SEI flag
+ * [11]- chroma_resampling_display_color_volume prefix SEI flag
+ * [12]- knee_function_info SEI flag
+ * [13]- tone_mapping_info prefix SEI flag
+ * [14]- film_grain_characteristics_info prefix SEI flag
+ * [15]- content_light_level_info prefix SEI flag
+ * [16]- color_remapping_info prefix SEI flag
+ * [28]- 2nd user_data_registed_itu_t_t35 prefix SEI flag
+ * [29]- 3rd user_data_registed_itu_t_t35 prefix SEI flag
+ * [30]- 2nd user_data_registed_itu_t_t35 suffix SEI flag
+ * [31]- 3rd user_data_registed_itu_t_t35 suffix SEI flag
+ */
+#define W5_RET_DEC_USERDATA_IDC             (W5_REG_BASE + 0x0148)
+#define W5_RET_DEC_PIC_SIZE                 (W5_REG_BASE + 0x014C)
+#define W5_RET_DEC_CROP_TOP_BOTTOM          (W5_REG_BASE + 0x0150)
+#define W5_RET_DEC_CROP_LEFT_RIGHT          (W5_REG_BASE + 0x0154)
+/*
+ * #define W5_RET_DEC_AU_START_POS             (W5_REG_BASE + 0x0158)
+ * => Access unit (AU) Bitstream start position
+ * #define W5_RET_DEC_AU_END_POS               (W5_REG_BASE + 0x015C)
+ * => Access unit (AU) Bitstream end position
+ */
+
+/*
+ * Decoded picture type:
+ * reg_val & 0x7			=> picture type
+ * (reg_val >> 4) & 0x3f		=> VCL NAL unit type
+ * (reg_val >> 31) & 0x1		=> output_flag
+ * 16 << ((reg_val >> 10) & 0x3)	=> ctu_size
+ */
+#define W5_RET_DEC_PIC_TYPE                 (W5_REG_BASE + 0x0160)
+#define W5_RET_DEC_PIC_POC                  (W5_REG_BASE + 0x0164)
+/*
+ * #define W5_RET_DEC_RECOVERY_POINT           (W5_REG_BASE + 0x0168)
+ * => HEVC recovery point
+ * reg_val & 0xff => number of signed recovery picture order counts
+ * (reg_val >> 16) & 0x1 => exact match flag
+ * (reg_val >> 17) & 0x1 => broken link flag
+ * (reg_val >> 18) & 0x1 => exist flag
+ */
+#define W5_RET_DEC_DEBUG_INDEX              (W5_REG_BASE + 0x016C)
+#define W5_RET_DEC_DECODED_INDEX            (W5_REG_BASE + 0x0170)
+#define W5_RET_DEC_DISPLAY_INDEX            (W5_REG_BASE + 0x0174)
+/*
+ * #define W5_RET_DEC_REALLOC_INDEX            (W5_REG_BASE + 0x0178)
+ * => display picture index in decoded picture buffer
+ * reg_val & 0xf => display picture index for FBC buffer (by reordering)
+ */
+#define W5_RET_DEC_DISP_IDC                 (W5_REG_BASE + 0x017C)
+/*
+ * #define W5_RET_DEC_ERR_CTB_NUM              (W5_REG_BASE + 0x0180)
+ * => Number of error CTUs
+ * reg_val >> 16	=> erroneous CTUs in bitstream
+ * reg_val & 0xffff	=> total CTUs in bitstream
+ *
+ * #define W5_RET_DEC_PIC_PARAM                (W5_REG_BASE + 0x01A0)
+ * => Bitstream sequence/picture parameter information (AV1 only)
+ * reg_val & 0x1 => intrabc tool enable
+ * (reg_val >> 1) & 0x1 => screen content tools enable
+ */
+#define W5_RET_DEC_HOST_CMD_TICK            (W5_REG_BASE + 0x01B8)
+/*
+ * #define W5_RET_DEC_SEEK_START_TICK          (W5_REG_BASE + 0x01BC)
+ * #define W5_RET_DEC_SEEK_END_TICK            (W5_REG_BASE + 0x01C0)
+ * => Start and end ticks for seeking slices of the picture
+ * #define W5_RET_DEC_PARSING_START_TICK       (W5_REG_BASE + 0x01C4)
+ * #define W5_RET_DEC_PARSING_END_TICK         (W5_REG_BASE + 0x01C8)
+ * => Start and end ticks for parsing slices of the picture
+ * #define W5_RET_DEC_DECODING_START_TICK      (W5_REG_BASE + 0x01CC)
+ * => Start tick for decoding slices of the picture
+ */
+#define W5_RET_DEC_DECODING_ENC_TICK        (W5_REG_BASE + 0x01D0)
+#define W5_RET_DEC_WARN_INFO                (W5_REG_BASE + 0x01D4)
+#define W5_RET_DEC_ERR_INFO                 (W5_REG_BASE + 0x01D8)
+#define W5_RET_DEC_DECODING_SUCCESS         (W5_REG_BASE + 0x01DC)
+
+/************************************************************************/
+/* DECODER - FLUSH_INSTANCE                                             */
+/************************************************************************/
+#define W5_CMD_FLUSH_INST_OPT               (W5_REG_BASE + 0x104)
+
+/************************************************************************/
+/* DECODER - QUERY : UPDATE_DISP_FLAG                                   */
+/************************************************************************/
+#define W5_CMD_DEC_SET_DISP_IDC             (W5_REG_BASE + 0x0118)
+#define W5_CMD_DEC_CLR_DISP_IDC             (W5_REG_BASE + 0x011C)
+
+/************************************************************************/
+/* DECODER - QUERY : SET_BS_RD_PTR                                      */
+/************************************************************************/
+#define W5_RET_QUERY_DEC_SET_BS_RD_PTR      (W5_REG_BASE + 0x011C)
+
+/************************************************************************/
+/* DECODER - QUERY : GET_BS_RD_PTR                                      */
+/************************************************************************/
+#define W5_RET_QUERY_DEC_BS_RD_PTR          (W5_REG_BASE + 0x011C)
+
+/************************************************************************/
+/* QUERY : GET_DEBUG_INFO                                               */
+/************************************************************************/
+#define W5_RET_QUERY_DEBUG_PRI_REASON       (W5_REG_BASE + 0x114)
+
+/************************************************************************/
+/* GDI register for debugging                                           */
+/************************************************************************/
+#define W5_GDI_BASE                         0x8800
+#define W5_GDI_BUS_CTRL                     (W5_GDI_BASE + 0x0F0)
+#define W5_GDI_BUS_STATUS                   (W5_GDI_BASE + 0x0F4)
+
+#define W5_BACKBONE_BASE_VCPU               0xFE00
+#define W5_BACKBONE_BUS_CTRL_VCPU           (W5_BACKBONE_BASE_VCPU + 0x010)
+#define W5_BACKBONE_BUS_STATUS_VCPU         (W5_BACKBONE_BASE_VCPU + 0x014)
+#define W5_BACKBONE_PROG_AXI_ID             (W5_BACKBONE_BASE_VCPU + 0x00C)
+
+#define W5_BACKBONE_PROC_EXT_ADDR           (W5_BACKBONE_BASE_VCPU + 0x0C0)
+#define W5_BACKBONE_AXI_PARAM               (W5_BACKBONE_BASE_VCPU + 0x0E0)
+
+#define W5_BACKBONE_BASE_VCORE0             0x8E00
+#define W5_BACKBONE_BUS_CTRL_VCORE0         (W5_BACKBONE_BASE_VCORE0 + 0x010)
+#define W5_BACKBONE_BUS_STATUS_VCORE0       (W5_BACKBONE_BASE_VCORE0 + 0x014)
+
+#define W5_BACKBONE_BASE_VCORE1             0x9E00  // for dual-core product
+#define W5_BACKBONE_BUS_CTRL_VCORE1         (W5_BACKBONE_BASE_VCORE1 + 0x010)
+#define W5_BACKBONE_BUS_STATUS_VCORE1       (W5_BACKBONE_BASE_VCORE1 + 0x014)
+
+#define W5_COMBINED_BACKBONE_BASE           0xFE00
+#define W5_COMBINED_BACKBONE_BUS_CTRL       (W5_COMBINED_BACKBONE_BASE + 0x010)
+#define W5_COMBINED_BACKBONE_BUS_STATUS     (W5_COMBINED_BACKBONE_BASE + 0x014)
+
+/************************************************************************/
+/*                                                                      */
+/*               for  ENCODER                                           */
+/*                                                                      */
+/************************************************************************/
+#define W5_RET_STAGE3_INSTANCE_INFO             (W5_REG_BASE + 0x1F8)
+/************************************************************************/
+/* ENCODER - CREATE_INSTANCE                                            */
+/************************************************************************/
+// 0x114 ~ 0x124 : defined above (CREATE_INSTANCE COMMON)
+#define W5_CMD_ENC_VCORE_INFO                   (W5_REG_BASE + 0x0194)
+#define W5_CMD_ENC_SRC_OPTIONS                  (W5_REG_BASE + 0x0128)
+
+/************************************************************************/
+/* ENCODER - SET_FB                                                     */
+/************************************************************************/
+#define W5_FBC_STRIDE                           (W5_REG_BASE + 0x128)
+#define W5_ADDR_SUB_SAMPLED_FB_BASE             (W5_REG_BASE + 0x12C)
+#define W5_SUB_SAMPLED_ONE_FB_SIZE              (W5_REG_BASE + 0x130)
+
+/************************************************************************/
+/* ENCODER - ENC_SET_PARAM (COMMON & CHANGE_PARAM)                      */
+/************************************************************************/
+#define W5_CMD_ENC_SEQ_SET_PARAM_OPTION         (W5_REG_BASE + 0x104)
+#define W5_CMD_ENC_SEQ_SET_PARAM_ENABLE         (W5_REG_BASE + 0x118)
+#define W5_CMD_ENC_SEQ_SRC_SIZE                 (W5_REG_BASE + 0x11C)
+#define W5_CMD_ENC_SEQ_CUSTOM_MAP_ENDIAN        (W5_REG_BASE + 0x120)
+#define W5_CMD_ENC_SEQ_SPS_PARAM                (W5_REG_BASE + 0x124)
+#define W5_CMD_ENC_SEQ_PPS_PARAM                (W5_REG_BASE + 0x128)
+#define W5_CMD_ENC_SEQ_GOP_PARAM                (W5_REG_BASE + 0x12C)
+#define W5_CMD_ENC_SEQ_INTRA_PARAM              (W5_REG_BASE + 0x130)
+#define W5_CMD_ENC_SEQ_CONF_WIN_TOP_BOT         (W5_REG_BASE + 0x134)
+#define W5_CMD_ENC_SEQ_CONF_WIN_LEFT_RIGHT      (W5_REG_BASE + 0x138)
+#define W5_CMD_ENC_SEQ_RDO_PARAM                (W5_REG_BASE + 0x13C)
+#define W5_CMD_ENC_SEQ_INDEPENDENT_SLICE        (W5_REG_BASE + 0x140)
+#define W5_CMD_ENC_SEQ_DEPENDENT_SLICE          (W5_REG_BASE + 0x144)
+#define W5_CMD_ENC_SEQ_INTRA_REFRESH            (W5_REG_BASE + 0x148)
+#define W5_CMD_ENC_SEQ_INPUT_SRC_PARAM          (W5_REG_BASE + 0x14C)
+
+#define W5_CMD_ENC_SEQ_RC_FRAME_RATE            (W5_REG_BASE + 0x150)
+#define W5_CMD_ENC_SEQ_RC_TARGET_RATE           (W5_REG_BASE + 0x154)
+#define W5_CMD_ENC_SEQ_RC_PARAM                 (W5_REG_BASE + 0x158)
+#define W5_CMD_ENC_SEQ_RC_MIN_MAX_QP            (W5_REG_BASE + 0x15C)
+#define W5_CMD_ENC_SEQ_RC_BIT_RATIO_LAYER_0_3   (W5_REG_BASE + 0x160)
+#define W5_CMD_ENC_SEQ_RC_BIT_RATIO_LAYER_4_7   (W5_REG_BASE + 0x164)
+#define W5_CMD_ENC_SEQ_RC_INTER_MIN_MAX_QP      (W5_REG_BASE + 0x168)
+#define W5_CMD_ENC_SEQ_RC_WEIGHT_PARAM          (W5_REG_BASE + 0x16C)
+
+#define W5_CMD_ENC_SEQ_ROT_PARAM                (W5_REG_BASE + 0x170)
+#define W5_CMD_ENC_SEQ_NUM_UNITS_IN_TICK        (W5_REG_BASE + 0x174)
+#define W5_CMD_ENC_SEQ_TIME_SCALE               (W5_REG_BASE + 0x178)
+#define W5_CMD_ENC_SEQ_NUM_TICKS_POC_DIFF_ONE   (W5_REG_BASE + 0x17C)
+
+#define W5_CMD_ENC_SEQ_CUSTOM_MD_PU04           (W5_REG_BASE + 0x184)
+#define W5_CMD_ENC_SEQ_CUSTOM_MD_PU08           (W5_REG_BASE + 0x188)
+#define W5_CMD_ENC_SEQ_CUSTOM_MD_PU16           (W5_REG_BASE + 0x18C)
+#define W5_CMD_ENC_SEQ_CUSTOM_MD_PU32           (W5_REG_BASE + 0x190)
+#define W5_CMD_ENC_SEQ_CUSTOM_MD_CU08           (W5_REG_BASE + 0x194)
+#define W5_CMD_ENC_SEQ_CUSTOM_MD_CU16           (W5_REG_BASE + 0x198)
+#define W5_CMD_ENC_SEQ_CUSTOM_MD_CU32           (W5_REG_BASE + 0x19C)
+#define W5_CMD_ENC_SEQ_NR_PARAM                 (W5_REG_BASE + 0x1A0)
+#define W5_CMD_ENC_SEQ_NR_WEIGHT                (W5_REG_BASE + 0x1A4)
+#define W5_CMD_ENC_SEQ_BG_PARAM                 (W5_REG_BASE + 0x1A8)
+#define W5_CMD_ENC_SEQ_CUSTOM_LAMBDA_ADDR       (W5_REG_BASE + 0x1AC)
+#define W5_CMD_ENC_SEQ_USER_SCALING_LIST_ADDR   (W5_REG_BASE + 0x1B0)
+#define W5_CMD_ENC_SEQ_VUI_HRD_PARAM            (W5_REG_BASE + 0x180)
+#define W5_CMD_ENC_SEQ_VUI_RBSP_ADDR            (W5_REG_BASE + 0x1B8)
+#define W5_CMD_ENC_SEQ_HRD_RBSP_ADDR            (W5_REG_BASE + 0x1BC)
+
+/************************************************************************/
+/* ENCODER - ENC_SET_PARAM (CUSTOM_GOP)                                 */
+/************************************************************************/
+#define W5_CMD_ENC_CUSTOM_GOP_PARAM             (W5_REG_BASE + 0x11C)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_0       (W5_REG_BASE + 0x120)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_1       (W5_REG_BASE + 0x124)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_2       (W5_REG_BASE + 0x128)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_3       (W5_REG_BASE + 0x12C)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_4       (W5_REG_BASE + 0x130)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_5       (W5_REG_BASE + 0x134)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_6       (W5_REG_BASE + 0x138)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_7       (W5_REG_BASE + 0x13C)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_8       (W5_REG_BASE + 0x140)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_9       (W5_REG_BASE + 0x144)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_10      (W5_REG_BASE + 0x148)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_11      (W5_REG_BASE + 0x14C)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_12      (W5_REG_BASE + 0x150)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_13      (W5_REG_BASE + 0x154)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_14      (W5_REG_BASE + 0x158)
+#define W5_CMD_ENC_CUSTOM_GOP_PIC_PARAM_15      (W5_REG_BASE + 0x15C)
+
+/************************************************************************/
+/* ENCODER - ENC_PIC                                                    */
+/************************************************************************/
+#define W5_CMD_ENC_BS_START_ADDR                (W5_REG_BASE + 0x118)
+#define W5_CMD_ENC_BS_SIZE                      (W5_REG_BASE + 0x11C)
+#define W5_CMD_ENC_PIC_USE_SEC_AXI              (W5_REG_BASE + 0x124)
+#define W5_CMD_ENC_PIC_REPORT_PARAM             (W5_REG_BASE + 0x128)
+
+#define W5_CMD_ENC_PIC_CUSTOM_MAP_OPTION_PARAM  (W5_REG_BASE + 0x138)
+#define W5_CMD_ENC_PIC_CUSTOM_MAP_OPTION_ADDR   (W5_REG_BASE + 0x13C)
+#define W5_CMD_ENC_PIC_SRC_PIC_IDX              (W5_REG_BASE + 0x144)
+#define W5_CMD_ENC_PIC_SRC_ADDR_Y               (W5_REG_BASE + 0x148)
+#define W5_CMD_ENC_PIC_SRC_ADDR_U               (W5_REG_BASE + 0x14C)
+#define W5_CMD_ENC_PIC_SRC_ADDR_V               (W5_REG_BASE + 0x150)
+#define W5_CMD_ENC_PIC_SRC_STRIDE               (W5_REG_BASE + 0x154)
+#define W5_CMD_ENC_PIC_SRC_FORMAT               (W5_REG_BASE + 0x158)
+#define W5_CMD_ENC_PIC_SRC_AXI_SEL              (W5_REG_BASE + 0x160)
+#define W5_CMD_ENC_PIC_CODE_OPTION              (W5_REG_BASE + 0x164)
+#define W5_CMD_ENC_PIC_PIC_PARAM                (W5_REG_BASE + 0x168)
+#define W5_CMD_ENC_PIC_LONGTERM_PIC             (W5_REG_BASE + 0x16C)
+#define W5_CMD_ENC_PIC_WP_PIXEL_SIGMA_Y         (W5_REG_BASE + 0x170)
+#define W5_CMD_ENC_PIC_WP_PIXEL_SIGMA_C         (W5_REG_BASE + 0x174)
+#define W5_CMD_ENC_PIC_WP_PIXEL_MEAN_Y          (W5_REG_BASE + 0x178)
+#define W5_CMD_ENC_PIC_WP_PIXEL_MEAN_C          (W5_REG_BASE + 0x17C)
+#define W5_CMD_ENC_PIC_CF50_Y_OFFSET_TABLE_ADDR  (W5_REG_BASE + 0x190)
+#define W5_CMD_ENC_PIC_CF50_CB_OFFSET_TABLE_ADDR (W5_REG_BASE + 0x194)
+#define W5_CMD_ENC_PIC_CF50_CR_OFFSET_TABLE_ADDR (W5_REG_BASE + 0x198)
+#define W5_CMD_ENC_PIC_PREFIX_SEI_NAL_ADDR       (W5_REG_BASE + 0x180)
+#define W5_CMD_ENC_PIC_PREFIX_SEI_INFO           (W5_REG_BASE + 0x184)
+#define W5_CMD_ENC_PIC_SUFFIX_SEI_NAL_ADDR       (W5_REG_BASE + 0x188)
+#define W5_CMD_ENC_PIC_SUFFIX_SEI_INFO           (W5_REG_BASE + 0x18c)
+
+/************************************************************************/
+/* ENCODER - QUERY (GET_RESULT)                                         */
+/************************************************************************/
+#define W5_RET_ENC_NUM_REQUIRED_FB              (W5_REG_BASE + 0x11C)
+#define W5_RET_ENC_MIN_SRC_BUF_NUM              (W5_REG_BASE + 0x120)
+#define W5_RET_ENC_PIC_TYPE                     (W5_REG_BASE + 0x124)
+/*
+ * #define W5_RET_ENC_PIC_POC                      (W5_REG_BASE + 0x128)
+ * => picture order count value of current encoded picture
+ */
+#define W5_RET_ENC_PIC_IDX                      (W5_REG_BASE + 0x12C)
+/*
+ * #define W5_RET_ENC_PIC_SLICE_NUM                (W5_REG_BASE + 0x130)
+ * reg_val & 0xffff = total independent slice segment number (16 bits)
+ * (reg_val >> 16) & 0xffff = total dependent slice segment number (16 bits)
+ *
+ * #define W5_RET_ENC_PIC_SKIP                     (W5_REG_BASE + 0x134)
+ * reg_val & 0xfe = picture skip flag (7 bits)
+ *
+ * #define W5_RET_ENC_PIC_NUM_INTRA                (W5_REG_BASE + 0x138)
+ * => number of intra blocks in 8x8 (32 bits)
+ *
+ * #define W5_RET_ENC_PIC_NUM_MERGE                (W5_REG_BASE + 0x13C)
+ * => number of merge blocks in 8x8 (32 bits)
+ *
+ * #define W5_RET_ENC_PIC_NUM_SKIP                 (W5_REG_BASE + 0x144)
+ * => number of skip blocks in 8x8 (32 bits)
+ *
+ * #define W5_RET_ENC_PIC_AVG_CTU_QP               (W5_REG_BASE + 0x148)
+ * => Average CTU QP value (32 bits)
+ */
+#define W5_RET_ENC_PIC_BYTE                     (W5_REG_BASE + 0x14C)
+/*
+ * #define W5_RET_ENC_GOP_PIC_IDX                  (W5_REG_BASE + 0x150)
+ * => picture index in group of pictures
+ */
+#define W5_RET_ENC_USED_SRC_IDX                 (W5_REG_BASE + 0x154)
+/*
+ * #define W5_RET_ENC_PIC_NUM                      (W5_REG_BASE + 0x158)
+ * => encoded picture number
+ */
+#define W5_RET_ENC_VCL_NUT                      (W5_REG_BASE + 0x15C)
+/*
+ * Only for H264:
+ * #define W5_RET_ENC_PIC_DIST_LOW                 (W5_REG_BASE + 0x164)
+ * => lower 32 bits of the sum of squared difference between source Y picture
+ *    and reconstructed Y picture
+ * #define W5_RET_ENC_PIC_DIST_HIGH                (W5_REG_BASE + 0x168)
+ * => upper 32 bits of the sum of squared difference between source Y picture
+ *    and reconstructed Y picture
+ */
+#define W5_RET_ENC_PIC_MAX_LATENCY_PICS     (W5_REG_BASE + 0x16C)
+
+#define W5_RET_ENC_HOST_CMD_TICK                (W5_REG_BASE + 0x1B8)
+/*
+ * #define W5_RET_ENC_PREPARE_START_TICK           (W5_REG_BASE + 0x1BC)
+ * #define W5_RET_ENC_PREPARE_END_TICK             (W5_REG_BASE + 0x1C0)
+ * => Start and end ticks for preparing slices of the picture
+ * #define W5_RET_ENC_PROCESSING_START_TICK        (W5_REG_BASE + 0x1C4)
+ * #define W5_RET_ENC_PROCESSING_END_TICK          (W5_REG_BASE + 0x1C8)
+ * => Start and end ticks for processing slices of the picture
+ * #define W5_RET_ENC_ENCODING_START_TICK          (W5_REG_BASE + 0x1CC)
+ * => Start tick for encoding slices of the picture
+ */
+#define W5_RET_ENC_ENCODING_END_TICK            (W5_REG_BASE + 0x1D0)
+
+#define W5_RET_ENC_WARN_INFO                    (W5_REG_BASE + 0x1D4)
+#define W5_RET_ENC_ERR_INFO                     (W5_REG_BASE + 0x1D8)
+#define W5_RET_ENC_ENCODING_SUCCESS             (W5_REG_BASE + 0x1DC)
+
+/************************************************************************/
+/* ENCODER - QUERY (GET_BS_WR_PTR)                                      */
+/************************************************************************/
+#define W5_RET_ENC_RD_PTR                       (W5_REG_BASE + 0x114)
+#define W5_RET_ENC_WR_PTR                       (W5_REG_BASE + 0x118)
+#define W5_CMD_ENC_REASON_SEL                   (W5_REG_BASE + 0x11C)
+
+/************************************************************************/
+/* ENCODER - QUERY (GET_BW_REPORT)                                      */
+/************************************************************************/
+#define RET_QUERY_BW_PRP_AXI_READ               (W5_REG_BASE + 0x118)
+#define RET_QUERY_BW_PRP_AXI_WRITE              (W5_REG_BASE + 0x11C)
+#define RET_QUERY_BW_FBD_Y_AXI_READ             (W5_REG_BASE + 0x120)
+#define RET_QUERY_BW_FBC_Y_AXI_WRITE            (W5_REG_BASE + 0x124)
+#define RET_QUERY_BW_FBD_C_AXI_READ             (W5_REG_BASE + 0x128)
+#define RET_QUERY_BW_FBC_C_AXI_WRITE            (W5_REG_BASE + 0x12C)
+#define RET_QUERY_BW_PRI_AXI_READ               (W5_REG_BASE + 0x130)
+#define RET_QUERY_BW_PRI_AXI_WRITE              (W5_REG_BASE + 0x134)
+#define RET_QUERY_BW_SEC_AXI_READ               (W5_REG_BASE + 0x138)
+#define RET_QUERY_BW_SEC_AXI_WRITE              (W5_REG_BASE + 0x13C)
+#define RET_QUERY_BW_PROC_AXI_READ              (W5_REG_BASE + 0x140)
+#define RET_QUERY_BW_PROC_AXI_WRITE             (W5_REG_BASE + 0x144)
+#define RET_QUERY_BW_BWB_AXI_WRITE              (W5_REG_BASE + 0x148)
+#define W5_CMD_BW_OPTION                        (W5_REG_BASE + 0x14C)
+
+/************************************************************************/
+/* ENCODER - QUERY (GET_SRC_FLAG)                                       */
+/************************************************************************/
+#define W5_RET_RELEASED_SRC_INSTANCE            (W5_REG_BASE + 0x1EC)
+
+#define W5_ENC_PIC_SUB_FRAME_SYNC_IF            (W5_REG_BASE + 0x0300)
+
+#endif /* __WAVE5_REGISTER_DEFINE_H__ */
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vdi.c b/drivers/media/platform/chips-media/wave5/wave5-vdi.c
--- a/drivers/media/platform/chips-media/wave5/wave5-vdi.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-vdi.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Wave5 series multi-standard codec IP - low level access functions
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+
+#include <linux/bug.h>
+#include "wave5-vdi.h"
+#include "wave5-vpu.h"
+#include "wave5-regdefine.h"
+#include <linux/delay.h>
+
+#define VDI_SRAM_BASE_ADDR		0x00
+
+#define VDI_SYSTEM_ENDIAN		VDI_LITTLE_ENDIAN
+#define VDI_128BIT_BUS_SYSTEM_ENDIAN	VDI_128BIT_LITTLE_ENDIAN
+
+static int wave5_vdi_allocate_common_memory(struct device *dev)
+{
+	struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+
+	if (!vpu_dev->common_mem.vaddr) {
+		int ret;
+
+		vpu_dev->common_mem.size = SIZE_COMMON;
+		ret = wave5_vdi_allocate_dma_memory(vpu_dev, &vpu_dev->common_mem);
+		if (ret) {
+			dev_err(dev, "unable to allocate common buffer\n");
+			return ret;
+		}
+	}
+
+	dev_dbg(dev, "[VDI] common_mem: daddr=%pad size=%zu vaddr=0x%p\n",
+		&vpu_dev->common_mem.daddr, vpu_dev->common_mem.size, vpu_dev->common_mem.vaddr);
+
+	return 0;
+}
+
+int wave5_vdi_init(struct device *dev)
+{
+	struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+	int ret;
+
+	ret = wave5_vdi_allocate_common_memory(dev);
+	if (ret < 0) {
+		dev_err(dev, "[VDI] failed to get vpu common buffer from driver\n");
+		return ret;
+	}
+
+	if (!PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) {
+		WARN_ONCE(1, "unsupported product code: 0x%x\n", vpu_dev->product_code);
+		return 0;
+	}
+
+	// if BIT processor is not running.
+	if (wave5_vdi_readl(vpu_dev, W5_VCPU_CUR_PC) == 0) {
+		int i;
+
+		for (i = 0; i < 64; i++)
+			wave5_vdi_write_register(vpu_dev, (i * 4) + 0x100, 0x0);
+	}
+
+	dev_dbg(dev, "[VDI] driver initialized successfully\n");
+
+	return 0;
+}
+
+int wave5_vdi_release(struct device *dev)
+{
+	struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+
+	vpu_dev->vdb_register = NULL;
+	wave5_vdi_free_dma_memory(vpu_dev, &vpu_dev->common_mem);
+
+	return 0;
+}
+
+void wave5_vdi_write_register(struct vpu_device *vpu_dev, u32 addr, u32 data)
+{
+	writel(data, vpu_dev->vdb_register + addr);
+}
+
+unsigned int wave5_vdi_readl(struct vpu_device *vpu_dev, u32 addr)
+{
+	return readl(vpu_dev->vdb_register + addr);
+}
+
+int wave5_vdi_clear_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb)
+{
+	if (!vb || !vb->vaddr) {
+		dev_err(vpu_dev->dev, "%s: unable to clear unmapped buffer\n", __func__);
+		return -EINVAL;
+	}
+
+	memset(vb->vaddr, 0, vb->size);
+	return vb->size;
+}
+
+static void wave5_swap_endian(struct vpu_device *vpu_dev, u8 *data, size_t len,
+			      unsigned int endian);
+
+int wave5_vdi_write_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb, size_t offset,
+			   u8 *data, size_t len, unsigned int endian)
+{
+	if (!vb || !vb->vaddr) {
+		dev_err(vpu_dev->dev, "%s: unable to write to unmapped buffer\n", __func__);
+		return -EINVAL;
+	}
+
+	if (offset > vb->size || len > vb->size || offset + len > vb->size) {
+		dev_err(vpu_dev->dev, "%s: buffer too small\n", __func__);
+		return -ENOSPC;
+	}
+
+	wave5_swap_endian(vpu_dev, data, len, endian);
+	memcpy(vb->vaddr + offset, data, len);
+
+	return len;
+}
+
+int wave5_vdi_allocate_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb)
+{
+	void *vaddr;
+	dma_addr_t daddr;
+
+	if (!vb->size) {
+		dev_err(vpu_dev->dev, "%s: requested size==0\n", __func__);
+		return -EINVAL;
+	}
+
+	vaddr = dma_alloc_coherent(vpu_dev->dev, vb->size, &daddr, GFP_KERNEL);
+	if (!vaddr)
+		return -ENOMEM;
+	vb->vaddr = vaddr;
+	vb->daddr = daddr;
+
+	return 0;
+}
+
+void wave5_vdi_free_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb)
+{
+	if (vb->size == 0)
+		return;
+
+	if (!vb->vaddr)
+		dev_err(vpu_dev->dev, "%s: requested free of unmapped buffer\n", __func__);
+	else
+		dma_free_coherent(vpu_dev->dev, vb->size, vb->vaddr, vb->daddr);
+
+	memset(vb, 0, sizeof(*vb));
+}
+
+void wave5_vdi_allocate_sram(struct vpu_device *vpu_dev)
+{
+	struct vpu_buf *vb = &vpu_dev->sram_buf;
+
+	if (!vpu_dev->sram_pool || !vpu_dev->sram_size)
+		return;
+
+	if (!vb->vaddr) {
+		vb->size = vpu_dev->sram_size;
+		vb->vaddr = gen_pool_dma_alloc(vpu_dev->sram_pool, vb->size,
+					       &vb->daddr);
+		if (!vb->vaddr)
+			vb->size = 0;
+	}
+
+	dev_dbg(vpu_dev->dev, "%s: sram daddr: %pad, size: %zu, vaddr: 0x%p\n",
+		__func__, &vb->daddr, vb->size, vb->vaddr);
+}
+
+void wave5_vdi_free_sram(struct vpu_device *vpu_dev)
+{
+	struct vpu_buf *vb = &vpu_dev->sram_buf;
+
+	if (!vb->size || !vb->vaddr)
+		return;
+
+	if (vb->vaddr)
+		gen_pool_free(vpu_dev->sram_pool, (unsigned long)vb->vaddr,
+			      vb->size);
+
+	memset(vb, 0, sizeof(*vb));
+}
+
+unsigned int wave5_vdi_convert_endian(struct vpu_device *vpu_dev, unsigned int endian)
+{
+	if (PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) {
+		switch (endian) {
+		case VDI_LITTLE_ENDIAN:
+			endian = 0x00;
+			break;
+		case VDI_BIG_ENDIAN:
+			endian = 0x0f;
+			break;
+		case VDI_32BIT_LITTLE_ENDIAN:
+			endian = 0x04;
+			break;
+		case VDI_32BIT_BIG_ENDIAN:
+			endian = 0x03;
+			break;
+		}
+	}
+
+	return (endian & 0x0f);
+}
+
+static void byte_swap(unsigned char *data, size_t len)
+{
+	unsigned int i;
+
+	for (i = 0; i < len; i += 2)
+		swap(data[i], data[i + 1]);
+}
+
+static void word_swap(unsigned char *data, size_t len)
+{
+	u16 *ptr = (u16 *)data;
+	unsigned int i;
+	size_t size = len / sizeof(uint16_t);
+
+	for (i = 0; i < size; i += 2)
+		swap(ptr[i], ptr[i + 1]);
+}
+
+static void dword_swap(unsigned char *data, size_t len)
+{
+	u32 *ptr = (u32 *)data;
+	size_t size = len / sizeof(u32);
+	unsigned int i;
+
+	for (i = 0; i < size; i += 2)
+		swap(ptr[i], ptr[i + 1]);
+}
+
+static void lword_swap(unsigned char *data, size_t len)
+{
+	u64 *ptr = (u64 *)data;
+	size_t size = len / sizeof(uint64_t);
+	unsigned int i;
+
+	for (i = 0; i < size; i += 2)
+		swap(ptr[i], ptr[i + 1]);
+}
+
+static void wave5_swap_endian(struct vpu_device *vpu_dev, u8 *data, size_t len,
+			      unsigned int endian)
+{
+	int changes;
+	unsigned int sys_endian = VDI_128BIT_BUS_SYSTEM_ENDIAN;
+	bool byte_change, word_change, dword_change, lword_change;
+
+	if (!PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) {
+		dev_err(vpu_dev->dev, "unknown product id: %08x\n", vpu_dev->product_code);
+		return;
+	}
+
+	endian = wave5_vdi_convert_endian(vpu_dev, endian);
+	sys_endian = wave5_vdi_convert_endian(vpu_dev, sys_endian);
+	if (endian == sys_endian)
+		return;
+
+	changes = endian ^ sys_endian;
+	byte_change = changes & 0x01;
+	word_change = ((changes & 0x02) == 0x02);
+	dword_change = ((changes & 0x04) == 0x04);
+	lword_change = ((changes & 0x08) == 0x08);
+
+	if (byte_change)
+		byte_swap(data, len);
+	if (word_change)
+		word_swap(data, len);
+	if (dword_change)
+		dword_swap(data, len);
+	if (lword_change)
+		lword_swap(data, len);
+}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vdi.h b/drivers/media/platform/chips-media/wave5/wave5-vdi.h
--- a/drivers/media/platform/chips-media/wave5/wave5-vdi.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-vdi.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave5 series multi-standard codec IP - low level access functions
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+
+#ifndef _VDI_H_
+#define _VDI_H_
+
+#include "wave5-vpuconfig.h"
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+
+/************************************************************************/
+/* COMMON REGISTERS */
+/************************************************************************/
+#define VPU_PRODUCT_CODE_REGISTER 0x1044
+
+/* system register write */
+#define vpu_write_reg(VPU_INST, ADDR, DATA) wave5_vdi_write_register(VPU_INST, ADDR, DATA)
+/* system register read */
+#define vpu_read_reg(CORE, ADDR) wave5_vdi_readl(CORE, ADDR)
+
+struct vpu_buf {
+	size_t size;
+	dma_addr_t daddr;
+	void *vaddr;
+};
+
+enum endian_mode {
+	VDI_LITTLE_ENDIAN = 0, /* 64bit LE */
+	VDI_BIG_ENDIAN, /* 64bit BE */
+	VDI_32BIT_LITTLE_ENDIAN,
+	VDI_32BIT_BIG_ENDIAN,
+	/* WAVE PRODUCTS */
+	VDI_128BIT_LITTLE_ENDIAN = 16,
+	VDI_128BIT_LE_BYTE_SWAP,
+	VDI_128BIT_LE_WORD_SWAP,
+	VDI_128BIT_LE_WORD_BYTE_SWAP,
+	VDI_128BIT_LE_DWORD_SWAP,
+	VDI_128BIT_LE_DWORD_BYTE_SWAP,
+	VDI_128BIT_LE_DWORD_WORD_SWAP,
+	VDI_128BIT_LE_DWORD_WORD_BYTE_SWAP,
+	VDI_128BIT_BE_DWORD_WORD_BYTE_SWAP,
+	VDI_128BIT_BE_DWORD_WORD_SWAP,
+	VDI_128BIT_BE_DWORD_BYTE_SWAP,
+	VDI_128BIT_BE_DWORD_SWAP,
+	VDI_128BIT_BE_WORD_BYTE_SWAP,
+	VDI_128BIT_BE_WORD_SWAP,
+	VDI_128BIT_BE_BYTE_SWAP,
+	VDI_128BIT_BIG_ENDIAN = 31,
+	VDI_ENDIAN_MAX
+};
+
+#define VDI_128BIT_ENDIAN_MASK 0xf
+
+int wave5_vdi_init(struct device *dev);
+int wave5_vdi_release(struct device *dev);	//this function may be called only at system off.
+
+#endif //#ifndef _VDI_H_
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c
--- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,1041 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Wave5 series multi-standard codec IP - helper functions
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+
+#include <linux/bug.h>
+#include <linux/pm_runtime.h>
+#include "wave5-vpuapi.h"
+#include "wave5-regdefine.h"
+#include "wave5.h"
+
+#define DECODE_ALL_TEMPORAL_LAYERS 0
+#define DECODE_ALL_SPATIAL_LAYERS 0
+
+void wave5_vpu_clear_interrupt_ex(struct vpu_instance *inst, u32 intr_flag)
+{
+	wave5_vpu_clear_interrupt(inst, intr_flag);
+}
+
+static int wave5_initialize_vpu(struct device *dev, u8 *code, size_t size)
+{
+	int ret;
+	struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	if (wave5_vpu_is_init(vpu_dev)) {
+		wave5_vpu_re_init(dev, (void *)code, size);
+		ret = -EBUSY;
+		goto err_out;
+	}
+
+	ret = wave5_vpu_reset(dev, SW_RESET_ON_BOOT);
+	if (ret)
+		goto err_out;
+
+	ret = wave5_vpu_init(dev, (void *)code, size);
+
+err_out:
+	mutex_unlock(&vpu_dev->hw_lock);
+	return ret;
+}
+
+int wave5_vpu_init_with_bitcode(struct device *dev, u8 *bitcode, size_t size)
+{
+	if (!bitcode || size == 0)
+		return -EINVAL;
+
+	return wave5_initialize_vpu(dev, bitcode, size);
+}
+
+int wave5_vpu_get_version_info(struct device *dev, u32 *revision, unsigned int *product_id)
+{
+	int ret;
+	struct vpu_device *vpu_dev = dev_get_drvdata(dev);
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	if (!wave5_vpu_is_init(vpu_dev)) {
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	if (product_id)
+		*product_id = vpu_dev->product;
+	ret = wave5_vpu_get_version(vpu_dev, revision);
+
+err_out:
+	mutex_unlock(&vpu_dev->hw_lock);
+	return ret;
+}
+
+static int wave5_check_dec_open_param(struct vpu_instance *inst, struct dec_open_param *param)
+{
+	struct vpu_attr *p_attr = &inst->dev->attr;
+
+	if (inst->id >= MAX_NUM_INSTANCE) {
+		dev_err(inst->dev->dev, "Too many simultaneous instances: %d (max: %u)\n",
+			inst->id, MAX_NUM_INSTANCE);
+		return -EOPNOTSUPP;
+	}
+
+	if (param->bitstream_buffer % 8) {
+		dev_err(inst->dev->dev,
+			"Bitstream buffer must be aligned to a multiple of 8\n");
+		return -EINVAL;
+	}
+
+	if (param->bitstream_mode == BS_MODE_INTERRUPT &&
+	    (param->bitstream_buffer_size % 1024 ||
+	     param->bitstream_buffer_size < MIN_BITSTREAM_BUFFER_SIZE)) {
+		dev_err(inst->dev->dev,
+			"Bitstream buffer size must be aligned to a multiple of 1024 and have a minimum size of %d\n",
+			MIN_BITSTREAM_BUFFER_SIZE);
+		return -EINVAL;
+	}
+
+	if (!(BIT(param->bitstream_mode) && p_attr->support_bitstream_mode)) {
+		dev_err(inst->dev->dev,
+			"Bitstream mode only configurable with the 'support_bitstream_mode' flag");
+		return -EINVAL;
+	}
+
+	if (!(BIT(param->frame_endian) && p_attr->support_endian_mask)) {
+		dev_err(inst->dev->dev,
+			"Frame endianness only configurable with the 'support_endian_mask' flag");
+		return -EINVAL;
+	}
+
+	if (!(BIT(param->stream_endian) && p_attr->support_endian_mask)) {
+		dev_err(inst->dev->dev,
+			"Stream endianness only configurable with the 'support_endian_mask' flag");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int wave5_vpu_dec_open(struct vpu_instance *inst, struct dec_open_param *open_param)
+{
+	struct dec_info *p_dec_info;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+	dma_addr_t buffer_addr;
+	size_t buffer_size;
+
+	ret = wave5_check_dec_open_param(inst, open_param);
+	if (ret)
+		return ret;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	if (!wave5_vpu_is_init(vpu_dev)) {
+		mutex_unlock(&vpu_dev->hw_lock);
+		return -ENODEV;
+	}
+
+	inst->codec_info = kzalloc(sizeof(*inst->codec_info), GFP_KERNEL);
+	if (!inst->codec_info) {
+		mutex_unlock(&vpu_dev->hw_lock);
+		return -ENOMEM;
+	}
+
+	p_dec_info = &inst->codec_info->dec_info;
+	memcpy(&p_dec_info->open_param, open_param, sizeof(struct dec_open_param));
+
+	buffer_addr = open_param->bitstream_buffer;
+	buffer_size = open_param->bitstream_buffer_size;
+	p_dec_info->stream_wr_ptr = buffer_addr;
+	p_dec_info->stream_rd_ptr = buffer_addr;
+	p_dec_info->stream_buf_start_addr = buffer_addr;
+	p_dec_info->stream_buf_size = buffer_size;
+	p_dec_info->stream_buf_end_addr = buffer_addr + buffer_size;
+	p_dec_info->reorder_enable = TRUE;
+	p_dec_info->mirror_direction = MIRDIR_NONE;
+	p_dec_info->temp_id_select_mode = TEMPORAL_ID_MODE_ABSOLUTE;
+	p_dec_info->target_temp_id = DECODE_ALL_TEMPORAL_LAYERS;
+	p_dec_info->target_spatial_id = DECODE_ALL_SPATIAL_LAYERS;
+
+	ret = wave5_vpu_build_up_dec_param(inst, open_param);
+	if (ret)
+		goto free_codec_info;
+
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return 0;
+
+free_codec_info:
+	kfree(inst->codec_info);
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_dec_close(struct vpu_instance *inst, u32 *fail_res)
+{
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+	int i;
+
+	*fail_res = 0;
+	if (!inst->codec_info)
+		return -EINVAL;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	ret = wave5_vpu_dec_finish_seq(inst, fail_res);
+	if (ret) {
+		dev_warn(inst->dev->dev, "dec_finish_seq timed out\n");
+
+		if (*fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING) {
+			mutex_unlock(&vpu_dev->hw_lock);
+			return ret;
+		}
+	}
+
+	dev_dbg(inst->dev->dev, "%s: dec_finish_seq complete\n", __func__);
+
+	if (p_dec_info->vb_work.size)
+		wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_work);
+
+	for (i = 0 ; i < MAX_REG_FRAME; i++) {
+		if (p_dec_info->vb_mv[i].size)
+			wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_mv[i]);
+		if (p_dec_info->vb_fbc_y_tbl[i].size)
+			wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_fbc_y_tbl[i]);
+		if (p_dec_info->vb_fbc_c_tbl[i].size)
+			wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_fbc_c_tbl[i]);
+	}
+
+	if (p_dec_info->vb_task.size)
+		wave5_vdi_free_dma_memory(vpu_dev, &p_dec_info->vb_task);
+
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	kfree(inst->codec_info);
+
+	return 0;
+}
+
+int wave5_vpu_dec_issue_seq_init(struct vpu_instance *inst)
+{
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	ret = wave5_vpu_dec_init_seq(inst);
+
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_dec_complete_seq_init(struct vpu_instance *inst, struct dec_initial_info *info)
+{
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	ret = wave5_vpu_dec_get_seq_info(inst, info);
+	if (!ret)
+		p_dec_info->initial_info_obtained = true;
+
+	info->rd_ptr = wave5_vpu_dec_get_rd_ptr(inst);
+	info->wr_ptr = p_dec_info->stream_wr_ptr;
+
+	p_dec_info->initial_info = *info;
+
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_dec_register_frame_buffer_ex(struct vpu_instance *inst, int num_of_decoding_fbs,
+					   int num_of_display_fbs, int stride, int height,
+					   int map_type)
+{
+	struct dec_info *p_dec_info;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+	struct frame_buffer *fb;
+
+	if (num_of_decoding_fbs >= WAVE5_MAX_FBS || num_of_display_fbs >= WAVE5_MAX_FBS)
+		return -EINVAL;
+
+	p_dec_info = &inst->codec_info->dec_info;
+	p_dec_info->num_of_decoding_fbs = num_of_decoding_fbs;
+	p_dec_info->num_of_display_fbs = num_of_display_fbs;
+	p_dec_info->stride = stride;
+
+	if (!p_dec_info->initial_info_obtained)
+		return -EINVAL;
+
+	if (stride < p_dec_info->initial_info.pic_width || (stride % 8 != 0) ||
+	    height < p_dec_info->initial_info.pic_height)
+		return -EINVAL;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	fb = inst->frame_buf;
+	ret = wave5_vpu_dec_register_framebuffer(inst, &fb[p_dec_info->num_of_decoding_fbs],
+						 LINEAR_FRAME_MAP, p_dec_info->num_of_display_fbs);
+	if (ret)
+		goto err_out;
+
+	ret = wave5_vpu_dec_register_framebuffer(inst, &fb[0], COMPRESSED_FRAME_MAP,
+						 p_dec_info->num_of_decoding_fbs);
+
+err_out:
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_dec_get_bitstream_buffer(struct vpu_instance *inst, dma_addr_t *prd_ptr,
+				       dma_addr_t *pwr_ptr, size_t *size)
+{
+	struct dec_info *p_dec_info;
+	dma_addr_t rd_ptr;
+	dma_addr_t wr_ptr;
+	int room;
+	struct vpu_device *vpu_dev = inst->dev;
+	int ret;
+
+	p_dec_info = &inst->codec_info->dec_info;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+	rd_ptr = wave5_vpu_dec_get_rd_ptr(inst);
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	wr_ptr = p_dec_info->stream_wr_ptr;
+
+	if (p_dec_info->open_param.bitstream_mode != BS_MODE_PIC_END) {
+		if (wr_ptr < rd_ptr)
+			room = rd_ptr - wr_ptr;
+		else
+			room = (p_dec_info->stream_buf_end_addr - wr_ptr) +
+				(rd_ptr - p_dec_info->stream_buf_start_addr);
+		room--;
+	} else {
+		room = (p_dec_info->stream_buf_end_addr - wr_ptr);
+	}
+
+	if (prd_ptr)
+		*prd_ptr = rd_ptr;
+	if (pwr_ptr)
+		*pwr_ptr = wr_ptr;
+	if (size)
+		*size = room;
+
+	return 0;
+}
+
+int wave5_vpu_dec_update_bitstream_buffer(struct vpu_instance *inst, size_t size)
+{
+	struct dec_info *p_dec_info;
+	dma_addr_t wr_ptr;
+	dma_addr_t rd_ptr;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	if (!inst->codec_info)
+		return -EINVAL;
+
+	p_dec_info = &inst->codec_info->dec_info;
+	wr_ptr = p_dec_info->stream_wr_ptr;
+	rd_ptr = p_dec_info->stream_rd_ptr;
+
+	if (size > 0) {
+		if (wr_ptr < rd_ptr && rd_ptr <= wr_ptr + size)
+			return -EINVAL;
+
+		wr_ptr += size;
+
+		if (p_dec_info->open_param.bitstream_mode != BS_MODE_PIC_END) {
+			if (wr_ptr > p_dec_info->stream_buf_end_addr) {
+				u32 room = wr_ptr - p_dec_info->stream_buf_end_addr;
+
+				wr_ptr = p_dec_info->stream_buf_start_addr;
+				wr_ptr += room;
+			} else if (wr_ptr == p_dec_info->stream_buf_end_addr) {
+				wr_ptr = p_dec_info->stream_buf_start_addr;
+			}
+		}
+
+		p_dec_info->stream_wr_ptr = wr_ptr;
+		p_dec_info->stream_rd_ptr = rd_ptr;
+	}
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+	ret = wave5_vpu_dec_set_bitstream_flag(inst, (size == 0));
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_dec_start_one_frame(struct vpu_instance *inst, struct dec_param *param, u32 *res_fail)
+{
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	if (p_dec_info->stride == 0) // this means frame buffers have not been registered.
+		return -EINVAL;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	ret = wave5_vpu_decode(inst, param, res_fail);
+
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_dec_set_rd_ptr(struct vpu_instance *inst, dma_addr_t addr, int update_wr_ptr)
+{
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	ret = wave5_dec_set_rd_ptr(inst, addr);
+
+	p_dec_info->stream_rd_ptr = addr;
+	if (update_wr_ptr)
+		p_dec_info->stream_wr_ptr = addr;
+
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_dec_get_output_info(struct vpu_instance *inst, struct dec_output_info *info)
+{
+	struct dec_info *p_dec_info;
+	int ret;
+	struct vpu_rect rect_info;
+	u32 val;
+	u32 decoded_index;
+	u32 disp_idx;
+	u32 max_dec_index;
+	struct vpu_device *vpu_dev = inst->dev;
+	struct dec_output_info *disp_info;
+
+	if (!info)
+		return -EINVAL;
+
+	p_dec_info = &inst->codec_info->dec_info;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	memset(info, 0, sizeof(*info));
+
+	ret = wave5_vpu_dec_get_result(inst, info);
+	if (ret) {
+		info->rd_ptr = p_dec_info->stream_rd_ptr;
+		info->wr_ptr = p_dec_info->stream_wr_ptr;
+		goto err_out;
+	}
+
+	decoded_index = info->index_frame_decoded;
+
+	// calculate display frame region
+	val = 0;
+	//default value
+	rect_info.left = 0;
+	rect_info.right = 0;
+	rect_info.top = 0;
+	rect_info.bottom = 0;
+	if (decoded_index < WAVE5_MAX_FBS) {
+		if (inst->std == W_HEVC_DEC || inst->std == W_AVC_DEC)
+			rect_info = p_dec_info->initial_info.pic_crop_rect;
+
+		if (inst->std == W_HEVC_DEC)
+			p_dec_info->dec_out_info[decoded_index].decoded_poc = info->decoded_poc;
+
+		if (inst->std == W_AVS2_DEC)
+			p_dec_info->dec_out_info[decoded_index].avs2_info.decoded_poi =
+				info->avs2_info.decoded_poi;
+
+		p_dec_info->dec_out_info[decoded_index].rc_decoded = rect_info;
+	}
+	info->rc_decoded = rect_info;
+
+	disp_idx = info->index_frame_display;
+	disp_info = &p_dec_info->dec_out_info[disp_idx];
+	if (info->index_frame_display >= 0 && info->index_frame_display < WAVE5_MAX_FBS) {
+		u32 width = info->dec_pic_width;
+		u32 height = info->dec_pic_height;
+
+		if (info->index_frame_display != info->index_frame_decoded) {
+			/*
+			 * when index_frame_decoded < 0, and index_frame_display >= 0
+			 * info->dec_pic_width and info->dec_pic_height are still valid
+			 * but those of p_dec_info->dec_out_info[disp_idx] are invalid in VP9
+			 */
+			width = disp_info->dec_pic_width;
+			height = disp_info->dec_pic_height;
+		}
+		// TODO no rotation/mirror v4l2 cmd implemented for the decoder
+		if (p_dec_info->rotation_enable || p_dec_info->mirror_enable)
+			if (p_dec_info->rotation_angle == 90 || p_dec_info->rotation_angle == 270)
+				swap(width, height);
+
+		if (p_dec_info->rotation_enable) {
+			switch (p_dec_info->rotation_angle) {
+			case 90:
+				info->rc_display.left = disp_info->rc_decoded.top;
+				info->rc_display.right = disp_info->rc_decoded.bottom;
+				info->rc_display.top = disp_info->rc_decoded.right;
+				info->rc_display.bottom = disp_info->rc_decoded.left;
+				break;
+			case 270:
+				info->rc_display.left = disp_info->rc_decoded.bottom;
+				info->rc_display.right = disp_info->rc_decoded.top;
+				info->rc_display.top = disp_info->rc_decoded.left;
+				info->rc_display.bottom = disp_info->rc_decoded.right;
+				break;
+			case 180:
+				info->rc_display.left = disp_info->rc_decoded.right;
+				info->rc_display.right = disp_info->rc_decoded.left;
+				info->rc_display.top = disp_info->rc_decoded.bottom;
+				info->rc_display.bottom = disp_info->rc_decoded.top;
+				break;
+			default:
+				info->rc_display = disp_info->rc_decoded;
+				break;
+			}
+		} else {
+			info->rc_display = disp_info->rc_decoded;
+		}
+
+		if (p_dec_info->mirror_enable) {
+			if (p_dec_info->mirror_direction & MIRDIR_VER)
+				swap(info->rc_display.top, info->rc_display.bottom);
+			if (p_dec_info->mirror_direction & MIRDIR_HOR)
+				swap(info->rc_display.left, info->rc_display.right);
+		}
+
+		switch (inst->std) {
+		case W_AVS2_DEC:
+			info->avs2_info.display_poi =
+				disp_info->avs2_info.decoded_poi;
+			break;
+		default:
+			break;
+		}
+
+		info->disp_pic_width = width;
+		info->disp_pic_height = height;
+	} else {
+		info->rc_display.left = 0;
+		info->rc_display.right = 0;
+		info->rc_display.top = 0;
+		info->rc_display.bottom = 0;
+
+		if (p_dec_info->rotation_enable || p_dec_info->mirror_enable ||
+		    p_dec_info->dering_enable) {
+			info->disp_pic_width = info->dec_pic_width;
+			info->disp_pic_height = info->dec_pic_height;
+		} else {
+			info->disp_pic_width = 0;
+			info->disp_pic_height = 0;
+		}
+	}
+
+	p_dec_info->stream_rd_ptr = wave5_vpu_dec_get_rd_ptr(inst);
+	p_dec_info->frame_display_flag = vpu_read_reg(vpu_dev, W5_RET_DEC_DISP_IDC);
+	if (inst->std == W_VP9_DEC)
+		p_dec_info->frame_display_flag &= 0xFFFF;
+
+	if (p_dec_info->dering_enable || p_dec_info->mirror_enable || p_dec_info->rotation_enable) {
+		info->disp_frame = p_dec_info->rotator_output;
+		info->disp_frame.stride = p_dec_info->rotator_stride;
+	} else {
+		val = p_dec_info->num_of_decoding_fbs; //fb_offset
+
+		max_dec_index = (p_dec_info->num_of_decoding_fbs > p_dec_info->num_of_display_fbs) ?
+			p_dec_info->num_of_decoding_fbs : p_dec_info->num_of_display_fbs;
+
+		if (info->index_frame_display >= 0 &&
+		    info->index_frame_display < (int)max_dec_index)
+			info->disp_frame = inst->frame_buf[val + info->index_frame_display];
+	}
+
+	info->rd_ptr = p_dec_info->stream_rd_ptr;
+	info->wr_ptr = p_dec_info->stream_wr_ptr;
+	info->frame_display_flag = p_dec_info->frame_display_flag;
+
+	info->sequence_no = p_dec_info->initial_info.sequence_no;
+	if (decoded_index < WAVE5_MAX_FBS)
+		p_dec_info->dec_out_info[decoded_index] = *info;
+
+	if (disp_idx < WAVE5_MAX_FBS)
+		info->disp_frame.sequence_no = info->sequence_no;
+
+	if (info->sequence_changed &&
+	    !(info->sequence_changed & SEQ_CHANGE_INTER_RES_CHANGE)) {
+		memcpy((void *)&p_dec_info->initial_info, (void *)&p_dec_info->new_seq_info,
+		       sizeof(struct dec_initial_info));
+		p_dec_info->initial_info.sequence_no++;
+	}
+
+err_out:
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_dec_clr_disp_flag(struct vpu_instance *inst, int index)
+{
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	int ret = 0;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	if (index >= p_dec_info->num_of_display_fbs)
+		return -EINVAL;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+	ret = wave5_dec_clr_disp_flag(inst, index);
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_dec_set_disp_flag(struct vpu_instance *inst, int index)
+{
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+	int ret = 0;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	if (index >= p_dec_info->num_of_display_fbs)
+		return -EINVAL;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+	ret = wave5_dec_set_disp_flag(inst, index);
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_dec_give_command(struct vpu_instance *inst, enum codec_command cmd, void *parameter)
+{
+	struct dec_info *p_dec_info = &inst->codec_info->dec_info;
+
+	switch (cmd) {
+	case DEC_GET_QUEUE_STATUS: {
+		struct queue_status_info *queue_info = parameter;
+
+		queue_info->instance_queue_count = p_dec_info->instance_queue_count;
+		queue_info->report_queue_count = p_dec_info->report_queue_count;
+		break;
+	}
+	case ENABLE_DEC_THUMBNAIL_MODE:
+		p_dec_info->thumbnail_mode = true;
+		break;
+	case DEC_RESET_FRAMEBUF_INFO: {
+		int i;
+
+		for (i = 0; i < inst->dst_buf_count; i++) {
+			wave5_vdi_free_dma_memory(inst->dev, &inst->frame_vbuf[i]);
+			wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_mv[i]);
+			wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_fbc_y_tbl[i]);
+			wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_fbc_c_tbl[i]);
+		}
+
+		wave5_vdi_free_dma_memory(inst->dev, &p_dec_info->vb_task);
+		break;
+	}
+	case DEC_GET_SEQ_INFO: {
+		struct dec_initial_info *seq_info = parameter;
+
+		*seq_info = p_dec_info->initial_info;
+		break;
+	}
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int wave5_vpu_enc_open(struct vpu_instance *inst, struct enc_open_param *open_param)
+{
+	struct enc_info *p_enc_info;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	ret = wave5_vpu_enc_check_open_param(inst, open_param);
+	if (ret)
+		return ret;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	if (!wave5_vpu_is_init(vpu_dev)) {
+		mutex_unlock(&vpu_dev->hw_lock);
+		return -ENODEV;
+	}
+
+	inst->codec_info = kzalloc(sizeof(*inst->codec_info), GFP_KERNEL);
+	if (!inst->codec_info) {
+		mutex_unlock(&vpu_dev->hw_lock);
+		return -ENOMEM;
+	}
+
+	p_enc_info = &inst->codec_info->enc_info;
+	p_enc_info->open_param = *open_param;
+
+	ret = wave5_vpu_build_up_enc_param(vpu_dev->dev, inst, open_param);
+	if (ret)
+		goto free_codec_info;
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return 0;
+
+free_codec_info:
+	kfree(inst->codec_info);
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_enc_close(struct vpu_instance *inst, u32 *fail_res)
+{
+	struct enc_info *p_enc_info;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+	*fail_res = 0;
+
+	if (!inst->codec_info)
+		return -EINVAL;
+	p_enc_info = &inst->codec_info->enc_info;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	ret = wave5_vpu_enc_finish_seq(inst, fail_res);
+	if (ret) {
+		dev_warn(inst->dev->dev, "enc seq end timed out\n");
+
+		if (*fail_res == WAVE5_SYSERR_VPU_STILL_RUNNING) {
+			mutex_unlock(&vpu_dev->hw_lock);
+			return ret;
+		}
+	}
+
+	dev_dbg(inst->dev->dev, "%s: enc seq end timed out\n", __func__);
+
+	if (p_enc_info->vb_work.size)
+		wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_work);
+
+	if (inst->std == W_HEVC_ENC || inst->std == W_AVC_ENC) {
+		if (p_enc_info->vb_sub_sam_buf.size)
+			wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_sub_sam_buf);
+
+		if (p_enc_info->vb_mv.size)
+			wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_mv);
+
+		if (p_enc_info->vb_fbc_y_tbl.size)
+			wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_fbc_y_tbl);
+
+		if (p_enc_info->vb_fbc_c_tbl.size)
+			wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_fbc_c_tbl);
+	}
+
+	if (p_enc_info->vb_task.size)
+		wave5_vdi_free_dma_memory(vpu_dev, &p_enc_info->vb_task);
+
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	kfree(inst->codec_info);
+
+	return 0;
+}
+
+int wave5_vpu_enc_register_frame_buffer(struct vpu_instance *inst, unsigned int num,
+					unsigned int stride, int height,
+					enum tiled_map_type map_type)
+{
+	struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+	unsigned int size_luma, size_chroma;
+	int i;
+
+	if (p_enc_info->stride)
+		return -EINVAL;
+
+	if (!p_enc_info->initial_info_obtained)
+		return -EINVAL;
+
+	if (num < p_enc_info->initial_info.min_frame_buffer_count)
+		return -EINVAL;
+
+	if (stride == 0 || stride % 8 != 0)
+		return -EINVAL;
+
+	if (height <= 0)
+		return -EINVAL;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	p_enc_info->num_frame_buffers = num;
+	p_enc_info->stride = stride;
+
+	size_luma = stride * height;
+	size_chroma = ALIGN(stride / 2, 16) * height;
+
+	for (i = 0; i < num; i++) {
+		if (!inst->frame_buf[i].update_fb_info)
+			continue;
+
+		inst->frame_buf[i].update_fb_info = false;
+		inst->frame_buf[i].stride = stride;
+		inst->frame_buf[i].height = height;
+		inst->frame_buf[i].map_type = COMPRESSED_FRAME_MAP;
+		inst->frame_buf[i].endian = VDI_128BIT_LITTLE_ENDIAN;
+		inst->frame_buf[i].buf_y_size = size_luma;
+		inst->frame_buf[i].buf_cb = inst->frame_buf[i].buf_y + size_luma;
+		inst->frame_buf[i].buf_cb_size = size_chroma;
+		inst->frame_buf[i].buf_cr_size = 0;
+	}
+
+	ret = wave5_vpu_enc_register_framebuffer(inst->dev->dev, inst, &inst->frame_buf[0],
+						 COMPRESSED_FRAME_MAP,
+						 p_enc_info->num_frame_buffers);
+
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+static int wave5_check_enc_param(struct vpu_instance *inst, struct enc_param *param)
+{
+	struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+
+	if (!param)
+		return -EINVAL;
+
+	if (!param->skip_picture && !param->source_frame)
+		return -EINVAL;
+
+	if (p_enc_info->open_param.bit_rate == 0 && inst->std == W_HEVC_ENC) {
+		if (param->force_pic_qp_enable &&
+		    (param->force_pic_qp_i > MAX_INTRA_QP || param->force_pic_qp_p > MAX_INTRA_QP ||
+		     param->force_pic_qp_b > MAX_INTRA_QP))
+			return -EINVAL;
+		if (!p_enc_info->ring_buffer_enable &&
+		    (param->pic_stream_buffer_addr % 16 || param->pic_stream_buffer_size == 0))
+			return -EINVAL;
+	}
+	if (!p_enc_info->ring_buffer_enable &&
+	    (param->pic_stream_buffer_addr % 8 || param->pic_stream_buffer_size == 0))
+		return -EINVAL;
+
+	return 0;
+}
+
+static uint64_t wave5_get_timestamp(struct vpu_instance *inst)
+{
+	struct enc_info *p_enc_info;
+	u64 pts;
+	u32 fps;
+
+	if (!inst->codec_info)
+		return 0;
+
+	p_enc_info = &inst->codec_info->enc_info;
+	fps = p_enc_info->open_param.frame_rate_info;
+	if (fps == 0)
+		fps = 30;
+
+	pts = p_enc_info->cur_pts;
+	p_enc_info->cur_pts += 90000 / fps; /* 90_k_hz/fps */
+
+	return pts;
+}
+
+int wave5_vpu_enc_start_one_frame(struct vpu_instance *inst, struct enc_param *param, u32 *fail_res)
+{
+	struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	*fail_res = 0;
+
+	if (p_enc_info->stride == 0) // this means frame buffers have not been registered.
+		return -EINVAL;
+
+	ret = wave5_check_enc_param(inst, param);
+	if (ret)
+		return ret;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	p_enc_info->pts_map[param->src_idx] = p_enc_info->open_param.enable_pts ?
+					      wave5_get_timestamp(inst) : param->pts;
+
+	ret = wave5_vpu_encode(inst, param, fail_res);
+
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_enc_get_output_info(struct vpu_instance *inst, struct enc_output_info *info)
+{
+	struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	ret = wave5_vpu_enc_get_result(inst, info);
+	if (ret) {
+		info->pts = 0;
+		goto unlock;
+	}
+
+	if (info->recon_frame_index >= 0)
+		info->pts = p_enc_info->pts_map[info->enc_src_idx];
+
+unlock:
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_enc_give_command(struct vpu_instance *inst, enum codec_command cmd, void *parameter)
+{
+	struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+
+	switch (cmd) {
+	case ENABLE_ROTATION:
+		p_enc_info->rotation_enable = true;
+		break;
+	case ENABLE_MIRRORING:
+		p_enc_info->mirror_enable = true;
+		break;
+	case SET_MIRROR_DIRECTION: {
+		enum mirror_direction mir_dir;
+
+		mir_dir = *(enum mirror_direction *)parameter;
+		if (mir_dir != MIRDIR_NONE && mir_dir != MIRDIR_HOR &&
+		    mir_dir != MIRDIR_VER && mir_dir != MIRDIR_HOR_VER)
+			return -EINVAL;
+		p_enc_info->mirror_direction = mir_dir;
+		break;
+	}
+	case SET_ROTATION_ANGLE: {
+		int angle;
+
+		angle = *(int *)parameter;
+		if (angle && angle != 90 && angle != 180 && angle != 270)
+			return -EINVAL;
+		if (p_enc_info->initial_info_obtained && (angle == 90 || angle == 270))
+			return -EINVAL;
+		p_enc_info->rotation_angle = angle;
+		break;
+	}
+	case ENC_GET_QUEUE_STATUS: {
+		struct queue_status_info *queue_info = parameter;
+
+		queue_info->instance_queue_count = p_enc_info->instance_queue_count;
+		queue_info->report_queue_count = p_enc_info->report_queue_count;
+		break;
+	}
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int wave5_vpu_enc_issue_seq_init(struct vpu_instance *inst)
+{
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	ret = wave5_vpu_enc_init_seq(inst);
+
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return ret;
+}
+
+int wave5_vpu_enc_complete_seq_init(struct vpu_instance *inst, struct enc_initial_info *info)
+{
+	struct enc_info *p_enc_info = &inst->codec_info->enc_info;
+	int ret;
+	struct vpu_device *vpu_dev = inst->dev;
+
+	if (!info)
+		return -EINVAL;
+
+	ret = mutex_lock_interruptible(&vpu_dev->hw_lock);
+	if (ret)
+		return ret;
+
+	ret = wave5_vpu_enc_get_seq_info(inst, info);
+	if (ret) {
+		p_enc_info->initial_info_obtained = false;
+		mutex_unlock(&vpu_dev->hw_lock);
+		return ret;
+	}
+
+	p_enc_info->initial_info_obtained = true;
+	p_enc_info->initial_info = *info;
+
+	mutex_unlock(&vpu_dev->hw_lock);
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h
--- a/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpuapi.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,1172 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave5 series multi-standard codec IP - helper definitions
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+
+#ifndef VPUAPI_H_INCLUDED
+#define VPUAPI_H_INCLUDED
+
+#include <linux/kfifo.h>
+#include <linux/idr.h>
+#include <linux/genalloc.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-ctrls.h>
+#include "wave5-vpuerror.h"
+#include "wave5-vpuconfig.h"
+#include "wave5-vdi.h"
+
+enum product_id {
+	PRODUCT_ID_521,
+	PRODUCT_ID_511,
+	PRODUCT_ID_517,
+	PRODUCT_ID_NONE,
+};
+
+struct vpu_attr;
+
+enum vpu_instance_type {
+	VPU_INST_TYPE_DEC = 0,
+	VPU_INST_TYPE_ENC = 1
+};
+
+enum vpu_instance_state {
+	VPU_INST_STATE_NONE = 0,
+	VPU_INST_STATE_OPEN = 1,
+	VPU_INST_STATE_INIT_SEQ = 2,
+	VPU_INST_STATE_PIC_RUN = 3,
+	VPU_INST_STATE_STOP = 4
+};
+
+#define WAVE5_MAX_FBS 32
+
+#define MAX_REG_FRAME (WAVE5_MAX_FBS * 2)
+
+#define MAX_TIMESTAMP_CIR_BUF 30
+
+#define WAVE5_DEC_HEVC_BUF_SIZE(_w, _h) (DIV_ROUND_UP(_w, 64) * DIV_ROUND_UP(_h, 64) * 256 + 64)
+#define WAVE5_DEC_AVC_BUF_SIZE(_w, _h) ((((ALIGN(_w, 256) / 16) * (ALIGN(_h, 16) / 16)) + 16) * 80)
+#define WAVE5_DEC_VP9_BUF_SIZE(_w, _h) (((ALIGN(_w, 64) * ALIGN(_h, 64)) >> 2))
+#define WAVE5_DEC_AVS2_BUF_SIZE(_w, _h) (((ALIGN(_w, 64) * ALIGN(_h, 64)) >> 5))
+// AV1 BUF SIZE : MFMV + segment ID + CDF probs table + film grain param Y+ film graim param C
+#define WAVE5_DEC_AV1_BUF_SZ_1(_w, _h)	\
+	(((ALIGN(_w, 64) / 64) * (ALIGN(_h, 64) / 64) * 512) + 41984 + 8192 + 4864)
+#define WAVE5_DEC_AV1_BUF_SZ_2(_w1, _w2, _h)	\
+	(((ALIGN(_w1, 64) / 64) * 256 + (ALIGN(_w2, 256) / 64) * 128) * (ALIGN(_h, 64) / 64))
+
+#define WAVE5_FBC_LUMA_TABLE_SIZE(_w, _h) (ALIGN(_h, 64) * ALIGN(_w, 256) / 32)
+#define WAVE5_FBC_CHROMA_TABLE_SIZE(_w, _h) (ALIGN((_h), 64) * ALIGN((_w) / 2, 256) / 32)
+#define WAVE5_ENC_AVC_BUF_SIZE(_w, _h) (ALIGN(_w, 64) * ALIGN(_h, 64) / 32)
+#define WAVE5_ENC_HEVC_BUF_SIZE(_w, _h) (ALIGN(_w, 64) / 64 * ALIGN(_h, 64) / 64 * 128)
+#define DEC_BUF_OFFSET 3
+
+#define IS_WRAP(_v, _max) ((_v % _max) ? 1 : 0)
+
+/*
+ * common struct and definition
+ */
+enum cod_std {
+	STD_AVC = 0,
+	STD_VC1 = 1,
+	STD_MPEG2 = 2,
+	STD_MPEG4 = 3,
+	STD_H263 = 4,
+	STD_DIV3 = 5,
+	STD_RV = 6,
+	STD_AVS = 7,
+	STD_THO = 9,
+	STD_VP3 = 10,
+	STD_VP8 = 11,
+	STD_HEVC = 12,
+	STD_VP9 = 13,
+	STD_AVS2 = 14,
+	STD_AV1 = 16,
+	STD_MAX
+};
+
+enum wave_std {
+	W_HEVC_DEC = 0x00,
+	W_HEVC_ENC = 0x01,
+	W_AVC_DEC = 0x02,
+	W_AVC_ENC = 0x03,
+	W_VP9_DEC = 0x16,
+	W_AVS2_DEC = 0x18,
+	W_AV1_DEC = 0x1A,
+	STD_UNKNOWN = 0xFF
+};
+
+enum SET_PARAM_OPTION {
+	OPT_COMMON = 0, /* SET_PARAM command option for encoding sequence */
+	OPT_CUSTOM_GOP = 1, /* SET_PARAM command option for setting custom GOP */
+	OPT_CUSTOM_HEADER = 2, /* SET_PARAM command option for setting custom VPS/SPS/PPS */
+	OPT_VUI = 3, /* SET_PARAM command option for encoding VUI */
+	OPT_CHANGE_PARAM = 0x10,
+};
+
+enum DEC_PIC_HDR_OPTION {
+	INIT_SEQ_NORMAL = 0x01,
+	INIT_SEQ_W_THUMBNAIL = 0x11,
+};
+
+enum DEC_PIC_OPTION {
+	DEC_PIC_NORMAL = 0x00, /* it is normal mode of DEC_PIC command */
+	DEC_PIC_W_THUMBNAIL = 0x10, /* thumbnail mode (skip non-IRAP without reference reg) */
+	SKIP_NON_IRAP = 0x11, /* it skips to decode non-IRAP pictures */
+	SKIP_NON_REF_PIC = 0x13
+};
+
+/************************************************************************/
+/* PROFILE & LEVEL */
+/************************************************************************/
+/* HEVC */
+#define HEVC_PROFILE_MAIN 1
+#define HEVC_PROFILE_MAIN10 2
+#define HEVC_PROFILE_STILLPICTURE 3
+#define HEVC_PROFILE_MAIN10_STILLPICTURE 2
+
+/* H.264 profile for encoder*/
+#define H264_PROFILE_BP 1
+#define H264_PROFILE_MP 2
+#define H264_PROFILE_EXTENDED 3
+#define H264_PROFILE_HP 4
+#define H264_PROFILE_HIGH10 5
+#define H264_PROFILE_HIGH422 6
+#define H264_PROFILE_HIGH444 7
+
+/************************************************************************/
+/* error codes */
+/************************************************************************/
+
+/************************************************************************/
+/* utility macros */
+/************************************************************************/
+
+/* bit_alloc_mode */
+#define BIT_ALLOC_MODE_FIXED_RATIO		2
+
+/* bit_rate */
+#define MAX_BIT_RATE				700000000
+
+/* decoding_refresh_type */
+#define DEC_REFRESH_TYPE_NON_IRAP		0
+#define DEC_REFRESH_TYPE_CRA			1
+#define DEC_REFRESH_TYPE_IDR			2
+
+/* depend_slice_mode */
+#define DEPEND_SLICE_MODE_RECOMMENDED		1
+#define DEPEND_SLICE_MODE_BOOST			2
+#define DEPEND_SLICE_MODE_FAST			3
+
+/* hvs_max_delta_qp */
+#define MAX_HVS_MAX_DELTA_QP			51
+
+/* intra_refresh_mode */
+#define REFRESH_MODE_CTU_ROWS			1
+#define REFRESH_MODE_CTU_COLUMNS		2
+#define REFRESH_MODE_CTU_STEP_SIZE		3
+#define REFRESH_MODE_CTUS			4
+
+/* intra_mb_refresh_mode */
+#define REFRESH_MB_MODE_NONE			0
+#define REFRESH_MB_MODE_CTU_ROWS		1
+#define REFRESH_MB_MODE_CTU_COLUMNS		2
+#define REFRESH_MB_MODE_CTU_STEP_SIZE		3
+
+/* intra_qp */
+#define MAX_INTRA_QP				63
+
+/* nr_inter_weight_* */
+#define MAX_INTER_WEIGHT			31
+
+/* nr_intra_weight_* */
+#define MAX_INTRA_WEIGHT			31
+
+/* nr_noise_sigma_* */
+#define MAX_NOISE_SIGMA				255
+
+/* bitstream_buffer_size */
+#define MIN_BITSTREAM_BUFFER_SIZE		1024
+#define MIN_BITSTREAM_BUFFER_SIZE_WAVE521	(1024 * 64)
+
+/* vbv_buffer_size */
+#define MIN_VBV_BUFFER_SIZE			10
+#define MAX_VBV_BUFFER_SIZE			3000
+
+/* Bitstream buffer option: Explicit End
+ * When set to 1 the VPU assumes that the bitstream has at least one frame and
+ * will read until the end of the bitstream buffer.
+ * When set to 0 the VPU will not read the last few bytes.
+ * This option can be set anytime but cannot be cleared during processing.
+ * It can be set to force finish decoding even though there is not enough
+ * bitstream data for a full frame.
+ */
+#define BS_EXPLICIT_END_MODE_ON			1
+
+#define BUFFER_MARGIN				4096
+
+/************************************************************************/
+/* */
+/************************************************************************/
+/**
+ * \brief parameters of DEC_SET_SEQ_CHANGE_MASK
+ */
+#define SEQ_CHANGE_ENABLE_PROFILE BIT(5)
+#define SEQ_CHANGE_CHROMA_FORMAT_IDC BIT(15) /* AV1 */
+#define SEQ_CHANGE_ENABLE_SIZE BIT(16)
+#define SEQ_CHANGE_INTER_RES_CHANGE BIT(17) /* VP9 */
+#define SEQ_CHANGE_ENABLE_BITDEPTH BIT(18)
+#define SEQ_CHANGE_ENABLE_DPB_COUNT BIT(19)
+#define SEQ_CHANGE_ENABLE_ASPECT_RATIO BIT(21)
+#define SEQ_CHANGE_ENABLE_VIDEO_SIGNAL BIT(23)
+#define SEQ_CHANGE_ENABLE_VUI_TIMING_INFO BIT(29)
+
+#define SEQ_CHANGE_ENABLE_ALL_VP9 (SEQ_CHANGE_ENABLE_PROFILE | \
+		SEQ_CHANGE_ENABLE_SIZE | \
+		SEQ_CHANGE_INTER_RES_CHANGE | \
+		SEQ_CHANGE_ENABLE_BITDEPTH | \
+		SEQ_CHANGE_ENABLE_DPB_COUNT)
+
+#define SEQ_CHANGE_ENABLE_ALL_HEVC (SEQ_CHANGE_ENABLE_PROFILE | \
+		SEQ_CHANGE_ENABLE_SIZE | \
+		SEQ_CHANGE_ENABLE_BITDEPTH | \
+		SEQ_CHANGE_ENABLE_DPB_COUNT)
+
+#define SEQ_CHANGE_ENABLE_ALL_AVS2 (SEQ_CHANGE_ENABLE_PROFILE | \
+		SEQ_CHANGE_ENABLE_SIZE | \
+		SEQ_CHANGE_ENABLE_BITDEPTH | \
+		SEQ_CHANGE_ENABLE_DPB_COUNT)
+
+#define SEQ_CHANGE_ENABLE_ALL_AVC (SEQ_CHANGE_ENABLE_SIZE | \
+		SEQ_CHANGE_ENABLE_BITDEPTH | \
+		SEQ_CHANGE_ENABLE_DPB_COUNT | \
+		SEQ_CHANGE_ENABLE_ASPECT_RATIO | \
+		SEQ_CHANGE_ENABLE_VIDEO_SIGNAL | \
+		SEQ_CHANGE_ENABLE_VUI_TIMING_INFO)
+
+#define SEQ_CHANGE_ENABLE_ALL_AV1 (SEQ_CHANGE_ENABLE_PROFILE | \
+		SEQ_CHANGE_CHROMA_FORMAT_IDC | \
+		SEQ_CHANGE_ENABLE_SIZE | \
+		SEQ_CHANGE_ENABLE_BITDEPTH | \
+		SEQ_CHANGE_ENABLE_DPB_COUNT)
+
+#define DISPLAY_IDX_FLAG_SEQ_END -1
+#define DISPLAY_IDX_FLAG_NO_FB -3
+#define DECODED_IDX_FLAG_NO_FB -1
+#define DECODED_IDX_FLAG_SKIP -2
+
+#define RECON_IDX_FLAG_ENC_END -1
+#define RECON_IDX_FLAG_ENC_DELAY -2
+#define RECON_IDX_FLAG_HEADER_ONLY -3
+#define RECON_IDX_FLAG_CHANGE_PARAM -4
+
+enum codec_command {
+	ENABLE_ROTATION,
+	ENABLE_MIRRORING,
+	SET_MIRROR_DIRECTION,
+	SET_ROTATION_ANGLE,
+	ENABLE_DEC_THUMBNAIL_MODE,
+	DEC_GET_QUEUE_STATUS,
+	ENC_GET_QUEUE_STATUS,
+	DEC_RESET_FRAMEBUF_INFO,
+	DEC_GET_SEQ_INFO,
+};
+
+enum error_conceal_mode {
+	ERROR_CONCEAL_MODE_OFF = 0, /* conceal off */
+	ERROR_CONCEAL_MODE_INTRA_ONLY = 1, /* intra conceal in intra-picture, inter-picture */
+	ERROR_CONCEAL_MODE_INTRA_INTER = 2
+};
+
+enum error_conceal_unit {
+	ERROR_CONCEAL_UNIT_PICTURE = 0, /* picture-level error conceal */
+	ERROR_CONCEAL_UNIT_SLICE_TILE = 1, /* slice/tile-level error conceal */
+	ERROR_CONCEAL_UNIT_BLOCK_ROW = 2, /* block-row-level error conceal */
+	ERROR_CONCEAL_UNIT_BLOCK = 3 /* block-level conceal */
+};
+
+enum cb_cr_order {
+	CBCR_ORDER_NORMAL,
+	CBCR_ORDER_REVERSED
+};
+
+enum mirror_direction {
+	MIRDIR_NONE, /* no mirroring */
+	MIRDIR_VER, /* vertical mirroring */
+	MIRDIR_HOR, /* horizontal mirroring */
+	MIRDIR_HOR_VER /* horizontal and vertical mirroring */
+};
+
+enum frame_buffer_format {
+	FORMAT_ERR = -1,
+	FORMAT_420 = 0, /* 8bit */
+	FORMAT_422, /* 8bit */
+	FORMAT_224, /* 8bit */
+	FORMAT_444, /* 8bit */
+	FORMAT_400, /* 8bit */
+
+	/* little endian perspective */
+	/* | addr 0 | addr 1 | */
+	FORMAT_420_P10_16BIT_MSB = 5, /* lsb |000000xx|xxxxxxxx | msb */
+	FORMAT_420_P10_16BIT_LSB, /* lsb |xxxxxxx |xx000000 | msb */
+	FORMAT_420_P10_32BIT_MSB, /* lsb |00xxxxxxxxxxxxxxxxxxxxxxxxxxx| msb */
+	FORMAT_420_P10_32BIT_LSB, /* lsb |xxxxxxxxxxxxxxxxxxxxxxxxxxx00| msb */
+
+	/* 4:2:2 packed format */
+	/* little endian perspective */
+	/* | addr 0 | addr 1 | */
+	FORMAT_422_P10_16BIT_MSB, /* lsb |000000xx |xxxxxxxx | msb */
+	FORMAT_422_P10_16BIT_LSB, /* lsb |xxxxxxxx |xx000000 | msb */
+	FORMAT_422_P10_32BIT_MSB, /* lsb |00xxxxxxxxxxxxxxxxxxxxxxxxxxx| msb */
+	FORMAT_422_P10_32BIT_LSB, /* lsb |xxxxxxxxxxxxxxxxxxxxxxxxxxx00| msb */
+
+	FORMAT_YUYV, /* 8bit packed format : Y0U0Y1V0 Y2U1Y3V1 ... */
+	FORMAT_YUYV_P10_16BIT_MSB,
+	FORMAT_YUYV_P10_16BIT_LSB,
+	FORMAT_YUYV_P10_32BIT_MSB,
+	FORMAT_YUYV_P10_32BIT_LSB,
+
+	FORMAT_YVYU, /* 8bit packed format : Y0V0Y1U0 Y2V1Y3U1 ... */
+	FORMAT_YVYU_P10_16BIT_MSB,
+	FORMAT_YVYU_P10_16BIT_LSB,
+	FORMAT_YVYU_P10_32BIT_MSB,
+	FORMAT_YVYU_P10_32BIT_LSB,
+
+	FORMAT_UYVY, /* 8bit packed format : U0Y0V0Y1 U1Y2V1Y3 ... */
+	FORMAT_UYVY_P10_16BIT_MSB,
+	FORMAT_UYVY_P10_16BIT_LSB,
+	FORMAT_UYVY_P10_32BIT_MSB,
+	FORMAT_UYVY_P10_32BIT_LSB,
+
+	FORMAT_VYUY, /* 8bit packed format : V0Y0U0Y1 V1Y2U1Y3 ... */
+	FORMAT_VYUY_P10_16BIT_MSB,
+	FORMAT_VYUY_P10_16BIT_LSB,
+	FORMAT_VYUY_P10_32BIT_MSB,
+	FORMAT_VYUY_P10_32BIT_LSB,
+
+	FORMAT_MAX,
+};
+
+enum packed_format_num {
+	NOT_PACKED = 0,
+	PACKED_YUYV,
+	PACKED_YVYU,
+	PACKED_UYVY,
+	PACKED_VYUY,
+};
+
+enum wave5_interrupt_bit {
+	INT_WAVE5_INIT_VPU = 0,
+	INT_WAVE5_WAKEUP_VPU = 1,
+	INT_WAVE5_SLEEP_VPU = 2,
+	INT_WAVE5_CREATE_INSTANCE = 3,
+	INT_WAVE5_FLUSH_INSTANCE = 4,
+	INT_WAVE5_DESTROY_INSTANCE = 5,
+	INT_WAVE5_INIT_SEQ = 6,
+	INT_WAVE5_SET_FRAMEBUF = 7,
+	INT_WAVE5_DEC_PIC = 8,
+	INT_WAVE5_ENC_PIC = 8,
+	INT_WAVE5_ENC_SET_PARAM = 9,
+	INT_WAVE5_DEC_QUERY = 14,
+	INT_WAVE5_BSBUF_EMPTY = 15,
+	INT_WAVE5_BSBUF_FULL = 15,
+};
+
+enum pic_type {
+	PIC_TYPE_I = 0, /* I picture */
+	PIC_TYPE_KEY = 0, /* KEY frame for AV1*/
+	PIC_TYPE_P = 1, /* P picture */
+	PIC_TYPE_INTER = 1, /* inter frame for AV1*/
+	PIC_TYPE_B = 2, /* B picture (except VC1) */
+	PIC_TYPE_REPEAT = 2, /* repeat frame (VP9 only) */
+	PIC_TYPE_AV1_INTRA = 2, /* intra only frame (AV1 only) */
+	PIC_TYPE_VC1_BI = 2, /* VC1 BI picture (VC1 only) */
+	PIC_TYPE_VC1_B = 3, /* VC1 B picture (VC1 only) */
+	PIC_TYPE_D = 3,
+	PIC_TYPE_S = 3,
+	PIC_TYPE_AVS2_F = 3, /* F picture in AVS2 */
+	PIC_TYPE_AV1_SWITCH = 3, /* switch frame (AV1 only) */
+	PIC_TYPE_VC1_P_SKIP = 4, /* VC1 P skip picture (VC1 only) */
+	PIC_TYPE_MP4_P_SKIP_NOT_CODED = 4, /* not coded P picture in MPEG4 packed mode */
+	PIC_TYPE_AVS2_S = 4, /* S picture in AVS2 */
+	PIC_TYPE_IDR = 5, /* H.264/H.265 IDR picture */
+	PIC_TYPE_AVS2_G = 5, /* G picture in AVS2 */
+	PIC_TYPE_AVS2_GB = 6, /* GB picture in AVS2 */
+	PIC_TYPE_MAX /* no meaning */
+};
+
+enum bit_stream_mode {
+	BS_MODE_INTERRUPT,
+	BS_MODE_RESERVED, /* reserved for the future */
+	BS_MODE_PIC_END,
+};
+
+enum sw_reset_mode {
+	SW_RESET_SAFETY,
+	SW_RESET_FORCE,
+	SW_RESET_ON_BOOT
+};
+
+enum tiled_map_type {
+	LINEAR_FRAME_MAP = 0, /* linear frame map type */
+	COMPRESSED_FRAME_MAP = 17, /* compressed frame map type*/
+};
+
+enum temporal_id_mode {
+	TEMPORAL_ID_MODE_ABSOLUTE,
+	TEMPORAL_ID_MODE_RELATIVE,
+};
+
+struct vpu_attr {
+	u32 product_id; /* the product ID */
+	char product_name[8]; /* the product name in ascii code */
+	u32 product_version; /* the product version number */
+	u32 fw_version; /* the F/W version */
+	u32 customer_id; /* customer ID number */
+	u32 support_decoders; /* bitmask: see <<vpuapi_h_cod_std>> */
+	u32 support_encoders; /* bitmask: see <<vpuapi_h_cod_std>> */
+	u32 support_endian_mask; /* A variable of supported endian mode in product */
+	u32 support_bitstream_mode;
+	u32 support_backbone: 1;
+	u32 support_avc10bit_enc: 1;
+	u32 support_hevc10bit_enc: 1;
+	u32 support_dual_core: 1; /* this indicates whether a product has two vcores */
+	u32 support_vcore_backbone: 1;
+	u32 support_vcpu_backbone: 1;
+};
+
+struct frame_buffer {
+	dma_addr_t buf_y;
+	dma_addr_t buf_cb;
+	dma_addr_t buf_cr;
+	unsigned int buf_y_size;
+	unsigned int buf_cb_size;
+	unsigned int buf_cr_size;
+	unsigned int endian;
+	enum tiled_map_type map_type;
+	unsigned int stride; /* A horizontal stride for given frame buffer */
+	unsigned int width; /* A width for given frame buffer */
+	unsigned int height; /* A height for given frame buffer */
+	size_t size; /* A size for given frame buffer */
+	unsigned int sequence_no;
+	bool update_fb_info;
+};
+
+struct vpu_rect {
+	unsigned int left; /* horizontal pixel offset from left edge */
+	unsigned int top; /* vertical pixel offset from top edge */
+	unsigned int right; /* horizontal pixel offset from right edge */
+	unsigned int bottom; /* vertical pixel offset from bottom edge */
+};
+
+/*
+ * decode struct and definition
+ */
+
+struct dec_open_param {
+	dma_addr_t bitstream_buffer;
+	size_t bitstream_buffer_size;
+	enum cb_cr_order cbcr_order;
+	unsigned int frame_endian;
+	unsigned int stream_endian;
+	enum bit_stream_mode bitstream_mode;
+	u32 av1_format;
+	enum error_conceal_unit error_conceal_unit;
+	enum error_conceal_mode error_conceal_mode;
+	u32 pri_axprot;
+	u32 pri_axcache;
+	u32 enable_non_ref_fbc_write: 1;
+};
+
+struct dec_initial_info {
+	u32 pic_width;
+	u32 pic_height;
+	s32 f_rate_numerator; /* the numerator part of frame rate fraction */
+	s32 f_rate_denominator; /* the denominator part of frame rate fraction */
+	struct vpu_rect pic_crop_rect;
+	u32 min_frame_buffer_count; /* between 1 to 16 */
+	u32 frame_buf_delay;
+
+	u32 max_temporal_layers; /* it indicates the max number of temporal sub-layers */
+	u32 profile;
+	u32 level;
+	u32 tier;
+	bool is_ext_sar;
+	u32 aspect_rate_info;
+	u32 bit_rate;
+	u32 user_data_header;
+	u32 user_data_size;
+	bool user_data_buf_full;
+	u32 chroma_format_idc;/* A chroma format indicator */
+	u32 luma_bitdepth; /* A bit-depth of luma sample */
+	u32 chroma_bitdepth; /* A bit-depth of chroma sample */
+	u32 seq_init_err_reason;
+	u32 warn_info;
+	dma_addr_t rd_ptr; /* A read pointer of bitstream buffer */
+	dma_addr_t wr_ptr; /* A write pointer of bitstream buffer */
+	u32 sequence_no;
+	u32 output_bit_depth;
+	u32 vlc_buf_size; /* the size of vlc buffer */
+	u32 param_buf_size; /* the size of param buffer */
+};
+
+#define WAVE_SKIPMODE_WAVE_NONE 0
+#define WAVE_SKIPMODE_NON_IRAP 1
+#define WAVE_SKIPMODE_NON_REF 2
+
+struct dec_param {
+	u32 skipframe_mode: 2;
+	u32 cra_as_bla_flag: 1;
+	u32 disable_film_grain: 1;
+};
+
+struct avs2_info {
+	s32 decoded_poi;
+	int display_poi;
+};
+
+struct dec_output_info {
+	/**
+	 * this is a frame buffer index for the picture to be displayed at the moment among
+	 * frame buffers which are registered using vpu_dec_register_frame_buffer(). frame
+	 * data to be displayed are stored into the frame buffer with this index
+	 * when there is no display delay, this index is always
+	 * the same with index_frame_decoded, however, if display delay does exist for display
+	 * reordering in AVC
+	 * or B-frames in VC1), this index might be different with index_frame_decoded.
+	 * by checking this index, HOST application can easily know whether sequence decoding
+	 * has been finished or not.
+	 *
+	 * -3(0xFFFD) or -2(0xFFFE) : it is when a display output cannot be given due to picture
+	 * reordering or skip option
+	 * -1(0xFFFF) : it is when there is no more output for display at the end of sequence
+	 * decoding
+	 */
+	s32 index_frame_display;
+	/**
+	 * this is a frame buffer index of decoded picture among frame buffers which were
+	 * registered using vpu_dec_register_frame_buffer(). the currently decoded frame is stored
+	 * into the frame buffer specified by
+	 * this index.
+	 *
+	 * -2 : it indicates that no decoded output is generated because decoder meets EOS
+	 * (end of sequence) or skip
+	 * -1 : it indicates that decoder fails to decode a picture because there is no available
+	 * frame buffer
+	 */
+	s32 index_frame_decoded;
+	s32 index_frame_decoded_for_tiled;
+	u32 nal_type;
+	unsigned int pic_type;
+	struct vpu_rect rc_display;
+	unsigned int disp_pic_width;
+	unsigned int disp_pic_height;
+	struct vpu_rect rc_decoded;
+	u32 dec_pic_width;
+	u32 dec_pic_height;
+	struct avs2_info avs2_info;
+	s32 decoded_poc;
+	int temporal_id; /* A temporal ID of the picture */
+	dma_addr_t rd_ptr; /* A stream buffer read pointer for the current decoder instance */
+	dma_addr_t wr_ptr; /* A stream buffer write pointer for the current decoder instance */
+	struct frame_buffer disp_frame;
+	u32 frame_display_flag; /* it reports a frame buffer flag to be displayed */
+	/**
+	 * this variable reports that sequence has been changed while H.264/AVC stream decoding.
+	 * if it is 1, HOST application can get the new sequence information by calling
+	 * vpu_dec_get_initial_info() or wave5_vpu_dec_issue_seq_init().
+	 *
+	 * for H.265/HEVC decoder, each bit has a different meaning as follows.
+	 *
+	 * sequence_changed[5] : it indicates that the profile_idc has been changed
+	 * sequence_changed[16] : it indicates that the resolution has been changed
+	 * sequence_changed[19] : it indicates that the required number of frame buffer has
+	 * been changed.
+	 */
+	unsigned int frame_cycle; /* reports the number of cycles for processing a frame */
+	u32 sequence_no;
+
+	u32 dec_host_cmd_tick; /* tick of DEC_PIC command for the picture */
+	u32 dec_decode_end_tick; /* end tick of decoding slices of the picture */
+
+	u32 sequence_changed;
+};
+
+struct queue_status_info {
+	u32 instance_queue_count;
+	u32 report_queue_count;
+};
+
+/*
+ * encode struct and definition
+ */
+
+#define MAX_NUM_TEMPORAL_LAYER 7
+#define MAX_NUM_SPATIAL_LAYER 3
+#define MAX_GOP_NUM 8
+
+struct custom_gop_pic_param {
+	u32 pic_type; /* A picture type of nth picture in the custom GOP */
+	u32 poc_offset; /* A POC of nth picture in the custom GOP */
+	u32 pic_qp; /* A quantization parameter of nth picture in the custom GOP */
+	u32 use_multi_ref_p; /* use multiref pic for P picture. valid only if PIC_TYPE is P */
+	u32 ref_poc_l0; /* A POC of reference L0 of nth picture in the custom GOP */
+	u32 ref_poc_l1; /* A POC of reference L1 of nth picture in the custom GOP */
+	s32 temporal_id; /* A temporal ID of nth picture in the custom GOP */
+};
+
+struct custom_gop_param {
+	u32 custom_gop_size; /* the size of custom GOP (0~8) */
+	struct custom_gop_pic_param pic_param[MAX_GOP_NUM];
+};
+
+struct wave_custom_map_opt {
+	u32 roi_avg_qp; /* it sets an average QP of ROI map */
+	u32 addr_custom_map;
+	u32 custom_roi_map_enable: 1; /* it enables ROI map */
+	u32 custom_lambda_map_enable: 1; /* it enables custom lambda map */
+	u32 custom_mode_map_enable: 1;
+	u32 custom_coef_drop_enable: 1;
+};
+
+struct enc_wave_param {
+	/*
+	 * A profile indicator (HEVC only)
+	 *
+	 * 0 : the firmware determines a profile according to internalbitdepth
+	 * 1 : main profile
+	 * 2 : main10 profile
+	 * 3 : main still picture profile
+	 * in AVC encoder, a profile cannot be set by host application. the firmware decides it
+	 * based on internalbitdepth. it is HIGH profile for bitdepth of 8 and HIGH10 profile for
+	 * bitdepth of 10.
+	 */
+	u32 profile;
+	u32 level; /* A level indicator (level * 10) */
+	u32 internal_bit_depth: 4; /* 8/10 */
+	u32 gop_preset_idx: 4; /* 0 - 9 */
+	u32 decoding_refresh_type: 2; /* 0=non-IRAP, 1=CRA, 2=IDR */
+	u32 intra_qp; /* A quantization parameter of intra picture */
+	u32 intra_period; /* A period of intra picture in GOP size */
+	u32 forced_idr_header_enable: 2;
+	u32 conf_win_top; /* A top offset of conformance window */
+	u32 conf_win_bot; /* A bottom offset of conformance window */
+	u32 conf_win_left; /* A left offset of conformance window */
+	u32 conf_win_right; /* A right offset of conformance window */
+	u32 independ_slice_mode_arg;
+	u32 depend_slice_mode_arg;
+	u32 intra_refresh_mode: 3;
+	/*
+	 * it specifies an intra CTU refresh interval. depending on intra_refresh_mode,
+	 * it can mean one of the following.
+	 *
+	 * the number of consecutive CTU rows for intra_ctu_refresh_mode of 1
+	 * the number of consecutive CTU columns for intra_ctu_refresh_mode of 2
+	 * A step size in CTU for intra_ctu_refresh_mode of 3
+	 * the number of intra ct_us to be encoded in a picture for intra_ctu_refresh_mode of 4
+	 */
+	u32 intra_refresh_arg;
+	/*
+	 * 0 : custom setting
+	 * 1 : recommended encoder parameters (slow encoding speed, highest picture quality)
+	 * 2 : boost mode (normal encoding speed, moderate picture quality)
+	 * 3 : fast mode (fast encoding speed, low picture quality)
+	 */
+	u32 depend_slice_mode : 2;
+	u32 use_recommend_enc_param: 2;
+	u32 max_num_merge: 2;
+	u32 scaling_list_enable: 2;
+	u32 bit_alloc_mode: 2; /* 0=ref-pic-priority, 1=uniform, 2=fixed_bit_ratio */
+	s32 beta_offset_div2: 4; /* it sets beta_offset_div2 for deblocking filter */
+	s32 tc_offset_div2: 4; /* it sets tc_offset_div3 for deblocking filter */
+	u32 hvs_qp_scale: 4; /* QP scaling factor for CU QP adjust if hvs_qp_scale_enable is 1 */
+	u32 hvs_max_delta_qp; /* A maximum delta QP for HVS */
+	/*
+	 * A fixed bit ratio (1 ~ 255) for each picture of GOP's bit
+	 * allocation
+	 *
+	 * N = 0 ~ (MAX_GOP_SIZE - 1)
+	 * MAX_GOP_SIZE = 8
+	 *
+	 * for instance when MAX_GOP_SIZE is 3, fixed_bit_ratio0, fixed_bit_ratio1, and
+	 * fixed_bit_ratio2 can be set as 2, 1, and 1 respectively for
+	 * the fixed bit ratio 2:1:1. this is only valid when bit_alloc_mode is 2.
+	 */
+	u8 fixed_bit_ratio[MAX_GOP_NUM];
+	struct custom_gop_param gop_param; /* <<vpuapi_h_custom_gop_param>> */
+	u32 num_units_in_tick;
+	u32 time_scale;
+	u32 num_ticks_poc_diff_one;
+	s32 chroma_cb_qp_offset; /* the value of chroma(cb) QP offset */
+	s32 chroma_cr_qp_offset; /* the value of chroma(cr) QP offset */
+	s32 initial_rc_qp;
+	u32 nr_intra_weight_y;
+	u32 nr_intra_weight_cb; /* A weight to cb noise level for intra picture (0 ~ 31) */
+	u32 nr_intra_weight_cr; /* A weight to cr noise level for intra picture (0 ~ 31) */
+	u32 nr_inter_weight_y;
+	u32 nr_inter_weight_cb; /* A weight to cb noise level for inter picture (0 ~ 31) */
+	u32 nr_inter_weight_cr; /* A weight to cr noise level for inter picture (0 ~ 31) */
+	u32 nr_noise_sigma_y; /* Y noise standard deviation if nr_noise_est_enable is 0 */
+	u32 nr_noise_sigma_cb;/* cb noise standard deviation if nr_noise_est_enable is 0 */
+	u32 nr_noise_sigma_cr;/* cr noise standard deviation if nr_noise_est_enable is 0 */
+	u32 bg_thr_diff;
+	u32 bg_thr_mean_diff;
+	u32 bg_lambda_qp;
+	u32 bg_delta_qp;
+	u32 pu04_delta_rate: 8; /* added to the total cost of 4x4 blocks */
+	u32 pu08_delta_rate: 8; /* added to the total cost of 8x8 blocks */
+	u32 pu16_delta_rate: 8; /* added to the total cost of 16x16 blocks */
+	u32 pu32_delta_rate: 8; /* added to the total cost of 32x32 blocks */
+	u32 pu04_intra_planar_delta_rate: 8;
+	u32 pu04_intra_dc_delta_rate: 8;
+	u32 pu04_intra_angle_delta_rate: 8;
+	u32 pu08_intra_planar_delta_rate: 8;
+	u32 pu08_intra_dc_delta_rate: 8;
+	u32 pu08_intra_angle_delta_rate: 8;
+	u32 pu16_intra_planar_delta_rate: 8;
+	u32 pu16_intra_dc_delta_rate: 8;
+	u32 pu16_intra_angle_delta_rate: 8;
+	u32 pu32_intra_planar_delta_rate: 8;
+	u32 pu32_intra_dc_delta_rate: 8;
+	u32 pu32_intra_angle_delta_rate: 8;
+	u32 cu08_intra_delta_rate: 8;
+	u32 cu08_inter_delta_rate: 8;
+	u32 cu08_merge_delta_rate: 8;
+	u32 cu16_intra_delta_rate: 8;
+	u32 cu16_inter_delta_rate: 8;
+	u32 cu16_merge_delta_rate: 8;
+	u32 cu32_intra_delta_rate: 8;
+	u32 cu32_inter_delta_rate: 8;
+	u32 cu32_merge_delta_rate: 8;
+	u32 coef_clear_disable: 8;
+	u32 min_qp_i; /* A minimum QP of I picture for rate control */
+	u32 max_qp_i; /* A maximum QP of I picture for rate control */
+	u32 min_qp_p; /* A minimum QP of P picture for rate control */
+	u32 max_qp_p; /* A maximum QP of P picture for rate control */
+	u32 min_qp_b; /* A minimum QP of B picture for rate control */
+	u32 max_qp_b; /* A maximum QP of B picture for rate control */
+	u32 custom_lambda_addr; /* it specifies the address of custom lambda map */
+	u32 user_scaling_list_addr; /* it specifies the address of user scaling list file */
+	u32 avc_idr_period;/* A period of IDR picture (0 ~ 1024). 0 - implies an infinite period */
+	u32 avc_slice_arg;	/* the number of MB for a slice when avc_slice_mode is set with 1 */
+	u32 intra_mb_refresh_mode: 2; /* 0=none, 1=row, 2=column, 3=step-size-in-mb */
+	/**
+	 * it specifies an intra MB refresh interval. depending on intra_mb_refresh_mode,
+	 * it can mean one of the following.
+	 *
+	 * the number of consecutive MB rows for intra_mb_refresh_mode of 1
+	 * the number of consecutive MB columns for intra_mb_refresh_mode of 2
+	 * A step size in MB for intra_mb_refresh_mode of 3
+	 */
+	u32 intra_mb_refresh_arg;
+	u32 rc_weight_param;
+	u32 rc_weight_buf;
+
+	/* flags */
+	u32 en_still_picture: 1; /* still picture profile */
+	u32 tier: 1; /* 0=main, 1=high */
+	u32 independ_slice_mode : 1; /* 0=no-multi-slice, 1=slice-in-ctu-number*/
+	u32 avc_slice_mode: 1; /* 0=none, 1=slice-in-mb-number */
+	u32 entropy_coding_mode: 1; /* 0=CAVLC, 1=CABAC */
+	u32 lossless_enable: 1; /* enables lossless coding */
+	u32 const_intra_pred_flag: 1; /* enables constrained intra prediction */
+	u32 tmvp_enable: 1; /* enables temporal motion vector prediction */
+	u32 wpp_enable: 1;
+	u32 disable_deblk: 1; /* it disables in-loop deblocking filtering */
+	u32 lf_cross_slice_boundary_enable: 1;
+	u32 skip_intra_trans: 1;
+	u32 sao_enable: 1; /* it enables SAO (sample adaptive offset) */
+	u32 intra_nx_n_enable: 1; /* it enables intra nx_n p_us */
+	u32 cu_level_rc_enable: 1; /* it enable CU level rate control */
+	u32 hvs_qp_enable: 1; /* enable CU QP adjustment for subjective quality enhancement */
+	u32 roi_enable: 1; /* it enables ROI map. NOTE: it is valid when rate control is on */
+	u32 nr_y_enable: 1; /* it enables noise reduction algorithm to Y component */
+	u32 nr_noise_est_enable: 1;
+	u32 nr_cb_enable: 1; /* it enables noise reduction algorithm to cb component */
+	u32 nr_cr_enable: 1; /* it enables noise reduction algorithm to cr component */
+	u32 use_long_term: 1; /* it enables long-term reference function */
+	u32 monochrome_enable: 1; /* it enables monochrom encoding mode */
+	u32 strong_intra_smooth_enable: 1; /* it enables strong intra smoothing */
+	u32 weight_pred_enable: 1; /* it enables to use weighted prediction*/
+	u32 bg_detect_enable: 1; /* it enables background detection */
+	u32 custom_lambda_enable: 1; /* it enables custom lambda table */
+	u32 custom_md_enable: 1; /* it enables custom mode decision */
+	u32 rdo_skip: 1; /* it skips RDO(rate distortion optimization) */
+	u32 lambda_scaling_enable: 1; /* it enables lambda scaling using custom GOP */
+	u32 transform8x8_enable: 1; /* it enables 8x8 intra prediction and 8x8 transform */
+	u32 mb_level_rc_enable: 1; /* it enables MB-level rate control */
+	u32 s2fme_disable: 1; /* it disables s2me_fme (only for AVC encoder) */
+};
+
+struct enc_sub_frame_sync_config {
+	u32 sub_frame_sync_mode; /* 0=wire-based, 1=register-based */
+	u32 sub_frame_sync_on;
+};
+
+struct enc_open_param {
+	dma_addr_t bitstream_buffer;
+	unsigned int bitstream_buffer_size;
+	u32 pic_width; /* the width of a picture to be encoded in unit of sample */
+	u32 pic_height; /* the height of a picture to be encoded in unit of sample */
+	u32 frame_rate_info;/* desired fps */
+	u32 vbv_buffer_size;
+	u32 bit_rate; /* target bitrate in bps */
+	struct enc_wave_param wave_param;
+	enum cb_cr_order cbcr_order;
+	unsigned int stream_endian;
+	unsigned int source_endian;
+	enum packed_format_num packed_format; /* <<vpuapi_h_packed_format_num>> */
+	enum frame_buffer_format src_format;
+	/* enum frame_buffer_format output_format; not used yet */
+	u32 enc_hrd_rbsp_in_vps; /* it encodes the HRD syntax rbsp into VPS */
+	u32 hrd_rbsp_data_size; /* the bit size of the HRD rbsp data */
+	u32 hrd_rbsp_data_addr; /* the address of the HRD rbsp data */
+	u32 encode_vui_rbsp;
+	u32 vui_rbsp_data_size; /* the bit size of the VUI rbsp data */
+	u32 vui_rbsp_data_addr; /* the address of the VUI rbsp data */
+	u32 pri_axprot;
+	u32 pri_axcache;
+	bool ring_buffer_enable;
+	bool line_buf_int_en;
+	bool enable_pts; /* an enable flag to report PTS(presentation timestamp) */
+	u32 rc_enable : 1; /* rate control */
+	u32 enable_non_ref_fbc_write: 1;
+	u32 sub_frame_sync_enable: 1;
+	u32 sub_frame_sync_mode: 1;
+};
+
+struct enc_initial_info {
+	u32 min_frame_buffer_count; /* minimum number of frame buffer */
+	u32 min_src_frame_count; /* minimum number of source buffer */
+	u32 max_latency_pictures; /* maximum number of picture latency */
+	u32 seq_init_err_reason; /* error information */
+	u32 warn_info; /* warn information */
+	u32 vlc_buf_size; /* the size of task buffer */
+	u32 param_buf_size; /* the size of task buffer */
+};
+
+struct enc_code_opt {
+	u32 implicit_header_encode: 1;
+	u32 encode_vcl: 1; /* A flag to encode VCL nal unit explicitly */
+	u32 encode_vps: 1; /* A flag to encode VPS nal unit explicitly */
+	u32 encode_sps: 1; /* A flag to encode SPS nal unit explicitly */
+	u32 encode_pps: 1; /* A flag to encode PPS nal unit explicitly */
+	u32 encode_aud: 1; /* A flag to encode AUD nal unit explicitly */
+	u32 encode_eos: 1;
+	u32 encode_eob: 1;
+	u32 encode_vui: 1; /* A flag to encode VUI nal unit explicitly */
+};
+
+struct enc_param {
+	struct frame_buffer *source_frame;
+	dma_addr_t pic_stream_buffer_addr;
+	u64 pic_stream_buffer_size;
+	u32 force_pic_qp_i;
+	u32 force_pic_qp_p;
+	u32 force_pic_qp_b;
+	u32 force_pic_type: 2;
+	u32 src_idx; /* A source frame buffer index */
+	struct enc_code_opt code_option;
+	u32 use_cur_src_as_longterm_pic;
+	u32 use_longterm_ref;
+	u64 pts; /* the presentation timestamp (PTS) of input source */
+	struct wave_custom_map_opt custom_map_opt;
+	u32 wp_pix_sigma_y; /* pixel variance of Y component for weighted prediction */
+	u32 wp_pix_sigma_cb; /* pixel variance of cb component for weighted prediction */
+	u32 wp_pix_sigma_cr; /* pixel variance of cr component for weighted prediction */
+	u32 wp_pix_mean_y; /* pixel mean value of Y component for weighted prediction */
+	u32 wp_pix_mean_cb; /* pixel mean value of cb component for weighted prediction */
+	u32 wp_pix_mean_cr; /* pixel mean value of cr component for weighted prediction */
+	bool src_end_flag;
+	u32 skip_picture: 1;
+	u32 force_pic_qp_enable: 1; /* flag used to force picture quantization parameter */
+	u32 force_pic_type_enable: 1; /* A flag to use a force picture type */
+	u32 force_all_ctu_coef_drop_enable: 1; /* forces all coefficients to be zero after TQ */
+};
+
+struct enc_output_info {
+	dma_addr_t bitstream_buffer;
+	u32 bitstream_size; /* the byte size of encoded bitstream */
+	u32 pic_type: 2; /* <<vpuapi_h_pic_type>> */
+	s32 recon_frame_index;
+	dma_addr_t rd_ptr;
+	dma_addr_t wr_ptr;
+	u32 enc_pic_byte; /* the number of encoded picture bytes */
+	s32 enc_src_idx; /* the source buffer index of the currently encoded picture */
+	u32 enc_vcl_nut;
+	u32 error_reason; /* the error reason of the currently encoded picture */
+	u32 warn_info; /* the warning information of the currently encoded picture */
+	unsigned int frame_cycle; /* param for reporting the cycle number of encoding one frame*/
+	u64 pts;
+	u32 enc_host_cmd_tick; /* tick of ENC_PIC command for the picture */
+	u32 enc_encode_end_tick; /* end tick of encoding slices of the picture */
+};
+
+enum ENC_PIC_CODE_OPTION {
+	CODEOPT_ENC_HEADER_IMPLICIT = BIT(0),
+	CODEOPT_ENC_VCL = BIT(1), /* A flag to encode VCL nal unit explicitly */
+};
+
+enum GOP_PRESET_IDX {
+	PRESET_IDX_CUSTOM_GOP = 0, /* user defined GOP structure */
+	PRESET_IDX_ALL_I = 1, /* all intra, gopsize = 1 */
+	PRESET_IDX_IPP = 2, /* consecutive P, cyclic gopsize = 1 */
+	PRESET_IDX_IBBB = 3, /* consecutive B, cyclic gopsize = 1 */
+	PRESET_IDX_IBPBP = 4, /* gopsize = 2 */
+	PRESET_IDX_IBBBP = 5, /* gopsize = 4 */
+	PRESET_IDX_IPPPP = 6, /* consecutive P, cyclic gopsize = 4 */
+	PRESET_IDX_IBBBB = 7, /* consecutive B, cyclic gopsize = 4 */
+	PRESET_IDX_RA_IB = 8, /* random access, cyclic gopsize = 8 */
+	PRESET_IDX_IPP_SINGLE = 9, /* consecutive P, cyclic gopsize = 1, with single ref */
+};
+
+struct sec_axi_info {
+	u32 use_ip_enable;
+	u32 use_bit_enable;
+	u32 use_lf_row_enable: 1;
+	u32 use_enc_rdo_enable: 1;
+	u32 use_enc_lf_enable: 1;
+};
+
+struct dec_info {
+	struct dec_open_param open_param;
+	struct dec_initial_info initial_info;
+	struct dec_initial_info new_seq_info; /* temporal new sequence information */
+	dma_addr_t stream_wr_ptr;
+	dma_addr_t stream_rd_ptr;
+	u32 frame_display_flag;
+	dma_addr_t stream_buf_start_addr;
+	dma_addr_t stream_buf_end_addr;
+	u32 stream_buf_size;
+	struct vpu_buf vb_mv[MAX_REG_FRAME];
+	struct vpu_buf vb_fbc_y_tbl[MAX_REG_FRAME];
+	struct vpu_buf vb_fbc_c_tbl[MAX_REG_FRAME];
+	unsigned int num_of_decoding_fbs;
+	unsigned int num_of_display_fbs;
+	unsigned int stride;
+	enum mirror_direction mirror_direction;
+	unsigned int rotation_angle;
+	struct frame_buffer rotator_output;
+	unsigned int rotator_stride;
+	struct sec_axi_info sec_axi_info;
+	dma_addr_t user_data_buf_addr;
+	u32 user_data_enable;
+	u32 user_data_buf_size;
+	struct vpu_buf vb_work;
+	struct vpu_buf vb_task;
+	struct dec_output_info dec_out_info[WAVE5_MAX_FBS];
+	u32 seq_change_mask;
+	enum temporal_id_mode temp_id_select_mode;
+	u32 target_temp_id;
+	u32 target_spatial_id;
+	u32 instance_queue_count;
+	u32 report_queue_count;
+	u32 cycle_per_tick;
+	u32 product_code;
+	u32 vlc_buf_size;
+	u32 param_buf_size;
+	bool rotation_enable;
+	bool mirror_enable;
+	bool dering_enable;
+	bool initial_info_obtained;
+	bool reorder_enable;
+	bool thumbnail_mode;
+	bool first_cycle_check;
+	u32 stream_endflag: 1;
+};
+
+struct enc_info {
+	struct enc_open_param open_param;
+	struct enc_initial_info initial_info;
+	dma_addr_t stream_rd_ptr;
+	dma_addr_t stream_wr_ptr;
+	dma_addr_t stream_buf_start_addr;
+	dma_addr_t stream_buf_end_addr;
+	u32 stream_buf_size;
+	unsigned int num_frame_buffers;
+	unsigned int stride;
+	bool rotation_enable;
+	bool mirror_enable;
+	enum mirror_direction mirror_direction;
+	unsigned int rotation_angle;
+	bool initial_info_obtained;
+	bool ring_buffer_enable;
+	struct sec_axi_info sec_axi_info;
+	struct enc_sub_frame_sync_config sub_frame_sync_config;
+	bool line_buf_int_en;
+	struct vpu_buf vb_work;
+	struct vpu_buf vb_mv; /* col_mv buffer */
+	struct vpu_buf vb_fbc_y_tbl; /* FBC luma table buffer */
+	struct vpu_buf vb_fbc_c_tbl; /* FBC chroma table buffer */
+	struct vpu_buf vb_sub_sam_buf; /* sub-sampled buffer for ME */
+	struct vpu_buf vb_task;
+	u64 cur_pts; /* current timestamp in 90_k_hz */
+	u64 pts_map[32]; /* PTS mapped with source frame index */
+	u32 instance_queue_count;
+	u32 report_queue_count;
+	bool first_cycle_check;
+	u32 cycle_per_tick;
+	u32 product_code;
+	u32 vlc_buf_size;
+	u32 param_buf_size;
+};
+
+struct vpu_device {
+	struct device *dev;
+	struct v4l2_device v4l2_dev;
+	struct list_head instances;
+	struct video_device *video_dev_dec;
+	struct video_device *video_dev_enc;
+	struct mutex dev_lock; /* the lock for the src,dst v4l2 queues */
+	struct mutex hw_lock; /* lock hw configurations */
+	int irq;
+	enum product_id	product;
+	struct vpu_attr	attr;
+	struct vpu_buf common_mem;
+	u32 last_performance_cycles;
+	u32 sram_size;
+	struct gen_pool *sram_pool;
+	struct vpu_buf sram_buf;
+	void __iomem *vdb_register;
+	u32 product_code;
+	u32 ext_addr;
+	struct ida inst_ida;
+	struct clk_bulk_data *clks;
+	struct hrtimer hrtimer;
+	struct kthread_work work;
+	struct kthread_worker *worker;
+	int vpu_poll_interval;
+	int num_clks;
+	unsigned long opp_pixel_rate;
+	unsigned long opp_freq;
+};
+
+struct vpu_instance;
+
+struct vpu_instance_ops {
+	void (*start_process)(struct vpu_instance *inst);
+	void (*stop_process)(struct vpu_instance *inst);
+	void (*finish_process)(struct vpu_instance *inst);
+};
+
+/* for support GStreamer ver 1.20 over
+ * too old frame, eos sent too early
+ */
+struct timestamp_circ_buf {
+	u64 buf[MAX_TIMESTAMP_CIR_BUF];
+	int head;
+	int tail;
+};
+
+struct vpu_instance {
+	struct list_head list;
+	struct v4l2_fh v4l2_fh;
+	struct v4l2_ctrl_handler v4l2_ctrl_hdl;
+	struct vpu_device *dev;
+	struct v4l2_m2m_dev *v4l2_m2m_dev;
+	struct kfifo irq_status;
+	struct completion irq_done;
+
+	struct v4l2_pix_format_mplane src_fmt;
+	struct v4l2_pix_format_mplane dst_fmt;
+	enum v4l2_colorspace colorspace;
+	enum v4l2_xfer_func xfer_func;
+	enum v4l2_ycbcr_encoding ycbcr_enc;
+	enum v4l2_quantization quantization;
+	enum v4l2_hsv_encoding hsv_enc;
+
+	enum vpu_instance_state state;
+	enum vpu_instance_type type;
+	const struct vpu_instance_ops *ops;
+
+	enum wave_std std;
+	s32 id;
+	union {
+		struct enc_info enc_info;
+		struct dec_info dec_info;
+	} *codec_info;
+	struct vpu_rect pic_crop_rect;
+	struct frame_buffer frame_buf[MAX_REG_FRAME];
+	struct vpu_buf frame_vbuf[MAX_REG_FRAME];
+	u32 fbc_buf_count;
+	u32 dst_buf_count;
+	u32 queued_src_buf_num;
+	u32 queued_dst_buf_num;
+	struct list_head avail_src_bufs;
+	struct list_head avail_dst_bufs;
+	u32 conf_win_width;
+	u32 conf_win_height;
+	u64 timestamp;
+	struct timestamp_circ_buf time_stamp;
+	enum frame_buffer_format output_format;
+	bool cbcr_interleave;
+	bool nv21;
+	bool eos;
+
+	struct vpu_buf bitstream_vbuf;
+	bool thumbnail_mode;
+
+	unsigned int min_src_buf_count;
+	unsigned int src_buf_count;
+	unsigned int rot_angle;
+	unsigned int mirror_direction;
+	unsigned int bit_depth;
+	unsigned int frame_rate;
+	unsigned int vbv_buf_size;
+	unsigned int rc_mode;
+	unsigned int rc_enable;
+	unsigned int bit_rate;
+	struct enc_wave_param enc_param;
+	unsigned int *map_index;
+	unsigned long *mapped_dma_addr;
+	unsigned int cap_io_mode;
+	struct mutex *inst_lock;
+	unsigned long pixel_rate;
+};
+
+void wave5_vdi_write_register(struct vpu_device *vpu_dev, u32 addr, u32 data);
+u32 wave5_vdi_readl(struct vpu_device *vpu_dev, u32 addr);
+int wave5_vdi_clear_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb);
+int wave5_vdi_allocate_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb);
+int wave5_vdi_write_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb, size_t offset,
+			   u8 *data, size_t len, unsigned int endian);
+unsigned int wave5_vdi_convert_endian(struct vpu_device *vpu_dev, unsigned int endian);
+void wave5_vdi_free_dma_memory(struct vpu_device *vpu_dev, struct vpu_buf *vb);
+void wave5_vdi_allocate_sram(struct vpu_device *vpu_dev);
+void wave5_vdi_free_sram(struct vpu_device *vpu_dev);
+
+int wave5_vpu_init_with_bitcode(struct device *dev, u8 *bitcode, size_t size);
+void wave5_vpu_clear_interrupt_ex(struct vpu_instance *inst, u32 intr_flag);
+int wave5_vpu_get_version_info(struct device *dev, u32 *revision, unsigned int *product_id);
+int wave5_vpu_dec_open(struct vpu_instance *inst, struct dec_open_param *open_param);
+int wave5_vpu_dec_close(struct vpu_instance *inst, u32 *fail_res);
+int wave5_vpu_dec_issue_seq_init(struct vpu_instance *inst);
+int wave5_vpu_dec_complete_seq_init(struct vpu_instance *inst, struct dec_initial_info *info);
+int wave5_vpu_dec_register_frame_buffer_ex(struct vpu_instance *inst, int num_of_decoding_fbs,
+					   int num_of_display_fbs, int stride, int height,
+					   int map_type);
+int wave5_vpu_dec_start_one_frame(struct vpu_instance *inst, struct dec_param *param,
+				  u32 *res_fail);
+int wave5_vpu_dec_get_output_info(struct vpu_instance *inst, struct dec_output_info *info);
+int wave5_vpu_dec_set_rd_ptr(struct vpu_instance *inst, dma_addr_t addr, int update_wr_ptr);
+int wave5_vpu_dec_give_command(struct vpu_instance *inst, enum codec_command cmd, void *parameter);
+int wave5_vpu_dec_get_bitstream_buffer(struct vpu_instance *inst, dma_addr_t *prd_ptr,
+				       dma_addr_t *pwr_ptr, size_t *size);
+int wave5_vpu_dec_update_bitstream_buffer(struct vpu_instance *inst, size_t size);
+int wave5_vpu_dec_clr_disp_flag(struct vpu_instance *inst, int index);
+int wave5_vpu_dec_set_disp_flag(struct vpu_instance *inst, int index);
+
+int wave5_vpu_enc_open(struct vpu_instance *inst, struct enc_open_param *open_param);
+int wave5_vpu_enc_close(struct vpu_instance *inst, u32 *fail_res);
+int wave5_vpu_enc_issue_seq_init(struct vpu_instance *inst);
+int wave5_vpu_enc_complete_seq_init(struct vpu_instance *inst, struct enc_initial_info *info);
+int wave5_vpu_enc_register_frame_buffer(struct vpu_instance *inst, unsigned int num,
+					unsigned int stride, int height,
+					enum tiled_map_type map_type);
+int wave5_vpu_enc_start_one_frame(struct vpu_instance *inst, struct enc_param *param,
+				  u32 *fail_res);
+int wave5_vpu_enc_get_output_info(struct vpu_instance *inst, struct enc_output_info *info);
+int wave5_vpu_enc_give_command(struct vpu_instance *inst, enum codec_command cmd, void *parameter);
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpu.c b/drivers/media/platform/chips-media/wave5/wave5-vpu.c
--- a/drivers/media/platform/chips-media/wave5/wave5-vpu.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,487 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Wave5 series multi-standard codec IP - platform driver
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_opp.h>
+#include "wave5-vpu.h"
+#include "wave5-regdefine.h"
+#include "wave5-vpuconfig.h"
+#include "wave5.h"
+
+#define VPU_PLATFORM_DEVICE_NAME "vdec"
+#define VPU_CLK_NAME "vcodec"
+
+#define WAVE5_IS_ENC BIT(0)
+#define WAVE5_IS_DEC BIT(1)
+
+struct wave5_match_data {
+	int flags;
+	const char *fw_name;
+};
+
+static int vpu_poll_interval = 5;
+module_param(vpu_poll_interval, int, 0644);
+
+int wave5_vpu_wait_interrupt(struct vpu_instance *inst, unsigned int timeout)
+{
+	int ret;
+
+	ret = wait_for_completion_timeout(&inst->irq_done,
+					  msecs_to_jiffies(timeout));
+	if (!ret)
+		return -ETIMEDOUT;
+
+	reinit_completion(&inst->irq_done);
+
+	return 0;
+}
+
+static void wave5_vpu_get_interrupt_for_inst(struct vpu_instance *inst, u32 status)
+{
+	struct vpu_device *dev = inst->dev;
+	u32 seq_done;
+	u32 cmd_done;
+	int val;
+
+	seq_done = wave5_vdi_readl(dev, W5_RET_SEQ_DONE_INSTANCE_INFO);
+	cmd_done = wave5_vdi_readl(dev, W5_RET_QUEUE_CMD_DONE_INST);
+
+	if (status & BIT(INT_WAVE5_INIT_SEQ)) {
+		if (seq_done & BIT(inst->id)) {
+			seq_done &= ~BIT(inst->id);
+			wave5_vdi_write_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO, seq_done);
+			val = BIT(INT_WAVE5_INIT_SEQ);
+			kfifo_in(&inst->irq_status, &val, sizeof(int));
+		}
+	}
+	if (status & BIT(INT_WAVE5_ENC_SET_PARAM)) {
+		if (seq_done & BIT(inst->id)) {
+			seq_done &= ~BIT(inst->id);
+			wave5_vdi_write_register(dev, W5_RET_SEQ_DONE_INSTANCE_INFO, seq_done);
+			val = BIT(INT_WAVE5_ENC_SET_PARAM);
+			kfifo_in(&inst->irq_status, &val, sizeof(int));
+		}
+	}
+	if (status & BIT(INT_WAVE5_DEC_PIC) ||
+	    status & BIT(INT_WAVE5_ENC_PIC)) {
+		if (cmd_done & BIT(inst->id)) {
+			cmd_done &= ~BIT(inst->id);
+			wave5_vdi_write_register(dev, W5_RET_QUEUE_CMD_DONE_INST, cmd_done);
+			val = BIT(INT_WAVE5_DEC_PIC);
+			kfifo_in(&inst->irq_status, &val, sizeof(int));
+		}
+	}
+}
+
+static irqreturn_t wave5_vpu_irq(int irq, void *dev_id)
+{
+	struct vpu_device *dev = dev_id;
+
+	if (wave5_vdi_readl(dev, W5_VPU_VPU_INT_STS)) {
+		struct vpu_instance *inst;
+		u32 irq_status = wave5_vdi_readl(dev, W5_VPU_VINT_REASON);
+
+		list_for_each_entry(inst, &dev->instances, list) {
+			wave5_vpu_get_interrupt_for_inst(inst, irq_status);
+		}
+
+		wave5_vdi_write_register(dev, W5_VPU_VINT_REASON_CLR, irq_status);
+		wave5_vdi_write_register(dev, W5_VPU_VINT_CLEAR, 0x1);
+
+		return IRQ_WAKE_THREAD;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wave5_vpu_irq_thread(int irq, void *dev_id)
+{
+	struct vpu_device *dev = dev_id;
+	struct vpu_instance *inst;
+	int irq_status, ret;
+	u32 val;
+
+	list_for_each_entry(inst, &dev->instances, list) {
+		while (kfifo_len(&inst->irq_status)) {
+			struct vpu_instance *curr;
+
+			curr = v4l2_m2m_get_curr_priv(inst->v4l2_m2m_dev);
+			if (curr) {
+				inst->ops->finish_process(inst);
+			} else {
+				ret = kfifo_out(&inst->irq_status, &irq_status, sizeof(int));
+				if (!ret)
+					break;
+
+				val = wave5_vdi_readl(dev, W5_VPU_VINT_REASON_USR);
+				val &= ~irq_status;
+				wave5_vdi_write_register(dev, W5_VPU_VINT_REASON_USR, val);
+				complete(&inst->irq_done);
+			}
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void wave5_vpu_irq_work_fn(struct kthread_work *work)
+{
+	struct vpu_device *dev = container_of(work, struct vpu_device, work);
+	struct vpu_instance *inst;
+	int irq_status, ret;
+	u32 val;
+
+	list_for_each_entry(inst, &dev->instances, list) {
+		while (kfifo_len(&inst->irq_status)) {
+			struct vpu_instance *curr;
+
+			curr = v4l2_m2m_get_curr_priv(inst->v4l2_m2m_dev);
+			if (curr) {
+				inst->ops->finish_process(inst);
+			} else {
+				ret = kfifo_out(&inst->irq_status, &irq_status, sizeof(int));
+				if (!ret)
+					break;
+
+				val = wave5_vdi_readl(dev, W5_VPU_VINT_REASON_USR);
+				val &= ~irq_status;
+				wave5_vdi_write_register(dev, W5_VPU_VINT_REASON_USR, val);
+				complete(&inst->irq_done);
+			}
+		}
+	}
+}
+
+static enum hrtimer_restart wave5_vpu_timer_callback(struct hrtimer *timer)
+{
+	irqreturn_t ret;
+	struct vpu_device *dev =
+			container_of(timer, struct vpu_device, hrtimer);
+
+	ret = wave5_vpu_irq(0, dev);
+
+	if (ret == IRQ_WAKE_THREAD)
+		kthread_queue_work(dev->worker, &dev->work);
+
+	hrtimer_forward_now(timer, ns_to_ktime(vpu_poll_interval * NSEC_PER_MSEC));
+
+	return HRTIMER_RESTART;
+}
+
+static int wave5_vpu_load_firmware(struct device *dev, const char *fw_name)
+{
+	const struct firmware *fw;
+	int ret;
+	u32 revision;
+	unsigned int product_id;
+
+	ret = request_firmware(&fw, fw_name, dev);
+	if (ret) {
+		dev_err(dev, "request_firmware, fail: %d\n", ret);
+		return ret;
+	}
+
+	ret = wave5_vpu_init_with_bitcode(dev, (u8 *)fw->data, fw->size);
+	if (ret) {
+		dev_err(dev, "vpu_init_with_bitcode, fail: %d\n", ret);
+		goto release_fw;
+	}
+	release_firmware(fw);
+
+	ret = wave5_vpu_get_version_info(dev, &revision, &product_id);
+	if (ret) {
+		dev_err(dev, "vpu_get_version_info fail: %d\n", ret);
+		goto err_without_release;
+	}
+
+	dev_dbg(dev, "%s: enum product_id: %08x, fw revision: %u\n",
+		__func__, product_id, revision);
+
+	return 0;
+
+release_fw:
+	release_firmware(fw);
+err_without_release:
+	return ret;
+}
+
+static __maybe_unused int wave5_pm_suspend(struct device *dev)
+{
+	struct vpu_device *vpu = dev_get_drvdata(dev);
+
+	if (pm_runtime_suspended(dev))
+		return 0;
+
+	wave5_vpu_sleep_wake(dev, true, NULL, 0);
+	clk_bulk_disable_unprepare(vpu->num_clks, vpu->clks);
+
+	return 0;
+}
+
+static __maybe_unused int wave5_pm_resume(struct device *dev)
+{
+	struct vpu_device *vpu = dev_get_drvdata(dev);
+	int ret = 0;
+
+	wave5_vpu_sleep_wake(dev, false, NULL, 0);
+	ret = clk_bulk_prepare_enable(vpu->num_clks, vpu->clks);
+	if (ret) {
+		dev_err(dev, "Enabling clocks, fail: %d\n", ret);
+		return ret;
+	}
+	return ret;
+}
+
+static __maybe_unused int wave5_suspend(struct device *dev)
+{
+	struct vpu_device *vpu = dev_get_drvdata(dev);
+	struct vpu_instance *inst;
+
+	list_for_each_entry(inst, &vpu->instances, list) {
+		v4l2_m2m_suspend(inst->v4l2_m2m_dev);
+	}
+
+	return pm_runtime_force_suspend(dev);
+}
+
+static __maybe_unused int wave5_resume(struct device *dev)
+{
+	struct vpu_device *vpu = dev_get_drvdata(dev);
+	struct vpu_instance *inst;
+	int ret = 0;
+
+	ret = pm_runtime_force_resume(dev);
+	if (ret < 0)
+		return ret;
+	list_for_each_entry(inst, &vpu->instances, list) {
+		v4l2_m2m_resume(inst->v4l2_m2m_dev);
+	}
+	return ret;
+}
+
+static const struct dev_pm_ops wave5_pm_ops = {
+	SET_RUNTIME_PM_OPS(wave5_pm_suspend, wave5_pm_resume, NULL)
+};
+
+static int wave5_vpu_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct vpu_device *dev;
+	const struct wave5_match_data *match_data;
+
+	match_data = device_get_match_data(&pdev->dev);
+	if (!match_data) {
+		dev_err(&pdev->dev, "missing device match data\n");
+		return -EINVAL;
+	}
+
+	/* physical addresses limited to 48  bits */
+	dma_set_mask(&pdev->dev, DMA_BIT_MASK(48));
+	dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(48));
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->vdb_register = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(dev->vdb_register))
+		return PTR_ERR(dev->vdb_register);
+	ida_init(&dev->inst_ida);
+
+	mutex_init(&dev->dev_lock);
+	mutex_init(&dev->hw_lock);
+	dev_set_drvdata(&pdev->dev, dev);
+	dev->dev = &pdev->dev;
+
+	ret = devm_clk_bulk_get_all(&pdev->dev, &dev->clks);
+
+	/* continue without clock, assume externally managed */
+	if (ret < 0) {
+		dev_warn(&pdev->dev, "Getting clocks, fail: %d\n", ret);
+		ret = 0;
+	}
+	dev->num_clks = ret;
+
+	ret = clk_bulk_prepare_enable(dev->num_clks, dev->clks);
+	if (ret) {
+		dev_err(&pdev->dev, "Enabling clocks, fail: %d\n", ret);
+		return ret;
+	}
+
+	ret = of_property_read_u32(pdev->dev.of_node, "sram-size",
+				   &dev->sram_size);
+	if (ret) {
+		dev_warn(&pdev->dev, "sram-size not found\n");
+		dev->sram_size = 0;
+	}
+
+	dev->sram_pool = of_gen_pool_get(pdev->dev.of_node, "sram", 0);
+	if (!dev->sram_pool)
+		dev_warn(&pdev->dev, "sram node not found\n");
+
+	dev->product_code = wave5_vdi_readl(dev, VPU_PRODUCT_CODE_REGISTER);
+	ret = wave5_vdi_init(&pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "wave5_vdi_init, fail: %d\n", ret);
+		goto err_clk_dis;
+	}
+	dev->ext_addr = ((dev->common_mem.daddr >> 32) & 0xFFFF);
+	dev->product = wave5_vpu_get_product_id(dev);
+
+	dev->irq = platform_get_irq(pdev, 0);
+	if (dev->irq < 0) {
+		dev_err(&pdev->dev, "failed to get irq resource, falling back to polling\n");
+		hrtimer_init(&dev->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
+		dev->hrtimer.function = &wave5_vpu_timer_callback;
+		dev->worker = kthread_create_worker(0, "vpu_irq_thread");
+		if (IS_ERR(dev->worker)) {
+			dev_err(&pdev->dev, "failed to create vpu irq worker\n");
+			ret = PTR_ERR(dev->worker);
+			goto err_vdi_release;
+		}
+		dev->vpu_poll_interval = vpu_poll_interval;
+		kthread_init_work(&dev->work, wave5_vpu_irq_work_fn);
+	} else {
+		ret = devm_request_threaded_irq(&pdev->dev, dev->irq, wave5_vpu_irq,
+						wave5_vpu_irq_thread, 0, "vpu_irq", dev);
+		if (ret) {
+			dev_err(&pdev->dev, "Register interrupt handler, fail: %d\n", ret);
+			goto err_vdi_release;
+		}
+	}
+
+	INIT_LIST_HEAD(&dev->instances);
+	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "v4l2_device_register, fail: %d\n", ret);
+		goto err_vdi_release;
+	}
+
+	if (match_data->flags & WAVE5_IS_DEC) {
+		ret = wave5_vpu_dec_register_device(dev);
+		if (ret) {
+			dev_err(&pdev->dev, "wave5_vpu_dec_register_device, fail: %d\n", ret);
+			goto err_v4l2_unregister;
+		}
+	}
+	if (match_data->flags & WAVE5_IS_ENC) {
+		ret = wave5_vpu_enc_register_device(dev);
+		if (ret) {
+			dev_err(&pdev->dev, "wave5_vpu_enc_register_device, fail: %d\n", ret);
+			goto err_dec_unreg;
+		}
+	}
+
+
+	ret = wave5_vpu_load_firmware(&pdev->dev, match_data->fw_name);
+	if (ret) {
+		dev_err(&pdev->dev, "wave5_vpu_load_firmware, fail: %d\n", ret);
+		goto err_enc_unreg;
+	}
+
+	ret = dev_pm_opp_of_add_table(&pdev->dev);
+	if (ret && ret != -ENODEV)
+		dev_err(&pdev->dev, "Invalid OPP table in device tree\n");
+
+	dev_dbg(&pdev->dev, "Added wave5 driver with caps: %s %s and product code: 0x%x\n",
+		(match_data->flags & WAVE5_IS_ENC) ? "'ENCODE'" : "",
+		(match_data->flags & WAVE5_IS_DEC) ? "'DECODE'" : "",
+		dev->product_code);
+
+	pm_runtime_enable(&pdev->dev);
+	wave5_vpu_sleep_wake(&pdev->dev, true, NULL, 0);
+
+	return 0;
+
+err_enc_unreg:
+	if (match_data->flags & WAVE5_IS_ENC)
+		wave5_vpu_enc_unregister_device(dev);
+err_dec_unreg:
+	if (match_data->flags & WAVE5_IS_DEC)
+		wave5_vpu_dec_unregister_device(dev);
+err_v4l2_unregister:
+	v4l2_device_unregister(&dev->v4l2_dev);
+err_vdi_release:
+	wave5_vdi_release(&pdev->dev);
+err_clk_dis:
+	clk_bulk_disable_unprepare(dev->num_clks, dev->clks);
+
+	return ret;
+}
+
+static int wave5_vpu_remove(struct platform_device *pdev)
+{
+	struct vpu_device *dev = dev_get_drvdata(&pdev->dev);
+
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	dev_pm_opp_of_remove_table(&pdev->dev);
+	if (dev->irq < 0) {
+		kthread_destroy_worker(dev->worker);
+		hrtimer_cancel(&dev->hrtimer);
+	}
+
+	clk_bulk_disable_unprepare(dev->num_clks, dev->clks);
+	wave5_vpu_enc_unregister_device(dev);
+	wave5_vpu_dec_unregister_device(dev);
+	v4l2_device_unregister(&dev->v4l2_dev);
+	wave5_vdi_release(&pdev->dev);
+	ida_destroy(&dev->inst_ida);
+
+	return 0;
+}
+
+static const struct wave5_match_data wave511_data = {
+	.flags = WAVE5_IS_DEC,
+	.fw_name = "wave511_dec_fw.bin",
+};
+
+static const struct wave5_match_data wave521_data = {
+	.flags = WAVE5_IS_ENC,
+	.fw_name = "wave521_enc_fw.bin",
+};
+
+static const struct wave5_match_data wave521c_data = {
+	.flags = WAVE5_IS_ENC | WAVE5_IS_DEC,
+	.fw_name = "cnm/wave521c_codec_fw.bin",
+};
+
+static const struct wave5_match_data default_match_data = {
+	.flags = WAVE5_IS_ENC | WAVE5_IS_DEC,
+	.fw_name = "chagall.bin",
+};
+
+static const struct of_device_id wave5_dt_ids[] = {
+	{ .compatible = "cnm,cm511-vpu", .data = &wave511_data },
+	{ .compatible = "cnm,cm517-vpu", .data = &default_match_data },
+	{ .compatible = "cnm,cm521-vpu", .data = &wave521_data },
+	{ .compatible = "cnm,cm521c-vpu", .data = &wave521c_data },
+	{ .compatible = "cnm,cm521c-dual-vpu", .data = &wave521c_data },
+	{ .compatible = "cnm,cm521e1-vpu", .data = &default_match_data },
+	{ .compatible = "cnm,cm537-vpu", .data = &default_match_data },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, wave5_dt_ids);
+
+static struct platform_driver wave5_vpu_driver = {
+	.driver = {
+		.name = VPU_PLATFORM_DEVICE_NAME,
+		.of_match_table = of_match_ptr(wave5_dt_ids),
+		.pm = &wave5_pm_ops,
+		},
+	.probe = wave5_vpu_probe,
+	.remove = wave5_vpu_remove,
+};
+
+module_platform_driver(wave5_vpu_driver);
+MODULE_DESCRIPTION("chips&media VPU V4L2 driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h b/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h
--- a/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpuconfig.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave5 series multi-standard codec IP - product config definitions
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+
+#ifndef _VPU_CONFIG_H_
+#define _VPU_CONFIG_H_
+
+#define WAVE517_CODE                    0x5170
+#define WAVE537_CODE                    0x5370
+#define WAVE511_CODE                    0x5110
+#define WAVE521_CODE                    0x5210
+#define WAVE521C_CODE                   0x521c
+#define WAVE521C_DUAL_CODE              0x521d  // wave521 dual core
+#define WAVE521E1_CODE                  0x5211
+
+#define PRODUCT_CODE_W_SERIES(x) ({					\
+		int c = x;						\
+		((c) == WAVE517_CODE ||	(c) == WAVE537_CODE ||		\
+		 (c) == WAVE511_CODE || (c) == WAVE521_CODE ||		\
+		 (c) == WAVE521E1_CODE || (c) == WAVE521C_CODE ||	\
+		 (c) == WAVE521C_DUAL_CODE);				\
+})
+
+#define WAVE517_WORKBUF_SIZE            (2 * 1024 * 1024)
+#define WAVE521ENC_WORKBUF_SIZE         (128 * 1024)      //HEVC 128K, AVC 40K
+#define WAVE521DEC_WORKBUF_SIZE         (1784 * 1024)
+
+#define MAX_NUM_INSTANCE                32
+
+#define W5_MIN_ENC_PIC_WIDTH            256
+#define W5_MIN_ENC_PIC_HEIGHT           128
+#define W5_MAX_ENC_PIC_WIDTH            8192
+#define W5_MAX_ENC_PIC_HEIGHT           8192
+
+//  application specific configuration
+#define VPU_ENC_TIMEOUT                 60000
+#define VPU_DEC_TIMEOUT                 60000
+
+#define HOST_ENDIAN                     VDI_128BIT_LITTLE_ENDIAN
+#define VPU_FRAME_ENDIAN                HOST_ENDIAN
+#define VPU_STREAM_ENDIAN               HOST_ENDIAN
+#define VPU_USER_DATA_ENDIAN            HOST_ENDIAN
+#define VPU_SOURCE_ENDIAN               HOST_ENDIAN
+
+// for WAVE encoder
+#define USE_SRC_PRP_AXI         0
+#define USE_SRC_PRI_AXI         1
+#define DEFAULT_SRC_AXI         USE_SRC_PRP_AXI
+
+/************************************************************************/
+/* VPU COMMON MEMORY                                                    */
+/************************************************************************/
+#define VLC_BUF_NUM                     (2)
+
+#define COMMAND_QUEUE_DEPTH             (2)
+
+#define W5_REMAP_INDEX0                 0
+#define W5_REMAP_INDEX1                 1
+#define W5_REMAP_MAX_SIZE               (1024 * 1024)
+
+#define WAVE5_MAX_CODE_BUF_SIZE         (2 * 1024 * 1024)
+#define WAVE5_TEMPBUF_OFFSET            WAVE5_MAX_CODE_BUF_SIZE
+#define WAVE5_TEMPBUF_SIZE              (1024 * 1024)
+
+#define SIZE_COMMON                 (WAVE5_MAX_CODE_BUF_SIZE + WAVE5_TEMPBUF_SIZE)
+
+//=====4. VPU REPORT MEMORY  ======================//
+
+#define WAVE5_UPPER_PROC_AXI_ID     0x0
+
+#define WAVE5_PROC_AXI_ID           0x0
+#define WAVE5_PRP_AXI_ID            0x0
+#define WAVE5_FBD_Y_AXI_ID          0x0
+#define WAVE5_FBC_Y_AXI_ID          0x0
+#define WAVE5_FBD_C_AXI_ID          0x0
+#define WAVE5_FBC_C_AXI_ID          0x0
+#define WAVE5_SEC_AXI_ID            0x0
+#define WAVE5_PRI_AXI_ID            0x0
+
+#define WAVE5_PROC_AXI_AXPROT       0x0
+#define WAVE5_PROC_AXI_AXCACHE      0x0
+#define WAVE5_PROC_AXI_EXT_ADDR     0x0
+#define WAVE5_SEC_AXI_AXPROT        0x0
+#define WAVE5_SEC_AXI_AXCACHE       0x0
+#define WAVE5_SEC_AXI_EXT_ADDR      0x0
+
+#endif  /* _VPU_CONFIG_H_ */
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c
--- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,1727 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Wave5 series multi-standard codec IP - decoder interface
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+#include <linux/pm_runtime.h>
+
+#include "wave5-helper.h"
+
+#define VPU_DEC_DEV_NAME "C&M Wave5 VPU decoder"
+#define VPU_DEC_DRV_NAME "wave5-dec"
+#define V4L2_CID_VPU_THUMBNAIL_MODE (V4L2_CID_USER_BASE + 0x1001)
+
+#define DEFAULT_SRC_SIZE(width, height) ({			\
+	(width) * (height) / 8 * 3;					\
+})
+
+static const struct vpu_format dec_fmt_list[FMT_TYPES][MAX_FMTS] = {
+	[VPU_FMT_TYPE_CODEC] = {
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_HEVC,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_H264,
+			.max_width = 8192,
+			.min_width = 32,
+			.max_height = 4320,
+			.min_height = 32,
+		},
+	},
+	[VPU_FMT_TYPE_RAW] = {
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_YUV420,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_NV12,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_NV21,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_YUV422P,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_NV16,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_NV61,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_YUV420M,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_NV12M,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_NV21M,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_YUV422M,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_NV16M,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_NV61M,
+			.max_width = 8192,
+			.min_width = 8,
+			.max_height = 4320,
+			.min_height = 8,
+		},
+	}
+};
+
+static enum wave_std wave5_to_vpu_codstd(unsigned int v4l2_pix_fmt)
+{
+	switch (v4l2_pix_fmt) {
+	case V4L2_PIX_FMT_H264:
+		return W_AVC_DEC;
+	case V4L2_PIX_FMT_HEVC:
+		return W_HEVC_DEC;
+	default:
+		return STD_UNKNOWN;
+	}
+}
+
+static void wave5_handle_bitstream_buffer(struct vpu_instance *inst)
+{
+	struct v4l2_m2m_buffer *buf, *n;
+	int ret;
+
+	v4l2_m2m_for_each_src_buf_safe(inst->v4l2_fh.m2m_ctx, buf, n) {
+		struct vb2_v4l2_buffer *vbuf = &buf->vb;
+		struct vpu_buffer *vpu_buf = wave5_to_vpu_buf(vbuf);
+		size_t src_size = vb2_get_plane_payload(&vbuf->vb2_buf, 0);
+		void *src_buf = vb2_plane_vaddr(&vbuf->vb2_buf, 0);
+		dma_addr_t rd_ptr = 0;
+		dma_addr_t wr_ptr = 0;
+		size_t remain_size = 0;
+		size_t offset;
+
+		if (vpu_buf->consumed) {
+			dev_dbg(inst->dev->dev, "already consumed src buf (%u)\n",
+				vbuf->vb2_buf.index);
+			continue;
+		}
+
+		if (!src_buf) {
+			dev_dbg(inst->dev->dev,
+				"%s: Acquiring kernel pointer to src buf (%u), fail\n",
+				__func__, vbuf->vb2_buf.index);
+			break;
+		}
+
+		ret = wave5_vpu_dec_get_bitstream_buffer(inst, &rd_ptr, &wr_ptr, &remain_size);
+		if (ret) {
+			dev_err(inst->dev->dev, "Getting the bitstream buffer, fail: %d\n",
+				ret);
+			return;
+		}
+
+		if (remain_size < src_size) {
+			dev_dbg(inst->dev->dev,
+				"%s: remaining size: %zu < source size: %zu for src buf (%u)\n",
+				__func__, remain_size, src_size, vbuf->vb2_buf.index);
+			break;
+		}
+
+		offset = wr_ptr - inst->bitstream_vbuf.daddr;
+		if (wr_ptr + src_size > inst->bitstream_vbuf.daddr + inst->bitstream_vbuf.size) {
+			size_t size;
+
+			size = inst->bitstream_vbuf.daddr + inst->bitstream_vbuf.size - wr_ptr;
+			ret = wave5_vdi_write_memory(inst->dev, &inst->bitstream_vbuf, offset,
+						     (u8 *)src_buf, size, VDI_128BIT_LITTLE_ENDIAN);
+			if (ret < 0) {
+				dev_dbg(inst->dev->dev,
+					"%s: 1/2 write src buf (%u) into bitstream buf, fail: %d\n",
+					__func__, vbuf->vb2_buf.index, ret);
+				break;
+			}
+			ret = wave5_vdi_write_memory(inst->dev, &inst->bitstream_vbuf, 0,
+						     (u8 *)src_buf + size, src_size - size,
+						     VDI_128BIT_LITTLE_ENDIAN);
+			if (ret < 0) {
+				dev_dbg(inst->dev->dev,
+					"%s: 2/2 write src buf (%u) into bitstream buf, fail: %d\n",
+					__func__, vbuf->vb2_buf.index, ret);
+				break;
+			}
+		} else {
+			ret = wave5_vdi_write_memory(inst->dev, &inst->bitstream_vbuf, offset,
+						     (u8 *)src_buf, src_size,
+						     VDI_128BIT_LITTLE_ENDIAN);
+			if (ret < 0) {
+				dev_dbg(inst->dev->dev,
+					"%s: write src buf (%u) into bitstream buf, fail: %d",
+					__func__, vbuf->vb2_buf.index, ret);
+				break;
+			}
+		}
+
+		ret = wave5_vpu_dec_update_bitstream_buffer(inst, src_size);
+		if (ret) {
+			dev_dbg(inst->dev->dev,
+				"vpu_dec_update_bitstream_buffer fail: %d for src buf (%u)\n",
+				ret, vbuf->vb2_buf.index);
+			break;
+		}
+
+		vpu_buf->consumed = true;
+	}
+}
+
+static void wave5_handle_src_buffer(struct vpu_instance *inst)
+{
+	struct vb2_v4l2_buffer *src_buf;
+	int head = 0;
+
+	src_buf = v4l2_m2m_next_src_buf(inst->v4l2_fh.m2m_ctx);
+	if (src_buf) {
+		struct vpu_buffer *vpu_buf = wave5_to_vpu_buf(src_buf);
+
+		if (vpu_buf->consumed) {
+			dev_dbg(inst->dev->dev, "%s: already consumed buffer\n", __func__);
+			src_buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx);
+			head = inst->time_stamp.head;
+			inst->time_stamp.buf[head] = src_buf->vb2_buf.timestamp;
+			inst->time_stamp.head++;
+
+			if (IS_WRAP(inst->time_stamp.head, MAX_TIMESTAMP_CIR_BUF) == 0)
+				inst->time_stamp.head = 0;
+
+			v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+		}
+	}
+}
+
+static void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp, unsigned int width,
+				 unsigned int height)
+{
+	switch (pix_mp->pixelformat) {
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+		pix_mp->width = round_up(width, 32);
+		pix_mp->height = round_up(height, 16);
+		pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
+		pix_mp->plane_fmt[0].sizeimage = width * height * 3 / 2;
+		break;
+	case V4L2_PIX_FMT_YUV422P:
+	case V4L2_PIX_FMT_NV16:
+	case V4L2_PIX_FMT_NV61:
+		pix_mp->width = round_up(width, 32);
+		pix_mp->height = round_up(height, 16);
+		pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
+		pix_mp->plane_fmt[0].sizeimage = width * height * 2;
+		break;
+	case V4L2_PIX_FMT_YUV420M:
+		pix_mp->width = round_up(width, 32);
+		pix_mp->height = round_up(height, 16);
+		pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
+		pix_mp->plane_fmt[0].sizeimage = width * height;
+		pix_mp->plane_fmt[1].bytesperline = round_up(width, 32) / 2;
+		pix_mp->plane_fmt[1].sizeimage = width * height / 4;
+		pix_mp->plane_fmt[2].bytesperline = round_up(width, 32) / 2;
+		pix_mp->plane_fmt[2].sizeimage = width * height / 4;
+		break;
+	case V4L2_PIX_FMT_NV12M:
+	case V4L2_PIX_FMT_NV21M:
+		pix_mp->width = round_up(width, 32);
+		pix_mp->height = round_up(height, 16);
+		pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
+		pix_mp->plane_fmt[0].sizeimage = width * height;
+		pix_mp->plane_fmt[1].bytesperline = round_up(width, 32);
+		pix_mp->plane_fmt[1].sizeimage = width * height / 2;
+		break;
+	case V4L2_PIX_FMT_YUV422M:
+		pix_mp->width = round_up(width, 32);
+		pix_mp->height = round_up(height, 16);
+		pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
+		pix_mp->plane_fmt[0].sizeimage = width * height;
+		pix_mp->plane_fmt[1].bytesperline = round_up(width, 32) / 2;
+		pix_mp->plane_fmt[1].sizeimage = width * height / 2;
+		pix_mp->plane_fmt[2].bytesperline = round_up(width, 32) / 2;
+		pix_mp->plane_fmt[2].sizeimage = width * height / 2;
+		break;
+	case V4L2_PIX_FMT_NV16M:
+	case V4L2_PIX_FMT_NV61M:
+		pix_mp->width = round_up(width, 32);
+		pix_mp->height = round_up(height, 16);
+		pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
+		pix_mp->plane_fmt[0].sizeimage = width * height;
+		pix_mp->plane_fmt[1].bytesperline = round_up(width, 32);
+		pix_mp->plane_fmt[1].sizeimage = width * height;
+		break;
+	default:
+		pix_mp->width = width;
+		pix_mp->height = height;
+		pix_mp->plane_fmt[0].bytesperline = 0;
+		pix_mp->plane_fmt[0].sizeimage = max(DEFAULT_SRC_SIZE(width, height),
+						     pix_mp->plane_fmt[0].sizeimage);
+		break;
+	}
+}
+
+static void wave5_vpu_dec_start_decode(struct vpu_instance *inst)
+{
+	struct dec_param pic_param;
+	int ret;
+	u32 fail_res = 0;
+
+	memset(&pic_param, 0, sizeof(struct dec_param));
+
+	ret = wave5_vpu_dec_start_one_frame(inst, &pic_param, &fail_res);
+	if (ret && fail_res != WAVE5_SYSERR_QUEUEING_FAIL) {
+		struct vb2_v4l2_buffer *src_buf;
+
+		src_buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx);
+		inst->state = VPU_INST_STATE_STOP;
+		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+	}
+}
+
+static void wave5_vpu_dec_stop_decode(struct vpu_instance *inst)
+{
+	unsigned int i;
+	int ret;
+
+	inst->state = VPU_INST_STATE_STOP;
+
+	ret = wave5_vpu_dec_update_bitstream_buffer(inst, 0);
+	if (ret) {
+		dev_warn(inst->dev->dev,
+			 "Setting EOS for the bitstream, fail: %d\n", ret);
+	}
+
+	for (i = 0; i < inst->dst_buf_count; i++) {
+		ret = wave5_vpu_dec_clr_disp_flag(inst, i);
+		if (ret) {
+			dev_dbg(inst->dev->dev,
+				"%s: Clearing the display flag of buffer index: %u, fail: %d\n",
+				__func__, i, ret);
+		}
+	}
+
+	v4l2_m2m_job_finish(inst->v4l2_m2m_dev, inst->v4l2_fh.m2m_ctx);
+}
+
+static void wave5_handle_display_frame(struct vpu_instance *inst,
+				       struct dec_output_info *info, int index_to_remove)
+{
+	int stride = info->disp_frame.stride;
+	int height = info->disp_pic_height - info->rc_display.bottom;
+	unsigned int size;
+	int tail = 0;
+	struct vb2_v4l2_buffer *dst_buf =
+		v4l2_m2m_dst_buf_remove_by_idx(inst->v4l2_fh.m2m_ctx,
+					       index_to_remove);
+	if (dst_buf == NULL) {
+		pr_err("%s vb2 buffer not found index_to_remove : %d : %d\n",
+		       __func__, index_to_remove, info->index_frame_display);
+		return;
+	}
+
+	if (inst->dst_fmt.num_planes == 1) {
+		if (inst->output_format == FORMAT_422)
+			size = stride * height * 2;
+		else
+			size = stride * height * 3 / 2;
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, size);
+	} else if (inst->dst_fmt.num_planes == 2) {
+		size = stride * height;
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, size);
+		if (inst->output_format == FORMAT_422)
+			size = stride * height;
+		else
+			size = stride * height / 2;
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 1, size);
+	} else if (inst->dst_fmt.num_planes == 3) {
+		size = stride * height;
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, size);
+		if (inst->output_format == FORMAT_422)
+			size = stride * height / 2;
+		else
+			size = stride * height / 4;
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 1, size);
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 2, size);
+	}
+
+	tail = inst->time_stamp.tail;
+	dst_buf->vb2_buf.timestamp = inst->time_stamp.buf[tail];
+	inst->time_stamp.tail++;
+
+	if (IS_WRAP(inst->time_stamp.tail, MAX_TIMESTAMP_CIR_BUF) == 0)
+		inst->time_stamp.tail = 0;
+
+	dst_buf->field = V4L2_FIELD_NONE;
+	v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
+
+	dev_dbg(inst->dev->dev, "%s: frame_cycle %8u\n",
+		__func__, info->frame_cycle);
+}
+
+static void wave5_vpu_dec_finish_decode(struct vpu_instance *inst)
+{
+	struct dec_output_info dec_output_info;
+	int ret;
+	u32 irq_status;
+	int tail = 0;
+	int index_to_remove = -1;
+
+	if (kfifo_out(&inst->irq_status, &irq_status, sizeof(int)))
+		wave5_vpu_clear_interrupt_ex(inst, irq_status);
+
+	ret = wave5_vpu_dec_get_output_info(inst, &dec_output_info);
+	if (ret) {
+		v4l2_m2m_job_finish(inst->v4l2_m2m_dev, inst->v4l2_fh.m2m_ctx);
+		return;
+	}
+	index_to_remove = dec_output_info.index_frame_display;
+	if (dec_output_info.index_frame_decoded == DECODED_IDX_FLAG_NO_FB &&
+	    dec_output_info.index_frame_display == DISPLAY_IDX_FLAG_NO_FB) {
+		dev_dbg(inst->dev->dev, "%s: no more frame buffer\n", __func__);
+	} else {
+		wave5_handle_src_buffer(inst);
+
+		if (dec_output_info.index_frame_display >= 0) {
+			mutex_lock(inst->inst_lock);
+			index_to_remove =
+				inst->map_index[dec_output_info
+							.index_frame_display];
+			mutex_unlock(inst->inst_lock);
+			wave5_handle_display_frame(inst, &dec_output_info,
+						   index_to_remove);
+		} else if (dec_output_info.index_frame_display ==
+				   DISPLAY_IDX_FLAG_SEQ_END &&
+			   !inst->eos) {
+			static const struct v4l2_event vpu_event_eos = {
+				.type = V4L2_EVENT_EOS
+			};
+			struct vb2_v4l2_buffer *dst_buf =
+				v4l2_m2m_dst_buf_remove(inst->v4l2_fh.m2m_ctx);
+
+			if (!dst_buf)
+				return;
+
+			if (inst->dst_fmt.num_planes == 1) {
+				vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
+						      vb2_plane_size(&dst_buf->vb2_buf, 0));
+			} else if (inst->dst_fmt.num_planes == 2) {
+				vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
+						      vb2_plane_size(&dst_buf->vb2_buf, 0));
+				vb2_set_plane_payload(&dst_buf->vb2_buf, 1,
+						      vb2_plane_size(&dst_buf->vb2_buf, 1));
+			} else if (inst->dst_fmt.num_planes == 3) {
+				vb2_set_plane_payload(&dst_buf->vb2_buf, 0,
+						      vb2_plane_size(&dst_buf->vb2_buf, 0));
+				vb2_set_plane_payload(&dst_buf->vb2_buf, 1,
+						      vb2_plane_size(&dst_buf->vb2_buf, 1));
+				vb2_set_plane_payload(&dst_buf->vb2_buf, 2,
+						      vb2_plane_size(&dst_buf->vb2_buf, 2));
+			}
+
+			tail = inst->time_stamp.tail;
+			dst_buf->vb2_buf.timestamp = inst->time_stamp.buf[tail];
+			inst->time_stamp.tail++;
+
+			if (IS_WRAP(inst->time_stamp.tail, MAX_TIMESTAMP_CIR_BUF) == 0)
+				inst->time_stamp.tail = 0;
+
+			dst_buf->flags |= V4L2_BUF_FLAG_LAST;
+			dst_buf->field = V4L2_FIELD_NONE;
+			v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
+
+			inst->eos = TRUE;
+			v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_eos);
+
+			v4l2_m2m_job_finish(inst->v4l2_m2m_dev, inst->v4l2_fh.m2m_ctx);
+		}
+
+		if (inst->state == VPU_INST_STATE_STOP && !inst->eos)
+			inst->ops->start_process(inst);
+	}
+}
+
+static int wave5_vpu_dec_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
+{
+	strscpy(cap->driver, VPU_DEC_DRV_NAME, sizeof(cap->driver));
+	strscpy(cap->card, VPU_DEC_DRV_NAME, sizeof(cap->card));
+	strscpy(cap->bus_info, "platform:" VPU_DEC_DRV_NAME, sizeof(cap->bus_info));
+
+	return 0;
+}
+
+static int wave5_vpu_dec_enum_framesizes(struct file *f, void *fh, struct v4l2_frmsizeenum *fsize)
+{
+	const struct vpu_format *vpu_fmt;
+
+	if (fsize->index)
+		return -EINVAL;
+
+	vpu_fmt = wave5_find_vpu_fmt(fsize->pixel_format, dec_fmt_list[VPU_FMT_TYPE_CODEC]);
+	if (!vpu_fmt) {
+		vpu_fmt = wave5_find_vpu_fmt(fsize->pixel_format, dec_fmt_list[VPU_FMT_TYPE_RAW]);
+		if (!vpu_fmt)
+			return -EINVAL;
+	}
+
+	fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
+	fsize->stepwise.min_width = vpu_fmt->min_width;
+	fsize->stepwise.max_width = vpu_fmt->max_width;
+	fsize->stepwise.step_width = 1;
+	fsize->stepwise.min_height = vpu_fmt->min_height;
+	fsize->stepwise.max_height = vpu_fmt->max_height;
+	fsize->stepwise.step_height = 1;
+
+	return 0;
+}
+
+static int wave5_vpu_dec_enum_fmt_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+	const struct vpu_format *vpu_fmt;
+
+	vpu_fmt = wave5_find_vpu_fmt_by_idx(f->index, dec_fmt_list[VPU_FMT_TYPE_RAW]);
+	if (!vpu_fmt)
+		return -EINVAL;
+
+	f->pixelformat = vpu_fmt->v4l2_pix_fmt;
+	f->flags = 0;
+
+	return 0;
+}
+
+static int wave5_vpu_dec_try_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	const struct vpu_format *vpu_fmt;
+
+	dev_dbg(inst->dev->dev,
+		"%s: fourcc: %u width: %u height: %u nm planes: %u colorspace: %u field: %u\n",
+		__func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+		f->fmt.pix_mp.num_planes, f->fmt.pix_mp.colorspace, f->fmt.pix_mp.field);
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		return -EINVAL;
+
+	vpu_fmt = wave5_find_vpu_fmt(f->fmt.pix_mp.pixelformat, dec_fmt_list[VPU_FMT_TYPE_RAW]);
+	if (!vpu_fmt) {
+		f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat;
+		f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes;
+		wave5_update_pix_fmt(&f->fmt.pix_mp, inst->dst_fmt.width, inst->dst_fmt.height);
+	} else {
+		int width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width);
+		int height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height);
+		const struct v4l2_format_info *info = v4l2_format_info(vpu_fmt->v4l2_pix_fmt);
+
+		f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt;
+		f->fmt.pix_mp.num_planes = info->mem_planes;
+		wave5_update_pix_fmt(&f->fmt.pix_mp, width, height);
+	}
+
+	f->fmt.pix_mp.flags = 0;
+	f->fmt.pix_mp.field = V4L2_FIELD_NONE;
+	f->fmt.pix_mp.colorspace = inst->colorspace;
+	f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc;
+	f->fmt.pix_mp.hsv_enc = inst->hsv_enc;
+	f->fmt.pix_mp.quantization = inst->quantization;
+	f->fmt.pix_mp.xfer_func = inst->xfer_func;
+	memset(&f->fmt.pix_mp.reserved, 0, sizeof(f->fmt.pix_mp.reserved));
+
+	return 0;
+}
+
+static int wave5_vpu_dec_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	int i, ret;
+
+	dev_dbg(inst->dev->dev,
+		"%s: fourcc: %u width: %u height: %u num_planes: %u colorspace: %u field: %u\n",
+		__func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+		f->fmt.pix_mp.num_planes, f->fmt.pix_mp.colorspace, f->fmt.pix_mp.field);
+
+	ret = wave5_vpu_dec_try_fmt_cap(file, fh, f);
+	if (ret)
+		return ret;
+
+	inst->dst_fmt.width = f->fmt.pix_mp.width;
+	inst->dst_fmt.height = f->fmt.pix_mp.height;
+	inst->dst_fmt.pixelformat = f->fmt.pix_mp.pixelformat;
+	inst->dst_fmt.field = f->fmt.pix_mp.field;
+	inst->dst_fmt.flags = f->fmt.pix_mp.flags;
+	inst->dst_fmt.num_planes = f->fmt.pix_mp.num_planes;
+	for (i = 0; i < inst->dst_fmt.num_planes; i++) {
+		inst->dst_fmt.plane_fmt[i].bytesperline = f->fmt.pix_mp.plane_fmt[i].bytesperline;
+		inst->dst_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage;
+	}
+
+	if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV12 ||
+	    inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV12M) {
+		inst->cbcr_interleave = true;
+		inst->nv21 = false;
+		inst->output_format = FORMAT_420;
+	} else if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV21 ||
+		   inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV21M) {
+		inst->cbcr_interleave = true;
+		inst->nv21 = true;
+		inst->output_format = FORMAT_420;
+	} else if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV16 ||
+		   inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV16M) {
+		inst->cbcr_interleave = true;
+		inst->nv21 = false;
+		inst->output_format = FORMAT_422;
+	} else if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV61 ||
+		   inst->dst_fmt.pixelformat == V4L2_PIX_FMT_NV61M) {
+		inst->cbcr_interleave = true;
+		inst->nv21 = true;
+		inst->output_format = FORMAT_422;
+	} else if (inst->dst_fmt.pixelformat == V4L2_PIX_FMT_YUV422P ||
+		   inst->dst_fmt.pixelformat == V4L2_PIX_FMT_YUV422M) {
+		inst->cbcr_interleave = false;
+		inst->nv21 = false;
+		inst->output_format = FORMAT_422;
+	} else {
+		inst->cbcr_interleave = false;
+		inst->nv21 = false;
+		inst->output_format = FORMAT_420;
+	}
+
+	return 0;
+}
+
+static int wave5_vpu_dec_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	int i;
+
+	f->fmt.pix_mp.width = inst->dst_fmt.width;
+	f->fmt.pix_mp.height = inst->dst_fmt.height;
+	f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat;
+	f->fmt.pix_mp.field = inst->dst_fmt.field;
+	f->fmt.pix_mp.flags = inst->dst_fmt.flags;
+	f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes;
+	for (i = 0; i < f->fmt.pix_mp.num_planes; i++) {
+		f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->dst_fmt.plane_fmt[i].bytesperline;
+		f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->dst_fmt.plane_fmt[i].sizeimage;
+	}
+
+	f->fmt.pix_mp.colorspace = inst->colorspace;
+	f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc;
+	f->fmt.pix_mp.hsv_enc = inst->hsv_enc;
+	f->fmt.pix_mp.quantization = inst->quantization;
+	f->fmt.pix_mp.xfer_func = inst->xfer_func;
+
+	return 0;
+}
+
+static int wave5_vpu_dec_enum_fmt_out(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	const struct vpu_format *vpu_fmt;
+
+	dev_dbg(inst->dev->dev, "%s: index: %u\n", __func__, f->index);
+
+	vpu_fmt = wave5_find_vpu_fmt_by_idx(f->index, dec_fmt_list[VPU_FMT_TYPE_CODEC]);
+	if (!vpu_fmt)
+		return -EINVAL;
+
+	f->pixelformat = vpu_fmt->v4l2_pix_fmt;
+	f->flags = 0;
+
+	return 0;
+}
+
+static int wave5_vpu_dec_try_fmt_out(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	const struct vpu_format *vpu_fmt;
+
+	dev_dbg(inst->dev->dev,
+		"%s: fourcc: %u width: %u height: %u num_planes: %u colorspace: %u field: %u\n",
+		__func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+		f->fmt.pix_mp.num_planes, f->fmt.pix_mp.colorspace, f->fmt.pix_mp.field);
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return -EINVAL;
+
+	vpu_fmt = wave5_find_vpu_fmt(f->fmt.pix_mp.pixelformat, dec_fmt_list[VPU_FMT_TYPE_CODEC]);
+	if (!vpu_fmt) {
+		f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat;
+		f->fmt.pix_mp.num_planes = inst->src_fmt.num_planes;
+		wave5_update_pix_fmt(&f->fmt.pix_mp, inst->src_fmt.width, inst->src_fmt.height);
+	} else {
+		int width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width);
+		int height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height);
+
+		f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt;
+		f->fmt.pix_mp.num_planes = 1;
+		wave5_update_pix_fmt(&f->fmt.pix_mp, width, height);
+	}
+
+	f->fmt.pix_mp.flags = 0;
+	f->fmt.pix_mp.field = V4L2_FIELD_NONE;
+	memset(&f->fmt.pix_mp.reserved, 0, sizeof(f->fmt.pix_mp.reserved));
+
+	return 0;
+}
+
+static int wave5_vpu_dec_s_fmt_out(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	int i, ret;
+
+	dev_dbg(inst->dev->dev,
+		"%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n",
+		__func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+		f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field);
+
+	ret = wave5_vpu_dec_try_fmt_out(file, fh, f);
+	if (ret)
+		return ret;
+
+	inst->src_fmt.width = f->fmt.pix_mp.width;
+	inst->src_fmt.height = f->fmt.pix_mp.height;
+	inst->src_fmt.pixelformat = f->fmt.pix_mp.pixelformat;
+	inst->src_fmt.field = f->fmt.pix_mp.field;
+	inst->src_fmt.flags = f->fmt.pix_mp.flags;
+	inst->src_fmt.num_planes = f->fmt.pix_mp.num_planes;
+	for (i = 0; i < inst->src_fmt.num_planes; i++) {
+		inst->src_fmt.plane_fmt[i].bytesperline = f->fmt.pix_mp.plane_fmt[i].bytesperline;
+		inst->src_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage;
+	}
+
+	inst->colorspace = f->fmt.pix_mp.colorspace;
+	inst->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
+	inst->hsv_enc = f->fmt.pix_mp.hsv_enc;
+	inst->quantization = f->fmt.pix_mp.quantization;
+	inst->xfer_func = f->fmt.pix_mp.xfer_func;
+
+	wave5_update_pix_fmt(&inst->dst_fmt, f->fmt.pix_mp.width, f->fmt.pix_mp.height);
+
+	return 0;
+}
+
+static int wave5_vpu_dec_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+
+	dev_dbg(inst->dev->dev, "%s: type: %u | target: %u\n", __func__, s->type, s->target);
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	switch (s->target) {
+	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+	case V4L2_SEL_TGT_COMPOSE_PADDED:
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = inst->dst_fmt.width;
+		s->r.height = inst->dst_fmt.height;
+		break;
+	case V4L2_SEL_TGT_COMPOSE:
+	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+		s->r.left = inst->pic_crop_rect.left;
+		s->r.top = inst->pic_crop_rect.top;
+
+		if (inst->state > VPU_INST_STATE_OPEN) {
+			s->r.width = inst->conf_win_width;
+			s->r.height = inst->conf_win_height;
+		} else {
+			s->r.width = inst->src_fmt.width;
+			s->r.height = inst->src_fmt.height;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int wave5_vpu_dec_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (s->target != V4L2_SEL_TGT_COMPOSE)
+		return -EINVAL;
+
+	dev_dbg(inst->dev->dev, "V4L2_SEL_TGT_COMPOSE w: %u h: %u\n",
+		s->r.width, s->r.height);
+
+	s->r.left = 0;
+	s->r.top = 0;
+	s->r.width = inst->dst_fmt.width;
+	s->r.height = inst->dst_fmt.height;
+
+	return 0;
+}
+
+static int wave5_vpu_dec_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *dc)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	int ret;
+
+	dev_dbg(inst->dev->dev, "decoder command: %u\n", dc->cmd);
+
+	ret = v4l2_m2m_ioctl_try_decoder_cmd(file, fh, dc);
+	if (ret)
+		return ret;
+
+	if (!wave5_vpu_both_queues_are_streaming(inst))
+		return 0;
+
+	switch (dc->cmd) {
+	case V4L2_DEC_CMD_STOP:
+		inst->state = VPU_INST_STATE_STOP;
+
+		ret = wave5_vpu_dec_update_bitstream_buffer(inst, 0);
+		if (ret) {
+			dev_err(inst->dev->dev,
+				"Setting EOS for the bitstream, fail: %d\n", ret);
+			return ret;
+		}
+		inst->ops->start_process(inst);
+		break;
+	case V4L2_DEC_CMD_START:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops wave5_vpu_dec_ioctl_ops = {
+	.vidioc_querycap = wave5_vpu_dec_querycap,
+	.vidioc_enum_framesizes = wave5_vpu_dec_enum_framesizes,
+
+	.vidioc_enum_fmt_vid_cap	= wave5_vpu_dec_enum_fmt_cap,
+	.vidioc_s_fmt_vid_cap_mplane = wave5_vpu_dec_s_fmt_cap,
+	.vidioc_g_fmt_vid_cap_mplane = wave5_vpu_dec_g_fmt_cap,
+	.vidioc_try_fmt_vid_cap_mplane = wave5_vpu_dec_try_fmt_cap,
+
+	.vidioc_enum_fmt_vid_out	= wave5_vpu_dec_enum_fmt_out,
+	.vidioc_s_fmt_vid_out_mplane = wave5_vpu_dec_s_fmt_out,
+	.vidioc_g_fmt_vid_out_mplane = wave5_vpu_g_fmt_out,
+	.vidioc_try_fmt_vid_out_mplane = wave5_vpu_dec_try_fmt_out,
+
+	.vidioc_g_selection = wave5_vpu_dec_g_selection,
+	.vidioc_s_selection = wave5_vpu_dec_s_selection,
+
+	.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
+	.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+	.vidioc_streamon = v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+
+	.vidioc_try_decoder_cmd = v4l2_m2m_ioctl_try_decoder_cmd,
+	.vidioc_decoder_cmd = wave5_vpu_dec_decoder_cmd,
+
+	.vidioc_subscribe_event = wave5_vpu_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static int wave5_vpu_dec_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct vpu_instance *inst = wave5_ctrl_to_vpu_inst(ctrl);
+
+	dev_dbg(inst->dev->dev, "%s: name: %s | value: %d\n",
+		__func__, ctrl->name, ctrl->val);
+
+	switch (ctrl->id) {
+	case V4L2_CID_VPU_THUMBNAIL_MODE:
+		inst->thumbnail_mode = ctrl->val;
+		break;
+	case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops wave5_vpu_dec_ctrl_ops = {
+	.s_ctrl = wave5_vpu_dec_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config wave5_vpu_thumbnail_mode = {
+	.ops = &wave5_vpu_dec_ctrl_ops,
+	.id = V4L2_CID_VPU_THUMBNAIL_MODE,
+	.name = "thumbnail mode",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.def = 0,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.flags = V4L2_CTRL_FLAG_WRITE_ONLY,
+};
+
+static void wave5_set_default_dec_openparam(struct dec_open_param *open_param)
+{
+	open_param->bitstream_mode = BS_MODE_INTERRUPT;
+	open_param->stream_endian = VPU_STREAM_ENDIAN;
+	open_param->frame_endian = VPU_FRAME_ENDIAN;
+}
+
+static int wave5_vpu_dec_queue_setup(struct vb2_queue *q, unsigned int *num_buffers,
+				     unsigned int *num_planes, unsigned int sizes[],
+				     struct device *alloc_devs[])
+{
+	struct vpu_instance *inst = vb2_get_drv_priv(q);
+	struct v4l2_pix_format_mplane inst_format =
+		(q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? inst->src_fmt : inst->dst_fmt;
+	unsigned int i;
+	int ret;
+
+	dev_dbg(inst->dev->dev, "%s: num_buffers: %u | num_planes: %u | type: %u\n", __func__,
+		*num_buffers, *num_planes, q->type);
+
+	if (*num_planes) {
+		if (inst_format.num_planes != *num_planes)
+			return -EINVAL;
+
+		for (i = 0; i < *num_planes; i++) {
+			if (sizes[i] < inst_format.plane_fmt[i].sizeimage)
+				return -EINVAL;
+		}
+	} else {
+		*num_planes = inst_format.num_planes;
+
+		if (*num_planes == 1) {
+			if (inst->output_format == FORMAT_422)
+				sizes[0] = inst_format.width * inst_format.height * 2;
+			else
+				sizes[0] = inst_format.width * inst_format.height * 3 / 2;
+			if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+				sizes[0] = inst_format.plane_fmt[0].sizeimage;
+			dev_dbg(inst->dev->dev, "%s: size[0]: %u\n", __func__, sizes[0]);
+		} else if (*num_planes == 2) {
+			sizes[0] = inst_format.width * inst_format.height;
+			if (inst->output_format == FORMAT_422)
+				sizes[1] = inst_format.width * inst_format.height;
+			else
+				sizes[1] = inst_format.width * inst_format.height / 2;
+			dev_dbg(inst->dev->dev, "%s: size[0]: %u | size[1]: %u\n",
+				__func__, sizes[0], sizes[1]);
+		} else if (*num_planes == 3) {
+			sizes[0] = inst_format.width * inst_format.height;
+			if (inst->output_format == FORMAT_422) {
+				sizes[1] = inst_format.width * inst_format.height / 2;
+				sizes[2] = inst_format.width * inst_format.height / 2;
+			} else {
+				sizes[1] = inst_format.width * inst_format.height / 4;
+				sizes[2] = inst_format.width * inst_format.height / 4;
+			}
+			dev_dbg(inst->dev->dev, "%s: size[0]: %u | size[1]: %u | size[2]: %u\n",
+				__func__, sizes[0], sizes[1], sizes[2]);
+		}
+	}
+	if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		inst->cap_io_mode = q->memory;
+
+
+	if (inst->state == VPU_INST_STATE_NONE && q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		struct dec_open_param open_param;
+
+		memset(&open_param, 0, sizeof(struct dec_open_param));
+		wave5_set_default_dec_openparam(&open_param);
+
+		inst->bitstream_vbuf.size = ALIGN((inst->src_fmt.plane_fmt[0].sizeimage * 3), 1024);
+		ret = wave5_vdi_allocate_dma_memory(inst->dev, &inst->bitstream_vbuf);
+		if (ret) {
+			dev_dbg(inst->dev->dev, "%s: alloc bitstream of size %zu fail: %d\n",
+				__func__, inst->bitstream_vbuf.size, ret);
+			return ret;
+		}
+
+		inst->std = wave5_to_vpu_codstd(inst->src_fmt.pixelformat);
+		if (inst->std == STD_UNKNOWN) {
+			dev_warn(inst->dev->dev, "unsupported pixelformat: %.4s\n",
+				 (char *)&inst->src_fmt.pixelformat);
+			ret = -EINVAL;
+			goto free_bitstream_vbuf;
+		}
+		open_param.bitstream_buffer = inst->bitstream_vbuf.daddr;
+		open_param.bitstream_buffer_size = inst->bitstream_vbuf.size;
+
+		ret = wave5_vpu_dec_open(inst, &open_param);
+		if (ret) {
+			dev_dbg(inst->dev->dev, "%s: wave5_vpu_dec_open, fail: %d\n",
+				__func__, ret);
+			goto free_bitstream_vbuf;
+		}
+
+		inst->state = VPU_INST_STATE_OPEN;
+
+		if (inst->thumbnail_mode)
+			wave5_vpu_dec_give_command(inst, ENABLE_DEC_THUMBNAIL_MODE, NULL);
+
+	} else if (inst->state == VPU_INST_STATE_INIT_SEQ &&
+		   q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+
+		if (*num_buffers > inst->dst_buf_count &&
+		    *num_buffers < WAVE5_MAX_FBS)
+			inst->dst_buf_count = *num_buffers;
+
+		*num_buffers = inst->dst_buf_count;
+		inst->map_index =
+			kzalloc((inst->dst_buf_count) * sizeof(unsigned int),
+				GFP_KERNEL);
+		if (!inst->map_index) {
+			ret = -ENOMEM;
+			dev_dbg(inst->dev->dev,
+				"%s: Failed to allocate nenory, fail: %d\n",
+				__func__, ret);
+			goto free_bitstream_vbuf;
+		}
+		inst->mapped_dma_addr =
+			kzalloc((inst->dst_buf_count) * sizeof(unsigned long),
+				GFP_KERNEL);
+		if (!inst->mapped_dma_addr) {
+			ret = -ENOMEM;
+			dev_dbg(inst->dev->dev,
+				"%s: Failed to allocate nenory, fail: %d\n",
+				__func__, ret);
+			goto free_bitstream_vbuf;
+		}
+	} else if ((inst->state == VPU_INST_STATE_STOP || inst->state == VPU_INST_STATE_PIC_RUN) &&
+		   q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		*num_buffers = 0;
+	}
+
+	return 0;
+
+free_bitstream_vbuf:
+	wave5_vdi_free_dma_memory(inst->dev, &inst->bitstream_vbuf);
+	return ret;
+}
+
+static int wave5_prepare_fb(struct vpu_instance *inst)
+{
+	int linear_num;
+	int non_linear_num;
+	int fb_stride, fb_height;
+	int luma_size, chroma_size;
+	int ret, i;
+
+	linear_num = inst->dst_buf_count;
+	non_linear_num = inst->fbc_buf_count;
+
+	for (i = 0; i < non_linear_num; i++) {
+		struct frame_buffer *frame = &inst->frame_buf[i];
+		struct vpu_buf *vframe = &inst->frame_vbuf[i];
+
+		fb_stride = inst->dst_fmt.width;
+		fb_height = ALIGN(inst->dst_fmt.height, 32);
+		luma_size = fb_stride * fb_height;
+		chroma_size = ALIGN(fb_stride / 2, 16) * fb_height;
+
+		vframe->size = luma_size + chroma_size;
+		ret = wave5_vdi_allocate_dma_memory(inst->dev, vframe);
+		if (ret) {
+			dev_dbg(inst->dev->dev,
+				"%s: Allocating FBC buf of size %zu, fail: %d\n",
+				__func__, vframe->size, ret);
+			return ret;
+		}
+
+		frame->buf_y = vframe->daddr;
+		frame->buf_cb = vframe->daddr + luma_size;
+		frame->buf_cr = (dma_addr_t)-1;
+		frame->size = vframe->size;
+		frame->width = inst->src_fmt.width;
+		frame->stride = fb_stride;
+		frame->map_type = COMPRESSED_FRAME_MAP;
+		frame->update_fb_info = true;
+	}
+
+	ret = wave5_vpu_dec_register_frame_buffer_ex(inst, non_linear_num, linear_num,
+						     fb_stride, inst->dst_fmt.height,
+						     COMPRESSED_FRAME_MAP);
+	if (ret) {
+		dev_dbg(inst->dev->dev, "%s: vpu_dec_register_frame_buffer_ex fail: %d",
+			__func__, ret);
+		return ret;
+	}
+	if (inst->cap_io_mode == VB2_MEMORY_DMABUF) {
+		for (i = (linear_num - DEC_BUF_OFFSET); i < linear_num; i++)
+			ret = wave5_vpu_dec_set_disp_flag(inst, i);
+	}
+
+	return 0;
+}
+
+static int wave5_vpu_dec_start_streaming_open(struct vpu_instance *inst)
+{
+	struct dec_initial_info initial_info;
+	int ret = 0;
+
+	inst->time_stamp.head = 0;
+	inst->time_stamp.tail = 0;
+	memset(&inst->time_stamp.buf, 0, MAX_TIMESTAMP_CIR_BUF*sizeof(u64));
+
+	memset(&initial_info, 0, sizeof(struct dec_initial_info));
+
+	ret = wave5_vpu_dec_issue_seq_init(inst);
+	if (ret) {
+		dev_dbg(inst->dev->dev, "%s: wave5_vpu_dec_issue_seq_init, fail: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	if (wave5_vpu_wait_interrupt(inst, VPU_DEC_TIMEOUT) < 0)
+		dev_dbg(inst->dev->dev, "%s: failed to call vpu_wait_interrupt()\n", __func__);
+
+	ret = wave5_vpu_dec_complete_seq_init(inst, &initial_info);
+	if (ret) {
+		dev_dbg(inst->dev->dev, "%s: vpu_dec_complete_seq_init, fail: %d, reason: %u\n",
+			__func__, ret, initial_info.seq_init_err_reason);
+	} else {
+		static const struct v4l2_event vpu_event_src_ch = {
+			.type = V4L2_EVENT_SOURCE_CHANGE,
+			.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
+		};
+		struct v4l2_ctrl *ctrl;
+
+		dev_dbg(inst->dev->dev, "%s: width: %u height: %u profile: %u | minbuffer: %u\n",
+			__func__, initial_info.pic_width, initial_info.pic_height,
+			initial_info.profile, initial_info.min_frame_buffer_count);
+
+		inst->state = VPU_INST_STATE_INIT_SEQ;
+		inst->fbc_buf_count = initial_info.min_frame_buffer_count + 1;
+		inst->dst_buf_count = initial_info.frame_buf_delay + 1;
+
+		memset(&inst->pic_crop_rect, 0x0, sizeof(struct vpu_rect));
+
+		inst->pic_crop_rect.right = initial_info.pic_crop_rect.right;
+		inst->pic_crop_rect.left = initial_info.pic_crop_rect.left;
+		inst->pic_crop_rect.top = initial_info.pic_crop_rect.top;
+		inst->pic_crop_rect.bottom = initial_info.pic_crop_rect.bottom;
+
+		inst->conf_win_width = initial_info.pic_width - initial_info.pic_crop_rect.right;
+		inst->conf_win_height = initial_info.pic_height - initial_info.pic_crop_rect.bottom;
+
+		if (initial_info.pic_crop_rect.left != 0)
+			inst->conf_win_width = inst->conf_win_width - initial_info.pic_crop_rect.left;
+
+		if (initial_info.pic_crop_rect.top != 0)
+			inst->conf_win_height = inst->conf_win_height - initial_info.pic_crop_rect.top;
+
+		ctrl = v4l2_ctrl_find(&inst->v4l2_ctrl_hdl,
+				      V4L2_CID_MIN_BUFFERS_FOR_CAPTURE);
+		if (ctrl)
+			v4l2_ctrl_s_ctrl(ctrl, inst->dst_buf_count);
+
+		inst->frame_rate = (initial_info.f_rate_numerator /
+					initial_info.f_rate_denominator);
+		wave5_instance_set_clk(inst);
+
+		if (initial_info.pic_width != inst->src_fmt.width ||
+		    initial_info.pic_height != inst->src_fmt.height) {
+			wave5_update_pix_fmt(&inst->src_fmt, initial_info.pic_width,
+					     initial_info.pic_height);
+			wave5_update_pix_fmt(&inst->dst_fmt, initial_info.pic_width,
+					     initial_info.pic_height);
+		}
+		v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_src_ch);
+	}
+
+	return ret;
+}
+
+static int wave5_vpu_dec_start_streaming_seek(struct vpu_instance *inst)
+{
+	struct dec_initial_info initial_info;
+	struct dec_param pic_param;
+	struct dec_output_info dec_output_info;
+	int ret = 0;
+	u32 fail_res = 0;
+
+	memset(&pic_param, 0, sizeof(struct dec_param));
+
+	ret = wave5_vpu_dec_start_one_frame(inst, &pic_param, &fail_res);
+	if (ret && fail_res != WAVE5_SYSERR_QUEUEING_FAIL) {
+		struct vb2_v4l2_buffer *src_buf;
+
+		src_buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx);
+		inst->state = VPU_INST_STATE_STOP;
+		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+		dev_dbg(inst->dev->dev, "%s: wave5_vpu_dec_start_one_frame\n", __func__);
+		return ret;
+	}
+
+	if (wave5_vpu_wait_interrupt(inst, VPU_DEC_TIMEOUT) < 0)
+		dev_dbg(inst->dev->dev, "%s: failed to call vpu_wait_interrupt()\n", __func__);
+
+	ret = wave5_vpu_dec_get_output_info(inst, &dec_output_info);
+	if (ret) {
+		dev_dbg(inst->dev->dev, "%s: wave5_vpu_dec_get_output_info, fail: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	if (dec_output_info.sequence_changed) {
+		static const struct v4l2_event vpu_event_src_ch = {
+			.type = V4L2_EVENT_SOURCE_CHANGE,
+			.u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION,
+		};
+		struct v4l2_ctrl *ctrl;
+
+		wave5_vpu_dec_give_command(inst, DEC_RESET_FRAMEBUF_INFO, NULL);
+		wave5_vpu_dec_give_command(inst, DEC_GET_SEQ_INFO, &initial_info);
+
+		dev_dbg(inst->dev->dev, "%s: width: %u height: %u profile: %u | minbuffer: %u\n",
+			__func__, initial_info.pic_width, initial_info.pic_height,
+			initial_info.profile, initial_info.min_frame_buffer_count);
+
+		inst->fbc_buf_count = initial_info.min_frame_buffer_count + 1;
+		inst->dst_buf_count = initial_info.frame_buf_delay + 1;
+
+		inst->conf_win_width = initial_info.pic_width - initial_info.pic_crop_rect.right;
+		inst->conf_win_height = initial_info.pic_height - initial_info.pic_crop_rect.bottom;
+
+		ctrl = v4l2_ctrl_find(&inst->v4l2_ctrl_hdl,
+				      V4L2_CID_MIN_BUFFERS_FOR_CAPTURE);
+		if (ctrl)
+			v4l2_ctrl_s_ctrl(ctrl, inst->dst_buf_count);
+
+		if (initial_info.pic_width != inst->src_fmt.width ||
+		    initial_info.pic_height != inst->src_fmt.height) {
+			wave5_update_pix_fmt(&inst->src_fmt, initial_info.pic_width,
+					     initial_info.pic_height);
+			wave5_update_pix_fmt(&inst->dst_fmt, initial_info.pic_width,
+					     initial_info.pic_height);
+		}
+		v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_src_ch);
+
+		wave5_handle_src_buffer(inst);
+	}
+
+	return ret;
+}
+
+static void wave5_vpu_dec_buf_queue_src(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vpu_instance *inst = vb2_get_drv_priv(vb->vb2_queue);
+	struct vpu_buffer *vpu_buf = wave5_to_vpu_buf(vbuf);
+
+	vpu_buf->consumed = false;
+	vbuf->sequence = inst->queued_src_buf_num++;
+
+	if (inst->state == VPU_INST_STATE_PIC_RUN) {
+		wave5_handle_bitstream_buffer(inst);
+		inst->ops->start_process(inst);
+	}
+}
+
+static void wave5_vpu_dec_buf_queue_dst(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vpu_instance *inst = vb2_get_drv_priv(vb->vb2_queue);
+	unsigned long addr;
+	int ret, i, act_index = -1;
+
+	addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+	if (vb->vb2_queue->memory == VB2_MEMORY_DMABUF) {
+		mutex_lock(inst->inst_lock);
+		if (vb->index < (inst->dst_buf_count - DEC_BUF_OFFSET)) {
+			if (inst->queued_dst_buf_num <
+			    (inst->dst_buf_count - DEC_BUF_OFFSET)) {
+				ret = wave5_vpu_dec_clr_disp_flag(inst,
+								  vb->index);
+				inst->map_index[vb->index] = vb->index;
+			} else {
+				for (i = 0; i < inst->dst_buf_count; i++) {
+					if (inst->mapped_dma_addr[i] == addr) {
+						act_index = i;
+						break;
+					}
+				}
+				if (act_index >= 0) {
+					ret = wave5_vpu_dec_clr_disp_flag(
+						inst, act_index);
+					if (ret) {
+						dev_dbg(inst->dev->dev,
+							"%s: Clearing the display flag of buffer index: %u, fail: %d\n",
+							__func__, vb->index,
+							ret);
+					}
+					inst->map_index[act_index] = vb->index;
+				} else {
+					pr_err("%s Address not found for index : %d: %lx\n",
+					       __func__, vb->index, addr);
+					v4l2_m2m_dst_buf_remove_by_idx(
+						inst->v4l2_fh.m2m_ctx,
+						vb->index);
+					v4l2_m2m_buf_done(
+						to_vb2_v4l2_buffer(vb),
+						VB2_BUF_STATE_ERROR);
+					mutex_unlock(inst->inst_lock);
+					return;
+				}
+			}
+			vbuf->sequence = inst->queued_dst_buf_num++;
+		}
+		mutex_unlock(inst->inst_lock);
+	} else {
+		inst->map_index[vb->index] = vb->index;
+		vbuf->sequence = inst->queued_dst_buf_num++;
+		ret = wave5_vpu_dec_clr_disp_flag(inst, vb->index);
+		if (ret) {
+			dev_dbg(inst->dev->dev,
+				"%s: Clearing the display flag of buffer index: %u, fail: %d\n",
+				__func__, vb->index, ret);
+		}
+	}
+
+	if (inst->state == VPU_INST_STATE_INIT_SEQ) {
+		dma_addr_t buf_addr_y = 0, buf_addr_cb = 0, buf_addr_cr = 0;
+		u32 buf_size = 0;
+		u32 fb_index = inst->fbc_buf_count + vb->index;
+		u32 fb_stride = inst->dst_fmt.width;
+		u32 luma_size = fb_stride * inst->dst_fmt.height;
+		u32 chroma_size;
+
+		inst->mapped_dma_addr[vb->index] = addr;
+		if (inst->output_format == FORMAT_422)
+			chroma_size = fb_stride * inst->dst_fmt.height / 2;
+		else
+			chroma_size = fb_stride * inst->dst_fmt.height / 4;
+
+		if (inst->dst_fmt.num_planes == 1) {
+			buf_size = vb2_plane_size(&vbuf->vb2_buf, 0);
+			buf_addr_y = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
+			buf_addr_cb = buf_addr_y + luma_size;
+			buf_addr_cr = buf_addr_cb + chroma_size;
+		} else if (inst->dst_fmt.num_planes == 2) {
+			buf_size = vb2_plane_size(&vbuf->vb2_buf, 0) +
+				vb2_plane_size(&vbuf->vb2_buf, 1);
+			buf_addr_y = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
+			buf_addr_cb = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 1);
+			buf_addr_cr = buf_addr_cb + chroma_size;
+		} else if (inst->dst_fmt.num_planes == 3) {
+			buf_size = vb2_plane_size(&vbuf->vb2_buf, 0) +
+				vb2_plane_size(&vbuf->vb2_buf, 1) +
+				vb2_plane_size(&vbuf->vb2_buf, 2);
+			buf_addr_y = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
+			buf_addr_cb = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 1);
+			buf_addr_cr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 2);
+		}
+		inst->frame_buf[fb_index].buf_y = buf_addr_y;
+		inst->frame_buf[fb_index].buf_cb = buf_addr_cb;
+		inst->frame_buf[fb_index].buf_cr = buf_addr_cr;
+		inst->frame_buf[fb_index].size = buf_size;
+		inst->frame_buf[fb_index].width = inst->src_fmt.width;
+		inst->frame_buf[fb_index].stride = fb_stride;
+		inst->frame_buf[fb_index].map_type = LINEAR_FRAME_MAP;
+		inst->frame_buf[fb_index].update_fb_info = true;
+	}
+
+	if (!vb2_is_streaming(vb->vb2_queue))
+		return;
+
+	if (inst->state == VPU_INST_STATE_STOP && inst->eos == FALSE)
+		inst->ops->start_process(inst);
+}
+
+static void wave5_vpu_dec_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vpu_instance *inst = vb2_get_drv_priv(vb->vb2_queue);
+
+	dev_dbg(inst->dev->dev, "%s: type: %4u index: %4u size: ([0]=%4lu, [1]=%4lu, [2]=%4lu)\n",
+		__func__, vb->type, vb->index, vb2_plane_size(&vbuf->vb2_buf, 0),
+		vb2_plane_size(&vbuf->vb2_buf, 1), vb2_plane_size(&vbuf->vb2_buf, 2));
+
+	if ((vb->vb2_queue->memory == VB2_MEMORY_DMABUF) &&
+	    (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
+		if (vb->index < (inst->dst_buf_count - DEC_BUF_OFFSET))
+			v4l2_m2m_buf_queue(inst->v4l2_fh.m2m_ctx, vbuf);
+		else
+			v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+	} else {
+		v4l2_m2m_buf_queue(inst->v4l2_fh.m2m_ctx, vbuf);
+	}
+	if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		wave5_vpu_dec_buf_queue_src(vb);
+	else if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		wave5_vpu_dec_buf_queue_dst(vb);
+}
+
+static int wave5_vpu_dec_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct vpu_instance *inst = vb2_get_drv_priv(q);
+	int ret = 0;
+
+	dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, q->type);
+
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		wave5_handle_bitstream_buffer(inst);
+		if (inst->state == VPU_INST_STATE_OPEN)
+			ret = wave5_vpu_dec_start_streaming_open(inst);
+		else if (inst->state == VPU_INST_STATE_INIT_SEQ)
+			ret = wave5_vpu_dec_start_streaming_seek(inst);
+
+		if (ret) {
+			struct vb2_v4l2_buffer *buf;
+
+			while ((buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx))) {
+				dev_dbg(inst->dev->dev, "%s: (Multiplanar) buf type %4d | index %4d\n",
+					    __func__, buf->vb2_buf.type, buf->vb2_buf.index);
+				v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED);
+			}
+		}
+	}
+
+	if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+	    inst->state == VPU_INST_STATE_INIT_SEQ)
+		ret = wave5_prepare_fb(inst);
+
+	return ret;
+}
+
+static void wave5_vpu_dec_stop_streaming(struct vb2_queue *q)
+{
+	struct vpu_instance *inst = vb2_get_drv_priv(q);
+	struct vb2_v4l2_buffer *buf;
+	bool check_cmd = TRUE;
+
+	dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, q->type);
+
+	while (check_cmd) {
+		struct queue_status_info q_status;
+		struct dec_output_info dec_output_info;
+
+		wave5_vpu_dec_give_command(inst, DEC_GET_QUEUE_STATUS, &q_status);
+
+		if (q_status.instance_queue_count + q_status.report_queue_count == 0)
+			break;
+
+		if (wave5_vpu_wait_interrupt(inst, VPU_DEC_TIMEOUT) < 0)
+			break;
+
+		if (wave5_vpu_dec_get_output_info(inst, &dec_output_info))
+			dev_dbg(inst->dev->dev, "Getting decoding results from fw, fail\n");
+	}
+
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		while ((buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx))) {
+			dev_dbg(inst->dev->dev, "%s: (Multiplanar) buf type %4u | index %4u\n",
+				__func__, buf->vb2_buf.type, buf->vb2_buf.index);
+			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
+		}
+		inst->queued_src_buf_num = 0;
+	} else {
+		unsigned int i;
+		int ret;
+		dma_addr_t rd_ptr, wr_ptr;
+
+		while ((buf = v4l2_m2m_dst_buf_remove(inst->v4l2_fh.m2m_ctx))) {
+			u32 plane;
+
+			dev_dbg(inst->dev->dev, "%s: buf type %4u | index %4u\n",
+				__func__, buf->vb2_buf.type, buf->vb2_buf.index);
+
+			for (plane = 0; plane < inst->dst_fmt.num_planes; plane++)
+				vb2_set_plane_payload(&buf->vb2_buf, plane, 0);
+
+			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
+		}
+
+		for (i = 0; i < inst->dst_buf_count; i++) {
+			ret = wave5_vpu_dec_set_disp_flag(inst, i);
+			if (ret) {
+				dev_dbg(inst->dev->dev,
+					"%s: Setting display flag of buf index: %u, fail: %d\n",
+					__func__, i, ret);
+			}
+		}
+
+		ret = wave5_vpu_dec_get_bitstream_buffer(inst, &rd_ptr, &wr_ptr, NULL);
+		if (ret) {
+			dev_err(inst->dev->dev,
+				"Getting bitstream buf, fail: %d\n", ret);
+			return;
+		}
+		ret = wave5_vpu_dec_set_rd_ptr(inst, wr_ptr, TRUE);
+		if (ret) {
+			dev_err(inst->dev->dev,
+				"Setting read pointer for the decoder, fail: %d\n", ret);
+			return;
+		}
+		if (inst->eos) {
+			inst->eos = FALSE;
+			inst->state = VPU_INST_STATE_INIT_SEQ;
+		}
+		inst->queued_dst_buf_num = 0;
+	}
+}
+
+static const struct vb2_ops wave5_vpu_dec_vb2_ops = {
+	.queue_setup = wave5_vpu_dec_queue_setup,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.buf_queue = wave5_vpu_dec_buf_queue,
+	.start_streaming = wave5_vpu_dec_start_streaming,
+	.stop_streaming = wave5_vpu_dec_stop_streaming,
+};
+
+static void wave5_set_default_format(struct v4l2_pix_format_mplane *src_fmt,
+				     struct v4l2_pix_format_mplane *dst_fmt)
+{
+	unsigned int dst_pix_fmt = dec_fmt_list[VPU_FMT_TYPE_RAW][0].v4l2_pix_fmt;
+	const struct v4l2_format_info *dst_fmt_info = v4l2_format_info(dst_pix_fmt);
+
+	src_fmt->pixelformat = dec_fmt_list[VPU_FMT_TYPE_CODEC][0].v4l2_pix_fmt;
+	src_fmt->field = V4L2_FIELD_NONE;
+	src_fmt->flags = 0;
+	src_fmt->num_planes = 1;
+	wave5_update_pix_fmt(src_fmt, 720, 480);
+
+	dst_fmt->pixelformat = dst_pix_fmt;
+	dst_fmt->field = V4L2_FIELD_NONE;
+	dst_fmt->flags = 0;
+	dst_fmt->num_planes = dst_fmt_info->mem_planes;
+	wave5_update_pix_fmt(dst_fmt, 736, 480);
+}
+
+static int wave5_vpu_dec_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
+{
+	return wave5_vpu_queue_init(priv, src_vq, dst_vq, &wave5_vpu_dec_vb2_ops);
+}
+
+static const struct vpu_instance_ops wave5_vpu_dec_inst_ops = {
+	.start_process = wave5_vpu_dec_start_decode,
+	.stop_process = wave5_vpu_dec_stop_decode,
+	.finish_process = wave5_vpu_dec_finish_decode,
+};
+
+static void wave5_vpu_dec_device_run(void *priv)
+{
+	struct vpu_instance *inst = priv;
+
+	inst->ops->start_process(inst);
+
+	inst->state = VPU_INST_STATE_PIC_RUN;
+}
+
+static void wave5_vpu_dec_job_abort(void *priv)
+{
+	struct vpu_instance *inst = priv;
+
+	inst->ops->stop_process(inst);
+}
+
+static const struct v4l2_m2m_ops wave5_vpu_dec_m2m_ops = {
+	.device_run = wave5_vpu_dec_device_run,
+	.job_abort = wave5_vpu_dec_job_abort,
+};
+
+static int wave5_vpu_open_dec(struct file *filp)
+{
+	struct video_device *vdev = video_devdata(filp);
+	struct vpu_device *dev = video_drvdata(filp);
+	struct vpu_instance *inst = NULL;
+	int ret = 0, err;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+
+	inst->dev = dev;
+	inst->type = VPU_INST_TYPE_DEC;
+	inst->ops = &wave5_vpu_dec_inst_ops;
+
+	v4l2_fh_init(&inst->v4l2_fh, vdev);
+	filp->private_data = &inst->v4l2_fh;
+	v4l2_fh_add(&inst->v4l2_fh);
+
+	INIT_LIST_HEAD(&inst->list);
+
+	inst->v4l2_m2m_dev = v4l2_m2m_init(&wave5_vpu_dec_m2m_ops);
+	if (IS_ERR(inst->v4l2_m2m_dev)) {
+		ret = PTR_ERR(inst->v4l2_m2m_dev);
+		dev_err(inst->dev->dev, "v4l2_m2m_init, fail: %d\n", ret);
+		goto cleanup_inst;
+	}
+
+	inst->v4l2_fh.m2m_ctx =
+		v4l2_m2m_ctx_init(inst->v4l2_m2m_dev, inst, wave5_vpu_dec_queue_init);
+	if (IS_ERR(inst->v4l2_fh.m2m_ctx)) {
+		ret = PTR_ERR(inst->v4l2_fh.m2m_ctx);
+		goto cleanup_inst;
+	}
+
+	v4l2_ctrl_handler_init(&inst->v4l2_ctrl_hdl, 10);
+	v4l2_ctrl_new_custom(&inst->v4l2_ctrl_hdl, &wave5_vpu_thumbnail_mode, NULL);
+	v4l2_ctrl_new_std(&inst->v4l2_ctrl_hdl, &wave5_vpu_dec_ctrl_ops,
+			  V4L2_CID_MIN_BUFFERS_FOR_CAPTURE, 1, 32, 1, 1);
+
+	if (inst->v4l2_ctrl_hdl.error) {
+		ret = -ENODEV;
+		goto cleanup_inst;
+	}
+
+	inst->v4l2_fh.ctrl_handler = &inst->v4l2_ctrl_hdl;
+	v4l2_ctrl_handler_setup(&inst->v4l2_ctrl_hdl);
+
+	wave5_set_default_format(&inst->src_fmt, &inst->dst_fmt);
+	inst->colorspace = V4L2_COLORSPACE_REC709;
+	inst->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	inst->hsv_enc = 0;
+	inst->quantization = V4L2_QUANTIZATION_DEFAULT;
+	inst->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+
+	init_completion(&inst->irq_done);
+	ret = kfifo_alloc(&inst->irq_status, 16 * sizeof(int), GFP_KERNEL);
+	if (ret) {
+		dev_err(inst->dev->dev, "failed to allocate fifo\n");
+		goto cleanup_inst;
+	}
+
+	inst->id = ida_alloc(&inst->dev->inst_ida, GFP_KERNEL);
+	if (inst->id < 0) {
+		dev_warn(inst->dev->dev, "Allocating instance ID, fail: %d\n", inst->id);
+		ret = inst->id;
+		goto cleanup_inst;
+	}
+	inst->inst_lock = kzalloc(sizeof(*inst->inst_lock), GFP_KERNEL);
+	if (!inst->inst_lock) {
+		ret = -ENOMEM;
+		goto cleanup_inst;
+	}
+	mutex_init(inst->inst_lock);
+
+	err = pm_runtime_resume_and_get(inst->dev->dev);
+	if (err) {
+		dev_err(inst->dev->dev, "runtime resume failed %d\n", err);
+		ret = -EINVAL;
+		goto cleanup_inst;
+	}
+
+	ret = mutex_lock_interruptible(&dev->dev_lock);
+	if (ret)
+		goto cleanup_inst;
+
+	if (dev->irq < 0 && !hrtimer_active(&dev->hrtimer) && list_empty(&dev->instances))
+		hrtimer_start(&dev->hrtimer, ns_to_ktime(dev->vpu_poll_interval * NSEC_PER_MSEC),
+			      HRTIMER_MODE_REL_PINNED);
+
+	list_add_tail(&inst->list, &dev->instances);
+
+	mutex_unlock(&dev->dev_lock);
+	wave5_vdi_allocate_sram(inst->dev);
+
+	return 0;
+
+cleanup_inst:
+	wave5_cleanup_instance(inst);
+	return ret;
+}
+
+static int wave5_vpu_dec_release(struct file *filp)
+{
+	return wave5_vpu_release_device(filp, wave5_vpu_dec_close, "decoder");
+}
+
+static const struct v4l2_file_operations wave5_vpu_dec_fops = {
+	.owner = THIS_MODULE,
+	.open = wave5_vpu_open_dec,
+	.release = wave5_vpu_dec_release,
+	.unlocked_ioctl = video_ioctl2,
+	.poll = v4l2_m2m_fop_poll,
+	.mmap = v4l2_m2m_fop_mmap,
+};
+
+int wave5_vpu_dec_register_device(struct vpu_device *dev)
+{
+	struct video_device *vdev_dec;
+	int ret;
+
+	vdev_dec = devm_kzalloc(dev->v4l2_dev.dev, sizeof(*vdev_dec), GFP_KERNEL);
+	if (!vdev_dec)
+		return -ENOMEM;
+
+	dev->video_dev_dec = vdev_dec;
+
+	strscpy(vdev_dec->name, VPU_DEC_DEV_NAME, sizeof(vdev_dec->name));
+	vdev_dec->fops = &wave5_vpu_dec_fops;
+	vdev_dec->ioctl_ops = &wave5_vpu_dec_ioctl_ops;
+	vdev_dec->release = video_device_release_empty;
+	vdev_dec->v4l2_dev = &dev->v4l2_dev;
+	vdev_dec->vfl_dir = VFL_DIR_M2M;
+	vdev_dec->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+	vdev_dec->lock = &dev->dev_lock;
+
+	ret = video_register_device(vdev_dec, VFL_TYPE_VIDEO, -1);
+	if (ret)
+		return ret;
+
+	video_set_drvdata(vdev_dec, dev);
+
+	return 0;
+}
+
+void wave5_vpu_dec_unregister_device(struct vpu_device *dev)
+{
+	video_unregister_device(dev->video_dev_dec);
+}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c
--- a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,1740 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Wave5 series multi-standard codec IP - encoder interface
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+
+#include <linux/pm_runtime.h>
+#include "wave5-helper.h"
+
+#define VPU_ENC_DEV_NAME "C&M Wave5 VPU encoder"
+#define VPU_ENC_DRV_NAME "wave5-enc"
+
+#define DEFAULT_SRC_SIZE(width, height) ({			\
+	(width) * (height) / 8 * 3;					\
+})
+
+static const struct vpu_format enc_fmt_list[FMT_TYPES][MAX_FMTS] = {
+	[VPU_FMT_TYPE_CODEC] = {
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_HEVC,
+			.max_width = W5_MAX_ENC_PIC_WIDTH,
+			.min_width = W5_MIN_ENC_PIC_WIDTH,
+			.max_height = W5_MAX_ENC_PIC_HEIGHT,
+			.min_height = W5_MIN_ENC_PIC_HEIGHT,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_H264,
+			.max_width = W5_MAX_ENC_PIC_WIDTH,
+			.min_width = W5_MIN_ENC_PIC_WIDTH,
+			.max_height = W5_MAX_ENC_PIC_HEIGHT,
+			.min_height = W5_MIN_ENC_PIC_HEIGHT,
+		},
+	},
+	[VPU_FMT_TYPE_RAW] = {
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_YUV420,
+			.max_width = W5_MAX_ENC_PIC_WIDTH,
+			.min_width = W5_MIN_ENC_PIC_WIDTH,
+			.max_height = W5_MAX_ENC_PIC_HEIGHT,
+			.min_height = W5_MIN_ENC_PIC_HEIGHT,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_NV12,
+			.max_width = W5_MAX_ENC_PIC_WIDTH,
+			.min_width = W5_MIN_ENC_PIC_WIDTH,
+			.max_height = W5_MAX_ENC_PIC_HEIGHT,
+			.min_height = W5_MIN_ENC_PIC_HEIGHT,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_NV21,
+			.max_width = W5_MAX_ENC_PIC_WIDTH,
+			.min_width = W5_MIN_ENC_PIC_WIDTH,
+			.max_height = W5_MAX_ENC_PIC_HEIGHT,
+			.min_height = W5_MIN_ENC_PIC_HEIGHT,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_YUV420M,
+			.max_width = W5_MAX_ENC_PIC_WIDTH,
+			.min_width = W5_MIN_ENC_PIC_WIDTH,
+			.max_height = W5_MAX_ENC_PIC_HEIGHT,
+			.min_height = W5_MIN_ENC_PIC_HEIGHT,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_NV12M,
+			.max_width = W5_MAX_ENC_PIC_WIDTH,
+			.min_width = W5_MIN_ENC_PIC_WIDTH,
+			.max_height = W5_MAX_ENC_PIC_HEIGHT,
+			.min_height = W5_MIN_ENC_PIC_HEIGHT,
+		},
+		{
+			.v4l2_pix_fmt = V4L2_PIX_FMT_NV21M,
+			.max_width = W5_MAX_ENC_PIC_WIDTH,
+			.min_width = W5_MIN_ENC_PIC_WIDTH,
+			.max_height = W5_MAX_ENC_PIC_HEIGHT,
+			.min_height = W5_MIN_ENC_PIC_HEIGHT,
+		},
+	}
+};
+
+static enum wave_std wave5_to_vpu_wavestd(unsigned int v4l2_pix_fmt)
+{
+	switch (v4l2_pix_fmt) {
+	case V4L2_PIX_FMT_H264:
+		return W_AVC_ENC;
+	case V4L2_PIX_FMT_HEVC:
+		return W_HEVC_ENC;
+	default:
+		return STD_UNKNOWN;
+	}
+}
+
+static void wave5_update_pix_fmt(struct v4l2_pix_format_mplane *pix_mp, unsigned int width,
+				 unsigned int height)
+{
+	switch (pix_mp->pixelformat) {
+	case V4L2_PIX_FMT_YUV420:
+	case V4L2_PIX_FMT_NV12:
+	case V4L2_PIX_FMT_NV21:
+		pix_mp->width = width;
+		pix_mp->height = height;
+		pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
+		pix_mp->plane_fmt[0].sizeimage = round_up(width, 32) * height * 3 / 2;
+		break;
+	case V4L2_PIX_FMT_YUV420M:
+		pix_mp->width = width;
+		pix_mp->height = height;
+		pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
+		pix_mp->plane_fmt[0].sizeimage = round_up(width, 32) * height;
+		pix_mp->plane_fmt[1].bytesperline = round_up(width, 32) / 2;
+		pix_mp->plane_fmt[1].sizeimage = round_up(width, 32) * height / 4;
+		pix_mp->plane_fmt[2].bytesperline = round_up(width, 32) / 2;
+		pix_mp->plane_fmt[2].sizeimage = round_up(width, 32) * height / 4;
+		break;
+	case V4L2_PIX_FMT_NV12M:
+	case V4L2_PIX_FMT_NV21M:
+		pix_mp->width = width;
+		pix_mp->height = height;
+		pix_mp->plane_fmt[0].bytesperline = round_up(width, 32);
+		pix_mp->plane_fmt[0].sizeimage = round_up(width, 32) * height;
+		pix_mp->plane_fmt[1].bytesperline = round_up(width, 32);
+		pix_mp->plane_fmt[1].sizeimage = round_up(width, 32) * height / 2;
+		break;
+	default:
+		pix_mp->width = width;
+		pix_mp->height = height;
+		pix_mp->plane_fmt[0].bytesperline = 0;
+		pix_mp->plane_fmt[0].sizeimage = max(DEFAULT_SRC_SIZE(width, height),
+						     pix_mp->plane_fmt[0].sizeimage);
+		break;
+	}
+}
+
+static void wave5_vpu_enc_start_encode(struct vpu_instance *inst)
+{
+	int ret;
+	struct vb2_v4l2_buffer *src_buf;
+	struct vb2_v4l2_buffer *dst_buf;
+	struct vpu_buffer *src_vbuf;
+	struct vpu_buffer *dst_vbuf;
+	struct frame_buffer frame_buf;
+	struct enc_param pic_param;
+	u32 stride = ALIGN(inst->dst_fmt.width, 32);
+	u32 luma_size = (stride * inst->dst_fmt.height);
+	u32 chroma_size = ((stride / 2) * (inst->dst_fmt.height / 2));
+	u32 fail_res;
+
+	memset(&pic_param, 0, sizeof(struct enc_param));
+	memset(&frame_buf, 0, sizeof(struct frame_buffer));
+
+	src_vbuf = list_first_entry_or_null(&inst->avail_src_bufs, struct vpu_buffer, list);
+	dst_vbuf = list_first_entry_or_null(&inst->avail_dst_bufs, struct vpu_buffer, list);
+	if (!dst_vbuf) {
+		dev_dbg(inst->dev->dev, "no valid dst buf\n");
+		return;
+	}
+
+	dst_buf = &dst_vbuf->v4l2_m2m_buf.vb;
+	pic_param.pic_stream_buffer_addr =
+		vb2_dma_contig_plane_dma_addr(&dst_buf->vb2_buf, 0);
+	pic_param.pic_stream_buffer_size =
+		vb2_plane_size(&dst_buf->vb2_buf, 0);
+
+	if (!src_vbuf) {
+		dev_dbg(inst->dev->dev, "no valid src buf\n");
+		if (inst->state == VPU_INST_STATE_STOP)
+			pic_param.src_end_flag = 1;
+		else
+			return;
+	} else {
+		src_buf = &src_vbuf->v4l2_m2m_buf.vb;
+		if (inst->src_fmt.num_planes == 1) {
+			frame_buf.buf_y =
+				vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+			frame_buf.buf_cb = frame_buf.buf_y + luma_size;
+			frame_buf.buf_cr = frame_buf.buf_cb + chroma_size;
+		} else if (inst->src_fmt.num_planes == 2) {
+			frame_buf.buf_y =
+				vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+			frame_buf.buf_cb =
+				vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 1);
+			frame_buf.buf_cr = frame_buf.buf_cb + chroma_size;
+		} else if (inst->src_fmt.num_planes == 3) {
+			frame_buf.buf_y =
+				vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 0);
+			frame_buf.buf_cb =
+				vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 1);
+			frame_buf.buf_cr =
+				vb2_dma_contig_plane_dma_addr(&src_buf->vb2_buf, 2);
+		}
+		frame_buf.stride = stride;
+		pic_param.src_idx = src_buf->vb2_buf.index;
+	}
+
+	pic_param.source_frame = &frame_buf;
+	pic_param.code_option.implicit_header_encode = 1;
+	ret = wave5_vpu_enc_start_one_frame(inst, &pic_param, &fail_res);
+	if (ret) {
+		if (fail_res == WAVE5_SYSERR_QUEUEING_FAIL)
+			return;
+
+		dev_dbg(inst->dev->dev, "%s: wave5_vpu_enc_start_one_frame fail: %d\n",
+			__func__, ret);
+		src_buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx);
+		if (!src_buf) {
+			dev_dbg(inst->dev->dev,
+				"%s: Removing src buf failed, the queue is empty\n",
+				__func__);
+			return;
+		}
+		dst_buf = v4l2_m2m_dst_buf_remove(inst->v4l2_fh.m2m_ctx);
+		if (!dst_buf) {
+			dev_dbg(inst->dev->dev,
+				"%s: Removing dst buf failed, the queue is empty\n",
+				__func__);
+			return;
+		}
+		inst->state = VPU_INST_STATE_STOP;
+		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
+	} else {
+		dev_dbg(inst->dev->dev, "%s: wave5_vpu_enc_start_one_frame success\n",
+			__func__);
+		if (src_vbuf) {
+			src_vbuf->consumed = true;
+			list_del_init(&src_vbuf->list);
+		}
+		if (dst_vbuf) {
+			dst_vbuf->consumed = true;
+			list_del_init(&dst_vbuf->list);
+		}
+	}
+}
+
+static void wave5_vpu_enc_stop_encode(struct vpu_instance *inst)
+{
+	inst->state = VPU_INST_STATE_STOP;
+
+	v4l2_m2m_job_finish(inst->v4l2_m2m_dev, inst->v4l2_fh.m2m_ctx);
+}
+
+static void wave5_vpu_enc_finish_encode(struct vpu_instance *inst)
+{
+	int ret;
+	struct enc_output_info enc_output_info;
+	u32 irq_status;
+
+	if (kfifo_out(&inst->irq_status, &irq_status, sizeof(int)))
+		wave5_vpu_clear_interrupt_ex(inst, irq_status);
+
+	ret = wave5_vpu_enc_get_output_info(inst, &enc_output_info);
+	if (ret) {
+		dev_dbg(inst->dev->dev,
+			"%s: vpu_enc_get_output_info fail: %d  reason: %u | info: %u\n",
+			__func__, ret, enc_output_info.error_reason, enc_output_info.warn_info);
+		return;
+	}
+
+	if (enc_output_info.enc_src_idx >= 0) {
+		struct vb2_v4l2_buffer *src_buf =
+			v4l2_m2m_src_buf_remove_by_idx(inst->v4l2_fh.m2m_ctx,
+						       enc_output_info.enc_src_idx);
+
+		inst->timestamp = src_buf->vb2_buf.timestamp;
+		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+	}
+
+	if (enc_output_info.recon_frame_index == RECON_IDX_FLAG_ENC_END) {
+		struct vb2_v4l2_buffer *dst_buf =
+			v4l2_m2m_dst_buf_remove(inst->v4l2_fh.m2m_ctx);
+		static const struct v4l2_event vpu_event_eos = {
+			.type = V4L2_EVENT_EOS
+		};
+
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, 0);
+		dst_buf->vb2_buf.timestamp = inst->timestamp;
+		dst_buf->field = V4L2_FIELD_NONE;
+		dst_buf->flags |= V4L2_BUF_FLAG_LAST;
+		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
+
+		inst->eos = true;
+		v4l2_event_queue_fh(&inst->v4l2_fh, &vpu_event_eos);
+
+		v4l2_m2m_job_finish(inst->v4l2_m2m_dev, inst->v4l2_fh.m2m_ctx);
+	} else {
+		struct vb2_v4l2_buffer *dst_buf =
+			v4l2_m2m_dst_buf_remove(inst->v4l2_fh.m2m_ctx);
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, enc_output_info.bitstream_size);
+
+		dst_buf->vb2_buf.timestamp = inst->timestamp;
+		dst_buf->field = V4L2_FIELD_NONE;
+		if (enc_output_info.pic_type == PIC_TYPE_I) {
+			if (enc_output_info.enc_vcl_nut == 19 ||
+			    enc_output_info.enc_vcl_nut == 20)
+				dst_buf->flags |= V4L2_BUF_FLAG_KEYFRAME;
+			else
+				dst_buf->flags |= V4L2_BUF_FLAG_PFRAME;
+		} else if (enc_output_info.pic_type == PIC_TYPE_P) {
+			dst_buf->flags |= V4L2_BUF_FLAG_PFRAME;
+		} else if (enc_output_info.pic_type == PIC_TYPE_B) {
+			dst_buf->flags |= V4L2_BUF_FLAG_BFRAME;
+		}
+
+		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
+
+		dev_dbg(inst->dev->dev, "%s: frame_cycle %8u\n",
+			__func__, enc_output_info.frame_cycle);
+	}
+}
+
+static int wave5_vpu_enc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
+{
+	strscpy(cap->driver, VPU_ENC_DRV_NAME, sizeof(cap->driver));
+	strscpy(cap->card, VPU_ENC_DRV_NAME, sizeof(cap->card));
+	strscpy(cap->bus_info, "platform:" VPU_ENC_DRV_NAME, sizeof(cap->bus_info));
+
+	return 0;
+}
+
+static int wave5_vpu_enc_enum_framesizes(struct file *f, void *fh, struct v4l2_frmsizeenum *fsize)
+{
+	const struct vpu_format *vpu_fmt;
+
+	if (fsize->index)
+		return -EINVAL;
+
+	vpu_fmt = wave5_find_vpu_fmt(fsize->pixel_format, enc_fmt_list[VPU_FMT_TYPE_CODEC]);
+	if (!vpu_fmt) {
+		vpu_fmt = wave5_find_vpu_fmt(fsize->pixel_format, enc_fmt_list[VPU_FMT_TYPE_RAW]);
+		if (!vpu_fmt)
+			return -EINVAL;
+	}
+
+	fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
+	fsize->stepwise.min_width = vpu_fmt->min_width;
+	fsize->stepwise.max_width = vpu_fmt->max_width;
+	fsize->stepwise.step_width = 1;
+	fsize->stepwise.min_height = vpu_fmt->min_height;
+	fsize->stepwise.max_height = vpu_fmt->max_height;
+	fsize->stepwise.step_height = 1;
+
+	return 0;
+}
+
+static int wave5_vpu_enc_enum_fmt_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	const struct vpu_format *vpu_fmt;
+
+	dev_dbg(inst->dev->dev, "%s: index: %u\n", __func__, f->index);
+
+	vpu_fmt = wave5_find_vpu_fmt_by_idx(f->index, enc_fmt_list[VPU_FMT_TYPE_CODEC]);
+	if (!vpu_fmt)
+		return -EINVAL;
+
+	f->pixelformat = vpu_fmt->v4l2_pix_fmt;
+	f->flags = 0;
+
+	return 0;
+}
+
+static int wave5_vpu_enc_try_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	const struct vpu_format *vpu_fmt;
+
+	dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n",
+		__func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+		f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field);
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		return -EINVAL;
+
+	vpu_fmt = wave5_find_vpu_fmt(f->fmt.pix_mp.pixelformat, enc_fmt_list[VPU_FMT_TYPE_CODEC]);
+	if (!vpu_fmt) {
+		f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat;
+		f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes;
+		wave5_update_pix_fmt(&f->fmt.pix_mp, inst->dst_fmt.width, inst->dst_fmt.height);
+	} else {
+		int width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width);
+		int height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height);
+
+		f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt;
+		f->fmt.pix_mp.num_planes = 1;
+		wave5_update_pix_fmt(&f->fmt.pix_mp, width, height);
+	}
+
+	f->fmt.pix_mp.flags = 0;
+	f->fmt.pix_mp.field = V4L2_FIELD_NONE;
+	f->fmt.pix_mp.colorspace = inst->colorspace;
+	f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc;
+	f->fmt.pix_mp.hsv_enc = inst->hsv_enc;
+	f->fmt.pix_mp.quantization = inst->quantization;
+	f->fmt.pix_mp.xfer_func = inst->xfer_func;
+	memset(&f->fmt.pix_mp.reserved, 0, sizeof(f->fmt.pix_mp.reserved));
+
+	return 0;
+}
+
+static int wave5_vpu_enc_s_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	int i, ret;
+
+	dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n",
+		__func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+		f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field);
+
+	ret = wave5_vpu_enc_try_fmt_cap(file, fh, f);
+	if (ret)
+		return ret;
+
+	inst->dst_fmt.width = f->fmt.pix_mp.width;
+	inst->dst_fmt.height = f->fmt.pix_mp.height;
+	inst->dst_fmt.pixelformat = f->fmt.pix_mp.pixelformat;
+	inst->dst_fmt.field = f->fmt.pix_mp.field;
+	inst->dst_fmt.flags = f->fmt.pix_mp.flags;
+	inst->dst_fmt.num_planes = f->fmt.pix_mp.num_planes;
+	for (i = 0; i < inst->dst_fmt.num_planes; i++) {
+		inst->dst_fmt.plane_fmt[i].bytesperline = f->fmt.pix_mp.plane_fmt[i].bytesperline;
+		inst->dst_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage;
+	}
+
+	return 0;
+}
+
+static int wave5_vpu_enc_g_fmt_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	int i;
+
+	f->fmt.pix_mp.width = inst->dst_fmt.width;
+	f->fmt.pix_mp.height = inst->dst_fmt.height;
+	f->fmt.pix_mp.pixelformat = inst->dst_fmt.pixelformat;
+	f->fmt.pix_mp.field = inst->dst_fmt.field;
+	f->fmt.pix_mp.flags = inst->dst_fmt.flags;
+	f->fmt.pix_mp.num_planes = inst->dst_fmt.num_planes;
+	for (i = 0; i < f->fmt.pix_mp.num_planes; i++) {
+		f->fmt.pix_mp.plane_fmt[i].bytesperline = inst->dst_fmt.plane_fmt[i].bytesperline;
+		f->fmt.pix_mp.plane_fmt[i].sizeimage = inst->dst_fmt.plane_fmt[i].sizeimage;
+	}
+
+	f->fmt.pix_mp.colorspace = inst->colorspace;
+	f->fmt.pix_mp.ycbcr_enc = inst->ycbcr_enc;
+	f->fmt.pix_mp.hsv_enc = inst->hsv_enc;
+	f->fmt.pix_mp.quantization = inst->quantization;
+	f->fmt.pix_mp.xfer_func = inst->xfer_func;
+
+	return 0;
+}
+
+static int wave5_vpu_enc_enum_fmt_out(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	const struct vpu_format *vpu_fmt;
+
+	dev_dbg(inst->dev->dev, "%s: index: %u\n", __func__, f->index);
+
+	vpu_fmt = wave5_find_vpu_fmt_by_idx(f->index, enc_fmt_list[VPU_FMT_TYPE_RAW]);
+	if (!vpu_fmt)
+		return -EINVAL;
+
+	f->pixelformat = vpu_fmt->v4l2_pix_fmt;
+	f->flags = 0;
+
+	return 0;
+}
+
+static int wave5_vpu_enc_try_fmt_out(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	const struct vpu_format *vpu_fmt;
+
+	dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n",
+		__func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+		f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field);
+
+	if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return -EINVAL;
+
+	vpu_fmt = wave5_find_vpu_fmt(f->fmt.pix_mp.pixelformat, enc_fmt_list[VPU_FMT_TYPE_RAW]);
+	if (!vpu_fmt) {
+		f->fmt.pix_mp.pixelformat = inst->src_fmt.pixelformat;
+		f->fmt.pix_mp.num_planes = inst->src_fmt.num_planes;
+		wave5_update_pix_fmt(&f->fmt.pix_mp, inst->src_fmt.width, inst->src_fmt.height);
+	} else {
+		int width = clamp(f->fmt.pix_mp.width, vpu_fmt->min_width, vpu_fmt->max_width);
+		int height = clamp(f->fmt.pix_mp.height, vpu_fmt->min_height, vpu_fmt->max_height);
+		const struct v4l2_format_info *info = v4l2_format_info(vpu_fmt->v4l2_pix_fmt);
+
+		f->fmt.pix_mp.pixelformat = vpu_fmt->v4l2_pix_fmt;
+		f->fmt.pix_mp.num_planes = info->mem_planes;
+		wave5_update_pix_fmt(&f->fmt.pix_mp, width, height);
+	}
+
+	f->fmt.pix_mp.flags = 0;
+	f->fmt.pix_mp.field = V4L2_FIELD_NONE;
+	memset(&f->fmt.pix_mp.reserved, 0, sizeof(f->fmt.pix_mp.reserved));
+
+	return 0;
+}
+
+static int wave5_vpu_enc_s_fmt_out(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	int i, ret;
+
+	dev_dbg(inst->dev->dev, "%s: fourcc: %u width: %u height: %u num_planes: %u field: %u\n",
+		__func__, f->fmt.pix_mp.pixelformat, f->fmt.pix_mp.width, f->fmt.pix_mp.height,
+		f->fmt.pix_mp.num_planes, f->fmt.pix_mp.field);
+
+	ret = wave5_vpu_enc_try_fmt_out(file, fh, f);
+	if (ret)
+		return ret;
+
+	inst->src_fmt.width = f->fmt.pix_mp.width;
+	inst->src_fmt.height = f->fmt.pix_mp.height;
+	inst->src_fmt.pixelformat = f->fmt.pix_mp.pixelformat;
+	inst->src_fmt.field = f->fmt.pix_mp.field;
+	inst->src_fmt.flags = f->fmt.pix_mp.flags;
+	inst->src_fmt.num_planes = f->fmt.pix_mp.num_planes;
+	for (i = 0; i < inst->src_fmt.num_planes; i++) {
+		inst->src_fmt.plane_fmt[i].bytesperline = f->fmt.pix_mp.plane_fmt[i].bytesperline;
+		inst->src_fmt.plane_fmt[i].sizeimage = f->fmt.pix_mp.plane_fmt[i].sizeimage;
+	}
+
+	if (inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV12 ||
+	    inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV12M) {
+		inst->cbcr_interleave = true;
+		inst->nv21 = false;
+	} else if (inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV21 ||
+		   inst->src_fmt.pixelformat == V4L2_PIX_FMT_NV21M) {
+		inst->cbcr_interleave = true;
+		inst->nv21 = true;
+	} else {
+		inst->cbcr_interleave = false;
+		inst->nv21 = false;
+	}
+
+	inst->colorspace = f->fmt.pix_mp.colorspace;
+	inst->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
+	inst->hsv_enc = f->fmt.pix_mp.hsv_enc;
+	inst->quantization = f->fmt.pix_mp.quantization;
+	inst->xfer_func = f->fmt.pix_mp.xfer_func;
+
+	wave5_update_pix_fmt(&inst->dst_fmt, f->fmt.pix_mp.width, f->fmt.pix_mp.height);
+
+	return 0;
+}
+
+static int wave5_vpu_enc_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+
+	dev_dbg(inst->dev->dev, "%s: type: %u | target: %u\n", __func__, s->type, s->target);
+
+	if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+		switch (s->target) {
+		case V4L2_SEL_TGT_CROP_DEFAULT:
+		case V4L2_SEL_TGT_CROP_BOUNDS:
+			s->r.left = 0;
+			s->r.top = 0;
+			s->r.width = inst->dst_fmt.width;
+			s->r.height = inst->dst_fmt.height;
+			break;
+		case V4L2_SEL_TGT_CROP:
+			s->r.left = 0;
+			s->r.top = 0;
+			s->r.width = inst->dst_fmt.width;
+			s->r.height = inst->dst_fmt.height;
+			dev_dbg(inst->dev->dev, "%s: V4L2_SEL_TGT_CROP width: %u | height: %u\n",
+				__func__, s->r.width, s->r.height);
+			break;
+		default:
+			return -EINVAL;
+		}
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int wave5_vpu_enc_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		return -EINVAL;
+
+	if (s->target != V4L2_SEL_TGT_CROP)
+		return -EINVAL;
+
+	dev_dbg(inst->dev->dev, "%s: V4L2_SEL_TGT_CROP width: %u | height: %u\n",
+		__func__, s->r.width, s->r.height);
+
+	s->r.left = 0;
+	s->r.top = 0;
+	s->r.width = inst->src_fmt.width;
+	s->r.height = inst->src_fmt.height;
+
+	return 0;
+}
+
+static int wave5_vpu_enc_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *ec)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+	int ret;
+
+	ret = v4l2_m2m_ioctl_try_encoder_cmd(file, fh, ec);
+	if (ret)
+		return ret;
+
+	if (!wave5_vpu_both_queues_are_streaming(inst))
+		return 0;
+
+	switch (ec->cmd) {
+	case V4L2_ENC_CMD_STOP:
+		inst->state = VPU_INST_STATE_STOP;
+		inst->ops->start_process(inst);
+		break;
+	case V4L2_ENC_CMD_START:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int wave5_vpu_enc_g_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+
+	dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, a->type);
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return -EINVAL;
+
+	a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+	a->parm.output.timeperframe.numerator = 1;
+	a->parm.output.timeperframe.denominator = inst->frame_rate;
+
+	dev_dbg(inst->dev->dev, "%s: numerator: %u | denominator: %u\n",
+		__func__, a->parm.output.timeperframe.numerator,
+		a->parm.output.timeperframe.denominator);
+
+	return 0;
+}
+
+static int wave5_vpu_enc_s_parm(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct vpu_instance *inst = wave5_to_vpu_inst(fh);
+
+	dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, a->type);
+
+	if (a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && a->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return -EINVAL;
+
+	a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+	if (a->parm.output.timeperframe.denominator && a->parm.output.timeperframe.numerator) {
+		inst->frame_rate = a->parm.output.timeperframe.denominator /
+				   a->parm.output.timeperframe.numerator;
+	} else {
+		a->parm.output.timeperframe.numerator = 1;
+		a->parm.output.timeperframe.denominator = inst->frame_rate;
+	}
+
+	dev_dbg(inst->dev->dev, "%s: numerator: %u | denominator: %u\n",
+		__func__, a->parm.output.timeperframe.numerator,
+		a->parm.output.timeperframe.denominator);
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops wave5_vpu_enc_ioctl_ops = {
+	.vidioc_querycap = wave5_vpu_enc_querycap,
+	.vidioc_enum_framesizes = wave5_vpu_enc_enum_framesizes,
+
+	.vidioc_enum_fmt_vid_cap	= wave5_vpu_enc_enum_fmt_cap,
+	.vidioc_s_fmt_vid_cap_mplane = wave5_vpu_enc_s_fmt_cap,
+	.vidioc_g_fmt_vid_cap_mplane = wave5_vpu_enc_g_fmt_cap,
+	.vidioc_try_fmt_vid_cap_mplane = wave5_vpu_enc_try_fmt_cap,
+
+	.vidioc_enum_fmt_vid_out	= wave5_vpu_enc_enum_fmt_out,
+	.vidioc_s_fmt_vid_out_mplane = wave5_vpu_enc_s_fmt_out,
+	.vidioc_g_fmt_vid_out_mplane = wave5_vpu_g_fmt_out,
+	.vidioc_try_fmt_vid_out_mplane = wave5_vpu_enc_try_fmt_out,
+
+	.vidioc_g_selection = wave5_vpu_enc_g_selection,
+	.vidioc_s_selection = wave5_vpu_enc_s_selection,
+
+	.vidioc_g_parm = wave5_vpu_enc_g_parm,
+	.vidioc_s_parm = wave5_vpu_enc_s_parm,
+
+	.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
+	.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+	.vidioc_streamon = v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+
+	.vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
+	.vidioc_encoder_cmd = wave5_vpu_enc_encoder_cmd,
+
+	.vidioc_subscribe_event = wave5_vpu_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static int wave5_vpu_enc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct vpu_instance *inst = wave5_ctrl_to_vpu_inst(ctrl);
+
+	dev_dbg(inst->dev->dev, "%s: name: %s | value: %d\n", __func__, ctrl->name, ctrl->val);
+
+	switch (ctrl->id) {
+	case V4L2_CID_HFLIP:
+		inst->mirror_direction |= (ctrl->val << 1);
+		break;
+	case V4L2_CID_VFLIP:
+		inst->mirror_direction |= ctrl->val;
+		break;
+	case V4L2_CID_ROTATE:
+		inst->rot_angle = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_VBV_SIZE:
+		inst->vbv_buf_size = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
+		switch (ctrl->val) {
+		case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
+			inst->rc_mode = 0;
+			break;
+		case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
+			inst->rc_mode = 1;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		inst->bit_rate = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		inst->enc_param.avc_idr_period = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
+		inst->enc_param.independ_slice_mode = ctrl->val;
+		inst->enc_param.avc_slice_mode = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
+		inst->enc_param.independ_slice_mode_arg = ctrl->val;
+		inst->enc_param.avc_slice_arg = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE:
+		inst->rc_enable = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE:
+		inst->enc_param.mb_level_rc_enable = ctrl->val;
+		inst->enc_param.cu_level_rc_enable = ctrl->val;
+		inst->enc_param.hvs_qp_enable = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
+		switch (ctrl->val) {
+		case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN:
+			inst->enc_param.profile = HEVC_PROFILE_MAIN;
+			inst->bit_depth = 8;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE:
+			inst->enc_param.profile = HEVC_PROFILE_STILLPICTURE;
+			inst->enc_param.en_still_picture = 1;
+			inst->bit_depth = 8;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10:
+			inst->enc_param.profile = HEVC_PROFILE_MAIN10;
+			inst->bit_depth = 10;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
+		switch (ctrl->val) {
+		case V4L2_MPEG_VIDEO_HEVC_LEVEL_1:
+			inst->enc_param.level = 10 * 3;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_LEVEL_2:
+			inst->enc_param.level = 20 * 3;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_LEVEL_2_1:
+			inst->enc_param.level = 21 * 3;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_LEVEL_3:
+			inst->enc_param.level = 30 * 3;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_LEVEL_3_1:
+			inst->enc_param.level = 31 * 3;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_LEVEL_4:
+			inst->enc_param.level = 40 * 3;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_LEVEL_4_1:
+			inst->enc_param.level = 41 * 3;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_LEVEL_5:
+			inst->enc_param.level = 50 * 3;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1:
+			inst->enc_param.level = 51 * 3;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2:
+			inst->enc_param.level = 52 * 3;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP:
+		inst->enc_param.min_qp_i = ctrl->val;
+		inst->enc_param.min_qp_p = ctrl->val;
+		inst->enc_param.min_qp_b = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP:
+		inst->enc_param.max_qp_i = ctrl->val;
+		inst->enc_param.max_qp_p = ctrl->val;
+		inst->enc_param.max_qp_b = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP:
+		inst->enc_param.intra_qp = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE:
+		switch (ctrl->val) {
+		case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED:
+			inst->enc_param.disable_deblk = 1;
+			inst->enc_param.sao_enable = 0;
+			inst->enc_param.lf_cross_slice_boundary_enable = 0;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED:
+			inst->enc_param.disable_deblk = 0;
+			inst->enc_param.sao_enable = 1;
+			inst->enc_param.lf_cross_slice_boundary_enable = 1;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY:
+			inst->enc_param.disable_deblk = 0;
+			inst->enc_param.sao_enable = 1;
+			inst->enc_param.lf_cross_slice_boundary_enable = 0;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2:
+		inst->enc_param.beta_offset_div2 = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2:
+		inst->enc_param.tc_offset_div2 = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE:
+		switch (ctrl->val) {
+		case V4L2_MPEG_VIDEO_HEVC_REFRESH_NONE:
+			inst->enc_param.decoding_refresh_type = 0;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_REFRESH_CRA:
+			inst->enc_param.decoding_refresh_type = 1;
+			break;
+		case V4L2_MPEG_VIDEO_HEVC_REFRESH_IDR:
+			inst->enc_param.decoding_refresh_type = 2;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD:
+		inst->enc_param.intra_period = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU:
+		inst->enc_param.lossless_enable = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED:
+		inst->enc_param.const_intra_pred_flag = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT:
+		inst->enc_param.wpp_enable = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOOTHING:
+		inst->enc_param.strong_intra_smooth_enable = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1:
+		inst->enc_param.max_num_merge = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_HEVC_TMV_PREDICTION:
+		inst->enc_param.tmvp_enable = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+		switch (ctrl->val) {
+		case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+		case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+			inst->enc_param.profile = H264_PROFILE_BP;
+			inst->bit_depth = 8;
+			break;
+		case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+			inst->enc_param.profile = H264_PROFILE_MP;
+			inst->bit_depth = 8;
+			break;
+		case V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED:
+			inst->enc_param.profile = H264_PROFILE_EXTENDED;
+			inst->bit_depth = 8;
+			break;
+		case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
+			inst->enc_param.profile = H264_PROFILE_HP;
+			inst->bit_depth = 8;
+			break;
+		case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10:
+			inst->enc_param.profile = H264_PROFILE_HIGH10;
+			inst->bit_depth = 10;
+			break;
+		case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422:
+			inst->enc_param.profile = H264_PROFILE_HIGH422;
+			inst->bit_depth = 10;
+			break;
+		case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE:
+			inst->enc_param.profile = H264_PROFILE_HIGH444;
+			inst->bit_depth = 10;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+		switch (ctrl->val) {
+		case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
+			inst->enc_param.level = 10;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
+			inst->enc_param.level = 9;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
+			inst->enc_param.level = 11;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
+			inst->enc_param.level = 12;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
+			inst->enc_param.level = 13;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
+			inst->enc_param.level = 20;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
+			inst->enc_param.level = 21;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
+			inst->enc_param.level = 22;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
+			inst->enc_param.level = 30;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
+			inst->enc_param.level = 31;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
+			inst->enc_param.level = 32;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
+			inst->enc_param.level = 40;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
+			inst->enc_param.level = 41;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
+			inst->enc_param.level = 42;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
+			inst->enc_param.level = 50;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
+			inst->enc_param.level = 51;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+		inst->enc_param.min_qp_i = ctrl->val;
+		inst->enc_param.min_qp_p = ctrl->val;
+		inst->enc_param.min_qp_b = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_MAX_QP:
+		inst->enc_param.max_qp_i = ctrl->val;
+		inst->enc_param.max_qp_p = ctrl->val;
+		inst->enc_param.max_qp_b = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+		inst->enc_param.intra_qp = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE:
+		switch (ctrl->val) {
+		case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED:
+			inst->enc_param.disable_deblk = 1;
+			inst->enc_param.lf_cross_slice_boundary_enable = 1;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED:
+			inst->enc_param.disable_deblk = 0;
+			inst->enc_param.lf_cross_slice_boundary_enable = 1;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY:
+			inst->enc_param.disable_deblk = 0;
+			inst->enc_param.lf_cross_slice_boundary_enable = 0;
+			break;
+		default:
+			return -EINVAL;
+		}
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA:
+		inst->enc_param.beta_offset_div2 = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA:
+		inst->enc_param.tc_offset_div2 = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
+		inst->enc_param.transform8x8_enable = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION:
+		inst->enc_param.const_intra_pred_flag = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET:
+		inst->enc_param.chroma_cb_qp_offset = ctrl->val;
+		inst->enc_param.chroma_cr_qp_offset = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
+		inst->enc_param.intra_period = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+		inst->enc_param.entropy_coding_mode = ctrl->val;
+		break;
+	case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
+		break;
+	case V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR:
+		inst->enc_param.forced_idr_header_enable = ctrl->val;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops wave5_vpu_enc_ctrl_ops = {
+	.s_ctrl = wave5_vpu_enc_s_ctrl,
+};
+
+static void wave5_set_enc_openparam(struct enc_open_param *open_param,
+				    struct vpu_instance *inst)
+{
+	struct enc_wave_param input = inst->enc_param;
+	u32 num_ctu_row = ALIGN(inst->dst_fmt.height, 64) / 64;
+	u32 num_mb_row = ALIGN(inst->dst_fmt.height, 16) / 16;
+
+	open_param->wave_param.gop_preset_idx = PRESET_IDX_IPP_SINGLE;
+	open_param->wave_param.hvs_qp_scale = 2;
+	open_param->wave_param.hvs_max_delta_qp = 10;
+	open_param->wave_param.skip_intra_trans = 1;
+	open_param->wave_param.intra_nx_n_enable = 1;
+	open_param->wave_param.nr_intra_weight_y = 7;
+	open_param->wave_param.nr_intra_weight_cb = 7;
+	open_param->wave_param.nr_intra_weight_cr = 7;
+	open_param->wave_param.nr_inter_weight_y = 4;
+	open_param->wave_param.nr_inter_weight_cb = 4;
+	open_param->wave_param.nr_inter_weight_cr = 4;
+	open_param->wave_param.rdo_skip = 1;
+	open_param->wave_param.lambda_scaling_enable = 1;
+
+	open_param->stream_endian = VPU_STREAM_ENDIAN;
+	open_param->source_endian = VPU_SOURCE_ENDIAN;
+	open_param->line_buf_int_en = true;
+	open_param->pic_width = inst->dst_fmt.width;
+	open_param->pic_height = inst->dst_fmt.height;
+	open_param->frame_rate_info = inst->frame_rate;
+	open_param->rc_enable = inst->rc_enable;
+	if (inst->rc_enable) {
+		open_param->wave_param.initial_rc_qp = -1;
+		open_param->wave_param.rc_weight_param = 16;
+		open_param->wave_param.rc_weight_buf = 128;
+	}
+	open_param->wave_param.mb_level_rc_enable = input.mb_level_rc_enable;
+	open_param->wave_param.cu_level_rc_enable = input.cu_level_rc_enable;
+	open_param->wave_param.hvs_qp_enable = input.hvs_qp_enable;
+	open_param->bit_rate = inst->bit_rate;
+	open_param->vbv_buffer_size = inst->vbv_buf_size;
+	if (inst->rc_mode == 0)
+		open_param->vbv_buffer_size = 3000;
+	open_param->wave_param.profile = input.profile;
+	open_param->wave_param.en_still_picture = input.en_still_picture;
+	open_param->wave_param.level = input.level;
+	open_param->wave_param.internal_bit_depth = inst->bit_depth;
+	open_param->wave_param.intra_qp = input.intra_qp;
+	open_param->wave_param.min_qp_i = input.min_qp_i;
+	open_param->wave_param.max_qp_i = input.max_qp_i;
+	open_param->wave_param.min_qp_p = input.min_qp_p;
+	open_param->wave_param.max_qp_p = input.max_qp_p;
+	open_param->wave_param.min_qp_b = input.min_qp_b;
+	open_param->wave_param.max_qp_b = input.max_qp_b;
+	open_param->wave_param.disable_deblk = input.disable_deblk;
+	open_param->wave_param.lf_cross_slice_boundary_enable =
+		input.lf_cross_slice_boundary_enable;
+	open_param->wave_param.tc_offset_div2 = input.tc_offset_div2;
+	open_param->wave_param.beta_offset_div2 = input.beta_offset_div2;
+	open_param->wave_param.decoding_refresh_type = input.decoding_refresh_type;
+	open_param->wave_param.intra_period = input.intra_period;
+	if (inst->std == W_HEVC_ENC) {
+		if (input.intra_period == 0) {
+			open_param->wave_param.decoding_refresh_type = DEC_REFRESH_TYPE_IDR;
+			open_param->wave_param.intra_period = input.avc_idr_period;
+		}
+	} else {
+		open_param->wave_param.avc_idr_period = input.avc_idr_period;
+	}
+	open_param->wave_param.entropy_coding_mode = input.entropy_coding_mode;
+	open_param->wave_param.lossless_enable = input.lossless_enable;
+	open_param->wave_param.const_intra_pred_flag = input.const_intra_pred_flag;
+	open_param->wave_param.wpp_enable = input.wpp_enable;
+	open_param->wave_param.strong_intra_smooth_enable = input.strong_intra_smooth_enable;
+	open_param->wave_param.max_num_merge = input.max_num_merge;
+	open_param->wave_param.tmvp_enable = input.tmvp_enable;
+	open_param->wave_param.transform8x8_enable = input.transform8x8_enable;
+	open_param->wave_param.chroma_cb_qp_offset = input.chroma_cb_qp_offset;
+	open_param->wave_param.chroma_cr_qp_offset = input.chroma_cr_qp_offset;
+	open_param->wave_param.independ_slice_mode = input.independ_slice_mode;
+	open_param->wave_param.independ_slice_mode_arg = input.independ_slice_mode_arg;
+	open_param->wave_param.avc_slice_mode = input.avc_slice_mode;
+	open_param->wave_param.avc_slice_arg = input.avc_slice_arg;
+	open_param->wave_param.intra_mb_refresh_mode = input.intra_mb_refresh_mode;
+	if (input.intra_mb_refresh_mode != REFRESH_MB_MODE_NONE) {
+		if (num_mb_row >= input.intra_mb_refresh_arg)
+			open_param->wave_param.intra_mb_refresh_arg =
+				num_mb_row / input.intra_mb_refresh_arg;
+		else
+			open_param->wave_param.intra_mb_refresh_arg = num_mb_row;
+	}
+	open_param->wave_param.intra_refresh_mode = input.intra_refresh_mode;
+	if (input.intra_refresh_mode != 0) {
+		if (num_ctu_row >= input.intra_refresh_arg)
+			open_param->wave_param.intra_refresh_arg =
+				num_ctu_row / input.intra_refresh_arg;
+		else
+			open_param->wave_param.intra_refresh_arg = num_ctu_row;
+	}
+	open_param->wave_param.forced_idr_header_enable = input.forced_idr_header_enable;
+}
+
+static int wave5_vpu_enc_queue_setup(struct vb2_queue *q, unsigned int *num_buffers,
+				     unsigned int *num_planes, unsigned int sizes[],
+				     struct device *alloc_devs[])
+{
+	struct vpu_instance *inst = vb2_get_drv_priv(q);
+	struct v4l2_pix_format_mplane inst_format =
+		(q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ? inst->src_fmt : inst->dst_fmt;
+	unsigned int i;
+	int ret;
+
+	dev_dbg(inst->dev->dev, "%s: num_buffers: %u | num_planes: %u | type: %u\n", __func__,
+		*num_buffers, *num_planes, q->type);
+
+	if (*num_planes) {
+		if (inst_format.num_planes != *num_planes)
+			return -EINVAL;
+
+		for (i = 0; i < *num_planes; i++) {
+			if (sizes[i] < inst_format.plane_fmt[i].sizeimage)
+				return -EINVAL;
+		}
+	} else {
+		*num_planes = inst_format.num_planes;
+		for (i = 0; i < *num_planes; i++) {
+			sizes[i] = inst_format.plane_fmt[i].sizeimage;
+			dev_dbg(inst->dev->dev, "%s: size[%u]: %u\n", __func__, i, sizes[i]);
+		}
+	}
+
+	dev_dbg(inst->dev->dev, "%s: size: %u\n", __func__, sizes[0]);
+
+	if (inst->state == VPU_INST_STATE_NONE && q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		unsigned int non_linear_num = 0;
+		u32 fb_stride = 0;
+		u32 fb_height = 0;
+		struct enc_open_param open_param;
+		struct enc_initial_info initial_info;
+		struct v4l2_ctrl *ctrl;
+
+		wave5_instance_set_clk(inst);
+		memset(&open_param, 0, sizeof(struct enc_open_param));
+
+		inst->std = wave5_to_vpu_wavestd(inst->dst_fmt.pixelformat);
+		if (inst->std == STD_UNKNOWN) {
+			dev_warn(inst->dev->dev, "unsupported pixelformat: %.4s\n",
+				 (char *)&inst->dst_fmt.pixelformat);
+			return -EINVAL;
+		}
+
+		wave5_set_enc_openparam(&open_param, inst);
+
+		ret = wave5_vpu_enc_open(inst, &open_param);
+		if (ret) {
+			dev_dbg(inst->dev->dev, "%s: wave5_vpu_enc_open, fail: %d\n",
+				__func__, ret);
+			return ret;
+		}
+
+		inst->state = VPU_INST_STATE_OPEN;
+
+		if (inst->mirror_direction) {
+			wave5_vpu_enc_give_command(inst, ENABLE_MIRRORING, NULL);
+			wave5_vpu_enc_give_command(inst, SET_MIRROR_DIRECTION,
+						   &inst->mirror_direction);
+		}
+		if (inst->rot_angle) {
+			wave5_vpu_enc_give_command(inst, ENABLE_ROTATION, NULL);
+			wave5_vpu_enc_give_command(inst, SET_ROTATION_ANGLE, &inst->rot_angle);
+		}
+
+		ret = wave5_vpu_enc_issue_seq_init(inst);
+		if (ret) {
+			dev_dbg(inst->dev->dev, "%s: wave5_vpu_enc_issue_seq_init, fail: %d\n",
+				__func__, ret);
+			return ret;
+		}
+
+		if (wave5_vpu_wait_interrupt(inst, VPU_ENC_TIMEOUT) < 0) {
+			dev_dbg(inst->dev->dev, "%s: wave5_vpu_wait_interrupt failed\n", __func__);
+			return -EINVAL;
+		}
+
+		ret = wave5_vpu_enc_complete_seq_init(inst, &initial_info);
+		if (ret)
+			return ret;
+
+		dev_dbg(inst->dev->dev, "%s: min_frame_buffer: %u | min_source_buffer: %u\n",
+			__func__, initial_info.min_frame_buffer_count,
+			initial_info.min_src_frame_count);
+		inst->state = VPU_INST_STATE_INIT_SEQ;
+		inst->min_src_buf_count = initial_info.min_src_frame_count +
+					  COMMAND_QUEUE_DEPTH;
+
+		ctrl = v4l2_ctrl_find(&inst->v4l2_ctrl_hdl,
+				      V4L2_CID_MIN_BUFFERS_FOR_OUTPUT);
+		if (ctrl)
+			v4l2_ctrl_s_ctrl(ctrl, inst->min_src_buf_count);
+
+		inst->fbc_buf_count = initial_info.min_frame_buffer_count;
+		inst->src_buf_count = inst->min_src_buf_count;
+
+		if (*num_buffers > inst->src_buf_count)
+			inst->src_buf_count = *num_buffers;
+
+		*num_buffers = inst->src_buf_count;
+		non_linear_num = inst->fbc_buf_count;
+
+		fb_stride = ALIGN(inst->dst_fmt.width, 32);
+		fb_height = ALIGN(inst->dst_fmt.height, 32);
+
+		for (i = 0; i < non_linear_num; i++) {
+			u32 luma_size = fb_stride * fb_height;
+			u32 chroma_size = ALIGN(fb_stride / 2, 16) * fb_height;
+
+			inst->frame_vbuf[i].size = luma_size + chroma_size;
+			ret = wave5_vdi_allocate_dma_memory(inst->dev, &inst->frame_vbuf[i]);
+			if (ret < 0) {
+				dev_dbg(inst->dev->dev, "%s: failed to allocate FBC buffer %zu\n",
+					__func__, inst->frame_vbuf[i].size);
+				goto free_buffers;
+			}
+
+			inst->frame_buf[i].buf_y = inst->frame_vbuf[i].daddr;
+			inst->frame_buf[i].buf_cb = (dma_addr_t)-1;
+			inst->frame_buf[i].buf_cr = (dma_addr_t)-1;
+			inst->frame_buf[i].update_fb_info = true;
+			inst->frame_buf[i].size = inst->frame_vbuf[i].size;
+		}
+
+		ret = wave5_vpu_enc_register_frame_buffer(inst, non_linear_num, fb_stride,
+							  fb_height, COMPRESSED_FRAME_MAP);
+		if (ret) {
+			dev_dbg(inst->dev->dev,
+				"%s: wave5_vpu_enc_register_frame_buffer, fail: %d\n",
+				__func__, ret);
+			goto free_buffers;
+		}
+
+		inst->state = VPU_INST_STATE_PIC_RUN;
+	}
+
+	if (inst->state == VPU_INST_STATE_INIT_SEQ &&
+	    q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		*num_buffers = inst->src_buf_count;
+		dev_dbg(inst->dev->dev, "%s: src buf num: %u", __func__, *num_buffers);
+	}
+
+	return 0;
+
+free_buffers:
+	for (i = 0; i < inst->fbc_buf_count; i++)
+		wave5_vdi_free_dma_memory(inst->dev, &inst->frame_vbuf[i]);
+	return ret;
+}
+
+static void wave5_vpu_enc_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vpu_instance *inst = vb2_get_drv_priv(vb->vb2_queue);
+	struct vpu_buffer *vpu_buf = wave5_to_vpu_buf(vbuf);
+
+	dev_dbg(inst->dev->dev, "%s: type: %4u index: %4u size: ([0]=%4lu, [1]=%4lu, [2]=%4lu)\n",
+		__func__, vb->type, vb->index, vb2_plane_size(&vbuf->vb2_buf, 0),
+		vb2_plane_size(&vbuf->vb2_buf, 1), vb2_plane_size(&vbuf->vb2_buf, 2));
+
+	if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		vbuf->sequence = inst->queued_src_buf_num++;
+		list_add_tail(&vpu_buf->list, &inst->avail_src_bufs);
+	} else {
+		vbuf->sequence = inst->queued_dst_buf_num++;
+		list_add_tail(&vpu_buf->list, &inst->avail_dst_bufs);
+	}
+
+	vpu_buf->consumed = FALSE;
+	v4l2_m2m_buf_queue(inst->v4l2_fh.m2m_ctx, vbuf);
+
+	if (vb2_start_streaming_called(vb->vb2_queue)) {
+		if (inst->state != VPU_INST_STATE_STOP) {
+			if ((!list_empty_careful(&inst->avail_src_bufs)) &&
+			    (!list_empty_careful(&inst->avail_dst_bufs)))
+				inst->ops->start_process(inst);
+		} else {
+			if (!inst->eos)
+				inst->ops->start_process(inst);
+		}
+	}
+}
+
+static void wave5_vpu_enc_stop_streaming(struct vb2_queue *q)
+{
+	struct vpu_instance *inst = vb2_get_drv_priv(q);
+	struct vpu_buffer *vbuf, *n;
+	struct vb2_v4l2_buffer *buf;
+	bool check_cmd = true;
+
+	dev_dbg(inst->dev->dev, "%s: type: %u\n", __func__, q->type);
+
+	if (wave5_vpu_both_queues_are_streaming(inst))
+		inst->state = VPU_INST_STATE_STOP;
+
+	while (check_cmd) {
+		struct queue_status_info q_status;
+		struct enc_output_info enc_output_info;
+
+		wave5_vpu_enc_give_command(inst, ENC_GET_QUEUE_STATUS, &q_status);
+
+		if (q_status.instance_queue_count + q_status.report_queue_count == 0)
+			break;
+
+		if (wave5_vpu_wait_interrupt(inst, VPU_ENC_TIMEOUT) < 0)
+			break;
+
+		if (wave5_vpu_enc_get_output_info(inst, &enc_output_info))
+			dev_dbg(inst->dev->dev, "Getting encoding results from fw, fail\n");
+	}
+
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		while ((buf = v4l2_m2m_src_buf_remove(inst->v4l2_fh.m2m_ctx))) {
+			dev_dbg(inst->dev->dev, "%s: buf type %4u | index %4u\n",
+				__func__, buf->vb2_buf.type, buf->vb2_buf.index);
+			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
+		}
+
+		list_for_each_entry_safe(vbuf, n, &inst->avail_src_bufs, list)
+			list_del_init(&vbuf->list);
+	} else {
+		while ((buf = v4l2_m2m_dst_buf_remove(inst->v4l2_fh.m2m_ctx))) {
+			dev_dbg(inst->dev->dev, "%s: buf type %4u | index %4u\n",
+				__func__, buf->vb2_buf.type, buf->vb2_buf.index);
+			vb2_set_plane_payload(&buf->vb2_buf, 0, 0);
+			v4l2_m2m_buf_done(buf, VB2_BUF_STATE_ERROR);
+		}
+
+		list_for_each_entry_safe(vbuf, n, &inst->avail_dst_bufs, list)
+			list_del_init(&vbuf->list);
+	}
+}
+
+static const struct vb2_ops wave5_vpu_enc_vb2_ops = {
+	.queue_setup = wave5_vpu_enc_queue_setup,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.buf_queue = wave5_vpu_enc_buf_queue,
+	.stop_streaming = wave5_vpu_enc_stop_streaming,
+};
+
+static void wave5_set_default_format(struct v4l2_pix_format_mplane *src_fmt,
+				     struct v4l2_pix_format_mplane *dst_fmt)
+{
+	unsigned int src_pix_fmt = enc_fmt_list[VPU_FMT_TYPE_RAW][0].v4l2_pix_fmt;
+	const struct v4l2_format_info *src_fmt_info = v4l2_format_info(src_pix_fmt);
+
+	src_fmt->pixelformat = src_pix_fmt;
+	src_fmt->field = V4L2_FIELD_NONE;
+	src_fmt->flags = 0;
+	src_fmt->num_planes = src_fmt_info->mem_planes;
+	wave5_update_pix_fmt(src_fmt, 416, 240);
+
+	dst_fmt->pixelformat = enc_fmt_list[VPU_FMT_TYPE_CODEC][0].v4l2_pix_fmt;
+	dst_fmt->field = V4L2_FIELD_NONE;
+	dst_fmt->flags = 0;
+	dst_fmt->num_planes = 1;
+	wave5_update_pix_fmt(dst_fmt, 416, 240);
+}
+
+static int wave5_vpu_enc_queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
+{
+	return wave5_vpu_queue_init(priv, src_vq, dst_vq, &wave5_vpu_enc_vb2_ops);
+}
+
+static const struct vpu_instance_ops wave5_vpu_enc_inst_ops = {
+	.start_process = wave5_vpu_enc_start_encode,
+	.stop_process = wave5_vpu_enc_stop_encode,
+	.finish_process = wave5_vpu_enc_finish_encode,
+};
+
+static void wave5_vpu_enc_device_run(void *priv)
+{
+	struct vpu_instance *inst = priv;
+
+	inst->ops->start_process(inst);
+}
+
+static int wave5_vpu_enc_job_ready(void *priv)
+{
+	struct vpu_instance *inst = priv;
+
+	if (inst->state == VPU_INST_STATE_STOP)
+		return 0;
+
+	return 1;
+}
+
+static void wave5_vpu_enc_job_abort(void *priv)
+{
+	struct vpu_instance *inst = priv;
+
+	inst->ops->stop_process(inst);
+}
+
+static const struct v4l2_m2m_ops wave5_vpu_enc_m2m_ops = {
+	.device_run = wave5_vpu_enc_device_run,
+	.job_ready = wave5_vpu_enc_job_ready,
+	.job_abort = wave5_vpu_enc_job_abort,
+};
+
+static int wave5_vpu_open_enc(struct file *filp)
+{
+	struct video_device *vdev = video_devdata(filp);
+	struct vpu_device *dev = video_drvdata(filp);
+	struct vpu_instance *inst = NULL;
+	struct v4l2_ctrl_handler *v4l2_ctrl_hdl;
+	int ret = 0, err;
+
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+	if (!inst)
+		return -ENOMEM;
+	v4l2_ctrl_hdl = &inst->v4l2_ctrl_hdl;
+
+	inst->dev = dev;
+	inst->type = VPU_INST_TYPE_ENC;
+	inst->ops = &wave5_vpu_enc_inst_ops;
+
+	v4l2_fh_init(&inst->v4l2_fh, vdev);
+	filp->private_data = &inst->v4l2_fh;
+	v4l2_fh_add(&inst->v4l2_fh);
+
+	INIT_LIST_HEAD(&inst->list);
+
+	INIT_LIST_HEAD(&inst->avail_src_bufs);
+	INIT_LIST_HEAD(&inst->avail_dst_bufs);
+
+	inst->v4l2_m2m_dev = v4l2_m2m_init(&wave5_vpu_enc_m2m_ops);
+	if (IS_ERR(inst->v4l2_m2m_dev)) {
+		ret = PTR_ERR(inst->v4l2_m2m_dev);
+		dev_err(inst->dev->dev, "v4l2_m2m_init, fail: %d\n", ret);
+		goto cleanup_inst;
+	}
+
+	inst->v4l2_fh.m2m_ctx =
+		v4l2_m2m_ctx_init(inst->v4l2_m2m_dev, inst, wave5_vpu_enc_queue_init);
+	if (IS_ERR(inst->v4l2_fh.m2m_ctx)) {
+		ret = PTR_ERR(inst->v4l2_fh.m2m_ctx);
+		goto cleanup_inst;
+	}
+
+	v4l2_ctrl_handler_init(v4l2_ctrl_hdl, 50);
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_HEVC_PROFILE,
+			       V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10, 0,
+			       V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN);
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_HEVC_LEVEL,
+			       V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1, 0,
+			       V4L2_MPEG_VIDEO_HEVC_LEVEL_1);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
+			  0, 63, 1, 8);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP,
+			  0, 63, 1, 51);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP,
+			  0, 63, 1, 30);
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE,
+			       V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY, 0,
+			       V4L2_MPEG_VIDEO_HEVC_LOOP_FILTER_MODE_ENABLED);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_HEVC_LF_BETA_OFFSET_DIV2,
+			  -6, 6, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_HEVC_LF_TC_OFFSET_DIV2,
+			  -6, 6, 1, 0);
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_TYPE,
+			       V4L2_MPEG_VIDEO_HEVC_REFRESH_IDR, 0,
+			       V4L2_MPEG_VIDEO_HEVC_REFRESH_CRA);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_HEVC_REFRESH_PERIOD,
+			  0, 2047, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_HEVC_LOSSLESS_CU,
+			  0, 1, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_HEVC_CONST_INTRA_PRED,
+			  0, 1, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_HEVC_WAVEFRONT,
+			  0, 1, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_HEVC_STRONG_SMOOTHING,
+			  0, 1, 1, 1);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_HEVC_MAX_NUM_MERGE_MV_MINUS1,
+			  1, 2, 1, 2);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_HEVC_TMV_PREDICTION,
+			  0, 1, 1, 1);
+
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+			       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE, 0,
+			       V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE);
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+			       V4L2_MPEG_VIDEO_H264_LEVEL_5_1, 0,
+			       V4L2_MPEG_VIDEO_H264_LEVEL_1_0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_H264_MIN_QP,
+			  0, 63, 1, 8);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_H264_MAX_QP,
+			  0, 63, 1, 51);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
+			  0, 63, 1, 30);
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE,
+			       V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY, 0,
+			       V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA,
+			  -6, 6, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA,
+			  -6, 6, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
+			  0, 1, 1, 1);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_H264_CONSTRAINED_INTRA_PREDICTION,
+			  0, 1, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_H264_CHROMA_QP_INDEX_OFFSET,
+			  -12, 12, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_H264_I_PERIOD,
+			  0, 2047, 1, 0);
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
+			       V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, 0,
+			       V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC);
+
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_HFLIP,
+			  0, 1, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_VFLIP,
+			  0, 1, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_ROTATE,
+			  0, 270, 90, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_VBV_SIZE,
+			  10, 3000, 1, 1000);
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_BITRATE_MODE,
+			       V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, 0,
+			       V4L2_MPEG_VIDEO_BITRATE_MODE_CBR);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_BITRATE,
+			  0, 700000000, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+			  0, 2047, 1, 0);
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
+			       V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_MAX_MB, 0,
+			       V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB,
+			  0, 0xFFFF, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE,
+			  0, 1, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE,
+			  0, 1, 1, 0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 1);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &wave5_vpu_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_PREPEND_SPSPPS_TO_IDR, 0, 1, 1, 0);
+	if (v4l2_ctrl_hdl->error) {
+		ret = -ENODEV;
+		goto cleanup_inst;
+	}
+
+	inst->v4l2_fh.ctrl_handler = v4l2_ctrl_hdl;
+	v4l2_ctrl_handler_setup(v4l2_ctrl_hdl);
+
+	wave5_set_default_format(&inst->src_fmt, &inst->dst_fmt);
+	inst->colorspace = V4L2_COLORSPACE_REC709;
+	inst->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	inst->hsv_enc = 0;
+	inst->quantization = V4L2_QUANTIZATION_DEFAULT;
+	inst->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+	inst->frame_rate = 30;
+
+	init_completion(&inst->irq_done);
+	ret = kfifo_alloc(&inst->irq_status, 16 * sizeof(int), GFP_KERNEL);
+	if (ret) {
+		dev_err(inst->dev->dev, "Allocating fifo, fail: %d\n", ret);
+		goto cleanup_inst;
+	}
+
+	inst->id = ida_alloc(&inst->dev->inst_ida, GFP_KERNEL);
+	if (inst->id < 0) {
+		dev_warn(inst->dev->dev, "Allocating instance ID, fail: %d\n", inst->id);
+		ret = inst->id;
+		goto cleanup_inst;
+	}
+
+	err = pm_runtime_resume_and_get(inst->dev->dev);
+	if (err) {
+		dev_err(inst->dev->dev, "runtime resume failed %d\n", err);
+		ret = -EINVAL;
+		goto cleanup_inst;
+	}
+
+	ret = mutex_lock_interruptible(&dev->dev_lock);
+	if (ret)
+		goto cleanup_inst;
+
+	if (dev->irq < 0 && !hrtimer_active(&dev->hrtimer) && list_empty(&dev->instances))
+		hrtimer_start(&dev->hrtimer, ns_to_ktime(dev->vpu_poll_interval * NSEC_PER_MSEC),
+			      HRTIMER_MODE_REL_PINNED);
+
+	list_add_tail(&inst->list, &dev->instances);
+
+	mutex_unlock(&dev->dev_lock);
+	wave5_vdi_allocate_sram(inst->dev);
+
+	return 0;
+
+cleanup_inst:
+	wave5_cleanup_instance(inst);
+	return ret;
+}
+
+static int wave5_vpu_enc_release(struct file *filp)
+{
+	return wave5_vpu_release_device(filp, wave5_vpu_enc_close, "encoder");
+}
+
+static const struct v4l2_file_operations wave5_vpu_enc_fops = {
+	.owner = THIS_MODULE,
+	.open = wave5_vpu_open_enc,
+	.release = wave5_vpu_enc_release,
+	.unlocked_ioctl = video_ioctl2,
+	.poll = v4l2_m2m_fop_poll,
+	.mmap = v4l2_m2m_fop_mmap,
+};
+
+int wave5_vpu_enc_register_device(struct vpu_device *dev)
+{
+	struct video_device *vdev_enc;
+	int ret;
+
+	vdev_enc = devm_kzalloc(dev->v4l2_dev.dev, sizeof(*vdev_enc), GFP_KERNEL);
+	if (!vdev_enc)
+		return -ENOMEM;
+
+	dev->video_dev_enc = vdev_enc;
+
+	strscpy(vdev_enc->name, VPU_ENC_DEV_NAME, sizeof(vdev_enc->name));
+	vdev_enc->fops = &wave5_vpu_enc_fops;
+	vdev_enc->ioctl_ops = &wave5_vpu_enc_ioctl_ops;
+	vdev_enc->release = video_device_release_empty;
+	vdev_enc->v4l2_dev = &dev->v4l2_dev;
+	vdev_enc->vfl_dir = VFL_DIR_M2M;
+	vdev_enc->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+	vdev_enc->lock = &dev->dev_lock;
+
+	ret = video_register_device(vdev_enc, VFL_TYPE_VIDEO, -1);
+	if (ret)
+		return ret;
+
+	video_set_drvdata(vdev_enc, dev);
+
+	return 0;
+}
+
+void wave5_vpu_enc_unregister_device(struct vpu_device *dev)
+{
+	video_unregister_device(dev->video_dev_enc);
+}
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpuerror.h b/drivers/media/platform/chips-media/wave5/wave5-vpuerror.h
--- a/drivers/media/platform/chips-media/wave5/wave5-vpuerror.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpuerror.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,454 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave5 series multi-standard codec IP - error values
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+
+#ifndef ERROR_CODE_H_INCLUDED
+#define ERROR_CODE_H_INCLUDED
+
+/*
+ * WAVE5
+ */
+
+/************************************************************************/
+/* WAVE5 COMMON SYSTEM ERROR (FAIL_REASON)                              */
+/************************************************************************/
+#define WAVE5_SYSERR_QUEUEING_FAIL                                     0x00000001
+#define WAVE5_SYSERR_ACCESS_VIOLATION_HW                               0x00000040
+#define WAVE5_SYSERR_BUS_ERROR                                         0x00000200
+#define WAVE5_SYSERR_DOUBLE_FAULT                                      0x00000400
+#define WAVE5_SYSERR_RESULT_NOT_READY                                  0x00000800
+#define WAVE5_SYSERR_VPU_STILL_RUNNING                                 0x00001000
+#define WAVE5_SYSERR_UNKNOWN_CMD                                       0x00002000
+#define WAVE5_SYSERR_UNKNOWN_CODEC_STD                                 0x00004000
+#define WAVE5_SYSERR_UNKNOWN_QUERY_OPTION                              0x00008000
+#define WAVE5_SYSERR_VLC_BUF_FULL                                      0x00010000
+#define WAVE5_SYSERR_WATCHDOG_TIMEOUT                                  0x00020000
+#define WAVE5_SYSERR_VCPU_TIMEOUT                                      0x00080000
+#define WAVE5_SYSERR_TEMP_SEC_BUF_OVERFLOW                             0x00200000
+#define WAVE5_SYSERR_NEED_MORE_TASK_BUF                                0x00400000
+#define WAVE5_SYSERR_PRESCAN_ERR                                       0x00800000
+#define WAVE5_SYSERR_ENC_GBIN_OVERCONSUME                              0x01000000
+#define WAVE5_SYSERR_ENC_MAX_ZERO_DETECT                               0x02000000
+#define WAVE5_SYSERR_ENC_LVL_FIRST_ERROR                               0x04000000
+#define WAVE5_SYSERR_ENC_EG_RANGE_OVER                                 0x08000000
+#define WAVE5_SYSERR_ENC_IRB_FRAME_DROP                                0x10000000
+#define WAVE5_SYSERR_INPLACE_V                                         0x20000000
+#define WAVE5_SYSERR_FATAL_VPU_HANGUP                                  0xf0000000
+
+/************************************************************************/
+/* WAVE5 COMMAND QUEUE ERROR (FAIL_REASON)                              */
+/************************************************************************/
+#define WAVE5_CMDQ_ERR_NOT_QUEABLE_CMD                                 0x00000001
+#define WAVE5_CMDQ_ERR_SKIP_MODE_ENABLE                                0x00000002
+#define WAVE5_CMDQ_ERR_INST_FLUSHING                                   0x00000003
+#define WAVE5_CMDQ_ERR_INST_INACTIVE                                   0x00000004
+#define WAVE5_CMDQ_ERR_QUEUE_FAIL                                      0x00000005
+#define WAVE5_CMDQ_ERR_CMD_BUF_FULL                                    0x00000006
+
+/************************************************************************/
+/* WAVE5 ERROR ON DECODER (ERR_INFO)                                    */
+/************************************************************************/
+// HEVC
+#define HEVC_SPSERR_SEQ_PARAMETER_SET_ID                               0x00001000
+#define HEVC_SPSERR_CHROMA_FORMAT_IDC                                  0x00001001
+#define HEVC_SPSERR_PIC_WIDTH_IN_LUMA_SAMPLES                          0x00001002
+#define HEVC_SPSERR_PIC_HEIGHT_IN_LUMA_SAMPLES                         0x00001003
+#define HEVC_SPSERR_CONF_WIN_LEFT_OFFSET                               0x00001004
+#define HEVC_SPSERR_CONF_WIN_RIGHT_OFFSET                              0x00001005
+#define HEVC_SPSERR_CONF_WIN_TOP_OFFSET                                0x00001006
+#define HEVC_SPSERR_CONF_WIN_BOTTOM_OFFSET                             0x00001007
+#define HEVC_SPSERR_BIT_DEPTH_LUMA_MINUS8                              0x00001008
+#define HEVC_SPSERR_BIT_DEPTH_CHROMA_MINUS8                            0x00001009
+#define HEVC_SPSERR_LOG2_MAX_PIC_ORDER_CNT_LSB_MINUS4                  0x0000100A
+#define HEVC_SPSERR_SPS_MAX_DEC_PIC_BUFFERING                          0x0000100B
+#define HEVC_SPSERR_SPS_MAX_NUM_REORDER_PICS                           0x0000100C
+#define HEVC_SPSERR_SPS_MAX_LATENCY_INCREASE                           0x0000100D
+#define HEVC_SPSERR_LOG2_MIN_LUMA_CODING_BLOCK_SIZE_MINUS3             0x0000100E
+#define HEVC_SPSERR_LOG2_DIFF_MAX_MIN_LUMA_CODING_BLOCK_SIZE           0x0000100F
+#define HEVC_SPSERR_LOG2_MIN_TRANSFORM_BLOCK_SIZE_MINUS2               0x00001010
+#define HEVC_SPSERR_LOG2_DIFF_MAX_MIN_TRANSFORM_BLOCK_SIZE             0x00001011
+#define HEVC_SPSERR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTER                0x00001012
+#define HEVC_SPSERR_MAX_TRANSFORM_HIERARCHY_DEPTH_INTRA                0x00001013
+#define HEVC_SPSERR_SCALING_LIST                                       0x00001014
+#define HEVC_SPSERR_LOG2_DIFF_MIN_PCM_LUMA_CODING_BLOCK_SIZE_MINUS3    0x00001015
+#define HEVC_SPSERR_LOG2_DIFF_MAX_MIN_PCM_LUMA_CODING_BLOCK_SIZE       0x00001016
+#define HEVC_SPSERR_NUM_SHORT_TERM_REF_PIC_SETS                        0x00001017
+#define HEVC_SPSERR_NUM_LONG_TERM_REF_PICS_SPS                         0x00001018
+#define HEVC_SPSERR_GBU_PARSING_ERROR                                  0x00001019
+#define HEVC_SPSERR_EXTENSION_FLAG                                     0x0000101A
+#define HEVC_SPSERR_VUI_ERROR                                          0x0000101B
+#define HEVC_SPSERR_ACTIVATE_SPS                                       0x0000101C
+#define HEVC_SPSERR_PROFILE_SPACE                                      0x0000101D
+#define HEVC_PPSERR_PPS_PIC_PARAMETER_SET_ID                           0x00002000
+#define HEVC_PPSERR_PPS_SEQ_PARAMETER_SET_ID                           0x00002001
+#define HEVC_PPSERR_NUM_REF_IDX_L0_DEFAULT_ACTIVE_MINUS1               0x00002002
+#define HEVC_PPSERR_NUM_REF_IDX_L1_DEFAULT_ACTIVE_MINUS1               0x00002003
+#define HEVC_PPSERR_INIT_QP_MINUS26                                    0x00002004
+#define HEVC_PPSERR_DIFF_CU_QP_DELTA_DEPTH                             0x00002005
+#define HEVC_PPSERR_PPS_CB_QP_OFFSET                                   0x00002006
+#define HEVC_PPSERR_PPS_CR_QP_OFFSET                                   0x00002007
+#define HEVC_PPSERR_NUM_TILE_COLUMNS_MINUS1                            0x00002008
+#define HEVC_PPSERR_NUM_TILE_ROWS_MINUS1                               0x00002009
+#define HEVC_PPSERR_COLUMN_WIDTH_MINUS1                                0x0000200A
+#define HEVC_PPSERR_ROW_HEIGHT_MINUS1                                  0x0000200B
+#define HEVC_PPSERR_PPS_BETA_OFFSET_DIV2                               0x0000200C
+#define HEVC_PPSERR_PPS_TC_OFFSET_DIV2                                 0x0000200D
+#define HEVC_PPSERR_SCALING_LIST                                       0x0000200E
+#define HEVC_PPSERR_LOG2_PARALLEL_MERGE_LEVEL_MINUS2                   0x0000200F
+#define HEVC_PPSERR_NUM_TILE_COLUMNS_RANGE_OUT                         0x00002010
+#define HEVC_PPSERR_NUM_TILE_ROWS_RANGE_OUT                            0x00002011
+#define HEVC_PPSERR_MORE_RBSP_DATA_ERROR                               0x00002012
+#define HEVC_PPSERR_PPS_PIC_PARAMETER_SET_ID_RANGE_OUT                 0x00002013
+#define HEVC_PPSERR_PPS_SEQ_PARAMETER_SET_ID_RANGE_OUT                 0x00002014
+#define HEVC_PPSERR_NUM_REF_IDX_L0_DEFAULT_ACTIVE_MINUS1_RANGE_OUT     0x00002015
+#define HEVC_PPSERR_NUM_REF_IDX_L1_DEFAULT_ACTIVE_MINUS1_RANGE_OUT     0x00002016
+#define HEVC_PPSERR_PPS_CB_QP_OFFSET_RANGE_OUT                         0x00002017
+#define HEVC_PPSERR_PPS_CR_QP_OFFSET_RANGE_OUT                         0x00002018
+#define HEVC_PPSERR_COLUMN_WIDTH_MINUS1_RANGE_OUT                      0x00002019
+#define HEVC_PPSERR_ROW_HEIGHT_MINUS1_RANGE_OUT                        0x00002020
+#define HEVC_PPSERR_PPS_BETA_OFFSET_DIV2_RANGE_OUT                     0x00002021
+#define HEVC_PPSERR_PPS_TC_OFFSET_DIV2_RANGE_OUT                       0x00002022
+#define HEVC_SHERR_SLICE_PIC_PARAMETER_SET_ID                          0x00003000
+#define HEVC_SHERR_ACTIVATE_PPS                                        0x00003001
+#define HEVC_SHERR_ACTIVATE_SPS                                        0x00003002
+#define HEVC_SHERR_SLICE_TYPE                                          0x00003003
+#define HEVC_SHERR_FIRST_SLICE_IS_DEPENDENT_SLICE                      0x00003004
+#define HEVC_SHERR_SHORT_TERM_REF_PIC_SET_SPS_FLAG                     0x00003005
+#define HEVC_SHERR_SHORT_TERM_REF_PIC_SET                              0x00003006
+#define HEVC_SHERR_SHORT_TERM_REF_PIC_SET_IDX                          0x00003007
+#define HEVC_SHERR_NUM_LONG_TERM_SPS                                   0x00003008
+#define HEVC_SHERR_NUM_LONG_TERM_PICS                                  0x00003009
+#define HEVC_SHERR_LT_IDX_SPS_IS_OUT_OF_RANGE                          0x0000300A
+#define HEVC_SHERR_DELTA_POC_MSB_CYCLE_LT                              0x0000300B
+#define HEVC_SHERR_NUM_REF_IDX_L0_ACTIVE_MINUS1                        0x0000300C
+#define HEVC_SHERR_NUM_REF_IDX_L1_ACTIVE_MINUS1                        0x0000300D
+#define HEVC_SHERR_COLLOCATED_REF_IDX                                  0x0000300E
+#define HEVC_SHERR_PRED_WEIGHT_TABLE                                   0x0000300F
+#define HEVC_SHERR_FIVE_MINUS_MAX_NUM_MERGE_CAND                       0x00003010
+#define HEVC_SHERR_SLICE_QP_DELTA                                      0x00003011
+#define HEVC_SHERR_SLICE_QP_DELTA_IS_OUT_OF_RANGE                      0x00003012
+#define HEVC_SHERR_SLICE_CB_QP_OFFSET                                  0x00003013
+#define HEVC_SHERR_SLICE_CR_QP_OFFSET                                  0x00003014
+#define HEVC_SHERR_SLICE_BETA_OFFSET_DIV2                              0x00003015
+#define HEVC_SHERR_SLICE_TC_OFFSET_DIV2                                0x00003016
+#define HEVC_SHERR_NUM_ENTRY_POINT_OFFSETS                             0x00003017
+#define HEVC_SHERR_OFFSET_LEN_MINUS1                                   0x00003018
+#define HEVC_SHERR_SLICE_SEGMENT_HEADER_EXTENSION_LENGTH               0x00003019
+#define HEVC_SHERR_WRONG_POC_IN_STILL_PICTURE_PROFILE                  0x0000301A
+#define HEVC_SHERR_SLICE_TYPE_ERROR_IN_STILL_PICTURE_PROFILE           0x0000301B
+#define HEVC_SHERR_PPS_ID_NOT_EQUAL_PREV_VALUE                         0x0000301C
+#define HEVC_SPECERR_OVER_PICTURE_WIDTH_SIZE                           0x00004000
+#define HEVC_SPECERR_OVER_PICTURE_HEIGHT_SIZE                          0x00004001
+#define HEVC_SPECERR_OVER_CHROMA_FORMAT                                0x00004002
+#define HEVC_SPECERR_OVER_BIT_DEPTH                                    0x00004003
+#define HEVC_SPECERR_OVER_BUFFER_OVER_FLOW                             0x00004004
+#define HEVC_SPECERR_OVER_WRONG_BUFFER_ACCESS                          0x00004005
+#define HEVC_ETCERR_INIT_SEQ_SPS_NOT_FOUND                             0x00005000
+#define HEVC_ETCERR_DEC_PIC_VCL_NOT_FOUND                              0x00005001
+#define HEVC_ETCERR_NO_VALID_SLICE_IN_AU                               0x00005002
+#define HEVC_ETCERR_INPLACE_V                                          0x0000500F
+
+// AVC
+#define AVC_SPSERR_SEQ_PARAMETER_SET_ID                                0x00001000
+#define AVC_SPSERR_CHROMA_FORMAT_IDC                                   0x00001001
+#define AVC_SPSERR_PIC_WIDTH_IN_LUMA_SAMPLES                           0x00001002
+#define AVC_SPSERR_PIC_HEIGHT_IN_LUMA_SAMPLES                          0x00001003
+#define AVC_SPSERR_CONF_WIN_LEFT_OFFSET                                0x00001004
+#define AVC_SPSERR_CONF_WIN_RIGHT_OFFSET                               0x00001005
+#define AVC_SPSERR_CONF_WIN_TOP_OFFSET                                 0x00001006
+#define AVC_SPSERR_CONF_WIN_BOTTOM_OFFSET                              0x00001007
+#define AVC_SPSERR_BIT_DEPTH_LUMA_MINUS8                               0x00001008
+#define AVC_SPSERR_BIT_DEPTH_CHROMA_MINUS8                             0x00001009
+#define AVC_SPSERR_SPS_MAX_DEC_PIC_BUFFERING                           0x0000100B
+#define AVC_SPSERR_SPS_MAX_NUM_REORDER_PICS                            0x0000100C
+#define AVC_SPSERR_SCALING_LIST                                        0x00001014
+#define AVC_SPSERR_GBU_PARSING_ERROR                                   0x00001019
+#define AVC_SPSERR_VUI_ERROR                                           0x0000101B
+#define AVC_SPSERR_ACTIVATE_SPS                                        0x0000101C
+#define AVC_PPSERR_PPS_PIC_PARAMETER_SET_ID                            0x00002000
+#define AVC_PPSERR_PPS_SEQ_PARAMETER_SET_ID                            0x00002001
+#define AVC_PPSERR_NUM_REF_IDX_L0_DEFAULT_ACTIVE_MINUS1                0x00002002
+#define AVC_PPSERR_NUM_REF_IDX_L1_DEFAULT_ACTIVE_MINUS1                0x00002003
+#define AVC_PPSERR_INIT_QP_MINUS26                                     0x00002004
+#define AVC_PPSERR_PPS_CB_QP_OFFSET                                    0x00002006
+#define AVC_PPSERR_PPS_CR_QP_OFFSET                                    0x00002007
+#define AVC_PPSERR_SCALING_LIST                                        0x0000200E
+#define AVC_PPSERR_MORE_RBSP_DATA_ERROR                                0x00002012
+#define AVC_PPSERR_PPS_PIC_PARAMETER_SET_ID_RANGE_OUT                  0x00002013
+#define AVC_PPSERR_PPS_SEQ_PARAMETER_SET_ID_RANGE_OUT                  0x00002014
+#define AVC_PPSERR_NUM_REF_IDX_L0_DEFAULT_ACTIVE_MINUS1_RANGE_OUT      0x00002015
+#define AVC_PPSERR_NUM_REF_IDX_L1_DEFAULT_ACTIVE_MINUS1_RANGE_OUT      0x00002016
+#define AVC_PPSERR_PPS_CB_QP_OFFSET_RANGE_OUT                          0x00002017
+#define AVC_PPSERR_PPS_CR_QP_OFFSET_RANGE_OUT                          0x00002018
+#define AVC_SHERR_SLICE_PIC_PARAMETER_SET_ID                           0x00003000
+#define AVC_SHERR_ACTIVATE_PPS                                         0x00003001
+#define AVC_SHERR_ACTIVATE_SPS                                         0x00003002
+#define AVC_SHERR_SLICE_TYPE                                           0x00003003
+#define AVC_SHERR_FIRST_MB_IN_SLICE                                    0x00003004
+#define AVC_SHERR_RPLM                                                 0x00003006
+#define AVC_SHERR_LT_IDX_SPS_IS_OUT_OF_RANGE                           0x0000300A
+#define AVC_SHERR_NUM_REF_IDX_L0_ACTIVE_MINUS1                         0x0000300C
+#define AVC_SHERR_NUM_REF_IDX_L1_ACTIVE_MINUS1                         0x0000300D
+#define AVC_SHERR_PRED_WEIGHT_TABLE                                    0x0000300F
+#define AVC_SHERR_SLICE_QP_DELTA                                       0x00003011
+#define AVC_SHERR_SLICE_BETA_OFFSET_DIV2                               0x00003015
+#define AVC_SHERR_SLICE_TC_OFFSET_DIV2                                 0x00003016
+#define AVC_SHERR_DISABLE_DEBLOCK_FILTER_IDC                           0x00003017
+#define AVC_SPECERR_OVER_PICTURE_WIDTH_SIZE                            0x00004000
+#define AVC_SPECERR_OVER_PICTURE_HEIGHT_SIZE                           0x00004001
+#define AVC_SPECERR_OVER_CHROMA_FORMAT                                 0x00004002
+#define AVC_SPECERR_OVER_BIT_DEPTH                                     0x00004003
+#define AVC_SPECERR_OVER_BUFFER_OVER_FLOW                              0x00004004
+#define AVC_SPECERR_OVER_WRONG_BUFFER_ACCESS                           0x00004005
+#define AVC_ETCERR_INIT_SEQ_SPS_NOT_FOUND                              0x00005000
+#define AVC_ETCERR_DEC_PIC_VCL_NOT_FOUND                               0x00005001
+#define AVC_ETCERR_NO_VALID_SLICE_IN_AU                                0x00005002
+#define AVC_ETCERR_ASO                                                 0x00005004
+#define AVC_ETCERR_FMO                                                 0x00005005
+#define AVC_ETCERR_INPLACE_V                                           0x0000500F
+
+// AV1
+#define AV1_SPSERR_MAX_FRAME_WIDTH                                     0x00001001
+#define AV1_SPSERR_MAX_FRAME_HEIGHT                                    0x00001002
+#define AV1_SPSERR_ID_LEN_EXCEED_16                                    0x00001004
+#define AV1_SPSERR_NOT_FOUND_FIRST_SPS                                 0x0000100A
+#define AV1_SPSERR_SEQ_PROFILE                                         0x0000100B
+#define AV1_SPSERR_STILL_PICTURE                                       0x0000100C
+#define AV1_PPSERR_FRAME_SIZE_WIDTH                                    0x00002001
+#define AV1_PPSERR_FRAME_SIZE_HEIGHT                                   0x00002002
+#define AV1_PPSERR_SEEN_FRAME_HEADER                                   0x00002003
+#define AV1_PPSERR_REF_VALID                                           0x00002007
+#define AV1_PPSERR_LAST_ORDER_HINT                                     0x0000200B
+#define AV1_PPSERR_GOLD_ORDER_HINT                                     0x0000200C
+#define AV1_PPSERR_CODED_LOSSLESS_DELTA_Q                              0x0000200E
+#define AV1_PPSERR_FILM_GRAIN_PARAM_REF_IDX                            0x0000200F
+#define AV1_PPSERR_SEQ_CHANGE_BIT_DEPTH                                0x00002010
+#define AV1_PPSERR_SEQ_CHANGE_PROFILE                                  0x00002012
+#define AV1_PPSERR_SEQ_CHANGE_DETECTED_INTER                           0x00002013
+#define AV1_PPSERR_NUM_Y_POINTS                                        0x00002014
+#define AV1_PPSERR_POINT_Y_VALUE                                       0x00002015
+#define AV1_PPSERR_NUM_CB_POINTS                                       0x00002016
+#define AV1_PPSERR_POINT_CB_VALUE                                      0x00002017
+#define AV1_PPSERR_NUM_CR_POINTS                                       0x00002018
+#define AV1_PPSERR_POINT_CR_VALUE                                      0x00002019
+#define AV1_PPSERR_SUBSAMPLING_FORMAT                                  0x0000201A
+#define AV1_FRAMEERR_TILE_START_END_PRESENT                            0x00003001
+#define AV1_FRAMEERR_SHOW_EXISING_FRAME                                0x00003002
+#define AV1_TGERR_NUM_TILES_ZERO                                       0x00004001
+#define AV1_TGERR_START_NOT_TILE_NUM                                   0x00004002
+#define AV1_TGERR_END_LESS_THAN_TG_START                               0x00004003
+#define AV1_TGERR_TILE_SIZE_GREATER_THAN_32M                           0x00004004
+#define AV1_SPECERR_OVER_MAX_H_SIZE                                    0x00005001
+#define AV1_SPECERR_OVER_MAX_V_SIZE                                    0x00005002
+#define AV1_SPECERR_OVER_MAX_TILE_COLS                                 0x00005004
+#define AV1_SPECERR_OVER_MAX_TILE_ROWS                                 0x00005005
+#define AV1_SPECERR_OVER_TILE_SIZE                                     0x00005006
+#define AV1_SPECERR_OVER_NUMTILES_GT_MAX_TILES                         0x00005007
+#define AV1_ETCERR_OBU_HEADER                                          0x00006001
+#define AV1_ETCERR_OBU_SIZE                                            0x00006003
+#define AV1_ETCERR_OVERCONSUME                                         0x00006004
+#define AV1_ETCERR_NOT_SUPPORTED_FEATURE                               0x00006005
+#define AV1_ETCERR_RESILIENCE_FAIL                                     0x00006006
+
+// VP9
+#define VP9_PICERR_FRAME_MARKER                                        0x00001000
+#define VP9_PICERR_PROFILE                                             0x00001001
+#define VP9_PICERR_SYNC_CODE                                           0x00001002
+#define VP9_PICERR_PROFILE_COLOR_SAMPLE                                0x00001003
+#define VP9_PICERR_FRAME_SIZE                                          0x00001004
+#define VP9_PICERR_SEGMENT                                             0x00001005
+#define VP9_PICERR_TILE                                                0x00001006
+#define VP9_PICERR_PROFILE_COMP_MISMATCH_WITH_REF                      0x00001007
+#define VP9_PICERR_COMP_DAT_OVER_CS                                    0x00001008
+#define VP9_PICERR_COMP_TRAILING_BIT_ERR                               0x00001009
+#define VP9_PICERR_MARKER                                              0x0000100A
+#define VP9_PICERR_NOT_EXIST_REF_FRAME                                 0x0000100B
+#define VP9_PICERR_UNINIT_CTX                                          0x0000100C
+#define VP9_PICERR_FRAME_SIZE_LIMIT_BY_REF                             0x0000100D
+#define VP9_SPECERR_OVER_PICTURE_WIDTH_SIZE                            0x00004000
+#define VP9_SPECERR_OVER_PICTURE_HEIGHT_SIZE                           0x00004001
+#define VP9_SPECERR_OVER_CHROMA_FORMAT                                 0x00004002
+#define VP9_SPECERR_OVER_BIT_DEPTH                                     0x00004003
+#define VP9_ETCERR_INIT_KEY_FRAME_NOT_FOUND                            0x00005000
+#define VP9_ETCERR_FORBIDDEN_BS_MODE                                   0x00005004
+#define VP9_ETCERR_SPP_OVER_CS_AU                                      0x00005005
+
+// AVS2
+#define AVS2_SPSERR_PROFILE_ID                                         0x00001000
+#define AVS2_SPSERR_LEVEL_ID                                           0x00001001
+#define AVS2_SPSERR_HORIZONTAL_SIZE                                    0x00001002
+#define AVS2_SPSERR_VERTICAL_SIZE                                      0x00001003
+#define AVS2_SPSERR_CHROMA_FORMAT                                      0x00001004
+#define AVS2_SPSERR_SAMPLE_PRECISION                                   0x00001005
+#define AVS2_SPSERR_ENCODING_PRECISION                                 0x00001006
+#define AVS2_SPSERR_LCU_SIZE                                           0x00001007
+#define AVS2_SPSERR_WEIGHT_QUANT_MATRIX                                0x00001008
+#define AVS2_SPSERR_NUM_OF_RCS                                         0x00001009
+#define AVS2_SPSERR_REFERENCE_CONFIGURATION_SET                        0x0000100A
+#define AVS2_SPSERR_OUTPUT_REORDER_DELAY                               0x0000100B
+#define AVS2_PPSERR_BBV_DELAY                                          0x00002000
+#define AVS2_PPSERR_TIME_CODE                                          0x00002001
+#define AVS2_PPSERR_DECODE_ORDER_INDEX                                 0x00002002
+#define AVS2_PPSERR_TEMPORAL_ID                                        0x00002003
+#define AVS2_PPSERR_PICTURE_OUTPUT_DELAY                               0x00002004
+#define AVS2_PPSERR_RCS_INDEX                                          0x00002005
+#define AVS2_PPSERR_REFERENCE_CONFIGURATION_SET                        0x00002006
+#define AVS2_PPSERR_BBV_CHECK_TIMES                                    0x00002007
+#define AVS2_PPSERR_PICTURE_QP                                         0x00002008
+#define AVS2_PPSERR_ALPHA_C_OFFSET                                     0x00002009
+#define AVS2_PPSERR_BETA_OFFSET                                        0x0000200A
+#define AVS2_PPSERR_CHROMA_QUANT_PARAM_DELTA_CB                        0x0000200B
+#define AVS2_PPSERR_CHROMA_QUANT_PARAM_DELTA_CR                        0x0000200C
+#define AVS2_PPSERR_WEIGHT_QUANT_PARAM_DELTA1                          0x0000200D
+#define AVS2_PPSERR_WEIGHT_QUANT_PARAM_DELTA2                          0x0000200E
+#define AVS2_PPSERR_PICTURE_CODING_TYPE                                0x0000200F
+#define AVS2_PPSERR_ALF_FILTER_NUM_MINUS1                              0x00002010
+#define AVS2_PPSERR_ALF_REGION_DISTANCE                                0x00002011
+#define AVS2_PPSERR_ALF_COEFF_LUMA                                     0x00002012
+#define AVS2_PPSERR_ALF_COEFF_CHROMA_CB                                0x00002013
+#define AVS2_PPSERR_ALF_COEFF_CHROMA_CR                                0x00002014
+#define AVS2_SHERR_SLICE_VERTICAL_POSITION                             0x00003000
+#define AVS2_SHERR_SLICE_VERTICAL_POSITION_EXTENSION                   0x00003001
+#define AVS2_SHERR_SLICE_HORIZONTAL_POSITION                           0x00003002
+#define AVS2_SHERR_SLICE_HORIZONTAL_POSITION_EXTENSION                 0x00003003
+#define AVS2_SHERR_FIXED_SLICE_QP                                      0x00003004
+#define AVS2_SHERR_SLICE_QP                                            0x00003005
+#define AVS2_SHERR_SLICE_SAO_ENABLE_FLAG                               0x00003006
+#define AVS2_SHERR_AEC_BYTE_ALIGNMENT_BIT                              0x00003007
+#define AVS2_SHERR_STREAM_END                                          0x00003008
+#define AVS2_SPECERR_OVER_PICTURE_WIDTH_SIZE                           0x00004000
+#define AVS2_SPECERR_OVER_PICTURE_HEIGHT_SIZE                          0x00004001
+#define AVS2_SPECERR_OVER_CHROMA_FORMAT                                0x00004002
+#define AVS2_SPECERR_OVER_BIT_DEPTH                                    0x00004003
+#define AVS2_SPECERR_OVER_REF_TEMPORAL_ID                              0x00004004
+#define AVS2_ETCERR_SPS_NOT_FOUND                                      0x00005000
+#define AVS2_ETCERR_DEC_PIC_VCL_NOT_FOUND                              0x00005001
+#define AVS2_ETCERR_NO_VALID_SLICE_IN_AU                               0x00005002
+#define AVS2_ETCERR_PPS_ERROR                                          0x00005003
+#define AVS2_ETCERR_SLICE_NUM_OVERFLOW                                 0x00005004
+
+/************************************************************************/
+/* WAVE5 WARNING ON DECODER (WARN_INFO)                                 */
+/************************************************************************/
+// HEVC
+#define HEVC_SPSWARN_MAX_SUB_LAYERS_MINUS1                             0x00000001
+#define HEVC_SPSWARN_GENERAL_RESERVED_ZERO_44BITS                      0x00000002
+#define HEVC_SPSWARN_RESERVED_ZERO_2BITS                               0x00000004
+#define HEVC_SPSWARN_SUB_LAYER_RESERVED_ZERO_44BITS                    0x00000008
+#define HEVC_SPSWARN_GENERAL_LEVEL_IDC                                 0x00000010
+#define HEVC_SPSWARN_SPS_MAX_DEC_PIC_BUFFERING_VALUE_OVER              0x00000020
+#define HEVC_SPSWARN_RBSP_TRAILING_BITS                                0x00000040
+#define HEVC_SPSWARN_ST_RPS_UE_ERROR                                   0x00000080
+#define HEVC_SPSWARN_EXTENSION_FLAG                                    0x01000000
+#define HEVC_SPSWARN_REPLACED_WITH_PREV_SPS                            0x02000000
+#define HEVC_PPSWARN_RBSP_TRAILING_BITS                                0x00000100
+#define HEVC_PPSWARN_REPLACED_WITH_PREV_PPS                            0x00000200
+#define HEVC_SHWARN_FIRST_SLICE_SEGMENT_IN_PIC_FLAG                    0x00001000
+#define HEVC_SHWARN_NO_OUTPUT_OF_PRIOR_PICS_FLAG                       0x00002000
+#define HEVC_SHWARN_PIC_OUTPUT_FLAG                                    0x00004000
+#define HEVC_SHWARN_DUPLICATED_SLICE_SEGMENT                           0x00008000
+#define HEVC_ETCWARN_INIT_SEQ_VCL_NOT_FOUND                            0x00010000
+#define HEVC_ETCWARN_MISSING_REFERENCE_PICTURE                         0x00020000
+#define HEVC_ETCWARN_WRONG_TEMPORAL_ID                                 0x00040000
+#define HEVC_ETCWARN_ERROR_PICTURE_IS_REFERENCED                       0x00080000
+#define HEVC_SPECWARN_OVER_PROFILE                                     0x00100000
+#define HEVC_SPECWARN_OVER_LEVEL                                       0x00200000
+#define HEVC_PRESWARN_PARSING_ERR                                      0x04000000
+#define HEVC_PRESWARN_MVD_OUT_OF_RANGE                                 0x08000000
+#define HEVC_PRESWARN_CU_QP_DELTA_VAL_OUT_OF_RANGE                     0x09000000
+#define HEVC_PRESWARN_COEFF_LEVEL_REMAINING_OUT_OF_RANGE               0x0A000000
+#define HEVC_PRESWARN_PCM_ERR                                          0x0B000000
+#define HEVC_PRESWARN_OVERCONSUME                                      0x0C000000
+#define HEVC_PRESWARN_END_OF_SUBSET_ONE_BIT_ERR                        0x10000000
+#define HEVC_PRESWARN_END_OF_SLICE_SEGMENT_FLAG                        0x20000000
+
+// AVC
+#define AVC_SPSWARN_RESERVED_ZERO_2BITS                                0x00000004
+#define AVC_SPSWARN_GENERAL_LEVEL_IDC                                  0x00000010
+#define AVC_SPSWARN_RBSP_TRAILING_BITS                                 0x00000040
+#define AVC_PPSWARN_RBSP_TRAILING_BITS                                 0x00000100
+#define AVC_SHWARN_NO_OUTPUT_OF_PRIOR_PICS_FLAG                        0x00002000
+#define AVC_ETCWARN_INIT_SEQ_VCL_NOT_FOUND                             0x00010000
+#define AVC_ETCWARN_MISSING_REFERENCE_PICTURE                          0x00020000
+#define AVC_ETCWARN_ERROR_PICTURE_IS_REFERENCED                        0x00080000
+#define AVC_SPECWARN_OVER_PROFILE                                      0x00100000
+#define AVC_SPECWARN_OVER_LEVEL                                        0x00200000
+#define AVC_PRESWARN_MVD_RANGE_OUT                                     0x00400000
+#define AVC_PRESWARN_MB_QPD_RANGE_OUT                                  0x00500000
+#define AVC_PRESWARN_COEFF_RANGE_OUT                                   0x00600000
+#define AVC_PRESWARN_MV_RANGE_OUT                                      0x00700000
+#define AVC_PRESWARN_MB_SKIP_RUN_RANGE_OUT                             0x00800000
+#define AVC_PRESWARN_MB_TYPE_RANGE_OUT                                 0x00900000
+#define AVC_PRESWARN_SUB_MB_TYPE_RANGE_OUT                             0x00A00000
+#define AVC_PRESWARN_CBP_RANGE_OUT                                     0x00B00000
+#define AVC_PRESWARN_INTRA_CHROMA_PRED_MODE_RANGE_OUT                  0x00C00000
+#define AVC_PRESWARN_REF_IDX_RANGE_OUT                                 0x00D00000
+#define AVC_PRESWARN_COEFF_TOKEN_RANGE_OUT                             0x00E00000
+#define AVC_PRESWARN_TOTAL_ZERO_RANGE_OUT                              0x00F00000
+#define AVC_PRESWARN_RUN_BEFORE_RANGE_OUT                              0x01000000
+#define AVC_PRESWARN_OVERCONSUME                                       0x01100000
+#define AVC_PRESWARN_MISSING_SLICE                                     0x01200000
+
+// AV1
+#define AV1_SPSWARN_OBU_EXTENSION_FLAG_ZERO                            0x00001000
+#define AV1_SPSWARN_DUPLICATE_OPERATING_POINT_IDX                      0x00001001
+#define AV1_SPSWARN_MC_IDENTIY_SUBSAMPLING_X                           0x00001002
+#define AV1_PPSWARN_MC_IDENTIY_SUBSAMPLING_Y                           0x00001003
+#define AV1_SPSWARN_NUM_UNITS_IN_DISPLAY_TICK                          0x00001004
+#define AV1_SPSWARN_TIME_SCALE_ZERO                                    0x00001005
+#define AV1_SPSWARN_NUM_TICKS_PER_PICTURE                              0x00001006
+#define AV1_PPSWARN_TILE_WIDTH                                         0x00002001
+#define AV1_PPSWARN_TILE_HEIGHT                                        0x00002002
+#define AV1_PPSWARN_SHOW_EXISTING_KEY_FRAME_OUTPUT                     0x00002004
+#define AV1_PPSWARN_DIFF_FRAME_ID                                      0x00002008
+#define AV1_PPSWARN_CURRENT_FRAME_ID                                   0x00002010
+#define AV1_PPSWARN_REFRESH_FRAME_FLAGS                                0x00002020
+#define AV1_PPSWARN_DISPLAY_ID                                         0x00002040
+#define AV1_PPSWARN_PREV_FRAME_SHOWABLE_FLAG_ZERO                      0x00002080
+#define AV1_PPSWARN_EXPECTED_FRAME_ID                                  0x00002100
+#define AV1_SPECWARN_OVER_MAX_TILE_AREA_SB                             0x00005000
+#define AV1_SPECWARN_OVER_MAX_PIC_SIZE                                 0x00005001
+#define AV1_ETCWARN_OBU_EXTENSION_FLAG                                 0x00006000
+#define AV1_TGWARN_TRAIL_BIT_POS                                       0x00400000
+#define AV1_TGWARN_TRAIL_PAD_BIT                                       0x00800000
+#define AV1_TGWARN_SYM_MAX_OVER                                        0x01000000
+#define AV1_TGWARN_EXP_GOLB_OVER                                       0x02000000
+#define AV1_TGWARN_MV_NOT_VALID                                        0x04000000
+
+// VP9
+#define VP9_PICWARN_COLOR_SPACE_MISMATCH_WITH_REF                      0x00001000
+#define VP9_PRESWARN_OVERCONSUME                                       0x00400000
+#define VP9_PRESWARN_TRAILING_BITS                                     0x00800000
+#define VP9_PRESWARN_MARKER                                            0x01000000
+#define VP9_PRESWARN_MV_RANGE_OVER                                     0x02000000
+#define VP9_PRESWARN_MISIZE_SEG_LVL_ACTIVE                             0x04000000
+
+// AVS2
+#define AVS2_ETCWARN_INIT_SEQ_VCL_NOT_FOUND                            0x00010000
+#define AVS2_ETCWARN_MISSING_REFERENCE_PICTURE                         0x00020000
+#define AVS2_ETCWARN_WRONG_TEMPORAL_ID                                 0x00040000
+#define AVS2_ETCWARN_ERROR_PICTURE_IS_REFERENCED                       0x00080000
+#define AVS2_ETCWARN_REF_WRONG_TEMPORAL_ID                             0x00080001
+#define AVS2_ETCWARN_SPS_ERROR                                         0x00080002
+
+/************************************************************************/
+/* WAVE5 ERROR ON ENCODER (ERR_INFO)                                    */
+/************************************************************************/
+
+/************************************************************************/
+/* WAVE5 WARNING ON ENCODER (WARN_INFO)                                 */
+/************************************************************************/
+#define WAVE5_ETCWARN_FORCED_SPLIT_BY_CU8X8                            0x000000001
+
+/************************************************************************/
+/* WAVE5 debug info (PRI_REASON)                                        */
+/************************************************************************/
+#define WAVE5_DEC_VCORE_VCE_HANGUP                                     0x0001
+#define WAVE5_DEC_VCORE_UNDETECTED_SYNTAX_ERR                          0x0002
+#define WAVE5_DEC_VCORE_MIB_BUSY                                       0x0003
+#define WAVE5_DEC_VCORE_VLC_BUSY                                       0x0004
+
+#endif /* ERROR_CODE_H_INCLUDED */
diff -Naur --no-dereference a/drivers/media/platform/chips-media/wave5/wave5-vpu.h b/drivers/media/platform/chips-media/wave5/wave5-vpu.h
--- a/drivers/media/platform/chips-media/wave5/wave5-vpu.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpu.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Wave5 series multi-standard codec IP - basic types
+ *
+ * Copyright (C) 2021 CHIPS&MEDIA INC
+ */
+#ifndef __VPU_DRV_H__
+#define __VPU_DRV_H__
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-dma-contig.h>
+#include <media/videobuf2-vmalloc.h>
+#include "wave5-vpuconfig.h"
+#include "wave5-vpuapi.h"
+
+#define VPU_BUF_SYNC_TO_DEVICE 0
+#define VPU_BUF_SYNC_FROM_DEVICE 1
+
+struct vpu_buffer {
+	struct v4l2_m2m_buffer v4l2_m2m_buf;
+	bool consumed;
+	struct list_head list;
+};
+
+enum vpu_fmt_type {
+	VPU_FMT_TYPE_CODEC = 0,
+	VPU_FMT_TYPE_RAW   = 1
+};
+
+struct vpu_format {
+	unsigned int v4l2_pix_fmt;
+	unsigned int max_width;
+	unsigned int min_width;
+	unsigned int max_height;
+	unsigned int min_height;
+};
+
+static inline struct vpu_instance *wave5_to_vpu_inst(struct v4l2_fh *vfh)
+{
+	return container_of(vfh, struct vpu_instance, v4l2_fh);
+}
+
+static inline struct vpu_instance *wave5_ctrl_to_vpu_inst(struct v4l2_ctrl *vctrl)
+{
+	return container_of(vctrl->handler, struct vpu_instance, v4l2_ctrl_hdl);
+}
+
+static inline struct vpu_buffer *wave5_to_vpu_buf(struct vb2_v4l2_buffer *vbuf)
+{
+	return container_of(vbuf, struct vpu_buffer, v4l2_m2m_buf.vb);
+}
+
+int wave5_vpu_wait_interrupt(struct vpu_instance *inst, unsigned int timeout);
+
+int  wave5_vpu_dec_register_device(struct vpu_device *dev);
+void wave5_vpu_dec_unregister_device(struct vpu_device *dev);
+int  wave5_vpu_enc_register_device(struct vpu_device *dev);
+void wave5_vpu_enc_unregister_device(struct vpu_device *dev);
+static inline bool wave5_vpu_both_queues_are_streaming(struct vpu_instance *inst)
+{
+	struct vb2_queue *vq_cap =
+		v4l2_m2m_get_vq(inst->v4l2_fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+	struct vb2_queue *vq_out =
+		v4l2_m2m_get_vq(inst->v4l2_fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
+
+	return vb2_is_streaming(vq_cap) && vb2_is_streaming(vq_out);
+}
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/e5010/e5010-core-regs.h b/drivers/media/platform/img/e5010/e5010-core-regs.h
--- a/drivers/media/platform/img/e5010/e5010-core-regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/e5010/e5010-core-regs.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,592 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * TI E5010 JPEG Encoder driver.
+ *
+ * Copyright (c) 2023 Texas Instruments Inc.
+ * Author: David Huang <d-huang@ti.com>
+ * Author: Devarsh Thakkar <devarsht@ti.com>
+ */
+
+#ifndef _E5010_CORE_REGS_H
+#define _E5010_CORE_REGS_H
+
+#define JASPER_CORE_ID_OFFSET				(0x0000)
+#define JASPER_CORE_ID_CR_GROUP_ID_MASK			(0xFF000000)
+#define JASPER_CORE_ID_CR_GROUP_ID_SHIFT		(24)
+#define JASPER_CORE_ID_CR_CORE_ID_MASK			(0x00FF0000)
+#define JASPER_CORE_ID_CR_CORE_ID_SHIFT			(16)
+#define JASPER_CORE_ID_CR_UNIQUE_NUM_MASK		(0x0000FFF8)
+#define JASPER_CORE_ID_CR_UNIQUE_NUM_SHIFT		(3)
+#define JASPER_CORE_ID_CR_PELS_PER_CYCLE_MASK		(0x00000007)
+#define JASPER_CORE_ID_CR_PELS_PER_CYCLE_SHIFT		(0)
+
+#define JASPER_CORE_REV_OFFSET				(0x0004)
+#define JASPER_CORE_REV_CR_JASPER_DESIGNER_MASK		(0xFF000000)
+#define JASPER_CORE_REV_CR_JASPER_DESIGNER_SHIFT	(24)
+#define JASPER_CORE_REV_CR_JASPER_MAJOR_REV_MASK	(0x00FF0000)
+#define JASPER_CORE_REV_CR_JASPER_MAJOR_REV_SHIFT	(16)
+#define JASPER_CORE_REV_CR_JASPER_MINOR_REV_MASK	(0x0000FF00)
+#define JASPER_CORE_REV_CR_JASPER_MINOR_REV_SHIFT	(8)
+#define JASPER_CORE_REV_CR_JASPER_MAINT_REV_MASK	(0x000000FF)
+#define JASPER_CORE_REV_CR_JASPER_MAINT_REV_SHIFT	(0)
+
+#define JASPER_INTERRUPT_MASK_OFFSET					(0x0008)
+#define JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_MASK	(0x00000002)
+#define JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_SHIFT	(1)
+#define JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_MASK		(0x00000001)
+#define JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_SHIFT		(0)
+
+#define JASPER_INTERRUPT_STATUS_OFFSET					(0x000C)
+#define JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_MASK	(0x00000002)
+#define JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_SHIFT	(1)
+#define JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_MASK		(0x00000001)
+#define JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_SHIFT		(0)
+
+#define JASPER_INTERRUPT_CLEAR_OFFSET					(0x0010)
+#define JASPER_INTERRUPT_CLEAR_CR_OUTPUT_ERROR_CLEAR_MASK		(0x00000002)
+#define JASPER_INTERRUPT_CLEAR_CR_OUTPUT_ERROR_CLEAR_SHIFT		(1)
+#define JASPER_INTERRUPT_CLEAR_CR_PICTURE_DONE_CLEAR_MASK		(0x00000001)
+#define JASPER_INTERRUPT_CLEAR_CR_PICTURE_DONE_CLEAR_SHIFT		(0)
+
+#define JASPER_CLK_CONTROL_OFFSET				(0x0014)
+#define JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_MASK	(0x00000002)
+#define JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_SHIFT	(1)
+#define JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_MASK	(0x00000001)
+#define JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_SHIFT	(0)
+
+#define JASPER_CLK_STATUS_OFFSET			(0x0018)
+#define JASPER_CLK_STATUS_CR_JASPER_CLKG_STATUS_MASK	(0x00000001)
+#define JASPER_CLK_STATUS_CR_JASPER_CLKG_STATUS_SHIFT	(0)
+
+#define JASPER_RESET_OFFSET			(0x001C)
+#define JASPER_RESET_CR_SYS_RESET_MASK		(0x00000002)
+#define JASPER_RESET_CR_SYS_RESET_SHIFT		(1)
+#define JASPER_RESET_CR_CORE_RESET_MASK		(0x00000001)
+#define JASPER_RESET_CR_CORE_RESET_SHIFT	(0)
+
+#define JASPER_CORE_CTRL_OFFSET				(0x0020)
+#define JASPER_CORE_CTRL_CR_JASPER_ENCODE_START_MASK	(0x00000001)
+#define JASPER_CORE_CTRL_CR_JASPER_ENCODE_START_SHIFT	(0)
+
+#define JASPER_STATUS_OFFSET				(0x0024)
+#define JASPER_STATUS_CR_FLUSH_MODE_MASK		(0x00000002)
+#define JASPER_STATUS_CR_FLUSH_MODE_SHIFT		(1)
+#define JASPER_STATUS_CR_JASPER_BUSY_MASK		(0x00000001)
+#define JASPER_STATUS_CR_JASPER_BUSY_SHIFT		(0)
+
+#define JASPER_CRC_CLEAR_OFFSET					(0x0028)
+#define JASPER_CRC_CLEAR_CR_FRONT_END_CRC_CLEAR_MASK		(0x00000001)
+#define JASPER_CRC_CLEAR_CR_FRONT_END_CRC_CLEAR_SHIFT		(0)
+#define JASPER_CRC_CLEAR_CR_DCT_CRC_CLEAR_MASK			(0x00000002)
+#define JASPER_CRC_CLEAR_CR_DCT_CRC_CLEAR_SHIFT			(1)
+#define JASPER_CRC_CLEAR_CR_ZZ_CRC_CLEAR_MASK			(0x00000004)
+#define JASPER_CRC_CLEAR_CR_ZZ_CRC_CLEAR_SHIFT			(2)
+#define JASPER_CRC_CLEAR_CR_QUANT_CRC_CLEAR_MASK		(0x00000008)
+#define JASPER_CRC_CLEAR_CR_QUANT_CRC_CLEAR_SHIFT		(3)
+#define JASPER_CRC_CLEAR_CR_ENTROPY_ENCODER_CRC_CLEAR_MASK	(0x00000010)
+#define JASPER_CRC_CLEAR_CR_ENTROPY_ENCODER_CRC_CLEAR_SHIFT	(4)
+#define JASPER_CRC_CLEAR_CR_PACKING_BUFFER_CRC_CLEAR_MASK	(0x00000020)
+#define JASPER_CRC_CLEAR_CR_PACKING_BUFFER_CRC_CLEAR_SHIFT	(5)
+
+#define JASPER_INPUT_CTRL0_OFFSET			(0x002C)
+#define JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_MASK	(0x01000000)
+#define JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_SHIFT	(24)
+#define JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_MASK	(0x00030000)
+#define JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_SHIFT	(16)
+#define JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_MASK		(0x00000004)
+#define JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_SHIFT	(2)
+
+#define JASPER_INPUT_CTRL1_OFFSET			(0x0030)
+#define JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_MASK	(0x1FC00000)
+#define JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_SHIFT	(22)
+#define JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_MASK	(0x00001FC0)
+#define JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_SHIFT	(6)
+
+#define JASPER_MMU_CTRL_OFFSET				(0x0034)
+#define JASPER_MMU_CTRL_CR_JASPER_TILING_SCHEME_MASK	(0x00000002)
+#define JASPER_MMU_CTRL_CR_JASPER_TILING_SCHEME_SHIFT	(1)
+#define JASPER_MMU_CTRL_CR_JASPER_TILING_ENABLE_MASK	(0x00000001)
+#define JASPER_MMU_CTRL_CR_JASPER_TILING_ENABLE_SHIFT	(0)
+
+#define JASPER_IMAGE_SIZE_OFFSET				(0x0038)
+#define JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_MASK		(0x1FFF0000)
+#define JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_SHIFT		(16)
+#define JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_MASK		(0x00001FFF)
+#define JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_SHIFT	(0)
+
+#define INPUT_LUMA_BASE_OFFSET				(0x003C)
+#define INPUT_LUMA_BASE_CR_INPUT_LUMA_BASE_MASK		(0xFFFFFFC0)
+#define INPUT_LUMA_BASE_CR_INPUT_LUMA_BASE_SHIFT	(6)
+
+#define INPUT_CHROMA_BASE_OFFSET			(0x0040)
+#define INPUT_CHROMA_BASE_CR_INPUT_CHROMA_BASE_MASK	(0xFFFFFFC0)
+#define INPUT_CHROMA_BASE_CR_INPUT_CHROMA_BASE_SHIFT	(6)
+
+#define JASPER_OUTPUT_BASE_OFFSET		(0x0044)
+#define JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_MASK	(0xFFFFFFFF)
+#define JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_SHIFT	(0)
+
+#define JASPER_OUTPUT_SIZE_OFFSET			(0x0048)
+#define JASPER_OUTPUT_SIZE_CR_OUTPUT_SIZE_MASK		(0xFFFFFFFF)
+#define JASPER_OUTPUT_SIZE_CR_OUTPUT_SIZE_SHIFT		(0)
+#define JASPER_OUTPUT_MAX_SIZE_OFFSET			(0x004C)
+#define JASPER_OUTPUT_MAX_SIZE_CR_OUTPUT_MAX_SIZE_MASK	(0xFFFFFFFF)
+#define JASPER_OUTPUT_MAX_SIZE_CR_OUTPUT_MAX_SIZE_SHIFT	(0)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE0_OFFSET					(0x0050)
+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_03_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_03_SHIFT	(24)
+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_02_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_02_SHIFT	(16)
+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_01_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_01_SHIFT	(8)
+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_00_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE0_CR_LUMA_QUANTIZATION_TABLE_00_SHIFT	(0)
+#define JASPER_LUMA_QUANTIZATION_TABLE1_OFFSET					(0x0054)
+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_07_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_07_SHIFT	(24)
+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_06_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_06_SHIFT	(16)
+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_05_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_05_SHIFT	(8)
+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_04_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE1_CR_LUMA_QUANTIZATION_TABLE_04_SHIFT	(0)
+#define JASPER_LUMA_QUANTIZATION_TABLE2_OFFSET					(0x0058)
+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_13_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_13_SHIFT	(24)
+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_12_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_12_SHIFT	(16)
+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_11_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_11_SHIFT	(8)
+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_10_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE2_CR_LUMA_QUANTIZATION_TABLE_10_SHIFT	(0)
+#define JASPER_LUMA_QUANTIZATION_TABLE3_OFFSET					(0x005C)
+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_17_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_17_SHIFT	(24)
+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_16_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_16_SHIFT	(16)
+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_15_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_15_SHIFT	(8)
+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_14_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE3_CR_LUMA_QUANTIZATION_TABLE_14_SHIFT	(0)
+#define JASPER_LUMA_QUANTIZATION_TABLE4_OFFSET		(0x0060)
+#define JASPER_LUMA_QUANTIZATION_TABLE4_CR_LUMA_QUANTIZATION_TABLE_21_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE4_CR_LUMA_QUANTIZATION_TABLE_21_SHIFT	(8)
+#define JASPER_LUMA_QUANTIZATION_TABLE4_CR_LUMA_QUANTIZATION_TABLE_20_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE4_CR_LUMA_QUANTIZATION_TABLE_20_SHIFT	(0)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE5_OFFSET		(0x0064)
+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_27_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_27_SHIFT	(24)
+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_26_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_26_SHIFT	(16)
+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_25_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_25_SHIFT	(8)
+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_24_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE5_CR_LUMA_QUANTIZATION_TABLE_24_SHIFT	(0)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE6_OFFSET		(0x0068)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_33_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_33_SHIFT	(24)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_32_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_32_SHIFT	(16)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_31_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_31_SHIFT	(8)
+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_30_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE6_CR_LUMA_QUANTIZATION_TABLE_30_SHIFT	(0)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE7_OFFSET		(0x006C)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_37_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_37_SHIFT	(24)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_36_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_36_SHIFT	(16)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_35_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_35_SHIFT	(8)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_34_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE7_CR_LUMA_QUANTIZATION_TABLE_34_SHIFT	(0)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE8_OFFSET		(0x0070)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_43_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_43_SHIFT	(24)
+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_42_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_42_SHIFT	(16)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_41_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_41_SHIFT	(8)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_40_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE8_CR_LUMA_QUANTIZATION_TABLE_40_SHIFT	(0)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE9_OFFSET		(0x0074)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_47_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_47_SHIFT	(24)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_46_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_46_SHIFT	(16)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_45_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_45_SHIFT	(8)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_44_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE9_CR_LUMA_QUANTIZATION_TABLE_44_SHIFT	(0)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE10_OFFSET		(0x0078)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_53_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_53_SHIFT	(24)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_52_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_52_SHIFT	(16)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_51_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_51_SHIFT	(8)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_50_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE10_CR_LUMA_QUANTIZATION_TABLE_50_SHIFT	(0)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE11_OFFSET	(0x007C)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_57_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_57_SHIFT	(24)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_56_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_56_SHIFT	(16)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_55_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_55_SHIFT	(8)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_54_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE11_CR_LUMA_QUANTIZATION_TABLE_54_SHIFT	(0)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE12_OFFSET	(0x0080)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_63_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_63_SHIFT	(24)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_62_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_62_SHIFT	(16)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_61_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_61_SHIFT	(8)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_60_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE12_CR_LUMA_QUANTIZATION_TABLE_60_SHIFT	(0)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE13_OFFSET	(0x0084)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_67_MASK	(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_67_SHIFT	(24)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_66_MASK	(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_66_SHIFT	(16)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_65_MASK	(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_65_SHIFT	(8)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_64_MASK	(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE13_CR_LUMA_QUANTIZATION_TABLE_64_SHIFT	(0)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE14_OFFSET		(0x0088)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_73_MASK		(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_73_SHIFT		(24)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_72_MASK		(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_72_SHIFT		(16)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_71_MASK		(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_71_SHIFT		(8)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_70_MASK		(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE14_CR_LUMA_QUANTIZATION_TABLE_70_SHIFT		(0)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE15_OFFSET		(0x008C)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_77_MASK		(0xFF000000)
+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_77_SHIFT		(24)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_76_MASK		(0x00FF0000)
+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_76_SHIFT		(16)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_75_MASK		(0x0000FF00)
+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_75_SHIFT		(8)
+
+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_74_MASK		(0x000000FF)
+#define JASPER_LUMA_QUANTIZATION_TABLE15_CR_LUMA_QUANTIZATION_TABLE_74_SHIFT		(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE0_OFFSET		(0x0090)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_03_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_03_SHIFT		(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_02_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_02_SHIFT		(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_01_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_01_SHIFT		(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_00_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE0_CR_CHROMA_QUANTIZATION_TABLE_00_SHIFT		(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE1_OFFSET		(0x0094)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_07_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_07_SHIFT		(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_06_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_06_SHIFT		(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_05_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_05_SHIFT		(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_04_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE1_CR_CHROMA_QUANTIZATION_TABLE_04_SHIFT		(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE2_OFFSET		(0x0098)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_13_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_13_SHIFT		(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_12_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_12_SHIFT		(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_11_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_11_SHIFT		(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_10_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE2_CR_CHROMA_QUANTIZATION_TABLE_10_SHIFT		(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE3_OFFSET		(0x009C)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_17_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_17_SHIFT		(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_16_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_16_SHIFT		(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_15_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_15_SHIFT		(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_14_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE3_CR_CHROMA_QUANTIZATION_TABLE_14_SHIFT		(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE4_OFFSET		(0x00A0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_23_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_23_SHIFT		(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_22_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_22_SHIFT		(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_21_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_21_SHIFT		(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_20_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE4_CR_CHROMA_QUANTIZATION_TABLE_20_SHIFT		(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE5_OFFSET		(0x00A4)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_27_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_27_SHIFT		(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_26_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_26_SHIFT		(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_25_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_25_SHIFT		(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_24_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE5_CR_CHROMA_QUANTIZATION_TABLE_24_SHIFT		(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE6_OFFSET		(0x00A8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_33_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_33_SHIFT		(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_32_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_32_SHIFT		(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_31_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_31_SHIFT		(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_30_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE6_CR_CHROMA_QUANTIZATION_TABLE_30_SHIFT		(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE7_OFFSET		(0x00AC)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_37_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_37_SHIFT		(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_36_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_36_SHIFT		(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_35_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_35_SHIFT		(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_34_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE7_CR_CHROMA_QUANTIZATION_TABLE_34_SHIFT		(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE8_OFFSET		(0x00B0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_43_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_43_SHIFT		(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_42_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_42_SHIFT		(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_41_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_41_SHIFT		(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_40_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE8_CR_CHROMA_QUANTIZATION_TABLE_40_SHIFT		(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE9_OFFSET		(0x00B4)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_47_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_47_SHIFT		(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_46_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_46_SHIFT		(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_45_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_45_SHIFT		(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_44_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE9_CR_CHROMA_QUANTIZATION_TABLE_44_SHIFT		(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE10_OFFSET		(0x00B8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_53_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_53_SHIFT	(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_52_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_52_SHIFT	(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_51_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_51_SHIFT	(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_50_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE10_CR_CHROMA_QUANTIZATION_TABLE_50_SHIFT	(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE11_OFFSET		(0x00BC)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_57_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_57_SHIFT	(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_56_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_56_SHIFT	(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_55_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_55_SHIFT	(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_54_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE11_CR_CHROMA_QUANTIZATION_TABLE_54_SHIFT	(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE12_OFFSET		(0x00C0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_63_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_63_SHIFT	(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_62_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_62_SHIFT	(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_61_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_61_SHIFT	(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_60_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE12_CR_CHROMA_QUANTIZATION_TABLE_60_SHIFT	(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE13_OFFSET		(0x00C4)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_67_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_67_SHIFT	(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_66_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_66_SHIFT	(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_65_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_65_SHIFT	(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_64_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE13_CR_CHROMA_QUANTIZATION_TABLE_64_SHIFT	(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE14_OFFSET		(0x00C8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_73_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_73_SHIFT	(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_72_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_72_SHIFT	(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_71_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_71_SHIFT	(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_70_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE14_CR_CHROMA_QUANTIZATION_TABLE_70_SHIFT	(0)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE15_OFFSET		(0x00CC)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_77_MASK		(0xFF000000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_77_SHIFT	(24)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_76_MASK		(0x00FF0000)
+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_76_SHIFT	(16)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_75_MASK		(0x0000FF00)
+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_75_SHIFT	(8)
+
+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_74_MASK		(0x000000FF)
+#define JASPER_CHROMA_QUANTIZATION_TABLE15_CR_CHROMA_QUANTIZATION_TABLE_74_SHIFT	(0)
+
+#define JASPER_CRC_CTRL_OFFSET		(0x00D0)
+
+#define JASPER_CRC_CTRL_JASPER_CRC_ENABLE_MASK		(0x00000001)
+#define JASPER_CRC_CTRL_JASPER_CRC_ENABLE_SHIFT		(0)
+
+#define JASPER_FRONT_END_CRC_OFFSET		(0x00D4)
+
+#define JASPER_FRONT_END_CRC_CR_JASPER_FRONT_END_CRC_OUT_MASK		(0xFFFFFFFF)
+#define JASPER_FRONT_END_CRC_CR_JASPER_FRONT_END_CRC_OUT_SHIFT		(0)
+
+#define JASPER_DCT_CRC_OFFSET		(0x00D8)
+
+#define JASPER_DCT_CRC_CR_JASPER_DCT_CRC_OUT_MASK		(0xFFFFFFFF)
+#define JASPER_DCT_CRC_CR_JASPER_DCT_CRC_OUT_SHIFT		(0)
+
+#define JASPER_ZZ_CRC_OFFSET		(0x00DC)
+
+#define JASPER_ZZ_CRC_CR_JASPER_ZZ_CRC_OUT_MASK		(0xFFFFFFFF)
+#define JASPER_ZZ_CRC_CR_JASPER_ZZ_CRC_OUT_SHIFT		(0)
+
+#define JASPER_QUANT_CRC_OFFSET		(0x00E0)
+
+#define JASPER_QUANT_CRC_CR_JASPER_QUANT_CRC_OUT_MASK		(0xFFFFFFFF)
+#define JASPER_QUANT_CRC_CR_JASPER_QUANT_CRC_OUT_SHIFT		(0)
+
+#define JASPER_ENTROPY_ENCODER_CRC_OFFSET		(0x00E4)
+
+#define JASPER_ENTROPY_ENCODER_CRC_CR_JASPER_ENTROPY_CRC_OUT_MASK		(0xFFFFFFFF)
+#define JASPER_ENTROPY_ENCODER_CRC_CR_JASPER_ENTROPY_CRC_OUT_SHIFT		(0)
+
+#define JASPER_PACKING_BUFFER_DATA_CRC_OFFSET		(0x00E8)
+
+#define JASPER_PACKING_BUFFER_DATA_CRC_CR_JASPER_PACKING_DATA_CRC_OUT_MASK		(0xFFFFFFFF)
+#define JASPER_PACKING_BUFFER_DATA_CRC_CR_JASPER_PACKING_DATA_CRC_OUT_SHIFT		(0)
+
+#define JASPER_PACKING_BUFFER_ADDR_CRC_OFFSET		(0x00EC)
+
+#define JASPER_PACKING_BUFFER_ADDR_CRC_CR_JASPER_PACKING_ADDR_OUT_CRC_MASK		(0xFFFFFFFF)
+#define JASPER_PACKING_BUFFER_ADDR_CRC_CR_JASPER_PACKING_ADDR_OUT_CRC_SHIFT		(0)
+
+#define JASPER_CORE_BYTE_SIZE		(0x00F0)
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/e5010/e5010-jpeg-enc.c b/drivers/media/platform/img/e5010/e5010-jpeg-enc.c
--- a/drivers/media/platform/img/e5010/e5010-jpeg-enc.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/e5010/e5010-jpeg-enc.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,1766 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Imagination E5010 JPEG Encoder driver.
+ *
+ * Copyright (c) 2023 Texas Instruments Inc.
+ * Author: David Huang <d-huang@ti.com>
+ * Author: Devarsh Thakkar <devarsht@ti.com>
+ */
+
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/printk.h>
+#include <linux/ioctl.h>
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/pm_runtime.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-v4l2.h>
+#include <media/videobuf2-dma-contig.h>
+#include "e5010-jpeg-enc.h"
+#include "e5010-jpeg-enc-hw.h"
+
+static const struct of_device_id e5010_of_match[];
+
+static const struct v4l2_file_operations e5010_fops;
+
+static const struct v4l2_ioctl_ops e5010_ioctl_ops;
+
+static const struct vb2_ops e5010_video_ops;
+
+static const struct v4l2_m2m_ops e5010_m2m_ops;
+
+static struct e5010_fmt e5010_formats[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_NV12,
+		.num_planes = 1,
+		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+		.chroma_order = CHROMA_ORDER_CB_CR,
+		.h_align = 6,
+		.v_align = 3,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV12M,
+		.num_planes = 2,
+		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+		.chroma_order = CHROMA_ORDER_CB_CR,
+		.h_align = 6,
+		.v_align = 3,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV21,
+		.num_planes = 1,
+		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+		.chroma_order = CHROMA_ORDER_CR_CB,
+		.h_align = 6,
+		.v_align = 3,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV21M,
+		.num_planes = 2,
+		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_420,
+		.chroma_order = CHROMA_ORDER_CR_CB,
+		.h_align = 6,
+		.v_align = 3,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV16,
+		.num_planes = 1,
+		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+		.chroma_order = CHROMA_ORDER_CB_CR,
+		.h_align = 6,
+		.v_align = 3,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV16M,
+		.num_planes = 2,
+		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+		.chroma_order = CHROMA_ORDER_CB_CR,
+		.h_align = 6,
+		.v_align = 3,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV61,
+		.num_planes = 1,
+		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+		.chroma_order = CHROMA_ORDER_CR_CB,
+		.h_align = 6,
+		.v_align = 3,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV61M,
+		.num_planes = 2,
+		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.subsampling = V4L2_JPEG_CHROMA_SUBSAMPLING_422,
+		.chroma_order = CHROMA_ORDER_CR_CB,
+		.h_align = 6,
+		.v_align = 3,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_JPEG,
+		.num_planes = 1,
+		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.subsampling = 0,
+		.chroma_order = 0,
+		.h_align = 0,
+		.v_align = 0,
+	},
+};
+
+/* Luma and chroma qp table to acheive 50% compression quality
+ * This is as per example in Annex K.1 of IS0/IEC 10918-1:1994(E)
+ */
+static const u8 luma[64] = {
+	16, 11, 10, 16, 24, 40, 51, 61,
+	12, 12, 14, 19, 26, 58, 60, 55,
+	14, 13, 16, 24, 40, 57, 69, 56,
+	14, 17, 22, 29, 51, 87, 80, 62,
+	18, 22, 37, 56, 68, 109, 103, 77,
+	24, 35, 55, 64, 81, 104, 113, 92,
+	49, 64, 78, 87, 103, 121, 120, 101,
+	72, 92, 95, 98, 112, 100, 103, 99
+};
+
+static const u8 chroma[64] = {
+	17, 18, 24, 47, 99, 99, 99, 99,
+	18, 21, 26, 66, 99, 99, 99, 99,
+	24, 26, 56, 99, 99, 99, 99, 99,
+	47, 66, 99, 99, 99, 99, 99, 99,
+	99, 99, 99, 99, 99, 99, 99, 99,
+	99, 99, 99, 99, 99, 99, 99, 99,
+	99, 99, 99, 99, 99, 99, 99, 99,
+	99, 99, 99, 99, 99, 99, 99, 99
+};
+
+/* Zigzag scan pattern */
+static const u8 zigzag[64] = {
+	0,   1,  8, 16,  9,  2,  3, 10,
+	17, 24, 32, 25, 18, 11,  4,  5,
+	12, 19, 26, 33, 40, 48, 41, 34,
+	27, 20, 13,  6,  7, 14, 21, 28,
+	35, 42, 49, 56, 57, 50, 43, 36,
+	29, 22, 15, 23, 30, 37, 44, 51,
+	58, 59, 52, 45, 38, 31, 39, 46,
+	53, 60, 61, 54, 47, 55, 62, 63
+};
+
+/*
+ * Contains the data that needs to be sent in the marker segment of an interchange format JPEG
+ * stream or an abbreviated format table specification data stream.
+ * Specifies the huffman table used for encoding the luminance DC coefficient differences.
+ * The table represents Table K.3 of IS0/IEC 10918-1:1994(E)
+ */
+static const u8 marker_luma_dc[] = {
+	0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B
+};
+
+/*
+ * Contains the data that needs to be sent in the marker segment of an interchange format JPEG
+ * stream or an abbreviated format table specification data stream.
+ * Specifies the huffman table used for encoding the luminance AC coefficients.
+ * The table represents Table K.5 of IS0/IEC 10918-1:1994(E)
+ */
+static const u8 marker_luma_ac[] = {
+	0x10, 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
+	0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D,
+	0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
+	0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52,
+	0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25,
+	0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45,
+	0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64,
+	0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83,
+	0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
+	0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
+	0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3,
+	0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8,
+	0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
+};
+
+/*
+ * Contains the data that needs to be sent in the marker segment of an interchange format JPEG
+ * stream or an abbreviated format table specification data stream.
+ * Specifies the huffman table used for encoding the chrominance DC coefficient differences.
+ * The table represents Table K.4 of IS0/IEC 10918-1:1994(E)
+ */
+static const u8 marker_chroma_dc[] = {
+	0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B
+};
+
+/*
+ * Contains the data that needs to be sent in the marker segment of an interchange format JPEG
+ * stream or an abbreviated format table specification data stream.
+ * Specifies the huffman table used for encoding the chrominance AC coefficients.
+ * The table represents Table K.6 of IS0/IEC 10918-1:1994(E)
+ */
+static const u8 marker_chroma_ac[] = {
+	0x11, 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+	0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
+	0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61,
+	0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33,
+	0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18,
+	0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
+	0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63,
+	0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A,
+	0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4,
+	0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA,
+	0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+	0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA
+};
+
+static unsigned int debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "debug level");
+
+#define dprintk(dev, lvl, fmt, arg...) \
+	v4l2_dbg(lvl, debug, &(dev)->v4l2_dev, "%s: " fmt, __func__, ## arg)
+
+static const struct v4l2_event e5010_eos_event = {
+	.type = V4L2_EVENT_EOS
+};
+
+static const char *type_name(enum v4l2_buf_type type)
+{
+	switch (type) {
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		return "Output";
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		return "Capture";
+	default:
+		return "Invalid";
+	}
+}
+
+static struct e5010_q_data *get_queue(struct e5010_context *ctx, enum v4l2_buf_type type)
+{
+	switch (type) {
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		return &ctx->out_queue;
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		return &ctx->cap_queue;
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+static void calculate_qp_tables(struct e5010_context *ctx)
+{
+	long long luminosity, contrast;
+	int quality, i;
+
+	quality = 100 - ctx->quality;
+	quality -= 50;
+
+	luminosity = LUMINOSITY * quality / 50;
+	contrast = CONTRAST * quality / 50;
+
+	if (quality > 0) {
+		luminosity *= INCREASE;
+		contrast *= INCREASE;
+	}
+
+	for (i = 0; i < 64; i++) {
+		long long delta = chroma[i] * contrast + luminosity;
+		int val = (int)(chroma[i] + delta);
+
+		if (val < 1)
+			val = 1;
+		if (val > 255)
+			val = 255;
+		ctx->chroma_qp[i] = quality == -50 ? 1 : val;
+
+		delta = luma[i] * contrast + luminosity;
+		val = (int)(luma[i] + delta);
+		if (val < 1)
+			val = 1;
+		if (val > 255)
+			val = 255;
+		ctx->luma_qp[i] = quality == -50 ? 1 : val;
+	}
+
+	ctx->update_qp = true;
+}
+
+static int update_qp_tables(struct e5010_context *ctx)
+{
+	struct e5010_dev *dev = ctx->dev;
+	int i, ret = 0;
+	u32 lvalue, cvalue;
+
+	lvalue = 0;
+	cvalue = 0;
+
+	for (i = 0; i < (QP_TABLE_SIZE); i++) {
+		lvalue |= ctx->luma_qp[i] << (8 * (i % 4));
+		cvalue |= ctx->chroma_qp[i] << (8 * (i % 4));
+		if (i % 4 == 3) {
+			ret |= e5010_hw_set_qpvalue(dev->jasper_base,
+							JASPER_LUMA_QUANTIZATION_TABLE0_OFFSET
+							+ QP_TABLE_FIELD_OFFSET * ((i - 3) / 4),
+							lvalue);
+			ret |= e5010_hw_set_qpvalue(dev->jasper_base,
+							JASPER_CHROMA_QUANTIZATION_TABLE0_OFFSET
+							+ QP_TABLE_FIELD_OFFSET * ((i - 3) / 4),
+							cvalue);
+			lvalue = 0;
+			cvalue = 0;
+		}
+	}
+
+	return ret;
+}
+
+static int e5010_set_input_subsampling(void __iomem *core_base, int subsampling)
+{
+	switch (subsampling) {
+	case V4L2_JPEG_CHROMA_SUBSAMPLING_420:
+		return e5010_hw_set_input_subsampling(core_base, SUBSAMPLING_420);
+	case V4L2_JPEG_CHROMA_SUBSAMPLING_422:
+		return e5010_hw_set_input_subsampling(core_base, SUBSAMPLING_422);
+	default:
+		return -EINVAL;
+	};
+}
+
+static int e5010_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
+{
+	strncpy(cap->driver, E5010_MODULE_NAME, sizeof(cap->driver));
+	strncpy(cap->card, E5010_MODULE_NAME, sizeof(cap->card));
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", E5010_MODULE_NAME);
+	cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+	return 0;
+}
+
+static struct e5010_fmt *find_format(struct v4l2_format *f)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(e5010_formats); ++i) {
+		if (e5010_formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
+		    e5010_formats[i].type == f->type)
+			return &e5010_formats[i];
+	}
+
+	return NULL;
+}
+
+static int e5010_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f)
+{
+	int i, index = 0;
+	struct e5010_fmt *fmt = NULL;
+	struct e5010_context *ctx = file->private_data;
+
+	if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
+		dev_err(ctx->dev->dev, "ENUMFMT with Invalid type: %d\n", f->type);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(e5010_formats); ++i) {
+		if (e5010_formats[i].type == f->type) {
+			if (index == f->index) {
+				fmt = &e5010_formats[i];
+				break;
+			}
+			index++;
+		}
+	}
+
+	if (!fmt)
+		return -EINVAL;
+
+	f->pixelformat = fmt->fourcc;
+	return 0;
+}
+
+static int e5010_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+	struct e5010_context *ctx = file->private_data;
+	struct e5010_q_data *queue;
+	int i;
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
+
+	if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
+		dev_err(ctx->dev->dev, "G_FMT with Invalid type: %d\n", f->type);
+		return -EINVAL;
+	}
+
+	queue = get_queue(ctx, f->type);
+	if (IS_ERR(queue))
+		return PTR_ERR(queue);
+
+	pix_mp->flags = 0;
+	pix_mp->field = V4L2_FIELD_NONE;
+	pix_mp->pixelformat = queue->fmt->fourcc;
+	pix_mp->width = queue->width_adjusted;
+	pix_mp->height = queue->height_adjusted;
+	pix_mp->num_planes = queue->fmt->num_planes;
+
+	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+		if (!pix_mp->colorspace)
+			pix_mp->colorspace = V4L2_COLORSPACE_SRGB;
+
+		for (i = 0; i < queue->fmt->num_planes; i++) {
+			plane_fmt[i].sizeimage = queue->sizeimage[i];
+			plane_fmt[i].bytesperline = queue->bytesperline[i];
+		}
+
+	} else {
+		pix_mp->colorspace = V4L2_COLORSPACE_JPEG;
+		plane_fmt[0].bytesperline = 0;
+		plane_fmt[0].sizeimage = queue->sizeimage[0];
+	}
+	pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+	pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT;
+
+	return 0;
+}
+
+static void e5010_queue_update_bytesperline(struct e5010_q_data *q)
+{
+	if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {
+		/* bytesperline unused for compressed formats */
+		q->bytesperline[0] = 0;
+		q->bytesperline[1] = 0;
+	} else if (q->fmt->num_planes == 1) {
+		q->bytesperline[0] = q->width_adjusted;
+		q->bytesperline[1] = 0;
+	} else {
+		q->bytesperline[0] = q->width_adjusted;
+		q->bytesperline[1] = q->bytesperline[0];
+	}
+}
+
+static void e5010_queue_update_sizeimage(struct e5010_q_data *q, struct e5010_context *ctx)
+{
+	if (q->fmt->fourcc == V4L2_PIX_FMT_JPEG) {
+		if (ctx->out_queue.fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420)
+			q->sizeimage[0] = q->width_adjusted * q->height_adjusted * 3 / 2;
+		else
+			q->sizeimage[0] = q->width_adjusted * q->height_adjusted * 2;
+		q->sizeimage[0] += HEADER_SIZE;
+		q->sizeimage[1] = 0;
+	} else if (q->fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_420) {
+		if (q->fmt->num_planes == 1)	{
+			q->sizeimage[0] = q->width_adjusted * q->height_adjusted * 3 / 2;
+			q->sizeimage[1] = 0;
+		} else {
+			q->sizeimage[0] = q->width_adjusted * q->height_adjusted;
+			q->sizeimage[1] = q->sizeimage[0] / 2;
+		}
+	} else {
+		if (q->fmt->num_planes == 1)	{
+			q->sizeimage[0] = q->width_adjusted * q->height_adjusted * 2;
+			q->sizeimage[1] = 0;
+		} else {
+			q->sizeimage[0] = q->width_adjusted * q->height_adjusted;
+			q->sizeimage[1] = q->sizeimage[0];
+		}
+	}
+}
+
+static int e5010_jpeg_try_fmt(struct v4l2_format *f, struct e5010_context *ctx)
+{
+	struct e5010_fmt *fmt;
+	struct e5010_q_data *queue;
+	int i;
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
+
+	if (!V4L2_TYPE_IS_MULTIPLANAR(f->type)) {
+		dev_err(ctx->dev->dev, "G_FMT with Invalid type: %d\n", f->type);
+		return -EINVAL;
+	}
+
+	fmt = find_format(f);
+	if (!fmt) {
+		if (V4L2_TYPE_IS_OUTPUT(f->type))
+			pix_mp->pixelformat = V4L2_PIX_FMT_NV12;
+		else
+			pix_mp->pixelformat = V4L2_PIX_FMT_JPEG;
+		fmt = find_format(f);
+		if (!fmt)
+			return -EINVAL;
+	}
+
+	queue = get_queue(ctx, f->type);
+	if (IS_ERR(queue))
+		return PTR_ERR(queue);
+
+	queue->fmt = fmt;
+	queue->width = pix_mp->width;
+	queue->height = pix_mp->height;
+
+	queue->width_adjusted = queue->width;
+	queue->height_adjusted = queue->height;
+
+	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+		if (!pix_mp->colorspace)
+			pix_mp->colorspace = V4L2_COLORSPACE_JPEG;
+		if (!pix_mp->ycbcr_enc)
+			pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+		if (!pix_mp->quantization)
+			pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT;
+		if (!pix_mp->xfer_func)
+			pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+
+		v4l_bound_align_image(&queue->width_adjusted,
+				      MIN_DIMENSION,
+				      MAX_DIMENSION,
+				      fmt->h_align,
+				      &queue->height_adjusted,
+				      MIN_DIMENSION, /* adjust upwards*/
+				      MAX_DIMENSION,
+				      fmt->v_align,
+				      0);
+		e5010_queue_update_bytesperline(queue);
+		e5010_queue_update_sizeimage(queue, ctx);
+		for (i = 0; i < fmt->num_planes; i++) {
+			memset(plane_fmt[i].reserved, 0, sizeof(plane_fmt[i].reserved));
+			plane_fmt[i].bytesperline = queue->bytesperline[i];
+			plane_fmt[i].sizeimage = queue->sizeimage[i];
+		}
+	} else {
+		pix_mp->colorspace = V4L2_COLORSPACE_JPEG;
+		pix_mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+		pix_mp->quantization = V4L2_QUANTIZATION_DEFAULT;
+		pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+
+		plane_fmt[0].bytesperline = 0;
+
+		memset(plane_fmt[0].reserved, 0, sizeof(plane_fmt[0].reserved));
+		v4l_bound_align_image(&queue->width_adjusted,
+				      MIN_DIMENSION,
+				      MAX_DIMENSION,
+				      4,
+				      &queue->height_adjusted,
+				      MIN_DIMENSION, /* adjust upwards*/
+				      MAX_DIMENSION,
+				      ctx->out_queue.fmt->v_align,
+				      0);
+		e5010_queue_update_bytesperline(queue);
+		e5010_queue_update_sizeimage(queue, ctx);
+		plane_fmt[0].sizeimage = queue->sizeimage[0];
+	}
+	pix_mp->flags = 0;
+	pix_mp->field = V4L2_FIELD_NONE;
+	pix_mp->pixelformat = fmt->fourcc;
+	pix_mp->width = queue->width_adjusted;
+	pix_mp->height = queue->height_adjusted;
+	pix_mp->num_planes = fmt->num_planes;
+	memset(pix_mp->reserved, 0, sizeof(pix_mp->reserved));
+
+	dprintk(ctx->dev, 2,
+		"ctx: 0x%p: format type %s:, wxh: %dx%d (plane0 : %d bytes, plane1 : %d bytes),fmt: %c%c%c%c\n",
+		ctx, type_name(f->type), queue->width_adjusted, queue->height_adjusted,
+		queue->sizeimage[0], queue->sizeimage[1],
+		(queue->fmt->fourcc & 0xff),
+		(queue->fmt->fourcc >>  8) & 0xff,
+		(queue->fmt->fourcc >> 16) & 0xff,
+		(queue->fmt->fourcc >> 24) & 0xff);
+
+	return 0;
+}
+
+static int e5010_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+	struct e5010_context *ctx = file->private_data;
+
+	return e5010_jpeg_try_fmt(f, ctx);
+}
+
+static int e5010_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+	struct e5010_context *ctx = file->private_data;
+	struct vb2_queue *vq;
+
+	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+	if (!vq)
+		return -EINVAL;
+
+	if (vb2_is_busy(vq)) {
+		v4l2_err(&ctx->dev->v4l2_dev, "queue busy\n");
+		return -EBUSY;
+	}
+
+	return e5010_jpeg_try_fmt(f, ctx);
+}
+
+static int e5010_enum_framesizes(struct file *file, void *priv, struct v4l2_frmsizeenum *fsize)
+{
+	struct v4l2_format f;
+
+	if (fsize->index != 0)
+		return -EINVAL;
+
+	f.fmt.pix_mp.pixelformat = fsize->pixel_format;
+	if (f.fmt.pix_mp.pixelformat ==  V4L2_PIX_FMT_JPEG)
+		f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	else
+		f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+
+	if (!find_format(&f))
+		return -EINVAL;
+
+	fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
+	fsize->stepwise.min_width = MIN_DIMENSION;
+	fsize->stepwise.max_width = MAX_DIMENSION;
+	fsize->stepwise.step_width = 1;
+	fsize->stepwise.min_height = MIN_DIMENSION;
+	fsize->stepwise.max_height = MAX_DIMENSION;
+	fsize->stepwise.step_height = 1;
+
+	fsize->reserved[0] = 0;
+	fsize->reserved[1] = 0;
+
+	return 0;
+}
+
+static int e5010_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
+{
+	struct e5010_context *ctx = file->private_data;
+	struct e5010_q_data *queue;
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return -EINVAL;
+
+	queue = get_queue(ctx, s->type);
+	if (IS_ERR(queue))
+		return PTR_ERR(queue);
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_CROP_DEFAULT:
+	case V4L2_SEL_TGT_CROP_BOUNDS:
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = queue->width;
+		s->r.height = queue->height;
+		break;
+	case V4L2_SEL_TGT_CROP:
+		s->r = queue->crop;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int e5010_s_selection(struct file *file, void *fh, struct v4l2_selection *s)
+{
+	struct e5010_context *ctx = file->private_data;
+	struct e5010_q_data *queue;
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		return -EINVAL;
+
+	queue = get_queue(ctx, s->type);
+	if (IS_ERR(queue))
+		return PTR_ERR(queue);
+
+	queue->crop.left = 0;
+	queue->crop.top = 0;
+	queue->crop.width = s->r.width;
+	queue->crop.height = s->r.height;
+
+	return 0;
+}
+
+static int e5010_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_EOS:
+		return v4l2_event_subscribe(fh, sub, 0, NULL);
+	case V4L2_EVENT_CTRL:
+		return v4l2_ctrl_subscribe_event(fh, sub);
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
+{
+	struct e5010_context *ctx = priv;
+	struct e5010_dev *dev = ctx->dev;
+	int ret = 0;
+
+	/* src_vq */
+	memset(src_vq, 0, sizeof(*src_vq));
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
+	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	src_vq->drv_priv = ctx;
+	src_vq->buf_struct_size = sizeof(struct e5010_buffer);
+	src_vq->ops = &e5010_video_ops;
+	src_vq->mem_ops = &vb2_dma_contig_memops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock = &dev->mutex;
+	src_vq->dev = dev->v4l2_dev.dev;
+
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	/* dst_vq */
+	memset(dst_vq, 0, sizeof(*dst_vq));
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	src_vq->dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
+	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	dst_vq->drv_priv = ctx;
+	dst_vq->buf_struct_size = sizeof(struct e5010_buffer);
+	dst_vq->ops = &e5010_video_ops;
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock = &dev->mutex;
+	dst_vq->dev = dev->v4l2_dev.dev;
+
+	ret = vb2_queue_init(dst_vq);
+	if (ret) {
+		vb2_queue_release(src_vq);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int e5010_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct e5010_context *ctx =
+		container_of(ctrl->handler, struct e5010_context, ctrl_handler);
+
+	switch (ctrl->id) {
+	case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+		ctx->quality = ctrl->val;
+		calculate_qp_tables(ctx);
+		break;
+	default:
+		dev_err(ctx->dev->dev, "Invalid control, id = %d, val = %d\n",
+			ctrl->id, ctrl->val);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops e5010_ctrl_ops = {
+	.s_ctrl = e5010_s_ctrl,
+};
+
+static void e5010_encode_ctrls(struct e5010_context *ctx)
+{
+	v4l2_ctrl_new_std(&ctx->ctrl_handler, &e5010_ctrl_ops,
+			  V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 75);
+}
+
+static int e5010_ctrls_setup(struct e5010_context *ctx)
+{
+	int err;
+
+	v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1);
+
+	e5010_encode_ctrls(ctx);
+
+	if (ctx->ctrl_handler.error) {
+		err = ctx->ctrl_handler.error;
+		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+		return err;
+	}
+
+	err = v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
+	if (err)
+		v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+
+	return err;
+}
+
+static void e5010_jpeg_set_default_params(struct e5010_context *ctx)
+{
+	struct e5010_q_data *queue;
+	struct v4l2_format f;
+	struct e5010_fmt *fmt;
+
+	f.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
+	fmt = find_format(&f);
+	queue = &ctx->out_queue;
+	queue->fmt = fmt;
+	queue->width = DEFAULT_WIDTH;
+	queue->height = DEFAULT_HEIGHT;
+	queue->width_adjusted = queue->width;
+	queue->height_adjusted = queue->height;
+
+	v4l_bound_align_image(&queue->width_adjusted,
+			      MIN_DIMENSION,
+			      MAX_DIMENSION,
+			      fmt->h_align,
+			      &queue->height_adjusted,
+			      MIN_DIMENSION, /* adjust upwards*/
+			      MAX_DIMENSION,
+			      fmt->v_align,
+			      0);
+
+	e5010_queue_update_bytesperline(queue);
+	e5010_queue_update_sizeimage(queue, ctx);
+	queue->format_set = false;
+	queue->streaming = false;
+
+	f.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_JPEG;
+	fmt = find_format(&f);
+	queue = &ctx->cap_queue;
+	queue->fmt = fmt;
+	queue->width = DEFAULT_WIDTH;
+	queue->height = DEFAULT_HEIGHT;
+	queue->width_adjusted = queue->width;
+	queue->height_adjusted = queue->height;
+	v4l_bound_align_image(&queue->width_adjusted,
+			      MIN_DIMENSION,
+			      MAX_DIMENSION,
+			      4,
+			      &queue->height_adjusted,
+			      MIN_DIMENSION, /* adjust upwards*/
+			      MAX_DIMENSION,
+			      ctx->out_queue.fmt->v_align,
+			      0);
+
+	e5010_queue_update_bytesperline(queue);
+	e5010_queue_update_sizeimage(queue, ctx);
+	queue->format_set = false;
+	queue->streaming = false;
+}
+
+static int e5010_open(struct file *file)
+{
+	struct e5010_dev *dev = video_drvdata(file);
+	struct video_device *vdev = video_devdata(file);
+	struct e5010_context *ctx;
+	int ret = 0;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	if (mutex_lock_interruptible(&dev->mutex)) {
+		ret = -ERESTARTSYS;
+		goto free;
+	}
+
+	v4l2_fh_init(&ctx->fh, vdev);
+	file->private_data = ctx;
+	v4l2_fh_add(&ctx->fh);
+
+	ctx->dev = dev;
+	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, queue_init);
+	if (IS_ERR(ctx->fh.m2m_ctx)) {
+		dev_err(dev->dev, "Failed to init m2m ctx\n");
+		ret = PTR_ERR(ctx->fh.m2m_ctx);
+		goto exit;
+	}
+
+	ret = e5010_ctrls_setup(ctx);
+	if (ret) {
+		dev_err(ctx->dev->dev, "failed to setup e5010 jpeg controls\n");
+		goto err_ctrls_setup;
+	}
+	ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+
+	e5010_jpeg_set_default_params(ctx);
+
+	dprintk(dev, 1, "Created instance: 0x%p, m2m_ctx: 0x%p\n", ctx, ctx->fh.m2m_ctx);
+
+	mutex_unlock(&dev->mutex);
+	return 0;
+
+err_ctrls_setup:
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+exit:
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	mutex_unlock(&dev->mutex);
+free:
+	kfree(ctx);
+	return ret;
+}
+
+static int e5010_release(struct file *file)
+{
+	struct e5010_dev *dev = video_drvdata(file);
+	struct e5010_context *ctx = file->private_data;
+
+	dprintk(dev, 1, "Releasing instance: 0x%p, m2m_ctx: 0x%p\n", ctx, ctx->fh.m2m_ctx);
+	mutex_lock(&dev->mutex);
+	v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	kfree(ctx);
+	mutex_unlock(&dev->mutex);
+
+	return 0;
+}
+
+static struct video_device e5010_videodev = {
+	.name = E5010_MODULE_NAME,
+	.fops = &e5010_fops,
+	.ioctl_ops = &e5010_ioctl_ops,
+	.minor = -1,
+	.release = video_device_release_empty,
+	.vfl_dir = VFL_DIR_M2M,
+	.device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
+};
+
+static void header_write(struct e5010_context *ctx, u8 *addr, unsigned int *offset,
+			 unsigned int no_bytes, unsigned long bits)
+{
+	u8 *w_addr = addr + *offset;
+	int i;
+
+	if ((*offset + no_bytes) > HEADER_SIZE) {
+		dev_warn(ctx->dev->dev, "%s: %s: %d: Problem writing header. %d > HEADER_SIZE %d\n",
+			 __FILE__, __func__, __LINE__, *offset + no_bytes, HEADER_SIZE);
+		return;
+	}
+
+	for (i = no_bytes - 1; i >= 0; i--)
+		*(w_addr++) = ((u8 *)&bits)[i];
+
+	*offset += no_bytes;
+}
+
+static void encode_marker_segment(struct e5010_context *ctx, void *addr, unsigned int *offset)
+{
+	u8 *buffer = (u8 *)addr;
+	int i;
+
+	header_write(ctx, buffer, offset, 2, START_OF_IMAGE);
+	header_write(ctx, buffer, offset, 2, DQT_MARKER);
+	header_write(ctx, buffer, offset, 3, LQPQ << 4);
+	for (i = 0; i < PELS_IN_BLOCK; i++)
+		header_write(ctx, buffer, offset, 1, ctx->luma_qp[zigzag[i]]);
+
+	header_write(ctx, buffer, offset, 2, DQT_MARKER);
+	header_write(ctx, buffer, offset, 3, (LQPQ << 4) | 1);
+	for (i = 0; i < PELS_IN_BLOCK; i++)
+		header_write(ctx, buffer, offset, 1, ctx->chroma_qp[zigzag[i]]);
+
+	/* Huffman tables */
+	header_write(ctx, buffer, offset, 2, DHT_MARKER);
+	header_write(ctx, buffer, offset, 2, LH_DC);
+	for (i = 0 ; i < (LH_DC - 2); i++)
+		header_write(ctx, buffer, offset, 1, marker_luma_dc[i]);
+
+	header_write(ctx, buffer, offset, 2, DHT_MARKER);
+	header_write(ctx, buffer, offset, 2, LH_AC);
+	for (i = 0 ; i < (LH_AC - 2); i++)
+		header_write(ctx, buffer, offset, 1, marker_luma_ac[i]);
+
+	header_write(ctx, buffer, offset, 2, DHT_MARKER);
+	header_write(ctx, buffer, offset, 2, LH_DC);
+	for (i = 0 ; i < (LH_DC - 2); i++)
+		header_write(ctx, buffer, offset, 1, marker_chroma_dc[i]);
+
+	header_write(ctx, buffer, offset, 2, DHT_MARKER);
+	header_write(ctx, buffer, offset, 2, LH_AC);
+	for (i = 0 ; i < (LH_AC - 2); i++)
+		header_write(ctx, buffer, offset, 1, marker_chroma_ac[i]);
+}
+
+static void encode_frame_header(struct e5010_context *ctx, void *addr, unsigned int *offset)
+{
+	u8 *buffer = (u8 *)addr;
+
+	header_write(ctx, buffer, offset, 2, SOF_BASELINE_DCT);
+	header_write(ctx, buffer, offset, 2, 8 + (3 * UC_NUM_COMP));
+	header_write(ctx, buffer, offset, 1, PRECISION);
+	header_write(ctx, buffer, offset, 2, ctx->out_queue.height);
+	header_write(ctx, buffer, offset, 2, ctx->out_queue.width);
+	header_write(ctx, buffer, offset, 1, UC_NUM_COMP);
+
+	/* Luma details */
+	header_write(ctx, buffer, offset, 1, 1);
+	if (ctx->out_queue.fmt->subsampling == V4L2_JPEG_CHROMA_SUBSAMPLING_422)
+		header_write(ctx, buffer, offset, 1,
+			     HORZ_SAMPLING_FACTOR | (VERT_SAMPLING_FACTOR_422));
+	else
+		header_write(ctx, buffer, offset, 1,
+			     HORZ_SAMPLING_FACTOR | (VERT_SAMPLING_FACTOR_420));
+	header_write(ctx, buffer, offset, 1, 0);
+	/* Chroma details */
+	header_write(ctx, buffer, offset, 1, 2);
+	header_write(ctx, buffer, offset, 1, (HORZ_SAMPLING_FACTOR >> 1) | 1);
+	header_write(ctx, buffer, offset, 1, 1);
+	header_write(ctx, buffer, offset, 1, 3);
+	header_write(ctx, buffer, offset, 1, (HORZ_SAMPLING_FACTOR >> 1) | 1);
+	header_write(ctx, buffer, offset, 1, 1);
+
+	header_write(ctx, buffer, offset, 1, 0xFF);
+}
+
+static void jpg_encode_sos_header(struct e5010_context *ctx, void *addr, unsigned int *offset)
+{
+	u8 *buffer = (u8 *)addr;
+	int i;
+
+	header_write(ctx, buffer, offset, 2, START_OF_SCAN);
+	header_write(ctx, buffer, offset, 2, 6 + (COMPONENTS_IN_SCAN << 1));
+	header_write(ctx, buffer, offset, 1, COMPONENTS_IN_SCAN);
+
+	for (i = 0; i < COMPONENTS_IN_SCAN; i++) {
+		header_write(ctx, buffer, offset, 1, i + 1);
+		if (i == 0)
+			header_write(ctx, buffer, offset, 1, 0);
+		else
+			header_write(ctx, buffer, offset, 1, 17);
+	}
+
+	header_write(ctx, buffer, offset, 1, 0);
+	header_write(ctx, buffer, offset, 1, 63);
+	header_write(ctx, buffer, offset, 1, 0);
+}
+
+static void write_header(struct e5010_context *ctx, void *addr)
+{
+	unsigned int offset = 0;
+
+	encode_marker_segment(ctx, addr, &offset);
+	encode_frame_header(ctx, addr, &offset);
+	jpg_encode_sos_header(ctx, addr, &offset);
+}
+
+static irqreturn_t e5010_irq(int irq, void *data)
+{
+	struct e5010_dev *dev = data;
+	struct e5010_context *ctx;
+	int output_size;
+	struct vb2_v4l2_buffer *src_buf, *dst_buf;
+	bool pic_done, out_addr_err;
+
+	spin_lock(&dev->hw_lock);
+	pic_done = e5010_hw_pic_done_irq(dev->jasper_base);
+	out_addr_err = e5010_hw_output_address_irq(dev->jasper_base);
+
+	if (!pic_done && !out_addr_err) {
+		spin_unlock(&dev->hw_lock);
+		return IRQ_NONE;
+	}
+
+	ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
+	if (WARN_ON(!ctx))
+		goto job_unlock;
+
+	dst_buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+	src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	if (!dst_buf || !src_buf) {
+		dev_err(dev->dev, "ctx: 0x%p No source or destination buffer\n", ctx);
+		goto job_unlock;
+	}
+
+	if (out_addr_err) {
+		e5010_hw_clear_output_error(dev->jasper_base, 1);
+		dev_warn(dev->dev, "ctx: 0x%p Output bitstream size exceeded max size\n", ctx);
+		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, dst_buf->planes[0].length);
+		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_ERROR);
+		if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) {
+			dst_buf->flags |= V4L2_BUF_FLAG_LAST;
+			v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
+			v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
+			dprintk(dev, 2, "ctx: 0x%p Sending EOS\n", ctx);
+		}
+	}
+
+	if (pic_done) {
+		e5010_hw_clear_picture_done(dev->jasper_base, 1);
+		dprintk(dev, 3, "ctx: 0x%p Got output bitstream of size %d bytes\n",
+			ctx, readl(dev->jasper_base + JASPER_OUTPUT_SIZE_OFFSET));
+
+		if (v4l2_m2m_is_last_draining_src_buf(ctx->fh.m2m_ctx, src_buf)) {
+			dst_buf->flags |= V4L2_BUF_FLAG_LAST;
+			v4l2_m2m_mark_stopped(ctx->fh.m2m_ctx);
+			v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
+			dprintk(dev, 2, "ctx: 0x%p Sending EOS\n", ctx);
+		}
+		v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+		output_size = e5010_hw_get_output_size(dev->jasper_base);
+		vb2_set_plane_payload(&dst_buf->vb2_buf, 0, output_size + HEADER_SIZE);
+		v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
+		dprintk(dev, 3,
+			"ctx: 0x%p frame done for dst_buf->sequence: %d src_buf->sequence: %d\n",
+			ctx, dst_buf->sequence, src_buf->sequence);
+	}
+
+	v4l2_m2m_job_finish(dev->m2m_dev, ctx->fh.m2m_ctx);
+	dprintk(dev, 3, "ctx: 0x%p Finish job\n", ctx);
+
+job_unlock:
+	spin_unlock(&dev->hw_lock);
+	return IRQ_HANDLED;
+}
+
+static int e5010_init_device(struct e5010_dev *dev)
+{
+	int ret = 0;
+
+	/*TODO: Set MMU in bypass mode until support for the same is added in driver*/
+	e5010_hw_bypass_mmu(dev->mmu_base, 1);
+
+	if (e5010_hw_enable_auto_clock_gating(dev->jasper_base, 1))
+		dev_warn(dev->dev, "Failed to enable auto clock gating\n");
+
+	if (e5010_hw_enable_manual_clock_gating(dev->jasper_base, 0))
+		dev_warn(dev->dev, "Failed to disable manual clock gating\n");
+
+	if (e5010_hw_enable_crc_check(dev->jasper_base, 0))
+		dev_warn(dev->dev, "Failed to disable CRC check\n");
+
+	if (e5010_hw_enable_output_address_error_irq(dev->jasper_base, 1))
+		dev_err(dev->dev, "Failed to enable Output Address Error interrupts\n");
+
+	ret = e5010_hw_set_input_source_to_memory(dev->jasper_base, 1);
+	if (ret) {
+		dev_err(dev->dev, "Failed to set input source to memory\n");
+		goto fail;
+	}
+
+	ret = e5010_hw_enable_picture_done_irq(dev->jasper_base, 1);
+	if (ret)
+		dev_err(dev->dev, "Failed to enable Picture Done interrupts\n");
+fail:
+	return ret;
+}
+
+static int e5010_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *of_dev_id;
+	struct e5010_dev *dev;
+	struct resource *res;
+	int irq, ret = 0;
+
+	of_dev_id = of_match_device(e5010_of_match, &pdev->dev);
+	if (!of_dev_id) {
+		dev_err(&pdev->dev, "%s: Unable to match device\n", __func__);
+		return -ENODEV;
+	}
+
+	ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+	if (ret) {
+		dev_err(&pdev->dev, "32-bit consistent DMA enable failed\n");
+		return ret;
+	}
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, dev);
+
+	dev->dev = &pdev->dev;
+
+	mutex_init(&dev->mutex);
+	spin_lock_init(&dev->hw_lock);
+
+	dev->vdev = &e5010_videodev;
+	dev->vdev->v4l2_dev = &dev->v4l2_dev;
+	dev->vdev->lock = &dev->mutex;
+	dev->vdev->queue = NULL;
+	dev->vdev->prio = NULL;
+	dev->vdev->dev_parent = NULL;
+	dev->vdev->minor = -1;
+
+	ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+	if (ret) {
+		dev_err(dev->dev, "Failed to register v4l2 device\n");
+		return ret;
+	}
+
+	dev->m2m_dev = v4l2_m2m_init(&e5010_m2m_ops);
+	if (!dev->m2m_dev) {
+		dev_err(dev->dev, "Failed to initialize m2m device\n");
+		ret = -ENOMEM;
+		goto fail_after_v4l2_register;
+	}
+
+	video_set_drvdata(dev->vdev, dev);
+
+	ret = video_register_device(dev->vdev, VFL_TYPE_VIDEO, 0);
+	if (ret) {
+		dev_err(dev->dev, "Failed to register video device\n");
+		ret = -ENOMEM;
+		goto fail_after_v4l2_register;
+	}
+
+	dev_info(dev->dev, "Device registered as /dev/video%d\n",
+		 dev->vdev->num);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regjasper");
+	if (!res) {
+		dev_err(dev->dev, "Missing 'regjasper' resources area\n");
+		ret = -ENOMEM;
+		goto fail_after_video_register_device;
+	}
+	dev->jasper_base = devm_ioremap_resource(&pdev->dev, res);
+	if (!dev->jasper_base) {
+		ret = -ENOMEM;
+		goto fail_after_video_register_device;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regmmu");
+	if (!res) {
+		dev_err(dev->dev, "Missing 'regmmu' resources area\n");
+		ret = -ENOMEM;
+		goto fail_after_video_register_device;
+	}
+	dev->mmu_base = devm_ioremap_resource(&pdev->dev, res);
+	if (!dev->mmu_base) {
+		ret = -ENOMEM;
+		goto fail_after_video_register_device;
+	}
+
+	dev->last_context_run = NULL;
+
+	irq = platform_get_irq(pdev, 0);
+	ret = devm_request_irq(dev->dev, irq, e5010_irq, 0,
+			       E5010_MODULE_NAME, dev);
+	if (ret) {
+		dev_err(dev->dev, "Failed to register IRQ %d\n", irq);
+		goto fail_after_video_register_device;
+	}
+
+	dev->clk = devm_clk_get(&pdev->dev, "core_clk");
+	if (IS_ERR(dev->clk)) {
+		dev_err(dev->dev, "failed to get clock\n");
+		ret = PTR_ERR(dev->clk);
+		goto fail_after_video_register_device;
+	}
+
+	pm_runtime_enable(dev->dev);
+
+	return 0;
+
+fail_after_video_register_device:
+	video_device_release(dev->vdev);
+	v4l2_m2m_release(dev->m2m_dev);
+fail_after_v4l2_register:
+	v4l2_device_unregister(&dev->v4l2_dev);
+	return ret;
+}
+
+static int e5010_remove(struct platform_device *pdev)
+{
+	struct e5010_dev *dev = platform_get_drvdata(pdev);
+
+	pm_runtime_disable(dev->dev);
+	video_unregister_device(dev->vdev);
+	v4l2_m2m_release(dev->m2m_dev);
+	v4l2_device_unregister(&dev->v4l2_dev);
+
+	return 0;
+}
+
+static int e5010_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, unsigned int *nplanes,
+			     unsigned int sizes[], struct device *alloc_devs[])
+{
+	struct e5010_context *ctx = vb2_get_drv_priv(vq);
+	struct e5010_q_data *queue;
+	int i;
+
+	if (!V4L2_TYPE_IS_MULTIPLANAR(vq->type)) {
+		dev_err(ctx->dev->dev, "queue setup with Invalid type: %d\n", vq->type);
+		return -EINVAL;
+	}
+
+	queue = get_queue(ctx, vq->type);
+	if (IS_ERR(queue))
+		return PTR_ERR(queue);
+
+	if (*nplanes) {
+		if (*nplanes != queue->fmt->num_planes)
+			return -EINVAL;
+		for (i = 0; i < *nplanes; i++) {
+			if (sizes[i] < queue->sizeimage[i])
+				return -EINVAL;
+		}
+		return 0;
+	}
+
+	*nbuffers = max_t(unsigned int, *nbuffers, 1);
+	*nplanes = queue->fmt->num_planes;
+	for (i = 0; i < *nplanes; i++)
+		sizes[i] = queue->sizeimage[i];
+
+	dprintk(ctx->dev, 2,
+		"ctx: 0x%p, type %s, buffer(s): %d, planes %d, plane1: bytes %d plane2: %d bytes\n",
+		ctx, type_name(vq->type), *nbuffers, *nplanes, sizes[0], sizes[1]);
+
+	return 0;
+}
+
+static void e5010_buf_finish(struct vb2_buffer *vb)
+{
+	struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	void *d_addr;
+
+	if (vb->state != VB2_BUF_STATE_DONE || V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type))
+		return;
+
+	d_addr = vb2_plane_vaddr(vb, 0);
+	write_header(ctx, d_addr);
+}
+
+static int e5010_buf_out_validate(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+	if (vbuf->field != V4L2_FIELD_NONE)
+		dprintk(ctx->dev, 1, "ctx: 0x%p, field isn't supported\n", ctx);
+
+	vbuf->field = V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+static int e5010_buf_prepare(struct vb2_buffer *vb)
+{
+	struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct e5010_q_data *queue;
+	int i;
+
+	vbuf->field = V4L2_FIELD_NONE;
+
+	queue = get_queue(ctx, vb->vb2_queue->type);
+	if (IS_ERR(queue))
+		return PTR_ERR(queue);
+
+	for (i = 0; i < queue->fmt->num_planes; i++) {
+		if (vb2_plane_size(vb, i) < (unsigned long)queue->sizeimage[i]) {
+			dev_err(ctx->dev->dev, "plane %d too small (%lu < %lu)", i,
+				vb2_plane_size(vb, i), (unsigned long)queue->sizeimage[i]);
+
+			return -EINVAL;
+		}
+	}
+
+	if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type)) {
+		vb2_set_plane_payload(vb, 0, 0);
+		vb2_set_plane_payload(vb, 1, 0);
+	}
+
+	return 0;
+}
+
+static void e5010_buf_queue(struct vb2_buffer *vb)
+{
+	struct e5010_context *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+
+	if (V4L2_TYPE_IS_CAPTURE(vb->vb2_queue->type) &&
+	    vb2_is_streaming(vb->vb2_queue) &&
+	    v4l2_m2m_dst_buf_is_last(ctx->fh.m2m_ctx)) {
+		struct e5010_q_data *queue = get_queue(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+
+		if (IS_ERR(queue))
+			return;
+		vbuf->sequence = queue->sequence++;
+		v4l2_m2m_last_buffer_done(ctx->fh.m2m_ctx, vbuf);
+		v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
+		return;
+	}
+
+	v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+}
+
+static int e5010_encoder_cmd(struct file *file, void *priv,
+			     struct v4l2_encoder_cmd *cmd)
+{
+	struct e5010_context *ctx = file->private_data;
+	int ret;
+	struct vb2_queue *cap_vq;
+
+	cap_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
+
+	ret = v4l2_m2m_ioctl_try_encoder_cmd(file, &ctx->fh, cmd);
+	if (ret < 0)
+		return ret;
+
+	if (!vb2_is_streaming(v4l2_m2m_get_src_vq(ctx->fh.m2m_ctx)) ||
+	    !vb2_is_streaming(v4l2_m2m_get_dst_vq(ctx->fh.m2m_ctx)))
+		return 0;
+
+	ret = v4l2_m2m_ioctl_encoder_cmd(file, &ctx->fh, cmd);
+	if (ret < 0)
+		return ret;
+
+	if (cmd->cmd == V4L2_ENC_CMD_STOP &&
+	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
+		v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
+
+	if (cmd->cmd == V4L2_ENC_CMD_START &&
+	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx))
+		vb2_clear_last_buffer_dequeued(cap_vq);
+
+	return 0;
+}
+
+static int e5010_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+	struct e5010_context *ctx = vb2_get_drv_priv(q);
+	int ret;
+
+	struct e5010_q_data *queue = get_queue(ctx, q->type);
+
+	if (IS_ERR(queue))
+		return PTR_ERR(queue);
+	queue->streaming = true;
+	v4l2_m2m_update_start_streaming_state(ctx->fh.m2m_ctx, q);
+	queue->sequence = 0;
+
+	ret = pm_runtime_resume_and_get(ctx->dev->dev);
+	if (ret < 0) {
+		dev_err(ctx->dev->dev, "Failed to power up jpeg\n");
+		return ret;
+	}
+
+	ret = e5010_init_device(ctx->dev);
+	if (ret)
+		dev_err(ctx->dev->dev, "Failed to Enable e5010 device\n");
+
+	return ret;
+}
+
+static void e5010_stop_streaming(struct vb2_queue *q)
+{
+	struct e5010_context *ctx = vb2_get_drv_priv(q);
+	struct vb2_v4l2_buffer *vbuf;
+	struct e5010_q_data *queue;
+
+	queue = get_queue(ctx, q->type);
+	if (IS_ERR(queue))
+		return;
+
+	queue->streaming = false;
+
+	if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		while ((vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx))) {
+			dprintk(ctx->dev, 2, "ctx: 0x%p, buf type %s | index %d\n",
+				ctx, type_name(vbuf->vb2_buf.type), vbuf->vb2_buf.index);
+			v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+		}
+	} else {
+		while ((vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx))) {
+			dprintk(ctx->dev, 2, "ctx: 0x%p, buf type %s | index %d\n",
+				ctx, type_name(vbuf->vb2_buf.type), vbuf->vb2_buf.index);
+			vb2_set_plane_payload(&vbuf->vb2_buf, 0, 0);
+			v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR);
+		}
+	}
+
+	if (V4L2_TYPE_IS_OUTPUT(q->type))
+		v4l2_m2m_update_stop_streaming_state(ctx->fh.m2m_ctx, q);
+
+	if (V4L2_TYPE_IS_OUTPUT(q->type) &&
+	    v4l2_m2m_has_stopped(ctx->fh.m2m_ctx)) {
+		v4l2_event_queue_fh(&ctx->fh, &e5010_eos_event);
+	}
+
+	pm_runtime_put_sync(ctx->dev->dev);
+}
+
+static void e5010_device_run(void *priv)
+{
+	struct e5010_context *ctx = priv;
+	struct e5010_dev *dev = ctx->dev;
+	struct vb2_v4l2_buffer *s_vb, *d_vb;
+	u32 reg = 0;
+	int ret = 0;
+	unsigned long flags;
+	int num_planes = ctx->out_queue.fmt->num_planes;
+
+	spin_lock_irqsave(&dev->hw_lock, flags);
+	s_vb = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+	WARN_ON(!s_vb);
+	d_vb = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
+	WARN_ON(!d_vb);
+	if (!s_vb || !d_vb)
+		goto no_ready_buf_err;
+
+	s_vb->sequence = ctx->out_queue.sequence++;
+	d_vb->sequence = ctx->cap_queue.sequence++;
+
+	v4l2_m2m_buf_copy_metadata(s_vb, d_vb, false);
+
+	if (ctx != dev->last_context_run || ctx->update_qp) {
+		dprintk(dev, 1, "ctx updated: 0x%p -> 0x%p, updating qp tables\n",
+			dev->last_context_run, ctx);
+		ret = update_qp_tables(ctx);
+	}
+
+	if (ret) {
+		ctx->update_qp = true;
+		dev_err(dev->dev, "Failed to update QP tables\n");
+		goto device_busy_err;
+	} else {
+		dev->last_context_run = ctx;
+		ctx->update_qp = false;
+	}
+
+	/* Set I/O Buffer addresses */
+	reg = (u32)vb2_dma_contig_plane_dma_addr(&s_vb->vb2_buf, 0);
+	ret = e5010_hw_set_input_luma_addr(dev->jasper_base, reg);
+	if (ret || !reg) {
+		dev_err(dev->dev, "Failed to set input luma address\n");
+		goto device_busy_err;
+	}
+
+	if (num_planes == 1)
+		reg += (ctx->out_queue.bytesperline[0]) * (ctx->out_queue.height);
+	else
+		reg = (u32)vb2_dma_contig_plane_dma_addr(&s_vb->vb2_buf, 1);
+
+	dprintk(dev, 3,
+		"ctx: 0x%p, luma_addr: 0x%x, chroma_addr: 0x%x, out_addr: 0x%x\n",
+		ctx, (u32)vb2_dma_contig_plane_dma_addr(&s_vb->vb2_buf, 0), reg,
+		(u32)vb2_dma_contig_plane_dma_addr(&d_vb->vb2_buf, 0));
+
+	dprintk(dev, 3,
+		"ctx: 0x%p, buf indices: src_index: %d, dst_index: %d\n",
+		ctx, s_vb->vb2_buf.index, d_vb->vb2_buf.index);
+
+	ret = e5010_hw_set_input_chroma_addr(dev->jasper_base, reg);
+	if (ret || !reg) {
+		dev_err(dev->dev, "Failed to set input chroma address\n");
+		goto device_busy_err;
+	}
+
+	reg = (u32)vb2_dma_contig_plane_dma_addr(&d_vb->vb2_buf, 0);
+	reg += HEADER_SIZE;
+	ret = e5010_hw_set_output_base_addr(dev->jasper_base, reg);
+	if (ret || !reg) {
+		dev_err(dev->dev, "Failed to set output size\n");
+		goto device_busy_err;
+	}
+
+	/* Set input settings */
+	ret = e5010_hw_set_horizontal_size(dev->jasper_base, ctx->out_queue.width - 1);
+	if (ret) {
+		dev_err(dev->dev, "Failed to set input width\n");
+		goto device_busy_err;
+	}
+
+	ret = e5010_hw_set_vertical_size(dev->jasper_base, ctx->out_queue.height - 1);
+	if (ret) {
+		dev_err(dev->dev, "Failed to set input width\n");
+		goto device_busy_err;
+	}
+
+	ret = e5010_hw_set_luma_stride(dev->jasper_base, ctx->out_queue.bytesperline[0]);
+	if (ret) {
+		dev_err(dev->dev, "Failed to set luma stride\n");
+		goto device_busy_err;
+	}
+
+	ret = e5010_hw_set_chroma_stride(dev->jasper_base, ctx->out_queue.bytesperline[0]);
+	if (ret) {
+		dev_err(dev->dev, "Failed to set chroma stride\n");
+		goto device_busy_err;
+	}
+
+	ret = e5010_set_input_subsampling(dev->jasper_base, ctx->out_queue.fmt->subsampling);
+	if (ret) {
+		dev_err(dev->dev, "Failed to set input subsampling\n");
+		goto device_busy_err;
+	}
+
+	ret = e5010_hw_set_chroma_order(dev->jasper_base, ctx->out_queue.fmt->chroma_order);
+	if (ret) {
+		dev_err(dev->dev, "Failed to set chroma order\n");
+		goto device_busy_err;
+	}
+
+	e5010_hw_set_output_max_size(dev->jasper_base, d_vb->planes[0].length);
+	e5010_hw_encode_start(dev->jasper_base, 1);
+
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+
+	return;
+
+device_busy_err:
+	e5010_reset(dev->dev, dev->jasper_base, dev->mmu_base);
+
+no_ready_buf_err:
+	if (s_vb) {
+		v4l2_m2m_src_buf_remove_by_buf(ctx->fh.m2m_ctx, s_vb);
+		v4l2_m2m_buf_done(s_vb, VB2_BUF_STATE_ERROR);
+	}
+
+	if (d_vb) {
+		v4l2_m2m_dst_buf_remove_by_buf(ctx->fh.m2m_ctx, d_vb);
+		/* Payload set to 1 since 0 payload can trigger EOS */
+		vb2_set_plane_payload(&d_vb->vb2_buf, 0, 1);
+		v4l2_m2m_buf_done(d_vb, VB2_BUF_STATE_ERROR);
+	}
+	v4l2_m2m_job_finish(dev->m2m_dev, ctx->fh.m2m_ctx);
+	spin_unlock_irqrestore(&dev->hw_lock, flags);
+
+	return;
+}
+
+#ifdef CONFIG_PM
+static int e5010_runtime_resume(struct device *dev)
+{
+	struct e5010_dev *e5010_dev = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(e5010_dev->clk);
+	if (ret < 0) {
+		dev_err(dev, "failed to enable clock\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int e5010_runtime_suspend(struct device *dev)
+{
+	struct e5010_dev *e5010_dev = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(e5010_dev->clk);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int e5010_suspend(struct device *dev)
+{
+	struct e5010_dev *e5010_dev = dev_get_drvdata(dev);
+
+	v4l2_m2m_suspend(e5010_dev->m2m_dev);
+	return pm_runtime_force_suspend(dev);
+}
+
+static int e5010_resume(struct device *dev)
+{
+	struct e5010_dev *e5010_dev = dev_get_drvdata(dev);
+	int ret;
+
+	ret = pm_runtime_force_resume(dev);
+	if (ret < 0)
+		return ret;
+
+	v4l2_m2m_resume(e5010_dev->m2m_dev);
+	return ret;
+}
+#endif
+
+static const struct dev_pm_ops	e5010_pm_ops = {
+	SET_RUNTIME_PM_OPS(e5010_runtime_suspend,
+			   e5010_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(e5010_suspend, e5010_resume)
+};
+
+static const struct v4l2_ioctl_ops e5010_ioctl_ops = {
+	.vidioc_querycap = e5010_querycap,
+
+	.vidioc_enum_fmt_vid_cap = e5010_enum_fmt,
+	.vidioc_g_fmt_vid_cap_mplane = e5010_g_fmt,
+	.vidioc_try_fmt_vid_cap_mplane = e5010_try_fmt,
+	.vidioc_s_fmt_vid_cap_mplane = e5010_s_fmt,
+
+	.vidioc_enum_fmt_vid_out = e5010_enum_fmt,
+	.vidioc_g_fmt_vid_out_mplane = e5010_g_fmt,
+	.vidioc_try_fmt_vid_out_mplane = e5010_try_fmt,
+	.vidioc_s_fmt_vid_out_mplane = e5010_s_fmt,
+
+	.vidioc_g_selection = e5010_g_selection,
+	.vidioc_s_selection = e5010_s_selection,
+
+	.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+	.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+	.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
+	.vidioc_prepare_buf = v4l2_m2m_ioctl_prepare_buf,
+
+	.vidioc_streamon = v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+	.vidioc_log_status = v4l2_ctrl_log_status,
+
+	.vidioc_subscribe_event = e5010_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+	.vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
+	.vidioc_encoder_cmd = e5010_encoder_cmd,
+
+	.vidioc_enum_framesizes = e5010_enum_framesizes,
+};
+
+static const struct vb2_ops e5010_video_ops = {
+	.queue_setup = e5010_queue_setup,
+	.buf_queue = e5010_buf_queue,
+	.buf_finish = e5010_buf_finish,
+	.buf_prepare = e5010_buf_prepare,
+	.buf_out_validate = e5010_buf_out_validate,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.start_streaming = e5010_start_streaming,
+	.stop_streaming = e5010_stop_streaming,
+};
+
+static const struct v4l2_file_operations e5010_fops = {
+	.owner = THIS_MODULE,
+	.open = e5010_open,
+	.release = e5010_release,
+	.poll = v4l2_m2m_fop_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.mmap = v4l2_m2m_fop_mmap,
+};
+
+static const struct v4l2_m2m_ops e5010_m2m_ops = {
+	.device_run = e5010_device_run,
+};
+
+static const struct of_device_id e5010_of_match[] = {
+	{.compatible = "img,e5010-jpeg-enc"},   { /* end */},
+};
+MODULE_DEVICE_TABLE(of, e5010_of_match);
+
+static struct platform_driver e5010_driver = {
+	.probe = e5010_probe,
+	.remove = e5010_remove,
+	.driver = {
+		.name = E5010_MODULE_NAME,
+		.of_match_table = e5010_of_match,
+		.pm = &e5010_pm_ops,
+	},
+};
+module_platform_driver(e5010_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Imagination E5010 JPEG encoder driver");
diff -Naur --no-dereference a/drivers/media/platform/img/e5010/e5010-jpeg-enc.h b/drivers/media/platform/img/e5010/e5010-jpeg-enc.h
--- a/drivers/media/platform/img/e5010/e5010-jpeg-enc.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/e5010/e5010-jpeg-enc.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2023 Texas Instruments Inc.
+ *
+ */
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+
+#ifndef _E5010_JPEG_ENC_H
+#define _E5010_JPEG_ENC_H
+
+#define MAX_PLANES			2
+#define HEADER_SIZE			0x025E
+#define MIN_DIMENSION			64
+#define MAX_DIMENSION			8192
+#define DEFAULT_WIDTH			640
+#define DEFAULT_HEIGHT			480
+#define E5010_MODULE_NAME		"e5010"
+
+/* JPEG marker definitions */
+#define START_OF_IMAGE			0xFFD8
+#define SOF_BASELINE_DCT		0xFFC0
+#define END_OF_IMAGE			0xFFD9
+#define START_OF_SCAN			0xFFDA
+
+/* Definitions for the huffman table specification in the Marker segment */
+#define DHT_MARKER			0xFFC4
+#define LH_DC				0x001F
+#define LH_AC				0x00B5
+
+/* Definitions for the quantization table specification in the Marker segment */
+#define DQT_MARKER			0xFFDB
+#define ACMAX				0x03FF
+#define DCMAX				0x07FF
+
+/* Length and precision of the quantization table parameters */
+#define LQPQ				0x00430
+#define QMAX				255
+
+/* Misc JPEG header definitions */
+#define UC_NUM_COMP			3
+#define PRECISION			8
+#define HORZ_SAMPLING_FACTOR		(2 << 4)
+#define VERT_SAMPLING_FACTOR_422	1
+#define VERT_SAMPLING_FACTOR_420	2
+#define COMPONENTS_IN_SCAN		3
+#define PELS_IN_BLOCK			64
+
+/* Used for Qp table generation */
+#define LUMINOSITY			10
+#define CONTRAST			1
+#define INCREASE			2
+#define QP_TABLE_SIZE			(8 * 8)
+#define QP_TABLE_FIELD_OFFSET		0x04
+
+/*
+ * vb2 queue structure
+ * contains queue data information
+ *
+ * @fmt: format info
+ * @width: frame width
+ * @height: frame height
+ * @bytesperline: bytes per line in memory
+ * @size_image: image size in memory
+ */
+struct e5010_q_data {
+	struct e5010_fmt *fmt;
+	u32 width;
+	u32 height;
+	u32 width_adjusted;
+	u32 height_adjusted;
+	u32 sizeimage[MAX_PLANES];
+	u32 bytesperline[MAX_PLANES];
+	bool format_set;
+	bool streaming;
+	u32			sequence;
+	struct v4l2_rect	crop;
+};
+
+/*
+ * Driver device structure
+ * Holds all memory handles and global parameters
+ * Shared by all instances
+ */
+struct e5010_dev {
+	struct device *dev;
+	struct v4l2_device v4l2_dev;
+	struct v4l2_m2m_dev *m2m_dev;
+	struct video_device *vdev;
+	void __iomem *jasper_base;
+	void __iomem *mmu_base;
+	struct clk   *clk;
+	struct e5010_context *last_context_run;
+	/* Protect access to device data */
+	struct mutex mutex;
+	/* Protect access to hardware*/
+	spinlock_t hw_lock;
+};
+
+/*
+ * Driver context structure
+ * One of these exists for every m2m context
+ * Holds context specific data
+ */
+struct e5010_context {
+	struct v4l2_fh fh;
+	struct e5010_dev *dev;
+	struct e5010_q_data out_queue;
+	struct e5010_q_data cap_queue;
+	int quality;
+	bool update_qp;
+	struct v4l2_ctrl_handler ctrl_handler;
+	u8 luma_qp[QP_TABLE_SIZE];
+	u8 chroma_qp[QP_TABLE_SIZE];
+};
+
+/*
+ * Buffer structure
+ * Contains info for all buffers
+ */
+struct e5010_buffer {
+	struct v4l2_m2m_buffer buffer;
+};
+
+enum {
+	CHROMA_ORDER_CB_CR = 0, //UV ordering
+	CHROMA_ORDER_CR_CB = 1, //VU ordering
+};
+
+enum {
+	SUBSAMPLING_420 = 1,
+	SUBSAMPLING_422 = 2,
+};
+
+/*
+ * e5010 format structure
+ * contains format information
+ */
+struct e5010_fmt {
+	u32 fourcc;
+	unsigned int num_planes;
+	unsigned int type;
+	u32 subsampling;
+	u32 chroma_order;
+	u32 h_align;
+	u32 v_align;
+};
+
+/*
+ * struct e5010_ctrl - contains info for each supported v4l2 control
+ */
+struct e5010_ctrl {
+	unsigned int cid;
+	enum v4l2_ctrl_type type;
+	unsigned char name[32];
+	int minimum;
+	int maximum;
+	int step;
+	int default_value;
+	unsigned char compound;
+};
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/e5010/e5010-jpeg-enc-hw.c b/drivers/media/platform/img/e5010/e5010-jpeg-enc-hw.c
--- a/drivers/media/platform/img/e5010/e5010-jpeg-enc-hw.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/e5010/e5010-jpeg-enc-hw.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,320 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TI E5010 JPEG Encoder HW driver.
+ *
+ * Copyright (c) 2023 Texas Instruments Inc.
+ * Author: David Huang <d-huang@ti.com>
+ * Author: Devarsh Thakkar <devarsht@ti.com>
+ */
+
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/dev_printk.h>
+#include "e5010-jpeg-enc-hw.h"
+
+static void write_reg_field(void __iomem *base, unsigned int offset, u32 mask,
+			    unsigned int shift, u32 value)
+{
+	u32 reg;
+
+	value <<= shift;
+	if (mask != 0xffffffff) {
+		reg = readl(base + offset);
+		value = (value & mask) | (reg & ~mask);
+	}
+	writel(value, (void *)(base + offset));
+}
+
+static int write_reg_field_not_busy(void __iomem *jasper_base, void __iomem *wr_base,
+				    unsigned int offset, u32 mask, unsigned int shift,
+				    u32 value)
+{
+	int ret;
+	u32 val;
+
+	ret = readl_poll_timeout_atomic(jasper_base + JASPER_STATUS_OFFSET, val,
+					(val & JASPER_STATUS_CR_JASPER_BUSY_MASK) == 0,
+					2000, 50000);
+	if (ret)
+		return ret;
+
+	write_reg_field(wr_base, offset, mask, shift, value);
+
+	return 0;
+}
+
+void e5010_reset(struct device *dev, void __iomem *core_base, void __iomem *mmu_base)
+{
+	int ret = 0;
+	u32 val;
+
+	write_reg_field(core_base, JASPER_RESET_OFFSET,
+			JASPER_RESET_CR_CORE_RESET_MASK,
+			JASPER_RESET_CR_CORE_RESET_SHIFT, 1);
+
+	write_reg_field(mmu_base, MMU_MMU_CONTROL1_OFFSET,
+			MMU_MMU_CONTROL1_MMU_SOFT_RESET_MASK,
+			MMU_MMU_CONTROL1_MMU_SOFT_RESET_SHIFT, 1);
+
+	ret = readl_poll_timeout_atomic(mmu_base + MMU_MMU_CONTROL1_OFFSET, val,
+					(val & MMU_MMU_CONTROL1_MMU_SOFT_RESET_MASK) == 0,
+					2000, 50000);
+	if (ret)
+		dev_warn(dev, "MMU soft reset timed out, forcing system soft reset\n");
+
+	write_reg_field(core_base, JASPER_RESET_OFFSET,
+			JASPER_RESET_CR_SYS_RESET_MASK,
+			JASPER_RESET_CR_SYS_RESET_SHIFT, 1);
+}
+
+void e5010_hw_bypass_mmu(void __iomem *mmu_base, u32 enable)
+{
+	/* Bypass MMU */
+	write_reg_field(mmu_base,
+			MMU_MMU_ADDRESS_CONTROL_OFFSET,
+			MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_MASK,
+			MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_SHIFT,
+			enable);
+}
+
+int e5010_hw_enable_output_address_error_irq(void __iomem *core_base, u32 enable)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_INTERRUPT_MASK_OFFSET,
+				       JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_MASK,
+				       JASPER_INTERRUPT_MASK_CR_OUTPUT_ADDRESS_ERROR_ENABLE_SHIFT,
+				       enable);
+	return ret;
+}
+
+bool e5010_hw_pic_done_irq(void __iomem *core_base)
+{
+	u32 reg;
+	bool pic_done;
+
+	reg = readl(core_base + JASPER_INTERRUPT_STATUS_OFFSET);
+	pic_done = (reg & JASPER_INTERRUPT_STATUS_CR_PICTURE_DONE_IRQ_MASK) ? true : false;
+
+	return pic_done;
+}
+
+bool e5010_hw_output_address_irq(void __iomem *core_base)
+{
+	u32 reg;
+	bool output_address_error;
+
+	reg = readl(core_base + JASPER_INTERRUPT_STATUS_OFFSET);
+	output_address_error = (reg & JASPER_INTERRUPT_STATUS_CR_OUTPUT_ADDRESS_ERROR_IRQ_MASK) ?
+				true : false;
+
+	return output_address_error;
+}
+
+int e5010_hw_enable_picture_done_irq(void __iomem *core_base, u32 enable)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_INTERRUPT_MASK_OFFSET,
+				       JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_MASK,
+				       JASPER_INTERRUPT_MASK_CR_PICTURE_DONE_ENABLE_SHIFT,
+				       enable);
+	return ret;
+}
+
+int e5010_hw_enable_auto_clock_gating(void __iomem *core_base, u32 enable)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_CLK_CONTROL_OFFSET,
+				       JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_MASK,
+				       JASPER_CLK_CONTROL_CR_JASPER_AUTO_CLKG_ENABLE_SHIFT,
+				       enable);
+	return ret;
+}
+
+int e5010_hw_enable_manual_clock_gating(void __iomem *core_base, u32 enable)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_CLK_CONTROL_OFFSET,
+				       JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_MASK,
+				       JASPER_CLK_CONTROL_CR_JASPER_MAN_CLKG_ENABLE_SHIFT, 0);
+	return ret;
+}
+
+int e5010_hw_enable_crc_check(void __iomem *core_base, u32 enable)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_CRC_CTRL_OFFSET,
+				       JASPER_CRC_CTRL_JASPER_CRC_ENABLE_MASK,
+				       JASPER_CRC_CTRL_JASPER_CRC_ENABLE_SHIFT, enable);
+	return ret;
+}
+
+int e5010_hw_set_input_source_to_memory(void __iomem *core_base, u32 set)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_INPUT_CTRL0_OFFSET,
+				       JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_MASK,
+				       JASPER_INPUT_CTRL0_CR_INPUT_SOURCE_SHIFT, set);
+	return ret;
+}
+
+int e5010_hw_set_input_luma_addr(void __iomem *core_base, u32 val)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       INPUT_LUMA_BASE_OFFSET,
+				       INPUT_LUMA_BASE_CR_INPUT_LUMA_BASE_MASK, 0, val);
+	return ret;
+}
+
+int e5010_hw_set_input_chroma_addr(void __iomem *core_base, u32 val)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       INPUT_CHROMA_BASE_OFFSET,
+				       INPUT_CHROMA_BASE_CR_INPUT_CHROMA_BASE_MASK, 0, val);
+	return ret;
+}
+
+int e5010_hw_set_output_base_addr(void __iomem *core_base, u32 val)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_OUTPUT_BASE_OFFSET,
+				       JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_MASK,
+				       JASPER_OUTPUT_BASE_CR_OUTPUT_BASE_SHIFT, val);
+	return ret;
+}
+
+int e5010_hw_set_horizontal_size(void __iomem *core_base, u32 val)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_IMAGE_SIZE_OFFSET,
+				       JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_MASK,
+				       JASPER_IMAGE_SIZE_CR_IMAGE_HORIZONTAL_SIZE_SHIFT,
+				       val);
+	return ret;
+}
+
+int e5010_hw_set_vertical_size(void __iomem *core_base, u32 val)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_IMAGE_SIZE_OFFSET,
+				       JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_MASK,
+				       JASPER_IMAGE_SIZE_CR_IMAGE_VERTICAL_SIZE_SHIFT,
+				       val);
+	return ret;
+}
+
+int e5010_hw_set_luma_stride(void __iomem *core_base, u32 bytesperline)
+{
+	int ret;
+	u32 val = bytesperline / 64;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_INPUT_CTRL1_OFFSET,
+				       JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_MASK,
+				       JASPER_INPUT_CTRL1_CR_INPUT_LUMA_STRIDE_SHIFT,
+				       val);
+	return ret;
+}
+
+int e5010_hw_set_chroma_stride(void __iomem *core_base, u32 bytesperline)
+{
+	int ret;
+	u32 val = bytesperline / 64;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_INPUT_CTRL1_OFFSET,
+				       JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_MASK,
+				       JASPER_INPUT_CTRL1_CR_INPUT_CHROMA_STRIDE_SHIFT,
+				       val);
+	return ret;
+}
+
+int e5010_hw_set_input_subsampling(void __iomem *core_base, u32 val)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_INPUT_CTRL0_OFFSET,
+				       JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_MASK,
+				       JASPER_INPUT_CTRL0_CR_INPUT_SUBSAMPLING_SHIFT,
+				       val);
+	return ret;
+}
+
+int e5010_hw_set_chroma_order(void __iomem *core_base, u32 val)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base,
+				       JASPER_INPUT_CTRL0_OFFSET,
+				       JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_MASK,
+				       JASPER_INPUT_CTRL0_CR_INPUT_CHROMA_ORDER_SHIFT,
+				       val);
+	return ret;
+}
+
+void e5010_hw_set_output_max_size(void __iomem *core_base, u32 val)
+{
+	write_reg_field(core_base, JASPER_OUTPUT_MAX_SIZE_OFFSET,
+			JASPER_OUTPUT_MAX_SIZE_CR_OUTPUT_MAX_SIZE_MASK,
+			JASPER_OUTPUT_MAX_SIZE_CR_OUTPUT_MAX_SIZE_SHIFT,
+			val);
+}
+
+int e5010_hw_set_qpvalue(void __iomem *core_base, u32 offset, u32 val)
+{
+	int ret;
+
+	ret = write_reg_field_not_busy(core_base, core_base, offset, 0xffffffff, 0, val);
+	return ret;
+}
+
+void e5010_hw_clear_output_error(void __iomem *core_base, u32 clear)
+{
+	/* Make sure interrupts are clear */
+	write_reg_field(core_base, JASPER_INTERRUPT_CLEAR_OFFSET,
+			JASPER_INTERRUPT_CLEAR_CR_OUTPUT_ERROR_CLEAR_MASK,
+			JASPER_INTERRUPT_CLEAR_CR_OUTPUT_ERROR_CLEAR_SHIFT, clear);
+}
+
+void e5010_hw_clear_picture_done(void __iomem *core_base, u32 clear)
+{
+	write_reg_field(core_base,
+			JASPER_INTERRUPT_CLEAR_OFFSET,
+			JASPER_INTERRUPT_CLEAR_CR_PICTURE_DONE_CLEAR_MASK,
+			JASPER_INTERRUPT_CLEAR_CR_PICTURE_DONE_CLEAR_SHIFT, clear);
+}
+
+int e5010_hw_get_output_size(void __iomem *core_base)
+{
+	return readl(core_base + JASPER_OUTPUT_SIZE_OFFSET);
+}
+
+void e5010_hw_encode_start(void __iomem *core_base, u32 start)
+{
+	write_reg_field(core_base, JASPER_CORE_CTRL_OFFSET,
+			JASPER_CORE_CTRL_CR_JASPER_ENCODE_START_MASK,
+			JASPER_CORE_CTRL_CR_JASPER_ENCODE_START_SHIFT, start);
+}
+
diff -Naur --no-dereference a/drivers/media/platform/img/e5010/e5010-jpeg-enc-hw.h b/drivers/media/platform/img/e5010/e5010-jpeg-enc-hw.h
--- a/drivers/media/platform/img/e5010/e5010-jpeg-enc-hw.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/e5010/e5010-jpeg-enc-hw.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * TI E5010 JPEG Encoder driver.
+ *
+ * Copyright (c) 2023 Texas Instruments Inc.
+ * Author: David Huang <d-huang@ti.com>
+ * Author: Devarsh Thakkar <devarsht@ti.com>
+ */
+
+#ifndef _E5010_JPEG_ENC_HW_H
+#define _E5010_JPEG_ENC_HW_H
+
+#include "e5010-core-regs.h"
+#include "e5010-mmu-regs.h"
+
+int e5010_hw_enable_output_address_error_irq(void __iomem *core_offset, u32 enable);
+int e5010_hw_enable_picture_done_irq(void __iomem *core_offset, u32 enable);
+int e5010_hw_enable_auto_clock_gating(void __iomem *core_offset, u32 enable);
+int e5010_hw_enable_manual_clock_gating(void __iomem *core_offset, u32 enable);
+int e5010_hw_enable_crc_check(void __iomem *core_offset, u32 enable);
+int e5010_hw_set_input_source_to_memory(void __iomem *core_offset, u32 set);
+int e5010_hw_set_input_luma_addr(void __iomem *core_offset, u32 val);
+int e5010_hw_set_input_chroma_addr(void __iomem *core_offset, u32 val);
+int e5010_hw_set_output_base_addr(void __iomem *core_offset, u32 val);
+int e5010_hw_get_output_size(void __iomem *core_offset);
+int e5010_hw_set_horizontal_size(void __iomem *core_offset, u32 val);
+int e5010_hw_set_vertical_size(void __iomem *core_offset, u32 val);
+int e5010_hw_set_luma_stride(void __iomem *core_offset, u32 bytesperline);
+int e5010_hw_set_chroma_stride(void __iomem *core_offset, u32 bytesperline);
+int e5010_hw_set_input_subsampling(void __iomem *core_offset, u32 val);
+int e5010_hw_set_chroma_order(void __iomem *core_offset, u32 val);
+int e5010_hw_set_qpvalue(void __iomem *core_offset, u32 offset, u32 value);
+void e5010_reset(struct device *dev, void __iomem *core_offset, void __iomem *mmu_offset);
+void e5010_hw_set_output_max_size(void __iomem *core_offset, u32 val);
+void e5010_hw_clear_picture_done(void __iomem *core_offset, u32 clear);
+void e5010_hw_encode_start(void __iomem *core_offset, u32 start);
+void e5010_hw_clear_output_error(void __iomem *core_offset, u32 clear);
+void e5010_hw_bypass_mmu(void __iomem *mmu_base, u32 enable);
+bool e5010_hw_pic_done_irq(void __iomem *core_base);
+bool e5010_hw_output_address_irq(void __iomem *core_base);
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/e5010/e5010-mmu-regs.h b/drivers/media/platform/img/e5010/e5010-mmu-regs.h
--- a/drivers/media/platform/img/e5010/e5010-mmu-regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/e5010/e5010-mmu-regs.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,303 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _E5010_MMU_REGS_H
+#define _E5010_MMU_REGS_H
+
+#define MMU_MMU_DIR_BASE_ADDR_OFFSET					(0x0020)
+#define MMU_MMU_DIR_BASE_ADDR_STRIDE					(4)
+#define MMU_MMU_DIR_BASE_ADDR_NO_ENTRIES				(4)
+
+#define MMU_MMU_DIR_BASE_ADDR_MMU_DIR_BASE_ADDR_MASK			(0xFFFFFFFF)
+#define MMU_MMU_DIR_BASE_ADDR_MMU_DIR_BASE_ADDR_SHIFT			(0)
+
+#define MMU_MMU_TILE_CFG_OFFSET						(0x0040)
+#define MMU_MMU_TILE_CFG_STRIDE						(4)
+#define MMU_MMU_TILE_CFG_NO_ENTRIES					(4)
+
+#define MMU_MMU_TILE_CFG_TILE_128INTERLEAVE_MASK			(0x00000010)
+#define MMU_MMU_TILE_CFG_TILE_128INTERLEAVE_SHIFT			(4)
+
+#define MMU_MMU_TILE_CFG_TILE_ENABLE_MASK				(0x00000008)
+#define MMU_MMU_TILE_CFG_TILE_ENABLE_SHIFT				(3)
+
+#define MMU_MMU_TILE_CFG_TILE_STRIDE_MASK				(0x00000007)
+#define MMU_MMU_TILE_CFG_TILE_STRIDE_SHIFT				(0)
+
+#define MMU_MMU_TILE_MIN_ADDR_OFFSET					(0x0050)
+#define MMU_MMU_TILE_MIN_ADDR_STRIDE					(4)
+#define MMU_MMU_TILE_MIN_ADDR_NO_ENTRIES				(4)
+
+#define MMU_MMU_TILE_MIN_ADDR_TILE_MIN_ADDR_MASK			(0xFFFFFFFF)
+#define MMU_MMU_TILE_MIN_ADDR_TILE_MIN_ADDR_SHIFT			(0)
+
+#define MMU_MMU_TILE_MAX_ADDR_OFFSET					(0x0060)
+#define MMU_MMU_TILE_MAX_ADDR_STRIDE					(4)
+#define MMU_MMU_TILE_MAX_ADDR_NO_ENTRIES				(4)
+
+#define MMU_MMU_TILE_MAX_ADDR_TILE_MAX_ADDR_MASK			(0xFFFFFFFF)
+#define MMU_MMU_TILE_MAX_ADDR_TILE_MAX_ADDR_SHIFT			(0)
+
+#define MMU_MMU_CONTROL0_OFFSET						(0x0000)
+
+#define MMU_MMU_CONTROL0_MMU_TILING_SCHEME_MASK				(0x00000001)
+#define MMU_MMU_CONTROL0_MMU_TILING_SCHEME_SHIFT			(0)
+
+#define MMU_MMU_CONTROL0_MMU_CACHE_POLICY_MASK				(0x00000100)
+#define MMU_MMU_CONTROL0_MMU_CACHE_POLICY_SHIFT				(8)
+
+#define MMU_MMU_CONTROL0_FORCE_CACHE_POLICY_BYPASS_MASK			(0x00000200)
+#define MMU_MMU_CONTROL0_FORCE_CACHE_POLICY_BYPASS_SHIFT		(9)
+
+#define MMU_MMU_CONTROL0_STALL_ON_PROTOCOL_FAULT_MASK			(0x00001000)
+#define MMU_MMU_CONTROL0_STALL_ON_PROTOCOL_FAULT_SHIFT			(12)
+
+#define MMU_MMU_CONTROL1_OFFSET						(0x0008)
+
+#define MMU_MMU_CONTROL1_MMU_FLUSH_MASK					(0x00000008)
+#define MMU_MMU_CONTROL1_MMU_FLUSH_SHIFT				(3)
+#define MMU_MMU_CONTROL1_MMU_FLUSH_NO_REPS				(4)
+#define MMU_MMU_CONTROL1_MMU_FLUSH_SIZE					(1)
+
+#define MMU_MMU_CONTROL1_MMU_INVALDC_MASK				(0x00000800)
+#define MMU_MMU_CONTROL1_MMU_INVALDC_SHIFT				(11)
+#define MMU_MMU_CONTROL1_MMU_INVALDC_NO_REPS				(4)
+#define MMU_MMU_CONTROL1_MMU_INVALDC_SIZE				(1)
+
+#define MMU_MMU_CONTROL1_MMU_FAULT_CLEAR_MASK				(0x00010000)
+#define MMU_MMU_CONTROL1_MMU_FAULT_CLEAR_SHIFT				(16)
+
+#define MMU_MMU_CONTROL1_PROTOCOL_FAULT_CLEAR_MASK			(0x00100000)
+#define MMU_MMU_CONTROL1_PROTOCOL_FAULT_CLEAR_SHIFT			(20)
+
+#define MMU_MMU_CONTROL1_MMU_PAUSE_SET_MASK				(0x01000000)
+#define MMU_MMU_CONTROL1_MMU_PAUSE_SET_SHIFT				(24)
+
+#define MMU_MMU_CONTROL1_MMU_PAUSE_CLEAR_MASK				(0x02000000)
+#define MMU_MMU_CONTROL1_MMU_PAUSE_CLEAR_SHIFT				(25)
+
+#define MMU_MMU_CONTROL1_MMU_SOFT_RESET_MASK				(0x10000000)
+#define MMU_MMU_CONTROL1_MMU_SOFT_RESET_SHIFT				(28)
+
+#define MMU_MMU_BANK_INDEX_OFFSET					(0x0010)
+
+#define MMU_MMU_BANK_INDEX_MMU_BANK_INDEX_MASK				(0xC0000000)
+#define MMU_MMU_BANK_INDEX_MMU_BANK_INDEX_SHIFT				(30)
+#define MMU_MMU_BANK_INDEX_MMU_BANK_INDEX_NO_REPS			(16)
+#define MMU_MMU_BANK_INDEX_MMU_BANK_INDEX_SIZE				(2)
+
+#define MMU_REQUEST_PRIORITY_ENABLE_OFFSET				(0x0018)
+
+#define MMU_REQUEST_PRIORITY_ENABLE_CMD_PRIORITY_ENABLE_MASK		(0x00008000)
+#define MMU_REQUEST_PRIORITY_ENABLE_CMD_PRIORITY_ENABLE_SHIFT		(15)
+#define MMU_REQUEST_PRIORITY_ENABLE_CMD_PRIORITY_ENABLE_NO_REPS		(16)
+#define MMU_REQUEST_PRIORITY_ENABLE_CMD_PRIORITY_ENABLE_SIZE		(1)
+
+#define MMU_REQUEST_PRIORITY_ENABLE_CMD_MMU_PRIORITY_ENABLE_MASK	(0x00010000)
+#define MMU_REQUEST_PRIORITY_ENABLE_CMD_MMU_PRIORITY_ENABLE_SHIFT	(16)
+
+#define MMU_REQUEST_LIMITED_THROUGHPUT_OFFSET				(0x001C)
+
+#define MMU_REQUEST_LIMITED_THROUGHPUT_LIMITED_WORDS_MASK		(0x000003FF)
+#define MMU_REQUEST_LIMITED_THROUGHPUT_LIMITED_WORDS_SHIFT		(0)
+
+#define MMU_REQUEST_LIMITED_THROUGHPUT_REQUEST_GAP_MASK			(0x0FFF0000)
+#define MMU_REQUEST_LIMITED_THROUGHPUT_REQUEST_GAP_SHIFT		(16)
+
+#define MMU_MMU_ADDRESS_CONTROL_OFFSET					(0x0070)
+#define MMU_MMU_ADDRESS_CONTROL_TRUSTED					(IMG_TRUE)
+
+#define MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_MASK				(0x00000001)
+#define MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_SHIFT			(0)
+
+#define MMU_MMU_ADDRESS_CONTROL_MMU_ENABLE_EXT_ADDRESSING_MASK		(0x00000010)
+#define MMU_MMU_ADDRESS_CONTROL_MMU_ENABLE_EXT_ADDRESSING_SHIFT		(4)
+
+#define MMU_MMU_ADDRESS_CONTROL_UPPER_ADDRESS_FIXED_MASK		(0x00FF0000)
+#define MMU_MMU_ADDRESS_CONTROL_UPPER_ADDRESS_FIXED_SHIFT		(16)
+
+#define MMU_MMU_CONFIG0_OFFSET						(0x0080)
+
+#define MMU_MMU_CONFIG0_NUM_REQUESTORS_MASK				(0x0000000F)
+#define MMU_MMU_CONFIG0_NUM_REQUESTORS_SHIFT				(0)
+
+#define MMU_MMU_CONFIG0_EXTENDED_ADDR_RANGE_MASK			(0x000000F0)
+#define MMU_MMU_CONFIG0_EXTENDED_ADDR_RANGE_SHIFT			(4)
+
+#define MMU_MMU_CONFIG0_GROUP_OVERRIDE_SIZE_MASK			(0x00000700)
+#define MMU_MMU_CONFIG0_GROUP_OVERRIDE_SIZE_SHIFT			(8)
+
+#define MMU_MMU_CONFIG0_ADDR_COHERENCY_SUPPORTED_MASK			(0x00001000)
+#define MMU_MMU_CONFIG0_ADDR_COHERENCY_SUPPORTED_SHIFT			(12)
+
+#define MMU_MMU_CONFIG0_MMU_SUPPORTED_MASK				(0x00002000)
+#define MMU_MMU_CONFIG0_MMU_SUPPORTED_SHIFT				(13)
+
+#define MMU_MMU_CONFIG0_TILE_ADDR_GRANULARITY_MASK			(0x001F0000)
+#define MMU_MMU_CONFIG0_TILE_ADDR_GRANULARITY_SHIFT			(16)
+
+#define MMU_MMU_CONFIG0_NO_READ_REORDER_MASK				(0x00200000)
+#define MMU_MMU_CONFIG0_NO_READ_REORDER_SHIFT				(21)
+
+#define MMU_MMU_CONFIG0_TAGS_SUPPORTED_MASK				(0xFFC00000)
+#define MMU_MMU_CONFIG0_TAGS_SUPPORTED_SHIFT				(22)
+
+#define MMU_MMU_CONFIG1_OFFSET						(0x0084)
+
+#define MMU_MMU_CONFIG1_PAGE_SIZE_MASK					(0x0000000F)
+#define MMU_MMU_CONFIG1_PAGE_SIZE_SHIFT					(0)
+
+#define MMU_MMU_CONFIG1_PAGE_CACHE_ENTRIES_MASK				(0x0000FF00)
+#define MMU_MMU_CONFIG1_PAGE_CACHE_ENTRIES_SHIFT			(8)
+
+#define MMU_MMU_CONFIG1_DIR_CACHE_ENTRIES_MASK				(0x001F0000)
+#define MMU_MMU_CONFIG1_DIR_CACHE_ENTRIES_SHIFT				(16)
+
+#define MMU_MMU_CONFIG1_BANDWIDTH_COUNT_SUPPORTED_MASK			(0x01000000)
+#define MMU_MMU_CONFIG1_BANDWIDTH_COUNT_SUPPORTED_SHIFT			(24)
+
+#define MMU_MMU_CONFIG1_STALL_COUNT_SUPPORTED_MASK			(0x02000000)
+#define MMU_MMU_CONFIG1_STALL_COUNT_SUPPORTED_SHIFT			(25)
+
+#define MMU_MMU_CONFIG1_LATENCY_COUNT_SUPPORTED_MASK			(0x04000000)
+#define MMU_MMU_CONFIG1_LATENCY_COUNT_SUPPORTED_SHIFT			(26)
+
+#define MMU_MMU_STATUS0_OFFSET						(0x0088)
+
+#define MMU_MMU_STATUS0_MMU_PF_N_RW_MASK				(0x00000001)
+#define MMU_MMU_STATUS0_MMU_PF_N_RW_SHIFT				(0)
+
+#define MMU_MMU_STATUS0_MMU_FAULT_ADDR_MASK				(0xFFFFF000)
+#define MMU_MMU_STATUS0_MMU_FAULT_ADDR_SHIFT				(12)
+
+#define MMU_MMU_STATUS1_OFFSET						(0x008C)
+
+#define MMU_MMU_STATUS1_MMU_FAULT_REQ_STAT_MASK				(0x0000FFFF)
+#define MMU_MMU_STATUS1_MMU_FAULT_REQ_STAT_SHIFT			(0)
+
+#define MMU_MMU_STATUS1_MMU_FAULT_REQ_ID_MASK				(0x000F0000)
+#define MMU_MMU_STATUS1_MMU_FAULT_REQ_ID_SHIFT				(16)
+
+#define MMU_MMU_STATUS1_MMU_FAULT_INDEX_MASK				(0x03000000)
+#define MMU_MMU_STATUS1_MMU_FAULT_INDEX_SHIFT				(24)
+
+#define MMU_MMU_STATUS1_MMU_FAULT_RNW_MASK				(0x10000000)
+#define MMU_MMU_STATUS1_MMU_FAULT_RNW_SHIFT				(28)
+
+#define MMU_MMU_MEM_REQ_OFFSET						(0x0090)
+
+#define MMU_MMU_MEM_REQ_TAG_OUTSTANDING_MASK				(0x000003FF)
+#define MMU_MMU_MEM_REQ_TAG_OUTSTANDING_SHIFT				(0)
+
+#define MMU_MMU_MEM_REQ_EXT_WRRESP_FAULT_MASK				(0x00001000)
+#define MMU_MMU_MEM_REQ_EXT_WRRESP_FAULT_SHIFT				(12)
+
+#define MMU_MMU_MEM_REQ_EXT_RDRESP_FAULT_MASK				(0x00002000)
+#define MMU_MMU_MEM_REQ_EXT_RDRESP_FAULT_SHIFT				(13)
+
+#define MMU_MMU_MEM_REQ_EXT_READ_BURST_FAULT_MASK			(0x00004000)
+#define MMU_MMU_MEM_REQ_EXT_READ_BURST_FAULT_SHIFT			(14)
+
+#define MMU_MMU_MEM_REQ_INT_PROTOCOL_FAULT_MASK				(0x80000000)
+#define MMU_MMU_MEM_REQ_INT_PROTOCOL_FAULT_SHIFT			(31)
+#define MMU_MMU_MEM_REQ_INT_PROTOCOL_FAULT_NO_REPS			(16)
+#define MMU_MMU_MEM_REQ_INT_PROTOCOL_FAULT_SIZE				(1)
+
+#define MMU_MMU_FAULT_SELECT_OFFSET					(0x00A0)
+
+#define MMU_MMU_FAULT_SELECT_MMU_FAULT_SELECT_MASK			(0x0000000F)
+#define MMU_MMU_FAULT_SELECT_MMU_FAULT_SELECT_SHIFT			(0)
+
+#define MMU_PROTOCOL_FAULT_OFFSET					(0x00A8)
+
+#define MMU_PROTOCOL_FAULT_FAULT_PAGE_BREAK_MASK			(0x00000001)
+#define MMU_PROTOCOL_FAULT_FAULT_PAGE_BREAK_SHIFT			(0)
+
+#define MMU_PROTOCOL_FAULT_FAULT_WRITE_MASK				(0x00000010)
+#define MMU_PROTOCOL_FAULT_FAULT_WRITE_SHIFT				(4)
+
+#define MMU_PROTOCOL_FAULT_FAULT_READ_MASK				(0x00000020)
+#define MMU_PROTOCOL_FAULT_FAULT_READ_SHIFT				(5)
+
+#define MMU_TOTAL_READ_REQ_OFFSET					(0x0100)
+
+#define MMU_TOTAL_READ_REQ_TOTAL_READ_REQ_MASK				(0xFFFFFFFF)
+#define MMU_TOTAL_READ_REQ_TOTAL_READ_REQ_SHIFT				(0)
+
+#define MMU_TOTAL_WRITE_REQ_OFFSET					(0x0104)
+
+#define MMU_TOTAL_WRITE_REQ_TOTAL_WRITE_REQ_MASK			(0xFFFFFFFF)
+#define MMU_TOTAL_WRITE_REQ_TOTAL_WRITE_REQ_SHIFT			(0)
+
+#define MMU_READS_LESS_64_REQ_OFFSET					(0x0108)
+
+#define MMU_READS_LESS_64_REQ_READS_LESS_64_REQ_MASK			(0xFFFFFFFF)
+#define MMU_READS_LESS_64_REQ_READS_LESS_64_REQ_SHIFT			(0)
+
+#define MMU_WRITES_LESS_64_REQ_OFFSET					(0x010C)
+
+#define MMU_WRITES_LESS_64_REQ_WRITES_LESS_64_REQ_MASK			(0xFFFFFFFF)
+#define MMU_WRITES_LESS_64_REQ_WRITES_LESS_64_REQ_SHIFT			(0)
+
+#define MMU_EXT_CMD_STALL_OFFSET					(0x0120)
+
+#define MMU_EXT_CMD_STALL_EXT_CMD_STALL_MASK				(0xFFFFFFFF)
+#define MMU_EXT_CMD_STALL_EXT_CMD_STALL_SHIFT				(0)
+
+#define MMU_WRITE_REQ_STALL_OFFSET					(0x0124)
+
+#define MMU_WRITE_REQ_STALL_WRITE_REQ_STALL_MASK			(0xFFFFFFFF)
+#define MMU_WRITE_REQ_STALL_WRITE_REQ_STALL_SHIFT			(0)
+
+#define MMU_MMU_MISS_STALL_OFFSET					(0x0128)
+
+#define MMU_MMU_MISS_STALL_MMU_MISS_STALL_MASK				(0xFFFFFFFF)
+#define MMU_MMU_MISS_STALL_MMU_MISS_STALL_SHIFT				(0)
+
+#define MMU_ADDRESS_STALL_OFFSET					(0x012C)
+
+#define MMU_ADDRESS_STALL_ADDRESS_STALL_MASK				(0xFFFFFFFF)
+#define MMU_ADDRESS_STALL_ADDRESS_STALL_SHIFT				(0)
+
+#define MMU_TAG_STALL_OFFSET						(0x0130)
+
+#define MMU_TAG_STALL_TAG_STALL_MASK					(0xFFFFFFFF)
+#define MMU_TAG_STALL_TAG_STALL_SHIFT					(0)
+
+#define MMU_PEAK_READ_OUTSTANDING_OFFSET				(0x0140)
+
+#define MMU_PEAK_READ_OUTSTANDING_PEAK_TAG_OUTSTANDING_MASK		(0x000003FF)
+#define MMU_PEAK_READ_OUTSTANDING_PEAK_TAG_OUTSTANDING_SHIFT		(0)
+
+#define MMU_PEAK_READ_OUTSTANDING_PEAK_READ_LATENCY_MASK		(0xFFFF0000)
+#define MMU_PEAK_READ_OUTSTANDING_PEAK_READ_LATENCY_SHIFT		(16)
+
+#define MMU_AVERAGE_READ_LATENCY_OFFSET					(0x0144)
+
+#define MMU_AVERAGE_READ_LATENCY_AVERAGE_READ_LATENCY_MASK		(0xFFFFFFFF)
+#define MMU_AVERAGE_READ_LATENCY_AVERAGE_READ_LATENCY_SHIFT		(0)
+
+#define MMU_STATISTICS_CONTROL_OFFSET					(0x0160)
+
+#define MMU_STATISTICS_CONTROL_BANDWIDTH_STATS_INIT_MASK		(0x00000001)
+#define MMU_STATISTICS_CONTROL_BANDWIDTH_STATS_INIT_SHIFT		(0)
+
+#define MMU_STATISTICS_CONTROL_STALL_STATS_INIT_MASK			(0x00000002)
+#define MMU_STATISTICS_CONTROL_STALL_STATS_INIT_SHIFT			(1)
+
+#define MMU_STATISTICS_CONTROL_LATENCY_STATS_INIT_MASK			(0x00000004)
+#define MMU_STATISTICS_CONTROL_LATENCY_STATS_INIT_SHIFT			(2)
+
+#define MMU_MMU_VERSION_OFFSET						(0x01D0)
+
+#define MMU_MMU_VERSION_MMU_MAJOR_REV_MASK				(0x00FF0000)
+#define MMU_MMU_VERSION_MMU_MAJOR_REV_SHIFT				(16)
+
+#define MMU_MMU_VERSION_MMU_MINOR_REV_MASK				(0x0000FF00)
+#define MMU_MMU_VERSION_MMU_MINOR_REV_SHIFT				(8)
+
+#define MMU_MMU_VERSION_MMU_MAINT_REV_MASK				(0x000000FF)
+#define MMU_MMU_VERSION_MMU_MAINT_REV_SHIFT				(0)
+
+#define MMU_BYTE_SIZE							(0x01D4)
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/e5010/Kconfig b/drivers/media/platform/img/e5010/Kconfig
--- a/drivers/media/platform/img/e5010/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/e5010/Kconfig	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+config VIDEO_E5010_JPEG_ENC
+	tristate "Imagination E5010 JPEG Encoder Driver"
+	depends on VIDEO_DEV
+	depends on ARCH_K3 || COMPILE_TEST
+	select VIDEOBUF2_DMA_CONTIG
+	select VIDEOBUF2_VMALLOC
+	select V4L2_MEM2MEM_DEV
+	help
+	  This is a video4linux2 M2M driver for Imagination E5010 JPEG encoder,
+	  which supports JPEG and MJPEG baseline encoding of YUV422 and YUV420
+	  semiplanar video formats, with resolution ranging from 64x64 to 8K x 8K
+	  pixels. The module will be named as e5010_jpeg_enc.
diff -Naur --no-dereference a/drivers/media/platform/img/e5010/Makefile b/drivers/media/platform/img/e5010/Makefile
--- a/drivers/media/platform/img/e5010/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/e5010/Makefile	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+e5010_jpeg_enc-objs := e5010-jpeg-enc-hw.o e5010-jpeg-enc.o
+obj-$(CONFIG_VIDEO_E5010_JPEG_ENC) += e5010_jpeg_enc.o
diff -Naur --no-dereference a/drivers/media/platform/img/Kconfig b/drivers/media/platform/img/Kconfig
--- a/drivers/media/platform/img/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/Kconfig	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,37 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+comment "IMG media platform drivers"
+
+config VIDEO_IMG_VXD_DEC
+  tristate "IMG VXD DEC (Video Decoder) driver"
+	depends on V4L_MEM2MEM_DRIVERS
+  depends on VIDEO_DEV
+  depends on ARCH_K3 || COMPILE_TEST
+  depends on V4L_PLATFORM_DRIVERS
+  select VIDEOBUF2_CORE
+  select VIDEOBUF2_DMA_CONTIG
+  select VIDEOBUF2_DMA_SG
+  select V4L2_MEM2MEM_DEV
+  help
+    This is an IMG VXD DEC V4L2 driver that adds support for the
+    Imagination D5520 (Video Decoder) hardware as used on the Texas
+    Instruments Jacinto and Sitara devices.
+    The module name when built is vxd-dec.
+
+config VIDEO_IMG_VXE_ENC
+  tristate "IMG VXE ENC (Video Encoder) driver"
+	depends on V4L_MEM2MEM_DRIVERS
+  depends on VIDEO_DEV
+  depends on ARCH_K3 || COMPILE_TEST
+  depends on V4L_PLATFORM_DRIVERS
+  select VIDEOBUF2_CORE
+  select VIDEOBUF2_DMA_CONTIG
+  select VIDEOBUF2_DMA_SG
+  select V4L2_MEM2MEM_DEV
+  help
+    This is an IMG VXE ENC V4L2 driver that adds support for the
+    Imagination VXE384 (Video Encoder) hardware as used on the Texas
+    Instruments Jacinto and Sitara devices.
+    The module name when built is vxe-enc.
+
+source "drivers/media/platform/img/e5010/Kconfig"
diff -Naur --no-dereference a/drivers/media/platform/img/Makefile b/drivers/media/platform/img/Makefile
--- a/drivers/media/platform/img/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/Makefile	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += vxe-vxd/ e5010/
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/addr_alloc.c b/drivers/media/platform/img/vxe-vxd/common/addr_alloc.c
--- a/drivers/media/platform/img/vxe-vxd/common/addr_alloc.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/addr_alloc.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,499 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Address allocation APIs - used to manage address allocation
+ * with a number of predefined regions.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/slab.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "addr_alloc.h"
+#include "hash.h"
+#include "img_errors.h"
+
+/* Global context. */
+static struct addr_context global_ctx = {0};
+/* Sub-system initialized. */
+static int global_initialized;
+/* Count of contexts. */
+static unsigned int num_ctx;
+/* Global mutex */
+static struct mutex *global_lock;
+
+/**
+ * addr_initialise - addr_initialise
+ */
+
+int addr_initialise(void)
+{
+	unsigned int result = IMG_ERROR_ALREADY_INITIALISED;
+
+	/* If we are not initialized */
+	if (!global_initialized)
+		result = addr_cx_initialise(&global_ctx);
+	return result;
+}
+
+int addr_cx_initialise(struct addr_context * const context)
+{
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!context)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (!global_initialized) {
+		/* Initialise context */
+		memset(context, 0x00, sizeof(struct addr_context));
+
+		/* If no mutex associated with this resource */
+		if (!global_lock) {
+			/* Create one */
+
+			global_lock = kzalloc(sizeof(*global_lock), GFP_KERNEL);
+			if (!global_lock)
+				return -ENOMEM;
+
+			mutex_init(global_lock);
+		}
+
+		mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+		/* Initialise the hash functions. */
+		result = vid_hash_initialise();
+		if (result != IMG_SUCCESS) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+
+		/* Initialise the arena functions */
+		result = vid_ra_initialise();
+		if (result != IMG_SUCCESS) {
+			mutex_unlock(global_lock);
+			result = vid_hash_finalise();
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+
+		/* We are now initialized */
+		global_initialized = TRUE;
+		result = IMG_SUCCESS;
+	} else {
+		mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+	}
+
+	num_ctx++;
+	mutex_unlock(global_lock);
+
+	return result;
+}
+
+int addr_deinitialise(void)
+{
+	return addr_cx_deinitialise(&global_ctx);
+}
+
+int addr_cx_deinitialise(struct addr_context * const context)
+{
+	struct addr_region *tmp_region = NULL;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!context)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (global_initialized) {
+		mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+		tmp_region = context->regions;
+
+		/* Delete all arena structure */
+		if (context->default_region)
+			result = vid_ra_delete(context->default_region->arena);
+
+		while (tmp_region) {
+			result = vid_ra_delete(tmp_region->arena);
+			tmp_region = tmp_region->nxt_region;
+		}
+
+		if (num_ctx != 0)
+			num_ctx--;
+
+		result = IMG_SUCCESS;
+		if (num_ctx == 0) {
+			/* Free off resources */
+			result = vid_hash_finalise();
+			result = vid_ra_deinit();
+			global_initialized = FALSE;
+
+			mutex_unlock(global_lock);
+			mutex_destroy(global_lock);
+			kfree(global_lock);
+			global_lock = NULL;
+		} else {
+			mutex_unlock(global_lock);
+		}
+	}
+
+	return result;
+}
+
+int addr_define_mem_region(struct addr_region * const region)
+{
+	return addr_cx_define_mem_region(&global_ctx, region);
+}
+
+int addr_cx_define_mem_region(struct addr_context * const context,
+			      struct addr_region * const region)
+{
+	struct addr_region *tmp_region = NULL;
+	unsigned int result = IMG_SUCCESS;
+
+	if (!context || !region)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+	tmp_region = context->regions;
+
+	/* Ensure the link to the next is NULL */
+	region->nxt_region = NULL;
+
+	/* If this is the default memory region */
+	if (!region->name) {
+		/* Should not previously have been defined */
+		if (context->default_region) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+
+		context->default_region = region;
+		context->no_regions++;
+
+		/*
+		 * Create an arena for memory allocation
+		 * name of resource arena for debug
+		 * start of resource
+		 * size of resource
+		 * allocation quantum
+		 * import allocator
+		 * import deallocator
+		 * import handle
+		 */
+		result = vid_ra_create("memory",
+				       region->base_addr,
+				       region->size,
+				       1,
+				       NULL,
+				       NULL,
+				       NULL,
+				       &region->arena);
+
+		if (result != IMG_SUCCESS) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+	} else {
+		/*
+		 * Run down the list of existing named regions
+		 * to check if there is a region with this name
+		 */
+		while (tmp_region &&
+		       (strcmp(region->name, tmp_region->name) != 0) &&
+		       tmp_region->nxt_region) {
+			tmp_region = tmp_region->nxt_region;
+		}
+
+		/* If we have items in the list */
+		if (tmp_region) {
+			/*
+			 * Check we didn't stop because the name
+			 * clashes with one already defined.
+			 */
+
+			if (strcmp(region->name, tmp_region->name) == 0 ||
+			    tmp_region->nxt_region) {
+				mutex_unlock(global_lock);
+				return IMG_ERROR_UNEXPECTED_STATE;
+			}
+
+			/* Add to end of list */
+			tmp_region->nxt_region = region;
+		} else {
+			/* Add to head of list */
+			context->regions = region;
+		}
+
+		context->no_regions++;
+
+		/*
+		 * Create an arena for memory allocation
+		 * name of resource arena for debug
+		 * start of resource
+		 * size of resource
+		 * allocation quantum
+		 * import allocator
+		 * import deallocator
+		 * import handle
+		 */
+		result = vid_ra_create(region->name,
+				       region->base_addr,
+				       region->size,
+				       1,
+				       NULL,
+				       NULL,
+				       NULL,
+				       &region->arena);
+
+		if (result != IMG_SUCCESS) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+	}
+
+	mutex_unlock(global_lock);
+
+	/* Check the arean was created OK */
+	if (!region->arena)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	return result;
+}
+
+int addr_malloc(const unsigned char * const name,
+		unsigned long long size,
+		unsigned long long * const base_adr)
+{
+	return addr_cx_malloc(&global_ctx, name, size, base_adr);
+}
+
+int addr_cx_malloc(struct addr_context * const context,
+		   const unsigned char * const name,
+		   unsigned long long size,
+		   unsigned long long * const base_adr)
+{
+	unsigned int result = IMG_ERROR_FATAL;
+	struct addr_region *tmp_region = NULL;
+
+	if (!context || !base_adr || !name)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	*(base_adr) = (unsigned long long)-1LL;
+
+	mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+	tmp_region = context->regions;
+
+	/*
+	 * Run down the list of existing named
+	 * regions to locate this
+	 */
+	while (tmp_region && (strcmp(name, tmp_region->name) != 0) && (tmp_region->nxt_region))
+		tmp_region = tmp_region->nxt_region;
+
+	/* If there was no match. */
+	if (!tmp_region || (strcmp(name, tmp_region->name) != 0)) {
+		/* Use the default */
+		if (!context->default_region) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+
+		tmp_region = context->default_region;
+	}
+
+	if (!tmp_region) {
+		mutex_unlock(global_lock);
+		return IMG_ERROR_UNEXPECTED_STATE;
+	}
+
+	/* Allocate size + guard band */
+	result = vid_ra_alloc(tmp_region->arena,
+			      size + tmp_region->guard_band,
+			      NULL,
+			      NULL,
+			      SEQUENTIAL_ALLOCATION,
+			      1,
+			      base_adr);
+	if (result != IMG_SUCCESS) {
+		mutex_unlock(global_lock);
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	mutex_unlock(global_lock);
+
+	return result;
+}
+
+int addr_cx_malloc_res(struct addr_context * const context,
+		       const unsigned char * const name,
+		       unsigned long long size,
+		       unsigned long long * const base_adr)
+{
+	unsigned int result = IMG_ERROR_FATAL;
+	struct addr_region *tmp_region = NULL;
+
+	if (!context || !base_adr || !name)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+	tmp_region = context->regions;
+	/* If the allocation is for the default region */
+	/*
+	 * Run down the list of existing named
+	 * regions to locate this
+	 */
+	while (tmp_region && (strcmp(name, tmp_region->name) != 0) && (tmp_region->nxt_region))
+		tmp_region = tmp_region->nxt_region;
+
+	/* If there was no match. */
+	if (!tmp_region || (strcmp(name, tmp_region->name) != 0)) {
+		/* Use the default */
+		if (!context->default_region) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+		tmp_region = context->default_region;
+	}
+	if (!tmp_region) {
+		mutex_unlock(global_lock);
+		return IMG_ERROR_UNEXPECTED_STATE;
+	}
+	/* Allocate size + guard band */
+	result = vid_ra_alloc(tmp_region->arena, size + tmp_region->guard_band,
+			      NULL, NULL, SEQUENTIAL_ALLOCATION, 1, base_adr);
+	if (result != IMG_SUCCESS) {
+		mutex_unlock(global_lock);
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+	mutex_unlock(global_lock);
+
+	return result;
+}
+
+int addr_cx_malloc_align_res(struct addr_context * const context,
+			     const unsigned char * const name,
+			     unsigned long long size,
+			     unsigned long long alignment,
+			     unsigned long long * const base_adr)
+{
+	unsigned int result;
+	struct addr_region *tmp_region = NULL;
+
+	if (!context || !base_adr || !name)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+	tmp_region = context->regions;
+
+	/*
+	 * Run down the list of existing named
+	 * regions to locate this
+	 */
+	while (tmp_region &&
+	       (strcmp(name, tmp_region->name) != 0) &&
+	       (tmp_region->nxt_region)) {
+		tmp_region = tmp_region->nxt_region;
+	}
+	/* If there was no match. */
+	if (!tmp_region ||
+	    (strcmp(name, tmp_region->name) != 0)) {
+		/* Use the default */
+		if (!context->default_region) {
+			mutex_unlock(global_lock);
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+
+		tmp_region = context->default_region;
+	}
+
+	if (!tmp_region) {
+		mutex_unlock(global_lock);
+		return IMG_ERROR_UNEXPECTED_STATE;
+	}
+	/* Allocate size + guard band */
+	result = vid_ra_alloc(tmp_region->arena,
+			      size + tmp_region->guard_band,
+			      NULL,
+			      NULL,
+			      SEQUENTIAL_ALLOCATION,
+			      alignment,
+			      base_adr);
+	if (result != IMG_SUCCESS) {
+		mutex_unlock(global_lock);
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	mutex_unlock(global_lock);
+
+	return result;
+}
+
+int addr_free(const unsigned char * const name, unsigned long long addr)
+{
+	return addr_cx_free(&global_ctx, name, addr);
+}
+
+int addr_cx_free(struct addr_context * const context,
+		 const unsigned char * const name,
+		 unsigned long long addr)
+{
+	struct addr_region *tmp_region;
+	unsigned int result;
+
+	if (!context)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	tmp_region = context->regions;
+
+	mutex_lock_nested(global_lock, SUBCLASS_ADDR_ALLOC);
+
+	/* If the allocation is for the default region */
+	if (!name) {
+		if (!context->default_region) {
+			result = IMG_ERROR_INVALID_PARAMETERS;
+			goto error;
+		}
+		tmp_region = context->default_region;
+	} else {
+		/*
+		 * Run down the list of existing named
+		 * regions to locate this
+		 */
+		while (tmp_region &&
+		       (strcmp(name, tmp_region->name) != 0) &&
+		       tmp_region->nxt_region) {
+			tmp_region = tmp_region->nxt_region;
+		}
+
+		/* If there was no match */
+		if (!tmp_region || (strcmp(name, tmp_region->name) != 0)) {
+			/* Use the default */
+			if (!context->default_region) {
+				result = IMG_ERROR_INVALID_PARAMETERS;
+				goto error;
+			}
+			tmp_region = context->default_region;
+		}
+	}
+
+	/* Free the address */
+	result = vid_ra_free(tmp_region->arena, addr);
+
+error:
+	mutex_unlock(global_lock);
+	return result;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/addr_alloc.h b/drivers/media/platform/img/vxe-vxd/common/addr_alloc.h
--- a/drivers/media/platform/img/vxe-vxd/common/addr_alloc.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/addr_alloc.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,238 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Address allocation management API.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef __ADDR_ALLOC_H__
+#define __ADDR_ALLOC_H__
+
+#include <linux/types.h>
+#include "ra.h"
+
+/* Defines whether sequential or random allocation is used */
+enum {
+	SEQUENTIAL_ALLOCATION,
+	RANDOM_ALLOCATION,
+	RANDOM_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/**
+ * struct addr_region - Memory region structure
+ *@name: A pointer to a sring containing the name of the region.
+ *		NULL for the default memory region.
+ *@base_addr: The base address of the memory region.
+ *@size: The size of the memory region.
+ *@guard_band: The size of any guard band to be used.
+ *		Guard bands can be useful in separating block allocations
+ *		and allows the caller to detect erroneous accesses
+ *		into these areas.
+ *@nxt_region:Used internally by the ADDR API.A pointer used to point
+ *		to the next memory region.
+ *@arena: Used internally by the ADDR API. A to a structure used to
+ *		maintain and perform address allocation.
+ *
+ * This structure contains information about the memory region.
+ */
+struct addr_region {
+	unsigned char *name;
+	unsigned long long base_addr;
+	unsigned long long size;
+	unsigned int guard_band;
+	struct addr_region *nxt_region;
+	void *arena;
+};
+
+/*
+ * This structure contains the context for allocation.
+ *@regions: Pointer the first region in the list.
+ *@default_region: Pointer the default region.
+ *@no_regions: Number of regions currently available (including default)
+ */
+struct addr_context {
+	struct addr_region *regions;
+	struct addr_region *default_region;
+	unsigned int no_regions;
+};
+
+/*
+ * @Function	ADDR_Initialise
+ * @Description
+ * This function is used to initialise the address alocation sub-system.
+ * NOTE: This function may be called multiple times. The initialisation only
+ * happens the first time it is called.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_initialise(void);
+
+/*
+ * @Function	addr_deinitialise
+ * @Description
+ * This function is used to de-initialise the address alocation sub-system.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_deinitialise(void);
+
+/*
+ * @Function	addr_define_mem_region
+ * @Description
+ * This function is used define a memory region.
+ * NOTE: The region structure MUST be defined in static memory as this
+ * is retained and used by the ADDR sub-system.
+ * NOTE: Invalid parameters are trapped by asserts.
+ * @Input	region: A pointer to a region structure.
+ * @Return	IMG_RESULT  : IMG_SUCCESS or an error code.
+ */
+int addr_define_mem_region(struct addr_region * const region);
+
+/*
+ * @Function	addr_malloc
+ * @Description
+ * This function is used allocate space within a memory region.
+ * NOTE: Allocation failures or invalid parameters are trapped by asserts.
+ * @Input	name: Is a pointer the name of the memory region.
+ *		NULL can be used to allocate space from the
+ *		default memory region.
+ * @Input	size: The size (in bytes) of the allocation.
+ * @Output	base_adr : The address of the allocated space.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_malloc(const unsigned char *const name,
+		unsigned long long size,
+		unsigned long long *const base_adr);
+
+/*
+ * @Function	addr_free
+ * @Description
+ * This function is used free a previously allocate space within
+ * a memory region.
+ * NOTE: Invalid parameters are trapped by asserts.
+ * @Input	name: Is a pointer to the name of the memory region.
+ *		NULL is used to free space from the default memory region.
+ *@Input	addr: The address allocated.
+ *@Return	IMG_SUCCESS or an error code.
+ */
+int addr_free(const unsigned char * const name, unsigned long long addr);
+
+/*
+ * @Function	addr_cx_initialise
+ * @Description
+ * This function is used to initialise the address allocation sub-system with
+ * an external context structure.
+ * NOTE: This function should be call only once for the context.
+ * @Input	context : Pointer to context structure.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_initialise(struct addr_context * const context);
+
+/*
+ * @Function	addr_cx_deinitialise
+ * @Description
+ * This function is used to de-initialise the address allocation
+ * sub-system with an external context structure.
+ * @Input	context : Pointer to context structure.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_deinitialise(struct addr_context * const context);
+
+/*
+ * @Function	addr_cx_define_mem_region
+ * @Description
+ * This function is used define a memory region with an external
+ * context structure.
+ * NOTE: The region structure MUST be defined in static memory as this
+ * is retained and used by the ADDR sub-system.
+ * NOTE: Invalid parameters are trapped by asserts.
+ * @Input	context : Pointer to context structure.
+ * @Input	region : A pointer to a region structure.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_define_mem_region(struct addr_context *const context,
+			      struct addr_region *const region);
+
+/*
+ * @Function	addr_cx_malloc
+ * @Description
+ * This function is used allocate space within a memory region with
+ * an external context structure.
+ * NOTE: Allocation failures or invalid parameters are trapped by asserts.
+ * @Input	context : Pointer to context structure.
+ * @Input	name : Is a pointer the name of the memory region.
+ *		NULL can be used to allocate space from the
+ *		default memory region.
+ * @Input	size : The size (in bytes) of the allocation.
+ * @Output	base_adr : The address of the allocated space.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_malloc(struct addr_context * const context,
+		   const unsigned char *const name,
+		   unsigned long long size,
+		   unsigned long long *const base_adr);
+
+/*
+ * @Function	addr_cx_malloc_res
+ * @Description
+ * This function is used allocate space within a memory region with
+ * an external context structure.
+ * NOTE: Allocation failures are returned in IMG_RESULT, however invalid
+ * parameters are trapped by asserts.
+ * @Input	context : Pointer to context structure.
+ * @Input	name : Is a pointer the name of the memory region.
+ *		NULL can be used to allocate space from the
+ *		default memory region.
+ * @Input	size : The size (in bytes) of the allocation.
+ * @Input	base_adr : Pointer to the address of the allocated space.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_malloc_res(struct addr_context *const context,
+		       const unsigned char *const name,
+		       unsigned long long size,
+		       unsigned long long * const base_adr);
+
+/*
+ * @Function	addr_cx_malloc1_res
+ * @Description
+ * This function is used allocate space within a memory region with
+ * an external context structure.
+ * NOTE: Allocation failures are returned in IMG_RESULT, however invalid
+ * parameters are trapped by asserts.
+ * @Input	context : Pointer to context structure.
+ * @Input	name : Is a pointer the name of the memory region.
+ *		NULL can be used to allocate space from the
+ *		default memory region.
+ * @Input	size	: The size (in bytes) of the allocation.
+ * @Input	alignment : The required byte alignment (1, 2, 4, 8, 16 etc).
+ * @Input	base_adr : Pointer to the address of the allocated space.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_malloc_align_res(struct addr_context *const context,
+			     const unsigned char *const name,
+			     unsigned long long size,
+			     unsigned long long alignment,
+			     unsigned long long *const base_adr);
+
+/*
+ * @Function	addr_cx_free
+ * @Description
+ * This function is used free a previously allocate space within a memory region
+ * with an external context structure.
+ * NOTE: Invalid parameters are trapped by asserts.
+ * @Input	context : Pointer to context structure.
+ * @Input	name : Is a pointer the name of the memory region.
+ *		NULL is used to free space from the
+ *		default memory region.
+ * @Input	addr : The address allocated.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int addr_cx_free(struct addr_context *const context,
+		 const unsigned char *const name,
+		 unsigned long long addr);
+
+#endif /* __ADDR_ALLOC_H__	*/
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/dq.c b/drivers/media/platform/img/vxe-vxd/common/dq.c
--- a/drivers/media/platform/img/vxe-vxd/common/dq.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/dq.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,248 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Utility module for doubly linked queues.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "dq.h"
+#include "img_errors.h"
+
+void dq_init(struct dq_linkage_t *queue)
+{
+	queue->fwd = (struct dq_linkage_t *)queue;
+	queue->back = (struct dq_linkage_t *)queue;
+}
+
+void dq_addhead(struct dq_linkage_t *queue, void *item)
+{
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->fwd);
+
+	if (!((struct dq_linkage_t *)queue)->back ||
+	    !((struct dq_linkage_t *)queue)->fwd)
+		return;
+
+	((struct dq_linkage_t *)item)->back = (struct dq_linkage_t *)queue;
+	((struct dq_linkage_t *)item)->fwd =
+					((struct dq_linkage_t *)queue)->fwd;
+	((struct dq_linkage_t *)queue)->fwd->back = (struct dq_linkage_t *)item;
+	((struct dq_linkage_t *)queue)->fwd = (struct dq_linkage_t *)item;
+}
+
+void dq_addtail(struct dq_linkage_t *queue, void *item)
+{
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->fwd);
+
+	if (!((struct dq_linkage_t *)queue)->back ||
+	    !((struct dq_linkage_t *)queue)->fwd)
+		return;
+
+	((struct dq_linkage_t *)item)->fwd = (struct dq_linkage_t *)queue;
+	((struct dq_linkage_t *)item)->back =
+					((struct dq_linkage_t *)queue)->back;
+	((struct dq_linkage_t *)queue)->back->fwd = (struct dq_linkage_t *)item;
+	((struct dq_linkage_t *)queue)->back = (struct dq_linkage_t *)item;
+}
+
+int dq_empty(struct dq_linkage_t *queue)
+{
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->fwd);
+
+	if (!((struct dq_linkage_t *)queue)->back ||
+	    !((struct dq_linkage_t *)queue)->fwd)
+		return 1;
+
+	return ((queue)->fwd == (struct dq_linkage_t *)(queue));
+}
+
+void *dq_first(struct dq_linkage_t *queue)
+{
+	struct dq_linkage_t *temp = queue->fwd;
+
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->fwd);
+
+	if (!((struct dq_linkage_t *)queue)->back ||
+	    !((struct dq_linkage_t *)queue)->fwd)
+		return NULL;
+
+	return temp == (struct dq_linkage_t *)queue ? NULL : temp;
+}
+
+void *dq_last(struct dq_linkage_t *queue)
+{
+	struct dq_linkage_t *temp = queue->back;
+
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->fwd);
+
+	if (!((struct dq_linkage_t *)queue)->back ||
+	    !((struct dq_linkage_t *)queue)->fwd)
+		return NULL;
+
+	return temp == (struct dq_linkage_t *)queue ? NULL : temp;
+}
+
+void *dq_next(void *item)
+{
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)item)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)item)->fwd);
+
+	if (!((struct dq_linkage_t *)item)->back ||
+	    !((struct dq_linkage_t *)item)->fwd)
+		return NULL;
+
+	return ((struct dq_linkage_t *)item)->fwd;
+}
+
+void *dq_previous(void *item)
+{
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)item)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)item)->fwd);
+
+	if (!((struct dq_linkage_t *)item)->back ||
+	    !((struct dq_linkage_t *)item)->fwd)
+		return NULL;
+
+	return ((struct dq_linkage_t *)item)->back;
+}
+
+void dq_remove(void *item)
+{
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)item)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)item)->fwd);
+
+	if (!((struct dq_linkage_t *)item)->back ||
+	    !((struct dq_linkage_t *)item)->fwd)
+		return;
+
+	((struct dq_linkage_t *)item)->fwd->back =
+					((struct dq_linkage_t *)item)->back;
+	((struct dq_linkage_t *)item)->back->fwd =
+					((struct dq_linkage_t *)item)->fwd;
+
+	/* make item linkages safe for "orphan" removes */
+	((struct dq_linkage_t *)item)->fwd = item;
+	((struct dq_linkage_t *)item)->back = item;
+}
+
+void *dq_removehead(struct dq_linkage_t *queue)
+{
+	struct dq_linkage_t *temp;
+
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->fwd);
+
+	if (!((struct dq_linkage_t *)queue)->back ||
+	    !((struct dq_linkage_t *)queue)->fwd)
+		return NULL;
+
+	if ((queue)->fwd == (struct dq_linkage_t *)(queue))
+		return NULL;
+
+	temp = ((struct dq_linkage_t *)queue)->fwd;
+	temp->fwd->back = temp->back;
+	temp->back->fwd = temp->fwd;
+
+	/* make item linkages safe for "orphan" removes */
+	temp->fwd = temp;
+	temp->back = temp;
+	return temp;
+}
+
+void *dq_removetail(struct dq_linkage_t *queue)
+{
+	struct dq_linkage_t *temp;
+
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)queue)->fwd);
+
+	if (!((struct dq_linkage_t *)queue)->back ||
+	    !((struct dq_linkage_t *)queue)->fwd)
+		return NULL;
+
+	if ((queue)->fwd == (struct dq_linkage_t *)(queue))
+		return NULL;
+
+	temp = ((struct dq_linkage_t *)queue)->back;
+	temp->fwd->back = temp->back;
+	temp->back->fwd = temp->fwd;
+
+	/* make item linkages safe for "orphan" removes */
+	temp->fwd = temp;
+	temp->back = temp;
+
+	return temp;
+}
+
+void dq_addbefore(void *successor, void *item)
+{
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)successor)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)successor)->fwd);
+
+	if (!((struct dq_linkage_t *)successor)->back ||
+	    !((struct dq_linkage_t *)successor)->fwd)
+		return;
+
+	((struct dq_linkage_t *)item)->fwd = (struct dq_linkage_t *)successor;
+	((struct dq_linkage_t *)item)->back =
+				((struct dq_linkage_t *)successor)->back;
+	((struct dq_linkage_t *)item)->back->fwd = (struct dq_linkage_t *)item;
+	((struct dq_linkage_t *)successor)->back = (struct dq_linkage_t *)item;
+}
+
+void dq_addafter(void *predecessor, void *item)
+{
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)predecessor)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)predecessor)->fwd);
+
+	if (!((struct dq_linkage_t *)predecessor)->back ||
+	    !((struct dq_linkage_t *)predecessor)->fwd)
+		return;
+
+	((struct dq_linkage_t *)item)->fwd =
+				((struct dq_linkage_t *)predecessor)->fwd;
+	((struct dq_linkage_t *)item)->back =
+					(struct dq_linkage_t *)predecessor;
+	((struct dq_linkage_t *)item)->fwd->back = (struct dq_linkage_t *)item;
+	((struct dq_linkage_t *)predecessor)->fwd = (struct dq_linkage_t *)item;
+}
+
+void dq_move(struct dq_linkage_t *from, struct dq_linkage_t *to)
+{
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)from)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)from)->fwd);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)to)->back);
+	IMG_DBG_ASSERT(((struct dq_linkage_t *)to)->fwd);
+
+	if (!((struct dq_linkage_t *)from)->back ||
+	    !((struct dq_linkage_t *)from)->fwd ||
+	    !((struct dq_linkage_t *)to)->back ||
+	    !((struct dq_linkage_t *)to)->fwd)
+		return;
+
+	if ((from)->fwd == (struct dq_linkage_t *)(from)) {
+		dq_init(to);
+	} else {
+		*to = *from;
+		to->fwd->back = (struct dq_linkage_t *)to;
+		to->back->fwd = (struct dq_linkage_t *)to;
+		dq_init(from);
+	}
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/dq.h b/drivers/media/platform/img/vxe-vxd/common/dq.h
--- a/drivers/media/platform/img/vxe-vxd/common/dq.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/dq.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Utility module for doubly linked queues.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ */
+#ifndef DQ_H
+#define DQ_H
+
+/* dq structure */
+struct dq_linkage_t {
+	struct dq_linkage_t *fwd;
+	struct dq_linkage_t *back;
+};
+
+/* Function Prototypes */
+void dq_addafter(void *predecessor, void *item);
+void dq_addbefore(void *successor, void *item);
+void dq_addhead(struct dq_linkage_t *queue, void *item);
+void dq_addtail(struct dq_linkage_t *queue, void *item);
+int dq_empty(struct dq_linkage_t *queue);
+void *dq_first(struct dq_linkage_t *queue);
+void *dq_last(struct dq_linkage_t *queue);
+void dq_init(struct dq_linkage_t *queue);
+void dq_move(struct dq_linkage_t *from, struct dq_linkage_t *to);
+void *dq_next(void *item);
+void *dq_previous(void *item);
+void dq_remove(void *item);
+void *dq_removehead(struct dq_linkage_t *queue);
+void *dq_removetail(struct dq_linkage_t *queue);
+
+#endif /* #define DQ_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/hash.c b/drivers/media/platform/img/vxe-vxd/common/hash.c
--- a/drivers/media/platform/img/vxe-vxd/common/hash.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/hash.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,481 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Self scaling hash tables.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "hash.h"
+#include "img_errors.h"
+#include "pool.h"
+
+/* pool of struct hash objects */
+static struct pool *global_hashpool;
+
+/* pool of struct bucket objects */
+static struct pool *global_bucketpool;
+
+static int global_initialized;
+
+/* Each entry in a hash table is placed into a bucket */
+struct bucket {
+	struct bucket *next;
+	unsigned long long key;
+	unsigned long long value;
+};
+
+struct hash {
+	struct bucket **table;
+	unsigned int size;
+	unsigned int count;
+	unsigned int minimum_size;
+};
+
+/**
+ * hash_func - Hash function intended for hashing addresses.
+ * @vale : The key to hash.
+ * @size : The size of the hash table
+ */
+static unsigned int hash_func(unsigned long long vale,
+			      unsigned int size)
+{
+	unsigned int hash = (unsigned int)(vale);
+
+	hash += (hash << 12);
+	hash ^= (hash >> 22);
+	hash += (hash << 4);
+	hash ^= (hash >> 9);
+	hash += (hash << 10);
+	hash ^= (hash >> 2);
+	hash += (hash << 7);
+	hash ^= (hash >> 12);
+	hash &= (size - 1);
+	return hash;
+}
+
+/*
+ * @Function	hash_chain_insert
+ * @Description
+ * Hash function intended for hashing addresses.
+ * @Input	bucket : The bucket
+ * @Input	table : The hash table
+ * @Input	size : The size of the hash table
+ * @Return	IMG_SUCCESS or an error code.
+ */
+static int hash_chain_insert(struct bucket *bucket,
+			     struct bucket **table,
+			     unsigned int size)
+{
+	unsigned int idx;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!bucket || !table || !size) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	idx = hash_func(bucket->key, size);
+
+	if (idx < size) {
+		result = IMG_SUCCESS;
+		bucket->next = table[idx];
+		table[idx] = bucket;
+	}
+
+	return result;
+}
+
+/*
+ * @Function	hash_rehash
+ * @Description
+ * Iterate over every entry in an old hash table and rehash into the new table.
+ * @Input	old_table : The old hash table
+ * @Input	old_size : The size of the old hash table
+ * @Input	new_table : The new hash table
+ * @Input	new_sz : The size of the new hash table
+ * @Return	IMG_SUCCESS or an error code.
+ */
+static int hash_rehash(struct bucket **old_table,
+		       unsigned int old_size,
+		       struct bucket **new_table,
+		       unsigned int new_sz)
+{
+	unsigned int idx;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!old_table || !new_table) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	for (idx = 0; idx < old_size; idx++) {
+		struct bucket *bucket;
+		struct bucket *nex_bucket;
+
+		bucket = old_table[idx];
+		while (bucket) {
+			nex_bucket = bucket->next;
+			result = hash_chain_insert(bucket, new_table, new_sz);
+			if (result != IMG_SUCCESS) {
+				result = IMG_ERROR_UNEXPECTED_STATE;
+				return result;
+			}
+			bucket = nex_bucket;
+		}
+	}
+	result = IMG_SUCCESS;
+
+	return result;
+}
+
+/*
+ * @Function	hash_resize
+ * @Description
+ * Attempt to resize a hash table, failure to allocate a new larger hash table
+ * is not considered a hard failure. We simply continue and allow the table to
+ * fill up, the effect is to allow hash chains to become longer.
+ * @Input	hash_arg : Pointer to the hash table
+ * @Input	new_sz : The size of the new hash table
+ * @Return	IMG_SUCCESS or an error code.
+ */
+static int hash_resize(struct hash *hash_arg,
+		       unsigned int new_sz)
+{
+	unsigned int malloc_sz = 0;
+	unsigned int result = IMG_ERROR_FATAL;
+	unsigned int idx;
+
+	if (!hash_arg) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	if (new_sz != hash_arg->size) {
+		struct bucket **new_bkt_table;
+
+		malloc_sz = (sizeof(struct bucket *) * new_sz);
+		new_bkt_table = kmalloc(malloc_sz, GFP_KERNEL);
+
+		if (!new_bkt_table) {
+			result = IMG_ERROR_MALLOC_FAILED;
+			return result;
+		}
+
+		for (idx = 0; idx < new_sz; idx++)
+			new_bkt_table[idx] = NULL;
+
+		result = hash_rehash(hash_arg->table,
+				     hash_arg->size,
+				     new_bkt_table,
+				     new_sz);
+
+		if (result != IMG_SUCCESS) {
+			kfree(new_bkt_table);
+			new_bkt_table = NULL;
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+
+		kfree(hash_arg->table);
+		hash_arg->table = new_bkt_table;
+		hash_arg->size = new_sz;
+	}
+	result = IMG_SUCCESS;
+
+	return result;
+}
+
+static unsigned int private_max(unsigned int a, unsigned int b)
+{
+	unsigned int ret = (a > b) ? a : b;
+	return ret;
+}
+
+/*
+ * @Function	vid_hash_initialise
+ * @Description
+ * To initialise the hash module.
+ * @Input	None
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_initialise(void)
+{
+	unsigned int result = IMG_ERROR_ALREADY_COMPLETE;
+
+	if (!global_initialized) {
+		if (global_hashpool || global_bucketpool) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+
+		result = pool_create("img-hash",
+				     sizeof(struct hash),
+				     &global_hashpool);
+
+		if (result != IMG_SUCCESS) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+
+		result = pool_create("img-sBucket",
+				     sizeof(struct bucket),
+				     &global_bucketpool);
+		if (result != IMG_SUCCESS) {
+			if (global_bucketpool) {
+				result = pool_delete(global_bucketpool);
+				global_bucketpool = NULL;
+			}
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+		global_initialized = true;
+		result = IMG_SUCCESS;
+	}
+	return result;
+}
+
+/*
+ * @Function	vid_hash_finalise
+ * @Description
+ * To finalise the hash module. All allocated hash tables should
+ * be deleted before calling this function.
+ * @Input	None
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_finalise(void)
+{
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (global_initialized) {
+		if (global_hashpool) {
+			result = pool_delete(global_hashpool);
+			if (result != IMG_SUCCESS)
+				return result;
+
+			global_hashpool = NULL;
+		}
+
+		if (global_bucketpool) {
+			result = pool_delete(global_bucketpool);
+			if (result != IMG_SUCCESS)
+				return result;
+
+			global_bucketpool = NULL;
+		}
+		global_initialized = false;
+		result = IMG_SUCCESS;
+	}
+
+	return result;
+}
+
+/*
+ * @Function	vid_hash_create
+ * @Description
+ * Create a self scaling hash table.
+ * @Input	initial_size : Initial and minimum size of the hash table.
+ * @Output	hash_arg : Will countin the hash table handle or NULL.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_create(unsigned int initial_size,
+		    struct hash ** const hash_arg)
+{
+	unsigned int idx;
+	unsigned int tbl_sz = 0;
+	unsigned int result = IMG_ERROR_FATAL;
+	struct hash *local_hash = NULL;
+
+	if (!hash_arg) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	if (global_initialized) {
+		pool_alloc(global_hashpool, ((void **)&local_hash));
+		if (!local_hash) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			*hash_arg = NULL;
+			return result;
+		}
+
+		local_hash->count = 0;
+		local_hash->size = initial_size;
+		local_hash->minimum_size = initial_size;
+
+		tbl_sz = (sizeof(struct bucket *) * local_hash->size);
+		local_hash->table = kmalloc(tbl_sz, GFP_KERNEL);
+		if (!local_hash->table) {
+			result = pool_free(global_hashpool, local_hash);
+			if (result != IMG_SUCCESS)
+				result = IMG_ERROR_UNEXPECTED_STATE;
+			result |= IMG_ERROR_MALLOC_FAILED;
+			*hash_arg = NULL;
+			return result;
+		}
+
+		for (idx = 0; idx < local_hash->size; idx++)
+			local_hash->table[idx] = NULL;
+
+		*hash_arg = local_hash;
+		result = IMG_SUCCESS;
+	}
+	return result;
+}
+
+/*
+ * @Function	vid_hash_delete
+ * @Description
+ * To delete a hash table, all entries in the table should be
+ * removed before calling this function.
+ * @Input	hash_arg : Hash table pointer
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_delete(struct hash * const hash_arg)
+{
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!hash_arg) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	if (global_initialized) {
+		if (hash_arg->count != 0) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+
+		kfree(hash_arg->table);
+		hash_arg->table = NULL;
+
+		result = pool_free(global_hashpool, hash_arg);
+		if (result != IMG_SUCCESS) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+	}
+	return result;
+}
+
+/*
+ * @Function	vid_hash_insert
+ * @Description
+ * To insert a key value pair into a hash table.
+ * @Input	hash_arg : Hash table pointer
+ * @Input	key : Key value
+ * @Input	value : The value associated with the key.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_insert(struct hash * const hash_arg,
+		    unsigned long long key,
+		    unsigned long long value)
+{
+	struct bucket *ps_bucket = NULL;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!hash_arg) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	if (global_initialized) {
+		result = pool_alloc(global_bucketpool, ((void **)&ps_bucket));
+		if (result != IMG_SUCCESS || !ps_bucket) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+		ps_bucket->next = NULL;
+		ps_bucket->key = key;
+		ps_bucket->value = value;
+
+		result = hash_chain_insert(ps_bucket,
+					   hash_arg->table,
+					   hash_arg->size);
+
+		if (result != IMG_SUCCESS) {
+			pool_free(global_bucketpool, ((void **)&ps_bucket));
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			return result;
+		}
+
+		hash_arg->count++;
+
+		/* check if we need to think about re-balancing */
+		if ((hash_arg->count << 1) > hash_arg->size) {
+			result = hash_resize(hash_arg, (hash_arg->size << 1));
+			if (result != IMG_SUCCESS) {
+				result = IMG_ERROR_UNEXPECTED_STATE;
+				return result;
+			}
+		}
+		result = IMG_SUCCESS;
+	}
+	return result;
+}
+
+/*
+ * @Function	vid_hash_remove
+ * @Description
+ * To remove a key value pair from a hash table
+ * @Input	hash_arg : Hash table pointer
+ * @Input	key : Key value
+ * @Input	ret_result : 0 if the key is missing or the value
+ *		associated with the key.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_remove(struct hash * const hash_arg,
+		    unsigned long long key,
+		    unsigned long * const ret_result)
+{
+	unsigned int idx;
+	unsigned int tmp1 = 0;
+	unsigned int tmp2 = 0;
+	unsigned int result = IMG_ERROR_FATAL;
+	struct bucket **bucket = NULL;
+
+	if (!hash_arg) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	idx = hash_func(key, hash_arg->size);
+
+	for (bucket = &hash_arg->table[idx]; (*bucket) != NULL;
+		bucket = &((*bucket)->next)) {
+		if ((*bucket)->key == key) {
+			struct bucket *ps_bucket = (*bucket);
+
+			unsigned long long value = ps_bucket->value;
+
+			*bucket = ps_bucket->next;
+			result = pool_free(global_bucketpool, ps_bucket);
+
+			hash_arg->count--;
+
+			/* check if we need to think about re-balencing */
+			if (hash_arg->size > (hash_arg->count << 2) &&
+			    hash_arg->size > hash_arg->minimum_size) {
+				tmp1 = (hash_arg->size >> 1);
+				tmp2 = hash_arg->minimum_size;
+				result = hash_resize(hash_arg,
+						     private_max(tmp1, tmp2));
+			}
+			*ret_result = value;
+			result = IMG_SUCCESS;
+			break;
+		}
+	}
+	return result;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/hash.h b/drivers/media/platform/img/vxe-vxd/common/hash.h
--- a/drivers/media/platform/img/vxe-vxd/common/hash.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/hash.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Self scaling hash tables.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *      Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef _HASH_H_
+#define _HASH_H_
+
+#include <linux/types.h>
+struct hash;
+
+/**
+ * vid_hash_initialise - VID_HASH_Initialise
+ * @Input	 None
+ *
+ * To initialise the hash module.
+ */
+int vid_hash_initialise(void);
+
+/*
+ * @Function	VID_HASH_Finalise
+ * @Description
+ * To finalise the hash module. All allocated hash tables should
+ * be deleted before calling this function.
+ * @Input	None
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_finalise(void);
+
+/*
+ * @Function	VID_HASH_Create
+ * @Description
+ * Create a self scaling hash table.
+ * @Input	initial_size : Initial and minimum size of the hash table.
+ * @Output	hash : Hash table handle or NULL.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_create(unsigned int initial_size,
+		    struct hash ** const hash_hndl);
+
+/*
+ * @Function	VID_HASH_Delete
+ * @Description
+ * To delete a hash table, all entries in the table should be
+ * removed before calling this function.
+ * @Input	hash : Hash table pointer
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_delete(struct hash * const ps_hash);
+
+/*
+ * @Function	VID_HASH_Insert
+ * @Description
+ * To insert a key value pair into a hash table.
+ * @Input	ps_hash : Hash table pointer
+ * @Input	key : Key value
+ * @Input	value : The value associated with the key.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_insert(struct hash * const ps_hash,
+		    unsigned long long key,
+		    unsigned long long value);
+
+/*
+ * @Function	VID_HASH_Remove
+ * @Description
+ * To remove a key value pair from a hash table
+ * @Input	ps_hash : Hash table pointer
+ * @Input	key : Key value
+ * @Input	result : 0 if the key is missing or the value
+ *		associated with the key.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int vid_hash_remove(struct hash * const ps_hash,
+		    unsigned long long key,
+		    unsigned long * const result);
+
+#endif /* _HASH_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/idgen_api.c b/drivers/media/platform/img/vxe-vxd/common/idgen_api.c
--- a/drivers/media/platform/img/vxe-vxd/common/idgen_api.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/idgen_api.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,449 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ID generation manager API.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "idgen_api.h"
+#include "lst.h"
+
+/*
+ * This structure contains ID context.
+ */
+struct idgen_context {
+	/* List of handle block structures */
+	struct lst_t hdlblklst;
+	/* Max ID - set by IDGEN_CreateContext(). */
+	unsigned int maxid;
+	/*
+	 * The number of handle per block. In case of
+	 * incrementing ids, size of the Hash table.
+	 */
+	unsigned int blksize;
+	/* Next free slot. */
+	unsigned int freeslot;
+	/* Max slot+1 for which we have allocated blocks. */
+	unsigned int maxslotplus1;
+	/* Incrementing ID's */
+	/* API needed to return incrementing IDs */
+	int incids;
+	/* Latest ID given back */
+	unsigned int latestincnumb;
+	/* Array of list to hold IDGEN_sHdlId */
+	struct lst_t *incidlist;
+};
+
+/*
+ * This structure represents internal representation of an Incrementing ID.
+ */
+struct idgen_id {
+	void **link; /* to be part of single linked list */
+	/* Incrementing ID returned */
+	unsigned int incid;
+	void *hid;
+};
+
+/*
+ * Structure contains the ID context.
+ */
+struct idgen_hdblk {
+	void **link; /* to be part of single linked list */
+	/* Array of handles in this block. */
+	void *ahhandles[1];
+};
+
+/*
+ * A hashing function could go here. Currently just makes a circular list of
+ * max number of concurrent Ids (idgen_context->blksize) in the system.
+ */
+static unsigned int idgen_func(struct idgen_context *idcontext, unsigned int id)
+{
+	return ((id - 1) % idcontext->blksize);
+}
+
+int idgen_createcontext(unsigned int maxid, unsigned int blksize,
+			int incid, void **idgenhandle)
+{
+	struct idgen_context *idcontext;
+
+	/* Create context structure */
+	idcontext = kzalloc(sizeof(*idcontext), GFP_KERNEL);
+	if (!idcontext)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/* InitIalise the context */
+	lst_init(&idcontext->hdlblklst);
+	idcontext->maxid   = maxid;
+	idcontext->blksize = blksize;
+
+	/* If we need incrementing Ids */
+	idcontext->incids = incid;
+	idcontext->latestincnumb = 0;
+	idcontext->incidlist  = NULL;
+	if (idcontext->incids) {
+		unsigned int i = 0;
+		/* Initialise the hash table of lists of length ui32BlkSize */
+		idcontext->incidlist = kzalloc((sizeof(*idcontext->incidlist) *
+				idcontext->blksize), GFP_KERNEL);
+		if (!idcontext->incidlist) {
+			kfree(idcontext);
+			return IMG_ERROR_OUT_OF_MEMORY;
+		}
+
+		/* Initialise all the lists in the hash table */
+		for (i = 0; i < idcontext->blksize; i++)
+			lst_init(&idcontext->incidlist[i]);
+	}
+
+	/* Return context structure as handle */
+	*idgenhandle = idcontext;
+
+	return IMG_SUCCESS;
+}
+
+int idgen_destroycontext(void *idgenhandle)
+{
+	struct idgen_context *idcontext = (struct idgen_context *)idgenhandle;
+	struct idgen_hdblk *hdblk;
+
+	if (!idcontext)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* If incrementing Ids, free the List of Incrementing Ids */
+	if (idcontext->incids) {
+		struct idgen_id *id;
+		unsigned int i = 0;
+
+		for (i = 0; i < idcontext->blksize; i++) {
+			id = lst_removehead(&idcontext->incidlist[i]);
+			while (id) {
+				kfree(id);
+				id = lst_removehead(&idcontext->incidlist[i]);
+			}
+		}
+		kfree(idcontext->incidlist);
+	}
+
+	/* Remove and free all handle blocks */
+	hdblk = (struct idgen_hdblk *)lst_removehead(&idcontext->hdlblklst);
+	while (hdblk) {
+		kfree(hdblk);
+		hdblk = (struct idgen_hdblk *)
+				lst_removehead(&idcontext->hdlblklst);
+	}
+
+	/* Free context structure */
+	kfree(idcontext);
+
+	return IMG_SUCCESS;
+}
+
+static int idgen_findnextfreeslot(void *idgenhandle, unsigned int prevfreeslot)
+{
+	struct idgen_context *idcontext = (struct idgen_context *)idgenhandle;
+	struct idgen_hdblk *hdblk;
+	unsigned int freslotblk;
+	unsigned int freeslot;
+
+	if (!idcontext)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Find the block containing the current free slot */
+	freeslot	= prevfreeslot;
+	freslotblk = prevfreeslot;
+	hdblk = (struct idgen_hdblk *)lst_first(&idcontext->hdlblklst);
+	if (!hdblk)
+		return IMG_ERROR_FATAL;
+
+	while (freslotblk >= idcontext->blksize) {
+		freslotblk -= idcontext->blksize;
+		hdblk = (struct idgen_hdblk *)lst_next(hdblk);
+	}
+
+	/* Locate the next free slot */
+	while (hdblk) {
+		while (freslotblk < idcontext->blksize) {
+			if (!hdblk->ahhandles[freslotblk]) {
+				/* Found */
+				idcontext->freeslot = freeslot;
+				return IMG_SUCCESS;
+			}
+			freeslot++;
+			freslotblk++;
+		}
+		freslotblk = 0;
+		hdblk = (struct idgen_hdblk *)lst_next(hdblk);
+	}
+
+	/* Beyond the last block */
+	idcontext->freeslot = freeslot;
+	return IMG_SUCCESS;
+}
+
+/*
+ * This function returns ID structure (
+ */
+static struct idgen_id *idgen_getid(struct lst_t *idlist, unsigned int id)
+{
+	struct idgen_id *idstruct;
+
+	idstruct = lst_first(idlist);
+	while (idstruct) {
+		if (idstruct->incid == id)
+			break;
+
+		idstruct = lst_next(idstruct);
+	}
+	return idstruct;
+}
+
+/*
+ * This function does IDGEN allocation.
+ */
+int idgen_allocid(void *idgenhandle, void *handle, unsigned int *id)
+{
+	struct idgen_context *idcontext = (struct idgen_context *)idgenhandle;
+	struct idgen_hdblk *hdblk;
+	unsigned int size = 0;
+	unsigned int freeslot = 0;
+	unsigned int result = 0;
+
+	if (!idcontext || !handle)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (!idcontext->incids) {
+		/* If the free slot is >= to the max id */
+		if (idcontext->freeslot >= idcontext->maxid) {
+			result = IMG_ERROR_INVALID_ID;
+			goto error;
+		}
+
+		/* If all of the allocated Ids have been used */
+		if (idcontext->freeslot >= idcontext->maxslotplus1) {
+			/* Allocate a stream context */
+			size = sizeof(*hdblk) + (sizeof(void *) *
+				(idcontext->blksize - 1));
+			hdblk = kzalloc(size, GFP_KERNEL);
+			if (!hdblk) {
+				result = IMG_ERROR_OUT_OF_MEMORY;
+				goto error;
+			}
+
+			lst_add(&idcontext->hdlblklst, hdblk);
+			idcontext->maxslotplus1 += idcontext->blksize;
+		}
+
+		/* Find the block containing the next free slot */
+		freeslot = idcontext->freeslot;
+		hdblk = (struct idgen_hdblk *)lst_first(&idcontext->hdlblklst);
+		if (!hdblk) {
+			result = IMG_ERROR_FATAL;
+			goto error;
+		}
+		while (freeslot >= idcontext->blksize) {
+			freeslot -= idcontext->blksize;
+			hdblk = (struct idgen_hdblk *)lst_next(hdblk);
+			if (!hdblk) {
+				result = IMG_ERROR_FATAL;
+				goto error;
+			}
+		}
+
+		/* Put handle in the next free slot */
+		hdblk->ahhandles[freeslot] = handle;
+
+		*id = idcontext->freeslot + 1;
+
+		/* Find a new free slot */
+		result = idgen_findnextfreeslot(idcontext, idcontext->freeslot);
+		if (result != 0)
+			goto error;
+	/*
+	 * If incrementing IDs, just add the ID node to the correct hash table
+	 * list.
+	 */
+	} else {
+		struct idgen_id *psid;
+		unsigned int currentincnum, funcid;
+		/*
+		 * If incrementing IDs, increment the id for returning back,and
+		 * save the ID node in the list of ids, indexed by hash function
+		 * (idgen_func). We might want to use a better hashing function
+		 */
+		currentincnum = (idcontext->latestincnumb + 1) %
+				idcontext->maxid;
+
+		/* Increment the id. Wraps if greater then Max Id */
+		if (currentincnum == 0)
+			currentincnum++;
+
+		idcontext->latestincnumb = currentincnum;
+
+		result = IMG_ERROR_INVALID_ID;
+		do {
+			/* Add to list in the correct hash table entry */
+			funcid = idgen_func(idcontext, idcontext->latestincnumb);
+			if (idgen_getid(&idcontext->incidlist[funcid],
+					idcontext->latestincnumb) == NULL) {
+				psid = kmalloc(sizeof(*psid), GFP_KERNEL);
+				if (!psid) {
+					result = IMG_ERROR_OUT_OF_MEMORY;
+					goto error;
+				}
+
+				psid->incid = idcontext->latestincnumb;
+				psid->hid = handle;
+
+				funcid = idgen_func(idcontext,
+						    idcontext->latestincnumb);
+				lst_add(&idcontext->incidlist[funcid],
+					psid);
+
+				result = IMG_SUCCESS;
+			} else {
+				idcontext->latestincnumb =
+					(idcontext->latestincnumb + 1) %
+						idcontext->maxid;
+				if (idcontext->latestincnumb == 0) {
+					/* Do not want to have zero as pic id */
+					idcontext->latestincnumb++;
+				}
+				/*
+				 * We have reached a point where we have wrapped
+				 * allowed Ids (MaxId) and we want to overwrite
+				 * ID still not released
+				 */
+				if (idcontext->latestincnumb == currentincnum)
+					goto error;
+			}
+		} while (result != IMG_SUCCESS);
+
+		*id = psid->incid;
+	}
+	return IMG_SUCCESS;
+error:
+	return result;
+}
+
+int idgen_freeid(void *idgenhandle, unsigned int id)
+{
+	struct idgen_context *idcontext = (struct idgen_context *)idgenhandle;
+	struct idgen_hdblk *hdblk;
+	unsigned int origslot;
+	unsigned int slot;
+
+	if (idcontext->incids) {
+		/*
+		 * Find the slot in the correct hash table entry, and
+		 * remove the ID.
+		 */
+		struct idgen_id *psid;
+
+		psid = idgen_getid(&idcontext->incidlist
+				[idgen_func(idcontext, id)], id);
+		if (psid) {
+			lst_remove(&idcontext->incidlist
+					[idgen_func(idcontext, id)], psid);
+			kfree(psid);
+		} else {
+			return IMG_ERROR_INVALID_ID;
+		}
+	} else {
+		/* If not incrementing id */
+		slot = id - 1;
+		origslot = slot;
+
+		if (slot >= idcontext->maxslotplus1)
+			return IMG_ERROR_INVALID_ID;
+
+		/* Find the block containing the id */
+		hdblk = (struct idgen_hdblk *)lst_first(&idcontext->hdlblklst);
+		if (!hdblk)
+			return IMG_ERROR_FATAL;
+
+		while (slot >= idcontext->blksize) {
+			slot -= idcontext->blksize;
+			hdblk = (struct idgen_hdblk *)lst_next(hdblk);
+			if (!hdblk)
+				return IMG_ERROR_FATAL;
+		}
+
+		/* Slot should be occupied */
+		if (!hdblk->ahhandles[slot])
+			return IMG_ERROR_INVALID_ID;
+
+		/* Free slot */
+		hdblk->ahhandles[slot] = NULL;
+
+		/* If this slot is before the previous free slot */
+		if ((origslot) < idcontext->freeslot)
+			idcontext->freeslot = origslot;
+	}
+	return IMG_SUCCESS;
+}
+
+int idgen_gethandle(void *idgenhandle, unsigned int id, void **handle)
+{
+	struct idgen_context *idcontext = (struct idgen_context *)idgenhandle;
+	struct idgen_hdblk *hdblk;
+	unsigned int slot;
+
+	if (!idcontext)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (idcontext->incids) {
+		/*
+		 * Find the slot in the correct hash table entry, and return
+		 * the handles.
+		 */
+		struct idgen_id *psid;
+
+		psid = idgen_getid(&idcontext->incidlist
+				[idgen_func(idcontext, id)], id);
+		if (psid)
+			*handle = psid->hid;
+
+		else
+			return IMG_ERROR_INVALID_ID;
+	} else {
+		/* If not incrementing IDs */
+		slot = id - 1;
+		if (slot >= idcontext->maxslotplus1)
+			return IMG_ERROR_INVALID_ID;
+
+		/* Find the block containing the id */
+		hdblk = (struct idgen_hdblk *)lst_first(&idcontext->hdlblklst);
+		if (!hdblk)
+			return IMG_ERROR_INVALID_PARAMETERS;
+
+		while (slot >= idcontext->blksize) {
+			slot -= idcontext->blksize;
+			hdblk = (struct idgen_hdblk *)lst_next(hdblk);
+			if (!hdblk)
+				return IMG_ERROR_INVALID_PARAMETERS;
+		}
+
+		/* Slot should be occupied */
+		if (!hdblk->ahhandles[slot])
+			return IMG_ERROR_INVALID_ID;
+
+		/* Return the handle */
+		*handle = hdblk->ahhandles[slot];
+		}
+
+	return IMG_SUCCESS;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/idgen_api.h b/drivers/media/platform/img/vxe-vxd/common/idgen_api.h
--- a/drivers/media/platform/img/vxe-vxd/common/idgen_api.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/idgen_api.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * ID generation manager API.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+#ifndef __IDGENAPI_H__
+#define __IDGENAPI_H__
+
+#include <linux/types.h>
+
+#include "img_errors.h"
+
+/*
+ * This function is used to create Id generation context.
+ * NOTE: Should only be called once to setup the context structure.
+ * NOTE: The client is responsible for providing thread/process safe locks on
+ * the context structure to maintain coherence.
+ */
+int idgen_createcontext(unsigned int maxid, unsigned int blksize,
+			int incid, void **idgenhandle);
+
+/*
+ * This function is used to destroy an Id generation context.  This function
+ * discards any handle blocks associated with the context.
+ * NOTE: The client is responsible for providing thread/process safe locks on
+ * the context structure to maintain coherence.
+ */
+int idgen_destroycontext(void *idgenhandle);
+
+/*
+ * This function is used to associate a handle with an Id.
+ * NOTE: The client is responsible for providing thread/process safe locks on
+ * the context structure to maintain coherency.
+ */
+int idgen_allocid(void *idgenhandle, void *handle, unsigned int *id);
+
+/*
+ * This function is used to free an Id.
+ * NOTE: The client is responsible for providing thread/process safe locks on
+ * the context structure to maintain coherency.
+ */
+int idgen_freeid(void *idgenhandle, unsigned int id);
+
+/*
+ * This function is used to get the handle associated with an Id.
+ * NOTE: The client is responsible for providing thread/process safe locks on
+ * the context structure to maintain coherency.
+ */
+int idgen_gethandle(void *idgenhandle, unsigned int id, void **handle);
+#endif /* __IDGENAPI_H__ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/img_errors.h b/drivers/media/platform/img/vxe-vxd/common/img_errors.h
--- a/drivers/media/platform/img/vxe-vxd/common/img_errors.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/img_errors.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Error codes.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ */
+#ifndef __IMG_ERRORS__
+#define __IMG_ERRORS__
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#define IMG_DBG_ASSERT(expected) ({WARN_ON(!(expected)); 0; })
+
+/* @brief Success */
+#define IMG_SUCCESS                                     (0)
+/* @brief Timeout */
+#define IMG_ERROR_TIMEOUT                               (1)
+/* @brief memory allocation failed */
+#define IMG_ERROR_MALLOC_FAILED                         (2)
+/* @brief Unspecified fatal error */
+#define IMG_ERROR_FATAL                                 (3)
+/* @brief Memory allocation failed */
+#define IMG_ERROR_OUT_OF_MEMORY                         (4)
+/* @brief Device is not found */
+#define IMG_ERROR_DEVICE_NOT_FOUND                      (5)
+/* @brief Device is not available/in use */
+#define IMG_ERROR_DEVICE_UNAVAILABLE                    (6)
+/* @brief Generic/unspecified failure */
+#define IMG_ERROR_GENERIC_FAILURE                       (7)
+/* @brief Operation was interrupted - retry */
+#define IMG_ERROR_INTERRUPTED                           (8)
+/* @brief Invalid id  */
+#define IMG_ERROR_INVALID_ID                            (9)
+/* @brief A signature value was found to be incorrect */
+#define IMG_ERROR_SIGNATURE_INCORRECT                   (10)
+/* @brief The provided parameters were inconsistent/incorrect */
+#define IMG_ERROR_INVALID_PARAMETERS                    (11)
+/* @brief A list/pool has run dry     */
+#define IMG_ERROR_STORAGE_TYPE_EMPTY                    (12)
+/* @brief A list is full      */
+#define IMG_ERROR_STORAGE_TYPE_FULL                     (13)
+/* @brief Something has already occurred which the code thinks has not */
+#define IMG_ERROR_ALREADY_COMPLETE                      (14)
+/* @brief A state machine is in an unexpected/illegal state */
+#define IMG_ERROR_UNEXPECTED_STATE                      (15)
+/* @brief A required resource could not be created/locked */
+#define IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE             (16)
+/*
+ * @brief An attempt to access a structure/resource was
+ * made before it was initialised
+ */
+#define IMG_ERROR_NOT_INITIALISED                       (17)
+/*
+ * @brief An attempt to initialise a structure/resource
+ * was made when it has already been initialised
+ */
+#define IMG_ERROR_ALREADY_INITIALISED                   (18)
+/* @brief A provided value exceeded stated bounds */
+#define IMG_ERROR_VALUE_OUT_OF_RANGE                    (19)
+/* @brief The operation has been cancelled */
+#define IMG_ERROR_CANCELLED                             (20)
+/* @brief A specified minimum has not been met */
+#define IMG_ERROR_MINIMUM_LIMIT_NOT_MET                 (21)
+/* @brief The requested feature or mode is not supported */
+#define IMG_ERROR_NOT_SUPPORTED                         (22)
+/* @brief A device or process was idle */
+#define IMG_ERROR_IDLE                                  (23)
+/* @brief A device or process was busy */
+#define IMG_ERROR_BUSY                                  (24)
+/* @brief The device or resource has been disabled */
+#define IMG_ERROR_DISABLED                              (25)
+/* @brief The requested operation is not permitted at this time */
+#define IMG_ERROR_OPERATION_PROHIBITED                  (26)
+/* @brief The entry read from the MMU page directory is invalid */
+#define IMG_ERROR_MMU_PAGE_DIRECTORY_FAULT              (27)
+/* @brief The entry read from an MMU page table is invalid */
+#define IMG_ERROR_MMU_PAGE_TABLE_FAULT                  (28)
+/* @brief The entry read from an MMU page catalogue is invalid */
+#define IMG_ERROR_MMU_PAGE_CATALOGUE_FAULT              (29)
+/* @brief Memory can not be freed as it is still been used */
+#define IMG_ERROR_MEMORY_IN_USE                         (30)
+/* @brief A mismatch has unexpectedly occurred in data */
+#define IMG_ERROR_TEST_MISMATCH                         (31)
+
+#define IMG_ERROR_INVALID_CONTEXT			(32)
+
+#define IMG_ERROR_RETRY					(33)
+#define IMG_ERROR_UNDEFINED				(34)
+#define IMG_ERROR_INVALID_SIZE				(35)
+#define IMG_ERROR_SURFACE_LOCKED			(36)
+
+/* Mutex subclasses */
+#define SUBCLASS_BASE       0
+#define SUBCLASS_VXD_V4L2   1
+#define SUBCLASS_VXE_V4L2   1
+#define SUBCLASS_BSPP       1
+#define SUBCLASS_ADDR_ALLOC 7
+#define SUBCLASS_IMGMEM     6
+#define SUBCLASS_RMAN       1
+#define SUBCLASS_TALMMU     5
+#define SUBCLASS_VXD_CORE   2
+#define SUBCLASS_POOL       3
+#define SUBCLASS_POOL_RES   5
+#define SUBCLASS_TOPAZ_API  2
+#define SUBCLASS_TOPAZDD_TX 4
+#define SUBCLASS_TOPAZDD    3
+
+#endif /* __IMG_ERRORS__ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/img_mem.h b/drivers/media/platform/img/vxe-vxd/common/img_mem.h
--- a/drivers/media/platform/img/vxe-vxd/common/img_mem.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/img_mem.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Typedefs for memory pool and attributes
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef __IMG_MEM__
+#define __IMG_MEM__
+
+/*
+ * This type defines the memory attributes.
+ * @0x00000001: Memory to be allocated as cached
+ * @0x00000002: Memory to be allocated as uncached
+ * @0x00000004: Memory to be allocated as write-combined
+ *	(or equivalent buffered/burst writes mechanism)
+ * @0x00001000: Memory can be read only by the core
+ * @0x00002000: Memory can be written only by the core
+ * @0x00010000: Memory should be readable by the cpu
+ * @0x00020000: Memory should be writable by the cpu
+ */
+enum sys_emem_attrib {
+	SYS_MEMATTRIB_CACHED             = 0x00000001,
+	SYS_MEMATTRIB_UNCACHED           = 0x00000002,
+	SYS_MEMATTRIB_WRITECOMBINE       = 0x00000004,
+	SYS_MEMATTRIB_SECURE             = 0x00000010,
+	SYS_MEMATTRIB_INPUT              = 0x00000100,
+	SYS_MEMATTRIB_OUTPUT             = 0x00000200,
+	SYS_MEMATTRIB_INTERNAL           = 0x00000400,
+	SYS_MEMATTRIB_CORE_READ_ONLY     = 0x00001000,
+	SYS_MEMATTRIB_CORE_WRITE_ONLY    = 0x00002000,
+	SYS_MEMATTRIB_CPU_READ           = 0x00010000,
+	SYS_MEMATTRIB_CPU_WRITE          = 0x00020000,
+	SYS_MEMATTRIB_FORCE32BITS	 = 0x7FFFFFFFU
+};
+
+#endif /* __IMG_MEM__ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/img_mem_man.c b/drivers/media/platform/img/vxe-vxd/common/img_mem_man.c
--- a/drivers/media/platform/img/vxe-vxd/common/img_mem_man.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/img_mem_man.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,1125 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMG DEC Memory Manager
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/idr.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "imgmmu.h"
+#include "img_mem_man.h"
+#include "img_errors.h"
+
+#define VXD_MMU_SHIFT 8 /* assume 40-bit MMU */
+/* heaps ids (global) */
+#define MIN_HEAP 1
+#define MAX_HEAP 16
+
+/*
+ * struct dev_mem_man - the device memory management
+ * @heaps: idr list of heap for the device memory manager
+ * @mem_ctxs: contains lists of mem_ctx
+ * @mutex: mutex for this device
+ */
+struct mem_man {
+	void *dev;
+	struct idr *heaps;
+	struct list_head mem_ctxs;
+	struct mutex *mutex; /* mutex for this device */
+};
+
+static struct mem_man mem_man_data = {0};
+
+/**
+ * struct mmu_page - the mmu page information for the buffer
+ * @buffer: buffer pointer for the particular mmu_page
+ * @page_cfg: mmu page configuration of physical and virtual addr
+ * @addr_shift: address shifting information
+ */
+struct mmu_page {
+	struct buffer *buffer;
+	struct mmu_page_cfg page_cfg;
+	unsigned int addr_shift;
+};
+
+static void _img_mem_free(struct buffer *buffer);
+static void _img_mmu_unmap(struct mmu_ctx_mapping *mapping);
+static void _img_mmu_ctx_destroy(struct mmu_ctx *ctx);
+
+#if defined(DEBUG_DECODER_DRIVER)
+static unsigned char *get_heap_name(enum heap_type type)
+{
+	switch (type) {
+	case MEM_HEAP_TYPE_UNIFIED:
+		return "unified";
+	default:
+		return "unknown";
+	}
+}
+#endif
+
+int img_mem_add_heap(const struct heap_config *heap_cfg, int *heap_id)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct heap *heap;
+	int (*init_fn)(const struct heap_config *heap_cfg, struct heap *heap);
+	int ret;
+
+	switch (heap_cfg->type) {
+	case MEM_HEAP_TYPE_UNIFIED:
+		init_fn = img_mem_unified_init;
+		break;
+	default:
+		dev_err(mem_man->dev, "%s: heap type %d unknown\n", __func__,
+			heap_cfg->type);
+		return -EINVAL;
+	}
+
+	heap = kmalloc(sizeof(*heap), GFP_KERNEL);
+	if (!heap)
+		return -ENOMEM;
+
+	ret = mutex_lock_interruptible_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+	if (ret)
+		goto lock_failed;
+
+	ret = idr_alloc(mem_man->heaps, heap, MIN_HEAP, MAX_HEAP, GFP_KERNEL);
+	if (ret < 0) {
+		dev_err(mem_man->dev, "%s: idr_alloc failed\n", __func__);
+		goto alloc_id_failed;
+	}
+
+	heap->id = ret;
+	heap->type = heap_cfg->type;
+	heap->options = heap_cfg->options;
+	heap->to_dev_addr = heap_cfg->to_dev_addr;
+	heap->priv = NULL;
+
+	ret = init_fn(heap_cfg, heap);
+	if (ret) {
+		dev_err(mem_man->dev, "%s: heap init failed\n", __func__);
+		goto heap_init_failed;
+	}
+
+	*heap_id = heap->id;
+	mutex_unlock(mem_man->mutex);
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_info(mem_man->dev, "%s created heap %d type %d (%s)\n",
+		 __func__, *heap_id, heap_cfg->type, get_heap_name(heap->type));
+#endif
+	return 0;
+
+heap_init_failed:
+	idr_remove(mem_man->heaps, heap->id);
+alloc_id_failed:
+	mutex_unlock(mem_man->mutex);
+lock_failed:
+	kfree(heap);
+	return ret;
+}
+
+static void _img_mem_del_heap(struct heap *heap)
+{
+	struct mem_man *mem_man = &mem_man_data;
+
+	if (heap->ops->destroy)
+		heap->ops->destroy(heap);
+
+	idr_remove(mem_man->heaps, heap->id);
+}
+
+void img_mem_del_heap(int heap_id)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct heap *heap;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+
+	heap = idr_find(mem_man->heaps, heap_id);
+	if (!heap) {
+		dev_warn(mem_man->dev, "%s heap %d not found!\n", __func__,
+			 heap_id);
+		mutex_unlock(mem_man->mutex);
+		return;
+	}
+
+	_img_mem_del_heap(heap);
+
+	mutex_unlock(mem_man->mutex);
+
+	kfree(heap);
+}
+
+int img_mem_create_ctx(struct mem_ctx **new_ctx)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct mem_ctx *ctx;
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->buffers = kzalloc(sizeof(*ctx->buffers), GFP_KERNEL);
+	if (!ctx->buffers)
+		return -ENOMEM;
+	idr_init(ctx->buffers);
+
+	INIT_LIST_HEAD(&ctx->mmu_ctxs);
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+	list_add(&ctx->mem_man_entry, &mem_man->mem_ctxs);
+	mutex_unlock(mem_man->mutex);
+
+	*new_ctx = ctx;
+	return 0;
+}
+
+static void _img_mem_destroy_ctx(struct mem_ctx *ctx)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct buffer *buffer;
+	int buff_id;
+
+	/* free derelict mmu contexts */
+	while (!list_empty(&ctx->mmu_ctxs)) {
+		struct mmu_ctx *mc;
+
+		mc = list_first_entry(&ctx->mmu_ctxs,
+				      struct mmu_ctx, mem_ctx_entry);
+		dev_warn(mem_man->dev, "%s: found derelict mmu context %p\n",
+			 __func__, mc);
+		_img_mmu_ctx_destroy(mc);
+		kfree(mc);
+	}
+
+	/* free derelict buffers */
+	buff_id = MEM_MAN_MIN_BUFFER;
+	buffer = idr_get_next(ctx->buffers, &buff_id);
+	while (buffer) {
+		dev_warn(mem_man->dev, "%s: found derelict buffer %d\n",
+			 __func__, buff_id);
+		if (buffer->heap)
+			_img_mem_free(buffer);
+		else
+			idr_remove(ctx->buffers, buffer->id);
+		kfree(buffer);
+		buff_id = MEM_MAN_MIN_BUFFER;
+		buffer = idr_get_next(ctx->buffers, &buff_id);
+	}
+
+	idr_destroy(ctx->buffers);
+	kfree(ctx->buffers);
+	__list_del_entry(&ctx->mem_man_entry);
+}
+
+void img_mem_destroy_ctx(struct mem_ctx *ctx)
+{
+	struct mem_man *mem_man = &mem_man_data;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+	_img_mem_destroy_ctx(ctx);
+	mutex_unlock(mem_man->mutex);
+
+	kfree(ctx);
+}
+
+static int _img_mem_alloc(void *device, struct mem_ctx *ctx,
+			  struct heap *heap, unsigned long size,
+			  enum mem_attr attr, struct buffer **buffer_new)
+{
+	struct buffer *buffer;
+	int ret;
+
+	if (size == 0) {
+		dev_err(device, "%s: buffer size is zero\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!heap->ops || !heap->ops->alloc) {
+		dev_err(device, "%s: no alloc function in heap %d!\n",
+			__func__, heap->id);
+		return -EINVAL;
+	}
+
+	buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	ret = idr_alloc(ctx->buffers, buffer,
+			MEM_MAN_MIN_BUFFER, MEM_MAN_MAX_BUFFER, GFP_KERNEL);
+	if (ret < 0) {
+		dev_err(device, "%s: idr_alloc failed\n", __func__);
+		goto idr_alloc_failed;
+	}
+
+	buffer->id = ret;
+	buffer->request_size = size;
+	buffer->actual_size = ((size + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
+	buffer->device = device;
+	buffer->mem_ctx = ctx;
+	buffer->heap = heap;
+	INIT_LIST_HEAD(&buffer->mappings);
+	buffer->kptr = NULL;
+	buffer->priv = NULL;
+
+	ret = heap->ops->alloc(device, heap, buffer->actual_size, attr,
+		buffer);
+	if (ret) {
+		dev_err(device, "%s: heap %d alloc failed\n", __func__,
+			heap->id);
+		goto heap_alloc_failed;
+	}
+
+	*buffer_new = buffer;
+
+	dev_dbg(device, "%s heap %p ctx %p created buffer %d (%p) actual_size %lu\n",
+		__func__, heap, ctx, buffer->id, buffer, buffer->actual_size);
+	return 0;
+
+heap_alloc_failed:
+	idr_remove(ctx->buffers, buffer->id);
+idr_alloc_failed:
+	kfree(buffer);
+	return ret;
+}
+
+int img_mem_alloc(void *device, struct mem_ctx *ctx, int heap_id,
+		  unsigned long size, enum mem_attr attr, int *buf_id)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct heap *heap;
+	struct buffer *buffer;
+	int ret;
+
+	dev_dbg(device, "%s heap %d ctx %p size %lu\n", __func__, heap_id,
+		ctx, size);
+
+	ret = mutex_lock_interruptible_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+	if (ret)
+		return ret;
+
+	heap = idr_find(mem_man->heaps, heap_id);
+	if (!heap) {
+		dev_err(device, "%s: heap id %d not found\n", __func__,
+			heap_id);
+		mutex_unlock(mem_man->mutex);
+		return -EINVAL;
+	}
+
+	ret = _img_mem_alloc(device, ctx, heap, size, attr, &buffer);
+	if (ret) {
+		mutex_unlock(mem_man->mutex);
+		return ret;
+	}
+
+	*buf_id = buffer->id;
+	mutex_unlock(mem_man->mutex);
+
+	dev_dbg(device, "%s heap %d ctx %p created buffer %d (%p) size %lu\n",
+		__func__, heap_id, ctx, *buf_id, buffer, size);
+	return ret;
+}
+
+static int _img_mem_import(void *device, struct mem_ctx *ctx,
+			   unsigned long size, enum mem_attr attr, struct buffer **buffer_new)
+{
+	struct buffer *buffer;
+	int ret;
+
+	if (size == 0) {
+		dev_err(device, "%s: buffer size is zero\n", __func__);
+		return -EINVAL;
+	}
+
+	buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	ret = idr_alloc(ctx->buffers, buffer,
+			MEM_MAN_MIN_BUFFER, MEM_MAN_MAX_BUFFER, GFP_KERNEL);
+	if (ret < 0) {
+		dev_err(device, "%s: idr_alloc failed\n", __func__);
+		goto idr_alloc_failed;
+	}
+
+	buffer->id = ret;
+	buffer->request_size = size;
+	buffer->actual_size = ((size + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
+	buffer->device = device;
+	buffer->mem_ctx = ctx;
+	buffer->heap = NULL;
+	INIT_LIST_HEAD(&buffer->mappings);
+	buffer->kptr = NULL;
+	buffer->priv = NULL;
+
+	*buffer_new = buffer;
+
+	dev_dbg(device, "%s ctx %p created buffer %d (%p) actual_size %lu\n",
+		__func__, ctx, buffer->id, buffer, buffer->actual_size);
+	return 0;
+
+idr_alloc_failed:
+	kfree(buffer);
+	return ret;
+}
+
+int img_mem_import(void *device, struct mem_ctx *ctx,
+		   unsigned long size, enum mem_attr attr, int *buf_id)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct buffer *buffer;
+	int ret;
+
+	dev_dbg(device, "%s ctx %p size %lu\n", __func__, ctx, size);
+
+	ret = mutex_lock_interruptible_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+	if (ret)
+		return ret;
+
+	ret = _img_mem_import(device, ctx, size, attr, &buffer);
+	if (ret) {
+		mutex_unlock(mem_man->mutex);
+		return ret;
+	}
+
+	*buf_id = buffer->id;
+	mutex_unlock(mem_man->mutex);
+
+	dev_dbg(device, "%s ctx %p created buffer %d (%p) size %lu\n",
+		__func__, ctx, *buf_id, buffer, size);
+	return ret;
+}
+
+static void _img_mem_free(struct buffer *buffer)
+{
+	void *dev = buffer->device;
+	struct heap *heap = buffer->heap;
+	struct mem_ctx *ctx = buffer->mem_ctx;
+
+	if (!heap->ops || !heap->ops->free) {
+		dev_err(dev, "%s: no free function in heap %d!\n",
+			__func__, heap->id);
+		return;
+	}
+
+	while (!list_empty(&buffer->mappings)) {
+		struct mmu_ctx_mapping *map;
+
+		map = list_first_entry(&buffer->mappings,
+				       struct mmu_ctx_mapping, buffer_entry);
+		dev_warn(dev, "%s: found mapping for buffer %d (size %lu)\n",
+			 __func__, map->buffer->id, map->buffer->actual_size);
+
+		_img_mmu_unmap(map);
+
+		kfree(map);
+	}
+
+	heap->ops->free(heap, buffer);
+
+	idr_remove(ctx->buffers, buffer->id);
+}
+
+void img_mem_free(struct mem_ctx *ctx, int buff_id)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct buffer *buffer;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+
+	buffer = idr_find(ctx->buffers, buff_id);
+	if (!buffer) {
+		dev_err(mem_man->dev, "%s: buffer id %d not found\n",
+			__func__, buff_id);
+		mutex_unlock(mem_man->mutex);
+		return;
+	}
+
+	_img_mem_free(buffer);
+
+	mutex_unlock(mem_man->mutex);
+
+	kfree(buffer);
+}
+
+void img_mem_free_bufid(struct mem_ctx *ctx, int buff_id)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct buffer *buffer;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+
+	buffer = idr_find(ctx->buffers, buff_id);
+	if (!buffer) {
+		dev_err(mem_man->dev, "%s: buffer id %d not found\n",
+			__func__, buff_id);
+		mutex_unlock(mem_man->mutex);
+		return;
+	}
+
+	idr_remove(ctx->buffers, buffer->id);
+
+	mutex_unlock(mem_man->mutex);
+
+	kfree(buffer);
+}
+
+static int _img_mem_map_km(struct buffer *buffer)
+{
+	void *dev = buffer->device;
+	struct heap *heap = buffer->heap;
+
+	if (!heap->ops || !heap->ops->map_km) {
+		dev_err(dev, "%s: no map_km in heap %d!\n", __func__, heap->id);
+		return -EINVAL;
+	}
+
+	return heap->ops->map_km(heap, buffer);
+}
+
+int img_mem_map_km(struct mem_ctx *ctx, int buff_id)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct buffer *buffer;
+	int ret;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+	buffer = idr_find(ctx->buffers, buff_id);
+	if (!buffer) {
+		dev_err(mem_man->dev, "%s: buffer id %d not found\n",
+			__func__, buff_id);
+		mutex_unlock(mem_man->mutex);
+		return -EINVAL;
+	}
+
+	ret = _img_mem_map_km(buffer);
+
+	mutex_unlock(mem_man->mutex);
+
+	return ret;
+}
+
+void *img_mem_get_kptr(struct mem_ctx *ctx, int buff_id)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct buffer *buffer;
+	void *kptr;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+	buffer = idr_find(ctx->buffers, buff_id);
+	if (!buffer) {
+		dev_err(mem_man->dev, "%s: buffer id %d not found\n", __func__,
+			buff_id);
+		mutex_unlock(mem_man->mutex);
+		return NULL;
+	}
+	kptr = buffer->kptr;
+	mutex_unlock(mem_man->mutex);
+	return kptr;
+}
+
+static void _img_mem_sync_cpu_to_device(struct buffer *buffer)
+{
+	struct heap *heap = buffer->heap;
+
+	if (heap->ops && heap->ops->sync_cpu_to_dev)
+		heap->ops->sync_cpu_to_dev(heap, buffer);
+
+	/* sync to device memory */
+	mb();
+}
+
+int img_mem_sync_cpu_to_device(struct mem_ctx *ctx, int buff_id)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct buffer *buffer;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+	buffer = idr_find(ctx->buffers, buff_id);
+	if (!buffer) {
+		dev_err(mem_man->dev, "%s: buffer id %d not found\n", __func__,
+			buff_id);
+		mutex_unlock(mem_man->mutex);
+		return -EINVAL;
+	}
+
+	_img_mem_sync_cpu_to_device(buffer);
+
+	mutex_unlock(mem_man->mutex);
+	return 0;
+}
+
+static void _img_mem_sync_device_to_cpu(struct buffer *buffer)
+{
+	struct heap *heap = buffer->heap;
+
+	if (heap->ops && heap->ops->sync_dev_to_cpu)
+		heap->ops->sync_dev_to_cpu(heap, buffer);
+}
+
+int img_mem_sync_device_to_cpu(struct mem_ctx *ctx, int buff_id)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct buffer *buffer;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+	buffer = idr_find(ctx->buffers, buff_id);
+	if (!buffer) {
+		dev_err(mem_man->dev, "%s: buffer id %d not found\n", __func__,
+			buff_id);
+		mutex_unlock(mem_man->mutex);
+		return -EINVAL;
+	}
+
+	_img_mem_sync_device_to_cpu(buffer);
+
+	mutex_unlock(mem_man->mutex);
+	return 0;
+}
+
+static struct mmu_page_cfg *mmu_page_alloc(void *arg)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct mmu_ctx *mmu_ctx = arg;
+	struct mmu_page *page;
+	struct buffer *buffer;
+	struct heap *heap;
+	int ret;
+
+	dev_dbg(mmu_ctx->device, "%s:%d arg %p\n", __func__, __LINE__, arg);
+
+	WARN_ON(!mutex_is_locked(mem_man->mutex));
+
+	page = kzalloc(sizeof(*page), GFP_KERNEL);
+	if (!page)
+		return NULL;
+
+	ret = _img_mem_alloc(mmu_ctx->device, mmu_ctx->mem_ctx,
+			     mmu_ctx->heap, PAGE_SIZE, (enum mem_attr)0, &buffer);
+	if (ret) {
+		dev_err(mmu_ctx->device, "%s: img_mem_alloc failed (%d)\n",
+			__func__, ret);
+		goto free_page;
+	}
+
+	ret = _img_mem_map_km(buffer);
+	if (ret) {
+		dev_err(mmu_ctx->device, "%s: img_mem_map_km failed (%d)\n",
+			__func__, ret);
+		goto free_buffer;
+	}
+
+	page->addr_shift = mmu_ctx->mmu_config_addr_width - 32;
+	page->buffer = buffer;
+	page->page_cfg.cpu_virt_addr = (unsigned long)buffer->kptr;
+
+	heap = buffer->heap;
+	if (heap->ops && heap->ops->get_sg_table) {
+		void *sgt;
+
+		ret = heap->ops->get_sg_table(heap, buffer, &sgt);
+		if (ret) {
+			dev_err(mmu_ctx->device,
+				"%s: heap %d buffer %d no sg_table!\n",
+				__func__, heap->id, buffer->id);
+			ret = -EINVAL;
+			goto free_buffer;
+		}
+		page->page_cfg.phys_addr = sg_phys(img_mmu_get_sgl(sgt));
+	} else {
+		dev_err(mmu_ctx->device, "%s: heap %d buffer %d no get_sg!\n",
+			__func__, heap->id, buffer->id);
+		ret = -EINVAL;
+		goto free_buffer;
+	}
+
+	dev_dbg(mmu_ctx->device, "%s:%d virt addr %#lx\n", __func__, __LINE__,
+		page->page_cfg.cpu_virt_addr);
+	dev_dbg(mmu_ctx->device, "%s:%d phys addr %#llx\n", __func__, __LINE__,
+		page->page_cfg.phys_addr);
+	return &page->page_cfg;
+
+free_buffer:
+	_img_mem_free(buffer);
+	kfree(buffer);
+free_page:
+	kfree(page);
+	return NULL;
+}
+
+static void mmu_page_free(struct mmu_page_cfg *arg)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct mmu_page *page;
+
+	page = container_of(arg, struct mmu_page, page_cfg);
+
+	WARN_ON(!mutex_is_locked(mem_man->mutex));
+
+	_img_mem_free(page->buffer);
+	kfree(page->buffer);
+	kfree(page);
+}
+
+static void mmu_page_write(struct mmu_page_cfg *page_cfg,
+			   unsigned int offset, unsigned long long addr,
+			   unsigned int flags)
+{
+	unsigned int *mem = (unsigned int *)page_cfg->cpu_virt_addr;
+	struct mmu_page *mmu_page;
+	struct heap *heap;
+
+	mmu_page = container_of(page_cfg, struct mmu_page, page_cfg);
+	heap = mmu_page->buffer->heap;
+
+	/* skip translation when flags are zero, assuming address is invalid */
+	if (flags && heap->to_dev_addr)
+		addr = heap->to_dev_addr(&heap->options, addr);
+	addr >>= mmu_page->addr_shift;
+
+	mem[offset] = addr | flags;
+}
+
+static void mmu_update_page(struct mmu_page_cfg *arg)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct mmu_page *page;
+
+	page = container_of(arg, struct mmu_page, page_cfg);
+
+	WARN_ON(!mutex_is_locked(mem_man->mutex));
+
+	_img_mem_sync_cpu_to_device(page->buffer);
+}
+
+int img_mmu_ctx_create(void *device, unsigned int mmu_config_addr_width,
+		       struct mem_ctx *mem_ctx, int heap_id,
+		       void (*callback_fn)(enum mmu_callback_type type,
+					   int buff_id, void *data),
+		       void *callback_data, struct mmu_ctx **mmu_ctx)
+{
+	struct mem_man *mem_man = &mem_man_data;
+
+	static struct mmu_info mmu_functions = {
+		.pfn_page_alloc = mmu_page_alloc,
+		.pfn_page_free = mmu_page_free,
+		.pfn_page_write = mmu_page_write,
+		.pfn_page_update = mmu_update_page,
+	};
+	struct mmu_ctx *ctx;
+	int ret;
+
+	if (mmu_config_addr_width < 32) {
+		dev_err(device,
+			"%s: invalid addr_width (%d) must be >= 32 !\n",
+			__func__, mmu_config_addr_width);
+		return -EINVAL;
+	}
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->device = device;
+	ctx->mem_ctx = mem_ctx;
+	ctx->mmu_config_addr_width = mmu_config_addr_width;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+
+	ctx->heap = idr_find(mem_man->heaps, heap_id);
+	if (!ctx->heap) {
+		dev_err(device, "%s: invalid heap_id (%d)!\n", __func__,
+			heap_id);
+		mutex_unlock(mem_man->mutex);
+		kfree(ctx);
+		return -EINVAL;
+	}
+
+	mmu_functions.alloc_ctx = ctx;
+	ctx->mmu_dir = mmu_create_directory(&mmu_functions);
+	if (IS_ERR_VALUE((unsigned long)ctx->mmu_dir)) {
+		ret = (long)(ctx->mmu_dir);
+		dev_err(device, "%s: directory create failed (%d)!\n", __func__,
+			ret);
+		ctx->mmu_dir = NULL;
+		mutex_unlock(mem_man->mutex);
+		kfree(ctx);
+		return ret;
+	}
+
+	list_add(&ctx->mem_ctx_entry, &mem_ctx->mmu_ctxs);
+	INIT_LIST_HEAD(&ctx->mappings);
+
+	ctx->callback_fn = callback_fn;
+	ctx->callback_data = callback_data;
+
+	*mmu_ctx = ctx;
+
+	mutex_unlock(mem_man->mutex);
+
+	return 0;
+}
+
+static void _img_mmu_ctx_destroy(struct mmu_ctx *ctx)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	int ret;
+
+	while (!list_empty(&ctx->mappings)) {
+		struct mmu_ctx_mapping *map;
+
+		map = list_first_entry(&ctx->mappings,
+				       struct mmu_ctx_mapping, mmu_ctx_entry);
+#ifdef DEBUG_DECODER_DRIVER
+		dev_info(ctx->device,
+			 "%s: found mapped buffer %d (size %lu)\n",
+			 __func__, map->buffer->id, map->buffer->request_size);
+#endif
+
+		_img_mmu_unmap(map);
+
+		kfree(map);
+	}
+
+	ret = mmu_destroy_directory(ctx->mmu_dir);
+	if (ret)
+		dev_err(mem_man->dev, "mmu_destroy_directory failed (%d)!\n",
+			ret);
+	__list_del_entry(&ctx->mem_ctx_entry);
+}
+
+void img_mmu_ctx_destroy(struct mmu_ctx *ctx)
+{
+	struct mem_man *mem_man = &mem_man_data;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+	_img_mmu_ctx_destroy(ctx);
+	mutex_unlock(mem_man->mutex);
+
+	kfree(ctx);
+}
+
+int img_mmu_map_sg(struct mmu_ctx *mmu_ctx, struct mem_ctx *mem_ctx,
+		   int buff_id, void *sgt, unsigned int virt_addr,
+		   unsigned int map_flags)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct mmu_ctx_mapping *mapping;
+	struct mmu_heap_alloc heap_alloc;
+	struct buffer *buffer;
+	int ret = 0;
+
+	dev_dbg(mmu_ctx->device, "%s sgt %p virt_addr %#x\n", __func__,
+		sgt, virt_addr);
+
+	mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
+	if (!mapping)
+		return -ENOMEM;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+	buffer = idr_find(mem_ctx->buffers, buff_id);
+	if (!buffer) {
+		dev_err(mmu_ctx->device, "%s: buffer id %d not found\n",
+			__func__, buff_id);
+		ret = -EINVAL;
+		goto error;
+	}
+	dev_dbg(mmu_ctx->device, "%s buffer %d 0x%p size %lu virt_addr %#x\n",
+		__func__, buff_id, buffer, buffer->request_size, virt_addr);
+
+	heap_alloc.virt_addr = virt_addr;
+	heap_alloc.alloc_size = buffer->actual_size;
+
+	mapping->mmu_ctx = mmu_ctx;
+	mapping->buffer = buffer;
+	mapping->virt_addr = virt_addr;
+
+	if (sgt) {
+		struct sg_table *sgt_new = sgt;
+
+		mapping->map = mmu_directory_map_sg(mmu_ctx->mmu_dir, sgt_new->sgl,
+						    &heap_alloc, map_flags);
+		if (IS_ERR_VALUE((unsigned long)mapping->map)) {
+			ret = (long)(mapping->map);
+			mapping->map = NULL;
+		}
+	} else {
+		dev_err(mmu_ctx->device, "%s: buffer %d no get_sg!\n",
+			__func__, buffer->id);
+		ret = -EINVAL;
+		goto error;
+	}
+	if (ret) {
+		dev_err(mmu_ctx->device, "mmu_directory_map_sg failed (%d)!\n",
+			ret);
+		goto error;
+	}
+
+	list_add(&mapping->mmu_ctx_entry, &mmu_ctx->mappings);
+	list_add(&mapping->buffer_entry, &mapping->buffer->mappings);
+
+	if (mmu_ctx->callback_fn)
+		mmu_ctx->callback_fn(MMU_CALLBACK_MAP, buffer->id,
+				     mmu_ctx->callback_data);
+
+	mutex_unlock(mem_man->mutex);
+	return 0;
+
+error:
+	mutex_unlock(mem_man->mutex);
+	kfree(mapping);
+	return ret;
+}
+
+int img_mmu_map(struct mmu_ctx *mmu_ctx, struct mem_ctx *mem_ctx,
+		int buff_id, unsigned int virt_addr, unsigned int map_flags)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct mmu_ctx_mapping *mapping;
+	struct mmu_heap_alloc heap_alloc;
+	struct buffer *buffer;
+	struct heap *heap;
+	int ret;
+
+	dev_dbg(mmu_ctx->device, "%s buffer %d virt_addr %#x\n", __func__,
+		buff_id, virt_addr);
+
+	mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
+	if (!mapping)
+		return -ENOMEM;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+	buffer = idr_find(mem_ctx->buffers, buff_id);
+	if (!buffer) {
+		dev_err(mmu_ctx->device, "%s: buffer id %d not found\n",
+			__func__, buff_id);
+		ret = -EINVAL;
+		goto error;
+	}
+	dev_dbg(mmu_ctx->device, "%s buffer %d 0x%p size %lu virt_addr %#x\n",
+		__func__, buff_id, buffer, buffer->request_size, virt_addr);
+
+	heap_alloc.virt_addr = virt_addr;
+	heap_alloc.alloc_size = buffer->actual_size;
+
+	mapping->mmu_ctx = mmu_ctx;
+	mapping->buffer = buffer;
+	mapping->virt_addr = virt_addr;
+
+	heap = buffer->heap;
+	if (heap->ops && heap->ops->get_sg_table) {
+		void *sgt;
+
+		ret = heap->ops->get_sg_table(heap, buffer, &sgt);
+		if (ret) {
+			dev_err(mmu_ctx->device,
+				"%s: heap %d buffer %d no sg_table!\n",
+				__func__, heap->id, buffer->id);
+			goto error;
+		}
+
+		mapping->map = mmu_directory_map_sg(mmu_ctx->mmu_dir, img_mmu_get_sgl(sgt),
+						    &heap_alloc, map_flags);
+		if (IS_ERR_VALUE((unsigned long)mapping->map)) {
+			ret = (long)(mapping->map);
+			mapping->map = NULL;
+		}
+	} else {
+		dev_err(mmu_ctx->device, "%s: heap %d buffer %d no get_sg!\n",
+			__func__, heap->id, buffer->id);
+		ret = -EINVAL;
+		goto error;
+	}
+	if (ret) {
+		dev_err(mmu_ctx->device, "mmu_directory_map failed (%d)!\n",
+			ret);
+		goto error;
+	}
+
+	list_add(&mapping->mmu_ctx_entry, &mmu_ctx->mappings);
+	list_add(&mapping->buffer_entry, &mapping->buffer->mappings);
+
+	if (mmu_ctx->callback_fn)
+		mmu_ctx->callback_fn(MMU_CALLBACK_MAP, buffer->id,
+				     mmu_ctx->callback_data);
+
+	mutex_unlock(mem_man->mutex);
+	return 0;
+
+error:
+	mutex_unlock(mem_man->mutex);
+	kfree(mapping);
+	return ret;
+}
+
+static void _img_mmu_unmap(struct mmu_ctx_mapping *mapping)
+{
+	struct mmu_ctx *ctx = mapping->mmu_ctx;
+	int res;
+
+	dev_dbg(ctx->device, "%s:%d mapping %p buffer %d\n", __func__,
+		__LINE__, mapping, mapping->buffer->id);
+
+	res = mmu_directory_unmap(mapping->map);
+	if (res)
+		dev_warn(ctx->device, "mmu_directory_unmap failed (%d)!\n",
+			 res);
+
+	__list_del_entry(&mapping->mmu_ctx_entry);
+	__list_del_entry(&mapping->buffer_entry);
+
+	if (ctx->callback_fn)
+		ctx->callback_fn(MMU_CALLBACK_UNMAP, mapping->buffer->id,
+				 ctx->callback_data);
+}
+
+int img_mmu_unmap(struct mmu_ctx *mmu_ctx, struct mem_ctx *mem_ctx,
+		  int buff_id)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct mmu_ctx_mapping *mapping;
+	struct list_head *lst;
+
+	dev_dbg(mmu_ctx->device, "%s:%d buffer %d\n", __func__, __LINE__,
+		buff_id);
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+
+	mapping = NULL;
+	list_for_each(lst, &mmu_ctx->mappings) {
+		struct mmu_ctx_mapping *m;
+
+		m = list_entry(lst, struct mmu_ctx_mapping, mmu_ctx_entry);
+		if (m->buffer->id == buff_id) {
+			mapping = m;
+			break;
+		}
+	}
+
+	if (!mapping) {
+		dev_err(mmu_ctx->device, "%s: buffer id %d not found\n",
+			__func__, buff_id);
+		mutex_unlock(mem_man->mutex);
+		return -EINVAL;
+	}
+
+	_img_mmu_unmap(mapping);
+
+	mutex_unlock(mem_man->mutex);
+	kfree(mapping);
+	return 0;
+}
+
+int img_mmu_get_ptd(const struct mmu_ctx *ctx, unsigned int *ptd)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct mmu_page_cfg *page_cfg;
+	unsigned long long addr;
+
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+
+	page_cfg = mmu_directory_get_page(ctx->mmu_dir);
+	if (!page_cfg) {
+		mutex_unlock(mem_man->mutex);
+		return -EINVAL;
+	}
+
+	addr = page_cfg->phys_addr;
+	if (ctx->heap->to_dev_addr)
+		addr = ctx->heap->to_dev_addr(&ctx->heap->options, addr);
+
+	mutex_unlock(mem_man->mutex);
+
+	*ptd = (unsigned int)(addr >>= VXD_MMU_SHIFT);
+
+	dev_dbg(ctx->device, "%s: addr %#llx ptd %#x\n", __func__,
+		page_cfg->phys_addr, *ptd);
+	return 0;
+}
+
+int img_mmu_get_pagetable_entry(const struct mmu_ctx *ctx, unsigned long dev_virt_addr)
+{
+	if (!ctx)
+		return 0xFFFFFF;
+
+	return mmu_directory_get_pagetable_entry(ctx->mmu_dir, dev_virt_addr);
+}
+
+/*
+ * Initialisation
+ */
+int img_mem_init(void *dev)
+{
+	struct mem_man *mem_man = &mem_man_data;
+
+	mem_man->dev = dev;
+	mem_man->heaps = kzalloc(sizeof(*mem_man->heaps), GFP_KERNEL);
+	if (!mem_man->heaps)
+		return -ENOMEM;
+	idr_init(mem_man->heaps);
+	INIT_LIST_HEAD(&mem_man->mem_ctxs);
+	mem_man->mutex = kzalloc(sizeof(*mem_man->mutex), GFP_KERNEL);
+	if (!mem_man->mutex) {
+		pr_err("Memory allocation failed for mutex\n");
+		return -ENOMEM;
+	}
+	mutex_init(mem_man->mutex);
+
+	return 0;
+}
+
+void img_mem_exit(void)
+{
+	struct mem_man *mem_man = &mem_man_data;
+	struct heap *heap;
+	int heap_id;
+
+	/* keeps mutex checks (WARN_ON) happy, this will never actually wait */
+	mutex_lock_nested(mem_man->mutex, SUBCLASS_IMGMEM);
+
+	while (!list_empty(&mem_man->mem_ctxs)) {
+		struct mem_ctx *mc;
+
+		mc = list_first_entry(&mem_man->mem_ctxs,
+				      struct mem_ctx, mem_man_entry);
+		dev_warn(mem_man->dev, "%s derelict memory context %p!\n",
+			 __func__, mc);
+		_img_mem_destroy_ctx(mc);
+		kfree(mc);
+	}
+
+	heap_id = MIN_HEAP;
+	heap = idr_get_next(mem_man->heaps, &heap_id);
+	while (heap) {
+		dev_warn(mem_man->dev, "%s derelict heap %d!\n", __func__,
+			 heap_id);
+		_img_mem_del_heap(heap);
+		kfree(heap);
+		heap_id = MIN_HEAP;
+		heap = idr_get_next(mem_man->heaps, &heap_id);
+	}
+	idr_destroy(mem_man->heaps);
+	kfree(mem_man->heaps);
+
+	mutex_unlock(mem_man->mutex);
+
+	mutex_destroy(mem_man->mutex);
+	kfree(mem_man->mutex);
+	mem_man->mutex = NULL;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/img_mem_man.h b/drivers/media/platform/img/vxe-vxd/common/img_mem_man.h
--- a/drivers/media/platform/img/vxe-vxd/common/img_mem_man.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/img_mem_man.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,231 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG DEC Memory Manager header file
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _IMG_DEC_MEM_MGR_H
+#define _IMG_DEC_MEM_MGR_H
+
+#include <linux/types.h>
+
+/* buffer ids (per memory context) */
+#define MEM_MAN_MIN_BUFFER 1
+#define MEM_MAN_MAX_BUFFER 16384
+
+enum mem_attr {
+	MEM_ATTR_CACHED        = 0x00000001,
+	MEM_ATTR_UNCACHED      = 0x00000002,
+	MEM_ATTR_WRITECOMBINE  = 0x00000004,
+	MEM_ATTR_SECURE        = 0x00000010,
+	MEM_ATTR_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum mmu_callback_type {
+	MMU_CALLBACK_MAP = 1,
+	MMU_CALLBACK_UNMAP,
+	MMU_CALLBACK_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum heap_type {
+	MEM_HEAP_TYPE_UNIFIED = 1,
+	MEM_HEAP_TYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+union heap_options {
+	struct {
+		long long gfp_type; /* pool and flags for buffer allocations */
+	} unified;
+};
+
+/**
+ * struct heap_config - contains heap configuration structure
+ * @type: enumeration of heap_type
+ * @options: pool and flags for buffer allocations, eg GFP_KERNEL
+ * @to_dev_addr: function pointer for retrieving device addr
+ */
+struct heap_config {
+	enum heap_type type;
+	union heap_options options;
+	unsigned long long (*to_dev_addr)(union heap_options *opts, unsigned long long addr);
+};
+
+/*
+ * struct mmu_heap - typedef for mmu_heap
+ * @virt_addr_start: start of the device virtual address
+ * @alloc_atom: atom allocation in bytes
+ * @size: total size of the heap in bytes
+ */
+struct mmu_heap {
+	unsigned long	virt_addr_start;
+	unsigned long alloc_atom;
+	unsigned long size;
+};
+
+/*
+ * struct mem_ctx - the memory context
+ * @buffers: idr list of buffers
+ * @mmu_ctxs: contains linked lists of struct mmu_ctx
+ * @mem_man_entry: the entry list for dev_mem_main:mem_ctxs linked list
+ */
+struct mem_ctx {
+	struct idr *buffers;
+	struct list_head mmu_ctxs;
+	struct list_head mem_man_entry;
+};
+
+/*
+ * struct mmu_ctx_mapping - the mmu context mapping information
+ * @mmu_ctx: pointer to the mmu_ctx to which this mmu mapping information
+ *	     belongs
+ * @buffer: pointer to the buffer which this mmu_ctx_mapping is for
+ * @map: pointer to the mmu_map which this mmu_ctx_mapping belongs
+ * @virt_addr: Virtual address
+ * @mmu_ctx_entry: the entry list for mmu_ctx:mapping linked list.
+ * @buffer_entry: the entry list for buffer:mappings linked list.
+ */
+struct mmu_ctx_mapping {
+	struct mmu_ctx *mmu_ctx;
+	struct buffer *buffer;
+	struct mmu_map *map;
+	unsigned int virt_addr;
+	struct list_head mmu_ctx_entry;
+	struct list_head buffer_entry;
+};
+
+/*
+ * struct mmu_ctx - the mmu context information - one per stream
+ * @device: pointer to the device
+ * @mmu_config_addr_width: the address width for the mmu config
+ * @mem_ctx: pointer to mem_ctx where this mmu_ctx belongs to
+ * @heap: pointer to struct heap to where this mem_ctx belongs to
+ * @mmu_dir: pointer to the mmu_directory this mmu_ctx belongs to
+ * @mappings: contains linked list of struct mmu_ctx_mapping
+ * @mem_ctx_entry: the entry list for mem_ctx:mmu_ctxs
+ * @callback_fn: pointer to function callback
+ * @callback_data: pointer to the callback data
+ */
+struct mmu_ctx {
+	void *device;
+	unsigned int mmu_config_addr_width;
+	struct mem_ctx *mem_ctx;
+	struct heap *heap;
+	struct mmu_directory *mmu_dir;
+	struct list_head mappings;
+	struct list_head mem_ctx_entry;
+	void (*callback_fn)(enum mmu_callback_type type, int buff_id,
+			    void *data);
+	void *callback_data;
+};
+
+/*
+ * struct buffer - the mmu context information - one per stream
+ * @id: buffer identification
+ * @request_size: request size for the allocation
+ * @actual_size: size aligned with the PAGE_SIZE allocation
+ * @device: pointer to the device
+ * @mem_ctx: pointer to struct mem_ctx to where this buffer belongs to
+ * @heap: pointer to struct heap to where this buffer belongs to
+ * @mappings: contains linked lists of struct mmu_ctx_mapping
+ * @kptr: pointer to virtual mapping for the buffer object into kernel address
+ *	  space
+ * @priv: pointer to priv data used for scaterlist table info
+ */
+struct buffer {
+	int id; /* Generated in <mem_ctx:buffers> */
+	unsigned long request_size;
+	unsigned long actual_size;
+	void *device;
+	struct mem_ctx *mem_ctx;
+	struct heap *heap;
+	struct list_head mappings; /* contains <struct mmu_ctx_mapping> */
+	void *kptr;
+	void *priv;
+};
+
+struct heap_ops {
+	int (*alloc)(void *device, struct heap *heap,
+		     unsigned long size, enum mem_attr attr,
+		     struct buffer *buffer);
+	void (*free)(struct heap *heap, struct buffer *buffer);
+	int (*map_km)(struct heap *heap, struct buffer *buffer);
+	int (*get_sg_table)(struct heap *heap, struct buffer *buffer,
+			    void **sg_table);
+	void (*sync_cpu_to_dev)(struct heap *heap, struct buffer *buffer);
+	void (*sync_dev_to_cpu)(struct heap *heap, struct buffer *buffer);
+	void (*destroy)(struct heap *heap);
+};
+
+struct heap {
+	int id; /* Generated in <mem_man:heaps> */
+	enum heap_type type;
+	struct heap_ops *ops;
+	union heap_options options;
+	unsigned long long (*to_dev_addr)(union heap_options *opts, unsigned long long addr);
+	void *priv;
+};
+
+int img_mem_init(void *dev);
+void img_mem_exit(void);
+
+int img_mem_create_ctx(struct mem_ctx **new_ctx);
+void img_mem_destroy_ctx(struct mem_ctx *ctx);
+
+int img_mem_import(void *device, struct mem_ctx *ctx,
+		   unsigned long size, enum mem_attr attr, int *buf_id);
+
+int img_mem_alloc(void *device, struct mem_ctx *ctx, int heap_id,
+		  unsigned long size, enum mem_attr attributes, int *buf_id);
+void img_mem_free(struct mem_ctx *ctx, int buff_id);
+
+void img_mem_free_bufid(struct mem_ctx *ctx, int buf_id);
+
+int img_mem_map_km(struct mem_ctx *ctx, int buf_id);
+void *img_mem_get_kptr(struct mem_ctx *ctx, int buff_id);
+
+int img_mem_sync_cpu_to_device(struct mem_ctx *ctx, int buf_id);
+int img_mem_sync_device_to_cpu(struct mem_ctx *ctx, int buf_id);
+
+int img_mmu_ctx_create(void *device, unsigned int mmu_config_addr_width,
+		       struct mem_ctx *mem_ctx, int heap_id,
+		       void (*callback_fn)(enum mmu_callback_type type,
+					   int buff_id, void *data),
+		       void *callback_data, struct mmu_ctx **mmu_ctx);
+void img_mmu_ctx_destroy(struct mmu_ctx *ctx);
+
+int img_mmu_map(struct mmu_ctx *mmu_ctx, struct mem_ctx *mem_ctx,
+		int buff_id, unsigned int virt_addr, unsigned int map_flags);
+int img_mmu_map_sg(struct mmu_ctx *mmu_ctx, struct mem_ctx *mem_ctx,
+		   int buff_id, void *sgt, unsigned int virt_addr,
+		   unsigned int map_flags);
+int img_mmu_unmap(struct mmu_ctx *mmu_ctx, struct mem_ctx *mem_ctx,
+		  int buff_id);
+
+int img_mmu_get_ptd(const struct mmu_ctx *ctx, unsigned int *ptd);
+
+int img_mmu_get_pagetable_entry(const struct mmu_ctx *ctx, unsigned long dev_virt_addr);
+
+int img_mem_add_heap(const struct heap_config *heap_cfg, int *heap_id);
+void img_mem_del_heap(int heap_id);
+
+/* Heap operation related function */
+int img_mem_unified_init(const struct heap_config *config,
+			 struct heap *heap);
+
+/* page and sg list related functions */
+void img_mmu_get_pages(void **page_args, void *sgt_args);
+unsigned int img_mmu_get_orig_nents(void *sgt_args);
+void img_mmu_set_sgt_nents(void *sgt_args, int ret);
+void img_mmu_set_sg_table(void **sg_table_args, void *buffer);
+unsigned int img_mmu_get_sgl_length(void *sgl_args);
+void *img_mmu_get_sgl(void *sgt_args);
+
+#endif /* _IMG_DEC_MEM_MGR */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/img_mem_unified.c b/drivers/media/platform/img/vxe-vxd/common/img_mem_unified.c
--- a/drivers/media/platform/img/vxe-vxd/common/img_mem_unified.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/img_mem_unified.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,276 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMG DEC Memory Manager for unified memory
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "img_mem_man.h"
+
+void img_mmu_get_pages(void **page_args, void *sgt_args)
+{
+	struct page **pages = (struct page **)page_args;
+	struct sg_table *sgt = sgt_args;
+	struct scatterlist *sgl = sgt->sgl;
+	int i;
+
+	i = 0;
+	while (sgl) {
+		pages[i++] = sg_page(sgl);
+		sgl = sg_next(sgl);
+	}
+}
+
+unsigned int img_mmu_get_orig_nents(void *sgt_args)
+{
+	struct sg_table *sgt = sgt_args;
+
+	return sgt->orig_nents;
+}
+
+void img_mmu_set_sgt_nents(void *sgt_args, int ret)
+{
+	struct sg_table *sgt = sgt_args;
+
+	sgt->nents = ret;
+}
+
+void img_mmu_set_sg_table(void **sg_table_args, void *buffer)
+{
+	struct sg_table **sg_table = (struct sg_table **)sg_table_args;
+
+	*sg_table = buffer;
+}
+
+unsigned int img_mmu_get_sgl_length(void *sgl_args)
+{
+	struct scatterlist *sgl = (struct scatterlist *)sgl_args;
+
+	return sgl->length;
+}
+
+void *img_mmu_get_sgl(void *sgt_args)
+{
+	struct sg_table *sgt = sgt_args;
+
+	return sgt->sgl;
+}
+
+static int unified_alloc(void *device, struct heap *heap,
+			 unsigned long size, enum mem_attr attr,
+			 struct buffer *buffer)
+{
+	struct sg_table *sgt;
+	void *sgl;
+	int pages;
+	int ret;
+
+	dev_dbg(device, "%s:%d buffer %d (0x%p)\n", __func__, __LINE__,
+		buffer->id, buffer);
+
+	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+	if (!sgt)
+		return -ENOMEM;
+
+	pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+
+	ret = sg_alloc_table(sgt, pages, GFP_KERNEL);
+	if (ret)
+		goto sg_alloc_table_failed;
+
+	sgl = img_mmu_get_sgl(sgt);
+	while (sgl) {
+		void *page;
+		unsigned long long dma_addr;
+
+		page = alloc_page(heap->options.unified.gfp_type);
+		if (!page) {
+			dev_err(device, "%s alloc_page failed!\n", __func__);
+			ret = -ENOMEM;
+			goto alloc_page_failed;
+		}
+
+		/*
+		 * dma_map_page() is probably going to fail if alloc flags are
+		 * GFP_HIGHMEM, since it is not mapped to CPU. Hopefully, this
+		 * will never happen because memory of this sort cannot be used
+		 * for DMA anyway. To check if this is the case, build with
+		 * debug, set trace_physical_pages=1 and check if page_address
+		 * printed above is NULL
+		 */
+		dma_addr = dma_map_page(device, page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
+		if (dma_mapping_error(device, dma_addr)) {
+			__free_page(page);
+			dev_err(device, "%s dma_map_page failed!\n", __func__);
+			ret = -EIO;
+			goto alloc_page_failed;
+		}
+		dma_unmap_page(device, dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
+
+		sg_set_page(sgl, page, PAGE_SIZE, 0);
+
+		sgl = sg_next(sgl);
+	}
+
+	buffer->priv = sgt;
+	return 0;
+
+alloc_page_failed:
+	sgl = img_mmu_get_sgl(sgt);
+	while (sgl) {
+		void *page = sg_page(sgl);
+
+		if (page)
+			__free_page(page);
+
+		sgl = sg_next(sgl);
+	}
+	sg_free_table(sgt);
+sg_alloc_table_failed:
+	kfree(sgt);
+	return ret;
+}
+
+static void unified_free(struct heap *heap, struct buffer *buffer)
+{
+	void *dev = buffer->device;
+	void *sgt = buffer->priv;
+	void *sgl;
+
+	dev_dbg(dev, "%s:%d buffer %d (0x%p)\n", __func__, __LINE__,
+		buffer->id, buffer);
+
+	if (buffer->kptr) {
+		dev_dbg(dev, "%s vunmap 0x%p\n", __func__, buffer->kptr);
+		dma_unmap_sg(dev, img_mmu_get_sgl(sgt), img_mmu_get_orig_nents(sgt),
+			     DMA_FROM_DEVICE);
+		vunmap(buffer->kptr);
+	}
+
+	sgl = img_mmu_get_sgl(sgt);
+	while (sgl) {
+		__free_page(sg_page(sgl));
+		sgl = sg_next(sgl);
+	}
+	sg_free_table(sgt);
+	kfree(sgt);
+}
+
+static int unified_map_km(struct heap *heap, struct buffer *buffer)
+{
+	void *dev = buffer->device;
+	void *sgt = buffer->priv;
+	void *sgl = img_mmu_get_sgl(sgt);
+	unsigned int num_pages = sg_nents(sgl);
+	unsigned int orig_nents = img_mmu_get_orig_nents(sgt);
+	void **pages;
+	int ret;
+	pgprot_t prot;
+
+	dev_dbg(dev, "%s:%d buffer %d (0x%p)\n", __func__, __LINE__, buffer->id, buffer);
+
+	if (buffer->kptr) {
+		dev_warn(dev, "%s called for already mapped buffer %d\n", __func__, buffer->id);
+		return 0;
+	}
+
+	pages = kmalloc_array(num_pages, sizeof(void *), GFP_KERNEL);
+	if (!pages)
+		return -ENOMEM;
+
+	img_mmu_get_pages(pages, sgt);
+
+	prot = PAGE_KERNEL;
+	prot = pgprot_writecombine(prot);
+	buffer->kptr = vmap((struct page **)pages, num_pages, VM_MAP, prot);
+	kfree(pages);
+	if (!buffer->kptr) {
+		dev_err(dev, "%s vmap failed!\n", __func__);
+		return -EFAULT;
+	}
+
+	ret = dma_map_sg(dev, sgl, orig_nents, DMA_FROM_DEVICE);
+
+	if (ret <= 0) {
+		dev_err(dev, "%s dma_map_sg failed!\n", __func__);
+		vunmap(buffer->kptr);
+		return -EFAULT;
+	}
+	dev_dbg(dev, "%s:%d buffer %d orig_nents %d nents %d\n", __func__,
+		__LINE__, buffer->id, orig_nents, ret);
+
+	img_mmu_set_sgt_nents(sgt, ret);
+
+	dev_dbg(dev, "%s:%d buffer %d vmap to 0x%p\n", __func__, __LINE__,
+		buffer->id, buffer->kptr);
+
+	return 0;
+}
+
+static int unified_get_sg_table(struct heap *heap, struct buffer *buffer, void **sg_table)
+{
+	img_mmu_set_sg_table(sg_table, buffer->priv);
+	return 0;
+}
+
+static void unified_sync_cpu_to_dev(struct heap *heap, struct buffer *buffer)
+{
+	void *dev = buffer->device;
+	void *sgt = buffer->priv;
+
+	if (!buffer->kptr)
+		return;
+
+	dev_dbg(dev, "%s:%d buffer %d (0x%p)\n", __func__, __LINE__, buffer->id, buffer);
+
+	dma_sync_sg_for_device(dev, img_mmu_get_sgl(sgt), img_mmu_get_orig_nents(sgt),
+			       DMA_TO_DEVICE);
+}
+
+static void unified_sync_dev_to_cpu(struct heap *heap, struct buffer *buffer)
+{
+	void *dev = buffer->device;
+	void *sgt = buffer->priv;
+
+	if (!buffer->kptr)
+		return;
+
+	dev_dbg(dev, "%s:%d buffer %d (0x%p)\n", __func__, __LINE__,
+		buffer->id, buffer);
+
+	dma_sync_sg_for_cpu(dev, img_mmu_get_sgl(sgt), img_mmu_get_orig_nents(sgt),
+			    DMA_FROM_DEVICE);
+}
+
+static void unified_heap_destroy(struct heap *heap)
+{
+}
+
+static struct heap_ops unified_heap_ops = {
+	.alloc = unified_alloc,
+	.free = unified_free,
+	.map_km = unified_map_km,
+	.get_sg_table = unified_get_sg_table,
+	.sync_cpu_to_dev = unified_sync_cpu_to_dev,
+	.sync_dev_to_cpu = unified_sync_dev_to_cpu,
+	.destroy = unified_heap_destroy,
+};
+
+int img_mem_unified_init(const struct heap_config *heap_cfg,
+			 struct heap *heap)
+{
+	heap->ops = &unified_heap_ops;
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/imgmmu.c b/drivers/media/platform/img/vxe-vxd/common/imgmmu.c
--- a/drivers/media/platform/img/vxe-vxd/common/imgmmu.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/imgmmu.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,782 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMG DEC MMU function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include "img_mem_man.h"
+#include "imgmmu.h"
+
+/**
+ * struct mmu_directory - the MMU directory information
+ * @dir_page: pointer to the mmu_page_cfg_table (physical table used) which
+ *	      this mmu_directory belongs to
+ * @dir_page_table: All the page table structures in a static array of pointers
+ * @mmu_info_cfg: Functions to use to manage pages allocation, liberation and
+ *		  writing
+ * @num_mapping: number of mapping using this directory
+ */
+struct mmu_directory {
+	struct mmu_page_cfg *dir_page;
+	struct mmu_page_cfg_table **dir_page_table;
+	struct mmu_info mmu_info_cfg;
+	unsigned int num_mapping;
+};
+
+/*
+ * struct mmu_map - the MMU mapping information
+ * @mmu_dir: pointer to the mmu_directory which this mmu_map belongs to
+ * @dev_virt_addr: device virtual address root associated with this mapping
+ * @used_flag: flag used when allocating
+ * @n_entries: number of entries mapped
+ */
+struct mmu_map {
+	struct mmu_directory *mmu_dir;
+	struct mmu_heap_alloc dev_virt_addr;
+	unsigned int used_flag;
+	unsigned int n_entries;
+};
+
+/*
+ * struct mmu_page_cfg_table - the MMU page table information.
+ *			       One page table of the directory.
+ * @mmu_dir: pointer to the mmu_directory which this mmu_page_cfg_table
+ *	     belongs to
+ * @page: page used to store this mapping in the MMU
+ * @valid_entries: number of valid entries in this page
+ */
+struct mmu_page_cfg_table {
+	struct mmu_directory *mmu_dir;
+	struct mmu_page_cfg *page;
+	unsigned int valid_entries;
+};
+
+/*
+ * mmu_pgt_destroy() - Destruction of a page table (does not follow the
+ *                     child pointer)
+ * @pgt: pointer to the MMU page table information
+ *
+ * Warning: Does not verify if pages are still valid or not
+ */
+static void mmu_pgt_destroy(struct mmu_page_cfg_table *pgt)
+{
+	if (!pgt->mmu_dir ||
+	    !pgt->mmu_dir->mmu_info_cfg.pfn_page_free ||
+	    !pgt->page) {
+		return;
+	}
+
+	pr_debug("%s:%d Destroy page table (phys addr %llu)\n",
+		 __func__, __LINE__, pgt->page->phys_addr);
+
+	pgt->mmu_dir->mmu_info_cfg.pfn_page_free(pgt->page);
+	pgt->page = NULL;
+
+	kfree(pgt);
+}
+
+/*
+ * mmu_dir_entry() - Extact the directory index from a virtual address
+ * @vaddr: virtual address
+ */
+static inline unsigned int mmu_dir_entry(unsigned long vaddr)
+{
+	return (unsigned int)((vaddr & VIRT_DIR_IDX_MASK) >> MMU_DIR_SHIFT);
+}
+
+/*
+ * mmu_pg_entry() - Extract the page table index from a virtual address
+ * @vaddr: virtual address
+ */
+static inline unsigned int mmu_pg_entry(unsigned long vaddr)
+{
+	return (unsigned int)((vaddr & VIRT_PAGE_TBL_MASK) >> MMU_PAGE_SHIFT);
+}
+
+/*
+ * mmu_pg_wr() - Default function used when a mmu_info structure has an empty
+ *		 pfn_page_write pointer
+ * @mmu_page: pointer to the mmu_page to update
+ * @offset: offset into the directory
+ * @pa_to_write: physical address value to add to the entr
+ * @mmu_flag: mmu flag(s) to set
+ */
+static void mmu_pg_wr(struct mmu_page_cfg *mmu_page, unsigned int offset,
+		      unsigned long long pa_to_write, unsigned int mmu_flag)
+{
+	unsigned int *dir_mem = NULL;
+	unsigned long long cur_pa = pa_to_write;
+
+	if (!mmu_page)
+		return;
+
+	dir_mem = (unsigned int *)mmu_page->cpu_virt_addr;
+	/*
+	 * assumes that the MMU HW has the extra-bits enabled (this default
+	 * function has no way of knowing)
+	 */
+	if ((MMU_PHYS_SIZE - MMU_VIRT_SIZE) > 0)
+		cur_pa >>= (MMU_PHYS_SIZE - MMU_VIRT_SIZE);
+	/*
+	 * The MMU_PAGE_SHIFT bottom bits should be masked because page
+	 * allocation.
+	 * MMU_PAGE_SHIFT-(MMU_PHYS_SIZE-MMU_VIRT_SIZE) are used for
+	 * flags so it's ok
+	 */
+	dir_mem[offset] = (unsigned int)cur_pa | (mmu_flag);
+}
+
+/*
+ * mmu_page_cfg_table() - Create a page table
+ * @mmu_dir: pointer to the mmu_directory in which to create the new page table
+ *	     structure
+ *
+ * Return: A pointer to the new page table structure in case of success.
+ *	   (void *) in case of error
+ */
+static struct mmu_page_cfg_table *mmu_pgt_create(struct mmu_directory *mmu_dir)
+{
+	struct mmu_page_cfg_table *neo = NULL;
+	unsigned int i;
+
+	if (!mmu_dir || !mmu_dir->mmu_info_cfg.pfn_page_alloc ||
+	    !mmu_dir->mmu_info_cfg.pfn_page_write)
+		return (void *)(-EINVAL);
+
+	neo = kmalloc(sizeof(*neo), GFP_KERNEL);
+	if (!neo)
+		return (void *)(-ENOMEM);
+
+	neo->mmu_dir = mmu_dir;
+
+	neo->page =
+		mmu_dir->mmu_info_cfg.pfn_page_alloc(mmu_dir->mmu_info_cfg.alloc_ctx);
+	if (!neo->page) {
+		pr_err("%s:%d failed to allocate Page Table physical page\n",
+		       __func__, __LINE__);
+		kfree(neo);
+		return (void *)(-ENOMEM);
+	}
+	pr_debug("%s:%d Create page table (phys addr 0x%llx CPU Virt 0x%lx)\n",
+		 __func__, __LINE__, neo->page->phys_addr,
+			neo->page->cpu_virt_addr);
+
+	/* invalidate all pages */
+	for (i = 0; i < MMU_N_PAGE; i++) {
+		mmu_dir->mmu_info_cfg.pfn_page_write(neo->page, i, 0,
+				MMU_FLAG_INVALID);
+	}
+
+	/*
+	 * When non-UMA need to update the device memory after setting
+	 * it to 0
+	 */
+	if (mmu_dir->mmu_info_cfg.pfn_page_update)
+		mmu_dir->mmu_info_cfg.pfn_page_update(neo->page);
+
+	return neo;
+}
+
+/*
+ * mmu_create_directory - Create a directory entry based on a given directory
+ *			  configuration
+ * @mmu_info_ops: contains the functions to use to manage page table memory.
+ *		  Is copied and not modified.
+ *
+ * @warning Obviously creation of the directory allocates memory - do not call
+ * while interrupts are disabled
+ *
+ * @return The opaque handle to the mmu_directory object and result to 0
+ * @return (void *) in case of an error and result has the value:
+ * @li -EINVAL if mmu_info configuration is NULL or does not
+ * contain function pointers
+ * @li -ENOMEM if an internal allocation failed
+ * @li -ENOMEM if the given mmu_pfn_page_alloc returned NULL
+ */
+struct mmu_directory *mmu_create_directory(const struct mmu_info *mmu_info_ops)
+{
+	struct mmu_directory *neo = NULL;
+	unsigned int i;
+
+	/*
+	 * invalid information in the directory config:
+	 * - invalid page allocator and dealloc (page write can be NULL)
+	 * - invalid virtual address representation
+	 * - invalid page size
+	 * - invalid MMU size
+	 */
+	if (!mmu_info_ops || !mmu_info_ops->pfn_page_alloc || !mmu_info_ops->pfn_page_free) {
+		pr_err("%s:%d invalid MMU configuration\n", __func__, __LINE__);
+		return (void *)(-EINVAL);
+	}
+
+	neo = kzalloc(sizeof(*neo), GFP_KERNEL);
+	if (!neo)
+		return (void *)(-ENOMEM);
+
+	neo->dir_page_table = kcalloc(MMU_N_TABLE, sizeof(struct mmu_page_cfg_table *),
+				      GFP_KERNEL);
+	if (!neo->dir_page_table) {
+		kfree(neo);
+		return (void *)(-ENOMEM);
+	}
+
+	memcpy(&neo->mmu_info_cfg, mmu_info_ops, sizeof(struct mmu_info));
+	if (!mmu_info_ops->pfn_page_write) {
+		pr_debug("%s:%d using default MMU write\n", __func__, __LINE__);
+		/* use internal function */
+		neo->mmu_info_cfg.pfn_page_write = &mmu_pg_wr;
+	}
+
+	neo->dir_page = mmu_info_ops->pfn_page_alloc(mmu_info_ops->alloc_ctx);
+	if (!neo->dir_page) {
+		kfree(neo->dir_page_table);
+		kfree(neo);
+		return (void *)(-ENOMEM);
+	}
+
+	pr_debug("%s:%d (phys page 0x%llx; CPU virt 0x%lx)\n", __func__,
+		 __LINE__, neo->dir_page->phys_addr,
+			neo->dir_page->cpu_virt_addr);
+	/* now we have a valid mmu_directory structure */
+
+	/* invalidate all entries */
+	for (i = 0; i < MMU_N_TABLE; i++) {
+		neo->mmu_info_cfg.pfn_page_write(neo->dir_page, i, 0,
+				MMU_FLAG_INVALID);
+	}
+
+	/* when non-UMA need to update the device memory */
+	if (neo->mmu_info_cfg.pfn_page_update)
+		neo->mmu_info_cfg.pfn_page_update(neo->dir_page);
+
+	return neo;
+}
+
+/*
+ * mmu_destroy_directory - Destroy the mmu_directory - assumes that the HW is
+ *			   not going to access the memory any-more
+ * @mmu_dir: pointer to the mmu directory to destroy
+ *
+ * Does not invalidate any memory because it assumes that everything is not
+ * used any-more
+ */
+int mmu_destroy_directory(struct mmu_directory *mmu_dir)
+{
+	unsigned int i;
+
+	if (!mmu_dir) {
+		/* could be an assert */
+		pr_err("%s:%d mmu_dir is NULL\n", __func__, __LINE__);
+		return -EINVAL;
+	}
+
+	if (mmu_dir->num_mapping > 0)
+		/* mappings should have been destroyed! */
+		pr_err("%s:%d directory still has %u mapping attached to it\n",
+		       __func__, __LINE__, mmu_dir->num_mapping);
+	/*
+	 * not exiting because clearing the page table map is more
+	 * important than losing a few structures
+	 */
+
+	if (!mmu_dir->mmu_info_cfg.pfn_page_free || !mmu_dir->dir_page_table)
+		return -EINVAL;
+
+	pr_debug("%s:%d destroy MMU dir (phys page 0x%llx)\n",
+		 __func__, __LINE__, mmu_dir->dir_page->phys_addr);
+
+	/* first we destroy the directory entry */
+	mmu_dir->mmu_info_cfg.pfn_page_free(mmu_dir->dir_page);
+	mmu_dir->dir_page = NULL;
+
+	/* destroy every mapping that still exists */
+	for (i = 0; i < MMU_N_TABLE; i++) {
+		if (mmu_dir->dir_page_table[i]) {
+			mmu_pgt_destroy(mmu_dir->dir_page_table[i]);
+			mmu_dir->dir_page_table[i] = NULL;
+		}
+	}
+
+	kfree(mmu_dir->dir_page_table);
+	kfree(mmu_dir);
+	return 0;
+}
+
+/*
+ * mmu_directory_get_page - Get access to the page table structure used in the
+ *			    directory (to be able to write it to registers)
+ * @mmu_dir: pointer to the mmu directory. asserts if mmu_dir is NULL
+ *
+ * @return the page table structure used
+ */
+struct mmu_page_cfg *mmu_directory_get_page(struct mmu_directory *mmu_dir)
+{
+	if (!mmu_dir)
+		return NULL;
+
+	return mmu_dir->dir_page;
+}
+
+static struct mmu_map *mmu_directory_map(struct mmu_directory *mmu_dir,
+					 const struct mmu_heap_alloc *dev_va,
+					 unsigned int ui_map_flags,
+					 int (*phys_iter_next)(void *arg,
+							       unsigned long long *next),
+					 void *phys_iter_arg)
+{
+	unsigned int first_dir = 0;
+	unsigned int first_pg = 0;
+	unsigned int dir_off = 0;
+	unsigned int pg_off = 0;
+	unsigned int n_entries = 0;
+	unsigned int i;
+	unsigned int d;
+	const unsigned int duplicate = PAGE_SIZE / mmu_get_page_size();
+	int res = 0;
+	struct mmu_map *neo = NULL;
+	struct mmu_page_cfg_table **dir_pgtbl = NULL;
+
+	/*
+	 * in non UMA updates on pages needs to be done - store index of
+	 * directory entry pages to update
+	 */
+	unsigned int *to_update;
+	/*
+	 * number of pages in to_update (will be at least 1 for the first_pg to
+	 * update)
+	 */
+	unsigned int n_pgs_to_update = 0;
+	/*
+	 * to know if we also need to update the directory page (creation of new
+	 * page)
+	 */
+	unsigned char dir_modified = FALSE;
+
+	if (!mmu_dir || !dev_va || duplicate < 1)
+		return (void *)(-EINVAL);
+
+	dir_pgtbl = mmu_dir->dir_page_table;
+
+	n_entries = dev_va->alloc_size / PAGE_SIZE;
+	if (dev_va->alloc_size % MMU_PAGE_SIZE != 0 || n_entries == 0) {
+		pr_err("%s:%d invalid allocation size\n", __func__, __LINE__);
+		return (void *)(-EINVAL);
+	}
+
+	if ((ui_map_flags & MMU_FLAG_VALID) != 0) {
+		pr_err("%s:%d valid flag (0x%x) is set in the falgs 0x%x\n",
+		       __func__, __LINE__, MMU_FLAG_VALID, ui_map_flags);
+		return (void *)(-EINVAL);
+	}
+
+	/*
+	 * has to be dynamically allocated because it is bigger than 1k (max
+	 * stack in the kernel)
+	 * MMU_N_TABLE is 1024 for 4096B pages, that's a 4k allocation (1 page)
+	 *  - if it gets bigger may IMG_BIGALLOC should be used
+	 */
+	to_update = kcalloc(MMU_N_TABLE, sizeof(unsigned int), GFP_KERNEL);
+	if (!to_update)
+		return (void *)(-ENOMEM);
+
+	/* manage multiple page table mapping */
+
+	first_dir = mmu_dir_entry(dev_va->virt_addr);
+	first_pg = mmu_pg_entry(dev_va->virt_addr);
+
+	if (first_dir >= MMU_N_TABLE || first_pg >= MMU_N_PAGE) {
+		kfree(to_update);
+		return (void *)(-EINVAL);
+	}
+
+	/* verify that the pages that should be used are available */
+	dir_off = first_dir;
+	pg_off = first_pg;
+
+	/*
+	 * loop over the number of entries given by CPU allocator but CPU page
+	 * size can be > than MMU page size therefore it may need to "duplicate"
+	 * entries by creating a fake physical address
+	 */
+	for (i = 0; i < n_entries * duplicate; i++) {
+		if (pg_off >= MMU_N_PAGE) {
+			dir_off++; /* move to next directory */
+			if (dir_off >= MMU_N_TABLE) {
+				res = -EINVAL;
+				break;
+			}
+			pg_off = 0; /* using its first page */
+		}
+
+		/*
+		 * if dir_pgtbl[dir_off] == NULL not yet
+		 * allocated it means all entries are available
+		 */
+		if (dir_pgtbl[dir_off]) {
+			/*
+			 * inside a pagetable - verify that the required offset
+			 * is invalid
+			 */
+			struct mmu_page_cfg_table *tbl = dir_pgtbl[dir_off];
+			unsigned int *page_mem = (unsigned int *)tbl->page->cpu_virt_addr;
+
+			if ((page_mem[pg_off] & MMU_FLAG_VALID) != 0) {
+				pr_err("%s:%d one of the required page is currently in use\n",
+				       __func__, __LINE__);
+				res = -EPERM;
+				break;
+			}
+		}
+		/* PageTable struct exists */
+		pg_off++;
+	} /* for all needed entries */
+
+	/* it means one entry was not invalid or not enough page were given */
+	if (res != 0) {
+		/*
+		 * message already printed
+		 * IMG_ERROR_MEMORY_IN_USE when an entry is not invalid
+		 * IMG_ERROR_INVALID_PARAMETERS when not enough pages are given
+		 *  (or too much)
+		 */
+		kfree(to_update);
+		return (void *)(unsigned long)(res);
+	}
+
+	neo = kmalloc(sizeof(*neo), GFP_KERNEL);
+	if (!neo) {
+		kfree(to_update);
+		return (void *)(-ENOMEM);
+	}
+	neo->mmu_dir = mmu_dir;
+	neo->dev_virt_addr = *dev_va;
+	memcpy(&neo->dev_virt_addr, dev_va, sizeof(struct mmu_heap_alloc));
+	neo->used_flag = ui_map_flags;
+
+	/* we now know that all pages are available */
+	dir_off = first_dir;
+	pg_off = first_pg;
+
+	to_update[n_pgs_to_update] = first_dir;
+	n_pgs_to_update++;
+
+	for (i = 0; i < n_entries; i++) {
+		unsigned long long cur_phys_addr;
+
+		if (phys_iter_next(phys_iter_arg, &cur_phys_addr) != 0) {
+			pr_err("%s:%d not enough entries in physical address array\n",
+			       __func__, __LINE__);
+			kfree(neo);
+			kfree(to_update);
+			return (void *)(-EBUSY);
+		}
+		for (d = 0; d < duplicate; d++) {
+			if (pg_off >= MMU_N_PAGE) {
+				/* move to next directory */
+				dir_off++;
+				/* using its first page */
+				pg_off = 0;
+
+				to_update[n_pgs_to_update] = dir_off;
+				n_pgs_to_update++;
+			}
+
+			/* this page table object does not exists, create it */
+			if (!dir_pgtbl[dir_off]) {
+				dir_pgtbl[dir_off] = mmu_pgt_create(mmu_dir);
+				if (IS_ERR_VALUE((unsigned long)dir_pgtbl[dir_off])) {
+					dir_pgtbl[dir_off] = NULL;
+					goto cleanup_fail;
+				}
+				/*
+				 * make this page table valid
+				 * should be dir_off
+				 */
+				mmu_dir->mmu_info_cfg.pfn_page_write(mmu_dir->dir_page,
+						dir_off,
+						dir_pgtbl[dir_off]->page->phys_addr,
+						MMU_FLAG_VALID);
+				dir_modified = TRUE;
+			}
+
+			/*
+			 * map this particular page in the page table
+			 * use d*(MMU page size) to add additional entries from
+			 * the given physical address with the correct offset
+			 * for the MMU
+			 */
+			mmu_dir->mmu_info_cfg.pfn_page_write(dir_pgtbl[dir_off]->page,
+							     pg_off,
+							     cur_phys_addr + d *
+							     mmu_get_page_size(),
+							     neo->used_flag |
+							     MMU_FLAG_VALID);
+			dir_pgtbl[dir_off]->valid_entries++;
+
+			pg_off++;
+		} /* for duplicate */
+	} /* for entries */
+
+	neo->n_entries = n_entries * duplicate;
+	/* one more mapping is related to this directory */
+	mmu_dir->num_mapping++;
+
+	/* if non UMA we need to update device memory */
+	if (mmu_dir->mmu_info_cfg.pfn_page_update) {
+		while (n_pgs_to_update > 0) {
+			unsigned int idx = to_update[n_pgs_to_update - 1];
+			struct mmu_page_cfg_table *tbl = dir_pgtbl[idx];
+
+			mmu_dir->mmu_info_cfg.pfn_page_update(tbl->page);
+			n_pgs_to_update--;
+		}
+		if (dir_modified)
+			mmu_dir->mmu_info_cfg.pfn_page_update(mmu_dir->dir_page);
+	}
+
+	kfree(to_update);
+	return neo;
+
+cleanup_fail:
+	pr_err("%s:%d failed to create a non-existing page table\n", __func__, __LINE__);
+
+	/*
+	 * invalidate all already mapped pages -
+	 * do not destroy the created pages
+	 */
+	while (i > 1) {
+		if (d == 0) {
+			i--;
+			d = duplicate;
+		}
+		d--;
+
+		if (pg_off == 0) {
+			pg_off = MMU_N_PAGE;
+			if (!dir_off)
+				continue;
+			dir_off--;
+		}
+
+		pg_off--;
+
+		/* it should have been used before */
+		if (!dir_pgtbl[dir_off])
+			continue;
+
+		mmu_dir->mmu_info_cfg.pfn_page_write(dir_pgtbl[dir_off]->page,
+				pg_off, 0,
+				MMU_FLAG_INVALID);
+		dir_pgtbl[dir_off]->valid_entries--;
+	}
+
+	kfree(neo);
+	kfree(to_update);
+	return (void *)(-ENOMEM);
+}
+
+/*
+ * with sg
+ */
+struct sg_phys_iter {
+	void *sgl;
+	unsigned int offset;
+};
+
+static int sg_phys_iter_next(void *arg, unsigned long long *next)
+{
+	struct sg_phys_iter *iter = arg;
+
+	if (!iter->sgl)
+		return -ENOENT;
+
+	*next = sg_phys(iter->sgl) + iter->offset; /* phys_addr to dma_addr? */
+	iter->offset += PAGE_SIZE;
+
+	if (iter->offset == img_mmu_get_sgl_length(iter->sgl)) {
+		iter->sgl = sg_next(iter->sgl);
+		iter->offset = 0;
+	}
+
+	return 0;
+}
+
+/*
+ * mmu_directory_map_sg - Create a page table mapping for a list of physical
+ *			  pages and device virtual address
+ *
+ * @mmu_dir: directory to use for the mapping
+ * @phys_page_sg: sorted array of physical addresses (ascending order). The
+ *		  number of elements is dev_va->alloc_size/MMU_PAGE_SIZE
+ * @note This array can potentially be big, the caller may need to use vmalloc
+ * if running the linux kernel (e.g. mapping a 1080p NV12 is 760 entries, 6080
+ * Bytes - 2 CPU pages needed, fine with kmalloc; 4k NV12 is 3038 entries,
+ * 24304 Bytes - 6 CPU pages needed, kmalloc would try to find 8 contiguous
+ * pages which may be problematic if memory is fragmented)
+ * @dev_va: associated device virtual address. Given structure is copied
+ * @map_flag: flags to apply on the page (typically 0x2 for Write Only,
+ *	      0x4 for Read Only) - the flag should not set bit 1 as 0x1 is the
+ *	      valid flag.
+ *
+ * @warning Mapping can cause memory allocation (missing pages) - do not call
+ * while interrupts are disabled
+ *
+ * @return The opaque handle to the mmu_map object and result to 0
+ * @return (void *) in case of an error with the following values:
+ * @li -EINVAL if the allocation size is not a multiple of MMU_PAGE_SIZE,
+ *     if the given list of page table is too long or not long enough for the
+ *     mapping or if the give flags set the invalid bit
+ * @li -EPERM if the virtual memory is already mapped
+ * @li -ENOMEM if an internal allocation failed
+ * @li -ENOMEM if a page creation failed
+ */
+struct mmu_map *mmu_directory_map_sg(struct mmu_directory *mmu_dir,
+				     void *phys_page_sg,
+				     const struct mmu_heap_alloc *dev_va,
+				     unsigned int map_flag)
+{
+	struct sg_phys_iter arg = { phys_page_sg };
+
+	return mmu_directory_map(mmu_dir, dev_va, map_flag,
+				 sg_phys_iter_next, &arg);
+}
+
+/*
+ * mmu_directory_unmap - Un-map the mapped pages (invalidate their entries) and
+ *			 destroy the mapping object
+ * @map: pointer to the pages to un-map
+ *
+ * This does not destroy the created Page Table (even if they are becoming
+ * un-used) and does not change the Directory valid bits.
+ *
+ * @return 0
+ */
+int mmu_directory_unmap(struct mmu_map *map)
+{
+	unsigned int first_dir = 0;
+	unsigned int first_pg = 0;
+	unsigned int dir_offset = 0;
+	unsigned int pg_offset = 0;
+	unsigned int i;
+	struct mmu_directory *mmu_dir = NULL;
+
+	/*
+	 * in non UMA updates on pages needs to be done - store index of
+	 * directory entry pages to update
+	 */
+	unsigned int *to_update;
+	unsigned int n_pgs_to_update = 0;
+
+	if (!map || map->n_entries <= 0 || !map->mmu_dir)
+		return -EINVAL;
+
+	mmu_dir = map->mmu_dir;
+
+	/*
+	 * has to be dynamically allocated because it is bigger than 1k (max
+	 * stack in the kernel)
+	 */
+	to_update = kcalloc(MMU_N_TABLE, sizeof(unsigned int), GFP_KERNEL);
+	if (!to_update)
+		return -ENOMEM;
+
+	first_dir = mmu_dir_entry(map->dev_virt_addr.virt_addr);
+	first_pg = mmu_pg_entry(map->dev_virt_addr.virt_addr);
+
+	/* verify that the pages that should be used are available */
+	dir_offset = first_dir;
+	pg_offset = first_pg;
+
+	to_update[n_pgs_to_update] = first_dir;
+	n_pgs_to_update++;
+
+	for (i = 0; i < map->n_entries; i++) {
+		if (pg_offset >= MMU_N_PAGE) {
+			/* move to next directory */
+			dir_offset++;
+			/* using its first page */
+			pg_offset = 0;
+
+			to_update[n_pgs_to_update] = dir_offset;
+			n_pgs_to_update++;
+		}
+
+		/*
+		 * this page table object does not exist, something destroyed
+		 * it while the mapping was supposed to use it
+		 */
+		if (mmu_dir->dir_page_table[dir_offset]) {
+			mmu_dir->mmu_info_cfg.pfn_page_write
+				(mmu_dir->dir_page_table[dir_offset]->page,
+				 pg_offset, 0,
+				 MMU_FLAG_INVALID);
+			mmu_dir->dir_page_table[dir_offset]->valid_entries--;
+		}
+
+		pg_offset++;
+	}
+
+	mmu_dir->num_mapping--;
+
+	if (mmu_dir->mmu_info_cfg.pfn_page_update)
+		while (n_pgs_to_update > 0) {
+			unsigned int idx = to_update[n_pgs_to_update - 1];
+			struct mmu_page_cfg_table *tbl = mmu_dir->dir_page_table[idx];
+
+			mmu_dir->mmu_info_cfg.pfn_page_update(tbl->page);
+			n_pgs_to_update--;
+		}
+
+	/* mapping does not own the given virtual address */
+	kfree(map);
+	kfree(to_update);
+	return 0;
+}
+
+unsigned int mmu_directory_get_pagetable_entry(struct mmu_directory *mmu_dir,
+					       unsigned long dev_virt_addr)
+{
+	unsigned int dir_entry = 0;
+	unsigned int table_entry = 0;
+	struct mmu_page_cfg_table *tbl;
+	struct mmu_page_cfg_table **dir_pgtbl = NULL;
+	unsigned int *page_mem;
+
+	if (!mmu_dir) {
+		pr_err("mmu directory table is NULL\n");
+		return 0xFFFFFF;
+	}
+
+	dir_pgtbl = mmu_dir->dir_page_table;
+
+	dir_entry = mmu_dir_entry(dev_virt_addr);
+	table_entry = mmu_pg_entry(dev_virt_addr);
+
+	tbl = dir_pgtbl[dir_entry];
+	if (!tbl) {
+		pr_err("page table entry is NULL\n");
+		return 0xFFFFFF;
+	}
+
+	page_mem = (unsigned int *)tbl->page->cpu_virt_addr;
+
+#if defined(DEBUG_DECODER_DRIVER) || defined(DEBUG_ENCODER_DRIVER)
+	pr_info("Page table value@dir_entry:table_entry[%d : %d] = %x\n",
+		dir_entry, table_entry, page_mem[table_entry]);
+#endif
+
+	return page_mem[table_entry];
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/imgmmu.h b/drivers/media/platform/img/vxe-vxd/common/imgmmu.h
--- a/drivers/media/platform/img/vxe-vxd/common/imgmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/imgmmu.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,180 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG DEC MMU Library
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef IMG_DEC_MMU_MMU_H
+#define IMG_DEC_MMU_MMU_H
+
+#include <linux/types.h>
+
+#ifndef MMU_PHYS_SIZE
+/* @brief MMU physical address size in bits */
+#define MMU_PHYS_SIZE 40
+#endif
+
+#ifndef MMU_VIRT_SIZE
+/* @brief MMU virtual address size in bits */
+#define MMU_VIRT_SIZE 32
+#endif
+
+#ifndef MMU_PAGE_SIZE
+/* @brief Page size in bytes */
+#define MMU_PAGE_SIZE 4096u
+#define MMU_PAGE_SHIFT 12
+#define MMU_DIR_SHIFT 22
+#endif
+
+#if MMU_VIRT_SIZE == 32
+/* @brief max number of pagetable that can be stored in the directory entry */
+#define MMU_N_TABLE (MMU_PAGE_SIZE / 4u)
+/* @brief max number of page mapping in the pagetable */
+#define MMU_N_PAGE (MMU_PAGE_SIZE / 4u)
+#endif
+
+/* @brief Memory flag used to mark a page mapping as invalid */
+#define MMU_FLAG_VALID 0x1
+#define MMU_FLAG_INVALID 0x0
+
+/*
+ * This type defines MMU variant.
+ */
+enum mmu_etype {
+	MMU_TYPE_NONE = 0,
+	MMU_TYPE_32BIT,
+	MMU_TYPE_36BIT,
+	MMU_TYPE_40BIT,
+	MMU_TYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* @brief Page offset mask in virtual address - bottom bits */
+static const unsigned long VIRT_PAGE_OFF_MASK = ((1 << MMU_PAGE_SHIFT) - 1);
+/* @brief Page table index mask in virtual address - middle bits */
+static const unsigned long VIRT_PAGE_TBL_MASK =
+	(((1 << MMU_DIR_SHIFT) - 1) & ~(((1 << MMU_PAGE_SHIFT) - 1)));
+/* @brief Directory index mask in virtual address - high bits */
+static const unsigned long VIRT_DIR_IDX_MASK = (~((1 << MMU_DIR_SHIFT) - 1));
+
+/*
+ * struct mmu_heap_alloc - information about a virtual mem heap allocation
+ * @virt_addr: pointer to start of the allocation
+ * @alloc_size: size in bytes
+ */
+struct mmu_heap_alloc {
+	unsigned long	virt_addr;
+	unsigned long	alloc_size;
+};
+
+/*
+ * struct mmu_page_cfg - mmu_page configuration
+ * @phys_addr: physical address - unsigned long long is used to support extended physical
+ *	       address on 32bit system
+ * @cpu_virt_addr: CPU virtual address pointer
+ */
+struct mmu_page_cfg {
+	unsigned long long	phys_addr;
+	unsigned long	cpu_virt_addr;
+};
+
+/*
+ * typedef mmu_pfn_page_alloc - page table allocation function
+ *
+ * Pointer to a function implemented by the used allocator to create 1
+ * page table (used for the MMU mapping - directory page and mapping page)
+ *
+ * Return:
+ * * A populated mmu_page_cfg structure with the result of the page alloc.
+ * * NULL if the allocation failed.
+ */
+typedef struct mmu_page_cfg *(*mmu_pfn_page_alloc) (void *);
+
+/*
+ * typedef mmu_pfn_page_free
+ * @arg1: pointer to the mmu_page_cfg that is allocated using mmu_pfn_page_alloc
+ *
+ * Pointer to a function to free the allocated page table used for MMU mapping.
+ *
+ * @return void
+ */
+typedef void (*mmu_pfn_page_free) (struct mmu_page_cfg *arg1);
+
+/*
+ * typedef mmu_pfn_page_update
+ * @arg1: pointer to the mmu_page_cfg that is allocated using mmu_pfn_page_alloc
+ *
+ * Pointer to a function to update Device memory on non Unified Memory
+ *
+ * @return void
+ */
+typedef void (*mmu_pfn_page_update) (struct mmu_page_cfg *arg1);
+
+/*
+ * typedef mmu_pfn_page_write
+ * @mmu_page: mmu_page mmu page configuration to be written
+ * @offset: offset in entries (32b word)
+ * @pa_to_write: pa_to_write physical address to write
+ * @flags: flags bottom part of the entry used as flags for the MMU (including
+ *	   valid flag)
+ *
+ * Pointer to a function to write to a device address
+ *
+ * @return void
+ */
+typedef void (*mmu_pfn_page_write) (struct mmu_page_cfg *mmu_page,
+				    unsigned int offset,
+				    unsigned long long pa_to_write, unsigned int flags);
+
+/*
+ * struct mmu_info
+ * @pfn_page_alloc: function pointer for allocating a physical page used in
+ *		    MMU mapping
+ * @alloc_ctx: allocation context handler
+ * @pfn_page_free: function pointer for freeing a physical page used in
+ *		   MMU mapping
+ * @pfn_page_write: function pointer to write a physical address onto a page.
+ *		    If NULL, then internal function is used. Internal function
+ *		    assumes that MMU_PHYS_SIZE is the MMU size.
+ * @pfn_page_update: function pointer to update a physical page on device if
+ *		     non UMA.
+ */
+struct mmu_info {
+	mmu_pfn_page_alloc	pfn_page_alloc;
+	void			*alloc_ctx;
+	mmu_pfn_page_free	pfn_page_free;
+	mmu_pfn_page_write	pfn_page_write;
+	mmu_pfn_page_update	pfn_page_update;
+};
+
+/*
+ * mmu_get_page_size() - Access the compilation specified page size of the
+ *			 MMU (in Bytes)
+ */
+static inline unsigned long mmu_get_page_size(void)
+{
+	return MMU_PAGE_SIZE;
+}
+
+struct mmu_directory *mmu_create_directory(const struct mmu_info *mmu_info_ops);
+int mmu_destroy_directory(struct mmu_directory *mmu_dir);
+
+struct mmu_page_cfg *mmu_directory_get_page(struct mmu_directory *mmu_dir);
+
+struct mmu_map *mmu_directory_map_sg(struct mmu_directory *mmu_dir,
+				     void *phys_page_sg,
+				     const struct mmu_heap_alloc *dev_va,
+				     unsigned int map_flag);
+int mmu_directory_unmap(struct mmu_map *map);
+
+unsigned int mmu_directory_get_pagetable_entry(struct mmu_directory *mmu_dir,
+					       unsigned long dev_virt_addr);
+
+#endif /* IMG_DEC_MMU_MMU_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/lst.c b/drivers/media/platform/img/vxe-vxd/common/lst.c
--- a/drivers/media/platform/img/vxe-vxd/common/lst.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/lst.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * List processing primitives.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ */
+
+#include "lst.h"
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+void lst_add(struct lst_t *list, void *item)
+{
+	if (!list->first) {
+		list->first = item;
+		list->last = item;
+	} else {
+		*list->last = item;
+		list->last = item;
+	}
+	*((void **)item) = NULL;
+}
+
+void lst_addhead(struct lst_t *list, void *item)
+{
+	if (!list->first) {
+		list->first = item;
+		list->last = item;
+		*((void **)item) = NULL;
+	} else {
+		*((void **)item) = list->first;
+		list->first = item;
+	}
+}
+
+int lst_empty(struct lst_t *list)
+{
+	if (!list->first)
+		return 1;
+	else
+		return 0;
+}
+
+void *lst_first(struct lst_t *list)
+{
+	return list->first;
+}
+
+void lst_init(struct lst_t *list)
+{
+	list->first = NULL;
+	list->last = NULL;
+}
+
+void *lst_last(struct lst_t *list)
+{
+	return list->last;
+}
+
+void *lst_next(void *item)
+{
+	return *((void **)item);
+}
+
+void *lst_removehead(struct lst_t *list)
+{
+	void **temp = list->first;
+
+	if (temp) {
+		list->first = *temp;
+		if (!list->first)
+			list->last = NULL;
+	}
+	return temp;
+}
+
+void *lst_remove(struct lst_t *list, void *item)
+{
+	void **p;
+	void **q;
+
+	p = (void **)list;
+	q = *p;
+	while (q) {
+		if (q == item) {
+			*p = *q;
+			if (list->last == q)
+				list->last = p;
+			return item;
+		}
+		p = q;
+		q = *p;
+	}
+
+	return NULL;
+}
+
+int lst_check(struct lst_t *list, void *item)
+{
+	void **p;
+	void **q;
+
+	p = (void **)list;
+	q = *p;
+	while (q) {
+		if (q == item)
+			return 1;
+		p = q;
+		q = *p;
+	}
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/lst.h b/drivers/media/platform/img/vxe-vxd/common/lst.h
--- a/drivers/media/platform/img/vxe-vxd/common/lst.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/lst.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * List processing primitives.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ */
+#ifndef __LIST_H__
+#define __LIST_H__
+
+#include <linux/types.h>
+
+struct lst_t {
+	void **first;
+	void **last;
+};
+
+void lst_add(struct lst_t *list, void *item);
+void lst_addhead(struct lst_t *list, void *item);
+
+/**
+ * lst_empty- Is list empty?
+ * @list: pointer to list
+ */
+int  lst_empty(struct lst_t *list);
+void *lst_first(struct lst_t *list);
+void lst_init(struct lst_t *list);
+void *lst_last(struct lst_t *list);
+void *lst_next(void *item);
+void *lst_remove(struct lst_t *list, void *item);
+void *lst_removehead(struct lst_t *list);
+int lst_check(struct lst_t *list, void *item);
+
+#endif /* __LIST_H__ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/pool_api.c b/drivers/media/platform/img/vxe-vxd/common/pool_api.c
--- a/drivers/media/platform/img/vxe-vxd/common/pool_api.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/pool_api.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,710 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Resource pool manager API.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/slab.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <linux/types.h>
+
+#include "idgen_api.h"
+#include "lst.h"
+#include "pool_api.h"
+#include "img_errors.h"
+
+/*
+ * list can be modified by different instances. So please,
+ * make sure to acquire mutex lock before initializing the list.
+ */
+static struct mutex *shared_res_mutex_handle;
+
+/*
+ * Max resource ID's.
+ */
+#define POOL_IDGEN_MAX_ID	   (0xFFFFFFFF)
+/*
+ * Size of blocks used for ID's.
+ */
+#define POOL_IDGEN_BLOCK_SIZE  (50)
+
+/*
+ * Indicates if the pool API has been indialized or not.
+ * zero if not done. 1 if done.
+ */
+static int poolinitdone;
+
+/* list of resource pool */
+static struct lst_t poollist = {0};
+
+/**
+ * struct poollist - Structure contains resource list information.
+ * @link: to be able to part of single linked list
+ * @pool_mutex: lock
+ * @freereslst: list of free resource structure
+ * @actvreslst: list of active resource structure
+ * @pfnfree: pool free callback function
+ * @idgenhandle: ID generator context handl
+ */
+struct poollist {
+	void **link;
+	struct mutex *pool_mutex; /* Mutex lock */
+	struct lst_t freereslst;
+	struct lst_t actvreslst;
+	pfrecalbkpntr pfnfree;
+	void *idgenhandle;
+};
+
+/*
+ * This structure contains pool resource.
+ */
+struct poolres {
+	void **link; /* to be able to part of single linked list */
+	/* Resource id */
+	unsigned int resid;
+	/* Pointer to destructor function */
+	pdestcallbkptr desfunc;
+	/* resource param */
+	void *resparam;
+	/* size of resource param in bytes */
+	unsigned int resparmsize;
+	/* pointer to resource pool list */
+	struct poollist *respoollst;
+	/* 1 if this is a clone of the original resource */
+	int isclone;
+	/* pointer to original resource */
+	struct poolres *origres;
+	/* list of cloned resource structures. Only used on the original */
+	struct lst_t clonereslst;
+	/* reference count. Only used on the original resource */
+	unsigned int refcnt;
+	void *cb_handle;
+};
+
+/*
+ * This function initializes the list if not done earlier.
+ */
+int pool_init(void)
+{
+	/* Check if list already initialized */
+	if (!poolinitdone) {
+		/*
+		 * list can be modified by different instances. So please,
+		 * make sure to acquire mutex lock before initializing the list.
+		 */
+
+		shared_res_mutex_handle = kzalloc(sizeof(*shared_res_mutex_handle), GFP_KERNEL);
+		if (!shared_res_mutex_handle)
+			return -ENOMEM;
+
+		mutex_init(shared_res_mutex_handle);
+
+		/* initialize the list of pools */
+		lst_init(&poollist);
+		/* Get initialized flag to true */
+		poolinitdone = 1;
+	}
+
+	return 0;
+}
+
+/*
+ * This function de-initializes the list.
+ */
+void pool_deinit(void)
+{
+	struct poollist *respoollist;
+
+	/* Check if list initialized */
+	if (poolinitdone) {
+		/* destroy any active pools */
+		respoollist = (struct poollist *)lst_first(&poollist);
+		while (respoollist) {
+			pool_destroy(respoollist);
+			respoollist = (struct poollist *)lst_first(&poollist);
+		}
+
+		/* Destroy mutex */
+		mutex_destroy(shared_res_mutex_handle);
+		kfree(shared_res_mutex_handle);
+		shared_res_mutex_handle = NULL;
+
+		/* set initialized flag to 0 */
+		poolinitdone = 0;
+	}
+}
+
+/*
+ * This function creates pool.
+ */
+int pool_api_create(void **poolhndle)
+{
+	struct poollist *respoollist;
+	unsigned int result = 0;
+
+	/* Allocate a pool structure */
+	respoollist = kzalloc(sizeof(*respoollist), GFP_KERNEL);
+	if (!respoollist)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/* Initialize the pool info */
+	lst_init(&respoollist->freereslst);
+	lst_init(&respoollist->actvreslst);
+
+	/* Create mutex */
+	respoollist->pool_mutex = kzalloc(sizeof(*respoollist->pool_mutex), GFP_KERNEL);
+	if (!respoollist->pool_mutex) {
+		result = ENOMEM;
+		goto error_create_context;
+	}
+	mutex_init(respoollist->pool_mutex);
+
+	/* Create context for the Id generator */
+	result = idgen_createcontext(POOL_IDGEN_MAX_ID,
+				     POOL_IDGEN_BLOCK_SIZE, 0,
+				     &respoollist->idgenhandle);
+	if (result != IMG_SUCCESS)
+		goto error_create_context;
+
+	/* Disable interrupts */
+	mutex_lock_nested(shared_res_mutex_handle, SUBCLASS_POOL_RES);
+
+	/* Add to list of pools */
+	lst_add(&poollist, respoollist);
+
+	/* Enable interrupts */
+	mutex_unlock(shared_res_mutex_handle);
+
+	/* Return handle to pool */
+	*poolhndle = respoollist;
+
+	return IMG_SUCCESS;
+
+	/* Error handling. */
+error_create_context:
+	kfree(respoollist);
+
+	return result;
+}
+
+/*
+ * This function destroys the pool.
+ */
+int pool_destroy(void *poolhndle)
+{
+	struct poollist *respoollist = poolhndle;
+	struct poolres *respool;
+	struct poolres *clonerespool;
+	unsigned int result = 0;
+
+	if (!poolinitdone || !respoollist) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto	error_nolock;
+	}
+
+	/* Lock the pool */
+	mutex_lock_nested(respoollist->pool_mutex, SUBCLASS_POOL);
+
+	/* Disable interrupts */
+	/*
+	 * We need to check if we really need to check disable,
+	 * interrupts because before deleting we need to make sure the
+	 * pool lst is not being used other process. As of now getting ipl
+	 * global mutex
+	 */
+	mutex_lock_nested(shared_res_mutex_handle, SUBCLASS_POOL_RES);
+
+	/* Remove the pool from the active list */
+	lst_remove(&poollist, respoollist);
+
+	/* Enable interrupts */
+	mutex_unlock(shared_res_mutex_handle);
+
+	/* Destroy any resources in the free list */
+	respool = (struct poolres *)lst_removehead(&respoollist->freereslst);
+	while (respool) {
+		respool->desfunc(respool->resparam, respool->cb_handle);
+		kfree(respool);
+		respool = (struct poolres *)
+				lst_removehead(&respoollist->freereslst);
+	}
+
+	/* Destroy any resources in the active list */
+	respool = (struct poolres *)lst_removehead(&respoollist->actvreslst);
+	while (respool) {
+		clonerespool = (struct poolres *)
+				lst_removehead(&respool->clonereslst);
+		while (clonerespool) {
+			/*
+			 * If we created a copy of the resources pvParam
+			 * then free it.
+			 * kfree(NULL) is safe and this check is probably not
+			 * required
+			 */
+			kfree(clonerespool->resparam);
+
+			kfree(clonerespool);
+			clonerespool = (struct poolres *)
+					lst_removehead(&respool->clonereslst);
+		}
+
+		/* Call the resource destructor */
+		respool->desfunc(respool->resparam, respool->cb_handle);
+		kfree(respool);
+		respool = (struct poolres *)
+				lst_removehead(&respoollist->actvreslst);
+	}
+	/* Destroy the context for the Id generator */
+	if (respoollist->idgenhandle)
+		result = idgen_destroycontext(respoollist->idgenhandle);
+
+	/* Unlock the pool */
+	mutex_unlock(respoollist->pool_mutex);
+
+	/* Destroy mutex */
+	mutex_destroy(respoollist->pool_mutex);
+	kfree(respoollist->pool_mutex);
+	respoollist->pool_mutex = NULL;
+
+	/* Free the pool structure */
+	kfree(respoollist);
+
+	return IMG_SUCCESS;
+
+error_nolock:
+	return result;
+}
+
+int pool_setfreecalbck(void *poolhndle, pfrecalbkpntr pfnfree)
+{
+	struct poollist *respoollist = poolhndle;
+	struct poolres *respool;
+	unsigned int result = 0;
+
+	if (!poolinitdone || !respoollist) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error_nolock;
+	}
+
+	/* Lock the pool */
+	mutex_lock_nested(respoollist->pool_mutex, SUBCLASS_POOL);
+
+	respoollist->pfnfree = pfnfree;
+
+	/* If free callback set */
+	if (respoollist->pfnfree) {
+		/* Move resources from free to active list */
+		respool = (struct poolres *)
+				lst_removehead(&respoollist->freereslst);
+		while (respool) {
+			/* Add to active list */
+			lst_add(&respoollist->actvreslst, respool);
+			respool->refcnt++;
+
+			/* Unlock the pool */
+			mutex_unlock(respoollist->pool_mutex);
+
+			/* Call the free callback */
+			respoollist->pfnfree(respool->resid, respool->resparam);
+
+			/* Lock the pool */
+			mutex_lock_nested(respoollist->pool_mutex, SUBCLASS_POOL);
+
+			/* Get next free resource */
+			respool = (struct poolres *)
+				lst_removehead(&respoollist->freereslst);
+		}
+	}
+
+	/* Unlock the pool */
+	mutex_unlock(respoollist->pool_mutex);
+
+	/* Return IMG_SUCCESS */
+	return IMG_SUCCESS;
+
+error_nolock:
+	return result;
+}
+
+int pool_resreg(void *poolhndle, pdestcallbkptr fndestructor,
+		void *resparam, unsigned int resparamsize,
+		int balloc, unsigned int *residptr,
+		void **poolreshndle, void *cb_handle)
+{
+	struct poollist *respoollist = poolhndle;
+	struct poolres *respool;
+	unsigned int result = 0;
+
+	if (!poolinitdone || !respoollist) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto	error_nolock;
+	}
+
+	/* Allocate a resource structure */
+	respool = kzalloc(sizeof(*respool), GFP_KERNEL);
+	if (!respool)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/* Setup the resource */
+	respool->desfunc  = fndestructor;
+	respool->cb_handle = cb_handle;
+	respool->resparam = resparam;
+	respool->resparmsize = resparamsize;
+	respool->respoollst = respoollist;
+	lst_init(&respool->clonereslst);
+
+	/* Lock the pool */
+	mutex_lock_nested(respoollist->pool_mutex, SUBCLASS_POOL);
+
+	/* Set resource id */
+	result = idgen_allocid(respoollist->idgenhandle,
+			       (void *)respool, &respool->resid);
+	if (result != IMG_SUCCESS) {
+		kfree(respool);
+		/* Unlock the pool */
+		mutex_unlock(respoollist->pool_mutex);
+		return result;
+	}
+
+	/* If allocated or free callback not set */
+	if (balloc || respoollist->pfnfree) {
+		/* Add to active list */
+		lst_add(&respoollist->actvreslst, respool);
+		respool->refcnt++;
+	} else {
+		/* Add to free list */
+		lst_add(&respoollist->freereslst, respool);
+	}
+
+	/* Return the resource id */
+	if (residptr)
+		*residptr = respool->resid;
+
+	/* Return the handle to the resource */
+	if (poolreshndle)
+		*poolreshndle = respool;
+
+	/* Unlock the pool */
+	mutex_unlock(respoollist->pool_mutex);
+
+	/* If free callback set */
+	if (respoollist->pfnfree) {
+		/* Call the free callback */
+		respoollist->pfnfree(respool->resid, respool->resparam);
+	}
+
+	/* Return IMG_SUCCESS */
+	return IMG_SUCCESS;
+
+error_nolock:
+	return result;
+}
+
+int pool_resdestroy(void *poolreshndle, int bforce)
+{
+	struct poolres *respool = poolreshndle;
+	struct poollist *respoollist;
+	struct poolres *origrespool;
+	unsigned int result = 0;
+
+	if (!poolinitdone || !respool) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error_nolock;
+	}
+
+	respoollist = respool->respoollst;
+
+	/* If this is a clone */
+	if (respool->isclone) {
+		/* Get access to the original */
+		origrespool = respool->origres;
+		if (!origrespool) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			goto error_nolock;
+		}
+
+		if (origrespool->isclone) {
+			result = IMG_ERROR_UNEXPECTED_STATE;
+			goto error_nolock;
+		}
+
+		/* Remove from the clone list */
+		lst_remove(&origrespool->clonereslst, respool);
+
+		/* Free resource id */
+		result = idgen_freeid(respoollist->idgenhandle,
+				      respool->resid);
+		if (result != IMG_SUCCESS)
+			return result;
+
+		/*
+		 * If we created a copy of the resources pvParam then free it
+		 * kfree(NULL) is safe and this check is probably not required.
+		 */
+		kfree(respool->resparam);
+
+		/* Free the clone resource structure */
+		kfree(respool);
+
+		/* Set resource to be "freed" to the original */
+		respool = origrespool;
+	}
+
+	/* If there are still outstanding references */
+	if (!bforce && respool->refcnt != 0) {
+		/*
+		 * We may need to mark the resource and destroy it when
+		 * there are no outstanding references
+		 */
+		return IMG_SUCCESS;
+	}
+
+	/* Has the resource outstanding references */
+	if (respool->refcnt != 0) {
+		/* Remove the resource from the active list */
+		lst_remove(&respoollist->actvreslst, respool);
+	} else {
+		/* Remove the resource from the free list */
+		lst_remove(&respoollist->freereslst, respool);
+	}
+
+	/* Free resource id */
+	result = idgen_freeid(respoollist->idgenhandle,
+			      respool->resid);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Call the resource destructor */
+	respool->desfunc(respool->resparam, respool->cb_handle);
+	kfree(respool);
+
+	return IMG_SUCCESS;
+
+error_nolock:
+	return result;
+}
+
+int pool_resalloc(void *poolhndle, void *poolreshndle)
+{
+	struct poollist *respoollist = poolhndle;
+	struct poolres *respool = poolreshndle;
+	unsigned int result = 0;
+
+	if (!poolinitdone || !respoollist || !poolreshndle) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error_nolock;
+	}
+
+	/* Lock the pool */
+	mutex_lock_nested(respoollist->pool_mutex, SUBCLASS_POOL);
+
+	/* Remove resource from free list */
+	lst_remove(&respoollist->freereslst, respool);
+
+	/* Add to active list */
+	lst_add(&respoollist->actvreslst, respool);
+	respool->refcnt++;
+
+	/* Unlock the pool */
+	mutex_unlock(respoollist->pool_mutex);
+
+	/* Return IMG_SUCCESS */
+	return IMG_SUCCESS;
+
+error_nolock:
+	return result;
+}
+
+int pool_resfree(void *poolreshndle)
+{
+	struct poolres *respool = poolreshndle;
+	struct poollist *respoollist;
+	struct poolres *origrespool;
+	unsigned int result = 0;
+
+	if (!poolinitdone || !respool) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error_nolock;
+	}
+
+	respoollist = respool->respoollst;
+
+	/* Lock the pool */
+	mutex_lock_nested(respoollist->pool_mutex, SUBCLASS_POOL);
+
+	/* If this is a clone */
+	if (respool->isclone) {
+		/* Get access to the original */
+		origrespool = respool->origres;
+		if (!origrespool) {
+			mutex_unlock(respoollist->pool_mutex);
+			return IMG_ERROR_INVALID_PARAMETERS;
+		}
+
+		/* Remove from the clone list */
+		lst_remove(&origrespool->clonereslst, respool);
+
+		/* Free resource id */
+		result = idgen_freeid(respoollist->idgenhandle,
+				      respool->resid);
+		if (result != IMG_SUCCESS) {
+			/* Unlock the pool */
+			mutex_unlock(respoollist->pool_mutex);
+			return result;
+		}
+
+		/*
+		 * If we created a copy of the resources pvParam then free it
+		 * kfree(NULL) is safe and this check is probably not required.
+		 */
+		kfree(respool->resparam);
+
+		/* Free the clone resource structure */
+		kfree(respool);
+
+		/* Set resource to be "freed" to the original */
+		respool = origrespool;
+	}
+
+	/* Update the reference count */
+	respool->refcnt--;
+
+	/* If there are still outstanding references */
+	if (respool->refcnt != 0) {
+		/* Unlock the pool */
+		mutex_unlock(respoollist->pool_mutex);
+		/* Return IMG_SUCCESS */
+		return IMG_SUCCESS;
+	}
+
+	/* Remove the resource from the active list */
+	lst_remove(&respoollist->actvreslst, respool);
+
+	/* If free callback set */
+	if (respoollist->pfnfree) {
+		/* Add to active list */
+		lst_add(&respoollist->actvreslst, respool);
+		respool->refcnt++;
+	} else {
+		/* Add to free list */
+		lst_add(&respoollist->freereslst, respool);
+	}
+
+	/* Unlock the pool */
+	mutex_unlock(respoollist->pool_mutex);
+
+	/* If free callback set */
+	if (respoollist->pfnfree) {
+		/* Call the free callback */
+		respoollist->pfnfree(respool->resid, respool->resparam);
+	}
+
+	/* Return IMG_SUCCESS */
+	return IMG_SUCCESS;
+
+error_nolock:
+	return result;
+}
+
+int pool_resclone(void *poolreshndle, void **clonereshndle, void **resparam)
+{
+	struct poolres *respool = poolreshndle;
+	struct poollist *respoollist;
+	struct poolres *origrespool = respool;
+	struct poolres *clonerespool;
+	unsigned int result = 0;
+
+	if (!poolinitdone || !respool) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error_nolock;
+	}
+
+	/* Allocate a resource structure */
+	clonerespool = kzalloc(sizeof(*clonerespool), GFP_KERNEL);
+	if (!clonerespool)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	respoollist = respool->respoollst;
+	if (!respoollist)
+		return IMG_ERROR_FATAL;
+
+	/* Lock the pool */
+	mutex_lock_nested(respoollist->pool_mutex, SUBCLASS_POOL);
+
+	/* Set resource id */
+	result = idgen_allocid(respoollist->idgenhandle,
+			       (void *)clonerespool, &clonerespool->resid);
+	if (result != IMG_SUCCESS)
+		goto error_alloc_id;
+
+	/* If this is a clone, set the original */
+	if (respool->isclone)
+		origrespool = respool->origres;
+
+	/* Setup the cloned resource */
+	clonerespool->isclone = 1;
+	clonerespool->respoollst = respoollist;
+	clonerespool->origres = origrespool;
+
+	/* Add to clone list */
+	lst_add(&origrespool->clonereslst, clonerespool);
+	origrespool->refcnt++;
+
+	/* If ppvParam is not IMG_NULL */
+	if (resparam) {
+		/* If the size of the original vParam is 0 */
+		if (origrespool->resparmsize == 0) {
+			*resparam = NULL;
+		} else {
+			/* Allocate memory for a copy of the original vParam */
+			/*
+			 * kmemdup allocates memory of length
+			 * origrespool->resparmsize and to resparam and copy
+			 * origrespool->resparam to resparam of the allocated
+			 * length
+			 */
+			*resparam = kmemdup(origrespool->resparam,
+					    origrespool->resparmsize,
+					    GFP_KERNEL);
+			if (!(*resparam)) {
+				result = IMG_ERROR_OUT_OF_MEMORY;
+				goto error_copy_param;
+			}
+		}
+	}
+
+	/* Unlock the pool */
+	mutex_unlock(respoollist->pool_mutex);
+
+	/* Return the cloned resource */
+	*clonereshndle = clonerespool;
+
+	/* Return IMG_SUCCESS */
+	return IMG_SUCCESS;
+
+	/* Error handling. */
+error_copy_param:
+	lst_remove(&origrespool->clonereslst, clonerespool);
+	origrespool->refcnt--;
+error_alloc_id:
+	kfree(clonerespool);
+
+	/* Unlock the pool */
+	mutex_unlock(respoollist->pool_mutex);
+
+error_nolock:
+	return result;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/pool_api.h b/drivers/media/platform/img/vxe-vxd/common/pool_api.h
--- a/drivers/media/platform/img/vxe-vxd/common/pool_api.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/pool_api.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Resource pool manager API.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef __POOLAPI_H__
+#define __POOLAPI_H__
+
+#include "img_errors.h"
+#include "lst.h"
+
+/*
+ * This is the prototype for "free" callback functions.  This function
+ * is called when resources are returned to the pools list of free resources.
+ * NOTE: The "freed" resource is then allocated and passed to the callback
+ * function.
+ */
+typedef void (*pfrecalbkpntr)(unsigned int ui32resid, void *resparam);
+
+/*
+ * This is the prototype for "destructor" callback functions.  This function
+ * is called when a resource registered with the resource pool manager is to
+ * be destroyed.
+ */
+typedef void (*pdestcallbkptr)(void *resparam, void *cb_handle);
+
+/*
+ * pool_init - This function is used to initializes the resource pool manager component
+ * and should be called at start-up.
+ */
+int pool_init(void);
+
+/*
+ * This function is used to deinitialises the resource pool manager component
+ * and would normally be called at shutdown.
+ */
+void pool_deinit(void);
+
+/*
+ * This function is used to create a resource pool into which resources can be
+ * placed.
+ */
+int pool_api_create(void **poolhndle);
+
+/*
+ * This function is used to destroy a resource pool.
+ * NOTE: Destroying a resource pool destroys all of the resources within the
+ * pool by calling the associated destructor function #POOL_pfnDestructor
+ * defined when the resource what registered using POOL_ResRegister().
+ *
+ * NOTE: All of the pools resources must be in the pools free list - the
+ * allocated list must be empty.
+ */
+int pool_destroy(void *poolhndle);
+
+/*
+ * This function is used to set or remove a free callback function on a pool.
+ * The free callback function gets call for any resources already in the
+ * pools free list or for any resources that subsequently get freed.
+ * NOTE: The resource passed to the callback function has been allocated before
+ * the callback is made.
+ */
+int pool_setfreecalbck(void *poolhndle, pfrecalbkpntr pfnfree);
+
+/*
+ * This function is used to register a resource within a resource pool.  The
+ * resource is added to the pools allocated or free list based on the value
+ * of bAlloc.
+ */
+int pool_resreg(void *poolhndle, pdestcallbkptr fndestructor,
+		void *resparam, unsigned int resparamsize,
+		int balloc, unsigned int *residptr,
+		void **poolreshndle, void *cb_handle);
+
+/*
+ * This function is used to destroy a resource.
+ */
+int pool_resdestroy(void *poolreshndle, int bforce);
+
+/*
+ * This function is used to get/allocate a resource from a pool.  This moves
+ * the resource from the free to allocated list.
+ */
+int pool_resalloc(void *poolhndle, void *poolreshndle);
+
+/*
+ * This function is used to free a resource and return it to the pools lists of
+ * free resources.
+ * NOTE: The resources is only moved to the free list when all references to
+ * the resource have been freed.
+ */
+int pool_resfree(void *poolreshndle);
+
+/*
+ * This function is used to clone a resource - this creates an additional
+ * reference to the resource.
+ * NOTE: The resources is only moved to the free list when all references to
+ * the resource have been freed.
+ * NOTE: If this function is used to clone the resource's pvParam data then
+ * the clone of the data is freed when the clone of the resource is freed.
+ * The resource destructor is NOT used for this - simply an IMG_FREE.
+ */
+int pool_resclone(void *poolreshndle, void **clonereshndle, void **resparam);
+
+#endif /* __POOLAPI_H__ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/pool.c b/drivers/media/platform/img/vxe-vxd/common/pool.c
--- a/drivers/media/platform/img/vxe-vxd/common/pool.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/pool.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Object Pool Memory Allocator
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "img_errors.h"
+#include "pool.h"
+
+#define BUFF_MAX_SIZE 4096
+#define BUFF_MAX_GROW 32
+
+/* 64 bits */
+#define ALIGN_SIZE (sizeof(long long) - 1)
+
+struct pool {
+	unsigned char *name;
+	unsigned int size;
+	unsigned int grow;
+	struct buffer *buffers;
+	struct object *objects;
+};
+
+struct buffer {
+	struct buffer *next;
+};
+
+struct object {
+	struct object *next;
+};
+
+static inline unsigned char *strdup_cust(const unsigned char *str)
+{
+	unsigned char *r = kmalloc(strlen(str) + 1, GFP_KERNEL);
+
+	if (r)
+		strcpy(r, str);
+	return r;
+}
+
+/*
+ * pool_create - Create an sObject pool
+ * @name: Name of sObject pool for diagnostic purposes
+ * @obj_size: size of each sObject in the pool in bytes
+ * @pool_hdnl: Will contain NULL or sObject pool handle
+ *
+ * This function Create an sObject pool
+ */
+
+int pool_create(const unsigned char * const name,
+		unsigned int obj_size,
+		struct pool ** const pool_hdnl)
+{
+	struct pool *local_pool = NULL;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!name || !pool_hdnl) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	local_pool = kmalloc((sizeof(*local_pool)), GFP_KERNEL);
+	if (!local_pool) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	local_pool->name = strdup_cust((unsigned char *)name);
+	local_pool->size = obj_size;
+	local_pool->buffers = NULL;
+	local_pool->objects = NULL;
+	local_pool->grow =
+		(BUFF_MAX_SIZE - sizeof(struct buffer)) /
+		(obj_size + ALIGN_SIZE);
+
+	if (local_pool->grow == 0)
+		local_pool->grow = 1;
+	else if (local_pool->grow > BUFF_MAX_GROW)
+		local_pool->grow = BUFF_MAX_GROW;
+
+	*pool_hdnl = local_pool;
+	result = IMG_SUCCESS;
+
+	return result;
+}
+
+/*
+ * @Function	pool_delete
+ * @Description
+ * Delete an sObject pool. All psObjects allocated from the pool must
+ * be free'd with pool_free() before deleting the sObject pool.
+ * @Input	pool : Object Pool pointer
+ * @Return IMG_SUCCESS or an error code.
+ */
+int pool_delete(struct pool * const pool_arg)
+{
+	struct buffer *local_buf = NULL;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!pool_arg) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	local_buf = pool_arg->buffers;
+	while (local_buf) {
+		local_buf = local_buf->next;
+		kfree(pool_arg->buffers);
+		pool_arg->buffers = local_buf;
+	}
+
+	kfree(pool_arg->name);
+	pool_arg->name = NULL;
+
+	kfree(pool_arg);
+	result = IMG_SUCCESS;
+
+	return result;
+}
+
+/*
+ * @Function	pool_alloc
+ * @Description
+ * Allocate an sObject from an sObject pool.
+ * @Input	pool_arg : Object Pool
+ * @Output	obj_hndl : Pointer containing the handle to the
+ * object created or IMG_NULL
+ * @Return    IMG_SUCCESS or an error code.
+ */
+int pool_alloc(struct pool * const pool_arg,
+	       void ** const obj_hndl)
+{
+	struct object *local_obj1 = NULL;
+	struct buffer *local_buf = NULL;
+	unsigned int idx = 0;
+	unsigned int sz = 0;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!pool_arg || !obj_hndl) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	if (!pool_arg->objects) {
+		sz = (pool_arg->size + ALIGN_SIZE);
+		sz *= (pool_arg->grow + sizeof(struct buffer));
+		local_buf = kmalloc(sz, GFP_KERNEL);
+		if (!local_buf) {
+			result = IMG_ERROR_MALLOC_FAILED;
+			return result;
+		}
+
+		local_buf->next = pool_arg->buffers;
+		pool_arg->buffers = local_buf;
+
+		for (idx = 0; idx < pool_arg->grow; idx++) {
+			struct object *local_obj2;
+			unsigned char *temp_ptr = NULL;
+
+			local_obj2 = (struct object *)(((unsigned char *)(local_buf + 1))
+				+ (idx * (pool_arg->size + ALIGN_SIZE)));
+
+			temp_ptr = (unsigned char *)local_obj2;
+			if ((unsigned long)temp_ptr & ALIGN_SIZE) {
+				temp_ptr += ((ALIGN_SIZE + 1)
+					- ((unsigned long)temp_ptr & ALIGN_SIZE));
+				local_obj2 = (struct object *)temp_ptr;
+			}
+
+			local_obj2->next = pool_arg->objects;
+			pool_arg->objects = local_obj2;
+		}
+	}
+
+	if (!pool_arg->objects) {
+		result = IMG_ERROR_UNEXPECTED_STATE;
+		return result;
+	}
+
+	local_obj1 = pool_arg->objects;
+	pool_arg->objects = local_obj1->next;
+
+	*obj_hndl = (void *)(local_obj1);
+	result = IMG_SUCCESS;
+
+	return result;
+}
+
+/*
+ * @Function	pool_free
+ * @Description
+ * Free an sObject previously allocated from an sObject pool.
+ * @Input	pool_arg : Object Pool pointer.
+ * @Output	h_object : Handle to the object to be freed.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int pool_free(struct pool * const pool_arg,
+	      void * const obj_hndl)
+{
+	struct object *object = NULL;
+	unsigned int result = IMG_ERROR_FATAL;
+
+	if (!pool_arg || !obj_hndl) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		return result;
+	}
+
+	object = (struct object *)obj_hndl;
+	object->next = pool_arg->objects;
+	pool_arg->objects = object;
+
+	result = IMG_SUCCESS;
+
+	return result;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/pool.h b/drivers/media/platform/img/vxe-vxd/common/pool.h
--- a/drivers/media/platform/img/vxe-vxd/common/pool.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/pool.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Object Pool Memory Allocator header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef _pool_h_
+#define _pool_h_
+
+#include <linux/types.h>
+
+struct pool;
+
+/**
+ * pool_create - Create an sObject pool
+ * @name: Name of sObject pool for diagnostic purposes
+ * @obj_size: size of each sObject in the pool in bytes
+ * @pool: Will contain NULL or sObject pool handle
+ *
+ * Return	IMG_SUCCESS or an error code.
+ */
+int pool_create(const unsigned char * const name,
+		unsigned int obj_size,
+		struct pool ** const pool);
+
+/*
+ * @Function	pool_delete
+ * @Description
+ * Delete an sObject pool. All psObjects allocated from the pool must
+ * be free'd with pool_free() before deleting the sObject pool.
+ * @Input	pool : Object Pool pointer
+ * @Return IMG_SUCCESS or an error code.
+ */
+int pool_delete(struct pool * const pool);
+
+/*
+ * @Function	pool_alloc
+ * @Description
+ * Allocate an Object from an Object pool.
+ * @Input	pool : Object Pool
+ * @Output	obj_hdnl : Pointer containing the handle to the
+ * object created or IMG_NULL
+ * @Return    IMG_SUCCESS or an error code.
+ */
+int pool_alloc(struct pool * const pool,
+	       void ** const obj_hdnl);
+
+/*
+ * @Function	pool_free
+ * @Description
+ * Free an sObject previously allocated from an sObject pool.
+ * @Input	pool : Object Pool pointer.
+ * @Output	obj_hdnl : Handle to the object to be freed.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int pool_free(struct pool * const pool,
+	      void * const obj_hdnl);
+
+#endif /* _pool_h_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/ra.c b/drivers/media/platform/img/vxe-vxd/common/ra.c
--- a/drivers/media/platform/img/vxe-vxd/common/ra.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/ra.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,972 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Implements generic resource allocation.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "hash.h"
+#include "img_errors.h"
+#include "pool.h"
+#include "ra.h"
+
+static unsigned char	global_init;
+
+/* pool of struct arena's */
+static struct pool *global_pool_arena;
+
+/* pool of struct boundary tag */
+static struct pool *global_pool_bt;
+
+/**
+ * ra_request_alloc_fail - ra_request_alloc_fail
+ * @import_hdnl : Callback handle.
+ * @requested_size : Requested allocation size.
+ * @ref : Pointer to user reference data.
+ * @alloc_flags : Allocation flags.
+ * @actual_size : Pointer to contain the actual allocated size.
+ * @base_addr : Allocation base(always 0,it is failing).
+ *
+ * Default callback allocator used if no callback is specified, always fails
+ * to allocate further resources to the arena.
+ */
+static int ra_request_alloc_fail(void *import_hdnl,
+				 unsigned long long requested_size,
+				 unsigned long long *actual_size,
+				 void **ref,
+				 unsigned int alloc_flags,
+				 unsigned long long *base_addr)
+{
+	if (base_addr)
+		*base_addr = 0;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	ra_log2
+ * @Description
+ * Calculates the Log2(n) with n being a 64-bit value.
+ *
+ * @Input	value : Input value.
+ * @Output	None
+ * @Return	result : Log2(ui64Value).
+ */
+
+static unsigned int ra_log2(unsigned long long value)
+{
+	int res = 0;
+
+	value >>= 1;
+	while (value > 0) {
+		value >>= 1;
+		res++;
+	}
+	return res;
+}
+
+/*
+ * @Function	ra_segment_list_insert_after
+ * @Description	Insert a boundary tag into an arena segment list after a
+ *		specified boundary tag.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_here_arg : The boundary tag before which psBTToInsert
+ *		will be added .
+ * @Input	bt_to_insert_arg : The boundary tag to insert.
+ * @Output	None
+ * @Return	None
+ */
+static void ra_segment_list_insert_after(struct arena *arena_arg,
+					 struct btag *bt_here_arg,
+					 struct btag *bt_to_insert_arg)
+{
+	bt_to_insert_arg->nxt_seg = bt_here_arg->nxt_seg;
+	bt_to_insert_arg->prv_seg = bt_here_arg;
+
+	if (!bt_here_arg->nxt_seg)
+		arena_arg->tail_seg = bt_to_insert_arg;
+	else
+		bt_here_arg->nxt_seg->prv_seg = bt_to_insert_arg;
+
+	bt_here_arg->nxt_seg = bt_to_insert_arg;
+}
+
+/*
+ * @Function	ra_segment_list_insert
+ * @Description
+ * Insert a boundary tag into an arena segment list at the appropriate point.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_to_insert_arg : The boundary tag to insert.
+ * @Output	None
+ * @Return	None
+ */
+static void ra_segment_list_insert(struct arena *arena_arg,
+				   struct btag *bt_to_insert_arg)
+{
+	/* insert into the segment chain */
+	if (!arena_arg->head_seg) {
+		arena_arg->head_seg = bt_to_insert_arg;
+		arena_arg->tail_seg = bt_to_insert_arg;
+		bt_to_insert_arg->nxt_seg = NULL;
+		bt_to_insert_arg->prv_seg = NULL;
+	} else {
+		struct btag *bt_scan = arena_arg->head_seg;
+
+		while (bt_scan->nxt_seg &&
+		       bt_to_insert_arg->base >=
+		       bt_scan->nxt_seg->base) {
+			bt_scan = bt_scan->nxt_seg;
+		}
+		ra_segment_list_insert_after(arena_arg,
+					     bt_scan,
+					     bt_to_insert_arg);
+	}
+}
+
+/*
+ * @Function	ra_SegmentListRemove
+ * @Description
+ * Insert a boundary tag into an arena segment list at the appropriate point.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_to_remove_arg : The boundary tag to insert.
+ * @Output	None
+ * @Return	None
+ */
+static void ra_segment_list_remove(struct arena *arena_arg,
+				   struct btag *bt_to_remove_arg)
+{
+	if (!bt_to_remove_arg->prv_seg)
+		arena_arg->head_seg = bt_to_remove_arg->nxt_seg;
+	else
+		bt_to_remove_arg->prv_seg->nxt_seg = bt_to_remove_arg->nxt_seg;
+
+	if (!bt_to_remove_arg->nxt_seg)
+		arena_arg->tail_seg = bt_to_remove_arg->prv_seg;
+	else
+		bt_to_remove_arg->nxt_seg->prv_seg = bt_to_remove_arg->prv_seg;
+}
+
+/*
+ * @Function	ra_segment_split
+ * @Description
+ * Split a segment into two, maintain the arena segment list.
+ * The boundary tag should not be in the free table. Neither the original or
+ * the new psBTNeighbour bounary tag will be in the free table.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_to_split_arg : The boundary tag to split.
+ *		The required segment size of boundary tag after the split.
+ * @Output	None
+ * @Return	btag *: New boundary tag.
+ */
+static struct btag *ra_segment_split(struct arena *arena_arg,
+				     struct btag *bt_to_split_arg,
+				     unsigned long long size)
+{
+	struct btag *local_bt_neighbour = NULL;
+	int res = IMG_ERROR_FATAL;
+
+	res = pool_alloc(global_pool_bt, ((void **)&local_bt_neighbour));
+	if (res != IMG_SUCCESS)
+		return NULL;
+
+	local_bt_neighbour->prv_seg = bt_to_split_arg;
+	local_bt_neighbour->nxt_seg = bt_to_split_arg->nxt_seg;
+	local_bt_neighbour->bt_type = RA_BOUNDARY_TAG_TYPE_FREE;
+	local_bt_neighbour->size = (bt_to_split_arg->size - size);
+	local_bt_neighbour->base = (bt_to_split_arg->base + size);
+	local_bt_neighbour->nxt_free = NULL;
+	local_bt_neighbour->prv_free = NULL;
+	local_bt_neighbour->ref = bt_to_split_arg->ref;
+
+	if (!bt_to_split_arg->nxt_seg)
+		arena_arg->tail_seg = local_bt_neighbour;
+	else
+		bt_to_split_arg->nxt_seg->prv_seg = local_bt_neighbour;
+
+	bt_to_split_arg->nxt_seg = local_bt_neighbour;
+	bt_to_split_arg->size = size;
+
+	return local_bt_neighbour;
+}
+
+/*
+ * @Function	ra_free_list_insert
+ * @Description
+ * Insert a boundary tag into an arena free table.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_arg : The boundary tag to insert into an arena
+ *		free table.
+ * @Output	None
+ * @Return	None
+ */
+static void ra_free_list_insert(struct arena *arena_arg,
+				struct btag *bt_arg)
+{
+	unsigned int index = ra_log2(bt_arg->size);
+
+	bt_arg->bt_type = RA_BOUNDARY_TAG_TYPE_FREE;
+	if (index < FREE_TABLE_LIMIT)
+		bt_arg->nxt_free = arena_arg->head_free[index];
+	else
+		bt_arg->nxt_free = NULL;
+
+	bt_arg->prv_free = NULL;
+
+	if (index < FREE_TABLE_LIMIT) {
+		if (arena_arg->head_free[index])
+			arena_arg->head_free[index]->prv_free = bt_arg;
+	}
+
+	if (index < FREE_TABLE_LIMIT)
+		arena_arg->head_free[index] = bt_arg;
+}
+
+/*
+ * @Function	ra_free_list_remove
+ * @Description
+ * Remove a boundary tag from an arena free table.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_arg    : The boundary tag to remove from
+ *		an arena free table.
+ * @Output	None
+ * @Return	None
+ */
+static void ra_free_list_remove(struct arena *arena_arg,
+				struct btag *bt_arg)
+{
+	unsigned int index = ra_log2(bt_arg->size);
+
+	if (bt_arg->nxt_free)
+		bt_arg->nxt_free->prv_free = bt_arg->prv_free;
+
+	if (!bt_arg->prv_free && index < FREE_TABLE_LIMIT)
+		arena_arg->head_free[index] = bt_arg->nxt_free;
+	else if (bt_arg->prv_free)
+		bt_arg->prv_free->nxt_free = bt_arg->nxt_free;
+}
+
+/*
+ * @Function	ra_build_span_marker
+ * @Description
+ * Construct a span marker boundary tag.
+ * @Input	base : The base of the boundary tag.
+ * @Output	None
+ * @Return    btag * : New span marker boundary tag
+ */
+static struct btag *ra_build_span_marker(unsigned long long base)
+{
+	struct btag *local_bt = NULL;
+	int res = IMG_ERROR_FATAL;
+
+	res = pool_alloc(global_pool_bt, ((void **)&local_bt));
+	if (res != IMG_SUCCESS)
+		return NULL;
+
+	local_bt->bt_type = RA_BOUNDARY_TAG_TYPE_SPAN;
+	local_bt->base = base;
+	local_bt->size = 0;
+	local_bt->nxt_seg = NULL;
+	local_bt->prv_seg = NULL;
+	local_bt->nxt_free = NULL;
+	local_bt->prv_free = NULL;
+	local_bt->ref = NULL;
+
+	return local_bt;
+}
+
+/*
+ * @Function	ra_build_bt
+ * @Description
+ * Construct a boundary tag for a free segment.
+ * @Input	    ui64Base    : The base of the resource segment.
+ * @Input	    ui64Size    : The extent of the resource segment.
+ * @Output	None
+ * @Return    btag *       : New boundary tag
+ */
+static struct btag *ra_build_bt(unsigned long long base, unsigned long long size)
+{
+	struct btag *local_bt = NULL;
+	int res = IMG_ERROR_FATAL;
+
+	res = pool_alloc(global_pool_bt, ((void **)&local_bt));
+
+	if (res != IMG_SUCCESS)
+		return local_bt;
+
+	local_bt->bt_type = RA_BOUNDARY_TAG_TYPE_FREE;
+	local_bt->base = base;
+	local_bt->size = size;
+	local_bt->nxt_seg = NULL;
+	local_bt->prv_seg = NULL;
+	local_bt->nxt_free = NULL;
+	local_bt->prv_free = NULL;
+	local_bt->ref = NULL;
+
+	return local_bt;
+}
+
+/*
+ * @Function	ra_insert_resource
+ * @Description
+ * Add a free resource segment to an arena.
+ * @Input	base : The base of the resource segment.
+ * @Input	size : The size of the resource segment.
+ * @Output	None
+ * @Return	IMG_SUCCESS or an error code.
+ */
+static int ra_insert_resource(struct arena *arena_arg,
+			      unsigned long long base,
+			      unsigned long long size)
+{
+	struct btag *local_bt = NULL;
+
+	local_bt = ra_build_bt(base, size);
+	if (!local_bt)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	ra_segment_list_insert(arena_arg, local_bt);
+	ra_free_list_insert(arena_arg, local_bt);
+	arena_arg->max_idx = ra_log2(size);
+	if (1ULL << arena_arg->max_idx < size)
+		arena_arg->max_idx++;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	ra_insert_resource_span
+ * @Description
+ * Add a free resource span to an arena, complete with span markers.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	base : The base of the resource segment.
+ * @Input	size : The size of the resource segment.
+ * @Output	None
+ * @Return	btag * : The boundary tag representing
+ *		the free resource segment.
+ */
+static struct btag *ra_insert_resource_span(struct arena *arena_arg,
+					    unsigned long long base,
+					    unsigned long long size)
+{
+	struct btag *local_bt = NULL;
+	struct btag *local_bt_span_start = NULL;
+	struct btag *local_bt_span_end = NULL;
+
+	local_bt_span_start = ra_build_span_marker(base);
+	if (!local_bt_span_start)
+		return NULL;
+
+	local_bt_span_end = ra_build_span_marker(base + size);
+	if (!local_bt_span_end) {
+		pool_free(global_pool_bt, local_bt_span_start);
+		return NULL;
+	}
+
+	local_bt = ra_build_bt(base, size);
+	if (!local_bt) {
+		pool_free(global_pool_bt, local_bt_span_end);
+		pool_free(global_pool_bt, local_bt_span_start);
+		return NULL;
+	}
+
+	ra_segment_list_insert(arena_arg, local_bt_span_start);
+	ra_segment_list_insert_after(arena_arg,
+				     local_bt_span_start,
+				     local_bt);
+	ra_free_list_insert(arena_arg, local_bt);
+	ra_segment_list_insert_after(arena_arg,
+				     local_bt,
+				     local_bt_span_end);
+
+	return local_bt;
+}
+
+/*
+ * @Function	ra_free_bt
+ * @Description
+ * Free a boundary tag taking care of the segment list and the
+ *		boundary tag free table.
+ * @Input	arena_arg : Pointer to the input arena.
+ * @Input	bt_arg : The boundary tag to free.
+ * @Output	None
+ * @Return	None
+ */
+static void ra_free_bt(struct arena *arena_arg,
+		       struct btag *bt_arg)
+{
+	struct btag *bt_neibr;
+
+	/* try and coalesce with left bt_neibr */
+	bt_neibr = bt_arg->prv_seg;
+	if (bt_neibr &&
+	    bt_neibr->bt_type == RA_BOUNDARY_TAG_TYPE_FREE &&
+	    bt_neibr->base + bt_neibr->size == bt_arg->base) {
+		ra_free_list_remove(arena_arg, bt_neibr);
+		ra_segment_list_remove(arena_arg, bt_neibr);
+		bt_arg->base = bt_neibr->base;
+		bt_arg->size += bt_neibr->size;
+		pool_free(global_pool_bt, bt_neibr);
+	}
+
+	/* try to coalesce with right psBTNeighbour */
+	bt_neibr = bt_arg->nxt_seg;
+	if (bt_neibr &&
+	    bt_neibr->bt_type == RA_BOUNDARY_TAG_TYPE_FREE &&
+	    bt_arg->base + bt_arg->size == bt_neibr->base) {
+		ra_free_list_remove(arena_arg, bt_neibr);
+		ra_segment_list_remove(arena_arg, bt_neibr);
+		bt_arg->size += bt_neibr->size;
+		pool_free(global_pool_bt, bt_neibr);
+	}
+
+	if (bt_arg->nxt_seg &&
+	    bt_arg->nxt_seg->bt_type == RA_BOUNDARY_TAG_TYPE_SPAN &&
+	    bt_arg->prv_seg && bt_arg->prv_seg->bt_type ==
+	    RA_BOUNDARY_TAG_TYPE_SPAN) {
+		struct btag *ps_bt_nxt = bt_arg->nxt_seg;
+		struct btag *ps_bt_prev = bt_arg->prv_seg;
+
+		ra_segment_list_remove(arena_arg, ps_bt_nxt);
+		ra_segment_list_remove(arena_arg, ps_bt_prev);
+		ra_segment_list_remove(arena_arg, bt_arg);
+		arena_arg->import_free_fxn(arena_arg->import_hdnl,
+					   bt_arg->base,
+					   bt_arg->ref);
+		pool_free(global_pool_bt, ps_bt_nxt);
+		pool_free(global_pool_bt, ps_bt_prev);
+		pool_free(global_pool_bt, bt_arg);
+	} else {
+		ra_free_list_insert(arena_arg, bt_arg);
+	}
+}
+
+static int ra_check_btag(struct arena *arena_arg,
+			 unsigned long long size_arg,
+			 void **ref,
+			 struct btag *bt_arg,
+			 unsigned long long align_arg,
+			 unsigned long long *base_arg,
+			 unsigned int align_log2)
+{
+	unsigned long long local_align_base;
+	int res = IMG_ERROR_FATAL;
+
+	while (bt_arg) {
+		if (align_arg > 1ULL)
+			local_align_base = ((bt_arg->base + align_arg - 1)
+				>> align_log2) << align_log2;
+		else
+			local_align_base = bt_arg->base;
+
+		if ((bt_arg->base + bt_arg->size) >=
+		     (local_align_base + size_arg)) {
+			ra_free_list_remove(arena_arg, bt_arg);
+
+			/*
+			 * with align_arg we might need to discard the front of
+			 * this segment
+			 */
+			if (local_align_base > bt_arg->base) {
+				struct btag *btneighbor;
+
+				btneighbor = ra_segment_split(arena_arg,
+							      bt_arg,
+							      (local_align_base -
+							       bt_arg->base));
+				/*
+				 * Partition the buffer, create a new boundary
+				 * tag
+				 */
+				if (!btneighbor)
+					return IMG_ERROR_UNEXPECTED_STATE;
+
+				ra_free_list_insert(arena_arg, bt_arg);
+				bt_arg = btneighbor;
+			}
+
+			/*
+			 * The segment might be too big, if so, discard the back
+			 * of the segment
+			 */
+			if (bt_arg->size > size_arg) {
+				struct btag *btneighbor;
+
+				btneighbor = ra_segment_split(arena_arg,
+							      bt_arg,
+							      size_arg);
+				/*
+				 * Partition the buffer, create a new boundary
+				 * tag
+				 */
+				if (!btneighbor)
+					return IMG_ERROR_UNEXPECTED_STATE;
+
+				ra_free_list_insert(arena_arg, btneighbor);
+			}
+
+			bt_arg->bt_type = RA_BOUNDARY_TAG_TYPE_LIVE;
+
+			res = vid_hash_insert(arena_arg->hash_tbl,
+					      bt_arg->base,
+					      (unsigned long)bt_arg);
+			if (res != IMG_SUCCESS) {
+				ra_free_bt(arena_arg, bt_arg);
+				*base_arg = 0;
+				return IMG_ERROR_UNEXPECTED_STATE;
+			}
+
+			if (ref)
+				*ref = bt_arg->ref;
+
+			*base_arg = bt_arg->base;
+			return IMG_SUCCESS;
+		}
+		bt_arg = bt_arg->nxt_free;
+	}
+
+	return res;
+}
+
+/*
+ * @Function	ra_attempt_alloc_aligned
+ * @Description	Attempt to allocate from an arena
+ * @Input	arena_arg: Pointer to the input arena
+ * @Input	size_arg: The requested allocation size
+ * @Input	ref: The user references associated with the allocated
+ *		segment
+ * @Input	align_arg: Required alignment
+ * @Output	base_arg: Allocated resource size
+ * @Return	IMG_SUCCESS or an error code
+ */
+static int ra_attempt_alloc_aligned(struct arena *arena_arg,
+				    unsigned long long size_arg,
+				    void **ref,
+				    unsigned long long align_arg,
+				    unsigned long long *base_arg)
+{
+	unsigned int index;
+	unsigned int align_log2;
+	int res = IMG_ERROR_FATAL;
+
+	if (!arena_arg || !base_arg)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/*
+	 * Take the log of the alignment to get number of bits to shift
+	 * left/right for multiply/divide. Assumption made here is that
+	 * alignment has to be a power of 2 value. Aserting otherwise.
+	 */
+	align_log2 = ra_log2(align_arg);
+
+	/*
+	 * Search for a near fit free boundary tag, start looking at the
+	 * log2 free table for our required size and work on up the table.
+	 */
+	index = ra_log2(size_arg);
+
+	/*
+	 * If the Size required is exactly 2**n then use the n bucket, because
+	 * we know that every free block in that bucket is larger than 2**n,
+	 * otherwise start at then next bucket up.
+	 */
+	if (size_arg > (1ull << index))
+		index++;
+
+	while ((index < FREE_TABLE_LIMIT) && !arena_arg->head_free[index])
+		index++;
+
+	if (index >= FREE_TABLE_LIMIT) {
+		pr_err("requested allocation size doesn't fit in the arena. Increase MMU HEAP Size\n");
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	while (index < FREE_TABLE_LIMIT) {
+		if (arena_arg->head_free[index]) {
+			/* we have a cached free boundary tag */
+			struct btag *local_bt =
+				arena_arg->head_free[index];
+
+			res = ra_check_btag(arena_arg,
+					    size_arg,
+					    ref,
+					    local_bt,
+					    align_arg,
+					    base_arg,
+					    align_log2);
+			if (res != IMG_SUCCESS)
+				return res;
+		}
+		index++;
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	vid_ra_init
+ * @Description	Initializes the RA module. Must be called before any other
+ *		ra API function
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_initialise(void)
+{
+	int res = IMG_ERROR_FATAL;
+
+	if (!global_init) {
+		res = pool_create("img-arena",
+				  sizeof(struct arena),
+				  &global_pool_arena);
+		if (res != IMG_SUCCESS)
+			return IMG_ERROR_UNEXPECTED_STATE;
+
+		res = pool_create("img-bt",
+				  sizeof(struct btag),
+				  &global_pool_bt);
+		if (res != IMG_SUCCESS) {
+			res = pool_delete(global_pool_arena);
+			global_pool_arena = NULL;
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+		global_init = 1;
+		res = IMG_SUCCESS;
+	}
+
+	return res;
+}
+
+/*
+ * @Function	vid_ra_deinit
+ * @Description	Deinitializes the RA module
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_deinit(void)
+{
+	int res = IMG_ERROR_FATAL;
+
+	if (global_init) {
+		if (global_pool_arena) {
+			res = pool_delete(global_pool_arena);
+			global_pool_arena = NULL;
+		}
+		if (global_pool_bt) {
+			res = pool_delete(global_pool_bt);
+			global_pool_bt = NULL;
+		}
+		global_init = 0;
+		res = IMG_SUCCESS;
+	}
+	return res;
+}
+
+/*
+ * @Function	vid_ra_create
+ * @Description	Used to create a resource arena.
+ * @Input	name: The name of the arena for diagnostic purposes
+ * @Input	base_arg: The base of an initial resource span or 0
+ * @Input	size_arg: The size of an initial resource span or 0
+ * @Input	quantum: The arena allocation quantum
+ * @Input	(*import_alloc_fxn): A resource allocation callback or NULL
+ * @Input	(*import_free_fxn): A resource de-allocation callback or NULL
+ * @Input	import_hdnl: Handle passed to alloc and free or NULL
+ * @Output	arena_hndl: The handle for the arene being created, or NULL
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_create(const unsigned char * const name,
+		  unsigned long long base_arg,
+		  unsigned long long size_arg,
+		  unsigned long	quantum,
+		  int (*import_alloc_fxn)(void * const import_hdnl,
+					  unsigned long long req_sz,
+					  unsigned long long * const actl_sz,
+					  void ** const ref,
+					  unsigned int alloc_flags,
+					  unsigned long long * const base_arg),
+		  int (*import_free_fxn)(void * const import_hdnl,
+					 unsigned long long import_base,
+					 void * const import_ref),
+					 void *import_hdnl,
+					 void **arena_hndl)
+{
+	struct arena *local_arena = NULL;
+	unsigned int idx = 0;
+	int res = IMG_ERROR_FATAL;
+
+	if (!arena_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	*(arena_hndl) = NULL;
+
+	if (global_init) {
+		res = pool_alloc(global_pool_arena, ((void **)&local_arena));
+		if (!local_arena || res != IMG_SUCCESS)
+			return IMG_ERROR_UNEXPECTED_STATE;
+
+		local_arena->name = NULL;
+		if (name)
+			local_arena->name = kstrdup((const signed char *)name,
+						    GFP_KERNEL);
+		if (import_alloc_fxn)
+			local_arena->import_alloc_fxn = import_alloc_fxn;
+		else
+			local_arena->import_alloc_fxn = ra_request_alloc_fail;
+
+		local_arena->import_free_fxn = import_free_fxn;
+		local_arena->import_hdnl = import_hdnl;
+
+		for (idx = 0; idx < FREE_TABLE_LIMIT; idx++)
+			local_arena->head_free[idx] = NULL;
+
+		local_arena->head_seg = NULL;
+		local_arena->tail_seg = NULL;
+		local_arena->quantum = quantum;
+
+		res = vid_hash_create(MINIMUM_HASH_SIZE,
+				      &local_arena->hash_tbl);
+
+		if (!local_arena->hash_tbl) {
+			vid_hash_delete(local_arena->hash_tbl);
+			kfree(local_arena->name);
+			local_arena->name = NULL;
+			return IMG_ERROR_UNEXPECTED_STATE;
+		}
+
+		//if (size_arg > (unsigned long long)0) {
+		if (size_arg > 0ULL) {
+			size_arg = (size_arg + quantum - 1) / quantum * quantum;
+
+			res = ra_insert_resource(local_arena,
+						 base_arg,
+						 size_arg);
+			if (res != IMG_SUCCESS) {
+				vid_hash_delete(local_arena->hash_tbl);
+				pool_free(global_pool_arena, local_arena);
+				kfree(local_arena->name);
+				local_arena->name = NULL;
+				return IMG_ERROR_UNEXPECTED_STATE;
+			}
+		}
+		*(arena_hndl) = local_arena;
+		res = IMG_SUCCESS;
+	}
+
+	return res;
+}
+
+/*
+ * @Function	vid_ra_delete
+ * @Description	Used to delete a resource arena. All resources allocated from
+ *		the arena must be freed before deleting the arena
+ * @Input	arena_hndl: The handle to the arena to delete
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_delete(void * const arena_hndl)
+{
+	int res = IMG_ERROR_FATAL;
+	struct arena *local_arena = NULL;
+	unsigned int idx;
+
+	if (!arena_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (global_init) {
+		local_arena = (struct arena *)arena_hndl;
+		kfree(local_arena->name);
+		local_arena->name = NULL;
+		for (idx = 0; idx < FREE_TABLE_LIMIT; idx++)
+			local_arena->head_free[idx] = NULL;
+
+		while (local_arena->head_seg) {
+			struct btag *local_bt = local_arena->head_seg;
+
+			ra_segment_list_remove(local_arena, local_bt);
+		}
+		res = vid_hash_delete(local_arena->hash_tbl);
+		if (res != IMG_SUCCESS)
+			return IMG_ERROR_UNEXPECTED_STATE;
+
+		res = pool_free(global_pool_arena, local_arena);
+		if (res != IMG_SUCCESS)
+			return IMG_ERROR_UNEXPECTED_STATE;
+	}
+
+	return res;
+}
+
+/*
+ * @Function	vid_ra_add
+ * @Description	Used to add a resource span to an arena. The span must not
+ *		overlap with any span previously added to the arena
+ * @Input	base_arg: The base_arg of the span
+ * @Input	size_arg: The size of the span
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_add(void * const arena_hndl, unsigned long long base_arg, unsigned long long size_arg)
+{
+	int res = IMG_ERROR_FATAL;
+	struct arena *local_arena = NULL;
+
+	if (!arena_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (global_init) {
+		local_arena = (struct arena *)arena_hndl;
+		size_arg = (size_arg + local_arena->quantum - 1) /
+			local_arena->quantum * local_arena->quantum;
+
+		res = ra_insert_resource(local_arena, base_arg, size_arg);
+		if (res != IMG_SUCCESS)
+			return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	return res;
+}
+
+/*
+ * @Function	vid_ra_alloc
+ * @Description	Used to allocate resource from an arena
+ * @Input	arena_hndl: The handle to the arena to create the resource
+ * @Input	request_size: The requested size of resource segment
+ * @Input	actl_size: The actualSize of resource segment
+ * @Input	ref: The user reference associated with allocated resource
+ *		span
+ * @Input	alloc_flags: AllocationFlags influencing allocation policy
+ * @Input	align_arg: The alignment constraint required for the allocated
+ *		segment
+ * @Output	base_args: The base of the allocated resource
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_alloc(void * const arena_hndl,
+		 unsigned long long request_size,
+		 unsigned long long * const actl_sz,
+		 void ** const ref,
+		 unsigned int alloc_flags,
+		 unsigned long long alignarg,
+		 unsigned long long * const basearg)
+{
+	int res = IMG_ERROR_FATAL;
+	struct arena *arn_ctx = NULL;
+	unsigned long long loc_size = request_size;
+
+	if (!arena_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (global_init) {
+		arn_ctx = (struct arena *)arena_hndl;
+		loc_size = ((loc_size + arn_ctx->quantum - 1) /
+				arn_ctx->quantum) * arn_ctx->quantum;
+
+		if (actl_sz)
+			*actl_sz = loc_size;
+
+		/*
+		 * If allocation failed then we might have an import source
+		 * which can provide more resource, else we will have to fail
+		 * the allocation to the caller.
+		 */
+		if (alloc_flags == RA_SEQUENTIAL_ALLOCATION)
+			res = ra_attempt_alloc_aligned(arn_ctx,
+						       loc_size,
+						       ref,
+						       alignarg,
+						       basearg);
+
+		if (res != IMG_SUCCESS) {
+			void *import_ref = NULL;
+			unsigned long long import_base = 0ULL;
+			unsigned long long locimprt_reqsz = loc_size;
+			unsigned long long locimprt_actsz = 0ULL;
+
+			res = arn_ctx->import_alloc_fxn(arn_ctx->import_hdnl,
+					locimprt_reqsz,
+					&locimprt_actsz,
+					&import_ref,
+					alloc_flags,
+					&import_base);
+
+			if (res == IMG_SUCCESS) {
+				struct btag *local_bt =
+					ra_insert_resource_span(arn_ctx,
+								import_base,
+								locimprt_actsz);
+
+				/*
+				 * Successfully import more resource, create a
+				 * span to represent it and retry the allocation
+				 * attempt
+				 */
+				if (!local_bt) {
+					/*
+					 * Insufficient resources to insert the
+					 * newly acquired span, so free it back
+					 */
+					arn_ctx->import_free_fxn(arn_ctx->import_hdnl,
+							import_base,
+							import_ref);
+					return IMG_ERROR_UNEXPECTED_STATE;
+				}
+				local_bt->ref = import_ref;
+				if (alloc_flags == RA_SEQUENTIAL_ALLOCATION) {
+					res = ra_attempt_alloc_aligned(arn_ctx,
+								       loc_size,
+								       ref,
+								       alignarg,
+								       basearg);
+				}
+			}
+		}
+	}
+
+	return res;
+}
+
+/*
+ * @Function	vid_ra_free
+ * @Description	Used to free a resource segment
+ * @Input	arena_hndl: The arena the segment was originally allocated from
+ * @Input	base_arg: The base of the span
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_free(void * const arena_hndl, unsigned long long base_arg)
+{
+	int res = IMG_ERROR_FATAL;
+	struct arena *local_arena = NULL;
+	struct btag *local_bt = NULL;
+	unsigned long	uip_res;
+
+	if (!arena_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (global_init) {
+		local_arena = (struct arena *)arena_hndl;
+
+		res = vid_hash_remove(local_arena->hash_tbl,
+				      base_arg,
+				      &uip_res);
+		if (res != IMG_SUCCESS)
+			return res;
+		local_bt = (struct btag *)uip_res;
+
+		ra_free_bt(local_arena, local_bt);
+	}
+
+	return res;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/ra.h b/drivers/media/platform/img/vxe-vxd/common/ra.h
--- a/drivers/media/platform/img/vxe-vxd/common/ra.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/ra.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Implements generic resource allocation.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *      Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef _RA_H_
+#define _RA_H_
+
+#define MINIMUM_HASH_SIZE  (64)
+#define FREE_TABLE_LIMIT   (64)
+
+/* Defines whether sequential or random allocation is used */
+enum {
+	RA_SEQUENTIAL_ALLOCATION = 0,
+	RA_RANDOM_ALLOCATION,
+	RA_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Defines boundary tag type */
+enum eboundary_tag_type {
+	RA_BOUNDARY_TAG_TYPE_SPAN = 0,
+	RA_BOUNDARY_TAG_TYPE_FREE,
+	RA_BOUNDARY_TAG_TYPE_LIVE,
+	RA_BOUNDARY_TAG_TYPE_MAX,
+	RA_BOUNDARY_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * @Description
+ * Boundary tags, used to describe a resource segment
+ *
+ * @enum0: span markers
+ * @enum1: free resource segment
+ * @enum2: allocated resource segment
+ * @enum3: max
+ * @base,size: The base resource of this segment and extent of this segment
+ * @nxt_seg, prv_seg: doubly linked ordered list of all segments
+ *			within the arena
+ * @nxt_free, prv_free: doubly linked un-ordered list of free segments
+ * @reference : a user reference associated with this span, user
+ *		references are currently only provided in
+ *		the callback mechanism
+ */
+struct btag {
+	unsigned int bt_type;
+	unsigned long long base;
+	unsigned long long size;
+	struct btag *nxt_seg;
+	struct btag *prv_seg;
+	struct btag *nxt_free;
+	struct btag *prv_free;
+	void *ref;
+};
+
+/*
+ * @Description
+ * resource allocation arena
+ *
+ * @name: arena for diagnostics output
+ * @quantum: allocations within this arena are quantum sized
+ * @max_idx: index of the last position in the psBTHeadFree table,
+ *		with available free space
+ * @import_alloc_fxn: import interface, if provided
+ * @import_free_fxn: import interface, if provided
+ * @import_hdnl: import interface, if provided
+ * @head_free: head of list of free boundary tags for indexed by Log2
+ *		of the boundary tag size. Power-of-two table of free lists
+ * @head_seg, tail_seg : resource ordered segment list
+ * @ps_hash : segment address to boundary tag hash table
+ */
+struct arena {
+	unsigned char *name;
+	unsigned long quantum;
+	unsigned int max_idx;
+	int (*import_alloc_fxn)(void *import_hdnl,
+				unsigned long long requested_size,
+				unsigned long long *actual_size,
+				void **ref,
+				unsigned int alloc_flags,
+				unsigned long long *base_addr);
+	int (*import_free_fxn)(void *import_hdnl,
+			       unsigned long long base,
+			       void *ref);
+	void *import_hdnl;
+	struct btag *head_free[FREE_TABLE_LIMIT];
+	struct btag *head_seg;
+	struct btag *tail_seg;
+	struct hash *hash_tbl;
+};
+
+/*
+ * @Function	vid_ra_init
+ * @Description	Initializes the RA module. Must be called before any other
+ *		ra API function
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_initialise(void);
+
+/*
+ * @Function	vid_ra_deinit
+ * @Description	Deinitializes the RA module
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_deinit(void);
+
+/*
+ * @Function	vid_ra_create
+ * @Description	Used to create a resource arena.
+ * @Input	name: The name of the arena for diagnostic purposes
+ * @Input	base_arg: The base of an initial resource span or 0
+ * @Input	size_arg: The size of an initial resource span or 0
+ * @Input	quantum: The arena allocation quantum
+ * @Input	(*import_alloc_fxn): A resource allocation callback or NULL
+ * @Input	(*import_free_fxn): A resource de-allocation callback or NULL
+ * @Input	import_hdnl: Handle passed to alloc and free or NULL
+ * @Output	arena_hndl: The handle for the arene being created, or NULL
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_create(const unsigned char * const name,
+		  unsigned long long base_arg,
+		  unsigned long long size_arg,
+		  unsigned long quantum,
+		  int (*import_alloc_fxn)(void * const import_hdnl,
+					  unsigned long long req_sz,
+					  unsigned long long * const actl_sz,
+					  void ** const ref,
+					  unsigned int alloc_flags,
+					  unsigned long long * const base_arg),
+		  int (*import_free_fxn)(void * const import_hdnl,
+					 unsigned long long import_base,
+					 void * const import_ref),
+		  void *import_hdnl,
+		  void **arena_hndl);
+
+/*
+ * @Function	vid_ra_delete
+ * @Description	Used to delete a resource arena. All resources allocated from
+ *		the arena must be freed before deleting the arena
+ * @Input	arena_hndl: The handle to the arena to delete
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_delete(void * const arena_hndl);
+
+/*
+ * @Function	vid_ra_add
+ * @Description	Used to add a resource span to an arena. The span must not
+ *		overlap with any span previously added to the arena
+ * @Input	base_arg: The base_arg of the span
+ * @Input	size_arg: The size of the span
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_add(void * const arena_hndl, unsigned long long base_arg, unsigned long long size_arg);
+
+/*
+ * @Function	vid_ra_alloc
+ * @Description	Used to allocate resource from an arena
+ * @Input	arena_hndl: The handle to the arena to create the resource
+ * @Input	request_size: The requested size of resource segment
+ * @Input	actl_size: The actualSize of resource segment
+ * @Input	ref: The user reference associated with allocated resource
+ *		span
+ * @Input	alloc_flags: AllocationFlags influencing allocation policy
+ * @Input	align_arg: The alignment constraint required for the allocated
+ *		segment
+ * @Output	base_args: The base of the allocated resource
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_alloc(void * const arena_hndl,
+		 unsigned long long request_size,
+		 unsigned long long * const actl_sz,
+		 void ** const ref,
+		 unsigned int alloc_flags,
+		 unsigned long long align_arg,
+		 unsigned long long * const base_arg);
+
+/*
+ * @Function	vid_ra_free
+ * @Description	Used to free a resource segment
+ * @Input	arena_hndl: The arena the segment was originally allocated from
+ * @Input	base_arg: The base of the span
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int vid_ra_free(void * const arena_hndl, unsigned long long base_arg);
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/resource.c b/drivers/media/platform/img/vxe-vxd/common/resource.c
--- a/drivers/media/platform/img/vxe-vxd/common/resource.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/resource.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,578 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VXD DEC Resource manager implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "dq.h"
+#include "img_errors.h"
+#include "lst.h"
+#include "resource.h"
+
+struct resource_list_elem {
+	struct dq_linkage_t	link;
+	void *item;
+	unsigned int id;
+	unsigned int *refcnt;
+};
+
+/*
+ * marks an item as used by incrementing the reference count
+ */
+int resource_item_use(unsigned int *refcnt)
+{
+	if (refcnt)
+		(*refcnt)++;
+
+	return 0;
+}
+
+/*
+ * returns an item by decrementing the reference count
+ */
+void resource_item_return(unsigned int *refcnt)
+{
+	if (refcnt && *refcnt > 0)
+		(*refcnt)--;
+}
+
+/*
+ * releases an item by setting reference count to 1 (original owner)
+ */
+int resource_item_release(unsigned int *refcnt)
+{
+	if (refcnt)
+		*refcnt = 1;
+
+	return 0;
+}
+
+/*
+ * indicates whether an item is free to be used (no owners)
+ */
+int resource_item_isavailable(unsigned int *refcnt)
+{
+	if (refcnt)
+		return (*refcnt == 0) ? 1 : 0;
+	else
+		return 0;
+}
+
+/*
+ * adds an item (and associated id) to a resource list
+ */
+int resource_list_add_img(struct lst_t *list, void *item, unsigned int id, unsigned int *refcnt)
+{
+	struct resource_list_elem *listelem = NULL;
+	int bfound = 0;
+	unsigned int result = 0;
+
+	if (!list || !item) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error;
+	}
+
+	/*
+	 * Decrement the reference count on the item
+	 * to signal that the owner has relinquished it.
+	 */
+	resource_item_return(refcnt);
+
+	/*
+	 *  Determine whether this buffer is already in the list.
+	 */
+	listelem = lst_first(list);
+	while (listelem) {
+		if (listelem->item == item) {
+			bfound = 1;
+			break;
+		}
+
+		listelem = lst_next(listelem);
+	}
+
+	if (!bfound) {
+		/*
+		 * allocate the image buffer list element structure.
+		 */
+		listelem = kmalloc(sizeof(*(listelem)), GFP_KERNEL);
+		if (!listelem) {
+			result = IMG_ERROR_OUT_OF_MEMORY;
+			goto error;
+		}
+		memset(listelem, 0, sizeof(*(listelem)));
+
+		/*
+		 * setup the list element.
+		 */
+		listelem->item = item;
+		listelem->id = id;
+		listelem->refcnt = refcnt;
+
+		/*
+		 * add the element to the list.
+		 */
+		lst_add(list, (void *)listelem);
+	}
+
+	return 0;
+
+error:
+	return result;
+}
+
+/*
+ * obtains pointer to item at head of resource list
+ */
+void *resource_list_pickhead(struct lst_t *list)
+{
+	struct resource_list_elem *listelem = NULL;
+	void *item = NULL;
+
+	if (!list)
+		goto error;
+	/*
+	 * peek the head item of the list.
+	 */
+	listelem = lst_first(list);
+	if (listelem)
+		item = listelem->item;
+
+error:
+	return item;
+}
+
+/*
+ * removes item from resource list
+ */
+int resource_list_remove(struct lst_t *list, void *item)
+{
+	struct resource_list_elem *listelem = NULL;
+	unsigned int result = 0;
+
+	if (!list || !item) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error;
+	}
+
+	/*
+	 * find the specified item in the list.
+	 */
+	listelem = lst_first(list);
+	while (listelem) {
+		if (listelem->item == item) {
+			if (*listelem->refcnt != 0)
+				pr_warn("item remove from list still in use\n");
+
+			/*
+			 * Remove the item from the list.
+			 */
+			lst_remove(list, listelem);
+			/*
+			 * Free the stream unit queue element.
+			 */
+			kfree(listelem);
+			listelem = NULL;
+			return 0;
+		}
+
+		listelem = lst_next(listelem);
+	}
+
+#if defined(DEBUG_DECODER_DRIVER) || defined(DEBUG_ENCODER_DRIVER)
+	pr_info("item could not be located to remove from RESOURCE list\n");
+#endif
+
+	return IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+
+error:
+	return result;
+}
+
+/*
+ * resource_list_removehead - removes item at head of resource list
+ * @list: head of resource list
+ */
+void *resource_list_removehead(struct lst_t *list)
+{
+	struct resource_list_elem *listelem = NULL;
+	void *item = NULL;
+
+	if (!list)
+		goto error;
+
+	/*
+	 * peek the head item of the list.
+	 */
+	listelem = lst_removehead(list);
+	if (listelem) {
+		item = listelem->item;
+		kfree(listelem);
+		listelem = NULL;
+	}
+
+error:
+	return item;
+}
+
+/*
+ * removes next available item from resource list.
+ * item is freed if no longer used
+ */
+int resource_list_remove_nextavail(struct lst_t *list,
+				   resource_pfn_freeitem fn_freeitem,
+				   void *free_cb_param)
+{
+	struct resource_list_elem *listelem = NULL;
+	unsigned int result = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+
+	if (!list) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error;
+	}
+
+	/*
+	 * find the next unused item in the list.
+	 */
+	listelem = lst_first(list);
+	while (listelem) {
+		if (resource_item_isavailable(listelem->refcnt)) {
+			resource_item_return(listelem->refcnt);
+
+			if (*listelem->refcnt == 0) {
+				if (fn_freeitem)
+					fn_freeitem(listelem->item, free_cb_param);
+				else
+					kfree(listelem->item);
+
+				listelem->item = NULL;
+			}
+
+			/*
+			 * get the next element from the list.
+			 */
+			lst_remove(list, listelem);
+
+			/*
+			 * free the buffer list element.
+			 */
+			kfree(listelem);
+			listelem = NULL;
+
+			result = 0;
+			break;
+		}
+
+		listelem = lst_next(listelem);
+	}
+
+	if (result == IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE)
+		pr_debug("failed to locate an available resource element to remove\n");
+
+error:
+	return result;
+}
+
+/*
+ * obtains pointer to an available item from the resource list
+ */
+void *resource_list_get_avail(struct lst_t *list)
+{
+	struct resource_list_elem *listelem = NULL;
+	void *item = NULL;
+
+	if (!list)
+		goto error;
+
+	/*
+	 * find the next unused item in the list.
+	 */
+	listelem = lst_first(list);
+	while (listelem) {
+		if (resource_item_isavailable(listelem->refcnt)) {
+			resource_item_use(listelem->refcnt);
+			item = listelem->item;
+			break;
+		}
+		listelem = lst_next(listelem);
+	}
+
+error:
+	return item;
+}
+
+/*
+ * signal duplicate use of specified item with resource list
+ */
+void *resource_list_reuseitem(struct lst_t *list, void *item)
+{
+	struct resource_list_elem *listelem = NULL;
+	void *ret_item  = NULL;
+
+	if (!list || !item)
+		goto error;
+
+	/*
+	 * find the specified item in the list.
+	 */
+	listelem = lst_first(list);
+
+	while (listelem) {
+		if (listelem->item == item) {
+			resource_item_use(listelem->refcnt);
+			ret_item = item;
+			break;
+		}
+
+		listelem = lst_next(listelem);
+	}
+
+error:
+	return ret_item;
+}
+
+/*
+ * obtain pointer to item from resource list with id
+ */
+void *resource_list_getbyid(struct lst_t *list, unsigned int id)
+{
+	struct resource_list_elem *listelem = NULL;
+	void *item  = NULL;
+
+	if (!list)
+		goto error;
+
+	/*
+	 * find the next unused buffer in the list.
+	 */
+	listelem = lst_first(list);
+	while (listelem) {
+		if (listelem->id == id) {
+			resource_item_use(listelem->refcnt);
+			item = listelem->item;
+			break;
+		}
+
+		listelem = lst_next(listelem);
+	}
+
+error:
+	return item;
+}
+
+/*
+ * obtain the number of available (unused) items within list.
+ */
+int resource_list_getnumavail(struct lst_t *list)
+{
+	struct resource_list_elem *listelem = NULL;
+	unsigned int num_items = 0;
+
+	if (!list)
+		goto error;
+
+	/*
+	 * find the next unused buffer in the list.
+	 */
+	listelem = lst_first(list);
+	while (listelem) {
+		if (resource_item_isavailable(listelem->refcnt))
+			num_items++;
+
+		listelem = lst_next(listelem);
+	}
+
+error:
+	return num_items;
+}
+
+/*
+ * Obtain the number of items within list
+ */
+int resource_list_getnum(struct lst_t *list)
+{
+	struct resource_list_elem *listelem = NULL;
+	unsigned int num_items = 0;
+
+	if (!list)
+		goto error;
+
+	/*
+	 * find the next unused buffer in the list.
+	 */
+	listelem = lst_first(list);
+	while (listelem) {
+		num_items++;
+		listelem = lst_next(listelem);
+	}
+
+error:
+	return num_items;
+}
+
+/*
+ * replaces an item (of specified id) within a resource list
+ */
+int resource_list_replace(struct lst_t *list, void *item, unsigned int id, unsigned int *refcnt,
+			  resource_pfn_freeitem fn_freeitem,
+			  void *free_cb_param)
+{
+	struct resource_list_elem *listelem = NULL;
+	unsigned int result = 0;
+
+	if (!list || !item) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error;
+	}
+
+	/*
+	 * determine whether this sequence header is already in the list
+	 */
+	listelem = lst_first(list);
+	while (listelem) {
+		if (listelem->id == id) {
+			resource_item_return(listelem->refcnt);
+			if (*listelem->refcnt == 0) {
+				if (fn_freeitem)
+					fn_freeitem(listelem->item,
+						    free_cb_param);
+				else {
+					if (!listelem->item)
+						kfree(listelem->item);
+				}
+				listelem->item = NULL;
+			}
+
+			lst_remove(list, listelem);
+			break;
+		}
+
+		listelem = lst_next(listelem);
+	}
+
+	if (!listelem) {
+		/*
+		 * Allocate the sequence header list element structure.
+		 */
+		listelem = kmalloc(sizeof(*(listelem)), GFP_KERNEL);
+		if (!listelem) {
+			result = IMG_ERROR_OUT_OF_MEMORY;
+			goto error;
+		}
+		memset(listelem, 0, sizeof(*(listelem)));
+	}
+
+	/*
+	 * setup the sequence header list element.
+	 */
+	resource_item_use(refcnt);
+
+	listelem->item = item;
+	listelem->id = id;
+	listelem->refcnt = refcnt;
+
+	/*
+	 * Add the sequence header list element to the sequence header list.
+	 */
+	lst_add(list, (void *)listelem);
+
+	return 0;
+
+error:
+	return result;
+}
+
+/*
+ * removes all items from a resource list.
+ */
+int resource_list_empty(struct lst_t *list, unsigned int release_item,
+			resource_pfn_freeitem fn_freeitem,
+			void *free_cb_param)
+{
+	struct resource_list_elem *listelem = NULL;
+	unsigned int result = 0;
+
+	if (!list) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error;
+	}
+
+	/*
+	 * remove all the buffer list elements from the image buffer list
+	 */
+	listelem = lst_removehead(list);
+	while (listelem) {
+		if (release_item) {
+			resource_item_release(listelem->refcnt);
+		} else {
+			/*
+			 * Return and free.
+			 */
+			resource_item_return(listelem->refcnt);
+
+			if (!listelem->refcnt || *listelem->refcnt == 0) {
+				if (fn_freeitem)
+					fn_freeitem(listelem->item,
+						    free_cb_param);
+				else
+					kfree(listelem->item);
+				listelem->item = NULL;
+			}
+		}
+
+		/*
+		 * free the buffer list element.
+		 */
+		kfree(listelem);
+		listelem = NULL;
+
+		/*
+		 * Get the next element from the list.
+		 */
+		listelem = lst_removehead(list);
+	}
+
+	return 0;
+
+error:
+	return result;
+}
+
+/*
+ * obtain the number of pictures within list
+ */
+int resource_getnumpict(struct lst_t *list)
+{
+	struct resource_list_elem *listelem = NULL;
+	unsigned int num_pict = 0;
+
+	if (!list)
+		goto error;
+
+	/*
+	 * find the next unused buffer in the list.
+	 */
+	listelem = lst_first(list);
+	while (listelem) {
+		num_pict++;
+		listelem = lst_next(listelem);
+	}
+
+error:
+	return num_pict;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/resource.h b/drivers/media/platform/img/vxe-vxd/common/resource.h
--- a/drivers/media/platform/img/vxe-vxd/common/resource.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/resource.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD DEC SYSDEV and UI Interface header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#ifndef _VXD_RESOURCE_H
+#define _VXD_RESOURCE_H
+
+typedef int (*resource_pfn_freeitem)(void *item, void *free_cb_param);
+
+int resource_item_use(unsigned int *refcnt);
+
+void resource_item_return(unsigned int *refcnt);
+
+int resource_item_release(unsigned int *refcnt);
+
+int resource_item_isavailable(unsigned int *refcnt);
+
+int resource_list_add_img(struct lst_t *list, void *item, unsigned int id, unsigned int *refcnt);
+
+void *resource_list_pickhead(struct lst_t *list);
+
+int resource_list_remove(struct lst_t *list, void *item);
+
+/**
+ * resource_list_removehead - removes item at head of resource list
+ * @list: head of resource list
+ */
+
+void *resource_list_removehead(struct lst_t *list);
+
+int resource_list_remove_nextavail(struct lst_t *list,
+				   resource_pfn_freeitem fn_freeitem,
+				   void *free_cb_param);
+
+void *resource_list_get_avail(struct lst_t *list);
+
+void *resource_list_reuseitem(struct lst_t *list, void *item);
+
+void *resource_list_getbyid(struct lst_t *list, unsigned int id);
+
+int resource_list_getnumavail(struct lst_t *list);
+
+int resource_list_getnum(struct lst_t *list);
+
+int resource_list_replace(struct lst_t *list, void *item, unsigned int id, unsigned int *refcnt,
+			  resource_pfn_freeitem fn_freeitem,
+			  void *free_cb_param);
+
+int resource_list_empty(struct lst_t *list, unsigned int release_item,
+			resource_pfn_freeitem fn_freeitem,
+			void *free_cb_param);
+
+int resource_getnumpict(struct lst_t *list);
+
+#endif /* _VXD_RESOURCE_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/rman_api.c b/drivers/media/platform/img/vxe-vxd/common/rman_api.c
--- a/drivers/media/platform/img/vxe-vxd/common/rman_api.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/rman_api.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,621 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This component is used to track decoder resources,
+ * and share them across other components.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#include <linux/slab.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "dq.h"
+#include "idgen_api.h"
+#include "rman_api.h"
+#include "img_errors.h"
+
+/*
+ * The following macros are used to build/decompose the composite resource Id
+ * made up from the bucket index + 1 and the allocated resource Id.
+ */
+#define RMAN_CRESID_BUCKET_INDEX_BITS	(8)
+#define RMAN_CRESID_RES_ID_BITS		(32 - RMAN_CRESID_BUCKET_INDEX_BITS)
+#define RMAN_CRESID_MAX_RES_ID		((1 << RMAN_CRESID_RES_ID_BITS) - 1)
+#define RMAN_CRESID_RES_ID_MASK		(RMAN_CRESID_MAX_RES_ID)
+#define RMAN_CRESID_BUCKET_SHIFT	(RMAN_CRESID_RES_ID_BITS)
+#define RMAN_CRESID_MAX_BUCKET_INDEX	\
+			((1 << RMAN_CRESID_BUCKET_INDEX_BITS) - 1)
+
+#define RMAN_MAX_ID		4096
+#define RMAN_ID_BLOCKSIZE	256
+
+/* global state variable */
+static unsigned char inited;
+static struct rman_bucket *bucket_array[RMAN_CRESID_MAX_BUCKET_INDEX] = {0};
+static struct rman_bucket *global_res_bucket;
+static struct rman_bucket *shared_res_bucket;
+static struct mutex *shared_res_mutex_handle;
+static struct mutex *global_mutex;
+
+/*
+ * This structure contains the bucket information.
+ */
+struct rman_bucket {
+	void		**link; /* to be part of single linked list */
+	struct dq_linkage_t	res_list;
+	unsigned int		bucket_idx;
+	void		*id_gen;
+	unsigned int	res_cnt;
+};
+
+/*
+ * This structure contains the resource details for a resource registered with
+ * the resource manager.
+ */
+struct rman_res {
+	struct dq_linkage_t	link; /* to be part of double linked list */
+	struct rman_bucket	*bucket;
+	unsigned int		type_id;
+	rman_fn_free		fn_free;
+	void			*param;
+	unsigned int		res_id;
+	struct mutex		*mutex_handle; /*resource mutex */
+	unsigned char		*res_name;
+	struct rman_res		*shared_res;
+	unsigned int		ref_cnt;
+};
+
+/*
+ * initialization
+ */
+int rman_initialise(void)
+{
+	unsigned int ret;
+
+	if (!inited) {
+		shared_res_mutex_handle = kzalloc(sizeof(*shared_res_mutex_handle), GFP_KERNEL);
+		if (!shared_res_mutex_handle)
+			return IMG_ERROR_OUT_OF_MEMORY;
+
+		mutex_init(shared_res_mutex_handle);
+
+		/* Set initialised flag */
+		inited = TRUE;
+
+		/* Create the global resource bucket */
+		ret = rman_create_bucket((void **)&global_res_bucket);
+		IMG_DBG_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		/* Create the shared resource bucket */
+		ret = rman_create_bucket((void **)&shared_res_bucket);
+		IMG_DBG_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		global_mutex = kzalloc(sizeof(*global_mutex), GFP_KERNEL);
+		if (!global_mutex)
+			return IMG_ERROR_OUT_OF_MEMORY;
+
+		mutex_init(global_mutex);
+	}
+	return IMG_SUCCESS;
+}
+
+/*
+ * deinitialization
+ */
+void rman_deinitialise(void)
+{
+	unsigned int	i;
+
+	if (inited) {
+		/* Destroy the golbal resource bucket */
+		rman_destroy_bucket(global_res_bucket);
+
+		/* Destroy the shared resource bucket */
+		rman_destroy_bucket(shared_res_bucket);
+
+		/* Make sure we destroy the mutex after destroying the bucket */
+		mutex_destroy(global_mutex);
+		kfree(global_mutex);
+		global_mutex = NULL;
+
+		/* Destroy mutex */
+		mutex_destroy(shared_res_mutex_handle);
+		kfree(shared_res_mutex_handle);
+		shared_res_mutex_handle = NULL;
+
+		/* Check all buckets destroyed */
+		for (i = 0; i < RMAN_CRESID_MAX_BUCKET_INDEX; i++)
+			IMG_DBG_ASSERT(!bucket_array[i]);
+
+		/* Reset initialised flag */
+		inited = FALSE;
+	}
+}
+
+int rman_create_bucket(void **res_bucket_handle)
+{
+	struct rman_bucket	*bucket;
+	unsigned int			i;
+	int			ret;
+
+	IMG_DBG_ASSERT(inited);
+
+	/* Allocate a bucket structure */
+	bucket = kzalloc(sizeof(*bucket), GFP_KERNEL);
+	IMG_DBG_ASSERT(bucket);
+	if (!bucket)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/* Initialise the resource list */
+	dq_init(&bucket->res_list);
+
+	/* Then start allocating resource ids at the first */
+	ret = idgen_createcontext(RMAN_MAX_ID, RMAN_ID_BLOCKSIZE, FALSE,
+				  &bucket->id_gen);
+	if (ret != IMG_SUCCESS) {
+		kfree(bucket);
+		IMG_DBG_ASSERT("failed to create IDGEN context" == NULL);
+		return ret;
+	}
+
+	/* Locate free bucket index within the table */
+	mutex_lock_nested(shared_res_mutex_handle, SUBCLASS_RMAN);
+	for (i = 0; i < RMAN_CRESID_MAX_BUCKET_INDEX; i++) {
+		if (!bucket_array[i])
+			break;
+	}
+	if (i >= RMAN_CRESID_MAX_BUCKET_INDEX) {
+		mutex_unlock(shared_res_mutex_handle);
+		idgen_destroycontext(bucket->id_gen);
+		kfree(bucket);
+		IMG_DBG_ASSERT("No free buckets left" == NULL);
+		return IMG_ERROR_GENERIC_FAILURE;
+	}
+
+	/* Allocate bucket index */
+	bucket->bucket_idx = i;
+	bucket_array[i] = bucket;
+
+	mutex_unlock(shared_res_mutex_handle);
+
+	/* Return the bucket handle */
+	*res_bucket_handle = bucket;
+
+	return IMG_SUCCESS;
+}
+
+void rman_destroy_bucket(void *res_bucket_handle)
+{
+	struct rman_bucket *bucket = (struct rman_bucket *)res_bucket_handle;
+
+	IMG_DBG_ASSERT(inited);
+
+	IMG_DBG_ASSERT(bucket);
+	if (!bucket)
+		return;
+
+	IMG_DBG_ASSERT(bucket->bucket_idx < RMAN_CRESID_MAX_BUCKET_INDEX);
+	IMG_DBG_ASSERT(bucket_array[bucket->bucket_idx]);
+
+	/* Free all resources from the bucket */
+	rman_free_resources(res_bucket_handle, RMAN_TYPE_P1);
+	rman_free_resources(res_bucket_handle, RMAN_TYPE_P2);
+	rman_free_resources(res_bucket_handle, RMAN_TYPE_P3);
+	rman_free_resources(res_bucket_handle, RMAN_ALL_TYPES);
+
+	/* free sticky resources last: other resources are dependent on them */
+	rman_free_resources(res_bucket_handle, RMAN_STICKY);
+	/* Use proper locking around global buckets.  */
+	mutex_lock_nested(shared_res_mutex_handle, SUBCLASS_RMAN);
+
+	/* Free from array of bucket pointers */
+	bucket_array[bucket->bucket_idx] = NULL;
+
+	mutex_unlock(shared_res_mutex_handle);
+
+	/* Free the bucket itself */
+	idgen_destroycontext(bucket->id_gen);
+	kfree(bucket);
+}
+
+void *rman_get_global_bucket(void)
+{
+	IMG_DBG_ASSERT(inited);
+	IMG_DBG_ASSERT(global_res_bucket);
+
+	/* Return the handle of the global resource bucket */
+	return global_res_bucket;
+}
+
+int rman_register_resource(void *res_bucket_handle, unsigned int type_id,
+			   rman_fn_free fnfree, void *param,
+			   void **res_handle, unsigned int *res_id)
+{
+	struct rman_bucket *bucket = (struct rman_bucket *)res_bucket_handle;
+	struct rman_res		*res;
+	int			 ret;
+
+	IMG_DBG_ASSERT(inited);
+	IMG_DBG_ASSERT(type_id != RMAN_ALL_TYPES);
+
+	IMG_DBG_ASSERT(res_bucket_handle);
+	if (!res_bucket_handle)
+		return IMG_ERROR_GENERIC_FAILURE;
+
+	/* Allocate a resource structure */
+	res = kzalloc(sizeof(*res), GFP_KERNEL);
+	IMG_DBG_ASSERT(res);
+	if (!res)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/* Fill in the resource structure */
+	res->bucket	= bucket;
+	res->type_id	= type_id;
+	res->fn_free	= fnfree;
+	res->param	= param;
+
+	/* Allocate resource Id */
+	mutex_lock_nested(global_mutex, SUBCLASS_RMAN);
+	ret = idgen_allocid(bucket->id_gen, res, &res->res_id);
+	mutex_unlock(global_mutex);
+	if (ret != IMG_SUCCESS) {
+		IMG_DBG_ASSERT("failed to allocate RMAN id" == NULL);
+		return ret;
+	}
+	IMG_DBG_ASSERT(res->res_id <= RMAN_CRESID_MAX_RES_ID);
+
+	/* add this resource to the bucket */
+	mutex_lock_nested(shared_res_mutex_handle, SUBCLASS_RMAN);
+	dq_addtail(&bucket->res_list, res);
+
+	/* Update count of resources */
+	bucket->res_cnt++;
+	mutex_unlock(shared_res_mutex_handle);
+
+	/* If resource handle required */
+	if (res_handle)
+		*res_handle = res;
+
+	/* If resource id required */
+	if (res_id)
+		*res_id = rman_get_resource_id(res);
+
+	return IMG_SUCCESS;
+}
+
+unsigned int rman_get_resource_id(void *res_handle)
+{
+	struct rman_res *res = res_handle;
+	unsigned int		ext_res_id;
+
+	IMG_DBG_ASSERT(res_handle);
+	if (!res_handle)
+		return 0;
+
+	IMG_DBG_ASSERT(res->res_id <= RMAN_CRESID_MAX_RES_ID);
+	IMG_DBG_ASSERT(res->bucket->bucket_idx < RMAN_CRESID_MAX_BUCKET_INDEX);
+	if (res->bucket->bucket_idx >= RMAN_CRESID_MAX_BUCKET_INDEX)
+		return 0;
+
+	ext_res_id = (((res->bucket->bucket_idx + 1) <<
+			 RMAN_CRESID_BUCKET_SHIFT) | res->res_id);
+
+	return ext_res_id;
+}
+
+static void *rman_getresource_int(void *res_bucket_handle, unsigned int res_id,
+				  unsigned int type_id, void **res_handle)
+{
+	struct rman_bucket *bucket = (struct rman_bucket *)res_bucket_handle;
+	struct rman_res	*res;
+	int		ret;
+
+	IMG_DBG_ASSERT(res_id <= RMAN_CRESID_MAX_RES_ID);
+
+	/* Loop over the resources in this bucket till we find the required id */
+	mutex_lock_nested(global_mutex, SUBCLASS_RMAN);
+	ret = idgen_gethandle(bucket->id_gen, res_id, (void **)&res);
+	mutex_unlock(global_mutex);
+	if (ret != IMG_SUCCESS) {
+		IMG_DBG_ASSERT("failed to get RMAN resource" == NULL);
+		return NULL;
+	}
+
+	/* If the resource handle is required */
+	if (res_handle)
+		*res_handle = res; /* Return it */
+
+	/* If the resource was not found */
+	IMG_DBG_ASSERT(res);
+	IMG_DBG_ASSERT((void *)res != &bucket->res_list);
+	if (!res || ((void *)res == &bucket->res_list))
+		return NULL;
+
+	/* Cross check the type */
+	IMG_DBG_ASSERT(type_id == res->type_id);
+
+	/* Return the resource. */
+	return res->param;
+}
+
+int rman_get_resource(unsigned int res_id, unsigned int type_id, void **param,
+		      void **res_handle)
+{
+	unsigned int	bucket_idx = (res_id >> RMAN_CRESID_BUCKET_SHIFT) - 1;
+	unsigned int	int_res_id = (res_id & RMAN_CRESID_RES_ID_MASK);
+	void	*local_param;
+
+	IMG_DBG_ASSERT(bucket_idx < RMAN_CRESID_MAX_BUCKET_INDEX);
+	if (bucket_idx >= RMAN_CRESID_MAX_BUCKET_INDEX)
+		return IMG_ERROR_INVALID_ID; /* Happens when bucket_idx == 0 */
+
+	IMG_DBG_ASSERT(bucket_array[bucket_idx]);
+	if (!bucket_array[bucket_idx])
+		return IMG_ERROR_INVALID_ID;
+
+	local_param = rman_getresource_int(bucket_array[bucket_idx],
+					   int_res_id, type_id,
+					   res_handle);
+
+	/* If we didn't find the resource */
+	if (!local_param)
+		return IMG_ERROR_INVALID_ID;
+
+	/* Return the resource */
+	if (param)
+		*param = local_param;
+
+	return IMG_SUCCESS;
+}
+
+int rman_get_named_resource(unsigned char *res_name, rman_fn_alloc fn_alloc,
+			    void *alloc_info, void *res_bucket_handle,
+			    unsigned int type_id, rman_fn_free fn_free,
+			    void **param, void **res_handle, unsigned int *res_id)
+{
+	struct rman_bucket *bucket = res_bucket_handle;
+	struct rman_res	*res;
+	unsigned int		ret;
+	void	*local_param;
+	unsigned char	found = FALSE;
+
+	IMG_DBG_ASSERT(inited);
+
+	IMG_DBG_ASSERT(res_bucket_handle);
+	if (!res_bucket_handle)
+		return IMG_ERROR_GENERIC_FAILURE;
+
+	/* Lock the shared resources */
+	mutex_lock_nested(shared_res_mutex_handle, SUBCLASS_RMAN);
+	res = (struct rman_res *)dq_first(&bucket->res_list);
+	while (res && ((void *)res != &bucket->res_list)) {
+		/* If resource already in the shared list */
+		if (res->res_name && (strcmp(res_name,
+					     res->res_name) == 0)) {
+			IMG_DBG_ASSERT(res->fn_free == fn_free);
+			found = TRUE;
+			break;
+		}
+
+		/* Move to next resource */
+		res = (struct rman_res *)dq_next(res);
+	}
+	mutex_unlock(shared_res_mutex_handle);
+
+	/* If the named resource was not found */
+	if (!found) {
+		/* Allocate the resource */
+		ret = fn_alloc(alloc_info, &local_param);
+		IMG_DBG_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		/* Register the named resource */
+		ret = rman_register_resource(res_bucket_handle, type_id,
+					     fn_free, local_param,
+					     (void **)&res, NULL);
+		IMG_DBG_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		mutex_lock_nested(shared_res_mutex_handle, SUBCLASS_RMAN);
+		res->res_name = res_name;
+		mutex_unlock(shared_res_mutex_handle);
+	}
+
+	/* Return the pvParam value */
+	*param = res->param;
+
+	/* If resource handle required */
+	if (res_handle)
+		*res_handle = res;
+
+	/* If resource id required */
+	if (res_id)
+		*res_id = rman_get_resource_id(res);
+
+	/* Exit */
+	return IMG_SUCCESS;
+}
+
+static void rman_free_resource_int(struct rman_res *res)
+{
+	struct rman_bucket *bucket = res->bucket;
+
+	/* Remove the resource from the active list */
+	mutex_lock_nested(shared_res_mutex_handle, SUBCLASS_RMAN);
+
+	/* Remove from list */
+	dq_remove(res);
+
+	/* Update count of resources */
+	bucket->res_cnt--;
+
+	mutex_unlock(shared_res_mutex_handle);
+
+	/* If mutex associated with the resource */
+	if (res->mutex_handle) {
+		/* Destroy mutex */
+		mutex_destroy(res->mutex_handle);
+		kfree(res->mutex_handle);
+		res->mutex_handle = NULL;
+	}
+
+	/* If this resource is not already shared */
+	if (res->shared_res) {
+		/* Lock the shared resources */
+		mutex_lock_nested(shared_res_mutex_handle, SUBCLASS_RMAN);
+
+		/* Update the reference count */
+		IMG_DBG_ASSERT(res->shared_res->ref_cnt != 0);
+		res->shared_res->ref_cnt--;
+
+		/* If this is the last free for the shared resource */
+		if (res->shared_res->ref_cnt == 0)
+			/* Free the shared resource */
+			rman_free_resource_int(res->shared_res);
+
+		/* UnLock the shared resources */
+		mutex_unlock(shared_res_mutex_handle);
+	} else {
+		/* If there is a free callback function. */
+		if (res->fn_free)
+			/* Call resource free callback */
+			res->fn_free(res->param);
+	}
+
+	/* If the resource has a name then free it */
+	kfree(res->res_name);
+
+	/* Free the resource ID. */
+	mutex_lock_nested(global_mutex, SUBCLASS_RMAN);
+	idgen_freeid(bucket->id_gen, res->res_id);
+	mutex_unlock(global_mutex);
+
+	/* Free a resource structure */
+	kfree(res);
+}
+
+void rman_free_resource(void *res_handle)
+{
+	struct rman_res *res;
+
+	IMG_DBG_ASSERT(inited);
+
+	IMG_DBG_ASSERT(res_handle);
+	if (!res_handle)
+		return;
+
+	/* Get access to the resource structure */
+	res = (struct rman_res *)res_handle;
+
+	/* Free resource */
+	rman_free_resource_int(res);
+}
+
+void rman_lock_resource(void *res_handle)
+{
+	struct rman_res	*res;
+
+	IMG_DBG_ASSERT(inited);
+
+	IMG_DBG_ASSERT(res_handle);
+	if (!res_handle)
+		return;
+
+	/* Get access to the resource structure */
+	res = (struct rman_res *)res_handle;
+
+	/* If this is a shared resource */
+	if (res->shared_res)
+		/* We need to lock/unlock the underlying shared resource */
+		res = res->shared_res;
+
+	/* If no mutex associated with this resource */
+	if (!res->mutex_handle) {
+		/* Create one */
+
+		res->mutex_handle = kzalloc(sizeof(*res->mutex_handle), GFP_KERNEL);
+		if (!res->mutex_handle)
+			return;
+
+		mutex_init(res->mutex_handle);
+	}
+
+	/* lock it */
+	mutex_lock(res->mutex_handle);
+}
+
+void rman_unlock_resource(void *res_handle)
+{
+	struct rman_res *res;
+
+	IMG_DBG_ASSERT(inited);
+
+	IMG_DBG_ASSERT(res_handle);
+	if (!res_handle)
+		return;
+
+	/* Get access to the resource structure */
+	res = (struct rman_res *)res_handle;
+
+	/* If this is a shared resource */
+	if (res->shared_res)
+		/* We need to lock/unlock the underlying shared resource */
+		res = res->shared_res;
+
+	IMG_DBG_ASSERT(res->mutex_handle);
+
+	/* Unlock mutex */
+	mutex_unlock(res->mutex_handle);
+}
+
+void rman_free_resources(void *res_bucket_handle, unsigned int type_id)
+{
+	struct rman_bucket *bucket = (struct rman_bucket *)res_bucket_handle;
+	struct rman_res		*res;
+
+	IMG_DBG_ASSERT(inited);
+
+	IMG_DBG_ASSERT(res_bucket_handle);
+	if (!res_bucket_handle)
+		return;
+
+	/* Scan the active list looking for the resources to be freed */
+	mutex_lock_nested(shared_res_mutex_handle, SUBCLASS_RMAN);
+	res = (struct rman_res *)dq_first(&bucket->res_list);
+	while ((res) && ((void *)res != &bucket->res_list)) {
+		/* If this is resource is to be removed */
+		if ((type_id == RMAN_ALL_TYPES  &&
+		     res->type_id != RMAN_STICKY) ||
+		     res->type_id == type_id) {
+			/* Yes, remove it, Free current resource */
+			mutex_unlock(shared_res_mutex_handle);
+			rman_free_resource_int(res);
+			mutex_lock_nested(shared_res_mutex_handle, SUBCLASS_RMAN);
+
+			/* Restart from the beginning of the list */
+			res = (struct rman_res *)dq_first(&bucket->res_list);
+		} else {
+			/* Move to next resource */
+			res = (struct rman_res *)lst_next(res);
+		}
+	}
+	mutex_unlock(shared_res_mutex_handle);
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/rman_api.h b/drivers/media/platform/img/vxe-vxd/common/rman_api.h
--- a/drivers/media/platform/img/vxe-vxd/common/rman_api.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/rman_api.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * This component is used to track decoder resources,
+ * and share them across other components.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef __RMAN_API_H__
+#define __RMAN_API_H__
+
+#include <linux/types.h>
+
+#include "img_errors.h"
+#include "lst.h"
+
+#define	RMAN_ALL_TYPES		(0xFFFFFFFF)
+#define	RMAN_TYPE_P1		(0xFFFFFFFE)
+#define	RMAN_TYPE_P2		(0xFFFFFFFE)
+#define	RMAN_TYPE_P3		(0xFFFFFFFE)
+#define RMAN_STICKY		(0xFFFFFFFD)
+
+int rman_initialise(void);
+
+void rman_deinitialise(void);
+
+int rman_create_bucket(void **res_handle);
+
+void rman_destroy_bucket(void *res_handle);
+
+void *rman_get_global_bucket(void);
+
+typedef void (*rman_fn_free) (void *param);
+
+int rman_register_resource(void *res_handle, unsigned int type_id, rman_fn_free fn_free,
+			   void *param, void **res_handle_ptr,
+			   unsigned int *res_id);
+
+typedef int (*rman_fn_alloc) (void *alloc_info, void **param);
+
+int rman_get_named_resource(unsigned char *res_name, rman_fn_alloc fn_alloc,
+			    void *alloc_info, void *res_bucket_handle,
+			    unsigned int type_id, rman_fn_free fn_free,
+			    void **param, void **res_handle, unsigned int *res_id);
+
+unsigned int rman_get_resource_id(void *res_handle);
+
+int rman_get_resource(unsigned int res_id, unsigned int type_id, void **param,
+		      void **res_handle);
+
+void rman_free_resource(void *res_handle);
+
+void rman_lock_resource(void *res_handle);
+
+void rman_unlock_resource(void *res_hanle);
+
+void rman_free_resources(void *res_bucket_handle, unsigned int type_id);
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/talmmu_api.c b/drivers/media/platform/img/vxe-vxd/common/talmmu_api.c
--- a/drivers/media/platform/img/vxe-vxd/common/talmmu_api.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/talmmu_api.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,753 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TAL MMU Extensions.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#include <linux/slab.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "img_errors.h"
+#include "lst.h"
+#include "talmmu_api.h"
+
+static int global_init;
+static struct lst_t gl_dmtmpl_lst = {0};
+static struct mutex *global_lock;
+
+static int talmmu_devmem_free(void *mem_hndl)
+{
+	struct talmmu_memory *mem = mem_hndl;
+	struct talmmu_devmem_heap *mem_heap;
+
+	if (!mem_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	mem_heap = mem->devmem_heap;
+
+	if (!mem->ext_dev_virtaddr)
+		addr_cx_free(&mem_heap->ctx, "", mem->dev_virtoffset);
+
+	mutex_lock_nested(global_lock, SUBCLASS_TALMMU);
+
+	lst_remove(&mem_heap->memory_list, mem);
+
+	mutex_unlock(global_lock);
+
+	kfree(mem);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * talmmu_devmem_heap_empty - talmmu_devmem_heap_empty
+ * @devmem_heap_hndl: device memory heap handle
+ *
+ * This function is used for emptying the device memory heap list
+ */
+int talmmu_devmem_heap_empty(void *devmem_heap_hndl)
+{
+	struct talmmu_devmem_heap *devmem_heap = devmem_heap_hndl;
+
+	if (!devmem_heap)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	while (!lst_empty(&devmem_heap->memory_list))
+		talmmu_devmem_free(lst_first(&devmem_heap->memory_list));
+
+	addr_cx_deinitialise(&devmem_heap->ctx);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_devmem_heap_destroy
+ *
+ * @Description	This function is used for freeing the device memory heap
+ *
+ * @Input
+ *
+ * @Output
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+static void talmmu_devmem_heap_destroy(void *devmem_heap_hndl)
+{
+	struct talmmu_devmem_heap *devmem_heap = devmem_heap_hndl;
+
+	talmmu_devmem_heap_empty(devmem_heap_hndl);
+	kfree(devmem_heap);
+}
+
+/*
+ * @Function	talmmu_init
+ *
+ * @Description	This function is used to initialize the TALMMU component.
+ *
+ * @Input	None.
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_init(void)
+{
+	if (!global_init) {
+		/* If no mutex associated with this resource */
+		if (!global_lock) {
+			/* Create one */
+			global_lock = kzalloc(sizeof(*global_lock), GFP_KERNEL);
+			if (!global_lock)
+				return IMG_ERROR_OUT_OF_MEMORY;
+
+			mutex_init(global_lock);
+		}
+
+		lst_init(&gl_dmtmpl_lst);
+		global_init = 1;
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_deinit
+ *
+ * @Description	This function is used to de-initialize the TALMMU component.
+ *
+ * @Input	None.
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_deinit(void)
+{
+	struct talmmu_dm_tmpl *t;
+
+	if (global_init) {
+		while (!lst_empty(&gl_dmtmpl_lst)) {
+			t = (struct talmmu_dm_tmpl *)lst_first(&gl_dmtmpl_lst);
+			talmmu_devmem_template_destroy((void *)t);
+		}
+		mutex_destroy(global_lock);
+		kfree(global_lock);
+		global_lock = NULL;
+		global_init = 0;
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_devmem_template_create
+ *
+ * @Description	This function is used to create a device memory template
+ *
+ * @Input	devmem_info:  A pointer to a talmmu_devmem_info structure.
+ *
+ * @Output	devmem_template_hndl: A pointer used to return the template
+ *		handle
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_template_create(struct talmmu_devmem_info *devmem_info,
+				  void **devmem_template_hndl)
+{
+	struct talmmu_dm_tmpl *devmem_template;
+	struct talmmu_dm_tmpl *tmp_devmem_template;
+
+	if (!devmem_info)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	devmem_template = kzalloc(sizeof(*devmem_template), GFP_KERNEL);
+	if (!devmem_template)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	devmem_template->devmem_info = *devmem_info;
+
+	lst_init(&devmem_template->devmem_ctx_list);
+
+	mutex_lock_nested(global_lock, SUBCLASS_TALMMU);
+
+	tmp_devmem_template = lst_first(&gl_dmtmpl_lst);
+	while (tmp_devmem_template)
+		tmp_devmem_template = lst_next(tmp_devmem_template);
+
+	devmem_template->page_num_shift = 12;
+	devmem_template->byte_in_pagemask = 0xFFF;
+	devmem_template->heap_alignment = 0x400000;
+	devmem_template->pagetable_entries_perpage =
+		(devmem_template->devmem_info.page_size / sizeof(unsigned int));
+	devmem_template->pagetable_num_shift = 10;
+	devmem_template->index_in_pagetable_mask = 0x3FF;
+	devmem_template->pagedir_num_shift = 22;
+
+	lst_add(&gl_dmtmpl_lst, devmem_template);
+
+	mutex_unlock(global_lock);
+
+	*devmem_template_hndl = devmem_template;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_devmem_template_destroy
+ *
+ * @Description This function is used to obtain the template from the list and
+ *		destroy
+ *
+ * @Input	devmem_tmplt_hndl: Device memory template handle
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_template_destroy(void *devmem_tmplt_hndl)
+{
+	struct talmmu_dm_tmpl *dm_tmpl = devmem_tmplt_hndl;
+	unsigned int i;
+
+	if (!devmem_tmplt_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	while (!lst_empty(&dm_tmpl->devmem_ctx_list))
+		talmmu_devmem_ctx_destroy(lst_first(&dm_tmpl->devmem_ctx_list));
+
+	for (i = 0; i < dm_tmpl->num_heaps; i++)
+		talmmu_devmem_heap_destroy(dm_tmpl->devmem_heap[i]);
+
+	mutex_lock_nested(global_lock, SUBCLASS_TALMMU);
+
+	lst_remove(&gl_dmtmpl_lst, dm_tmpl);
+
+	mutex_unlock(global_lock);
+
+	kfree(dm_tmpl);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_create_heap
+ *
+ * @Description	This function is used to create a device memory heap
+ *
+ * @Input
+ *
+ * @Output
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+static int talmmu_create_heap(void *devmem_tmplt_hndl,
+			      struct talmmu_heap_info *heap_info_arg,
+			      unsigned char isfull,
+			      struct talmmu_devmem_heap **devmem_heap_arg)
+{
+	struct talmmu_dm_tmpl *devmem_template = devmem_tmplt_hndl;
+	struct talmmu_devmem_heap *devmem_heap;
+
+	/* Allocating memory for device memory heap */
+	devmem_heap = kzalloc(sizeof(*devmem_heap), GFP_KERNEL);
+	if (!devmem_heap)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/*
+	 * Update the device memory heap structure members
+	 * Update the device memory template
+	 */
+	devmem_heap->devmem_template = devmem_template;
+	/* Update the device memory heap information */
+	devmem_heap->heap_info = *heap_info_arg;
+
+	/* Initialize the device memory heap list */
+	lst_init(&devmem_heap->memory_list);
+
+	/* If full structure required */
+	if (isfull) {
+		addr_cx_initialise(&devmem_heap->ctx);
+		devmem_heap->regions.base_addr = 0;
+		devmem_heap->regions.size = devmem_heap->heap_info.size;
+		addr_cx_define_mem_region(&devmem_heap->ctx,
+					  &devmem_heap->regions);
+	}
+
+	*devmem_heap_arg = devmem_heap;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_devmem_heap_add
+ *
+ * @Description	This function is for creating and adding the heap to the
+ *		device memory template
+ *
+ * @Input	devmem_tmplt_hndl: device memory template handle
+ *
+ * @Input	heap_info_arg: pointer to the heap info structure
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_heap_add(void *devmem_tmplt_hndl,
+			   struct talmmu_heap_info *heap_info_arg)
+{
+	struct talmmu_dm_tmpl *devmem_template = devmem_tmplt_hndl;
+	struct talmmu_devmem_heap *devmem_heap;
+	unsigned int res;
+
+	if (!devmem_tmplt_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (!heap_info_arg)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	res = talmmu_create_heap(devmem_tmplt_hndl,
+				 heap_info_arg,
+				 1,
+				 &devmem_heap);
+	if (res != IMG_SUCCESS)
+		return res;
+
+	devmem_template->devmem_heap[devmem_template->num_heaps] = devmem_heap;
+	devmem_template->num_heaps++;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_devmem_ctx_create
+ *
+ * @Description	This function is used to create a device memory context
+ *
+ * @Input	devmem_tmplt_hndl: pointer to the device memory template handle
+ *
+ * @Input	mmu_ctx_id: MMU context ID used with the TAL
+ *
+ * @Output	devmem_ctx_hndl: pointer to the device memory context handle
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_ctx_create(void *devmem_tmplt_hndl,
+			     unsigned int mmu_ctx_id,
+			     void **devmem_ctx_hndl)
+{
+	struct talmmu_dm_tmpl *dm_tmpl = devmem_tmplt_hndl;
+	struct talmmu_devmem_ctx *dm_ctx;
+	struct talmmu_devmem_heap *dm_heap;
+	int i;
+	unsigned int res = IMG_SUCCESS;
+
+	if (!devmem_tmplt_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Allocate memory for device memory context */
+	dm_ctx = kzalloc((sizeof(struct talmmu_devmem_ctx)), GFP_KERNEL);
+	if (!dm_ctx)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/*
+	 * Update the device memory context structure members
+	 * Update the device memory template
+	 */
+	dm_ctx->devmem_template = dm_tmpl;
+	/* Update MMU context ID */
+	dm_ctx->mmu_ctx_id = mmu_ctx_id;
+
+	/* Check for PTD Alignment */
+	if (dm_tmpl->devmem_info.ptd_alignment == 0)
+		/*
+		 * Make sure alignment is a multiple of page size.
+		 * Set up PTD alignment to Page Size
+		 */
+		dm_tmpl->devmem_info.ptd_alignment =
+			dm_tmpl->devmem_info.page_size;
+
+	/* Reference or create heaps for this context */
+	for (i = 0; i < dm_tmpl->num_heaps; i++) {
+		dm_heap = dm_tmpl->devmem_heap[i];
+		if (!dm_heap)
+			goto error_heap_create;
+
+		switch (dm_heap->heap_info.heap_type) {
+		case TALMMU_HEAP_PERCONTEXT:
+			res = talmmu_create_heap(dm_tmpl,
+						 &dm_heap->heap_info,
+						 1,
+						 &dm_ctx->devmem_heap[i]);
+			if (res != IMG_SUCCESS)
+				goto error_heap_create;
+			break;
+
+		default:
+			break;
+		}
+
+		dm_ctx->num_heaps++;
+	}
+
+	mutex_lock_nested(global_lock, SUBCLASS_TALMMU);
+
+	/* Add the device memory context to the list */
+	lst_add(&dm_tmpl->devmem_ctx_list, dm_ctx);
+
+	dm_tmpl->num_ctxs++;
+
+	mutex_unlock(global_lock);
+
+	*devmem_ctx_hndl = dm_ctx;
+
+	return IMG_SUCCESS;
+
+error_heap_create:
+	/* Destroy the device memory heaps which were already created */
+	for (i--; i >= 0; i--) {
+		dm_heap = dm_ctx->devmem_heap[i];
+		if (dm_heap->heap_info.heap_type == TALMMU_HEAP_PERCONTEXT)
+			talmmu_devmem_heap_destroy(dm_heap);
+
+		dm_ctx->num_heaps--;
+	}
+	kfree(dm_ctx);
+	return res;
+}
+
+/*
+ * @Function	talmmu_devmem_ctx_destroy
+ *
+ * @Description	This function is used to get the device memory context from
+ *		the list and destroy
+ *
+ * @Input	devmem_ctx_hndl: device memory context handle
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_ctx_destroy(void *devmem_ctx_hndl)
+{
+	struct talmmu_devmem_ctx *devmem_ctx = devmem_ctx_hndl;
+	struct talmmu_dm_tmpl *devmem_template;
+	struct talmmu_devmem_heap *devmem_heap;
+	unsigned int i;
+
+	if (!devmem_ctx_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	devmem_template = devmem_ctx->devmem_template;
+
+	for (i = 0; i < devmem_ctx->num_heaps; i++) {
+		devmem_heap = devmem_ctx->devmem_heap[i];
+		if (!devmem_heap)
+			return IMG_ERROR_INVALID_PARAMETERS;
+
+		talmmu_devmem_heap_destroy(devmem_heap);
+	}
+
+	devmem_ctx->pagedir = NULL;
+
+	mutex_lock_nested(global_lock, SUBCLASS_TALMMU);
+
+	lst_remove(&devmem_template->devmem_ctx_list, devmem_ctx);
+
+	devmem_ctx->devmem_template->num_ctxs--;
+
+	mutex_unlock(global_lock);
+
+	kfree(devmem_ctx);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_get_heap_handle
+ *
+ * @Description	This function is used to get the device memory heap handle
+ *
+ * @Input	hid: heap id
+ *
+ * @Input	devmem_ctx_hndl: device memory context handle
+ *
+ * @Output	devmem_heap_hndl: pointer to the device memory heap handle
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_get_heap_handle(unsigned int hid,
+			   void *devmem_ctx_hndl,
+			   void **devmem_heap_hndl)
+{
+	struct talmmu_devmem_ctx *devmem_ctx = devmem_ctx_hndl;
+	unsigned int i;
+
+	if (!devmem_ctx_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	for (i = 0; i < devmem_ctx->num_heaps; i++) {
+		/*
+		 * Checking for requested heap id match and return the device
+		 * memory heap handle
+		 */
+		if (devmem_ctx->devmem_heap[i]->heap_info.heap_id == hid) {
+			*devmem_heap_hndl = devmem_ctx->devmem_heap[i];
+			return IMG_SUCCESS;
+		}
+	}
+
+	return IMG_ERROR_GENERIC_FAILURE;
+}
+
+/*
+ * @Function	talmmu_devmem_heap_options
+ *
+ * @Description	This function is used to set additional heap options
+ *
+ * @Input	devmem_heap_hndl: Handle for heap
+ *
+ * @Input	heap_opt_id: Heap options ID
+ *
+ * @Input	heap_options: Heap options
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+void talmmu_devmem_heap_options(void *devmem_heap_hndl,
+				enum talmmu_heap_option_id heap_opt_id,
+				union talmmu_heap_options heap_options)
+{
+	struct talmmu_devmem_heap *dm_heap = devmem_heap_hndl;
+
+	switch (heap_opt_id) {
+	case TALMMU_HEAP_OPT_ADD_GUARD_BAND:
+		dm_heap->guardband = heap_options.guardband_opt.guardband;
+		break;
+	default:
+		break;
+	}
+}
+
+/*
+ * @Function	talmmu_devmem_malloc_nonmap
+ *
+ * @Description
+ *
+ * @Input
+ *
+ * @Output
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+static int talmmu_devmem_alloc_nonmap(void *devmem_ctx_hndl,
+				      void *devmem_heap_hndl,
+				      unsigned int size,
+				      unsigned int align,
+				      unsigned int dev_virt_ofset,
+				      unsigned char ext_dev_vaddr,
+				      void **mem_hndl)
+{
+	struct talmmu_devmem_ctx *dm_ctx = devmem_ctx_hndl;
+	struct talmmu_dm_tmpl *dm_tmpl;
+	struct talmmu_devmem_heap *dm_heap = devmem_heap_hndl;
+	struct talmmu_memory *mem;
+	unsigned long long ui64_dev_offset = 0;
+	int res = IMG_SUCCESS;
+
+	if (!dm_ctx)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (!devmem_heap_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	dm_tmpl = dm_ctx->devmem_template;
+
+	/* Allocate memory for memory structure */
+	mem = kzalloc((sizeof(struct talmmu_memory)), GFP_KERNEL);
+	if (!mem)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	mem->devmem_heap = dm_heap;
+	mem->devmem_ctx = dm_ctx;
+	mem->ext_dev_virtaddr = ext_dev_vaddr;
+
+	/* We always for to be at least page aligned */
+	if (align >= dm_tmpl->devmem_info.page_size)
+		/*
+		 * alignment is larger than page size - make sure alignment is
+		 * a multiple of page size
+		 */
+		mem->alignment = align;
+	else
+		/*
+		 * alignment is smaller than page size - make sure page size is
+		 * a multiple of alignment. Now round up alignment to one page
+		 */
+		mem->alignment = dm_tmpl->devmem_info.page_size;
+
+	/* Round size up to next multiple of physical pages */
+	if ((size % dm_tmpl->devmem_info.page_size) != 0)
+		mem->size = ((size / dm_tmpl->devmem_info.page_size)
+			+ 1) * dm_tmpl->devmem_info.page_size;
+	else
+		mem->size = size;
+
+	/* If the device virtual address was externally defined */
+	if (mem->ext_dev_virtaddr) {
+		res = IMG_ERROR_INVALID_PARAMETERS;
+		goto free_mem;
+	}
+
+	res = addr_cx_malloc_align_res(&dm_heap->ctx, "",
+				       (mem->size + dm_heap->guardband),
+				       mem->alignment,
+				       &ui64_dev_offset);
+
+	mem->dev_virtoffset = (unsigned int)ui64_dev_offset;
+	if (res != IMG_SUCCESS)
+		/*
+		 * If heap space is unavaliable return NULL, the caller must
+		 * handle this condition
+		 */
+		goto free_virt;
+
+	mutex_lock_nested(global_lock, SUBCLASS_TALMMU);
+
+	/*
+	 * Add memory allocation to the list for this heap...
+	 * If the heap is empty...
+	 */
+	if (lst_empty(&dm_heap->memory_list))
+		/*
+		 * Save flag to indicate whether the device virtual address
+		 * is allocated internally or externally...
+		 */
+		dm_heap->ext_dev_virtaddr = mem->ext_dev_virtaddr;
+
+	/*
+	 * Once we have started allocating in one way ensure that we continue
+	 * to do this...
+	 */
+	lst_add(&dm_heap->memory_list, mem);
+
+	mutex_unlock(global_lock);
+
+	*mem_hndl = mem;
+
+	return IMG_SUCCESS;
+
+free_virt:
+	addr_cx_free(&dm_heap->ctx, "", mem->dev_virtoffset);
+free_mem:
+	kfree(mem);
+
+	return res;
+}
+
+/*
+ * @Function	talmmu_devmem_addr_alloc
+ *
+ * @Description
+ *
+ * @Input
+ *
+ * @Output
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_addr_alloc(void *devmem_ctx_hndl,
+			     void *devmem_heap_hndl,
+			     unsigned int size,
+			     unsigned int align,
+			     void **mem_hndl)
+{
+	unsigned int res;
+	void *mem;
+
+	res = talmmu_devmem_alloc_nonmap(devmem_ctx_hndl,
+					 devmem_heap_hndl,
+					 size,
+					 align,
+					 0,
+					 0,
+					 &mem);
+	if (res != IMG_SUCCESS)
+		return res;
+
+	*mem_hndl = mem;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	talmmu_devmem_addr_free
+ *
+ * @Description	This function is used to free device memory allocated using
+ *		talmmu_devmem_addr_alloc().
+ *
+ * @Input	mem_hndl : Handle for the memory object
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_devmem_addr_free(void *mem_hndl)
+{
+	unsigned int res;
+
+	if (!mem_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* free device memory allocated by calling talmmu_devmem_free() */
+	res = talmmu_devmem_free(mem_hndl);
+
+	return res;
+}
+
+/*
+ * @Function	talmmu_get_dev_virt_addr
+ *
+ * @Description	This function is use to obtain the device (virtual) memory
+ *		address which may be required for as a device virtual address
+ *		in some of the TAL image functions
+ *
+ * @Input	mem_hndl : Handle for the memory object
+ *
+ * @Output	dev_virt: A piointer used to return the device virtual address
+ *
+ * @Return	IMG_SUCCESS or an error code
+ *
+ */
+int talmmu_get_dev_virt_addr(void *mem_hndl,
+			     unsigned int *dev_virt)
+{
+	struct talmmu_memory *mem = mem_hndl;
+	struct talmmu_devmem_heap *devmem_heap;
+
+	if (!mem_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	devmem_heap = mem->devmem_heap;
+
+	/*
+	 * Device virtual address is addition of the specific device virtual
+	 * offset and the base device virtual address from the heap information
+	 */
+	*dev_virt = (devmem_heap->heap_info.basedev_virtaddr +
+		mem->dev_virtoffset);
+
+	return IMG_SUCCESS;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/talmmu_api.h b/drivers/media/platform/img/vxe-vxd/common/talmmu_api.h
--- a/drivers/media/platform/img/vxe-vxd/common/talmmu_api.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/talmmu_api.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,246 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * TAL MMU Extensions.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#include "addr_alloc.h"
+#include "ra.h"
+#include "lst.h"
+
+#ifndef __TALMMU_API_H__
+#define __TALMMU_API_H__
+
+#define	TALMMU_MAX_DEVICE_HEAPS	(32)
+#define	TALMMU_MAX_TEMPLATES	(32)
+
+/* MMU type */
+enum talmmu_mmu_type {
+	/* 4kb pages and 32-bit address range */
+	TALMMU_MMUTYPE_4K_PAGES_32BIT_ADDR = 0x1,
+	/* variable size pages and 32-bit address */
+	TALMMU_MMUTYPE_VAR_PAGES_32BIT_ADDR,
+	/* 4kb pages and 36-bit address range */
+	TALMMU_MMUTYPE_4K_PAGES_36BIT_ADDR,
+	/* 4kb pages and 40-bit address range */
+	TALMMU_MMUTYPE_4K_PAGES_40BIT_ADDR,
+	/* variable size pages and 40-bit address range */
+	TALMMU_MMUTYPE_VP_40BIT,
+	TALMMU_MMUTYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Device flags */
+enum talmmu_dev_flags {
+	TALMMU_DEVFLAGS_NONE = 0x0,
+	TALMMU_DEVFLAGS_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Heap type */
+enum talmmu_heap_type {
+	TALMMU_HEAP_SHARED_EXPORTED,
+	TALMMU_HEAP_PERCONTEXT,
+	TALMMU_HEAP_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Heap flags */
+enum talmmu_eheapflags {
+	TALMMU_HEAPFLAGS_NONE = 0x0,
+	TALMMU_HEAPFLAGS_SET_CACHE_CONSISTENCY = 0x00000001,
+	TALMMU_HEAPFLAGS_128BYTE_INTERLEAVE = 0x00000002,
+	TALMMU_HEAPFLAGS_256BYTE_INTERLEAVE = 0x00000004,
+	TALMMU_HEAPFLAGS_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Contains the device memory information */
+struct talmmu_devmem_info {
+	/* device id */
+	unsigned int device_id;
+	/* mmu type */
+	enum talmmu_mmu_type mmu_type;
+	/* Device flags - bit flags that can be combined */
+	enum talmmu_dev_flags dev_flags;
+	/* Name of the memory space for page directory allocations */
+	unsigned char *pagedir_memspace_name;
+	/* Name of the memory space for page table allocations */
+	unsigned char *pagetable_memspace_name;
+	/* Page size in bytes */
+	unsigned int page_size;
+	/* PTD alignment, must be multiple of Page size */
+	unsigned int ptd_alignment;
+};
+
+struct talmmu_heap_info {
+	/* heap id */
+	unsigned int heap_id;
+	/* heap type */
+	enum talmmu_heap_type heap_type;
+	/* heap flags - bit flags that can be combined */
+	enum talmmu_eheapflags heap_flags;
+	/* Name of the memory space for memory allocations */
+	unsigned char *memspace_name;
+	/* Base device virtual address */
+	unsigned int basedev_virtaddr;
+	/* size in bytes */
+	unsigned int size;
+};
+
+/* Device memory template information */
+struct talmmu_dm_tmpl {
+	/* list */
+	struct lst_t list;
+	/* Copy of device memory info structure */
+	struct talmmu_devmem_info devmem_info;
+	/* Memory space ID for PTD allocations */
+	void *ptd_memspace_hndl;
+	/* Memory space ID for Page Table allocations */
+	void *ptentry_memspace_hndl;
+	/* number of heaps */
+	unsigned int num_heaps;
+	/* Array of heap pointers */
+	struct talmmu_devmem_heap *devmem_heap[TALMMU_MAX_DEVICE_HEAPS];
+	/* Number of active contexts */
+	unsigned int num_ctxs;
+	/* List of device memory context created from this template */
+	struct lst_t devmem_ctx_list;
+	/* Number of bits to shift right to obtain page number */
+	unsigned int page_num_shift;
+	/* Mask to extract byte-within-page */
+	unsigned int byte_in_pagemask;
+	/* Heap alignment */
+	unsigned int heap_alignment;
+	/* Page table entries/page */
+	unsigned int pagetable_entries_perpage;
+	/* Number of bits to shift right to obtain page table number */
+	unsigned int pagetable_num_shift;
+	/* Mask to extract index-within-page-table */
+	unsigned int index_in_pagetable_mask;
+	/* Number of bits to shift right to obtain page dir number */
+	unsigned int pagedir_num_shift;
+};
+
+/* Device memory heap information */
+struct talmmu_devmem_heap {
+	/* list item */
+	struct lst_t list;
+	/* Copy of the heap info structure */
+	struct talmmu_heap_info heap_info;
+	/* Pointer to the device memory template */
+	struct talmmu_dm_tmpl *devmem_template;
+	/* true if device virtual address offset allocated externally by user */
+	unsigned int ext_dev_virtaddr;
+	/* list of memory allocations */
+	struct lst_t memory_list;
+	/* Memory space ID for memory allocations */
+	void *memspace_hndl;
+	/* Address context structure */
+	struct addr_context ctx;
+	/* Regions structure */
+	struct addr_region regions;
+	/* size of heap guard band */
+	unsigned int guardband;
+};
+
+struct talmmu_devmem_ctx {
+	/* list item */
+	struct lst_t list;
+	/* Pointer to device template */
+	struct talmmu_dm_tmpl *devmem_template;
+	/* No. of heaps */
+	unsigned int num_heaps;
+	/* Array of heap pointers */
+	struct talmmu_devmem_heap *devmem_heap[TALMMU_MAX_DEVICE_HEAPS];
+	/* The MMU context id */
+	unsigned int mmu_ctx_id;
+	/* Pointer to the memory that represents Page directory */
+	unsigned int *pagedir;
+};
+
+struct talmmu_memory {
+	/* list item */
+	struct lst_t list;
+	/* Heap from which memory was allocated */
+	struct talmmu_devmem_heap *devmem_heap;
+	/* Context through which memory was allocated */
+	struct talmmu_devmem_ctx *devmem_ctx;
+	/* size */
+	unsigned int size;
+	/* alignment */
+	unsigned int alignment;
+	/* device virtual offset of allocation */
+	unsigned int dev_virtoffset;
+	/* true if device virtual address offset allocated externally by user */
+	unsigned int ext_dev_virtaddr;
+};
+
+/* This type defines the event types for the TALMMU callbacks */
+enum talmmu_event {
+	/* Function to flush the cache. */
+	TALMMU_EVENT_FLUSH_CACHE,
+	/*! Function to write the page directory address to the device */
+	TALMMU_EVENT_WRITE_PAGE_DIRECTORY_REF,
+	/* Placeholder*/
+	TALMMU_NO_OF_EVENTS
+};
+
+enum talmmu_heap_option_id {
+	/* Add guard band to all mallocs */
+	TALMMU_HEAP_OPT_ADD_GUARD_BAND,
+	TALMMU_HEAP_OPT_SET_MEM_ATTRIB,
+	TALMMU_HEAP_OPT_SET_MEM_POOL,
+
+	/* Placeholder */
+	TALMMU_NO_OF_OPTIONS,
+	TALMMU_NO_OF_FORCE32BITS = 0x7FFFFFFFU
+};
+
+struct talmmu_guardband_options {
+	unsigned int guardband;
+};
+
+union talmmu_heap_options {
+	/* Guardband parameters */
+	struct talmmu_guardband_options guardband_opt;
+};
+
+int talmmu_init(void);
+int talmmu_deinit(void);
+int talmmu_devmem_template_create(struct talmmu_devmem_info *devmem_info,
+				  void **devmem_template_hndl);
+int talmmu_devmem_heap_add(void *devmem_tmplt_hndl,
+			   struct talmmu_heap_info *heap_info_arg);
+int talmmu_devmem_template_destroy(void *devmem_tmplt_hndl);
+int talmmu_devmem_ctx_create(void *devmem_tmplt_hndl,
+			     unsigned int mmu_ctx_id,
+			     void **devmem_ctx_hndl);
+int talmmu_devmem_ctx_destroy(void *devmem_ctx_hndl);
+int talmmu_get_heap_handle(unsigned int hid,
+			   void *devmem_ctx_hndl,
+			   void **devmem_heap_hndl);
+/**
+ * talmmu_devmem_heap_empty - talmmu_devmem_heap_empty
+ * @devmem_heap_hndl: device memory heap handle
+ *
+ * This function is used for emptying the device memory heap list
+ */
+
+int talmmu_devmem_heap_empty(void *devmem_heap_hndl);
+void talmmu_devmem_heap_options(void *devmem_heap_hndl,
+				enum talmmu_heap_option_id heap_opt_id,
+				union talmmu_heap_options heap_options);
+int talmmu_devmem_addr_alloc(void *devmem_ctx_hndl,
+			     void *devmem_heap_hndl,
+			     unsigned int size,
+			     unsigned int align,
+			     void **mem_hndl);
+int talmmu_devmem_addr_free(void *mem_hndl);
+int talmmu_get_dev_virt_addr(void *mem_hndl,
+			     unsigned int *dev_virt);
+
+#endif /* __TALMMU_API_H__ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/vid_buf.h b/drivers/media/platform/img/vxe-vxd/common/vid_buf.h
--- a/drivers/media/platform/img/vxe-vxd/common/vid_buf.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/vid_buf.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Low-level VXD interface component
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _VID_BUF_H
+#define _VID_BUF_H
+
+/*
+ * struct vidio_ddbufinfo - contains information about virtual address
+ * @buf_size: the size of the buffer (in bytes).
+ * @cpu_virt: the cpu virtual address  (mapped into the local cpu mmu)
+ * @dev_virt: device virtual address (pages mapped into IMG H/W mmu)
+ * @hndl_memory: handle to device mmu mapping
+ * @buff_id: buffer id used in communication with interface
+ * @is_internal: true, if the buffer is allocated internally
+ * @ref_count: reference count (number of users)
+ * @kmstr_id: stream id
+ * @core_id: core id
+ */
+struct vidio_ddbufinfo {
+	unsigned int buf_size;
+	void *cpu_virt;
+	unsigned int dev_virt;
+	void *hndl_memory;
+	unsigned int buff_id;
+	unsigned int is_internal;
+	unsigned int ref_count;
+	unsigned int kmstr_id;
+	unsigned int core_id;
+};
+
+#endif /* _VID_BUF_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/work_queue.c b/drivers/media/platform/img/vxe-vxd/common/work_queue.c
--- a/drivers/media/platform/img/vxe-vxd/common/work_queue.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/work_queue.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Work Queue Handling for Linux
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include <linux/slab.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+
+#include "work_queue.h"
+
+/* Defining and initilizing mutex
+ */
+DEFINE_MUTEX(mutex);
+
+#define false 0
+#define true 1
+
+struct node {
+	void **key;
+	struct node *next;
+};
+
+struct node *work_head;
+struct node *delayed_work_head;
+
+void init_work(void **work_args, void *work_fn, uint8_t hwa_id)
+{
+	struct work_struct **work = (struct work_struct **)work_args;
+	//create a link
+	struct node *link = kmalloc(sizeof(*link), GFP_KERNEL);
+
+	*work = kzalloc(sizeof(*work), GFP_KERNEL);
+	if (!(*work)) {
+		pr_err("Memory allocation failed for work_queue\n");
+		return;
+	}
+	INIT_WORK(*work, work_fn);
+
+	link->key = (void **)work;
+	mutex_lock(&mutex);
+	//point it to old first node
+	link->next = work_head;
+
+	//point first to new first node
+	work_head = link;
+	mutex_unlock(&mutex);
+}
+
+void init_delayed_work(void **work_args, void *work_fn, uint8_t hwa_id)
+{
+	struct delayed_work **work = (struct delayed_work **)work_args;
+	//create a link
+	struct node *link = kmalloc(sizeof(*link), GFP_KERNEL);
+
+	*work = kzalloc(sizeof(*work), GFP_KERNEL);
+	if (!(*work)) {
+		pr_err("Memory allocation failed for delayed_work_queue\n");
+		return;
+	}
+	INIT_DELAYED_WORK(*work, work_fn);
+
+	link->key = (void **)work;
+	mutex_lock(&mutex);
+	//point it to old first node
+	link->next = delayed_work_head;
+
+	//point first to new first node
+	delayed_work_head = link;
+	mutex_unlock(&mutex);
+}
+
+/**
+ * get_work_buff - get_work_buff
+ * @key: key value
+ * @flag: flag
+ */
+
+void *get_work_buff(void *key, signed char flag)
+{
+	struct node *data = NULL;
+	void *work_new = NULL;
+	struct node *temp = NULL;
+	struct node *previous = NULL;
+	struct work_struct **work = NULL;
+
+	//start from the first link
+	mutex_lock(&mutex);
+	temp = work_head;
+
+	//if list is empty
+	if (!work_head) {
+		mutex_unlock(&mutex);
+		return NULL;
+	}
+
+	work = ((struct work_struct **)(temp->key));
+	//navigate through list
+	while (*work != key) {
+		//if it is last node
+		if (!temp->next) {
+			mutex_unlock(&mutex);
+			return NULL;
+		}
+			//store reference to current link
+			previous = temp;
+			//move to next link
+			temp = temp->next;
+			work = ((struct work_struct **)(temp->key));
+	}
+
+	if (flag) {
+		//found a match, update the link
+		if (temp == work_head) {
+			//change first to point to next link
+			work_head = work_head->next;
+		} else {
+			//bypass the current link
+			previous->next = temp->next;
+		}
+	}
+
+	mutex_unlock(&mutex);
+	//return temp;
+	data = temp;
+	if (data) {
+		work_new = data->key;
+		if (flag)
+			kfree(data);
+	}
+	return work_new;
+}
+
+void *get_delayed_work_buff(void *key, signed char flag)
+{
+	struct node *data = NULL;
+	void *dwork_new = NULL;
+	struct node *temp = NULL;
+	struct node *previous = NULL;
+	struct delayed_work **dwork = NULL;
+
+	if (flag) {
+		/* This Condition is true when kernel module is removed */
+		return delayed_work_head;
+	}
+	//start from the first link
+	mutex_lock(&mutex);
+	temp = delayed_work_head;
+
+	//if list is empty
+	if (!delayed_work_head) {
+		mutex_unlock(&mutex);
+		return NULL;
+	}
+
+	dwork = ((struct delayed_work **)(temp->key));
+	//navigate through list
+	while (&(*dwork)->work != key) {
+		//if it is last node
+		if (!temp->next) {
+			mutex_unlock(&mutex);
+			return NULL;
+		}
+			//store reference to current link
+			previous = temp;
+			//move to next link
+			temp = temp->next;
+			dwork = ((struct delayed_work **)(temp->key));
+	}
+
+	mutex_unlock(&mutex);
+	data = temp;
+	if (data) {
+		dwork_new = data->key;
+		if (flag)
+			kfree(data);
+	}
+	return dwork_new;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/common/work_queue.h b/drivers/media/platform/img/vxe-vxd/common/work_queue.h
--- a/drivers/media/platform/img/vxe-vxd/common/work_queue.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/common/work_queue.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Work Queue Related Definitions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#ifndef WORKQUEUE_H_
+#define WORKQUEUE_H_
+
+#include <linux/types.h>
+
+enum {
+	HWA_DECODER   = 0,
+	HWA_ENCODER    = 1,
+	HWA_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * init_work - This function provides the necessary initialization
+ * and saving given pointer(work_args) in linked list.
+ * @work_args: structure for the initialization
+ * @work_fn: work function pointer
+ *
+ * This function provides the necessary initialization
+ * and setting of the handler function (passed by the user).
+ */
+void init_work(void **work_args, void *work_fn, uint8_t hwa_id);
+
+/*
+ * init_delayed_work - This function provides the necessary initialization.
+ * and saving given pointer(work_args) in linked list.
+ * @work_args: structure for the initialization
+ * @work_fn: work function pointer
+ *
+ * This function provides the necessary initialization
+ * and setting of the handler function (passed by the user).
+ */
+void init_delayed_work(void **work_args, void *work_fn, uint8_t hwa_id);
+
+/*
+ * get_delayed_work_buff - This function return base address of given pointer
+ * @key: The given work struct pointer
+ * @flag: If TRUE, delete the node from the linked list.
+ *
+ * Return: Base address of the given input buffer.
+ */
+void *get_delayed_work_buff(void *key, signed char flag);
+
+/**
+ * get_work_buff - This function return base address of given pointer
+ * @key: The given work struct pointer
+ * @flag: If TRUE, delete the node from the linked list.
+ *
+ * Return: Base address of the given input buffer.
+ */
+void *get_work_buff(void *key, signed char flag);
+
+#endif /* WORKQUEUE_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/bspp.c b/drivers/media/platform/img/vxe-vxd/decoder/bspp.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/bspp.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/bspp.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,2488 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VXD Bitstream Buffer Pre-Parser
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstreming
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/slab.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "bspp.h"
+#include "h264_secure_parser.h"
+#include "hevc_secure_parser.h"
+#ifdef HAS_JPEG
+#include "jpeg_secure_parser.h"
+#endif
+#include "lst.h"
+#include "swsr.h"
+#include "vdecdd_defs.h"
+#include "img_errors.h"
+
+#define BSPP_ERR_MSG_LENGTH     1024
+
+/*
+ * This type defines the exception flag to catch the error if more catch block
+ * is required to catch different kind of error then more enum can be added
+ * @breif BSPP exception handler to catch the errors
+ */
+enum bspp_exception_handler {
+	/* BSPP parse exception handler */
+	BSPP_EXCEPTION_HANDLER_NONE = 0x00,
+	/* Jump at exception (external use) */
+	BSPP_EXCEPTION_HANDLER_JUMP,
+	BSPP_EXCEPTION_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This structure contains bitstream buffer information.
+ * @brief  BSPP Bitstream Buffer Information
+ */
+struct bspp_bitstream_buffer {
+	void **lst_link;
+	struct bspp_ddbuf_info ddbuf_info;
+	unsigned int data_size;
+	unsigned int bufmap_id;
+	enum vdec_bstr_element_type bstr_element_type;
+	unsigned long long bytes_read;
+	void *pict_tag_param;
+};
+
+/*
+ * This structure contains shift-register state.
+ * @brief  BSPP Shift-register State
+ */
+struct bspp_parse_ctx {
+	void *swsr_context;
+	enum swsr_exception exception;
+};
+
+/*
+ * This structure contains context for the current picture.
+ * @brief  BSPP Picture Context
+ */
+struct bspp_pict_ctx {
+	struct bspp_sequence_hdr_info *sequ_hdr_info;
+	int closed_gop;
+	struct bspp_pict_hdr_info pict_hdr_info[VDEC_H264_MVC_MAX_VIEWS];
+	struct bspp_sequence_hdr_info *ext_sequ_hdr_info;
+	int present;
+	int invalid;
+	int unsupported;
+	int finished;
+	unsigned int new_pict_signalled;
+};
+
+/*
+ * This structure contains resources allocated for the stream.
+ * @brief  BSPP Stream Resource Allocations
+ */
+struct bspp_stream_alloc_data {
+	struct lst_t sequence_data_list[SEQUENCE_SLOTS];
+	struct lst_t pps_data_list[PPS_SLOTS];
+	struct lst_t available_sequence_list;
+	struct lst_t available_ppss_list;
+	struct lst_t raw_data_list_available;
+	struct lst_t raw_data_list_used;
+	struct lst_t vps_data_list[VPS_SLOTS];
+	struct lst_t raw_sei_alloc_list;
+	struct lst_t available_vps_list;
+};
+
+struct bspp_raw_sei_alloc {
+	void **lst_link;
+	struct vdec_raw_bstr_data raw_sei_data;
+};
+
+/*
+ * This structure contains bitstream parsing state information for the current
+ * group of buffers.
+ * @brief  BSPP Bitstream Parsing State Information
+ */
+struct bspp_grp_bstr_ctx {
+	enum vdec_vid_std vid_std;
+	int disable_mvc;
+	int delim_present;
+	void *swsr_context;
+	enum bspp_unit_type unit_type;
+	enum bspp_unit_type last_unit_type;
+	int not_pic_unit_yet;
+	int not_ext_pic_unit_yet;
+	unsigned int total_data_size;
+	unsigned int total_bytes_read;
+	struct lst_t buffer_chain;
+	struct lst_t in_flight_bufs;
+	struct lst_t *pre_pict_seg_list[3];
+	struct lst_t *pict_seg_list[3];
+	void **pict_tag_param_array[3];
+	struct lst_t *segment_list;
+	void **pict_tag_param;
+	struct lst_t *free_segments;
+	unsigned int segment_offset;
+	int insert_start_code;
+	unsigned char start_code_suffix;
+	unsigned char current_view_idx;
+};
+
+/*
+ * This structure contains the stream context information.
+ * @brief  BSPP Stream Context Information
+ */
+struct bspp_str_context {
+	enum vdec_vid_std vid_std;
+	int disable_mvc;
+	int full_scan;
+	int immediate_decode;
+	enum vdec_bstr_format bstr_format;
+	struct vdec_codec_config codec_config;
+	unsigned int user_str_id;
+	struct bspp_vid_std_features vid_std_features;
+	struct bspp_swsr_ctx swsr_ctx;
+	struct bspp_parser_callbacks parser_callbacks;
+	struct bspp_stream_alloc_data str_alloc;
+	unsigned int sequ_hdr_id;
+	unsigned char *sequ_hdr_info;
+	unsigned char *secure_sequence_info;
+	unsigned char *pps_info;
+	unsigned char *secure_pps_info;
+	unsigned char *raw_data;
+	struct bspp_grp_bstr_ctx grp_bstr_ctx;
+	struct bspp_parse_ctx parse_ctx;
+	struct bspp_inter_pict_data inter_pict_data;
+	struct lst_t decoded_pictures_list;
+	/* Mutex for secure access */
+	struct mutex *bspp_mutex;
+	int intra_frame_closed_gop;
+	struct bspp_pict_ctx pict_ctx;
+	struct bspp_parse_state parse_state;
+	unsigned int max_dec_frame_buffering;
+};
+
+/*
+ * This structure contains the standard related parser functions.
+ * @brief  BSPP Standard Related Functions
+ */
+struct bspp_parser_functions {
+	/* Pointer to standard-specific parser configuration function */
+	bspp_cb_set_parser_config set_parser_config;
+	/* Pointer to standard-specific unit type determining function */
+	bspp_cb_determine_unit_type determine_unit_type;
+};
+
+static struct bspp_parser_functions parser_fxns[VDEC_STD_MAX] = {
+	/* VDEC_STD_UNDEFINED */
+	{ .set_parser_config = NULL, .determine_unit_type = NULL },
+	/* VDEC_STD_MPEG2 */
+	{ .set_parser_config = NULL, .determine_unit_type = NULL },
+	/* VDEC_STD_MPEG4 */
+	{ .set_parser_config = NULL, .determine_unit_type = NULL },
+	/* VDEC_STD_H263 */
+	{ .set_parser_config = NULL, .determine_unit_type = NULL },
+	/* VDEC_STD_H264 */
+	{ .set_parser_config = bspp_h264_set_parser_config,
+		.determine_unit_type = bspp_h264_determine_unittype },
+	/* VDEC_STD_VC1 */
+	{ .set_parser_config = NULL, .determine_unit_type = NULL },
+	/* VDEC_STD_AVS */
+	{ .set_parser_config = NULL, .determine_unit_type = NULL },
+	/* VDEC_STD_REAL */
+	{ .set_parser_config = NULL, .determine_unit_type = NULL },
+	/* VDEC_STD_JPEG */
+#ifdef HAS_JPEG
+	{ .set_parser_config = bspp_jpeg_setparser_config,
+		.determine_unit_type = bspp_jpeg_determine_unit_type },
+#else
+	{ .set_parser_config = NULL, .determine_unit_type = NULL },
+#endif
+	/* VDEC_STD_VP6 */
+	{ .set_parser_config = NULL, .determine_unit_type = NULL },
+	/* VDEC_STD_VP8 */
+	{ .set_parser_config = NULL, .determine_unit_type = NULL },
+	/* VDEC_STD_SORENSON */
+	{ .set_parser_config = NULL, .determine_unit_type = NULL },
+	/* VDEC_STD_HEVC */
+	{ .set_parser_config = bspp_hevc_set_parser_config,
+		.determine_unit_type = bspp_hevc_determine_unittype },
+};
+
+/*
+ * @Function	bspp_get_pps_hdr
+ * @Description	Obtains the most recent PPS header of a given Id.
+ */
+struct bspp_pps_info *bspp_get_pps_hdr(void *str_res_handle, unsigned int pps_id)
+{
+	struct bspp_stream_alloc_data *alloc_data =
+		(struct bspp_stream_alloc_data *)str_res_handle;
+
+	if (pps_id >= PPS_SLOTS || !alloc_data)
+		return NULL;
+
+	return lst_last(&alloc_data->pps_data_list[pps_id]);
+}
+
+/*
+ * @Function	bspp_get_sequ_hdr
+ * @Description	Obtains the most recent sequence header of a given Id.
+ */
+struct bspp_sequence_hdr_info *bspp_get_sequ_hdr(void *str_res_handle,
+						 unsigned int sequ_id)
+{
+	struct bspp_stream_alloc_data *alloc_data =
+		(struct bspp_stream_alloc_data *)str_res_handle;
+	if (sequ_id >= SEQUENCE_SLOTS || !alloc_data)
+		return NULL;
+
+	return lst_last(&alloc_data->sequence_data_list[sequ_id]);
+}
+
+/*
+ * @Function	bspp_free_bitstream_elem
+ * @Description	Frees a bitstream chain element.
+ */
+static void bspp_free_bitstream_elem(struct bspp_bitstream_buffer *bstr_buf)
+{
+	memset(bstr_buf, 0, sizeof(struct bspp_bitstream_buffer));
+
+	kfree(bstr_buf);
+}
+
+/*
+ * @Function	bspp_create_segment
+ * @Description Constructs a bitstream segment for the current unit and adds
+ *		it to the list.
+ */
+static int bspp_create_segment(struct bspp_grp_bstr_ctx *grp_btsr_ctx,
+			       struct bspp_bitstream_buffer *cur_buf)
+{
+	struct bspp_bitstr_seg *segment;
+	unsigned int result;
+
+	/*
+	 * Only create a segment when data (not in a previous segment) has been
+	 * parsed from the buffer.
+	 */
+	if (cur_buf->bytes_read != grp_btsr_ctx->segment_offset) {
+		/* Allocate a software shift-register context structure */
+		segment = lst_removehead(grp_btsr_ctx->free_segments);
+		if (!segment) {
+			result = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+			goto error;
+		}
+		memset(segment, 0, sizeof(struct bspp_bitstr_seg));
+
+		segment->bufmap_id = cur_buf->bufmap_id;
+		segment->data_size = (unsigned int)cur_buf->bytes_read
+			- grp_btsr_ctx->segment_offset;
+		segment->data_byte_offset = grp_btsr_ctx->segment_offset;
+
+		if (cur_buf->bytes_read == cur_buf->data_size) {
+			/* This is the last segment in the buffer. */
+			segment->bstr_seg_flag |= VDECDD_BSSEG_LASTINBUFF;
+		}
+
+		/*
+		 * Next segment will start part way through the buffer
+		 * (current read position).
+		 */
+		grp_btsr_ctx->segment_offset = (unsigned int)cur_buf->bytes_read;
+
+		if (grp_btsr_ctx->insert_start_code) {
+			segment->bstr_seg_flag |= VDECDD_BSSEG_INSERT_STARTCODE;
+			segment->start_code_suffix = grp_btsr_ctx->start_code_suffix;
+			grp_btsr_ctx->insert_start_code = 0;
+		}
+
+		lst_add(grp_btsr_ctx->segment_list, segment);
+
+		/*
+		 * If multiple segments correspond to the same (picture)
+		 * stream-unit, update it only the first time
+		 */
+		if (cur_buf->pict_tag_param && grp_btsr_ctx->pict_tag_param &&
+		    (grp_btsr_ctx->segment_list ==
+		     grp_btsr_ctx->pict_seg_list[0] ||
+		     grp_btsr_ctx->segment_list ==
+		     grp_btsr_ctx->pict_seg_list[1] ||
+		     grp_btsr_ctx->segment_list ==
+		     grp_btsr_ctx->pict_seg_list[2]))
+			*grp_btsr_ctx->pict_tag_param = cur_buf->pict_tag_param;
+	}
+
+	return IMG_SUCCESS;
+error:
+	return result;
+}
+
+/*
+ * @Function bspp_DetermineUnitType
+ *
+ */
+static int bspp_determine_unit_type(enum vdec_vid_std vid_std,
+				    unsigned char unit_type,
+				    int disable_mvc,
+				    enum bspp_unit_type *unit_type_enum)
+{
+	/* Determine the unit type from the NAL type. */
+	if (vid_std < VDEC_STD_MAX && parser_fxns[vid_std].determine_unit_type)
+		parser_fxns[vid_std].determine_unit_type(unit_type, disable_mvc, unit_type_enum);
+	else
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	bspp_shift_reg_cb
+ *
+ */
+static void bspp_shift_reg_cb(enum swsr_cbevent event,
+			      struct bspp_grp_bstr_ctx *grp_btsr_ctx,
+			      unsigned char nal_type,
+			      unsigned char **data_buffer,
+			      unsigned long long *data_size)
+{
+	unsigned int result;
+
+	switch (event) {
+	case SWSR_EVENT_INPUT_BUFFER_START: {
+		struct bspp_bitstream_buffer *next_buf;
+
+		/* Take the next bitstream buffer for use in shift-register. */
+		next_buf = lst_removehead(&grp_btsr_ctx->buffer_chain);
+
+		if (next_buf && data_buffer && data_size) {
+			lst_add(&grp_btsr_ctx->in_flight_bufs, next_buf);
+
+			*data_buffer = next_buf->ddbuf_info.cpu_virt_addr;
+			*data_size = next_buf->data_size;
+
+			next_buf->bytes_read = 0;
+		} else {
+			goto error;
+		}
+	}
+	break;
+	case SWSR_EVENT_OUTPUT_BUFFER_END: {
+		struct bspp_bitstream_buffer *cur_buf;
+
+		cur_buf = lst_removehead(&grp_btsr_ctx->in_flight_bufs);
+
+		if (cur_buf) {
+			/*
+			 * Indicate that the whole buffer content has been
+			 * used.
+			 */
+			cur_buf->bytes_read = cur_buf->data_size;
+			grp_btsr_ctx->total_bytes_read += (unsigned int)cur_buf->bytes_read;
+
+			/*
+			 * Construct segment for current buffer and add to
+			 * active list.
+			 */
+			result = bspp_create_segment(grp_btsr_ctx, cur_buf);
+			if (result != IMG_SUCCESS)
+				goto error;
+
+			/*
+			 * Next segment will start at the beginning of the next
+			 * buffer.
+			 */
+			grp_btsr_ctx->segment_offset = 0;
+
+			/* Destroy the bitstream element. */
+			bspp_free_bitstream_elem(cur_buf);
+		} else {
+			goto error;
+		}
+	}
+	break;
+
+	case SWSR_EVENT_DELIMITER_NAL_TYPE:
+		/*
+		 * Initialise the unit type with the last (unclassified or
+		 * unsupported types are not retained since they.
+		 */
+		grp_btsr_ctx->unit_type = grp_btsr_ctx->last_unit_type;
+
+		/*
+		 * Determine the unit type without consuming any data (start
+		 * code) from shift-register. Segments are created automatically
+		 * when a new buffer is requested by the shift-register so the
+		 * unit type must be known in order to switch over the segment
+		 * list.
+		 */
+		result = bspp_determine_unit_type(grp_btsr_ctx->vid_std, nal_type,
+						  grp_btsr_ctx->disable_mvc,
+						  &grp_btsr_ctx->unit_type);
+
+		/*
+		 * Only look to change bitstream segment list when the unit type
+		 * is different and the current unit contains data that could be
+		 * placed in a new list.
+		 */
+		if (grp_btsr_ctx->last_unit_type != grp_btsr_ctx->unit_type &&
+		    grp_btsr_ctx->unit_type != BSPP_UNIT_UNSUPPORTED &&
+		    grp_btsr_ctx->unit_type != BSPP_UNIT_UNCLASSIFIED) {
+			int prev_pict_data;
+			int curr_pict_data;
+
+			prev_pict_data = (grp_btsr_ctx->last_unit_type == BSPP_UNIT_PICTURE ||
+					  grp_btsr_ctx->last_unit_type ==
+					  BSPP_UNIT_SKIP_PICTURE) ? 1 : 0;
+
+			curr_pict_data = (grp_btsr_ctx->unit_type == BSPP_UNIT_PICTURE ||
+					  grp_btsr_ctx->unit_type ==
+					  BSPP_UNIT_SKIP_PICTURE) ? 1 : 0;
+
+			/*
+			 * When switching between picture and non-picture
+			 * units.
+			 */
+			if ((prev_pict_data && !curr_pict_data) ||
+			    (!prev_pict_data && curr_pict_data)) {
+				/*
+				 * Only delimit unit change when we're not the
+				 * first unit and  we're not already in the last
+				 * segment list.
+				 */
+				if (grp_btsr_ctx->last_unit_type != BSPP_UNIT_NONE &&
+				    grp_btsr_ctx->segment_list !=
+				    grp_btsr_ctx->pict_seg_list[2]) {
+					struct bspp_bitstream_buffer *cur_buf =
+						lst_first(&grp_btsr_ctx->in_flight_bufs);
+					if (!cur_buf)
+						goto error;
+
+					/*
+					 * Update the offset within current buf.
+					 */
+					swsr_get_byte_offset_curbuf(grp_btsr_ctx->swsr_context,
+								    &cur_buf->bytes_read);
+
+					/*
+					 * Create the last segment of the
+					 * previous type (which may split a
+					 * buffer into two). If the unit is
+					 * exactly at the start of a buffer this
+					 * will not create a zero-byte segment.
+					 */
+					result = bspp_create_segment(grp_btsr_ctx, cur_buf);
+					if (result != IMG_SUCCESS)
+						goto error;
+				}
+
+				/* Point at the next segment list. */
+				if (grp_btsr_ctx->segment_list
+					== grp_btsr_ctx->pre_pict_seg_list[0]) {
+					grp_btsr_ctx->segment_list =
+						grp_btsr_ctx->pict_seg_list[0];
+					grp_btsr_ctx->pict_tag_param =
+						grp_btsr_ctx->pict_tag_param_array[0];
+				} else if (grp_btsr_ctx->segment_list
+					== grp_btsr_ctx->pict_seg_list[0])
+					grp_btsr_ctx->segment_list =
+						grp_btsr_ctx->pre_pict_seg_list[1];
+				else if (grp_btsr_ctx->segment_list
+					== grp_btsr_ctx->pre_pict_seg_list[1]) {
+					grp_btsr_ctx->segment_list =
+						grp_btsr_ctx->pict_seg_list[1];
+					grp_btsr_ctx->pict_tag_param =
+						grp_btsr_ctx->pict_tag_param_array[1];
+				} else if (grp_btsr_ctx->segment_list
+					== grp_btsr_ctx->pict_seg_list[1])
+					grp_btsr_ctx->segment_list =
+						grp_btsr_ctx->pre_pict_seg_list[2];
+				else if (grp_btsr_ctx->segment_list
+					== grp_btsr_ctx->pre_pict_seg_list[2]) {
+					grp_btsr_ctx->segment_list =
+						grp_btsr_ctx->pict_seg_list[2];
+					grp_btsr_ctx->pict_tag_param =
+						grp_btsr_ctx->pict_tag_param_array[2];
+				}
+			}
+
+			grp_btsr_ctx->last_unit_type = grp_btsr_ctx->unit_type;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+error:
+	return;
+}
+
+/*
+ * @Function	bspp_exception_handler
+ *
+ */
+static void bspp_exception_handler(enum swsr_exception exception, void *parse_ctx_handle)
+{
+	struct bspp_parse_ctx *parse_ctx = (struct bspp_parse_ctx *)parse_ctx_handle;
+
+	/* Store the exception. */
+	parse_ctx->exception = exception;
+
+	switch (parse_ctx->exception) {
+	case SWSR_EXCEPT_NO_EXCEPTION:
+		break;
+	case SWSR_EXCEPT_ENCAPULATION_ERROR1:
+		break;
+	case SWSR_EXCEPT_ENCAPULATION_ERROR2:
+		break;
+	case SWSR_EXCEPT_ACCESS_INTO_SCP:
+		break;
+	case SWSR_EXCEPT_ACCESS_BEYOND_EOD:
+		break;
+	case SWSR_EXCEPT_EXPGOULOMB_ERROR:
+		break;
+	case SWSR_EXCEPT_WRONG_CODEWORD_ERROR:
+		break;
+	case SWSR_EXCEPT_NO_SCP:
+		break;
+	case SWSR_EXCEPT_INVALID_CONTEXT:
+		break;
+
+	default:
+		break;
+	}
+
+	/* Clear the exception. */
+	swsr_check_exception(parse_ctx->swsr_context);
+}
+
+/*
+ * @Function	bspp_reset_sequence
+ *
+ */
+static void bspp_reset_sequence(struct bspp_str_context *str_ctx,
+				struct bspp_sequence_hdr_info *sequ_hdr_info)
+{
+	/* Temporarily store relevant sequence fields. */
+	struct bspp_ddbuf_array_info aux_fw_sequence = sequ_hdr_info->fw_sequence;
+	void *aux_secure_sequence_info_hndl = sequ_hdr_info->secure_sequence_info;
+
+	struct bspp_ddbuf_array_info *tmp = &sequ_hdr_info->fw_sequence;
+
+	/* Reset all related structures. */
+	memset(((unsigned char *)tmp->ddbuf_info.cpu_virt_addr + tmp->buf_offset), 0x00,
+	       sequ_hdr_info->fw_sequence.buf_element_size);
+
+	if (str_ctx->parser_callbacks.reset_data_cb)
+		str_ctx->parser_callbacks.reset_data_cb(BSPP_UNIT_SEQUENCE,
+			sequ_hdr_info->secure_sequence_info);
+	else
+		memset(aux_secure_sequence_info_hndl, 0, str_ctx->vid_std_features.seq_size);
+
+	memset(sequ_hdr_info, 0, sizeof(*sequ_hdr_info));
+
+	/* Restore relevant sequence fields. */
+	sequ_hdr_info->fw_sequence = aux_fw_sequence;
+	sequ_hdr_info->sequ_hdr_info.bufmap_id = aux_fw_sequence.ddbuf_info.bufmap_id;
+	sequ_hdr_info->sequ_hdr_info.buf_offset = aux_fw_sequence.buf_offset;
+	sequ_hdr_info->secure_sequence_info = aux_secure_sequence_info_hndl;
+}
+
+/*
+ * @Function	bspp_reset_pps
+ *
+ */
+static void bspp_reset_pps(struct bspp_str_context *str_ctx,
+			   struct bspp_pps_info *pps_info)
+{
+	/* Temporarily store relevant PPS fields. */
+	struct bspp_ddbuf_array_info aux_fw_pps = pps_info->fw_pps;
+	void *aux_secure_pps_info_hndl = pps_info->secure_pps_info;
+	struct bspp_ddbuf_array_info *tmp = &pps_info->fw_pps;
+
+	/* Reset all related structures. */
+	memset(((unsigned char *)tmp->ddbuf_info.cpu_virt_addr + tmp->buf_offset), 0x00,
+	       pps_info->fw_pps.buf_element_size);
+
+	/* Reset the parser specific data. */
+	if (str_ctx->parser_callbacks.reset_data_cb)
+		str_ctx->parser_callbacks.reset_data_cb(BSPP_UNIT_PPS, pps_info->secure_pps_info);
+
+	/* Reset the common data. */
+	memset(pps_info, 0, sizeof(*pps_info));
+
+	/* Restore relevant PPS fields. */
+	pps_info->fw_pps = aux_fw_pps;
+	pps_info->bufmap_id = aux_fw_pps.ddbuf_info.bufmap_id;
+	pps_info->buf_offset = aux_fw_pps.buf_offset;
+	pps_info->secure_pps_info = aux_secure_pps_info_hndl;
+}
+
+/*
+ * @Function	bspp_stream_submit_buffer
+ *
+ */
+int bspp_stream_submit_buffer(void *str_context_handle,
+			      const struct bspp_ddbuf_info *ddbuf_info,
+			      unsigned int bufmap_id,
+			      unsigned int data_size,
+			      void *pict_tag_param,
+			      enum vdec_bstr_element_type bstr_element_type)
+{
+	struct bspp_str_context *str_ctx = (struct bspp_str_context *)str_context_handle;
+	struct bspp_bitstream_buffer *bstr_buf;
+	unsigned int result = IMG_SUCCESS;
+
+	if (!str_context_handle) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error;
+	}
+
+	if (bstr_element_type == VDEC_BSTRELEMENT_UNDEFINED ||
+	    bstr_element_type >= VDEC_BSTRELEMENT_MAX) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error;
+	}
+
+	/*
+	 * Check that the new bitstream buffer is compatible with those
+	 * before.
+	 */
+	bstr_buf = lst_last(&str_ctx->grp_bstr_ctx.buffer_chain);
+	if (bstr_buf && bstr_buf->bstr_element_type != bstr_element_type) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error;
+	}
+
+	/* Allocate a bitstream buffer chain element structure */
+	bstr_buf = kmalloc(sizeof(*bstr_buf), GFP_KERNEL);
+	if (!bstr_buf) {
+		result = IMG_ERROR_OUT_OF_MEMORY;
+		goto error;
+	}
+	memset(bstr_buf, 0, sizeof(*bstr_buf));
+
+	/* Queue buffer in a chain since units might span buffers. */
+	if (ddbuf_info)
+		bstr_buf->ddbuf_info = *ddbuf_info;
+
+	bstr_buf->data_size = data_size;
+	bstr_buf->bstr_element_type = bstr_element_type;
+	bstr_buf->pict_tag_param = pict_tag_param;
+	bstr_buf->bufmap_id = bufmap_id;
+	lst_add(&str_ctx->grp_bstr_ctx.buffer_chain, bstr_buf);
+
+	str_ctx->grp_bstr_ctx.total_data_size += data_size;
+
+error:
+	return result;
+}
+
+/*
+ * @Function	bspp_sequence_hdr_info
+ *
+ */
+static struct bspp_sequence_hdr_info *bspp_obtain_sequence_hdr(struct bspp_str_context *str_ctx)
+{
+	struct bspp_stream_alloc_data *str_alloc = &str_ctx->str_alloc;
+	struct bspp_sequence_hdr_info *sequ_hdr_info;
+
+	/*
+	 * Obtain any partially filled sequence data else provide a new one
+	 * (always new for H.264 and HEVC)
+	 */
+	sequ_hdr_info = lst_last(&str_alloc->sequence_data_list[BSPP_DEFAULT_SEQUENCE_ID]);
+	if (!sequ_hdr_info || sequ_hdr_info->ref_count > 0 || str_ctx->vid_std == VDEC_STD_H264 ||
+	    str_ctx->vid_std == VDEC_STD_HEVC) {
+		/* Get Sequence resource. */
+		sequ_hdr_info = lst_removehead(&str_alloc->available_sequence_list);
+		if (sequ_hdr_info) {
+			bspp_reset_sequence(str_ctx, sequ_hdr_info);
+			sequ_hdr_info->sequ_hdr_info.sequ_hdr_id = BSPP_INVALID;
+		}
+	}
+
+	return sequ_hdr_info;
+}
+
+/*
+ * @Function	bspp_submit_picture_decoded
+ *
+ */
+int bspp_submit_picture_decoded(void *str_context_handle,
+				struct bspp_picture_decoded *picture_decoded)
+{
+	struct bspp_picture_decoded *picture_decoded_elem;
+	struct bspp_str_context *str_ctx = (struct bspp_str_context *)str_context_handle;
+
+	/* Validate input arguments. */
+	if (!str_context_handle)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	picture_decoded_elem = kmalloc(sizeof(*picture_decoded_elem), GFP_KERNEL);
+	if (!picture_decoded_elem)
+		return IMG_ERROR_MALLOC_FAILED;
+
+	*picture_decoded_elem = *picture_decoded;
+
+	/* Lock access to the list for adding a picture - HIGH PRIORITY */
+	mutex_lock_nested(str_ctx->bspp_mutex, SUBCLASS_BSPP);
+
+	lst_add(&str_ctx->decoded_pictures_list, picture_decoded_elem);
+
+	/* Unlock access to the list for adding a picture - HIGH PRIORITY */
+	mutex_unlock(str_ctx->bspp_mutex);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	bspp_check_and_detach_pps_info
+ *
+ */
+static void bspp_check_and_detach_pps_info(struct bspp_stream_alloc_data *str_alloc,
+					   unsigned int pps_id)
+{
+	if (pps_id != BSPP_INVALID) {
+		struct bspp_pps_info *pps_info = lst_first(&str_alloc->pps_data_list[pps_id]);
+
+		if (!pps_info) /* Invalid id */
+			return;
+
+		pps_info->ref_count--;
+		/* If nothing references it any more */
+		if (pps_info->ref_count == 0) {
+			struct bspp_pps_info *next_pps_info = lst_next(pps_info);
+
+			/*
+			 * If it is not the last sequence in the slot list
+			 * remove it and return it to the pool-list
+			 */
+			if (next_pps_info) {
+				lst_remove(&str_alloc->pps_data_list[pps_id], pps_info);
+				lst_addhead(&str_alloc->available_ppss_list, pps_info);
+			}
+		}
+	}
+}
+
+/*
+ * @Function	bspp_picture_decoded
+ *
+ */
+static int bspp_picture_decoded(struct bspp_str_context *str_ctx,
+				struct bspp_picture_decoded *picture_decoded)
+{
+	struct bspp_stream_alloc_data *str_alloc = &str_ctx->str_alloc;
+
+	/* Manage Sequence */
+	if (picture_decoded->sequ_hdr_id != BSPP_INVALID) {
+		struct bspp_sequence_hdr_info *seq =
+			lst_first(&str_alloc->sequence_data_list[picture_decoded->sequ_hdr_id]);
+
+		if (!seq)
+			return IMG_ERROR_INVALID_ID;
+
+		if (picture_decoded->not_decoded) {
+			/* Release sequence data. */
+			if (str_ctx->parser_callbacks.release_data_cb)
+				str_ctx->parser_callbacks.release_data_cb((void *)str_alloc,
+					BSPP_UNIT_SEQUENCE, seq->secure_sequence_info);
+		}
+
+		seq->ref_count--;
+		/* If nothing references it any more */
+		if (seq->ref_count == 0) {
+			struct bspp_sequence_hdr_info *next_sequ_hdr_info = lst_next(seq);
+
+			/*
+			 * If it is not the last sequence in the slot list
+			 * remove it and return it to the pool-list
+			 */
+			if (next_sequ_hdr_info) {
+				lst_remove(&str_alloc->sequence_data_list
+					   [picture_decoded->sequ_hdr_id], seq);
+				/* Release sequence data. */
+				if (str_ctx->parser_callbacks.release_data_cb)
+					str_ctx->parser_callbacks.release_data_cb((void *)str_alloc,
+						BSPP_UNIT_SEQUENCE, seq->secure_sequence_info);
+
+				lst_addhead(&str_alloc->available_sequence_list, seq);
+			}
+		}
+	}
+
+	/*
+	 * Expect at least one valid PPS for H.264 and always invalid for all
+	 * others
+	 */
+	bspp_check_and_detach_pps_info(str_alloc, picture_decoded->pps_id);
+	bspp_check_and_detach_pps_info(str_alloc, picture_decoded->second_pps_id);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	bspp_service_pictures_decoded
+ *
+ */
+static int bspp_service_pictures_decoded(struct bspp_str_context *str_ctx)
+{
+	struct bspp_picture_decoded *picture_decoded;
+
+	while (1) {
+		/*
+		 * Lock access to the list for removing a picture -
+		 * LOW PRIORITY
+		 */
+		mutex_lock_nested(str_ctx->bspp_mutex, SUBCLASS_BSPP);
+
+		picture_decoded = lst_removehead(&str_ctx->decoded_pictures_list);
+
+		/*
+		 * Unlock access to the list for removing a picture -
+		 * LOW PRIORITY
+		 */
+		mutex_unlock(str_ctx->bspp_mutex);
+
+		if (!picture_decoded)
+			break;
+
+		bspp_picture_decoded(str_ctx, picture_decoded);
+		kfree(picture_decoded);
+	}
+
+	return IMG_SUCCESS;
+}
+
+static void bspp_remove_unused_vps(struct bspp_str_context *str_ctx, unsigned int vps_id)
+{
+	struct bspp_stream_alloc_data *str_alloc = &str_ctx->str_alloc;
+	struct bspp_vps_info *temp_vps_info = NULL;
+	struct bspp_vps_info *next_temp_vps_info = NULL;
+
+	/*
+	 * Check the whole Vps slot list for any unused Vpss
+	 * BEFORE ADDING THE NEW ONE, if found remove them
+	 */
+	next_temp_vps_info = lst_first(&str_alloc->vps_data_list[vps_id]);
+	while (next_temp_vps_info) {
+		/* Set Temp, it is the one which we will potentially remove */
+		temp_vps_info = next_temp_vps_info;
+		/*
+		 *  Set Next Temp, it is the one for the next iteration
+		 * (we cannot ask for next after removing it)
+		 */
+		next_temp_vps_info = lst_next(temp_vps_info);
+		/* If it is not used remove it */
+		if (temp_vps_info->ref_count == 0 && next_temp_vps_info) {
+			/* Return resource to the available pool */
+			lst_remove(&str_alloc->vps_data_list[vps_id], temp_vps_info);
+			lst_addhead(&str_alloc->available_vps_list, temp_vps_info);
+		}
+	}
+}
+
+static void bspp_remove_unused_pps(struct bspp_str_context *str_ctx, unsigned int pps_id)
+{
+	struct bspp_stream_alloc_data *str_alloc = &str_ctx->str_alloc;
+	struct bspp_pps_info *temp_pps_info = NULL;
+	struct bspp_pps_info *next_temp_pps_info = NULL;
+
+	/*
+	 * Check the whole PPS slot list for any unused PPSs BEFORE ADDING
+	 * THE NEW ONE, if found remove them
+	 */
+	next_temp_pps_info = lst_first(&str_alloc->pps_data_list[pps_id]);
+	while (next_temp_pps_info) {
+		/* Set Temp, it is the one which we will potentially remove */
+		temp_pps_info = next_temp_pps_info;
+		/*
+		 * Set Next Temp, it is the one for the next iteration
+		 * (we cannot ask for next after removing it)
+		 */
+		next_temp_pps_info = lst_next(temp_pps_info);
+		/* If it is not used remove it */
+		if (temp_pps_info->ref_count == 0 && next_temp_pps_info) {
+			/* Return resource to the available pool */
+			lst_remove(&str_alloc->pps_data_list[pps_id], temp_pps_info);
+			lst_addhead(&str_alloc->available_ppss_list, temp_pps_info);
+		}
+	}
+}
+
+static void bspp_remove_unused_sequence(struct bspp_str_context *str_ctx, unsigned int sps_id)
+{
+	struct bspp_stream_alloc_data *str_alloc = &str_ctx->str_alloc;
+	struct bspp_sequence_hdr_info *seq = NULL;
+	struct bspp_sequence_hdr_info *next_seq = NULL;
+
+	/*
+	 * Check the whole sequence slot list for any unused sequences,
+	 * if found remove them
+	 */
+	next_seq = lst_first(&str_alloc->sequence_data_list[sps_id]);
+	while (next_seq) {
+		/* Set Temp, it is the one which we will potentially remove */
+		seq = next_seq;
+		/*
+		 * Set Next Temp, it is the one for the next iteration (we
+		 * cannot ask for next after removing it)
+		 */
+		next_seq = lst_next(seq);
+
+		/*
+		 * If the head is no longer used and there is something after,
+		 * remove it
+		 */
+		if (seq->ref_count == 0 && next_seq) {
+			/* Return resource to the pool-list */
+			lst_remove(&str_alloc->sequence_data_list[sps_id], seq);
+			if (str_ctx->parser_callbacks.release_data_cb) {
+				str_ctx->parser_callbacks.release_data_cb
+							((void *)str_alloc,
+							 BSPP_UNIT_SEQUENCE,
+							 seq->secure_sequence_info);
+			}
+			lst_addhead(&str_alloc->available_sequence_list, seq);
+		}
+	}
+}
+
+/*
+ * @Function	bspp_return_or_store_sequence_hdr
+ *
+ */
+static int bspp_return_or_store_sequence_hdr(struct bspp_str_context *str_ctx,
+					     enum bspp_error_type parse_error,
+					     struct bspp_sequence_hdr_info *sequ_hdr_info)
+{
+	struct bspp_stream_alloc_data *str_alloc = &str_ctx->str_alloc;
+	struct bspp_sequence_hdr_info *prev_sequ_hdr_info;
+
+	if (((parse_error & BSPP_ERROR_UNRECOVERABLE) || (parse_error & BSPP_ERROR_UNSUPPORTED)) &&
+	    sequ_hdr_info->sequ_hdr_info.sequ_hdr_id != BSPP_INVALID) {
+		prev_sequ_hdr_info =
+			lst_last(&str_alloc->sequence_data_list
+					[sequ_hdr_info->sequ_hdr_info.sequ_hdr_id]);
+
+		/* check if it's not the same pointer */
+		if (prev_sequ_hdr_info && prev_sequ_hdr_info != sequ_hdr_info) {
+			/*
+			 * Throw away corrupted sequence header if a previous "good" one exists.
+			 */
+			sequ_hdr_info->sequ_hdr_info.sequ_hdr_id = BSPP_INVALID;
+		}
+	}
+
+	/* Store or return Sequence resource. */
+	if (sequ_hdr_info->sequ_hdr_info.sequ_hdr_id != BSPP_INVALID) {
+		/* Only add when not already in list. */
+		if (sequ_hdr_info != lst_last(&str_alloc->sequence_data_list
+				[sequ_hdr_info->sequ_hdr_info.sequ_hdr_id])) {
+			/*
+			 * Add new sequence header (not already in list) to end
+			 * of the slot-list.
+			 */
+			lst_add(&str_alloc->sequence_data_list
+				[sequ_hdr_info->sequ_hdr_info.sequ_hdr_id], sequ_hdr_info);
+		}
+
+		bspp_remove_unused_sequence(str_ctx, sequ_hdr_info->sequ_hdr_info.sequ_hdr_id);
+	} else {
+		/*
+		 * if unit was not a sequnce info, add resource to the
+		 * pool-list
+		 */
+		lst_addhead(&str_alloc->available_sequence_list, sequ_hdr_info);
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	bspp_get_resource
+ *
+ */
+static int bspp_get_resource(struct bspp_str_context *str_ctx,
+			     struct bspp_pict_hdr_info *pict_hdr_info,
+			     struct bspp_unit_data *unit_data)
+{
+	int result = IMG_SUCCESS;
+	struct bspp_stream_alloc_data *str_alloc = &str_ctx->str_alloc;
+
+	switch (unit_data->unit_type) {
+	case BSPP_UNIT_VPS:
+		/* Get VPS resource (HEVC only). */
+		if (unit_data->vid_std != VDEC_STD_HEVC)
+			break;
+		unit_data->out.vps_info = lst_removehead(&str_alloc->available_vps_list);
+		if (!unit_data->out.vps_info) {
+			result = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+		} else {
+			unit_data->out.vps_info->vps_id = BSPP_INVALID;
+			unit_data->out.vps_info->ref_count = 0;
+		}
+		break;
+	case BSPP_UNIT_SEQUENCE:
+		unit_data->out.sequ_hdr_info = bspp_obtain_sequence_hdr(str_ctx);
+		if (!unit_data->out.sequ_hdr_info)
+			result = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+
+		break;
+
+	case BSPP_UNIT_PPS:
+		/* Get PPS resource (H.264 only). */
+		unit_data->out.pps_info = lst_removehead(&str_alloc->available_ppss_list);
+		/* allocate and return extra resources */
+		if (!unit_data->out.pps_info) {
+			result = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+		} else {
+			bspp_reset_pps(str_ctx, unit_data->out.pps_info);
+			unit_data->out.pps_info->pps_id = BSPP_INVALID;
+		}
+		break;
+
+	case BSPP_UNIT_PICTURE:
+	case BSPP_UNIT_SKIP_PICTURE:
+		unit_data->out.pict_hdr_info = pict_hdr_info;
+#ifdef HAS_JPEG
+		if (unit_data->vid_std == VDEC_STD_JPEG) {
+			unit_data->impl_sequ_hdr_info = bspp_obtain_sequence_hdr(str_ctx);
+			if (!unit_data->impl_sequ_hdr_info)
+				result = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+		}
+#endif
+		break;
+
+	default:
+		break;
+	}
+
+	return result;
+}
+
+/*
+ * @Function	bspp_file_resource
+ * @Description	Stores or returns all resources provided to parse unit.
+ */
+static int bspp_file_resource(struct bspp_str_context *str_ctx, struct bspp_unit_data *unit_data)
+{
+	unsigned int result = IMG_SUCCESS;
+	struct bspp_stream_alloc_data *str_alloc = &str_ctx->str_alloc;
+
+	switch (unit_data->unit_type) {
+	case BSPP_UNIT_VPS:
+		/* Store or return VPS resource (HEVC only) */
+		if (unit_data->vid_std != VDEC_STD_HEVC)
+			break;
+
+		if (unit_data->out.vps_info->vps_id != BSPP_INVALID) {
+			lst_add(&str_alloc->vps_data_list[unit_data->out.vps_info->vps_id],
+				unit_data->out.vps_info);
+
+			bspp_remove_unused_vps(str_ctx, unit_data->out.vps_info->vps_id);
+		} else {
+			lst_addhead(&str_alloc->available_vps_list, unit_data->out.vps_info);
+		}
+		break;
+	case BSPP_UNIT_SEQUENCE:
+		result = bspp_return_or_store_sequence_hdr(str_ctx, unit_data->parse_error,
+							   unit_data->out.sequ_hdr_info);
+		VDEC_ASSERT(result == IMG_SUCCESS);
+		break;
+
+	case BSPP_UNIT_PPS:
+		/* Store or return PPS resource (H.264 only). */
+		if (unit_data->out.pps_info->pps_id != BSPP_INVALID) {
+			/*
+			 * if unit was a PPS info, add resource to the slot-list
+			 * AFTER REMOVING THE UNUSED ONES otherwise this will be
+			 * removed along the rest unless special provision for
+			 * last is made
+			 */
+			lst_add(&str_alloc->pps_data_list[unit_data->out.pps_info->pps_id],
+				unit_data->out.pps_info);
+
+			bspp_remove_unused_pps(str_ctx, unit_data->out.pps_info->pps_id);
+		} else {
+			/*
+			 * if unit was not a PPS info, add resource to the
+			 * pool-list
+			 */
+			lst_addhead(&str_alloc->available_ppss_list, unit_data->out.pps_info);
+		}
+		break;
+
+	case BSPP_UNIT_PICTURE:
+	case BSPP_UNIT_SKIP_PICTURE:
+#ifdef HAS_JPEG
+		if (unit_data->vid_std == VDEC_STD_JPEG) {
+			result = bspp_return_or_store_sequence_hdr(str_ctx,
+								   unit_data->parse_error,
+								   unit_data->impl_sequ_hdr_info);
+			VDEC_ASSERT(result == IMG_SUCCESS);
+		}
+#endif
+		break;
+
+	default:
+		break;
+	}
+
+	return result;
+}
+
+/*
+ * @Function	bspp_process_unit
+ *
+ */
+static int bspp_process_unit(struct bspp_str_context *str_ctx,
+			     unsigned int size_delim_bits,
+			     struct bspp_pict_ctx *pict_ctx,
+			     struct bspp_parse_state *parse_state)
+{
+	struct bspp_unit_data unit_data;
+	unsigned long long unit_size = 0; /* Unit size (in bytes, size delimited only). */
+	unsigned int result;
+	unsigned char vidx = str_ctx->grp_bstr_ctx.current_view_idx;
+	struct bspp_pict_hdr_info *curr_pict_hdr_info;
+
+	/*
+	 * during call to swsr_consume_delim(), above.
+	 * Setup default unit data.
+	 */
+	memset(&unit_data, 0, sizeof(struct bspp_unit_data));
+
+	if (str_ctx->grp_bstr_ctx.delim_present) {
+		/* Consume delimiter and catch any exceptions. */
+		/*
+		 * Consume the bitstream unit delimiter (size or
+		 * start code prefix).
+		 * When size-delimited the unit size is also returned
+		 * so that the next unit can be found.
+		 */
+		result = swsr_consume_delim(str_ctx->swsr_ctx.swsr_context,
+					    str_ctx->swsr_ctx.emulation_prevention,
+					    size_delim_bits, &unit_size);
+		if (result != IMG_SUCCESS)
+			goto error;
+	}
+
+	unit_data.unit_type = str_ctx->grp_bstr_ctx.unit_type;
+	unit_data.vid_std = str_ctx->vid_std;
+	unit_data.delim_present = str_ctx->grp_bstr_ctx.delim_present;
+	unit_data.codec_config = &str_ctx->codec_config;
+	unit_data.parse_state = parse_state;
+	unit_data.pict_sequ_hdr_id = str_ctx->sequ_hdr_id;
+	unit_data.str_res_handle = &str_ctx->str_alloc;
+	unit_data.unit_data_size = str_ctx->grp_bstr_ctx.total_data_size;
+	unit_data.intra_frm_as_closed_gop = str_ctx->intra_frame_closed_gop;
+
+	unit_data.max_dec_frame_buffering = str_ctx->max_dec_frame_buffering;
+
+	/* ponit to picture headers, check boundaries */
+	curr_pict_hdr_info = vidx < VDEC_H264_MVC_MAX_VIEWS ?
+		&pict_ctx->pict_hdr_info[vidx] : NULL;
+	unit_data.parse_state->next_pict_hdr_info =
+		vidx + 1 < VDEC_H264_MVC_MAX_VIEWS ?
+		&pict_ctx->pict_hdr_info[vidx + 1] : NULL;
+	unit_data.parse_state->is_prefix = 0;
+
+	/* Obtain output data containers. */
+	result = bspp_get_resource(str_ctx, curr_pict_hdr_info, &unit_data);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Process Unit and catch any exceptions. */
+	/*
+	 * Call the standard-specific function to parse the bitstream
+	 * unit.
+	 */
+	result = str_ctx->parser_callbacks.parse_unit_cb(str_ctx->swsr_ctx.swsr_context,
+			&unit_data);
+	if (result != IMG_SUCCESS) {
+		pr_err("Failed to process unit, error = %d", unit_data.parse_error);
+		goto error;
+	}
+
+	if (unit_data.parse_error != BSPP_ERROR_NONE)
+		pr_err("Issues found while processing unit, error = %d\n", unit_data.parse_error);
+
+	/* Store or return resource used for parsing unit. */
+	result = bspp_file_resource(str_ctx, &unit_data);
+
+	if (!str_ctx->inter_pict_data.seen_closed_gop &&
+	    str_ctx->grp_bstr_ctx.unit_type == BSPP_UNIT_PICTURE &&
+		unit_data.slice &&
+		(unit_data.out.pict_hdr_info &&
+		unit_data.out.pict_hdr_info->intra_coded) &&
+		str_ctx->vid_std != VDEC_STD_H264)
+		unit_data.new_closed_gop = 1;
+
+	if (unit_data.new_closed_gop) {
+		str_ctx->inter_pict_data.seen_closed_gop = 1;
+		str_ctx->inter_pict_data.new_closed_gop = 1;
+	}
+
+	/*
+	 * Post-process unit (use local context in case
+	 * parse function tried to change the unit type.
+	 */
+	if (str_ctx->grp_bstr_ctx.unit_type == BSPP_UNIT_PICTURE ||
+	    str_ctx->grp_bstr_ctx.unit_type == BSPP_UNIT_SKIP_PICTURE) {
+		if (str_ctx->inter_pict_data.new_closed_gop) {
+			pict_ctx->closed_gop = 1;
+			str_ctx->inter_pict_data.new_closed_gop = 0;
+		}
+
+		if (unit_data.ext_slice && str_ctx->grp_bstr_ctx.not_ext_pic_unit_yet &&
+		    unit_data.pict_sequ_hdr_id != BSPP_INVALID) {
+			unsigned int id = unit_data.pict_sequ_hdr_id;
+
+			str_ctx->grp_bstr_ctx.not_ext_pic_unit_yet = 0;
+			pict_ctx->ext_sequ_hdr_info =
+				lst_last(&str_ctx->str_alloc.sequence_data_list[id]);
+		}
+
+		if (unit_data.slice) {
+			if (!curr_pict_hdr_info) {
+				VDEC_ASSERT(0);
+				return -EINVAL;
+			}
+			if (str_ctx->grp_bstr_ctx.not_pic_unit_yet &&
+			    unit_data.pict_sequ_hdr_id != BSPP_INVALID) {
+				str_ctx->grp_bstr_ctx.not_pic_unit_yet = 0;
+
+				/*
+				 * depend upon the picture header being
+				 * populated (in addition to slice data).
+				 */
+				pict_ctx->present = 1;
+
+				/*
+				 * Update the picture context from the last unit parsed.
+				 * This context must be stored since a non-picture unit may follow.
+				 * Obtain current instance of sequence data for given ID.
+				 */
+				if (!pict_ctx->sequ_hdr_info) {
+					unsigned int id = unit_data.pict_sequ_hdr_id;
+
+					pict_ctx->sequ_hdr_info =
+					lst_last(&str_ctx->str_alloc.sequence_data_list[id]);
+
+					/* Do the sequence flagging/reference-counting */
+					pict_ctx->sequ_hdr_info->ref_count++;
+				}
+
+				/* Override the field here. */
+				if (str_ctx->swsr_ctx.sr_config.delim_type == SWSR_DELIM_NONE) {
+					if (str_ctx->grp_bstr_ctx.unit_type ==
+						BSPP_UNIT_SKIP_PICTURE) {
+						/* VDECFW_SKIPPED_PICTURE; */
+						curr_pict_hdr_info->parser_mode =
+							VDECFW_SKIPPED_PICTURE;
+						curr_pict_hdr_info->pic_data_size = 0;
+					} else {
+						/* VDECFW_SIZE_SIDEBAND; */
+						curr_pict_hdr_info->parser_mode =
+							VDECFW_SIZE_SIDEBAND;
+						curr_pict_hdr_info->pic_data_size =
+							str_ctx->grp_bstr_ctx.total_data_size;
+					}
+				} else if (str_ctx->swsr_ctx.sr_config.delim_type ==
+					   SWSR_DELIM_SIZE) {
+					if (str_ctx->swsr_ctx.sr_config.delim_length <= 8)
+						/* VDECFW_SIZE_DELIMITED_1_ONLY; */
+						curr_pict_hdr_info->parser_mode =
+							VDECFW_SIZE_DELIMITED_1_ONLY;
+					else if (str_ctx->swsr_ctx.sr_config.delim_length <= 16)
+						/* VDECFW_SIZE_DELIMITED_2_ONLY; */
+						curr_pict_hdr_info->parser_mode =
+							VDECFW_SIZE_DELIMITED_2_ONLY;
+					else if (str_ctx->swsr_ctx.sr_config.delim_length <= 32)
+						/* VDECFW_SIZE_DELIMITED_4_ONLY; */
+						curr_pict_hdr_info->parser_mode =
+							VDECFW_SIZE_DELIMITED_4_ONLY;
+
+					curr_pict_hdr_info->pic_data_size +=
+						((unsigned int)unit_size
+						+ (size_delim_bits / 8));
+				} else if (str_ctx->swsr_ctx.sr_config.delim_type == SWSR_DELIM_SCP)
+					/* VDECFW_SCP_ONLY; */
+					curr_pict_hdr_info->parser_mode = VDECFW_SCP_ONLY;
+			}
+
+			/*
+			 * for MVC, the Slice Extension should also have the
+			 * same ParserMode as the Base view.
+			 */
+			if (unit_data.parse_state->next_pict_hdr_info) {
+				unit_data.parse_state->next_pict_hdr_info->parser_mode =
+					curr_pict_hdr_info->parser_mode;
+			}
+
+			if (unit_data.parse_error & BSPP_ERROR_UNSUPPORTED) {
+				pict_ctx->invalid = 1;
+				pict_ctx->unsupported = 1;
+			} else if (!str_ctx->full_scan) {
+				/*
+				 * Only parse up to and including the first
+				 * valid video slice unless full scanning.
+				 */
+				pict_ctx->finished = 1;
+			}
+		}
+	}
+
+	if (unit_data.extracted_all_data) {
+		enum swsr_found found;
+
+		swsr_byte_align(str_ctx->swsr_ctx.swsr_context);
+
+		found = swsr_check_delim_or_eod(str_ctx->swsr_ctx.swsr_context);
+		if (found != SWSR_FOUND_DELIM && found != SWSR_FOUND_EOD) {
+			/*
+			 * Should already be at the next delimiter or EOD.
+			 * Any bits left at the end of the unit could indicate
+			 * corrupted syntax or erroneous parsing.
+			 */
+		}
+	}
+
+	return IMG_SUCCESS;
+
+error:
+	if (unit_data.unit_type == BSPP_UNIT_PICTURE ||
+	    unit_data.unit_type == BSPP_UNIT_SKIP_PICTURE)
+		pict_ctx->invalid = 1;
+
+	/*
+	 * Tidy-up resources.
+	 * Store or return resource used for parsing unit.
+	 */
+	bspp_file_resource(str_ctx, &unit_data);
+
+	return result;
+}
+
+/*
+ * @Function	bspp_terminate_buffer
+ *
+ */
+static int bspp_terminate_buffer(struct bspp_grp_bstr_ctx *grp_btsr_ctx,
+				 struct bspp_bitstream_buffer *buf)
+{
+	int result = -1;
+
+	/* Indicate that all the data in buffer should be added to segment. */
+	buf->bytes_read = buf->data_size;
+
+	result = bspp_create_segment(grp_btsr_ctx, buf);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Next segment will start at the beginning of the next buffer. */
+	grp_btsr_ctx->segment_offset = 0;
+
+	bspp_free_bitstream_elem(buf);
+
+	return result;
+}
+
+/*
+ * @Function	bspp_jump_to_next_view
+ *
+ */
+static int bspp_jump_to_next_view(struct bspp_grp_bstr_ctx *grp_btsr_ctx,
+				  struct bspp_preparsed_data *preparsed_data,
+				  struct bspp_parse_state *parse_state)
+{
+	struct bspp_bitstream_buffer *cur_buf;
+	int result;
+	unsigned int i;
+	unsigned char vidx;
+
+	if (!grp_btsr_ctx || !parse_state || !preparsed_data) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error;
+	}
+
+	vidx = grp_btsr_ctx->current_view_idx;
+
+	if (vidx >= VDEC_H264_MVC_MAX_VIEWS) {
+		result = IMG_ERROR_NOT_SUPPORTED;
+		goto error;
+	}
+
+	/* get current buffer */
+	cur_buf = (struct bspp_bitstream_buffer *)lst_first(&grp_btsr_ctx->in_flight_bufs);
+	if (!cur_buf) {
+		result = IMG_ERROR_CANCELLED;
+		goto error;
+	}
+
+	if (cur_buf->bufmap_id != parse_state->prev_buf_map_id) {
+		/*
+		 * If we moved to the next buffer while parsing the slice
+		 * header of the new view we have to reduce the size of
+		 * the last segment up to the beginning of the new view slice
+		 * and create a new segment from that point up to the end of
+		 * the buffer. The new segment should belong to the new view.
+		 * THIS ONLY WORKS IF THE SLICE HEADER DOES NOT SPAN MORE THAN
+		 * TWO BUFFERS. If we want to support the case that the slice
+		 * header of the new view spans multiple buffer we either have
+		 * here remove all the segments up to the point were we find
+		 * the buffer we are looking for, then adjust the size of this
+		 * segment and then add the segments we removed to the next
+		 * view list or we can implement a mechanism like the one that
+		 * peeks for the NAL unit type and delimit the next view
+		 * segment before parsing the first slice of the view.
+		 */
+		struct bspp_bitstr_seg *segment;
+
+		segment = lst_last(grp_btsr_ctx->segment_list);
+		if (segment && segment->bufmap_id == parse_state->prev_buf_map_id) {
+			struct bspp_bitstream_buffer prev_buf;
+
+			segment->data_size -= parse_state->prev_buf_data_size
+				- parse_state->prev_byte_offset_buf;
+			segment->bstr_seg_flag &= ~VDECDD_BSSEG_LASTINBUFF;
+
+			/*
+			 * Change the segmenOffset value with the value it
+			 * would have if we had delemited the segment correctly
+			 * beforehand.
+			 */
+			grp_btsr_ctx->segment_offset = parse_state->prev_byte_offset_buf;
+
+			/* set lists of segments to new view... */
+			for (i = 0; i < BSPP_MAX_PICTURES_PER_BUFFER; i++) {
+				grp_btsr_ctx->pre_pict_seg_list[i] =
+					&preparsed_data->ext_pictures_data[vidx].pre_pict_seg_list
+					[i];
+				grp_btsr_ctx->pict_seg_list[i] =
+					&preparsed_data->ext_pictures_data[vidx].pict_seg_list[i];
+
+				lst_init(grp_btsr_ctx->pre_pict_seg_list[i]);
+				lst_init(grp_btsr_ctx->pict_seg_list[i]);
+			}
+			/* and current segment list */
+			grp_btsr_ctx->segment_list = grp_btsr_ctx->pict_seg_list[0];
+
+			memset(&prev_buf, 0, sizeof(struct bspp_bitstream_buffer));
+			prev_buf.bufmap_id = segment->bufmap_id;
+			prev_buf.data_size = parse_state->prev_buf_data_size;
+			prev_buf.bytes_read = prev_buf.data_size;
+
+			/* Create the segment the first part of the next view */
+			result = bspp_create_segment(grp_btsr_ctx, &prev_buf);
+			if (result != IMG_SUCCESS)
+				goto error;
+		} else {
+			result = IMG_ERROR_NOT_SUPPORTED;
+			goto error;
+		}
+	} else {
+		/*
+		 * the data just parsed belongs to new view, so use previous byte
+		 * offset
+		 */
+		cur_buf->bytes_read = parse_state->prev_byte_offset_buf;
+
+		/* Create the segment for previous view */
+		result = bspp_create_segment(grp_btsr_ctx, cur_buf);
+		if (result != IMG_SUCCESS)
+			goto error;
+
+		/* set lists of segments to new view */
+		for (i = 0; i < BSPP_MAX_PICTURES_PER_BUFFER; i++) {
+			grp_btsr_ctx->pre_pict_seg_list[i] =
+				&preparsed_data->ext_pictures_data[vidx].pre_pict_seg_list[i];
+			grp_btsr_ctx->pict_seg_list[i] =
+				&preparsed_data->ext_pictures_data[vidx].pict_seg_list[i];
+
+			lst_init(grp_btsr_ctx->pre_pict_seg_list[i]);
+			lst_init(grp_btsr_ctx->pict_seg_list[i]);
+		}
+		/* and current segment list */
+		grp_btsr_ctx->segment_list = grp_btsr_ctx->pict_seg_list[0];
+	}
+
+	/* update prefix flag */
+	preparsed_data->ext_pictures_data[vidx].is_prefix = parse_state->is_prefix;
+	/* and view index */
+	grp_btsr_ctx->current_view_idx++;
+
+	/* set number of extended pictures */
+	preparsed_data->num_ext_pictures = grp_btsr_ctx->current_view_idx;
+
+error:
+	return result;
+}
+
+static void bspp_reset_pict_state(struct bspp_str_context *str_ctx, struct bspp_pict_ctx *pict_ctx,
+				  struct bspp_parse_state *parse_state)
+{
+	memset(pict_ctx, 0, sizeof(struct bspp_pict_ctx));
+	memset(parse_state, 0, sizeof(struct bspp_parse_state));
+
+	/* Setup group buffer processing state. */
+	parse_state->inter_pict_ctx = &str_ctx->inter_pict_data;
+	parse_state->prev_bottom_pic_flag = (unsigned char)BSPP_INVALID;
+	parse_state->next_pic_is_new = 1;
+	parse_state->prev_frame_num = BSPP_INVALID;
+	parse_state->second_field_flag = 0;
+	parse_state->first_chunk = 1;
+}
+
+/*
+ * @Function	bspp_stream_preparse_buffers
+ * @Description	Buffer list cannot be processed since units in this last buffer
+ * may not be complete. Must wait until a buffer is provided with end-of-picture
+ * signalled. When the buffer indicates that units won't span then we can
+ * process the bitstream buffer chain.
+ */
+int bspp_stream_preparse_buffers(void *str_context_handle,
+				 const struct bspp_ddbuf_info *contig_buf_info,
+				 unsigned int contig_buf_map_id, struct lst_t *segments,
+				 struct bspp_preparsed_data *preparsed_data,
+				 int end_of_pic)
+{
+	struct bspp_str_context *str_ctx = (struct bspp_str_context *)str_context_handle;
+	struct bspp_pict_ctx *pict_ctx = &str_ctx->pict_ctx;
+	struct bspp_parse_state *parse_state = &str_ctx->parse_state;
+	int i;
+	unsigned int unit_count = 0, num_arrays = 0;
+	unsigned int size_delim_bits = 0;
+	enum swsr_found found = SWSR_FOUND_NONE;
+	unsigned int result;
+	struct bspp_bitstr_seg *segment;
+	struct lst_t temp_list;
+
+	/*
+	 * since it is new picture, resetting the context status to
+	 * beginning
+	 */
+	/* TODO: revisit this */
+	pict_ctx->finished = 0;
+	pict_ctx->new_pict_signalled = 0;
+
+	if (!str_context_handle)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (!segments || !preparsed_data)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Check that bitstream buffers have been registered. */
+	if (!lst_last(&str_ctx->grp_bstr_ctx.buffer_chain))
+		return IMG_ERROR_OPERATION_PROHIBITED;
+
+	/* Initialise the output data. */
+	memset(preparsed_data, 0, sizeof(struct bspp_preparsed_data));
+
+	if (!parse_state->initialised) {
+		bspp_reset_pict_state(str_ctx, pict_ctx, parse_state);
+		parse_state->initialised = 1;
+	}
+
+	for (i = 0; i < 3; i++) {
+		lst_init(&preparsed_data->picture_data.pre_pict_seg_list[i]);
+		lst_init(&preparsed_data->picture_data.pict_seg_list[i]);
+	}
+
+	/* Initialise parsing for this video standard. */
+	if (str_ctx->parser_callbacks.initialise_parsing_cb && parse_state->first_chunk)
+		str_ctx->parser_callbacks.initialise_parsing_cb(parse_state);
+
+	parse_state->first_chunk = 0;
+
+	for (i = 0; i < VDEC_H264_MVC_MAX_VIEWS; i++) {
+		pict_ctx->pict_hdr_info[i].pict_aux_data.id = BSPP_INVALID;
+		pict_ctx->pict_hdr_info[i].second_pict_aux_data.id = BSPP_INVALID;
+	}
+
+	/* Setup buffer group bitstream context. */
+	str_ctx->grp_bstr_ctx.vid_std = str_ctx->vid_std;
+	str_ctx->grp_bstr_ctx.disable_mvc = str_ctx->disable_mvc;
+	str_ctx->grp_bstr_ctx.delim_present = 1;
+	str_ctx->grp_bstr_ctx.swsr_context = str_ctx->swsr_ctx.swsr_context;
+	str_ctx->grp_bstr_ctx.unit_type = BSPP_UNIT_NONE;
+	str_ctx->grp_bstr_ctx.last_unit_type = BSPP_UNIT_NONE;
+	str_ctx->grp_bstr_ctx.not_pic_unit_yet = 1;
+	str_ctx->grp_bstr_ctx.not_ext_pic_unit_yet = 1;
+	str_ctx->grp_bstr_ctx.total_bytes_read = 0;
+	str_ctx->grp_bstr_ctx.current_view_idx = 0;
+
+	for (i = 0; i < 3; i++) {
+		str_ctx->grp_bstr_ctx.pre_pict_seg_list[i] =
+			&preparsed_data->picture_data.pre_pict_seg_list[i];
+		str_ctx->grp_bstr_ctx.pict_seg_list[i] =
+			&preparsed_data->picture_data.pict_seg_list[i];
+		str_ctx->grp_bstr_ctx.pict_tag_param_array[i] =
+			&preparsed_data->picture_data.pict_tag_param[i];
+	}
+	str_ctx->grp_bstr_ctx.segment_list = str_ctx->grp_bstr_ctx.pre_pict_seg_list[0];
+	str_ctx->grp_bstr_ctx.pict_tag_param = str_ctx->grp_bstr_ctx.pict_tag_param_array[0];
+	str_ctx->grp_bstr_ctx.free_segments = segments;
+	str_ctx->grp_bstr_ctx.segment_offset = 0;
+	str_ctx->grp_bstr_ctx.insert_start_code = 0;
+
+	/*
+	 * Before processing the units service all the picture decoded events
+	 * to free the resources1794
+	 */
+	bspp_service_pictures_decoded(str_ctx);
+
+	/*
+	 * A picture currently being parsed is already decoded (may happen
+	 * after dwr in low latency mode) and its recourses were freed. Skip
+	 * the rest of the picture.
+	 */
+	if (pict_ctx->sequ_hdr_info && pict_ctx->sequ_hdr_info->ref_count == 0) {
+		pict_ctx->present = 0;
+		pict_ctx->finished = 1;
+	}
+
+	/*
+	 * For bitstreams without unit delimiters treat all the buffers as
+	 * a single unit whose type is defined by the first buffer element.
+	 */
+	if (str_ctx->swsr_ctx.sr_config.delim_type == SWSR_DELIM_NONE) {
+		struct bspp_bitstream_buffer *cur_buf =
+			lst_first(&str_ctx->grp_bstr_ctx.buffer_chain);
+
+		/* if there is no picture data we must be skipped. */
+		if (!cur_buf || cur_buf->data_size == 0) {
+			str_ctx->grp_bstr_ctx.unit_type = BSPP_UNIT_SKIP_PICTURE;
+		} else if (cur_buf->bstr_element_type == VDEC_BSTRELEMENT_CODEC_CONFIG) {
+			str_ctx->grp_bstr_ctx.unit_type = BSPP_UNIT_SEQUENCE;
+		} else if (cur_buf->bstr_element_type == VDEC_BSTRELEMENT_PICTURE_DATA ||
+			 cur_buf->bstr_element_type == VDEC_BSTRELEMENT_UNSPECIFIED) {
+			str_ctx->grp_bstr_ctx.unit_type = BSPP_UNIT_PICTURE;
+			str_ctx->grp_bstr_ctx.segment_list = str_ctx->grp_bstr_ctx.pict_seg_list[0];
+		}
+
+		str_ctx->grp_bstr_ctx.delim_present = 0;
+	}
+
+	/*
+	 * Load the first section (buffer) of biststream into the software
+	 * shift-register. BSPP maps "buffer" to "section" and allows for
+	 * contiguous parsing of all buffers since unit boundaries are not
+	 * known up-front. Unit parsing and segment creation is happening in a
+	 * single pass.
+	 */
+	result = swsr_start_bitstream(str_ctx->swsr_ctx.swsr_context,
+				      &str_ctx->swsr_ctx.sr_config,
+				      str_ctx->grp_bstr_ctx.total_data_size,
+				      str_ctx->swsr_ctx.emulation_prevention);
+
+	/* Seek for next delimiter or end of data and catch any exceptions. */
+	if (str_ctx->grp_bstr_ctx.delim_present) {
+		/* Locate the first bitstream unit. */
+		found = swsr_seek_delim_or_eod(str_ctx->swsr_ctx.swsr_context);
+	}
+
+	if (str_ctx->swsr_ctx.sr_config.delim_type == SWSR_DELIM_SIZE) {
+		struct bspp_bitstream_buffer *cur_buf =
+			lst_first(&str_ctx->grp_bstr_ctx.in_flight_bufs);
+
+		if (cur_buf->bstr_element_type == VDEC_BSTRELEMENT_CODEC_CONFIG &&
+		    str_ctx->parser_callbacks.parse_codec_config_cb) {
+			/* Parse codec config header and catch any exceptions */
+			str_ctx->parser_callbacks.parse_codec_config_cb
+						(str_ctx->swsr_ctx.swsr_context,
+						 &unit_count,
+						 &num_arrays,
+						 &str_ctx->swsr_ctx.sr_config.delim_length,
+						 &size_delim_bits);
+		} else {
+			size_delim_bits = str_ctx->swsr_ctx.sr_config.delim_length;
+		}
+	}
+
+	/* Process all the bitstream units until the picture is located. */
+	while (found != SWSR_FOUND_EOD && !pict_ctx->finished) {
+		struct bspp_bitstream_buffer *cur_buf =
+			lst_first(&str_ctx->grp_bstr_ctx.in_flight_bufs);
+
+		if (!cur_buf) {
+			pr_err("%s: cur_buf pointer is NULL\n", __func__);
+			result = IMG_ERROR_INVALID_PARAMETERS;
+			goto error;
+		}
+
+		if (str_ctx->swsr_ctx.sr_config.delim_type ==
+			SWSR_DELIM_SIZE && cur_buf->bstr_element_type ==
+			VDEC_BSTRELEMENT_CODEC_CONFIG &&
+			str_ctx->parser_callbacks.update_unit_counts_cb) {
+			/*
+			 * Parse middle part of codec config header and catch
+			 * any exceptions.
+			 */
+			str_ctx->parser_callbacks.update_unit_counts_cb
+						(str_ctx->swsr_ctx.swsr_context,
+						 &unit_count,
+						 &num_arrays);
+		}
+
+		/* Process the next unit. */
+		result = bspp_process_unit(str_ctx, size_delim_bits, pict_ctx, parse_state);
+		if (result == IMG_ERROR_NOT_SUPPORTED)
+			goto error;
+
+		if (str_ctx->swsr_ctx.sr_config.delim_type != SWSR_DELIM_NONE)
+			str_ctx->grp_bstr_ctx.delim_present = 1;
+
+		/* jump to the next view */
+		if (parse_state->new_view) {
+			result = bspp_jump_to_next_view(&str_ctx->grp_bstr_ctx,
+							preparsed_data,
+							parse_state);
+			if (result != IMG_SUCCESS)
+				goto error;
+
+			parse_state->new_view = 0;
+		}
+
+		if (!pict_ctx->finished) {
+			/*
+			 * Seek for next delimiter or end of data and catch any
+			 * exceptions.
+			 */
+			/* Locate the next bitstream unit or end of data */
+			found = swsr_seek_delim_or_eod(str_ctx->swsr_ctx.swsr_context);
+
+			{
+				struct bspp_bitstream_buffer *buf;
+				/* Update the offset within current buffer. */
+				swsr_get_byte_offset_curbuf(str_ctx->grp_bstr_ctx.swsr_context,
+							    &parse_state->prev_byte_offset_buf);
+				buf = lst_first(&str_ctx->grp_bstr_ctx.in_flight_bufs);
+				if (buf) {
+					parse_state->prev_buf_map_id = buf->bufmap_id;
+					parse_state->prev_buf_data_size = buf->data_size;
+				}
+			}
+		}
+	}
+
+	/* Finalize parsing for this video standard. */
+	if (str_ctx->parser_callbacks.finalise_parsing_cb && end_of_pic) {
+		str_ctx->parser_callbacks.finalise_parsing_cb((void *)&str_ctx->str_alloc,
+			parse_state);
+	}
+
+	/*
+	 * Create segments for each buffer held by the software shift register
+	 * (and not yet processed).
+	 */
+	while (lst_first(&str_ctx->grp_bstr_ctx.in_flight_bufs)) {
+		struct bspp_bitstream_buffer *buf =
+			lst_removehead(&str_ctx->grp_bstr_ctx.in_flight_bufs);
+
+		result = bspp_terminate_buffer(&str_ctx->grp_bstr_ctx, buf);
+	}
+
+	/*
+	 * Create segments for each buffer not yet requested by the shift
+	 * register.
+	 */
+	while (lst_first(&str_ctx->grp_bstr_ctx.buffer_chain)) {
+		struct bspp_bitstream_buffer *buf =
+			lst_removehead(&str_ctx->grp_bstr_ctx.buffer_chain);
+
+		result = bspp_terminate_buffer(&str_ctx->grp_bstr_ctx, buf);
+	}
+
+	/*
+	 * Populate the parsed data information for picture only if one is
+	 * present. The anonymous data has already been added to the
+	 * appropriate segment list.
+	 */
+	if (pict_ctx->present && !pict_ctx->invalid) {
+		if (!pict_ctx->new_pict_signalled) {
+			/*
+			 * Provide data about sequence used by picture.
+			 * Signal "new sequence" if the sequence header is new
+			 * or has changed. always switch seq when changing base
+			 * and additional views
+			 */
+			if (pict_ctx->sequ_hdr_info) {
+				if (pict_ctx->sequ_hdr_info->sequ_hdr_info.sequ_hdr_id !=
+					str_ctx->sequ_hdr_id ||
+					pict_ctx->sequ_hdr_info->ref_count == 1 ||
+					pict_ctx->ext_sequ_hdr_info ||
+					pict_ctx->closed_gop) {
+					preparsed_data->new_sequence = 1;
+					preparsed_data->sequ_hdr_info =
+						pict_ctx->sequ_hdr_info->sequ_hdr_info;
+				}
+			}
+
+			/* Signal "new subsequence" and its common header information. */
+			if (pict_ctx->ext_sequ_hdr_info) {
+				preparsed_data->new_sub_sequence = 1;
+				preparsed_data->ext_sequ_hdr_info =
+					pict_ctx->ext_sequ_hdr_info->sequ_hdr_info;
+
+				for (i = 0; i < VDEC_H264_MVC_MAX_VIEWS - 1;
+					i++) {
+					/*
+					 * prefix is always the last one
+					 * do not attach any header info to it
+					 */
+					if (preparsed_data->ext_pictures_data[i].is_prefix)
+						break;
+
+					/* attach headers */
+					preparsed_data->ext_pictures_data[i].sequ_hdr_id =
+					pict_ctx->ext_sequ_hdr_info->sequ_hdr_info.sequ_hdr_id;
+					pict_ctx->ext_sequ_hdr_info->ref_count++;
+					preparsed_data->ext_pictures_data[i].pict_hdr_info =
+						pict_ctx->pict_hdr_info[i + 1];
+				}
+
+				preparsed_data->ext_pictures_data
+					[0].pict_hdr_info.first_pic_of_sequence =
+					preparsed_data->new_sub_sequence;
+
+				/*
+				 * Update the base view common sequence info
+				 * with the number of views that the stream has.
+				 * Otherwise the number of views is inconsistent
+				 * between base view sequence and dependent view
+				 * sequences. Also base view sequence appears
+				 * with one view and the driver calculates the
+				 * wrong number of resources.
+				 */
+				preparsed_data->sequ_hdr_info.com_sequ_hdr_info.num_views =
+				preparsed_data->ext_sequ_hdr_info.com_sequ_hdr_info.num_views;
+			}
+
+			/* Signal if this picture is the first in a closed GOP */
+			if (pict_ctx->closed_gop) {
+				preparsed_data->closed_gop = 1;
+				preparsed_data->sequ_hdr_info.com_sequ_hdr_info.not_dpb_flush =
+					str_ctx->inter_pict_data.not_dpb_flush;
+			}
+
+			/*
+			 * Signal "new picture" and its common header
+			 * information.
+			 */
+			preparsed_data->new_picture = 1;
+			if (pict_ctx->sequ_hdr_info) {
+				preparsed_data->picture_data.sequ_hdr_id =
+					pict_ctx->sequ_hdr_info->sequ_hdr_info.sequ_hdr_id;
+			}
+			preparsed_data->picture_data.pict_hdr_info = pict_ctx->pict_hdr_info[0];
+
+			preparsed_data->picture_data.pict_hdr_info.first_pic_of_sequence =
+				preparsed_data->new_sequence;
+			if (contig_buf_info)
+				preparsed_data->picture_data.pict_hdr_info.fragmented_data = 1;
+			else
+				preparsed_data->picture_data.pict_hdr_info.fragmented_data = 0;
+
+			str_ctx->sequ_hdr_id = preparsed_data->picture_data.sequ_hdr_id;
+
+			pict_ctx->new_pict_signalled = 1;
+
+			/*
+			 * aso/fmo supported only when a frame is submitted as
+			 * a whole
+			 */
+			if (parse_state->discontinuous_mb && !end_of_pic)
+				result = IMG_ERROR_NOT_SUPPORTED;
+		} else {
+			preparsed_data->new_fragment = 1;
+
+			if (parse_state->discontinuous_mb)
+				result = IMG_ERROR_NOT_SUPPORTED;
+		}
+
+		lst_init(&temp_list);
+
+		segment = lst_removehead(&preparsed_data->picture_data.pict_seg_list[0]);
+		while (segment) {
+			lst_add(&temp_list, segment);
+			segment = lst_removehead(&preparsed_data->picture_data.pict_seg_list[0]);
+		}
+
+		segment = lst_removehead(&str_ctx->inter_pict_data.pic_prefix_seg);
+		while (segment) {
+			lst_add(&preparsed_data->picture_data.pict_seg_list[0],
+				segment);
+			segment = lst_removehead(&str_ctx->inter_pict_data.pic_prefix_seg);
+		}
+
+		segment = lst_removehead(&temp_list);
+		while (segment) {
+			lst_add(&preparsed_data->picture_data.pict_seg_list[0],
+				segment);
+			segment = lst_removehead(&temp_list);
+		}
+
+		for (i = 0; i < VDEC_H264_MVC_MAX_VIEWS; i++) {
+			unsigned int j;
+			struct bspp_picture_data *ext_pic_data =
+				&preparsed_data->ext_pictures_data[i];
+
+			if (preparsed_data->ext_pictures_data[i].is_prefix) {
+				for (j = 0; j < BSPP_MAX_PICTURES_PER_BUFFER;
+					j++) {
+					segment = lst_removehead(&ext_pic_data->pict_seg_list[j]);
+					while (segment) {
+						lst_add(&str_ctx->inter_pict_data.pic_prefix_seg,
+							segment);
+						segment = lst_removehead
+								(&ext_pic_data->pict_seg_list[j]);
+					}
+				}
+				preparsed_data->num_ext_pictures--;
+				break;
+			}
+		}
+	} else if (pict_ctx->present && pict_ctx->sequ_hdr_info) {
+		/*
+		 * Reduce the reference count since this picture will not be
+		 * decoded.
+		 */
+		pict_ctx->sequ_hdr_info->ref_count--;
+		/* Release sequence data. */
+		if (str_ctx->parser_callbacks.release_data_cb) {
+			str_ctx->parser_callbacks.release_data_cb((void *)&str_ctx->str_alloc,
+				BSPP_UNIT_SEQUENCE,
+				pict_ctx->sequ_hdr_info->secure_sequence_info);
+		}
+	}
+
+	/* Reset the group bitstream context */
+	lst_init(&str_ctx->grp_bstr_ctx.buffer_chain);
+	memset(&str_ctx->grp_bstr_ctx, 0, sizeof(str_ctx->grp_bstr_ctx));
+
+	/*
+	 * for now: return IMG_ERROR_NOT_SUPPORTED only if explicitly set by
+	 * parser
+	 */
+	result = (result == IMG_ERROR_NOT_SUPPORTED) ?
+		IMG_ERROR_NOT_SUPPORTED : IMG_SUCCESS;
+
+	if (end_of_pic)
+		parse_state->initialised = 0;
+
+	return result;
+
+error:
+	/* Free the SWSR list of buffers */
+	while (lst_first(&str_ctx->grp_bstr_ctx.in_flight_bufs))
+		lst_removehead(&str_ctx->grp_bstr_ctx.in_flight_bufs);
+
+	return result;
+}
+
+/*
+ * @Function	bspp_stream_destroy
+ *
+ */
+int bspp_stream_destroy(void *str_context_handle)
+{
+	struct bspp_str_context *str_ctx = (struct bspp_str_context *)str_context_handle;
+	unsigned int i;
+	unsigned int sps_id;
+	unsigned int pps_id;
+	struct bspp_sequence_hdr_info *sequ_hdr_info;
+	struct bspp_pps_info *pps_info;
+	unsigned int result;
+
+	/* Validate input arguments. */
+	if (!str_context_handle) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error;
+	}
+
+	swsr_deinitialise(str_ctx->swsr_ctx.swsr_context);
+
+	/*
+	 * Service all the picture decoded events and free any unused
+	 * resources.
+	 */
+	bspp_service_pictures_decoded(str_ctx);
+	for (sps_id = 0; sps_id < SEQUENCE_SLOTS; sps_id++)
+		bspp_remove_unused_sequence(str_ctx, sps_id);
+
+	if (str_ctx->vid_std_features.uses_pps) {
+		for (pps_id = 0; pps_id < PPS_SLOTS; pps_id++)
+			bspp_remove_unused_pps(str_ctx, pps_id);
+	}
+
+	if (str_ctx->vid_std_features.uses_vps) {
+		struct bspp_vps_info *vps_info;
+
+		for (i = 0; i < VPS_SLOTS; ++i) {
+			vps_info = lst_removehead(&str_ctx->str_alloc.vps_data_list[i]);
+
+			if (vps_info)
+				lst_add(&str_ctx->str_alloc.available_vps_list, vps_info);
+
+			/*
+			 * when we are done with the stream we should have MAXIMUM 1 VPS
+			 * per slot, so after removing this one we should have none
+			 * In case of "decodenframes" this is not true because we send more
+			 * pictures for decode than what we expect to receive back, which
+			 * means that potentially additional sequences/PPS are in the list
+			 */
+			vps_info = lst_removehead(&str_ctx->str_alloc.vps_data_list[i]);
+			if (vps_info) {
+				do {
+					lst_add(&str_ctx->str_alloc.available_vps_list, vps_info);
+					vps_info =
+					lst_removehead(&str_ctx->str_alloc.vps_data_list[i]);
+				} while (vps_info);
+			}
+			VDEC_ASSERT(lst_empty(&str_ctx->str_alloc.vps_data_list[i]));
+		}
+
+		vps_info = NULL;
+		for (i = 0; i < MAX_VPSS; ++i) {
+			VDEC_ASSERT(!lst_empty(&str_ctx->str_alloc.available_vps_list));
+			vps_info = lst_removehead(&str_ctx->str_alloc.available_vps_list);
+			if (vps_info) {
+				kfree(vps_info->secure_vpsinfo);
+				kfree(vps_info);
+			} else {
+				VDEC_ASSERT(vps_info);
+				pr_err("vps still active at shutdown\n");
+			}
+		}
+		VDEC_ASSERT(lst_empty(&str_ctx->str_alloc.available_vps_list));
+	}
+
+	/* Free the memory required for this stream. */
+	for (i = 0; i < SEQUENCE_SLOTS; i++) {
+		sequ_hdr_info = lst_removehead(&str_ctx->str_alloc.sequence_data_list[i]);
+		if (sequ_hdr_info) {
+			if (str_ctx->parser_callbacks.release_data_cb)
+				str_ctx->parser_callbacks.release_data_cb
+					((void *)&str_ctx->str_alloc,
+					BSPP_UNIT_SEQUENCE,
+					sequ_hdr_info->secure_sequence_info);
+			lst_add(&str_ctx->str_alloc.available_sequence_list,
+				sequ_hdr_info);
+		}
+
+		/*
+		 * when we are done with the stream we should have MAXIMUM 1
+		 * sequence per slot, so after removing this one we should have
+		 * none In case of "decoded frames" this is not true because we
+		 * send more pictures for decode than what we expect to receive
+		 * back, which means that potentially additional sequences/PPS
+		 * are in the list
+		 */
+		sequ_hdr_info = lst_removehead(&str_ctx->str_alloc.sequence_data_list[i]);
+		if (sequ_hdr_info) {
+			unsigned int count_extra_sequences = 0;
+
+			do {
+				count_extra_sequences++;
+				if (str_ctx->parser_callbacks.release_data_cb) {
+					str_ctx->parser_callbacks.release_data_cb
+						((void *)&str_ctx->str_alloc,
+						 BSPP_UNIT_SEQUENCE,
+						 sequ_hdr_info->secure_sequence_info);
+				}
+				lst_add(&str_ctx->str_alloc.available_sequence_list,
+					sequ_hdr_info);
+				sequ_hdr_info =
+					lst_removehead(&str_ctx->str_alloc.sequence_data_list[i]);
+			} while (sequ_hdr_info);
+		}
+	}
+
+	if (str_ctx->vid_std_features.uses_pps) {
+		for (i = 0; i < PPS_SLOTS; i++) {
+			pps_info = lst_removehead(&str_ctx->str_alloc.pps_data_list[i]);
+			if (pps_info)
+				lst_add(&str_ctx->str_alloc.available_ppss_list, pps_info);
+
+			/*
+			 * when we are done with the stream we should have
+			 * MAXIMUM 1 PPS per slot, so after removing this one
+			 * we should have none
+			 * In case of "decodedframes" this is not true because
+			 * we send more pictures for decode than what we expect
+			 * to receive back, which means that potentially
+			 * additional sequences/PPS are in the list
+			 */
+			pps_info = lst_removehead(&str_ctx->str_alloc.pps_data_list[i]);
+			if (pps_info) {
+				unsigned int count_extra_ppss = 0;
+
+				do {
+					count_extra_ppss++;
+					lst_add(&str_ctx->str_alloc.available_ppss_list,
+						pps_info);
+					pps_info =
+					lst_removehead(&str_ctx->str_alloc.pps_data_list[i]);
+				} while (pps_info);
+			}
+		}
+	}
+
+	for (i = 0; i < MAX_SEQUENCES; i++) {
+		sequ_hdr_info = lst_removehead(&str_ctx->str_alloc.available_sequence_list);
+		if (sequ_hdr_info && str_ctx->parser_callbacks.destroy_data_cb)
+			str_ctx->parser_callbacks.destroy_data_cb
+				(BSPP_UNIT_SEQUENCE, sequ_hdr_info->secure_sequence_info);
+	}
+
+	kfree(str_ctx->secure_sequence_info);
+	str_ctx->secure_sequence_info = NULL;
+	kfree(str_ctx->sequ_hdr_info);
+	str_ctx->sequ_hdr_info = NULL;
+
+	if (str_ctx->vid_std_features.uses_pps) {
+		for (i = 0; i < MAX_PPSS; i++) {
+			pps_info = lst_removehead(&str_ctx->str_alloc.available_ppss_list);
+			if (pps_info && str_ctx->parser_callbacks.destroy_data_cb)
+				str_ctx->parser_callbacks.destroy_data_cb
+							(BSPP_UNIT_PPS, pps_info->secure_pps_info);
+		}
+
+		kfree(str_ctx->secure_pps_info);
+		str_ctx->secure_pps_info = NULL;
+		kfree(str_ctx->pps_info);
+		str_ctx->pps_info = NULL;
+	}
+
+	/* destroy mutex */
+	mutex_destroy(str_ctx->bspp_mutex);
+	kfree(str_ctx->bspp_mutex);
+	str_ctx->bspp_mutex = NULL;
+
+	kfree(str_ctx);
+
+	return IMG_SUCCESS;
+error:
+	return result;
+}
+
+/*
+ * @Function	bspp_set_codec_config
+ *
+ */
+int bspp_set_codec_config(const void *str_context_handle,
+			  const struct vdec_codec_config *codec_config)
+{
+	struct bspp_str_context *str_ctx = (struct bspp_str_context *)str_context_handle;
+	unsigned int result = IMG_SUCCESS;
+
+	/* Validate input arguments. */
+	if (!str_context_handle || !codec_config) {
+		result = IMG_ERROR_INVALID_PARAMETERS;
+		goto error;
+	}
+
+	switch (str_ctx->vid_std) {
+	default:
+		result = IMG_ERROR_NOT_SUPPORTED;
+		break;
+	}
+error:
+	return result;
+}
+
+/*
+ * @Function	bspp_stream_create
+ *
+ */
+int bspp_stream_create(const struct vdec_str_configdata *str_config_data,
+		       void **str_ctx_handle,
+		       struct bspp_ddbuf_array_info fw_sequence[],
+		       struct bspp_ddbuf_array_info fw_pps[])
+{
+	struct bspp_str_context *str_ctx;
+	unsigned int result = IMG_SUCCESS;
+	unsigned int i;
+	struct bspp_sequence_hdr_info *sequ_hdr_info;
+	struct bspp_pps_info *pps_info;
+	struct bspp_parse_state *parse_state;
+
+	/* Allocate a stream structure */
+	str_ctx = kmalloc(sizeof(*str_ctx), GFP_KERNEL);
+	if (!str_ctx) {
+		result = IMG_ERROR_OUT_OF_MEMORY;
+		goto error;
+	}
+	memset(str_ctx, 0, sizeof(*str_ctx));
+
+	/* Initialise the stream context structure. */
+	str_ctx->sequ_hdr_id = BSPP_INVALID;
+	str_ctx->vid_std = str_config_data->vid_std;
+	str_ctx->bstr_format = str_config_data->bstr_format;
+	str_ctx->disable_mvc = str_config_data->disable_mvc;
+	str_ctx->full_scan = str_config_data->full_scan;
+	str_ctx->immediate_decode = str_config_data->immediate_decode;
+	str_ctx->intra_frame_closed_gop = str_config_data->intra_frame_closed_gop;
+
+	str_ctx->max_dec_frame_buffering = str_config_data->max_dec_frame_buffering;
+
+	parse_state = &str_ctx->parse_state;
+
+	/* Setup group buffer processing state. */
+	parse_state->inter_pict_ctx = &str_ctx->inter_pict_data;
+	parse_state->prev_bottom_pic_flag = (unsigned char)BSPP_INVALID;
+	parse_state->next_pic_is_new = 1;
+	parse_state->prev_frame_num = BSPP_INVALID;
+	parse_state->second_field_flag = 0;
+
+	lst_init(&str_ctx->grp_bstr_ctx.buffer_chain);
+
+	if (str_ctx->vid_std < VDEC_STD_MAX && parser_fxns[str_ctx->vid_std].set_parser_config) {
+		parser_fxns[str_ctx->vid_std].set_parser_config(str_ctx->bstr_format,
+			&str_ctx->vid_std_features,
+			&str_ctx->swsr_ctx,
+			&str_ctx->parser_callbacks,
+			&str_ctx->inter_pict_data);
+	} else {
+		result = IMG_ERROR_NOT_SUPPORTED;
+		goto error;
+	}
+
+	/* Allocate the memory required for this stream for Sequence/PPS info */
+	lst_init(&str_ctx->str_alloc.available_sequence_list);
+
+	str_ctx->sequ_hdr_info = kmalloc((MAX_SEQUENCES * sizeof(struct bspp_sequence_hdr_info)),
+					 GFP_KERNEL);
+	if (!str_ctx->sequ_hdr_info) {
+		result = IMG_ERROR_OUT_OF_MEMORY;
+		goto error;
+	}
+	memset(str_ctx->sequ_hdr_info, 0x00,
+	       (MAX_SEQUENCES * sizeof(struct bspp_sequence_hdr_info)));
+
+	str_ctx->secure_sequence_info =
+		kmalloc((MAX_SEQUENCES * str_ctx->vid_std_features.seq_size),
+			GFP_KERNEL);
+	if (!str_ctx->secure_sequence_info) {
+		result = IMG_ERROR_OUT_OF_MEMORY;
+		goto error;
+	}
+	memset(str_ctx->secure_sequence_info, 0x00,
+	       (MAX_SEQUENCES * str_ctx->vid_std_features.seq_size));
+
+	sequ_hdr_info = (struct bspp_sequence_hdr_info *)(str_ctx->sequ_hdr_info);
+	for (i = 0; i < MAX_SEQUENCES; i++) {
+		/* Deal with the device memory for FW SPS data */
+		sequ_hdr_info->fw_sequence = fw_sequence[i];
+		sequ_hdr_info->sequ_hdr_info.bufmap_id =
+			fw_sequence[i].ddbuf_info.bufmap_id;
+		sequ_hdr_info->sequ_hdr_info.buf_offset =
+			fw_sequence[i].buf_offset;
+		sequ_hdr_info->secure_sequence_info = (void *)(str_ctx->secure_sequence_info +
+			(i * str_ctx->vid_std_features.seq_size));
+
+		lst_add(&str_ctx->str_alloc.available_sequence_list,
+			sequ_hdr_info);
+		sequ_hdr_info++;
+	}
+
+	if (str_ctx->vid_std_features.uses_pps) {
+		lst_init(&str_ctx->str_alloc.available_ppss_list);
+		str_ctx->pps_info = kmalloc((MAX_PPSS * sizeof(struct bspp_pps_info)), GFP_KERNEL);
+		if (!str_ctx->pps_info) {
+			result = IMG_ERROR_OUT_OF_MEMORY;
+			goto error;
+		}
+		memset(str_ctx->pps_info, 0x00, (MAX_PPSS * sizeof(struct bspp_pps_info)));
+		str_ctx->secure_pps_info = kmalloc((MAX_PPSS * str_ctx->vid_std_features.pps_size),
+						   GFP_KERNEL);
+		if (!str_ctx->secure_pps_info) {
+			result = IMG_ERROR_OUT_OF_MEMORY;
+			goto error;
+		}
+		memset(str_ctx->secure_pps_info, 0x00,
+		       (MAX_PPSS * str_ctx->vid_std_features.pps_size));
+
+		pps_info = (struct bspp_pps_info *)(str_ctx->pps_info);
+		for (i = 0; i < MAX_PPSS; i++) {
+			/* Deal with the device memory for FW PPS data */
+			pps_info->fw_pps = fw_pps[i];
+			pps_info->bufmap_id = fw_pps[i].ddbuf_info.bufmap_id;
+			pps_info->buf_offset = fw_pps[i].buf_offset;
+
+			/*
+			 * We have no container for the PPS that passes down to the kernel,
+			 * for this reason the h264 secure parser needs to populate that
+			 * info into the picture header (Second)PictAuxData.
+			 */
+			pps_info->secure_pps_info = (void *)(str_ctx->secure_pps_info + (i *
+							str_ctx->vid_std_features.pps_size));
+
+			lst_add(&str_ctx->str_alloc.available_ppss_list, pps_info);
+			pps_info++;
+		}
+
+		/* As only standards that use PPS also use VUI, initialise
+		 * the appropriate data structures here.
+		 * Initialise the list of raw bitstream data containers.
+		 */
+		lst_init(&str_ctx->str_alloc.raw_data_list_available);
+		lst_init(&str_ctx->str_alloc.raw_data_list_used);
+	}
+
+	if (str_ctx->vid_std_features.uses_vps) {
+		struct bspp_vps_info *vps_info;
+
+		lst_init(&str_ctx->str_alloc.available_vps_list);
+		for (i = 0; i < MAX_VPSS; ++i) {
+			vps_info = kmalloc(sizeof(*vps_info), GFP_KERNEL);
+			VDEC_ASSERT(vps_info);
+			if (!vps_info) {
+				result = IMG_ERROR_OUT_OF_MEMORY;
+				goto error;
+			}
+
+			memset(vps_info, 0x00, sizeof(struct bspp_vps_info));
+			/*
+			 * for VPS we do not allocate device memory since (at least for now)
+			 * there is no need to pass any data from VPS directly to FW
+			 */
+			/* Allocate memory for BSPP local VPS data structure. */
+			vps_info->secure_vpsinfo =
+				kmalloc(str_ctx->vid_std_features.vps_size, GFP_KERNEL);
+
+			VDEC_ASSERT(vps_info->secure_vpsinfo);
+			if (!vps_info->secure_vpsinfo) {
+				result = IMG_ERROR_OUT_OF_MEMORY;
+				goto error;
+			}
+			memset(vps_info->secure_vpsinfo, 0, str_ctx->vid_std_features.vps_size);
+
+			lst_add(&str_ctx->str_alloc.available_vps_list, vps_info);
+		}
+	}
+
+	/* ... and initialise the lists that will use this data */
+	for (i = 0; i < SEQUENCE_SLOTS; i++)
+		lst_init(&str_ctx->str_alloc.sequence_data_list[i]);
+
+	if (str_ctx->vid_std_features.uses_pps)
+		for (i = 0; i < PPS_SLOTS; i++)
+			lst_init(&str_ctx->str_alloc.pps_data_list[i]);
+
+	str_ctx->bspp_mutex = kzalloc(sizeof(*str_ctx->bspp_mutex), GFP_KERNEL);
+	if (!str_ctx->bspp_mutex) {
+		result = -ENOMEM;
+		goto error;
+	}
+	mutex_init(str_ctx->bspp_mutex);
+
+	/* Initialise the software shift-register */
+	swsr_initialise(bspp_exception_handler, &str_ctx->parse_ctx,
+			(swsr_callback_fxn) bspp_shift_reg_cb,
+			&str_ctx->grp_bstr_ctx,
+			&str_ctx->swsr_ctx.swsr_context);
+
+	/* Setup the parse context */
+	str_ctx->parse_ctx.swsr_context = str_ctx->swsr_ctx.swsr_context;
+
+	*str_ctx_handle = str_ctx;
+
+	return IMG_SUCCESS;
+
+error:
+	if (str_ctx) {
+		kfree(str_ctx->sequ_hdr_info);
+		kfree(str_ctx->secure_sequence_info);
+		kfree(str_ctx->pps_info);
+		kfree(str_ctx->secure_pps_info);
+		kfree(str_ctx);
+	}
+
+	return result;
+}
+
+void bspp_freeraw_sei_datacontainer(const void *str_res,
+				    struct vdec_raw_bstr_data *rawsei_datacontainer)
+{
+	struct bspp_raw_sei_alloc *rawsei_alloc = NULL;
+
+	/* Check input params. */
+	if (str_res && rawsei_datacontainer) {
+		struct bspp_stream_alloc_data *alloc_data =
+			(struct bspp_stream_alloc_data *)str_res;
+
+		rawsei_alloc = container_of(rawsei_datacontainer,
+					    struct bspp_raw_sei_alloc,
+					    raw_sei_data);
+		memset(&rawsei_alloc->raw_sei_data, 0, sizeof(rawsei_alloc->raw_sei_data));
+		lst_remove(&alloc_data->raw_sei_alloc_list, rawsei_alloc);
+		kfree(rawsei_alloc);
+	}
+}
+
+void bspp_freeraw_sei_datalist(const void *str_res, struct vdec_raw_bstr_data *rawsei_datalist)
+{
+	/* Check input params. */
+	if (rawsei_datalist && str_res) {
+		struct vdec_raw_bstr_data *sei_raw_datacurr = NULL;
+
+		/* Start fromm the first element... */
+		sei_raw_datacurr = rawsei_datalist;
+		/* Free all the linked raw SEI data containers. */
+		while (sei_raw_datacurr) {
+			struct vdec_raw_bstr_data *seiraw_datanext =
+				sei_raw_datacurr->next;
+			bspp_freeraw_sei_datacontainer(str_res, sei_raw_datacurr);
+			sei_raw_datacurr = seiraw_datanext;
+		}
+	}
+}
+
+void bspp_streamrelese_rawbstrdataplain(const void *str_res, const void *rawdata)
+{
+	struct bspp_stream_alloc_data *str_alloc =
+		(struct bspp_stream_alloc_data *)str_res;
+	struct bspp_raw_bitstream_data *rawbstrdata =
+		(struct bspp_raw_bitstream_data *)rawdata;
+
+	if (rawbstrdata) {
+		/* Decrement the raw bitstream data reference count. */
+		rawbstrdata->ref_count--;
+		/* If no entity is referencing the raw
+		 * bitstream data any more
+		 */
+		if (rawbstrdata->ref_count == 0) {
+			/* ... free the raw bistream data buffer... */
+			kfree(rawbstrdata->raw_bitstream_data.data);
+			memset(&rawbstrdata->raw_bitstream_data, 0,
+			       sizeof(rawbstrdata->raw_bitstream_data));
+			/* ...and return it to the list. */
+			lst_remove(&str_alloc->raw_data_list_used, rawbstrdata);
+			lst_add(&str_alloc->raw_data_list_available, rawbstrdata);
+		}
+	}
+}
+
+struct bspp_vps_info *bspp_get_vpshdr(void *str_res, unsigned int vps_id)
+{
+	struct bspp_stream_alloc_data *alloc_data =
+		(struct bspp_stream_alloc_data *)str_res;
+
+	if (vps_id >= VPS_SLOTS || !alloc_data)
+		return NULL;
+
+	return lst_last(&alloc_data->vps_data_list[vps_id]);
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/bspp.h b/drivers/media/platform/img/vxe-vxd/decoder/bspp.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/bspp.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/bspp.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,363 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD Bitstream Buffer Pre-Parser
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ * Re-written for upstreming
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef __BSPP_H__
+#define __BSPP_H__
+
+#include <linux/types.h>
+
+#include "h264fw_data.h"
+#include "lst.h"
+#include "vdec_defs.h"
+
+/*
+ * There are up to 2 pictures in each buffer
+ * (plus trailing data for the next picture, e.g. PPS).
+ */
+#define BSPP_MAX_PICTURES_PER_BUFFER 3
+
+#define BSPP_INVALID ((unsigned int)(-1))
+
+/*
+ * This enables signalling of closed gop at every I frame. Add resilience to
+ * seeking functionality.
+ */
+#define I_FRAME_SIGNALS_CLOSED_GOP
+
+/*
+ * enum bspp_error_type - enumeration of parsing error , different error flag
+ *	for different data unit
+ */
+enum bspp_error_type {
+	/* No Error in parsing. */
+	BSPP_ERROR_NONE                      = (0),
+	/* Correction in VSH, Replaced VSH with faulty one */
+	BSPP_ERROR_CORRECTION_VSH            = (1 << 0),
+	/*
+	 * Correction in parsed Value, clamp the value if it goes beyond
+	 * the limit
+	 */
+	BSPP_ERROR_CORRECTION_VALIDVALUE     = (1 << 1),
+	/* Error in Aux data (i.e. PPS in H.264) parsing */
+	BSPP_ERROR_AUXDATA                   = (1 << 2),
+	/* Error in  parsing, more data remains in VSH data unit after parsing */
+	BSPP_ERROR_DATA_REMAINS              = (1 << 3),
+	/* Error in  parsing, parsed codeword is invalid */
+	BSPP_ERROR_INVALID_VALUE             = (1 << 4),
+	/* Error in  parsing, parsing error */
+	BSPP_ERROR_DECODE                    = (1 << 5),
+	/* reference frame is not available for decoding */
+	BSPP_ERROR_NO_REF_FRAME              = (1 << 6),
+	/* Non IDR frame loss detected */
+	BSPP_ERROR_NONIDR_FRAME_LOSS         = (1 << 7),
+	/* IDR frame loss detected */
+	BSPP_ERROR_IDR_FRAME_LOSS            = (1 << 8),
+	/* Error in  parsing, insufficient data to complete parsing */
+	BSPP_ERROR_INSUFFICIENT_DATA         = (1 << 9),
+	/* Severe Error, Error indicates, no support for this picture data */
+	BSPP_ERROR_UNSUPPORTED               = (1 << 10),
+	/* Severe Error, Error in which could not be recovered */
+	BSPP_ERROR_UNRECOVERABLE             = (1 << 11),
+	/* Severe Error, to indicate that NAL Header is absent after SCP */
+	BSPP_ERROR_NO_NALHEADER              = (1 << 12),
+	BSPP_ERROR_NO_SEQUENCE_HDR           = (1 << 13),
+	BSPP_ERROR_SIGNALED_IN_STREAM        = (1 << 14),
+	BSPP_ERROR_UNKNOWN_DATAUNIT_DETECTED = (1 << 15),
+	BSPP_ERROR_NO_PPS                    = (1 << 16),
+	BSPP_ERROR_NO_VPS                    = (1 << 17),
+	BSPP_ERROR_OUT_OF_MEMORY             = (1 << 18),
+	/* The shift value of the last error bit */
+	BSPP_ERROR_MAX_SHIFT                 = 18,
+	BSPP_ERROR_FORCE32BITS               = 0x7FFFFFFFU
+};
+
+/*
+ * struct bspp_ddbuf_info - Buffer info
+ * @buf_size: The size of the buffer (in bytes)
+ * @cpu_virt_addr: The CPU virtual address  (mapped into the local cpu MMU)
+ * @mem_attrib: Memory attributes
+ * @bufmap_id: buffer mappind id
+ */
+struct bspp_ddbuf_info {
+	unsigned int buf_size;
+	void *cpu_virt_addr;
+	enum sys_emem_attrib mem_attrib;
+	unsigned int buf_id;
+	unsigned int bufmap_id;
+};
+
+/*
+ * struct bspp_ddbuf_array_info - Buffer array info
+ * @ddbuf_info: Buffer info (container)
+ * @buf_element_size: Size of each element
+ * @buf_offset: Offset for each element
+ */
+struct bspp_ddbuf_array_info {
+	struct bspp_ddbuf_info ddbuf_info;
+	unsigned int buf_element_size;
+	unsigned int buf_offset;
+};
+
+/**
+ * struct bspp_bitstr_seg - Bitstream segment
+ * @lst_padding:
+ * @data_size: Size of data
+ * @data_byte_offset: Offset for data
+ * @bstr_seg_flag: flag indicates the bitstream segment type
+ * @start_code_suffix: start code prefix
+ * @bufmap_id: Buffer map ID
+ */
+struct bspp_bitstr_seg {
+	void *lst_padding;
+	unsigned int data_size;
+	unsigned int data_byte_offset;
+	unsigned int bstr_seg_flag;
+	unsigned char start_code_suffix;
+	unsigned int bufmap_id;
+};
+
+/*
+ * struct bspp_pict_data - Picture Header Data Information
+ * @bufmap_id: Buffer ID to use inside kernel #VXDIO_sDdBufInfo
+ * @buf_offset: Buffer offset (for packed device buffers, e.g. PPS)
+ * @pic_data: Picture data
+ * @size: Size (in bytes) of data.
+ * @data_id: Data identifier.
+ */
+struct bspp_pict_data {
+	unsigned int bufmap_id;
+	unsigned int buf_offset;
+	void *pic_data;
+	unsigned int size;
+	unsigned int id;
+};
+
+/*
+ * struct bspp_pict_hdr_info - Picture Header Information
+ */
+struct bspp_pict_hdr_info {
+	/*
+	 * Picture is entirely intra-coded and doesn't use any reference data.
+	 * NOTE: should be IMG_FALSE if this cannot be determined.
+	 */
+	int intra_coded;
+	/* Picture might be referenced by subsequent pictures. */
+	int ref;
+	/* Picture is a field as part of a frame. */
+	int field;
+	/* Emulation prevention bytes are present in picture data. */
+	int emulation_prevention;
+	/* Post Processing */
+	int post_processing;
+	/* Macroblocks within the picture may not occur in raster-scan order */
+	int discontinuous_mbs;
+	/* Flag to indicate data is span across mulitple buffer. */
+	int fragmented_data;
+	/* SOS fields count value */
+	unsigned char sos_count;
+	/* This picture is the first of the sequence or not */
+	int first_pic_of_sequence;
+
+	enum vdecfw_parsermode parser_mode;
+	/* Total size of picture data which is going to be submitted. */
+	unsigned int pic_data_size;
+	/* Size of coded frame as specified in the bitstream. */
+	struct vdec_pict_size coded_frame_size;
+	/* Display information for picture */
+	struct vdec_pict_disp_info disp_info;
+
+	/* Picture auxiliary data (e.g. H.264 SPS/PPS) */
+	struct bspp_pict_data pict_aux_data;
+	/* Picture auxiliary data (e.g. H.264 SPS/PPS) for 2nd picture */
+	struct bspp_pict_data second_pict_aux_data;
+	/* Slice group-map data. */
+	struct bspp_pict_data pict_sgm_data;
+#ifdef HAS_JPEG
+	/* JPEG specific picture header information.*/
+	struct vdec_jpeg_pict_hdr_info jpeg_pict_hdr_info;
+#endif
+
+	struct h264_pict_hdr_info {
+		void *raw_vui_data;
+		void *raw_sei_data_list_first_field;
+		void *raw_sei_data_list_second_field;
+		unsigned char nal_ref_idc;
+		unsigned short frame_num;
+	} h264_pict_hdr_info;
+
+	struct {        /* HEVC specific frame information.*/
+		int range_ext_present;
+		int is_full_range_ext;
+		void *raw_vui_data;
+		void *raw_sei_datalist_firstfield;
+		void *raw_sei_datalist_secondfield;
+	} hevc_pict_hdr_info;
+};
+
+/*
+ * struct bspp_sequ_hdr_info - Sequence header information
+ */
+struct bspp_sequ_hdr_info {
+	unsigned int sequ_hdr_id;
+	unsigned int ref_count;
+	struct vdec_comsequ_hdrinfo com_sequ_hdr_info;
+	unsigned int bufmap_id;
+	unsigned int buf_offset;
+};
+
+/*
+ * struct bspp_picture_data - Picture data
+ */
+struct bspp_picture_data {
+	/* Anonymous */
+	/*
+	 * Bitstream segments that contain other (non-picture) data before
+	 * the picture in the buffer (elements of type #VDECDD_sBitStrSeg).
+	 */
+	struct lst_t pre_pict_seg_list[BSPP_MAX_PICTURES_PER_BUFFER];
+	/* Picture */
+	unsigned int sequ_hdr_id;
+	struct bspp_pict_hdr_info pict_hdr_info;
+	/*
+	 * Bitstream segments that contain picture data, one for each field
+	 * (if present in same group of buffers (elements of type
+	 * #VDECDD_sBitStrSeg).
+	 */
+	struct lst_t pict_seg_list[BSPP_MAX_PICTURES_PER_BUFFER];
+	void *pict_tag_param[BSPP_MAX_PICTURES_PER_BUFFER];
+	int is_prefix;
+};
+
+/*
+ * struct bspp_preparsed_data - Pre-parsed buffer information
+ */
+struct bspp_preparsed_data {
+	/* Sequence */
+	int new_sequence;
+	struct bspp_sequ_hdr_info sequ_hdr_info;
+	int sequence_end;
+
+	/* Closed GOP */
+	int closed_gop;
+
+	/* Picture */
+	int new_picture;
+	int new_fragment;
+	struct bspp_picture_data picture_data;
+
+	/* Additional pictures (MVC extension) */
+	int new_sub_sequence;
+	struct bspp_sequ_hdr_info ext_sequ_hdr_info;
+	/* non-base view pictures + picture prefix for next frame */
+	struct bspp_picture_data ext_pictures_data[VDEC_H264_MVC_MAX_VIEWS];
+	unsigned int num_ext_pictures;
+
+	/*
+	 * Additional information
+	 * Flags word to indicate error in parsing/decoding - see
+	 * #VDEC_eErrorType
+	 */
+	unsigned int error_flags;
+};
+
+/*
+ * struct bspp_picture_decoded - used to store picture-decoded information for
+ * resource handling (sequences/PPSs)
+ */
+struct bspp_picture_decoded {
+	void **lst_link;
+	unsigned int sequ_hdr_id;
+	unsigned int pps_id;
+	unsigned int second_pps_id;
+	int not_decoded;
+	struct vdec_raw_bstr_data *sei_raw_data_first_field;
+	struct vdec_raw_bstr_data *sei_raw_data_second_field;
+};
+
+/*
+ * @Function	bspp_stream_create
+ * @Description	Creates a stream context for which to pre-parse bitstream
+ *		buffers. The following allocations will take place:
+ *		- Local storage for high-level header parameters (secure)
+ *		- Host memory for common sequence information (insecure)
+ *		- Device memory for Sequence information (secure)
+ *		- Device memory for PPS (secure, H.264 only)
+ * @Input	vdec_str_configdata : config data corresponding to bitstream
+ * @Output	str_context : A pointer used to return the stream context handle
+ * @Input	fw_sequ: FW sequence data
+ * @Input	fw_pps: FW pps data
+ * @Return	This function returns either IMG_SUCCESS or an error code.
+ */
+int bspp_stream_create(const struct vdec_str_configdata *str_config_data,
+		       void **str_context,
+		       struct bspp_ddbuf_array_info fw_sequ[],
+		       struct bspp_ddbuf_array_info fw_pps[]);
+
+/*
+ * @Function	bspp_set_codec_config
+ * @Description	This function is used to set the out-of-band codec config data.
+ * @Input	str_context_handle     : Stream context handle.
+ * @Input	codec_config   : Codec-config data
+ * @Return	This function returns either IMG_SUCCESS or an error code.
+ */
+int bspp_set_codec_config(const void *str_context_handle,
+			  const struct vdec_codec_config *codec_config);
+
+/*
+ * @Function	bspp_stream_destroy
+ * @Description	Destroys a stream context used to pre-parse bitstream buffers.
+ * @Input	str_context_handle  : Stream context handle.
+ * @Return	This function returns either IMG_SUCCESS or an error code.
+ */
+int bspp_stream_destroy(void *str_context_handle);
+
+/*
+ * @Function	bspp_submit_picture_decoded
+ */
+int bspp_submit_picture_decoded(void *str_context_handle,
+				struct bspp_picture_decoded *picture_decoded);
+
+/*
+ * @Function	bspp_stream_submit_buffer
+ */
+int bspp_stream_submit_buffer(void *str_context_handle,
+			      const struct bspp_ddbuf_info *ddbuf_info,
+			      unsigned int bufmap_id,
+			      unsigned int data_size,
+			      void *pict_tag_param,
+			      enum vdec_bstr_element_type bstr_element_type);
+
+/*
+ * @Function	bspp_stream_preparse_buffers
+ * @Description	Pre-parses bistream buffer and returns picture information in
+ *		structure that also signals when the buffer is last in picture.
+ * @Input	str_context_handle: Stream context handle.
+ * @Input	contiguous_buf_info : Contiguous buffer information
+ *		multiple segments that may be non contiguous in memory
+ * @Input	contiguous_buf_map_id : Contiguous Buffer Map id
+ * @Input	segments: Pointer to a list of segments (see #VDECDD_sBitStrSeg)
+ * @Output	preparsed_data: Container to return picture information. Only
+ *		provide when buffer is last in picture (see #bForceEop in
+ *		function #VDEC_StreamSubmitBstrBuf)
+ * @Output	eos_flag: flag indicates end of stream
+ * @Return	int : This function returns either IMG_SUCCESS or an error code.
+ */
+int bspp_stream_preparse_buffers
+	(void *str_context_handle,
+	const struct bspp_ddbuf_info *contiguous_buf_info,
+	unsigned int contiguous_buf_map_id,
+	struct lst_t *segments,
+	struct bspp_preparsed_data *preparsed_data,
+	int eos_flag);
+
+#endif /* __BSPP_H__   */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/bspp_int.h b/drivers/media/platform/img/vxe-vxd/decoder/bspp_int.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/bspp_int.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/bspp_int.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,520 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD Bitstream Buffer Pre-Parser Internal
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef __BSPP_INT_H__
+#define __BSPP_INT_H__
+
+#include "bspp.h"
+#include "swsr.h"
+
+#define VDEC_MB_DIMENSION  (16)
+#define MAX_COMPONENTS  (4)
+
+#define print_value(a, ...)
+
+#define BSPP_DEFAULT_SEQUENCE_ID   (0)
+
+enum bspp_unit_type {
+	BSPP_UNIT_NONE = 0,
+	/* Only relevant for HEVC. */
+	BSPP_UNIT_VPS,
+	/* Only relevant for h.264 and HEVC */
+	BSPP_UNIT_SEQUENCE, BSPP_UNIT_PPS,
+	/*
+	 * !< Data from these units should be placed in non-picture bitstream
+	 *  segment lists. In conformant streams these units should not occur
+	 *  in-between the picture data.
+	 */
+	BSPP_UNIT_PICTURE,
+	BSPP_UNIT_SKIP_PICTURE,
+	BSPP_UNIT_NON_PICTURE,
+	BSPP_UNIT_UNCLASSIFIED,
+	/* Unit is unsupported, don't change segment list */
+	BSPP_UNIT_UNSUPPORTED,
+	BSPP_UNIT_MAX,
+	BSPP_UNIT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+struct bspp_raw_bitstream_data {
+	void **lst_link;
+	unsigned int ref_count;
+	struct vdec_raw_bstr_data raw_bitstream_data;
+};
+
+/*
+ * struct bspp_h264_inter_pict_ctx
+ * @Brief: This structure contains H264 state to be retained between pictures.
+ */
+struct bspp_h264_inter_pict_ctx {
+	/*
+	 *  The following get applied to every picture until updated
+	 * (bitstream properties)
+	 */
+	int disable_vdmc_filt;
+	int b4x4transform_mb_unavailable;
+	/*
+	 *  The following get applied to the next picture only
+	 * (picture properties)
+	 */
+	int repeat_first_field;
+	unsigned int max_frm_repeat;
+	/*
+	 *  Control variable to decide when to attach the SEI info
+	 * (picture properties) to a picture
+	 */
+	int sei_info_attached_to_pic;
+	/*
+	 * The following variable is an approximation because we cannot
+	 * parse out-of-order, it takes value as described:
+	 *	 1) Initially it is BSPP_INVALID
+	 *	 2) The first SPS sets it to its SPSid
+	 *	 3) The last bspp_H264SeiBufferingPeriod sets it, and it is used
+	 * for every SEI parsing until updated by another
+	 * bspp_H264SeiBufferingPeriod message
+	 */
+	unsigned int active_sps_for_sei_parsing;
+	unsigned short current_view_id;
+	struct vdec_raw_bstr_data *sei_raw_data_list;
+};
+
+/* This structure contains HEVC state to be retained between pictures. */
+struct bspp_hevc_inter_pict_ctx {
+	/* Picture count in a sequence */
+	unsigned int seq_pic_count;
+	struct {
+		/* There was EOS NAL detected and no new picture yet */
+		unsigned eos_detected : 1;
+		/* This is first picture after EOS NAL */
+		unsigned first_after_eos : 1;
+	};
+
+	/* control variable to decide when to attach the SEI info
+	 * (picture properties) to a picture.
+	 */
+	unsigned char sei_info_attached_to_pic;
+	/* Raw SEI list to be attached to a picture. */
+	struct vdec_raw_bstr_data *sei_rawdata_list;
+	/* Handle to a picture header field to attach the raw SEI list to. */
+	void **hndl_pichdr_sei_rawdata_list;
+};
+
+/*
+ * struct bspp_inter_pict_data
+ * @Brief	This structure contains state to be retained between pictures.
+ */
+struct bspp_inter_pict_data {
+	/* A closed GOP has occurred in the bitstream. */
+	int seen_closed_gop;
+	/* Closed GOP has been signaled by a unit before the next picture */
+	int new_closed_gop;
+	/* Indicates whether or not DPB flush is needed */
+	int not_dpb_flush;
+	struct lst_t pic_prefix_seg;
+	union {
+		struct bspp_h264_inter_pict_ctx h264_ctx;
+		struct bspp_hevc_inter_pict_ctx hevc_ctx;
+	};
+};
+
+/*
+ * struct bspp_parse_state
+ * @Brief	This structure contains parse state
+ */
+struct bspp_parse_state {
+	struct bspp_inter_pict_data *inter_pict_ctx;
+	int initialised;
+
+	/* Input/Output (H264 etc. state). */
+	/* For SCP ASO detection we need to log 3 components */
+	unsigned int prev_first_mb_in_slice[MAX_COMPONENTS];
+	struct bspp_pict_hdr_info *next_pict_hdr_info;
+	unsigned char prev_bottom_pic_flag;
+	unsigned char second_field_flag;
+	unsigned char next_pic_is_new;
+	unsigned int prev_frame_num;
+	unsigned int prev_pps_id;
+	unsigned int prev_field_pic_flag;
+	unsigned int prev_nal_ref_idc;
+	unsigned int prev_pic_order_cnt_lsb;
+	int prev_delta_pic_order_cnt_bottom;
+	int prev_delta_pic_order_cnt[2];
+	int prev_nal_unit_type;
+	int prev_idr_pic_id;
+	int discontinuous_mb;
+	/* Position in bitstream before parsing a unit */
+	unsigned long long prev_byte_offset_buf;
+	unsigned int prev_buf_map_id;
+	unsigned int prev_buf_data_size;
+	/*
+	 * !< Flags word to indicate error in parsing/decoding
+	 * - see #VDEC_eErrorType.
+	 */
+	unsigned int error_flags;
+	/* Outputs. */
+	int new_closed_gop;
+	unsigned char new_view;
+	unsigned char is_prefix;
+	int first_chunk;
+};
+
+/*
+ * struct bspp_pps_info
+ * @Brief	Contains PPS information
+ */
+struct bspp_pps_info {
+	void **lst_link;
+	/* PPS Id. INSECURE MEMORY HOST */
+	unsigned int pps_id;
+	/* Reference count for PPS. INSECURE MEMORY HOST */
+	unsigned int ref_count;
+	struct bspp_ddbuf_array_info fw_pps;
+	/* Buffer ID to be used in Kernel */
+	unsigned int bufmap_id;
+	/* Parsing Info.    SECURE MEMORY HOST   */
+	void *secure_pps_info;
+	/* Buffer Offset to be used in kernel */
+	unsigned int buf_offset;
+};
+
+/*
+ * struct bspp_sequence_hdr_info
+ * @Brief	Contains SPS information
+ */
+struct bspp_sequence_hdr_info {
+	void **lst_link;
+	/* Reference count for sequence header */
+	unsigned int ref_count;
+	struct bspp_sequ_hdr_info sequ_hdr_info;
+	struct bspp_ddbuf_array_info fw_sequence;
+	/* Parsing Info.  SECURE MEMORY HOST */
+	void *secure_sequence_info;
+};
+
+enum bspp_element_status {
+	BSPP_UNALLOCATED = 0,
+	BSPP_AVAILABLE,
+	BSPP_UNAVAILABLE,
+	BSPP_STATUSMAX,
+	BSPP_FORCE32BITS = 0x7FFFFFFFU
+};
+
+struct bspp_vps_info {
+	void **lst_link;
+	/* VPS Id   INSECURE MEMORY HOST */
+	unsigned int vps_id;
+	/* Reference count for video header. INSECURE MEMORY HOST */
+	unsigned int ref_count;
+	/*!< Parsing Info. SECURE MEMORY HOST */
+	void *secure_vpsinfo;
+};
+
+/*
+ * struct bspp_unit_data
+ * @Brief	Contains bitstream unit data
+ */
+struct bspp_unit_data {
+	/* Input. */
+	/* Indicates which output data to populate */
+	enum bspp_unit_type unit_type;
+	/* Video Standard of unit to parse */
+	enum vdec_vid_std vid_std;
+	/* Indicates whether delimiter is present for unit */
+	int delim_present;
+	/* Codec configuration used by this stream */
+	const struct vdec_codec_config *codec_config;
+	void *str_res_handle;
+	/* Needed for calculating the size of the last fragment */
+	unsigned int unit_data_size;
+	/* Input/Output. */
+	struct bspp_parse_state *parse_state;
+	/* Output */
+	/* eVidStd == VDEC_STD_H263 && BSPP_UNIT_PICTURE. */
+	struct bspp_sequence_hdr_info *impl_sequ_hdr_info;
+	/* Union of output data for each of the unit types. */
+	union {
+		/* BSPP_UNIT_SEQUENCE. */
+		struct bspp_sequence_hdr_info *sequ_hdr_info;
+		/* BSPP_UNIT_PPS. */
+		struct bspp_pps_info *pps_info;
+		/* BSPP_UNIT_PICTURE. */
+		struct bspp_pict_hdr_info *pict_hdr_info;
+		/* For Video Header (HEVC) */
+		struct bspp_vps_info *vps_info;
+	} out;
+
+	/*
+	 * For picture it should give the SequenceHdrId, for anything
+	 * else it should contain BSPP_INVALID. This value is pre-loaded
+	 * with the sequence ID of the last picture.
+	 */
+	unsigned int pict_sequ_hdr_id;
+	/* State: output. */
+	/*
+	 * Picture unit (BSPP_UNIT_PICTURE) contains slice data.
+	 * Picture header information must be populated once this unit has been
+	 * parsed.
+	 */
+	int slice;
+	int ext_slice; /* Current slice belongs to non-base view (MVC only) */
+	/*
+	 * True if we meet a unit that signifies closed gop, different
+	 * for each standard.
+	 */
+	int new_closed_gop;
+	/* True if the end of a sequence of pictures has been reached. */
+	int sequence_end;
+	/*
+	 * Extracted all data from unit whereby shift-register should now
+	 * be at the next delimiter or end of data (when byte-aligned).
+	 */
+	int extracted_all_data;
+	/* Indicates the presence of any errors while processing this unit. */
+	enum bspp_error_type parse_error;
+	/* To turn on/off considering I-Frames as ClosedGop boundaries. */
+	int intra_frm_as_closed_gop;
+
+	/*
+	 * constrain the amount of DPB's allowed
+	 * a value of 0 means let the firmware decide
+	 */
+	unsigned int max_dec_frame_buffering;
+};
+
+/*
+ * struct bspp_swsr_ctx
+ * @brief	BSPP Software Shift Register Context Information
+ */
+struct bspp_swsr_ctx {
+	/*
+	 * Default configuration for the shift-register for this
+	 * stream. The delimiter type may be adjusted for each unit
+	 * where the buffer requires it. Information about how to
+	 * process each unit will be passed down with the picture
+	 * header information.
+	 */
+	struct swsr_config sr_config;
+	/*
+	 * Emulation prevention scheme present in bitstream. This is
+	 * sometimes not ascertained (e.g. VC-1) until the first
+	 * bitstream buffer (often codec configuration) has been
+	 * received.
+	 */
+	enum swsr_emprevent emulation_prevention;
+	/* Software shift-register context. */
+	void *swsr_context;
+};
+
+/*
+ * struct bspp_vid_std_features
+ * @brief  BSPP Video Standard Specific Features and Information
+ */
+struct bspp_vid_std_features {
+	/* The size of the sequence header structure for this video standard */
+	unsigned long seq_size;
+	/* This video standard uses Picture Parameter Sets. */
+	int uses_pps;
+	/*
+	 * The size of the Picture Parameter Sets structure for
+	 * this video standard.
+	 */
+	unsigned long pps_size;
+	/* This video standard uses Video Parameter Sets. */
+	int uses_vps;
+	/*
+	 * The size of the Video Parameter Sets structure for
+	 * this video standard
+	 */
+	unsigned long vps_size;
+};
+
+/*
+ * @Function	bspp_cb_parse_unit
+ * @Description	Function prototype for the parse unit callback functions.
+ * @Input	swsr_context_handle: A handle to software shift-register context
+ * @InOut	unit_data: A pointer to unit data which includes input & output
+ *		parameters as defined by structure.
+ * @Return	int : This function returns either IMG_SUCCESS or an error code.
+ */
+typedef int (*bspp_cb_parse_unit)(void *swsr_context_handle,
+				    struct bspp_unit_data *unit_data);
+
+/*
+ * @Function	bspp_pfnReleaseData
+ * @Description	This is a function prototype for the data releasing callback
+ *		functions.
+ * @Input	str_alloc_handle   : A handle to stream related resources.
+ * @Input	data_type   : A type of data which is to be released.
+ * @Input	data_handle : A handle for data which is to be released.
+ * @Return	int : This function returns either IMG_SUCCESS or an error code.
+ */
+typedef int (*bspp_cb_release_data)(void *str_alloc_handle,
+				      enum bspp_unit_type data_type,
+				      void *data_handle);
+
+/*
+ * @Function	bspp_cb_reset_data
+ * @Description	This is a function prototype for the data resetting callback
+ *		functions.
+ * @Input	data_type   : A type of data which is to be reset.
+ * @InOut	data_handle : A handle for data which is to be reset.
+ * @Return	int : This function returns either IMG_SUCCESS or an error code.
+ */
+typedef int (*bspp_cb_reset_data)(enum bspp_unit_type data_type,
+				    void *data_handle);
+
+/*
+ * @Function	bspp_cb_destroy_data
+ * @Description	This is a function prototype for the data destruction callback
+ *		functions.
+ * @Input	data_type   : A type of data which is to be destroyed.
+ * @InOut	data_handle : A handle for data which is to be destroyed.
+ * @Return	int : This function returns either IMG_SUCCESS or an error code.
+ */
+typedef int (*bspp_cb_destroy_data)(enum bspp_unit_type data_type,
+				      void *data_handle);
+
+/*
+ * @Function	bspp_cb_parse_codec_config
+ * @Description	This is a function prototype for parsing codec config bitstream
+ *		element for size delimited bitstreams.
+ * @Input	swsr_context_handle: A handle to Shift Register processing
+ *		current bitstream.
+ * @Output	unit_count: A pointer to variable in which to return unit count.
+ * @Output	unit_array_count: A pointer to variable in which to return unit
+ *		array count.
+ * @Output	delim_length: A pointer to variable in which to return NAL
+ *		delimiter length in bits.
+ * @Output	size_delim_length: A pointer to variable in which to return size
+ *		delimiter length in bits.
+ * @Return	None.
+ */
+typedef void (*bspp_cb_parse_codec_config)(void *swsr_context_handle,
+					   unsigned int *unit_count,
+					   unsigned int *unit_array_count,
+					   unsigned int *delim_length,
+					   unsigned int *size_delim_length);
+
+/*
+ * @Function	bspp_cb_update_unit_counts
+ * @Description	This is a function prototype for updating unit counts for size
+ *		delimited bitstreams.
+ * @Input	swsr_context_handle: A handle to Shift Register processing
+ *		current bitstream.
+ * @InOut	unit_count: A pointer to variable holding current unit count
+ * @InOut	unit_array_count: A pointer to variable holding current unit
+ *		array count.
+ * @Return	None.
+ */
+typedef void (*bspp_cb_update_unit_counts)(void *swsr_context_handle,
+					   unsigned int *unit_count,
+					   unsigned int *unit_array_count);
+
+/*
+ * @Function	bspp_cb_initialise_parsing
+ * @Description	This prototype is for unit group parsing initialization.
+ * @InOut	parse_state: The current unit group parsing state.
+ * @Return	None.
+ */
+typedef void (*bspp_cb_initialise_parsing)(struct bspp_parse_state *prs_state);
+
+/*
+ * @Function	bspp_cb_finalise_parsing
+ * @Description	This is prototype is for unit group parsing finalization.
+ * @Input	str_alloc_handle: A handle to stream related resources.
+ * @InOut	parse_state: The current unit group parsing state.
+ * @Return	None.
+ */
+typedef void (*bspp_cb_finalise_parsing)(void *str_alloc_handle,
+					 struct bspp_parse_state *parse_state);
+
+/*
+ * struct bspp_parser_callbacks
+ * @brief	BSPP Standard Related Parser Callback Functions
+ */
+struct bspp_parser_callbacks {
+	/* Pointer to standard-specific unit parsing callback function. */
+	bspp_cb_parse_unit parse_unit_cb;
+	/* Pointer to standard-specific data releasing callback function. */
+	bspp_cb_release_data release_data_cb;
+	/* Pointer to standard-specific data resetting callback function. */
+	bspp_cb_reset_data reset_data_cb;
+	/* Pointer to standard-specific data destruction callback function. */
+	bspp_cb_destroy_data destroy_data_cb;
+	/* Pointer to standard-specific codec config parsing callback function */
+	bspp_cb_parse_codec_config parse_codec_config_cb;
+	/* Pointer to standard-specific unit count updating callback function */
+	bspp_cb_update_unit_counts update_unit_counts_cb;
+	/*
+	 * Pointer to standard-specific unit group parsing initialization
+	 * function.
+	 */
+	bspp_cb_initialise_parsing initialise_parsing_cb;
+	/*
+	 * Pointer to standard-specific unit group parsing finalization
+	 * function
+	 */
+	bspp_cb_finalise_parsing finalise_parsing_cb;
+};
+
+/*
+ * @Function	bspp_cb_set_parser_config
+ * @Description	Prototype is for the setting parser config callback functions.
+ * @Input	bstr_format: Input bitstream format.
+ * @Output	vid_std_features: Features of video standard for this bitstream.
+ * @Output	swsr_ctx: Software Shift Register settings for this bitstream.
+ * @Output	parser_callbacks: Parser functions to be used for parsing this
+ *		bitstream.
+ * @Output	inter_pict_data: Inter-picture settings specific for this
+ *		bitstream.
+ * @Return	int : This function returns either IMG_SUCCESS or an error code.
+ */
+typedef int (*bspp_cb_set_parser_config)(enum vdec_bstr_format bstr_format,
+					   struct bspp_vid_std_features *vid_std_features,
+					   struct bspp_swsr_ctx *swsr_ctx,
+					   struct bspp_parser_callbacks *parser_callbacks,
+					   struct bspp_inter_pict_data *inter_pict_data);
+
+/*
+ * @Function	bspp_cb_determine_unit_type
+ * @Description	This is a function prototype for determining the BSPP unit type
+ *		based on the bitstream (video standard specific) unit type
+ *		callback functions.
+ * @Input	bitstream_unit_type: Bitstream (video standard specific) unit
+ *		type.
+ * @Input	disable_mvc: Skip MVC related units (relevant for standards
+ *		that support it).
+ * @InOut	bspp_unit_type *: Last BSPP unit type on input. Current BSPP
+ *		unit type on output.
+ * @Return	None.
+ */
+typedef void (*bspp_cb_determine_unit_type)(unsigned char bitstream_unit_type,
+					    int disable_mvc,
+					    enum bspp_unit_type *bspp_unit_type);
+
+struct bspp_pps_info *bspp_get_pps_hdr(void *str_res_handle, unsigned int pps_id);
+
+struct bspp_sequence_hdr_info *bspp_get_sequ_hdr(void *str_res_handle,
+						 unsigned int sequ_id);
+
+struct bspp_vps_info *bspp_get_vpshdr(void *str_res, unsigned int vps_id);
+
+void bspp_streamrelese_rawbstrdataplain(const void *str_res,
+					const void *rawdata);
+
+void bspp_freeraw_sei_datacontainer(const void *str_res,
+				    struct vdec_raw_bstr_data *rawsei_datacontainer);
+
+void bspp_freeraw_sei_datalist(const void *str_res,
+			       struct vdec_raw_bstr_data *rawsei_datalist);
+
+#endif /* __BSPP_INT_H__   */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/core.c b/drivers/media/platform/img/vxe-vxd/decoder/core.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/core.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/core.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,3723 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VXD Decoder Core component function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include "core.h"
+#include "decoder.h"
+#include "img_errors.h"
+#include "img_pixfmts.h"
+#include "img_profiles_levels.h"
+#include "lst.h"
+#include "resource.h"
+#include "rman_api.h"
+#include "vdecdd_utils.h"
+#include "vdec_mmu_wrapper.h"
+#include "vxd_dec.h"
+
+#ifdef HAS_HEVC
+#define SEQ_RES_NEEDED
+#define GENC_BUFF_COUNT 4
+#endif
+
+/*
+ * This enum defines resource availability masks.
+ * @brief  Resource Availability
+ */
+enum core_availability {
+	CORE_AVAIL_PICTBUF      = (1 << 0),
+	CORE_AVAIL_PICTRES      = (1 << 1),
+	CORE_AVAIL_CORE         = (1 << 2),
+	CORE_AVAIL_MAX,
+	CORE_AVAIL_FORCE32BITS = 0x7FFFFFFFU
+};
+
+struct core_mbparam_alloc_info {
+	unsigned char alloc_mbparam_bufs;
+	unsigned int mbparam_size;
+	unsigned int overalloc_mbnum;
+};
+
+static struct core_mbparam_alloc_info mbparam_allocinfo[VDEC_STD_MAX - 1] = {
+	/*                AllocFlag    MBParamSize    Overalloc     */
+	/* MPEG2    */ { TRUE,    0xc8,          0             },
+	/* MPEG4    */ { TRUE,    0xc8,          0             },
+	/* H263     */ { TRUE,    0xc8,          0             },
+	/* H264     */ { TRUE,    0x80,          0             },
+	/* VC1      */ { TRUE,    0x80,          (4096 * 2) / 0x80 },
+	/* AVS      */ { TRUE,    0x80,          0             },
+	/* REAL     */ { TRUE,    0x80,          0             },
+	/* JPEG     */ { FALSE,   0x00,          0             },
+	/* VP6      */ { TRUE,    0x80,          0             },
+	/* VP8      */ { TRUE,    0x80,          0             },
+	/* SORENSON */ { TRUE,    0xc8,          0             },
+	/* HEVC     */ { TRUE,    0x40,          0             },
+};
+
+struct vxdio_mempool {
+	unsigned int mem_heap_id;
+	enum sys_emem_attrib mem_attrib;
+};
+
+static unsigned int global_avail_slots;
+static unsigned char is_core_initialized;
+
+/*
+ * This structure contains the core Context.
+ * @brief  core Context
+ */
+struct core_context {
+	struct vdecdd_dddev_context     *dev_ctx;
+	/* List of stream context structures */
+	struct lst_t core_str_ctx;
+	vxd_cb vxd_str_processed_cb;
+};
+
+/* Global Core Context */
+static struct core_context *global_core_ctx;
+
+/*
+ * This structure contains the picture buffer size info.
+ * @brief  Picture Resource Info
+ */
+struct core_pict_bufsize_info {
+	unsigned int mbparams_bufsize;
+
+#ifdef HAS_HEVC
+	union {
+		struct hevc_bufsize_pict {
+			/* Size of GENC fragment buffer for HEVC */
+			unsigned int genc_fragment_bufsize;
+		} hevc_bufsize_pict;
+	};
+#endif
+};
+
+/*
+ * This structure contains the sequence resource info.
+ * @brief  Sequence Resource Info
+ */
+struct core_seq_resinfo {
+	union {
+#ifdef HAS_HEVC
+		struct hevc_bufsize_seqres {
+			unsigned int genc_bufsize; /* Size of GEN buffers for HEVC */
+			unsigned int intra_bufsize; /* Size of GEN buffers for HEVC */
+			unsigned int aux_bufsize;   /* Size of GEN buffers for HEVC */
+		} hevc_bufsize_seqres;
+#endif
+
+#ifndef SEQ_RES_NEEDED
+		unsigned int dummy;
+#endif
+	};
+};
+
+struct core_pict_resinfo {
+	unsigned int pict_res_num;
+	struct core_pict_bufsize_info size_info;
+	unsigned char is_valid;
+};
+
+/*
+ * This structure contains the standard specific part of plant context.
+ * @brief  Standard Specific Context
+ */
+struct core_std_spec_context {
+	union {
+#ifdef HAS_HEVC
+		struct hevc_ctx {
+			/* Counts genc buffer allocations  */
+			unsigned short genc_id_gen;
+		} hevc_ctx;
+#else
+		unsigned int dummy;
+#endif
+	};
+};
+
+struct core_stream_context;
+
+struct core_std_spec_operations {
+	/* Allocates standard specific picture buffers.  */
+	int (*alloc_picture_buffers)(struct core_stream_context *core_strctx,
+				     struct vdecdd_pict_resint *pict_resint,
+				     struct vxdio_mempool mem_pool,
+				     struct core_pict_resinfo *pict_res_info);
+
+	/* Frees standard specific picture buffers.  */
+	int (*free_picture_resource)(struct core_stream_context *core_strctx,
+				     struct vdecdd_pict_resint *pic_res_int);
+
+	/* Allocates standard specific sequence buffers.  */
+	int (*alloc_sequence_buffers)(struct core_stream_context *core_strctx,
+				      struct vdecdd_seq_resint *seq_res_int,
+				      struct vxdio_mempool mem_pool,
+				      struct core_seq_resinfo *seq_res_info);
+
+	/* Frees standard specific sequence buffers.  */
+	int (*free_sequence_resource)(struct core_stream_context *core_strctx,
+				      struct vdecdd_seq_resint *seq_res_int);
+
+	/* Returns buffer's sizes (common and standard specific).  */
+	int (*bufs_get_size)(struct core_stream_context *core_strctx,
+			     const struct vdec_comsequ_hdrinfo *seq_hdrinfo,
+			     struct vdec_pict_size *max_pict_size,
+			     struct core_pict_bufsize_info *size_info,
+			     struct core_seq_resinfo *seq_resinfo,
+			     unsigned char *resource_needed);
+
+	/* Checks whether resource is still suitable.  */
+	unsigned char (*is_stream_resource_suitable)(struct core_pict_resinfo *pict_resinfo,
+						     struct core_pict_resinfo *old_pict_resinfo,
+						     struct core_seq_resinfo *seq_resinfo,
+						     struct core_seq_resinfo *old_seq_resinfo);
+};
+
+/*
+ * This structure contains the core Stream Context.
+ * @brief  core Stream Context
+ */
+struct core_stream_context {
+	void    **link; /* to be part of single linked list */
+	struct core_context     *core_ctx;
+	struct vdecdd_ddstr_ctx *dd_str_ctx;
+	struct vxd_dec_ctx      *vxd_dec_context;
+
+	/* list of picture buffers */
+	struct lst_t pict_buf_list;
+
+	/* List of picture resources allocated for this stream */
+	struct lst_t pict_res_list;
+	struct lst_t old_pict_res_list;
+
+	struct lst_t aux_pict_res_list;
+
+#ifdef SEQ_RES_NEEDED
+	/* List of active sequence resources that are allocated for this stream. */
+	struct lst_t seq_res_list;
+	/*
+	 * List of sequence resources that are allocated for this stream but no
+	 * longer suitable for new sequence(s).
+	 */
+	struct lst_t old_seq_res_list;
+#endif
+
+	/* List of sequence header information */
+	struct lst_t seq_hdr_list;
+	/* Queue of stream units to be processed */
+	struct lst_t str_unit_list;
+
+	struct vdec_comsequ_hdrinfo comseq_hdr_info;
+	unsigned char opcfg_set;
+	/* Picture buffer layout to use for decoding. */
+	struct vdecdd_ddpict_buf disp_pict_buf;
+	struct vdec_str_opconfig op_cfg;
+	unsigned char new_seq;
+	unsigned char new_op_cfg;
+	unsigned char no_prev_refs_used;
+	unsigned int avail_slots;
+	unsigned int res_avail;
+	unsigned char stopped;
+	struct core_pict_resinfo pict_resinfo;
+	/* Current sequence resource info. */
+	struct core_seq_resinfo seq_resinfo;
+
+	/* Reconstructed picture buffer */
+	struct vdecdd_ddpict_buf recon_pictbuf;
+	/* Coded picture size of last reconfiguration */
+	struct vdec_pict_size coded_pict_size;
+	/* Standard specific operations. */
+	struct core_std_spec_operations *std_spec_ops;
+	/* Standard specific context. */
+	struct core_std_spec_context std_spec_context;
+};
+
+#ifdef HAS_HEVC
+static int core_free_hevc_picture_resource(struct core_stream_context *core_strctx,
+					   struct vdecdd_pict_resint *pic_res_int);
+
+static int core_free_hevc_sequence_resource(struct core_stream_context *core_strctx,
+					    struct vdecdd_seq_resint *seq_res_int);
+
+static int core_hevc_bufs_get_size(struct core_stream_context *core_str_ctx,
+				   const struct vdec_comsequ_hdrinfo *seq_hdr_info,
+				   struct vdec_pict_size *max_pict_size,
+				   struct core_pict_bufsize_info *size_info,
+				   struct core_seq_resinfo *seq_res_info,
+				   unsigned char *resource_needed);
+
+static unsigned char core_is_hevc_stream_resource_suitable
+			(struct core_pict_resinfo *pict_res_info,
+			 struct core_pict_resinfo *old_pict_res_info,
+			 struct core_seq_resinfo *seq_res_info,
+			 struct core_seq_resinfo *old_seq_res_info);
+
+static int core_alloc_hevc_specific_seq_buffers(struct core_stream_context *core_strctx,
+						struct vdecdd_seq_resint *seq_res_int,
+						struct vxdio_mempool mempool,
+						struct core_seq_resinfo *seq_res_info);
+
+static int core_alloc_hevc_specific_pict_buffers(struct core_stream_context *core_strctx,
+						 struct vdecdd_pict_resint *pict_res_int,
+						 struct vxdio_mempool mempool,
+						 struct core_pict_resinfo *pict_res_info);
+#endif
+
+static int
+core_common_bufs_getsize(struct core_stream_context *core_str_ctx,
+			 const struct vdec_comsequ_hdrinfo *comseq_hdrinfo,
+			 struct vdec_pict_size *max_pict_size,
+			 struct core_pict_bufsize_info     *size_info,
+			 struct core_seq_resinfo  *seq_res_info, unsigned char *res_needed);
+
+static struct core_std_spec_operations std_specific_ops[VDEC_STD_MAX - 1] = {
+	/* AllocPicture  FreePicture  AllocSeq   FreeSeq   BufsGetSize  IsStreamResourceSuitable */
+	/* MPEG2   */ { .alloc_picture_buffers = NULL,
+		.free_picture_resource = NULL,
+		.alloc_sequence_buffers = NULL,
+		.free_sequence_resource = NULL,
+		.bufs_get_size = NULL,
+		.is_stream_resource_suitable = NULL},
+
+	/* MPEG4   */ { .alloc_picture_buffers = NULL,
+		.free_picture_resource = NULL,
+		.alloc_sequence_buffers = NULL,
+		.free_sequence_resource = NULL,
+		.bufs_get_size = NULL,
+		.is_stream_resource_suitable = NULL},
+
+	/* H263   */ { .alloc_picture_buffers = NULL,
+		.free_picture_resource = NULL,
+		.alloc_sequence_buffers = NULL,
+		.free_sequence_resource = NULL,
+		.bufs_get_size = NULL,
+		.is_stream_resource_suitable = NULL},
+
+	/* H264   */ { .alloc_picture_buffers = NULL,
+		.free_picture_resource = NULL,
+		.alloc_sequence_buffers = NULL,
+		.free_sequence_resource = NULL,
+		.bufs_get_size = core_common_bufs_getsize,
+		.is_stream_resource_suitable = NULL},
+
+	/* VC1   */ { .alloc_picture_buffers = NULL,
+		.free_picture_resource = NULL,
+		.alloc_sequence_buffers = NULL,
+		.free_sequence_resource = NULL,
+		.bufs_get_size = NULL,
+		.is_stream_resource_suitable = NULL},
+
+	/* AVS   */ { .alloc_picture_buffers = NULL,
+		.free_picture_resource = NULL,
+		.alloc_sequence_buffers = NULL,
+		.free_sequence_resource = NULL,
+		.bufs_get_size = NULL,
+		.is_stream_resource_suitable = NULL},
+
+	/* REAL   */ { .alloc_picture_buffers = NULL,
+		.free_picture_resource = NULL,
+		.alloc_sequence_buffers = NULL,
+		.free_sequence_resource = NULL,
+		.bufs_get_size = NULL,
+		.is_stream_resource_suitable = NULL},
+
+	/* JPEG   */ { .alloc_picture_buffers = NULL,
+		.free_picture_resource = NULL,
+		.alloc_sequence_buffers = NULL,
+		.free_sequence_resource = NULL,
+		.bufs_get_size = NULL,
+		.is_stream_resource_suitable = NULL},
+
+	/* VP6   */ { .alloc_picture_buffers = NULL,
+		.free_picture_resource = NULL,
+		.alloc_sequence_buffers = NULL,
+		.free_sequence_resource = NULL,
+		.bufs_get_size = NULL,
+		.is_stream_resource_suitable = NULL},
+
+	/* VP8   */ { .alloc_picture_buffers = NULL,
+		.free_picture_resource = NULL,
+		.alloc_sequence_buffers = NULL,
+		.free_sequence_resource = NULL,
+		.bufs_get_size = NULL,
+		.is_stream_resource_suitable = NULL},
+
+	/* SORENSON */ { .alloc_picture_buffers = NULL,
+		.free_picture_resource = NULL,
+		.alloc_sequence_buffers = NULL,
+		.free_sequence_resource = NULL,
+		.bufs_get_size = NULL,
+		.is_stream_resource_suitable = NULL},
+
+#ifdef HAS_HEVC
+	/* HEVC*/ { .alloc_picture_buffers = core_alloc_hevc_specific_pict_buffers,
+		.free_picture_resource = core_free_hevc_picture_resource,
+		.alloc_sequence_buffers = core_alloc_hevc_specific_seq_buffers,
+		.free_sequence_resource = core_free_hevc_sequence_resource,
+		.bufs_get_size = core_hevc_bufs_get_size,
+		.is_stream_resource_suitable = core_is_hevc_stream_resource_suitable},
+#else
+	/* HEVC */ { .alloc_picture_buffers = NULL,
+		.free_picture_resource = NULL,
+		.alloc_sequence_buffers = NULL,
+		.free_sequence_resource = NULL,
+		.bufs_get_size = NULL,
+		.is_stream_resource_suitable = NULL},
+#endif
+};
+
+#ifdef ERROR_CONCEALMENT
+/*
+ * This structure contains the Error Recovery Frame Store info.
+ * @brief  Error Recovery Frame Store Info
+ */
+struct core_err_recovery_frame_info {
+	/* Flag to indicate if Error Recovery Frame Store is enabled for standard. */
+	unsigned char enabled;
+	/* Limitation for maximum frame size based on dimensions. */
+	unsigned int max_size;
+};
+
+static struct core_err_recovery_frame_info err_recovery_frame_info[VDEC_STD_MAX - 1] = {
+	/*               enabled  max_frame_size  */
+	/* MPEG2    */ { TRUE,     ~0         },
+	/* MPEG4    */ { TRUE,     ~0         },
+	/* H263     */ { FALSE,     0         },
+	/* H264     */ { TRUE,     ~0         },
+	/* VC1      */ { FALSE,     0         },
+	/* AVS      */ { FALSE,     0         },
+	/* REAL     */ { FALSE,     0         },
+	/* JPEG     */ { FALSE,     0         },
+	/* VP6      */ { FALSE,     0         },
+	/* VP8      */ { FALSE,     0         },
+	/* SORENSON */ { FALSE,     0         },
+	/* HEVC     */ { TRUE,     ~0         },
+};
+#endif
+
+static void core_fw_response_cb(int res_str_id, unsigned int *msg, unsigned int msg_size,
+				unsigned int msg_flags)
+{
+	struct core_stream_context *core_str_ctx;
+	int ret;
+
+	/* extract core_str_ctx and dec_core_ctx from res_str_id */
+	VDEC_ASSERT(res_str_id);
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(res_str_id, VDECDD_STREAM_TYPE_ID, (void **)&core_str_ctx, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		pr_err("could not extract core_str_context\n");
+
+	ret = decoder_service_firmware_response(core_str_ctx->dd_str_ctx->dec_ctx,
+						msg, msg_size, msg_flags);
+	VDEC_ASSERT((ret == IMG_SUCCESS) | (ret == IMG_ERROR_FATAL));
+	if (ret != IMG_SUCCESS)
+		pr_err("decoder_service_firmware_response failed\n");
+}
+
+/*
+ * @Function core_initialise
+ */
+int core_initialise(void *dev_handle, unsigned int int_heap_id, void *vxd_cb_ptr)
+{
+	struct vdecdd_dd_devconfig dev_cfg_local;
+	unsigned int num_pipes_local;
+	int ret;
+
+	if (is_core_initialized)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	is_core_initialized = TRUE;
+
+	global_core_ctx = kzalloc(sizeof(*global_core_ctx), GFP_KERNEL);
+	if (!global_core_ctx) {
+		is_core_initialized = FALSE;
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	global_core_ctx->dev_ctx = kzalloc(sizeof(*global_core_ctx->dev_ctx), GFP_KERNEL);
+	if (!global_core_ctx->dev_ctx) {
+		kfree(global_core_ctx);
+		global_core_ctx = NULL;
+		is_core_initialized = FALSE;
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* Initialise device context. */
+	global_core_ctx->dev_ctx->dev_handle = dev_handle; /* v4L2 dev handle */
+	global_core_ctx->vxd_str_processed_cb = (vxd_cb)vxd_cb_ptr;
+
+	ret = decoder_initialise(global_core_ctx->dev_ctx, int_heap_id,
+				 &dev_cfg_local, &num_pipes_local,
+				 &global_core_ctx->dev_ctx->dec_context);
+	if (ret != IMG_SUCCESS)
+		goto decoder_init_error;
+
+	global_core_ctx->dev_ctx->internal_heap_id = int_heap_id;
+
+#ifdef DEBUG_DECODER_DRIVER
+	/* Dump codec config */
+	pr_info("Decode slots/core:  %d", dev_cfg_local.num_slots_per_pipe);
+#endif
+
+	lst_init(&global_core_ctx->core_str_ctx);
+
+	/* Ensure the resource manager is initialised.. */
+	ret = rman_initialise();
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto rman_init_error;
+
+	/* Create resource bucket.. */
+	ret = rman_create_bucket(&global_core_ctx->dev_ctx->res_buck_handle);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto create_bucket_error;
+
+	return IMG_SUCCESS;
+
+create_bucket_error:
+	rman_deinitialise();
+
+rman_init_error:
+	decoder_deinitialise(global_core_ctx->dev_ctx->dec_context);
+
+decoder_init_error:
+	kfree(global_core_ctx->dev_ctx);
+	global_core_ctx->dev_ctx = NULL;
+	kfree(global_core_ctx);
+	global_core_ctx = NULL;
+
+	is_core_initialized = FALSE;
+
+	return ret;
+}
+
+/*
+ * @Function    core_check_decoder_support
+ * @Description
+ * This function determines whether Decoder supports bitstream and
+ * configuration.
+ */
+static int
+core_check_decoder_support(const struct vdecdd_dddev_context *dd_dev_ctx,
+			   const struct vdec_str_configdata  *str_cfg_data,
+			   const struct vdec_comsequ_hdrinfo *prev_seq_hdrinfo,
+			   const struct bspp_pict_hdr_info *prev_pict_hdrinfo,
+			   const struct vdecdd_mapbuf_info *map_bufinfo,
+			   struct vdecdd_supp_check *supp_check)
+{
+	int ret;
+	struct vdec_unsupp_flags unsupported;
+	struct vdec_pict_rendinfo disp_pict_rend_info;
+
+	memset(&disp_pict_rend_info, 0, sizeof(struct vdec_pict_rendinfo));
+
+	/*
+	 * If output picture buffer information is provided create another
+	 * with properties required by bitstream so that it can be compared.
+	 */
+	if (supp_check->disp_pictbuf) {
+		struct vdec_pict_rend_config pict_rend_cfg;
+
+		memset(&pict_rend_cfg, 0, sizeof(pict_rend_cfg));
+
+		/*
+		 * Cannot validate the display picture buffer layout without
+		 * knowing the pixel format required for the output and the
+		 * sequence information.
+		 */
+		if (supp_check->comseq_hdrinfo && supp_check->op_cfg) {
+			pict_rend_cfg.coded_pict_size =
+				supp_check->comseq_hdrinfo->max_frame_size;
+
+			pict_rend_cfg.byte_interleave =
+					supp_check->disp_pictbuf->buf_config.byte_interleave;
+
+			pict_rend_cfg.packed =
+					supp_check->disp_pictbuf->buf_config.packed;
+
+			pict_rend_cfg.stride_alignment =
+					supp_check->disp_pictbuf->buf_config.stride_alignment;
+
+			/*
+			 * Recalculate render picture layout based upon
+			 * sequence and output config.
+			 */
+			vdecddutils_pictbuf_getinfo(str_cfg_data,
+						    &pict_rend_cfg,
+						    supp_check->op_cfg,
+						    &disp_pict_rend_info);
+		}
+	}
+	/* Check that the decoder supports the picture. */
+	ret = decoder_check_support(dd_dev_ctx->dec_context, str_cfg_data,
+				    supp_check->op_cfg,
+				    supp_check->disp_pictbuf,
+				    (disp_pict_rend_info.rendered_size) ?
+				    &disp_pict_rend_info : NULL,
+				    supp_check->comseq_hdrinfo,
+				    supp_check->pict_hdrinfo,
+				    prev_seq_hdrinfo,
+				    prev_pict_hdrinfo,
+				    supp_check->non_cfg_req,
+				    &unsupported,
+				    &supp_check->features);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS) {
+		if (ret == IMG_ERROR_NOT_SUPPORTED)
+			supp_check->unsupp_flags = unsupported;
+	}
+
+	return ret;
+}
+
+/*
+ * @Function  core_supported_features
+ */
+int core_supported_features(struct vdec_features *features)
+{
+	struct vdecdd_dddev_context *dd_dev_ctx;
+
+	VDEC_ASSERT(global_core_ctx);
+
+	dd_dev_ctx = global_core_ctx->dev_ctx;
+	VDEC_ASSERT(dd_dev_ctx);
+	if (!dd_dev_ctx)
+		return IMG_ERROR_NOT_INITIALISED;
+
+	return decoder_supported_features(dd_dev_ctx->dec_context, features);
+}
+
+/*
+ * @Function core_stream_stop
+ */
+int core_stream_stop(unsigned int res_str_id)
+{
+	int ret = IMG_SUCCESS;
+	struct vdecdd_str_unit *stop_unit;
+	struct vdecdd_ddstr_ctx *ddstr_ctx;
+	struct core_stream_context *core_str_ctx;
+
+	/*
+	 * Stream based messages without a device context
+	 * must have a stream ID.
+	 */
+	VDEC_ASSERT(res_str_id);
+
+	if (res_str_id == 0) {
+		pr_err("Invalid params passed to %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(res_str_id, VDECDD_STREAM_TYPE_ID,
+				(void **)&core_str_ctx, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	VDEC_ASSERT(core_str_ctx);
+
+	ddstr_ctx = core_str_ctx->dd_str_ctx;
+
+	/* Validate input arguments */
+	VDEC_ASSERT(ddstr_ctx);
+
+	/*
+	 * Disregard this stop request if the stream is currently
+	 * stopped or being stopped.
+	 */
+	if (ddstr_ctx->dd_str_state == VDECDD_STRSTATE_PLAYING) {
+		vdecddutils_create_strunit(&stop_unit, NULL);
+		if (!stop_unit) {
+			pr_err("Failed to allocate memory for stop unit\n");
+			return IMG_ERROR_OUT_OF_MEMORY;
+		}
+		memset(stop_unit, 0, sizeof(*stop_unit));
+
+		stop_unit->str_unit_type = VDECDD_STRUNIT_STOP;
+		stop_unit->str_unit_tag = NULL;
+		stop_unit->decode = FALSE;
+
+		/*
+		 * Since the stop is now to be passed to the decoder signal
+		 * that we're stopping.
+		 */
+		ddstr_ctx->dd_str_state = VDECDD_STRSTATE_STOPPING;
+		decoder_stream_process_unit(ddstr_ctx->dec_ctx, stop_unit);
+		core_str_ctx->stopped = TRUE;
+		vdecddutils_free_strunit(stop_unit);
+	}
+
+	return ret;
+}
+
+/*
+ * @Function              core_is_stream_idle
+ */
+static unsigned char core_is_stream_idle(struct vdecdd_ddstr_ctx *dd_str_ctx)
+{
+	unsigned char is_stream_idle;
+
+	is_stream_idle = decoder_is_stream_idle(dd_str_ctx->dec_ctx);
+
+	return is_stream_idle;
+}
+
+/*
+ * @Function              core_stream_destroy
+ */
+int core_stream_destroy(unsigned int res_str_id)
+{
+	struct vdecdd_ddstr_ctx *ddstr_ctx;
+	struct core_stream_context *core_str_ctx;
+	int ret;
+
+	/*
+	 * Stream based messages without a device context
+	 * must have a stream ID.
+	 */
+	VDEC_ASSERT(res_str_id);
+
+	if (res_str_id == 0) {
+		pr_err("Invalid params passed to %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(res_str_id, VDECDD_STREAM_TYPE_ID,
+				(void **)&core_str_ctx, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	VDEC_ASSERT(core_str_ctx);
+
+	ddstr_ctx = core_str_ctx->dd_str_ctx;
+
+	/* Validate input arguments */
+	VDEC_ASSERT(ddstr_ctx);
+
+	ret = core_stream_stop(res_str_id);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	lst_remove(&global_core_ctx->core_str_ctx, core_str_ctx);
+
+	/* Destroy stream if idle otherwise wait and do it later */
+	if (core_is_stream_idle(ddstr_ctx))
+		rman_free_resource(ddstr_ctx->res_handle);
+
+	pr_debug("Core stream destroy successfully\n");
+	/* Return success.. */
+	return IMG_SUCCESS;
+}
+
+static int
+core_picture_attach_resources(struct core_stream_context *core_str_ctx,
+			      struct vdecdd_str_unit *str_unit, unsigned char check)
+{
+	unsigned int ret = IMG_SUCCESS;
+
+	/*
+	 * Take sequence header from cache.
+	 * Note: sequence header id must be set in PICTURE_START unit
+	 */
+	str_unit->seq_hdr_info = resource_list_getbyid(&core_str_ctx->seq_hdr_list,
+						       str_unit->seq_hdr_id);
+
+	/* Check is not needed e.g. when freeing resources at stream destroy */
+	if (check && !str_unit->seq_hdr_info) {
+		pr_err("[USERSID=0x%08X] Sequence header not available for current picture while attaching",
+		       core_str_ctx->dd_str_ctx->str_config_data.user_str_id);
+		ret = IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	return ret;
+}
+
+/*
+ * @Function core_handle_processed_unit
+ */
+static int core_handle_processed_unit(struct core_stream_context *c_str_ctx,
+				      struct vdecdd_str_unit *str_unit)
+{
+	struct bspp_bitstr_seg *bstr_seg;
+	struct vdecdd_ddstr_ctx *dd_str_ctx = c_str_ctx->dd_str_ctx;
+	int ret;
+	struct core_context *g_ctx = global_core_ctx;
+
+	pr_debug("%s stream unit type = %d\n", __func__, str_unit->str_unit_type);
+	/* check for type of the unit */
+	switch (str_unit->str_unit_type) {
+	case VDECDD_STRUNIT_SEQUENCE_START:
+		/* nothing to be done as sps is maintained till it changes */
+		break;
+
+	case VDECDD_STRUNIT_PICTURE_START:
+		/* Loop over bit stream segments.. */
+		bstr_seg = (struct bspp_bitstr_seg *)
+			lst_removehead(&str_unit->bstr_seg_list);
+
+		while (bstr_seg) {
+			lst_add(&c_str_ctx->vxd_dec_context->seg_list, bstr_seg);
+			if (bstr_seg->bstr_seg_flag & VDECDD_BSSEG_LASTINBUFF &&
+			    dd_str_ctx->dd_str_state != VDECDD_STRSTATE_STOPPED) {
+				struct vdecdd_ddbuf_mapinfo *ddbuf_map_info;
+				/* Get access to map info context.. */
+				ret = rman_get_resource(bstr_seg->bufmap_id, VDECDD_BUFMAP_TYPE_ID,
+							(void **)&ddbuf_map_info, NULL);
+				VDEC_ASSERT(ret == IMG_SUCCESS);
+				if (ret != IMG_SUCCESS)
+					return ret;
+
+				g_ctx->vxd_str_processed_cb(c_str_ctx->vxd_dec_context,
+					VXD_CB_STRUNIT_PROCESSED,
+					bstr_seg->bufmap_id, 0);
+			}
+			/* Get next segment. */
+			bstr_seg = (struct bspp_bitstr_seg *)
+				lst_removehead(&str_unit->bstr_seg_list);
+		}
+		break;
+
+	case VDECDD_STRUNIT_PICTURE_END:
+		g_ctx->vxd_str_processed_cb(c_str_ctx->vxd_dec_context,
+			VXD_CB_PICT_END, 0xFFFF, 0);
+		break;
+
+	case VDECDD_STRUNIT_STOP:
+		/*
+		 * Signal that the stream has been stopped in the
+		 * device driver.
+		 */
+		dd_str_ctx->dd_str_state = VDECDD_STRSTATE_STOPPED;
+
+		break;
+
+	default:
+		pr_err("Invalid stream unit type passed\n");
+		return IMG_ERROR_GENERIC_FAILURE;
+	}
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("[SID=0x%08X] [UTYPE=0x%08X] PROCESSED",
+		dd_str_ctx->res_str_id,
+		str_unit->str_unit_type);
+#endif
+
+	/* Return success.. */
+	return IMG_SUCCESS;
+}
+
+static int
+core_handle_decoded_picture(struct core_stream_context *core_str_ctx,
+			    struct vdecdd_picture *picture, unsigned int type)
+{
+	/* Pick the client image buffer. */
+	struct vdecdd_ddbuf_mapinfo *pictbuf_mapinfo = picture->disp_pict_buf.pict_buf;
+
+	VDEC_ASSERT(pictbuf_mapinfo);
+	if (!pictbuf_mapinfo)
+		return IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+
+	global_core_ctx->vxd_str_processed_cb(core_str_ctx->vxd_dec_context,
+		(enum vxd_cb_type)type, pictbuf_mapinfo->buf_map_id,
+		picture->dec_pict_info->err_flags);
+	return IMG_SUCCESS;
+}
+
+static int core_stream_processed_cb(void *handle, int cb_type, void *cb_item)
+{
+	int ret;
+	struct core_stream_context *core_str_ctx =
+		(struct core_stream_context *)handle;
+	VDEC_ASSERT(core_str_ctx);
+	if (!core_str_ctx) {
+		pr_err("NULL handle passed to core callback\n");
+		return IMG_ERROR_GENERIC_FAILURE;
+	}
+
+	pr_debug("%s callback type = %d\n", __func__, cb_type);
+	/* Based on callback type, retrieve the item */
+	switch (cb_type) {
+	case VXD_CB_STRUNIT_PROCESSED:
+	{
+		struct vdecdd_str_unit *str_unit =
+			(struct vdecdd_str_unit *)cb_item;
+		VDEC_ASSERT(str_unit);
+		if (!str_unit) {
+			pr_err("NULL item passed to core callback type STRUNIT_PROCESSED\n");
+			return IMG_ERROR_GENERIC_FAILURE;
+		}
+		ret = core_handle_processed_unit(core_str_ctx, str_unit);
+		if (ret != IMG_SUCCESS) {
+			pr_err("core_handle_processed_unit returned error\n");
+			return ret;
+		}
+		break;
+	}
+
+	case VXD_CB_PICT_DECODED:
+	case VXD_CB_PICT_DISPLAY:
+	case VXD_CB_PICT_RELEASE:
+	{
+		struct vdecdd_picture *picture = (struct vdecdd_picture *)cb_item;
+
+		if (!picture) {
+			pr_err("NULL item passed to core callback type PICTURE_DECODED\n");
+			return IMG_ERROR_GENERIC_FAILURE;
+		}
+		ret = core_handle_decoded_picture(core_str_ctx, picture, cb_type);
+		break;
+	}
+
+	case VXD_CB_STR_END:
+		global_core_ctx->vxd_str_processed_cb(core_str_ctx->vxd_dec_context,
+			(enum vxd_cb_type)cb_type, 0, 0);
+		ret = IMG_SUCCESS;
+
+		break;
+	case VXD_CB_ERROR_FATAL:
+		/*
+		 * Whenever the error case occurs, we need to handle the error case.
+		 * Need to forward this error to v4l2 glue layer.
+		 * in this case the cb_item is the error_code as we may not have
+		 * an associated picture.
+		 */
+		global_core_ctx->vxd_str_processed_cb(core_str_ctx->vxd_dec_context,
+			(enum vxd_cb_type)cb_type, 0, *((unsigned int *)cb_item));
+		ret = IMG_SUCCESS;
+		break;
+	default:
+		return 0;
+	}
+
+	return ret;
+}
+
+static int core_decoder_queries(void *handle, int query, void *item)
+{
+	struct core_stream_context *core_str_ctx =
+		(struct core_stream_context *)handle;
+	VDEC_ASSERT(core_str_ctx);
+	if (!core_str_ctx) {
+		pr_err("NULL handle passed to %s callback\n", __func__);
+		return IMG_ERROR_GENERIC_FAILURE;
+	}
+
+	switch (query) {
+	case DECODER_CORE_GET_RES_LIMIT:
+	{
+		unsigned int num_img_bufs;
+		unsigned int num_res;
+
+		num_img_bufs = resource_list_getnum(&core_str_ctx->pict_buf_list);
+
+		/* Return the number of internal resources. */
+		num_res = core_str_ctx->pict_resinfo.pict_res_num;
+
+		/* Return the minimum of the two. */
+		*((unsigned int *)item) = vdec_size_min(num_img_bufs, num_res);
+	}
+	break;
+
+	default:
+		return IMG_ERROR_GENERIC_FAILURE;
+	}
+	return IMG_SUCCESS;
+}
+
+static int
+core_free_common_picture_resource(struct core_stream_context *core_str_ctx,
+				  struct vdecdd_pict_resint *pict_resint)
+{
+	int ret = IMG_SUCCESS;
+
+	if (pict_resint->mb_param_buf && pict_resint->mb_param_buf->ddbuf_info.hndl_memory) {
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("mmu_free for buff_id[%d]\n",
+			pict_resint->mb_param_buf->ddbuf_info.buff_id);
+#endif
+		ret = mmu_free_mem(core_str_ctx->dd_str_ctx->mmu_str_handle,
+				   &pict_resint->mb_param_buf->ddbuf_info);
+		if (ret != IMG_SUCCESS)
+			pr_err("MMU_Free for MBParam buffer failed with error %u", ret);
+
+		kfree(pict_resint->mb_param_buf);
+		pict_resint->mb_param_buf = NULL;
+	}
+	return ret;
+}
+
+static int core_free_resbuf(struct vdecdd_ddbuf_mapinfo **buf_handle, void *mmu_handle)
+{
+	int ret = IMG_SUCCESS;
+	struct vdecdd_ddbuf_mapinfo *buf = *buf_handle;
+
+	if (buf) {
+		if (buf->ddbuf_info.hndl_memory) {
+			ret = mmu_free_mem(mmu_handle, &buf->ddbuf_info);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+		}
+		kfree(buf);
+		*buf_handle = NULL;
+	}
+	return ret;
+}
+
+/*
+ * @Function              core_free_picture_resource
+ */
+static int
+core_free_picture_resource(struct core_stream_context *core_strctx,
+			   struct vdecdd_pict_resint *pict_resint)
+{
+	int result = IMG_SUCCESS;
+
+	/* Check input arguments */
+	if (!core_strctx || !pict_resint) {
+		VDEC_ASSERT(0);
+		return -EINVAL;
+	}
+
+	result = core_free_common_picture_resource(core_strctx, pict_resint);
+
+	VDEC_ASSERT(core_strctx->std_spec_ops);
+	if (core_strctx->std_spec_ops->free_picture_resource)
+		core_strctx->std_spec_ops->free_picture_resource(core_strctx,
+			pict_resint);
+
+#ifdef SEQ_RES_NEEDED
+	if (pict_resint->seq_resint) {
+		resource_item_return(&pict_resint->seq_resint->ref_count);
+		pict_resint->seq_resint = 0;
+	}
+#endif
+
+	if (result == IMG_SUCCESS)
+		kfree(pict_resint);
+
+	return result;
+}
+
+/*
+ * @Function              core_free_sequence_resource
+ */
+#ifdef SEQ_RES_NEEDED
+static int
+core_free_common_sequence_resource(struct core_stream_context *core_strctx,
+				   struct vdecdd_seq_resint *seqres_int)
+{
+	int result;
+
+	result = core_free_resbuf(&seqres_int->err_pict_buf,
+				  core_strctx->dd_str_ctx->mmu_str_handle);
+	if (result != IMG_SUCCESS)
+		pr_err("MMU_Free for Error Recover Frame Store buffer failed with error %u",
+		       result);
+
+	return result;
+}
+
+static void
+core_free_sequence_resource(struct core_stream_context *core_strctx,
+			    struct vdecdd_seq_resint *seqres_int)
+{
+	VDEC_ASSERT(core_strctx->std_spec_ops);
+	core_free_common_sequence_resource(core_strctx, seqres_int);
+
+	if (core_strctx->std_spec_ops->free_sequence_resource)
+		core_strctx->std_spec_ops->free_sequence_resource(core_strctx, seqres_int);
+
+	kfree(seqres_int);
+}
+#endif
+
+/*
+ * @Function              core_stream_resource_deprecate
+ */
+static int core_stream_resource_deprecate(struct core_stream_context *core_str_ctx)
+{
+	struct vdecdd_pict_resint *picres_int;
+	int ret;
+
+	/* Free all "old" picture resources since these should now be unused. */
+	picres_int = lst_first(&core_str_ctx->old_pict_res_list);
+	while (picres_int) {
+		if (picres_int->ref_cnt != 0) {
+			pr_warn("[USERSID=0x%08X] Internal resource should be unused since it has been deprecated before",
+				core_str_ctx->dd_str_ctx->str_config_data.user_str_id);
+
+			picres_int = lst_next(picres_int);
+		} else {
+			struct vdecdd_pict_resint *picres_int_to_remove = picres_int;
+
+			picres_int = lst_next(picres_int);
+
+			lst_remove(&core_str_ctx->old_pict_res_list, picres_int_to_remove);
+			ret = core_free_picture_resource(core_str_ctx, picres_int_to_remove);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+		}
+	}
+
+	/* Move all "active" picture resources to the "old" list if they are still in use. */
+	picres_int = lst_removehead(&core_str_ctx->pict_res_list);
+	while (picres_int) {
+		/* Remove picture resource from the list. */
+		ret = resource_list_remove(&core_str_ctx->aux_pict_res_list, picres_int);
+
+		/* IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE is a valid return code
+		 * e.g. during reconfigure we are clearing the sPictBufferList list
+		 * and then try to remove the buffers again from the same list (empty now)
+		 * though core UNMAP_BUF messages
+		 */
+		if (ret != IMG_SUCCESS && ret != IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE) {
+			pr_err("[USERSID=0x%08X] Failed to remove picture resource",
+			       core_str_ctx->dd_str_ctx->str_config_data.user_str_id);
+			return ret;
+		}
+		/*
+		 * If the active resource is not being used, free now.
+		 * Otherwise add to the old list to be freed later.
+		 */
+		if (picres_int->ref_cnt == 0) {
+			ret = core_free_picture_resource(core_str_ctx, picres_int);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+		} else {
+			lst_add(&core_str_ctx->old_pict_res_list, picres_int);
+		}
+		picres_int = lst_removehead(&core_str_ctx->pict_res_list);
+	}
+
+	/* Reset the resource configuration. */
+	memset(&core_str_ctx->pict_resinfo, 0, sizeof(core_str_ctx->pict_resinfo));
+
+#ifdef SEQ_RES_NEEDED
+	{
+		struct vdecdd_seq_resint *seqres_int;
+
+		/* Free all "old" sequence resources since these should now be unused. */
+		seqres_int = lst_first(&core_str_ctx->old_seq_res_list);
+		while (seqres_int) {
+			if (seqres_int->ref_count != 0) {
+				pr_warn("[USERSID=0x%08X] Internal sequence resource should be unused since it has been deprecated before",
+					core_str_ctx->dd_str_ctx->str_config_data.user_str_id);
+				seqres_int = lst_next(seqres_int);
+			} else {
+				struct vdecdd_seq_resint *seqres_int_to_remove = seqres_int;
+
+				seqres_int = lst_next(seqres_int);
+
+				lst_remove(&core_str_ctx->old_seq_res_list, seqres_int_to_remove);
+				core_free_sequence_resource(core_str_ctx, seqres_int_to_remove);
+			}
+		}
+
+		/* Move all "active" sequence resources to the "old"
+		 * list if they are still in use.
+		 */
+		seqres_int = lst_removehead(&core_str_ctx->seq_res_list);
+		while (seqres_int) {
+			/*
+			 * If the active resource is not being used, free now.
+			 * Otherwise add to the old list to be freed later.
+			 */
+			seqres_int->ref_count == 0 ? core_free_sequence_resource(core_str_ctx,
+				seqres_int) :
+			lst_add(&core_str_ctx->old_seq_res_list, seqres_int);
+
+			seqres_int = lst_removehead(&core_str_ctx->seq_res_list);
+		}
+
+		/* Reset the resource configuration. */
+		memset(&core_str_ctx->seq_resinfo, 0, sizeof(core_str_ctx->seq_resinfo));
+	}
+#endif
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function              core_stream_resource_destroy
+ */
+static int core_stream_resource_destroy(struct core_stream_context *core_str_ctx)
+{
+	struct vdecdd_pict_resint *picres_int;
+	int ret;
+
+	/* Remove any "active" picture resources allocated for this stream. */
+	picres_int = lst_removehead(&core_str_ctx->pict_res_list);
+	while (picres_int) {
+		ret = core_free_picture_resource(core_str_ctx, picres_int);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		picres_int = lst_removehead(&core_str_ctx->pict_res_list);
+	}
+
+	/* Remove any "old" picture resources allocated for this stream. */
+	picres_int = lst_removehead(&core_str_ctx->old_pict_res_list);
+	while (picres_int) {
+		ret = core_free_picture_resource(core_str_ctx, picres_int);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		picres_int = lst_removehead(&core_str_ctx->old_pict_res_list);
+	}
+
+	/* Reset the resource configuration. */
+	memset(&core_str_ctx->pict_resinfo, 0, sizeof(core_str_ctx->pict_resinfo));
+
+#ifdef SEQ_RES_NEEDED
+	{
+		struct vdecdd_seq_resint *seqres_int;
+
+		/* Remove any "active" sequence resources allocated for this stream. */
+		seqres_int = lst_removehead(&core_str_ctx->seq_res_list);
+		while (seqres_int) {
+			core_free_sequence_resource(core_str_ctx, seqres_int);
+			seqres_int = lst_removehead(&core_str_ctx->seq_res_list);
+		}
+
+		/* Remove any "old" sequence resources allocated for this stream. */
+		seqres_int = lst_removehead(&core_str_ctx->old_seq_res_list);
+		while (seqres_int) {
+			core_free_sequence_resource(core_str_ctx, seqres_int);
+			seqres_int = lst_removehead(&core_str_ctx->old_seq_res_list);
+		}
+
+		/* Reset the resource configuration. */
+		memset(&core_str_ctx->seq_resinfo, 0, sizeof(core_str_ctx->seq_resinfo));
+	}
+#endif
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function core_fn_free_stream_unit
+ */
+static int core_fn_free_stream_unit(struct vdecdd_str_unit *str_unit, void *param)
+{
+	struct core_stream_context *core_str_ctx = (struct core_stream_context *)param;
+	unsigned int ret = IMG_SUCCESS;
+
+	/* Attach picture resources where required. */
+	if (str_unit->str_unit_type == VDECDD_STRUNIT_PICTURE_START)
+		/*
+		 * Do not force attachment because the resources can be
+		 * unattached yet, e.g. in case of not yet processed picture
+		 * units
+		 */
+		ret = core_picture_attach_resources(core_str_ctx, str_unit, FALSE);
+
+	str_unit->decode = FALSE;
+
+	return ret;
+}
+
+/*
+ * @Function  core_fn_free_stream
+ */
+static void core_fn_free_stream(void *param)
+{
+	int ret;
+	struct vdecdd_ddstr_ctx *dd_str_context;
+	struct vdecdd_dddev_context *dd_dev_ctx;
+	struct core_stream_context *core_str_ctx;
+
+	/* Validate input arguments */
+	VDEC_ASSERT(param);
+
+	core_str_ctx = (struct core_stream_context *)param;
+
+	dd_str_context = core_str_ctx->dd_str_ctx;
+
+	VDEC_ASSERT(dd_str_context);
+	if (!dd_str_context)
+		return;
+
+	dd_dev_ctx = dd_str_context->dd_dev_context;
+	VDEC_ASSERT(dd_dev_ctx);
+
+	if (!lst_empty(&core_str_ctx->str_unit_list)) {
+		/*
+		 * Try and empty the list. Since this function is tearing down the core stream,
+		 * test result using assert and continue to tidy-up as much as possible.
+		 */
+		ret = resource_list_empty(&core_str_ctx->str_unit_list, FALSE,
+					  (resource_pfn_freeitem)core_fn_free_stream_unit,
+					  core_str_ctx);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+	}
+
+	if (!lst_empty(&core_str_ctx->pict_buf_list)) {
+		/*
+		 * Try and empty the list. Since this function is tearing down the core stream,
+		 * test result using assert and continue to tidy-up as much as possible.
+		 */
+		ret = resource_list_empty(&core_str_ctx->pict_buf_list, TRUE, NULL, NULL);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+	}
+
+	if (!lst_empty(&core_str_ctx->aux_pict_res_list)) {
+		/*
+		 * Try and empty the list. Since this function is tearing down the core stream,
+		 * test result using assert and continue to tidy-up as much as possible.
+		 */
+		ret = resource_list_empty(&core_str_ctx->aux_pict_res_list, TRUE, NULL, NULL);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+	}
+
+	if (!lst_empty(&core_str_ctx->seq_hdr_list)) {
+		/*
+		 * Try and empty the list. Since this function is tearing down the core stream,
+		 * test result using assert and continue to tidy-up as much as possible.
+		 */
+		ret = resource_list_empty(&core_str_ctx->seq_hdr_list, FALSE, NULL, NULL);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+	}
+
+	/* Destroy stream in the Decoder. */
+	if (dd_str_context->dec_ctx) {
+		ret = decoder_stream_destroy(dd_str_context->dec_ctx, FALSE);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		dd_str_context->dec_ctx = NULL;
+	}
+
+	core_stream_resource_destroy(core_str_ctx);
+
+	/* Destroy the MMU context for this stream. */
+	if (dd_str_context->mmu_str_handle) {
+		ret = mmu_stream_destroy(dd_str_context->mmu_str_handle);
+
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		dd_str_context->mmu_str_handle = NULL;
+	}
+
+	/* Destroy the stream resources. */
+	if (dd_str_context->res_buck_handle) {
+		rman_destroy_bucket(dd_str_context->res_buck_handle);
+		dd_str_context->res_buck_handle = NULL;
+	}
+
+	/* Free stream context. */
+	kfree(dd_str_context);
+
+	/* Free the stream context. */
+	kfree(core_str_ctx);
+}
+
+/*
+ * @Function  core_is_unsupported
+ */
+static unsigned char core_is_unsupported(struct vdec_unsupp_flags *unsupp_flags)
+{
+	unsigned char unsupported = FALSE;
+
+	if (unsupp_flags->str_cfg || unsupp_flags->seq_hdr ||
+	    unsupp_flags->pict_hdr || unsupp_flags->str_opcfg ||
+	    unsupp_flags->op_bufcfg)
+		unsupported = TRUE;
+
+	return unsupported;
+}
+
+int core_stream_create(void *vxd_dec_ctx_arg,
+		       const struct vdec_str_configdata *str_cfg_data,
+		       unsigned int *res_str_id)
+{
+	int ret;
+	struct vdecdd_ddstr_ctx *dd_str_context;
+	struct vdecdd_supp_check supp_check;
+	struct vdecdd_dddev_context *dd_dev_ctx;
+	struct core_stream_context *core_str_ctx;
+
+	/* Validate input arguments */
+	VDEC_ASSERT(str_cfg_data);
+	VDEC_ASSERT(res_str_id);
+
+	VDEC_ASSERT(global_core_ctx);
+	dd_dev_ctx = global_core_ctx->dev_ctx;
+
+	VDEC_ASSERT(dd_dev_ctx);
+	if (!dd_dev_ctx)
+		return IMG_ERROR_NOT_INITIALISED;
+
+	/* Allocate Core Stream Context */
+	core_str_ctx = kzalloc(sizeof(*core_str_ctx), GFP_KERNEL);
+	if (!core_str_ctx)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	core_str_ctx->core_ctx = global_core_ctx;
+	core_str_ctx->vxd_dec_context = (struct vxd_dec_ctx *)vxd_dec_ctx_arg;
+
+	((struct vxd_dec_ctx *)vxd_dec_ctx_arg)->dev_ctx = global_core_ctx->dev_ctx;
+
+	/* register callback for firmware response */
+	core_str_ctx->vxd_dec_context->cb = (decode_cb)core_fw_response_cb;
+
+	lst_init(&core_str_ctx->pict_buf_list);
+	lst_init(&core_str_ctx->pict_res_list);
+	lst_init(&core_str_ctx->old_pict_res_list);
+	lst_init(&core_str_ctx->aux_pict_res_list);
+	lst_init(&core_str_ctx->seq_hdr_list);
+	lst_init(&core_str_ctx->str_unit_list);
+
+#ifdef SEQ_RES_NEEDED
+	lst_init(&core_str_ctx->seq_res_list);
+	lst_init(&core_str_ctx->old_seq_res_list);
+#endif
+
+	/* Allocate device stream context.. */
+	dd_str_context = kzalloc(sizeof(*dd_str_context), GFP_KERNEL);
+	VDEC_ASSERT(dd_str_context);
+	if (!dd_str_context) {
+		kfree(core_str_ctx);
+		core_str_ctx = NULL;
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	dd_str_context->dd_dev_context = dd_dev_ctx;
+	core_str_ctx->dd_str_ctx = dd_str_context;
+
+	/* Check stream configuration. */
+	memset(&supp_check, 0x0, sizeof(supp_check));
+	ret = core_check_decoder_support(dd_dev_ctx, str_cfg_data, NULL, NULL, NULL, &supp_check);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	if (core_is_unsupported(&supp_check.unsupp_flags)) {
+		ret = IMG_ERROR_NOT_SUPPORTED;
+		goto error;
+	}
+
+	/* Create a bucket for the resources.. */
+	ret = rman_create_bucket(&dd_str_context->res_buck_handle);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	/* Register the stream as a device resource.. */
+	ret = rman_register_resource(dd_dev_ctx->res_buck_handle,
+				     VDECDD_STREAM_TYPE_ID,
+				     core_fn_free_stream, core_str_ctx,
+				     &dd_str_context->res_handle,
+				     &dd_str_context->res_str_id);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	/* Create unique Stream Id */
+	dd_str_context->km_str_id = core_str_ctx->vxd_dec_context->stream.id;
+
+	/*
+	 * Create stream in the Decoder.
+	 * NOTE: this must take place first since it creates the MMU context.
+	 */
+	ret = decoder_stream_create(dd_dev_ctx->dec_context, *str_cfg_data,
+				    dd_str_context->km_str_id,
+				    &dd_str_context->mmu_str_handle,
+				    core_str_ctx->vxd_dec_context,
+				    core_str_ctx, &dd_str_context->dec_ctx,
+				    (void *)core_stream_processed_cb,
+				    (void *)core_decoder_queries);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	/* Setup stream context.. */
+	dd_str_context->str_config_data = *str_cfg_data;
+	dd_str_context->dd_str_state = VDECDD_STRSTATE_STOPPED;
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("[SID=0x%08X] New stream created [USERSID=0x%08X]",
+		dd_str_context->res_str_id, str_cfg_data->user_str_id);
+#endif
+
+	*res_str_id = dd_str_context->res_str_id;
+	if (str_cfg_data->vid_std > 0 &&  str_cfg_data->vid_std <= VDEC_STD_MAX) {
+		core_str_ctx->std_spec_ops = &std_specific_ops[str_cfg_data->vid_std - 1];
+	} else {
+		pr_err("%s: Invalid parameters\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	lst_add(&global_core_ctx->core_str_ctx, core_str_ctx);
+
+	/* Return success.. */
+	return IMG_SUCCESS;
+
+error:
+	if (dd_str_context->res_handle)
+		rman_free_resource(dd_str_context->res_handle);
+	else
+		core_fn_free_stream(core_str_ctx);
+
+	return ret;
+}
+
+static int
+core_get_resource_availability(struct core_stream_context *core_str_ctx)
+{
+	unsigned int avail = ~0;
+
+	if (resource_list_getnumavail(&core_str_ctx->pict_buf_list) == 0)
+		avail &= ~CORE_AVAIL_PICTBUF;
+
+	if (resource_list_getnumavail(&core_str_ctx->aux_pict_res_list) == 0)
+		avail &= ~CORE_AVAIL_PICTRES;
+
+	if (global_avail_slots == 0)
+		avail &= ~CORE_AVAIL_CORE;
+
+	return avail;
+}
+
+static int
+core_stream_set_pictbuf_config(struct vdecdd_ddstr_ctx *dd_str_ctx,
+			       struct vdec_pict_bufconfig *pictbuf_cfg)
+{
+	int ret;
+
+	/* Validate input arguments */
+	VDEC_ASSERT(dd_str_ctx);
+	VDEC_ASSERT(pictbuf_cfg);
+
+	/*
+	 * If there are no buffers mapped or the configuration is not set
+	 * (only done when reconfiguring output) then calculate the output
+	 * picture buffer layout.
+	 */
+	if (dd_str_ctx->map_buf_info.num_buf == 0 ||
+	    dd_str_ctx->disp_pict_buf.buf_config.buf_size == 0) {
+		struct vdecdd_supp_check supp_check;
+		struct vdecdd_ddpict_buf disp_pictbuf;
+
+		memset(&disp_pictbuf, 0, sizeof(disp_pictbuf));
+
+		disp_pictbuf.buf_config = *pictbuf_cfg;
+
+		/*
+		 * Ensure that the external picture buffer information
+		 * is compatible with the hardware and convert to internal
+		 * driver representation.
+		 */
+		ret = vdecddutils_convert_buffer_config(&dd_str_ctx->str_config_data,
+							&disp_pictbuf.buf_config,
+							&disp_pictbuf.rend_info);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			goto error;
+
+		/*
+		 * Provide the current state for validation against the new
+		 * buffer configuration.
+		 */
+		memset(&supp_check, 0, sizeof(supp_check));
+		supp_check.disp_pictbuf = &disp_pictbuf;
+
+		if (dd_str_ctx->comseq_hdr_info.max_frame_size.width)
+			supp_check.comseq_hdrinfo = &dd_str_ctx->comseq_hdr_info;
+
+		if (dd_str_ctx->str_op_configured)
+			supp_check.op_cfg = &dd_str_ctx->opconfig;
+
+		ret = core_check_decoder_support(dd_str_ctx->dd_dev_context,
+						 &dd_str_ctx->str_config_data,
+						 &dd_str_ctx->prev_comseq_hdr_info,
+						 &dd_str_ctx->prev_pict_hdr_info,
+						 &dd_str_ctx->map_buf_info,
+						 &supp_check);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			goto error;
+
+		if (core_is_unsupported(&supp_check.unsupp_flags)) {
+			ret = IMG_ERROR_NOT_SUPPORTED;
+			goto error;
+		}
+
+		dd_str_ctx->disp_pict_buf = disp_pictbuf;
+	} else {
+		/*
+		 * Check configuration of buffer matches that for stream
+		 * including any picture buffers that are already mapped.
+		 */
+		if (memcmp(pictbuf_cfg, &dd_str_ctx->disp_pict_buf.buf_config,
+			   sizeof(*pictbuf_cfg))) {
+			/*
+			 * Configuration of output buffer doesn't match the
+			 * rest.
+			 */
+			pr_err("[SID=0x%08X] All output buffers must have the same properties.",
+			       dd_str_ctx->res_str_id);
+			ret = IMG_ERROR_INVALID_PARAMETERS;
+			goto error;
+		}
+	}
+
+	/* Return success.. */
+	return IMG_SUCCESS;
+
+error:
+	return ret;
+}
+
+int
+core_stream_set_output_config(unsigned int res_str_id,
+			      struct vdec_str_opconfig *str_opcfg,
+			      struct vdec_pict_bufconfig *pict_bufcfg_handle)
+{
+	struct vdecdd_supp_check supp_check;
+	struct vdec_pict_bufconfig pict_buf_cfg;
+	struct vdec_pict_rendinfo disp_pict_rend_info;
+	int ret;
+
+	struct vdecdd_ddstr_ctx *dd_str_context;
+	struct core_stream_context      *core_str_ctx;
+
+	/*
+	 * Stream based messages without a device context
+	 * must have a stream ID.
+	 */
+	VDEC_ASSERT(res_str_id);
+
+	/* Get access to stream context */
+	ret = rman_get_resource(res_str_id, VDECDD_STREAM_TYPE_ID, (void **)&core_str_ctx, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	dd_str_context = core_str_ctx->dd_str_ctx;
+
+	VDEC_ASSERT(dd_str_context);
+	VDEC_ASSERT(str_opcfg);
+
+	memset(&supp_check, 0, sizeof(supp_check));
+	if (core_str_ctx->new_seq)
+		supp_check.comseq_hdrinfo = &dd_str_context->comseq_hdr_info;
+	else
+		supp_check.comseq_hdrinfo = NULL;
+
+	supp_check.op_cfg = str_opcfg;
+
+	/*
+	 * Validate stream output configuration against display
+	 * buffer properties if no new picture buffer configuration
+	 * is provided.
+	 */
+	if (!pict_bufcfg_handle) {
+		VDEC_ASSERT(dd_str_context->disp_pict_buf.rend_info.rendered_size);
+		supp_check.disp_pictbuf = &dd_str_context->disp_pict_buf;
+	}
+
+	/* Validate output configuration. */
+	ret = core_check_decoder_support(dd_str_context->dd_dev_context,
+					 &dd_str_context->str_config_data,
+					 &dd_str_context->prev_comseq_hdr_info,
+					 &dd_str_context->prev_pict_hdr_info,
+					 &dd_str_context->map_buf_info,
+					 &supp_check);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return IMG_SUCCESS;
+
+	if (core_is_unsupported(&supp_check.unsupp_flags))
+		return IMG_ERROR_NOT_SUPPORTED;
+
+	/* Update the stream output configuration. */
+	dd_str_context->opconfig = *str_opcfg;
+
+	/* Mark output as configured. */
+	dd_str_context->str_op_configured = TRUE;
+
+	if (pict_bufcfg_handle) {
+		/*
+		 * Clear/invalidate the latest picture buffer configuration
+		 * since it is easier to reuse the set function to calculate
+		 * for this new output configuration than to determine
+		 * compatibility. Keep a copy beforehand just in case the new
+		 * configuration is invalid.
+		 */
+		if (dd_str_context->disp_pict_buf.rend_info.rendered_size != 0) {
+			pict_buf_cfg = dd_str_context->disp_pict_buf.buf_config;
+			disp_pict_rend_info = dd_str_context->disp_pict_buf.rend_info;
+
+			memset(&dd_str_context->disp_pict_buf.buf_config, 0,
+			       sizeof(dd_str_context->disp_pict_buf.buf_config));
+			memset(&dd_str_context->disp_pict_buf.rend_info, 0,
+			       sizeof(dd_str_context->disp_pict_buf.rend_info));
+		}
+
+		/*
+		 * Recalculate the picture buffer internal layout from the
+		 * externalconfiguration. These settings provided by the
+		 * allocator should be adhered to since the display process
+		 * will expect the decoder to use them.
+		 * If the configuration is invalid we need to leave the
+		 * decoder state as it was before.
+		 */
+		ret = core_stream_set_pictbuf_config(dd_str_context, pict_bufcfg_handle);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS && dd_str_context->disp_pict_buf.rend_info.rendered_size
+		    != 0) {
+			/* Restore old picture buffer configuration */
+			dd_str_context->disp_pict_buf.buf_config =
+				pict_buf_cfg;
+			dd_str_context->disp_pict_buf.rend_info =
+				disp_pict_rend_info;
+			return ret;
+		}
+	} else if (core_is_unsupported(&supp_check.unsupp_flags)) {
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	/* Return success.. */
+	return ret;
+}
+
+/*
+ * @Function core_stream_play
+ */
+int core_stream_play(unsigned int res_str_id)
+{
+	int ret;
+	struct vdecdd_ddstr_ctx *dd_str_context;
+	struct core_stream_context *core_str_ctx;
+	/* Picture buffer layout to use for decoding. */
+	struct vdecdd_ddpict_buf *disp_pict_buf;
+	struct vdec_str_opconfig *op_cfg;
+	struct vdecdd_supp_check supp_check;
+
+	/*
+	 * Stream based messages without a device context
+	 * must have a stream ID.
+	 */
+	VDEC_ASSERT(res_str_id);
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(res_str_id, VDECDD_STREAM_TYPE_ID,
+				(void **)&core_str_ctx, NULL);
+
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	dd_str_context = core_str_ctx->dd_str_ctx;
+
+	VDEC_ASSERT(dd_str_context);
+
+	/* Ensure we are stopped. */
+	VDEC_ASSERT(dd_str_context->dd_str_state == VDECDD_STRSTATE_STOPPED);
+
+	/* Set "playing". */
+	dd_str_context->dd_str_state = VDECDD_STRSTATE_PLAYING;
+
+	/* set that is it not yet in closed GOP */
+	core_str_ctx->no_prev_refs_used = TRUE;
+
+	disp_pict_buf = dd_str_context->disp_pict_buf.rend_info.rendered_size ?
+		&dd_str_context->disp_pict_buf : NULL;
+	op_cfg = dd_str_context->str_op_configured ?
+		&dd_str_context->opconfig : NULL;
+
+	if (disp_pict_buf && op_cfg) {
+		VDEC_ASSERT(!disp_pict_buf->pict_buf);
+
+		if (memcmp(&core_str_ctx->op_cfg, op_cfg,
+			   sizeof(core_str_ctx->op_cfg)) ||
+			memcmp(&core_str_ctx->disp_pict_buf, disp_pict_buf,
+			       sizeof(core_str_ctx->disp_pict_buf)))
+			core_str_ctx->new_op_cfg = TRUE;
+
+		core_str_ctx->disp_pict_buf = *disp_pict_buf;
+		core_str_ctx->op_cfg = *op_cfg;
+
+		core_str_ctx->opcfg_set = TRUE;
+	} else {
+		core_str_ctx->opcfg_set = FALSE;
+		/* Must not be decoding without output configuration */
+		VDEC_ASSERT(0);
+	}
+
+	memset(&supp_check, 0, sizeof(supp_check));
+
+	if (vdec_size_nz(core_str_ctx->comseq_hdr_info.max_frame_size))
+		supp_check.comseq_hdrinfo = &core_str_ctx->comseq_hdr_info;
+
+	if (core_str_ctx->opcfg_set) {
+		supp_check.op_cfg = &core_str_ctx->op_cfg;
+		supp_check.disp_pictbuf = &core_str_ctx->disp_pict_buf;
+	}
+	supp_check.non_cfg_req = TRUE;
+	ret = core_check_decoder_support(dd_str_context->dd_dev_context,
+					 &dd_str_context->str_config_data,
+					 &dd_str_context->prev_comseq_hdr_info,
+					 &dd_str_context->prev_pict_hdr_info,
+					 &dd_str_context->map_buf_info,
+					 &supp_check);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	/* Return success.. */
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function  core_deinitialise
+ */
+int core_deinitialise(void)
+{
+	struct vdecdd_dddev_context *dd_dev_ctx;
+	int ret;
+
+	dd_dev_ctx = global_core_ctx->dev_ctx;
+	VDEC_ASSERT(dd_dev_ctx);
+	if (!dd_dev_ctx)
+		return IMG_ERROR_NOT_INITIALISED;
+
+	ret = decoder_deinitialise(dd_dev_ctx->dec_context);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+
+	/* Free context resources.. */
+	rman_destroy_bucket(dd_dev_ctx->res_buck_handle);
+
+	rman_deinitialise();
+
+	kfree(dd_dev_ctx);
+
+	global_core_ctx->dev_ctx = NULL;
+
+	kfree(global_core_ctx);
+	global_core_ctx = NULL;
+
+	is_core_initialized = FALSE;
+
+	pr_debug("Core deinitialise successfully\n");
+	return IMG_SUCCESS;
+}
+
+static int core_get_mb_num(unsigned int width, unsigned int height)
+{
+	/*
+	 * Calculate the number of MBs needed for current video
+	 * sequence settings.
+	 */
+	unsigned int width_mb  = ALIGN(width, VDEC_MB_DIMENSION) / VDEC_MB_DIMENSION;
+	unsigned int height_mb = ALIGN(height, 2 * VDEC_MB_DIMENSION) / VDEC_MB_DIMENSION;
+
+	return width_mb * height_mb;
+}
+
+static int core_common_bufs_getsize(struct core_stream_context *core_str_ctx,
+				    const struct vdec_comsequ_hdrinfo *comseq_hdrinfo,
+				    struct vdec_pict_size *max_pict_size,
+				    struct core_pict_bufsize_info     *size_info,
+				    struct core_seq_resinfo  *seq_res_info,
+				    unsigned char *res_needed)
+{
+	enum vdec_vid_std vid_std = core_str_ctx->dd_str_ctx->str_config_data.vid_std;
+	unsigned int std_idx = vid_std - 1;
+	unsigned int mb_num = 0;
+
+	if (core_str_ctx->dd_str_ctx->str_config_data.vid_std >= VDEC_STD_MAX)
+		return IMG_ERROR_GENERIC_FAILURE;
+
+	/* Reset the MB parameters buffer size. */
+	size_info->mbparams_bufsize = 0;
+
+	if (mbparam_allocinfo[std_idx].alloc_mbparam_bufs) {
+		*res_needed = TRUE;
+
+		/*
+		 * Calculate the number of MBs needed for current video
+		 * sequence settings.
+		 */
+		mb_num = core_get_mb_num(max_pict_size->width, max_pict_size->height);
+
+		/* Calculate the final number of MBs needed. */
+		mb_num += mbparam_allocinfo[std_idx].overalloc_mbnum;
+
+		/* Calculate the MB params buffer size. */
+		size_info->mbparams_bufsize = mb_num * mbparam_allocinfo[std_idx].mbparam_size;
+
+		/* Adjust the buffer size for MSVDX. */
+		vdecddutils_buf_vxd_adjust_size(&size_info->mbparams_bufsize);
+
+		if (comseq_hdrinfo->separate_chroma_planes)
+			size_info->mbparams_bufsize *= 3;
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function core_pict_res_getinfo
+ */
+static int
+core_pict_res_getinfo(struct core_stream_context *core_str_ctx,
+		      const struct vdec_comsequ_hdrinfo *comseq_hdrinfo,
+		      const struct vdec_str_opconfig *op_cfg,
+		      const struct vdecdd_ddpict_buf *disp_pictbuf,
+		      struct core_pict_resinfo *pict_resinfo,
+		      struct core_seq_resinfo *seq_resinfo)
+{
+	struct vdec_pict_size coded_pict_size;
+	struct dec_ctx *decctx;
+	unsigned char res_needed = FALSE;
+	int ret;
+
+	/* Reset the picture resource info. */
+	memset(pict_resinfo, 0, sizeof(*pict_resinfo));
+
+	coded_pict_size = comseq_hdrinfo->max_frame_size;
+
+	VDEC_ASSERT(core_str_ctx->std_spec_ops);
+	if (core_str_ctx->std_spec_ops->bufs_get_size)
+		core_str_ctx->std_spec_ops->bufs_get_size(core_str_ctx, comseq_hdrinfo,
+			&coded_pict_size,
+			&pict_resinfo->size_info, seq_resinfo, &res_needed);
+
+	/* If any picture resources are needed... */
+	if (res_needed) {
+		/* Get the number of resources required. */
+		ret = vdecddutils_get_minrequired_numpicts
+							(&core_str_ctx->dd_str_ctx->str_config_data,
+							  comseq_hdrinfo, op_cfg,
+							  &pict_resinfo->pict_res_num);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		decctx = (struct dec_ctx *)global_core_ctx->dev_ctx->dec_context;
+
+		if (core_str_ctx->dd_str_ctx->str_config_data.vid_std == VDEC_STD_HEVC)
+			pict_resinfo->pict_res_num += decctx->dev_cfg->num_slots_per_pipe - 1;
+		else
+			pict_resinfo->pict_res_num +=
+				decctx->num_pipes * decctx->dev_cfg->num_slots_per_pipe - 1;
+	}
+
+	return IMG_SUCCESS;
+}
+
+static int core_alloc_resbuf(struct vdecdd_ddbuf_mapinfo **buf_handle,
+			     unsigned int size, void *mmu_handle,
+			     struct vxdio_mempool mem_pool)
+{
+	int ret;
+	struct vdecdd_ddbuf_mapinfo *buf;
+
+	*buf_handle = kzalloc(sizeof(**buf_handle), GFP_KERNEL);
+	buf = *buf_handle;
+	VDEC_ASSERT(buf);
+	if (buf) {
+		buf->mmuheap_id = MMU_HEAP_STREAM_BUFFERS;
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("%s:%d calling MMU_StreamMalloc", __func__, __LINE__);
+#endif
+		ret = mmu_stream_alloc(mmu_handle, buf->mmuheap_id,
+				       mem_pool.mem_heap_id,
+				       mem_pool.mem_attrib, size,
+				       DEV_MMU_PAGE_SIZE,
+				       &buf->ddbuf_info);
+
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			ret = IMG_ERROR_OUT_OF_MEMORY;
+	} else {
+		ret = IMG_ERROR_OUT_OF_MEMORY;
+	}
+	return ret;
+}
+
+#ifdef SEQ_RES_NEEDED
+static int core_alloc_common_sequence_buffers(struct core_stream_context *core_str_ctx,
+					      struct vdecdd_seq_resint *seqres_int,
+					      struct vxdio_mempool mem_pool,
+					      struct core_seq_resinfo *seqres_info,
+					      struct core_pict_resinfo *pictres_info,
+					      const struct vdec_str_opconfig *op_cfg,
+					      const struct vdecdd_ddpict_buf *disp_pict_buf)
+{
+	int ret = IMG_SUCCESS;
+#ifdef ERROR_CONCEALMENT
+	enum vdec_vid_std vid_std = core_str_ctx->dd_str_ctx->str_config_data.vid_std;
+	unsigned int std_idx = vid_std - 1;
+	struct vidio_ddbufinfo *err_buf_info;
+
+	/* Allocate error concealment pattern frame for current sequence */
+	if (err_recovery_frame_info[std_idx].enabled) {
+		struct vdec_pict_bufconfig buf_config;
+		unsigned int size;
+
+		buf_config = disp_pict_buf->buf_config;
+		size = buf_config.coded_width * buf_config.coded_height;
+
+		if (err_recovery_frame_info[std_idx].max_size > size) {
+			seqres_int->err_pict_buf = kzalloc(sizeof(*seqres_int->err_pict_buf),
+							   GFP_KERNEL);
+			VDEC_ASSERT(seqres_int->err_pict_buf);
+			if (!seqres_int->err_pict_buf)
+				return IMG_ERROR_OUT_OF_MEMORY;
+
+			seqres_int->err_pict_buf->mmuheap_id = MMU_HEAP_STREAM_BUFFERS;
+
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("===== %s:%d calling MMU_StreamMalloc", __func__, __LINE__);
+#endif
+			ret = mmu_stream_alloc(core_str_ctx->dd_str_ctx->mmu_str_handle,
+					       seqres_int->err_pict_buf->mmuheap_id,
+					       mem_pool.mem_heap_id,
+					       (enum sys_emem_attrib)(mem_pool.mem_attrib |
+						       SYS_MEMATTRIB_CPU_WRITE),
+					       buf_config.buf_size,
+					       DEV_MMU_PAGE_ALIGNMENT,
+					       &seqres_int->err_pict_buf->ddbuf_info);
+			if (ret != IMG_SUCCESS)
+				return IMG_ERROR_OUT_OF_MEMORY;
+
+			/* make grey pattern - luma & chroma at mid-rail */
+			err_buf_info = &seqres_int->err_pict_buf->ddbuf_info;
+			if (op_cfg->pixel_info.mem_pkg == PIXEL_BIT10_MP) {
+				unsigned int *out = (unsigned int *)err_buf_info->cpu_virt;
+				unsigned int i;
+
+				for (i = 0; i < err_buf_info->buf_size / sizeof(unsigned int); i++)
+					/* See PIXEL_BIT10_MP layout definition */
+					out[i] = 0x20080200;
+			} else {
+				/* Note: Setting 0x80 also gives grey pattern
+				 * for 10bit upacked MSB format.
+				 */
+				memset(err_buf_info->cpu_virt, 0x80, err_buf_info->buf_size);
+			}
+		}
+	}
+#endif
+	return ret;
+}
+#endif
+
+/*
+ * @Function              core_do_resource_realloc
+ */
+static unsigned char core_do_resource_realloc(struct core_stream_context *core_str_ctx,
+					      struct core_pict_resinfo *pictres_info,
+					      struct core_seq_resinfo *seqres_info)
+{
+	VDEC_ASSERT(core_str_ctx->std_spec_ops);
+	/* If buffer sizes are sufficient and only the greater number of resources is needed... */
+	if (core_str_ctx->pict_resinfo.size_info.mbparams_bufsize >=
+		pictres_info->size_info.mbparams_bufsize &&
+		(core_str_ctx->std_spec_ops->is_stream_resource_suitable ?
+		core_str_ctx->std_spec_ops->is_stream_resource_suitable(pictres_info,
+		&core_str_ctx->pict_resinfo,
+		seqres_info, &core_str_ctx->seq_resinfo) : TRUE) &&
+		core_str_ctx->pict_resinfo.pict_res_num < pictres_info->pict_res_num)
+		/* ...full internal resource reallocation is not required. */
+		return FALSE;
+
+	/* Otherwise request full internal resource reallocation. */
+	return TRUE;
+}
+
+/*
+ * @Function              core_is_stream_resource_suitable
+ */
+static unsigned char core_is_stream_resource_suitable
+		(struct core_stream_context *core_str_ctx,
+		 const struct vdec_comsequ_hdrinfo *comseq_hdrinfo,
+		 const struct vdec_str_opconfig *op_cfg,
+		 const struct vdecdd_ddpict_buf *disp_pict_buf,
+		 struct core_pict_resinfo *pictres_info,
+		 struct core_seq_resinfo *seqres_info_ptr)
+{
+	int ret;
+	struct core_pict_resinfo aux_pictes_info;
+	struct core_pict_resinfo    *aux_pictes_info_ptr;
+	struct core_seq_resinfo seqres_info;
+
+	/* If resource info is needed externally, just use it. Otherwise use internal structure. */
+	if (pictres_info)
+		aux_pictes_info_ptr = pictres_info;
+	else
+		aux_pictes_info_ptr = &aux_pictes_info;
+
+	if (!seqres_info_ptr)
+		seqres_info_ptr = &seqres_info;
+
+	/* Get the resource info for current settings. */
+	ret = core_pict_res_getinfo(core_str_ctx, comseq_hdrinfo, op_cfg, disp_pict_buf,
+				    aux_pictes_info_ptr, seqres_info_ptr);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return FALSE;
+
+	VDEC_ASSERT(core_str_ctx->std_spec_ops);
+	if (core_str_ctx->std_spec_ops->is_stream_resource_suitable) {
+		if (!core_str_ctx->std_spec_ops->is_stream_resource_suitable
+					(aux_pictes_info_ptr,
+					 &core_str_ctx->pict_resinfo,
+					 seqres_info_ptr, &core_str_ctx->seq_resinfo))
+			return FALSE;
+	}
+
+	/* Check the number of picture resources required against the current number. */
+	if (aux_pictes_info_ptr->pict_res_num > core_str_ctx->pict_resinfo.pict_res_num)
+		return FALSE;
+
+	return TRUE;
+}
+
+static int core_alloc_common_pict_buffers(struct core_stream_context *core_str_ctx,
+					  struct vdecdd_pict_resint *pictres_int,
+					  struct vxdio_mempool mem_pool,
+					  struct core_pict_resinfo *pictres_info)
+{
+	int ret = IMG_SUCCESS;
+
+	/* If MB params buffers are needed... */
+	if (pictres_info->size_info.mbparams_bufsize > 0)
+		/* Allocate the MB parameters buffer info structure. */
+		ret = core_alloc_resbuf(&pictres_int->mb_param_buf,
+					pictres_info->size_info.mbparams_bufsize,
+					core_str_ctx->dd_str_ctx->mmu_str_handle,
+					mem_pool);
+
+	return ret;
+}
+
+/*
+ * @Function              core_stream_resource_create
+ */
+static int core_stream_resource_create(struct core_stream_context *core_str_ctx,
+				       unsigned char closed_gop, unsigned int mem_heap_id,
+				       const struct vdec_comsequ_hdrinfo *comseq_hdrinfo,
+				       const struct vdec_str_opconfig *op_cfg,
+				       const struct vdecdd_ddpict_buf *disp_pict_buf)
+{
+	struct vdecdd_pict_resint *pictres_int = NULL;
+	int ret = IMG_SUCCESS;
+	unsigned int i, start_cnt = 0;
+	struct core_pict_resinfo pictres_info;
+	struct vdecdd_seq_resint *seqres_int = NULL;
+	struct core_seq_resinfo seqres_info;
+	struct vxdio_mempool mem_pool;
+
+	mem_pool.mem_heap_id = mem_heap_id;
+	mem_pool.mem_attrib = (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED
+				| SYS_MEMATTRIB_WRITECOMBINE | SYS_MEMATTRIB_INTERNAL);
+
+#ifdef SEQ_RES_NEEDED
+	seqres_int = lst_first(&core_str_ctx->seq_res_list);
+#endif
+	/*
+	 * Clear the reconstructed picture buffer layout if the previous
+	 * references are no longer used. Only under these circumstances
+	 * should the bitstream resolution change.
+	 */
+	if (closed_gop) {
+		memset(&core_str_ctx->recon_pictbuf.rend_info, 0,
+		       sizeof(core_str_ctx->recon_pictbuf.rend_info));
+		memset(&core_str_ctx->coded_pict_size, 0, sizeof(core_str_ctx->coded_pict_size));
+	} else {
+		if (vdec_size_ne(core_str_ctx->coded_pict_size, comseq_hdrinfo->max_frame_size)) {
+			VDEC_ASSERT(FALSE);
+			pr_err("Coded picture size changed within the closed GOP (i.e. mismatched references)");
+		}
+	}
+
+	/* If current buffers are not suitable for specified VSH/Output config... */
+	if (!core_is_stream_resource_suitable(core_str_ctx, comseq_hdrinfo,
+					      op_cfg, disp_pict_buf, &pictres_info,
+					      &seqres_info)) {
+		/* If full internal resource reallocation is needed... */
+		if (core_do_resource_realloc(core_str_ctx, &pictres_info, &seqres_info)) {
+			/*
+			 * Mark all the active resources as deprecated and
+			 * free-up where no longer used.
+			 */
+			core_stream_resource_deprecate(core_str_ctx);
+		} else {
+			/* Use current buffer size settings. */
+			pictres_info.size_info = core_str_ctx->pict_resinfo.size_info;
+			seqres_info = core_str_ctx->seq_resinfo;
+
+			/* Set start counter to only allocate the number of
+			 * resources that are missing.
+			 */
+			start_cnt = core_str_ctx->pict_resinfo.pict_res_num;
+		}
+
+#ifdef SEQ_RES_NEEDED
+		/* allocate sequence resources */
+		{
+			seqres_int = kzalloc(sizeof(*seqres_int), GFP_KERNEL);
+			VDEC_ASSERT(seqres_int);
+			if (!seqres_int)
+				goto err_out_of_memory;
+
+			lst_add(&core_str_ctx->seq_res_list, seqres_int);
+			/* Allocate sequence buffers common for all standards. */
+			ret = core_alloc_common_sequence_buffers
+							(core_str_ctx, seqres_int, mem_pool,
+							 &seqres_info,
+							 &pictres_info, op_cfg, disp_pict_buf);
+			if (ret != IMG_SUCCESS)
+				goto err_out_of_memory;
+
+			VDEC_ASSERT(core_str_ctx->std_spec_ops);
+			if (core_str_ctx->std_spec_ops->alloc_sequence_buffers) {
+				ret = core_str_ctx->std_spec_ops->alloc_sequence_buffers
+							(core_str_ctx, seqres_int,
+							 mem_pool, &seqres_info);
+				if (ret != IMG_SUCCESS)
+					goto err_out_of_memory;
+			}
+		}
+#endif
+		/* Allocate resources for current settings. */
+		for (i = start_cnt; i < pictres_info.pict_res_num; i++) {
+			/* Allocate the picture resources structure. */
+			pictres_int = kzalloc(sizeof(*pictres_int), GFP_KERNEL);
+			VDEC_ASSERT(pictres_int);
+			if (!pictres_int)
+				goto err_out_of_memory;
+
+			/* Allocate picture buffers common for all standards. */
+			ret = core_alloc_common_pict_buffers(core_str_ctx, pictres_int,
+							     mem_pool, &pictres_info);
+			if (ret != IMG_SUCCESS)
+				goto err_out_of_memory;
+
+			/* Allocate standard specific picture buffers. */
+			VDEC_ASSERT(core_str_ctx->std_spec_ops);
+			if (core_str_ctx->std_spec_ops->alloc_picture_buffers) {
+				ret = core_str_ctx->std_spec_ops->alloc_picture_buffers
+							(core_str_ctx, pictres_int,
+							 mem_pool, &pictres_info);
+				if (ret != IMG_SUCCESS)
+					goto err_out_of_memory;
+			}
+
+			/* attach sequence resources */
+#ifdef SEQ_RES_NEEDED
+			resource_item_use(&seqres_int->ref_count);
+			pictres_int->seq_resint = seqres_int;
+#endif
+			lst_add(&core_str_ctx->pict_res_list, pictres_int);
+			core_str_ctx->pict_resinfo.pict_res_num++;
+		}
+	}
+
+	/*
+	 * When demand for picture resources reduces (in quantity) the extra buffers
+	 * are still retained. Preserve the existing count in case the demand increases
+	 * again, at which time these residual buffers won't need to be reallocated.
+	 */
+	pictres_info.pict_res_num = core_str_ctx->pict_resinfo.pict_res_num;
+
+	/* Store the current resource config. */
+	core_str_ctx->pict_resinfo = pictres_info;
+	core_str_ctx->seq_resinfo = seqres_info;
+
+	pictres_int = lst_first(&core_str_ctx->pict_res_list);
+	while (pictres_int) {
+		/*
+		 * Increment the reference count to indicate that this resource is also
+		 * held by plant until it is added to the Scheduler list. If the resource has
+		 * not just been created it might already be in circulation.
+		 */
+		resource_item_use(&pictres_int->ref_cnt);
+#ifdef SEQ_RES_NEEDED
+		/* attach sequence resources */
+		resource_item_use(&seqres_int->ref_count);
+		pictres_int->seq_resint = seqres_int;
+#endif
+		/* Add the internal picture resources to the list. */
+		ret = resource_list_add_img(&core_str_ctx->aux_pict_res_list,
+					    pictres_int, 0, &pictres_int->ref_cnt);
+
+		pictres_int = lst_next(pictres_int);
+	}
+
+	/*
+	 * Set the reconstructed buffer properties if they
+	 * may have been changed.
+	 */
+	if (core_str_ctx->recon_pictbuf.rend_info.rendered_size == 0) {
+		core_str_ctx->recon_pictbuf.rend_info =
+			disp_pict_buf->rend_info;
+		core_str_ctx->recon_pictbuf.buf_config =
+			disp_pict_buf->buf_config;
+		core_str_ctx->coded_pict_size = comseq_hdrinfo->max_frame_size;
+	} else {
+		if (memcmp(&disp_pict_buf->rend_info,
+			   &core_str_ctx->recon_pictbuf.rend_info,
+			   sizeof(core_str_ctx->recon_pictbuf.rend_info))) {
+			/*
+			 * Reconstructed picture buffer information has changed
+			 * during a closed GOP.
+			 */
+			VDEC_ASSERT
+			("Reconstructed picture buffer information cannot change within a GOP"
+				 == NULL);
+			pr_err("Reconstructed picture buffer information cannot change within a GOP.");
+			return IMG_ERROR_GENERIC_FAILURE;
+		}
+	}
+
+	/*
+	 * When demand for picture resources reduces (in quantity) the extra buffers
+	 * are still retained. Preserve the existing count in case the demand increases
+	 * again, at which time these residual buffers won't need to be reallocated.
+	 */
+	pictres_info.pict_res_num = core_str_ctx->pict_resinfo.pict_res_num;
+
+	/* Store the current resource config. */
+	core_str_ctx->pict_resinfo = pictres_info;
+	core_str_ctx->seq_resinfo = seqres_info;
+
+	return IMG_SUCCESS;
+
+	/* Handle out of memory errors. */
+err_out_of_memory:
+	/* Free resources being currently allocated. */
+	if (pictres_int) {
+		core_free_common_picture_resource(core_str_ctx, pictres_int);
+		if (core_str_ctx->std_spec_ops->free_picture_resource)
+			core_str_ctx->std_spec_ops->free_picture_resource(core_str_ctx,
+				pictres_int);
+
+		kfree(pictres_int);
+	}
+
+#ifdef SEQ_RES_NEEDED
+	if (seqres_int) {
+		core_free_common_sequence_resource(core_str_ctx, seqres_int);
+
+		if (core_str_ctx->std_spec_ops->free_sequence_resource)
+			core_str_ctx->std_spec_ops->free_sequence_resource(core_str_ctx,
+				seqres_int);
+
+		VDEC_ASSERT(lst_last(&core_str_ctx->seq_res_list) == seqres_int);
+		lst_remove(&core_str_ctx->seq_res_list, seqres_int);
+		kfree(seqres_int);
+	}
+#endif
+
+	/* Free all the other resources. */
+	core_stream_resource_destroy(core_str_ctx);
+
+	pr_err("[USERSID=0x%08X] Core not able to allocate stream resources due to lack of memory",
+	       core_str_ctx->dd_str_ctx->str_config_data.user_str_id);
+
+	return IMG_ERROR_OUT_OF_MEMORY;
+}
+
+static int
+core_reconfigure_recon_pictbufs(struct core_stream_context *core_str_ctx,
+				unsigned char no_references)
+{
+	struct vdecdd_ddstr_ctx *dd_str_ctx;
+	int ret;
+
+	dd_str_ctx = core_str_ctx->dd_str_ctx;
+	VDEC_ASSERT(dd_str_ctx->str_op_configured);
+
+	/* Re-configure the internal picture buffers now that none are held. */
+	ret = core_stream_resource_create(core_str_ctx, no_references,
+					  dd_str_ctx->dd_dev_context->internal_heap_id,
+					  &dd_str_ctx->comseq_hdr_info,
+					  &dd_str_ctx->opconfig,
+					  &dd_str_ctx->disp_pict_buf);
+	return ret;
+}
+
+/*
+ * @Function              core_picture_prepare
+ */
+static int core_picture_prepare(struct core_stream_context *core_str_ctx,
+				struct vdecdd_str_unit *str_unit)
+{
+	int ret = IMG_SUCCESS;
+	struct vdecdd_picture *pict_local = NULL;
+	unsigned int avail = 0;
+	unsigned char need_pict_res;
+
+	/*
+	 * For normal decode, setup picture data.
+	 * Preallocate the picture structure.
+	 */
+	pict_local = kzalloc(sizeof(*pict_local), GFP_KERNEL);
+	if (!pict_local)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/* Determine whether the picture can be decoded. */
+	ret = decoder_get_load(core_str_ctx->dd_str_ctx->dec_ctx, &global_avail_slots);
+	if (ret != IMG_SUCCESS) {
+		pr_err("No resources avaialable to decode this picture");
+		ret = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+		goto unwind;
+	}
+
+	/*
+	 * Load and availability is cached in stream context simply
+	 * for status reporting.
+	 */
+	avail = core_get_resource_availability(core_str_ctx);
+
+	if ((avail & CORE_AVAIL_CORE) == 0) {
+		/* Return straight away if the core is not available */
+		ret = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+		goto unwind;
+	}
+
+	if (core_str_ctx->new_op_cfg || core_str_ctx->new_seq) {
+		/*
+		 * Reconstructed buffers should be checked for reconfiguration
+		 * under these conditions:
+		 *     1. New output configuration,
+		 *     2. New sequence.
+		 * Core can decide to reset the reconstructed buffer properties
+		 * if there are no previous reference pictures used
+		 * (i.e. at a closed GOP). This code must go here because we
+		 * may not stop when new sequence is found or references become
+		 * unused.
+		 */
+		ret = core_reconfigure_recon_pictbufs(core_str_ctx,
+						      core_str_ctx->no_prev_refs_used);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			goto unwind;
+	}
+
+	/* Update the display information for this picture. */
+	ret = vdecddutils_get_display_region(&str_unit->pict_hdr_info->coded_frame_size,
+					     &str_unit->pict_hdr_info->disp_info.enc_disp_region,
+					     &str_unit->pict_hdr_info->disp_info.disp_region);
+
+	if (ret != IMG_SUCCESS)
+		goto unwind;
+
+	/* Clear internal state */
+	core_str_ctx->new_seq = FALSE;
+	core_str_ctx->new_op_cfg = FALSE;
+	core_str_ctx->no_prev_refs_used = FALSE;
+
+	/*
+	 * Recalculate this since we might have just created
+	 * internal resources.
+	 */
+	core_str_ctx->res_avail = core_get_resource_availability(core_str_ctx);
+
+	/*
+	 * If picture resources were needed for this stream, picture resources
+	 * list wouldn't be empty
+	 */
+	need_pict_res = !lst_empty(&core_str_ctx->aux_pict_res_list);
+	/* If there are resources available */
+	if ((core_str_ctx->res_avail & CORE_AVAIL_PICTBUF) &&
+	    (!need_pict_res || (core_str_ctx->res_avail & CORE_AVAIL_PICTRES))) {
+		/* Pick internal picture resources. */
+		if (need_pict_res) {
+			pict_local->pict_res_int =
+				resource_list_get_avail(&core_str_ctx->aux_pict_res_list);
+
+			VDEC_ASSERT(pict_local->pict_res_int);
+			if (!pict_local->pict_res_int) {
+				ret = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+				goto unwind;
+			}
+		}
+
+		/* Pick the client image buffer. */
+		pict_local->disp_pict_buf.pict_buf =
+			resource_list_get_avail(&core_str_ctx->pict_buf_list);
+		VDEC_ASSERT(pict_local->disp_pict_buf.pict_buf);
+		if (!pict_local->disp_pict_buf.pict_buf) {
+			ret = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+			goto unwind;
+		}
+	} else {
+		/* Need resources to process picture start. */
+		ret = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+		goto unwind;
+	}
+
+	/* Ensure that the buffer contains layout information. */
+	pict_local->disp_pict_buf.rend_info = core_str_ctx->disp_pict_buf.rend_info;
+	pict_local->disp_pict_buf.buf_config = core_str_ctx->disp_pict_buf.buf_config;
+	pict_local->op_config = core_str_ctx->op_cfg;
+	pict_local->last_pict_in_seq = str_unit->last_pict_in_seq;
+
+	str_unit->dd_pict_data = pict_local;
+
+	/* Indicate that all necessary resources are now available. */
+	if (core_str_ctx->res_avail != ~0) {
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("LAST AVAIL: 0x%08X\n", core_str_ctx->res_avail);
+#endif
+		core_str_ctx->res_avail = ~0;
+	}
+
+#ifdef DEBUG_DECODER_DRIVER
+	/* dump decoder internal resource addresses */
+	if (pict_local->pict_res_int) {
+		if (pict_local->pict_res_int->mb_param_buf) {
+			pr_info("[USERSID=0x%08X] MB parameter buffer device virtual address: 0x%08X",
+				core_str_ctx->dd_str_ctx->str_config_data.user_str_id,
+				pict_local->pict_res_int->mb_param_buf->ddbuf_info.dev_virt);
+		}
+
+		if (core_str_ctx->comseq_hdr_info.separate_chroma_planes) {
+			pr_info("[USERSID=0x%08X] Display picture virtual address: LUMA 0x%08X, CHROMA 0x%08X, CHROMA2 0x%08X",
+				core_str_ctx->dd_str_ctx->str_config_data.user_str_id,
+				pict_local->disp_pict_buf.pict_buf->ddbuf_info.dev_virt,
+				pict_local->disp_pict_buf.pict_buf->ddbuf_info.dev_virt +
+				pict_local->disp_pict_buf.rend_info.plane_info
+						[VDEC_PLANE_VIDEO_U].offset,
+				pict_local->disp_pict_buf.pict_buf->ddbuf_info.dev_virt +
+				pict_local->disp_pict_buf.rend_info.plane_info
+						[VDEC_PLANE_VIDEO_V].offset);
+		} else {
+			pr_info("[USERSID=0x%08X] Display picture virtual address: LUMA 0x%08X, CHROMA 0x%08X",
+				core_str_ctx->dd_str_ctx->str_config_data.user_str_id,
+				pict_local->disp_pict_buf.pict_buf->ddbuf_info.dev_virt,
+				pict_local->disp_pict_buf.pict_buf->ddbuf_info.dev_virt +
+				pict_local->disp_pict_buf.rend_info.plane_info
+						[VDEC_PLANE_VIDEO_UV].offset);
+		}
+	}
+#endif
+
+	ret = core_picture_attach_resources(core_str_ctx, str_unit, TRUE);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto unwind;
+
+	return IMG_SUCCESS;
+
+unwind:
+	if (pict_local->pict_res_int) {
+		resource_item_return(&pict_local->pict_res_int->ref_cnt);
+		pict_local->pict_res_int = NULL;
+	}
+	if (pict_local->disp_pict_buf.pict_buf) {
+		resource_item_return(&pict_local->disp_pict_buf.pict_buf->ddbuf_info.ref_count);
+		pict_local->disp_pict_buf.pict_buf = NULL;
+	}
+	kfree(pict_local);
+	return ret;
+}
+
+/*
+ * @Function              core_validate_new_sequence
+ */
+static int core_validate_new_sequence(struct core_stream_context *core_str_ctx,
+				      const struct vdec_comsequ_hdrinfo *comseq_hdrinfo)
+{
+	int ret;
+	struct vdecdd_supp_check supp_check;
+	struct vdecdd_ddstr_ctx *dd_str_ctx;
+	unsigned int num_req_bufs_prev, num_req_bufs_cur;
+	struct vdecdd_mapbuf_info mapbuf_info;
+
+	memset(&supp_check, 0, sizeof(supp_check));
+
+	/*
+	 * Omit picture header from this setup since we can'supp_check
+	 * validate this here.
+	 */
+	supp_check.comseq_hdrinfo = comseq_hdrinfo;
+
+	if (core_str_ctx->opcfg_set) {
+		supp_check.op_cfg = &core_str_ctx->op_cfg;
+		supp_check.disp_pictbuf = &core_str_ctx->disp_pict_buf;
+
+		ret = vdecddutils_get_minrequired_numpicts
+			(&core_str_ctx->dd_str_ctx->str_config_data,
+			 &core_str_ctx->comseq_hdr_info,
+			 &core_str_ctx->op_cfg,
+			 &num_req_bufs_prev);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		ret = vdecddutils_get_minrequired_numpicts
+			(&core_str_ctx->dd_str_ctx->str_config_data,
+			 comseq_hdrinfo,
+			 &core_str_ctx->op_cfg,
+			 &num_req_bufs_cur);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+	}
+
+	/* Check if the output configuration is compatible with new VSH. */
+	dd_str_ctx = core_str_ctx->dd_str_ctx;
+	mapbuf_info = dd_str_ctx->map_buf_info;
+
+	/* Check the compatibility of the bitstream data and configuration */
+	supp_check.non_cfg_req = TRUE;
+	ret = core_check_decoder_support(dd_str_ctx->dd_dev_context,
+					 &dd_str_ctx->str_config_data,
+					 &dd_str_ctx->prev_comseq_hdr_info,
+					 &dd_str_ctx->prev_pict_hdr_info,
+					 &mapbuf_info, &supp_check);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	core_str_ctx->new_seq = TRUE;
+
+	return IMG_SUCCESS;
+}
+
+static int
+core_validate_new_picture(struct core_stream_context *core_str_ctx,
+			  const struct bspp_pict_hdr_info *pict_hdrinfo,
+			  unsigned int *features)
+{
+	int ret;
+	struct vdecdd_supp_check supp_check;
+	struct vdecdd_ddstr_ctx *dd_str_ctx;
+	struct vdecdd_mapbuf_info mapbuf_info;
+
+	memset(&supp_check, 0, sizeof(supp_check));
+	supp_check.comseq_hdrinfo = &core_str_ctx->comseq_hdr_info;
+	supp_check.pict_hdrinfo = pict_hdrinfo;
+
+	/*
+	 * They cannot become invalid during a sequence.
+	 * However, output configuration may signal something that
+	 * changes compatibility on a closed GOP within a sequence
+	 * (e.g. resolution may significantly decrease
+	 * in a GOP and scaling wouldn't be supported). This resolution shift
+	 * would not be signalled in the sequence header
+	 * (since that is the maximum) but only
+	 * found now when validating the first picture in the GOP.
+	 */
+	if (core_str_ctx->opcfg_set)
+		supp_check.op_cfg = &core_str_ctx->op_cfg;
+
+	/*
+	 * Check if the new picture is compatible with the
+	 * current driver state.
+	 */
+	dd_str_ctx = core_str_ctx->dd_str_ctx;
+	mapbuf_info = dd_str_ctx->map_buf_info;
+
+	/* Check the compatibility of the bitstream data and configuration */
+	supp_check.non_cfg_req = TRUE;
+	ret = core_check_decoder_support(dd_str_ctx->dd_dev_context,
+					 &dd_str_ctx->str_config_data,
+					 &dd_str_ctx->prev_comseq_hdr_info,
+					 &dd_str_ctx->prev_pict_hdr_info,
+					 &mapbuf_info, &supp_check);
+
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	if (supp_check.unsupp_flags.str_opcfg || supp_check.unsupp_flags.pict_hdr)
+		return IMG_ERROR_NOT_SUPPORTED;
+
+	/*
+	 * Clear the reconfiguration flags unless triggered by
+	 * unsupported output config.
+	 */
+	*features = supp_check.features;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function core_stream_submit_unit
+ */
+int core_stream_submit_unit(unsigned int res_str_id, struct vdecdd_str_unit *str_unit)
+{
+	int ret;
+	unsigned char process_str_unit = TRUE;
+
+	struct vdecdd_ddstr_ctx *dd_str_context;
+	struct core_stream_context *core_str_ctx;
+
+	/*
+	 * Stream based messages without a device context
+	 * must have a stream ID.
+	 */
+	VDEC_ASSERT(res_str_id);
+	VDEC_ASSERT(str_unit);
+
+	if (res_str_id == 0 || !str_unit) {
+		pr_err("Invalid params passed to %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(res_str_id, VDECDD_STREAM_TYPE_ID, (void **)&core_str_ctx, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	VDEC_ASSERT(core_str_ctx);
+	dd_str_context = core_str_ctx->dd_str_ctx;
+	VDEC_ASSERT(dd_str_context);
+
+	ret = resource_list_add_img(&core_str_ctx->str_unit_list, str_unit, 0, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+
+	pr_debug("%s stream unit type = %d\n", __func__, str_unit->str_unit_type);
+	switch (str_unit->str_unit_type) {
+	case VDECDD_STRUNIT_SEQUENCE_START:
+		if (str_unit->seq_hdr_info) {
+			/* Add sequence header to cache. */
+			ret =
+				resource_list_replace(&core_str_ctx->seq_hdr_list,
+						      str_unit->seq_hdr_info,
+						      str_unit->seq_hdr_info->sequ_hdr_id,
+						      &str_unit->seq_hdr_info->ref_count,
+						      NULL, NULL);
+
+			if (ret != IMG_SUCCESS)
+				pr_err("[USERSID=0x%08X] Failed to replace resource",
+				       res_str_id);
+		} else {
+			/* ...or take from cache. */
+			str_unit->seq_hdr_info =
+				resource_list_getbyid(&core_str_ctx->seq_hdr_list,
+						      str_unit->seq_hdr_id);
+		}
+
+		VDEC_ASSERT(str_unit->seq_hdr_info);
+		if (!str_unit->seq_hdr_info) {
+			pr_err("Sequence header information not available for current picture");
+			break;
+		}
+		/*
+		 * Check that this latest sequence header information is
+		 * compatible with current state and then if no errors store
+		 * as current.
+		 */
+		core_str_ctx->comseq_hdr_info = str_unit->seq_hdr_info->com_sequ_hdr_info;
+
+		ret = core_validate_new_sequence(core_str_ctx,
+						 &str_unit->seq_hdr_info->com_sequ_hdr_info);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		dd_str_context->prev_comseq_hdr_info =
+			dd_str_context->comseq_hdr_info;
+		dd_str_context->comseq_hdr_info =
+			str_unit->seq_hdr_info->com_sequ_hdr_info;
+
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("[SID=0x%08X] VSH: Maximum Frame Resolution [%dx%d]",
+			dd_str_context->res_str_id,
+			dd_str_context->comseq_hdr_info.max_frame_size.width,
+			dd_str_context->comseq_hdr_info.max_frame_size.height);
+#endif
+
+		break;
+
+	case VDECDD_STRUNIT_PICTURE_START:
+		/*
+		 * Check that the picture configuration is compatible
+		 * with the current state.
+		 */
+		ret = core_validate_new_picture(core_str_ctx,
+						str_unit->pict_hdr_info,
+						&str_unit->features);
+		if (ret != IMG_SUCCESS) {
+			if (ret == IMG_ERROR_NOT_SUPPORTED) {
+				/*
+				 * Do not process stream unit since there is
+				 * something unsupported.
+				 */
+				process_str_unit = FALSE;
+				break;
+			}
+		}
+
+		/* Prepare picture for decoding. */
+		ret = core_picture_prepare(core_str_ctx, str_unit);
+		if (ret != IMG_SUCCESS)
+			if (ret == IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE ||
+			    ret == IMG_ERROR_NOT_SUPPORTED)
+				/*
+				 * Do not process stream unit since there is
+				 * something unsupported or resources are not
+				 * available.
+				 */
+				process_str_unit = FALSE;
+		break;
+
+	default:
+		/*
+		 * Sequence/picture headers should only be attached to
+		 * corresponding units.
+		 */
+		VDEC_ASSERT(!str_unit->seq_hdr_info);
+		VDEC_ASSERT(!str_unit->pict_hdr_info);
+		break;
+	}
+
+	if (process_str_unit) {
+		/* Submit stream unit to the decoder for processing. */
+		str_unit->decode = TRUE;
+		ret = decoder_stream_process_unit(dd_str_context->dec_ctx,
+						  str_unit);
+	} else {
+		ret = IMG_ERROR_GENERIC_FAILURE;
+	}
+
+	return ret;
+}
+
+/*
+ * @Function  core_stream_fill_pictbuf
+ */
+int core_stream_fill_pictbuf(unsigned int buf_map_id)
+{
+	int ret;
+	struct vdecdd_ddbuf_mapinfo *ddbuf_map_info;
+	struct vdecdd_ddstr_ctx *dd_str_ctx;
+	struct core_stream_context *core_str_ctx;
+
+	/* Get access to map info context.. */
+	ret = rman_get_resource(buf_map_id, VDECDD_BUFMAP_TYPE_ID,
+				(void **)&ddbuf_map_info, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	dd_str_ctx = ddbuf_map_info->ddstr_context;
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(dd_str_ctx->res_str_id, VDECDD_STREAM_TYPE_ID,
+				(void **)&core_str_ctx, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	/* Check buffer type. */
+	VDEC_ASSERT(ddbuf_map_info->buf_type == VDEC_BUFTYPE_PICTURE);
+
+	/* Add the image buffer to the list */
+	ret = resource_list_add_img(&core_str_ctx->pict_buf_list, ddbuf_map_info,
+				    0, &ddbuf_map_info->ddbuf_info.ref_count);
+
+	return ret;
+}
+
+/*
+ * @Function              core_fn_free_mapped
+ */
+static void core_fn_free_mapped(void *param)
+{
+	struct vdecdd_ddbuf_mapinfo *ddbuf_map_info =
+		(struct vdecdd_ddbuf_mapinfo *)param;
+
+	/* Validate input arguments */
+	VDEC_ASSERT(param);
+
+	/* Do not free the MMU mapping. It is handled by talmmu code. */
+	kfree(ddbuf_map_info);
+}
+
+/*
+ * @Function              core_stream_map_buf
+ */
+int core_stream_map_buf(unsigned int res_str_id, enum vdec_buf_type buf_type,
+			struct vdec_buf_info *buf_info, unsigned int *buf_map_id)
+{
+	int ret;
+	struct vdecdd_ddstr_ctx *dd_str_ctx;
+	struct core_stream_context *core_str_ctx;
+	struct vdecdd_ddbuf_mapinfo *ddbuf_map_info;
+
+	/*
+	 * Stream based messages without a device context
+	 * must have a stream ID.
+	 */
+	VDEC_ASSERT(res_str_id);
+	VDEC_ASSERT(buf_type < VDEC_BUFTYPE_MAX);
+	VDEC_ASSERT(buf_info);
+	VDEC_ASSERT(buf_map_id);
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(res_str_id, VDECDD_STREAM_TYPE_ID,
+				(void **)&core_str_ctx, NULL);
+
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	dd_str_ctx = core_str_ctx->dd_str_ctx;
+
+	VDEC_ASSERT(dd_str_ctx);
+
+	/* Allocate an active stream unit.. */
+	ddbuf_map_info = kzalloc(sizeof(*ddbuf_map_info), GFP_KERNEL);
+	VDEC_ASSERT(ddbuf_map_info);
+
+	if (!ddbuf_map_info) {
+		pr_err("[SID=0x%08X] Failed to allocate memory for DD buffer map information",
+		       dd_str_ctx->res_str_id);
+
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+	memset(ddbuf_map_info, 0, sizeof(*ddbuf_map_info));
+
+	/* Save the stream context etc. */
+	ddbuf_map_info->ddstr_context   = dd_str_ctx;
+	ddbuf_map_info->buf_type        = buf_type;
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s:%d vdec2plus: vxd map buff id %d", __func__, __LINE__,
+		buf_info->buf_id);
+#endif
+	ddbuf_map_info->buf_id = buf_info->buf_id;
+
+	/* Register the allocation as a stream resource.. */
+	ret = rman_register_resource(dd_str_ctx->res_buck_handle,
+				     VDECDD_BUFMAP_TYPE_ID,
+				     core_fn_free_mapped,
+				     ddbuf_map_info,
+				     &ddbuf_map_info->res_handle,
+				     buf_map_id);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	ddbuf_map_info->buf_map_id = *buf_map_id;
+
+	if (buf_type == VDEC_BUFTYPE_PICTURE) {
+		if (dd_str_ctx->map_buf_info.num_buf == 0) {
+			dd_str_ctx->map_buf_info.buf_size = buf_info->buf_size;
+			dd_str_ctx->map_buf_info.byte_interleave =
+				buf_info->pictbuf_cfg.byte_interleave;
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("[SID=0x%08X] Mapped Buffer size: %d (bytes)",
+				dd_str_ctx->res_str_id, buf_info->buf_size);
+#endif
+		} else {
+			/*
+			 * Same byte interleaved setting should be used.
+			 * Convert to actual bools by comparing with zero.
+			 */
+			if (buf_info->pictbuf_cfg.byte_interleave !=
+				dd_str_ctx->map_buf_info.byte_interleave) {
+				pr_err("[SID=0x%08X] Buffer cannot be mapped since its byte interleave value (%s) is not the same as buffers already mapped (%s)",
+				       dd_str_ctx->res_str_id,
+				       buf_info->pictbuf_cfg.byte_interleave ?
+				       "ON" : "OFF",
+				       dd_str_ctx->map_buf_info.byte_interleave ?
+				       "ON" : "OFF");
+				ret = IMG_ERROR_INVALID_PARAMETERS;
+				goto error;
+			}
+		}
+
+		/* Configure the buffer.. */
+		ret = core_stream_set_pictbuf_config(dd_str_ctx, &buf_info->pictbuf_cfg);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			goto error;
+	}
+
+	/* Map heap from VDEC to MMU. */
+	switch (buf_type) {
+	case VDEC_BUFTYPE_BITSTREAM:
+		ddbuf_map_info->mmuheap_id = MMU_HEAP_BITSTREAM_BUFFERS;
+		break;
+
+	case VDEC_BUFTYPE_PICTURE:
+		mmu_get_heap(buf_info->pictbuf_cfg.stride[VDEC_PLANE_VIDEO_Y],
+			     &ddbuf_map_info->mmuheap_id);
+		break;
+
+	default:
+		VDEC_ASSERT(FALSE);
+	}
+
+	/* Map this buffer into the MMU. */
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("----- %s:%d calling MMU_StreamMapExt", __func__, __LINE__);
+#endif
+	ret = mmu_stream_map_ext(dd_str_ctx->mmu_str_handle,
+				 (enum mmu_eheap_id)ddbuf_map_info->mmuheap_id,
+				 ddbuf_map_info->buf_id,
+				 buf_info->buf_size, DEV_MMU_PAGE_SIZE,
+				 buf_info->mem_attrib,
+				 buf_info->cpu_linear_addr,
+				 &ddbuf_map_info->ddbuf_info);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	if (buf_type == VDEC_BUFTYPE_PICTURE)
+		dd_str_ctx->map_buf_info.num_buf++;
+
+	/*
+	 * Initialise the reference count to indicate that the client
+	 * still holds the buffer.
+	 */
+	ddbuf_map_info->ddbuf_info.ref_count = 1;
+
+	/* Return success.. */
+	return IMG_SUCCESS;
+
+error:
+	if (ddbuf_map_info) {
+		if (ddbuf_map_info->res_handle)
+			rman_free_resource(ddbuf_map_info->res_handle);
+		else
+			kfree(ddbuf_map_info);
+	}
+
+	return ret;
+}
+
+/*
+ * @Function              core_stream_map_buf_sg
+ */
+int core_stream_map_buf_sg(unsigned int res_str_id, enum vdec_buf_type buf_type,
+			   struct vdec_buf_info *buf_info,
+			   void *sgt, unsigned int *buf_map_id)
+{
+	int ret;
+	struct vdecdd_ddstr_ctx *dd_str_ctx;
+	struct core_stream_context *core_str_ctx;
+	struct vdecdd_ddbuf_mapinfo *ddbuf_map_info;
+
+	/*
+	 * Resource stream ID cannot be zero. If zero just warning and
+	 * proceeding further will break the code. Return IMG_ERROR_INVALID_ID.
+	 */
+	if (res_str_id <= 0)
+		return IMG_ERROR_INVALID_ID;
+
+	VDEC_ASSERT(buf_type < VDEC_BUFTYPE_MAX);
+	VDEC_ASSERT(buf_info);
+	VDEC_ASSERT(buf_map_id);
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(res_str_id, VDECDD_STREAM_TYPE_ID, (void **)&core_str_ctx, NULL);
+
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	dd_str_ctx = core_str_ctx->dd_str_ctx;
+
+	VDEC_ASSERT(dd_str_ctx);
+
+	/* Allocate an active stream unit.. */
+	ddbuf_map_info = kzalloc(sizeof(*ddbuf_map_info), GFP_KERNEL);
+	VDEC_ASSERT(ddbuf_map_info);
+
+	if (!ddbuf_map_info) {
+		pr_err("[SID=0x%08X] Failed to allocate memory for DD buffer map information",
+		       dd_str_ctx->res_str_id);
+
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* Save the stream context etc. */
+	ddbuf_map_info->ddstr_context = dd_str_ctx;
+	ddbuf_map_info->buf_type = buf_type;
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s:%d vdec2plus: vxd map buff id %d", __func__, __LINE__,
+		buf_info->buf_id);
+#endif
+	ddbuf_map_info->buf_id = buf_info->buf_id;
+
+	/* Register the allocation as a stream resource.. */
+	ret = rman_register_resource(dd_str_ctx->res_buck_handle,
+				     VDECDD_BUFMAP_TYPE_ID,
+				     core_fn_free_mapped, ddbuf_map_info,
+				     &ddbuf_map_info->res_handle, buf_map_id);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	ddbuf_map_info->buf_map_id = *buf_map_id;
+
+	if (buf_type == VDEC_BUFTYPE_PICTURE) {
+		if (dd_str_ctx->map_buf_info.num_buf == 0) {
+			dd_str_ctx->map_buf_info.buf_size = buf_info->buf_size;
+
+			dd_str_ctx->map_buf_info.byte_interleave =
+				buf_info->pictbuf_cfg.byte_interleave;
+
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("[SID=0x%08X] Mapped Buffer size: %d (bytes)",
+				dd_str_ctx->res_str_id, buf_info->buf_size);
+#endif
+		} else {
+			/*
+			 * Same byte interleaved setting should be used.
+			 * Convert to actual bools by comparing with zero.
+			 */
+			if (buf_info->pictbuf_cfg.byte_interleave !=
+				dd_str_ctx->map_buf_info.byte_interleave) {
+				pr_err("[SID=0x%08X] Buffer cannot be mapped since its byte interleave value (%s) is not the same as buffers already mapped (%s)",
+				       dd_str_ctx->res_str_id,
+				       buf_info->pictbuf_cfg.byte_interleave ?
+				       "ON" : "OFF",
+				       dd_str_ctx->map_buf_info.byte_interleave ?
+				       "ON" : "OFF");
+				ret = IMG_ERROR_INVALID_PARAMETERS;
+				goto error;
+			}
+		}
+
+		/* Configure the buffer.. */
+		ret = core_stream_set_pictbuf_config(dd_str_ctx, &buf_info->pictbuf_cfg);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			goto error;
+	}
+
+	/* Map heap from VDEC to MMU. */
+	switch (buf_type) {
+	case VDEC_BUFTYPE_BITSTREAM:
+		ddbuf_map_info->mmuheap_id = MMU_HEAP_BITSTREAM_BUFFERS;
+		break;
+
+	case VDEC_BUFTYPE_PICTURE:
+		mmu_get_heap(buf_info->pictbuf_cfg.stride[VDEC_PLANE_VIDEO_Y],
+			     &ddbuf_map_info->mmuheap_id);
+		break;
+
+	default:
+		VDEC_ASSERT(FALSE);
+	}
+
+	/* Map this buffer into the MMU. */
+#ifdef	DEBUG_DECODER_DRIVER
+	pr_info("----- %s:%d calling MMU_StreamMapExt_sg", __func__, __LINE__);
+#endif
+	ret =
+		mmu_stream_map_ext_sg(dd_str_ctx->mmu_str_handle,
+				      (enum mmu_eheap_id)ddbuf_map_info->mmuheap_id,
+				      sgt, buf_info->buf_size, DEV_MMU_PAGE_SIZE,
+				      buf_info->mem_attrib, buf_info->cpu_linear_addr,
+				      &ddbuf_map_info->ddbuf_info,
+				      &ddbuf_map_info->buf_id);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	if (buf_type == VDEC_BUFTYPE_PICTURE)
+		dd_str_ctx->map_buf_info.num_buf++;
+
+	/*
+	 * Initialise the reference count to indicate that the client
+	 * still holds the buffer.
+	 */
+	ddbuf_map_info->ddbuf_info.ref_count = 1;
+
+	/* Return success.. */
+	return IMG_SUCCESS;
+
+error:
+	if (ddbuf_map_info->res_handle)
+		rman_free_resource(ddbuf_map_info->res_handle);
+	else
+		kfree(ddbuf_map_info);
+
+	return ret;
+}
+
+/*
+ * @Function  core_stream_unmap_buf
+ */
+int core_stream_unmap_buf(unsigned int buf_map_id)
+{
+	int ret;
+	struct vdecdd_ddbuf_mapinfo *ddbuf_map_info;
+	struct vdecdd_ddstr_ctx *dd_str_ctx;
+	struct core_stream_context *core_str_ctx;
+
+	/* Get access to map info context.. */
+	ret = rman_get_resource(buf_map_id, VDECDD_BUFMAP_TYPE_ID,
+				(void **)&ddbuf_map_info, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	dd_str_ctx = ddbuf_map_info->ddstr_context;
+	VDEC_ASSERT(dd_str_ctx);
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(dd_str_ctx->res_str_id, VDECDD_STREAM_TYPE_ID,
+				(void **)&core_str_ctx, NULL);
+	VDEC_ASSERT(core_str_ctx);
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("UNMAP: PM [0x%p] --> VM [0x%08X - 0x%08X] (%d bytes)",
+		ddbuf_map_info->ddbuf_info.cpu_virt,
+		ddbuf_map_info->ddbuf_info.dev_virt,
+		ddbuf_map_info->ddbuf_info.dev_virt +
+		ddbuf_map_info->ddbuf_info.buf_size,
+		ddbuf_map_info->ddbuf_info.buf_size);
+#endif
+
+	/* Buffer should only be held by the client. */
+	VDEC_ASSERT(ddbuf_map_info->ddbuf_info.ref_count == 1);
+	if (ddbuf_map_info->ddbuf_info.ref_count != 1)
+		return IMG_ERROR_MEMORY_IN_USE;
+
+	ddbuf_map_info->ddbuf_info.ref_count = 0;
+	if (ddbuf_map_info->buf_type == VDEC_BUFTYPE_PICTURE) {
+		/* Remove this picture buffer from pictbuf list */
+		ret = resource_list_remove(&core_str_ctx->pict_buf_list, ddbuf_map_info);
+
+		VDEC_ASSERT(ret == IMG_SUCCESS || ret == IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE);
+		if (ret != IMG_SUCCESS && ret != IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE)
+			return ret;
+
+		ddbuf_map_info->ddstr_context->map_buf_info.num_buf--;
+
+		/* Clear some state if there are no more mapped buffers. */
+		if (dd_str_ctx->map_buf_info.num_buf == 0) {
+			dd_str_ctx->map_buf_info.buf_size = 0;
+			dd_str_ctx->map_buf_info.byte_interleave = FALSE;
+		}
+	}
+
+	/* Unmap this buffer from the MMU. */
+	ret = mmu_free_mem(dd_str_ctx->mmu_str_handle, &ddbuf_map_info->ddbuf_info);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	/* Free buffer map info. */
+	rman_free_resource(ddbuf_map_info->res_handle);
+
+	/* Return success.. */
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function              core_stream_unmap_buf_sg
+ */
+int core_stream_unmap_buf_sg(unsigned int buf_map_id)
+{
+	int ret;
+	struct vdecdd_ddbuf_mapinfo *ddbuf_map_info;
+	struct vdecdd_ddstr_ctx *dd_str_ctx;
+	struct core_stream_context *core_str_ctx;
+
+	/* Get access to map info context.. */
+	ret = rman_get_resource(buf_map_id, VDECDD_BUFMAP_TYPE_ID, (void **)&ddbuf_map_info, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	dd_str_ctx = ddbuf_map_info->ddstr_context;
+	VDEC_ASSERT(dd_str_ctx);
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(dd_str_ctx->res_str_id, VDECDD_STREAM_TYPE_ID,
+				(void **)&core_str_ctx, NULL);
+	VDEC_ASSERT(core_str_ctx);
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("UNMAP: PM [0x%p] --> VM [0x%08X - 0x%08X] (%d bytes)",
+		ddbuf_map_info->ddbuf_info.cpu_virt,
+		ddbuf_map_info->ddbuf_info.dev_virt,
+		ddbuf_map_info->ddbuf_info.dev_virt +
+		ddbuf_map_info->ddbuf_info.buf_size,
+		ddbuf_map_info->ddbuf_info.buf_size);
+#endif
+
+	/* Buffer should only be held by the client. */
+	VDEC_ASSERT(ddbuf_map_info->ddbuf_info.ref_count == 1);
+	if (ddbuf_map_info->ddbuf_info.ref_count != 1)
+		return IMG_ERROR_MEMORY_IN_USE;
+
+	ddbuf_map_info->ddbuf_info.ref_count = 0;
+
+	if (ddbuf_map_info->buf_type == VDEC_BUFTYPE_PICTURE) {
+		/* Remove this picture buffer from pictbuf list */
+		ret = resource_list_remove(&core_str_ctx->pict_buf_list, ddbuf_map_info);
+
+		VDEC_ASSERT(ret == IMG_SUCCESS || ret == IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE);
+		if (ret != IMG_SUCCESS && ret != IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE)
+			return ret;
+
+		ddbuf_map_info->ddstr_context->map_buf_info.num_buf--;
+
+		/*
+		 * Clear some state if there are no more
+		 * mapped buffers.
+		 */
+		if (dd_str_ctx->map_buf_info.num_buf == 0) {
+			dd_str_ctx->map_buf_info.buf_size = 0;
+			dd_str_ctx->map_buf_info.byte_interleave = FALSE;
+		}
+	}
+
+	/* Unmap this buffer from the MMU. */
+	ret = mmu_free_mem_sg(dd_str_ctx->mmu_str_handle, &ddbuf_map_info->ddbuf_info);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	/* Free buffer map info. */
+	rman_free_resource(ddbuf_map_info->res_handle);
+
+	/* Return success.. */
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function              core_stream_flush
+ */
+int core_stream_flush(unsigned int res_str_id, unsigned char discard_refs)
+{
+	struct vdecdd_ddstr_ctx *dd_str_ctx;
+	struct core_stream_context *core_str_ctx;
+	int ret;
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(res_str_id, VDECDD_STREAM_TYPE_ID,
+				(void **)&core_str_ctx, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	dd_str_ctx = core_str_ctx->dd_str_ctx;
+
+	VDEC_ASSERT(dd_str_ctx);
+	VDEC_ASSERT(dd_str_ctx->dd_str_state == VDECDD_STRSTATE_STOPPED);
+
+	/*
+	 * If unsupported sequence is found, we need to do additional
+	 * check for DPB flush condition
+	 */
+	if (!dd_str_ctx->comseq_hdr_info.not_dpb_flush) {
+		ret = decoder_stream_flush(dd_str_ctx->dec_ctx, discard_refs);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+	}
+
+	/* Return success.. */
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function              core_stream_release_bufs
+ */
+int core_stream_release_bufs(unsigned int res_str_id, enum vdec_buf_type buf_type)
+{
+	int ret;
+	struct core_stream_context *core_str_ctx;
+	struct vdecdd_ddstr_ctx *dd_str_ctx;
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(res_str_id, VDECDD_STREAM_TYPE_ID, (void **)&core_str_ctx, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	dd_str_ctx = core_str_ctx->dd_str_ctx;
+
+	VDEC_ASSERT(dd_str_ctx);
+	VDEC_ASSERT(buf_type < VDEC_BUFTYPE_MAX);
+
+	switch (buf_type) {
+	case VDEC_BUFTYPE_PICTURE:
+	{
+		/* Empty all the decoded picture related buffer lists. */
+		ret = resource_list_empty(&core_str_ctx->pict_buf_list, TRUE, NULL, NULL);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		break;
+	}
+
+	case VDEC_BUFTYPE_BITSTREAM:
+	{
+		/* Empty the stream unit queue. */
+		ret = resource_list_empty(&core_str_ctx->str_unit_list, FALSE,
+					  (resource_pfn_freeitem)core_fn_free_stream_unit,
+					   core_str_ctx);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		break;
+	}
+
+	case VDEC_BUFTYPE_ALL:
+	{
+		/* Empty all the decoded picture related buffer lists. */
+		ret = resource_list_empty(&core_str_ctx->pict_buf_list, TRUE, NULL, NULL);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+
+		/* Empty the stream unit queue. */
+		ret = resource_list_empty(&core_str_ctx->str_unit_list, FALSE,
+					  (resource_pfn_freeitem)core_fn_free_stream_unit,
+					   core_str_ctx);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		break;
+	}
+
+	default:
+	{
+		ret = IMG_ERROR_INVALID_PARAMETERS;
+		VDEC_ASSERT(FALSE);
+		break;
+	}
+	}
+
+	if (buf_type == VDEC_BUFTYPE_PICTURE || buf_type == VDEC_BUFTYPE_ALL) {
+		ret = decoder_stream_release_buffers(dd_str_ctx->dec_ctx);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+	}
+
+	/* Return success.. */
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function              core_stream_get_status
+ */
+int core_stream_get_status(unsigned int res_str_id,
+			   struct vdecdd_decstr_status *str_st)
+{
+	int ret;
+	struct core_stream_context *core_str_ctx;
+	struct vdecdd_ddstr_ctx *dd_str_ctx;
+
+	/* Get access to stream context.. */
+	ret = rman_get_resource(res_str_id, VDECDD_STREAM_TYPE_ID, (void **)&core_str_ctx, NULL);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	dd_str_ctx = core_str_ctx->dd_str_ctx;
+
+	VDEC_ASSERT(dd_str_ctx);
+	VDEC_ASSERT(str_st);
+
+	ret = decoder_stream_get_status(dd_str_ctx->dec_ctx, str_st);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	/* Return success.. */
+	return IMG_SUCCESS;
+}
+
+#ifdef HAS_HEVC
+/*
+ * @Function              core_free_hevc_picture_resource
+ */
+static int core_free_hevc_picture_resource(struct core_stream_context *core_strctx,
+					   struct vdecdd_pict_resint *pic_res_int)
+{
+	int ret = IMG_SUCCESS;
+
+	ret = core_free_resbuf(&pic_res_int->genc_fragment_buf,
+			       core_strctx->dd_str_ctx->mmu_str_handle);
+	if (ret != IMG_SUCCESS)
+		pr_err("MMU_Free for Genc Fragment buffer failed with error %u", ret);
+
+	return ret;
+}
+
+/*
+ * @Function              core_free_hevc_sequence_resource
+ */
+static int core_free_hevc_sequence_resource(struct core_stream_context *core_strctx,
+					    struct vdecdd_seq_resint *seq_res_int)
+{
+	unsigned int i;
+	int local_result = IMG_SUCCESS;
+	int ret = IMG_SUCCESS;
+
+	for (i = 0; i < GENC_BUFF_COUNT; ++i) {
+		local_result = core_free_resbuf(&seq_res_int->genc_buffers[i],
+						core_strctx->dd_str_ctx->mmu_str_handle);
+		if (local_result != IMG_SUCCESS) {
+			ret = local_result;
+			pr_warn("MMU_Free for GENC buffer %u failed with error %u", i,
+				local_result);
+		}
+	}
+
+	local_result = core_free_resbuf(&seq_res_int->intra_buffer,
+					core_strctx->dd_str_ctx->mmu_str_handle);
+	if (local_result != IMG_SUCCESS) {
+		ret = local_result;
+		pr_warn("MMU_Free for GENC buffer %u failed with error %u", i, local_result);
+	}
+
+	local_result = core_free_resbuf(&seq_res_int->aux_buffer,
+					core_strctx->dd_str_ctx->mmu_str_handle);
+	if (local_result != IMG_SUCCESS) {
+		ret = local_result;
+		pr_warn("MMU_Free for GENC buffer %u failed with error %u", i, local_result);
+	}
+
+	return ret;
+}
+
+/*
+ * @Function              core_hevc_bufs_get_size
+ */
+static int core_hevc_bufs_get_size(struct core_stream_context *core_strctx,
+				   const struct vdec_comsequ_hdrinfo *seqhdr_info,
+				   struct vdec_pict_size *max_pict_size,
+				   struct core_pict_bufsize_info *size_info,
+				   struct core_seq_resinfo *seqres_info,
+				   unsigned char *resource_needed)
+{
+	enum vdec_vid_std vid_std = core_strctx->dd_str_ctx->str_config_data.vid_std;
+	unsigned int std_idx = vid_std - 1;
+
+	static const unsigned short max_slice_segments_list
+		[HEVC_LEVEL_MAJOR_NUM][HEVC_LEVEL_MINOR_NUM] = {
+		/* level: 1.0  1.1  1.2  */
+		{ 16,    0,   0, },
+		/* level: 2.0  2.1  2.2  */
+		{ 16,   20,   0, },
+		/* level: 3.0  3.1  3.2  */
+		{ 30,   40,   0, },
+		/* level: 4.0  4.1  4.2  */
+		{ 75,   75,   0, },
+		/* level: 5.0  5.1  5.2  */
+		{ 200, 200, 200, },
+		/* level: 6.0  6.1  6.2  */
+		{ 600, 600, 600, }
+	};
+
+	static const unsigned char max_tile_cols_list
+		[HEVC_LEVEL_MAJOR_NUM][HEVC_LEVEL_MINOR_NUM] = {
+		/* level: 1.0  1.1  1.2  */
+		{   1,   0,   0, },
+		/* level: 2.0  2.1  2.2  */
+		{   1,   1,   0, },
+		/* level: 3.0  3.1  3.2  */
+		{   2,   3,   0, },
+		/* level: 4.0  4.1  4.2  */
+		{   5,   5,   0, },
+		/* level: 5.0  5.1  5.2  */
+		{  10,  10,  10, },
+		/* level: 6.0  6.1  6.2  */
+		{  20,  20,  20, }
+	};
+
+	/* TRM 3.11.11 */
+	static const unsigned int total_sample_per_mb[PIXEL_FORMAT_444 + 1] = {
+		256, 384, 384, 512, 768};
+
+	static const unsigned int HEVC_LEVEL_IDC_MIN = 30;
+	static const unsigned int HEVC_LEVEL_IDC_MAX = 186;
+	static const unsigned int GENC_ALIGNMENT = 0x1000;
+	static const unsigned int mb_size = 16;
+	static const unsigned int max_mb_rows_in_ctu = 4;
+	static const unsigned int bytes_per_fragment_pointer = 16;
+
+	const unsigned int max_tile_height_in_mbs =
+		seqhdr_info->max_frame_size.height / mb_size;
+
+	signed char level_maj = seqhdr_info->codec_level / 30;
+	signed char level_min = (seqhdr_info->codec_level % 30) / 3;
+
+	/*
+	 * If we are somehow able to deliver more information here (CTU size,
+	 * number of tile columns/rows) then memory usage could be reduced
+	 */
+	const struct pixel_pixinfo *pix_info = &seqhdr_info->pixel_info;
+	const unsigned int bit_depth = pix_info->bitdepth_y >= pix_info->bitdepth_c ?
+		pix_info->bitdepth_y : pix_info->bitdepth_c;
+	unsigned short max_slice_segments;
+	unsigned char max_tile_cols;
+	unsigned int raw_byte_per_mb;
+	unsigned int *genc_fragment_bufsize;
+	unsigned int *genc_buf_size;
+
+	/* Reset the MB parameters buffer size. */
+	size_info->mbparams_bufsize = 0;
+	*resource_needed = TRUE;
+
+	if (mbparam_allocinfo[std_idx].alloc_mbparam_bufs) {
+		/* shall be == 64 (0x40)*/
+		const unsigned int align = mbparam_allocinfo[std_idx].mbparam_size;
+		const unsigned int dpb_width = (max_pict_size->width + align * 2 - 1) / align * 2;
+		const unsigned int pic_height = (max_pict_size->height + align - 1) / align;
+		const unsigned int pic_width = (max_pict_size->width + align - 1) / align;
+
+		/* calculating for worst case: max frame size, B-frame */
+		size_info->mbparams_bufsize = (align * 2) * pic_width * pic_height +
+			align * dpb_width * pic_height;
+
+		/* Adjust the buffer size for MSVDX. */
+		vdecddutils_buf_vxd_adjust_size(&size_info->mbparams_bufsize);
+	}
+
+	if (seqhdr_info->codec_level > HEVC_LEVEL_IDC_MAX ||
+	    seqhdr_info->codec_level < HEVC_LEVEL_IDC_MIN) {
+		level_maj = 6;
+		level_min = 2;
+	}
+
+	if (level_maj > 0 && level_maj <= HEVC_LEVEL_MAJOR_NUM &&
+	    level_min >= 0 && level_min < HEVC_LEVEL_MINOR_NUM) {
+		max_slice_segments = max_slice_segments_list[level_maj - 1][level_min];
+		max_tile_cols = max_tile_cols_list[level_maj - 1][level_min];
+	} else {
+		pr_err("%s: Invalid parameters\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	raw_byte_per_mb = total_sample_per_mb[pix_info->chroma_fmt_idc] *
+		VDEC_ALIGN_SIZE(bit_depth, 8, unsigned int, int) / 8;
+
+	genc_fragment_bufsize = &size_info->hevc_bufsize_pict.genc_fragment_bufsize;
+	genc_buf_size = &seqres_info->hevc_bufsize_seqres.genc_bufsize;
+
+	*genc_fragment_bufsize = bytes_per_fragment_pointer * (seqhdr_info->max_frame_size.height /
+		mb_size * max_tile_cols + max_slice_segments - 1) * max_mb_rows_in_ctu;
+
+	/*
+	 * GencBufferSize formula is taken from TRM and found by HW * CSIM teams for a sensible
+	 * streams i.e. size_of_stream < size_of_output_YUV. In videostream data base it's
+	 * possible to find pathological Argon streams that do not fulfill this sensible
+	 * requirement. eg. #58417, #58419, #58421, #58423. To make a #58417 stream running the
+	 * formula below should be changed from (2 * 384) *... ---> (3 * 384) *...
+	 * This solution is applied by DEVA.
+	 */
+	*genc_buf_size = 2 * raw_byte_per_mb * seqhdr_info->max_frame_size.width /
+		mb_size * max_tile_height_in_mbs / 4;
+
+	*genc_buf_size = VDEC_ALIGN_SIZE(*genc_buf_size, GENC_ALIGNMENT,
+					 unsigned int, unsigned int);
+	*genc_fragment_bufsize = VDEC_ALIGN_SIZE(*genc_fragment_bufsize, GENC_ALIGNMENT,
+						 unsigned int, unsigned int);
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("Sizes for GENC in HEVC: 0x%X (frag), 0x%X (x4)",
+		*genc_fragment_bufsize,
+		*genc_buf_size);
+#endif
+
+	seqres_info->hevc_bufsize_seqres.intra_bufsize = 4 * seqhdr_info->max_frame_size.width;
+	if (seqhdr_info->pixel_info.mem_pkg != PIXEL_BIT8_MP)
+		seqres_info->hevc_bufsize_seqres.intra_bufsize *= 2;
+
+	seqres_info->hevc_bufsize_seqres.aux_bufsize = (512 * 1024);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function              core_is_hevc_stream_resource_suitable
+ */
+static unsigned char
+core_is_hevc_stream_resource_suitable(struct core_pict_resinfo *pict_res_info,
+				      struct core_pict_resinfo *old_pict_res_info,
+				      struct core_seq_resinfo *seq_res_info,
+				      struct core_seq_resinfo *old_seq_res_info)
+{
+	return (seq_res_info->hevc_bufsize_seqres.genc_bufsize <=
+	       old_seq_res_info->hevc_bufsize_seqres.genc_bufsize &&
+	       seq_res_info->hevc_bufsize_seqres.intra_bufsize <=
+	       old_seq_res_info->hevc_bufsize_seqres.intra_bufsize &&
+	       seq_res_info->hevc_bufsize_seqres.aux_bufsize <=
+	       old_seq_res_info->hevc_bufsize_seqres.aux_bufsize &&
+	       pict_res_info->size_info.hevc_bufsize_pict.genc_fragment_bufsize <=
+	       old_pict_res_info->size_info.hevc_bufsize_pict.genc_fragment_bufsize);
+}
+
+/*
+ * @Function  core_alloc_hevc_specific_seq_buffers
+ */
+static int
+core_alloc_hevc_specific_seq_buffers(struct core_stream_context *core_strctx,
+				     struct vdecdd_seq_resint *seqres_int,
+				     struct vxdio_mempool mempool,
+				     struct core_seq_resinfo *seqres_info)
+{
+	unsigned int i;
+	int ret = IMG_SUCCESS;
+
+	/* Allocate GENC buffers */
+	for (i = 0; i < GENC_BUFF_COUNT; ++i) {
+		/* Allocate the GENC buffer info structure. */
+		ret = core_alloc_resbuf(&seqres_int->genc_buffers[i],
+					seqres_info->hevc_bufsize_seqres.genc_bufsize,
+					core_strctx->dd_str_ctx->mmu_str_handle,
+					mempool);
+		if (ret != IMG_SUCCESS)
+			return ret;
+	}
+
+	seqres_int->genc_buf_id = ++core_strctx->std_spec_context.hevc_ctx.genc_id_gen;
+
+	/* Allocate the intra buffer info structure. */
+	ret = core_alloc_resbuf(&seqres_int->intra_buffer,
+				seqres_info->hevc_bufsize_seqres.intra_bufsize,
+				core_strctx->dd_str_ctx->mmu_str_handle,
+				mempool);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	/* Allocate the aux buffer info structure. */
+	ret = core_alloc_resbuf(&seqres_int->aux_buffer,
+				seqres_info->hevc_bufsize_seqres.aux_bufsize,
+				core_strctx->dd_str_ctx->mmu_str_handle,
+				mempool);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function              core_alloc_hevc_specific_pict_buffers
+ */
+static int
+core_alloc_hevc_specific_pict_buffers(struct core_stream_context *core_strctx,
+				      struct vdecdd_pict_resint *pict_res_int,
+				      struct vxdio_mempool mempool,
+				      struct core_pict_resinfo *pict_res_info)
+{
+	int ret;
+
+	/* Allocate the GENC fragment buffer. */
+	ret = core_alloc_resbuf(&pict_res_int->genc_fragment_buf,
+				pict_res_info->size_info.hevc_bufsize_pict.genc_fragment_bufsize,
+				core_strctx->dd_str_ctx->mmu_str_handle,
+				mempool);
+
+	return ret;
+}
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/core.h b/drivers/media/platform/img/vxe-vxd/decoder/core.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/core.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/core.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD Decoder CORE and V4L2 Node Interface header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *      Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *      Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#ifndef __CORE_H__
+#define __CORE_H__
+
+#include <linux/types.h>
+#include "decoder.h"
+
+int core_initialise(void *dev_handle, unsigned int internal_heap_id,
+		    void *cb);
+
+/**
+ * core_deinitialise - deinitialise core
+ */
+int core_deinitialise(void);
+
+int core_supported_features(struct vdec_features *features);
+
+int core_stream_create(void *vxd_dec_ctx_arg,
+		       const struct vdec_str_configdata *str_cfgdata,
+		       unsigned int *res_str_id);
+
+int core_stream_destroy(unsigned int res_str_id);
+
+int core_stream_play(unsigned int res_str_id);
+
+int core_stream_stop(unsigned int res_str_id);
+
+int core_stream_map_buf(unsigned int res_str_id, enum vdec_buf_type buf_type,
+			struct vdec_buf_info *buf_info, unsigned int *buf_map_id);
+
+int core_stream_map_buf_sg(unsigned int res_str_id,
+			   enum vdec_buf_type buf_type,
+			   struct vdec_buf_info *buf_info,
+			   void *sgt, unsigned int *buf_map_id);
+
+int core_stream_unmap_buf(unsigned int buf_map_id);
+
+int core_stream_unmap_buf_sg(unsigned int buf_map_id);
+
+int core_stream_submit_unit(unsigned int res_str_id,
+			    struct vdecdd_str_unit *str_unit);
+
+int core_stream_fill_pictbuf(unsigned int buf_map_id);
+
+/* This function to be called before stream play */
+int core_stream_set_output_config(unsigned int res_str_id,
+				  struct vdec_str_opconfig *str_opcfg,
+				  struct vdec_pict_bufconfig *pict_bufcg);
+
+int core_stream_flush(unsigned int res_str_id, unsigned char discard_refs);
+
+int core_stream_release_bufs(unsigned int res_str_id,
+			     enum vdec_buf_type buf_type);
+
+int core_stream_get_status(unsigned int res_str_id,
+			   struct vdecdd_decstr_status *str_status);
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/decoder.c b/drivers/media/platform/img/vxe-vxd/decoder/decoder.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/decoder.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/decoder.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,4629 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VXD Decoder Component function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include "decoder.h"
+#include "dec_resources.h"
+#include "dq.h"
+#include "hw_control.h"
+#include "h264fw_data.h"
+#include "idgen_api.h"
+#include "img_errors.h"
+#ifdef HAS_JPEG
+#include "jpegfw_data.h"
+#endif
+#include "lst.h"
+#include "pool_api.h"
+#include "resource.h"
+#include "translation_api.h"
+#include "vdecdd_utils.h"
+#include "vdec_mmu_wrapper.h"
+#include "vxd_dec.h"
+
+#define MAX_PLATFORM_SUPPORTED_HEIGHT 65536
+#define MAX_PLATFORM_SUPPORTED_WIDTH 65536
+
+#define MAX_CONCURRENT_STREAMS 16
+
+/* Maximum number of unique picture ids within stream. */
+#define DECODER_MAX_PICT_ID     GET_STREAM_PICTURE_ID(((1ULL << 32) - 1ULL))
+
+/* Maximum number of concurrent pictures within stream. */
+#define DECODER_MAX_CONCURRENT_PICT     0x100
+
+static inline unsigned int get_next_picture_id(unsigned int cur_pict_id)
+{
+	return(cur_pict_id == FWIF_BIT_MASK(FWIF_NUMBITS_STREAM_PICTURE_ID) ?
+	       1 : cur_pict_id + 1);
+}
+
+static inline unsigned int get_prev_picture_id(unsigned int cur_pict_id)
+{
+	return(cur_pict_id == 1 ?
+	       FWIF_BIT_MASK(FWIF_NUMBITS_STREAM_PICTURE_ID) :
+	       cur_pict_id - 1);
+}
+
+#define H264_SGM_BUFFER_BYTES_PER_MB  1
+#define H264_SGM_MAX_MBS              3600
+
+#define CONTEXT_BUFF_SIZE       (72)
+
+/*
+ * Number of bits in transaction ID used to represent
+ * picture number in stream.
+ */
+#define FWIF_NUMBITS_STREAM_PICTURE_ID          16
+/*
+ * Number of bits in transaction ID used to represent
+ * picture number in core.
+ */
+#define FWIF_NUMBITS_CORE_PICTURE_ID            4
+/*
+ * Number of bits in transaction ID used to represent
+ * stream id.
+ */
+#define FWIF_NUMBITS_STREAM_ID                  8
+/* Number of bits in transaction ID used to represent core id. */
+#define FWIF_NUMBITS_CORE_ID                    4
+
+/* Offset in transaction ID to picture number in stream. */
+#define FWIF_OFFSET_STREAM_PICTURE_ID           0
+/* Offset in transaction ID to picture number in core. */
+#define FWIF_OFFSET_CORE_PICTURE_ID     (FWIF_OFFSET_STREAM_PICTURE_ID + \
+	FWIF_NUMBITS_STREAM_PICTURE_ID)
+/* Offset in transaction ID to stream id. */
+#define FWIF_OFFSET_STREAM_ID           (FWIF_OFFSET_CORE_PICTURE_ID + \
+	FWIF_NUMBITS_CORE_PICTURE_ID)
+/* Offset in transaction ID to core id. */
+#define FWIF_OFFSET_CORE_ID             (FWIF_OFFSET_STREAM_ID + \
+	FWIF_NUMBITS_STREAM_ID)
+
+/* Maximum number of unique picture ids within stream. */
+#define DECODER_MAX_PICT_ID GET_STREAM_PICTURE_ID(((1ULL << 32) - 1ULL))
+
+/* Maximum number of concurrent pictures within stream. */
+#define DECODER_MAX_CONCURRENT_PICT     0x100
+
+#define CREATE_TRANSACTION_ID(core_id, stream_id, core_pic, stream_pic) \
+	(SET_CORE_ID((core_id)) | SET_STREAM_ID((stream_id)) | \
+	SET_CORE_PICTURE_ID((core_pic)) | SET_STREAM_PICTURE_ID((stream_pic)))
+
+static inline struct dec_core_ctx *decoder_str_ctx_to_core_ctx(struct dec_str_ctx *decstrctx)
+{
+	if (decstrctx && decstrctx->decctx)
+		return decstrctx->decctx->dec_core_ctx;
+
+	else
+		return NULL;
+}
+
+static const struct vdecdd_dd_devconfig def_dev_cfg = {
+	CORE_NUM_DECODE_SLOTS,       /* ui32NumSlotsPerPipe; */
+};
+
+/*
+ * This array defines names of the VDEC standards.
+ * Shall be in sync with #VDEC_eVidStd
+ * @brief  Names of the VDEC standards
+ */
+static unsigned char *vid_std_names[] = {
+	"VDEC_STD_UNDEFINED",
+	"VDEC_STD_MPEG2",
+	"VDEC_STD_MPEG4",
+	"VDEC_STD_H263",
+	"VDEC_STD_H264",
+	"VDEC_STD_VC1",
+	"VDEC_STD_AVS",
+	"VDEC_STD_REAL",
+	"VDEC_STD_JPEG",
+	"VDEC_STD_VP6",
+	"VDEC_STD_VP8",
+	"VDEC_STD_SORENSON",
+	"VDEC_STD_HEVC"
+};
+
+#ifdef ERROR_RECOVERY_SIMULATION
+extern int fw_error_value;
+#endif
+
+/*
+ * @Function decoder_set_device_config
+ */
+static int decoder_set_device_config(const struct vdecdd_dd_devconfig **dd_dev_config)
+{
+	struct vdecdd_dd_devconfig *local_dev_cfg;
+
+	VDEC_ASSERT(dd_dev_config);
+
+	/* Allocate device configuration structure */
+	local_dev_cfg = kzalloc(sizeof(*local_dev_cfg), GFP_KERNEL);
+	VDEC_ASSERT(local_dev_cfg);
+	if (!local_dev_cfg)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/* Set the default device configuration */
+	*local_dev_cfg = def_dev_cfg;
+
+	*dd_dev_config = local_dev_cfg;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function  decoder_set_feature_flags
+ * @Description
+ * This function sets the features flags from the core properties.
+ * @Input     p                     : Pointer to core properties.
+ * @Input     core_feat_flags : Pointer to core feature flags word.
+ */
+static void decoder_set_feature_flags(struct vxd_coreprops *core_props,
+				      unsigned int *core_feat_flags,
+				      unsigned int *pipe_feat_flags)
+{
+	unsigned char pipe_minus_one;
+
+	VDEC_ASSERT(core_props);
+	VDEC_ASSERT(core_feat_flags);
+	VDEC_ASSERT(pipe_feat_flags);
+
+	for (pipe_minus_one = 0; pipe_minus_one < core_props->num_pixel_pipes;
+		pipe_minus_one++) {
+		*core_feat_flags |= pipe_feat_flags[pipe_minus_one] |=
+				core_props->h264[pipe_minus_one] ?
+				VDECDD_COREFEATURE_H264 : 0;
+#ifdef HAS_JPEG
+		*core_feat_flags |= pipe_feat_flags[pipe_minus_one] |=
+				core_props->jpeg[pipe_minus_one] ?
+				VDECDD_COREFEATURE_JPEG : 0;
+#endif
+#ifdef HAS_HEVC
+		*core_feat_flags |= pipe_feat_flags[pipe_minus_one] |=
+				core_props->hevc[pipe_minus_one] ?
+				VDECDD_COREFEATURE_HEVC : 0;
+#endif
+	}
+}
+
+/*
+ * @Function  decoder_stream_get_context
+ * @Description
+ * This function returns the stream context structure for the given
+ * stream handle.
+ * @Return    struct dec_str_ctx : This function returns a pointer
+ * to the stream
+ *                            context structure or NULL if not found.
+ */
+static struct dec_str_ctx *decoder_stream_get_context(void *dec_str_context)
+{
+	return (struct dec_str_ctx *)dec_str_context;
+}
+
+/*
+ * @Function decoder_core_enumerate
+ * @Description
+ * This function enumerates a decoder core and returns its handle.
+ * Usage: before calls to other DECODE_Core or DECODE_Stream functions.
+ * @Input     dec_context : Pointer to Decoder context.
+ * @Input     dev_cfg : Device configuration.
+ * @Return    This function returns either IMG_SUCCESS or an
+ * error code.
+ */
+static int decoder_core_enumerate(struct dec_ctx *dec_context,
+				  const struct vdecdd_dd_devconfig *dev_cfg,
+				  unsigned int *num_pipes)
+{
+	struct dec_core_ctx *dec_core_ctx_local;
+	unsigned int ret;
+	unsigned int ptd_align = DEV_MMU_PAGE_ALIGNMENT;
+
+	/* Create the core. */
+	dec_core_ctx_local = kzalloc(sizeof(*dec_core_ctx_local), GFP_KERNEL);
+	if (!dec_core_ctx_local)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	dec_core_ctx_local->dec_ctx = (struct dec_ctx *)dec_context;
+
+	/* Initialise the hwctrl block here */
+	ret = hwctrl_initialise(dec_core_ctx_local, dec_context->user_data,
+				dev_cfg, &dec_core_ctx_local->core_props,
+				&dec_core_ctx_local->hw_ctx);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	decoder_set_feature_flags(&dec_core_ctx_local->core_props,
+				  &dec_core_ctx_local->core_features,
+				  dec_core_ctx_local->pipe_features);
+
+	/* Perform device setup for master core. */
+	if (num_pipes)
+		*num_pipes = dec_core_ctx_local->core_props.num_pixel_pipes;
+
+	/* DEVA PVDEC FW requires PTD to be 64k aligned. */
+	ptd_align = 0x10000;
+
+	/* Create a device MMU context. */
+	ret = mmu_device_create(dec_core_ctx_local->core_props.mmu_type,
+				ptd_align, &dec_context->mmu_dev_handle);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	dec_core_ctx_local->enumerated = TRUE;
+
+	dec_context->dec_core_ctx = dec_core_ctx_local;
+
+	return IMG_SUCCESS;
+
+error:
+	if (dec_core_ctx_local) {
+		unsigned int deinit_result = IMG_SUCCESS;
+
+		/* Destroy a device MMU context. */
+		if (dec_context->mmu_dev_handle) {
+			deinit_result =
+				mmu_device_destroy(dec_context->mmu_dev_handle);
+			VDEC_ASSERT(deinit_result == IMG_SUCCESS);
+			if (deinit_result != IMG_SUCCESS)
+				pr_warn("MMU_DeviceDestroy() failed to tidy-up after error");
+		}
+
+		kfree(dec_core_ctx_local);
+		dec_core_ctx_local = NULL;
+	}
+
+	return ret;
+}
+
+/*
+ * @Function  decoder_initialise
+ */
+int decoder_initialise(void *user_init_data, unsigned int int_heap_id,
+		       struct vdecdd_dd_devconfig *dd_device_config,
+		       unsigned int *num_pipes,
+		       void **dec_ctx_handle)
+{
+	struct dec_ctx *dec_context = (struct dec_ctx *)*dec_ctx_handle;
+	int ret;
+
+	if (!dec_context) {
+		dec_context = kzalloc(sizeof(*dec_context), GFP_KERNEL);
+		VDEC_ASSERT(dec_context);
+		if (!dec_context)
+			return IMG_ERROR_OUT_OF_MEMORY;
+
+		*dec_ctx_handle = dec_context;
+	}
+
+	/* Determine which standards are supported. */
+	memset(&dec_context->sup_stds, 0x0, sizeof(dec_context->sup_stds[VDEC_STD_MAX]));
+
+	dec_context->sup_stds[VDEC_STD_H264] = TRUE;
+#ifdef HAS_HEVC
+	dec_context->sup_stds[VDEC_STD_HEVC] = TRUE;
+#endif
+	if (!dec_context->inited) {
+		/* Check and store input parameters. */
+		dec_context->user_data = user_init_data;
+		dec_context->dev_handle =
+			((struct vdecdd_dddev_context *)user_init_data)->dev_handle;
+
+		/* Initialise the context lists. */
+		lst_init(&dec_context->str_list);
+
+		/* Make sure POOL API is initialised */
+		ret = pool_init();
+		if (ret != IMG_SUCCESS)
+			goto pool_init_error;
+
+		ret = decoder_set_device_config(&dec_context->dev_cfg);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			goto error;
+
+		dec_context->internal_heap_id = int_heap_id;
+
+		/* Enumerate the master core. */
+		ret = decoder_core_enumerate(dec_context, dec_context->dev_cfg,
+					     &dec_context->num_pipes);
+		if (ret != IMG_SUCCESS)
+			goto error;
+
+		if (dd_device_config)
+			*dd_device_config = *dec_context->dev_cfg;
+
+		if (num_pipes)
+			*num_pipes = dec_context->num_pipes;
+
+		dec_context->inited = TRUE;
+	}
+
+	return IMG_SUCCESS;
+
+error:
+	pool_deinit();
+
+pool_init_error:
+	if (dec_context->dev_cfg) {
+		kfree((void *)dec_context->dev_cfg);
+		dec_context->dev_cfg = NULL;
+	}
+
+	kfree(*dec_ctx_handle);
+	*dec_ctx_handle = NULL;
+
+	return ret;
+}
+
+/*
+ * @Function  decoder_supported_features
+ */
+int decoder_supported_features(void *dec_ctx, struct vdec_features *features)
+{
+	struct dec_ctx *dec_context = (struct dec_ctx *)dec_ctx;
+	struct dec_core_ctx *dec_core_ctx_local;
+
+	/* Check input parameters. */
+	VDEC_ASSERT(dec_context);
+	VDEC_ASSERT(features);
+	if (!dec_context || !features) {
+		pr_err("Invalid parameters!");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Ensure that Decoder component is initialised. */
+	VDEC_ASSERT(dec_context->inited);
+
+	/* Loop over all cores checking for support. */
+	dec_core_ctx_local = dec_context->dec_core_ctx;
+	VDEC_ASSERT(dec_core_ctx_local);
+
+	/*
+	 * Determine whether the required core attribute
+	 * is present to support requested feature
+	 */
+	features->h264     |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_H264) ? TRUE : FALSE;
+	features->mpeg2    |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_MPEG2) ? TRUE : FALSE;
+	features->mpeg4    |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_MPEG4) ? TRUE : FALSE;
+	features->vc1      |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_VC1) ? TRUE : FALSE;
+	features->avs      |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_AVS) ? TRUE : FALSE;
+	features->real     |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_REAL) ? TRUE : FALSE;
+	features->jpeg     |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_JPEG) ? TRUE : FALSE;
+	features->vp6      |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_VP6) ? TRUE : FALSE;
+	features->vp8      |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_VP8) ? TRUE : FALSE;
+	features->hd       |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_HD_DECODE) ? TRUE : FALSE;
+	features->rotation |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_ROTATION) ? TRUE : FALSE;
+	features->scaling  |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_SCALING) ? TRUE : FALSE;
+	features->hevc     |= (dec_core_ctx_local->core_features &
+		VDECDD_COREFEATURE_HEVC) ? TRUE : FALSE;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function decoder_stream_get_status
+ */
+int decoder_stream_get_status(void *dec_str_ctx_handle,
+			      struct vdecdd_decstr_status *dec_str_st)
+{
+	struct dec_str_ctx *dec_str_ctx;
+	struct dec_decoded_pict *decoded_pict;
+	struct dec_core_ctx *dec_core_ctx;
+	unsigned int item;
+
+	VDEC_ASSERT(dec_str_st);
+	if (!dec_str_st) {
+		pr_err("Invalid decoder streams status pointer!");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	dec_str_ctx = decoder_stream_get_context(dec_str_ctx_handle);
+	VDEC_ASSERT(dec_str_ctx);
+	if (!dec_str_ctx) {
+		pr_err("Invalid decoder stream context handle!");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Obtain the state of each core. */
+	dec_core_ctx = decoder_str_ctx_to_core_ctx(dec_str_ctx);
+	VDEC_ASSERT(dec_core_ctx);
+
+	/*
+	 * Obtain the display and release list of first unprocessed
+	 * picture in decoded list
+	 */
+	dec_str_ctx->dec_str_st.display_pics = 0;
+	dec_str_ctx->dec_str_st.release_pics = 0;
+	decoded_pict = dq_first(&dec_str_ctx->str_decd_pict_list);
+	while (decoded_pict) {
+		/* if this is the first unprocessed picture */
+		if (!decoded_pict->processed) {
+			unsigned int idx;
+			struct vdecfw_buffer_control *buf_ctrl;
+
+			VDEC_ASSERT(decoded_pict->pict_ref_res);
+			buf_ctrl =
+		(struct vdecfw_buffer_control *)decoded_pict->pict_ref_res->fw_ctrlbuf.cpu_virt;
+			VDEC_ASSERT(buf_ctrl);
+
+			/* Get display pictures */
+			idx = decoded_pict->disp_idx;
+			item = dec_str_ctx->dec_str_st.display_pics;
+			while (idx < buf_ctrl->display_list_length &&
+			       item < VDECFW_MAX_NUM_PICTURES) {
+				dec_str_ctx->dec_str_st.next_display_items[item] =
+					buf_ctrl->display_list[idx];
+				dec_str_ctx->dec_str_st.next_display_item_parent[item] =
+					decoded_pict->transaction_id;
+				idx++;
+				item++;
+			}
+			dec_str_ctx->dec_str_st.display_pics = item;
+
+			/* Get release pictures */
+			idx = decoded_pict->rel_idx;
+			item = dec_str_ctx->dec_str_st.release_pics;
+			while (idx < buf_ctrl->release_list_length &&
+			       item < VDECFW_MAX_NUM_PICTURES) {
+				dec_str_ctx->dec_str_st.next_release_items[item] =
+					buf_ctrl->release_list[idx];
+				dec_str_ctx->dec_str_st.next_release_item_parent[item] =
+					decoded_pict->transaction_id;
+				idx++;
+				item++;
+			}
+			dec_str_ctx->dec_str_st.release_pics = item;
+			break;
+		}
+
+		if (decoded_pict != dq_last(&dec_str_ctx->str_decd_pict_list))
+			decoded_pict = dq_next(decoded_pict);
+		else
+			decoded_pict = NULL;
+	}
+
+	/* Get list of held decoded pictures */
+	item = 0;
+	decoded_pict = dq_first(&dec_str_ctx->str_decd_pict_list);
+	while (decoded_pict) {
+		dec_str_ctx->dec_str_st.decoded_picts[item] =
+			decoded_pict->transaction_id;
+		item++;
+
+		if (decoded_pict != dq_last(&dec_str_ctx->str_decd_pict_list))
+			decoded_pict = dq_next(decoded_pict);
+		else
+			decoded_pict = NULL;
+	}
+
+	VDEC_ASSERT(item == dec_str_ctx->dec_str_st.num_pict_decoded);
+	*dec_str_st = dec_str_ctx->dec_str_st;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function  decoder_deinitialise
+ */
+int decoder_deinitialise(void *dec_ctx)
+{
+	struct dec_ctx *dec_context = (struct dec_ctx *)dec_ctx;
+	int ret;
+	/*  Remove and free all core context structures */
+	struct dec_decpict *dec_pict;
+
+	if (dec_context && dec_context->inited) {
+		struct dec_core_ctx *dec_core_ctx_local =
+			dec_context->dec_core_ctx;
+
+		if (!dec_core_ctx_local) {
+			pr_warn("%s %d NULL Decoder context passed", __func__, __LINE__);
+			VDEC_ASSERT(0);
+			return -EFAULT;
+		}
+
+		/* Stream list should be empty. */
+		if (!lst_empty(&dec_context->str_list))
+			pr_warn("%s %d stream list should be empty", __func__, __LINE__);
+
+		/*
+		 * All cores should now be idle since there are no
+		 * connections/streams.
+		 */
+		ret = hwctrl_peekheadpiclist(dec_core_ctx_local->hw_ctx, &dec_pict);
+		VDEC_ASSERT(ret != IMG_SUCCESS);
+
+		/* Destroy a device MMU context. */
+		ret = mmu_device_destroy(dec_context->mmu_dev_handle);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		/* Remove and free core context structure */
+		dec_core_ctx_local = dec_context->dec_core_ctx;
+		VDEC_ASSERT(dec_core_ctx_local);
+
+		hwctrl_deinitialise(dec_core_ctx_local->hw_ctx);
+
+		kfree(dec_core_ctx_local);
+		dec_core_ctx_local = NULL;
+
+		VDEC_ASSERT(dec_context->dev_cfg);
+		if (dec_context->dev_cfg)
+			kfree((void *)dec_context->dev_cfg);
+
+		dec_context->user_data = NULL;
+
+		pool_deinit();
+
+		dec_context->inited = FALSE;
+
+		kfree(dec_context);
+	} else {
+		pr_err("Decoder has not been initialised so cannot be de-initialised");
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	pr_debug("Decoder deinitialise successfully\n");
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function   decoder_picture_destroy
+ * @Description
+ * Free the picture container and optionally release image buffer back to
+ * client.
+ * Default is to decrement the reference count held by this picture.
+ */
+static int decoder_picture_destroy(struct dec_str_ctx *dec_str_ctx,
+				   unsigned int pict_id,
+				   unsigned char release_image)
+{
+	struct vdecdd_picture *picture;
+	int ret;
+
+	VDEC_ASSERT(dec_str_ctx);
+
+	ret = idgen_gethandle(dec_str_ctx->pict_idgen, pict_id, (void **)&picture);
+	if (ret == IMG_SUCCESS) {
+		VDEC_ASSERT(picture);
+		ret = idgen_freeid(dec_str_ctx->pict_idgen, pict_id);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		if (picture->dec_pict_info) {
+			/* Destroy the picture */
+			kfree(picture->dec_pict_info);
+			picture->dec_pict_info = NULL;
+		}
+
+		/* Return unused picture and internal resources */
+		if (picture->disp_pict_buf.pict_buf) {
+			if (release_image)
+				resource_item_release
+					(&picture->disp_pict_buf.pict_buf->ddbuf_info.ref_count);
+			else
+				resource_item_return
+					(&picture->disp_pict_buf.pict_buf->ddbuf_info.ref_count);
+
+			memset(&picture->disp_pict_buf, 0, sizeof(picture->disp_pict_buf));
+		}
+
+		if (picture->pict_res_int) {
+			resource_item_return(&picture->pict_res_int->ref_cnt);
+			picture->pict_res_int = NULL;
+		}
+
+		kfree(picture);
+		picture = NULL;
+	} else {
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		return ret;
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function decoder_decoded_picture_destroy
+ */
+static int
+decoder_decoded_picture_destroy(struct dec_str_ctx *dec_str_ctx,
+				struct dec_decoded_pict *decoded_pict,
+	unsigned char release_image)
+{
+	int ret;
+
+	VDEC_ASSERT(dec_str_ctx);
+	VDEC_ASSERT(decoded_pict);
+
+	if (decoded_pict->pict) {
+		VDEC_ASSERT(decoded_pict->pict->pict_id ==
+			GET_STREAM_PICTURE_ID(decoded_pict->transaction_id));
+
+		ret = decoder_picture_destroy(dec_str_ctx, decoded_pict->pict->pict_id,
+					      release_image);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		decoded_pict->pict = NULL;
+	}
+
+	dq_remove(decoded_pict);
+	dec_str_ctx->dec_str_st.num_pict_decoded--;
+
+	resource_item_return(&decoded_pict->pict_ref_res->ref_cnt);
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("[USERSID=0x%08X] [TID=0x%08X] COMPLETE",
+		GET_STREAM_ID(decoded_pict->transaction_id),
+		decoded_pict->transaction_id);
+#endif
+
+	kfree(decoded_pict->first_fld_fwmsg);
+	decoded_pict->first_fld_fwmsg = NULL;
+
+	kfree(decoded_pict->second_fld_fwmsg);
+	decoded_pict->second_fld_fwmsg = NULL;
+
+	kfree(decoded_pict);
+	decoded_pict = NULL;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function  decoder_stream_decode_resource_destroy
+ */
+static int decoder_stream_decode_resource_destroy(void *item, void *free_cb_param)
+{
+	struct dec_pictdec_res *pict_dec_res = item;
+	struct dec_str_ctx *dec_str_ctx_local =
+		(struct dec_str_ctx *)free_cb_param;
+	int ret;
+
+	VDEC_ASSERT(pict_dec_res);
+	VDEC_ASSERT(resource_item_isavailable(&pict_dec_res->ref_cnt));
+
+	/* Free memory (device-based) to store fw contexts for stream. */
+	ret = mmu_free_mem(dec_str_ctx_local->mmu_str_handle, &pict_dec_res->fw_ctx_buf);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	if (pict_dec_res->h264_sgm_buf.hndl_memory) {
+		/* Free memory (device-based) to store SGM. */
+		ret = mmu_free_mem(dec_str_ctx_local->mmu_str_handle, &pict_dec_res->h264_sgm_buf);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+	}
+
+	kfree(pict_dec_res);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function  decoder_stream_release_buffers
+ */
+int decoder_stream_release_buffers(void *dec_str_ctx_handle)
+{
+	struct dec_str_ctx *dec_str_ctx;
+	struct dec_decoded_pict *decoded_pict;
+	int ret;
+
+	dec_str_ctx = decoder_stream_get_context(dec_str_ctx_handle);
+
+	/* Decoding queue should be empty since we are stopped */
+	VDEC_ASSERT(dec_str_ctx);
+	if (!dec_str_ctx) {
+		pr_err("Invalid decoder stream context handle!");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+	VDEC_ASSERT(lst_empty(&dec_str_ctx->pend_strunit_list));
+
+	/* Destroy all pictures in the decoded list */
+	decoded_pict = dq_first(&dec_str_ctx->str_decd_pict_list);
+	while (decoded_pict) {
+		ret = decoder_decoded_picture_destroy(dec_str_ctx, decoded_pict, TRUE);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		decoded_pict = dq_first(&dec_str_ctx->str_decd_pict_list);
+	}
+
+	/* if and only if the output buffers were used for reference. */
+	if (dec_str_ctx->last_be_pict_dec_res) {
+		/*
+		 * Clear the firmware context so that reference pictures
+		 * are no longer referred to.
+		 */
+		memset(dec_str_ctx->last_be_pict_dec_res->fw_ctx_buf.cpu_virt, 0,
+		       dec_str_ctx->last_be_pict_dec_res->fw_ctx_buf.buf_size);
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function  decoder_stream_reference_resource_destroy
+ */
+static int decoder_stream_reference_resource_destroy(void *item, void *free_cb_param)
+{
+	struct dec_pictref_res  *pict_ref_res = item;
+	struct dec_str_ctx *dec_str_ctx_local =
+		(struct dec_str_ctx *)free_cb_param;
+	int ret;
+
+	VDEC_ASSERT(pict_ref_res);
+	VDEC_ASSERT(resource_item_isavailable(&pict_ref_res->ref_cnt));
+
+	/* Free memory (device-based) to store fw contexts for stream */
+	ret = mmu_free_mem(dec_str_ctx_local->mmu_str_handle, &pict_ref_res->fw_ctrlbuf);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	kfree(pict_ref_res);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function decoder_stream_destroy
+ */
+int decoder_stream_destroy(void *dec_str_context, unsigned char abort)
+{
+	struct dec_str_ctx *dec_str_ctx_local;
+	struct dec_str_unit *dec_str_unit_local;
+	struct dec_decoded_pict *decoded_pict_local;
+	unsigned int i;
+	int ret;
+	unsigned int pict_id;
+	void **res_handle_local;
+
+	/* Required for getting segments from decode picture to free */
+	struct dec_decpict_seg *dec_pict_seg_local;
+	struct dec_ctx *dec_context;
+	struct dec_core_ctx *dec_core_ctx_local;
+
+	/* Get the Decoder stream context. */
+	dec_str_ctx_local = decoder_stream_get_context(dec_str_context);
+
+	VDEC_ASSERT(dec_str_ctx_local);
+	if (!dec_str_ctx_local) {
+		pr_err("Invalid decoder stream context handle!");
+		return FALSE;
+	}
+	VDEC_ASSERT(dec_str_ctx_local->decctx);
+
+	/* Decrement the stream count */
+	dec_str_ctx_local->decctx->str_cnt--;
+
+	/*
+	 * Ensure that there are no pictures for this stream outstanding
+	 * on any decoder cores.
+	 * This should not be removed, it is important to see it if
+	 * it ever happens.
+	 * In practice we see it many times with Application Timeout.
+	 */
+	if (!abort)
+		VDEC_ASSERT(lst_empty(&dec_str_ctx_local->pend_strunit_list));
+
+	/*
+	 * At this point all resources for the stream are guaranteed to
+	 * not be used and no further hardware interrupts will be received.
+	 */
+
+	/* Destroy all stream units submitted for processing. */
+	dec_str_unit_local =
+		lst_removehead(&dec_str_ctx_local->pend_strunit_list);
+	while (dec_str_unit_local) {
+		/* If the unit was submitted for decoding (picture)... */
+		if (dec_str_unit_local->dec_pict) {
+			/*
+			 * Explicitly remove picture from core decode queue
+			 * and destroy.
+			 */
+			struct dec_core_ctx *dec_core_ctx_local =
+				decoder_str_ctx_to_core_ctx(dec_str_ctx_local);
+			VDEC_ASSERT(dec_core_ctx_local);
+
+			res_handle_local = &dec_str_ctx_local->resources;
+
+			if (!dec_core_ctx_local) {
+				VDEC_ASSERT(0);
+				return -EINVAL;
+			}
+
+			hwctrl_removefrom_piclist(dec_core_ctx_local->hw_ctx,
+						  dec_str_unit_local->dec_pict);
+
+			/* Free decoder picture */
+			kfree(dec_str_unit_local->dec_pict->first_fld_fwmsg);
+			dec_str_unit_local->dec_pict->first_fld_fwmsg = NULL;
+
+			kfree(dec_str_unit_local->dec_pict->second_fld_fwmsg);
+			dec_str_unit_local->dec_pict->second_fld_fwmsg = NULL;
+
+			dec_res_picture_detach(res_handle_local, dec_str_unit_local->dec_pict);
+
+			/* Free all the segments of the picture */
+			dec_pict_seg_local =
+				lst_removehead(&dec_str_unit_local->dec_pict->dec_pict_seg_list);
+			while (dec_pict_seg_local) {
+				if (dec_pict_seg_local->internal_seg) {
+					VDEC_ASSERT(dec_pict_seg_local->bstr_seg);
+					kfree(dec_pict_seg_local->bstr_seg);
+					dec_pict_seg_local->bstr_seg = NULL;
+				}
+
+				kfree(dec_pict_seg_local);
+				dec_pict_seg_local = NULL;
+
+				dec_pict_seg_local =
+					lst_removehead
+					(&dec_str_unit_local->dec_pict->dec_pict_seg_list);
+			}
+
+			VDEC_ASSERT(dec_str_unit_local->dec_pict->dec_str_ctx == dec_str_ctx_local);
+
+			dec_str_ctx_local->dec_str_st.num_pict_decoding--;
+			pict_id =
+				GET_STREAM_PICTURE_ID(dec_str_unit_local->dec_pict->transaction_id);
+
+			ret = decoder_picture_destroy(dec_str_ctx_local, pict_id, TRUE);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+
+			kfree(dec_str_unit_local->dec_pict);
+			dec_str_unit_local->dec_pict = NULL;
+		}
+
+		/* Free the picture container */
+		kfree(dec_str_unit_local);
+		dec_str_unit_local = NULL;
+
+		dec_str_unit_local = lst_removehead(&dec_str_ctx_local->pend_strunit_list);
+	}
+
+	/* Destroy all pictures in the decoded list */
+	decoded_pict_local = dq_first(&dec_str_ctx_local->str_decd_pict_list);
+	while (decoded_pict_local) {
+		ret = decoder_decoded_picture_destroy(dec_str_ctx_local,
+						      decoded_pict_local,
+						      TRUE);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		decoded_pict_local = dq_first(&dec_str_ctx_local->str_decd_pict_list);
+	}
+
+	/* Ensure all picture queues are empty */
+	VDEC_ASSERT(lst_empty(&dec_str_ctx_local->pend_strunit_list));
+	VDEC_ASSERT(dq_empty(&dec_str_ctx_local->str_decd_pict_list));
+
+	/* Free memory to store stream context buffer. */
+	ret = mmu_free_mem(dec_str_ctx_local->mmu_str_handle,
+			   &dec_str_ctx_local->pvdec_fw_ctx_buf);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	/* Release any fw contexts held by stream. */
+	if (dec_str_ctx_local->prev_fe_pict_dec_res)
+		resource_item_return(&dec_str_ctx_local->prev_fe_pict_dec_res->ref_cnt);
+
+	if (dec_str_ctx_local->cur_fe_pict_dec_res)
+		resource_item_return(&dec_str_ctx_local->cur_fe_pict_dec_res->ref_cnt);
+
+	if (dec_str_ctx_local->last_be_pict_dec_res)
+		resource_item_return(&dec_str_ctx_local->last_be_pict_dec_res->ref_cnt);
+
+	/*
+	 * Remove the device resources used for decoding and the two
+	 * added to hold the last on front and back-end for stream.
+	 */
+	for (i = 0; i < dec_str_ctx_local->num_dec_res + 2; i++) {
+		ret = resource_list_empty(&dec_str_ctx_local->dec_res_lst, FALSE,
+					  decoder_stream_decode_resource_destroy,
+					  dec_str_ctx_local);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+	}
+	VDEC_ASSERT(lst_empty(&dec_str_ctx_local->dec_res_lst));
+
+	/* Remove all stream decode resources. */
+	ret = resource_list_empty(&dec_str_ctx_local->ref_res_lst, FALSE,
+				  decoder_stream_reference_resource_destroy,
+				  dec_str_ctx_local);
+
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	VDEC_ASSERT(lst_empty(&dec_str_ctx_local->ref_res_lst));
+
+	idgen_destroycontext(dec_str_ctx_local->pict_idgen);
+
+	dec_context = dec_str_ctx_local->decctx;
+	dec_core_ctx_local = decoder_str_ctx_to_core_ctx(dec_str_ctx_local);
+
+	VDEC_ASSERT(dec_context);
+	VDEC_ASSERT(dec_core_ctx_local);
+
+	res_handle_local = &dec_str_ctx_local->resources;
+
+	if (*res_handle_local) {
+		ret = dec_res_destroy(dec_str_ctx_local->mmu_str_handle, *res_handle_local);
+		if (ret != IMG_SUCCESS)
+			pr_warn("resourceS_Destroy() failed to tidy-up after error");
+
+		*res_handle_local = NULL;
+	}
+
+	lst_remove(&dec_str_ctx_local->decctx->str_list, dec_str_ctx_local);
+
+	kfree(dec_str_ctx_local);
+	dec_str_ctx_local = NULL;
+
+	pr_debug("%s successfully", __func__);
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function  decoder_init_avail_slots
+ */
+static int decoder_init_avail_slots(struct dec_str_ctx *dec_str_context)
+{
+	VDEC_ASSERT(dec_str_context);
+
+	switch (dec_str_context->config.vid_std) {
+	case VDEC_STD_H264:
+		/*
+		 * only first pipe can be master when decoding H264 in
+		 * multipipe mode (FW restriction)
+		 */
+		dec_str_context->avail_slots =
+			dec_str_context->decctx->dev_cfg->num_slots_per_pipe *
+			dec_str_context->decctx->num_pipes;
+		break;
+
+	default:
+		/* all pipes by default */
+		dec_str_context->avail_slots =
+			dec_str_context->decctx->dev_cfg->num_slots_per_pipe;
+		break;
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function  decoder_stream_decode_resource_create
+ */
+static int decoder_stream_decode_resource_create(struct dec_str_ctx *dec_str_context)
+{
+	struct dec_pictdec_res *pict_dec_res;
+	int ret;
+	unsigned int mem_heap_id;
+	enum sys_emem_attrib mem_attribs;
+
+	unsigned char fw_ctx_buf = FALSE;
+
+	/* Validate input arguments */
+	if (!dec_str_context || !dec_str_context->decctx ||
+	    !dec_str_context->decctx->dev_cfg) {
+		VDEC_ASSERT(0);
+		return -EINVAL;
+	}
+
+	mem_heap_id = dec_str_context->decctx->internal_heap_id;
+	mem_attribs = (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE);
+	mem_attribs |= (enum sys_emem_attrib)SYS_MEMATTRIB_INTERNAL;
+
+	/* Allocate the firmware context buffer info structure. */
+	pict_dec_res = kzalloc(sizeof(*pict_dec_res), GFP_KERNEL);
+	VDEC_ASSERT(pict_dec_res);
+	if (!pict_dec_res)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/*
+	 * Allocate the firmware context buffer to contain
+	 * data required for subsequent picture.
+	 */
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s:%d calling MMU_StreamMalloc", __func__, __LINE__);
+#endif
+
+	ret = mmu_stream_alloc(dec_str_context->mmu_str_handle,
+			       MMU_HEAP_STREAM_BUFFERS, mem_heap_id,
+			       (enum sys_emem_attrib)(mem_attribs | SYS_MEMATTRIB_CPU_READ |
+			       SYS_MEMATTRIB_CPU_WRITE),
+			       sizeof(union dec_fw_contexts),
+			       DEV_MMU_PAGE_ALIGNMENT,
+			       &pict_dec_res->fw_ctx_buf);
+
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto err_out_of_memory;
+
+	fw_ctx_buf = TRUE;
+
+	/*
+	 * Clear the context data in preparation for first time
+	 * use by the firmware.
+	 */
+	memset(pict_dec_res->fw_ctx_buf.cpu_virt, 0, pict_dec_res->fw_ctx_buf.buf_size);
+
+	switch (dec_str_context->config.vid_std) {
+	case VDEC_STD_H264:
+		/* Allocate the SGM buffer */
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("%s:%d calling MMU_StreamMalloc", __func__, __LINE__);
+#endif
+		ret = mmu_stream_alloc
+			(dec_str_context->mmu_str_handle,
+			 MMU_HEAP_STREAM_BUFFERS, mem_heap_id,
+			 (enum sys_emem_attrib)(mem_attribs | SYS_MEMATTRIB_CPU_WRITE),
+			 H264_SGM_BUFFER_BYTES_PER_MB *
+			 H264_SGM_MAX_MBS,
+			 DEV_MMU_PAGE_ALIGNMENT,
+			 &pict_dec_res->h264_sgm_buf);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			goto err_out_of_memory;
+
+		/* Clear the SGM data. */
+		memset(pict_dec_res->h264_sgm_buf.cpu_virt, 0, pict_dec_res->h264_sgm_buf.buf_size);
+		break;
+
+	default:
+		break;
+	}
+
+	pict_dec_res->ref_cnt = 1;
+
+	ret = resource_list_add_img(&dec_str_context->dec_res_lst, pict_dec_res, 0,
+				    &pict_dec_res->ref_cnt);
+
+	if (ret != IMG_SUCCESS) {
+		pr_warn("[USERSID=0x%08X] Failed to add resource",
+			dec_str_context->config.user_str_id);
+	}
+
+	return IMG_SUCCESS;
+
+err_out_of_memory:
+	if (pict_dec_res) {
+		if (fw_ctx_buf)
+			mmu_free_mem(dec_str_context->mmu_str_handle, &pict_dec_res->fw_ctx_buf);
+
+		kfree(pict_dec_res);
+		pict_dec_res = NULL;
+	}
+
+	pr_err("[USERSID=0x%08X] Failed to allocate device memory for stream decode resources",
+	       dec_str_context->config.user_str_id);
+
+	return IMG_ERROR_OUT_OF_MEMORY;
+}
+
+/*
+ * @Function  decoder_stream_create
+ */
+int decoder_stream_create(void *dec_ctx_arg,
+			  struct vdec_str_configdata str_cfg,
+			  unsigned int km_str_id, void **mmu_str_handle,
+			  void *vxd_dec_ctx, void *str_user_int_data,
+			  void **dec_str_ctx_arg, void *decoder_cb,
+			  void *query_cb)
+{
+	struct dec_ctx *dec_context = (struct dec_ctx *)dec_ctx_arg;
+	struct dec_str_ctx *dec_str_ctx = NULL;
+	unsigned int i;
+	int ret;
+	unsigned int mem_heap_id;
+	enum sys_emem_attrib mem_attribs;
+	struct dec_core_ctx *dec_core_ctx_local;
+
+	/* Check input parameters. */
+	VDEC_ASSERT(dec_ctx_arg);
+	if (!dec_ctx_arg) {
+		pr_err("Invalid parameters!");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (dec_context->str_cnt >= MAX_CONCURRENT_STREAMS) {
+		pr_err("Device has too many concurrent streams. Number of Concurrent streams allowed: %d.",
+		       MAX_CONCURRENT_STREAMS);
+		return IMG_ERROR_DEVICE_UNAVAILABLE;
+	}
+
+	mem_heap_id = dec_context->internal_heap_id;
+	mem_attribs = (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE);
+	mem_attribs |= (enum sys_emem_attrib)SYS_MEMATTRIB_INTERNAL;
+
+	/* Allocate Decoder Stream Context */
+	dec_str_ctx = kzalloc(sizeof(*dec_str_ctx), GFP_KERNEL);
+	VDEC_ASSERT(dec_str_ctx);
+	if (!dec_str_ctx)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/* Increment the stream counter */
+	dec_context->str_cnt++;
+
+	/*
+	 * Initialise the context structure to NULL. Any non-zero
+	 * default values should be set at this point.
+	 */
+	dec_str_ctx->config = str_cfg;
+	dec_str_ctx->vxd_dec_ctx = vxd_dec_ctx;
+	dec_str_ctx->usr_int_data = str_user_int_data;
+	dec_str_ctx->decctx = dec_context;
+
+	decoder_init_avail_slots(dec_str_ctx);
+
+	dec_str_ctx->next_dec_pict_id = 1;
+	dec_str_ctx->next_pict_id_expected = 1;
+
+	dec_str_ctx->km_str_id = km_str_id;
+	VDEC_ASSERT(dec_str_ctx->km_str_id > 0);
+
+	lst_init(&dec_str_ctx->pend_strunit_list);
+	dq_init(&dec_str_ctx->str_decd_pict_list);
+	lst_init(&dec_str_ctx->ref_res_lst);
+	lst_init(&dec_str_ctx->dec_res_lst);
+
+	ret = idgen_createcontext(DECODER_MAX_PICT_ID + 1,
+				  DECODER_MAX_CONCURRENT_PICT,
+				  TRUE,
+				  &dec_str_ctx->pict_idgen);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	/* Create an MMU context for this stream. */
+	ret = mmu_stream_create(dec_context->mmu_dev_handle,
+				dec_str_ctx->km_str_id,
+				dec_str_ctx->vxd_dec_ctx,
+				&dec_str_ctx->mmu_str_handle);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	dec_core_ctx_local = dec_context->dec_core_ctx;
+
+	VDEC_ASSERT(dec_core_ctx_local);
+
+	/* Create core resources */
+	ret = dec_res_create(dec_str_ctx->mmu_str_handle,
+			     &dec_core_ctx_local->core_props,
+			     dec_context->dev_cfg->num_slots_per_pipe *
+			     dec_context->num_pipes,
+			     dec_context->internal_heap_id,
+			     &dec_str_ctx->resources);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	/* Allocate the PVDEC firmware context buffer */
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s:%d calling MMU_StreamMalloc", __func__, __LINE__);
+#endif
+	ret = mmu_stream_alloc(dec_str_ctx->mmu_str_handle, MMU_HEAP_STREAM_BUFFERS,
+			       mem_heap_id,
+			       (enum sys_emem_attrib)(mem_attribs | SYS_MEMATTRIB_CPU_WRITE),
+			       CONTEXT_BUFF_SIZE,
+			       DEV_MMU_PAGE_ALIGNMENT,
+			       &dec_str_ctx->pvdec_fw_ctx_buf);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	/*
+	 * Clear the context data in preparation for
+	 * first time use by the firmware.
+	 */
+	memset(dec_str_ctx->pvdec_fw_ctx_buf.cpu_virt, 0, dec_str_ctx->pvdec_fw_ctx_buf.buf_size);
+
+	/*
+	 * Create enough device resources to hold last context on
+	 * front and back-end for stream.
+	 */
+	dec_str_ctx->num_dec_res =
+		dec_str_ctx->decctx->dev_cfg->num_slots_per_pipe *
+		dec_str_ctx->decctx->num_pipes;
+	for (i = 0; i < dec_str_ctx->num_dec_res + 2; i++) {
+		ret = decoder_stream_decode_resource_create(dec_str_ctx);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			goto error;
+	}
+
+	dec_str_ctx->str_processed_cb = (strunit_processed_cb)decoder_cb;
+
+	dec_str_ctx->core_query_cb = (core_gen_cb)query_cb;
+
+	lst_add(&dec_context->str_list, dec_str_ctx);
+
+	*dec_str_ctx_arg = (void *)dec_str_ctx;
+	*mmu_str_handle = dec_str_ctx->mmu_str_handle;
+
+	return IMG_SUCCESS;
+
+	/* Roll back in case of errors. */
+error:
+	decoder_stream_destroy((void *)dec_str_ctx, FALSE);
+
+	return ret;
+}
+
+/*
+ * @Function  decoder_get_decoded_pict
+ */
+static struct dec_decoded_pict *decoder_get_decoded_pict(unsigned int transaction_id,
+							 struct dq_linkage_t *dq_list)
+{
+	struct dec_decoded_pict *decoded_pict;
+	void *item = NULL;
+
+	VDEC_ASSERT(dq_list);
+
+	decoded_pict = dq_first(dq_list);
+	while (decoded_pict) {
+		if (decoded_pict->transaction_id == transaction_id) {
+			item = decoded_pict;
+			break;
+		}
+
+		if (decoded_pict != dq_last(dq_list))
+			decoded_pict = dq_next(decoded_pict);
+		else
+			decoded_pict = NULL;
+	}
+
+	return item;
+}
+
+/*
+ * @Function  decoder_get_decoded_pict_of_stream
+ */
+static struct dec_decoded_pict *decoder_get_decoded_pict_of_stream(unsigned int pict_id,
+								   struct dq_linkage_t *dq_list)
+{
+	struct dec_decoded_pict *decoded_pict;
+	void *item = NULL;
+
+	VDEC_ASSERT(dq_list);
+
+	decoded_pict = dq_first(dq_list);
+	while (decoded_pict) {
+		if (GET_STREAM_PICTURE_ID(decoded_pict->transaction_id) == pict_id) {
+			item = decoded_pict;
+			break;
+		}
+
+		if (decoded_pict != dq_last(dq_list))
+			decoded_pict = dq_next(decoded_pict);
+		else
+			decoded_pict = NULL;
+	}
+	return item;
+}
+
+/*
+ * @Function  decoder_get_next_decpict_contiguous
+ */
+static struct
+dec_decoded_pict *decoder_get_next_decpict_contiguous(struct dec_decoded_pict *decoded_pict,
+						      unsigned int next_dec_pict_id,
+						      struct dq_linkage_t *str_decoded_pict_list)
+{
+	struct dec_decoded_pict *next_dec_pict = NULL;
+	struct dec_decoded_pict *result_dec_pict = NULL;
+
+	VDEC_ASSERT(str_decoded_pict_list);
+	if (!str_decoded_pict_list) {
+		pr_err("Invalid parameter");
+		return NULL;
+	}
+
+	if (decoded_pict) {
+		if (decoded_pict != dq_last(str_decoded_pict_list)) {
+			next_dec_pict = dq_next(decoded_pict);
+			if (!next_dec_pict) {
+				VDEC_ASSERT(0);
+				return NULL;
+			}
+
+			if (next_dec_pict->pict) {
+				/*
+				 * If we have no holes in the decoded list
+				 * (i.e. next decoded picture is next in
+				 * bitstream decode order).
+				 */
+				if (HAS_X_REACHED_Y(next_dec_pict_id, next_dec_pict->pict->pict_id,
+						    1 << FWIF_NUMBITS_STREAM_PICTURE_ID,
+						    unsigned int)) {
+					result_dec_pict = next_dec_pict;
+				}
+			}
+		}
+	}
+
+	return result_dec_pict;
+}
+
+/*
+ * @Function  decoder_next_picture
+ * @Description
+ * Returns the next unprocessed picture or NULL if the next picture is not
+ * next in bitstream decode order or there are no more decoded pictures in the
+ * list.
+
+ * @Input     psCurrentDecodedPicture : Pointer to current decoded picture.
+
+ * @Input     ui32NextDecPictId       : Picture ID of next picture in decode
+ *					order.
+
+ * @Input     psStrDecdPictList       : Pointer to decoded picture list.
+
+ * @Return    DECODER_sDecodedPict *  : Pointer to next decoded picture to
+ *					process.
+ */
+static struct dec_decoded_pict *decoder_next_picture(struct dec_decoded_pict *cur_decoded_pict,
+						     unsigned int next_dec_pict_d,
+						     struct dq_linkage_t *str_decodec_pict_list)
+{
+	struct dec_decoded_pict *ret = NULL;
+
+	VDEC_ASSERT(str_decodec_pict_list);
+	if (!str_decodec_pict_list)
+		return NULL;
+
+	if (!cur_decoded_pict)
+		cur_decoded_pict = dq_first(str_decodec_pict_list);
+
+	if (cur_decoded_pict && !cur_decoded_pict->process_failed) {
+		/* Search for picture ID greater than picture in list */
+		do {
+			if (!cur_decoded_pict->processed) {
+				/*
+				 * Return the current one because it has not
+				 * been processed
+				 */
+				ret = cur_decoded_pict;
+				break;
+			}
+			/*
+			 * Obtain a pointer to the next picture in bitstream
+			 * decode order.
+			 */
+			cur_decoded_pict = decoder_get_next_decpict_contiguous
+								(cur_decoded_pict,
+								 next_dec_pict_d,
+								 str_decodec_pict_list);
+		} while (cur_decoded_pict &&
+			!cur_decoded_pict->process_failed);
+	}
+	return ret;
+}
+
+/*
+ * @Function  decoder_picture_display
+ */
+static int decoder_picture_display(struct dec_str_ctx *dec_str_ctx,
+				   unsigned int pict_id, unsigned char last)
+{
+	struct vdecdd_picture *picture;
+	int ret;
+	static unsigned int display_num;
+
+	VDEC_ASSERT(dec_str_ctx);
+
+	ret = idgen_gethandle(dec_str_ctx->pict_idgen, pict_id, (void **)&picture);
+	if (ret == IMG_SUCCESS) {
+		struct vdecdd_ddbuf_mapinfo *pict_buf;
+
+		/* validate pointers */
+		if (!picture || !picture->dec_pict_info) {
+			VDEC_ASSERT(0);
+			return -EIO;
+		}
+
+		pict_buf = picture->disp_pict_buf.pict_buf;
+		VDEC_ASSERT(pict_buf);
+
+		/*
+		 * Indicate whether there are more pictures
+		 * coming for display.
+		 */
+		picture->dec_pict_info->last_in_seq = last;
+
+		/* Set decode order id */
+		picture->dec_pict_info->decode_id = pict_id;
+
+		/* Return the picture to the client for display */
+		dec_str_ctx->dec_str_st.total_pict_displayed++;
+		resource_item_use(&pict_buf->ddbuf_info.ref_count);
+		display_num++;
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("[USERSID=0x%08X] DISPLAY(%d): PIC_ID[%d]",
+			dec_str_ctx->config.user_str_id, display_num, pict_id);
+#endif
+
+		VDEC_ASSERT(dec_str_ctx->decctx);
+		ret = dec_str_ctx->str_processed_cb(dec_str_ctx->usr_int_data,
+				VXD_CB_PICT_DISPLAY,
+				picture);
+
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		/*
+		 * All handles will be freed after actually
+		 * displaying the picture.
+		 * Reset them to NULL here to avoid any confusion.
+		 */
+		memset(&picture->dec_pict_sup_data, 0, sizeof(picture->dec_pict_sup_data));
+	} else {
+		pr_warn("[USERSID=0x%08X] ERROR: DISPLAY PICTURE HAS AN EXPIRED ID",
+			dec_str_ctx->config.user_str_id);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+	}
+
+	return IMG_SUCCESS;
+}
+
+#ifdef ERROR_CONCEALMENT
+/*
+ * @Function              decoder_get_pict_processing_info
+ */
+static unsigned char decoder_get_pict_processing_info(struct dec_core_ctx *dec_corectx,
+						      struct dec_str_ctx *dec_strctx,
+						      struct bspp_pict_hdr_info *pict_hdr_info,
+						      struct dec_decoded_pict *decoded_pict,
+						      struct dec_decpict *dec_pict,
+						      unsigned int *pict_last_mb)
+{
+	int ret = IMG_SUCCESS;
+	unsigned char pipe_minus1;
+	struct hwctrl_state last_state;
+	unsigned int width_in_mb;
+	unsigned int height_in_mb;
+	unsigned int i;
+
+	memset(&last_state, 0, sizeof(last_state));
+
+	VDEC_ASSERT(pict_hdr_info);
+	width_in_mb = (pict_hdr_info->coded_frame_size.width +
+		(VDEC_MB_DIMENSION - 1)) / VDEC_MB_DIMENSION;
+	height_in_mb = (pict_hdr_info->coded_frame_size.height +
+		(VDEC_MB_DIMENSION - 1)) / VDEC_MB_DIMENSION;
+
+	VDEC_ASSERT(pict_last_mb);
+	*pict_last_mb = width_in_mb * height_in_mb;
+	VDEC_ASSERT(decoded_pict);
+
+	if (decoded_pict->first_fld_fwmsg->pict_attrs.pict_attrs.dwrfired ||
+	    decoded_pict->second_fld_fwmsg->pict_attrs.pict_attrs.dwrfired ||
+	    decoded_pict->first_fld_fwmsg->pict_attrs.pict_attrs.mmufault ||
+	    decoded_pict->second_fld_fwmsg->pict_attrs.pict_attrs.mmufault) {
+		struct dec_pict_attrs *pict_attrs = &decoded_pict->first_fld_fwmsg->pict_attrs;
+		unsigned char be_found = FALSE;
+		unsigned int mbs_dropped = 0;
+		unsigned int mbs_recovered = 0;
+		unsigned int no_be_wdt = 0;
+		unsigned int max_y = 0;
+		unsigned int row_drop = 0;
+
+		VDEC_ASSERT(dec_corectx);
+		/* Obtain the last available core status -
+		 * cached before clocks where switched off
+		 */
+		ret = hwctrl_getcore_cached_status(dec_corectx->hw_ctx, &last_state);
+		if (ret != IMG_SUCCESS)
+			return FALSE;
+
+		/* Try to determine pipe where the last picture was decoded on (BE) */
+		for (pipe_minus1 = 0; pipe_minus1 < VDEC_MAX_PIXEL_PIPES; pipe_minus1++) {
+			for (i = VDECFW_CHECKPOINT_BE_END; i >= VDECFW_CHECKPOINT_BE_START; i--) {
+				struct vxd_pipestate *pipe_state =
+					&last_state.core_state.fw_state.pipe_state[pipe_minus1];
+
+				if (!pipe_state->is_pipe_present)
+					continue;
+
+				if (pipe_state->acheck_point[i] == decoded_pict->transaction_id) {
+					row_drop += width_in_mb - pipe_state->be_mb.x;
+					if (pipe_state->be_mb.y > max_y)
+						max_y = pipe_state->be_mb.y;
+
+					if (pipe_state->be_mbs_dropped > mbs_dropped)
+						mbs_dropped = pipe_state->be_mbs_dropped;
+
+					if (pipe_state->be_mbs_recovered > mbs_recovered)
+						mbs_recovered = pipe_state->be_mbs_recovered;
+
+					no_be_wdt += pipe_state->be_errored_slices;
+					be_found = TRUE;
+				}
+			}
+			if (be_found)
+				/* No need to check FE as we already have an info from BE */
+				continue;
+
+			/* If not found, we probbaly stuck on FE ? */
+			for (i = VDECFW_CHECKPOINT_FE_END; i >= VDECFW_CHECKPOINT_FE_START; i--) {
+				struct vxd_pipestate *pipe_state =
+					&last_state.core_state.fw_state.pipe_state[pipe_minus1];
+
+				if (!pipe_state->is_pipe_present)
+					continue;
+
+				if (pipe_state->acheck_point[i] == decoded_pict->transaction_id) {
+					/* Mark all MBs as dropped */
+					pict_attrs->mbs_dropped = *pict_last_mb;
+					pict_attrs->mbs_recovered = 0;
+					return TRUE;
+				}
+			}
+		}
+
+		if (be_found) {
+			/* Calculate last macroblock number processed on BE */
+			unsigned int num_mb_processed = (max_y * width_in_mb) - row_drop;
+
+			/* Sanity check, as HW may signal MbYX position
+			 * beyond picture for corrupted streams
+			 */
+			if (num_mb_processed > (*pict_last_mb))
+				num_mb_processed = (*pict_last_mb); /* trim */
+
+			if (((*pict_last_mb) - num_mb_processed) > mbs_dropped)
+				mbs_dropped = (*pict_last_mb) - num_mb_processed;
+
+			pict_attrs->mbs_dropped = mbs_dropped;
+			pict_attrs->mbs_recovered = num_mb_processed;
+			pict_attrs->no_be_wdt = no_be_wdt;
+			return TRUE;
+		}
+		return FALSE;
+	}
+	/* Picture was decoded without DWR, so we have already the required info */
+	return TRUE;
+}
+#endif
+
+/*
+ * @Function  decoder_picture_release
+ */
+static int decoder_picture_release(struct dec_str_ctx *dec_str_ctx,
+				   unsigned int pict_id,
+				   unsigned char displayed,
+				   unsigned char merged)
+{
+	struct vdecdd_picture *picture;
+	int ret;
+
+	/* validate input arguments */
+	if (!dec_str_ctx) {
+		VDEC_ASSERT(0);
+		return -EINVAL;
+	}
+
+	ret = idgen_gethandle(dec_str_ctx->pict_idgen, pict_id, (void **)&picture);
+	if (ret == IMG_SUCCESS) {
+		if (!picture || !picture->dec_pict_info) {
+			VDEC_ASSERT(0);
+			return -EINVAL;
+		}
+
+		/* Set decode order id */
+		picture->dec_pict_info->decode_id = pict_id;
+
+		VDEC_ASSERT(dec_str_ctx->decctx);
+
+		pr_debug("Decoder picture released pict_id = %d\n", pict_id);
+		ret = dec_str_ctx->str_processed_cb(dec_str_ctx->usr_int_data,
+				VXD_CB_PICT_RELEASE,
+				picture);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		/*
+		 * All handles will be freed after actually displaying
+		 * the picture. Reset them to NULL here to avoid any
+		 * confusion.
+		 */
+		memset(&picture->dec_pict_sup_data, 0, sizeof(picture->dec_pict_sup_data));
+	} else {
+		pr_err("[USERSID=0x%08X] ERROR: RELEASE PICTURE HAS AN EXPIRED ID",
+		       dec_str_ctx->config.user_str_id);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function decoder_stream_flush_process_dpb_h264
+ */
+static int
+decoder_stream_flush_process_dpb_h264(struct dec_str_ctx *dec_str_ctx,
+				      struct dec_decoded_pict *decoded_pict,
+				      unsigned char discard_refs)
+{
+	int ret;
+
+	struct h264fw_context_data *ctx_data =
+	(struct h264fw_context_data *)dec_str_ctx->last_be_pict_dec_res->fw_ctx_buf.cpu_virt;
+	unsigned char found = TRUE;
+	unsigned int i;
+	int min_cnt;
+	int min_cnt_idx;
+	unsigned int num_display_pics = 0;
+	unsigned int num_pics_displayed = 0;
+	struct dec_decoded_pict *display_pict = NULL;
+	unsigned int last_disp_pict_tid;
+	unsigned int pict_id;
+
+	/* Determine how many display pictures reside in the DPB */
+	if (ctx_data->dpb_size > H264FW_MAX_DPB_SIZE || ctx_data->dpb_size <= 0) {
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("[USERSID=0x%08X] Incorrect DPB size: %d",
+			dec_str_ctx->config.user_str_id, ctx_data->dpb_size);
+#endif
+		ctx_data->dpb_size = H264FW_MAX_DPB_SIZE;
+	}
+	for (i = 0; i < ctx_data->dpb_size; i++) {
+		if (ctx_data->dpb[i].transaction_id)
+			if (ctx_data->dpb[i].needed_for_output)
+				num_display_pics++;
+	}
+
+	last_disp_pict_tid = ctx_data->last_displayed_pic_data[0].transaction_id;
+	/* Check for picture stuck outside the dpb */
+	if (last_disp_pict_tid) {
+		VDEC_ASSERT(last_disp_pict_tid != 0xffffffff);
+
+		display_pict = decoder_get_decoded_pict(last_disp_pict_tid,
+							&dec_str_ctx->str_decd_pict_list);
+
+		if (display_pict && display_pict->pict &&
+		    display_pict->pict->dec_pict_info) {
+			if (FLAG_IS_SET(ctx_data->prev_display_flags,
+					VDECFW_BUFFLAG_DISPLAY_FIELD_CODED)) {
+				if (!FLAG_IS_SET(ctx_data->prev_display_flags,
+						 VDECFW_BUFFLAG_DISPLAY_SINGLE_FIELD))
+					display_pict->pict->dec_pict_info->buf_type =
+						IMG_BUFFERTYPE_PAIR;
+				else
+					display_pict->pict->dec_pict_info->buf_type =
+						FLAG_IS_SET
+						(ctx_data->prev_display_flags,
+						 VDECFW_BUFFLAG_DISPLAY_BOTTOM_FIELD) ?
+						 IMG_BUFFERTYPE_FIELD_BOTTOM :
+						 IMG_BUFFERTYPE_FIELD_TOP;
+			} else {
+				display_pict->pict->dec_pict_info->buf_type =
+					IMG_BUFFERTYPE_FRAME;
+			}
+		} else {
+			VDEC_ASSERT(display_pict);
+			VDEC_ASSERT(display_pict && display_pict->pict);
+			VDEC_ASSERT(display_pict && display_pict->pict &&
+				    display_pict->pict->dec_pict_info);
+		}
+
+		if (display_pict && !display_pict->displayed) {
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("[USERSID=0x%08X] [TID=0x%08X] DISPLAY",
+				dec_str_ctx->config.user_str_id,
+				last_disp_pict_tid);
+#endif
+			display_pict->displayed = TRUE;
+			ret = decoder_picture_display
+				(dec_str_ctx, GET_STREAM_PICTURE_ID(last_disp_pict_tid),
+				 TRUE);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+		}
+	}
+
+	while (found) {
+		min_cnt = ((unsigned int)(1 << 31)) - 1;
+		min_cnt_idx = -1;
+		found = FALSE;
+
+		/* Loop over the DPB to find the first in order */
+		for (i = 0; i < ctx_data->dpb_size; i++) {
+			if (ctx_data->dpb[i].transaction_id &&
+			    (ctx_data->dpb[i].needed_for_output ||
+				discard_refs)) {
+				if (ctx_data->dpb[i].top_field_order_count <
+					min_cnt) {
+					min_cnt =
+						ctx_data->dpb[i].top_field_order_count;
+					min_cnt_idx = i;
+					found = TRUE;
+				}
+			}
+		}
+
+		if (found) {
+			unsigned int umin_cnt_tid = ctx_data->dpb[min_cnt_idx].transaction_id;
+
+			if (ctx_data->dpb[min_cnt_idx].needed_for_output) {
+				VDEC_ASSERT(umin_cnt_tid != 0xffffffff);
+				display_pict =
+					decoder_get_decoded_pict(umin_cnt_tid,
+								 &dec_str_ctx->str_decd_pict_list);
+
+				if ((display_pict && display_pict->pict &&
+				     display_pict->pict->dec_pict_info) &&
+				    FLAG_IS_SET(ctx_data->dpb[min_cnt_idx].display_flags,
+						VDECFW_BUFFLAG_DISPLAY_FIELD_CODED)) {
+					if (!FLAG_IS_SET(ctx_data->dpb[min_cnt_idx].display_flags,
+							 VDECFW_BUFFLAG_DISPLAY_SINGLE_FIELD))
+						display_pict->pict->dec_pict_info->buf_type =
+									IMG_BUFFERTYPE_PAIR;
+					else
+						display_pict->pict->dec_pict_info->buf_type =
+							FLAG_IS_SET
+							(ctx_data->dpb
+							 [min_cnt_idx].display_flags,
+							 VDECFW_BUFFLAG_DISPLAY_BOTTOM_FIELD)
+							?
+							IMG_BUFFERTYPE_FIELD_BOTTOM :
+							IMG_BUFFERTYPE_FIELD_TOP;
+					display_pict->pict->dec_pict_info->view_id =
+						ctx_data->dpb[min_cnt_idx].view_id;
+				} else if ((display_pict && display_pict->pict &&
+					   display_pict->pict->dec_pict_info) &&
+					   (!FLAG_IS_SET(ctx_data->dpb[min_cnt_idx].display_flags,
+					    VDECFW_BUFFLAG_DISPLAY_FIELD_CODED))){
+					display_pict->pict->dec_pict_info->buf_type =
+						IMG_BUFFERTYPE_FRAME;
+					display_pict->pict->dec_pict_info->view_id =
+						ctx_data->dpb[min_cnt_idx].view_id;
+				} else {
+					VDEC_ASSERT(display_pict);
+					VDEC_ASSERT(display_pict && display_pict->pict);
+					VDEC_ASSERT(display_pict && display_pict->pict &&
+						    display_pict->pict->dec_pict_info);
+				}
+
+				if (display_pict && !display_pict->displayed) {
+#ifdef DEBUG_DECODER_DRIVER
+					pr_info("[USERSID=0x%08X] [TID=0x%08X] DISPLAY",
+						dec_str_ctx->config.user_str_id,
+						umin_cnt_tid);
+#endif
+					display_pict->displayed = TRUE;
+					num_pics_displayed++;
+					ret = decoder_picture_display
+							(dec_str_ctx,
+							 GET_STREAM_PICTURE_ID(umin_cnt_tid),
+							 num_pics_displayed == num_display_pics ?
+							 TRUE : FALSE);
+					VDEC_ASSERT(ret == IMG_SUCCESS);
+					if (ret != IMG_SUCCESS)
+						return ret;
+				}
+				ctx_data->dpb[min_cnt_idx].needed_for_output = FALSE;
+			}
+
+			if (discard_refs) {
+				decoded_pict =
+					decoder_get_decoded_pict(umin_cnt_tid,
+								 &dec_str_ctx->str_decd_pict_list);
+				if (decoded_pict) {
+					/* Signal releasing this picture to upper layers. */
+					pict_id =
+						GET_STREAM_PICTURE_ID(decoded_pict->transaction_id);
+					decoder_picture_release(dec_str_ctx,
+								pict_id,
+								decoded_pict->displayed,
+								decoded_pict->merged);
+					/* Destroy the decoded picture. */
+					ret = decoder_decoded_picture_destroy(dec_str_ctx,
+									      decoded_pict, FALSE);
+					VDEC_ASSERT(ret == IMG_SUCCESS);
+					if (ret != IMG_SUCCESS)
+						return ret;
+				}
+				ctx_data->dpb[min_cnt_idx].transaction_id = 0;
+			}
+		}
+	}
+
+	VDEC_ASSERT(num_pics_displayed == num_display_pics);
+
+	return IMG_SUCCESS;
+}
+
+#ifdef HAS_HEVC
+/*
+ * decoder_StreamFlushProcessDPB_HEVC
+ */
+static int decoder_stream_flush_process_dpb_hevc(struct dec_str_ctx *decstr_ctx,
+						 struct dec_decoded_pict *decoded_pict,
+						 unsigned char discard_refs)
+{
+	int result;
+	struct hevcfw_ctx_data *ctx =
+		(struct hevcfw_ctx_data *)decstr_ctx->last_be_pict_dec_res->fw_ctx_buf.cpu_virt;
+	struct hevcfw_decoded_picture_buffer *dpb;
+	unsigned char found = TRUE;
+	unsigned char idx;
+	int min_poc_val;
+	signed char dpb_idx;
+	unsigned char num_display_pics = 0;
+	unsigned char num_pics_displayed = 0;
+	struct dec_decoded_pict *display_pict = NULL;
+
+	/*
+	 * Update the fw context for analysing the dpb in order
+	 * to display or release any outstanding picture
+	 */
+	dpb = &ctx->dpb;
+
+	/* Determine how many display pictures reside in the DPB. */
+	for (idx = 0; idx < HEVCFW_MAX_DPB_SIZE; ++idx) {
+		struct hevcfw_picture_in_dpb *dpb_pic = &dpb->pictures[idx];
+
+		if (dpb_pic->valid && dpb_pic->needed_for_output)
+			++num_display_pics;
+	}
+
+	while (found) {
+		struct hevcfw_picture_in_dpb *dpb_pic;
+
+		min_poc_val = 0x7fffffff;
+		dpb_idx = HEVCFW_DPB_IDX_INVALID;
+		found = FALSE;
+
+		/* Loop over the DPB to find the first in order */
+		for (idx = 0; idx < HEVCFW_MAX_DPB_SIZE; ++idx) {
+			dpb_pic = &dpb->pictures[idx];
+			if (dpb_pic->valid && (dpb_pic->needed_for_output || discard_refs)) {
+				if (dpb_pic->picture.pic_order_cnt_val < min_poc_val) {
+					min_poc_val = dpb_pic->picture.pic_order_cnt_val;
+					dpb_idx = idx;
+					found = TRUE;
+				}
+			}
+		}
+
+		if (!found)
+			break;
+
+		dpb_pic = &dpb->pictures[dpb_idx];
+
+		if (dpb_pic->needed_for_output) {
+			unsigned int str_pic_id = GET_STREAM_PICTURE_ID
+							(dpb_pic->picture.transaction_id);
+
+			VDEC_ASSERT(dpb_pic->picture.transaction_id != 0xffffffff);
+			display_pict = decoder_get_decoded_pict(dpb_pic->picture.transaction_id,
+								&decstr_ctx->str_decd_pict_list);
+
+			if (display_pict && display_pict->pict &&
+			    display_pict->pict->dec_pict_info) {
+				display_pict->pict->dec_pict_info->buf_type = IMG_BUFFERTYPE_FRAME;
+			} else {
+				VDEC_ASSERT(display_pict);
+				VDEC_ASSERT(display_pict && display_pict->pict);
+				VDEC_ASSERT(display_pict && display_pict->pict &&
+					    display_pict->pict->dec_pict_info);
+
+				dpb_pic->valid = FALSE;
+				continue;
+			}
+
+			if (!display_pict->displayed) {
+				display_pict->displayed = TRUE;
+				++num_pics_displayed;
+				result = decoder_picture_display(decstr_ctx, str_pic_id,
+								 num_pics_displayed ==
+								 num_display_pics);
+				VDEC_ASSERT(result == IMG_SUCCESS);
+				if (result != IMG_SUCCESS)
+					return result;
+			}
+			dpb_pic->needed_for_output = FALSE;
+		}
+
+		if (discard_refs) {
+			decoded_pict = decoder_get_decoded_pict(dpb_pic->picture.transaction_id,
+								&decstr_ctx->str_decd_pict_list);
+
+			if (decoded_pict) {
+				/* Signal releasing this picture to upper layers. */
+				decoder_picture_release(decstr_ctx,
+							GET_STREAM_PICTURE_ID
+							(decoded_pict->transaction_id),
+							decoded_pict->displayed,
+							decoded_pict->merged);
+				/* Destroy the decoded picture. */
+				result = decoder_decoded_picture_destroy(decstr_ctx, decoded_pict,
+									 FALSE);
+				VDEC_ASSERT(result == IMG_SUCCESS);
+				if (result != IMG_SUCCESS)
+					return result;
+			}
+			dpb_pic->valid = FALSE;
+		}
+	}
+
+	VDEC_ASSERT(num_pics_displayed == num_display_pics);
+
+	return IMG_SUCCESS;
+}
+#endif
+
+/*
+ * @Function        decoder_stream_flush_process_dpb
+ * @Description
+ * Process DPB fetched from firmware, display and release relevant pictures.
+ */
+static int decoder_stream_flush_process_dpb(struct dec_str_ctx *dec_str_ctx,
+					    struct dec_decoded_pict *decoded_pict,
+					    unsigned char discard_refs)
+{
+	int ret = 0;
+	/* Get oldest reference to display. */
+	decoded_pict = dq_last(&dec_str_ctx->str_decd_pict_list);
+	if (decoded_pict) {
+		switch (dec_str_ctx->config.vid_std) {
+		case VDEC_STD_H264:
+			ret = decoder_stream_flush_process_dpb_h264(dec_str_ctx, decoded_pict,
+								    discard_refs);
+
+			break;
+#ifdef HAS_HEVC
+		case VDEC_STD_HEVC:
+			decoder_stream_flush_process_dpb_hevc(dec_str_ctx,
+							      decoded_pict, discard_refs);
+#endif
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	return ret;
+}
+
+int decoder_stream_flush(void *dec_str_ctx_arg, unsigned char discard_refs)
+{
+	struct dec_str_ctx *dec_str_ctx;
+	struct dec_str_unit *dec_str_unit;
+	struct dec_decoded_pict *decoded_pict;
+	int ret = 0;
+
+	dec_str_ctx = decoder_stream_get_context(dec_str_ctx_arg);
+	VDEC_ASSERT(dec_str_ctx);
+	if (!dec_str_ctx) {
+		pr_err("Invalid decoder stream context handle!");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/*
+	 * Since the stream should be stopped before flushing
+	 * there should be no pictures in the stream list.
+	 */
+	dec_str_unit = lst_first(&dec_str_ctx->pend_strunit_list);
+	while (dec_str_unit) {
+		VDEC_ASSERT(dec_str_unit->str_unit->str_unit_type !=
+			VDECDD_STRUNIT_PICTURE_START);
+		dec_str_unit = lst_next(dec_str_unit);
+	}
+
+	decoded_pict = dq_last(&dec_str_ctx->str_decd_pict_list);
+
+	ret = decoder_stream_flush_process_dpb(dec_str_ctx, decoded_pict,
+					       discard_refs);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	if (discard_refs) {
+		while (!dq_empty(&dec_str_ctx->str_decd_pict_list)) {
+			struct dec_decoded_pict *non_decoded_pict =
+				dq_first(&dec_str_ctx->str_decd_pict_list);
+
+			if (!non_decoded_pict) {
+				VDEC_ASSERT(0);
+				return -EINVAL;
+			}
+
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("[USERSID=0x%08X] Decoded picture list contains item ID:0x%08x when DPB is empty",
+				dec_str_ctx->config.user_str_id,
+				non_decoded_pict->transaction_id);
+#endif
+
+			/* release the buffers back to vxd_decoder */
+			decoder_picture_release(dec_str_ctx, GET_STREAM_PICTURE_ID
+							(non_decoded_pict->transaction_id), FALSE,
+							 FALSE);
+
+			ret = decoder_decoded_picture_destroy(dec_str_ctx, non_decoded_pict, FALSE);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+		}
+		VDEC_ASSERT(dq_empty(&dec_str_ctx->str_decd_pict_list));
+
+		if (dec_str_ctx->last_be_pict_dec_res)
+			/*
+			 * Clear the firmware context so that reference
+			 * pictures are no longer referred to.
+			 */
+			memset(dec_str_ctx->last_be_pict_dec_res->fw_ctx_buf.cpu_virt, 0,
+			       dec_str_ctx->last_be_pict_dec_res->fw_ctx_buf.buf_size);
+	}
+
+	pr_debug("Decoder stream flushed successfully\n");
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function  decoder_stream_prepare_ctx
+ */
+int decoder_stream_prepare_ctx(void *dec_str_ctx_arg, unsigned char flush_dpb)
+{
+	struct dec_str_ctx *dec_str_ctx =
+		decoder_stream_get_context(dec_str_ctx_arg);
+	int ret;
+
+	VDEC_ASSERT(dec_str_ctx);
+	if (!dec_str_ctx)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("[USERSID=0x%08X] [TID=0x%08X] Preparing stream context after seek",
+		dec_str_ctx->config.user_str_id,
+		dec_str_ctx->last_fe_transaction_id);
+#endif
+
+	if (flush_dpb) {
+		ret = decoder_stream_flush(dec_str_ctx, TRUE);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+	}
+
+	/* Reset front-end temporary pointers */
+	if (dec_str_ctx->prev_fe_pict_dec_res) {
+		resource_item_return(&dec_str_ctx->prev_fe_pict_dec_res->ref_cnt);
+		dec_str_ctx->prev_fe_pict_dec_res = NULL;
+	}
+	if (dec_str_ctx->cur_fe_pict_dec_res) {
+		resource_item_return(&dec_str_ctx->cur_fe_pict_dec_res->ref_cnt);
+		dec_str_ctx->cur_fe_pict_dec_res = NULL;
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function  decoder_get_load
+ */
+int decoder_get_load(void *dec_str_ctx_arg, unsigned int *avail_slots)
+{
+	struct dec_str_ctx *dec_str_ctx =
+		decoder_stream_get_context(dec_str_ctx_arg);
+	struct dec_core_ctx *dec_core_ctx_local = NULL;
+
+	/* Check input parameters. */
+	VDEC_ASSERT(dec_str_ctx);
+	if (!dec_str_ctx || !avail_slots) {
+		pr_err("Invalid parameters!");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	dec_core_ctx_local = decoder_str_ctx_to_core_ctx(dec_str_ctx);
+	if (!dec_core_ctx_local)  {
+		VDEC_ASSERT(0);
+		return -EIO;
+	}
+
+	if (dec_core_ctx_local->busy)
+		*avail_slots = 0;
+	else
+		*avail_slots = dec_str_ctx->avail_slots;
+
+	return IMG_SUCCESS;
+}
+
+static int decoder_check_ref_errors(struct dec_str_ctx *dec_str_ctx,
+				    struct vdecfw_buffer_control *buf_ctrl,
+				    struct vdecdd_picture *picture)
+{
+	struct dec_decoded_pict *ref_pict;
+	unsigned int i;
+
+	if (!dec_str_ctx) {
+		VDEC_ASSERT(0);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!buf_ctrl || !picture) {
+		pr_err("[USERSID=0x%08X] Invalid parameters for checking reference lists.",
+		       dec_str_ctx->config.user_str_id);
+		VDEC_ASSERT(0);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	for (i = 0; i < VDECFW_MAX_NUM_PICTURES && buf_ctrl->ref_list[i];
+		i++) {
+		ref_pict = decoder_get_decoded_pict_of_stream
+			(GET_STREAM_PICTURE_ID(buf_ctrl->ref_list[i]),
+				&dec_str_ctx->str_decd_pict_list);
+		if (ref_pict && ref_pict->pict && ref_pict->pict->dec_pict_info &&
+		    ref_pict->pict->dec_pict_info->err_flags) {
+			picture->dec_pict_info->err_flags |=
+				VDEC_ERROR_CORRUPTED_REFERENCE;
+			pr_warn("Picture decoded using corrupted reference: 0x%08X 0x%08X",
+				ref_pict->transaction_id,
+				ref_pict->pict->dec_pict_info->err_flags);
+		}
+	}
+
+	return IMG_SUCCESS;
+}
+
+static void decoder_clean_bitstr_segments(struct lst_t *decpict_seglist)
+{
+	struct dec_decpict_seg *dec_pict_seg;
+
+	while (NULL != (dec_pict_seg = lst_removehead(decpict_seglist))) {
+		if (dec_pict_seg->internal_seg) {
+			VDEC_ASSERT(dec_pict_seg->bstr_seg);
+			kfree(dec_pict_seg->bstr_seg);
+			dec_pict_seg->bstr_seg = NULL;
+		}
+		kfree(dec_pict_seg);
+	}
+}
+
+static int decoder_wrap_bitstr_segments(struct lst_t *bitstr_seglist,
+					struct lst_t *decpict_seglist,
+					unsigned int user_str_id)
+{
+	/* Required for attaching segments to the decode picture */
+	struct bspp_bitstr_seg  *bit_str_seg;
+	struct dec_decpict_seg  *dec_pict_seg;
+
+	VDEC_ASSERT(bitstr_seglist);
+	VDEC_ASSERT(decpict_seglist);
+
+	/* Add the segments to the Decode Picture */
+	bit_str_seg = lst_first(bitstr_seglist);
+	while (bit_str_seg) {
+		dec_pict_seg = kzalloc(sizeof(*dec_pict_seg), GFP_KERNEL);
+		VDEC_ASSERT(dec_pict_seg);
+		if (!dec_pict_seg)
+			return IMG_ERROR_OUT_OF_MEMORY;
+
+		dec_pict_seg->bstr_seg = bit_str_seg;
+		dec_pict_seg->internal_seg = FALSE;
+		lst_add(decpict_seglist, dec_pict_seg);
+
+		bit_str_seg = lst_next(bit_str_seg);
+	}
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function decoder_picture_decode
+ */
+static int decoder_picture_decode(struct dec_str_ctx *dec_str_ctx,
+				  struct vdecdd_str_unit *str_unit,
+				  struct dec_decpict **dec_pict_ptr)
+{
+	struct vdecdd_picture *picture;
+	struct dec_core_ctx *dec_core_ctx;
+	struct dec_decpict *dec_pict;
+	int ret = IMG_SUCCESS;
+	struct decoder_regsoffsets regs_offsets;
+
+	/* Validate input arguments */
+	if (!dec_str_ctx || !str_unit || !str_unit->pict_hdr_info || !dec_pict_ptr) {
+		VDEC_ASSERT(0);
+		return -EIO;
+	}
+
+	picture = (struct vdecdd_picture *)str_unit->dd_pict_data;
+	dec_core_ctx = decoder_str_ctx_to_core_ctx(dec_str_ctx);
+
+	if (!picture || !dec_core_ctx) {
+		VDEC_ASSERT(0);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Ensure this is a new picture */
+	VDEC_ASSERT(!dec_str_ctx->cur_pict);
+	VDEC_ASSERT(str_unit->str_unit_type == VDECDD_STRUNIT_PICTURE_START);
+
+	dec_core_ctx->cum_pics++;
+
+	/* Allocate a unique id to the picture */
+	ret = idgen_allocid(dec_str_ctx->pict_idgen, picture, &picture->pict_id);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	/* Allocate the decoded picture information structure. */
+	picture->dec_pict_info = kzalloc(sizeof(*picture->dec_pict_info), GFP_KERNEL);
+	VDEC_ASSERT(picture->dec_pict_info);
+	if (!picture->dec_pict_info)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/* Extract decoded information from the stream unit */
+	picture->dec_pict_info->err_flags = str_unit->err_flags;
+	picture->dec_pict_info->first_fld_tag_container.pict_tag_param =
+		(unsigned long)(str_unit->str_unit_tag);
+	picture->dec_pict_info->op_config = picture->op_config;
+	picture->dec_pict_info->rend_info = picture->disp_pict_buf.rend_info;
+	picture->dec_pict_info->disp_info = str_unit->pict_hdr_info->disp_info;
+
+	/* Extract aux picture information from the stream unit */
+	picture->dec_pict_aux_info.seq_hdr_id =
+		str_unit->seq_hdr_info->sequ_hdr_id;
+	picture->dec_pict_aux_info.pps_id =
+		str_unit->pict_hdr_info->pict_aux_data.id;
+	picture->dec_pict_aux_info.second_pps_id =
+		str_unit->pict_hdr_info->second_pict_aux_data.id;
+
+	/* Create a new decoder picture container. */
+	dec_pict = kzalloc(sizeof(*dec_pict), GFP_KERNEL);
+	VDEC_ASSERT(dec_pict);
+	if (!dec_pict) {
+		ret = IMG_ERROR_OUT_OF_MEMORY;
+		goto error_dec_pict;
+	}
+
+	/* Attach decoder/picture context information. */
+	dec_pict->dec_str_ctx = dec_str_ctx;
+
+	/*
+	 * Construct the transaction Id.
+	 * This consists of stream and core number in addition to picture
+	 * number in stream and a 4-bit value representing the picture number
+	 * in core.
+	 */
+	dec_pict->transaction_id =
+		CREATE_TRANSACTION_ID(0, dec_str_ctx->km_str_id, dec_core_ctx->cum_pics,
+				      picture->pict_id);
+
+	/* Add picture to core decode list */
+	dec_str_ctx->dec_str_st.num_pict_decoding++;
+
+	/* Fake a FW message to process when decoded. */
+	dec_pict->first_fld_fwmsg = kzalloc(sizeof(*dec_pict->first_fld_fwmsg), GFP_KERNEL);
+	VDEC_ASSERT(dec_pict->first_fld_fwmsg);
+	if (!dec_pict->first_fld_fwmsg) {
+		ret = IMG_ERROR_OUT_OF_MEMORY;
+		goto error_fw_msg;
+	}
+
+	dec_pict->second_fld_fwmsg =
+		kzalloc(sizeof(*dec_pict->second_fld_fwmsg), GFP_KERNEL);
+	VDEC_ASSERT(dec_pict->second_fld_fwmsg);
+	if (!dec_pict->second_fld_fwmsg) {
+		ret = IMG_ERROR_OUT_OF_MEMORY;
+		goto error_fw_msg;
+	}
+
+	/* Add the segments to the Decode Picture */
+	ret = decoder_wrap_bitstr_segments(&str_unit->bstr_seg_list,
+					   &dec_pict->dec_pict_seg_list,
+					   dec_str_ctx->config.user_str_id);
+
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error_segments;
+
+	/*
+	 * Shuffle the current and previous
+	 * Hold a reference to the last context on the FE
+	 */
+	if (dec_str_ctx->prev_fe_pict_dec_res) {
+		/* Return previous last FW context. */
+		resource_item_return(&dec_str_ctx->prev_fe_pict_dec_res->ref_cnt);
+
+		if (resource_item_isavailable(&dec_str_ctx->prev_fe_pict_dec_res->ref_cnt)) {
+			resource_list_remove(&dec_str_ctx->dec_res_lst,
+					     dec_str_ctx->prev_fe_pict_dec_res);
+
+			resource_list_add_img(&dec_str_ctx->dec_res_lst,
+					      dec_str_ctx->prev_fe_pict_dec_res, 0,
+					      &dec_str_ctx->prev_fe_pict_dec_res->ref_cnt);
+		}
+	}
+
+	dec_str_ctx->prev_fe_pict_dec_res = dec_str_ctx->cur_fe_pict_dec_res;
+	dec_pict->prev_pict_dec_res = dec_str_ctx->prev_fe_pict_dec_res;
+
+	/* Get a new stream decode resource bundle for current picture. */
+	dec_pict->cur_pict_dec_res = resource_list_get_avail(&dec_str_ctx->dec_res_lst);
+	VDEC_ASSERT(dec_pict->cur_pict_dec_res);
+	if (!dec_pict->cur_pict_dec_res) {
+		ret = IMG_ERROR_UNEXPECTED_STATE;
+		goto error_dec_res;
+	}
+
+	if (dec_str_ctx->config.vid_std == VDEC_STD_H264) {
+		/* Copy any SGM for current picture. */
+		if (str_unit->pict_hdr_info->pict_sgm_data.id !=
+			BSPP_INVALID) {
+			VDEC_ASSERT(str_unit->pict_hdr_info->pict_sgm_data.size <=
+				    dec_pict->cur_pict_dec_res->h264_sgm_buf.buf_size);
+			/* Updated in translation_api */
+			memcpy(dec_pict->cur_pict_dec_res->h264_sgm_buf.cpu_virt,
+			       str_unit->pict_hdr_info->pict_sgm_data.pic_data,
+			       str_unit->pict_hdr_info->pict_sgm_data.size);
+		}
+	}
+
+	dec_pict->cur_pict_dec_res->transaction_id = dec_pict->transaction_id;
+	dec_str_ctx->cur_fe_pict_dec_res = dec_pict->cur_pict_dec_res;
+	resource_item_use(&dec_str_ctx->cur_fe_pict_dec_res->ref_cnt);
+
+	/* Get a new control buffer */
+	dec_pict->pict_ref_res =
+		resource_list_get_avail(&dec_str_ctx->ref_res_lst);
+	VDEC_ASSERT(dec_pict->pict_ref_res);
+	if (!dec_pict->pict_ref_res) {
+		ret = IMG_ERROR_UNEXPECTED_STATE;
+		goto error_ref_res;
+	}
+
+	VDEC_ASSERT(dec_str_ctx->decctx);
+	VDEC_ASSERT(dec_str_ctx->decctx->dev_cfg);
+
+	dec_pict->str_pvdec_fw_ctxbuf = &dec_str_ctx->pvdec_fw_ctx_buf;
+	dec_pict->pict_hdr_info = str_unit->pict_hdr_info;
+
+	/* Obtain (core) resources for the picture */
+	ret = dec_res_picture_attach(&dec_str_ctx->resources,
+				     dec_str_ctx->config.vid_std, dec_pict);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error_res_attach;
+
+	/* Clear fw context data for re-use */
+	memset(dec_pict->cur_pict_dec_res->fw_ctx_buf.cpu_virt, 0,
+	       dec_pict->cur_pict_dec_res->fw_ctx_buf.buf_size);
+
+	/*
+	 * Clear the control data in case the picture is discarded before
+	 * being prepared by firmware.
+	 */
+	memset(dec_pict->pict_ref_res->fw_ctrlbuf.cpu_virt, 0,
+	       dec_pict->pict_ref_res->fw_ctrlbuf.buf_size);
+
+	ret = hwctrl_getregsoffset(dec_core_ctx->hw_ctx, &regs_offsets);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error_other;
+
+	ret = translation_ctrl_alloc_prepare(&dec_str_ctx->config, str_unit,
+					     dec_pict,
+					     &dec_core_ctx->core_props,
+					     &regs_offsets);
+
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error_other;
+
+	ret = hwctrl_picture_submitbatch(dec_core_ctx->hw_ctx, dec_pict,
+					 dec_str_ctx->vxd_dec_ctx);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error_other;
+
+	VDEC_ASSERT(dec_str_ctx->avail_slots > 0);
+	dec_str_ctx->avail_slots--;
+
+	VDEC_ASSERT(!dec_core_ctx->busy);
+	dec_core_ctx->busy = TRUE;
+	/* Store this transaction ID in stream context */
+	dec_str_ctx->last_fe_transaction_id = dec_pict->transaction_id;
+	dec_str_ctx->cur_pict = (struct dec_decpict *)dec_pict;
+
+	dec_str_ctx->dec_str_st.features = str_unit->features;
+
+	if (str_unit->eop)
+		dec_pict->eop_found = TRUE;
+
+	*dec_pict_ptr = dec_pict;
+
+	return IMG_SUCCESS;
+
+	/* Roll back in case of errors. */
+error_other:
+	dec_res_picture_detach(&dec_str_ctx->resources, dec_pict);
+error_res_attach:
+error_ref_res:
+error_dec_res:
+error_segments:
+	decoder_clean_bitstr_segments(&dec_pict->dec_pict_seg_list);
+	kfree(dec_pict->first_fld_fwmsg);
+	kfree(dec_pict->second_fld_fwmsg);
+error_fw_msg:
+	kfree(dec_pict);
+error_dec_pict:
+	kfree(picture->dec_pict_info);
+
+	return ret;
+}
+
+/*
+ * @Function decoder_stream_reference_resource_create
+ */
+static int
+decoder_stream_reference_resource_create(struct dec_str_ctx *dec_str_ctx)
+{
+	struct dec_pictref_res  *pict_ref_res;
+	int ret;
+	unsigned int mem_heap_id;
+	enum sys_emem_attrib mem_attribs;
+
+	if (!dec_str_ctx || !dec_str_ctx->decctx) {
+		VDEC_ASSERT(0);
+		return -EINVAL;
+	}
+
+	mem_heap_id = dec_str_ctx->decctx->internal_heap_id;
+	mem_attribs = (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE);
+	mem_attribs |= (enum sys_emem_attrib)SYS_MEMATTRIB_INTERNAL;
+
+	/* Allocate the firmware context buffer info structure. */
+	pict_ref_res = kzalloc(sizeof(*pict_ref_res), GFP_KERNEL);
+	VDEC_ASSERT(pict_ref_res);
+	if (!pict_ref_res)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/*
+	 * Allocate the firmware context buffer to contain data required for
+	 * subsequent picture.
+	 */
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s:%d calling MMU_StreamMalloc", __func__, __LINE__);
+#endif
+	ret = mmu_stream_alloc(dec_str_ctx->mmu_str_handle, MMU_HEAP_STREAM_BUFFERS, mem_heap_id,
+			       (enum sys_emem_attrib)(mem_attribs | SYS_MEMATTRIB_CPU_READ |
+				SYS_MEMATTRIB_CPU_WRITE),
+			       sizeof(struct vdecfw_buffer_control),
+			       DEV_MMU_PAGE_ALIGNMENT,
+			       &pict_ref_res->fw_ctrlbuf);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto err_out_of_memory;
+
+	/*
+	 * Clear the context data in preparation for first time use by
+	 * the firmware.
+	 */
+	memset(pict_ref_res->fw_ctrlbuf.cpu_virt, 0, pict_ref_res->fw_ctrlbuf.buf_size);
+
+	pict_ref_res->ref_cnt = 1;
+
+	ret = resource_list_add_img(&dec_str_ctx->ref_res_lst, pict_ref_res, 0,
+				    &pict_ref_res->ref_cnt);
+	if (ret != IMG_SUCCESS) {
+		pr_err("[USERSID=0x%08X] Failed to add resource", dec_str_ctx->config.user_str_id);
+		return ret;
+	}
+
+	return IMG_SUCCESS;
+
+err_out_of_memory:
+
+	kfree(pict_ref_res);
+	pict_ref_res = NULL;
+
+	pr_err("[USERSID=0x%08X] Failed to allocate device memory for stream reference resources",
+	       dec_str_ctx->config.user_str_id);
+
+	return IMG_ERROR_OUT_OF_MEMORY;
+}
+
+/*
+ * @Function  decoder_picture_finalize
+ */
+static int decoder_picture_finalize(struct dec_str_ctx *dec_str_ctx,
+				    struct vdecdd_str_unit *str_unit)
+{
+	struct dec_decpict *dec_pict;
+	struct dec_core_ctx *dec_core_ctx = NULL;
+
+	VDEC_ASSERT(dec_str_ctx);
+
+	dec_pict = dec_str_ctx->cur_pict;
+	if (!dec_pict) {
+		pr_err("[USERSID=0x%08X] Unable to get the current picture from Decoder context",
+		       dec_str_ctx->config.user_str_id);
+		return IMG_ERROR_GENERIC_FAILURE;
+	}
+
+	dec_core_ctx = decoder_str_ctx_to_core_ctx(dec_str_ctx);
+
+	if (!dec_core_ctx || !dec_core_ctx->busy) {
+		VDEC_ASSERT(0);
+		return -EINVAL;
+	}
+
+	dec_core_ctx->busy = FALSE;
+
+	/* Picture data are now complete, nullify pointer */
+	dec_str_ctx->cur_pict = NULL;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function  decoder_submit_fragment
+ */
+static int decoder_submit_fragment(struct dec_str_ctx *dec_str_context,
+				   struct vdecdd_str_unit *str_unit,
+				   unsigned char eop)
+{
+	struct dec_core_ctx *dec_core_context = NULL;
+	struct lst_t dec_fragment_seg_list;
+	struct dec_decpict_seg *dec_pict_seg;
+	struct dec_pict_fragment *pict_fragment;
+	int ret = IMG_SUCCESS;
+
+	if (!dec_str_context) {
+		VDEC_ASSERT(0);
+		return IMG_ERROR_GENERIC_FAILURE;
+	}
+
+	if (!dec_str_context->cur_pict) {
+		pr_err("[USERSID=0x%08X] Unable to get the current picture from Decoder context",
+		       dec_str_context->config.user_str_id);
+		VDEC_ASSERT(0);
+		return IMG_ERROR_GENERIC_FAILURE;
+	}
+
+	dec_core_context = decoder_str_ctx_to_core_ctx(dec_str_context);
+	if (!dec_core_context) {
+		VDEC_ASSERT(0);
+		return IMG_ERROR_GENERIC_FAILURE;
+	}
+
+	pict_fragment = kzalloc(sizeof(*pict_fragment), GFP_KERNEL);
+	VDEC_ASSERT(pict_fragment);
+	if (!pict_fragment)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	lst_init(&dec_fragment_seg_list);
+
+	/* Add the segments to the temporary list */
+	ret = decoder_wrap_bitstr_segments(&str_unit->bstr_seg_list,
+					   &dec_fragment_seg_list,
+					   dec_str_context->config.user_str_id);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	/* Prepare ctr alloc for the fragment */
+	ret = translation_fragment_prepare(dec_str_context->cur_pict,
+					   &dec_fragment_seg_list, eop,
+					   pict_fragment);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	/*
+	 * Move segments of the fragment from the temporary list to the picture
+	 * segment list
+	 */
+	dec_pict_seg = lst_removehead(&dec_fragment_seg_list);
+	while (dec_pict_seg) {
+		lst_add(&dec_str_context->cur_pict->dec_pict_seg_list,
+			dec_pict_seg);
+		dec_pict_seg = lst_removehead(&dec_fragment_seg_list);
+	}
+
+	/* Submit fragment */
+	ret = hwctrl_picture_submit_fragment(dec_core_context->hw_ctx,
+					     pict_fragment,
+					     dec_str_context->cur_pict,
+					     dec_str_context->vxd_dec_ctx);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	lst_add(&dec_str_context->cur_pict->fragment_list, pict_fragment);
+
+	if (eop)
+		dec_str_context->cur_pict->eop_found = TRUE;
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("[USERSID=0x%08X] [TID=0x%08X] FRAGMENT",
+		dec_str_context->config.user_str_id,
+		dec_str_context->last_fe_transaction_id);
+#endif
+
+	return IMG_SUCCESS;
+error:
+	kfree(pict_fragment);
+
+	return ret;
+}
+
+/*
+ * @Function  decoder_stream_process_unit
+ */
+int decoder_stream_process_unit(void *dec_str_ctx_arg,
+				struct vdecdd_str_unit *str_unit)
+{
+	struct dec_str_ctx *dec_str_ctx =
+		decoder_stream_get_context(dec_str_ctx_arg);
+
+	struct dec_str_unit *dec_str_unit;
+	struct dec_decpict *dec_pict = NULL;
+	unsigned char processed = FALSE;
+	int ret;
+
+	VDEC_ASSERT(dec_str_ctx);
+	VDEC_ASSERT(str_unit);
+
+	if (!dec_str_ctx || !str_unit) {
+		pr_err("Invalid decoder stream context handle!\n");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+	pr_debug("%s : stream unit type = %d\n"
+		, __func__, str_unit->str_unit_type);
+	/* Process the stream unit */
+	switch (str_unit->str_unit_type) {
+	case VDECDD_STRUNIT_SEQUENCE_END:
+	case VDECDD_STRUNIT_ANONYMOUS:
+	case VDECDD_STRUNIT_CLOSED_GOP:
+	case VDECDD_STRUNIT_PICTURE_PORTENT:
+	case VDECDD_STRUNIT_FENCE:
+		/* Nothing more to do so mark the stream unit as processed */
+		processed = TRUE;
+		break;
+
+	case VDECDD_STRUNIT_STOP:
+		if (dec_str_ctx->cur_pict && !dec_str_ctx->cur_pict->eop_found) {
+			ret = decoder_submit_fragment(dec_str_ctx, str_unit, TRUE);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+
+			ret = decoder_picture_finalize(dec_str_ctx, str_unit);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("[USERSID=0x%08X] [TID=0x%08X] FORCED END",
+				dec_str_ctx->config.user_str_id,
+				dec_str_ctx->last_fe_transaction_id);
+#endif
+		}
+
+		processed = TRUE;
+		break;
+
+	case VDECDD_STRUNIT_SEQUENCE_START:
+	{
+		unsigned int max_num_activ_pict = 0;
+
+		VDEC_ASSERT(str_unit->seq_hdr_info);
+		/*
+		 * Determine how many decoded pictures can be held for
+		 * reference in the decoder for this stream.
+		 */
+		ret = vdecddutils_ref_pict_get_maxnum(&dec_str_ctx->config,
+						      &str_unit->seq_hdr_info->com_sequ_hdr_info,
+						      &max_num_activ_pict);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		/* Double for field coding */
+		max_num_activ_pict *= 2;
+
+		/*
+		 * Ensure that there are enough resource to have pictures
+		 * filling all slots on all cores.
+		 */
+		max_num_activ_pict +=
+			dec_str_ctx->decctx->dev_cfg->num_slots_per_pipe *
+			dec_str_ctx->decctx->num_pipes;
+
+		/* Increase decoder stream resources if necessary. */
+		while (dec_str_ctx->num_ref_res < max_num_activ_pict) {
+			ret = decoder_stream_reference_resource_create(dec_str_ctx);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+
+			dec_str_ctx->num_ref_res++;
+		}
+
+		/* Nothing more to do so mark the stream unit as processed */
+		processed = TRUE;
+		break;
+	}
+
+	case VDECDD_STRUNIT_PICTURE_START:
+		if (str_unit->decode) {
+			/* Prepare and submit picture to decode. */
+			ret = decoder_picture_decode(dec_str_ctx, str_unit, &dec_pict);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("[USERSID=0x%08X] [TID=0x%08X] START",
+				dec_str_ctx->config.user_str_id,
+				dec_str_ctx->last_fe_transaction_id);
+#endif
+		} else {
+			processed = TRUE;
+		}
+		break;
+
+	case VDECDD_STRUNIT_PICTURE_END:
+		if (str_unit->decode) {
+			ret = decoder_picture_finalize(dec_str_ctx, str_unit);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("[USERSID=0x%08X] [TID=0x%08X] END",
+				dec_str_ctx->config.user_str_id,
+				dec_str_ctx->last_fe_transaction_id);
+#endif
+		} else {
+			processed = TRUE;
+		}
+		break;
+
+	default:
+		VDEC_ASSERT(FALSE);
+		break;
+	}
+
+	/*
+	 * If this or any preceding stream unit(s) could not be
+	 * completely processed, add this unit to the queue.
+	 */
+	if (!processed) {
+		/* Add unit to stream decode list */
+		dec_str_unit = kzalloc(sizeof(*dec_str_unit), GFP_KERNEL);
+		VDEC_ASSERT(dec_str_unit);
+		if (!dec_str_unit)
+			return IMG_ERROR_OUT_OF_MEMORY;
+
+		dec_str_unit->str_unit = str_unit;
+
+		/* make PICTURE_START owner of dec_pict */
+		if (dec_pict) {
+			VDEC_ASSERT(str_unit->str_unit_type == VDECDD_STRUNIT_PICTURE_START);
+			dec_str_unit->dec_pict = dec_pict;
+		}
+
+		lst_add(&dec_str_ctx->pend_strunit_list, dec_str_unit);
+	} else {
+		/*
+		 * If there is nothing being decoded for this stream,
+		 * immediately handle the unit (non-picture so doesn't need
+		 * decoding). Report that this unit has been processed.
+		 */
+		VDEC_ASSERT(dec_str_ctx->decctx);
+		ret = dec_str_ctx->str_processed_cb(dec_str_ctx->usr_int_data,
+				VXD_CB_STRUNIT_PROCESSED,
+				str_unit);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+	}
+
+	return IMG_SUCCESS;
+}
+
+static int
+decoder_get_required_core_features(const struct vdec_str_configdata *str_cfg,
+				   const struct vdec_str_opconfig *op_cfg,
+				   unsigned int *features)
+{
+	unsigned int features_local = 0;
+
+	VDEC_ASSERT(str_cfg);
+	VDEC_ASSERT(features);
+
+	/* Check Video Standard. */
+	switch (str_cfg->vid_std) {
+	case VDEC_STD_H264:
+		features_local = VDECDD_COREFEATURE_H264;
+		break;
+#ifdef HAS_JPEG
+	case VDEC_STD_JPEG:
+		features_local = VDECDD_COREFEATURE_JPEG;
+		break;
+#endif
+#ifdef HAS_HEVC
+	case VDEC_STD_HEVC:
+		features_local = VDECDD_COREFEATURE_HEVC;
+		break;
+#endif
+	default:
+		VDEC_ASSERT(FALSE);
+		break;
+	}
+
+	*features = features_local;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function  decoder_is_supported_by_atleast_onepipe
+ */
+static unsigned char decoder_is_supported_by_atleast_onepipe(unsigned char *features,
+							     unsigned int num_pipes)
+{
+	unsigned int i;
+
+	VDEC_ASSERT(features);
+	VDEC_ASSERT(num_pipes <= VDEC_MAX_PIXEL_PIPES);
+
+	for (i = 0; i < num_pipes; i++) {
+		if (features[i])
+			return TRUE;
+	}
+
+	return FALSE;
+}
+
+/*
+ * @Function  decoder_check_support
+ */
+int decoder_check_support(void *dec_ctx_arg,
+			  const struct vdec_str_configdata *str_cfg,
+			  const struct vdec_str_opconfig *str_op_cfg,
+			  const struct vdecdd_ddpict_buf *disp_pict_buf,
+			  const struct vdec_pict_rendinfo *req_pict_rendinfo,
+			  const struct vdec_comsequ_hdrinfo *comseq_hdrinfo,
+			  const struct bspp_pict_hdr_info *pict_hdrinfo,
+			  const struct vdec_comsequ_hdrinfo *prev_comseq_hdrinfo,
+			  const struct bspp_pict_hdr_info *prev_pict_hdrinfo,
+			  unsigned char non_cfg_req,
+			  struct vdec_unsupp_flags *unsupported,
+			  unsigned int *features)
+{
+	struct dec_ctx *dec_ctx = (struct dec_ctx *)dec_ctx_arg;
+	struct dec_core_ctx *dec_core_ctx;
+	struct vxd_coreprops *core_props;
+	const struct vdec_pict_rendinfo *disp_pict_rendinfo = NULL;
+	int ret = IMG_ERROR_NOT_SUPPORTED;
+
+	/* Ensure input parameters are valid. */
+	VDEC_ASSERT(dec_ctx_arg);
+	VDEC_ASSERT(str_cfg);
+	VDEC_ASSERT(unsupported);
+
+	if (!dec_ctx_arg || !str_cfg || !unsupported) {
+		pr_err("Invalid parameters!");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (disp_pict_buf)
+		disp_pict_rendinfo = &disp_pict_buf->rend_info;
+
+	/*
+	 * Validate compatibility between the supplied configuration/state
+	 * and the master core only at the moment (assumed to have superset
+	 * of features).
+	 * Some features may not be present on any slave cores which might
+	 * cause poor utilisation of hardware.
+	 */
+	memset(unsupported, 0, sizeof(*unsupported));
+
+	dec_core_ctx = dec_ctx->dec_core_ctx;
+	VDEC_ASSERT(dec_core_ctx);
+
+	core_props = &dec_core_ctx->core_props;
+	VDEC_ASSERT(core_props);
+
+	/* Check that the video standard is supported */
+	switch (str_cfg->vid_std) {
+	case VDEC_STD_H264:
+		if (!decoder_is_supported_by_atleast_onepipe(core_props->h264,
+							     core_props->num_pixel_pipes)) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: VIDEO STANDARD (H.264)",
+				str_cfg->user_str_id);
+			unsupported->str_cfg |=
+				VDECDD_UNSUPPORTED_STRCONFIG_STD;
+		}
+
+		if (comseq_hdrinfo && (H264_PROFILE_MVC_HIGH ==
+		    comseq_hdrinfo->codec_profile || H264_PROFILE_MVC_STEREO ==
+		    comseq_hdrinfo->codec_profile) && comseq_hdrinfo->num_views >
+		    VDEC_H264_MVC_MAX_VIEWS) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[SW]: NUMBER OF VIEWS",
+				str_cfg->user_str_id);
+			unsupported->seq_hdr |= VDECDD_UNSUPPORTED_SEQUHDR_NUM_OF_VIEWS;
+		}
+		break;
+#ifdef HAS_HEVC
+	case VDEC_STD_HEVC:
+		if (!decoder_is_supported_by_atleast_onepipe(core_props->hevc,
+							     core_props->num_pixel_pipes)) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: VIDEO STANDARD (HEVC)",
+				str_cfg->user_str_id);
+			unsupported->str_cfg |= VDECDD_UNSUPPORTED_STRCONFIG_STD;
+		}
+		if (pict_hdrinfo && pict_hdrinfo->hevc_pict_hdr_info.range_ext_present)
+			if ((pict_hdrinfo->hevc_pict_hdr_info.is_full_range_ext &&
+			     !decoder_is_supported_by_atleast_onepipe(core_props->hevc_range_ext,
+			     core_props->num_pixel_pipes)) ||
+			   (!pict_hdrinfo->hevc_pict_hdr_info.is_full_range_ext &&
+			   core_props->vidstd_props[str_cfg->vid_std].max_chroma_format ==
+			   PIXEL_FORMAT_420)) {
+				pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: HEVC RANGE EXTENSIONS",
+					str_cfg->user_str_id);
+				unsupported->pict_hdr |= VDECDD_UNSUPPORTED_PICTHDR_HEVC_RANGE_EXT;
+			}
+		break;
+#endif
+#ifdef HAS_JPEG
+	case VDEC_STD_JPEG:
+		if (!decoder_is_supported_by_atleast_onepipe(core_props->jpeg,
+							     core_props->num_pixel_pipes)) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: VIDEO STANDARD (JPEG)",
+				str_cfg->user_str_id);
+			unsupported->str_cfg |=
+				VDECDD_UNSUPPORTED_STRCONFIG_STD;
+		}
+		break;
+#endif
+	default:
+		pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: VIDEO STANDARD (UNKNOWN)",
+			str_cfg->user_str_id);
+		unsupported->str_cfg |=
+			VDECDD_UNSUPPORTED_STRCONFIG_STD;
+		break;
+	}
+
+	if (str_op_cfg) {
+		/*
+		 * Ensure that each display feature is supported by the
+		 * hardware.
+		 */
+		if (comseq_hdrinfo) {
+			/* Validate display pixel format */
+			if (non_cfg_req && prev_comseq_hdrinfo &&
+			    vdec_size_nz(prev_comseq_hdrinfo->frame_size) &&
+			    prev_comseq_hdrinfo->pixel_info.chroma_fmt_idc ==
+			    str_op_cfg->pixel_info.chroma_fmt_idc &&
+			    comseq_hdrinfo->pixel_info.chroma_fmt_idc !=
+			    prev_comseq_hdrinfo->pixel_info.chroma_fmt_idc) {
+				/*
+				 * If this is a non-configuration request and
+				 * it looks like a new sequence with
+				 * sub-sampling change, just indicate output
+				 * format mismatch without any error messages.
+				 */
+				unsupported->str_opcfg |= VDECDD_UNSUPPORTED_OUTPUTCONFIG_PIXFORMAT;
+			} else {
+				switch (str_op_cfg->pixel_info.chroma_fmt_idc) {
+				case PIXEL_FORMAT_420:
+					if (comseq_hdrinfo->pixel_info.chroma_fmt_idc ==
+						PIXEL_FORMAT_MONO) {
+						pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: TRANSFORM PIXEL FORMAT FROM 400 TO 420",
+							str_cfg->user_str_id);
+							unsupported->str_opcfg |=
+							VDECDD_UNSUPPORTED_OUTPUTCONFIG_PIXFORMAT;
+					}
+					break;
+
+				case PIXEL_FORMAT_422:
+					if (comseq_hdrinfo->pixel_info.chroma_fmt_idc ==
+						PIXEL_FORMAT_420 &&
+						str_op_cfg->pixel_info.num_planes > 1) {
+						pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: REQUESTED NUMBER OF PLANES FOR 422 UPSAMPLING",
+							str_cfg->user_str_id);
+						unsupported->str_opcfg |=
+						VDECDD_UNSUPPORTED_OUTPUTCONFIG_PIXFORMAT;
+					} else if (comseq_hdrinfo->pixel_info.chroma_fmt_idc ==
+						PIXEL_FORMAT_MONO) {
+						pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: TRANSFORM PIXEL FORMAT FROM 400 TO 422",
+							str_cfg->user_str_id);
+							unsupported->str_opcfg |=
+							VDECDD_UNSUPPORTED_OUTPUTCONFIG_PIXFORMAT;
+					}
+					break;
+
+				default:
+					break;
+				}
+			}
+		}
+
+		if (str_op_cfg->pixel_info.bitdepth_y >
+			core_props->vidstd_props[str_cfg->vid_std].max_luma_bitdepth ||
+			str_op_cfg->pixel_info.bitdepth_y < 8 ||
+			str_op_cfg->pixel_info.bitdepth_y == 9) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: DISPLAY PICTURE LUMA BIT DEPTH %d [RANGE: 8->%d for %s]",
+				str_cfg->user_str_id,
+				str_op_cfg->pixel_info.bitdepth_y,
+				core_props->vidstd_props[str_cfg->vid_std].max_luma_bitdepth,
+				vid_std_names[str_cfg->vid_std]);
+				unsupported->str_opcfg |=
+				VDECDD_UNSUPPORTED_OUTPUTCONFIG_PIXFORMAT;
+		}
+
+		if (str_op_cfg->pixel_info.chroma_fmt_idc !=
+			PIXEL_FORMAT_MONO &&
+			(str_op_cfg->pixel_info.bitdepth_c >
+			core_props->vidstd_props[str_cfg->vid_std].max_chroma_bitdepth ||
+			str_op_cfg->pixel_info.bitdepth_c < 8 ||
+			str_op_cfg->pixel_info.bitdepth_c == 9)) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: DISPLAY PICTURE CHROMA BIT DEPTH %d [RANGE: 8->%d for %s]",
+				str_cfg->user_str_id,
+				str_op_cfg->pixel_info.bitdepth_c,
+				core_props->vidstd_props[str_cfg->vid_std].max_chroma_bitdepth,
+				vid_std_names[str_cfg->vid_std]);
+				unsupported->str_opcfg |=
+				VDECDD_UNSUPPORTED_OUTPUTCONFIG_PIXFORMAT;
+		}
+
+#ifdef HAS_JPEG
+		/* Validate display configuration against existing stream configuration.*/
+		if (str_cfg->vid_std == VDEC_STD_JPEG) {
+			if (str_op_cfg->force_oold) {
+				pr_err("[USERSID=0x%08X] UNSUPPORTED[HW]: OOLD WITH JPEG\n",
+				       str_cfg->user_str_id);
+				       unsupported->str_opcfg |=
+				       VDECDD_UNSUPPORTED_OUTPUTCONFIG_X_WITH_JPEG;
+			}
+		}
+#endif
+	}
+
+	if (disp_pict_rendinfo) {
+		unsigned int stride_alignment = VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT;
+
+		if (req_pict_rendinfo) {
+			/*
+			 * Picture size declared in buffer must be at least as
+			 * large as that required by bitstream/output config.
+			 */
+			if (!vdec_size_ge(disp_pict_rendinfo->rend_pict_size,
+					  req_pict_rendinfo->rend_pict_size)) {
+				pr_warn("[USERSID=0x%08X] Picture size of output picture buffer [%d x %d] is not large enough for sequence [%d x %d]",
+					str_cfg->user_str_id,
+					disp_pict_rendinfo->rend_pict_size.width,
+					disp_pict_rendinfo->rend_pict_size.height,
+					req_pict_rendinfo->rend_pict_size.width,
+					req_pict_rendinfo->rend_pict_size.height);
+					unsupported->str_opcfg |=
+					VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_PICTURE_SIZE;
+			}
+
+			/*
+			 * Size of each plane must be at least as large
+			 * as that required.
+			 */
+			if (disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_Y].size <
+				req_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_Y].size) {
+				pr_warn("[USERSID=0x%08X] Y plane of output picture buffer [%d bytes] is not large enough for bitstream/config [%d bytes]",
+					str_cfg->user_str_id,
+					disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_Y].size,
+					req_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_Y].size);
+					unsupported->op_bufcfg |=
+					VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_Y_SIZE;
+			}
+
+			/*
+			 * Stride of each plane must be at least as large as that
+			 * required.
+			 */
+			if (disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_Y].stride <
+				req_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_Y].stride) {
+				pr_warn("[USERSID=0x%08X] Y stride of output picture buffer [%d bytes] is not large enough for bitstream/config [%d bytes]",
+					str_cfg->user_str_id,
+					disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_Y].stride,
+					req_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_Y].stride);
+					unsupported->op_bufcfg |=
+					VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_Y_STRIDE;
+			}
+
+			/*
+			 * Size of each plane must be at least
+			 * as large as that required.
+			 */
+			if (disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_UV].size <
+				req_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_UV].size) {
+				pr_warn("[USERSID=0x%08X] UV plane of output picture buffer [%d bytes] is not large enough for bitstream/config [%d bytes]",
+					str_cfg->user_str_id,
+					disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_UV].size,
+					req_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_UV].size);
+					unsupported->op_bufcfg |=
+					VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_UV_SIZE;
+			}
+
+			/*
+			 * Stride of each plane must be at least
+			 * as large as that required.
+			 */
+			if (disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_UV].stride <
+				req_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_UV].stride) {
+				pr_warn("[USERSID=0x%08X] UV stride of output picture buffer [%d bytes] is not large enough for bitstream/config [%d bytes]",
+					str_cfg->user_str_id,
+					disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_UV].stride,
+					req_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_UV].stride);
+					unsupported->op_bufcfg |=
+					VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_UV_STRIDE;
+			}
+
+			if ((req_pict_rendinfo->stride_alignment &
+				(VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT - 1)) != 0) {
+				pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: STRIDE ALIGNMENT [%d] must be a multiple of %d bytes",
+					str_cfg->user_str_id,
+					req_pict_rendinfo->stride_alignment,
+					VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT);
+					unsupported->op_bufcfg |=
+					VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_64BYTE_STRIDE;
+			}
+
+			if (req_pict_rendinfo->stride_alignment > 0)
+				stride_alignment = req_pict_rendinfo->stride_alignment;
+		}
+
+		if ((disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_Y].stride %
+			stride_alignment) != 0) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: Y STRIDE [%d] must be a multiple of %d bytes",
+				str_cfg->user_str_id,
+				disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_Y].stride,
+				stride_alignment);
+				unsupported->op_bufcfg |=
+				VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_64BYTE_STRIDE;
+		}
+
+		if ((disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_UV].stride %
+			stride_alignment) != 0) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: UV STRIDE [%d] must be a multiple of %d bytes",
+				str_cfg->user_str_id,
+				disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_UV].stride,
+				stride_alignment);
+				unsupported->op_bufcfg |=
+				VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_64BYTE_STRIDE;
+		}
+
+		if ((disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_V].stride %
+			stride_alignment) != 0) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: V STRIDE [%d] must be a multiple of %d bytes",
+				str_cfg->user_str_id,
+				disp_pict_rendinfo->plane_info[VDEC_PLANE_VIDEO_V].stride,
+				stride_alignment);
+				unsupported->op_bufcfg |=
+				VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_64BYTE_STRIDE;
+		}
+
+		if (req_pict_rendinfo) {
+			if (str_op_cfg) {
+				if (str_cfg->vid_std != VDEC_STD_JPEG) {
+					if (str_op_cfg->pixel_info.num_planes <= 2)
+						/*
+						 * V plane only required when chroma is
+						 * separated.
+						 */
+						VDEC_ASSERT(req_pict_rendinfo->plane_info
+								[VDEC_PLANE_VIDEO_V].size == 0);
+
+					if (str_op_cfg->pixel_info.num_planes <= 3)
+						/* Alpha planes should not be required. */
+						VDEC_ASSERT(req_pict_rendinfo->plane_info
+								[VDEC_PLANE_VIDEO_A].size == 0);
+				}
+			}
+
+			/* Size of buffer must be at least as large as that required. */
+			if (disp_pict_rendinfo->rendered_size <
+			    req_pict_rendinfo->rendered_size) {
+				pr_warn("[USERSID=0x%08X] Output picture buffer [%d bytes] is not large enough for bitstream/config [%d bytes]",
+					str_cfg->user_str_id,
+					disp_pict_rendinfo->rendered_size,
+					req_pict_rendinfo->rendered_size);
+					unsupported->op_bufcfg |=
+					VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_BUFFER_SIZE;
+			}
+		}
+
+		if (str_op_cfg) {
+			if (comseq_hdrinfo) {
+				if (vdec_size_lt(disp_pict_rendinfo->rend_pict_size,
+						 comseq_hdrinfo->max_frame_size)) {
+					pr_warn("[USERSID=0x%08X] Buffers [%d x %d] must be large enough to contain the maximum frame size [%d x %d] when not scaling",
+						str_cfg->user_str_id,
+						disp_pict_rendinfo->rend_pict_size.width,
+						disp_pict_rendinfo->rend_pict_size.height,
+						comseq_hdrinfo->max_frame_size.width,
+						comseq_hdrinfo->max_frame_size.height);
+						unsupported->op_bufcfg |=
+						VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_PICTURE_SIZE;
+				}
+			}
+		}
+	}
+
+	if (comseq_hdrinfo) {
+		unsigned int max_width =
+			vdec_size_min(core_props->vidstd_props[str_cfg->vid_std].max_width,
+				      MAX_PLATFORM_SUPPORTED_WIDTH);
+
+		unsigned int max_height =
+			vdec_size_min(core_props->vidstd_props[str_cfg->vid_std].max_height,
+				      MAX_PLATFORM_SUPPORTED_HEIGHT);
+
+		if (comseq_hdrinfo->max_frame_size.width > max_width ||
+		    comseq_hdrinfo->max_frame_size.height > max_height) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: FRAME WIDTH %dpx or HEIGHT %dpx are over maximum allowed value [%d, %d]",
+				str_cfg->user_str_id,
+				comseq_hdrinfo->max_frame_size.width,
+				comseq_hdrinfo->max_frame_size.height,
+				max_width, max_height);
+				unsupported->seq_hdr |=
+						VDECDD_UNSUPPORTED_SEQUHDR_SIZE;
+		}
+
+		if (comseq_hdrinfo->pixel_info.bitdepth_y >
+			core_props->vidstd_props[str_cfg->vid_std].max_luma_bitdepth ||
+			comseq_hdrinfo->pixel_info.bitdepth_y < 8 ||
+			comseq_hdrinfo->pixel_info.bitdepth_y == 9) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: CODED PICTURE LUMA BIT DEPTH %d [RANGE: 8->%d for %s]",
+				str_cfg->user_str_id,
+				comseq_hdrinfo->pixel_info.bitdepth_y,
+				core_props->vidstd_props[str_cfg->vid_std].max_luma_bitdepth,
+				vid_std_names[str_cfg->vid_std]);
+				unsupported->seq_hdr |=
+						VDECDD_UNSUPPORTED_SEQUHDR_PIXFORMAT_BIT_DEPTH;
+		}
+
+		if (comseq_hdrinfo->pixel_info.chroma_fmt_idc !=
+			PIXEL_FORMAT_MONO &&
+			(comseq_hdrinfo->pixel_info.bitdepth_c >
+			core_props->vidstd_props[str_cfg->vid_std].max_chroma_bitdepth ||
+			comseq_hdrinfo->pixel_info.bitdepth_c < 8 ||
+			comseq_hdrinfo->pixel_info.bitdepth_c == 9)) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: CODED PICTURE CHROMA BIT DEPTH %d [RANGE: 8->%d for %s]",
+				str_cfg->user_str_id,
+				comseq_hdrinfo->pixel_info.bitdepth_c,
+				core_props->vidstd_props[str_cfg->vid_std].max_chroma_bitdepth,
+				vid_std_names[str_cfg->vid_std]);
+				unsupported->seq_hdr |=
+						VDECDD_UNSUPPORTED_SEQUHDR_PIXFORMAT_BIT_DEPTH;
+		}
+
+		if (comseq_hdrinfo->pixel_info.chroma_fmt_idc !=
+			PIXEL_FORMAT_MONO &&
+			comseq_hdrinfo->pixel_info.bitdepth_y !=
+			comseq_hdrinfo->pixel_info.bitdepth_c) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: CODED PICTURE MIXED BIT DEPTH [%d vs %d]",
+				str_cfg->user_str_id,
+				comseq_hdrinfo->pixel_info.bitdepth_y,
+				comseq_hdrinfo->pixel_info.bitdepth_c);
+				unsupported->seq_hdr |=
+						VDECDD_UNSUPPORTED_SEQUHDR_PIXFORMAT_BIT_DEPTH;
+		}
+
+		if (comseq_hdrinfo->pixel_info.chroma_fmt_idc >
+			core_props->vidstd_props[str_cfg->vid_std].max_chroma_format) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: CODED PIXEL FORMAT IDC %s [for %s]",
+				str_cfg->user_str_id,
+				comseq_hdrinfo->pixel_info.chroma_fmt_idc <
+				ARRAY_SIZE
+				(pix_fmt_idc_names) ? (unsigned char *)
+				 pix_fmt_idc_names[comseq_hdrinfo->pixel_info.chroma_fmt_idc] :
+				(unsigned char *)"Invalid",
+				vid_std_names[str_cfg->vid_std]);
+			unsupported->seq_hdr |=
+				VDECDD_UNSUPPORTED_SEQUHDR_PIXEL_FORMAT;
+		}
+
+		if (comseq_hdrinfo->pixel_info.chroma_fmt_idc ==
+			PIXEL_FORMAT_INVALID) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[SW]: UNKNOWN CODED PIXEL FORMAT",
+				str_cfg->user_str_id);
+			unsupported->seq_hdr |=
+				VDECDD_UNSUPPORTED_SEQUHDR_PIXEL_FORMAT;
+		}
+	}
+
+	if (pict_hdrinfo && comseq_hdrinfo) {
+		unsigned int coded_cmd_width;
+		unsigned int coded_cmd_height;
+		unsigned int min_width = core_props->vidstd_props[str_cfg->vid_std].min_width;
+		unsigned int min_height =
+			ALIGN(core_props->vidstd_props[str_cfg->vid_std].min_height,
+			      (pict_hdrinfo->field) ?
+			      2 * VDEC_MB_DIMENSION : VDEC_MB_DIMENSION);
+		unsigned int pict_size_in_mbs;
+		unsigned int max_height = core_props->vidstd_props[str_cfg->vid_std].max_height;
+		unsigned int max_width = core_props->vidstd_props[str_cfg->vid_std].max_width;
+		unsigned int max_mbs = core_props->vidstd_props[str_cfg->vid_std].max_macroblocks;
+
+#ifdef HAS_JPEG
+		/* For JPEG, max picture size of four plane images is 16k*16k. */
+		if (str_cfg->vid_std == VDEC_STD_JPEG) {
+			if (comseq_hdrinfo->pixel_info.num_planes >= 4) {
+				max_width = (max_width > 16 * 1024) ? 16 * 1024 : max_width;
+				max_height = (max_height > 16 * 1024) ? 16 * 1024 : max_height;
+			}
+		}
+#endif
+
+		coded_cmd_width =
+			ALIGN(pict_hdrinfo->coded_frame_size.width, VDEC_MB_DIMENSION);
+		coded_cmd_height =
+			ALIGN(pict_hdrinfo->coded_frame_size.height,
+			      pict_hdrinfo->field ?
+			      2 * VDEC_MB_DIMENSION : VDEC_MB_DIMENSION);
+
+		pict_size_in_mbs = (coded_cmd_width * coded_cmd_height) /
+			(VDEC_MB_DIMENSION * VDEC_MB_DIMENSION);
+
+		if ((str_cfg->vid_std == VDEC_STD_H264 &&
+		     max_mbs && pict_size_in_mbs > max_mbs) ||
+		    coded_cmd_width > max_width ||
+		    coded_cmd_height > max_height) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: CODED PICTURE SIZE %d x %d [MAX: %d x %d or %d MBs]",
+				str_cfg->user_str_id,
+				coded_cmd_width, coded_cmd_height,
+				max_width, max_height, max_mbs);
+			unsupported->pict_hdr |= VDECDD_UNSUPPORTED_PICTHDR_RESOLUTION;
+		}
+
+		if (pict_hdrinfo->coded_frame_size.width < min_width ||
+		    pict_hdrinfo->coded_frame_size.height < min_height) {
+#ifdef USE_STRICT_MIN_PIC_SIZE_CHECK
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: CODED PICTURE SIZE %d x %d [MIN: %d x %d]",
+				str_cfg->user_str_id,
+				pict_hdrinfo->coded_frame_size.width,
+				pict_hdrinfo->coded_frame_size.height,
+				min_width, min_height);
+				unsupported->pict_hdr |= VDECDD_UNSUPPORTED_PICTHDR_RESOLUTION;
+#else /* ndef USE_STRICT_MIN_PIC_SIZE_CHECK */
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: CODED PICTURE SIZE %d x %d [MIN: %d x %d]",
+				str_cfg->user_str_id,
+				pict_hdrinfo->coded_frame_size.width,
+				pict_hdrinfo->coded_frame_size.height,
+				min_width, min_height);
+#endif /* ndef USE_STRICT_MIN_PIC_SIZE_CHECK */
+		}
+
+		if (pict_hdrinfo->pict_sgm_data.id !=
+			BSPP_INVALID && pict_hdrinfo->coded_frame_size.width > 1280) {
+			pr_warn("[USERSID=0x%08X] UNSUPPORTED[HW]: SGM & coded frame width > 1280",
+				str_cfg->user_str_id);
+			unsupported->pict_hdr |=
+				VDECDD_UNSUPPORTED_PICTHDR_OVERSIZED_SGM;
+		}
+
+		if (pict_hdrinfo->discontinuous_mbs)
+			pr_info("Stream has Discontinuous Macroblocks");
+
+		decoder_get_required_core_features(str_cfg, str_op_cfg, features);
+	}
+
+	if (unsupported->str_cfg == 0 && unsupported->str_opcfg == 0 &&
+	    unsupported->op_bufcfg == 0 && unsupported->pict_hdr == 0)
+		ret = IMG_SUCCESS;
+
+	return ret;
+}
+
+/*
+ * @Function  decoder_picture_decoded
+ */
+static int decoder_picture_decoded(struct dec_str_ctx *dec_str_ctx,
+				   struct dec_core_ctx *dec_core_ctx,
+				   struct vdecdd_picture *picture,
+				   struct dec_decpict *dec_pict,
+				   struct bspp_pict_hdr_info *pict_hdrinfo,
+				   struct vdecdd_str_unit *str_unit)
+{
+	struct dec_fwmsg *first_fld_fwmsg;
+	struct dec_fwmsg *second_fld_fwmsg;
+	struct dec_pictref_res  *pict_ref_res;
+	unsigned int transaction_id;
+	struct dec_decoded_pict *decoded_pict;
+	struct dec_decoded_pict *next_decoded_pict;
+	struct vdecdd_ddbuf_mapinfo *pict_buf;
+	struct dec_decoded_pict  *prev_decoded_pict;
+	struct vdecfw_buffer_control *buf_control;
+	struct vdec_comsequ_hdrinfo  *comseq_hdrinfo;
+	unsigned int res_limit = 0;
+	unsigned int dec_pict_num = 0;
+	unsigned int req_pict_num = 0;
+	struct dec_decoded_pict *aux_decoded_pict;
+	struct dec_decoded_pict *displayed_decoded_pict = NULL;
+	int ret;
+	unsigned int pict_id;
+	struct vdec_pict_tag_container *fld_tag_container;
+#ifdef ERROR_CONCEALMENT
+	unsigned int first_field_err_level = 0;
+	unsigned int second_field_err_level = 0;
+	unsigned int pict_last_mb = 0;
+#endif
+	struct vxd_dec_ctx *ctx;
+	unsigned int error_flag = 0;
+
+	VDEC_ASSERT(dec_str_ctx);
+	VDEC_ASSERT(str_unit);
+	VDEC_ASSERT(dec_pict);
+
+	first_fld_fwmsg = dec_pict->first_fld_fwmsg;
+	second_fld_fwmsg = dec_pict->second_fld_fwmsg;
+	pict_ref_res = dec_pict->pict_ref_res;
+	transaction_id = dec_pict->transaction_id;
+
+	VDEC_ASSERT(picture);
+	pict_buf = picture->disp_pict_buf.pict_buf;
+	VDEC_ASSERT(pict_buf);
+	comseq_hdrinfo = &pict_buf->ddstr_context->comseq_hdr_info;
+
+	/* Create a container for decoded picture. */
+	decoded_pict = kzalloc(sizeof(*decoded_pict), GFP_KERNEL);
+	VDEC_ASSERT(decoded_pict);
+	if (!decoded_pict)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	decoded_pict->pict = picture;
+	decoded_pict->first_fld_fwmsg = first_fld_fwmsg;
+	decoded_pict->second_fld_fwmsg = second_fld_fwmsg;
+	decoded_pict->pict_ref_res = pict_ref_res;
+	decoded_pict->transaction_id = transaction_id;
+
+	/* Populate the decoded picture information structure. */
+	picture->dec_pict_info->pict_state = VDEC_PICT_STATE_DECODED;
+
+	memcpy(&picture->dec_pict_info->first_fld_tag_container.pict_hwcrc,
+	       &first_fld_fwmsg->pict_hwcrc,
+	       sizeof(picture->dec_pict_info->first_fld_tag_container.pict_hwcrc));
+
+	memcpy(&picture->dec_pict_info->second_fld_tag_container.pict_hwcrc,
+	       &second_fld_fwmsg->pict_hwcrc,
+	       sizeof(picture->dec_pict_info->second_fld_tag_container.pict_hwcrc));
+
+	buf_control =
+		(struct vdecfw_buffer_control *)decoded_pict->pict_ref_res->fw_ctrlbuf.cpu_virt;
+	if (buf_control->second_field_of_pair) {
+		/* Search the first field and fill the second_fld_tag_container */
+		unsigned int prev_dec_pict_id =
+			get_prev_picture_id(GET_STREAM_PICTURE_ID(decoded_pict->transaction_id));
+		prev_decoded_pict =
+			decoder_get_decoded_pict_of_stream(prev_dec_pict_id,
+							   &dec_str_ctx->str_decd_pict_list);
+
+		if (prev_decoded_pict) {
+			memcpy(&picture->dec_pict_info->second_fld_tag_container.pict_hwcrc,
+			       &prev_decoded_pict->first_fld_fwmsg->pict_hwcrc,
+				sizeof
+				(picture->dec_pict_info->second_fld_tag_container.pict_hwcrc));
+		} else {
+			pr_warn("[USERSID=0x%08X] [TID 0x%08X] Failed to find decoded picture to attach second_fld_tag_container",
+				dec_str_ctx->config.user_str_id,
+				decoded_pict->transaction_id);
+		}
+		prev_decoded_pict = NULL;
+	}
+
+	/* Report any issues in decoding */
+	if (decoded_pict->pict->dec_pict_info->err_flags)
+		pr_warn("[USERSID=0x%08X] [PID=0x%08X] BSPP reported errors [flags: 0x%08X]",
+			dec_str_ctx->config.user_str_id,
+			decoded_pict->pict->pict_id,
+			decoded_pict->pict->dec_pict_info->err_flags);
+
+	if ((decoded_pict->first_fld_fwmsg->pict_attrs.fe_err &
+		FLAG_MASK(VDECFW_MSGFLAG_DECODED_FEERROR_ENTDECERROR)) ||
+		(decoded_pict->second_fld_fwmsg->pict_attrs.fe_err &
+		FLAG_MASK(VDECFW_MSGFLAG_DECODED_FEERROR_ENTDECERROR))) {
+		pr_warn("[USERSID=0x%08X] [TID 0x%08X] Front-end HW processing terminated prematurely due to an error.",
+			dec_str_ctx->config.user_str_id,
+			decoded_pict->transaction_id);
+		picture->dec_pict_info->err_flags |= VDEC_ERROR_FEHW_DECODE;
+	}
+
+	if ((decoded_pict->first_fld_fwmsg->pict_attrs.fe_err &
+		FLAG_MASK(VDECFW_MSGFLAG_DECODED_FEERROR_SRERROR)) ||
+		(decoded_pict->second_fld_fwmsg->pict_attrs.fe_err &
+		FLAG_MASK(VDECFW_MSGFLAG_DECODED_FEERROR_SRERROR))) {
+		pr_warn("[USERSID=0x%08X] [TID 0x%08X] HW Shift Register access returned an error during FEHW parsing.",
+			dec_str_ctx->config.user_str_id,
+			decoded_pict->transaction_id);
+		picture->dec_pict_info->err_flags |= VDEC_ERROR_SR_ERROR;
+	}
+
+	if ((decoded_pict->first_fld_fwmsg->pict_attrs.fe_err &
+		FLAG_MASK(VDECFW_MSGFLAG_DECODED_FEERROR_HWWDT)) ||
+		(decoded_pict->second_fld_fwmsg->pict_attrs.fe_err &
+		FLAG_MASK(VDECFW_MSGFLAG_DECODED_FEERROR_HWWDT))) {
+		pr_warn("[USERSID=0x%08X] [TID 0x%08X] Front-end HW processing timed-out.",
+			dec_str_ctx->config.user_str_id,
+			decoded_pict->transaction_id);
+		picture->dec_pict_info->err_flags |= VDEC_ERROR_FEHW_TIMEOUT;
+	}
+
+	if ((decoded_pict->first_fld_fwmsg->pict_attrs.fe_err &
+		FLAG_MASK(VDECFW_MSGFLAG_DECODED_MISSING_REFERENCES)) ||
+		(decoded_pict->second_fld_fwmsg->pict_attrs.fe_err &
+		FLAG_MASK(VDECFW_MSGFLAG_DECODED_MISSING_REFERENCES))) {
+		pr_warn("[USERSID=0x%08X] [TID 0x%08X] There are missing references for the current frame. May have corruption",
+			dec_str_ctx->config.user_str_id,
+			decoded_pict->transaction_id);
+		/*
+		 * This is not a serious error, indicate host app to drop the
+		 * frame as may have corruption.
+		 */
+		picture->dec_pict_info->err_flags |=
+			VDEC_ERROR_MISSING_REFERENCES;
+	}
+
+	if ((decoded_pict->first_fld_fwmsg->pict_attrs.fe_err &
+		FLAG_MASK(VDECFW_MSGFLAG_DECODED_MMCO_ERROR)) ||
+		(decoded_pict->second_fld_fwmsg->pict_attrs.fe_err &
+		FLAG_MASK(VDECFW_MSGFLAG_DECODED_MMCO_ERROR))) {
+		pr_warn("[USERSID=0x%08X] [TID 0x%08X] MMCO error accured when processing the current frame. May have corruption",
+			dec_str_ctx->config.user_str_id,
+			decoded_pict->transaction_id);
+
+		/*
+		 * This is not a serious error, indicate host app to drop
+		 * the frame as may have corruption.
+		 */
+		picture->dec_pict_info->err_flags |= VDEC_ERROR_MMCO;
+	}
+
+	if ((decoded_pict->first_fld_fwmsg->pict_attrs.fe_err &
+		FLAG_MASK(VDECFW_MSGFLAG_DECODED_MBS_DROPPED_ERROR)) ||
+		(decoded_pict->second_fld_fwmsg->pict_attrs.fe_err &
+		FLAG_MASK(VDECFW_MSGFLAG_DECODED_MBS_DROPPED_ERROR))) {
+		pr_warn("[USERSID=0x%08X] [TID 0x%08X] Some macroblocks were dropped when processing the current frame. May have corruption",
+			dec_str_ctx->config.user_str_id,
+			decoded_pict->transaction_id);
+
+		/*
+		 * This is not a serious error, indicate host app to
+		 * drop the frame as may have corruption.
+		 */
+		picture->dec_pict_info->err_flags |= VDEC_ERROR_MBS_DROPPED;
+	}
+
+	if (decoded_pict->first_fld_fwmsg->pict_attrs.no_be_wdt > 0) {
+		pr_warn("[USERSID=0x%08X] [TID 0x%08X] Back-end HW processing timed-out. Aborted slices %d",
+			dec_str_ctx->config.user_str_id,
+			decoded_pict->transaction_id,
+			decoded_pict->first_fld_fwmsg->pict_attrs.no_be_wdt);
+		picture->dec_pict_info->err_flags |= VDEC_ERROR_BEHW_TIMEOUT;
+	}
+
+	if (decoded_pict->second_fld_fwmsg->pict_attrs.no_be_wdt > 0) {
+		pr_warn("[USERSID=0x%08X] [TID 0x%08X] Back-end HW processing timed-out. Aborted slices %d",
+			dec_str_ctx->config.user_str_id,
+			decoded_pict->transaction_id,
+			decoded_pict->second_fld_fwmsg->pict_attrs.no_be_wdt);
+		picture->dec_pict_info->err_flags |= VDEC_ERROR_BEHW_TIMEOUT;
+	}
+
+#ifdef ERROR_CONCEALMENT
+	/* Estimate error level in percentage */
+	if (decoder_get_pict_processing_info(dec_core_ctx, dec_str_ctx, pict_hdrinfo,
+					     decoded_pict, dec_pict, &pict_last_mb) == TRUE) {
+		if (pict_last_mb) {
+			first_field_err_level = 100 - ((100 * (pict_last_mb -
+				decoded_pict->first_fld_fwmsg->pict_attrs.mbs_dropped +
+				decoded_pict->first_fld_fwmsg->pict_attrs.mbs_recovered)) /
+				pict_last_mb);
+
+			second_field_err_level = 100 - ((100 * (pict_last_mb -
+				decoded_pict->second_fld_fwmsg->pict_attrs.mbs_dropped +
+				decoded_pict->second_fld_fwmsg->pict_attrs.mbs_recovered)) /
+				pict_last_mb);
+		}
+
+		/* does not work properly with discontinuous mbs */
+		if (!pict_hdrinfo->discontinuous_mbs)
+			picture->dec_pict_info->err_level = first_field_err_level >
+				second_field_err_level ?
+				first_field_err_level : second_field_err_level;
+
+		VDEC_ASSERT(picture->dec_pict_info->err_level <= 100);
+		if (picture->dec_pict_info->err_level)
+			pr_warn("[USERSID=0x%08X] [TID 0x%08X] Picture error level: %d(%%)",
+				dec_str_ctx->config.user_str_id, decoded_pict->transaction_id,
+				picture->dec_pict_info->err_level);
+	}
+#endif
+
+	if (decoded_pict->first_fld_fwmsg->pict_attrs.pict_attrs.dwrfired ||
+	    decoded_pict->second_fld_fwmsg->pict_attrs.pict_attrs.dwrfired) {
+		pr_warn("[USERSID=0x%08X] VXD Device Reset (Lockup).",
+			dec_str_ctx->config.user_str_id);
+		picture->dec_pict_info->err_flags |=
+			VDEC_ERROR_SERVICE_TIMER_EXPIRY;
+	}
+
+	if (decoded_pict->first_fld_fwmsg->pict_attrs.pict_attrs.mmufault ||
+	    decoded_pict->second_fld_fwmsg->pict_attrs.pict_attrs.mmufault) {
+		pr_warn("[USERSID=0x%08X] VXD Device Reset (MMU fault).",
+			dec_str_ctx->config.user_str_id);
+		picture->dec_pict_info->err_flags |= VDEC_ERROR_MMU_FAULT;
+	}
+
+	if (decoded_pict->first_fld_fwmsg->pict_attrs.pict_attrs.deverror ||
+	    decoded_pict->second_fld_fwmsg->pict_attrs.pict_attrs.deverror) {
+		pr_warn("[USERSID=0x%08X] VXD Device Error (e.g. firmware load failed).",
+			dec_str_ctx->config.user_str_id);
+		picture->dec_pict_info->err_flags |= VDEC_ERROR_DEVICE;
+	}
+
+	/*
+	 * Assigned error flag from the decoder error flag for error recovery.
+	 */
+	error_flag = picture->dec_pict_info->err_flags;
+	/*
+	 * Loop over references, for each one find the related picture
+	 * on the decPictList, and propagate errors if needed
+	 */
+	ret =
+		decoder_check_ref_errors(dec_str_ctx, (struct vdecfw_buffer_control *)
+			decoded_pict->pict_ref_res->fw_ctrlbuf.cpu_virt,
+			picture);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+
+	if (dec_str_ctx->config.vid_std == VDEC_STD_H264) {
+		/* Attach the supplementary data to the decoded picture. */
+		picture->dec_pict_sup_data.raw_vui_data =
+			pict_hdrinfo->h264_pict_hdr_info.raw_vui_data;
+		pict_hdrinfo->h264_pict_hdr_info.raw_vui_data = NULL;
+
+		picture->dec_pict_sup_data.raw_sei_list_first_fld =
+			pict_hdrinfo->h264_pict_hdr_info.raw_sei_data_list_first_field;
+		pict_hdrinfo->h264_pict_hdr_info.raw_sei_data_list_first_field = NULL;
+
+		picture->dec_pict_sup_data.raw_sei_list_second_fld =
+			pict_hdrinfo->h264_pict_hdr_info.raw_sei_data_list_second_field;
+		pict_hdrinfo->h264_pict_hdr_info.raw_sei_data_list_second_field = NULL;
+
+		picture->dec_pict_sup_data.h264_pict_supl_data.nal_ref_idc =
+			pict_hdrinfo->h264_pict_hdr_info.nal_ref_idc;
+
+		picture->dec_pict_sup_data.h264_pict_supl_data.frame_num =
+			pict_hdrinfo->h264_pict_hdr_info.frame_num;
+	}
+
+#ifdef HAS_HEVC
+	if (dec_str_ctx->config.vid_std == VDEC_STD_HEVC) {
+		/* Attach the supplementary data to the decoded picture. */
+		picture->dec_pict_sup_data.raw_vui_data =
+			pict_hdrinfo->hevc_pict_hdr_info.raw_vui_data;
+
+		pict_hdrinfo->hevc_pict_hdr_info.raw_vui_data = NULL;
+
+		picture->dec_pict_sup_data.raw_sei_list_first_fld =
+			pict_hdrinfo->hevc_pict_hdr_info.raw_sei_datalist_firstfield;
+
+		pict_hdrinfo->hevc_pict_hdr_info.raw_sei_datalist_firstfield = NULL;
+
+		picture->dec_pict_sup_data.raw_sei_list_second_fld =
+			pict_hdrinfo->hevc_pict_hdr_info.raw_sei_datalist_secondfield;
+
+		pict_hdrinfo->hevc_pict_hdr_info.raw_sei_datalist_secondfield = NULL;
+
+		picture->dec_pict_sup_data.hevc_pict_supl_data.pic_order_cnt =
+			buf_control->hevc_data.pic_order_count;
+	}
+#endif
+
+	if (!((buf_control->dec_pict_type == IMG_BUFFERTYPE_PAIR &&
+	       VDECFW_PICMGMT_FIELD_CODED_PICTURE_EXECUTED(buf_control->picmgmt_flags)) ||
+	      FLAG_IS_SET(buf_control->picmgmt_flags, VDECFW_PICMGMTFLAG_PICTURE_EXECUTED))) {
+		pr_warn("[USERSID=0x%08X] [TID 0x%08X] Picture management was not executed for this picture; forcing display.",
+			dec_str_ctx->config.user_str_id,
+			decoded_pict->transaction_id);
+		decoded_pict->force_display = TRUE;
+	}
+
+	dec_str_ctx->dec_str_st.total_pict_finished++;
+
+	/*
+	 * Use NextPictIdExpected to do this check. ui32NextPictId could be
+	 * different from what expected at this point because we failed to
+	 * process a picture the last time run this function (this is still
+	 * an error (unless doing multi-core) but not the error reported here.
+	 */
+	if (picture->pict_id != dec_str_ctx->next_pict_id_expected) {
+		pr_warn("[USERSID=0x%08X] ERROR: MISSING DECODED PICTURE (%d)",
+			dec_str_ctx->config.user_str_id,
+			dec_str_ctx->next_dec_pict_id);
+	}
+
+	dec_str_ctx->next_dec_pict_id =
+		get_next_picture_id(GET_STREAM_PICTURE_ID(decoded_pict->transaction_id));
+	dec_str_ctx->next_pict_id_expected = dec_str_ctx->next_dec_pict_id;
+
+	/* Add the picture itself to the decoded list */
+	next_decoded_pict = dq_first(&dec_str_ctx->str_decd_pict_list);
+	while (next_decoded_pict &&
+	       !HAS_X_REACHED_Y(GET_STREAM_PICTURE_ID(next_decoded_pict->transaction_id),
+				picture->pict_id,
+				1 << FWIF_NUMBITS_STREAM_PICTURE_ID, unsigned int)) {
+		if (next_decoded_pict !=
+			dq_last(&dec_str_ctx->str_decd_pict_list))
+			next_decoded_pict = dq_next(next_decoded_pict);
+		else
+			next_decoded_pict = NULL;
+	}
+
+	if (next_decoded_pict)
+		dq_addbefore(next_decoded_pict, decoded_pict);
+	else
+		dq_addtail(&dec_str_ctx->str_decd_pict_list, decoded_pict);
+
+	dec_str_ctx->dec_str_st.num_pict_decoded++;
+
+	pr_debug("%s : number of picture decoded = %d\n"
+		, __func__, dec_str_ctx->dec_str_st.num_pict_decoded);
+	/* Process the decoded pictures in the encoded order */
+	decoded_pict = dq_first(&dec_str_ctx->str_decd_pict_list);
+	VDEC_ASSERT(decoded_pict);
+	if (!decoded_pict)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	ret = dec_str_ctx->str_processed_cb((void *)dec_str_ctx->usr_int_data,
+			VXD_CB_PICT_DECODED, (void *)picture);
+
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+	/*
+	 * Loop on the unprocessed pictures until we failed to process one
+	 * or we have processed them all
+	 */
+	for (next_decoded_pict = decoder_next_picture(decoded_pict,
+						      dec_str_ctx->next_dec_pict_id,
+						      &dec_str_ctx->str_decd_pict_list);
+	     next_decoded_pict;
+	      next_decoded_pict = decoder_next_picture(decoded_pict,
+						       dec_str_ctx->next_dec_pict_id,
+						       &dec_str_ctx->str_decd_pict_list)) {
+		unsigned int i = 0;
+		struct dec_decoded_pict *display_pict = NULL;
+		struct dec_decoded_pict *release_pict = NULL;
+		unsigned char last_to_display_for_seq = FALSE;
+
+		/*
+		 * next_decoded_pict is used to temporarily store decoded_pict
+		 * so that we can clear the bProcessFailed flag before
+		 * returning
+		 */
+		decoded_pict = next_decoded_pict;
+		if (!decoded_pict->force_display) {
+			struct vdecfw_buffer_control *buf_ctrl = NULL;
+
+			buf_ctrl = (struct vdecfw_buffer_control *)
+				decoded_pict->pict_ref_res->fw_ctrlbuf.cpu_virt;
+
+			if (buf_ctrl->real_data.width && buf_ctrl->real_data.height) {
+				/*
+				 * Firmware sets image size as it is in
+				 * bitstream.
+				 */
+				picture->dec_pict_info->disp_info.disp_region.width =
+					buf_ctrl->real_data.width;
+				picture->dec_pict_info->disp_info.disp_region.height =
+					buf_ctrl->real_data.height;
+				picture->dec_pict_info->disp_info.disp_region.top_offset = 0;
+				picture->dec_pict_info->disp_info.disp_region.left_offset = 0;
+
+				picture->dec_pict_info->rend_info.rend_pict_size.width =
+					picture->dec_pict_info->disp_info.disp_region.width;
+				picture->dec_pict_info->rend_info.rend_pict_size.height =
+					picture->dec_pict_info->disp_info.disp_region.height;
+
+				/*
+				 * Update encoded size with values coded in
+				 * bitstream,so golden image can be loaded
+				 * correctly
+				 */
+				picture->dec_pict_info->disp_info.enc_disp_region.width =
+					buf_ctrl->real_data.width;
+				picture->dec_pict_info->disp_info.enc_disp_region.height =
+					buf_ctrl->real_data.height;
+			}
+
+			decoded_pict->pict->dec_pict_info->timestamp =
+				buf_ctrl->real_data.timestamp;
+			decoded_pict->pict->dec_pict_info->disp_info.top_fld_first =
+				buf_ctrl->top_field_first;
+			decoded_pict->pict->dec_pict_info->disp_info.top_fld_first =
+				buf_ctrl->top_field_first;
+
+			decoded_pict->pict->dec_pict_info->id_for_hwcrc_chk =
+				GET_STREAM_PICTURE_ID(decoded_pict->transaction_id) - 1;
+			decoded_pict->pict->dec_pict_info->id_for_hwcrc_chk +=
+				dec_str_ctx->dec_str_st.flds_as_frm_decodes;
+
+			if (buf_ctrl->dec_pict_type == IMG_BUFFERTYPE_PAIR &&
+			    !buf_ctrl->second_field_of_pair)
+				dec_str_ctx->dec_str_st.flds_as_frm_decodes++;
+
+			if (buf_ctrl->second_field_of_pair) {
+				/*
+				 * Second field of pair is always complementary
+				 * type to the eFirstPictTagType of the
+				 * previous picture
+				 */
+				unsigned int prev_dec_pict_id =
+			get_prev_picture_id(GET_STREAM_PICTURE_ID(decoded_pict->transaction_id));
+
+				prev_decoded_pict =
+					decoder_get_decoded_pict_of_stream
+							(prev_dec_pict_id,
+							 &dec_str_ctx->str_decd_pict_list);
+				if (prev_decoded_pict) {
+					fld_tag_container =
+				&prev_decoded_pict->pict->dec_pict_info->second_fld_tag_container;
+					fld_tag_container->pict_tag_param =
+		decoded_pict->pict->dec_pict_info->first_fld_tag_container.pict_tag_param;
+
+					/*
+					 * Copy the first field info in the
+					 * proper place
+					 */
+					memcpy(&fld_tag_container->pict_hwcrc,
+					       &first_fld_fwmsg->pict_hwcrc,
+					       sizeof(fld_tag_container->pict_hwcrc));
+
+					/*
+					 * Attach the raw SEI data list for a
+					 * second field to a picture.
+					 */
+			prev_decoded_pict->pict->dec_pict_sup_data.raw_sei_list_second_fld =
+				decoded_pict->pict->dec_pict_sup_data.raw_sei_list_first_fld;
+
+				prev_decoded_pict->pict->dec_pict_info->disp_info.top_fld_first =
+						buf_ctrl->top_field_first;
+
+					/* Mark this picture as merged fields. */
+					prev_decoded_pict->pict->dec_pict_sup_data.merged_flds =
+						TRUE;
+					/* Mark the picture that was merged to the previous one. */
+					decoded_pict->merged = TRUE;
+				} else {
+					pr_warn("[USERSID=0x%08X] [TID 0x%08X] Failed to find decoded picture to attach tag",
+						dec_str_ctx->config.user_str_id,
+						decoded_pict->transaction_id);
+				}
+			} else {
+				/*
+				 * Not Second-field-of-pair picture tag
+				 * correlates its Tag to the its type by
+				 * setting the eFirstPictTagType in the
+				 * following way
+				 */
+				decoded_pict->pict->dec_pict_info->first_fld_tag_container.pict_type
+					=
+					buf_ctrl->dec_pict_type;
+				memcpy(&picture->dec_pict_info->first_fld_tag_container.pict_hwcrc,
+				       &first_fld_fwmsg->pict_hwcrc,
+				       sizeof
+				(picture->dec_pict_info->first_fld_tag_container.pict_hwcrc));
+			}
+
+			/*
+			 * Update the id of the next picture to process. It has
+			 * to be update always (even if we fail to process)
+			 * This has to be a global flag because it will be
+			 * passed in both decoder_NextPicture (and then to
+			 * DECODER_NextDecPictContiguous inside it)
+			 * and to the corner case check below
+			 */
+			dec_str_ctx->next_dec_pict_id =
+				get_next_picture_id(GET_STREAM_PICTURE_ID
+						    (decoded_pict->transaction_id));
+			/*
+			 * Display all the picture in the list that have been
+			 * decoded and signalled by the fw to be displayed
+			 */
+			for (i = decoded_pict->disp_idx;
+				i < buf_ctrl->display_list_length &&
+				!decoded_pict->process_failed;
+				i++, decoded_pict->disp_idx++) {
+				/*
+				 * Display picture if it has been decoded
+				 * (i.e. in decoded list).
+				 */
+				display_pict = decoder_get_decoded_pict
+							(buf_ctrl->display_list[i],
+							 &dec_str_ctx->str_decd_pict_list);
+				if (display_pict) {
+					if (FLAG_IS_SET(buf_ctrl->display_flags[i],
+							VDECFW_BUFFLAG_DISPLAY_FIELD_CODED) &&
+							(!FLAG_IS_SET
+							 (buf_ctrl->display_flags[i],
+							  VDECFW_BUFFLAG_DISPLAY_SINGLE_FIELD))) {
+						display_pict->pict->dec_pict_info->buf_type =
+									IMG_BUFFERTYPE_PAIR;
+					if (FLAG_IS_SET
+						(buf_ctrl->display_flags[i],
+						 VDECFW_BUFFLAG_DISPLAY_INTERLACED_FIELDS))
+						display_pict->pict->dec_pict_info->interlaced_flds =
+								TRUE;
+					} else if (FLAG_IS_SET
+							(buf_ctrl->display_flags[i],
+							 VDECFW_BUFFLAG_DISPLAY_FIELD_CODED) &&
+							FLAG_IS_SET
+							(buf_ctrl->display_flags[i],
+							 VDECFW_BUFFLAG_DISPLAY_SINGLE_FIELD)) {
+						display_pict->pict->dec_pict_info->buf_type =
+							FLAG_IS_SET
+							(buf_ctrl->display_flags[i],
+							 VDECFW_BUFFLAG_DISPLAY_BOTTOM_FIELD) ?
+							IMG_BUFFERTYPE_FIELD_BOTTOM :
+							IMG_BUFFERTYPE_FIELD_TOP;
+					} else {
+						display_pict->pict->dec_pict_info->buf_type =
+							IMG_BUFFERTYPE_FRAME;
+					}
+
+					display_pict->pict->dec_pict_info->view_id =
+						buf_ctrl->display_view_ids[i];
+
+					/*
+					 * When no reference pictures are left to
+					 * display and this is the last display
+					 * picture in response to the last decoded
+					 * picture, signal.
+					 */
+					if (decoded_pict->pict->last_pict_in_seq &&
+					    i == (buf_ctrl->display_list_length - 1))
+						last_to_display_for_seq = TRUE;
+
+					if (!display_pict->displayed) {
+#ifdef DEBUG_DECODER_DRIVER
+						pr_info("[USERSID=0x%08X] [TID=0x%08X] DISPLAY",
+							dec_str_ctx->config.user_str_id,
+							buf_ctrl->display_list[i]);
+#endif
+						display_pict->displayed = TRUE;
+						pict_id = GET_STREAM_PICTURE_ID
+							(buf_ctrl->display_list[i]);
+
+						ret = decoder_picture_display
+								(dec_str_ctx, pict_id,
+								 last_to_display_for_seq);
+					}
+				} else {
+					/*
+					 * In single core scenario should
+					 * not come here.
+					 */
+					pr_warn("[USERSID=0x%08X] Failed to find decoded picture [TID = 0x%08X] to send for display",
+						dec_str_ctx->config.user_str_id,
+						buf_ctrl->display_list[i]);
+				}
+				VDEC_ASSERT(ret == IMG_SUCCESS);
+				if (ret != IMG_SUCCESS)
+					return ret;
+			}
+
+			/* Release all unused pictures (firmware request) */
+			for (i = decoded_pict->rel_idx;
+				i < buf_ctrl->release_list_length &&
+				!decoded_pict->process_failed;
+				i++,  decoded_pict->rel_idx++) {
+				release_pict = decoder_get_decoded_pict
+						(buf_ctrl->release_list[i],
+						 &dec_str_ctx->str_decd_pict_list);
+				if (release_pict) {
+#ifdef DEBUG_DECODER_DRIVER
+					pr_info("[USERSID=0x%08X] RELEASE( ): PIC_ID[%d]",
+						dec_str_ctx->config.user_str_id,
+						release_pict->pict->pict_id);
+#endif
+					/*
+					 * Signal releasing this picture to upper
+					 * layers.
+					 */
+					decoder_picture_release(dec_str_ctx,
+								GET_STREAM_PICTURE_ID
+								(buf_ctrl->release_list[i]),
+								 release_pict->displayed,
+								 release_pict->merged);
+					if (release_pict->processed) {
+						/*
+						 * If the decoded picture has been
+						 * processed, destroy now.
+						 */
+						ret = decoder_decoded_picture_destroy(dec_str_ctx,
+										      release_pict,
+										      FALSE);
+					} else {
+						/*
+						 * If the decoded picture is not
+						 * processed just destroy the
+						 * containing picture.
+						 */
+						pict_id = GET_STREAM_PICTURE_ID
+									(buf_ctrl->release_list[i]);
+						ret = decoder_picture_destroy(dec_str_ctx,
+									      pict_id, FALSE);
+						VDEC_ASSERT(ret == IMG_SUCCESS);
+					if (ret != IMG_SUCCESS)
+						return ret;
+					release_pict->pict = NULL;
+					}
+					VDEC_ASSERT(ret == IMG_SUCCESS);
+					if (ret != IMG_SUCCESS)
+						return ret;
+				} else {
+					/*
+					 * In single core scenario should not
+					 * come here.
+					 */
+#ifdef DEBUG_DECODER_DRIVER
+					pr_info("[USERSID=0x%08X] Failed to find decoded picture [TID = 0x%08X] to release",
+						dec_str_ctx->config.user_str_id,
+						buf_ctrl->release_list[i]);
+#endif
+				}
+			}
+		} else {
+			/* Always display the picture if we have no hardware */
+			if (!decoded_pict->displayed) {
+#ifdef DEBUG_DECODER_DRIVER
+				pr_info("[USERSID=0x%08X] [TID=0x%08X] DISPLAY",
+					dec_str_ctx->config.user_str_id,
+					decoded_pict->transaction_id);
+#endif
+				decoded_pict->displayed = TRUE;
+				ret = decoder_picture_display
+						(dec_str_ctx,
+						 decoded_pict->pict->pict_id,
+						 decoded_pict->pict->last_pict_in_seq);
+				VDEC_ASSERT(ret == IMG_SUCCESS);
+				if (ret != IMG_SUCCESS)
+					return ret;
+			}
+
+			/* Always release the picture if we have no hardware */
+			ret = decoder_picture_destroy(dec_str_ctx,
+						      decoded_pict->pict->pict_id,
+					FALSE);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+
+			decoded_pict->pict = NULL;
+		}
+
+		/* If we have processed the current picture */
+		if (!decoded_pict->process_failed) {
+			decoded_pict->processed = TRUE;
+
+			/*
+			 * If the current picture has been released then
+			 * remove the container from the decoded list
+			 */
+			if (!decoded_pict->pict) {
+				/*
+				 * Only destroy the decoded picture once it is processed
+				 * and the fw has instructed to release the picture.
+				 */
+				ret = decoder_decoded_picture_destroy(dec_str_ctx,
+								      decoded_pict, FALSE);
+				VDEC_ASSERT(ret == IMG_SUCCESS);
+				if (ret != IMG_SUCCESS)
+					return ret;
+
+				decoded_pict = NULL;
+			} /* end if (decoded_pict->pict == NULL) */
+		} /* end if (!decoded_pict->process_failed) */
+	} /* end for */
+
+	/*
+	 * Always clear the process_failed flag to ensure that this picture
+	 * will be processed on the next function call
+	 */
+	if (decoded_pict)
+		decoded_pict->process_failed = FALSE;
+
+	/*
+	 * Go through the list of decoded pictures to check if there are any
+	 * pictures left for displaying and that are still not displayed due
+	 * to picture management errors.
+	 * Get the minimum required number of picture buffers.
+	 */
+	vdecddutils_ref_pict_get_maxnum(&dec_str_ctx->config,
+					comseq_hdrinfo, &req_pict_num);
+	req_pict_num += comseq_hdrinfo->interlaced_frames ? 2 : 1;
+
+	ret = dec_str_ctx->core_query_cb(dec_str_ctx->usr_int_data,
+			DECODER_CORE_GET_RES_LIMIT,
+			&res_limit);
+
+	/* Start the procedure only if there is enough resources available. */
+	if (res_limit >= req_pict_num) {
+		/* Allow for one picture buffer for display. */
+		res_limit--;
+
+		/*
+		 * Count the number of decoded pictures that were not
+		 * displayed yet.
+		 */
+		aux_decoded_pict = dq_first(&dec_str_ctx->str_decd_pict_list);
+		while (aux_decoded_pict) {
+			if (aux_decoded_pict->pict) {
+				dec_pict_num++;
+				if (!displayed_decoded_pict)
+					displayed_decoded_pict =
+						aux_decoded_pict;
+			}
+			if (aux_decoded_pict !=
+				dq_last(&dec_str_ctx->str_decd_pict_list))
+				aux_decoded_pict = dq_next(aux_decoded_pict);
+			else
+				aux_decoded_pict = NULL;
+		}
+	}
+
+	/* If there is at least one not displayed picture... */
+	if (displayed_decoded_pict) {
+		/*
+		 * While the number of not displayed decoded pictures exceeds
+		 * the number of maximum allowed number of pictures being held
+		 * by VDEC...
+		 */
+		while (dec_pict_num > res_limit) {
+			pr_warn("[USERSID=0x%08X] Number of outstanding decoded pictures exceeded number of available pictures buffers.",
+				dec_str_ctx->config.user_str_id);
+
+			if (!displayed_decoded_pict) {
+				VDEC_ASSERT(0);
+				return -EINVAL;
+			}
+			/* Find the picture with the least picture id. */
+			aux_decoded_pict = dq_next(displayed_decoded_pict);
+			while (aux_decoded_pict) {
+				if (aux_decoded_pict !=
+					dq_last(&dec_str_ctx->str_decd_pict_list)) {
+					if (aux_decoded_pict->pict &&
+					    aux_decoded_pict->pict->pict_id <
+					    displayed_decoded_pict->pict->pict_id)
+						displayed_decoded_pict = aux_decoded_pict;
+
+					aux_decoded_pict = dq_next(aux_decoded_pict);
+				} else {
+					if (aux_decoded_pict->pict &&
+					    aux_decoded_pict->pict->pict_id <
+					    displayed_decoded_pict->pict->pict_id)
+						displayed_decoded_pict = aux_decoded_pict;
+
+					aux_decoded_pict = NULL;
+				}
+			}
+
+			/* Display and release the picture with the least picture id. */
+			if (!displayed_decoded_pict->displayed) {
+				pr_warn("[USERSID=0x%08X] [TID=0x%08X] DISPLAY FORCED",
+					dec_str_ctx->config.user_str_id,
+					displayed_decoded_pict->transaction_id);
+				displayed_decoded_pict->displayed = TRUE;
+				ret = decoder_picture_display
+						(dec_str_ctx,
+						 displayed_decoded_pict->pict->pict_id,
+						 displayed_decoded_pict->pict->last_pict_in_seq);
+				VDEC_ASSERT(ret == IMG_SUCCESS);
+				if (ret != IMG_SUCCESS)
+					return ret;
+			}
+
+			ret = decoder_picture_destroy(dec_str_ctx,
+						      displayed_decoded_pict->pict->pict_id,
+						      FALSE);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+
+			displayed_decoded_pict->pict = NULL;
+			displayed_decoded_pict->processed = TRUE;
+
+			ret = decoder_decoded_picture_destroy(dec_str_ctx, displayed_decoded_pict,
+							      FALSE);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				return ret;
+
+			displayed_decoded_pict = NULL;
+
+			/*
+			 * Decrease the number of not displayed decoded
+			 * pictures.
+			 */
+			dec_pict_num--;
+		}
+	}
+
+#ifdef ERROR_RECOVERY_SIMULATION
+	/*
+	 * This part of the code should execute only when, DEBUG_FW_ERR_RECOVERY
+	 * flag is enabled. This basically reads the error flag attribute from
+	 * user space to create fake errors for testing the firmware error
+	 * recovery.
+	 */
+	if (fw_error_value != VDEC_ERROR_MAX) {
+		error_flag = error_flag | (1 << fw_error_value);
+		/* Now lets make it VDEC_ERROR_MAX */
+		fw_error_value = VDEC_ERROR_MAX;
+	}
+#endif
+
+	/*
+	 * Whenever the error flag is set, we need to handle the error case.
+	 * Need to forward this error to stream processed callback.
+	 */
+	switch (error_flag) {
+	case VDEC_ERROR_NONE:
+	case VDEC_ERROR_CORRUPTED_REFERENCE:
+	case VDEC_ERROR_MISSING_REFERENCES:
+	case VDEC_ERROR_MMCO:
+	case VDEC_ERROR_MBS_DROPPED:
+		/* these are not fatal */
+		break;
+	default:
+		/* anything else is */
+		pr_err("%s : %d err_flags: 0x%x\n", __func__, __LINE__, error_flag);
+		ret = dec_str_ctx->str_processed_cb((void *)dec_str_ctx->usr_int_data,
+				VXD_CB_ERROR_FATAL, &error_flag);
+		break;
+	}
+	/*
+	 * check for eos on bitstream and propagate the same to picture
+	 * buffer
+	 */
+	ctx = dec_str_ctx->vxd_dec_ctx;
+	ctx->num_decoding--;
+	if (ctx->eos) {
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("EOS reached\n");
+#endif
+		ret = dec_str_ctx->str_processed_cb((void *)dec_str_ctx->usr_int_data,
+				VXD_CB_STR_END, NULL);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+	}
+
+	return ret;
+}
+
+/*
+ * @Function  decoder_service_firmware_response
+ */
+int decoder_service_firmware_response(void *dec_str_ctx_arg, unsigned int *msg,
+				      unsigned int msg_size, unsigned int msg_flags)
+{
+	int ret = IMG_SUCCESS;
+	struct dec_decpict *dec_pict = NULL;
+	unsigned char head_of_queue = TRUE;
+	struct dec_str_ctx *dec_str_ctx;
+	struct dec_str_unit *dec_str_unit;
+	unsigned char pict_start = FALSE;
+	enum vdecdd_str_unit_type str_unit_type;
+	struct vdecdd_picture *picture;
+	struct decoder_pict_fragment *pict_fragment;
+	struct dec_str_ctx *dec_strctx;
+	struct dec_core_ctx *dec_core_ctx;
+
+	/* validate input arguments */
+	if (!dec_str_ctx_arg || !msg) {
+		VDEC_ASSERT(0);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	dec_strctx = decoder_stream_get_context(dec_str_ctx_arg);
+
+	dec_core_ctx = decoder_str_ctx_to_core_ctx(dec_strctx);
+
+	if (!dec_core_ctx) {
+		pr_err("%s: dec_core_ctx is NULL\n", __func__);
+		VDEC_ASSERT(0);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	pr_debug("%s : process firmware response\n", __func__);
+	ret = hwctrl_process_msg(dec_core_ctx->hw_ctx, msg_flags, msg, &dec_pict);
+	VDEC_ASSERT((ret == IMG_SUCCESS) | (ret == IMG_ERROR_FATAL));
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	if (!dec_pict || (dec_pict->state != DECODER_PICTURE_STATE_DECODED &&
+			  dec_pict->state != DECODER_PICTURE_STATE_TO_DISCARD))
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	/*
+	 * Try and locate the stream context in the list of active
+	 * streams.
+	 */
+	VDEC_ASSERT(dec_core_ctx->dec_ctx);
+	dec_str_ctx = lst_first(&dec_core_ctx->dec_ctx->str_list);
+	if (!dec_str_ctx) {
+		VDEC_ASSERT(0);
+		return -EINVAL;
+	}
+
+	while (dec_str_ctx) {
+		if (dec_str_ctx == dec_pict->dec_str_ctx)
+			break;
+
+		dec_str_ctx = lst_next(dec_str_ctx);
+	}
+
+	/*
+	 * If the stream is not in the list of active streams then
+	 * it must have been destroyed.
+	 * This interrupt should be ignored.
+	 */
+	if (dec_str_ctx != dec_pict->dec_str_ctx)
+		return IMG_SUCCESS;
+
+	/*
+	 * Retrieve the picture from the head of the core decode queue
+	 * primarily to obtain the correct stream context.
+	 */
+	hwctrl_removefrom_piclist(dec_core_ctx->hw_ctx, dec_pict);
+
+	if (!dec_str_ctx) {
+		VDEC_ASSERT(0);
+		return -EINVAL;
+	}
+	dec_str_ctx->avail_slots++;
+	VDEC_ASSERT(dec_str_ctx->avail_slots > 0);
+
+	/*
+	 * Store the stream context of the picture that has been
+	 * decoded.
+	 */
+	dec_str_ctx = dec_pict->dec_str_ctx;
+	VDEC_ASSERT(dec_str_ctx);
+
+	if (!dec_str_ctx)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	/*
+	 * Picture has been discarded before EOP unit,
+	 * recover the decoder to valid state
+	 */
+	if (!dec_pict->eop_found) {
+		VDEC_ASSERT(dec_pict == dec_str_ctx->cur_pict);
+
+		dec_core_ctx->busy = FALSE;
+		dec_str_ctx->cur_pict = NULL;
+	}
+
+	/*
+	 * Peek the first stream unit and validate against core
+	 * queue to ensure that this really is the next picture
+	 * for the stream.
+	 */
+	dec_str_unit = lst_first(&dec_str_ctx->pend_strunit_list);
+	if (dec_str_unit) {
+		if (dec_str_unit->dec_pict != dec_pict) {
+			head_of_queue = FALSE;
+
+			/*
+			 * For pictures to be decoded
+			 * out-of-order there must be
+			 * more than one decoder core.
+			 */
+			VDEC_ASSERT(dec_str_ctx->decctx->num_pipes > 1);
+			while (dec_str_unit) {
+				dec_str_unit = lst_next(dec_str_unit);
+				if (dec_str_unit->dec_pict == dec_pict)
+					break;
+			}
+		}
+		VDEC_ASSERT(dec_str_unit);
+		if (!dec_str_unit)
+			return IMG_ERROR_FATAL;
+
+		VDEC_ASSERT(dec_str_unit->dec_pict == dec_pict);
+		VDEC_ASSERT(dec_str_unit->str_unit->str_unit_type ==
+			VDECDD_STRUNIT_PICTURE_START);
+	}
+
+	/*
+	 * Process all units from the pending stream list until
+	 * the next picture start.
+	 */
+	while (dec_str_unit && !pict_start) {
+		/*
+		 * Actually remove the unit now from the
+		 * pending stream list.
+		 */
+		lst_remove(&dec_str_ctx->pend_strunit_list, dec_str_unit);
+		if (!dec_str_unit->str_unit || !dec_pict)
+			break;
+
+		str_unit_type = dec_str_unit->str_unit->str_unit_type;
+
+		if (str_unit_type != VDECDD_STRUNIT_PICTURE_START)
+			break;
+
+		dec_str_ctx = dec_pict->dec_str_ctx;
+
+		dec_str_ctx->dec_str_st.num_pict_decoding--;
+		dec_str_ctx->dec_str_st.total_pict_decoded++;
+
+		ret = idgen_gethandle(dec_str_ctx->pict_idgen,
+				      GET_STREAM_PICTURE_ID(dec_str_unit->dec_pict->transaction_id),
+				      (void **)&picture);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS || !picture) {
+			pr_err("[USERSID=0x%08X] Failed to find picture from ID",
+			       dec_str_ctx->config.user_str_id);
+			return IMG_ERROR_INVALID_ID;
+		}
+
+		VDEC_ASSERT(picture == dec_str_unit->str_unit->dd_pict_data);
+
+		/* Hold a reference to the last context on the BE */
+		if (dec_str_ctx->last_be_pict_dec_res && HAS_X_PASSED_Y
+		    (picture->pict_id,
+		     GET_STREAM_PICTURE_ID(dec_str_ctx->last_be_pict_dec_res->transaction_id),
+		    1 << FWIF_NUMBITS_STREAM_PICTURE_ID, unsigned int)) {
+			/* Return previous last FW context. */
+			resource_item_return(&dec_str_ctx->last_be_pict_dec_res->ref_cnt);
+
+			if (resource_item_isavailable(&dec_str_ctx->last_be_pict_dec_res->ref_cnt
+						      )) {
+				resource_list_remove(&dec_str_ctx->dec_res_lst,
+						     dec_str_ctx->last_be_pict_dec_res);
+				resource_list_add_img(&dec_str_ctx->dec_res_lst,
+						      dec_str_ctx->last_be_pict_dec_res, 0,
+						      &dec_str_ctx->last_be_pict_dec_res->ref_cnt);
+			}
+		}
+		if (!dec_str_ctx->last_be_pict_dec_res ||
+		    (dec_str_ctx->last_be_pict_dec_res && HAS_X_PASSED_Y
+		    (picture->pict_id,
+		     GET_STREAM_PICTURE_ID(dec_str_ctx->last_be_pict_dec_res->transaction_id),
+		    1 << FWIF_NUMBITS_STREAM_PICTURE_ID, unsigned int))) {
+			/* Hold onto last FW context. */
+			dec_str_ctx->last_be_pict_dec_res = dec_pict->cur_pict_dec_res;
+			resource_item_use(&dec_str_ctx->last_be_pict_dec_res->ref_cnt);
+		}
+		resource_item_return(&dec_pict->cur_pict_dec_res->ref_cnt);
+
+		if (resource_item_isavailable(&dec_pict->cur_pict_dec_res->ref_cnt)) {
+			resource_list_remove(&dec_str_ctx->dec_res_lst,
+					     dec_pict->cur_pict_dec_res);
+			resource_list_add_img(&dec_str_ctx->dec_res_lst,
+					      dec_pict->cur_pict_dec_res, 0,
+					      &dec_pict->cur_pict_dec_res->ref_cnt);
+		}
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("[USERSID=0x%08X] [TID=0x%08X] DECODED",
+			dec_str_ctx->config.user_str_id,
+			dec_pict->transaction_id);
+#endif
+
+		ret = decoder_picture_decoded(dec_str_ctx, dec_core_ctx,
+					      picture, dec_pict,
+					      dec_pict->pict_hdr_info,
+					      dec_str_unit->str_unit);
+
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+
+		dec_res_picture_detach(&dec_str_ctx->resources, dec_pict);
+
+		/* Free the segments from the decode picture */
+		decoder_clean_bitstr_segments(&dec_pict->dec_pict_seg_list);
+
+		pict_fragment = lst_removehead(&dec_pict->fragment_list);
+		while (pict_fragment) {
+			kfree(pict_fragment);
+			pict_fragment =
+				lst_removehead(&dec_pict->fragment_list);
+		}
+
+		pict_start = (!head_of_queue) ? TRUE : FALSE;
+
+		ret = dec_str_ctx->str_processed_cb(dec_str_ctx->usr_int_data,
+				VXD_CB_STRUNIT_PROCESSED,
+				dec_str_unit->str_unit);
+
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS) {
+			/* Free decoder picture */
+			kfree(dec_pict);
+			dec_pict = NULL;
+			return ret;
+		}
+
+		/* Destroy the Decoder stream unit wrapper */
+		kfree(dec_str_unit);
+
+		/* Peek at the next stream unit */
+		dec_str_unit = lst_first(&dec_str_ctx->pend_strunit_list);
+		if (dec_str_unit)
+			pict_start = (dec_str_unit->str_unit->str_unit_type ==
+				VDECDD_STRUNIT_PICTURE_START &&
+				dec_str_unit->dec_pict != dec_pict);
+
+		/* Free decoder picture */
+		kfree(dec_pict);
+		dec_pict = NULL;
+	}
+
+	kfree(dec_str_unit);
+	return ret;
+}
+
+/*
+ * @Function  decoder_is_stream_idle
+ */
+unsigned char decoder_is_stream_idle(void *dec_str_ctx_handle)
+{
+	struct dec_str_ctx *dec_str_ctx;
+
+	dec_str_ctx = decoder_stream_get_context(dec_str_ctx_handle);
+	VDEC_ASSERT(dec_str_ctx);
+	if (!dec_str_ctx) {
+		pr_err("Invalid decoder stream context handle!");
+		return FALSE;
+	}
+
+	return lst_empty(&dec_str_ctx->pend_strunit_list);
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/decoder.h b/drivers/media/platform/img/vxe-vxd/decoder/decoder.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/decoder.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/decoder.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,376 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD Decoder Component header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *      Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *      Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#ifndef __DECODER_H__
+#define __DECODER_H__
+
+#include "bspp.h"
+#include "dq.h"
+#ifdef HAS_JPEG
+#include "jpegfw_data.h"
+#endif
+#include "lst.h"
+#include "vdecdd_defs.h"
+#include "vdec_defs.h"
+#include "vid_buf.h"
+#include "vxd_ext.h"
+#include "vxd_props.h"
+#include "hevcfw_data.h"
+
+#define MAX_CONCURRENT_STREAMS 16
+#define CORE_NUM_DECODE_SLOTS 2
+
+enum dec_pict_states {
+	DECODER_PICTURE_STATE_TO_DECODE = 0,
+	DECODER_PICTURE_STATE_DECODED,
+	DECODER_PICTURE_STATE_TO_DISCARD,
+	DECODER_PICTURE_STATE_MAX,
+	DECODER_PICTURE_FORCE32BITS     = 0x7FFFFFFFU
+};
+
+enum dec_res_type {
+	DECODER_RESTYPE_TRANSACTION = 0,
+	DECODER_RESTYPE_HDR,
+	DECODER_RESTYPE_BATCH_MSG,
+#ifdef HAS_HEVC
+	DECODER_RESTYPE_PVDEC_BUF,
+#endif
+	DECODER_RESTYPE_MAX,
+	DECODER_RESTYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum dec_core_query_type {
+	DECODER_CORE_GET_RES_LIMIT = 0,
+	DECODER_CORE_FORCE32BITS   = 0x7FFFFFFFU
+};
+
+/*
+ * @Function              pfnRefPicGetMaxNum
+ * @Description
+ * This is the prototype for functions calculating the maximum number
+ * of reference pictures required per video standard.
+ *
+ * @Input    psComSequHdrInfo  : A pointer to the common VSH information
+ * structure.
+ *
+ * @Output   pui32MaxRefPicNum :  A pointer used to return the maximum number
+ *                               of reference frames required.
+ *
+ * @Return   IMG_RESULT : This function returns either IMG_SUCCESS or
+ * an error code.
+ */
+typedef int (*ref_pic_get_maximum)(const struct vdec_comsequ_hdrinfo *comseq_hdr_info,
+				   unsigned int *max_ref_pict_num);
+
+typedef int (*strunit_processed_cb)(void *handle, int cb_type, void *item);
+
+typedef int (*core_gen_cb)(void *handle, int query, void *item);
+
+struct dec_ctx;
+
+/*
+ * This structure contains the core context.
+ * @brief  Decoder Core Context
+ */
+struct dec_core_ctx {
+	void **link;            /* to be part of single linked list */
+	struct dec_ctx *dec_ctx;
+	unsigned char enumerated;
+	unsigned char master;
+	unsigned char configured;
+	unsigned int core_features;
+	unsigned int pipe_features[VDEC_MAX_PIXEL_PIPES];
+	struct vxd_coreprops core_props;
+	void *resources;
+	void *hw_ctx;
+	unsigned int cum_pics;
+	unsigned char busy;
+};
+
+struct dec_ctx {
+	unsigned char inited;
+	void *user_data;
+	const struct vdecdd_dd_devconfig *dev_cfg;
+	unsigned int num_pipes;
+	struct dec_core_ctx *dec_core_ctx;
+	struct lst_t str_list;
+	void *mmu_dev_handle;
+	void *dev_handle;
+	struct vidio_ddbufinfo ptd_buf_info;
+	unsigned char sup_stds[VDEC_STD_MAX];
+	unsigned int internal_heap_id;
+	unsigned int str_cnt;
+};
+
+/*
+ * This structure contains the device decode resource (used for decoding and
+ * held for subsequent decoding).
+ * @brief  Decoder Device Resource
+ */
+struct dec_pictdec_res {
+	void **link;    /* to be part of single linked list */
+	unsigned int transaction_id;
+	struct vidio_ddbufinfo fw_ctx_buf;
+	struct vidio_ddbufinfo h264_sgm_buf;
+	unsigned int ref_cnt;
+};
+
+struct dec_decpict;
+
+/*
+ *
+ * This structure contains the stream context.
+ * @brief  Decoder Stream Context
+ */
+struct dec_str_ctx {
+	void **link;    /* to be part of single linked list */
+	int km_str_id;
+	struct vdec_str_configdata config;
+	struct dec_ctx *decctx;
+	void *vxd_dec_ctx;
+	void *usr_int_data;
+	void *mmu_str_handle;
+	void *pict_idgen;
+	struct lst_t pend_strunit_list;
+	struct dq_linkage_t str_decd_pict_list;
+	unsigned int num_ref_res;
+	struct lst_t ref_res_lst;
+	unsigned int num_dec_res;
+	struct lst_t dec_res_lst;
+	unsigned int avail_pipes;
+	unsigned int avail_slots;
+	struct vdecdd_decstr_status dec_str_st;
+	struct vidio_ddbufinfo pvdec_fw_ctx_buf;
+	unsigned int last_fe_transaction_id;
+	unsigned int next_dec_pict_id;
+	unsigned int next_pict_id_expected;
+	struct dec_pictdec_res *cur_fe_pict_dec_res;
+	struct dec_pictdec_res *prev_fe_pict_dec_res;
+	struct dec_pictdec_res *last_be_pict_dec_res;
+	struct dec_decpict *cur_pict;
+	void *resources;
+	strunit_processed_cb str_processed_cb;
+	core_gen_cb core_query_cb;
+};
+
+/*
+ * Resource Structure for DECODER_sDdResourceInfo to be used with pools
+ */
+struct res_resinfo {
+	void **link;                    /* to be part of single linked list */
+	void *res;
+	struct vidio_ddbufinfo *ddbuf_info;
+};
+
+struct vdecdd_ddstr_ctx;
+
+/*
+ * This structure contains the Decoded attributes
+ * @brief Decoded attributes
+ */
+struct dec_pict_attrs {
+	unsigned char first_fld_rcvd;
+	unsigned int fe_err;
+	unsigned int no_be_wdt;
+	unsigned int mbs_dropped;
+	unsigned int mbs_recovered;
+	struct vxd_pict_attrs pict_attrs;
+};
+
+/*
+ * This union contains firmware contexts. Used to allocate buffers for firmware
+ * context.
+ */
+union dec_fw_contexts {
+	struct h264fw_context_data h264_context;
+#ifdef HAS_JPEG
+	struct jpegfw_context_data jpeg_context;
+#endif
+#ifdef HAS_HEVC
+	struct hevcfw_ctx_data hevc_context;
+#endif
+};
+
+/*
+ * for debug
+ */
+struct dec_fwmsg {
+	void **link;
+	struct dec_pict_attrs pict_attrs;
+	struct vdec_pict_hwcrc pict_hwcrc;
+};
+
+/*
+ * This structure contains the stream decode resource (persistent for
+ * longer than decoding).
+ * @brief  Decoder Stream Resource
+ */
+struct dec_pictref_res {
+	void **link;                    /* to be part of single linked list */
+	struct vidio_ddbufinfo fw_ctrlbuf;
+	unsigned int ref_cnt;
+};
+
+/*
+ * This structure defines the decode picture.
+ * @brief  Decoder Picture
+ */
+struct dec_decpict {
+	void **link;
+	unsigned int transaction_id;
+	void *dec_str_ctx;
+	unsigned char twopass;
+	unsigned char first_fld_rcvd;
+	struct res_resinfo *transaction_info;
+	struct res_resinfo *hdr_info;
+#ifdef HAS_HEVC
+	struct res_resinfo *pvdec_info;
+	unsigned int temporal_out_addr;
+#endif
+	struct vdecdd_ddpict_buf *recon_pict;
+	struct vdecdd_ddpict_buf *alt_pict;
+	struct res_resinfo *batch_msginfo;
+	struct vidio_ddbufinfo *intra_bufinfo;
+	struct vidio_ddbufinfo *auxline_bufinfo;
+	struct vidio_ddbufinfo *vlc_tables_bufinfo;
+	struct vidio_ddbufinfo *vlc_idx_tables_bufinfo;
+	struct vidio_ddbufinfo *start_code_bufinfo;
+	struct dec_fwmsg *first_fld_fwmsg;
+	struct dec_fwmsg *second_fld_fwmsg;
+	struct bspp_pict_hdr_info *pict_hdr_info;
+	struct dec_pictdec_res *cur_pict_dec_res;
+	struct dec_pictdec_res *prev_pict_dec_res;
+	struct dec_pictref_res *pict_ref_res;
+	struct lst_t dec_pict_seg_list;
+	struct lst_t fragment_list;
+	unsigned char eop_found;
+	unsigned int operating_op;
+	unsigned short genc_id;
+	struct vdecdd_ddbuf_mapinfo **genc_bufs;
+	struct vdecdd_ddbuf_mapinfo *genc_fragment_buf;
+	unsigned int ctrl_alloc_bytes;
+	unsigned int ctrl_alloc_offset;
+	enum dec_pict_states state;
+	struct vidio_ddbufinfo *str_pvdec_fw_ctxbuf;
+};
+
+/*
+ *
+ * This structure defines the decode picture reference.
+ * @brief  Decoder Picture Reference
+ */
+struct dec_str_unit {
+	void **link;                    /* to be part of single linked list */
+	struct dec_decpict *dec_pict;
+	struct vdecdd_str_unit *str_unit;
+};
+
+/*
+ * This structure defines the decoded picture.
+ * @brief  Decoded Picture
+ */
+struct dec_decoded_pict {
+	struct dq_linkage_t link;     /* to be part of double linked list */
+	unsigned int transaction_id;
+	unsigned char processed;
+	unsigned char process_failed;
+	unsigned char force_display;
+	unsigned char displayed;
+	unsigned char merged;
+	unsigned int disp_idx;
+	unsigned int rel_idx;
+	struct vdecdd_picture *pict;
+	struct dec_fwmsg *first_fld_fwmsg;
+	struct dec_fwmsg *second_fld_fwmsg;
+	struct dec_pictref_res *pict_ref_res;
+};
+
+struct dec_pict_fragment {
+	void **link;    /* to be part of single linked list */
+	/* Control allocation size in bytes */
+	unsigned int ctrl_alloc_bytes;
+	/* Control allocation offset in bytes */
+	unsigned int ctrl_alloc_offset;
+};
+
+/*
+ * This structure contains the pointer to the picture segment.
+ * All the segments could be added to the list in struct dec_decpict,
+ * but because list items cannot belong to more than one list this wrapper
+ * is used which is added in the list sDecPictSegList inside struct dec_decpict
+ * @brief  Decoder Picture Segment
+ */
+struct dec_decpict_seg {
+	void **link;                    /* to be part of single linked list */
+	struct bspp_bitstr_seg *bstr_seg;
+	unsigned char internal_seg;
+};
+
+struct decoder_regsoffsets {
+	unsigned int vdmc_cmd_offset;
+	unsigned int vec_offset;
+	unsigned int entropy_offset;
+	unsigned int vec_be_regs_offset;
+	unsigned int vdec_be_codec_regs_offset;
+};
+
+int decoder_initialise(void *init_usr_data, unsigned int internal_heap_id,
+		       struct vdecdd_dd_devconfig *dd_devcfg, unsigned int *num_pipes,
+		       void **dec_ctx);
+
+int decoder_deinitialise(void *dec_ctx);
+
+int decoder_supported_features(void *dec_ctx, struct vdec_features *features);
+
+int decoder_stream_destroy(void *dec_str_ctx, unsigned char abort);
+
+int decoder_stream_create(void *dec_ctx, struct vdec_str_configdata str_cfg,
+			  unsigned int kmstr_id, void **mmu_str_handle,
+			  void *vxd_dec_ctx, void *str_usr_int_data,
+			  void **dec_str_ctx, void *decoder_cb, void *query_cb);
+
+int decoder_stream_prepare_ctx(void *dec_str_ctx, unsigned char flush_dpb);
+
+int decoder_stream_process_unit(void *dec_str_ctx,
+				struct vdecdd_str_unit *str_unit);
+
+int decoder_get_load(void *dec_str_ctx, unsigned int *avail_slots);
+
+int
+decoder_check_support(void *dec_ctx,
+		      const struct vdec_str_configdata *str_cfg,
+		      const struct vdec_str_opconfig *op_cfg,
+		      const struct vdecdd_ddpict_buf *disp_pictbuf,
+		      const struct vdec_pict_rendinfo *req_pict_rendinfo,
+		      const struct vdec_comsequ_hdrinfo *comseq_hdrinfo,
+		      const struct bspp_pict_hdr_info *pict_hdrinfo,
+		      const struct vdec_comsequ_hdrinfo *prev_comseq_hdrinfo,
+		      const struct bspp_pict_hdr_info *prev_pict_hdrinfo,
+		      unsigned char non_cfg_req, struct vdec_unsupp_flags *unsupported,
+		      unsigned int *features);
+
+unsigned char decoder_is_stream_idle(void *dec_str_ctx);
+
+int decoder_stream_flush(void *dec_str_ctx, unsigned char discard_refs);
+
+int decoder_stream_release_buffers(void *dec_str_ctx);
+
+int decoder_stream_get_status(void *dec_str_ctx,
+			      struct vdecdd_decstr_status *dec_str_st);
+
+int decoder_service_firmware_response(void *dec_str_ctx_arg, unsigned int *msg,
+				      unsigned int msg_size, unsigned int msg_flags);
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/dec_resources.c b/drivers/media/platform/img/vxe-vxd/decoder/dec_resources.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/dec_resources.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/dec_resources.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,554 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VXD Decoder resource allocation and tracking function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "decoder.h"
+#include "dec_resources.h"
+#include "hw_control.h"
+#include "h264fw_data.h"
+#include "h264_idx.h"
+#include "h264_vlc.h"
+#include "img_mem.h"
+#include "pool_api.h"
+#include "vdecdd_utils.h"
+#include "vdec_mmu_wrapper.h"
+#include "vid_buf.h"
+#include "vxd_mmu_defs.h"
+
+#define DECODER_END_BYTES_SIZE  40
+
+#define BATCH_MSG_BUFFER_SIZE   (8 * 4096)
+#define INTRA_BUF_SIZE          (1024 * 32)
+#define AUX_LINE_BUFFER_SIZE    (512 * 1024)
+
+static void decres_pack_vlc_tables(unsigned short *packed,
+				   unsigned short *unpacked,
+				   unsigned short size)
+{
+	unsigned short i, j;
+
+	for (i = 0; i < size; i++) {
+		j = i * 3;
+		/*
+		 * opcode 14:12
+		 * width 11:9
+		 * symbol 8:0
+		 */
+		packed[i] = 0 | ((unpacked[j]) << 12) |
+			((unpacked[j + 1]) << 9) | (unpacked[j + 2]);
+	}
+}
+
+struct dec_vlctable {
+	void    *data;
+	unsigned int num_entries;
+	void    *index_table;
+	unsigned int num_tables;
+};
+
+/*
+ * Union with sizes of firmware parser header structure sizes. Dec_resources
+ * uses the largest to allocate the header buffer.
+ */
+union decres_fw_hdrs {
+	struct h264fw_header_data h264_header;
+};
+
+/*
+ * This array contains the size of each resource allocation.
+ * @brief  Resource Allocation Sizes
+ * NOTE: This should be kept in step with #DECODER_eResType.
+ */
+static const unsigned int res_size[DECODER_RESTYPE_MAX] = {
+	sizeof(struct vdecfw_transaction),
+	sizeof(union decres_fw_hdrs),
+	BATCH_MSG_BUFFER_SIZE,
+#ifdef HAS_HEVC
+	MEM_TO_REG_BUF_SIZE + SLICE_PARAMS_BUF_SIZE + ABOVE_PARAMS_BUF_SIZE,
+#endif
+};
+
+static const unsigned char start_code[] = {
+	0x00, 0x00, 0x01, 0x00,
+};
+
+static void decres_get_vlc_data(struct dec_vlctable *vlc_table,
+				enum vdec_vid_std vid_std)
+{
+	switch (vid_std) {
+	case VDEC_STD_H264:
+		vlc_table->data = h264_vlc_table_data;
+		vlc_table->num_entries = h264_vlc_table_size;
+		vlc_table->index_table = h264_vlc_index_data;
+		vlc_table->num_tables = h264_vlc_index_size;
+		break;
+
+	default:
+		memset(vlc_table, 0x0, sizeof(*vlc_table));
+		break;
+	}
+}
+
+static void decres_fnbuf_info_destructor(void *param, void *cb_handle)
+{
+	struct vidio_ddbufinfo *dd_bufinfo = (struct vidio_ddbufinfo *)param;
+	int ret;
+	void *mmu_handle = cb_handle;
+
+	VDEC_ASSERT(dd_bufinfo);
+
+	ret = mmu_free_mem(mmu_handle, dd_bufinfo);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+
+	kfree(dd_bufinfo);
+	dd_bufinfo = NULL;
+}
+
+int dec_res_picture_detach(void **res_ctx, struct dec_decpict *dec_pict)
+{
+	struct dec_res_ctx *local_res_ctx;
+
+	VDEC_ASSERT(res_ctx);
+	VDEC_ASSERT(res_ctx && *res_ctx);
+	VDEC_ASSERT(dec_pict);
+	VDEC_ASSERT(dec_pict && dec_pict->transaction_info);
+
+	if (!res_ctx || !(*res_ctx) || !dec_pict ||
+	    !dec_pict->transaction_info) {
+		pr_err("Invalid parameters\n");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	local_res_ctx = (struct dec_res_ctx *)*res_ctx;
+
+	/* return transaction buffer */
+	lst_add(&local_res_ctx->pool_data_list[DECODER_RESTYPE_TRANSACTION],
+		dec_pict->transaction_info);
+	pool_resfree(dec_pict->transaction_info->res);
+
+	/* return picture header information buffer */
+	lst_add(&local_res_ctx->pool_data_list[DECODER_RESTYPE_HDR],
+		dec_pict->hdr_info);
+	pool_resfree(dec_pict->hdr_info->res);
+
+	/* return batch message buffer */
+	lst_add(&local_res_ctx->pool_data_list[DECODER_RESTYPE_BATCH_MSG],
+		dec_pict->batch_msginfo);
+	pool_resfree(dec_pict->batch_msginfo->res);
+
+#ifdef HAS_HEVC
+	if (dec_pict->pvdec_info) {
+		lst_add(&local_res_ctx->pool_data_list[DECODER_RESTYPE_PVDEC_BUF],
+			dec_pict->pvdec_info);
+		pool_resfree(dec_pict->pvdec_info->res);
+	}
+#endif
+
+	return IMG_SUCCESS;
+}
+
+static int decres_get_resource(struct dec_res_ctx *res_ctx,
+			       enum dec_res_type res_type,
+			       struct res_resinfo **res_info,
+			       unsigned char fill_zeros)
+{
+	struct res_resinfo *local_res_info = NULL;
+	unsigned int ret = IMG_SUCCESS;
+
+	VDEC_ASSERT(res_ctx);
+	VDEC_ASSERT(res_info);
+
+	local_res_info = lst_removehead(&res_ctx->pool_data_list[res_type]);
+	VDEC_ASSERT(local_res_info);
+	if (local_res_info) {
+		VDEC_ASSERT(local_res_info->ddbuf_info);
+		if (local_res_info->ddbuf_info) {
+			ret = pool_resalloc(res_ctx->res_pool[res_type], local_res_info->res);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS) {
+				ret = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+				return ret;
+			}
+
+			if (fill_zeros)
+				memset(local_res_info->ddbuf_info->cpu_virt, 0,
+				       local_res_info->ddbuf_info->buf_size);
+
+			*res_info = local_res_info;
+		} else {
+			ret = IMG_ERROR_FATAL;
+			return ret;
+		}
+	} else {
+		ret = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+		return ret;
+	}
+
+	return ret;
+}
+
+int dec_res_picture_attach(void **res_ctx, enum vdec_vid_std vid_std,
+			   struct dec_decpict *dec_pict)
+{
+	struct dec_res_ctx *local_res_ctx;
+	int ret;
+
+	VDEC_ASSERT(res_ctx);
+	VDEC_ASSERT(res_ctx && *res_ctx);
+	VDEC_ASSERT(dec_pict);
+	if (!res_ctx || !(*res_ctx) || !dec_pict) {
+		pr_err("Invalid parameters");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	local_res_ctx = (struct dec_res_ctx *)*res_ctx;
+
+	/* Obtain transaction buffer. */
+	ret = decres_get_resource(local_res_ctx, DECODER_RESTYPE_TRANSACTION,
+				  &dec_pict->transaction_info, TRUE);
+
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	/* Obtain picture header information buffer */
+	ret = decres_get_resource(local_res_ctx, DECODER_RESTYPE_HDR,
+				  &dec_pict->hdr_info, TRUE);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+#ifdef HAS_HEVC
+	/* Obtain HEVC buffer */
+	if (vid_std == VDEC_STD_HEVC) {
+		ret = decres_get_resource(local_res_ctx, DECODER_RESTYPE_PVDEC_BUF,
+					  &dec_pict->pvdec_info, TRUE);
+
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			return ret;
+	}
+#endif
+	/* Obtain picture batch message buffer */
+	ret = decres_get_resource(local_res_ctx, DECODER_RESTYPE_BATCH_MSG,
+				  &dec_pict->batch_msginfo, TRUE);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	dec_pict->intra_bufinfo = &local_res_ctx->intra_bufinfo;
+	dec_pict->auxline_bufinfo = &local_res_ctx->auxline_bufinfo;
+	dec_pict->vlc_tables_bufinfo =
+		&local_res_ctx->vlc_tables_bufinfo[vid_std];
+	dec_pict->vlc_idx_tables_bufinfo =
+		&local_res_ctx->vlc_idxtables_bufinfo[vid_std];
+	dec_pict->start_code_bufinfo = &local_res_ctx->start_code_bufinfo;
+
+	return IMG_SUCCESS;
+}
+
+int dec_res_create(void *mmu_handle, struct vxd_coreprops *core_props,
+		   unsigned int num_dec_slots,
+		   unsigned int mem_heap_id, void **resources)
+{
+	struct dec_res_ctx *local_res_ctx;
+	int ret;
+	unsigned int i = 0;
+	struct dec_vlctable vlc_table;
+	enum sys_emem_attrib mem_attrib;
+
+	VDEC_ASSERT(core_props);
+	VDEC_ASSERT(resources);
+	if (!core_props || !resources) {
+		pr_err("Invalid parameters");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	mem_attrib = (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE);
+	mem_attrib |= (enum sys_emem_attrib)SYS_MEMATTRIB_INTERNAL;
+
+	local_res_ctx = kzalloc(sizeof(*local_res_ctx), GFP_KERNEL);
+	VDEC_ASSERT(local_res_ctx);
+	if (!local_res_ctx)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/* Allocate Intra buffer. */
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s:%d call MMU_StreamMalloc", __func__, __LINE__);
+#endif
+
+	ret = mmu_stream_alloc(mmu_handle, MMU_HEAP_STREAM_BUFFERS, mem_heap_id,
+			       mem_attrib,
+			       core_props->num_pixel_pipes *
+			       INTRA_BUF_SIZE * 3,
+			       DEV_MMU_PAGE_ALIGNMENT,
+			       &local_res_ctx->intra_bufinfo);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	/* Allocate aux line buffer. */
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s:%d call MMU_StreamMalloc", __func__, __LINE__);
+#endif
+	ret = mmu_stream_alloc(mmu_handle, MMU_HEAP_STREAM_BUFFERS, mem_heap_id,
+			       mem_attrib,
+			       AUX_LINE_BUFFER_SIZE * 3 *
+			       core_props->num_pixel_pipes,
+			       DEV_MMU_PAGE_ALIGNMENT,
+			       &local_res_ctx->auxline_bufinfo);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	/* Allocate standard-specific buffers. */
+	for (i = VDEC_STD_UNDEFINED + 1; i < VDEC_STD_MAX; i++) {
+		decres_get_vlc_data(&vlc_table, (enum vdec_vid_std)i);
+
+		if (vlc_table.num_tables > 0) {
+			/*
+			 * Size of VLC IDX table in bytes. Has to be aligned
+			 * to 4, so transfer to MTX succeeds.
+			 * (VLC IDX is copied to local RAM of MTX)
+			 */
+			unsigned int vlc_idxtable_sz =
+				ALIGN((sizeof(unsigned short) * vlc_table.num_tables * 3), 4);
+
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info(" %s:%d calling MMU_StreamMalloc", __func__, __LINE__);
+#endif
+
+			ret = mmu_stream_alloc(mmu_handle,
+					       MMU_HEAP_STREAM_BUFFERS,
+					       mem_heap_id, (enum sys_emem_attrib)(mem_attrib |
+					       SYS_MEMATTRIB_CORE_READ_ONLY |
+					       SYS_MEMATTRIB_CPU_WRITE),
+					       sizeof(unsigned short) * vlc_table.num_entries,
+					       DEV_MMU_PAGE_ALIGNMENT,
+					       &local_res_ctx->vlc_tables_bufinfo[i]);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				goto error;
+
+			if (vlc_table.data)
+				decres_pack_vlc_tables
+					(local_res_ctx->vlc_tables_bufinfo[i].cpu_virt,
+					 vlc_table.data,
+					 vlc_table.num_entries);
+
+			/* VLC index table */
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("%s:%d calling MMU_StreamMalloc",
+				__func__, __LINE__);
+#endif
+			ret = mmu_stream_alloc(mmu_handle,
+					       MMU_HEAP_STREAM_BUFFERS,
+					       mem_heap_id, (enum sys_emem_attrib)(mem_attrib |
+					       SYS_MEMATTRIB_CORE_READ_ONLY |
+					       SYS_MEMATTRIB_CPU_WRITE),
+					       vlc_idxtable_sz,
+					       DEV_MMU_PAGE_ALIGNMENT,
+					       &local_res_ctx->vlc_idxtables_bufinfo[i]);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				goto error;
+
+			if (vlc_table.index_table)
+				memcpy(local_res_ctx->vlc_idxtables_bufinfo[i].cpu_virt,
+				       vlc_table.index_table,
+				       local_res_ctx->vlc_idxtables_bufinfo[i].buf_size);
+		}
+	}
+
+	/* Start code */
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s:%d calling MMU_StreamMalloc", __func__, __LINE__);
+#endif
+	ret = mmu_stream_alloc(mmu_handle, MMU_HEAP_STREAM_BUFFERS, mem_heap_id,
+			       (enum sys_emem_attrib)(mem_attrib |
+			       SYS_MEMATTRIB_CORE_READ_ONLY |
+			       SYS_MEMATTRIB_CPU_WRITE),
+			       sizeof(start_code),
+			       DEV_MMU_PAGE_ALIGNMENT,
+			       &local_res_ctx->start_code_bufinfo);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		goto error;
+
+	memcpy(local_res_ctx->start_code_bufinfo.cpu_virt, start_code, sizeof(start_code));
+
+	for (i = 0; i < DECODER_RESTYPE_MAX; i++) {
+		unsigned int j;
+
+		ret = pool_api_create(&local_res_ctx->res_pool[i]);
+		VDEC_ASSERT(ret == IMG_SUCCESS);
+		if (ret != IMG_SUCCESS)
+			goto error;
+
+		lst_init(&local_res_ctx->pool_data_list[i]);
+
+		for (j = 0; j < num_dec_slots; j++) {
+			struct res_resinfo *local_res_info;
+
+			local_res_info = kzalloc(sizeof(*local_res_info), GFP_KERNEL);
+
+			VDEC_ASSERT(local_res_info);
+			if (!local_res_info) {
+				pr_err("Failed to allocate memory\n");
+				ret = IMG_ERROR_OUT_OF_MEMORY;
+				goto error_local_res_info_alloc;
+			}
+
+			local_res_info->ddbuf_info = kzalloc(sizeof(*local_res_info->ddbuf_info),
+							     GFP_KERNEL);
+			VDEC_ASSERT(local_res_info->ddbuf_info);
+			if (!local_res_info->ddbuf_info) {
+				pr_err("Failed to allocate memory for resource buffer information structure");
+				ret = IMG_ERROR_OUT_OF_MEMORY;
+				goto error_local_dd_buf_alloc;
+			}
+
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("%s:%d calling MMU_StreamMalloc", __func__, __LINE__);
+#endif
+			ret = mmu_stream_alloc(mmu_handle, MMU_HEAP_STREAM_BUFFERS,
+					       mem_heap_id, (enum sys_emem_attrib)(mem_attrib |
+					       SYS_MEMATTRIB_CPU_READ |
+					       SYS_MEMATTRIB_CPU_WRITE),
+					       res_size[i],
+					       DEV_MMU_PAGE_ALIGNMENT,
+					       local_res_info->ddbuf_info);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				goto error_local_res_alloc;
+
+			/* Register with the buffer pool */
+			ret = pool_resreg(local_res_ctx->res_pool[i],
+					  decres_fnbuf_info_destructor,
+					  local_res_info->ddbuf_info,
+					  sizeof(*local_res_info->ddbuf_info),
+					  FALSE, NULL,
+					  &local_res_info->res, mmu_handle);
+			VDEC_ASSERT(ret == IMG_SUCCESS);
+			if (ret != IMG_SUCCESS)
+				goto error_local_res_register;
+
+			lst_add(&local_res_ctx->pool_data_list[i],
+				local_res_info);
+			continue;
+
+/* Roll back in case of local errors. */
+error_local_res_register: mmu_free_mem(mmu_handle, local_res_info->ddbuf_info);
+
+error_local_res_alloc:  kfree(local_res_info->ddbuf_info);
+
+error_local_dd_buf_alloc: kfree(local_res_info);
+
+error_local_res_info_alloc: goto error;
+		}
+	}
+
+	*resources = (void *)local_res_ctx;
+
+	return IMG_SUCCESS;
+
+/* Roll back in case of errors. */
+error:  dec_res_destroy(mmu_handle, (void *)local_res_ctx);
+
+	return ret;
+}
+
+/*
+ *@Function RESOURCES_Destroy
+ *
+ */
+int dec_res_destroy(void *mmudev_handle, void *res_ctx)
+{
+	int ret = IMG_SUCCESS;
+	int ret1 = IMG_SUCCESS;
+	unsigned int i = 0;
+	struct res_resinfo *local_res_info;
+	struct res_resinfo *next_res_info;
+
+	struct dec_res_ctx *local_res_ctx = (struct dec_res_ctx *)res_ctx;
+
+	if (!local_res_ctx) {
+		pr_err("Invalid parameters");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (local_res_ctx->intra_bufinfo.hndl_memory) {
+		ret1 = mmu_free_mem(mmudev_handle, &local_res_ctx->intra_bufinfo);
+		VDEC_ASSERT(ret1 == IMG_SUCCESS);
+		if (ret1 != IMG_SUCCESS)
+			ret = ret1;
+	}
+
+	if (local_res_ctx->auxline_bufinfo.hndl_memory) {
+		ret1 = mmu_free_mem(mmudev_handle, &local_res_ctx->auxline_bufinfo);
+		VDEC_ASSERT(ret1 == IMG_SUCCESS);
+		if (ret1 != IMG_SUCCESS)
+			ret = ret1;
+	}
+
+	for (i = 0; i < VDEC_STD_MAX; i++) {
+		if (local_res_ctx->vlc_tables_bufinfo[i].hndl_memory) {
+			ret1 = mmu_free_mem(mmudev_handle, &local_res_ctx->vlc_tables_bufinfo[i]);
+			VDEC_ASSERT(ret1 == IMG_SUCCESS);
+			if (ret1 != IMG_SUCCESS)
+				ret = ret1;
+		}
+
+		if (local_res_ctx->vlc_idxtables_bufinfo[i].hndl_memory) {
+			ret1 = mmu_free_mem(mmudev_handle,
+					    &local_res_ctx->vlc_idxtables_bufinfo[i]);
+			VDEC_ASSERT(ret1 == IMG_SUCCESS);
+			if (ret1 != IMG_SUCCESS)
+				ret = ret1;
+		}
+	}
+
+	if (local_res_ctx->start_code_bufinfo.hndl_memory) {
+		ret1 = mmu_free_mem(mmudev_handle, &local_res_ctx->start_code_bufinfo);
+		VDEC_ASSERT(ret1 == IMG_SUCCESS);
+		if (ret1 != IMG_SUCCESS)
+			ret = ret1;
+	}
+
+	for (i = 0; i < DECODER_RESTYPE_MAX; i++) {
+		if (local_res_ctx->res_pool[i]) {
+			local_res_info =
+				lst_first(&local_res_ctx->pool_data_list[i]);
+			while (local_res_info) {
+				next_res_info = lst_next(local_res_info);
+				lst_remove(&local_res_ctx->pool_data_list[i], local_res_info);
+				ret1 = pool_resdestroy(local_res_info->res, TRUE);
+				VDEC_ASSERT(ret1 == IMG_SUCCESS);
+				if (ret1 != IMG_SUCCESS)
+					ret = ret1;
+				kfree(local_res_info);
+				local_res_info = next_res_info;
+			}
+			pool_destroy(local_res_ctx->res_pool[i]);
+		}
+	}
+
+	kfree(local_res_ctx);
+	return ret;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/dec_resources.h b/drivers/media/platform/img/vxe-vxd/decoder/dec_resources.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/dec_resources.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/dec_resources.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD Decoder resource allocation and destroy Interface header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *      Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _DEC_RESOURCES_H_
+#define _DEC_RESOURCES_H_
+
+#include "decoder.h"
+#include "lst.h"
+
+/*
+ * This structure contains the core resources.
+ * @brief  Decoder Core Resources
+ */
+struct dec_res_ctx {
+	struct vidio_ddbufinfo intra_bufinfo;
+	struct vidio_ddbufinfo auxline_bufinfo;
+	struct vidio_ddbufinfo start_code_bufinfo;
+	struct vidio_ddbufinfo vlc_tables_bufinfo[VDEC_STD_MAX];
+	struct vidio_ddbufinfo vlc_idxtables_bufinfo[VDEC_STD_MAX];
+	void *res_pool[DECODER_RESTYPE_MAX];
+	struct lst_t pool_data_list[DECODER_RESTYPE_MAX];
+};
+
+int dec_res_picture_detach(void **res_ctx, struct dec_decpict *dec_pict);
+
+int dec_res_picture_attach(void **res_ctx, enum vdec_vid_std vid_std,
+			   struct dec_decpict *dec_pict);
+
+int dec_res_create(void *mmudev_handle,
+		   struct vxd_coreprops *core_props, unsigned int num_dec_slots,
+		   unsigned int mem_heap_id, void **resources);
+
+int dec_res_destroy(void *mmudev_handle, void *res_ctx);
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/fw_interface.h b/drivers/media/platform/img/vxe-vxd/decoder/fw_interface.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/fw_interface.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/fw_interface.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,818 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG MSVDX core Registers
+ * This file contains the MSVDX_CORE_REGS_H Definitions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef FW_INTERFACE_H_
+#define FW_INTERFACE_H_
+
+/* TODO For now this macro defined, need to think and enable */
+#define VDEC_USE_PVDEC_COMPATIBILITY    1
+
+#define MSG_TYPE_PADDING                                (0x00)
+/* Start of parser specific Host->MTX messages */
+#define MSG_TYPE_START_PSR_HOSTMTX_MSG  (0x80)
+/* Start of parser specific MTX->Host message */
+#define MSG_TYPE_START_PSR_MTXHOST_MSG  (0xC0)
+
+enum {
+	FW_DEVA_INIT = MSG_TYPE_START_PSR_HOSTMTX_MSG,
+	FW_DEVA_DECODE_FE,
+	FW_DEVA_RES_0,
+	FW_DEVA_RES_1,
+	FW_DEVA_DECODE_BE,
+	FW_DEVA_HOST_BE_OPP,
+	FW_DEVA_DEBLOCK,
+	FW_DEVA_INTRA_OOLD,
+	FW_DEVA_ENDFRAME,
+
+	FW_DEVA_PARSE,
+	FW_DEVA_PARSE_FRAGMENT,
+	FW_DEVA_BEGINFRAME,
+
+#ifdef VDEC_USE_PVDEC_COMPATIBILITY
+#ifdef VDEC_USE_PVDEC_SEC
+	FWBSP_INIT,
+	FWBSP_PARSE_BITSTREAM,
+	FWDEC_DECODE,
+#endif /* VDEC_USE_PVDEC_SEC */
+#endif /* VDEC_USE_PVDEC_COMPATIBILITY */
+
+	/* Sent by the firmware on the MTX to the host. */
+	FW_DEVA_COMPLETED = MSG_TYPE_START_PSR_MTXHOST_MSG,
+#ifndef VDEC_USE_PVDEC_COMPATIBILITY
+	FW_DEVA_RES_2,
+	FW_DEVA_RES_3,
+	FW_DEVA_RES_4,
+	FW_DEVA_RES_5,
+
+	FW_DEVA_RES_6,
+	FW_DEVA_CONTIGUITY_WARNING,
+	FW_DEVA_PANIC,
+	FW_DEVA_RES_7,
+	FW_DEVA_RES_8,
+#else   /* ndef VDEC_USE_PVDEC_COMPATIBILITY */
+	FW_DEVA_PANIC,
+	FW_ASSERT,
+	FW_PERF,
+	/* An empty completion message sent by new vxd driver */
+	FW_VXD_EMPTY_COMPL,
+	FW_DEC_REQ_RECEIVED,
+	FW_SO,
+#ifdef VDEC_USE_PVDEC_SEC
+	FWBSP_NEW_SEQ,
+	FWBSP_NEW_PIC,
+	FWBSP_BUF_EMPTY,
+	FWBSP_ERROR,
+	FWDEC_COMPLETED,
+#endif /* VDEC_USE_PVDEC_SEC */
+#endif /* VDEC_USE_PVDEC_COMPATIBILITY */
+	FW_DEVA_SIGNATURES_LEGACY      = 0xD0,
+	FW_DEVA_SIGNATURES_HEVC        = 0xE0,
+	FW_DEVA_SIGNATURES_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Defines the Host/Firmware communication area */
+#ifndef VDEC_USE_PVDEC_COMPATIBILITY
+#define COMMS_HEADER_SIZE               (0x34)
+#else /* def VDEC_USE_PVDEC_COMPATIBILITY */
+#define COMMS_HEADER_SIZE       (0x40)
+#endif /* def VDEC_USE_PVDEC_COMPATIBILITY */
+/* dwords */
+#define PVDEC_COM_RAM_FW_STATUS_OFFSET                          0x00
+#define PVDEC_COM_RAM_TASK_STATUS_OFFSET                        0x04
+#define PVDEC_COM_RAM_FW_ID_OFFSET                              0x08
+#define PVDEC_COM_RAM_FW_MTXPC_OFFSET                           0x0c
+#define PVDEC_COM_RAM_MSG_COUNTER_OFFSET                        0x10
+#define PVDEC_COM_RAM_SIGNATURE_OFFSET                          0x14
+#define PVDEC_COM_RAM_TO_HOST_BUF_SIZE_AND_OFFSET_OFFSET        0x18
+#define PVDEC_COM_RAM_TO_HOST_RD_INDEX_OFFSET                   0x1c
+#define PVDEC_COM_RAM_TO_HOST_WRT_INDEX_OFFSET                  0x20
+#define PVDEC_COM_RAM_TO_MTX_BUF_SIZE_AND_OFFSET_OFFSET         0x24
+#define PVDEC_COM_RAM_TO_MTX_RD_INDEX_OFFSET                    0x28
+#define PVDEC_COM_RAM_FLAGS_OFFSET                              0x2c
+#define PVDEC_COM_RAM_TO_MTX_WRT_INDEX_OFFSET                   0x30
+#ifdef VDEC_USE_PVDEC_COMPATIBILITY
+#define PVDEC_COM_RAM_STATE_BUF_SIZE_AND_OFFSET_OFFSET          0x34
+#define PVDEC_COM_RAM_FW_MMU_REPORT_OFFSET                      0x38
+#endif /* VDEC_USE_PVDEC_COMPATIBILITY */
+/* fields */
+#define PVDEC_COM_RAM_TO_HOST_BUF_SIZE_AND_OFFSET_SIZE_MASK     0xFFFF
+#define PVDEC_COM_RAM_TO_HOST_BUF_SIZE_AND_OFFSET_SIZE_SHIFT    0
+#define PVDEC_COM_RAM_TO_HOST_BUF_SIZE_AND_OFFSET_OFFSET_MASK   0xFFFF0000
+#define PVDEC_COM_RAM_TO_HOST_BUF_SIZE_AND_OFFSET_OFFSET_SHIFT  16
+
+#define PVDEC_COM_RAM_TO_MTX_BUF_SIZE_AND_OFFSET_SIZE_MASK      0xFFFF
+#define PVDEC_COM_RAM_TO_MTX_BUF_SIZE_AND_OFFSET_SIZE_SHIFT     0
+#define PVDEC_COM_RAM_TO_MTX_BUF_SIZE_AND_OFFSET_OFFSET_MASK    0xFFFF0000
+#define PVDEC_COM_RAM_TO_MTX_BUF_SIZE_AND_OFFSET_OFFSET_SHIFT   16
+#ifdef VDEC_USE_PVDEC_COMPATIBILITY
+#define PVDEC_COM_RAM_STATE_BUF_SIZE_AND_OFFSET_SIZE_MASK       0xFFFF
+#define PVDEC_COM_RAM_STATE_BUF_SIZE_AND_OFFSET_SIZE_SHIFT      0
+#define PVDEC_COM_RAM_STATE_BUF_SIZE_AND_OFFSET_OFFSET_MASK     0xFFFF0000
+#define PVDEC_COM_RAM_STATE_BUF_SIZE_AND_OFFSET_OFFSET_SHIFT    16
+#endif /* VDEC_USE_PVDEC_COMPATIBILITY */
+#define PVDEC_COM_RAM_BUF_GET_SIZE(_reg_, _name_) \
+	(((_reg_) & PVDEC_COM_RAM_ ## _name_ ## _BUF_SIZE_AND_OFFSET_SIZE_MASK) >> \
+	 PVDEC_COM_RAM_ ## _name_ ## _BUF_SIZE_AND_OFFSET_SIZE_SHIFT)
+#define PVDEC_COM_RAM_BUF_GET_OFFSET(_reg_, _name_) \
+	(((_reg_) & \
+	  PVDEC_COM_RAM_ ## _name_ ## _BUF_SIZE_AND_OFFSET_OFFSET_MASK) >> \
+	 PVDEC_COM_RAM_ ## _name_ ## _BUF_SIZE_AND_OFFSET_OFFSET_SHIFT)
+#define PVDEC_COM_RAM_BUF_SET_SIZE_AND_OFFSET(_name_, _size_, _offset_) \
+	((((_size_) << \
+		PVDEC_COM_RAM_ ## _name_ ## _BUF_SIZE_AND_OFFSET_SIZE_SHIFT) \
+	  & PVDEC_COM_RAM_ ## _name_ ## _BUF_SIZE_AND_OFFSET_SIZE_MASK) | \
+	 (((_offset_) << \
+		PVDEC_COM_RAM_ ## _name_ ## _BUF_SIZE_AND_OFFSET_OFFSET_SHIFT) \
+	  & PVDEC_COM_RAM_ ## _name_ ## _BUF_SIZE_AND_OFFSET_OFFSET_MASK))
+/* values */
+/* Firmware ready signature value */
+	#define FW_READY_SIGNATURE                              (0xA5A5A5A5)
+
+/* Firmware status values */
+	#define FW_STATUS_BUSY                                  0
+	#define FW_STATUS_IDLE                                  1
+	#define FW_STATUS_PANIC                                 2
+	#define FW_STATUS_ASSERT                                3
+	#define FW_STATUS_GAMEOVER                              4
+	#define FW_STATUS_FEWATCHDOG                            5
+	#define FW_STATUS_EPWATCHDOG                            6
+	#define FW_STATUS_BEWATCHDOG                            7
+#ifdef VDEC_USE_PVDEC_COMPATIBILITY
+	#define FW_STATUS_SO                                    8
+	#define FW_STATUS_INIT                                  0xF
+#endif
+
+/* Decode Message Flags */
+	#define FW_DEVA_RENDER_IS_FIRST_SLICE                   (0x00000001)
+/* This is H264 Mbaff - required for state store */
+	#define FW_DEVA_FORCE_RECON_WRITE_DISABLE               (0x00000002)
+	#define FW_DEVA_RENDER_IS_LAST_SLICE                    (0x00000004)
+/* Prevents insertion of end of picture or flush at VEC EOS */
+	#define FW_DEVA_DECODE_DISABLE_EOF_DETECTION            (0x00000008)
+
+	#define FW_DEVA_CONTEXT_BUFFER_INVALID                  (0x00000010)
+	#define FW_DEVA_FORCE_ALT_OUTPUT                        (0x00000020)
+	#define FW_SECURE_STREAM                                (0x00000040)
+	#define FW_LOW_LATENCY                                  (0x00000080)
+
+	#define FW_DEVA_CONTIGUITY_DETECTION                    (0x00000100)
+	#define FW_DEVA_FORCE_INIT_CMDS                         (0x00000200)
+	#define FW_DEVA_DEBLOCK_ENABLE                          (0x00000400)
+#ifdef VDEC_USE_PVDEC_COMPATIBILITY
+	#define FW_VDEC_SEND_SIGNATURES                         (0x00000800)
+#else
+/*							(0x00000800) */
+#endif /* VDEC_USE_PVDEC_COMPATIBILITY */
+
+	#define FW_DEVA_FORCE_AUX_LINE_BUF_DISABLE              (0x00001000)
+/*
+ * Cause no response message to be sent, and no interrupt
+ * generation on successful completion
+ */
+	#define FW_DEVA_RENDER_NO_RESPONSE_MSG                  (0x00002000)
+/*
+ * Cause an interrupt if a response message is generated
+ * on successful completion
+ */
+	#define FW_DEVA_RENDER_HOST_INT                         (0x00004000)
+/* Report contiguity errors to host */
+	#define FW_DEVA_CONTIGUITY_REPORTING                    (0x00008000)
+
+	#define FW_DEVA_VC1_SKIPPED_PICTURE                     (0x00010000)
+	#define FW_INTERNAL_RENDER_SWITCH                       (0x00020000)
+	#define FW_DEVA_UNSUPPORTED                             (0x00040000)
+	#define DEBLOCKING_FORCED_OFF                           (0x00080000)
+#ifdef VDEC_USE_PVDEC_COMPATIBILITY
+	#define FW_VDEC_CMD_PENDING                             (0x00100000)
+#else
+/*							(0x00100000) */
+#endif
+/* Only for debug */
+	#define DETECTED_RENDEC_FULL                            (0x00200000)
+/* Only for debug */
+	#define DETECTED_RENDEC_EMPTY                           (0x00400000)
+	#define FW_ONE_PASS_PARSE                               (0x00800000)
+
+	#define FW_DEVA_EARLY_COMPLETE                          (0x01000000)
+	#define FW_DEVA_FE_EP_SIGNATURES_READY                  (0x02000000)
+	#define FW_VEC_EOS                                      (0x04000000)
+/* hardware has reported an error relating to this command */
+	#define FW_DEVA_ERROR_DETECTED_ENT                      (0x08000000)
+
+	#define FW_DEVA_ERROR_DETECTED_PIX                      (0x10000000)
+	#define FW_DEVA_MP_SYNC                                 (0x20000000)
+	#define MORE_THAN_ONE_MB                                (0x40000000)
+	#define REATTEMPT_SINGLEPIPE                            (0x80000000)
+/* end of message flags */
+#ifdef VDEC_USE_PVDEC_COMPATIBILITY
+/* VDEC Decode Message Flags */
+/*
+ * H.264/H.265 are to be configured in SIZE_DELIMITED mode rather than SCP mode.
+ */
+#define FW_VDEC_NAL_SIZE_DELIM                  (0x00000001)
+/* Indicates if MMU cache shall be flushed. */
+#define FW_VDEC_MMU_FLUSH_CACHE                 (0x00000002)
+/* end of message flags */
+#endif /* VDEC_USE_PVDEC_COMPATIBILITY */
+
+/* FW flags */
+/* TODO : Temporary for HW testing */
+	#define FWFLAG_DISABLE_VDEB_PRELOAD             (0x00000001)
+	#define FWFLAG_BIG_TO_HOST_BUFFER               (0x00000002)
+/* FS is default regarless of this flag */
+	#define FWFLAG_FORCE_FS_FLOW                    (0x00000004)
+	#define FWFLAG_DISABLE_WATCHDOG_TIMERS          (0x00000008)
+
+	#define FWFLAG_DISABLE_AEH                      (0x00000020)
+	#define FWFLAG_DISABLE_AUTONOMOUS_RESET         (0x00000040)
+	#define FWFLAG_NON_ACCUMULATING_HWSIGS          (0x00000080)
+
+	#define FWFLAG_DISABLE_2PASS_DEBLOCK            (0x00000100)
+	#define FWFLAG_NO_INT_ON_TOHOST_FULL            (0x00000200)
+	#define FWFLAG_RETURN_VDEB_CR                   (0x00000800)
+
+	#define FWFLAG_DISABLE_AUTOCLOCKGATING          (0x00001000)
+	#define FWFLAG_DISABLE_IDLE_GPIO                (0x00002000)
+	#define FWFLAG_XPL                              (0x00004000)
+	#define FWFLAG_INFINITE_MTX_TIMEOUT             (0x00008000)
+
+	#define FWFLAG_DECOUPLE_BE_FE                   (0x00010000)
+	#define FWFLAG_ENABLE_SECURITY                  (0x00080000)
+
+	#define FWFLAG_ENABLE_CONCEALMENT               (0x00100000)
+/* Not currently supported */
+/*	#define	FWFLAG_PREEMPT				(0x00200000) */
+/* NA in FS */
+	#define FWFLAG_FORCE_FLUSHING                   (0x00400000)
+/* NA in FS */
+	#define FWFLAG_DISABLE_GENC_FLUSHING            (0x00800000)
+
+	#define FWFLAG_DISABLE_COREWDT_TIMERS           (0x01000000)
+	#define FWFLAG_DISABLE_RENDEC_AUTOFLUSH         (0x02000000)
+	#define FWFLAG_FORCE_STRICT_SINGLEPIPE          (0x04000000)
+	#define FWFLAG_CONSISTENT_MULTIPIPE_FLOW        (0x08000000)
+
+	#define FWFLAG_DISABLE_IDLE_FAST_EVAL           (0x10000000)
+	#define FWFLAG_FAKE_COMPLETION                  (0x20000000)
+	#define FWFLAG_MAN_PP_CLK                       (0x40000000)
+	#define FWFLAG_STACK_CHK                        (0x80000000)
+
+/* end of FW flags */
+
+#ifdef FW_STACK_USAGE_TRACKING
+/* FW task identifiers */
+enum task_id {
+	TASK_ID_RX = 0,
+	TASK_ID_TX,
+	TASK_ID_EP1,
+	TASK_ID_FE1,
+	TASK_ID_FE2,
+	TASK_ID_FE3,
+	TASK_ID_BE1,
+	TASK_ID_BE2,
+	TASK_ID_BE3,
+	TASK_ID_PARSER,
+	TASK_ID_MAX,
+	TASK_ID_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* FW task stack info utility macros */
+#define TASK_STACK_SIZE_MASK   0xFFFF
+#define TASK_STACK_SIZE_SHIFT  0
+#define TASK_STACK_USED_MASK   0xFFFF0000
+#define TASK_STACK_USED_SHIFT  16
+#define TASK_STACK_SET_INFO(_task_id_, _stack_info_, _size_, _used_) \
+	(_stack_info_[_task_id_] = \
+		 ((_size_) << TASK_STACK_SIZE_SHIFT) | \
+		 ((_used_) << TASK_STACK_USED_SHIFT))
+#define TASK_STACK_GET_SIZE(_task_id_, _stack_info_) \
+	((_stack_info_[_task_id_] & TASK_STACK_SIZE_MASK) >> \
+	 TASK_STACK_SIZE_SHIFT)
+#define TASK_STACK_GET_USED(_task_id_, _stack_info_) \
+	((_stack_info_[_task_id_] & TASK_STACK_USED_MASK) >> \
+	 TASK_STACK_USED_SHIFT)
+#endif /* FW_STACK_USAGE_TRACKING */
+
+/* Control Allocation */
+#define CMD_MASK                                (0xF0000000)
+
+/* Ctrl Allocation Header */
+#define CMD_CTRL_ALLOC_HEADER                   (0x90000000)
+
+struct ctrl_alloc_header {
+	unsigned int cmd_additional_params;
+	unsigned int slice_params;
+	union {
+		unsigned int vp8_probability_data;
+		unsigned int h264_pipeintra_buffersize;
+	};
+	unsigned int chroma_strides;
+	unsigned int slice_first_mb_yx;
+	unsigned int pic_last_mb_yx;
+	/* VC1 only : Store Range Map flags in bottom bits of [0] */
+	unsigned int alt_output_addr[2];
+	unsigned int alt_output_flags;
+	/* H264 Only : Extended Operating Mode */
+	unsigned int ext_opmode;
+};
+
+#define CMD_CTRL_ALLOC_HEADER_DWSIZE \
+	(sizeof(struct ctrl_alloc_header) / sizeof(unsigned int))
+
+/* Additional Parameter flags */
+#define VC1_PARSEHDR_MASK               (0x00000001)
+#define VC1_SKIPPIC_MASK                (0x00000002)
+
+#define VP6_BUFFOFFSET_MASK             (0x0000ffff)
+#define VP6_MULTISTREAM_MASK            (0x01000000)
+#define VP6_FRAMETYPE_MASK              (0x02000000)
+
+#define VP8_BUFFOFFSET_MASK             (0x00ffffff)
+#define VP8_PARTITIONSCOUNT_MASK        (0x0f000000)
+#define VP8_PARTITIONSCOUNT_SHIFT       (24)
+
+/* Nop Command */
+#define CMD_NOP                         (0x00000000)
+#define CMD_NOP_DWSIZE                  (1)
+
+/* Register Block */
+#define CMD_REGISTER_BLOCK                      (0x10000000)
+#define CMD_REGISTER_BLOCK_PATCHING_REQUIRED    (0x01000000)
+#define CMD_REGISTER_BLOCK_FLAG_PRELOAD         (0x04000000)
+#define CMD_REGISTER_BLOCK_FLAG_VLC_DATA        (0x08000000)
+
+/* Rendec Command */
+#define CMD_RENDEC_BLOCK                        (0x50000000)
+#define CMD_RENDEC_BLOCK_FLAG_MASK              (0x0F000000)
+#define CMD_RENDEC_FORCE                        (0x08000000)
+#define CMD_RENDEC_PATCHING_REQUIRED            (0x01000000)
+#define CMD_RENDEC_WORD_COUNT_MASK              (0x00ff0000)
+#define CMD_RENDEC_WORD_COUNT_SHIFT             (16)
+#define CMD_RENDEC_ADDRESS_MASK                 (0x0000ffff)
+#define CMD_RENDEC_ADDRESS_SHIFT                (0)
+
+#ifndef VDEC_USE_PVDEC_SEC
+/* Deblock */
+#define CMD_DEBLOCK                             (0x70000000)
+#define CMD_DEBLOCK_TYPE_STD                    (0x00000000)
+#define CMD_DEBLOCK_TYPE_OOLD                   (0x00000001)
+#define CMD_DEBLOCK_TYPE_SKIP                   (0x00000002)
+/* End Of Frame */
+#define CMD_DEBLOCK_TYPE_EF                     (0x00000003)
+
+struct deblock_cmd {
+	unsigned int cmd; /* 0x70000000 */
+	unsigned int source_mb_data;
+	unsigned int address_a[2];
+};
+
+#define CMD_DEBLOCK_DWSIZE              (sizeof(DEBLOCK_CMD) / sizeof(unsigned int))
+#endif /* !VDEC_USE_PVDEC_SEC */
+
+/* Skip */
+#define CMD_CONDITIONAL_SKIP                    (0x80000000)
+#define CMD_CONDITIONAL_SKIP_DWSIZE             (1)
+#define CMD_CONDITIONAL_SKIP_DWORDS             (0x0000ffff)
+#define CMD_CONDITIONAL_SKIP_CONTEXT_SWITCH     BIT(20)
+
+/* DMA */
+#define CMD_DMA                                 (0xE0000000)
+#define CMD_DMA_DMA_TYPE_MASK                   (0x03000000)
+#define CMD_DMA_DMA_TYPE_SHIFT                  (24)
+#define CMD_DMA_FLAG_MASK                       (0x00100000)
+#define CMD_DMA_FLAG_SHIFT                      (20)
+#define CMD_DMA_DMA_SIZE_MASK                   (0x000fffff)
+
+#define CMD_DMA_OFFSET_FLAG                     (0x00100000)
+
+#define CMD_DMA_MAX_OFFSET                      (0xFFF)
+#define CMD_DMA_TYPE_VLC_TABLE                  (0 << CMD_DMA_DMA_TYPE_SHIFT)
+#define CMD_DMA_TYPE_PROBABILITY_DATA           BIT(CMD_DMA_DMA_TYPE_SHIFT)
+
+struct dma_cmd {
+	unsigned int cmd;
+	unsigned int dev_virt_add;
+};
+
+#define CMD_DMA_DWSIZE                          (sizeof(DMA_CMD) / sizeof(unsigned int))
+
+struct dma_cmd_offset_dwsize {
+	unsigned int cmd;
+	unsigned int dev_virt_add;
+	unsigned int byte_offset;
+};
+
+#define CMD_DMA_OFFSET_DWSIZE   (sizeof(DMA_CMD_WITH_OFFSET) / sizeof(unsigned int))
+
+/* HOST COPY */
+#define CMD_HOST_COPY                           (0xF0000000)
+#define CMD_HOST_COPY_SIZE_MASK                 (0x000fffff)
+
+struct host_copy_cmd {
+	unsigned int cmd;
+	unsigned int src_dev_virt_add;
+	unsigned int dst_dev_virt_add;
+};
+
+#define CMD_HOST_COPY_DWSIZE            (sizeof(HOST_COPY_CMD) / sizeof(unsigned int))
+
+/* Shift register setup and Bitstream DMA */
+#define CMD_SR_SETUP                            (0xB0000000)
+#define CMD_SR_ENABLE_RBDU_EXTRACTION           (0x00000001)
+#define CMD_SR_ENABLE_AES_COUNTER               (0x00000002)
+#define CMD_SR_VERIFY_STARTCODE                 (0x00000004)
+#define CMD_SR_BITSTR_ADDR_DEREF                (0x00000008)
+#define CMD_SR_BITSTR_PARSE_KEY                 (0x00000010)
+
+struct sr_setup_cmd {
+	unsigned int cmd;
+	unsigned int bitstream_offset_bits;
+	unsigned int bitstream_size_bytes;
+};
+
+#define CMD_SR_DWSIZE                   (sizeof(SR_SETUP_CMD) / sizeof(unsigned int))
+
+#define CMD_BITSTREAM_DMA                       (0xA0000000)
+#define CMD_BITSTREAM_DMA_DWSIZE                (2)
+/* VC1 Parse Header Command */
+#define CMD_PARSE_HEADER                        (0x30000000)
+#define CMD_PARSE_HEADER_CONTEXT_MASK           (0x000000ff)
+#define CMD_PARSE_HEADER_NEWSLICE               (0x00000001)
+#define CMD_PARSE_HEADER_SKIP_PIC               (0x00000002)
+#define CMD_PARSE_HEADER_ONEPASSPARSE           (0x00000004)
+#define CMD_PARSE_HEADER_NUMSLICE_MINUS1        (0x00ffff00)
+
+struct parse_header_cmd {
+	unsigned int cmd;
+	unsigned int seq_hdr_data;
+	unsigned int pic_dimensions;
+	unsigned int bitplane_addr[3];
+	unsigned int vlc_table_addr;
+};
+
+#define CMD_PARSE_DWSIZE                (sizeof(PARSE_HEADER_CMD) / sizeof(unsigned int))
+
+#define CMD_SLICE_INFO                          (0x20000000)
+#define CMD_SLICE_INFO_SLICENUM                 (0xff000000)
+#define CMD_SLICE_INFO_FIRSTMBY                 (0x00ff0000)
+#define CMD_SLICE_INFO_MBBITOFFSET              (0x0000ffff)
+
+struct slice_info {
+	unsigned char slice_num;
+	unsigned char slice_first_mby;
+	unsigned short slice_mb_bitoffset;
+};
+
+#ifdef VDEC_USE_PVDEC_COMPATIBILITY
+/* VDEC extension */
+#define CMD_VDEC_EXT                            (0xC0000000)
+#ifdef VDEC_USE_PVDEC_SEC
+/*
+ * Used only between firmware secure modules FWBSP->FWDEC,
+ * thus the structure is defined in firmware structures.h
+ */
+#define CMD_VDEC_SECURE_EXT                     (0x40000000)
+#endif/* VDEC_USE_PVDEC_SEC */
+
+#define MEM2REG_SIZE_HOST_PART_MASK 0x0000FFFF
+#define MEM2REG_SIZE_HOST_PART_SHIFT 0
+
+#define MEM2REG_SIZE_BUF_TOTAL_MASK 0xFFFF0000
+#define MEM2REG_SIZE_BUF_TOTAL_SHIFT 16
+
+struct vdec_ext_cmd {
+	unsigned int cmd;
+	unsigned int trans_id;
+	unsigned int hdr_addr;
+	unsigned int hdr_size;
+	unsigned int ctx_save_addr;
+	unsigned int ctx_load_addr;
+	unsigned int buf_ctrl_addr;
+	unsigned int seq_addr;
+	unsigned int pps_addr;
+	unsigned int pps_2addr;
+	unsigned int mem_to_reg_addr;
+	/* 31-16: buff size, 15-0: size filled by host; dwords */
+	unsigned int mem_to_reg_size;
+	unsigned int slice_params_addr;
+	unsigned int slice_params_size;  /* dwords */
+	unsigned int last_luma_recon;
+	unsigned int last_chroma_recon;
+	unsigned int luma_err_base;
+	unsigned int chroma_err_base;
+	unsigned int scaled_display_size;
+	unsigned int horz_scale_control;
+	unsigned int vert_scale_control;
+	unsigned int scale_output_size;
+	unsigned int vlc_idx_table_size;
+	unsigned int vlc_idx_table_addr;
+	unsigned int vlc_tables_size;
+	unsigned int vlc_tables_addr;
+	unsigned int display_picture_size;
+	unsigned int parser_mode;
+	/* needed for separate colour planes */
+	unsigned int intra_buf_base_addr;
+	unsigned int intra_buf_size_per_plane;
+	unsigned int intra_buf_size_per_pipe;
+	unsigned int chroma2reconstructed_addr;
+	unsigned int luma_alt_addr;
+	unsigned int chroma_alt_addr;
+	unsigned int chroma2alt_addr;
+	unsigned int aux_line_buf_size_per_pipe;
+	unsigned int aux_line_buffer_base_addr;
+	unsigned int alt_output_pict_rotation;
+	/* miscellaneous flags */
+	struct {
+		unsigned is_chromainterleaved   : 1;
+		unsigned is_packedformat        : 1;
+		unsigned is_discontinuousmbs    : 1;
+	};
+};
+
+#define CMD_VDEC_EXT_DWSIZE             (sizeof(VDEC_EXT_CMD) / sizeof(unsigned int))
+#endif /* VDEC_USE_PVDEC_COMPATIBILITY */
+
+/* Completion */
+#define CMD_COMPLETION                          (0x60000000)
+#define CMD_COMPLETION_DWSIZE                   (1)
+
+#ifdef VDEC_USE_PVDEC_SEC
+/* Slice done */
+#define CMD_SLICE_DONE                          (0x70000000)
+#define CMD_SLICE_DONE_DWSIZE                   (1)
+#endif /* VDEC_USE_PVDEC_SEC */
+
+/* Bitstream segments */
+#define CMD_BITSTREAM_SEGMENTS                  (0xD0000000)
+#define CMD_BITSTREAM_SEGMENTS_MINUS1_MASK      (0x0000001F)
+#define CMD_BITSTREAM_PARSE_BLK_MASK            (0x0000FF00)
+#ifdef VDEC_USE_PVDEC_COMPATIBILITY
+#define CMD_BITSTREAM_SEGMENTS_MORE_FOLLOW_MASK (0x00000020)
+#define CMD_BITSTREAM_EOP_MASK                  (0x00000040)
+#define CMD_BITSTREAM_BS_TOT_SIZE_WORD_OFFSET   (1)
+#define CMD_BITSTREAM_BS_SEG_LIST_WORD_OFFSET   (2)
+#define CMD_BITSTREAM_HDR_DW_SIZE       CMD_BITSTREAM_BS_SEG_LIST_WORD_OFFSET
+
+#define CMD_BITSTREAM_SEGMENTS_MAX_NUM          (60)
+#endif /* VDEC_USE_PVDEC_COMPATIBILITY */
+
+#ifdef VDEC_USE_PVDEC_COMPATIBILITY
+/* Signatures */
+/* Signature set ids (see hwSignatureModules.c for exact order). */
+/* -- FRONT END/ENTROPY_PIPE ----------------------------------- */
+/*
+ * Signature group 0:
+ * REG(PVDEC_ENTROPY, CR_SR_SIGNATURE)
+ * REG(MSVDX_VEC,     CR_SR_CRC)
+ */
+#define PVDEC_SIGNATURE_GROUP_0  BIT(0)
+/*
+ * Signature group 1:
+ * REG(PVDEC_ENTROPY, CR_HEVC_PARSER_SIGNATURE)
+ * REG(PVDEC_ENTROPY, CR_ENCAP_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_1  BIT(1)
+/*
+ * Signature group 2:
+ * REG(PVDEC_ENTROPY, CR_GENC_ENGINE_OUTPUT_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_2  BIT(2)
+/*
+ * Signature group 3:
+ * REGREP(PVDEC_ENTROPY, CR_GENC_BUFFER_SIGNATURE, 0)
+ * REGREP(PVDEC_ENTROPY, CR_GENC_BUFFER_SIGNATURE, 1)
+ * REGREP(PVDEC_ENTROPY, CR_GENC_BUFFER_SIGNATURE, 2)
+ * REGREP(PVDEC_ENTROPY, CR_GENC_BUFFER_SIGNATURE, 3)
+ * REG(   PVDEC_ENTROPY, CR_GENC_FRAGMENT_SIGNATURE)
+ * REG(   PVDEC_ENTROPY, CR_GENC_FRAGMENT_READ_SIGNATURE)
+ * REG(   PVDEC_ENTROPY, CR_GENC_FRAGMENT_WRADDR_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_3  BIT(3)
+/* -- GENC_DEC -------------------------------------------------- */
+/*
+ * Signature group 4:
+ * REG(   PVDEC_VEC_BE, CR_GDEC_FRAGMENT_REQ_SIGNATURE)
+ * REG(   PVDEC_VEC_BE, CR_GDEC_SYS_WR_SIGNATURE)
+ * REG(   PVDEC_VEC_BE, CR_GDEC_MEM2REG_SYS_WR_SIGNATURE)
+ * REG(   PVDEC_VEC_BE, CR_SLICE_STRUCTURE_REQ_SIGNATURE)
+ * REG(   PVDEC_VEC_BE, CR_SLICE_STRUCTURE_OVER1K_REQ_SIGNATURE)
+ * REG(   PVDEC_VEC_BE, CR_MEM_STRUCTURE_REQ_SIGNATURE)
+ * REGREP(PVDEC_VEC_BE, CR_GDEC_DATA_REQ_SIGNATURE, 0)
+ * REGREP(PVDEC_VEC_BE, CR_GDEC_DATA_REQ_SIGNATURE, 1)
+ * REGREP(PVDEC_VEC_BE, CR_GDEC_DATA_REQ_SIGNATURE, 2)
+ * REGREP(PVDEC_VEC_BE, CR_GDEC_DATA_REQ_SIGNATURE, 3)
+ */
+#define PVDEC_SIGNATURE_GROUP_4  BIT(4)
+/*
+ * Signature group 5:
+ * REG(   PVDEC_VEC_BE, CR_GDEC_FRAGMENT_SIGNATURE)
+ * REG(   PVDEC_VEC_BE, CR_SLICE_STRUCTURE_SIGNATURE)
+ * REG(   PVDEC_VEC_BE, CR_SLICE_STRUCTURE_OVER1K_SIGNATURE)
+ * REG(   PVDEC_VEC_BE, CR_MEM_STRUCTURE_SIGNATURE)
+ * REGREP(PVDEC_VEC_BE, CR_GDEC_BUFFER_SIGNATURE, 0)
+ * REGREP(PVDEC_VEC_BE, CR_GDEC_BUFFER_SIGNATURE, 1)
+ * REGREP(PVDEC_VEC_BE, CR_GDEC_BUFFER_SIGNATURE, 2)
+ * REGREP(PVDEC_VEC_BE, CR_GDEC_BUFFER_SIGNATURE, 3)
+ */
+#define PVDEC_SIGNATURE_GROUP_5  BIT(5)
+/* -- RESIDUAL AND COMMAND DEBUG--------------------------------- */
+/*
+ * Signature group 12:
+ * REG(PVDEC_VEC_BE, CR_DECODE_TO_COMMAND_PRIME_SIGNATURE)
+ * REG(PVDEC_VEC_BE, CR_DECODE_TO_COMMAND_SECOND_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_12  BIT(12)
+/*
+ * Signature group 13:
+ * REG(PVDEC_VEC_BE, CR_DECODE_TO_RESIDUAL_PRIME_SIGNATURE)
+ * REG(PVDEC_VEC_BE, CR_DECODE_TO_RESIDUAL_SECOND_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_13  BIT(13)
+/*
+ * Signature group 14:
+ * REG(PVDEC_VEC_BE, CR_COMMAND_ABOVE_READ_SIGNATURE)
+ * REG(PVDEC_VEC_BE, CR_COMMAND_ABOVE_WRITE_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_14  BIT(14)
+/*
+ * Signature group 15:
+ * REG(PVDEC_VEC_BE, CR_TEMPORAL_READ_SIGNATURE)
+ * REG(PVDEC_VEC_BE, CR_TEMPORAL_WRITE_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_15  BIT(15)
+/* --VEC--------------------------------------------------------- */
+/*
+ * Signature group 16:
+ * REG(PVDEC_VEC_BE, CR_COMMAND_OUTPUT_SIGNATURE)
+ * REG(MSVDX_VEC,    CR_VEC_IXFORM_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_16  BIT(16)
+/*
+ * Signature group 17:
+ * REG(PVDEC_VEC_BE, CR_RESIDUAL_OUTPUT_SIGNATURE)
+ * REG(MSVDX_VEC,    CR_VEC_COMMAND_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_17  BIT(17)
+/* --VDMC-------------------------------------------------------- */
+/*
+ * Signature group 18:
+ * REG(MSVDX_VDMC, CR_VDMC_REFERENCE_CACHE_SIGNATURE)
+ * REG(MSVDX_VDMC, CR_VDMC_REFERENCE_CACHE_MEM_WADDR_SIGNATURE)
+ * REG(MSVDX_VDMC, CR_VDMC_REFERENCE_CACHE_MEM_RADDR_SIGNATURE)
+ * REG(MSVDX_VDMC, CR_VDMC_REFERENCE_CACHE_MEM_WDATA_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_18  BIT(18)
+/*
+ * Signature group 19:
+ * REG(MSVDX_VDMC, CR_VDMC_2D_FILTER_PIPELINE_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_19  BIT(19)
+/*
+ * Signature group 20:
+ * REG(MSVDX_VDMC, CR_VDMC_PIXEL_RECONSTRUCTION_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_20  BIT(20)
+/*
+ * Signature group 21:
+ * REG(MSVDX_VDMC, CR_VDMC_MCU_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_21  BIT(21)
+/* ---VDEB------------------------------------------------------- */
+/*
+ * Signature group 22:
+ * REG(MSVDX_VDEB, CR_VDEB_SYS_MEM_RDATA_LUMA_SIGNATURE)
+ * REG(MSVDX_VDEB, CR_VDEB_SYS_MEM_RDATA_CHROMA_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_22  BIT(22)
+/*
+ * Signature group 23:
+ * REG(MSVDX_VDEB, CR_VDEB_SYS_MEM_ADDR_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_23  BIT(23)
+/*
+ * Signature group 24:
+ * REG(MSVDX_VDEB, CR_VDEB_SYS_MEM_WDATA_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_24  BIT(24)
+/* ---SCALER----------------------------------------------------- */
+/*
+ * Signature group 25:
+ * REG(MSVDX_VDEB, CR_VDEB_SCALE_ADDR_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_25  BIT(25)
+/*
+ * Signature group 26:
+ * REG(MSVDX_VDEB, CR_VDEB_SCALE_WDATA_SIGNATURE)
+ */
+#define PVDEC_SIGNATURE_GROUP_26  BIT(26)
+/* ---PICTURE CHECKSUM------------------------------------------- */
+/*
+ * Signature group 27:
+ * REG(MSVDX_VDEB, CR_VDEB_HEVC_CHECKSUM_LUMA)
+ * REG(MSVDX_VDEB, CR_VDEB_HEVC_CHECKSUM_CB)
+ * REG(MSVDX_VDEB, CR_VDEB_HEVC_CHECKSUM_CR)
+ */
+#define PVDEC_SIGNATURE_GROUP_27  BIT(27)
+#define PVDEC_SIGNATURE_NEW_METHOD  BIT(31)
+
+/* Debug messages */
+#define DEBUG_DATA_TYPE_MASK             0xF
+#define DEBUG_DATA_TYPE_SHIFT            28
+
+#define DEBUG_DATA_MSG_TYPE_MASK         0x1
+#define DEBUG_DATA_MSG_TYPE_SHIFT        15
+
+#define DEBUG_DATA_MSG_ARG_COUNT_MASK    0x7
+#define DEBUG_DATA_MSG_ARG_COUNT_SHIFT   12
+
+#define DEBUG_DATA_MSG_LINE_NO_MASK      0xFFF
+#define DEBUG_DATA_MSG_LINE_NO_SHIFT     0
+
+#define DEBUG_DATA_TYPE_HEADER  (0)
+#define DEBUG_DATA_TYPE_STRING  (1)
+#define DEBUG_DATA_TYPE_PARAMS  (2)
+#define DEBUG_DATA_TYPE_MSG     (3)
+#define DEBUG_DATA_TYPE_PERF    (6)
+
+#define DEBUG_DATA_MSG_TYPE_LOG     0
+#define DEBUG_DATA_MSG_TYPE_ASSERT  1
+
+#define DEBUG_DATA_TAPE_PERF_INC_TIME_MASK   0x1
+#define DEBUG_DATA_TYPE_PERF_INC_TIME_SHIFT  28
+#define DEBUG_DATA_TYPE_PERF_INC_TIME        0x1
+
+#define DEBUG_DATA_SET_TYPE(val, type, data_type) \
+	({ \
+		data_type __val = val; \
+		((__val) = (__val & ~(DEBUG_DATA_TYPE_MASK << DEBUG_DATA_TYPE_SHIFT)) | \
+			   ((type) << DEBUG_DATA_TYPE_SHIFT)); })
+
+#define DEBUG_DATA_MSG_SET_ARG_COUNT(val, ac, data_type) \
+	({ \
+		data_type __val = val; \
+		(__val = (__val & \
+			  ~(DEBUG_DATA_MSG_ARG_COUNT_MASK << DEBUG_DATA_MSG_ARG_COUNT_SHIFT)) \
+			 | ((ac) << DEBUG_DATA_MSG_ARG_COUNT_SHIFT)); })
+
+#define DEBUG_DATA_MSG_SET_LINE_NO(val, ln, type) \
+	({ \
+		type __val = val; \
+		(__val = (__val & \
+			  ~(DEBUG_DATA_MSG_LINE_NO_MASK << DEBUG_DATA_MSG_LINE_NO_SHIFT)) \
+			 | ((ln) << DEBUG_DATA_MSG_LINE_NO_SHIFT)); })
+
+#define DEBUG_DATA_MSG_SET_TYPE(val, tp, type) \
+	({ \
+		type __val = val; \
+		(__val = (__val & \
+			  ~(DEBUG_DATA_MSG_TYPE_MASK << DEBUG_DATA_MSG_TYPE_SHIFT)) \
+			 | ((tp) << DEBUG_DATA_MSG_TYPE_SHIFT)); })
+
+#define DEBUG_DATA_GET_TYPE(val) \
+	(((val) >> DEBUG_DATA_TYPE_SHIFT) & DEBUG_DATA_TYPE_MASK)
+#define DEBUG_DATA_TYPE_PERF_IS_INC_TIME(val) \
+	(((val) >> DEBUG_DATA_TYPE_PERF_INC_TIME_SHIFT) \
+	 & DEBUG_DATA_TAPE_PERF_INC_TIME_MASK)
+#define DEBUG_DATA_MSG_GET_ARG_COUNT(val) \
+	(((val) >> DEBUG_DATA_MSG_ARG_COUNT_SHIFT) \
+	 & DEBUG_DATA_MSG_ARG_COUNT_MASK)
+#define DEBUG_DATA_MSG_GET_LINE_NO(val) \
+	(((val) >> DEBUG_DATA_MSG_LINE_NO_SHIFT) \
+	 & DEBUG_DATA_MSG_LINE_NO_MASK)
+#define DEBUG_DATA_MSG_GET_TYPE(val) \
+	(((val) >> DEBUG_DATA_MSG_TYPE_SHIFT) & DEBUG_DATA_MSG_TYPE_MASK)
+#define DEBUG_DATA_MSG_TYPE_IS_ASSERT(val) \
+	(DEBUG_DATA_MSG_GET_TYPE(val) == DEBUG_DATA_MSG_TYPE_ASSERT \
+	 ? IMG_TRUE : IMG_FALSE)
+#define DEBUG_DATA_MSG_TYPE_IS_LOG(val) \
+	(DEBUG_DATA_MSG_GET_TYPE(val) == DEBUG_DATA_MSG_TYPE_LOG ? \
+	 IMG_TRUE : IMG_FALSE)
+
+#define DEBUG_DATA_MSG_LAT(ln, ac, tp)            \
+	(((ln) << DEBUG_DATA_MSG_LINE_NO_SHIFT) | \
+	 ((ac) << DEBUG_DATA_MSG_ARG_COUNT_SHIFT) | \
+	 ((tp) << DEBUG_DATA_MSG_TYPE_SHIFT))
+/* FWBSP-mode specific defines. */
+#ifdef VDEC_USE_PVDEC_SEC
+/**
+ * FWBSP_ENC_BSTR_BUF_QUEUE_LEN - Suggested number of bitstream buffers submitted (queued)
+ * to firmware for processing at the same time.
+ */
+#define FWBSP_ENC_BSTR_BUF_QUEUE_LEN 1
+
+#endif /* VDEC_USE_PVDEC_SEC */
+
+#endif /* VDEC_USE_PVDEC_COMPATIBILITY */
+#endif /* FW_INTERFACE_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/h264fw_data.h b/drivers/media/platform/img/vxe-vxd/decoder/h264fw_data.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/h264fw_data.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/h264fw_data.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,652 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Public data structures for the h264 parser firmware module.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+/* Include shared header version here to replace the standard version */
+#include "h264fw_data_shared.h"
+
+#ifndef _H264FW_DATA_H_
+#define _H264FW_DATA_H_
+
+#include "vdecfw_shared.h"
+
+/* Maximum number of alternative CPB specifications in the stream */
+#define H264_MAXIMUMVALUEOFCPB_CNT  32
+
+/*
+ * The maximum DPB size is related to the number of MVC views supported
+ * The size is defined in H.10.2 for the H.264 spec.
+ * If the number of views needs to be changed the DPB size should be too
+ * The limits are as follows:
+ * NumViews		1,  2,  4,  8, 16
+ * MaxDpbFrames:	16, 16, 32, 48, 64
+ */
+#ifdef H264_ENABLE_MVC
+#define H264FW_MAX_NUM_VIEWS            4
+#define H264FW_MAX_DPB_SIZE             32
+#define H264FW_MAX_NUM_MVC_REFS         16
+#else
+#define H264FW_MAX_NUM_VIEWS            1
+#define H264FW_MAX_DPB_SIZE             16
+#define H264FW_MAX_NUM_MVC_REFS         1
+#endif
+
+/* Maximum value for num_ref_frames_in_pic_order_cnt_cycle */
+#define H264FW_MAX_CYCLE_REF_FRAMES     256
+
+/* 4x4 scaling list size */
+#define H264FW_4X4_SIZE                 16
+/* 8x8 scaling list size */
+#define H264FW_8X8_SIZE                 64
+/* Number of 4x4 scaling lists */
+#define H264FW_NUM_4X4_LISTS            6
+/* Number of 8x8 scaling lists */
+#define H264FW_NUM_8X8_LISTS            6
+
+/* Number of reference picture lists */
+#define H264FW_MAX_REFPIC_LISTS         2
+
+/*
+ * The maximum number of slice groups
+ * remove if slice group map is prepared on the host
+ */
+#define H264FW_MAX_SLICE_GROUPS         8
+
+/* The maximum number of planes for 4:4:4 separate color plane streams */
+#define H264FW_MAX_PLANES               3
+
+#define H264_MAX_SGM_SIZE               8196
+
+#define IS_H264_HIGH_PROFILE(profile_idc, type) \
+	({ \
+		type __profile_idc = profile_idc;       \
+		((__profile_idc) == H264_PROFILE_HIGH) ||      \
+		((__profile_idc) == H264_PROFILE_HIGH10) ||      \
+		((__profile_idc) == H264_PROFILE_HIGH422) ||      \
+		((__profile_idc) == H264_PROFILE_HIGH444) ||      \
+		((__profile_idc) == H264_PROFILE_CAVLC444) ||      \
+		((__profile_idc) == H264_PROFILE_MVC_HIGH) ||      \
+		((__profile_idc) == H264_PROFILE_MVC_STEREO); })        \
+
+/*
+ * This type describes the H.264 NAL unit types
+ */
+enum h264_enaltype {
+	H264FW_NALTYPE_SLICE               = 1,
+	H264FW_NALTYPE_IDRSLICE            = 5,
+	H264FW_NALTYPE_SEI                 = 6,
+	H264FW_NALTYPE_SPS                 = 7,
+	H264FW_NALTYPE_PPS                 = 8,
+	H264FW_NALTYPE_AUD                 = 9,
+	H264FW_NALTYPE_EOSEQ               = 10,
+	H264FW_NALTYPE_EOSTR               = 11,
+	H264FW_NALTYPE_PREFIX              = 14,
+	H264FW_NALTYPE_SUBSET_SPS          = 15,
+	H264FW_NALTYPE_AUXILIARY_SLICE     = 19,
+	H264FW_NALTYPE_EXTSLICE            = 20,
+	H264FW_NALTYPE_EXTSLICE_DEPTH_VIEW = 21,
+	H264FW_NALTYPE_FORCE32BITS         = 0x7FFFFFFFU
+};
+
+/*
+ * AVC Profile IDC definitions
+ */
+enum h264_eprofileidc {
+	/* YUV 4:4:4/14 "CAVLC 4:4:4 */
+	H264_PROFILE_CAVLC444    =       44,
+	/* YUV 4:2:0/8  "Baseline */
+	H264_PROFILE_BASELINE    =       66,
+	/* YUV 4:2:0/8  "Main */
+	H264_PROFILE_MAIN        =       77,
+	/* YUV 4:2:0/8  "Scalable" */
+	H264_PROFILE_SCALABLE    =       83,
+	/* YUV 4:2:0/8  "Extended" */
+	H264_PROFILE_EXTENDED    =       88,
+	/* YUV 4:2:0/8  "High" */
+	H264_PROFILE_HIGH        =       100,
+	/* YUV 4:2:0/10 "High 10" */
+	H264_PROFILE_HIGH10      =       110,
+	/* YUV 4:2:0/8  "Multiview High" */
+	H264_PROFILE_MVC_HIGH    =       118,
+	/* YUV 4:2:2/10 "High 4:2:2" */
+	H264_PROFILE_HIGH422     =       122,
+	/* YUV 4:2:0/8  "Stereo High" */
+	H264_PROFILE_MVC_STEREO  =       128,
+	/* YUV 4:4:4/14 "High 4:4:4" */
+	H264_PROFILE_HIGH444     =       244,
+	H264_PROFILE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This type defines the constraint set flags
+ */
+enum h264fw_econstraint_flag {
+	/* Compatible with Baseline profile */
+	H264FW_CONSTRAINT_BASELINE_SHIFT   =       7,
+	/* Compatible with Main profile */
+	H264FW_CONSTRAINT_MAIN_SHIFT       =       6,
+	/* Compatible with Extended profile */
+	H264FW_CONSTRAINT_EXTENDED_SHIFT   =       5,
+	/* Compatible with Intra profiles */
+	H264FW_CONSTRAINT_INTRA_SHIFT      =       4,
+	/* Compatible with Multiview High profile */
+	H264FW_CONSTRAINT_MULTIHIGH_SHIFT  =       3,
+	/* Compatible with Stereo High profile */
+	H264FW_CONSTRAINT_STEREOHIGH_SHIFT =       2,
+	/* Reserved flag */
+	H264FW_CONSTRAINT_RESERVED6_SHIFT  =       1,
+	/* Reserved flag */
+	H264FW_CONSTRAINT_RESERVED7_SHIFT  =       0,
+	H264FW_CONSTRAINT_FORCE32BITS      = 0x7FFFFFFFU
+};
+
+/*
+ * This enum describes the reference status of an H.264 picture.
+ * Unpaired fields should have all eRefStatusX set to the same value
+ *
+ * For Frame, Mbaff, and Pair types individual fields and frame ref status
+ * should be set accordingly.
+ *
+ * eRefStatusFrame    eRefStatusTop   eRefStatusBottom
+ * UNUSED             UNUSED          UNUSED
+ * SHORTTERM          SHORTTERM       SHORTTERM
+ * LONGTERM           LONGTERM        LONGTERM
+ *
+ * UNUSED             SHORT/LONGTERM  UNUSED
+ * UNUSED             UNUSED          SHORT/LONGTERM
+ *
+ * SHORTTERM          LONGTERM        SHORTTERM
+ * SHORTTERM          SHORTTERM       LONGTERM
+ * NB: It is not clear from the spec if the Frame should be marked as short
+ * or long term in this case
+ */
+enum h264fw_ereference {
+	/* Picture is unused for reference */
+	H264FW_REF_UNUSED = 0,
+	/* used for short term reference */
+	H264FW_REF_SHORTTERM,
+	/* used for Long Term reference */
+	H264FW_REF_LONGTERM,
+	H264FW_REF_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This type defines the picture structure.
+ */
+enum h264fw_epicture_type {
+	/* No valid picture */
+	H264FW_TYPE_NONE = 0,
+	/* Picture contains the top (even) lines of the frame */
+	H264FW_TYPE_TOP,
+	/* Picture contains the bottom (odd) lines of the frame */
+	H264FW_TYPE_BOTTOM,
+	/* Picture contains the entire frame */
+	H264FW_TYPE_FRAME,
+	/* Picture contains an MBAFF frame */
+	H264FW_TYPE_MBAFF,
+	/* Picture contains top and bottom lines of the frame */
+	H264FW_TYPE_PAIR,
+	H264FW_TYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This describes the SPS header data required by the H264 firmware that should
+ * be supplied by the Host.
+ */
+struct h264fw_sequence_ps {
+	/* syntax elements from SPS */
+	/* syntax element from bitstream - 8 bit */
+	unsigned char profile_idc;
+	/* syntax element from bitstream - 2 bit */
+	unsigned char chroma_format_idc;
+	/* syntax element from bitstream - 1 bit */
+	unsigned char separate_colour_plane_flag;
+	/* syntax element from bitstream - 3 bit */
+	unsigned char bit_depth_luma_minus8;
+	/* syntax element from bitstream - 3 bit */
+	unsigned char bit_depth_chroma_minus8;
+	/* syntax element from bitstream - 1 bit */
+	unsigned char delta_pic_order_always_zero_flag;
+	/* syntax element from bitstream - 4+ bit */
+	unsigned char log2_max_pic_order_cnt_lsb;
+	/* syntax element from bitstream - 5 bit */
+	unsigned char max_num_ref_frames;
+	/* syntax element from bitstream - 4+ bit */
+	unsigned char log2_max_frame_num;
+	/* syntax element from bitstream - 2 bit */
+	unsigned char pic_order_cnt_type;
+	/* syntax element from bitstream - 1 bit */
+	unsigned char frame_mbs_only_flag;
+	/* syntax element from bitstream - 1 bit */
+	unsigned char gaps_in_frame_num_value_allowed_flag;
+
+	/*
+	 * set0--7 flags as they occur in the bitstream (including reserved
+	 * values)
+	 */
+	unsigned char constraint_set_flags;
+	/* syntax element from bitstream - 8 bit */
+	unsigned char level_idc;
+	/* syntax element from bitstream - 8 bit */
+	unsigned char num_ref_frames_in_pic_order_cnt_cycle;
+	/* syntax element from bitstream - 1 bit */
+	unsigned char mb_adaptive_frame_field_flag;
+	/* syntax element from bitstream - 32 bit */
+	int offset_for_non_ref_pic;
+	/* syntax element from bitstream - 32 bit */
+	int offset_for_top_to_bottom_field;
+
+	/* syntax element from bitstream */
+	unsigned int pic_width_in_mbs_minus1;
+	/* syntax element from bitstream */
+	unsigned int pic_height_in_map_units_minus1;
+	/* syntax element from bitstream - 1 bit */
+	unsigned char direct_8x8_inference_flag;
+	/* syntax element from bitstream */
+	unsigned char qpprime_y_zero_transform_bypass_flag;
+
+	/* syntax element from bitstream - 32 bit each */
+	int offset_for_ref_frame[H264FW_MAX_CYCLE_REF_FRAMES];
+
+	/* From VUI information */
+	unsigned char num_reorder_frames;
+	/*
+	 * From VUI/MVC SEI, 0 indicates not set, any actual 0 value will be
+	 * inferred by the firmware
+	 */
+	unsigned char max_dec_frame_buffering;
+
+	/* From SPS MVC Extension - for the current view_id */
+	/* Number of views in this stream */
+	unsigned char num_views;
+	/* a Map in order of VOIdx of view_id's */
+	unsigned short view_ids[H264FW_MAX_NUM_VIEWS];
+
+	/* Disable VDMC horizontal/vertical filtering */
+	unsigned char disable_vdmc_filt;
+	/* Disable CABAC 4:4:4 4x4 transform as not available */
+	unsigned char transform4x4_mb_not_available;
+
+	/* anchor reference list */
+	unsigned short anchor_inter_view_reference_id_list[2]
+	[H264FW_MAX_NUM_VIEWS][H264FW_MAX_NUM_MVC_REFS];
+	/* nonanchor reference list */
+	unsigned short non_anchor_inter_view_reference_id_list[2]
+	[H264FW_MAX_NUM_VIEWS][H264FW_MAX_NUM_MVC_REFS];
+	/* number of elements in aui16AnchorInterViewReferenceIndiciesLX[] */
+	unsigned short num_anchor_refsx[2][H264FW_MAX_NUM_VIEWS];
+	/* number of elements in aui16NonAnchorInterViewReferenceIndiciesLX[] */
+	unsigned short num_non_anchor_refsx[2][H264FW_MAX_NUM_VIEWS];
+};
+
+/*
+ * This structure represents HRD parameters.
+ */
+struct h264fw_hrd {
+	/* cpb_cnt_minus1 */
+	unsigned char cpb_cnt_minus1;
+	/* bit_rate_scale */
+	unsigned char bit_rate_scale;
+	/* cpb_size_scale */
+	unsigned char cpb_size_scale;
+	/* bit_rate_value_minus1 */
+	unsigned int bit_rate_value_minus1[H264_MAXIMUMVALUEOFCPB_CNT];
+	/* cpb_size_value_minus1 */
+	unsigned int cpb_size_value_minus1[H264_MAXIMUMVALUEOFCPB_CNT];
+	/* cbr_flag */
+	unsigned char cbr_flag[H264_MAXIMUMVALUEOFCPB_CNT];
+	/* initial_cpb_removal_delay_length_minus1 */
+	unsigned char initial_cpb_removal_delay_length_minus1;
+	/* cpb_removal_delay_length_minus1 */
+	unsigned char cpb_removal_delay_length_minus1;
+	/* dpb_output_delay_length_minus1 */
+	unsigned char dpb_output_delay_length_minus1;
+	/* time_offset_length */
+	unsigned char time_offset_length;
+};
+
+/*
+ * This structure represents the VUI parameters data.
+ */
+struct h264fw_vui {
+	int aspect_ratio_info_present_flag;
+	unsigned char aspect_ratio_idc;
+	unsigned short sar_width;
+	unsigned short sar_height;
+	int overscan_info_present_flag;
+	int overscan_appropriate_flag;
+	int video_signal_type_present_flag;
+	unsigned char video_format;
+	int video_full_range_flag;
+	int colour_description_present_flag;
+	unsigned char colour_primaries;
+	unsigned char transfer_characteristics;
+	unsigned char matrix_coefficients;
+	int chroma_location_info_present_flag;
+	unsigned int chroma_sample_loc_type_top_field;
+	unsigned int chroma_sample_loc_type_bottom_field;
+	int timing_info_present_flag;
+	unsigned int num_units_in_tick;
+	unsigned int time_scale;
+	int fixed_frame_rate_flag;
+	int nal_hrd_parameters_present_flag;
+	struct h264fw_hrd nal_hrd_params;
+	int vcl_hrd_parameters_present_flag;
+	struct h264fw_hrd vcl_hrd_params;
+	int low_delay_hrd_flag;
+	int pic_struct_present_flag;
+	int bitstream_restriction_flag;
+	int motion_vectors_over_pic_boundaries_flag;
+	unsigned int max_bytes_per_pic_denom;
+	unsigned int max_bits_per_mb_denom;
+	unsigned int log2_max_mv_length_vertical;
+	unsigned int log2_max_mv_length_horizontal;
+	unsigned int num_reorder_frames;
+	unsigned int max_dec_frame_buffering;
+};
+
+/*
+ * This describes the HW specific SPS header data required by the H264
+ * firmware that should be supplied by the Host.
+ */
+struct h264fw_ddsequence_ps {
+	/* pre-packed registers derived from SPS */
+	/* Value for CR_VEC_ENTDEC_FE_CONTROL */
+	unsigned int regentdec_control;
+
+	/* NB: This register should contain the 4-bit SGM flag */
+	/* Value for CR_VEC_H264_FE_SPS0 & CR_VEC_H264_BE_SPS0 combined */
+	unsigned int reg_sps0;
+	/* Value of CR_VEC_H264_BE_INTRA_8x8 */
+	unsigned int reg_beintra;
+	/* Value of CR_VEC_H264_FE_CABAC444 */
+	unsigned int reg_fecaabac444;
+	/* Treat CABAC 4:4:4 4x4 transform as not available */
+	unsigned char transform4x4_mb_notavialbale;
+	/* Disable VDMC horizontal/vertical filtering */
+	unsigned char disable_vdmcfilt;
+};
+
+/*
+ * This describes the PPS header data required by the H264 firmware that should
+ * be supplied by the Host.
+ */
+struct h264fw_picture_ps {
+	/* syntax elements from the PPS */
+	/* syntax element from bitstream - 1 bit */
+	unsigned char deblocking_filter_control_present_flag;
+	/* syntax element from bitstream - 1 bit */
+	unsigned char transform_8x8_mode_flag;
+	/* syntax element from bitstream - 1 bit */
+	unsigned char entropy_coding_mode_flag;
+	/* syntax element from bitstream - 1 bit */
+	unsigned char redundant_pic_cnt_present_flag;
+
+	/* syntax element from bitstream - 2 bit */
+	unsigned char weighted_bipred_idc;
+	/* syntax element from bitstream - 1 bit */
+	unsigned char weighted_pred_flag;
+	/* syntax element from bitstream - 1 bit */
+	unsigned char pic_order_present_flag;
+
+	/* 26 + syntax element from bitstream - 7 bit */
+	unsigned char pic_init_qp;
+	/* syntax element from bitstream - 1 bit */
+	unsigned char constrained_intra_pred_flag;
+	/* syntax element from bitstream - 5 bit each */
+	unsigned char num_ref_lx_active_minus1[H264FW_MAX_REFPIC_LISTS];
+
+	/* syntax element from bitstream - 3 bit */
+	unsigned char slice_group_map_type;
+	/* syntax element from bitstream - 3 bit */
+	unsigned char num_slice_groups_minus1;
+	/* syntax element from bitstream - 13 bit */
+	unsigned short slice_group_change_rate_minus1;
+
+	/* syntax element from bitstream */
+	unsigned int chroma_qp_index_offset;
+	/* syntax element from bitstream */
+	unsigned int second_chroma_qp_index_offset;
+
+	/* scaling lists are derived from both SPS and PPS information */
+	/* but will change whenever the PPS changes */
+	/* The derived set of tables are associated here with the PPS */
+	/* NB: These are in H.264 order */
+	/* derived from SPS and PPS - 8 bit each */
+	unsigned char scalinglist4x4[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE];
+	/* derived from SPS and PPS - 8 bit each */
+	unsigned char scalinglist8x8[H264FW_NUM_8X8_LISTS][H264FW_8X8_SIZE];
+};
+
+/*
+ * This describes the HW specific PPS header data required by the H264
+ * firmware that should be supplied by the Host.
+ */
+struct h264fw_dd_picture_ps {
+	/* values derived from the PPS */
+	/* Value for MSVDX_CMDS_SLICE_PARAMS_MODE_CONFIG */
+	unsigned char vdmc_mode_config;
+
+	/* pre-packed registers derived from the PPS */
+	/* Value for CR_VEC_H264_FE_PPS0 & CR_VEC_H264_BE_PPS0 combined */
+	unsigned int reg_pps0;
+
+	/*
+	 * scaling lists are derived from both SPS and PPS information
+	 * but will change whenever the PPS changes
+	 * The derived set of tables are associated here with the PPS
+	 * But this will become invalid if the SPS changes and will have to be
+	 * recalculated
+	 * These tables MUST be aligned on a 32-bit boundary
+	 * NB: These are in MSVDX order
+	 */
+	/* derived from SPS and PPS - 8 bit each */
+	unsigned char scalinglist4x4[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE];
+	/* derived from SPS and PPS - 8 bit each */
+	unsigned char scalinglist8x8[H264FW_NUM_8X8_LISTS][H264FW_8X8_SIZE];
+};
+
+/*
+ * This describes the H.264 parser component "Header data", shown in the
+ * Firmware Memory Layout diagram. This data is required by the H264 firmware
+ * and should be supplied by the Host.
+ */
+struct h264fw_header_data {
+	/* Decode buffers and output control for the current picture */
+	/* Primary decode buffer base addresses */
+	struct vdecfw_image_buffer primary;
+	/* buffer base addresses for alternate output */
+	struct vdecfw_image_buffer alternate;
+	/* Output control: rotation, scaling, oold, etc. */
+	unsigned int pic_cmds[VDECFW_CMD_MAX];
+	/* Macroblock parameters base address for the picture */
+	unsigned int mbparams_base_address;
+
+	unsigned int mbparams_size_per_plane;
+
+	/* Buffers for context preload for colour plane switching (6.x.x) */
+	unsigned int preload_buffer_base_address
+	[H264FW_MAX_PLANES];
+
+	/*
+	 * slice group map should be calculated on Host
+	 * (using some slice params) and base address provided here
+	 */
+	/* Base address of active slice group map */
+	/* Base address of active slice group map */
+	unsigned int slicegroupmap_base_address;
+
+	/* H264 specific control */
+	/* do second pass Intra Deblock on frame */
+	unsigned int do_old __attribute__ (aligned(4));
+	/* set to IMG_FALSE to disable second-pass deblock */
+	unsigned int two_pass_flag __attribute__ (aligned(4));
+	/* set to IMG_TRUE to disable MVC */
+	unsigned int disable_mvc __attribute__ (aligned(4));
+	/*
+	 * Do we have second PPS in uipSecondPPSInfoSource provided for the
+	 * second field
+	 */
+	unsigned int second_pps __attribute__ (aligned(4));
+};
+
+/*
+ * This describes an H.264 picture. It is part of the Context data
+ */
+struct h264fw_picture {
+	/* Primary (reconstructed) picture buffers */
+	struct vdecfw_image_buffer primary;
+	/* Secondary (alternative) picture buffers */
+	struct vdecfw_image_buffer alternate;
+	/* Macroblock parameters base address for the picture */
+	unsigned int mbparams_base_address;
+
+	/* Unique ID for this picture */
+	unsigned int transaction_id;
+	/* Picture type */
+	enum h264fw_epicture_type pricture_type;
+
+	/* Reference status of the picture */
+	enum h264fw_ereference ref_status_bottom;
+	/* Reference status of the picture */
+	enum h264fw_ereference ref_status_top;
+	/* Reference status of the picture */
+	enum h264fw_ereference ref_status_frame;
+
+	/* Frame Number */
+	unsigned int frame_number;
+	/* Short term reference info */
+	int fame_number_wrap;
+	/* long term reference number - should be 8-bit */
+	unsigned int longterm_frame_idx;
+
+	/* Top field order count for this picture */
+	int top_field_order_count;
+	/* Bottom field order count for this picture */
+	int bottom_field_order_count;
+	/* MVC view_id */
+	unsigned short view_id;
+	/*
+	 * When picture is in the DPB Offset to use into the MSVDX DPB reg table
+	 * when the current picture is the same view as this.
+	 */
+	unsigned char view_dpb_offset;
+	/* Flags for this picture for the display process */
+	unsigned char display_flags;
+
+	/* IMG_FALSE if sent to display, or otherwise not needed for display */
+	unsigned char needed_for_output;
+};
+
+/*
+ * This structure describes frame data for POC calculation
+ */
+struct h264fw_poc_picture_data {
+	/* type 0,1,2 */
+	unsigned char mmco_5_flag;
+
+	/* type 0 */
+	unsigned char bottom_field_flag;
+	unsigned short pic_order_cnt_lsb;
+	int top_field_order_count;
+	int pic_order_count_msb;
+
+	/* type 1,2 */
+	int16 frame_num;
+	int frame_num_offset;
+
+	/* output */
+	int bottom_filed_order_count;
+};
+
+/*
+ * This structure describes picture data for determining Complementary
+ * Field Pairs
+ */
+struct h264fw_last_pic_data {
+	/* Unique ID for this picture */
+	unsigned int transaction_id;
+	/* Picture type */
+	enum h264fw_epicture_type picture_type;
+	/* Reference status of the picture */
+	enum h264fw_ereference ref_status_frame;
+	/* Frame Number */
+	unsigned int frame_number;
+
+	unsigned int luma_recon;
+	unsigned int chroma_recon;
+	unsigned int chroma_2_recon;
+	unsigned int luma_alter;
+	unsigned int chroma_alter;
+	unsigned int chroma_2_alter;
+	struct vdecfw_image_buffer primary;
+	struct vdecfw_image_buffer alternate;
+	unsigned int mbparams_base_address;
+	/* Top field order count for this picture */
+	int top_field_order_count;
+	/* Bottom field order count for this picture */
+	int bottom_field_order_count;
+};
+
+/*
+ * This describes the H.264 parser component "Context data", shown in the
+ * Firmware Memory Layout diagram. This data is the state preserved across
+ * pictures. It is loaded and saved by the Firmware, but requires the host to
+ * provide buffer(s) for this.
+ */
+struct h264fw_context_data {
+	/* Decoded Picture Buffer */
+	struct h264fw_picture dpb[H264FW_MAX_DPB_SIZE];
+	/*
+	 * Inter-view reference components - also used as detail of the previous
+	 * picture for any particular view, can be used to determine
+	 * complemetary field pairs
+	 */
+	struct h264fw_picture interview_prediction_ref[H264FW_MAX_NUM_VIEWS];
+	/* previous ref pic for type0, previous pic for type1&2 */
+	struct h264fw_poc_picture_data prev_poc_pic_data[H264FW_MAX_NUM_VIEWS];
+	/* previous picture information to detect complementary field pairs */
+	struct h264fw_last_pic_data last_pic_data[H264FW_MAX_NUM_VIEWS];
+	struct h264fw_last_pic_data last_displayed_pic_data
+	[H264FW_MAX_NUM_VIEWS];
+
+	/* previous reference frame number for each view */
+	unsigned short prev_ref_frame_num[H264FW_MAX_NUM_VIEWS];
+	/* Bitmap of used slots in each view DPB */
+	unsigned short dpb_bitmap[H264FW_MAX_NUM_VIEWS];
+
+	/* DPB size */
+	unsigned int dpb_size;
+	/* Number of pictures in DPB */
+	unsigned int dpb_fullness;
+
+	unsigned char prev_display_flags;
+	int prev_display;
+	int prev_release;
+	/* Active parameter sets */
+	/* Sequence Parameter Set data */
+	struct h264fw_sequence_ps sps;
+	/* Picture Parameter Set data */
+	struct h264fw_picture_ps pps;
+	/*
+	 * Picture Parameter Set data for second field when in the same buffer
+	 */
+	struct h264fw_picture_ps second_pps;
+
+	/* Set if stream is MVC */
+	int mvc;
+	/* DPB long term reference information */
+	int max_longterm_frame_idx[H264FW_MAX_NUM_VIEWS];
+};
+
+#endif /* _H264FW_DATA_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/h264fw_data_shared.h b/drivers/media/platform/img/vxe-vxd/decoder/h264fw_data_shared.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/h264fw_data_shared.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/h264fw_data_shared.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,760 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Public data structures for the h264 parser firmware module
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifdef USE_SHARING
+#endif
+
+#ifndef _H264FW_DATA_H_
+#define _H264FW_DATA_H_
+
+#include "vdecfw_share.h"
+#include "vdecfw_shared.h"
+
+#define H264_MAX_SPS_COUNT 32
+#define H264_MAX_PPS_COUNT 256
+
+#define H264_SCALING_LISTS_NUM_CHROMA_IDC_NON_3 (8)
+#define H264_SCALING_LISTS_NUM_CHROMA_IDC_3 (12)
+#define MAX_PIC_SCALING_LIST (12)
+
+/* Maximum number of alternative CPB specifications in the stream */
+#define H264_MAXIMUMVALUEOFCPB_CNT 32
+
+/*
+ * The maximum DPB size is related to the number of MVC views supported
+ * The size is defined in H.10.2 for the H.264 spec.
+ * If the number of views needs to be changed the DPB size should be too
+ * The limits are as follows:
+ * NumViews: 1, 2, 4, 8, 16
+ * MaxDpbFrames: 16, 16, 32, 48, 64
+ */
+
+/* firmware supports MVC - so need 16 refs */
+#define H264FW_MAX_NUM_VIEWS       4
+#define H264FW_MAX_DPB_SIZE        32
+#define H264FW_MAX_NUM_MVC_REFS    16
+
+/* Number of H264 VLC table configuration registers */
+#define H264FW_NUM_VLC_REG 22
+
+/* Maximum value for num_ref_frames_in_pic_order_cnt_cycle */
+#define H264FW_MAX_CYCLE_REF_FRAMES 256
+
+/* 4x4 scaling list size */
+#define H264FW_4X4_SIZE 16
+/* 8x8 scaling list size */
+#define H264FW_8X8_SIZE 64
+/* Number of 4x4 scaling lists */
+#define H264FW_NUM_4X4_LISTS 6
+/* Number of 8x8 scaling lists */
+#define H264FW_NUM_8X8_LISTS 6
+
+/* Number of reference picture lists */
+#define H264FW_MAX_REFPIC_LISTS 2
+
+/*
+ * The maximum number of slice groups
+ * remove if slice group map is prepared on the host
+ */
+#define H264FW_MAX_SLICE_GROUPS 8
+
+/* The maximum number of planes for 4:4:4 separate colour plane streams */
+#define H264FW_MAX_PLANES 3
+
+#define H264_MAX_SGM_SIZE 8196
+
+#define IS_H264_HIGH_PROFILE(profile_idc, type) \
+	({ \
+		type __profile_idc = profile_idc; \
+		(__profile_idc == H264_PROFILE_HIGH) || \
+		(__profile_idc == H264_PROFILE_HIGH10) || \
+		(__profile_idc == H264_PROFILE_HIGH422) || \
+		(__profile_idc == H264_PROFILE_HIGH444) || \
+		(__profile_idc == H264_PROFILE_CAVLC444) || \
+		(__profile_idc == H264_PROFILE_MVC_HIGH) || \
+		(__profile_idc == H264_PROFILE_MVC_STEREO); })  \
+
+/* This type describes the H.264 NAL unit types */
+enum h264_enaltype {
+	H264FW_NALTYPE_SLICE               = 1,
+	H264FW_NALTYPE_IDRSLICE            = 5,
+	H264FW_NALTYPE_SEI                 = 6,
+	H264FW_NALTYPE_SPS                 = 7,
+	H264FW_NALTYPE_PPS                 = 8,
+	H264FW_NALTYPE_AUD                 = 9,
+	H264FW_NALTYPE_EOSEQ               = 10,
+	H264FW_NALTYPE_EOSTR               = 11,
+	H264FW_NALTYPE_PREFIX              = 14,
+	H264FW_NALTYPE_SUBSET_SPS          = 15,
+	H264FW_NALTYPE_AUXILIARY_SLICE     = 19,
+	H264FW_NALTYPE_EXTSLICE            = 20,
+	H264FW_NALTYPE_EXTSLICE_DEPTH_VIEW = 21,
+	H264FW_NALTYPE_FORCE32BITS         = 0x7FFFFFFFU
+};
+
+/* AVC Profile IDC definitions */
+enum h264_eprofileidc {
+	H264_PROFILE_CAVLC444    = 44,
+	H264_PROFILE_BASELINE    = 66,
+	H264_PROFILE_MAIN        = 77,
+	H264_PROFILE_SCALABLE    = 83,
+	H264_PROFILE_EXTENDED    = 88,
+	H264_PROFILE_HIGH        = 100,
+	H264_PROFILE_HIGH10      = 110,
+	H264_PROFILE_MVC_HIGH    = 118,
+	H264_PROFILE_HIGH422     = 122,
+	H264_PROFILE_MVC_STEREO  = 128,
+	H264_PROFILE_HIGH444     = 244,
+	H264_PROFILE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* This type defines the constraint set flags */
+enum h264fw_econstraint_flag {
+	H264FW_CONSTRAINT_BASELINE_SHIFT   = 7,
+	H264FW_CONSTRAINT_MAIN_SHIFT       = 6,
+	H264FW_CONSTRAINT_EXTENDED_SHIFT   = 5,
+	H264FW_CONSTRAINT_INTRA_SHIFT      = 4,
+	H264FW_CONSTRAINT_MULTIHIGH_SHIFT  = 3,
+	H264FW_CONSTRAINT_STEREOHIGH_SHIFT = 2,
+	H264FW_CONSTRAINT_RESERVED6_SHIFT  = 1,
+	H264FW_CONSTRAINT_RESERVED7_SHIFT  = 0,
+	H264FW_CONSTRAINT_FORCE32BITS      = 0x7FFFFFFFU
+};
+
+/*
+ * This enum describes the reference status of an H.264 picture.
+ *
+ * Unpaired fields should have all eRefStatusX set to the same value
+ *
+ * For Frame, Mbaff, and Pair types individual fields and frame ref status
+ * should be set accordingly.
+ *
+ * eRefStatusFrame eRefStatusTop eRefStatusBottom
+ * UNUSED UNUSED UNUSED
+ * SHORTTERM SHORTTERM SHORTTERM
+ * LONGTERM LONGTERM LONGTERM
+ *
+ * UNUSED SHORT/LONGTERM UNUSED
+ * UNUSED UNUSED SHORT/LONGTERM
+ *
+ * SHORTTERM LONGTERM SHORTTERM
+ * SHORTTERM SHORTTERM LONGTERM
+ * - NB: It is not clear from the spec if the Frame should be marked as short
+ * or long term in this case
+ */
+enum h264fw_ereference {
+	H264FW_REF_UNUSED      = 0,
+	H264FW_REF_SHORTTERM,
+	H264FW_REF_LONGTERM,
+	H264FW_REF_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* This type defines the picture structure. */
+enum h264fw_epicture_type {
+	H264FW_TYPE_NONE = 0,
+	H264FW_TYPE_TOP,
+	H264FW_TYPE_BOTTOM,
+	H264FW_TYPE_FRAME,
+	H264FW_TYPE_MBAFF,
+	H264FW_TYPE_PAIR,
+	H264FW_TYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This describes the SPS header data required by the H264 firmware that should
+ * be supplied by the Host.
+ */
+struct h264fw_sequence_ps {
+	/* syntax elements from SPS */
+
+	/* syntax element from bitstream - 8 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, profile_idc);
+	/* syntax element from bitstream - 2 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, chroma_format_idc);
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, separate_colour_plane_flag);
+	/* syntax element from bitstream - 3 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, bit_depth_luma_minus8);
+	/* syntax element from bitstream - 3 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, bit_depth_chroma_minus8);
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, delta_pic_order_always_zero_flag);
+	/* syntax element from bitstream - 4+ bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, log2_max_pic_order_cnt_lsb);
+
+	/* syntax element from bitstream - 5 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, max_num_ref_frames);
+	/* syntax element from bitstream - 4+ bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, log2_max_frame_num);
+	/* syntax element from bitstream - 2 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pic_order_cnt_type);
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, frame_mbs_only_flag);
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, gaps_in_frame_num_value_allowed_flag);
+
+	/*
+	 * set0--7 flags as they occur in the bitstream
+	 * (including reserved values)
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, constraint_set_flags);
+	/* syntax element from bitstream - 8 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, level_idc);
+	/* syntax element from bitstream - 8 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_ref_frames_in_pic_order_cnt_cycle);
+
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, mb_adaptive_frame_field_flag);
+	/* syntax element from bitstream - 32 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, offset_for_non_ref_pic);
+	/* syntax element from bitstream - 32 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, offset_for_top_to_bottom_field);
+
+	/* syntax element from bitstream */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, pic_width_in_mbs_minus1);
+	/* syntax element from bitstream */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, pic_height_in_map_units_minus1);
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, direct_8x8_inference_flag);
+	/* syntax element from bitstream */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, qpprime_y_zero_transform_bypass_flag);
+
+	/* syntax element from bitstream - 32 bit each */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, offset_for_ref_frame[H264FW_MAX_CYCLE_REF_FRAMES]);
+
+	/* From VUI information */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_reorder_frames);
+	/*
+	 * From VUI/MVC SEI, 0 indicates not set, any actual 0
+	 * value will be inferred by the firmware
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, max_dec_frame_buffering);
+
+	/* From SPS MVC Extension - for the current view_id */
+
+	/* Number of views in this stream */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_views);
+	/* a Map in order of VOIdx of view_id's */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, view_ids[H264FW_MAX_NUM_VIEWS]);
+
+	/* Disable VDMC horizontal/vertical filtering */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, disable_vdmc_filt);
+	/* Disable CABAC 4:4:4 4x4 transform as not available */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, transform4x4_mb_not_available);
+
+	/* anchor reference list */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned short,
+			anchor_inter_view_reference_id_list[2][H264FW_MAX_NUM_VIEWS]
+			[H264FW_MAX_NUM_MVC_REFS]);
+	/* nonanchor reference list */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned short,
+			non_anchor_inter_view_reference_id_list[2][H264FW_MAX_NUM_VIEWS]
+			[H264FW_MAX_NUM_MVC_REFS]);
+	/* number of elements in aui16AnchorInterViewReferenceIndiciesLX[] */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned short,
+			num_anchor_refsx[2][H264FW_MAX_NUM_VIEWS]);
+	/* number of elements in aui16NonAnchorInterViewReferenceIndiciesLX[] */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned short,
+			num_non_anchor_refsx[2][H264FW_MAX_NUM_VIEWS]);
+};
+
+/*
+ * This structure represents HRD parameters.
+ */
+struct h264fw_hrd {
+	/* cpb_cnt_minus1; */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, cpb_cnt_minus1);
+	/* bit_rate_scale; */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, bit_rate_scale);
+	/* cpb_size_scale; */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, cpb_size_scale);
+	/* bit_rate_value_minus1 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int,
+			bit_rate_value_minus1[H264_MAXIMUMVALUEOFCPB_CNT]);
+	/* cpb_size_value_minus1 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int,
+			cpb_size_value_minus1[H264_MAXIMUMVALUEOFCPB_CNT]);
+	/* cbr_flag */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			cbr_flag[H264_MAXIMUMVALUEOFCPB_CNT]);
+	/* initial_cpb_removal_delay_length_minus1; */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			initial_cpb_removal_delay_length_minus1);
+	/* cpb_removal_delay_length_minus1; */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			cpb_removal_delay_length_minus1);
+	/* dpb_output_delay_length_minus1; */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			dpb_output_delay_length_minus1);
+	/* time_offset_length; */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, time_offset_length);
+};
+
+/*
+ * This structure represents the VUI parameters data.
+ */
+struct h264fw_vui {
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, aspect_ratio_info_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, aspect_ratio_idc);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, sar_width);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, sar_height);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, overscan_info_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, overscan_appropriate_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, video_signal_type_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, video_format);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, video_full_range_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, colour_description_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, colour_primaries);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, transfer_characteristics);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, matrix_coefficients);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, chroma_location_info_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, chroma_sample_loc_type_top_field);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, chroma_sample_loc_type_bottom_field);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, timing_info_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, num_units_in_tick);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, time_scale);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, fixed_frame_rate_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, nal_hrd_parameters_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			struct h264fw_hrd, nal_hrd_params);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, vcl_hrd_parameters_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			struct h264fw_hrd, vcl_hrd_params);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, low_delay_hrd_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, pic_struct_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, bitstream_restriction_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, motion_vectors_over_pic_boundaries_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, max_bytes_per_pic_denom);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, max_bits_per_mb_denom);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, log2_max_mv_length_vertical);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, log2_max_mv_length_horizontal);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, num_reorder_frames);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, max_dec_frame_buffering);
+};
+
+/*
+ * This describes the HW specific SPS header data required by the H264
+ * firmware that should be supplied by the Host.
+ */
+struct h264fw_ddsequence_ps {
+	/* Value for CR_VEC_ENTDEC_FE_CONTROL */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, regentdec_control);
+
+	/* NB: This register should contain the 4-bit SGM flag */
+
+	/* Value for CR_VEC_H264_FE_SPS0 & CR_VEC_H264_BE_SPS0 combined */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int, reg_sps0);
+	/* Value of CR_VEC_H264_BE_INTRA_8x8 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, reg_beintra);
+	/* Value of CR_VEC_H264_FE_CABAC444 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, reg_fecaabac444);
+
+	/* Treat CABAC 4:4:4 4x4 transform as not available */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			transform4x4_mb_notavialbale);
+	/* Disable VDMC horizontal/vertical filtering */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			disable_vdmcfilt);
+};
+
+/*
+ * This describes the PPS header data required by the H264 firmware that should
+ * be supplied by the Host.
+ */
+struct h264fw_picture_ps {
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			deblocking_filter_control_present_flag);
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			transform_8x8_mode_flag);
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			entropy_coding_mode_flag);
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			redundant_pic_cnt_present_flag);
+
+	/* syntax element from bitstream - 2 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			weighted_bipred_idc);
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			weighted_pred_flag);
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			pic_order_present_flag);
+
+	/* 26 + syntax element from bitstream - 7 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char, pic_init_qp);
+	/* syntax element from bitstream - 1 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			constrained_intra_pred_flag);
+	/* syntax element from bitstream - 5 bit each */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			num_ref_lx_active_minus1[H264FW_MAX_REFPIC_LISTS]);
+
+	/* syntax element from bitstream - 3 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			slice_group_map_type);
+	/* syntax element from bitstream - 3 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			num_slice_groups_minus1);
+	/* syntax element from bitstream - 13 bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned short,
+			slice_group_change_rate_minus1);
+
+	/* syntax element from bitstream */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, int,
+			chroma_qp_index_offset);
+	/* syntax element from bitstream */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, int,
+			second_chroma_qp_index_offset);
+
+	/*
+	 * scaling lists are derived from both SPS and PPS information
+	 * but will change whenever the PPS changes
+	 * The derived set of tables are associated here with the PPS
+	 * NB: These are in H.264 order
+	 */
+
+	/* derived from SPS and PPS - 8 bit each */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			scalinglist4x4[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE]);
+	/* derived from SPS and PPS - 8 bit each */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			scalinglist8x8[H264FW_NUM_8X8_LISTS][H264FW_8X8_SIZE]);
+};
+
+/*
+ * This describes the HW specific PPS header data required by the H264
+ * firmware that should be supplied by the Host.
+ */
+struct h264fw_dd_picture_ps {
+	/* Value for MSVDX_CMDS_SLICE_PARAMS_MODE_CONFIG */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			vdmc_mode_config);
+	/* Value for CR_VEC_H264_FE_PPS0 & CR_VEC_H264_BE_PPS0 combined */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int, reg_pps0);
+
+	/*
+	 * Scaling lists are derived from both SPS and PPS information
+	 * but will change whenever the PPS changes. The derived set of tables
+	 * are associated here with the PPS, but this will become invalid if
+	 * the SPS changes and will have to be recalculated.
+	 * These tables MUST be aligned on a 32-bit boundary
+	 * NB: These are in MSVDX order
+	 */
+
+	/* derived from SPS and PPS - 8 bit each */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			scalinglist4x4[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE]);
+	/* derived from SPS and PPS - 8 bit each */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			scalinglist8x8[H264FW_NUM_8X8_LISTS][H264FW_8X8_SIZE]);
+};
+
+/*
+ * This describes the H.264 parser component "Header data", shown in the
+ * Firmware Memory Layout diagram. This data is required by the H264 firmware
+ * and should be supplied by the Host.
+ */
+struct h264fw_header_data {
+	struct vdecfw_image_buffer primary;
+	struct vdecfw_image_buffer alternate;
+
+	/* Output control: rotation, scaling, oold, etc. */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int,
+			pic_cmds[VDECFW_CMD_MAX]);
+	/* Macroblock parameters base address for the picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int,
+			mbparams_base_address);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int,
+			mbparams_size_per_plane);
+	/* Buffers for context preload for colour plane switching (6.x.x) */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int,
+			preload_buffer_base_address[H264FW_MAX_PLANES]);
+	/* Base address of active slice group map */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int,
+			slicegroupmap_base_address);
+
+	/* do second pass Intra Deblock on frame */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char, do_old);
+	/* set to IMG_FALSE to disable second-pass deblock */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			two_pass_flag);
+	/* set to IMG_TRUE to disable MVC */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			disable_mvc);
+	/*
+	 * Do we have second PPS in uipSecondPPSInfoSource provided
+	 * for the second field.
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			second_pps);
+};
+
+/* This describes an H.264 picture. It is part of the Context data */
+struct h264fw_picture {
+	/* Primary (reconstructed) picture buffers */
+	struct vdecfw_image_buffer primary;
+	/* Secondary (alternative) picture buffers */
+	struct vdecfw_image_buffer alternate;
+	/* Macroblock parameters base address for the picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, mbparams_base_address);
+
+	/* Unique ID for this picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, transaction_id);
+	/* Picture type */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			enum h264fw_epicture_type, pricture_type);
+
+	/* Reference status of the picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			enum h264fw_ereference, ref_status_bottom);
+	/* Reference status of the picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			enum h264fw_ereference, ref_status_top);
+	/* Reference status of the picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			enum h264fw_ereference, ref_status_frame);
+
+	/* Frame Number */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, frame_number);
+	/* Short term reference info */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, frame_number_wrap);
+	/* long term reference number - should be 8-bit */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, longterm_frame_idx);
+
+	/* Top field order count for this picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, top_field_order_count);
+	/* Bottom field order count for this picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, bottom_field_order_count);
+
+	/* MVC view_id */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, view_id);
+
+	/*
+	 * When picture is in the DPB Offset to use into
+	 * the MSVDX DPB reg table when the current
+	 * picture is the same view as this.
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, view_dpb_offset);
+	/* Flags for this picture for the display process */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, display_flags);
+
+	/* IMG_FALSE if sent to display, or otherwise not needed for display */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, needed_for_output);
+};
+
+/* This structure describes frame data for POC calculation */
+struct h264fw_poc_picture_data {
+	/* type 0,1,2 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, mmco_5_flag);
+
+	/* type 0 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, bottom_field_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, pic_order_cnt_lsb);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, top_field_order_count);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, pic_order_count_msb);
+
+	/* type 1,2 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, short, frame_num);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, int, frame_num_offset);
+
+	/* output */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, bottom_filed_order_count);
+};
+
+/*
+ * This structure describes picture data for determining
+ * Complementary Field Pairs
+ */
+struct h264fw_last_pic_data {
+	/* Unique ID for this picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, transaction_id);
+	/* Picture type */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			enum h264fw_epicture_type, picture_type);
+	/* Reference status of the picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			enum h264fw_ereference, ref_status_frame);
+	/* Frame Number */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, frame_number);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, luma_recon);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, chroma_recon);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, chroma_2_recon);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, luma_alter);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, chroma_alter);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, chroma_2_alter);
+
+	struct vdecfw_image_buffer primary;
+	struct vdecfw_image_buffer alternate;
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, mbparams_base_address);
+	/* Top field order count for this picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, top_field_order_count);
+	/* Bottom field order count for this picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, bottom_field_order_count);
+};
+
+/*
+ * This describes the H.264 parser component "Context data", shown in the
+ * Firmware Memory Layout diagram. This data is the state preserved across
+ * pictures. It is loaded and saved by the Firmware, but requires the host to
+ * provide buffer(s) for this.
+ */
+struct h264fw_context_data {
+	struct h264fw_picture dpb[H264FW_MAX_DPB_SIZE];
+	/*
+	 * Inter-view reference components - also used as detail of the previous
+	 * picture for any particular view, can be used to determine
+	 * complemetary field pairs
+	 */
+	struct h264fw_picture interview_prediction_ref[H264FW_MAX_NUM_VIEWS];
+	/* previous ref pic for type0, previous pic for type1&2 */
+	struct h264fw_poc_picture_data prev_poc_pic_data[H264FW_MAX_NUM_VIEWS];
+	/* previous picture information to detect complementary field pairs */
+	struct h264fw_last_pic_data last_pic_data[H264FW_MAX_NUM_VIEWS];
+	struct h264fw_last_pic_data
+		last_displayed_pic_data[H264FW_MAX_NUM_VIEWS];
+
+	/* previous reference frame number for each view */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned short,
+			prev_ref_frame_num[H264FW_MAX_NUM_VIEWS]);
+	/* Bitmap of used slots in each view DPB */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned short,
+			dpb_bitmap[H264FW_MAX_NUM_VIEWS]);
+
+	/* DPB size */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int, dpb_size);
+	/* Number of pictures in DPB */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int,
+			dpb_fullness);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			prev_display_flags);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, int, prev_display);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, int, prev_release);
+	/* Sequence Parameter Set data */
+	struct h264fw_sequence_ps sps;
+	/* Picture Parameter Set data */
+	struct h264fw_picture_ps pps;
+	/* Picture Parameter Set data for second field if in the same buffer */
+	struct h264fw_picture_ps second_pps;
+
+	/* Set if stream is MVC */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, int, mvc);
+	/* DPB long term reference information */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, int,
+			max_longterm_frame_idx[H264FW_MAX_NUM_VIEWS]);
+};
+
+#endif /* _H264FW_DATA_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/h264_idx.h b/drivers/media/platform/img/vxe-vxd/decoder/h264_idx.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/h264_idx.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/h264_idx.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * h264 idx table definitions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ */
+
+#ifndef __H264_IDX_H__
+#define __H264_IDX_H__
+
+#include <linux/types.h>
+
+static unsigned short h264_vlc_index_data[38][3] = {
+	{ 2, 5, 0   },  /* NumCoeffTrailingOnes_Table9-5_nC_0-1.out */
+	{ 0, 3, 76  },  /* NumCoeffTrailingOnes_Table9-5_nC_2-3.out */
+	{ 0, 3, 160 },  /* NumCoeffTrailingOnes_Table9-5_nC_4-7.out */
+	{ 0, 2, 231 },  /* NumCoeffTrailingOnesFixedLen.out */
+	{ 2, 2, 244 },  /* NumCoeffTrailingOnesChromaDC_YUV420.out */
+	{ 2, 5, 261 },  /* NumCoeffTrailingOnesChromaDC_YUV422.out */
+	{ 2, 5, 301 },  /* TotalZeros_00.out */
+	{ 0, 2, 326 },  /* TotalZeros_01.out */
+	{ 0, 2, 345 },  /* TotalZeros_02.out */
+	{ 0, 2, 363 },  /* TotalZeros_03.out */
+	{ 0, 2, 379 },  /* TotalZeros_04.out */
+	{ 0, 2, 394 },  /* TotalZeros_05.out */
+	{ 0, 2, 406 },  /* TotalZeros_06.out */
+	{ 0, 1, 418 },  /* TotalZeros_07.out */
+	{ 0, 1, 429 },  /* TotalZeros_08.out */
+	{ 0, 1, 438 },  /* TotalZeros_09.out */
+	{ 2, 2, 446 },  /* TotalZeros_10.out */
+	{ 2, 2, 452 },  /* TotalZeros_11.out */
+	{ 2, 1, 456 },  /* TotalZeros_12.out */
+	{ 0, 0, 459 },  /* TotalZeros_13.out */
+	{ 0, 0, 461 },  /* TotalZeros_14.out */
+	{ 2, 2, 463 },  /* TotalZerosChromaDC_YUV420_00.out */
+	{ 2, 1, 467 },  /* TotalZerosChromaDC_YUV420_01.out */
+	{ 0, 0, 470 },  /* TotalZerosChromaDC_YUV420_02.out */
+	{ 0, 0, 472 },  /* Run_00.out */
+	{ 2, 1, 474 },  /* Run_01.out */
+	{ 0, 1, 477 },  /* Run_02.out */
+	{ 0, 1, 481 },  /* Run_03.out */
+	{ 1, 1, 487 },  /* Run_04.out */
+	{ 0, 2, 494 },  /* Run_05.out */
+	{ 0, 2, 502 },  /* Run_06.out */
+	{ 2, 4, 520 },  /* TotalZerosChromaDC_YUV422_00.out */
+	{ 2, 2, 526 },  /* TotalZerosChromaDC_YUV422_01.out */
+	{ 0, 1, 530 },  /* TotalZerosChromaDC_YUV422_02.out */
+	{ 1, 2, 534 },  /* TotalZerosChromaDC_YUV422_03.out */
+	{ 0, 0, 538 },  /* TotalZerosChromaDC_YUV422_04.out */
+	{ 0, 0, 540 },  /* TotalZerosChromaDC_YUV422_05.out */
+	{ 0, 0, 542 },  /* TotalZerosChromaDC_YUV422_06.out */
+};
+
+static const unsigned char h264_vlc_index_size = 38;
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/h264_secure_parser.c b/drivers/media/platform/img/vxe-vxd/decoder/h264_secure_parser.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/h264_secure_parser.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/h264_secure_parser.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,3055 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * h.264 secure data unit parsing API.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ * Re-written for upstreming
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "bspp.h"
+#include "bspp_int.h"
+#include "h264_secure_parser.h"
+#include "pixel_api.h"
+#include "swsr.h"
+#include "vdec_defs.h"
+
+/*
+ * Reduce DPB to 1 when no pic reordering.
+ */
+#define SL_MAX_REF_IDX          32
+#define VUI_CPB_CNT_MAX         32
+#define MAX_SPS_COUNT           32
+#define MAX_PPS_COUNT           256
+/* changed from 810 */
+#define MAX_SLICE_GROUPMBS      65536
+#define MAX_SPS_COUNT           32
+#define MAX_PPS_COUNT           256
+#define MAX_SLICEGROUP_COUNT    8
+#define MAX_WIDTH_IN_MBS        256
+#define MAX_HEIGHT_IN_MBS       256
+#define MAX_COLOR_PLANE         4
+#define H264_MAX_SGM_SIZE       8196
+
+#define H264_MAX_CHROMA_QP_INDEX_OFFSET (12)
+#define H264_MIN_CHROMA_QP_INDEX_OFFSET (-12)
+
+/*
+ * AVC Profile IDC definitions
+ */
+enum h264_profile_idc {
+	h264_profile_cavlc444   = 44,   /*  YUV 4:4:4/14 "CAVLC 4:4:4" */
+	h264_profile_baseline   = 66,   /* YUV 4:2:0/8  "Baseline" */
+	h264_profile_main       = 77,   /* YUV 4:2:0/8  "Main" */
+	h264_profile_scalable   = 83,   /* YUV 4:2:0/8  "Scalable" */
+	h264_profile_extended   = 88,   /* YUV 4:2:0/8  "Extended" */
+	h264_profile_high       = 100,  /* YUV 4:2:0/8  "High" */
+	h264_profile_hig10     = 110,  /* YUV 4:2:0/10 "High 10" */
+	h264_profile_mvc_high   = 118,  /* YUV 4:2:0/8  "Multiview High" */
+	h264_profile_high422    = 122,  /* YUV 4:2:2/10 "High 4:2:2" */
+	h264_profile_mvc_stereo = 128,  /* YUV 4:2:0/8  "Stereo High" */
+	h264_profile_high444    = 244,  /* YUV 4:4:4/14 "High 4:4:4" */
+	h264_profile_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Remap H.264 colour format into internal representation.
+ */
+static const enum pixel_fmt_idc pixel_format_idc[] = {
+	PIXEL_FORMAT_MONO,
+	PIXEL_FORMAT_420,
+	PIXEL_FORMAT_422,
+	PIXEL_FORMAT_444,
+};
+
+/*
+ * Pixel Aspect Ratio
+ */
+static const unsigned short pixel_aspect[17][2] = {
+	{ 0, 1 },
+	{ 1, 1 },
+	{ 12, 11 },
+	{ 10, 11 },
+	{ 16, 11 },
+	{ 40, 33 },
+	{ 24, 11 },
+	{ 20, 11 },
+	{ 32, 11 },
+	{ 80, 33 },
+	{ 18, 11 },
+	{ 15, 11 },
+	{ 64, 33 },
+	{ 160, 99 },
+	{ 4, 3 },
+	{ 3, 2 },
+	{ 2, 1 },
+};
+
+/*
+ * Table 7-3, 7-4: Default Scaling lists
+ */
+static const unsigned char default_4x4_intra[16] = {
+	6, 13, 13, 20,
+	20, 20, 28, 28,
+	28, 28, 32, 32,
+	32, 37, 37, 42
+};
+
+static const unsigned char default_4x4_inter[16] = {
+	10, 14, 14, 20,
+	20, 20, 24, 24,
+	24, 24, 27, 27,
+	27, 30, 30, 34
+};
+
+static const unsigned char default_8x8_intra[64] = {
+	6, 10, 10, 13, 11, 13, 16, 16,
+	16, 16, 18, 18, 18, 18, 18, 23,
+	23, 23, 23, 23, 23, 25, 25, 25,
+	25, 25, 25, 25, 27, 27, 27, 27,
+	27, 27, 27, 27, 29, 29, 29, 29,
+	29, 29, 29, 31, 31, 31, 31, 31,
+	31, 33, 33, 33, 33, 33, 36, 36,
+	36, 36, 38, 38, 38, 40, 40, 42
+};
+
+static const unsigned char default_8x8_inter[64] = {
+	9, 13, 13, 15, 13, 15, 17, 17,
+	17, 17, 19, 19, 19, 19, 19, 21,
+	21, 21, 21, 21, 21, 22, 22, 22,
+	22, 22, 22, 22, 24, 24, 24, 24,
+	24, 24, 24, 24, 25, 25, 25, 25,
+	25, 25, 25, 27, 27, 27, 27, 27,
+	27, 28, 28, 28, 28, 28, 30, 30,
+	30, 30, 32, 32, 32, 33, 33, 35
+};
+
+/*
+ * to be use if no q matrix is chosen
+ */
+static const unsigned char default_4x4_org[16] = {
+	16, 16, 16, 16,
+	16, 16, 16, 16,
+	16, 16, 16, 16,
+	16, 16, 16, 16
+};
+
+/*
+ * to be use if no q matrix is chosen
+ */
+static const unsigned char default_8x8_org[64] = {
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16,
+	16, 16, 16, 16, 16, 16, 16, 16
+};
+
+/*
+ * source: ITU-T H.264 2010/03, page 20 Table 6-1
+ */
+static const int bspp_subheightc[] = { -1, 2, 1, 1 };
+
+/*
+ * source: ITU-T H.264 2010/03, page 20 Table 6-1
+ */
+static const int bspp_subwidthc[] = { -1, 2, 2, 1 };
+
+/*
+ * inline functions for Minimum and Maximum value
+ */
+static inline unsigned int umin(unsigned int a, unsigned int b)
+{
+	return (((a) < (b)) ? (a) : (b));
+}
+
+static inline int smin(int a, int b)
+{
+	return (((a) < (b)) ? (a) : (b));
+}
+
+static inline int smax(int a, int b)
+{
+	return (((a) > (b)) ? (a) : (b));
+}
+
+static void set_if_not_determined_yet(int *determined,
+				      unsigned char condition,
+				      int *target,
+				      unsigned int value)
+{
+	if ((!(*determined)) && (condition)) {
+		*target = value;
+		*determined = 1;
+	}
+}
+
+static int bspp_h264_get_subwidthc(int chroma_format_idc, int separate_colour_plane_flag)
+{
+	return bspp_subwidthc[chroma_format_idc];
+}
+
+static int bspp_h264_get_subheightc(int chroma_format_idc, int separate_colour_plane_flag)
+{
+	return bspp_subheightc[chroma_format_idc];
+}
+
+static unsigned int h264ceillog2(unsigned int value)
+{
+	unsigned int status = 0;
+
+	value -= 1;
+	while (value > 0) {
+		value >>= 1;
+		status++;
+	}
+	return status;
+}
+
+/*
+ * @Function              bspp_h264_set_default_vui
+ * @Description           Sets default values of the VUI info
+ */
+static void bspp_h264_set_default_vui(struct bspp_h264_vui_info *vui_info)
+{
+	unsigned int *nal_hrd_bitrate_valueminus1 = NULL;
+	unsigned int *vcl_hrd_bitrate_valueminus1 = NULL;
+	unsigned int *nal_hrd_cpbsize_valueminus1 = NULL;
+	unsigned int *vcl_hrd_cpbsize_valueminus1 = NULL;
+	unsigned char *nal_hrd_cbr_flag = NULL;
+	unsigned char *vcl_hrd_cbr_flag = NULL;
+
+	/* Saving pointers */
+	nal_hrd_bitrate_valueminus1 = vui_info->nal_hrd_parameters.bit_rate_value_minus1;
+	vcl_hrd_bitrate_valueminus1 = vui_info->vcl_hrd_parameters.bit_rate_value_minus1;
+
+	nal_hrd_cpbsize_valueminus1 = vui_info->nal_hrd_parameters.cpb_size_value_minus1;
+	vcl_hrd_cpbsize_valueminus1 = vui_info->vcl_hrd_parameters.cpb_size_value_minus1;
+
+	nal_hrd_cbr_flag = vui_info->nal_hrd_parameters.cbr_flag;
+	vcl_hrd_cbr_flag = vui_info->vcl_hrd_parameters.cbr_flag;
+
+	/* Cleaning sVUIInfo */
+	if (vui_info->nal_hrd_parameters.bit_rate_value_minus1)
+		memset(vui_info->nal_hrd_parameters.bit_rate_value_minus1, 0x00,
+		       VDEC_H264_MAXIMUMVALUEOFCPB_CNT * sizeof(unsigned int));
+
+	if (vui_info->nal_hrd_parameters.cpb_size_value_minus1)
+		memset(vui_info->nal_hrd_parameters.cpb_size_value_minus1, 0x00,
+		       VDEC_H264_MAXIMUMVALUEOFCPB_CNT * sizeof(unsigned int));
+
+	if (vui_info->vcl_hrd_parameters.cpb_size_value_minus1)
+		memset(vui_info->vcl_hrd_parameters.cpb_size_value_minus1, 0x00,
+		       VDEC_H264_MAXIMUMVALUEOFCPB_CNT * sizeof(unsigned int));
+
+	if (vui_info->nal_hrd_parameters.cbr_flag)
+		memset(vui_info->nal_hrd_parameters.cbr_flag, 0x00,
+		       VDEC_H264_MAXIMUMVALUEOFCPB_CNT * sizeof(unsigned char));
+
+	if (vui_info->vcl_hrd_parameters.cbr_flag)
+		memset(vui_info->vcl_hrd_parameters.cbr_flag, 0x00,
+		       VDEC_H264_MAXIMUMVALUEOFCPB_CNT * sizeof(unsigned char));
+
+	/* Make sure you set default for everything */
+	memset(vui_info, 0, sizeof(*vui_info));
+	vui_info->video_format                            = 5;
+	vui_info->colour_primaries                        = 2;
+	vui_info->transfer_characteristics                = 2;
+	vui_info->matrix_coefficients                     = 2;
+	vui_info->motion_vectors_over_pic_boundaries_flag = 1;
+	vui_info->max_bytes_per_pic_denom                 = 2;
+	vui_info->max_bits_per_mb_denom                   = 1;
+	vui_info->log2_max_mv_length_horizontal           = 16;
+	vui_info->log2_max_mv_length_vertical             = 16;
+
+#ifdef REDUCED_DPB_NO_PIC_REORDERING
+	vui_info->max_dec_frame_buffering                 = 1;
+	vui_info->num_reorder_frames                      = 0;
+#else
+	vui_info->max_dec_frame_buffering                 = 0;
+	vui_info->num_reorder_frames                      = vui_info->max_dec_frame_buffering;
+#endif
+
+	/* Restoring pointers */
+	vui_info->nal_hrd_parameters.bit_rate_value_minus1 = nal_hrd_bitrate_valueminus1;
+	vui_info->vcl_hrd_parameters.bit_rate_value_minus1 = vcl_hrd_bitrate_valueminus1;
+
+	vui_info->nal_hrd_parameters.cpb_size_value_minus1 = nal_hrd_cpbsize_valueminus1;
+	vui_info->vcl_hrd_parameters.cpb_size_value_minus1 = vcl_hrd_cpbsize_valueminus1;
+
+	vui_info->nal_hrd_parameters.cbr_flag = nal_hrd_cbr_flag;
+	vui_info->vcl_hrd_parameters.cbr_flag = vcl_hrd_cbr_flag;
+}
+
+/*
+ * @Function              bspp_h264_hrd_param_parser
+ * @Description           Parse the HRD parameter
+ */
+static enum bspp_error_type bspp_h264_hrd_param_parser
+					(void *swsr_context,
+					 struct bspp_h264_hrdparam_info *h264_hrd_param_info)
+{
+	unsigned int sched_sel_idx;
+
+	VDEC_ASSERT(swsr_context);
+	h264_hrd_param_info->cpb_cnt_minus1 = swsr_read_unsigned_expgoulomb(swsr_context);
+
+	if (h264_hrd_param_info->cpb_cnt_minus1 >= 32)
+		pr_info("pb_cnt_minus1 is not within the range");
+
+	h264_hrd_param_info->bit_rate_scale = swsr_read_bits(swsr_context, 4);
+	h264_hrd_param_info->cpb_size_scale = swsr_read_bits(swsr_context, 4);
+
+	if (!h264_hrd_param_info->bit_rate_value_minus1) {
+		h264_hrd_param_info->bit_rate_value_minus1 = kcalloc
+							(VDEC_H264_MAXIMUMVALUEOFCPB_CNT,
+							 sizeof(unsigned int), GFP_KERNEL);
+		VDEC_ASSERT(h264_hrd_param_info->bit_rate_value_minus1);
+		if (!h264_hrd_param_info->bit_rate_value_minus1)
+			return BSPP_ERROR_OUT_OF_MEMORY;
+	}
+
+	if (!h264_hrd_param_info->cpb_size_value_minus1) {
+		h264_hrd_param_info->cpb_size_value_minus1 = kcalloc
+							(VDEC_H264_MAXIMUMVALUEOFCPB_CNT,
+							 sizeof(unsigned int),
+							 GFP_KERNEL);
+		VDEC_ASSERT(h264_hrd_param_info->cpb_size_value_minus1);
+		if (!h264_hrd_param_info->cpb_size_value_minus1)
+			return BSPP_ERROR_OUT_OF_MEMORY;
+	}
+
+	if (!h264_hrd_param_info->cbr_flag) {
+		h264_hrd_param_info->cbr_flag =
+			kcalloc(VDEC_H264_MAXIMUMVALUEOFCPB_CNT, sizeof(unsigned char), GFP_KERNEL);
+		VDEC_ASSERT(h264_hrd_param_info->cbr_flag);
+		if (!h264_hrd_param_info->cbr_flag)
+			return BSPP_ERROR_OUT_OF_MEMORY;
+	}
+
+	for (sched_sel_idx = 0; sched_sel_idx <= h264_hrd_param_info->cpb_cnt_minus1;
+		sched_sel_idx++) {
+		h264_hrd_param_info->bit_rate_value_minus1[sched_sel_idx] =
+			swsr_read_unsigned_expgoulomb(swsr_context);
+		h264_hrd_param_info->cpb_size_value_minus1[sched_sel_idx] =
+			swsr_read_unsigned_expgoulomb(swsr_context);
+
+		if (h264_hrd_param_info->cpb_size_value_minus1[sched_sel_idx] == 0xffffffff)
+			/* 65 bit pattern, 32 0's -1 - 32 0's then value should be 0 */
+			h264_hrd_param_info->cpb_size_value_minus1[sched_sel_idx] = 0;
+
+		h264_hrd_param_info->cbr_flag[sched_sel_idx] = swsr_read_bits(swsr_context, 1);
+	}
+
+	h264_hrd_param_info->initial_cpb_removal_delay_length_minus1 = swsr_read_bits(swsr_context,
+										      5);
+	h264_hrd_param_info->cpb_removal_delay_length_minus1 = swsr_read_bits(swsr_context, 5);
+	h264_hrd_param_info->dpb_output_delay_length_minus1 = swsr_read_bits(swsr_context, 5);
+	h264_hrd_param_info->time_offset_length = swsr_read_bits(swsr_context, 5);
+
+	return BSPP_ERROR_NONE;
+}
+
+/*
+ * @Function              bspp_h264_get_default_hrd_param
+ * @Description           Get default value of the HRD parameter
+ */
+static void bspp_h264_get_default_hrd_param(struct bspp_h264_hrdparam_info *h264_hrd_param_info)
+{
+	/* other parameters already set to '0' */
+	h264_hrd_param_info->initial_cpb_removal_delay_length_minus1 = 23;
+	h264_hrd_param_info->cpb_removal_delay_length_minus1        = 23;
+	h264_hrd_param_info->dpb_output_delay_length_minus1         = 23;
+	h264_hrd_param_info->time_offset_length                   = 24;
+}
+
+/*
+ * @Function              bspp_h264_vui_parser
+ * @Description           Parse the VUI info
+ */
+static enum bspp_error_type bspp_h264_vui_parser(void *swsr_context,
+						 struct bspp_h264_vui_info *vui_info,
+						 struct bspp_h264_sps_info *sps_info)
+{
+	enum bspp_error_type vui_parser_error = BSPP_ERROR_NONE;
+
+	vui_info->aspect_ratio_info_present_flag = swsr_read_bits(swsr_context, 1);
+	if (vui_info->aspect_ratio_info_present_flag) {
+		vui_info->aspect_ratio_idc = swsr_read_bits(swsr_context, 8);
+		/* Extended SAR */
+		if (vui_info->aspect_ratio_idc == 255) {
+			vui_info->sar_width = swsr_read_bits(swsr_context, 16);
+			vui_info->sar_height = swsr_read_bits(swsr_context, 16);
+		} else if (vui_info->aspect_ratio_idc < 17) {
+			vui_info->sar_width = pixel_aspect[vui_info->aspect_ratio_idc][0];
+			vui_info->sar_height = pixel_aspect[vui_info->aspect_ratio_idc][1];
+		} else {
+			/* we can consider this error as a aux data error */
+			vui_parser_error |= BSPP_ERROR_INVALID_VALUE;
+		}
+	}
+
+	vui_info->overscan_info_present_flag = swsr_read_bits(swsr_context, 1);
+	if (vui_info->overscan_info_present_flag)
+		vui_info->overscan_appropriate_flag = swsr_read_bits(swsr_context, 1);
+
+	vui_info->video_signal_type_present_flag = swsr_read_bits(swsr_context, 1);
+	if (vui_info->video_signal_type_present_flag) {
+		vui_info->video_format = swsr_read_bits(swsr_context, 3);
+		vui_info->video_full_range_flag = swsr_read_bits(swsr_context, 1);
+		vui_info->colour_description_present_flag = swsr_read_bits(swsr_context, 1);
+		if (vui_info->colour_description_present_flag) {
+			vui_info->colour_primaries = swsr_read_bits(swsr_context, 8);
+			vui_info->transfer_characteristics = swsr_read_bits(swsr_context, 8);
+			vui_info->matrix_coefficients = swsr_read_bits(swsr_context, 8);
+		}
+	}
+
+	vui_info->chroma_location_info_present_flag = swsr_read_bits(swsr_context, 1);
+	if (vui_info->chroma_location_info_present_flag) {
+		vui_info->chroma_sample_loc_type_top_field = swsr_read_unsigned_expgoulomb
+										(swsr_context);
+		vui_info->chroma_sample_loc_type_bottom_field = swsr_read_unsigned_expgoulomb
+										(swsr_context);
+	}
+
+	vui_info->timing_info_present_flag = swsr_read_bits(swsr_context, 1);
+	if (vui_info->timing_info_present_flag) {
+		vui_info->num_units_in_tick = swsr_read_bits(swsr_context, 16);
+		vui_info->num_units_in_tick <<= 16;     /* SR can only do up to 31 bit reads */
+		vui_info->num_units_in_tick |= swsr_read_bits(swsr_context, 16);
+		vui_info->time_scale = swsr_read_bits(swsr_context, 16);
+		vui_info->time_scale <<= 16;     /* SR can only do up to 31 bit reads */
+		vui_info->time_scale |= swsr_read_bits(swsr_context, 16);
+		if (!vui_info->num_units_in_tick || !vui_info->time_scale)
+			vui_parser_error  |=  BSPP_ERROR_INVALID_VALUE;
+
+		vui_info->fixed_frame_rate_flag = swsr_read_bits(swsr_context, 1);
+	}
+
+	/* no default values */
+	vui_info->nal_hrd_parameters_present_flag = swsr_read_bits(swsr_context, 1);
+	if (vui_info->nal_hrd_parameters_present_flag)
+		vui_parser_error |= bspp_h264_hrd_param_parser(swsr_context,
+				&vui_info->nal_hrd_parameters);
+	else
+		bspp_h264_get_default_hrd_param(&vui_info->nal_hrd_parameters);
+
+	vui_info->vcl_hrd_parameters_present_flag = swsr_read_bits(swsr_context, 1);
+
+	if (vui_info->vcl_hrd_parameters_present_flag)
+		vui_parser_error |= bspp_h264_hrd_param_parser(swsr_context,
+				&vui_info->vcl_hrd_parameters);
+	else
+		bspp_h264_get_default_hrd_param(&vui_info->vcl_hrd_parameters);
+
+	if (vui_info->nal_hrd_parameters_present_flag || vui_info->vcl_hrd_parameters_present_flag)
+		vui_info->low_delay_hrd_flag = swsr_read_bits(swsr_context, 1);
+
+	vui_info->pic_struct_present_flag = swsr_read_bits(swsr_context, 1);
+	vui_info->bitstream_restriction_flag = swsr_read_bits(swsr_context, 1);
+	if (vui_info->bitstream_restriction_flag) {
+		vui_info->motion_vectors_over_pic_boundaries_flag = swsr_read_bits(swsr_context, 1);
+		vui_info->max_bytes_per_pic_denom = swsr_read_unsigned_expgoulomb(swsr_context);
+		vui_info->max_bits_per_mb_denom = swsr_read_unsigned_expgoulomb(swsr_context);
+		vui_info->log2_max_mv_length_horizontal =
+			swsr_read_unsigned_expgoulomb(swsr_context);
+		vui_info->log2_max_mv_length_vertical = swsr_read_unsigned_expgoulomb(swsr_context);
+		vui_info->num_reorder_frames = swsr_read_unsigned_expgoulomb(swsr_context);
+		vui_info->max_dec_frame_buffering = swsr_read_unsigned_expgoulomb(swsr_context);
+	}
+
+	if ((sps_info->profile_idc == h264_profile_baseline ||
+	     sps_info->profile_idc == h264_profile_extended) &&
+	    sps_info->max_num_ref_frames == 1) {
+		vui_info->bitstream_restriction_flag = 1;
+		vui_info->num_reorder_frames = 0;
+		vui_info->max_dec_frame_buffering = 1;
+	}
+
+	if (vui_info->num_reorder_frames > 32)
+		vui_parser_error |= BSPP_ERROR_UNSUPPORTED;
+
+	return vui_parser_error;
+}
+
+/*
+ * Parse scaling list
+ */
+static enum bspp_error_type bspp_h264_scl_listparser(void *swsr_context,
+						     unsigned char *scaling_list,
+						     unsigned char sizeof_scaling_list,
+						     unsigned char *usedefaultscalingmatrixflag)
+{
+	enum bspp_error_type parse_error = BSPP_ERROR_NONE;
+	int delta_scale;
+	unsigned int lastscale = 8;
+	unsigned int nextscale = 8;
+	unsigned int j;
+
+	VDEC_ASSERT(swsr_context);
+	VDEC_ASSERT(scaling_list);
+	VDEC_ASSERT(usedefaultscalingmatrixflag);
+
+	if (!scaling_list || !swsr_context || !usedefaultscalingmatrixflag) {
+		parse_error = BSPP_ERROR_UNRECOVERABLE;
+		return parse_error;
+	}
+
+	/* 7.3.2.1.1 */
+	for (j = 0; j < sizeof_scaling_list; j++) {
+		if (nextscale != 0) {
+			delta_scale = swsr_read_signed_expgoulomb(swsr_context);
+			if ((-128 > delta_scale) || delta_scale > 127)
+				parse_error |= BSPP_ERROR_INVALID_VALUE;
+			nextscale = (lastscale + delta_scale + 256) & 0xff;
+			*usedefaultscalingmatrixflag = (j == 0 && nextscale == 0);
+		}
+		scaling_list[j] = (nextscale == 0) ? lastscale : nextscale;
+		lastscale = scaling_list[j];
+	}
+	return parse_error;
+}
+
+/*
+ * Parse the SPS NAL unit
+ */
+static enum bspp_error_type bspp_h264_sps_parser(void *swsr_context,
+						 void *str_res,
+						 struct bspp_h264_seq_hdr_info *h264_seq_hdr_info)
+{
+	unsigned int i;
+	unsigned char scaling_list_num;
+	struct bspp_h264_sps_info *sps_info;
+	struct bspp_h264_vui_info *vui_info;
+	enum bspp_error_type sps_parser_error = BSPP_ERROR_NONE;
+	enum bspp_error_type vui_parser_error = BSPP_ERROR_NONE;
+
+	sps_info = &h264_seq_hdr_info->sps_info;
+	vui_info = &h264_seq_hdr_info->vui_info;
+
+	/* Set always the default VUI/MVCExt, their values
+	 * may be used even if VUI/MVCExt not present
+	 */
+	bspp_h264_set_default_vui(vui_info);
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("Parsing Sequence Parameter Set");
+#endif
+	sps_info->profile_idc = swsr_read_bits(swsr_context, 8);
+	if (sps_info->profile_idc != H264_PROFILE_BASELINE &&
+	    sps_info->profile_idc != H264_PROFILE_MAIN &&
+	    sps_info->profile_idc != H264_PROFILE_SCALABLE &&
+	    sps_info->profile_idc != H264_PROFILE_EXTENDED &&
+	    sps_info->profile_idc != H264_PROFILE_HIGH &&
+	    sps_info->profile_idc != H264_PROFILE_HIGH10 &&
+	    sps_info->profile_idc != H264_PROFILE_MVC_HIGH &&
+	    sps_info->profile_idc != H264_PROFILE_HIGH422 &&
+	    sps_info->profile_idc != H264_PROFILE_CAVLC444 &&
+	    sps_info->profile_idc != H264_PROFILE_MVC_STEREO &&
+	    sps_info->profile_idc != H264_PROFILE_HIGH444) {
+		pr_err("Invalid Profile ID [%d],Parsed by BSPP", sps_info->profile_idc);
+		return BSPP_ERROR_UNSUPPORTED;
+	}
+	sps_info->constraint_set_flags = swsr_read_bits(swsr_context, 8);
+	sps_info->level_idc = swsr_read_bits(swsr_context, 8);
+
+	/* sequence parameter set id */
+	sps_info->seq_parameter_set_id = swsr_read_unsigned_expgoulomb(swsr_context);
+	if (sps_info->seq_parameter_set_id >= MAX_SPS_COUNT) {
+		pr_err("SPS ID [%d] goes beyond the limit", sps_info->seq_parameter_set_id);
+		return BSPP_ERROR_UNSUPPORTED;
+	}
+
+	/* High profile settings */
+	if (sps_info->profile_idc == H264_PROFILE_HIGH ||
+	    sps_info->profile_idc == H264_PROFILE_HIGH10 ||
+	    sps_info->profile_idc == H264_PROFILE_HIGH422 ||
+	    sps_info->profile_idc == H264_PROFILE_HIGH444 ||
+	    sps_info->profile_idc == H264_PROFILE_CAVLC444 ||
+	    sps_info->profile_idc == H264_PROFILE_MVC_HIGH ||
+	    sps_info->profile_idc == H264_PROFILE_MVC_STEREO) {
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("This is High Profile Bitstream");
+#endif
+		sps_info->chroma_format_idc = swsr_read_unsigned_expgoulomb(swsr_context);
+		if (sps_info->chroma_format_idc > 3) {
+			pr_err("chroma_format_idc[%d] is not within the range",
+			       sps_info->chroma_format_idc);
+			sps_parser_error |= BSPP_ERROR_INVALID_VALUE;
+		}
+		if (sps_info->chroma_format_idc == 3)
+			sps_info->separate_colour_plane_flag = swsr_read_bits(swsr_context, 1);
+		else
+			sps_info->separate_colour_plane_flag = 0;
+
+		sps_info->bit_depth_luma_minus8 = swsr_read_unsigned_expgoulomb(swsr_context);
+		if (sps_info->bit_depth_luma_minus8 > 6)
+			sps_parser_error |= BSPP_ERROR_INVALID_VALUE;
+
+		sps_info->bit_depth_chroma_minus8 = swsr_read_unsigned_expgoulomb(swsr_context);
+		if (sps_info->bit_depth_chroma_minus8 > 6)
+			sps_parser_error |= BSPP_ERROR_INVALID_VALUE;
+
+		sps_info->qpprime_y_zero_transform_bypass_flag = swsr_read_bits(swsr_context, 1);
+		sps_info->seq_scaling_matrix_present_flag = swsr_read_bits(swsr_context, 1);
+		if (sps_info->seq_scaling_matrix_present_flag) {
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("seq_scaling_matrix_present_flag is available");
+#endif
+			scaling_list_num = (sps_info->chroma_format_idc != 3) ? 8 : 12;
+
+			if (!sps_info->scllst4x4seq) {
+				sps_info->scllst4x4seq =
+					kmalloc((sizeof(unsigned char[H264FW_NUM_4X4_LISTS]
+							[H264FW_4X4_SIZE])), GFP_KERNEL);
+				if (!sps_info->scllst4x4seq) {
+					sps_parser_error |= BSPP_ERROR_OUT_OF_MEMORY;
+				} else {
+					VDEC_ASSERT(sps_info->scllst4x4seq);
+					memset(sps_info->scllst4x4seq, 0x00,
+					       sizeof(unsigned char[H264FW_NUM_4X4_LISTS]
+					       [H264FW_4X4_SIZE]));
+				}
+			}
+			if (!sps_info->scllst8x8seq) {
+				sps_info->scllst8x8seq =
+					kmalloc((sizeof(unsigned char[H264FW_NUM_8X8_LISTS]
+							[H264FW_8X8_SIZE])), GFP_KERNEL);
+				if (!sps_info->scllst8x8seq) {
+					sps_parser_error |= BSPP_ERROR_OUT_OF_MEMORY;
+				} else {
+					VDEC_ASSERT(sps_info->scllst8x8seq);
+					memset(sps_info->scllst8x8seq, 0x00,
+					       sizeof(unsigned char[H264FW_NUM_8X8_LISTS]
+						      [H264FW_8X8_SIZE]));
+				}
+			}
+
+		{
+			unsigned char(*scllst4x4seq)[H264FW_NUM_4X4_LISTS]
+				[H264FW_4X4_SIZE] =
+			(unsigned char (*)[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE])
+						sps_info->scllst4x4seq;
+			unsigned char(*scllst8x8seq)[H264FW_NUM_8X8_LISTS]
+				[H264FW_8X8_SIZE] =
+				(unsigned char (*)[H264FW_NUM_8X8_LISTS]
+				 [H264FW_8X8_SIZE])
+				sps_info->scllst8x8seq;
+
+			for (i = 0; i < scaling_list_num; i++) {
+				unsigned char *ptr =
+					&sps_info->usedefaultscalingmatrixflag_seq[i];
+
+				sps_info->seq_scaling_list_present_flag[i] =
+							swsr_read_bits(swsr_context, 1);
+				if (sps_info->seq_scaling_list_present_flag[i]) {
+					if (i < 6) {
+						sps_parser_error |=
+							bspp_h264_scl_listparser
+							(swsr_context,
+							 (*scllst4x4seq)[i], 16,
+							 ptr);
+					} else {
+						sps_parser_error |=
+							bspp_h264_scl_listparser
+							(swsr_context,
+							 (*scllst8x8seq)[i - 6], 64,
+							 ptr);
+					}
+				}
+			}
+		}
+		}
+	} else {
+		/* default values in here */
+		sps_info->chroma_format_idc = 1;
+		sps_info->bit_depth_luma_minus8 = 0;
+		sps_info->bit_depth_chroma_minus8 = 0;
+		sps_info->qpprime_y_zero_transform_bypass_flag = 0;
+		sps_info->seq_scaling_matrix_present_flag = 0;
+	}
+
+	sps_info->log2_max_frame_num_minus4 = swsr_read_unsigned_expgoulomb(swsr_context);
+	if (sps_info->log2_max_frame_num_minus4 > 12) {
+		pr_err("log2_max_frame_num_minus4[%d] is not within range  [0 - 12]",
+		       sps_info->log2_max_frame_num_minus4);
+		sps_parser_error |= BSPP_ERROR_INVALID_VALUE;
+	}
+
+	sps_info->pic_order_cnt_type = swsr_read_unsigned_expgoulomb(swsr_context);
+	if (sps_info->pic_order_cnt_type > 2) {
+		pr_err("pic_order_cnt_type[%d] is not within range  [0 - 2]",
+		       sps_info->pic_order_cnt_type);
+		sps_parser_error |= BSPP_ERROR_INVALID_VALUE;
+	}
+
+	if (sps_info->pic_order_cnt_type == 0) {
+		sps_info->log2_max_pic_order_cnt_lsb_minus4 = swsr_read_unsigned_expgoulomb
+										(swsr_context);
+		if (sps_info->log2_max_pic_order_cnt_lsb_minus4 > 12) {
+			pr_err("log2_max_pic_order_cnt_lsb_minus4[%d] is not within range  [0 - 12]",
+			       sps_info->log2_max_pic_order_cnt_lsb_minus4);
+			sps_info->log2_max_pic_order_cnt_lsb_minus4 = 12;
+			sps_parser_error |= BSPP_ERROR_CORRECTION_VALIDVALUE;
+		}
+	} else if (sps_info->pic_order_cnt_type == 1) {
+		sps_info->delta_pic_order_always_zero_flag = swsr_read_bits(swsr_context, 1);
+		sps_info->offset_for_non_ref_pic = swsr_read_signed_expgoulomb(swsr_context);
+		sps_info->offset_for_top_to_bottom_field = swsr_read_signed_expgoulomb
+										(swsr_context);
+		sps_info->num_ref_frames_in_pic_order_cnt_cycle = swsr_read_unsigned_expgoulomb
+										(swsr_context);
+		if (sps_info->num_ref_frames_in_pic_order_cnt_cycle > 255) {
+			pr_err("num_ref_frames_in_pic_order_cnt_cycle[%d] is not within range  [0 - 256]",
+			       sps_info->num_ref_frames_in_pic_order_cnt_cycle);
+			sps_parser_error |= BSPP_ERROR_INVALID_VALUE;
+		}
+
+		if (!sps_info->offset_for_ref_frame) {
+			sps_info->offset_for_ref_frame =
+				kmalloc((H264FW_MAX_CYCLE_REF_FRAMES * sizeof(unsigned int)),
+					GFP_KERNEL);
+			if (!sps_info->offset_for_ref_frame) {
+				pr_err("out of memory");
+				sps_parser_error |= BSPP_ERROR_OUT_OF_MEMORY;
+			}
+		}
+
+		if (sps_info->offset_for_ref_frame) {
+			VDEC_ASSERT(sps_info->num_ref_frames_in_pic_order_cnt_cycle <=
+				    H264FW_MAX_CYCLE_REF_FRAMES);
+			memset(sps_info->offset_for_ref_frame, 0x00,
+			       (H264FW_MAX_CYCLE_REF_FRAMES * sizeof(unsigned int)));
+			for (i = 0; i < sps_info->num_ref_frames_in_pic_order_cnt_cycle; i++) {
+				/* check the max value and if it crosses then exit from the loop */
+				sps_info->offset_for_ref_frame[i] = swsr_read_signed_expgoulomb
+										(swsr_context);
+			}
+		}
+	} else if (sps_info->pic_order_cnt_type != 2) {
+		sps_parser_error |= BSPP_ERROR_INVALID_VALUE;
+	}
+	sps_info->max_num_ref_frames = swsr_read_unsigned_expgoulomb(swsr_context);
+
+	if (sps_info->max_num_ref_frames > 16) {
+		pr_err("num_ref_frames[%d] is not within range [0 - 16]",
+		       sps_info->max_num_ref_frames);
+		sps_parser_error |= BSPP_ERROR_INVALID_VALUE;
+	}
+	sps_info->gaps_in_frame_num_value_allowed_flag = swsr_read_bits(swsr_context, 1);
+	sps_info->pic_width_in_mbs_minus1 = swsr_read_unsigned_expgoulomb(swsr_context);
+	if (sps_info->pic_width_in_mbs_minus1 >= MAX_WIDTH_IN_MBS) {
+		pr_err("pic_width_in_mbs_minus1[%d] is not within range",
+		       sps_info->pic_width_in_mbs_minus1);
+		sps_parser_error |= BSPP_ERROR_INVALID_VALUE;
+	}
+	sps_info->pic_height_in_map_units_minus1 = swsr_read_unsigned_expgoulomb(swsr_context);
+	if (sps_info->pic_height_in_map_units_minus1 >= MAX_HEIGHT_IN_MBS) {
+		pr_err("pic_height_in_map_units_minus1[%d] is not within range",
+		       sps_info->pic_height_in_map_units_minus1);
+		sps_parser_error |= BSPP_ERROR_INVALID_VALUE;
+	}
+
+	sps_info->frame_mbs_only_flag = swsr_read_bits(swsr_context, 1);
+	if (!sps_info->frame_mbs_only_flag)
+		sps_info->mb_adaptive_frame_field_flag = swsr_read_bits(swsr_context, 1);
+	else
+		sps_info->mb_adaptive_frame_field_flag = 0;
+
+	sps_info->direct_8x8_inference_flag = swsr_read_bits(swsr_context, 1);
+
+	sps_info->frame_cropping_flag = swsr_read_bits(swsr_context, 1);
+	if (sps_info->frame_cropping_flag) {
+		sps_info->frame_crop_left_offset = swsr_read_unsigned_expgoulomb(swsr_context);
+		sps_info->frame_crop_right_offset = swsr_read_unsigned_expgoulomb(swsr_context);
+		sps_info->frame_crop_top_offset = swsr_read_unsigned_expgoulomb(swsr_context);
+		sps_info->frame_crop_bottom_offset = swsr_read_unsigned_expgoulomb(swsr_context);
+	} else {
+		sps_info->frame_crop_left_offset = 0;
+		sps_info->frame_crop_right_offset = 0;
+		sps_info->frame_crop_top_offset = 0;
+		sps_info->frame_crop_bottom_offset = 0;
+	}
+
+	sps_info->vui_parameters_present_flag = swsr_read_bits(swsr_context, 1);
+	/* initialise matrix_coefficients to 2 (unspecified) */
+	vui_info->matrix_coefficients = 2;
+
+	if (sps_info->vui_parameters_present_flag) {
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("vui_parameters_present_flag is available");
+#endif
+		/* save the SPS parse error in temp variable */
+		vui_parser_error = bspp_h264_vui_parser(swsr_context, vui_info, sps_info);
+		if (vui_parser_error != BSPP_ERROR_NONE)
+			sps_parser_error  |= BSPP_ERROR_AUXDATA;
+
+#ifdef REDUCED_DPB_NO_PIC_REORDERING
+		vui_info->max_dec_frame_buffering = 1;
+		vui_info->num_reorder_frames = 0;
+#endif
+	}
+
+	if (sps_info->profile_idc == H264_PROFILE_MVC_HIGH ||
+	    sps_info->profile_idc == H264_PROFILE_MVC_STEREO) {
+		pr_err("No MVC Support for this version\n");
+	}
+
+	if (swsr_check_exception(swsr_context) != SWSR_EXCEPT_NO_EXCEPTION)
+		sps_parser_error |= BSPP_ERROR_INSUFFICIENT_DATA;
+
+	return sps_parser_error;
+}
+
+/*
+ * Parse the PPS NAL unit
+ */
+static enum bspp_error_type bspp_h264_pps_parser(void *swsr_context,
+						 void *str_res,
+						 struct bspp_h264_pps_info *h264_pps_info)
+{
+	int i, group, chroma_format_idc;
+	unsigned int number_bits_per_slicegroup_id;
+	unsigned char n_scaling_list;
+	unsigned char more_rbsp_data;
+	unsigned int result;
+	enum bspp_error_type pps_parse_error = BSPP_ERROR_NONE;
+
+	VDEC_ASSERT(swsr_context);
+
+	h264_pps_info->pps_id = swsr_read_unsigned_expgoulomb(swsr_context);
+	if (h264_pps_info->pps_id >= MAX_PPS_COUNT) {
+		pr_err("Picture Parameter Set(PPS) ID is not within the range");
+		h264_pps_info->pps_id = (int)BSPP_INVALID;
+		return BSPP_ERROR_UNSUPPORTED;
+	}
+	h264_pps_info->seq_parameter_set_id = swsr_read_unsigned_expgoulomb(swsr_context);
+	if (h264_pps_info->seq_parameter_set_id >= MAX_SPS_COUNT) {
+		pr_err("Sequence Parameter Set(SPS) ID is not within the range");
+		h264_pps_info->seq_parameter_set_id = (int)BSPP_INVALID;
+		return BSPP_ERROR_UNSUPPORTED;
+	}
+
+	{
+		/*
+		 * Get the chroma_format_idc from sps. Because of MVC sharing sps and subset sps ids
+		 * (H.7.4.1.2.1).
+		 * At this point is not clear if this pps refers to an sps or a subset sps.
+		 * It should be finehowever for the case of chroma_format_idc to try and locate
+		 * a subset sps if there isn't a normal one.
+		 */
+		struct bspp_h264_seq_hdr_info *h264_seq_hdr_info;
+		struct bspp_sequence_hdr_info *seq_hdr_info;
+
+		seq_hdr_info = bspp_get_sequ_hdr(str_res, h264_pps_info->seq_parameter_set_id);
+
+		if (!seq_hdr_info) {
+			seq_hdr_info = bspp_get_sequ_hdr(str_res,
+							 h264_pps_info->seq_parameter_set_id + 32);
+			if (!seq_hdr_info)
+				return BSPP_ERROR_NO_SEQUENCE_HDR;
+		}
+
+		h264_seq_hdr_info =
+			(struct bspp_h264_seq_hdr_info *)seq_hdr_info->secure_sequence_info;
+
+		chroma_format_idc = h264_seq_hdr_info->sps_info.chroma_format_idc;
+	}
+
+	h264_pps_info->entropy_coding_mode_flag = swsr_read_bits(swsr_context, 1);
+	h264_pps_info->pic_order_present_flag = swsr_read_bits(swsr_context, 1);
+	h264_pps_info->num_slice_groups_minus1 = swsr_read_unsigned_expgoulomb(swsr_context);
+	if ((h264_pps_info->num_slice_groups_minus1 + 1) >
+		MAX_SLICEGROUP_COUNT) {
+		h264_pps_info->num_slice_groups_minus1 =
+			MAX_SLICEGROUP_COUNT - 1;
+		pps_parse_error |= BSPP_ERROR_UNRECOVERABLE;
+	}
+
+	if (h264_pps_info->num_slice_groups_minus1 > 0) {
+		h264_pps_info->slice_group_map_type = swsr_read_unsigned_expgoulomb(swsr_context);
+		pr_err("slice_group_map_type is : %d, Parsed by BSPP",
+		       h264_pps_info->slice_group_map_type);
+		if (h264_pps_info->slice_group_map_type > 6) {
+			pr_err("slice_group_map_type [%d] is not within the range [ 0- 6 ]",
+			       h264_pps_info->slice_group_map_type);
+			       pps_parse_error |= BSPP_ERROR_UNRECOVERABLE;
+		}
+
+		if (h264_pps_info->slice_group_map_type == 0) {
+			for (group = 0; group <= h264_pps_info->num_slice_groups_minus1; group++) {
+				h264_pps_info->run_length_minus1[group] =
+					swsr_read_unsigned_expgoulomb(swsr_context);
+			}
+		} else if (h264_pps_info->slice_group_map_type == 2) {
+			for (group = 0; group < h264_pps_info->num_slice_groups_minus1; group++) {
+				h264_pps_info->top_left[group] = swsr_read_unsigned_expgoulomb
+										(swsr_context);
+				h264_pps_info->bottom_right[group] =
+					swsr_read_unsigned_expgoulomb(swsr_context);
+			}
+		} else if (h264_pps_info->slice_group_map_type == 3 ||
+			h264_pps_info->slice_group_map_type == 4 ||
+			h264_pps_info->slice_group_map_type == 5) {
+			h264_pps_info->slice_group_change_direction_flag = swsr_read_bits
+									(swsr_context, 1);
+			h264_pps_info->slice_group_change_rate_minus1 =
+				swsr_read_unsigned_expgoulomb(swsr_context);
+		} else if (h264_pps_info->slice_group_map_type == 6) {
+			h264_pps_info->pic_size_in_map_unit = swsr_read_unsigned_expgoulomb
+										(swsr_context);
+			if (h264_pps_info->pic_size_in_map_unit >= H264_MAX_SGM_SIZE) {
+				pr_err("pic_size_in_map_units_minus1 [%d] is not within the range",
+				       h264_pps_info->pic_size_in_map_unit);
+				pps_parse_error |= BSPP_ERROR_UNRECOVERABLE;
+			}
+			number_bits_per_slicegroup_id = h264ceillog2
+				(h264_pps_info->num_slice_groups_minus1 + 1);
+
+			if ((h264_pps_info->pic_size_in_map_unit + 1) >
+				h264_pps_info->h264_ppssgm_info.slicegroupidnum) {
+				unsigned char *slice_group_id =
+					kmalloc(((h264_pps_info->pic_size_in_map_unit + 1) *
+						sizeof(unsigned char)),
+						GFP_KERNEL);
+				if (!slice_group_id) {
+					pr_err("out of memory");
+					pps_parse_error |= BSPP_ERROR_OUT_OF_MEMORY;
+				} else {
+					pr_err("reallocating SGM info from size %lu bytes to size %lu bytes",
+					       h264_pps_info->h264_ppssgm_info.slicegroupidnum *
+					       sizeof(unsigned char),
+					       (h264_pps_info->pic_size_in_map_unit + 1) *
+					       sizeof(unsigned char));
+					if (h264_pps_info->h264_ppssgm_info.slice_group_id) {
+						memcpy
+						(slice_group_id,
+						 h264_pps_info->h264_ppssgm_info.slice_group_id,
+						 h264_pps_info->h264_ppssgm_info.slicegroupidnum *
+						 sizeof(unsigned char));
+						kfree
+						(h264_pps_info->h264_ppssgm_info.slice_group_id);
+					}
+					h264_pps_info->h264_ppssgm_info.slicegroupidnum =
+						(h264_pps_info->pic_size_in_map_unit + 1);
+					h264_pps_info->h264_ppssgm_info.slice_group_id =
+						slice_group_id;
+				}
+			}
+
+			VDEC_ASSERT((h264_pps_info->pic_size_in_map_unit + 1) <=
+				h264_pps_info->h264_ppssgm_info.slicegroupidnum);
+			for (i = 0; i <= h264_pps_info->pic_size_in_map_unit; i++)
+				h264_pps_info->h264_ppssgm_info.slice_group_id[i] =
+					swsr_read_bits(swsr_context, number_bits_per_slicegroup_id);
+		}
+	}
+
+	for (i = 0; i < H264FW_MAX_REFPIC_LISTS; i++) {
+		h264_pps_info->num_ref_idx_lx_active_minus1[i] = swsr_read_unsigned_expgoulomb
+										(swsr_context);
+		if (h264_pps_info->num_ref_idx_lx_active_minus1[i] >=
+			SL_MAX_REF_IDX) {
+			pr_err("num_ref_idx_lx_active_minus1[%d] [%d] is not within the range",
+			       i, h264_pps_info->num_ref_idx_lx_active_minus1[i]);
+			pps_parse_error |= BSPP_ERROR_UNRECOVERABLE;
+		}
+	}
+
+	h264_pps_info->weighted_pred_flag = swsr_read_bits(swsr_context, 1);
+	h264_pps_info->weighted_bipred_idc = swsr_read_bits(swsr_context, 2);
+	h264_pps_info->pic_init_qp_minus26 = swsr_read_signed_expgoulomb(swsr_context);
+	if (h264_pps_info->pic_init_qp_minus26 > 26)
+		pr_err("pic_init_qp_minus26[%d] is not within the range [-25 , 26]",
+		       h264_pps_info->pic_init_qp_minus26);
+
+	h264_pps_info->pic_init_qs_minus26 = swsr_read_signed_expgoulomb(swsr_context);
+	if (h264_pps_info->pic_init_qs_minus26 > 26)
+		pr_err("pic_init_qs_minus26[%d] is not within the range [-25 , 26]",
+		       h264_pps_info->pic_init_qs_minus26);
+
+	h264_pps_info->chroma_qp_index_offset = swsr_read_signed_expgoulomb(swsr_context);
+	if (h264_pps_info->chroma_qp_index_offset > H264_MAX_CHROMA_QP_INDEX_OFFSET)
+		h264_pps_info->chroma_qp_index_offset = H264_MAX_CHROMA_QP_INDEX_OFFSET;
+
+	else if (h264_pps_info->chroma_qp_index_offset < H264_MIN_CHROMA_QP_INDEX_OFFSET)
+		h264_pps_info->chroma_qp_index_offset = H264_MIN_CHROMA_QP_INDEX_OFFSET;
+
+	h264_pps_info->deblocking_filter_control_present_flag = swsr_read_bits(swsr_context, 1);
+	h264_pps_info->constrained_intra_pred_flag = swsr_read_bits(swsr_context, 1);
+	h264_pps_info->redundant_pic_cnt_present_flag = swsr_read_bits(swsr_context, 1);
+
+	/* Check for more rbsp data. */
+	result = swsr_check_more_rbsp_data(swsr_context, &more_rbsp_data);
+	if (result == 0 && more_rbsp_data) {
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("More RBSP data is available");
+#endif
+		/* Fidelity Range Extensions Stuff */
+		h264_pps_info->transform_8x8_mode_flag = swsr_read_bits(swsr_context, 1);
+		h264_pps_info->pic_scaling_matrix_present_flag = swsr_read_bits(swsr_context, 1);
+		if (h264_pps_info->pic_scaling_matrix_present_flag) {
+			if (!h264_pps_info->scllst4x4pic) {
+				h264_pps_info->scllst4x4pic =
+					kmalloc((sizeof(unsigned char[H264FW_NUM_4X4_LISTS]
+								[H264FW_4X4_SIZE])), GFP_KERNEL);
+				if (!h264_pps_info->scllst4x4pic) {
+					pps_parse_error |= BSPP_ERROR_OUT_OF_MEMORY;
+				} else {
+					VDEC_ASSERT(h264_pps_info->scllst4x4pic);
+					memset(h264_pps_info->scllst4x4pic, 0x00,
+					       sizeof(unsigned char[H264FW_NUM_4X4_LISTS]
+					       [H264FW_4X4_SIZE]));
+				}
+			}
+			if (!h264_pps_info->scllst8x8pic) {
+				h264_pps_info->scllst8x8pic =
+					kmalloc((sizeof(unsigned char[H264FW_NUM_8X8_LISTS]
+								[H264FW_8X8_SIZE])), GFP_KERNEL);
+				if (!h264_pps_info->scllst8x8pic) {
+					pps_parse_error |= BSPP_ERROR_OUT_OF_MEMORY;
+				} else {
+					VDEC_ASSERT(h264_pps_info->scllst8x8pic);
+					memset(h264_pps_info->scllst8x8pic, 0x00,
+					       sizeof(unsigned char[H264FW_NUM_8X8_LISTS]
+					       [H264FW_8X8_SIZE]));
+				}
+			}
+		{
+			unsigned char(*scllst4x4pic)[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE] =
+					(unsigned char (*)[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE])
+					h264_pps_info->scllst4x4pic;
+			unsigned char(*scllst8x8pic)[H264FW_NUM_8X8_LISTS][H264FW_8X8_SIZE] =
+					(unsigned char (*)[H264FW_NUM_8X8_LISTS][H264FW_8X8_SIZE])
+					h264_pps_info->scllst8x8pic;
+
+			/*
+			 * For chroma_format =3 (YUV444) total list would be 12
+			 * if transform_8x8_mode_flag is enabled else  6.
+			 */
+			n_scaling_list = 6 + (chroma_format_idc != 3 ? 2 : 6) *
+				h264_pps_info->transform_8x8_mode_flag;
+			if (n_scaling_list > 12)
+				pps_parse_error |= BSPP_ERROR_UNRECOVERABLE;
+
+			VDEC_ASSERT(h264_pps_info->scllst4x4pic);
+			VDEC_ASSERT(h264_pps_info->scllst8x8pic);
+			for (i = 0; i < n_scaling_list; i++) {
+				unsigned char *ptr =
+					&h264_pps_info->usedefaultscalingmatrixflag_pic[i];
+
+				h264_pps_info->pic_scaling_list_present_flag[i] =
+					swsr_read_bits(swsr_context, 1);
+				if (h264_pps_info->pic_scaling_list_present_flag[i]) {
+					if (i < 6)
+						pps_parse_error |=
+							bspp_h264_scl_listparser
+							(swsr_context,
+							 (*scllst4x4pic)[i], 16, ptr);
+					else
+						pps_parse_error |=
+							bspp_h264_scl_listparser
+							(swsr_context,
+							(*scllst8x8pic)[i - 6], 64, ptr);
+				}
+			}
+		}
+		}
+		h264_pps_info->second_chroma_qp_index_offset = swsr_read_signed_expgoulomb
+										(swsr_context);
+
+		if (h264_pps_info->second_chroma_qp_index_offset > H264_MAX_CHROMA_QP_INDEX_OFFSET)
+			h264_pps_info->second_chroma_qp_index_offset =
+				H264_MAX_CHROMA_QP_INDEX_OFFSET;
+		else if (h264_pps_info->second_chroma_qp_index_offset <
+			H264_MIN_CHROMA_QP_INDEX_OFFSET)
+			h264_pps_info->second_chroma_qp_index_offset =
+				H264_MIN_CHROMA_QP_INDEX_OFFSET;
+	} else {
+		h264_pps_info->second_chroma_qp_index_offset =
+			h264_pps_info->chroma_qp_index_offset;
+	}
+
+	if (swsr_check_exception(swsr_context) != SWSR_EXCEPT_NO_EXCEPTION)
+		pps_parse_error |= BSPP_ERROR_INSUFFICIENT_DATA;
+
+	return pps_parse_error;
+}
+
+static int bspp_h264_release_sequ_hdr_info(void *str_alloc, void *secure_sps_info)
+{
+	struct bspp_h264_seq_hdr_info *h264_seq_hdr_info =
+					(struct bspp_h264_seq_hdr_info *)secure_sps_info;
+
+	if (!h264_seq_hdr_info)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	return 0;
+}
+
+static int bspp_h264_reset_seq_hdr_info(void *secure_sps_info)
+{
+	struct bspp_h264_seq_hdr_info *h264_seq_hdr_info = NULL;
+	unsigned int *nal_hrd_bitrate_valueminus1 = NULL;
+	unsigned int *vcl_hrd_bitrate_valueminus1 = NULL;
+	unsigned int *nal_hrd_cpbsize_valueminus1 = NULL;
+	unsigned int *vcl_hrd_cpbsize_valueminus1 = NULL;
+	unsigned char *nal_hrd_cbrflag = NULL;
+	unsigned char *vcl_hrd_cbrflag = NULL;
+	unsigned int *offset_for_ref_frame = NULL;
+	unsigned char *scllst4x4seq = NULL;
+	unsigned char *scllst8x8seq = NULL;
+
+	if (!secure_sps_info)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	h264_seq_hdr_info = (struct bspp_h264_seq_hdr_info *)secure_sps_info;
+
+	offset_for_ref_frame = h264_seq_hdr_info->sps_info.offset_for_ref_frame;
+	scllst4x4seq = h264_seq_hdr_info->sps_info.scllst4x4seq;
+	scllst8x8seq = h264_seq_hdr_info->sps_info.scllst8x8seq;
+	nal_hrd_bitrate_valueminus1 =
+		h264_seq_hdr_info->vui_info.nal_hrd_parameters.bit_rate_value_minus1;
+	vcl_hrd_bitrate_valueminus1 =
+		h264_seq_hdr_info->vui_info.vcl_hrd_parameters.bit_rate_value_minus1;
+	nal_hrd_cpbsize_valueminus1 =
+		h264_seq_hdr_info->vui_info.nal_hrd_parameters.cpb_size_value_minus1;
+	vcl_hrd_cpbsize_valueminus1 =
+		h264_seq_hdr_info->vui_info.vcl_hrd_parameters.cpb_size_value_minus1;
+	nal_hrd_cbrflag = h264_seq_hdr_info->vui_info.nal_hrd_parameters.cbr_flag;
+	vcl_hrd_cbrflag = h264_seq_hdr_info->vui_info.vcl_hrd_parameters.cbr_flag;
+
+	/* Cleaning vui_info */
+	if (h264_seq_hdr_info->vui_info.nal_hrd_parameters.bit_rate_value_minus1)
+		memset(h264_seq_hdr_info->vui_info.nal_hrd_parameters.bit_rate_value_minus1,
+		       0x00, VDEC_H264_MAXIMUMVALUEOFCPB_CNT * sizeof(unsigned int));
+
+	if (h264_seq_hdr_info->vui_info.nal_hrd_parameters.cpb_size_value_minus1)
+		memset(h264_seq_hdr_info->vui_info.nal_hrd_parameters.cpb_size_value_minus1,
+		       0x00, VDEC_H264_MAXIMUMVALUEOFCPB_CNT * sizeof(unsigned int));
+
+	if (h264_seq_hdr_info->vui_info.vcl_hrd_parameters.cpb_size_value_minus1)
+		memset(h264_seq_hdr_info->vui_info.vcl_hrd_parameters.cpb_size_value_minus1,
+		       0x00, VDEC_H264_MAXIMUMVALUEOFCPB_CNT * sizeof(unsigned int));
+
+	if (h264_seq_hdr_info->vui_info.nal_hrd_parameters.cbr_flag)
+		memset(h264_seq_hdr_info->vui_info.nal_hrd_parameters.cbr_flag,
+		       0x00, VDEC_H264_MAXIMUMVALUEOFCPB_CNT * sizeof(unsigned char));
+
+	if (h264_seq_hdr_info->vui_info.vcl_hrd_parameters.cbr_flag)
+		memset(h264_seq_hdr_info->vui_info.vcl_hrd_parameters.cbr_flag,
+		       0x00, VDEC_H264_MAXIMUMVALUEOFCPB_CNT * sizeof(unsigned char));
+
+	/* Cleaning sps_info */
+	if (h264_seq_hdr_info->sps_info.offset_for_ref_frame)
+		memset(h264_seq_hdr_info->sps_info.offset_for_ref_frame, 0x00,
+		       H264FW_MAX_CYCLE_REF_FRAMES * sizeof(unsigned int));
+
+	if (h264_seq_hdr_info->sps_info.scllst4x4seq)
+		memset(h264_seq_hdr_info->sps_info.scllst4x4seq, 0x00,
+		       sizeof(unsigned char[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE]));
+
+	if (h264_seq_hdr_info->sps_info.scllst8x8seq)
+		memset(h264_seq_hdr_info->sps_info.scllst8x8seq, 0x00,
+		       sizeof(unsigned char[H264FW_NUM_8X8_LISTS][H264FW_8X8_SIZE]));
+
+	/* Erasing the structure */
+	memset(h264_seq_hdr_info, 0, sizeof(*h264_seq_hdr_info));
+
+	/* Restoring pointers */
+	h264_seq_hdr_info->sps_info.offset_for_ref_frame = offset_for_ref_frame;
+	h264_seq_hdr_info->sps_info.scllst4x4seq = scllst4x4seq;
+	h264_seq_hdr_info->sps_info.scllst8x8seq = scllst8x8seq;
+
+	h264_seq_hdr_info->vui_info.nal_hrd_parameters.bit_rate_value_minus1 =
+		nal_hrd_bitrate_valueminus1;
+	h264_seq_hdr_info->vui_info.vcl_hrd_parameters.bit_rate_value_minus1 =
+		vcl_hrd_bitrate_valueminus1;
+
+	h264_seq_hdr_info->vui_info.nal_hrd_parameters.cpb_size_value_minus1 =
+		nal_hrd_cpbsize_valueminus1;
+	h264_seq_hdr_info->vui_info.vcl_hrd_parameters.cpb_size_value_minus1 =
+		vcl_hrd_cpbsize_valueminus1;
+
+	h264_seq_hdr_info->vui_info.nal_hrd_parameters.cbr_flag = nal_hrd_cbrflag;
+	h264_seq_hdr_info->vui_info.vcl_hrd_parameters.cbr_flag = vcl_hrd_cbrflag;
+
+	return 0;
+}
+
+static int bspp_h264_reset_pps_info(void *secure_pps_info)
+{
+	struct bspp_h264_pps_info *h264_pps_info = NULL;
+	unsigned short slicegroupidnum = 0;
+	unsigned char *slice_group_id = NULL;
+	unsigned char *scllst4x4pic = NULL;
+	unsigned char *scllst8x8pic = NULL;
+
+	if (!secure_pps_info)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	h264_pps_info = (struct bspp_h264_pps_info *)secure_pps_info;
+
+	/*
+	 * Storing temp values (we want to leave the SGM structure
+	 * it may be useful again instead of reallocating later
+	 */
+	slice_group_id = h264_pps_info->h264_ppssgm_info.slice_group_id;
+	slicegroupidnum = h264_pps_info->h264_ppssgm_info.slicegroupidnum;
+	scllst4x4pic = h264_pps_info->scllst4x4pic;
+	scllst8x8pic = h264_pps_info->scllst8x8pic;
+
+	if (h264_pps_info->h264_ppssgm_info.slice_group_id)
+		memset(h264_pps_info->h264_ppssgm_info.slice_group_id, 0x00,
+		       h264_pps_info->h264_ppssgm_info.slicegroupidnum * sizeof(unsigned char));
+
+	if (h264_pps_info->scllst4x4pic)
+		memset(h264_pps_info->scllst4x4pic, 0x00,
+		       sizeof(unsigned char[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE]));
+
+	if (h264_pps_info->scllst8x8pic)
+		memset(h264_pps_info->scllst8x8pic, 0x00,
+		       sizeof(unsigned char[H264FW_NUM_8X8_LISTS][H264FW_8X8_SIZE]));
+
+	/* Erasing the structure */
+	memset(h264_pps_info, 0x00, sizeof(*h264_pps_info));
+
+	/* Copy the temp variable back */
+	h264_pps_info->h264_ppssgm_info.slicegroupidnum = slicegroupidnum;
+	h264_pps_info->h264_ppssgm_info.slice_group_id = slice_group_id;
+	h264_pps_info->scllst4x4pic = scllst4x4pic;
+	h264_pps_info->scllst8x8pic = scllst8x8pic;
+
+	return 0;
+}
+
+static enum bspp_error_type bspp_h264_pict_hdr_parser
+					(void *swsr_context, void *str_res,
+					 struct bspp_h264_slice_hdr_info *h264_slice_hdr_info,
+					 struct bspp_pps_info **pps_info,
+					 struct bspp_sequence_hdr_info **seq_hdr_info,
+					 enum h264_nalunittype nal_unit_type,
+					 unsigned char nal_ref_idc)
+{
+	enum bspp_error_type slice_parse_error = BSPP_ERROR_NONE;
+	struct bspp_h264_pps_info *h264_pps_info;
+	struct bspp_pps_info *pps_info_loc;
+	struct bspp_h264_seq_hdr_info *h264_seq_hdr_info;
+	struct bspp_sequence_hdr_info *seq_hdr_info_loc;
+	int id_loc;
+
+	VDEC_ASSERT(swsr_context);
+
+	memset(h264_slice_hdr_info, 0, sizeof(*h264_slice_hdr_info));
+
+	h264_slice_hdr_info->first_mb_in_slice = swsr_read_unsigned_expgoulomb(swsr_context);
+	h264_slice_hdr_info->slice_type = (enum bspp_h264_slice_type)swsr_read_unsigned_expgoulomb
+										(swsr_context);
+	if ((unsigned int)h264_slice_hdr_info->slice_type > 9) {
+		pr_err("Slice Type [%d] invalid, set to P", h264_slice_hdr_info->slice_type);
+		h264_slice_hdr_info->slice_type = (enum bspp_h264_slice_type)0;
+		slice_parse_error |= BSPP_ERROR_CORRECTION_VALIDVALUE;
+	}
+	h264_slice_hdr_info->slice_type =
+		(enum bspp_h264_slice_type)(h264_slice_hdr_info->slice_type % 5);
+
+	h264_slice_hdr_info->pps_id = swsr_read_unsigned_expgoulomb(swsr_context);
+	if (h264_slice_hdr_info->pps_id >= MAX_PPS_COUNT) {
+		pr_err("Picture Parameter ID [%d] invalid, set to 0", h264_slice_hdr_info->pps_id);
+		h264_slice_hdr_info->pps_id = 0;
+		slice_parse_error |= BSPP_ERROR_CORRECTION_VALIDVALUE;
+	}
+
+	/* Set relevant PPS and SPS */
+	pps_info_loc = bspp_get_pps_hdr(str_res, h264_slice_hdr_info->pps_id);
+
+	if (!pps_info_loc) {
+		slice_parse_error |= BSPP_ERROR_NO_PPS;
+		goto error;
+	}
+	h264_pps_info = (struct bspp_h264_pps_info *)pps_info_loc->secure_pps_info;
+	if (!h264_pps_info) {
+		slice_parse_error |= BSPP_ERROR_NO_PPS;
+		goto error;
+	}
+	VDEC_ASSERT(h264_pps_info->pps_id == h264_slice_hdr_info->pps_id);
+	*pps_info = pps_info_loc;
+
+	/* seq_parameter_set_id is always in range 0-31,
+	 * so we can add offset indicating subsequence header
+	 */
+	id_loc = h264_pps_info->seq_parameter_set_id;
+	id_loc = (nal_unit_type == H264_NALTYPE_SLICE_SCALABLE ||
+		nal_unit_type == H264_NALTYPE_SLICE_IDR_SCALABLE ||
+		nal_unit_type == H264_NALTYPE_SUBSET_SPS) ? id_loc + 32 : id_loc;
+
+	seq_hdr_info_loc = bspp_get_sequ_hdr(str_res, id_loc);
+
+	if (!seq_hdr_info_loc) {
+		slice_parse_error |= BSPP_ERROR_NO_SEQUENCE_HDR;
+		goto error;
+	}
+	h264_seq_hdr_info = (struct bspp_h264_seq_hdr_info *)seq_hdr_info_loc->secure_sequence_info;
+	VDEC_ASSERT((unsigned int)h264_seq_hdr_info->sps_info.seq_parameter_set_id ==
+		h264_pps_info->seq_parameter_set_id);
+	*seq_hdr_info = seq_hdr_info_loc;
+
+	/*
+	 * For MINIMAL parsing in secure mode, slice header parsing can stop
+	 * here, may be problematic with field-coded streams and splitting
+	 * fields
+	 */
+	if (h264_seq_hdr_info->sps_info.separate_colour_plane_flag)
+		h264_slice_hdr_info->colour_plane_id = swsr_read_bits(swsr_context, 2);
+
+	else
+		h264_slice_hdr_info->colour_plane_id = 0;
+
+	h264_slice_hdr_info->frame_num = swsr_read_bits
+					(swsr_context,
+					 h264_seq_hdr_info->sps_info.log2_max_frame_num_minus4
+					 + 4);
+
+	VDEC_ASSERT(h264_slice_hdr_info->frame_num <
+		(1UL << (h264_seq_hdr_info->sps_info.log2_max_frame_num_minus4 + 4)));
+
+	if (!h264_seq_hdr_info->sps_info.frame_mbs_only_flag) {
+		if (h264_slice_hdr_info->slice_type == B_SLICE &&
+		    !h264_seq_hdr_info->sps_info.direct_8x8_inference_flag)
+			slice_parse_error |= BSPP_ERROR_INVALID_VALUE;
+
+		h264_slice_hdr_info->field_pic_flag = swsr_read_bits(swsr_context, 1);
+		if (h264_slice_hdr_info->field_pic_flag)
+			h264_slice_hdr_info->bottom_field_flag = swsr_read_bits(swsr_context, 1);
+		else
+			h264_slice_hdr_info->bottom_field_flag = 0;
+	} else {
+		h264_slice_hdr_info->field_pic_flag = 0;
+		h264_slice_hdr_info->bottom_field_flag = 0;
+	}
+
+	/*
+	 * At this point we have everything we need, but we still lack all the
+	 * conditions for detecting new pictures (needed for error cases)
+	 */
+	if (nal_unit_type == H264_NALTYPE_IDR_SLICE)
+		h264_slice_hdr_info->idr_pic_id = swsr_read_unsigned_expgoulomb(swsr_context);
+
+	if (h264_seq_hdr_info->sps_info.pic_order_cnt_type == 0) {
+		h264_slice_hdr_info->pic_order_cnt_lsb = swsr_read_bits
+				(swsr_context,
+				 h264_seq_hdr_info->sps_info.log2_max_pic_order_cnt_lsb_minus4 + 4);
+		if (h264_pps_info->pic_order_present_flag && !h264_slice_hdr_info->field_pic_flag)
+			h264_slice_hdr_info->delta_pic_order_cnt_bottom =
+							swsr_read_signed_expgoulomb(swsr_context);
+	}
+
+	if (h264_seq_hdr_info->sps_info.pic_order_cnt_type == 1 &&
+	    !h264_seq_hdr_info->sps_info.delta_pic_order_always_zero_flag) {
+		h264_slice_hdr_info->delta_pic_order_cnt[0] = swsr_read_signed_expgoulomb
+									(swsr_context);
+		if (h264_pps_info->pic_order_present_flag && !h264_slice_hdr_info->field_pic_flag)
+			h264_slice_hdr_info->delta_pic_order_cnt[1] = swsr_read_signed_expgoulomb
+										(swsr_context);
+	}
+
+	if (h264_pps_info->redundant_pic_cnt_present_flag)
+		h264_slice_hdr_info->redundant_pic_cnt =
+			swsr_read_unsigned_expgoulomb(swsr_context);
+
+	/* For FMO streams, we need to go further */
+	if (h264_pps_info->num_slice_groups_minus1 != 0 &&
+	    h264_pps_info->slice_group_map_type >= 3 &&
+	    h264_pps_info->slice_group_map_type <= 5) {
+		if (h264_slice_hdr_info->slice_type == B_SLICE)
+			swsr_read_bits(swsr_context, 1);
+
+		if (h264_slice_hdr_info->slice_type == P_SLICE ||
+		    h264_slice_hdr_info->slice_type == SP_SLICE ||
+		    h264_slice_hdr_info->slice_type == B_SLICE) {
+			h264_slice_hdr_info->num_ref_idx_active_override_flag =
+				swsr_read_bits(swsr_context, 1);
+			if (h264_slice_hdr_info->num_ref_idx_active_override_flag) {
+				h264_slice_hdr_info->num_ref_idx_lx_active_minus1[0] =
+					swsr_read_unsigned_expgoulomb(swsr_context);
+				if (h264_slice_hdr_info->slice_type == B_SLICE)
+					h264_slice_hdr_info->num_ref_idx_lx_active_minus1[1] =
+						swsr_read_unsigned_expgoulomb(swsr_context);
+			}
+		}
+
+		if (h264_slice_hdr_info->slice_type != SI_SLICE &&
+		    h264_slice_hdr_info->slice_type != I_SLICE) {
+			/* Reference picture list modification */
+			/* parse reordering info and pack into commands */
+			unsigned int i;
+			unsigned int cmd_num, list_num;
+			unsigned int command;
+
+			i = (h264_slice_hdr_info->slice_type == B_SLICE) ? 2 : 1;
+
+			for (list_num = 0; list_num < i; list_num++) {
+				cmd_num = 0;
+				if (swsr_read_bits(swsr_context, 1)) {
+					do {
+						command =
+							swsr_read_unsigned_expgoulomb(swsr_context);
+					if (command != 3) {
+						swsr_read_unsigned_expgoulomb(swsr_context);
+						cmd_num++;
+					}
+					} while (command != 3 && cmd_num <= SL_MAX_REF_IDX);
+				}
+			}
+		}
+
+		if ((h264_pps_info->weighted_pred_flag &&
+		     h264_slice_hdr_info->slice_type == P_SLICE) ||
+		    (h264_pps_info->weighted_bipred_idc &&
+		     h264_slice_hdr_info->slice_type == B_SLICE)) {
+			int mono_chrome;
+			unsigned int list, i, j, k;
+
+			mono_chrome = (!h264_seq_hdr_info->sps_info.chroma_format_idc) ? 1 : 0;
+
+			swsr_read_unsigned_expgoulomb(swsr_context);
+			if (!mono_chrome)
+				swsr_read_unsigned_expgoulomb(swsr_context);
+
+			k = (h264_slice_hdr_info->slice_type == B_SLICE) ? 2 : 1;
+
+			for (list = 0; list < k; list++) {
+				for (i = 0;
+					i <=
+					h264_slice_hdr_info->num_ref_idx_lx_active_minus1[list];
+					i++) {
+					if (swsr_read_bits(swsr_context, 1)) {
+						swsr_read_signed_expgoulomb(swsr_context);
+						swsr_read_signed_expgoulomb(swsr_context);
+					}
+
+				if (!mono_chrome && (swsr_read_bits(swsr_context, 1))) {
+					for (j = 0; j < 2; j++) {
+						swsr_read_signed_expgoulomb
+								(swsr_context);
+						swsr_read_signed_expgoulomb
+								(swsr_context);
+					}
+				}
+				}
+			}
+		}
+
+		if (nal_ref_idc != 0) {
+			unsigned int memmanop;
+
+			if (nal_unit_type == H264_NALTYPE_IDR_SLICE) {
+				swsr_read_bits(swsr_context, 1);
+				swsr_read_bits(swsr_context, 1);
+			}
+			if (swsr_read_bits(swsr_context, 1)) {
+				do {
+					/* clamp 0--6 */
+					memmanop = swsr_read_unsigned_expgoulomb
+								(swsr_context);
+				if (memmanop != 0 && memmanop != 5) {
+					if (memmanop == 3) {
+						swsr_read_unsigned_expgoulomb
+							(swsr_context);
+						swsr_read_unsigned_expgoulomb
+							(swsr_context);
+					} else {
+						swsr_read_unsigned_expgoulomb
+							(swsr_context);
+					}
+				}
+				} while (memmanop != 0);
+			}
+		}
+
+		if (h264_pps_info->entropy_coding_mode_flag &&
+		    h264_slice_hdr_info->slice_type != I_SLICE)
+			swsr_read_unsigned_expgoulomb(swsr_context);
+
+		swsr_read_signed_expgoulomb(swsr_context);
+
+		if (h264_slice_hdr_info->slice_type == SP_SLICE ||
+		    h264_slice_hdr_info->slice_type == SI_SLICE) {
+			if (h264_slice_hdr_info->slice_type == SP_SLICE)
+				swsr_read_bits(swsr_context, 1);
+
+			/* slice_qs_delta */
+			swsr_read_signed_expgoulomb(swsr_context);
+		}
+
+		if (h264_pps_info->deblocking_filter_control_present_flag) {
+			if (swsr_read_unsigned_expgoulomb(swsr_context) != 1) {
+				swsr_read_signed_expgoulomb(swsr_context);
+				swsr_read_signed_expgoulomb(swsr_context);
+			}
+		}
+
+		if (h264_pps_info->slice_group_map_type >= 3 &&
+		    h264_pps_info->slice_group_map_type <= 5) {
+			unsigned int num_slice_group_map_units =
+				(h264_seq_hdr_info->sps_info.pic_height_in_map_units_minus1 + 1) *
+				(h264_seq_hdr_info->sps_info.pic_width_in_mbs_minus1 + 1);
+
+			unsigned short slice_group_change_rate =
+				(h264_pps_info->slice_group_change_rate_minus1 + 1);
+
+			unsigned int width = h264ceillog2(num_slice_group_map_units /
+					slice_group_change_rate +
+					(num_slice_group_map_units % slice_group_change_rate ==
+					 0 ? 0 : 1) + 1);                          /* (7-32) */
+			h264_slice_hdr_info->slice_group_change_cycle = swsr_read_bits(swsr_context,
+										       width);
+		}
+	}
+
+error:
+	return slice_parse_error;
+}
+
+static void bspp_h264_select_scaling_list(struct h264fw_picture_ps *h264fw_pps_info,
+					  struct bspp_h264_pps_info *h264_pps_info,
+					  struct bspp_h264_seq_hdr_info *h264_seq_hdr_info)
+{
+	unsigned int num8x8_lists;
+	unsigned int i;
+	const unsigned char *quant_matrix = NULL;
+	unsigned char (*scllst4x4pic)[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE] =
+	(unsigned char (*)[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE])h264_pps_info->scllst4x4pic;
+	unsigned char (*scllst8x8pic)[H264FW_NUM_8X8_LISTS][H264FW_8X8_SIZE] =
+	(unsigned char (*)[H264FW_NUM_8X8_LISTS][H264FW_8X8_SIZE])h264_pps_info->scllst8x8pic;
+
+	unsigned char (*scllst4x4seq)[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE] =
+		(unsigned char (*)[H264FW_NUM_4X4_LISTS][H264FW_4X4_SIZE])
+		h264_seq_hdr_info->sps_info.scllst4x4seq;
+	unsigned char (*scllst8x8seq)[H264FW_NUM_8X8_LISTS][H264FW_8X8_SIZE] =
+		(unsigned char (*)[H264FW_NUM_8X8_LISTS][H264FW_8X8_SIZE])
+		h264_seq_hdr_info->sps_info.scllst8x8seq;
+
+	if (h264_seq_hdr_info->sps_info.seq_scaling_matrix_present_flag) {
+		VDEC_ASSERT(h264_seq_hdr_info->sps_info.scllst4x4seq);
+		VDEC_ASSERT(h264_seq_hdr_info->sps_info.scllst8x8seq);
+	}
+
+	if (h264_pps_info->pic_scaling_matrix_present_flag) {
+		for (i = 0; i < H264FW_NUM_4X4_LISTS; i++) {
+			if (h264_pps_info->pic_scaling_list_present_flag[i]) {
+				if (h264_pps_info->usedefaultscalingmatrixflag_pic[i])
+					quant_matrix =
+						(i > 2) ? default_4x4_inter : default_4x4_intra;
+				else
+					quant_matrix = (*scllst4x4pic)[i];
+
+			} else {
+				if (h264_seq_hdr_info->sps_info.seq_scaling_matrix_present_flag) {
+					/* SPS matrix present - use fallback rule B */
+					/* first 4x4 Intra list */
+					if (i == 0) {
+						if
+				(h264_seq_hdr_info->sps_info.seq_scaling_list_present_flag[i] &&
+				!h264_seq_hdr_info->sps_info.usedefaultscalingmatrixflag_seq[i]) {
+							VDEC_ASSERT
+							(h264_seq_hdr_info->sps_info.scllst4x4seq);
+					if (scllst4x4seq)
+						quant_matrix = (*scllst4x4seq)[i];
+					} else {
+						quant_matrix = default_4x4_intra;
+					}
+					}
+					/* first 4x4 Inter list */
+					else if (i == 3) {
+						if
+				(h264_seq_hdr_info->sps_info.seq_scaling_list_present_flag[i] &&
+				!h264_seq_hdr_info->sps_info.usedefaultscalingmatrixflag_seq[i]) {
+							VDEC_ASSERT
+							(h264_seq_hdr_info->sps_info.scllst4x4seq);
+					if (scllst4x4seq)
+						quant_matrix = (*scllst4x4seq)[i];
+					} else {
+						quant_matrix = default_4x4_inter;
+					}
+					} else {
+						quant_matrix =
+							h264fw_pps_info->scalinglist4x4[i - 1];
+					}
+				} else {
+					/* SPS matrix not present - use fallback rule A */
+					/* first 4x4 Intra list */
+					if (i == 0)
+						quant_matrix = default_4x4_intra;
+					/* first 4x4 Interlist */
+					else if (i == 3)
+						quant_matrix = default_4x4_inter;
+					else
+						quant_matrix =
+							h264fw_pps_info->scalinglist4x4[i - 1];
+				}
+			}
+			if (!quant_matrix) {
+				VDEC_ASSERT(0);
+				return;
+			}
+			/* copy correct 4x4 list to output - as selected by PPS */
+			memcpy(h264fw_pps_info->scalinglist4x4[i], quant_matrix,
+			       sizeof(h264fw_pps_info->scalinglist4x4[i]));
+		}
+	} else {
+		/* PPS matrix not present, use SPS information */
+		if (h264_seq_hdr_info->sps_info.seq_scaling_matrix_present_flag) {
+			for (i = 0; i < H264FW_NUM_4X4_LISTS; i++) {
+				if (h264_seq_hdr_info->sps_info.seq_scaling_list_present_flag[i]) {
+					if
+					(h264_seq_hdr_info->sps_info.usedefaultscalingmatrixflag_seq
+											[i]) {
+						quant_matrix = (i > 2) ? default_4x4_inter
+							: default_4x4_intra;
+					} else {
+						VDEC_ASSERT
+							(h264_seq_hdr_info->sps_info.scllst4x4seq);
+					if (scllst4x4seq)
+						quant_matrix = (*scllst4x4seq)[i];
+					}
+				} else {
+					/* SPS list not present - use fallback rule A */
+					/* first 4x4 Intra list */
+					if (i == 0)
+						quant_matrix = default_4x4_intra;
+					else if (i == 3) /* first 4x4 Inter list */
+						quant_matrix = default_4x4_inter;
+					else
+						quant_matrix =
+							h264fw_pps_info->scalinglist4x4[i - 1];
+				}
+				if (quant_matrix) {
+					/* copy correct 4x4 list to output - as selected by SPS */
+					memcpy(h264fw_pps_info->scalinglist4x4[i], quant_matrix,
+					       sizeof(h264fw_pps_info->scalinglist4x4[i]));
+				}
+			}
+		} else {
+			/* SPS matrix not present - use flat lists */
+			quant_matrix = default_4x4_org;
+			for (i = 0; i < H264FW_NUM_4X4_LISTS; i++)
+				memcpy(h264fw_pps_info->scalinglist4x4[i], quant_matrix,
+				       sizeof(h264fw_pps_info->scalinglist4x4[i]));
+		}
+	}
+
+	/* 8x8 matrices */
+	num8x8_lists = (h264_seq_hdr_info->sps_info.chroma_format_idc == 3) ? 6 : 2;
+	if (h264_pps_info->transform_8x8_mode_flag) {
+		unsigned char *seq_scllstflg =
+			h264_seq_hdr_info->sps_info.seq_scaling_list_present_flag;
+		unsigned char *def_sclmatflg_seq =
+			h264_seq_hdr_info->sps_info.usedefaultscalingmatrixflag_seq;
+
+		if (h264_pps_info->pic_scaling_matrix_present_flag) {
+			for (i = 0; i < num8x8_lists; i++) {
+				if (h264_pps_info->pic_scaling_list_present_flag[i +
+					H264FW_NUM_4X4_LISTS]) {
+					if (h264_pps_info->usedefaultscalingmatrixflag_pic[i +
+							H264FW_NUM_4X4_LISTS]) {
+						quant_matrix = (i & 0x1) ? default_8x8_inter
+							: default_8x8_intra;
+					} else {
+						VDEC_ASSERT(h264_pps_info->scllst8x8pic);
+					if (scllst8x8pic)
+						quant_matrix = (*scllst8x8pic)[i];
+					}
+				} else {
+					if
+				(h264_seq_hdr_info->sps_info.seq_scaling_matrix_present_flag) {
+						/* SPS matrix present - use fallback rule B */
+						/* list 6 - first 8x8 Intra list */
+				if (i == 0) {
+					if (seq_scllstflg[i +
+						H264FW_NUM_4X4_LISTS] &&
+						!def_sclmatflg_seq[i +
+						H264FW_NUM_4X4_LISTS]) {
+						VDEC_ASSERT
+						(h264_seq_hdr_info->sps_info.scllst8x8seq);
+					if (scllst8x8seq)
+						quant_matrix = (*scllst8x8seq)[i];
+					} else {
+						quant_matrix = default_8x8_intra;
+						}
+				/* list 7 - first 8x8 Inter list */
+				} else if (i == 1) {
+					if (seq_scllstflg[i +
+							H264FW_NUM_4X4_LISTS] &&
+							!def_sclmatflg_seq[i +
+							H264FW_NUM_4X4_LISTS]) {
+						VDEC_ASSERT
+						(h264_seq_hdr_info->sps_info.scllst8x8seq);
+					if (scllst8x8seq)
+						quant_matrix = (*scllst8x8seq)[i];
+					} else {
+						quant_matrix = default_8x8_inter;
+					}
+					} else {
+						quant_matrix =
+							h264fw_pps_info->scalinglist8x8[i - 2];
+					}
+				} else {
+						/* SPS matrix not present - use fallback rule A */
+						/* list 6 - first 8x8 Intra list */
+					if (i == 0)
+						quant_matrix = default_8x8_intra;
+					/* list 7 - first 8x8 Inter list */
+					else if (i == 1)
+						quant_matrix = default_8x8_inter;
+					else
+						quant_matrix =
+							h264fw_pps_info->scalinglist8x8[i - 2];
+				}
+				}
+				if (quant_matrix) {
+					/* copy correct 8x8 list to output - as selected by PPS */
+					memcpy(h264fw_pps_info->scalinglist8x8[i], quant_matrix,
+					       sizeof(h264fw_pps_info->scalinglist8x8[i]));
+				}
+			}
+		} else {
+			/* PPS matrix not present, use SPS information */
+			if (h264_seq_hdr_info->sps_info.seq_scaling_matrix_present_flag) {
+				for (i = 0; i < num8x8_lists; i++) {
+					if (seq_scllstflg[i + H264FW_NUM_4X4_LISTS] &&
+					    def_sclmatflg_seq[i + H264FW_NUM_4X4_LISTS]) {
+						quant_matrix =
+							(i & 0x1) ? default_8x8_inter :
+							default_8x8_intra;
+					} else if ((seq_scllstflg[i + H264FW_NUM_4X4_LISTS]) &&
+						   !(def_sclmatflg_seq[i + H264FW_NUM_4X4_LISTS])) {
+						VDEC_ASSERT
+							(h264_seq_hdr_info->sps_info.scllst8x8seq);
+					if (scllst8x8seq)
+						quant_matrix = (*scllst8x8seq)[i];
+					} else if (!(seq_scllstflg[i + H264FW_NUM_4X4_LISTS]) &&
+						   (i == 0)) {
+						/* SPS list not present - use fallback rule A */
+						/* list 6 - first 8x8 Intra list */
+						quant_matrix = default_8x8_intra;
+					} else if (!(seq_scllstflg[i + H264FW_NUM_4X4_LISTS]) &&
+						   (i == 1)) {
+						/* list 7 - first 8x8 Inter list */
+						quant_matrix = default_8x8_inter;
+					} else {
+						quant_matrix =
+							h264fw_pps_info->scalinglist8x8
+							[i - 2];
+					}
+					if (quant_matrix) {
+						/* copy correct 8x8 list to output -
+						 * as selected by SPS
+						 */
+						memcpy(h264fw_pps_info->scalinglist8x8[i],
+						       quant_matrix,
+						       sizeof(h264fw_pps_info->scalinglist8x8[i]));
+					}
+				}
+			} else {
+				/* SPS matrix not present - use flat lists */
+				quant_matrix = default_8x8_org;
+				for (i = 0; i < num8x8_lists; i++)
+					memcpy(h264fw_pps_info->scalinglist8x8[i], quant_matrix,
+					       sizeof(h264fw_pps_info->scalinglist8x8[i]));
+			}
+		}
+	}
+}
+
+static void bspp_h264_fwpps_populate(struct bspp_h264_pps_info *h264_pps_info,
+				     struct h264fw_picture_ps *h264fw_pps_info)
+{
+	h264fw_pps_info->deblocking_filter_control_present_flag =
+					h264_pps_info->deblocking_filter_control_present_flag;
+	h264fw_pps_info->transform_8x8_mode_flag = h264_pps_info->transform_8x8_mode_flag;
+	h264fw_pps_info->entropy_coding_mode_flag = h264_pps_info->entropy_coding_mode_flag;
+	h264fw_pps_info->redundant_pic_cnt_present_flag =
+						h264_pps_info->redundant_pic_cnt_present_flag;
+	h264fw_pps_info->weighted_bipred_idc = h264_pps_info->weighted_bipred_idc;
+	h264fw_pps_info->weighted_pred_flag = h264_pps_info->weighted_pred_flag;
+	h264fw_pps_info->pic_order_present_flag = h264_pps_info->pic_order_present_flag;
+	h264fw_pps_info->pic_init_qp = h264_pps_info->pic_init_qp_minus26 + 26;
+	h264fw_pps_info->constrained_intra_pred_flag = h264_pps_info->constrained_intra_pred_flag;
+	VDEC_ASSERT(sizeof(h264fw_pps_info->num_ref_lx_active_minus1) ==
+		    sizeof(h264_pps_info->num_ref_idx_lx_active_minus1));
+	VDEC_ASSERT(sizeof(h264fw_pps_info->num_ref_lx_active_minus1) ==
+		    sizeof(unsigned char) * H264FW_MAX_REFPIC_LISTS);
+	memcpy(h264fw_pps_info->num_ref_lx_active_minus1,
+	       h264_pps_info->num_ref_idx_lx_active_minus1,
+	       sizeof(h264fw_pps_info->num_ref_lx_active_minus1));
+	h264fw_pps_info->slice_group_map_type = h264_pps_info->slice_group_map_type;
+	h264fw_pps_info->num_slice_groups_minus1 = h264_pps_info->num_slice_groups_minus1;
+	h264fw_pps_info->slice_group_change_rate_minus1 =
+					h264_pps_info->slice_group_change_rate_minus1;
+	h264fw_pps_info->chroma_qp_index_offset = h264_pps_info->chroma_qp_index_offset;
+	h264fw_pps_info->second_chroma_qp_index_offset =
+						h264_pps_info->second_chroma_qp_index_offset;
+}
+
+static void
+bspp_h264_fwseq_hdr_populate(struct bspp_h264_seq_hdr_info *h264_seq_hdr_info,
+			     struct h264fw_sequence_ps *h264_fwseq_hdr_info,
+			     unsigned int max_dec_frame_buffering)
+{
+	/* Basic SPS */
+	h264_fwseq_hdr_info->profile_idc = h264_seq_hdr_info->sps_info.profile_idc;
+	h264_fwseq_hdr_info->chroma_format_idc = h264_seq_hdr_info->sps_info.chroma_format_idc;
+	h264_fwseq_hdr_info->separate_colour_plane_flag =
+		h264_seq_hdr_info->sps_info.separate_colour_plane_flag;
+	h264_fwseq_hdr_info->bit_depth_luma_minus8 =
+		h264_seq_hdr_info->sps_info.bit_depth_luma_minus8;
+	h264_fwseq_hdr_info->bit_depth_chroma_minus8 =
+		h264_seq_hdr_info->sps_info.bit_depth_chroma_minus8;
+	h264_fwseq_hdr_info->delta_pic_order_always_zero_flag =
+		h264_seq_hdr_info->sps_info.delta_pic_order_always_zero_flag;
+	h264_fwseq_hdr_info->log2_max_pic_order_cnt_lsb =
+		h264_seq_hdr_info->sps_info.log2_max_pic_order_cnt_lsb_minus4 + 4;
+	h264_fwseq_hdr_info->max_num_ref_frames = h264_seq_hdr_info->sps_info.max_num_ref_frames;
+	h264_fwseq_hdr_info->log2_max_frame_num =
+		h264_seq_hdr_info->sps_info.log2_max_frame_num_minus4 + 4;
+	h264_fwseq_hdr_info->pic_order_cnt_type = h264_seq_hdr_info->sps_info.pic_order_cnt_type;
+	h264_fwseq_hdr_info->frame_mbs_only_flag = h264_seq_hdr_info->sps_info.frame_mbs_only_flag;
+	h264_fwseq_hdr_info->gaps_in_frame_num_value_allowed_flag =
+		h264_seq_hdr_info->sps_info.gaps_in_frame_num_value_allowed_flag;
+	h264_fwseq_hdr_info->constraint_set_flags =
+		h264_seq_hdr_info->sps_info.constraint_set_flags;
+	h264_fwseq_hdr_info->level_idc = h264_seq_hdr_info->sps_info.level_idc;
+	h264_fwseq_hdr_info->num_ref_frames_in_pic_order_cnt_cycle =
+		h264_seq_hdr_info->sps_info.num_ref_frames_in_pic_order_cnt_cycle;
+	h264_fwseq_hdr_info->mb_adaptive_frame_field_flag =
+		h264_seq_hdr_info->sps_info.mb_adaptive_frame_field_flag;
+	h264_fwseq_hdr_info->offset_for_non_ref_pic =
+		h264_seq_hdr_info->sps_info.offset_for_non_ref_pic;
+	h264_fwseq_hdr_info->offset_for_top_to_bottom_field =
+		h264_seq_hdr_info->sps_info.offset_for_top_to_bottom_field;
+	h264_fwseq_hdr_info->pic_width_in_mbs_minus1 =
+		h264_seq_hdr_info->sps_info.pic_width_in_mbs_minus1;
+	h264_fwseq_hdr_info->pic_height_in_map_units_minus1 =
+		h264_seq_hdr_info->sps_info.pic_height_in_map_units_minus1;
+	h264_fwseq_hdr_info->direct_8x8_inference_flag =
+		h264_seq_hdr_info->sps_info.direct_8x8_inference_flag;
+	h264_fwseq_hdr_info->qpprime_y_zero_transform_bypass_flag =
+		h264_seq_hdr_info->sps_info.qpprime_y_zero_transform_bypass_flag;
+
+	if (h264_seq_hdr_info->sps_info.offset_for_ref_frame)
+		memcpy(h264_fwseq_hdr_info->offset_for_ref_frame,
+		       h264_seq_hdr_info->sps_info.offset_for_ref_frame,
+		       sizeof(h264_fwseq_hdr_info->offset_for_ref_frame));
+	else
+		memset(h264_fwseq_hdr_info->offset_for_ref_frame, 0x00,
+		       sizeof(h264_fwseq_hdr_info->offset_for_ref_frame));
+
+	memset(h264_fwseq_hdr_info->anchor_inter_view_reference_id_list, 0x00,
+	       sizeof(h264_fwseq_hdr_info->anchor_inter_view_reference_id_list));
+	memset(h264_fwseq_hdr_info->non_anchor_inter_view_reference_id_list, 0x00,
+	       sizeof(h264_fwseq_hdr_info->non_anchor_inter_view_reference_id_list));
+
+#ifdef REDUCED_DPB_NO_PIC_REORDERING
+	/* From VUI */
+	h264_fwseq_hdr_info->max_dec_frame_buffering =
+		h264_seq_hdr_info->vui_info.max_dec_frame_buffering;
+	h264_fwseq_hdr_info->num_reorder_frames = h264_seq_hdr_info->vui_info.num_reorder_frames;
+#else
+	/* From VUI */
+	if (h264_seq_hdr_info->vui_info.bitstream_restriction_flag) {
+		VDEC_ASSERT(h264_seq_hdr_info->sps_info.vui_parameters_present_flag);
+		h264_fwseq_hdr_info->max_dec_frame_buffering =
+			h264_seq_hdr_info->vui_info.max_dec_frame_buffering;
+		h264_fwseq_hdr_info->num_reorder_frames =
+			h264_seq_hdr_info->vui_info.num_reorder_frames;
+	} else {
+		h264_fwseq_hdr_info->max_dec_frame_buffering = max_dec_frame_buffering;
+		h264_fwseq_hdr_info->num_reorder_frames = 16;
+	}
+#endif
+}
+
+static void bspp_h264_commonseq_hdr_populate(struct bspp_h264_seq_hdr_info *h264_seq_hdr_info,
+					     struct vdec_comsequ_hdrinfo *comseq_hdr_info)
+{
+	struct bspp_h264_sps_info *sps_info = &h264_seq_hdr_info->sps_info;
+	struct bspp_h264_vui_info *vui_info = &h264_seq_hdr_info->vui_info;
+
+	comseq_hdr_info->codec_profile = sps_info->profile_idc;
+	comseq_hdr_info->codec_level = sps_info->level_idc;
+
+	if (sps_info->vui_parameters_present_flag && vui_info->timing_info_present_flag) {
+		comseq_hdr_info->frame_rate_num = vui_info->time_scale;
+		comseq_hdr_info->frame_rate_den = 2 * vui_info->num_units_in_tick;
+		comseq_hdr_info->frame_rate = ((long)comseq_hdr_info->frame_rate_num) /
+			((long)comseq_hdr_info->frame_rate_den);
+	}
+
+	/*
+	 * ColorSpace Description was present in the VUI parameters.
+	 * copy it in CommonSeqHdr info for use by application.
+	 */
+	if (vui_info->video_signal_type_present_flag & vui_info->colour_description_present_flag) {
+		comseq_hdr_info->color_space_info.is_present = TRUE;
+		comseq_hdr_info->color_space_info.color_primaries = vui_info->colour_primaries;
+		comseq_hdr_info->color_space_info.transfer_characteristics =
+			vui_info->transfer_characteristics;
+		comseq_hdr_info->color_space_info.matrix_coefficients =
+			vui_info->matrix_coefficients;
+	}
+
+	if (vui_info->aspect_ratio_info_present_flag) {
+		comseq_hdr_info->aspect_ratio_num = vui_info->sar_width;
+		comseq_hdr_info->aspect_ratio_den = vui_info->sar_height;
+	}
+
+	comseq_hdr_info->interlaced_frames = sps_info->frame_mbs_only_flag ? 0 : 1;
+
+	/* pixel_info populate */
+	VDEC_ASSERT(sps_info->chroma_format_idc < 4);
+	comseq_hdr_info->pixel_info.chroma_fmt = (sps_info->chroma_format_idc == 0) ? 0 : 1;
+	comseq_hdr_info->pixel_info.chroma_fmt_idc = pixel_format_idc[sps_info->chroma_format_idc];
+	comseq_hdr_info->pixel_info.chroma_interleave =
+		((sps_info->chroma_format_idc == 0) ||
+		(sps_info->chroma_format_idc == 3 && sps_info->separate_colour_plane_flag)) ?
+		PIXEL_INVALID_CI : PIXEL_UV_ORDER;
+	comseq_hdr_info->pixel_info.num_planes =
+		(sps_info->chroma_format_idc == 0) ? 1 :
+		(sps_info->chroma_format_idc == 3 && sps_info->separate_colour_plane_flag) ? 3 : 2;
+	comseq_hdr_info->pixel_info.bitdepth_y = sps_info->bit_depth_luma_minus8 + 8;
+	comseq_hdr_info->pixel_info.bitdepth_c = sps_info->bit_depth_chroma_minus8 + 8;
+	comseq_hdr_info->pixel_info.mem_pkg =
+		(comseq_hdr_info->pixel_info.bitdepth_y > 8 ||
+		comseq_hdr_info->pixel_info.bitdepth_c > 8) ?
+		PIXEL_BIT10_MSB_MP : PIXEL_BIT8_MP;
+	comseq_hdr_info->pixel_info.pixfmt =
+		pixel_get_pixfmt(comseq_hdr_info->pixel_info.chroma_fmt_idc,
+				 comseq_hdr_info->pixel_info.chroma_interleave,
+				 comseq_hdr_info->pixel_info.mem_pkg,
+				 comseq_hdr_info->pixel_info.bitdepth_y,
+				 comseq_hdr_info->pixel_info.bitdepth_c,
+				 comseq_hdr_info->pixel_info.num_planes);
+
+	/* max_frame_size populate */
+	comseq_hdr_info->max_frame_size.width = (sps_info->pic_width_in_mbs_minus1 + 1) * 16;
+	/*
+	 * H264 has always coded size MB aligned. For sequences which *may* have Field-Coded
+	 * pictures, as described by the frame_mbs_only_flag, the pic_height_in_map_units_minus1
+	 * refers to field height in MBs, so to find the actual Frame height we need to do
+	 * Field_MBs_InHeight * 32
+	 */
+	comseq_hdr_info->max_frame_size.height = (sps_info->pic_height_in_map_units_minus1 + 1) *
+						(sps_info->frame_mbs_only_flag ? 1 : 2) * 16;
+
+	/* Passing 2*N to vxd_dec so that get_nbuffers can use formula N+3 for all codecs*/
+	comseq_hdr_info->max_ref_frame_num  = 2 * sps_info->max_num_ref_frames;
+
+	comseq_hdr_info->field_codec_mblocks = sps_info->mb_adaptive_frame_field_flag;
+	comseq_hdr_info->min_pict_buf_num = vui_info->max_dec_frame_buffering;
+
+	/* orig_display_region populate */
+	if (sps_info->frame_cropping_flag) {
+		int sub_width_c, sub_height_c, crop_unit_x, crop_unit_y;
+		int frame_crop_left, frame_crop_right, frame_crop_top, frame_crop_bottom;
+
+		sub_width_c = bspp_h264_get_subwidthc(sps_info->chroma_format_idc,
+						      sps_info->separate_colour_plane_flag);
+
+		sub_height_c = bspp_h264_get_subheightc(sps_info->chroma_format_idc,
+							sps_info->separate_colour_plane_flag);
+
+		/* equation source: ITU-T H.264 2010/03, page 77 */
+		/* ChromaArrayType == 0 */
+		if (sps_info->separate_colour_plane_flag || sps_info->chroma_format_idc == 0) {
+			/* (7-18) */
+			crop_unit_x = 1;
+			/* (7-19) */
+			crop_unit_y = 2 - sps_info->frame_mbs_only_flag;
+			/* ChromaArrayType == chroma_format_idc */
+		} else {
+			/* (7-20) */
+			crop_unit_x = sub_width_c;
+			/* (7-21) */
+			crop_unit_y = sub_height_c * (2 - sps_info->frame_mbs_only_flag);
+		}
+
+		VDEC_ASSERT(sps_info->frame_crop_left_offset <=
+			(comseq_hdr_info->max_frame_size.width / crop_unit_x) -
+			(sps_info->frame_crop_right_offset + 1));
+
+		VDEC_ASSERT(sps_info->frame_crop_top_offset <=
+			(comseq_hdr_info->max_frame_size.height / crop_unit_y) -
+			(sps_info->frame_crop_bottom_offset + 1));
+		frame_crop_left = crop_unit_x * sps_info->frame_crop_left_offset;
+		frame_crop_right = comseq_hdr_info->max_frame_size.width -
+			(crop_unit_x * sps_info->frame_crop_right_offset);
+		frame_crop_top = crop_unit_y * sps_info->frame_crop_top_offset;
+		frame_crop_bottom = comseq_hdr_info->max_frame_size.height -
+			(crop_unit_y * sps_info->frame_crop_bottom_offset);
+		comseq_hdr_info->orig_display_region.left_offset = (unsigned int)frame_crop_left;
+		comseq_hdr_info->orig_display_region.top_offset = (unsigned int)frame_crop_top;
+		comseq_hdr_info->orig_display_region.width = (frame_crop_right - frame_crop_left);
+		comseq_hdr_info->orig_display_region.height = (frame_crop_bottom - frame_crop_top);
+	} else {
+		comseq_hdr_info->orig_display_region.left_offset = 0;
+		comseq_hdr_info->orig_display_region.top_offset = 0;
+		comseq_hdr_info->orig_display_region.width = comseq_hdr_info->max_frame_size.width;
+		comseq_hdr_info->orig_display_region.height =
+			comseq_hdr_info->max_frame_size.height;
+	}
+
+#ifdef REDUCED_DPB_NO_PIC_REORDERING
+	comseq_hdr_info->max_reorder_picts = vui_info->max_dec_frame_buffering;
+#else
+	if (sps_info->vui_parameters_present_flag && vui_info->bitstream_restriction_flag)
+		comseq_hdr_info->max_reorder_picts = vui_info->max_dec_frame_buffering;
+	else
+		comseq_hdr_info->max_reorder_picts = 0;
+#endif
+	comseq_hdr_info->separate_chroma_planes =
+		h264_seq_hdr_info->sps_info.separate_colour_plane_flag ? 1 : 0;
+}
+
+static void bspp_h264_pict_hdr_populate(enum h264_nalunittype nal_unit_type,
+					struct bspp_h264_slice_hdr_info *h264_slice_hdr_info,
+					struct vdec_comsequ_hdrinfo *comseq_hdr_info,
+					struct bspp_pict_hdr_info *pict_hdr_info)
+{
+	/*
+	 * H264 has slice coding type, not picture. The bReference contrary to the rest of the
+	 * standards is set explicitly from the NAL externally (see just below the call to
+	 * bspp_h264_pict_hdr_populate) pict_hdr_info->bReference = ? (Set externally for H264)
+	 */
+	pict_hdr_info->intra_coded = (nal_unit_type == H264_NALTYPE_IDR_SLICE) ? 1 : 0;
+	pict_hdr_info->field = h264_slice_hdr_info->field_pic_flag;
+
+	pict_hdr_info->post_processing = 0;
+	/* For H264 Maximum and Coded sizes are the same */
+	pict_hdr_info->coded_frame_size.width = comseq_hdr_info->max_frame_size.width;
+	/* For H264 Maximum and Coded sizes are the same */
+	pict_hdr_info->coded_frame_size.height = comseq_hdr_info->max_frame_size.height;
+	/*
+	 * For H264 Encoded Display size has been precomputed as part of the
+	 * common sequence info
+	 */
+	pict_hdr_info->disp_info.enc_disp_region = comseq_hdr_info->orig_display_region;
+	/*
+	 * For H264 there is no resampling, so encoded and actual display
+	 * regions are the same
+	 */
+	pict_hdr_info->disp_info.disp_region = comseq_hdr_info->orig_display_region;
+	/* H264 does not have that */
+	pict_hdr_info->disp_info.num_pan_scan_windows = 0;
+	memset(pict_hdr_info->disp_info.pan_scan_windows, 0,
+	       sizeof(pict_hdr_info->disp_info.pan_scan_windows));
+}
+
+static int bspp_h264_destroy_seq_hdr_info(const void *secure_sps_info)
+{
+	struct bspp_h264_seq_hdr_info *h264_seq_hdr_info = NULL;
+
+	if (!secure_sps_info)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	h264_seq_hdr_info = (struct bspp_h264_seq_hdr_info *)secure_sps_info;
+
+	/* Cleaning vui_info */
+	kfree(h264_seq_hdr_info->vui_info.nal_hrd_parameters.bit_rate_value_minus1);
+	kfree(h264_seq_hdr_info->vui_info.nal_hrd_parameters.cpb_size_value_minus1);
+	kfree(h264_seq_hdr_info->vui_info.nal_hrd_parameters.cbr_flag);
+	kfree(h264_seq_hdr_info->vui_info.vcl_hrd_parameters.bit_rate_value_minus1);
+	kfree(h264_seq_hdr_info->vui_info.vcl_hrd_parameters.cpb_size_value_minus1);
+	kfree(h264_seq_hdr_info->vui_info.vcl_hrd_parameters.cbr_flag);
+
+	/* Cleaning sps_info */
+	kfree(h264_seq_hdr_info->sps_info.offset_for_ref_frame);
+	kfree(h264_seq_hdr_info->sps_info.scllst4x4seq);
+	kfree(h264_seq_hdr_info->sps_info.scllst8x8seq);
+
+	return 0;
+}
+
+static int bspp_h264_destroy_pps_info(const void *secure_pps_info)
+{
+	struct bspp_h264_pps_info *h264_pps_info = NULL;
+
+	if (!secure_pps_info)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	h264_pps_info = (struct bspp_h264_pps_info *)secure_pps_info;
+	kfree(h264_pps_info->h264_ppssgm_info.slice_group_id);
+	h264_pps_info->h264_ppssgm_info.slicegroupidnum = 0;
+	kfree(h264_pps_info->scllst4x4pic);
+	kfree(h264_pps_info->scllst8x8pic);
+
+	return 0;
+}
+
+static int bspp_h264_destroy_data(enum bspp_unit_type data_type, void *data_handle)
+{
+	int result = 0;
+
+	if (!data_handle)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	switch (data_type) {
+	case BSPP_UNIT_SEQUENCE:
+		result = bspp_h264_destroy_seq_hdr_info(data_handle);
+		break;
+	case BSPP_UNIT_PPS:
+		result = bspp_h264_destroy_pps_info(data_handle);
+		break;
+	default:
+		break;
+	}
+	return result;
+}
+
+static void bspp_h264_generate_slice_groupmap(struct bspp_h264_slice_hdr_info *h264_slice_hdr_info,
+					      struct bspp_h264_seq_hdr_info *h264_seq_hdr_info,
+					      struct bspp_h264_pps_info *h264_pps_info,
+					      unsigned char *map_unit_to_slice_groupmap,
+					      unsigned int map_size)
+{
+	int group;
+	unsigned int num_slice_group_mapunits;
+	unsigned int i = 0, j, k = 0;
+	unsigned char num_slice_groups = h264_pps_info->num_slice_groups_minus1 + 1;
+	unsigned int pic_width_in_mbs = h264_seq_hdr_info->sps_info.pic_width_in_mbs_minus1 + 1;
+	unsigned int pic_height_in_map_units =
+		h264_seq_hdr_info->sps_info.pic_height_in_map_units_minus1 + 1;
+
+	num_slice_group_mapunits = map_size;
+	if (h264_pps_info->slice_group_map_type == 6) {
+		if ((unsigned int)num_slice_groups != num_slice_group_mapunits) {
+			VDEC_ASSERT
+			("wrong pps->num_slice_group_map_units_minus1 for used SPS and FMO type 6"
+					==
+					NULL);
+			if (num_slice_group_mapunits >
+				h264_pps_info->h264_ppssgm_info.slicegroupidnum)
+				num_slice_group_mapunits =
+					h264_pps_info->h264_ppssgm_info.slicegroupidnum;
+		}
+	}
+
+	/* only one slice group */
+	if (h264_pps_info->num_slice_groups_minus1 == 0) {
+		memset(map_unit_to_slice_groupmap, 0, map_size * sizeof(unsigned char));
+		return;
+	}
+	if (h264_pps_info->num_slice_groups_minus1 >= MAX_SLICEGROUP_COUNT) {
+		memset(map_unit_to_slice_groupmap, 0, map_size * sizeof(unsigned char));
+		return;
+	}
+	if (h264_pps_info->slice_group_map_type == 0) {
+		do {
+			for (group =
+				0;
+				group <= h264_pps_info->num_slice_groups_minus1 &&
+				i < num_slice_group_mapunits;
+				i += h264_pps_info->run_length_minus1[group++] + 1) {
+				for (j = 0;
+					j <= h264_pps_info->run_length_minus1[group] &&
+					i + j < num_slice_group_mapunits;
+					j++)
+					map_unit_to_slice_groupmap[i + j] = group;
+			}
+		} while (i < num_slice_group_mapunits);
+	} else if (h264_pps_info->slice_group_map_type == 1) {
+		for (i = 0; i < num_slice_group_mapunits; i++) {
+			map_unit_to_slice_groupmap[i] = ((i % pic_width_in_mbs) +
+				(((i / pic_width_in_mbs) *
+				(h264_pps_info->num_slice_groups_minus1 + 1)) / 2)) %
+				(h264_pps_info->num_slice_groups_minus1 + 1);
+		}
+	} else if (h264_pps_info->slice_group_map_type == 2) {
+		unsigned int y_top_left, x_top_left, y_bottom_right, x_bottom_right, x, y;
+
+		for (i = 0; i < num_slice_group_mapunits; i++)
+			map_unit_to_slice_groupmap[i] = h264_pps_info->num_slice_groups_minus1;
+
+		for (group = h264_pps_info->num_slice_groups_minus1 - 1; group >= 0; group--) {
+			y_top_left = h264_pps_info->top_left[group] / pic_width_in_mbs;
+			x_top_left = h264_pps_info->top_left[group] % pic_width_in_mbs;
+			y_bottom_right = h264_pps_info->bottom_right[group] / pic_width_in_mbs;
+			x_bottom_right = h264_pps_info->bottom_right[group] % pic_width_in_mbs;
+			for (y = y_top_left; y <= y_bottom_right; y++)
+				for (x = x_top_left; x <= x_bottom_right; x++) {
+					if (h264_pps_info->top_left[group] >
+						h264_pps_info->bottom_right[group] ||
+						h264_pps_info->bottom_right[group] >=
+						num_slice_group_mapunits)
+						continue;
+					map_unit_to_slice_groupmap[y * pic_width_in_mbs +
+					x] = group;
+				}
+		}
+	} else if (h264_pps_info->slice_group_map_type == 3) {
+		int left_bound, top_bound, right_bound, bottom_bound;
+		int x, y, x_dir, y_dir;
+		int map_unit_vacant;
+
+		unsigned int mapunits_in_slicegroup_0 =
+			umin((unsigned int)((h264_pps_info->slice_group_change_rate_minus1 + 1) *
+				h264_slice_hdr_info->slice_group_change_cycle),
+				(unsigned int)num_slice_group_mapunits);
+
+		for (i = 0; i < num_slice_group_mapunits; i++)
+			map_unit_to_slice_groupmap[i] = 2;
+
+		x = (pic_width_in_mbs - h264_pps_info->slice_group_change_direction_flag) / 2;
+		y = (pic_height_in_map_units - h264_pps_info->slice_group_change_direction_flag) /
+			2;
+
+		left_bound = x;
+		top_bound = y;
+		right_bound = x;
+		bottom_bound = y;
+
+		x_dir = h264_pps_info->slice_group_change_direction_flag - 1;
+		y_dir = h264_pps_info->slice_group_change_direction_flag;
+
+		for (k = 0; k < num_slice_group_mapunits; k += map_unit_vacant) {
+			map_unit_vacant =
+				(map_unit_to_slice_groupmap[y * pic_width_in_mbs + x] ==
+				2);
+			if (map_unit_vacant)
+				map_unit_to_slice_groupmap[y * pic_width_in_mbs + x] =
+					(k >= mapunits_in_slicegroup_0);
+
+			if (x_dir == -1 && x == left_bound) {
+				left_bound = smax(left_bound - 1, 0);
+				x = left_bound;
+				x_dir = 0;
+				y_dir = 2 * h264_pps_info->slice_group_change_direction_flag - 1;
+			} else if (x_dir == 1 && x == right_bound) {
+				right_bound = smin(right_bound + 1, (int)pic_width_in_mbs - 1);
+				x = right_bound;
+				x_dir = 0;
+				y_dir = 1 - 2 * h264_pps_info->slice_group_change_direction_flag;
+			} else if (y_dir == -1 && y == top_bound) {
+				top_bound = smax(top_bound - 1, 0);
+				y = top_bound;
+				x_dir = 1 - 2 * h264_pps_info->slice_group_change_direction_flag;
+				y_dir = 0;
+			} else if (y_dir == 1 && y == bottom_bound) {
+				bottom_bound = smin(bottom_bound + 1,
+						    (int)pic_height_in_map_units - 1);
+				y = bottom_bound;
+				x_dir = 2 * h264_pps_info->slice_group_change_direction_flag - 1;
+				y_dir = 0;
+			} else {
+				x = x + x_dir;
+				y = y + y_dir;
+			}
+		}
+	} else if (h264_pps_info->slice_group_map_type == 4) {
+		unsigned int mapunits_in_slicegroup_0 =
+			umin((unsigned int)((h264_pps_info->slice_group_change_rate_minus1 + 1) *
+				h264_slice_hdr_info->slice_group_change_cycle),
+				(unsigned int)num_slice_group_mapunits);
+		unsigned int sizeof_upper_left_group =
+			h264_pps_info->slice_group_change_direction_flag ?
+			(num_slice_group_mapunits -
+			mapunits_in_slicegroup_0) : mapunits_in_slicegroup_0;
+		for (i = 0; i < num_slice_group_mapunits; i++) {
+			if (i < sizeof_upper_left_group)
+				map_unit_to_slice_groupmap[i] =
+					h264_pps_info->slice_group_change_direction_flag;
+
+			else
+				map_unit_to_slice_groupmap[i] = 1 -
+					h264_pps_info->slice_group_change_direction_flag;
+		}
+	} else if (h264_pps_info->slice_group_map_type == 5) {
+		unsigned int mapunits_in_slicegroup_0 =
+			umin((unsigned int)((h264_pps_info->slice_group_change_rate_minus1 + 1) *
+				h264_slice_hdr_info->slice_group_change_cycle),
+				(unsigned int)num_slice_group_mapunits);
+		unsigned int sizeof_upper_left_group =
+			h264_pps_info->slice_group_change_direction_flag ?
+			(num_slice_group_mapunits -
+			mapunits_in_slicegroup_0) : mapunits_in_slicegroup_0;
+
+		for (j = 0; j < (unsigned int)pic_width_in_mbs; j++) {
+			for (i = 0; i < (unsigned int)pic_height_in_map_units; i++) {
+				if (k++ < sizeof_upper_left_group)
+					map_unit_to_slice_groupmap[i * pic_width_in_mbs + j] =
+						h264_pps_info->slice_group_change_direction_flag;
+				else
+					map_unit_to_slice_groupmap[i * pic_width_in_mbs + j] =
+						1 -
+						h264_pps_info->slice_group_change_direction_flag;
+			}
+		}
+	} else if (h264_pps_info->slice_group_map_type == 6) {
+		VDEC_ASSERT(num_slice_group_mapunits <=
+			    h264_pps_info->h264_ppssgm_info.slicegroupidnum);
+		for (i = 0; i < num_slice_group_mapunits; i++)
+			map_unit_to_slice_groupmap[i] =
+				h264_pps_info->h264_ppssgm_info.slice_group_id[i];
+	}
+}
+
+static int bspp_h264_parse_mvc_slice_extension(void *swsr_context,
+					       struct bspp_h264_inter_pict_ctx *inter_pict_ctx)
+{
+	if (!swsr_read_bits(swsr_context, 1)) {
+		swsr_read_bits(swsr_context, 7);
+		inter_pict_ctx->current_view_id = swsr_read_bits(swsr_context, 10);
+		swsr_read_bits(swsr_context, 6);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int bspp_h264_unitparser_compile_sgmdata
+			(struct bspp_h264_slice_hdr_info *h264_slice_hdr_info,
+			 struct bspp_h264_seq_hdr_info *h264_seq_hdr_info,
+			 struct bspp_h264_pps_info *h264_pps_info,
+			 struct bspp_pict_hdr_info *pict_hdr_info)
+{
+	memset(&pict_hdr_info->pict_sgm_data, 0, sizeof(*&pict_hdr_info->pict_sgm_data));
+
+	pict_hdr_info->pict_sgm_data.id = 1;
+
+	/* Allocate memory for SGM. */
+	pict_hdr_info->pict_sgm_data.size =
+		(h264_seq_hdr_info->sps_info.pic_height_in_map_units_minus1 + 1) *
+		(h264_seq_hdr_info->sps_info.pic_width_in_mbs_minus1 + 1);
+
+	pict_hdr_info->pict_sgm_data.pic_data = kmalloc((pict_hdr_info->pict_sgm_data.size),
+							GFP_KERNEL);
+	VDEC_ASSERT(pict_hdr_info->pict_sgm_data.pic_data);
+	if (!pict_hdr_info->pict_sgm_data.pic_data) {
+		pict_hdr_info->pict_sgm_data.id = BSPP_INVALID;
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	bspp_h264_generate_slice_groupmap(h264_slice_hdr_info, h264_seq_hdr_info, h264_pps_info,
+					  pict_hdr_info->pict_sgm_data.pic_data,
+					  pict_hdr_info->pict_sgm_data.size);
+
+	/* check the discontinuous_mbs_flaginCurrFrame flag for FMO */
+	/* NO FMO support */
+	pict_hdr_info->discontinuous_mbs = 0;
+
+	return 0;
+}
+
+static int bspp_h264_unit_parser(void *swsr_context, struct bspp_unit_data *unit_data)
+{
+	unsigned int result = 0;
+	enum bspp_error_type parse_error = BSPP_ERROR_NONE;
+	enum h264_nalunittype nal_unit_type;
+	unsigned char nal_ref_idc;
+	struct bspp_h264_inter_pict_ctx *interpicctx;
+	struct bspp_sequence_hdr_info *out_seq_info;
+	unsigned char id;
+
+	interpicctx = &unit_data->parse_state->inter_pict_ctx->h264_ctx;
+	out_seq_info = unit_data->out.sequ_hdr_info;
+
+	/* At this point we should be EXACTLY at the NALTYPE byte */
+	/* parse the nal header type */
+	swsr_read_bits(swsr_context, 1);
+	nal_ref_idc = swsr_read_bits(swsr_context, 2);
+	nal_unit_type = (enum h264_nalunittype)swsr_read_bits(swsr_context, 5);
+
+	switch (unit_data->unit_type) {
+	case BSPP_UNIT_SEQUENCE:
+		VDEC_ASSERT(nal_unit_type == H264_NALTYPE_SEQUENCE_PARAMETER_SET ||
+			    nal_unit_type == H264_NALTYPE_SUBSET_SPS);
+		{
+			unsigned char id_loc;
+			/* Parse SPS structure */
+			struct bspp_h264_seq_hdr_info *h264_seq_hdr_info =
+			(struct bspp_h264_seq_hdr_info *)(out_seq_info->secure_sequence_info);
+			/* FW SPS Data structure */
+			struct bspp_ddbuf_array_info *tmp = &out_seq_info->fw_sequence;
+			struct h264fw_sequence_ps *h264_fwseq_hdr_info =
+			(struct h264fw_sequence_ps *)((unsigned char *)tmp->ddbuf_info.cpu_virt_addr
+				+ tmp->buf_offset);
+			/* Common Sequence Header Info */
+			struct vdec_comsequ_hdrinfo *comseq_hdr_info =
+				&out_seq_info->sequ_hdr_info.com_sequ_hdr_info;
+
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("Unit Parser:Found SEQUENCE_PARAMETER_SET NAL unit");
+#endif
+			VDEC_ASSERT(h264_seq_hdr_info);
+			VDEC_ASSERT(h264_fwseq_hdr_info);
+			if (!h264_seq_hdr_info)
+				return IMG_ERROR_ALREADY_COMPLETE;
+
+			if (!h264_fwseq_hdr_info)
+				return IMG_ERROR_ALREADY_COMPLETE;
+
+			/* Call SPS parser to populate the "Parse SPS Structure" */
+			unit_data->parse_error |=
+				bspp_h264_sps_parser(swsr_context, unit_data->str_res_handle,
+						     h264_seq_hdr_info);
+			/* From "Parse SPS Structure" populate the "FW SPS Data Structure" */
+			bspp_h264_fwseq_hdr_populate(
+				h264_seq_hdr_info, h264_fwseq_hdr_info,
+				unit_data->max_dec_frame_buffering);
+			/*
+			 * From "Parse SPS Structure" populate the
+			 * "Common Sequence Header Info"
+			 */
+			bspp_h264_commonseq_hdr_populate(h264_seq_hdr_info, comseq_hdr_info);
+			/* Set the SPS ID */
+			/*
+			 * seq_parameter_set_id is always in range 0-31, so we can
+			 * add offset indicating subsequence header
+			 */
+			id_loc = h264_seq_hdr_info->sps_info.seq_parameter_set_id;
+			out_seq_info->sequ_hdr_info.sequ_hdr_id =
+				(nal_unit_type == H264_NALTYPE_SLICE_SCALABLE ||
+				nal_unit_type == H264_NALTYPE_SLICE_IDR_SCALABLE ||
+				nal_unit_type == H264_NALTYPE_SUBSET_SPS) ? id_loc + 32 : id_loc;
+
+			/*
+			 * Set the first SPS ID as Active SPS ID for SEI parsing
+			 * to cover the case of not having SeiBufferingPeriod to
+			 * give us the SPS ID
+			 */
+			if (interpicctx->active_sps_for_sei_parsing == BSPP_INVALID)
+				interpicctx->active_sps_for_sei_parsing =
+					h264_seq_hdr_info->sps_info.seq_parameter_set_id;
+		}
+		break;
+
+	case BSPP_UNIT_PPS:
+		VDEC_ASSERT(nal_unit_type == H264_NALTYPE_PICTURE_PARAMETER_SET);
+		{
+			/* Parse PPS structure */
+			struct bspp_h264_pps_info *h264_pps_info =
+			(struct bspp_h264_pps_info *)(unit_data->out.pps_info->secure_pps_info);
+			/* FW PPS Data structure */
+			struct bspp_ddbuf_array_info *tmp = &unit_data->out.pps_info->fw_pps;
+			struct h264fw_picture_ps *h264fw_pps_info =
+				(struct h264fw_picture_ps *)((unsigned char *)
+						tmp->ddbuf_info.cpu_virt_addr + tmp->buf_offset);
+
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("Unit Parser:Found PICTURE_PARAMETER_SET NAL unit");
+#endif
+			VDEC_ASSERT(h264_pps_info);
+			VDEC_ASSERT(h264fw_pps_info);
+
+			/* Call PPS parser to populate the "Parse PPS Structure" */
+			unit_data->parse_error |=
+				bspp_h264_pps_parser(swsr_context, unit_data->str_res_handle,
+						     h264_pps_info);
+			/* From "Parse PPS Structure" populate the "FW PPS Data Structure"
+			 * - the scaling lists
+			 */
+			bspp_h264_fwpps_populate(h264_pps_info, h264fw_pps_info);
+			/* Set the PPS ID */
+			unit_data->out.pps_info->pps_id = h264_pps_info->pps_id;
+		}
+		break;
+
+	case BSPP_UNIT_PICTURE:
+		if (nal_unit_type == H264_NALTYPE_SLICE_PREFIX) {
+			if (bspp_h264_parse_mvc_slice_extension(swsr_context, interpicctx))
+				pr_err("%s: No MVC support\n", __func__);
+		} else if (nal_unit_type == H264_NALTYPE_SLICE_SCALABLE ||
+			nal_unit_type == H264_NALTYPE_SLICE_IDR_SCALABLE ||
+			nal_unit_type == H264_NALTYPE_SLICE ||
+			nal_unit_type == H264_NALTYPE_IDR_SLICE) {
+			struct bspp_h264_slice_hdr_info h264_slice_hdr_info;
+			struct bspp_h264_pps_info *h264_pps_info;
+			struct bspp_pps_info *pps_info;
+			struct h264fw_picture_ps *h264fw_pps_info;
+			struct h264fw_sequence_ps *h264_fwseq_hdr_info;
+			struct bspp_h264_seq_hdr_info *h264_seq_hdr_info;
+			struct bspp_sequence_hdr_info *sequ_hdr_info;
+			struct bspp_ddbuf_array_info *tmp1;
+			struct bspp_ddbuf_array_info *tmp2;
+			int current_pic_is_new = 0;
+			int determined = 0;
+			int id_loc;
+
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("Unit Parser:Found PICTURE DATA unit");
+#endif
+
+			unit_data->slice = 1;
+			unit_data->ext_slice = 0;
+
+			if (nal_unit_type == H264_NALTYPE_SLICE_SCALABLE ||
+			    nal_unit_type == H264_NALTYPE_SLICE_IDR_SCALABLE) {
+				pr_err("%s: No SVC support\n", __func__);
+			}
+
+			VDEC_ASSERT(unit_data->out.pict_hdr_info);
+			if (!unit_data->out.pict_hdr_info)
+				return IMG_ERROR_CANCELLED;
+
+			/* Default */
+			unit_data->out.pict_hdr_info->discontinuous_mbs = 0;
+
+			/*
+			 * Parse the Pic Header, return Parse SPS/PPS
+			 * structures
+			 */
+			parse_error = bspp_h264_pict_hdr_parser(swsr_context,
+								unit_data->str_res_handle,
+								&h264_slice_hdr_info,
+								&pps_info,
+								&sequ_hdr_info,
+								nal_unit_type,
+								nal_ref_idc);
+
+			if (parse_error) {
+				unit_data->parse_error |= parse_error;
+				return IMG_ERROR_CANCELLED;
+			}
+
+			/*
+			 * We are signalling closed GOP at every I frame
+			 * This does not conform 100% with the
+			 * specification but insures that seeking always
+			 * works.
+			 */
+			unit_data->new_closed_gop = h264_slice_hdr_info.slice_type ==
+				I_SLICE ? 1 : 0;
+
+			/*
+			 * Now pps_info and sequ_hdr_info contain the
+			 * PPS/SPS info related to this picture
+			 */
+			h264_pps_info = (struct bspp_h264_pps_info *)pps_info->secure_pps_info;
+			h264_seq_hdr_info =
+			(struct bspp_h264_seq_hdr_info *)sequ_hdr_info->secure_sequence_info;
+
+			tmp1 = &pps_info->fw_pps;
+			tmp2 = &sequ_hdr_info->fw_sequence;
+
+			h264fw_pps_info = (struct h264fw_picture_ps *)((unsigned char *)
+						tmp1->ddbuf_info.cpu_virt_addr + tmp1->buf_offset);
+			h264_fwseq_hdr_info = (struct h264fw_sequence_ps *)((unsigned char *)
+					tmp2->ddbuf_info.cpu_virt_addr + tmp2->buf_offset);
+			VDEC_ASSERT(h264_slice_hdr_info.pps_id == h264_pps_info->pps_id);
+			VDEC_ASSERT(h264_pps_info->seq_parameter_set_id ==
+				(unsigned int)h264_seq_hdr_info->sps_info.seq_parameter_set_id);
+
+			/*
+			 * Update the decoding-related FW SPS info related to the current picture
+			 * with the SEI data that were potentially received and also relate to
+			 * the current info. Until we receive the picture we do not know which
+			 * sequence to update with the SEI data.
+			 * Setfrom last SEI, needed for decoding
+			 */
+			h264_fwseq_hdr_info->disable_vdmc_filt = interpicctx->disable_vdmc_filt;
+			h264_fwseq_hdr_info->transform4x4_mb_not_available =
+							interpicctx->b4x4transform_mb_unavailable;
+
+			/*
+			 * Determine if current slice is a new picture, and update the related
+			 * params for future reference
+			 * Order of checks is important
+			 */
+			{
+				struct bspp_parse_state *state = unit_data->parse_state;
+
+				set_if_not_determined_yet(&determined, state->new_view,
+							  &current_pic_is_new, 1);
+				set_if_not_determined_yet(&determined, state->next_pic_is_new,
+							  &current_pic_is_new, 1);
+				set_if_not_determined_yet
+					(&determined,
+					 (h264_slice_hdr_info.redundant_pic_cnt > 0),
+					 &current_pic_is_new, 0);
+				set_if_not_determined_yet
+					(&determined,
+					 (state->prev_frame_num !=
+					  h264_slice_hdr_info.frame_num),
+					 &current_pic_is_new, 1);
+				set_if_not_determined_yet
+					(&determined,
+					 (state->prev_pps_id != h264_slice_hdr_info.pps_id),
+					 &current_pic_is_new, 1);
+				set_if_not_determined_yet
+					(&determined,
+					 (state->prev_field_pic_flag !=
+					  h264_slice_hdr_info.field_pic_flag),
+					 &current_pic_is_new, 1);
+				set_if_not_determined_yet
+					(&determined,
+					 ((h264_slice_hdr_info.field_pic_flag) &&
+					  (state->prev_bottom_pic_flag !=
+					   h264_slice_hdr_info.bottom_field_flag)),
+					 &current_pic_is_new, 1);
+				set_if_not_determined_yet
+					(&determined,
+					 ((state->prev_nal_ref_idc == 0 || nal_ref_idc == 0) &&
+					  (state->prev_nal_ref_idc != nal_ref_idc)),
+					 &current_pic_is_new, 1);
+				set_if_not_determined_yet
+					(&determined,
+					 ((h264_seq_hdr_info->sps_info.pic_order_cnt_type == 0) &&
+					  ((state->prev_pic_order_cnt_lsb !=
+					    h264_slice_hdr_info.pic_order_cnt_lsb) ||
+					   (state->prev_delta_pic_order_cnt_bottom !=
+					    h264_slice_hdr_info.delta_pic_order_cnt_bottom))),
+					 &current_pic_is_new, 1);
+				set_if_not_determined_yet
+					(&determined,
+					 ((h264_seq_hdr_info->sps_info.pic_order_cnt_type == 1) &&
+					  ((state->prev_delta_pic_order_cnt[0] !=
+					    h264_slice_hdr_info.delta_pic_order_cnt[0]) ||
+					   (state->prev_delta_pic_order_cnt[1] !=
+					    h264_slice_hdr_info.delta_pic_order_cnt[1]))),
+					 &current_pic_is_new, 1);
+				set_if_not_determined_yet
+					(&determined,
+					 ((state->prev_nal_unit_type ==
+					   (int)H264_NALTYPE_IDR_SLICE ||
+					   nal_unit_type == (int)H264_NALTYPE_IDR_SLICE) &&
+					  (state->prev_nal_unit_type !=
+					   (int)nal_unit_type)),
+					 &current_pic_is_new, 1);
+				set_if_not_determined_yet(&determined,
+							  ((state->prev_nal_unit_type ==
+							    (int)H264_NALTYPE_IDR_SLICE) &&
+							   (state->prev_idr_pic_id !=
+							    h264_slice_hdr_info.idr_pic_id)),
+							  &current_pic_is_new, 1);
+
+				/*
+				 * Update whatever is not updated already in different places of
+				 * the code or just needs to be updated here
+				 */
+				state->prev_frame_num = h264_slice_hdr_info.frame_num;
+				state->prev_pps_id = h264_slice_hdr_info.pps_id;
+				state->prev_field_pic_flag =
+					h264_slice_hdr_info.field_pic_flag;
+				state->prev_nal_ref_idc = nal_ref_idc;
+				state->prev_pic_order_cnt_lsb =
+					h264_slice_hdr_info.pic_order_cnt_lsb;
+				state->prev_delta_pic_order_cnt_bottom =
+					h264_slice_hdr_info.delta_pic_order_cnt_bottom;
+				state->prev_delta_pic_order_cnt[0] =
+					h264_slice_hdr_info.delta_pic_order_cnt[0];
+				state->prev_delta_pic_order_cnt[1] =
+					h264_slice_hdr_info.delta_pic_order_cnt[1];
+				state->prev_nal_unit_type = (int)nal_unit_type;
+				state->prev_idr_pic_id = h264_slice_hdr_info.idr_pic_id;
+			}
+
+			/* Detect second field and manage the prev_bottom_pic_flag flag */
+			if (h264_slice_hdr_info.field_pic_flag && current_pic_is_new) {
+				unit_data->parse_state->prev_bottom_pic_flag =
+					h264_slice_hdr_info.bottom_field_flag;
+			}
+
+			/* Detect ASO    Just met new pic */
+			id = h264_slice_hdr_info.colour_plane_id;
+			if (current_pic_is_new) {
+				unsigned int i;
+
+				for (i = 0; i < MAX_COMPONENTS; i++)
+					unit_data->parse_state->prev_first_mb_in_slice[i] = 0;
+			} else if (unit_data->parse_state->prev_first_mb_in_slice[id] >
+				h264_slice_hdr_info.first_mb_in_slice) {
+				/* We just found ASO */
+				unit_data->parse_state->discontinuous_mb = 1;
+			}
+			unit_data->parse_state->prev_first_mb_in_slice[id] =
+				h264_slice_hdr_info.first_mb_in_slice;
+
+			/* We may already knew we were DiscontinuousMB */
+			if (unit_data->parse_state->discontinuous_mb)
+				unit_data->out.pict_hdr_info->discontinuous_mbs =
+					unit_data->parse_state->discontinuous_mb;
+
+			/*
+			 * We want to calculate the scaling lists only once per picture/field,
+			 * not every slice We want to populate the VDEC Picture Header Info
+			 * only once per picture/field, not every slice
+			 */
+			if (current_pic_is_new) {
+				/* Common Sequence Header Info fetched */
+				struct vdec_comsequ_hdrinfo *comseq_hdr_info =
+					&sequ_hdr_info->sequ_hdr_info.com_sequ_hdr_info;
+				struct bspp_pict_data *type_pict_aux_data;
+
+				unit_data->parse_state->next_pic_is_new = 0;
+
+				/* Generate SGM for this picture */
+				if (h264_pps_info->num_slice_groups_minus1 != 0 &&
+				    h264_pps_info->slice_group_map_type <= 6) {
+					bspp_h264_unitparser_compile_sgmdata
+								(&h264_slice_hdr_info,
+								 h264_seq_hdr_info,
+								 h264_pps_info,
+								 unit_data->out.pict_hdr_info);
+				} else {
+					unit_data->out.pict_hdr_info->pict_sgm_data.pic_data = NULL;
+					unit_data->out.pict_hdr_info->pict_sgm_data.bufmap_id = 0;
+					unit_data->out.pict_hdr_info->pict_sgm_data.buf_offset = 0;
+					unit_data->out.pict_hdr_info->pict_sgm_data.id =
+						BSPP_INVALID;
+					unit_data->out.pict_hdr_info->pict_sgm_data.size = 0;
+				}
+
+				unit_data->parse_state->discontinuous_mb =
+					unit_data->out.pict_hdr_info->discontinuous_mbs;
+
+				/*
+				 * Select the scaling lists based on h264_pps_info and
+				 * h264_seq_hdr_info and pass them to h264fw_pps_info
+				 */
+				bspp_h264_select_scaling_list(h264fw_pps_info,
+							      h264_pps_info,
+							      h264_seq_hdr_info);
+
+				/*
+				 * Uses the common sequence/SINGLE-slice info to populate the
+				 * VDEC Picture Header Info
+				 */
+				bspp_h264_pict_hdr_populate(nal_unit_type, &h264_slice_hdr_info,
+							    comseq_hdr_info,
+							    unit_data->out.pict_hdr_info);
+
+				/* Store some raw bitstream fields for output. */
+				unit_data->out.pict_hdr_info->h264_pict_hdr_info.frame_num =
+					h264_slice_hdr_info.frame_num;
+				unit_data->out.pict_hdr_info->h264_pict_hdr_info.nal_ref_idc =
+					nal_ref_idc;
+
+				/*
+				 * Update the display-related picture header information with
+				 * the related SEI parsed data The display-related SEI is
+				 * used only for the first picture after the SEI
+				 */
+				if (!interpicctx->sei_info_attached_to_pic) {
+					interpicctx->sei_info_attached_to_pic = 1;
+					if (interpicctx->active_sps_for_sei_parsing !=
+						h264_seq_hdr_info->sps_info.seq_parameter_set_id) {
+						/*
+						 * We tried to guess the SPS ID that we should use
+						 * to parse the SEI, but we guessed wrong
+						 */
+						pr_err("Parsed SEI with wrong SPS, data may be parsed wrong");
+					}
+					unit_data->out.pict_hdr_info->disp_info.repeat_first_fld =
+						interpicctx->repeat_first_field;
+					unit_data->out.pict_hdr_info->disp_info.max_frm_repeat =
+						interpicctx->max_frm_repeat;
+					/* SEI - Not supported */
+				}
+
+				/*
+				 * For Idr slices update the Active
+				 * Sequence ID for SEI parsing,
+				 * error resilient
+				 */
+				if (nal_unit_type == H264_NALTYPE_IDR_SLICE)
+					interpicctx->active_sps_for_sei_parsing =
+						h264_seq_hdr_info->sps_info.seq_parameter_set_id;
+
+				/*
+				 * Choose the appropriate auxiliary data
+				 * structure to populate.
+				 */
+				if (unit_data->parse_state->second_field_flag)
+					type_pict_aux_data =
+						&unit_data->out.pict_hdr_info->second_pict_aux_data;
+
+				else
+					type_pict_aux_data =
+						&unit_data->out.pict_hdr_info->pict_aux_data;
+
+				/*
+				 * We have no container for the PPS that
+				 * passes down to the kernel, for this
+				 * reason the h264 secure parser needs
+				 * to populate that info into the
+				 * picture header (Second)PictAuxData.
+				 */
+				type_pict_aux_data->bufmap_id = pps_info->bufmap_id;
+				type_pict_aux_data->buf_offset = pps_info->buf_offset;
+				type_pict_aux_data->pic_data = (void *)h264fw_pps_info;
+				type_pict_aux_data->id = h264_pps_info->pps_id;
+				type_pict_aux_data->size = sizeof(struct h264fw_picture_ps);
+
+				pps_info->ref_count++;
+
+				/* This info comes from NAL directly */
+				unit_data->out.pict_hdr_info->ref = (nal_ref_idc == 0) ? 0 : 1;
+			}
+			if (nal_unit_type == H264_NALTYPE_IDR_SLICE)
+				unit_data->new_closed_gop = 1;
+
+			/* Return the SPS ID */
+			/*
+			 * seq_parameter_set_id is always in range 0-31,
+			 * so we can add offset indicating subsequence header
+			 */
+			id_loc = h264_pps_info->seq_parameter_set_id;
+			unit_data->pict_sequ_hdr_id =
+				(nal_unit_type == H264_NALTYPE_SLICE_SCALABLE ||
+				nal_unit_type ==
+				H264_NALTYPE_SLICE_IDR_SCALABLE) ? id_loc + 32 : id_loc;
+
+		} else if (nal_unit_type == H264_NALTYPE_SLICE_PARTITION_A ||
+			nal_unit_type == H264_NALTYPE_SLICE_PARTITION_B ||
+			nal_unit_type == H264_NALTYPE_SLICE_PARTITION_C) {
+			unit_data->slice = 1;
+
+			pr_err("Unsupported Slice NAL type: %d", nal_unit_type);
+			unit_data->parse_error = BSPP_ERROR_UNSUPPORTED;
+		}
+		break;
+
+	case BSPP_UNIT_UNCLASSIFIED:
+		if (nal_unit_type == H264_NALTYPE_ACCESS_UNIT_DELIMITER) {
+			unit_data->parse_state->next_pic_is_new = 1;
+		} else if (nal_unit_type == H264_NALTYPE_SLICE_PREFIX ||
+			nal_unit_type == H264_NALTYPE_SUBSET_SPS) {
+			/* if mvc disabled do nothing */
+		} else {
+			/* Should not have any other type of unclassified data. */
+			pr_err("unclassified data detected!\n");
+		}
+		break;
+
+	case BSPP_UNIT_NON_PICTURE:
+		if (nal_unit_type == H264_NALTYPE_END_OF_SEQUENCE ||
+		    nal_unit_type == H264_NALTYPE_END_OF_STREAM) {
+			unit_data->parse_state->next_pic_is_new = 1;
+		} else if (nal_unit_type == H264_NALTYPE_FILLER_DATA ||
+			nal_unit_type == H264_NALTYPE_SEQUENCE_PARAMETER_SET_EXTENSION ||
+			nal_unit_type == H264_NALTYPE_AUXILIARY_SLICE) {
+		} else if (nal_unit_type == H264_NALTYPE_SLICE_SCALABLE ||
+			nal_unit_type == H264_NALTYPE_SLICE_IDR_SCALABLE) {
+			/* if mvc disabled do nothing */
+		} else {
+			/* Should not have any other type of non-picture data. */
+			VDEC_ASSERT(0);
+		}
+		break;
+
+	case BSPP_UNIT_UNSUPPORTED:
+		pr_err("Unsupported NAL type: %d", nal_unit_type);
+		unit_data->parse_error = BSPP_ERROR_UNKNOWN_DATAUNIT_DETECTED;
+		break;
+
+	default:
+		VDEC_ASSERT(0);
+		break;
+	}
+
+	return result;
+}
+
+static int bspp_h264releasedata(void *str_alloc, enum bspp_unit_type data_type, void *data_handle)
+{
+	int result = 0;
+
+	if (!data_handle)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	switch (data_type) {
+	case BSPP_UNIT_SEQUENCE:
+		result = bspp_h264_release_sequ_hdr_info(str_alloc, data_handle);
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+
+static int bspp_h264resetdata(enum bspp_unit_type data_type, void *data_handle)
+{
+	int result = 0;
+
+	if (!data_handle)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	switch (data_type) {
+	case BSPP_UNIT_SEQUENCE:
+		result = bspp_h264_reset_seq_hdr_info(data_handle);
+		break;
+	case BSPP_UNIT_PPS:
+		result = bspp_h264_reset_pps_info(data_handle);
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+
+static void bspp_h264parse_codecconfig(void *swsr_ctx,
+				       unsigned int *unitcount,
+				       unsigned int *unit_arraycount,
+				       unsigned int *delimlength,
+				       unsigned int *size_delimlength)
+{
+	unsigned long long value = 6;
+
+	/*
+	 * Set the shift-register up to provide next 6 bytes
+	 * without emulation prevention detection.
+	 */
+	swsr_consume_delim(swsr_ctx, SWSR_EMPREVENT_NONE, 0, &value);
+
+	/*
+	 * Codec config header must be read for size delimited data (H.264)
+	 * to get to the start of each unit.
+	 * This parsing follows section 5.2.4.1.1 of ISO/IEC 14496-15:2004(E).
+	 */
+	/* Configuration version. */
+	swsr_read_bits(swsr_ctx, 8);
+	/* AVC Profile Indication. */
+	swsr_read_bits(swsr_ctx, 8);
+	/* Profile compatibility. */
+	swsr_read_bits(swsr_ctx, 8);
+	/* AVC Level Indication. */
+	swsr_read_bits(swsr_ctx, 8);
+	*delimlength = ((swsr_read_bits(swsr_ctx, 8) & 0x3) + 1) * 8;
+	*unitcount = swsr_read_bits(swsr_ctx, 8) & 0x1f;
+
+	/* Size delimiter is only 2 bytes for H.264 codec configuration. */
+	*size_delimlength = 2 * 8;
+}
+
+static void bspp_h264update_unitcounts(void *swsr_ctx,
+				       unsigned int *unitcount,
+				       unsigned int *unit_arraycount)
+{
+	if (*unitcount == 0) {
+		unsigned long long value = 1;
+
+		/*
+		 * Set the shift-register up to provide next 1 byte without
+		 * emulation prevention detection.
+		 */
+		swsr_consume_delim(swsr_ctx, SWSR_EMPREVENT_NONE, 0, &value);
+
+		*unitcount = swsr_read_bits(swsr_ctx, 8);
+	}
+
+	(*unitcount)--;
+}
+
+/*
+ * Sets the parser configuration
+ */
+int bspp_h264_set_parser_config(enum vdec_bstr_format bstr_format,
+				struct bspp_vid_std_features *pvidstd_features,
+				struct bspp_swsr_ctx *pswsr_ctx,
+				struct bspp_parser_callbacks *pparser_callbacks,
+				struct bspp_inter_pict_data *pinterpict_data)
+{
+	/* Set h.246 parser callbacks. */
+	pparser_callbacks->parse_unit_cb = bspp_h264_unit_parser;
+	pparser_callbacks->release_data_cb = bspp_h264releasedata;
+	pparser_callbacks->reset_data_cb = bspp_h264resetdata;
+	pparser_callbacks->destroy_data_cb = bspp_h264_destroy_data;
+	pparser_callbacks->parse_codec_config_cb = bspp_h264parse_codecconfig;
+	pparser_callbacks->update_unit_counts_cb = bspp_h264update_unitcounts;
+
+	/* Set h.246 specific features. */
+	pvidstd_features->seq_size = sizeof(struct bspp_h264_seq_hdr_info);
+	pvidstd_features->uses_pps = 1;
+	pvidstd_features->pps_size = sizeof(struct bspp_h264_pps_info);
+
+	/* Set h.246 specific shift register config. */
+	pswsr_ctx->emulation_prevention = SWSR_EMPREVENT_00000300;
+	pinterpict_data->h264_ctx.active_sps_for_sei_parsing = BSPP_INVALID;
+
+	if (bstr_format == VDEC_BSTRFORMAT_DEMUX_BYTESTREAM ||
+	    bstr_format == VDEC_BSTRFORMAT_ELEMENTARY) {
+		pswsr_ctx->sr_config.delim_type = SWSR_DELIM_SCP;
+		pswsr_ctx->sr_config.delim_length = 3 * 8;
+		pswsr_ctx->sr_config.scp_value = 0x000001;
+	} else if (bstr_format == VDEC_BSTRFORMAT_DEMUX_SIZEDELIMITED) {
+		pswsr_ctx->sr_config.delim_type = SWSR_DELIM_SIZE;
+		/* Set the default size-delimiter number of bits */
+		pswsr_ctx->sr_config.delim_length = 4 * 8;
+	} else {
+		VDEC_ASSERT(0);
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	return 0;
+}
+
+/*
+ * This function determines the BSPP unit type based on the
+ * provided bitstream (H264 specific) unit type
+ */
+void bspp_h264_determine_unittype(unsigned char bitstream_unittype,
+				  int disable_mvc,
+				  enum bspp_unit_type *bspp_unittype)
+{
+	unsigned char type = bitstream_unittype & 0x1f;
+
+	switch (type) {
+	case H264_NALTYPE_SLICE_PREFIX:
+		*bspp_unittype = disable_mvc ? BSPP_UNIT_UNCLASSIFIED : BSPP_UNIT_PICTURE;
+		break;
+	case H264_NALTYPE_SUBSET_SPS:
+		*bspp_unittype = disable_mvc ? BSPP_UNIT_UNCLASSIFIED : BSPP_UNIT_SEQUENCE;
+		break;
+	case H264_NALTYPE_SLICE_SCALABLE:
+	case H264_NALTYPE_SLICE_IDR_SCALABLE:
+		*bspp_unittype = disable_mvc ? BSPP_UNIT_NON_PICTURE : BSPP_UNIT_PICTURE;
+		break;
+	case H264_NALTYPE_SEQUENCE_PARAMETER_SET:
+		*bspp_unittype = BSPP_UNIT_SEQUENCE;
+		break;
+	case H264_NALTYPE_PICTURE_PARAMETER_SET:
+		*bspp_unittype = BSPP_UNIT_PPS;
+		break;
+	case H264_NALTYPE_SLICE:
+	case H264_NALTYPE_SLICE_PARTITION_A:
+	case H264_NALTYPE_SLICE_PARTITION_B:
+	case H264_NALTYPE_SLICE_PARTITION_C:
+	case H264_NALTYPE_IDR_SLICE:
+		*bspp_unittype = BSPP_UNIT_PICTURE;
+		break;
+	case H264_NALTYPE_ACCESS_UNIT_DELIMITER:
+	case H264_NALTYPE_SUPPLEMENTAL_ENHANCEMENT_INFO:
+		/*
+		 * Each of these NAL units should not change unit type if
+		 * current is picture, since they can occur anywhere, any number
+		 * of times
+		 */
+		*bspp_unittype = BSPP_UNIT_UNCLASSIFIED;
+		break;
+	case H264_NALTYPE_END_OF_SEQUENCE:
+	case H264_NALTYPE_END_OF_STREAM:
+	case H264_NALTYPE_FILLER_DATA:
+	case H264_NALTYPE_SEQUENCE_PARAMETER_SET_EXTENSION:
+	case H264_NALTYPE_AUXILIARY_SLICE:
+		*bspp_unittype = BSPP_UNIT_NON_PICTURE;
+		break;
+	default:
+		*bspp_unittype = BSPP_UNIT_UNSUPPORTED;
+		break;
+	}
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/h264_secure_parser.h b/drivers/media/platform/img/vxe-vxd/decoder/h264_secure_parser.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/h264_secure_parser.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/h264_secure_parser.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,278 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * h.264 secure data unit parsing API.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ * Re-written for upstreming
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef __H264SECUREPARSER_H__
+#define __H264SECUREPARSER_H__
+
+#include "bspp_int.h"
+#include "vdec_defs.h"
+
+/*
+ * enum h264_nalunittype
+ * @Description Contains H264 NAL unit types
+ */
+enum h264_nalunittype {
+	H264_NALTYPE_UNSPECIFIED                      = 0,
+	H264_NALTYPE_SLICE                            = 1,
+	H264_NALTYPE_SLICE_PARTITION_A                = 2,
+	H264_NALTYPE_SLICE_PARTITION_B                = 3,
+	H264_NALTYPE_SLICE_PARTITION_C                = 4,
+	H264_NALTYPE_IDR_SLICE                        = 5,
+	H264_NALTYPE_SUPPLEMENTAL_ENHANCEMENT_INFO    = 6,
+	H264_NALTYPE_SEQUENCE_PARAMETER_SET           = 7,
+	H264_NALTYPE_PICTURE_PARAMETER_SET            = 8,
+	H264_NALTYPE_ACCESS_UNIT_DELIMITER            = 9,
+	H264_NALTYPE_END_OF_SEQUENCE                  = 10,
+	H264_NALTYPE_END_OF_STREAM                    = 11,
+	H264_NALTYPE_FILLER_DATA                      = 12,
+	H264_NALTYPE_SEQUENCE_PARAMETER_SET_EXTENSION = 13,
+	H264_NALTYPE_SLICE_PREFIX                     = 14,
+	H264_NALTYPE_SUBSET_SPS                       = 15,
+	H264_NALTYPE_AUXILIARY_SLICE                  = 19,
+	H264_NALTYPE_SLICE_SCALABLE                   = 20,
+	H264_NALTYPE_SLICE_IDR_SCALABLE               = 21,
+	H264_NALTYPE_MAX                              = 31,
+	H264_NALTYPE_FORCE32BITS                      = 0x7FFFFFFFU
+};
+
+/*
+ * struct bspp_h264_sps_info
+ * @Description	H264 SPS parsed information
+ */
+struct bspp_h264_sps_info {
+	unsigned int profile_idc;
+	unsigned int constraint_set_flags;
+	unsigned int level_idc;
+	unsigned char seq_parameter_set_id;
+	unsigned char chroma_format_idc;
+	int separate_colour_plane_flag;
+	unsigned int bit_depth_luma_minus8;
+	unsigned int bit_depth_chroma_minus8;
+	unsigned char qpprime_y_zero_transform_bypass_flag;
+	int seq_scaling_matrix_present_flag;
+	unsigned char seq_scaling_list_present_flag[12];
+	unsigned int log2_max_frame_num_minus4;
+	unsigned int pic_order_cnt_type;
+	unsigned int log2_max_pic_order_cnt_lsb_minus4;
+	int delta_pic_order_always_zero_flag;
+	int offset_for_non_ref_pic;
+	int offset_for_top_to_bottom_field;
+	unsigned int num_ref_frames_in_pic_order_cnt_cycle;
+	unsigned int *offset_for_ref_frame;
+	unsigned int max_num_ref_frames;
+	int gaps_in_frame_num_value_allowed_flag;
+	unsigned int pic_width_in_mbs_minus1;
+	unsigned int pic_height_in_map_units_minus1;
+	int frame_mbs_only_flag;
+	int mb_adaptive_frame_field_flag;
+	int direct_8x8_inference_flag;
+	int frame_cropping_flag;
+	unsigned int frame_crop_left_offset;
+	unsigned int frame_crop_right_offset;
+	unsigned int frame_crop_top_offset;
+	unsigned int frame_crop_bottom_offset;
+	int vui_parameters_present_flag;
+	/* mvc_vui_parameters_present_flag;   UNUSED */
+	int bmvcvuiparameterpresentflag;
+	/*
+	 * scaling lists are derived from both SPS and PPS information
+	 * but will change whenever the PPS changes
+	 * The derived set of tables are associated here with the PPS
+	 * NB: These are in H.264 order
+	 */
+	/* derived from SPS and PPS - 8 bit each */
+	unsigned char *scllst4x4seq;
+	/* derived from SPS and PPS - 8 bit each */
+	unsigned char *scllst8x8seq;
+	/* This is not direct parsed data, though it is extracted */
+	unsigned char usedefaultscalingmatrixflag_seq[12];
+};
+
+struct bspp_h264_hrdparam_info {
+	unsigned char cpb_cnt_minus1;
+	unsigned char bit_rate_scale;
+	unsigned char cpb_size_scale;
+	unsigned int *bit_rate_value_minus1;
+	unsigned int *cpb_size_value_minus1;
+	unsigned char *cbr_flag;
+	unsigned char initial_cpb_removal_delay_length_minus1;
+	unsigned char cpb_removal_delay_length_minus1;
+	unsigned char dpb_output_delay_length_minus1;
+	unsigned char time_offset_length;
+};
+
+struct bspp_h264_vui_info {
+	unsigned char aspect_ratio_info_present_flag;
+	unsigned int aspect_ratio_idc;
+	unsigned int sar_width;
+	unsigned int sar_height;
+	unsigned char overscan_info_present_flag;
+	unsigned char overscan_appropriate_flag;
+	unsigned char video_signal_type_present_flag;
+	unsigned int video_format;
+	unsigned char video_full_range_flag;
+	unsigned char colour_description_present_flag;
+	unsigned int colour_primaries;
+	unsigned int transfer_characteristics;
+	unsigned int matrix_coefficients;
+	unsigned char chroma_location_info_present_flag;
+	unsigned int chroma_sample_loc_type_top_field;
+	unsigned int chroma_sample_loc_type_bottom_field;
+	unsigned char timing_info_present_flag;
+	unsigned int num_units_in_tick;
+	unsigned int time_scale;
+	unsigned char fixed_frame_rate_flag;
+	unsigned char nal_hrd_parameters_present_flag;
+	struct bspp_h264_hrdparam_info nal_hrd_parameters;
+	unsigned char vcl_hrd_parameters_present_flag;
+	struct bspp_h264_hrdparam_info vcl_hrd_parameters;
+	unsigned char low_delay_hrd_flag;
+	unsigned char pic_struct_present_flag;
+	unsigned char bitstream_restriction_flag;
+	unsigned char motion_vectors_over_pic_boundaries_flag;
+	unsigned int max_bytes_per_pic_denom;
+	unsigned int max_bits_per_mb_denom;
+	unsigned int log2_max_mv_length_vertical;
+	unsigned int log2_max_mv_length_horizontal;
+	unsigned int num_reorder_frames;
+	unsigned int max_dec_frame_buffering;
+};
+
+/*
+ * struct bspp_h264_seq_hdr_info
+ * @Description	Contains everything parsed from the Sequence Header.
+ */
+struct bspp_h264_seq_hdr_info {
+	/* Video sequence header information */
+	struct bspp_h264_sps_info sps_info;
+	/* VUI sequence header information. */
+	struct bspp_h264_vui_info vui_info;
+};
+
+/**
+ * struct bspp_h264_ppssgm_info - This structure contains H264 PPS parse data.
+ * @slice_group_id: slice_group_id
+ * @slicegroupidnum: slicegroupidnum
+ */
+struct bspp_h264_ppssgm_info {
+	unsigned char *slice_group_id;
+	unsigned short slicegroupidnum;
+};
+
+/*
+ * struct bspp_h264_pps_info
+ * @Description	This structure contains H264 PPS parse data.
+ */
+struct bspp_h264_pps_info {
+	/* pic_parameter_set_id: defines the PPS ID of the current PPS */
+	int pps_id;
+	/* seq_parameter_set_id: defines the SPS that current PPS points to */
+	int seq_parameter_set_id;
+	int entropy_coding_mode_flag;
+	int pic_order_present_flag;
+	unsigned char num_slice_groups_minus1;
+	unsigned char slice_group_map_type;
+	unsigned short run_length_minus1[8];
+	unsigned short top_left[8];
+	unsigned short bottom_right[8];
+	int slice_group_change_direction_flag;
+	unsigned short slice_group_change_rate_minus1;
+	unsigned short pic_size_in_map_unit;
+	struct bspp_h264_ppssgm_info h264_ppssgm_info;
+	unsigned char num_ref_idx_lx_active_minus1[H264FW_MAX_REFPIC_LISTS];
+	int weighted_pred_flag;
+	unsigned char weighted_bipred_idc;
+	int pic_init_qp_minus26;
+	int pic_init_qs_minus26;
+	int chroma_qp_index_offset;
+	int deblocking_filter_control_present_flag;
+	int constrained_intra_pred_flag;
+	int redundant_pic_cnt_present_flag;
+	int transform_8x8_mode_flag;
+	int pic_scaling_matrix_present_flag;
+	unsigned char pic_scaling_list_present_flag[12];
+	int second_chroma_qp_index_offset;
+
+	/*
+	 * scaling lists are derived from both SPS and PPS information
+	 * but will change whenever the PPS changes
+	 * The derived set of tables are associated here with the PPS
+	 * NB: These are in H.264 order
+	 */
+	/* derived from SPS and PPS - 8 bit each */
+	unsigned char *scllst4x4pic;
+	/* derived from SPS and PPS - 8 bit each */
+	unsigned char *scllst8x8pic;
+	/* This is not direct parsed data, though it is extracted */
+	unsigned char usedefaultscalingmatrixflag_pic[12];
+};
+
+/*
+ * enum bspp_h264_slice_type
+ * @Description	contains H264 slice types
+ */
+enum bspp_h264_slice_type {
+	P_SLICE = 0,
+	B_SLICE,
+	I_SLICE,
+	SP_SLICE,
+	SI_SLICE,
+	SLICE_TYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * struct bspp_h264_slice_hdr_info
+ * @Description This structure contains H264 slice header information
+ */
+struct bspp_h264_slice_hdr_info {
+	unsigned short first_mb_in_slice;
+	enum bspp_h264_slice_type slice_type;
+
+	/* data to ID new picture */
+	unsigned int pps_id;
+	unsigned int frame_num;
+	unsigned char colour_plane_id;
+	unsigned char field_pic_flag;
+	unsigned char bottom_field_flag;
+	unsigned int idr_pic_id;
+	unsigned int pic_order_cnt_lsb;
+	int delta_pic_order_cnt_bottom;
+	int delta_pic_order_cnt[2];
+	unsigned int redundant_pic_cnt;
+
+	/* Things we need to read out when doing In Secure */
+	unsigned char num_ref_idx_active_override_flag;
+	unsigned char num_ref_idx_lx_active_minus1[2];
+	unsigned short slice_group_change_cycle;
+};
+
+/*
+ * @Function	bspp_h264_set_parser_config
+ * @Description	Sets the parser configuration
+ */
+int bspp_h264_set_parser_config(enum vdec_bstr_format bstr_format,
+				struct bspp_vid_std_features *pvidstd_features,
+				struct bspp_swsr_ctx *pswsr_ctx,
+				struct bspp_parser_callbacks *pparser_callbacks,
+				struct bspp_inter_pict_data *pinterpict_data);
+
+/*
+ * @Function	bspp_h264_determine_unittype
+ * @Description	This function determines the BSPP unit type based on the
+ *		provided bitstream (H264 specific) unit type
+ */
+void bspp_h264_determine_unittype(unsigned char bitstream_unittype,
+				  int disable_mvc,
+				  enum bspp_unit_type *pbsppunittype);
+
+#endif /*__H264SECUREPARSER_H__ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/h264_vlc.h b/drivers/media/platform/img/vxe-vxd/decoder/h264_vlc.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/h264_vlc.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/h264_vlc.h	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,604 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * h264 vlc table definitions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ */
+
+#ifndef __H264_VLC_H__
+#define __H264_VLC_H__
+
+#include <linux/types.h>
+
+static unsigned short h264_vlc_table_data[] = {
+/* NumCoeffTrailingOnes_Table9-5_nC_0-1.out */
+	4, 0, 0,
+	4, 1, 5,
+	4, 2, 10,
+	2, 1, 4,
+	2, 1, 6,
+	0, 1, 8,
+	0, 2, 11,
+	4, 0, 15,
+	4, 1, 4,
+	4, 1, 9,
+	4, 0, 19,
+	4, 1, 14,
+	4, 1, 23,
+	4, 1, 27,
+	4, 1, 18,
+	4, 1, 13,
+	4, 1, 8,
+	2, 5, 8,
+	0, 1, 50,
+	0, 0, 53,
+	0, 0, 54,
+	4, 2, 31,
+	4, 2, 22,
+	4, 2, 17,
+	4, 2, 12,
+	0, 2, 7,
+	0, 2, 14,
+	0, 2, 21,
+	0, 2, 28,
+	0, 1, 35,
+	4, 5, 53,
+	3, 5, 0,
+	4, 2, 32,
+	4, 2, 38,
+	4, 2, 33,
+	4, 2, 28,
+	4, 2, 43,
+	4, 2, 34,
+	4, 2, 29,
+	4, 2, 24,
+	4, 2, 51,
+	4, 2, 46,
+	4, 2, 41,
+	4, 2, 40,
+	4, 2, 47,
+	4, 2, 42,
+	4, 2, 37,
+	4, 2, 36,
+	4, 2, 59,
+	4, 2, 54,
+	4, 2, 49,
+	4, 2, 48,
+	4, 2, 55,
+	4, 2, 50,
+	4, 2, 45,
+	4, 2, 44,
+	4, 2, 67,
+	4, 2, 62,
+	4, 2, 61,
+	4, 2, 56,
+	4, 2, 63,
+	4, 2, 58,
+	4, 2, 57,
+	4, 2, 52,
+	4, 1, 64,
+	4, 1, 66,
+	4, 1, 65,
+	4, 1, 60,
+	4, 1, 39,
+	4, 1, 30,
+	4, 1, 25,
+	4, 1, 20,
+	4, 0, 35,
+	4, 0, 26,
+	4, 0, 21,
+	4, 0, 16,
+/* NumCoeffTrailingOnes_Table9-5_nC_2-3.out */
+	0, 2, 16,
+	0, 1, 73,
+	0, 1, 76,
+	0, 0, 79,
+	4, 3, 19,
+	4, 3, 15,
+	4, 2, 10,
+	4, 2, 10,
+	4, 1, 5,
+	4, 1, 5,
+	4, 1, 5,
+	4, 1, 5,
+	4, 1, 0,
+	4, 1, 0,
+	4, 1, 0,
+	4, 1, 0,
+	2, 5, 8,
+	0, 1, 49,
+	0, 0, 52,
+	0, 0, 53,
+	4, 2, 35,
+	4, 2, 22,
+	4, 2, 21,
+	4, 2, 12,
+	0, 2, 7,
+	0, 2, 14,
+	0, 2, 21,
+	1, 1, 28,
+	0, 1, 34,
+	4, 5, 63,
+	3, 5, 0,
+	4, 2, 47,
+	4, 2, 38,
+	4, 2, 37,
+	4, 2, 32,
+	4, 2, 43,
+	4, 2, 34,
+	4, 2, 33,
+	4, 2, 28,
+	4, 2, 44,
+	4, 2, 46,
+	4, 2, 45,
+	4, 2, 40,
+	4, 2, 51,
+	4, 2, 42,
+	4, 2, 41,
+	4, 2, 36,
+	4, 2, 59,
+	4, 2, 54,
+	4, 2, 53,
+	4, 2, 52,
+	4, 2, 55,
+	4, 2, 50,
+	4, 2, 49,
+	4, 2, 48,
+	0, 1, 3,
+	4, 1, 58,
+	4, 1, 56,
+	4, 1, 61,
+	4, 1, 60,
+	4, 1, 62,
+	4, 1, 57,
+	4, 1, 67,
+	4, 1, 66,
+	4, 1, 65,
+	4, 1, 64,
+	4, 1, 39,
+	4, 1, 30,
+	4, 1, 29,
+	4, 1, 24,
+	4, 0, 20,
+	4, 0, 26,
+	4, 0, 25,
+	4, 0, 16,
+	4, 1, 31,
+	4, 1, 18,
+	4, 1, 17,
+	4, 1, 8,
+	4, 1, 27,
+	4, 1, 14,
+	4, 1, 13,
+	4, 1, 4,
+	4, 0, 23,
+	4, 0, 9,
+/* NumCoeffTrailingOnes_Table9-5_nC_4-7.out */
+	2, 1, 16,
+	0, 2, 50,
+	0, 1, 57,
+	0, 1, 60,
+	6, 0, 10,
+	6, 0, 8,
+	0, 0, 61,
+	0, 0, 62,
+	4, 3, 31,
+	4, 3, 27,
+	4, 3, 23,
+	4, 3, 19,
+	4, 3, 15,
+	4, 3, 10,
+	4, 3, 5,
+	4, 3, 0,
+	0, 2, 3,
+	0, 2, 10,
+	0, 3, 17,
+	4, 2, 51,
+	4, 2, 46,
+	4, 2, 41,
+	4, 2, 36,
+	4, 2, 47,
+	4, 2, 42,
+	4, 2, 37,
+	4, 2, 32,
+	4, 2, 48,
+	4, 2, 54,
+	4, 2, 49,
+	4, 2, 44,
+	4, 2, 55,
+	4, 2, 50,
+	4, 2, 45,
+	4, 2, 40,
+	3, 3, 0,
+	4, 3, 64,
+	4, 3, 67,
+	4, 3, 66,
+	4, 3, 65,
+	4, 3, 60,
+	4, 3, 63,
+	4, 3, 62,
+	4, 3, 61,
+	4, 3, 56,
+	4, 3, 59,
+	4, 3, 58,
+	4, 3, 57,
+	4, 3, 52,
+	4, 2, 53,
+	4, 2, 53,
+	4, 2, 28,
+	4, 2, 24,
+	4, 2, 38,
+	4, 2, 20,
+	4, 2, 43,
+	4, 2, 34,
+	4, 2, 33,
+	4, 2, 16,
+	4, 1, 12,
+	4, 1, 30,
+	4, 1, 29,
+	4, 1, 8,
+	4, 1, 39,
+	4, 1, 26,
+	4, 1, 25,
+	4, 1, 4,
+	4, 0, 13,
+	4, 0, 35,
+	4, 0, 14,
+	4, 0, 9,
+/* NumCoeffTrailingOnesFixedLen.out */
+	2, 1, 8,
+	5, 2, 6,
+	5, 2, 10,
+	5, 2, 14,
+	5, 2, 18,
+	5, 2, 22,
+	5, 2, 26,
+	5, 2, 30,
+	5, 1, 4,
+	0, 0, 2,
+	5, 0, 2,
+	3, 0, 0,
+	4, 0, 0,
+/* NumCoeffTrailingOnesChromaDC_YUV420.out */
+	4, 0, 5,
+	4, 1, 0,
+	4, 2, 10,
+	0, 2, 1,
+	1, 1, 8,
+	0, 0, 10,
+	4, 2, 16,
+	4, 2, 12,
+	4, 2, 8,
+	4, 2, 15,
+	4, 2, 9,
+	4, 2, 4,
+	4, 0, 19,
+	4, 1, 18,
+	4, 1, 17,
+	4, 0, 14,
+	4, 0, 13,
+/* NumCoeffTrailingOnesChromaDC_YUV422.out */
+	4, 0, 0,
+	4, 1, 5,
+	4, 2, 10,
+	0, 2, 4,
+	4, 4, 15,
+	4, 5, 19,
+	2, 3, 9,
+	4, 2, 27,
+	4, 2, 23,
+	4, 2, 18,
+	4, 2, 14,
+	4, 2, 13,
+	4, 2, 9,
+	4, 2, 8,
+	4, 2, 4,
+	0, 1, 5,
+	0, 1, 8,
+	0, 1, 11,
+	0, 1, 14,
+	1, 2, 17,
+	4, 1, 22,
+	4, 1, 17,
+	4, 1, 16,
+	4, 1, 12,
+	4, 1, 31,
+	4, 1, 26,
+	4, 1, 21,
+	4, 1, 20,
+	4, 1, 35,
+	4, 1, 30,
+	4, 1, 25,
+	4, 1, 24,
+	4, 1, 34,
+	4, 1, 33,
+	4, 1, 29,
+	4, 1, 28,
+	3, 2, 0,
+	3, 2, 0,
+	3, 2, 0,
+	4, 2, 32,
+/* TotalZeros_00.out */
+	4, 0, 0,
+	0, 0, 6,
+	0, 0, 7,
+	0, 0, 8,
+	0, 0, 9,
+	0, 0, 10,
+	0, 2, 11,
+	4, 0, 2,
+	4, 0, 1,
+	4, 0, 4,
+	4, 0, 3,
+	4, 0, 6,
+	4, 0, 5,
+	4, 0, 8,
+	4, 0, 7,
+	4, 0, 10,
+	4, 0, 9,
+	3, 2, 0,
+	4, 2, 15,
+	4, 2, 14,
+	4, 2, 13,
+	4, 1, 12,
+	4, 1, 12,
+	4, 1, 11,
+	4, 1, 11,
+/* TotalZeros_01.out */
+	1, 1, 8,
+	0, 0, 14,
+	0, 0, 15,
+	4, 2, 4,
+	4, 2, 3,
+	4, 2, 2,
+	4, 2, 1,
+	4, 2, 0,
+	0, 1, 3,
+	4, 1, 10,
+	4, 1, 9,
+	4, 1, 14,
+	4, 1, 13,
+	4, 1, 12,
+	4, 1, 11,
+	4, 0, 8,
+	4, 0, 7,
+	4, 0, 6,
+	4, 0, 5,
+/* TotalZeros_02.out */
+	0, 1, 8,
+	0, 0, 13,
+	0, 0, 14,
+	4, 2, 7,
+	4, 2, 6,
+	4, 2, 3,
+	4, 2, 2,
+	4, 2, 1,
+	0, 0, 4,
+	4, 1, 12,
+	4, 1, 10,
+	4, 1, 9,
+	4, 0, 13,
+	4, 0, 11,
+	4, 0, 8,
+	4, 0, 5,
+	4, 0, 4,
+	4, 0, 0,
+/* TotalZeros_03.out */
+	0, 1, 8,
+	0, 0, 11,
+	0, 0, 12,
+	4, 2, 8,
+	4, 2, 6,
+	4, 2, 5,
+	4, 2, 4,
+	4, 2, 1,
+	4, 1, 12,
+	4, 1, 11,
+	4, 1, 10,
+	4, 1, 0,
+	4, 0, 9,
+	4, 0, 7,
+	4, 0, 3,
+	4, 0, 2,
+/* TotalZeros_04.out */
+	2, 1, 8,
+	0, 0, 10,
+	0, 0, 11,
+	4, 2, 7,
+	4, 2, 6,
+	4, 2, 5,
+	4, 2, 4,
+	4, 2, 3,
+	4, 0, 10,
+	4, 1, 9,
+	4, 1, 11,
+	4, 0, 8,
+	4, 0, 2,
+	4, 0, 1,
+	4, 0, 0,
+/* TotalZeros_05.out */
+	2, 2, 8,
+	4, 2, 9,
+	4, 2, 7,
+	4, 2, 6,
+	4, 2, 5,
+	4, 2, 4,
+	4, 2, 3,
+	4, 2, 2,
+	4, 0, 8,
+	4, 1, 1,
+	4, 2, 0,
+	4, 2, 10,
+/* TotalZeros_06.out */
+	2, 2, 8,
+	4, 2, 8,
+	4, 2, 6,
+	4, 2, 4,
+	4, 2, 3,
+	4, 2, 2,
+	4, 1, 5,
+	4, 1, 5,
+	4, 0, 7,
+	4, 1, 1,
+	4, 2, 0,
+	4, 2, 9,
+/* TotalZeros_07.out */
+	2, 3, 4,
+	0, 0, 8,
+	4, 1, 5,
+	4, 1, 4,
+	4, 0, 7,
+	4, 1, 1,
+	4, 2, 2,
+	4, 3, 0,
+	4, 3, 8,
+	4, 0, 6,
+	4, 0, 3,
+/* TotalZeros_08.out */
+	2, 3, 4,
+	4, 1, 6,
+	4, 1, 4,
+	4, 1, 3,
+	4, 0, 5,
+	4, 1, 2,
+	4, 2, 7,
+	4, 3, 0,
+	4, 3, 1,
+/* TotalZeros_09.out */
+	2, 2, 4,
+	4, 1, 5,
+	4, 1, 4,
+	4, 1, 3,
+	4, 0, 2,
+	4, 1, 6,
+	4, 2, 0,
+	4, 2, 1,
+/* TotalZeros_10.out */
+	4, 0, 4,
+	0, 0, 3,
+	4, 2, 2,
+	5, 0, 0,
+	4, 0, 3,
+	4, 0, 5,
+/* TotalZeros_11.out */
+	4, 0, 3,
+	4, 1, 2,
+	4, 2, 4,
+	5, 0, 0,
+/* TotalZeros_12.out */
+	4, 0, 2,
+	4, 1, 3,
+	5, 0, 0,
+/* TotalZeros_13.out */
+	5, 0, 0,
+	4, 0, 2,
+/* TotalZeros_14.out */
+	4, 0, 0,
+	4, 0, 1,
+/* TotalZerosChromaDC_YUV420_00.out */
+	4, 0, 0,
+	4, 1, 1,
+	4, 2, 2,
+	4, 2, 3,
+/* TotalZerosChromaDC_YUV420_01.out */
+	4, 0, 0,
+	4, 1, 1,
+	4, 1, 2,
+/* TotalZerosChromaDC_YUV420_02.out */
+	4, 0, 1,
+	4, 0, 0,
+/* Run_00.out */
+	4, 0, 1,
+	4, 0, 0,
+/* Run_01.out */
+	4, 0, 0,
+	4, 1, 1,
+	4, 1, 2,
+/* Run_02.out */
+	4, 1, 3,
+	4, 1, 2,
+	4, 1, 1,
+	4, 1, 0,
+/* Run_03.out */
+	0, 0, 4,
+	4, 1, 2,
+	4, 1, 1,
+	4, 1, 0,
+	4, 0, 4,
+	4, 0, 3,
+/* Run_04.out */
+	0, 1, 3,
+	4, 1, 1,
+	4, 1, 0,
+	4, 1, 5,
+	4, 1, 4,
+	4, 1, 3,
+	4, 1, 2,
+/* Run_05.out */
+	4, 2, 1,
+	4, 2, 2,
+	4, 2, 4,
+	4, 2, 3,
+	4, 2, 6,
+	4, 2, 5,
+	4, 1, 0,
+	4, 1, 0,
+/* Run_06.out */
+	2, 5, 8,
+	4, 2, 6,
+	4, 2, 5,
+	4, 2, 4,
+	4, 2, 3,
+	4, 2, 2,
+	4, 2, 1,
+	4, 2, 0,
+	4, 0, 7,
+	4, 1, 8,
+	4, 2, 9,
+	4, 3, 10,
+	4, 4, 11,
+	4, 5, 12,
+	2, 1, 1,
+	4, 0, 13,
+	4, 1, 14,
+	3, 1, 0,
+/* TotalZerosChromaDC_YUV422_00.out */
+	4, 0, 0,
+	6, 0, 0,
+	6, 0, 1,
+	4, 3, 5,
+	4, 4, 6,
+	4, 4, 7,
+/* TotalZerosChromaDC_YUV422_01.out */
+	6, 1, 1,
+	4, 1, 1,
+	4, 2, 2,
+	4, 2, 0,
+/* TotalZerosChromaDC_YUV422_02.out */
+	5, 0, 0,
+	4, 1, 2,
+	4, 1, 3,
+	5, 0, 2,
+/* TotalZerosChromaDC_YUV422_03.out */
+	6, 0, 0,
+	4, 1, 3,
+	4, 2, 0,
+	4, 2, 4,
+/* TotalZerosChromaDC_YUV422_04.out */
+	5, 0, 0,
+	5, 0, 1,
+/* TotalZerosChromaDC_YUV422_05.out */
+	5, 0, 0,
+	4, 0, 2,
+/* TotalZerosChromaDC_YUV422_06.out */
+	4, 0, 0,
+	4, 0, 1
+};
+
+static const unsigned short h264_vlc_table_size = 544;
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/hevcfw_data.h b/drivers/media/platform/img/vxe-vxd/decoder/hevcfw_data.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/hevcfw_data.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/hevcfw_data.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,472 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Public data structures for the hevc parser firmware module.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+/* Include shared header version here to replace the standard version. */
+#include "hevcfw_data_shared.h"
+
+#ifndef _HEVCFW_DATA_H_
+#define _HEVCFW_DATA_H_
+
+#include "vdecfw_shared.h"
+
+#define HEVC_MAX_SPS_COUNT              16
+#define HEVC_MAX_PPS_COUNT              64
+
+#define HEVCFW_MAX_NUM_PROFILE_IDC 32
+
+#define HEVCFW_MAX_NUM_REF_PICS 16
+#define HEVCFW_MAX_NUM_ST_REF_PIC_SETS 65
+#define HEVCFW_MAX_NUM_LT_REF_PICS 32
+#define HEVCFW_MAX_NUM_SUBLAYERS 7
+#define HEVCFW_SCALING_LISTS_BUFSIZE 256
+#define HEVCFW_MAX_TILE_COLS 20
+#define HEVCFW_MAX_TILE_ROWS 22
+
+#define HEVCFW_MAX_CHROMA_QP 6
+
+#define HEVCFW_MAX_DPB_SIZE HEVCFW_MAX_NUM_REF_PICS
+#define HEVCFW_REF_PIC_LIST0 0
+#define HEVCFW_REF_PIC_LIST1 1
+#define HEVCFW_NUM_REF_PIC_LISTS 2
+#define HEVCFW_NUM_DPB_DIFF_REGS 4
+
+/* non-critical errors */
+#define HEVC_ERR_INVALID_VALUE (20)
+#define HEVC_ERR_CORRECTION_VALIDVALUE (21)
+
+#define HEVC_IS_ERR_CRITICAL(err) \
+	((err) > HEVC_ERR_CORRECTION_VALIDVALUE ? 1 : 0)
+
+/* critical errors */
+#define HEVC_ERR_INV_VIDEO_DIMENSION (22)
+#define HEVC_ERR_NO_SEQUENCE_HDR (23)
+#define HEVC_ERR_SPS_EXT_UNSUPP (24 | VDECFW_UNSUPPORTED_CODE_BASE)
+#define HEVC_ERR_PPS_EXT_UNSUPP (25 | VDECFW_UNSUPPORTED_CODE_BASE)
+
+#define HEVC_ERR_FAILED_TO_STORE_VPS (100)
+#define HEVC_ERR_FAILED_TO_STORE_SPS (101)
+#define HEVC_ERR_FAILED_TO_STORE_PPS (102)
+
+#define HEVC_ERR_FAILED_TO_FETCH_VPS (103)
+#define HEVC_ERR_FAILED_TO_FETCH_SPS (104)
+#define HEVC_ERR_FAILED_TO_FETCH_PPS (105)
+/* HEVC Scaling Lists (all values are maximum possible ones) */
+#define HEVCFW_SCALING_LIST_NUM_SIZES 4
+#define HEVCFW_SCALING_LIST_NUM_MATRICES 6
+#define HEVCFW_SCALING_LIST_MATRIX_SIZE 64
+
+struct hevcfw_scaling_listdata {
+	unsigned char dc_coeffs
+	[HEVCFW_SCALING_LIST_NUM_SIZES - 2]
+	[HEVCFW_SCALING_LIST_NUM_MATRICES];
+	unsigned char lists
+	[HEVCFW_SCALING_LIST_NUM_SIZES]
+	[HEVCFW_SCALING_LIST_NUM_MATRICES]
+	[HEVCFW_SCALING_LIST_MATRIX_SIZE];
+};
+
+/* HEVC Video Profile_Tier_Level */
+struct hevcfw_profile_tier_level {
+	unsigned char general_profile_space;
+	unsigned char general_tier_flag;
+	unsigned char general_profile_idc;
+	unsigned char general_profile_compatibility_flag[HEVCFW_MAX_NUM_PROFILE_IDC];
+	unsigned char general_progressive_source_flag;
+	unsigned char general_interlaced_source_flag;
+	unsigned char general_non_packed_constraint_flag;
+	unsigned char general_frame_only_constraint_flag;
+	unsigned char general_max_12bit_constraint_flag;
+	unsigned char general_max_10bit_constraint_flag;
+	unsigned char general_max_8bit_constraint_flag;
+	unsigned char general_max_422chroma_constraint_flag;
+	unsigned char general_max_420chroma_constraint_flag;
+	unsigned char general_max_monochrome_constraint_flag;
+	unsigned char general_intra_constraint_flag;
+	unsigned char general_one_picture_only_constraint_flag;
+	unsigned char general_lower_bit_rate_constraint_flag;
+	unsigned char general_level_idc;
+	unsigned char sub_layer_profile_present_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_level_present_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_profile_space[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_tier_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_profile_idc[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_profile_compatibility_flag[HEVCFW_MAX_NUM_SUBLAYERS -
+						   1][HEVCFW_MAX_NUM_PROFILE_IDC];
+	unsigned char sub_layer_progressive_source_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_interlaced_source_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_non_packed_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_frame_only_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_max_12bit_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_max_10bit_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_max_8bit_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_max_422chroma_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_max_420chroma_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_max_monochrome_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_intra_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_one_picture_only_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_lower_bit_rate_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_level_idc[HEVCFW_MAX_NUM_SUBLAYERS - 1];
+};
+
+struct hevcfw_video_ps {
+	int is_different;
+	int is_sent;
+	int is_available;
+	unsigned char vps_video_parameter_set_id;
+	unsigned char vps_reserved_three_2bits;
+	unsigned char vps_max_layers_minus1;
+	unsigned char vps_max_sub_layers_minus1;
+	unsigned char vps_temporal_id_nesting_flag;
+	unsigned short vps_reserved_0xffff_16bits;
+	struct hevcfw_profile_tier_level profile_tier_level;
+};
+
+/* HEVC Video Usability Information */
+struct hevcfw_vui_params {
+	unsigned char aspect_ratio_info_present_flag;
+	unsigned char aspect_ratio_idc;
+	unsigned short sar_width;
+	unsigned short sar_height;
+	unsigned char overscan_info_present_flag;
+	unsigned char overscan_appropriate_flag;
+	unsigned char video_signal_type_present_flag;
+	unsigned char video_format;
+	unsigned char video_full_range_flag;
+	unsigned char colour_description_present_flag;
+	unsigned char colour_primaries;
+	unsigned char transfer_characteristics;
+	unsigned char matrix_coeffs;
+	unsigned char chroma_loc_info_present_flag;
+	unsigned char chroma_sample_loc_type_top_field;
+	unsigned char chroma_sample_loc_type_bottom_field;
+	unsigned char neutral_chroma_indication_flag;
+	unsigned char field_seq_flag;
+	unsigned char frame_field_info_present_flag;
+	unsigned char default_display_window_flag;
+	unsigned short def_disp_win_left_offset;
+	unsigned short def_disp_win_right_offset;
+	unsigned short def_disp_win_top_offset;
+	unsigned short def_disp_win_bottom_offset;
+	unsigned char vui_timing_info_present_flag;
+	unsigned int vui_num_units_in_tick;
+	unsigned int vui_time_scale;
+};
+
+/* HEVC Short Term Reference Picture Set */
+struct hevcfw_short_term_ref_picset {
+	unsigned char num_negative_pics;
+	unsigned char num_positive_pics;
+	short delta_poc_s0[HEVCFW_MAX_NUM_REF_PICS];
+	short delta_poc_s1[HEVCFW_MAX_NUM_REF_PICS];
+	unsigned char used_bycurr_pic_s0[HEVCFW_MAX_NUM_REF_PICS];
+	unsigned char used_bycurr_pic_s1[HEVCFW_MAX_NUM_REF_PICS];
+	unsigned char num_delta_pocs;
+};
+
+/*
+ * This describes the SPS header data required by the HEVC firmware that should
+ * be supplied by the Host.
+ */
+struct hevcfw_sequence_ps {
+	/* syntax elements from SPS */
+	unsigned short pic_width_in_luma_samples;
+	unsigned short pic_height_in_luma_samples;
+	unsigned char num_short_term_ref_pic_sets;
+	unsigned char num_long_term_ref_pics_sps;
+	unsigned short lt_ref_pic_poc_lsb_sps[HEVCFW_MAX_NUM_LT_REF_PICS];
+	unsigned char used_by_curr_pic_lt_sps_flag[HEVCFW_MAX_NUM_LT_REF_PICS];
+	struct hevcfw_short_term_ref_picset st_rps_list[HEVCFW_MAX_NUM_ST_REF_PIC_SETS];
+	unsigned char sps_max_sub_layers_minus1;
+	unsigned char sps_max_dec_pic_buffering_minus1[HEVCFW_MAX_NUM_SUBLAYERS];
+	unsigned char sps_max_num_reorder_pics[HEVCFW_MAX_NUM_SUBLAYERS];
+	unsigned int sps_max_latency_increase_plus1[HEVCFW_MAX_NUM_SUBLAYERS];
+	unsigned char max_transform_hierarchy_depth_inter;
+	unsigned char max_transform_hierarchy_depth_intra;
+	unsigned char log2_diff_max_min_transform_block_size;
+	unsigned char log2_min_transform_block_size_minus2;
+	unsigned char log2_diff_max_min_luma_coding_block_size;
+	unsigned char log2_min_luma_coding_block_size_minus3;
+	unsigned char chroma_format_idc;
+	unsigned char separate_colour_plane_flag;
+	unsigned char num_extra_slice_header_bits;
+	unsigned char log2_max_pic_order_cnt_lsb_minus4;
+	unsigned char long_term_ref_pics_present_flag;
+	unsigned char sample_adaptive_offset_enabled_flag;
+	unsigned char sps_temporal_mvp_enabled_flag;
+	unsigned char bit_depth_luma_minus8;
+	unsigned char bit_depth_chroma_minus8;
+	unsigned char pcm_sample_bit_depth_luma_minus1;
+	unsigned char pcm_sample_bit_depth_chroma_minus1;
+	unsigned char log2_min_pcm_luma_coding_block_size_minus3;
+	unsigned char log2_diff_max_min_pcm_luma_coding_block_size;
+	unsigned char pcm_loop_filter_disabled_flag;
+	unsigned char amp_enabled_flag;
+	unsigned char pcm_enabled_flag;
+	unsigned char strong_intra_smoothing_enabled_flag;
+	unsigned char scaling_list_enabled_flag;
+	unsigned char transform_skip_rotation_enabled_flag;
+	unsigned char transform_skip_context_enabled_flag;
+	unsigned char implicit_rdpcm_enabled_flag;
+	unsigned char explicit_rdpcm_enabled_flag;
+	unsigned char extended_precision_processing_flag;
+	unsigned char intra_smoothing_disabled_flag;
+	unsigned char high_precision_offsets_enabled_flag;
+	unsigned char persistent_rice_adaptation_enabled_flag;
+	unsigned char cabac_bypass_alignment_enabled_flag;
+	/* derived elements */
+	unsigned int pic_size_in_ctbs_y;
+	unsigned short pic_height_in_ctbs_y;
+	unsigned short pic_width_in_ctbs_y;
+	unsigned char ctb_size_y;
+	unsigned char ctb_log2size_y;
+	int max_pic_order_cnt_lsb;
+	unsigned int sps_max_latency_pictures[HEVCFW_MAX_NUM_SUBLAYERS];
+	unsigned char pps_seq_parameter_set_id;
+	unsigned char sps_video_parameter_set_id;
+	unsigned char sps_temporal_id_nesting_flag;
+	unsigned char sps_seq_parameter_set_id;
+	/* local */
+	unsigned char conformance_window_flag;
+	unsigned short conf_win_left_offset;
+	unsigned short conf_win_right_offset;
+	unsigned short conf_win_top_offset;
+	unsigned short conf_win_bottom_offset;
+	unsigned char sps_sub_layer_ordering_info_present_flag;
+	unsigned char sps_scaling_list_data_present_flag;
+	unsigned char vui_parameters_present_flag;
+	unsigned char sps_extension_present_flag;
+	struct hevcfw_vui_params vui_params;
+	/* derived elements */
+	unsigned char sub_width_c;
+	unsigned char sub_height_c;
+	struct hevcfw_profile_tier_level profile_tier_level;
+	struct hevcfw_scaling_listdata scaling_listdata;
+};
+
+/*
+ * This describes the HEVC parser component "Header data", shown in the
+ * Firmware Memory Layout diagram. This data is required by the HEVC firmware
+ * and should be supplied by the Host.
+ */
+struct hevcfw_headerdata {
+	/* Decode buffers and output control for the current picture */
+	/* Primary decode buffer base addresses */
+	struct vdecfw_image_buffer primary;
+	/* buffer base addresses for alternate output */
+	struct vdecfw_image_buffer alternate;
+	/* address of buffer for temporal mv params */
+	unsigned int temporal_outaddr;
+};
+
+/*
+ * This describes the PPS header data required by the HEVC firmware that should
+ * be supplied by the Host.
+ */
+struct hevcfw_picture_ps {
+	/* syntax elements from the PPS */
+	unsigned char pps_pic_parameter_set_id;
+	unsigned char num_tile_columns_minus1;
+	unsigned char num_tile_rows_minus1;
+	unsigned char diff_cu_qp_delta_depth;
+	unsigned char init_qp_minus26;
+	unsigned char pps_beta_offset_div2;
+	unsigned char pps_tc_offset_div2;
+	unsigned char pps_cb_qp_offset;
+	unsigned char pps_cr_qp_offset;
+	unsigned char log2_parallel_merge_level_minus2;
+	unsigned char dependent_slice_segments_enabled_flag;
+	unsigned char output_flag_present_flag;
+	unsigned char num_extra_slice_header_bits;
+	unsigned char lists_modification_present_flag;
+	unsigned char cabac_init_present_flag;
+	unsigned char weighted_pred_flag;
+	unsigned char weighted_bipred_flag;
+	unsigned char pps_slice_chroma_qp_offsets_present_flag;
+	unsigned char deblocking_filter_override_enabled_flag;
+	unsigned char tiles_enabled_flag;
+	unsigned char entropy_coding_sync_enabled_flag;
+	unsigned char slice_segment_header_extension_present_flag;
+	unsigned char transquant_bypass_enabled_flag;
+	unsigned char cu_qp_delta_enabled_flag;
+	unsigned char transform_skip_enabled_flag;
+	unsigned char sign_data_hiding_enabled_flag;
+	unsigned char num_ref_idx_l0_default_active_minus1;
+	unsigned char num_ref_idx_l1_default_active_minus1;
+	unsigned char constrained_intra_pred_flag;
+	unsigned char pps_deblocking_filter_disabled_flag;
+	unsigned char pps_loop_filter_across_slices_enabled_flag;
+	unsigned char loop_filter_across_tiles_enabled_flag;
+	/* rewritten from SPS, maybe at some point we could get rid of this */
+	unsigned char scaling_list_enabled_flag;
+	unsigned char log2_max_transform_skip_block_size_minus2;
+	unsigned char cross_component_prediction_enabled_flag;
+	unsigned char chroma_qp_offset_list_enabled_flag;
+	unsigned char diff_cu_chroma_qp_offset_depth;
+	/*
+	 * PVDEC derived elements. HEVCFW_SCALING_LISTS_BUFSIZE is
+	 * multiplied by 2 to ensure that there will be space for address of
+	 * each element. These addresses are completed in lower layer.
+	 */
+	unsigned int scaling_lists[HEVCFW_SCALING_LISTS_BUFSIZE * 2];
+	/* derived elements */
+	unsigned short col_bd[HEVCFW_MAX_TILE_COLS + 1];
+	unsigned short row_bd[HEVCFW_MAX_TILE_ROWS + 1];
+
+	unsigned char chroma_qp_offset_list_len_minus1;
+	unsigned char cb_qp_offset_list[HEVCFW_MAX_CHROMA_QP];
+	unsigned char cr_qp_offset_list[HEVCFW_MAX_CHROMA_QP];
+
+	unsigned char uniform_spacing_flag;
+	unsigned char column_width_minus1[HEVCFW_MAX_TILE_COLS];
+	unsigned char row_height_minus1[HEVCFW_MAX_TILE_ROWS];
+
+	unsigned char pps_seq_parameter_set_id;
+	unsigned char deblocking_filter_control_present_flag;
+	unsigned char pps_scaling_list_data_present_flag;
+	unsigned char pps_extension_present_flag;
+
+	struct hevcfw_scaling_listdata scaling_list;
+};
+
+/* This enum determines reference picture status */
+enum hevcfw_reference_type {
+	HEVCFW_REF_UNUSED      = 0,
+	HEVCFW_REF_SHORTTERM,
+	HEVCFW_REF_LONGTERM,
+	HEVCFW_REF_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* This describes an HEVC picture. It is part of the Context data */
+struct hevcfw_picture {
+	/* Primary (reconstructed) picture buffers */
+	struct vdecfw_image_buffer primary;
+	/* Secondary (alternative) picture buffers */
+	struct vdecfw_image_buffer alternate;
+	/* Unique ID for this picture */
+	unsigned int transaction_id;
+	/* nut of first ssh of picture, determines picture type */
+	unsigned char nalunit_type;
+	/* Picture Order Count (frame number) */
+	int pic_order_cnt_val;
+	/* Slice Picture Order Count Lsb */
+	int slice_pic_ordercnt_lsb;
+	unsigned char pic_output_flag;
+	/* information about long-term pictures */
+	unsigned short dpb_longterm_flags;
+	unsigned int dpb_pic_order_diff[HEVCFW_NUM_DPB_DIFF_REGS];
+	/* address of buffer for temporal mv params */
+	unsigned int temporal_outaddr;
+	/* worst case Dpb diff for the current pic */
+	unsigned int dpb_diff;
+};
+
+/*
+ * This is a wrapper for a picture to hold it in a Decoded Picture Buffer
+ * for further reference
+ */
+struct hevcfw_picture_in_dpb {
+	/* DPB data about the picture */
+	enum hevcfw_reference_type ref_type;
+	unsigned char valid;
+	unsigned char needed_for_output;
+	unsigned char pic_latency_count;
+	/* Picture itself */
+	struct hevcfw_picture picture;
+};
+
+/*
+ * This describes an HEVC's Decoded Picture Buffer (DPB).
+ * It is part of the Context data
+ */
+#define HEVCFW_DPB_IDX_INVALID  -1
+
+struct hevcfw_decoded_picture_buffer {
+	/* reference pictures */
+	struct hevcfw_picture_in_dpb pictures[HEVCFW_MAX_DPB_SIZE];
+	/* organizational data of DPB */
+	unsigned int fullness;
+};
+
+/*
+ * This describes an HEVC's Reference Picture Set (RPS).
+ * It is part of the Context data
+ */
+struct hevcfw_reference_picture_set {
+	/* sizes of poc lists */
+	unsigned char num_pocst_curr_before;
+	unsigned char num_pocst_curr_after;
+	unsigned char num_pocst_foll;
+	unsigned char num_poclt_curr;
+	unsigned char num_poclt_foll;
+	/* poc lists */
+	int pocst_curr_before[HEVCFW_MAX_NUM_REF_PICS];
+	int pocst_curr_after[HEVCFW_MAX_NUM_REF_PICS];
+	int pocst_foll[HEVCFW_MAX_NUM_REF_PICS];
+	int poclt_curr[HEVCFW_MAX_NUM_REF_PICS];
+	int poclt_foll[HEVCFW_MAX_NUM_REF_PICS];
+	/* derived elements */
+	unsigned char curr_delta_pocmsb_presentflag[HEVCFW_MAX_NUM_REF_PICS];
+	unsigned char foll_delta_pocmsb_presentflag[HEVCFW_MAX_NUM_REF_PICS];
+	/* reference picture sets: indices in DPB */
+	unsigned char ref_picsetlt_curr[HEVCFW_MAX_NUM_REF_PICS];
+	unsigned char ref_picsetlt_foll[HEVCFW_MAX_NUM_REF_PICS];
+	unsigned char ref_picsetst_curr_before[HEVCFW_MAX_NUM_REF_PICS];
+	unsigned char ref_picsetst_curr_after[HEVCFW_MAX_NUM_REF_PICS];
+	unsigned char ref_picsetst_foll[HEVCFW_MAX_NUM_REF_PICS];
+};
+
+/*
+ * This describes the HEVC parser component "Context data", shown in the
+ * Firmware Memory Layout diagram. This data is the state preserved across
+ * pictures. It is loaded and saved by the Firmware, but requires the host to
+ * provide buffer(s) for this.
+ */
+struct hevcfw_ctx_data {
+	struct hevcfw_sequence_ps sps;
+	struct hevcfw_picture_ps pps;
+	/*
+	 * data from last picture with TemporalId = 0 that is not a RASL, RADL
+	 * or sub-layer non-reference picture
+	 */
+	int prev_pic_order_cnt_lsb;
+	int prev_pic_order_cnt_msb;
+	unsigned char last_irapnorasl_output_flag;
+	/*
+	 * Decoded Pictures Buffer holds information about decoded pictures
+	 * needed for further INTER decoding
+	 */
+	struct hevcfw_decoded_picture_buffer dpb;
+	/* Reference Picture Set is determined on per-picture basis */
+	struct hevcfw_reference_picture_set rps;
+	/*
+	 * Reference Picture List is determined using data from Reference
+	 * Picture Set and from Slice (Segment) Header on per-slice basis
+	 */
+	unsigned char ref_pic_list[HEVCFW_NUM_REF_PIC_LISTS][HEVCFW_MAX_NUM_REF_PICS];
+	/*
+	 * Reference Picture List used to send reflist to the host, the only
+	 * difference is that missing references are marked
+	 * with HEVCFW_DPB_IDX_INVALID
+	 */
+	unsigned char ref_pic_listhlp[HEVCFW_NUM_REF_PIC_LISTS][HEVCFW_MAX_NUM_REF_PICS];
+
+	unsigned int pic_count;
+	unsigned int slice_segment_count;
+	/* There was EOS NAL detected and no new picture yet */
+	int eos_detected;
+	/* This is first picture after EOS NAL */
+	int first_after_eos;
+};
+
+#endif /* _HEVCFW_DATA_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/hevcfw_data_shared.h b/drivers/media/platform/img/vxe-vxd/decoder/hevcfw_data_shared.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/hevcfw_data_shared.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/hevcfw_data_shared.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,767 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Public data structures for the hevc parser firmware module
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifdef USE_SHARING
+#endif
+
+#ifndef _HEVCFW_DATA_H_
+#define _HEVCFW_DATA_H_
+
+#include "vdecfw_share.h"
+#include "vdecfw_shared.h"
+
+#define HEVC_MAX_VPS_COUNT 16
+#define HEVC_MAX_SPS_COUNT 16
+#define HEVC_MAX_PPS_COUNT 64
+
+#define HEVCFW_MAX_NUM_PROFILE_IDC 32
+#define HEVCFW_MAX_VPS_OP_SETS_PLUS1 1024
+#define HEVCFW_MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1 1
+
+#define HEVCFW_MAX_NUM_REF_PICS 16
+#define HEVCFW_MAX_NUM_ST_REF_PIC_SETS 65
+#define HEVCFW_MAX_NUM_LT_REF_PICS 32
+#define HEVCFW_MAX_NUM_SUBLAYERS 7
+#define HEVCFW_SCALING_LISTS_BUFSIZE 256
+#define HEVCFW_MAX_TILE_COLS 20
+#define HEVCFW_MAX_TILE_ROWS 22
+
+#define HEVCFW_MAX_CHROMA_QP 6
+
+#define HEVCFW_MAX_DPB_SIZE HEVCFW_MAX_NUM_REF_PICS
+#define HEVCFW_REF_PIC_LIST0 0
+#define HEVCFW_REF_PIC_LIST1 1
+#define HEVCFW_NUM_REF_PIC_LISTS 2
+#define HEVCFW_NUM_DPB_DIFF_REGS 4
+
+/* non-critical errors*/
+#define HEVC_ERR_INVALID_VALUE (20)
+#define HEVC_ERR_CORRECTION_VALIDVALUE (21)
+
+#define HEVC_IS_ERR_CRITICAL(err) \
+	((err) > HEVC_ERR_CORRECTION_VALIDVALUE ? 1 : 0)
+
+/* critical errors*/
+#define HEVC_ERR_INV_VIDEO_DIMENSION (22)
+#define HEVC_ERR_NO_SEQUENCE_HDR (23)
+#define HEVC_ERR_SPS_EXT_UNSUPP (24 | VDECFW_UNSUPPORTED_CODE_BASE)
+#define HEVC_ERR_PPS_EXT_UNSUPP (25 | VDECFW_UNSUPPORTED_CODE_BASE)
+
+#define HEVC_ERR_FAILED_TO_STORE_VPS (100)
+#define HEVC_ERR_FAILED_TO_STORE_SPS (101)
+#define HEVC_ERR_FAILED_TO_STORE_PPS (102)
+
+#define HEVC_ERR_FAILED_TO_FETCH_VPS (103)
+#define HEVC_ERR_FAILED_TO_FETCH_SPS (104)
+#define HEVC_ERR_FAILED_TO_FETCH_PPS (105)
+/* HEVC Scaling Lists (all values are maximum possible ones) */
+#define HEVCFW_SCALING_LIST_NUM_SIZES 4
+#define HEVCFW_SCALING_LIST_NUM_MATRICES 6
+#define HEVCFW_SCALING_LIST_MATRIX_SIZE 64
+
+struct hevcfw_scaling_listdata {
+	unsigned char dc_coeffs
+	[HEVCFW_SCALING_LIST_NUM_SIZES - 2]
+	[HEVCFW_SCALING_LIST_NUM_MATRICES];
+
+	unsigned char lists
+	[HEVCFW_SCALING_LIST_NUM_SIZES]
+	[HEVCFW_SCALING_LIST_NUM_MATRICES]
+	[HEVCFW_SCALING_LIST_MATRIX_SIZE];
+};
+
+/* HEVC Video Profile_Tier_Level */
+struct hevcfw_profile_tier_level {
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_profile_space);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_tier_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_profile_idc);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			general_profile_compatibility_flag
+			[HEVCFW_MAX_NUM_PROFILE_IDC]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_progressive_source_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_interlaced_source_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_non_packed_constraint_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_frame_only_constraint_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_max_12bit_constraint_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_max_10bit_constraint_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_max_8bit_constraint_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_max_422chroma_constraint_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_max_420chroma_constraint_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_max_monochrome_constraint_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_intra_constraint_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			general_one_picture_only_constraint_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_lower_bit_rate_constraint_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, general_level_idc);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_profile_present_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_level_present_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_profile_space[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_tier_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_profile_idc[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_profile_compatibility_flag
+			[HEVCFW_MAX_NUM_SUBLAYERS - 1][HEVCFW_MAX_NUM_PROFILE_IDC]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_progressive_source_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_interlaced_source_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_non_packed_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_frame_only_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_max_12bit_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_max_10bit_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_max_8bit_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_max_422chroma_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_max_420chroma_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_max_monochrome_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_intra_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_one_picture_only_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_lower_bit_rate_constraint_flag[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sub_layer_level_idc[HEVCFW_MAX_NUM_SUBLAYERS - 1]);
+};
+
+struct hevcfw_video_ps {
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, is_different);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, is_sent);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, is_available);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, vps_video_parameter_set_id);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, vps_reserved_three_2bits);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, vps_max_layers_minus1);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, vps_max_sub_layers_minus1);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, vps_temporal_id_nesting_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, vps_reserved_0xffff_16bits);
+	struct hevcfw_profile_tier_level profile_tier_level;
+};
+
+/* HEVC Video Usability Information */
+struct hevcfw_vui_params {
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, aspect_ratio_info_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, aspect_ratio_idc);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, sar_width);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, sar_height);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, overscan_info_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, overscan_appropriate_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, video_signal_type_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, video_format);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, video_full_range_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, colour_description_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, colour_primaries);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, transfer_characteristics);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, matrix_coeffs);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, chroma_loc_info_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, chroma_sample_loc_type_top_field);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, chroma_sample_loc_type_bottom_field);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, neutral_chroma_indication_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, field_seq_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, frame_field_info_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, default_display_window_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, def_disp_win_left_offset);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, def_disp_win_right_offset);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, def_disp_win_top_offset);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, def_disp_win_bottom_offset);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, vui_timing_info_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, vui_num_units_in_tick);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, vui_time_scale);
+};
+
+/* HEVC Short Term Reference Picture Set */
+struct hevcfw_short_term_ref_picset {
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_negative_pics);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_positive_pics);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			short, delta_poc_s0[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			short, delta_poc_s1[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, used_bycurr_pic_s0[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, used_bycurr_pic_s1[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_delta_pocs);
+};
+
+/*
+ * This describes the SPS header data required by the HEVC firmware that should
+ * be supplied by the Host.
+ */
+struct hevcfw_sequence_ps {
+	/* syntax elements from SPS */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, pic_width_in_luma_samples);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, pic_height_in_luma_samples);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_short_term_ref_pic_sets);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_long_term_ref_pics_sps);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short,
+			lt_ref_pic_poc_lsb_sps[HEVCFW_MAX_NUM_LT_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			used_by_curr_pic_lt_sps_flag[HEVCFW_MAX_NUM_LT_REF_PICS]);
+	struct hevcfw_short_term_ref_picset st_rps_list[HEVCFW_MAX_NUM_ST_REF_PIC_SETS];
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, sps_max_sub_layers_minus1);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sps_max_dec_pic_buffering_minus1[HEVCFW_MAX_NUM_SUBLAYERS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			sps_max_num_reorder_pics[HEVCFW_MAX_NUM_SUBLAYERS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int,
+			sps_max_latency_increase_plus1[HEVCFW_MAX_NUM_SUBLAYERS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, max_transform_hierarchy_depth_inter);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, max_transform_hierarchy_depth_intra);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, log2_diff_max_min_transform_block_size);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, log2_min_transform_block_size_minus2);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			log2_diff_max_min_luma_coding_block_size);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, log2_min_luma_coding_block_size_minus3);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, chroma_format_idc);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, separate_colour_plane_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_extra_slice_header_bits);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, log2_max_pic_order_cnt_lsb_minus4);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, long_term_ref_pics_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, sample_adaptive_offset_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, sps_temporal_mvp_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, bit_depth_luma_minus8);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, bit_depth_chroma_minus8);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pcm_sample_bit_depth_luma_minus1);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pcm_sample_bit_depth_chroma_minus1);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			log2_min_pcm_luma_coding_block_size_minus3);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			log2_diff_max_min_pcm_luma_coding_block_size);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pcm_loop_filter_disabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, amp_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pcm_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, strong_intra_smoothing_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, scaling_list_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, transform_skip_rotation_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, transform_skip_context_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, implicit_rdpcm_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, explicit_rdpcm_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, extended_precision_processing_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, intra_smoothing_disabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, high_precision_offsets_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, persistent_rice_adaptation_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, cabac_bypass_alignment_enabled_flag);
+	/* derived elements */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, pic_size_in_ctbs_y);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, pic_height_in_ctbs_y);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, pic_width_in_ctbs_y);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, ctb_size_y);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, ctb_log2size_y);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, max_pic_order_cnt_lsb);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int,
+			sps_max_latency_pictures[HEVCFW_MAX_NUM_SUBLAYERS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pps_seq_parameter_set_id);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, sps_video_parameter_set_id);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, sps_temporal_id_nesting_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, sps_seq_parameter_set_id);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, conformance_window_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, conf_win_left_offset);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, conf_win_right_offset);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, conf_win_top_offset);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, conf_win_bottom_offset);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, sps_sub_layer_ordering_info_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, sps_scaling_list_data_present_flag);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, vui_parameters_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, sps_extension_present_flag);
+
+	struct hevcfw_vui_params vui_params;
+	/* derived elements */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, sub_width_c);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, sub_height_c);
+
+	struct hevcfw_profile_tier_level profile_tier_level;
+	struct hevcfw_scaling_listdata scaling_listdata;
+};
+
+/*
+ * This describes the HEVC parser component "Header data", shown in the
+ * Firmware Memory Layout diagram. This data is required by the HEVC firmware
+ * and should be supplied by the Host.
+ */
+struct hevcfw_headerdata {
+	/* Decode buffers and output control for the current picture */
+	/* Primary decode buffer base addresses */
+	struct vdecfw_image_buffer primary;
+	/* buffer base addresses for alternate output */
+	struct vdecfw_image_buffer alternate;
+	/* address of buffer for temporal mv params */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, temporal_outaddr);
+};
+
+/*
+ * This describes the PPS header data required by the HEVC firmware that should
+ * be supplied by the Host.
+ */
+struct hevcfw_picture_ps {
+	/* syntax elements from the PPS */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pps_pic_parameter_set_id);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_tile_columns_minus1);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_tile_rows_minus1);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, diff_cu_qp_delta_depth);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, init_qp_minus26);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pps_beta_offset_div2);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pps_tc_offset_div2);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pps_cb_qp_offset);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pps_cr_qp_offset);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, log2_parallel_merge_level_minus2);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, dependent_slice_segments_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, output_flag_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_extra_slice_header_bits);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, lists_modification_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, cabac_init_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, weighted_pred_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, weighted_bipred_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			pps_slice_chroma_qp_offsets_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			deblocking_filter_override_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, tiles_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, entropy_coding_sync_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			slice_segment_header_extension_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, transquant_bypass_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, cu_qp_delta_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, transform_skip_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, sign_data_hiding_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_ref_idx_l0_default_active_minus1);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_ref_idx_l1_default_active_minus1);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, constrained_intra_pred_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pps_deblocking_filter_disabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			pps_loop_filter_across_slices_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, loop_filter_across_tiles_enabled_flag);
+
+	/* rewritten from SPS, maybe at some point we could get rid of this */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, scaling_list_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			log2_max_transform_skip_block_size_minus2);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			cross_component_prediction_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, chroma_qp_offset_list_enabled_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, diff_cu_chroma_qp_offset_depth);
+	/*
+	 * PVDEC derived elements. HEVCFW_SCALING_LISTS_BUFSIZE is
+	 * multiplied by 2 to ensure that there will be space for address of
+	 * each element. These addresses are completed in lower layer.
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int,
+			scaling_lists[HEVCFW_SCALING_LISTS_BUFSIZE * 2]);
+	/* derived elements */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, col_bd[HEVCFW_MAX_TILE_COLS + 1]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, row_bd[HEVCFW_MAX_TILE_ROWS + 1]);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, chroma_qp_offset_list_len_minus1);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, cb_qp_offset_list[HEVCFW_MAX_CHROMA_QP]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, cr_qp_offset_list[HEVCFW_MAX_CHROMA_QP]);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, uniform_spacing_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			column_width_minus1[HEVCFW_MAX_TILE_COLS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			row_height_minus1[HEVCFW_MAX_TILE_ROWS]);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pps_seq_parameter_set_id);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, deblocking_filter_control_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pps_scaling_list_data_present_flag);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pps_extension_present_flag);
+
+	struct hevcfw_scaling_listdata scaling_list;
+};
+
+/* This enum determines reference picture status */
+enum hevcfw_reference_type {
+	HEVCFW_REF_UNUSED      = 0,
+	HEVCFW_REF_SHORTTERM,
+	HEVCFW_REF_LONGTERM,
+	HEVCFW_REF_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* This describes an HEVC picture. It is part of the Context data */
+struct hevcfw_picture {
+	/* Primary (reconstructed) picture buffers */
+	struct vdecfw_image_buffer primary;
+	/* Secondary (alternative) picture buffers */
+	struct vdecfw_image_buffer alternate;
+	/* Unique ID for this picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, transaction_id);
+	/* nut of first ssh of picture, determines picture type */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, nalunit_type);
+	/* Picture Order Count (frame number) */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, pic_order_cnt_val);
+	/* Slice Picture Order Count Lsb */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, slice_pic_ordercnt_lsb);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pic_output_flag);
+	/* information about long-term pictures */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, dpb_longterm_flags);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int,
+			dpb_pic_order_diff[HEVCFW_NUM_DPB_DIFF_REGS]);
+	/* address of buffer for temporal mv params */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, temporal_outaddr);
+	/* worst case Dpb diff for the current pic */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, dpb_diff);
+};
+
+/*
+ * This is a wrapper for a picture to hold it in a Decoded Picture Buffer
+ * for further reference
+ */
+struct hevcfw_picture_in_dpb {
+	/* DPB data about the picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			enum hevcfw_reference_type, ref_type);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, valid);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, needed_for_output);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, pic_latency_count);
+	/* Picture itself */
+	struct hevcfw_picture picture;
+};
+
+/*
+ * This describes an HEVC's Decoded Picture Buffer (DPB).
+ * It is part of the Context data
+ */
+
+#define HEVCFW_DPB_IDX_INVALID -1
+
+struct hevcfw_decoded_picture_buffer {
+	/* reference pictures */
+	struct hevcfw_picture_in_dpb pictures[HEVCFW_MAX_DPB_SIZE];
+	/* organizational data of DPB */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int, fullness);
+};
+
+/*
+ * This describes an HEVC's Reference Picture Set (RPS).
+ * It is part of the Context data
+ */
+struct hevcfw_reference_picture_set {
+	/* sizes of poc lists */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_pocst_curr_before);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_pocst_curr_after);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_pocst_foll);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_poclt_curr);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, num_poclt_foll);
+	/* poc lists */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, pocst_curr_before[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, pocst_curr_after[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, pocst_foll[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, poclt_curr[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, poclt_foll[HEVCFW_MAX_NUM_REF_PICS]);
+	/* derived elements */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			curr_delta_pocmsb_presentflag[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			foll_delta_pocmsb_presentflag[HEVCFW_MAX_NUM_REF_PICS]);
+	/* reference picture sets: indices in DPB */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, ref_picsetlt_curr[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, ref_picsetlt_foll[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			ref_picsetst_curr_before[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			ref_picsetst_curr_after[HEVCFW_MAX_NUM_REF_PICS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, ref_picsetst_foll[HEVCFW_MAX_NUM_REF_PICS]);
+};
+
+/*
+ * This describes the HEVC parser component "Context data", shown in the
+ * Firmware Memory Layout diagram. This data is the state preserved across
+ * pictures. It is loaded and saved by the Firmware, but requires the host to
+ * provide buffer(s) for this.
+ */
+struct hevcfw_ctx_data {
+	struct hevcfw_sequence_ps sps;
+	struct hevcfw_picture_ps pps;
+	/*
+	 * data from last picture with TemporalId = 0 that is not a RASL, RADL
+	 * or sub-layer non-reference picture
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, prev_pic_order_cnt_lsb);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, prev_pic_order_cnt_msb);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, last_irapnorasl_output_flag);
+	/*
+	 * Decoded Pictures Buffer holds information about decoded pictures
+	 * needed for further INTER decoding
+	 */
+	struct hevcfw_decoded_picture_buffer dpb;
+	/* Reference Picture Set is determined on per-picture basis */
+	struct hevcfw_reference_picture_set rps;
+	/*
+	 * Reference Picture List is determined using data from Reference
+	 * Picture Set and from Slice (Segment) Header on per-slice basis
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char,
+			ref_pic_list[HEVCFW_NUM_REF_PIC_LISTS][HEVCFW_MAX_NUM_REF_PICS]);
+	/*
+	 * Reference Picture List used to send reflist to the host, the only
+	 * difference is that missing references are marked
+	 * with HEVCFW_DPB_IDX_INVALID
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char,
+			ref_pic_listhlp[HEVCFW_NUM_REF_PIC_LISTS][HEVCFW_MAX_NUM_REF_PICS]);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, pic_count);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, slice_segment_count);
+	/* There was EOS NAL detected and no new picture yet */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, eos_detected);
+	/* This is first picture after EOS NAL */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, first_after_eos);
+};
+
+#endif /* _HEVCFW_DATA_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/hevc_secure_parser.c b/drivers/media/platform/img/vxe-vxd/decoder/hevc_secure_parser.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/hevc_secure_parser.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/hevc_secure_parser.c	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,2895 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * hevc secure data unit parsing API.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ * Re-written for upstreming
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "bspp_int.h"
+#include "hevc_secure_parser.h"
+#include "hevcfw_data.h"
+#include "pixel_api.h"
+#include "swsr.h"
+#include "vdec_defs.h"
+#include "vdecdd_utils.h"
+
+#if defined(DEBUG_DECODER_DRIVER)
+#define BSPP_HEVC_SYNTAX(fmt, ...)      pr_info("[hevc] " fmt, ## __VA_ARGS__)
+
+#else
+
+#define BSPP_HEVC_SYNTAX(fmt, ...)
+#endif
+
+static void HEVC_SWSR_U1(unsigned char *what, unsigned char *where, void *swsr_ctx)
+{
+	*where = swsr_read_bits(swsr_ctx, 1);
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s, u(1) : %u", what, *where);
+#endif
+}
+
+static void HEVC_SWSR_UN(unsigned char *what, unsigned int *where,
+			 unsigned char numbits, void *swsr_ctx)
+{
+	*where = swsr_read_bits(swsr_ctx, numbits);
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s, u(%u) : %u", what, numbits, *where);
+#endif
+}
+
+static void HEVC_SWSR_UE(unsigned char *what, unsigned int *where, void *swsr_ctx)
+{
+	*where = swsr_read_unsigned_expgoulomb(swsr_ctx);
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s, ue(v) : %u", what, *where);
+#endif
+}
+
+static void HEVC_SWSR_SE(unsigned char *what, int *where, void *swsr_ctx)
+{
+	*where = swsr_read_signed_expgoulomb(swsr_ctx);
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s, se(v) : %u", what, *where);
+#endif
+}
+
+static void HEVC_SWSR_FN(unsigned char *what, unsigned char *where,
+			 unsigned char numbits, unsigned char pattern,
+			 enum bspp_error_type *bspperror, void *swsr_ctx)
+{
+	*where = swsr_read_bits(swsr_ctx, numbits);
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s, f(%u) : %u", what, numbits, *where);
+#endif
+	if (*where != pattern) {
+		*bspperror |= BSPP_ERROR_INVALID_VALUE;
+		pr_warn("Invalid value of %s (f(%u), expected: %u, got: %u)",
+			what, numbits, pattern, *where);
+	}
+}
+
+static void HEVC_UCHECK(unsigned char *what, unsigned int val,
+			unsigned int expected,
+			enum bspp_error_type *bspperror)
+{
+	if (val != expected) {
+		*bspperror |= BSPP_ERROR_INVALID_VALUE;
+		pr_warn("Invalid value of %s (expected: %u, got: %u)",
+			what, expected, val);
+	}
+}
+
+static void HEVC_RANGEUCHECK(unsigned char *what, unsigned int val,
+			     unsigned int min, unsigned int max,
+	enum bspp_error_type *bspperror)
+{
+	if ((min > 0 && val < min) || val > max) {
+		*bspperror |= BSPP_ERROR_INVALID_VALUE;
+		pr_warn("Value of %s out of range (expected: [%u, %u], got: %u)",
+			what, min, max, val);
+	}
+}
+
+static void HEVC_RANGESCHECK(unsigned char *what, int val, int min, int max,
+			     enum bspp_error_type *bspperror)
+{
+	if (val < min || val > max) {
+		*bspperror |= BSPP_ERROR_INVALID_VALUE;
+		pr_warn("Value of %s out of range (expected: [%d, %d], got: %d)",
+			what, min, max, val);
+	}
+}
+
+#define HEVC_STATIC_ASSERT(expr) ((void)sizeof(unsigned char[1 - 2 * !(expr)]))
+
+#define HEVC_MIN(a, b, type) ({ \
+		type __a = a; \
+		type __b = b; \
+		(((__a) <= (__b)) ? (__a) : (__b)); })
+#define HEVC_MAX(a, b, type) ({ \
+		type __a = a; \
+		type __b = b; \
+		(((__a) >= (__b)) ? (__a) : (__b)); })
+#define HEVC_ALIGN(_val, _alignment, type) ({ \
+		type val = _val; \
+		type alignment = _alignment; \
+		(((val) + (alignment) - 1) & ~((alignment) - 1)); })
+
+static const enum pixel_fmt_idc pixelformat_idc[] = {
+	PIXEL_FORMAT_MONO,
+	PIXEL_FORMAT_420,
+	PIXEL_FORMAT_422,
+	PIXEL_FORMAT_444
+};
+
+static enum bspp_error_type bspp_hevc_parse_vps(void *sr_ctx, struct bspp_hevc_vps *vps);
+
+static void bspp_hevc_sublayhrdparams(void *sr_ctx,
+				      struct bspp_hevc_hrd_parameters *hrdparams,
+				      unsigned char sublayer_id);
+
+static void bspp_hevc_parsehrdparams(void *sr_ctx,
+				     struct bspp_hevc_hrd_parameters *hrdparams,
+				     unsigned char common_infpresent,
+				     unsigned char max_numsublayers_minus1);
+
+static enum bspp_error_type bspp_hevc_parsesps(void *sr_ctx,
+					       void *str_res,
+					       struct bspp_hevc_sps *sps);
+
+static enum bspp_error_type bspp_hevc_parsepps(void *sr_ctx, void *str_res,
+					       struct bspp_hevc_pps *pps);
+
+static int bspp_hevc_reset_ppsinfo(void *secure_ppsinfo);
+
+static void bspp_hevc_dotilecalculations(struct bspp_hevc_sps *sps,
+					 struct bspp_hevc_pps *pps);
+
+static enum bspp_error_type bspp_hevc_parse_slicesegmentheader
+		(void *sr_ctx, void *str_res,
+		 struct bspp_hevc_slice_segment_header *ssh,
+		 unsigned char nalunit_type,
+		 struct bspp_vps_info **vpsinfo,
+		 struct bspp_sequence_hdr_info **spsinfo,
+		 struct bspp_pps_info **ppsinfo);
+
+static enum bspp_error_type bspp_hevc_parse_profiletierlevel
+			(void *sr_ctx,
+			 struct bspp_hevc_profile_tierlevel *ptl,
+			 unsigned char vps_maxsublayers_minus1);
+
+static void bspp_hevc_getdefault_scalinglist(unsigned char size_id, unsigned char matrix_id,
+					     const unsigned char **default_scalinglist,
+					     unsigned int *size);
+
+static enum bspp_error_type bspp_hevc_parse_scalinglistdata
+				(void *sr_ctx,
+				 struct bspp_hevc_scalinglist_data *scaling_listdata);
+
+static void bspp_hevc_usedefault_scalinglists(struct bspp_hevc_scalinglist_data *scaling_listdata);
+
+static enum bspp_error_type bspp_hevc_parse_shortterm_refpicset
+		(void *sr_ctx,
+		 struct bspp_hevc_shortterm_refpicset *st_refpicset,
+		 unsigned char st_rps_idx,
+		 unsigned char in_slice_header);
+
+static void bspp_hevc_fillcommonseqhdr(struct bspp_hevc_sps *sps,
+				       struct vdec_comsequ_hdrinfo *common_seq);
+
+static void bspp_hevc_fillpicturehdr(struct vdec_comsequ_hdrinfo *common_seq,
+				     enum hevc_nalunittype nalunit_type,
+				     struct bspp_pict_hdr_info *picture_hdr,
+				     struct bspp_hevc_sps *sps,
+				     struct bspp_hevc_pps *pps,
+				     struct bspp_hevc_vps *vps);
+
+static void bspp_hevc_fill_fwsps(struct bspp_hevc_sps *sps,
+				 struct hevcfw_sequence_ps *fwsps);
+
+static void bspp_hevc_fill_fwst_rps(struct bspp_hevc_shortterm_refpicset *strps,
+				    struct hevcfw_short_term_ref_picset *fwstrps);
+
+static void bspp_hevc_fill_fwpps(struct bspp_hevc_pps *pps,
+				 struct hevcfw_picture_ps *fw_pps);
+
+static void bspp_hevc_fill_fw_scaling_lists(struct bspp_hevc_pps *pps,
+					    struct bspp_hevc_sps *sps,
+					    struct hevcfw_picture_ps *fw_pps);
+
+static unsigned int bspp_ceil_log2(unsigned int linear_val);
+
+static unsigned char bspp_hevc_picture_is_irap(enum hevc_nalunittype nalunit_type);
+
+static unsigned char bspp_hevc_picture_is_cra(enum hevc_nalunittype nalunit_type);
+
+static unsigned char bspp_hevc_picture_is_idr(enum hevc_nalunittype nalunit_type);
+
+static unsigned char bspp_hevc_picture_is_bla(enum hevc_nalunittype nalunit_type);
+
+static unsigned char bspp_hevc_picture_getnorasl_outputflag
+						(enum hevc_nalunittype nalunit_type,
+						 struct bspp_hevc_inter_pict_ctx *inter_pict_ctx);
+
+static unsigned char bspp_hevc_range_extensions_is_enabled
+					(struct bspp_hevc_profile_tierlevel *profile_tierlevel);
+
+static int bspp_hevc_unitparser(void *swsr_ctx, struct bspp_unit_data *unitdata)
+{
+	void *sr_ctx = swsr_ctx;
+	int result = 0;
+	enum bspp_error_type parse_err = BSPP_ERROR_NONE;
+	struct bspp_inter_pict_data *inter_pict_ctx =
+				unitdata->parse_state->inter_pict_ctx;
+	unsigned char forbidden_zero_bit = 0;
+	unsigned char nal_unit_type = 0;
+	unsigned char nuh_layer_id = 0;
+	unsigned char nuh_temporal_id_plus1 = 0;
+
+	HEVC_SWSR_FN("forbidden_zero_bit", &forbidden_zero_bit, 1, 0, &parse_err, sr_ctx);
+	HEVC_SWSR_UN("nal_unit_type", (unsigned int *)&nal_unit_type, 6, sr_ctx);
+	/* for current version of HEVC nuh_layer_id "shall be equal to 0" */
+	HEVC_SWSR_FN("nuh_layer_id", &nuh_layer_id, 6, 0, &parse_err, sr_ctx);
+	HEVC_SWSR_UN("nuh_temporal_id_plus1", (unsigned int *)&nuh_temporal_id_plus1, 3, sr_ctx);
+
+	switch (unitdata->unit_type) {
+	case BSPP_UNIT_VPS:
+	{
+		struct bspp_hevc_vps *vps =
+			(struct bspp_hevc_vps *)unitdata->out.vps_info->secure_vpsinfo;
+
+		unitdata->parse_error |= bspp_hevc_parse_vps(sr_ctx, vps);
+		unitdata->out.vps_info->vps_id =
+			vps->vps_video_parameter_set_id;
+	}
+	break;
+
+	case BSPP_UNIT_SEQUENCE:
+	{
+		struct bspp_ddbuf_array_info *tmp;
+		struct hevcfw_sequence_ps *fwsps;
+		struct vdec_comsequ_hdrinfo *common_seq;
+		struct bspp_hevc_sps *sps =
+			(struct bspp_hevc_sps *)unitdata->out.sequ_hdr_info->secure_sequence_info;
+
+		unitdata->parse_error |= bspp_hevc_parsesps(sr_ctx,
+				unitdata->str_res_handle,
+				sps);
+		unitdata->out.sequ_hdr_info->sequ_hdr_info.sequ_hdr_id =
+			sps->sps_seq_parameter_set_id;
+
+		tmp = &unitdata->out.sequ_hdr_info->fw_sequence;
+		/* handle firmware headers */
+		fwsps =
+		(struct hevcfw_sequence_ps *)((unsigned char *)tmp->ddbuf_info.cpu_virt_addr +
+			tmp->buf_offset);
+
+		bspp_hevc_fill_fwsps(sps, fwsps);
+
+		/* handle common sequence header */
+		common_seq =
+			&unitdata->out.sequ_hdr_info->sequ_hdr_info.com_sequ_hdr_info;
+
+		bspp_hevc_fillcommonseqhdr(sps, common_seq);
+	}
+	break;
+
+	case BSPP_UNIT_PPS:
+	{
+		struct bspp_ddbuf_array_info *tmp;
+		struct hevcfw_picture_ps *fw_pps;
+		struct bspp_hevc_pps *pps =
+			(struct bspp_hevc_pps *)unitdata->out.pps_info->secure_pps_info;
+
+		unitdata->parse_error |= bspp_hevc_parsepps(sr_ctx,
+				unitdata->str_res_handle,
+				pps);
+		unitdata->out.pps_info->pps_id = pps->pps_pic_parameter_set_id;
+
+		tmp = &unitdata->out.pps_info->fw_pps;
+		/* handle firmware headers */
+		fw_pps =
+		(struct hevcfw_picture_ps *)((unsigned char *)tmp->ddbuf_info.cpu_virt_addr +
+			tmp->buf_offset);
+		bspp_hevc_fill_fwpps(pps, fw_pps);
+	}
+	break;
+
+	case BSPP_UNIT_PICTURE:
+	{
+		struct bspp_hevc_slice_segment_header ssh;
+		struct bspp_vps_info *vps_info = NULL;
+		struct bspp_sequence_hdr_info *sequ_hdr_info = NULL;
+		struct bspp_hevc_sps *hevc_sps = NULL;
+		struct bspp_pps_info *ppsinfo = NULL;
+		enum bspp_error_type parse_error;
+		struct bspp_ddbuf_array_info *tmp;
+		struct hevcfw_picture_ps *fw_pps;
+		struct bspp_pict_data *pictdata;
+		struct bspp_hevc_pps *pps;
+
+		/*
+		 * EOS has to be attached to picture data, so it can be used
+		 * for NoRaslOutputFlag calculation in FW
+		 */
+		inter_pict_ctx->hevc_ctx.eos_detected = 0;
+		if (nal_unit_type == HEVC_NALTYPE_EOS) {
+			inter_pict_ctx->hevc_ctx.eos_detected = 1;
+			break;
+		}
+
+		parse_error = bspp_hevc_parse_slicesegmentheader(sr_ctx,
+								 unitdata->str_res_handle,
+								 &ssh,
+								 nal_unit_type,
+								 &vps_info,
+								 &sequ_hdr_info,
+								 &ppsinfo);
+		unitdata->parse_error |= parse_error;
+		unitdata->slice = 1;
+
+		if (parse_error != BSPP_ERROR_NONE &&
+		    parse_error != BSPP_ERROR_CORRECTION_VALIDVALUE) {
+			result = IMG_ERROR_CANCELLED;
+			break;
+		}
+
+		/* if we just started new picture. */
+		if (ssh.first_slice_segment_in_pic_flag) {
+			tmp = &ppsinfo->fw_pps;
+			/* handle firmware headers */
+			fw_pps =
+			(struct hevcfw_picture_ps *)((unsigned char *)tmp->ddbuf_info.cpu_virt_addr
+				+ tmp->buf_offset);
+
+			inter_pict_ctx->hevc_ctx.first_after_eos = 0;
+			if (inter_pict_ctx->hevc_ctx.eos_detected) {
+				inter_pict_ctx->hevc_ctx.first_after_eos = 1;
+				inter_pict_ctx->hevc_ctx.eos_detected = 0;
+			}
+
+			/* fill common picture header */
+			bspp_hevc_fillpicturehdr(&sequ_hdr_info->sequ_hdr_info.com_sequ_hdr_info,
+						 (enum hevc_nalunittype)nal_unit_type,
+						 unitdata->out.pict_hdr_info,
+						 (struct bspp_hevc_sps *)
+						 sequ_hdr_info->secure_sequence_info,
+						 (struct bspp_hevc_pps *)ppsinfo->secure_pps_info,
+						 (struct bspp_hevc_vps *)vps_info->secure_vpsinfo);
+
+			bspp_hevc_fill_fw_scaling_lists(ppsinfo->secure_pps_info,
+							sequ_hdr_info->secure_sequence_info,
+							fw_pps);
+
+			pictdata = &unitdata->out.pict_hdr_info->pict_aux_data;
+			/*
+			 * We have no container for the PPS that passes down
+			 * to the kernel, for this reason the hevc secure parser
+			 * needs to populate that info into the picture
+			 * header PictAuxData.
+			 */
+			pictdata->bufmap_id = ppsinfo->bufmap_id;
+			pictdata->buf_offset = ppsinfo->buf_offset;
+			pictdata->pic_data = fw_pps;
+			pictdata->id = fw_pps->pps_pic_parameter_set_id;
+			pictdata->size = sizeof(*fw_pps);
+
+			ppsinfo->ref_count++;
+
+			/* new Coded Video Sequence indication */
+			if (nal_unit_type == HEVC_NALTYPE_IDR_W_RADL ||
+			    nal_unit_type == HEVC_NALTYPE_IDR_N_LP ||
+			    nal_unit_type == HEVC_NALTYPE_BLA_N_LP ||
+			    nal_unit_type == HEVC_NALTYPE_BLA_W_RADL ||
+			    nal_unit_type == HEVC_NALTYPE_BLA_W_LP ||
+			    nal_unit_type == HEVC_NALTYPE_CRA) {
+				unitdata->new_closed_gop = 1;
+				inter_pict_ctx->hevc_ctx.seq_pic_count = 0;
+			}
+
+			/* Attach SEI data to the picture. */
+	if (!inter_pict_ctx->hevc_ctx.sei_info_attached_to_pic) {
+				/*
+				 *  If there is already a non-empty SEI list
+				 *  available
+				 */
+		if (inter_pict_ctx->hevc_ctx.sei_rawdata_list) {
+			/* attach it to the picture header. */
+			unitdata->out.pict_hdr_info->hevc_pict_hdr_info.raw_sei_datalist_firstfield
+					=
+				(void *)inter_pict_ctx->hevc_ctx.sei_rawdata_list;
+			inter_pict_ctx->hevc_ctx.sei_info_attached_to_pic = 1;
+		} else {
+				/* Otherwise expose a handle a picture header field to
+				 * attach SEI list later.
+				 */
+			inter_pict_ctx->hevc_ctx.hndl_pichdr_sei_rawdata_list =
+		&unitdata->out.pict_hdr_info->hevc_pict_hdr_info.raw_sei_datalist_firstfield;
+			}
+	}
+
+			/* Attach raw VUI data to the picture header. */
+			hevc_sps = (struct bspp_hevc_sps *)sequ_hdr_info->secure_sequence_info;
+			if (hevc_sps->vui_raw_data) {
+				hevc_sps->vui_raw_data->ref_count++;
+				unitdata->out.pict_hdr_info->hevc_pict_hdr_info.raw_vui_data =
+					(void *)hevc_sps->vui_raw_data;
+			}
+
+			inter_pict_ctx->hevc_ctx.seq_pic_count++;
+
+			/* NoOutputOfPriorPicsFlag */
+			inter_pict_ctx->not_dpb_flush = 0;
+			if (unitdata->new_closed_gop &&
+			    bspp_hevc_picture_is_irap((enum hevc_nalunittype)nal_unit_type) &&
+			    bspp_hevc_picture_getnorasl_outputflag((enum hevc_nalunittype)
+								   nal_unit_type,
+								   &inter_pict_ctx->hevc_ctx)) {
+				if (bspp_hevc_picture_is_cra((enum hevc_nalunittype)nal_unit_type))
+					inter_pict_ctx->not_dpb_flush = 1;
+				else
+					inter_pict_ctx->not_dpb_flush =
+						ssh.no_output_of_prior_pics_flag;
+			}
+
+			unitdata->parse_state->next_pic_is_new = 0;
+		}
+
+		pps = (struct bspp_hevc_pps *)ppsinfo->secure_pps_info;
+		unitdata->pict_sequ_hdr_id = pps->pps_seq_parameter_set_id;
+	}
+	break;
+
+	case BSPP_UNIT_UNCLASSIFIED:
+	case BSPP_UNIT_NON_PICTURE:
+	case BSPP_UNIT_UNSUPPORTED:
+		break;
+
+	default:
+		VDEC_ASSERT("Unknown BSPP Unit Type" == NULL);
+		break;
+	}
+
+	return result;
+}
+
+static void bspp_hevc_initialiseparsing(struct bspp_parse_state *parse_state)
+{
+	/* Indicate that SEI info has not yet been attached to this picture. */
+	parse_state->inter_pict_ctx->hevc_ctx.sei_info_attached_to_pic = 0;
+}
+
+static void bspp_hevc_finaliseparsing(void *str_alloc, struct bspp_parse_state *parse_state)
+{
+	/*
+	 * If SEI info has not yet been attached to the picture and
+	 * there is anything to be attached.
+	 */
+	if (!parse_state->inter_pict_ctx->hevc_ctx.sei_info_attached_to_pic &&
+	    parse_state->inter_pict_ctx->hevc_ctx.sei_rawdata_list) {
+		/* attach the SEI list if there is a handle provided for that. */
+		if (parse_state->inter_pict_ctx->hevc_ctx.hndl_pichdr_sei_rawdata_list) {
+			/* Attach the raw SEI list to the picture. */
+			*parse_state->inter_pict_ctx->hevc_ctx.hndl_pichdr_sei_rawdata_list =
+				(void *)parse_state->inter_pict_ctx->hevc_ctx.sei_rawdata_list;
+			/* Reset the inter-picture data. */
+			parse_state->inter_pict_ctx->hevc_ctx.hndl_pichdr_sei_rawdata_list = NULL;
+		} else {
+			/* Nowhere to attach the raw SEI list, so just free it. */
+			bspp_freeraw_sei_datalist
+				(str_alloc, parse_state->inter_pict_ctx->hevc_ctx.sei_rawdata_list);
+		}
+	}
+
+	/* Indicate that SEI info has been attached to the picture. */
+	parse_state->inter_pict_ctx->hevc_ctx.sei_info_attached_to_pic = 1;
+	/* Reset the inter-picture SEI list. */
+	parse_state->inter_pict_ctx->hevc_ctx.sei_rawdata_list = NULL;
+}
+
+static enum bspp_error_type bspp_hevc_parse_vps(void *sr_ctx, struct bspp_hevc_vps *vps)
+{
+	unsigned int parse_err = BSPP_ERROR_NONE;
+	unsigned int i, j;
+
+	VDEC_ASSERT(vps);
+	VDEC_ASSERT(sr_ctx);
+
+	memset(vps, 0, sizeof(struct bspp_hevc_vps));
+
+	HEVC_SWSR_UN("vps_video_parameter_set_id",
+		     (unsigned int *)&vps->vps_video_parameter_set_id, 4, sr_ctx);
+	HEVC_SWSR_UN("vps_reserved_three_2bits",
+		     (unsigned int *)&vps->vps_reserved_three_2bits, 2, sr_ctx);
+	HEVC_SWSR_UN("vps_max_layers_minus1",
+		     (unsigned int *)&vps->vps_max_layers_minus1, 6, sr_ctx);
+	HEVC_SWSR_UN("vps_max_sub_layers_minus1",
+		     (unsigned int *)&vps->vps_max_sub_layers_minus1, 3, sr_ctx);
+	HEVC_RANGEUCHECK("vps_max_sub_layers_minus1", vps->vps_max_sub_layers_minus1, 0,
+			 HEVC_MAX_NUM_SUBLAYERS - 1, &parse_err);
+	HEVC_SWSR_U1("vps_temporal_id_nesting_flag",
+		     &vps->vps_temporal_id_nesting_flag, sr_ctx);
+	HEVC_SWSR_UN("vps_reserved_0xffff_16bits",
+		     (unsigned int *)&vps->vps_reserved_0xffff_16bits, 16, sr_ctx);
+
+	if (vps->vps_max_sub_layers_minus1 == 0)
+		HEVC_UCHECK("vps_temporal_id_nesting_flag",
+			    vps->vps_temporal_id_nesting_flag, 1, &parse_err);
+
+	parse_err |= bspp_hevc_parse_profiletierlevel(sr_ctx, &vps->profiletierlevel,
+						      vps->vps_max_sub_layers_minus1);
+
+	HEVC_SWSR_U1("vps_sub_layer_ordering_info_present_flag",
+		     &vps->vps_sub_layer_ordering_info_present_flag, sr_ctx);
+	for (i = vps->vps_sub_layer_ordering_info_present_flag ?
+		0 : vps->vps_max_sub_layers_minus1;
+		i <= vps->vps_max_sub_layers_minus1; ++i) {
+		HEVC_SWSR_UE("vps_max_dec_pic_buffering_minus1",
+			     (unsigned int *)&vps->vps_max_dec_pic_buffering_minus1[i], sr_ctx);
+		HEVC_SWSR_UE("vps_max_num_reorder_pics",
+			     (unsigned int *)&vps->vps_max_num_reorder_pics[i], sr_ctx);
+		HEVC_SWSR_UE("vps_max_latency_increase_plus1",
+			     (unsigned int *)&vps->vps_max_latency_increase_plus1[i], sr_ctx);
+	}
+
+	HEVC_SWSR_UN("vps_max_layer_id", (unsigned int *)&vps->vps_max_layer_id, 6, sr_ctx);
+	HEVC_SWSR_UE("vps_num_layer_sets_minus1",
+		     (unsigned int *)&vps->vps_num_layer_sets_minus1, sr_ctx);
+
+	for (i = 1; i <= vps->vps_num_layer_sets_minus1; ++i) {
+		for (j = 0; j <= vps->vps_max_layer_id; ++j) {
+			HEVC_SWSR_U1("layer_id_included_flag",
+				     &vps->layer_id_included_flag[i][j], sr_ctx);
+		}
+	}
+
+	HEVC_SWSR_U1("vps_timing_info_present_flag", &vps->vps_timing_info_present_flag, sr_ctx);
+	if (vps->vps_timing_info_present_flag) {
+		HEVC_SWSR_UN("vps_num_units_in_tick",
+			     (unsigned int *)&vps->vps_num_units_in_tick, 32, sr_ctx);
+		HEVC_SWSR_UN("vps_time_scale",
+			     (unsigned int *)&vps->vps_time_scale, 32, sr_ctx);
+		HEVC_SWSR_U1("vps_poc_proportional_to_timing_flag",
+			     &vps->vps_poc_proportional_to_timing_flag, sr_ctx);
+		if (vps->vps_poc_proportional_to_timing_flag)
+			HEVC_SWSR_UE("vps_num_ticks_poc_diff_one_minus1",
+				     (unsigned int *)&vps->vps_num_ticks_poc_diff_one_minus1,
+				     sr_ctx);
+
+		HEVC_SWSR_UE("vps_num_hrd_parameters",
+			     (unsigned int *)&vps->vps_num_hrd_parameters, sr_ctx);
+
+		/* consume hrd_parameters */
+		for (i = 0; i < vps->vps_num_hrd_parameters; i++) {
+			unsigned short hrd_layer_set_idx;
+			unsigned char cprms_present_flag = 1;
+			struct bspp_hevc_hrd_parameters hrdparams;
+
+			HEVC_SWSR_UE("hrd_layer_set_idx",
+				     (unsigned int *)&hrd_layer_set_idx, sr_ctx);
+			if (i > 0)
+				HEVC_SWSR_U1("cprms_present_flag", &cprms_present_flag, sr_ctx);
+
+			bspp_hevc_parsehrdparams(sr_ctx, &hrdparams,
+						 cprms_present_flag,
+						 vps->vps_max_sub_layers_minus1);
+		}
+	}
+	HEVC_SWSR_U1("vps_extension_flag", &vps->vps_extension_flag, sr_ctx);
+
+	return (enum bspp_error_type)parse_err;
+}
+
+static void bspp_hevc_sublayhrdparams(void *sr_ctx,
+				      struct bspp_hevc_hrd_parameters *hrdparams,
+				      unsigned char sublayer_id)
+{
+	unsigned char i;
+	unsigned char cpb_cnt = hrdparams->cpb_cnt_minus1[sublayer_id];
+	struct bspp_hevc_sublayer_hrd_parameters *sublay_hrdparams =
+		&hrdparams->sublayhrdparams[sublayer_id];
+
+	VDEC_ASSERT(sr_ctx);
+	VDEC_ASSERT(hrdparams);
+	VDEC_ASSERT(cpb_cnt < HEVC_MAX_CPB_COUNT);
+	VDEC_ASSERT(sublayer_id < HEVC_MAX_NUM_SUBLAYERS);
+
+	for (i = 0; i <= cpb_cnt; i++) {
+		HEVC_SWSR_UE("bit_rate_value_minus1",
+			     (unsigned int *)&sublay_hrdparams->bit_rate_value_minus1[i], sr_ctx);
+		HEVC_SWSR_UE("cpb_size_value_minus1",
+			     (unsigned int *)&sublay_hrdparams->cpb_size_value_minus1[i], sr_ctx);
+		if (hrdparams->sub_pic_hrd_params_present_flag) {
+			HEVC_SWSR_UE("cpb_size_du_value_minus1",
+				     (unsigned int *)
+				     &sublay_hrdparams->cpb_size_du_value_minus1[i],
+				     sr_ctx);
+			HEVC_SWSR_UE("bit_rate_du_value_minus1",
+				     (unsigned int *)
+				     &sublay_hrdparams->bit_rate_du_value_minus1[i],
+				     sr_ctx);
+		}
+		HEVC_SWSR_U1("cbr_flag", &sublay_hrdparams->cbr_flag[i], sr_ctx);
+	}
+}
+
+static void bspp_hevc_parsehrdparams(void *sr_ctx,
+				     struct bspp_hevc_hrd_parameters *hrdparams,
+				     unsigned char common_infpresent,
+				     unsigned char max_numsublayers_minus1)
+{
+	unsigned char i;
+
+	VDEC_ASSERT(sr_ctx);
+	VDEC_ASSERT(hrdparams);
+	VDEC_ASSERT(max_numsublayers_minus1 < HEVC_MAX_NUM_SUBLAYERS);
+
+	memset(hrdparams, 0, sizeof(struct bspp_hevc_hrd_parameters));
+
+	if (common_infpresent) {
+		HEVC_SWSR_U1("nal_hrd_parameters_present_flag",
+			     &hrdparams->nal_hrd_parameters_present_flag, sr_ctx);
+		HEVC_SWSR_U1("vcl_hrd_parameters_present_flag",
+			     &hrdparams->vcl_hrd_parameters_present_flag, sr_ctx);
+		if (hrdparams->nal_hrd_parameters_present_flag ||
+		    hrdparams->vcl_hrd_parameters_present_flag) {
+			HEVC_SWSR_U1("sub_pic_hrd_params_present_flag",
+				     &hrdparams->sub_pic_hrd_params_present_flag,
+				     sr_ctx);
+			if (hrdparams->sub_pic_hrd_params_present_flag) {
+				HEVC_SWSR_UN("tick_divisor_minus2",
+					     (unsigned int *)&hrdparams->tick_divisor_minus2,
+					     8, sr_ctx);
+				HEVC_SWSR_UN
+				("du_cpb_removal_delay_increment_length_minus1",
+				 (unsigned int *)
+				 &hrdparams->du_cpb_removal_delay_increment_length_minus1,
+				 5, sr_ctx);
+				HEVC_SWSR_U1("sub_pic_cpb_params_in_pic_timing_sei_flag",
+					     &hrdparams->sub_pic_cpb_params_in_pic_timing_sei_flag,
+					     sr_ctx);
+				HEVC_SWSR_UN("dpb_output_delay_du_length_minus1",
+					     (unsigned int *)
+					     &hrdparams->dpb_output_delay_du_length_minus1,
+					     5, sr_ctx);
+			}
+			HEVC_SWSR_UN("bit_rate_scale",
+				     (unsigned int *)&hrdparams->bit_rate_scale, 4, sr_ctx);
+			HEVC_SWSR_UN("cpb_size_scale",
+				     (unsigned int *)&hrdparams->cpb_size_scale, 4, sr_ctx);
+			if (hrdparams->sub_pic_hrd_params_present_flag)
+				HEVC_SWSR_UN("cpb_size_du_scale",
+					     (unsigned int *)&hrdparams->cpb_size_du_scale,
+					     4, sr_ctx);
+
+			HEVC_SWSR_UN("initial_cpb_removal_delay_length_minus1",
+				     (unsigned int *)
+				     &hrdparams->initial_cpb_removal_delay_length_minus1,
+				     5, sr_ctx);
+			HEVC_SWSR_UN("au_cpb_removal_delay_length_minus1",
+				     (unsigned int *)&hrdparams->au_cpb_removal_delay_length_minus1,
+				     5, sr_ctx);
+			HEVC_SWSR_UN("dpb_output_delay_length_minus1",
+				     (unsigned int *)&hrdparams->dpb_output_delay_length_minus1,
+				     5, sr_ctx);
+		}
+	}
+	for (i = 0; i <= max_numsublayers_minus1; i++) {
+		HEVC_SWSR_U1("fixed_pic_rate_general_flag",
+			     &hrdparams->fixed_pic_rate_general_flag[i], sr_ctx);
+		hrdparams->fixed_pic_rate_within_cvs_flag[i] =
+			hrdparams->fixed_pic_rate_general_flag[i];
+		if (!hrdparams->fixed_pic_rate_general_flag[i])
+			HEVC_SWSR_U1("fixed_pic_rate_within_cvs_flag",
+				     &hrdparams->fixed_pic_rate_within_cvs_flag[i],
+				     sr_ctx);
+
+		if (hrdparams->fixed_pic_rate_within_cvs_flag[i])
+			HEVC_SWSR_UE("elemental_duration_in_tc_minus1",
+				     (unsigned int *)&hrdparams->elemental_duration_in_tc_minus1[i],
+				     sr_ctx);
+		else
+			HEVC_SWSR_U1("low_delay_hrd_flag",
+				     &hrdparams->low_delay_hrd_flag[i], sr_ctx);
+
+		if (!hrdparams->low_delay_hrd_flag[i])
+			HEVC_SWSR_UE("cpb_cnt_minus1",
+				     (unsigned int *)&hrdparams->cpb_cnt_minus1[i], sr_ctx);
+
+		if (hrdparams->nal_hrd_parameters_present_flag)
+			bspp_hevc_sublayhrdparams(sr_ctx, hrdparams, i);
+
+		if (hrdparams->vcl_hrd_parameters_present_flag)
+			bspp_hevc_sublayhrdparams(sr_ctx, hrdparams, i);
+	}
+}
+
+static enum bspp_error_type bspp_hevc_parsevui_parameters
+			(void *sr_ctx,
+			 struct bspp_hevc_vui_params *vui_params,
+			 unsigned char sps_max_sub_layers_minus1)
+{
+	enum bspp_error_type parse_err = BSPP_ERROR_NONE;
+
+	VDEC_ASSERT(sr_ctx);
+	VDEC_ASSERT(vui_params);
+
+	memset(vui_params, 0, sizeof(struct bspp_hevc_vui_params));
+
+	HEVC_SWSR_U1("aspect_ratio_info_present_flag",
+		     &vui_params->aspect_ratio_info_present_flag, sr_ctx);
+	if (vui_params->aspect_ratio_info_present_flag) {
+		HEVC_SWSR_UN("aspect_ratio_idc",
+			     (unsigned int *)&vui_params->aspect_ratio_idc, 8, sr_ctx);
+		if (vui_params->aspect_ratio_idc == HEVC_EXTENDED_SAR) {
+			HEVC_SWSR_UN("sar_width",
+				     (unsigned int *)&vui_params->sar_width, 16, sr_ctx);
+			HEVC_SWSR_UN("sar_height",
+				     (unsigned int *)&vui_params->sar_height, 16, sr_ctx);
+		}
+	}
+	HEVC_SWSR_U1("overscan_info_present_flag",
+		     &vui_params->overscan_info_present_flag, sr_ctx);
+
+	if (vui_params->overscan_info_present_flag)
+		HEVC_SWSR_U1("overscan_appropriate_flag",
+			     &vui_params->overscan_appropriate_flag, sr_ctx);
+
+	HEVC_SWSR_U1("video_signal_type_present_flag",
+		     &vui_params->video_signal_type_present_flag, sr_ctx);
+
+	if (vui_params->video_signal_type_present_flag) {
+		HEVC_SWSR_UN("video_format",
+			     (unsigned int *)&vui_params->video_format, 3, sr_ctx);
+		HEVC_SWSR_U1("video_full_range_flag",
+			     &vui_params->video_full_range_flag, sr_ctx);
+		HEVC_SWSR_U1("colour_description_present_flag",
+			     &vui_params->colour_description_present_flag,
+			     sr_ctx);
+		if (vui_params->colour_description_present_flag) {
+			HEVC_SWSR_UN("colour_primaries",
+				     (unsigned int *)&vui_params->colour_primaries, 8, sr_ctx);
+			HEVC_SWSR_UN("transfer_characteristics",
+				     (unsigned int *)&vui_params->transfer_characteristics,
+				     8, sr_ctx);
+			HEVC_SWSR_UN("matrix_coeffs",
+				     (unsigned int *)&vui_params->matrix_coeffs, 8, sr_ctx);
+		}
+	}
+
+	HEVC_SWSR_U1("chroma_loc_info_present_flag",
+		     &vui_params->chroma_loc_info_present_flag, sr_ctx);
+	if (vui_params->chroma_loc_info_present_flag) {
+		HEVC_SWSR_UE("chroma_sample_loc_type_top_field",
+			     (unsigned int *)&vui_params->chroma_sample_loc_type_top_field,
+			     sr_ctx);
+		HEVC_RANGEUCHECK("chroma_sample_loc_type_top_field",
+				 vui_params->chroma_sample_loc_type_top_field,
+				 0, 5, &parse_err);
+		HEVC_SWSR_UE("chroma_sample_loc_type_bottom_field",
+			     (unsigned int *)&vui_params->chroma_sample_loc_type_bottom_field,
+			     sr_ctx);
+		HEVC_RANGEUCHECK("chroma_sample_loc_type_bottom_field",
+				 vui_params->chroma_sample_loc_type_bottom_field,
+				 0, 5, &parse_err);
+	}
+	HEVC_SWSR_U1("neutral_chroma_indication_flag",
+		     &vui_params->neutral_chroma_indication_flag, sr_ctx);
+	HEVC_SWSR_U1("field_seq_flag",
+		     &vui_params->field_seq_flag, sr_ctx);
+	HEVC_SWSR_U1("frame_field_info_present_flag",
+		     &vui_params->frame_field_info_present_flag, sr_ctx);
+	HEVC_SWSR_U1("default_display_window_flag",
+		     &vui_params->default_display_window_flag, sr_ctx);
+	if (vui_params->default_display_window_flag) {
+		HEVC_SWSR_UE("def_disp_win_left_offset",
+			     (unsigned int *)&vui_params->def_disp_win_left_offset, sr_ctx);
+		HEVC_SWSR_UE("def_disp_win_right_offset",
+			     (unsigned int *)&vui_params->def_disp_win_right_offset, sr_ctx);
+		HEVC_SWSR_UE("def_disp_win_top_offset",
+			     (unsigned int *)&vui_params->def_disp_win_top_offset, sr_ctx);
+		HEVC_SWSR_UE("def_disp_win_bottom_offset",
+			     (unsigned int *)&vui_params->def_disp_win_bottom_offset, sr_ctx);
+	}
+	HEVC_SWSR_U1("vui_timing_info_present_flag",
+		     &vui_params->vui_timing_info_present_flag, sr_ctx);
+	if (vui_params->vui_timing_info_present_flag) {
+		HEVC_SWSR_UN("vui_num_units_in_tick",
+			     (unsigned int *)&vui_params->vui_num_units_in_tick, 32, sr_ctx);
+		HEVC_SWSR_UN("vui_time_scale",
+			     (unsigned int *)&vui_params->vui_time_scale, 32, sr_ctx);
+		HEVC_SWSR_U1("vui_poc_proportional_to_timing_flag",
+			     &vui_params->vui_poc_proportional_to_timing_flag,
+			     sr_ctx);
+		if (vui_params->vui_poc_proportional_to_timing_flag)
+			HEVC_SWSR_UE("vui_num_ticks_poc_diff_one_minus1",
+				     (unsigned int *)&vui_params->vui_num_ticks_poc_diff_one_minus1,
+				     sr_ctx);
+
+		HEVC_SWSR_U1("vui_hrd_parameters_present_flag",
+			     &vui_params->vui_hrd_parameters_present_flag,
+			     sr_ctx);
+		if (vui_params->vui_hrd_parameters_present_flag)
+			bspp_hevc_parsehrdparams(sr_ctx, &vui_params->vui_hrd_params,
+						 1, sps_max_sub_layers_minus1);
+	}
+	HEVC_SWSR_U1("bitstream_restriction_flag",
+		     &vui_params->bitstream_restriction_flag, sr_ctx);
+
+	if (vui_params->bitstream_restriction_flag) {
+		HEVC_SWSR_U1("tiles_fixed_structure_flag",
+			     &vui_params->tiles_fixed_structure_flag, sr_ctx);
+		HEVC_SWSR_U1("motion_vectors_over_pic_boundaries_flag",
+			     &vui_params->motion_vectors_over_pic_boundaries_flag,
+			     sr_ctx);
+		HEVC_SWSR_U1("restricted_ref_pic_lists_flag",
+			     &vui_params->restricted_ref_pic_lists_flag, sr_ctx);
+
+		HEVC_SWSR_UE("min_spatial_segmentation_idc",
+			     (unsigned int *)&vui_params->min_spatial_segmentation_idc, sr_ctx);
+		HEVC_RANGEUCHECK("min_spatial_segmentation_idc",
+				 vui_params->min_spatial_segmentation_idc,
+				 0, 4095, &parse_err);
+
+		HEVC_SWSR_UE("max_bytes_per_pic_denom",
+			     (unsigned int *)&vui_params->max_bytes_per_pic_denom, sr_ctx);
+		HEVC_RANGEUCHECK("max_bytes_per_pic_denom", vui_params->max_bytes_per_pic_denom,
+				 0, 16, &parse_err);
+
+		HEVC_SWSR_UE("max_bits_per_min_cu_denom",
+			     (unsigned int *)&vui_params->max_bits_per_min_cu_denom, sr_ctx);
+		HEVC_RANGEUCHECK("max_bits_per_min_cu_denom", vui_params->max_bits_per_min_cu_denom,
+				 0, 16, &parse_err);
+
+		HEVC_SWSR_UE("log2_max_mv_length_horizontal",
+			     (unsigned int *)&vui_params->log2_max_mv_length_horizontal, sr_ctx);
+		HEVC_RANGEUCHECK("log2_max_mv_length_horizontal",
+				 vui_params->log2_max_mv_length_horizontal,
+				 0, 16, &parse_err);
+
+		HEVC_SWSR_UE("log2_max_mv_length_vertical",
+			     (unsigned int *)&vui_params->log2_max_mv_length_vertical, sr_ctx);
+		HEVC_RANGEUCHECK("log2_max_mv_length_vertical",
+				 vui_params->log2_max_mv_length_vertical,
+				 0, 15, &parse_err);
+	}
+
+	return parse_err;
+}
+
+static enum bspp_error_type bspp_hevc_parse_spsrange_extensions
+					(void *sr_ctx,
+					 struct bspp_hevc_sps_range_exts *range_exts)
+{
+	enum bspp_error_type parse_err = BSPP_ERROR_NONE;
+
+	VDEC_ASSERT(sr_ctx);
+	VDEC_ASSERT(range_exts);
+
+	memset(range_exts, 0, sizeof(struct bspp_hevc_sps_range_exts));
+
+	HEVC_SWSR_U1("transform_skip_rotation_enabled_flag",
+		     &range_exts->transform_skip_rotation_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("transform_skip_context_enabled_flag",
+		     &range_exts->transform_skip_context_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("implicit_rdpcm_enabled_flag",
+		     &range_exts->implicit_rdpcm_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("explicit_rdpcm_enabled_flag",
+		     &range_exts->explicit_rdpcm_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("extended_precision_processing_flag",
+		     &range_exts->extended_precision_processing_flag, sr_ctx);
+	HEVC_UCHECK("extended_precision_processing_flag",
+		    range_exts->extended_precision_processing_flag,
+		    0, &parse_err);
+	HEVC_SWSR_U1("intra_smoothing_disabled_flag",
+		     &range_exts->intra_smoothing_disabled_flag, sr_ctx);
+	HEVC_SWSR_U1("high_precision_offsets_enabled_flag",
+		     &range_exts->high_precision_offsets_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("persistent_rice_adaptation_enabled_flag",
+		     &range_exts->persistent_rice_adaptation_enabled_flag,
+		     sr_ctx);
+	HEVC_SWSR_U1("cabac_bypass_alignment_enabled_flag",
+		     &range_exts->cabac_bypass_alignment_enabled_flag, sr_ctx);
+
+	return parse_err;
+}
+
+static unsigned char
+bspp_hevc_checksps_range_extensions(struct bspp_hevc_sps_range_exts *range_exts)
+{
+	VDEC_ASSERT(range_exts);
+
+	if (range_exts->transform_skip_rotation_enabled_flag ||
+	    range_exts->transform_skip_context_enabled_flag ||
+	    range_exts->implicit_rdpcm_enabled_flag ||
+	    range_exts->explicit_rdpcm_enabled_flag ||
+	    range_exts->extended_precision_processing_flag ||
+	    range_exts->intra_smoothing_disabled_flag ||
+	    range_exts->persistent_rice_adaptation_enabled_flag ||
+	    range_exts->cabac_bypass_alignment_enabled_flag)
+		return 1;
+	/*
+	 *  Note: high_precision_offsets_enabled_flag is supported even
+	 * if hw capabilities (bHevcRangeExt is not set)
+	 */
+	return 0;
+}
+
+static enum bspp_error_type bspp_hevc_parsesps(void *sr_ctx,
+					       void *str_res,
+					       struct bspp_hevc_sps *sps)
+{
+	enum bspp_error_type parse_err = BSPP_ERROR_NONE;
+	unsigned char i;
+	unsigned int min_cblog2_size_y;
+
+	if (!sr_ctx || !sps) {
+		VDEC_ASSERT(0);
+		return BSPP_ERROR_INVALID_VALUE;
+	}
+
+	memset(sps, 0, sizeof(struct bspp_hevc_sps));
+
+	HEVC_SWSR_UN("sps_video_parameter_set_id",
+		     (unsigned int *)&sps->sps_video_parameter_set_id, 4, sr_ctx);
+	HEVC_SWSR_UN("sps_max_sub_layers_minus1",
+		     (unsigned int *)&sps->sps_max_sub_layers_minus1, 3, sr_ctx);
+	HEVC_RANGEUCHECK("sps_max_sub_layers_minus1", sps->sps_max_sub_layers_minus1, 0,
+			 HEVC_MAX_NUM_SUBLAYERS - 1, &parse_err);
+	HEVC_SWSR_U1("sps_temporal_id_nesting_flag",
+		     &sps->sps_temporal_id_nesting_flag, sr_ctx);
+
+	if (sps->sps_max_sub_layers_minus1 == 0)
+		HEVC_UCHECK("sps_temporal_id_nesting_flag",
+			    sps->sps_temporal_id_nesting_flag, 1, &parse_err);
+
+	parse_err |= bspp_hevc_parse_profiletierlevel
+				(sr_ctx, &sps->profile_tier_level,
+				 sps->sps_max_sub_layers_minus1);
+
+	HEVC_SWSR_UE("sps_seq_parameter_set_id",
+		     (unsigned int *)&sps->sps_seq_parameter_set_id, sr_ctx);
+	HEVC_RANGEUCHECK("sps_seq_parameter_set_id", sps->sps_seq_parameter_set_id, 0,
+			 HEVC_MAX_SPS_COUNT - 1, &parse_err);
+
+	HEVC_SWSR_UE("chroma_format_idc", (unsigned int *)&sps->chroma_format_idc, sr_ctx);
+	HEVC_RANGEUCHECK("chroma_format_idc", sps->chroma_format_idc, 0, 3, &parse_err);
+
+	if (sps->chroma_format_idc == 3)
+		HEVC_SWSR_U1("separate_colour_plane_flag",
+			     &sps->separate_colour_plane_flag, sr_ctx);
+
+	HEVC_SWSR_UE("pic_width_in_luma_samples",
+		     (unsigned int *)&sps->pic_width_in_luma_samples, sr_ctx);
+	HEVC_SWSR_UE("pic_height_in_luma_samples",
+		     (unsigned int *)&sps->pic_height_in_luma_samples, sr_ctx);
+
+	HEVC_SWSR_U1("conformance_window_flag", &sps->conformance_window_flag, sr_ctx);
+
+	if (sps->pic_width_in_luma_samples == 0 ||
+	    sps->pic_height_in_luma_samples == 0) {
+		pr_warn("Invalid video dimensions (%u, %u)",
+			sps->pic_width_in_luma_samples,
+			sps->pic_height_in_luma_samples);
+		parse_err |= BSPP_ERROR_UNRECOVERABLE;
+	}
+
+	if (sps->conformance_window_flag) {
+		HEVC_SWSR_UE("conf_win_left_offset",
+			     (unsigned int *)&sps->conf_win_left_offset, sr_ctx);
+		HEVC_SWSR_UE("conf_win_right_offset",
+			     (unsigned int *)&sps->conf_win_right_offset, sr_ctx);
+		HEVC_SWSR_UE("conf_win_top_offset",
+			     (unsigned int *)&sps->conf_win_top_offset, sr_ctx);
+		HEVC_SWSR_UE("conf_win_bottom_offset",
+			     (unsigned int *)&sps->conf_win_bottom_offset, sr_ctx);
+	}
+
+	HEVC_SWSR_UE("bit_depth_luma_minus8",
+		     (unsigned int *)&sps->bit_depth_luma_minus8, sr_ctx);
+	HEVC_RANGEUCHECK("bit_depth_luma_minus8",
+			 sps->bit_depth_luma_minus8, 0, 6, &parse_err);
+	HEVC_SWSR_UE("bit_depth_chroma_minus8",
+		     (unsigned int *)&sps->bit_depth_chroma_minus8, sr_ctx);
+	HEVC_RANGEUCHECK("bit_depth_chroma_minus8", sps->bit_depth_chroma_minus8,
+			 0, 6, &parse_err);
+
+	HEVC_SWSR_UE("log2_max_pic_order_cnt_lsb_minus4",
+		     (unsigned int *)&sps->log2_max_pic_order_cnt_lsb_minus4, sr_ctx);
+	HEVC_RANGEUCHECK("log2_max_pic_order_cnt_lsb_minus4",
+			 sps->log2_max_pic_order_cnt_lsb_minus4,
+			 0, 12, &parse_err);
+
+	HEVC_SWSR_U1("sps_sub_layer_ordering_info_present_flag",
+		     &sps->sps_sub_layer_ordering_info_present_flag, sr_ctx);
+	for (i = (sps->sps_sub_layer_ordering_info_present_flag ?
+		0 : sps->sps_max_sub_layers_minus1);
+		i <= sps->sps_max_sub_layers_minus1; ++i) {
+		HEVC_SWSR_UE("sps_max_dec_pic_buffering_minus1",
+			     (unsigned int *)&sps->sps_max_dec_pic_buffering_minus1[i], sr_ctx);
+		HEVC_SWSR_UE("sps_max_num_reorder_pics",
+			     (unsigned int *)&sps->sps_max_num_reorder_pics[i], sr_ctx);
+		HEVC_SWSR_UE("sps_max_latency_increase_plus1",
+			     (unsigned int *)&sps->sps_max_latency_increase_plus1[i], sr_ctx);
+	}
+
+	HEVC_SWSR_UE("log2_min_luma_coding_block_size_minus3",
+		     (unsigned int *)&sps->log2_min_luma_coding_block_size_minus3, sr_ctx);
+	HEVC_SWSR_UE("log2_diff_max_min_luma_coding_block_size",
+		     (unsigned int *)&sps->log2_diff_max_min_luma_coding_block_size, sr_ctx);
+	HEVC_SWSR_UE("log2_min_transform_block_size_minus2",
+		     (unsigned int *)&sps->log2_min_transform_block_size_minus2, sr_ctx);
+	HEVC_SWSR_UE("log2_diff_max_min_transform_block_size",
+		     (unsigned int *)&sps->log2_diff_max_min_transform_block_size, sr_ctx);
+	HEVC_SWSR_UE("max_transform_hierarchy_depth_inter",
+		     (unsigned int *)&sps->max_transform_hierarchy_depth_inter, sr_ctx);
+	HEVC_SWSR_UE("max_transform_hierarchy_depth_intra",
+		     (unsigned int *)&sps->max_transform_hierarchy_depth_intra, sr_ctx);
+
+	HEVC_SWSR_U1("scaling_list_enabled_flag", &sps->scaling_list_enabled_flag, sr_ctx);
+
+	if (sps->scaling_list_enabled_flag) {
+		HEVC_SWSR_U1("sps_scaling_list_data_present_flag",
+			     &sps->sps_scaling_list_data_present_flag, sr_ctx);
+		if (sps->sps_scaling_list_data_present_flag)
+			parse_err |= bspp_hevc_parse_scalinglistdata(sr_ctx,
+								     &sps->scalinglist_data);
+		else
+			bspp_hevc_usedefault_scalinglists(&sps->scalinglist_data);
+	}
+
+	HEVC_SWSR_U1("amp_enabled_flag", &sps->amp_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("sample_adaptive_offset_enabled_flag",
+		     &sps->sample_adaptive_offset_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("pcm_enabled_flag", &sps->pcm_enabled_flag, sr_ctx);
+
+	if (sps->pcm_enabled_flag) {
+		HEVC_SWSR_UN("pcm_sample_bit_depth_luma_minus1",
+			     (unsigned int *)&sps->pcm_sample_bit_depth_luma_minus1,
+			     4, sr_ctx);
+		HEVC_SWSR_UN("pcm_sample_bit_depth_chroma_minus1",
+			     (unsigned int *)&sps->pcm_sample_bit_depth_chroma_minus1,
+			     4, sr_ctx);
+		HEVC_SWSR_UE("log2_min_pcm_luma_coding_block_size_minus3",
+			     (unsigned int *)&sps->log2_min_pcm_luma_coding_block_size_minus3,
+			     sr_ctx);
+		HEVC_SWSR_UE("log2_diff_max_min_pcm_luma_coding_block_size",
+			     (unsigned int *)&sps->log2_diff_max_min_pcm_luma_coding_block_size,
+			     sr_ctx);
+		HEVC_SWSR_U1("pcm_loop_filter_disabled_flag",
+			     &sps->pcm_loop_filter_disabled_flag, sr_ctx);
+	} else {
+		sps->pcm_sample_bit_depth_luma_minus1 = 7;
+		sps->pcm_sample_bit_depth_chroma_minus1 = 7;
+		sps->log2_min_pcm_luma_coding_block_size_minus3 = 0;
+		sps->log2_diff_max_min_pcm_luma_coding_block_size = 2;
+	}
+
+	HEVC_SWSR_UE("num_short_term_ref_pic_sets",
+		     (unsigned int *)&sps->num_short_term_ref_pic_sets, sr_ctx);
+	HEVC_RANGEUCHECK("num_short_term_ref_pic_sets", sps->num_short_term_ref_pic_sets, 0,
+			 HEVC_MAX_NUM_ST_REF_PIC_SETS - 1, &parse_err);
+
+	for (i = 0; i < sps->num_short_term_ref_pic_sets; ++i) {
+		parse_err |= bspp_hevc_parse_shortterm_refpicset(sr_ctx,
+				sps->rps_list,
+				i,
+				0);
+	}
+
+	HEVC_SWSR_U1("long_term_ref_pics_present_flag",
+		     &sps->long_term_ref_pics_present_flag, sr_ctx);
+	if (sps->long_term_ref_pics_present_flag) {
+		HEVC_SWSR_UE("num_long_term_ref_pics_sps",
+			     (unsigned int *)&sps->num_long_term_ref_pics_sps, sr_ctx);
+		HEVC_RANGEUCHECK("num_long_term_ref_pics_sps",
+				 sps->num_long_term_ref_pics_sps, 0,
+				 HEVC_MAX_NUM_LT_REF_PICS, &parse_err);
+		for (i = 0; i < sps->num_long_term_ref_pics_sps; ++i) {
+			HEVC_SWSR_UN("lt_ref_pic_poc_lsb_sps",
+				     (unsigned int *)&sps->lt_ref_pic_poc_lsb_sps[i],
+				     sps->log2_max_pic_order_cnt_lsb_minus4 + 4,
+				     sr_ctx);
+			HEVC_SWSR_U1("used_by_curr_pic_lt_sps_flag",
+				     &sps->used_by_curr_pic_lt_sps_flag[i],
+				     sr_ctx);
+		}
+	}
+
+	HEVC_SWSR_U1("sps_temporal_mvp_enabled_flag", &sps->sps_temporal_mvp_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("strong_intra_smoothing_enabled_flag",
+		     &sps->strong_intra_smoothing_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("vui_parameters_present_flag", &sps->vui_parameters_present_flag, sr_ctx);
+
+	if (sps->vui_parameters_present_flag)
+		bspp_hevc_parsevui_parameters(sr_ctx, &sps->vui_params,
+					      sps->sps_max_sub_layers_minus1);
+
+	HEVC_SWSR_U1("sps_extension_present_flag", &sps->sps_extension_present_flag, sr_ctx);
+	if (sps->sps_extension_present_flag &&
+	    bspp_hevc_range_extensions_is_enabled(&sps->profile_tier_level)) {
+		HEVC_SWSR_U1("sps_range_extensions_flag", &sps->sps_range_extensions_flag, sr_ctx);
+
+		HEVC_SWSR_UN("sps_extension_7bits", (unsigned int *)&sps->sps_extension_7bits, 7,
+			     sr_ctx);
+		/*
+		 *  ignore extension data. Although we inform
+		 * if some non-zero data was found
+		 */
+		HEVC_UCHECK("sps_extension_7bits", sps->sps_extension_7bits, 0, &parse_err);
+		/*
+		 * TODO ?: the newest HEVC spec (10/2014) splits
+		 * "sps_extension_7bits" to * sps_multilayer_extension_flag (1)
+		 * sps_extension_6bits (6)
+		 */
+		if (sps->sps_range_extensions_flag)
+			parse_err |= bspp_hevc_parse_spsrange_extensions
+						(sr_ctx, &sps->range_exts);
+	}
+	/*
+	 * calculate "derived" variables needed further in the parsing process
+	 * (of other headers) and save them for later use
+	 */
+	sps->sub_width_c = 1;
+	sps->sub_height_c = 1;
+	if (sps->chroma_format_idc == 2) {
+		sps->sub_width_c = 2;
+	} else if (sps->chroma_format_idc == 1) {
+		sps->sub_width_c = 2;
+		sps->sub_height_c = 2;
+	}
+
+	min_cblog2_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3;
+	sps->ctb_log2size_y =
+		min_cblog2_size_y + sps->log2_diff_max_min_luma_coding_block_size;
+	sps->ctb_size_y = 1 << sps->ctb_log2size_y;
+
+	if (sps->ctb_size_y > 0) {
+		/* use integer division with rounding up */
+		sps->pic_width_in_ctbs_y =
+			(sps->pic_width_in_luma_samples + sps->ctb_size_y - 1)
+			/ sps->ctb_size_y;
+		sps->pic_height_in_ctbs_y =
+			(sps->pic_height_in_luma_samples + sps->ctb_size_y - 1)
+			/ sps->ctb_size_y;
+	} else {
+		parse_err |= BSPP_ERROR_INVALID_VALUE;
+	}
+
+	sps->pic_size_in_ctbs_y =
+		sps->pic_width_in_ctbs_y * sps->pic_height_in_ctbs_y;
+
+	sps->max_pic_order_cnt_lsb =
+		1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
+
+	for (i = 0; i <= sps->sps_max_sub_layers_minus1; ++i) {
+		sps->sps_max_latency_pictures[i] =
+			sps->sps_max_num_reorder_pics[i] +
+			sps->sps_max_latency_increase_plus1[i] - 1;
+	}
+
+	BSPP_HEVC_SYNTAX("ctb_size_y: %u", sps->ctb_size_y);
+	BSPP_HEVC_SYNTAX("pic_width_in_ctbs_y: %u", sps->pic_width_in_ctbs_y);
+	BSPP_HEVC_SYNTAX("pic_height_in_ctbs_y: %u", sps->pic_height_in_ctbs_y);
+	BSPP_HEVC_SYNTAX("pic_size_in_ctbs_y: %u", sps->pic_size_in_ctbs_y);
+
+	return parse_err;
+}
+
+static int bspp_hevc_release_sequhdrinfo(void *str_alloc, void *secure_spsinfo)
+{
+	struct bspp_hevc_sps *hevc_sps = (struct bspp_hevc_sps *)secure_spsinfo;
+
+	if (!hevc_sps)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Release the raw VIU data. */
+	bspp_streamrelese_rawbstrdataplain(str_alloc, (void *)hevc_sps->vui_raw_data);
+	return 0;
+}
+
+static int bspp_hevc_releasedata(void *str_alloc, enum bspp_unit_type data_type,
+				 void *data_handle)
+{
+	int result = 0;
+
+	if (!data_handle)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	switch (data_type) {
+	case BSPP_UNIT_SEQUENCE:
+		result = bspp_hevc_release_sequhdrinfo(str_alloc, data_handle);
+		break;
+	default:
+		break;
+	}
+
+	return result;
+}
+
+static int bspp_hevc_reset_ppsinfo(void *secure_ppsinfo)
+{
+	struct bspp_hevc_pps *hevc_pps = NULL;
+
+	if (!secure_ppsinfo)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	hevc_pps = (struct bspp_hevc_pps *)secure_ppsinfo;
+
+	memset(hevc_pps, 0, sizeof(*hevc_pps));
+
+	return 0;
+}
+
+static int bspp_hevc_resetdata(enum bspp_unit_type data_type, void *data_handle)
+{
+	int result = 0;
+
+	switch (data_type) {
+	case BSPP_UNIT_PPS:
+		result = bspp_hevc_reset_ppsinfo(data_handle);
+		break;
+	default:
+		break;
+	}
+	return result;
+}
+
+static enum bspp_error_type bspp_hevc_parsepps_range_extensions
+			(void *sr_ctx,
+			 struct bspp_hevc_pps_range_exts *range_exts,
+			 unsigned char transform_skip_enabled_flag,
+			 unsigned char log2_diff_max_min_luma_coding_block_size)
+{
+	enum bspp_error_type parse_err = BSPP_ERROR_NONE;
+
+	VDEC_ASSERT(sr_ctx);
+	VDEC_ASSERT(range_exts);
+
+	memset(range_exts, 0, sizeof(struct bspp_hevc_pps_range_exts));
+
+	if (transform_skip_enabled_flag)
+		HEVC_SWSR_UE("log2_max_transform_skip_block_size_minus2",
+			     (unsigned int *)&range_exts->log2_max_transform_skip_block_size_minus2,
+			     sr_ctx);
+
+	HEVC_SWSR_U1("cross_component_prediction_enabled_flag",
+		     &range_exts->cross_component_prediction_enabled_flag,
+		     sr_ctx);
+	HEVC_UCHECK("cross_component_prediction_enabled_flag",
+		    range_exts->cross_component_prediction_enabled_flag, 0,
+		    &parse_err);
+
+	HEVC_SWSR_U1("chroma_qp_offset_list_enabled_flag",
+		     &range_exts->chroma_qp_offset_list_enabled_flag, sr_ctx);
+
+	if (range_exts->chroma_qp_offset_list_enabled_flag) {
+		unsigned char i;
+
+		HEVC_SWSR_UE("diff_cu_chroma_qp_offset_depth",
+			     (unsigned int *)&range_exts->diff_cu_chroma_qp_offset_depth,
+			     sr_ctx);
+		HEVC_RANGEUCHECK("diff_cu_chroma_qp_offset_depth",
+				 range_exts->diff_cu_chroma_qp_offset_depth, 0,
+				 log2_diff_max_min_luma_coding_block_size,
+				 &parse_err);
+
+		HEVC_SWSR_UE("chroma_qp_offset_list_len_minus1",
+			     (unsigned int *)&range_exts->chroma_qp_offset_list_len_minus1,
+			     sr_ctx);
+		HEVC_RANGEUCHECK("chroma_qp_offset_list_len_minus1",
+				 range_exts->chroma_qp_offset_list_len_minus1,
+				 0, HEVC_MAX_CHROMA_QP - 1, &parse_err);
+		for (i = 0; i <= range_exts->chroma_qp_offset_list_len_minus1; i++) {
+			HEVC_SWSR_SE("cb_qp_offset_list",
+				     (int *)&range_exts->cb_qp_offset_list[i], sr_ctx);
+			HEVC_RANGESCHECK("cb_qp_offset_list", range_exts->cb_qp_offset_list[i],
+					 -12, 12, &parse_err);
+			HEVC_SWSR_SE("cr_qp_offset_list",
+				     (int *)&range_exts->cr_qp_offset_list[i], sr_ctx);
+			HEVC_RANGESCHECK("cr_qp_offset_list", range_exts->cr_qp_offset_list[i],
+					 -12, 12, &parse_err);
+		}
+	}
+	HEVC_SWSR_UE("log2_sao_offset_scale_luma",
+		     (unsigned int *)&range_exts->log2_sao_offset_scale_luma, sr_ctx);
+	HEVC_UCHECK("log2_sao_offset_scale_luma",
+		    range_exts->log2_sao_offset_scale_luma, 0, &parse_err);
+	HEVC_SWSR_UE("log2_sao_offset_scale_chroma",
+		     (unsigned int *)&range_exts->log2_sao_offset_scale_chroma, sr_ctx);
+	HEVC_UCHECK("log2_sao_offset_scale_chroma",
+		    range_exts->log2_sao_offset_scale_chroma, 0, &parse_err);
+
+	return parse_err;
+}
+
+static unsigned char bspp_hevc_checkppsrangeextensions
+				(struct bspp_hevc_pps_range_exts *range_exts)
+{
+	VDEC_ASSERT(range_exts);
+
+	if (range_exts->log2_max_transform_skip_block_size_minus2 ||
+	    range_exts->cross_component_prediction_enabled_flag)
+		return 1;
+	/*
+	 * Note: chroma_qp_offset_list_enabled_flag is supported even
+	 * if hw capabilities (bHevcRangeExt is not set)
+	 */
+	return 0;
+}
+
+static enum bspp_error_type bspp_hevc_parsepps
+			(void *sr_ctx, void *str_res,
+			 struct bspp_hevc_pps *pps)
+{
+	enum bspp_error_type parse_err = BSPP_ERROR_NONE;
+	struct bspp_sequence_hdr_info *spsinfo = NULL;
+	struct bspp_hevc_sps *sps = NULL;
+
+	VDEC_ASSERT(sr_ctx);
+	VDEC_ASSERT(pps);
+	memset(pps, 0, sizeof(struct bspp_hevc_pps));
+
+	HEVC_SWSR_UE("pps_pic_parameter_set_id",
+		     (unsigned int *)&pps->pps_pic_parameter_set_id, sr_ctx);
+	HEVC_RANGEUCHECK("pps_pic_parameter_set_id", pps->pps_pic_parameter_set_id, 0,
+			 HEVC_MAX_PPS_COUNT - 1, &parse_err);
+	HEVC_SWSR_UE("pps_seq_parameter_set_id",
+		     (unsigned int *)&pps->pps_seq_parameter_set_id, sr_ctx);
+	HEVC_RANGEUCHECK("pps_seq_parameter_set_id", pps->pps_seq_parameter_set_id, 0,
+			 HEVC_MAX_SPS_COUNT - 1, &parse_err);
+
+	spsinfo = bspp_get_sequ_hdr(str_res, pps->pps_seq_parameter_set_id);
+	if (!spsinfo) {
+		parse_err |= BSPP_ERROR_NO_SEQUENCE_HDR;
+	} else {
+		sps = (struct bspp_hevc_sps *)spsinfo->secure_sequence_info;
+		VDEC_ASSERT(sps->sps_seq_parameter_set_id ==
+			pps->pps_seq_parameter_set_id);
+	}
+
+	HEVC_SWSR_U1("dependent_slice_segments_enabled_flag",
+		     &pps->dependent_slice_segments_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("output_flag_present_flag",
+		     &pps->output_flag_present_flag, sr_ctx);
+	HEVC_SWSR_UN("num_extra_slice_header_bits",
+		     (unsigned int *)&pps->num_extra_slice_header_bits, 3, sr_ctx);
+	HEVC_SWSR_U1("sign_data_hiding_enabled_flag", &pps->sign_data_hiding_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("cabac_init_present_flag", &pps->cabac_init_present_flag, sr_ctx);
+	HEVC_SWSR_UE("num_ref_idx_l0_default_active_minus1",
+		     (unsigned int *)&pps->num_ref_idx_l0_default_active_minus1, sr_ctx);
+	HEVC_RANGEUCHECK("num_ref_idx_l0_default_active_minus1",
+			 pps->num_ref_idx_l0_default_active_minus1, 0, 14, &parse_err);
+	HEVC_SWSR_UE("num_ref_idx_l1_default_active_minus1",
+		     (unsigned int *)&pps->num_ref_idx_l1_default_active_minus1, sr_ctx);
+	HEVC_RANGEUCHECK("num_ref_idx_l1_default_active_minus1",
+			 pps->num_ref_idx_l1_default_active_minus1, 0, 14, &parse_err);
+	HEVC_SWSR_SE("init_qp_minus26", (int *)&pps->init_qp_minus26, sr_ctx);
+
+	if (sps)
+		HEVC_RANGESCHECK("init_qp_minus26", pps->init_qp_minus26,
+				 -(26 + (6 * sps->bit_depth_luma_minus8)), 25, &parse_err);
+
+	HEVC_SWSR_U1("constrained_intra_pred_flag", &pps->constrained_intra_pred_flag, sr_ctx);
+	HEVC_SWSR_U1("transform_skip_enabled_flag", &pps->transform_skip_enabled_flag, sr_ctx);
+
+	HEVC_SWSR_U1("cu_qp_delta_enabled_flag", &pps->cu_qp_delta_enabled_flag, sr_ctx);
+
+	if (pps->cu_qp_delta_enabled_flag)
+		HEVC_SWSR_UE("diff_cu_qp_delta_depth",
+			     (unsigned int *)&pps->diff_cu_qp_delta_depth, sr_ctx);
+
+	HEVC_SWSR_SE("pps_cb_qp_offset", (int *)&pps->pps_cb_qp_offset, sr_ctx);
+	HEVC_RANGESCHECK("pps_cb_qp_offset", pps->pps_cb_qp_offset, -12, 12, &parse_err);
+	HEVC_SWSR_SE("pps_cr_qp_offset", (int *)&pps->pps_cr_qp_offset, sr_ctx);
+	HEVC_RANGESCHECK("pps_cr_qp_offset", pps->pps_cr_qp_offset, -12, 12, &parse_err);
+	HEVC_SWSR_U1("pps_slice_chroma_qp_offsets_present_flag",
+		     &pps->pps_slice_chroma_qp_offsets_present_flag, sr_ctx);
+	HEVC_SWSR_U1("weighted_pred_flag", &pps->weighted_pred_flag, sr_ctx);
+	HEVC_SWSR_U1("weighted_bipred_flag", &pps->weighted_bipred_flag, sr_ctx);
+	HEVC_SWSR_U1("transquant_bypass_enabled_flag",
+		     &pps->transquant_bypass_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("tiles_enabled_flag", &pps->tiles_enabled_flag, sr_ctx);
+	HEVC_SWSR_U1("entropy_coding_sync_enabled_flag",
+		     &pps->entropy_coding_sync_enabled_flag, sr_ctx);
+
+	if (pps->tiles_enabled_flag) {
+		HEVC_SWSR_UE("num_tile_columns_minus1",
+			     (unsigned int *)&pps->num_tile_columns_minus1, sr_ctx);
+		HEVC_RANGEUCHECK("num_tile_columns_minus1", pps->num_tile_columns_minus1, 0,
+				 HEVC_MAX_TILE_COLS - 1, &parse_err);
+
+		if (pps->num_tile_columns_minus1 > HEVC_MAX_TILE_COLS)
+			pps->num_tile_columns_minus1 = HEVC_MAX_TILE_COLS;
+
+		HEVC_SWSR_UE("num_tile_rows_minus1", (unsigned int *)&pps->num_tile_rows_minus1,
+			     sr_ctx);
+		HEVC_RANGEUCHECK("num_tile_rows_minus1", pps->num_tile_rows_minus1, 0,
+				 HEVC_MAX_TILE_ROWS - 1, &parse_err);
+
+		if (pps->num_tile_rows_minus1 > HEVC_MAX_TILE_ROWS)
+			pps->num_tile_rows_minus1 = HEVC_MAX_TILE_ROWS;
+
+		HEVC_SWSR_U1("uniform_spacing_flag", &pps->uniform_spacing_flag, sr_ctx);
+
+		if (!pps->uniform_spacing_flag) {
+			unsigned char i = 0;
+
+			for (i = 0; i < pps->num_tile_columns_minus1; ++i)
+				HEVC_SWSR_UE("column_width_minus1",
+					     (unsigned int *)&pps->column_width_minus1[i],
+					     sr_ctx);
+
+			for (i = 0; i < pps->num_tile_rows_minus1; ++i)
+				HEVC_SWSR_UE("row_height_minus1",
+					     (unsigned int *)&pps->row_height_minus1[i],
+					     sr_ctx);
+		}
+		HEVC_SWSR_U1("loop_filter_across_tiles_enabled_flag",
+			     &pps->loop_filter_across_tiles_enabled_flag, sr_ctx);
+	} else {
+		pps->loop_filter_across_tiles_enabled_flag = 1;
+	}
+
+	HEVC_SWSR_U1("pps_loop_filter_across_slices_enabled_flag",
+		     &pps->pps_loop_filter_across_slices_enabled_flag, sr_ctx);
+
+	HEVC_SWSR_U1("deblocking_filter_control_present_flag",
+		     &pps->deblocking_filter_control_present_flag, sr_ctx);
+
+	if (pps->deblocking_filter_control_present_flag) {
+		HEVC_SWSR_U1("deblocking_filter_override_enabled_flag",
+			     &pps->deblocking_filter_override_enabled_flag, sr_ctx);
+		HEVC_SWSR_U1("pps_deblocking_filter_disabled_flag",
+			     &pps->pps_deblocking_filter_disabled_flag, sr_ctx);
+		if (!pps->pps_deblocking_filter_disabled_flag) {
+			HEVC_SWSR_SE("pps_beta_offset_div2", (int *)&pps->pps_beta_offset_div2,
+				     sr_ctx);
+			HEVC_RANGESCHECK("pps_beta_offset_div2", pps->pps_beta_offset_div2, -6, 6,
+					 &parse_err);
+			HEVC_SWSR_SE("pps_tc_offset_div2", (int *)&pps->pps_tc_offset_div2, sr_ctx);
+			HEVC_RANGESCHECK("pps_tc_offset_div2", pps->pps_tc_offset_div2, -6, 6,
+					 &parse_err);
+		}
+	}
+
+	HEVC_SWSR_U1("pps_scaling_list_data_present_flag",
+		     &pps->pps_scaling_list_data_present_flag, sr_ctx);
+	if (pps->pps_scaling_list_data_present_flag)
+		parse_err |= bspp_hevc_parse_scalinglistdata(sr_ctx, &pps->scaling_list);
+
+	HEVC_SWSR_U1("lists_modification_present_flag",
+		     &pps->lists_modification_present_flag, sr_ctx);
+	HEVC_SWSR_UE("log2_parallel_merge_level_minus2",
+		     (unsigned int *)&pps->log2_parallel_merge_level_minus2, sr_ctx);
+	HEVC_SWSR_U1("slice_segment_header_extension_present_flag",
+		     &pps->slice_segment_header_extension_present_flag, sr_ctx);
+
+	HEVC_SWSR_U1("pps_extension_present_flag", &pps->pps_extension_present_flag, sr_ctx);
+	if (pps->pps_extension_present_flag &&
+	    bspp_hevc_range_extensions_is_enabled(&sps->profile_tier_level)) {
+		HEVC_SWSR_U1("pps_range_extensions_flag",
+			     &pps->pps_range_extensions_flag, sr_ctx);
+		HEVC_SWSR_UN("pps_extension_7bits",
+			     (unsigned int *)&pps->pps_extension_7bits, 7, sr_ctx);
+		/*
+		 * ignore extension data. Although we inform
+		 * if some non-zero data was found
+		 */
+		HEVC_UCHECK("pps_extension_7bits", pps->pps_extension_7bits, 0, &parse_err);
+
+		/*
+		 * TODO ?: the newest HEVC spec (10/2014) splits "pps_extension_7bits" to
+		 * pps_multilayer_extension_flag (1)
+		 * pps_extension_6bits (6)
+		 */
+		if (pps->pps_range_extensions_flag && sps) {
+			parse_err |= bspp_hevc_parsepps_range_extensions
+					(sr_ctx,
+					 &pps->range_exts,
+					 pps->transform_skip_enabled_flag,
+					 sps->log2_diff_max_min_luma_coding_block_size);
+		}
+	}
+
+	/* calculate derived elements */
+	if (pps->tiles_enabled_flag && sps)
+		bspp_hevc_dotilecalculations(sps, pps);
+
+	return parse_err;
+}
+
+static void bspp_hevc_dotilecalculations(struct bspp_hevc_sps *sps,
+					 struct bspp_hevc_pps *pps)
+{
+	unsigned short colwidth[HEVC_MAX_TILE_COLS];
+	unsigned short rowheight[HEVC_MAX_TILE_ROWS];
+	unsigned char i;
+
+	if (!pps->tiles_enabled_flag) {
+		pps->max_tile_height_in_ctbs_y = sps->pic_height_in_ctbs_y;
+		return;
+	}
+
+	if (pps->uniform_spacing_flag) {
+		for (i = 0; i <= pps->num_tile_columns_minus1; ++i) {
+			colwidth[i] = ((i + 1) * sps->pic_width_in_ctbs_y) /
+				(pps->num_tile_columns_minus1 + 1) -
+				(i * sps->pic_width_in_ctbs_y) /
+				(pps->num_tile_columns_minus1 + 1);
+		}
+
+		for (i = 0; i <= pps->num_tile_rows_minus1; ++i) {
+			rowheight[i] = ((i + 1) * sps->pic_height_in_ctbs_y) /
+				(pps->num_tile_rows_minus1 + 1) -
+				(i * sps->pic_height_in_ctbs_y) /
+				(pps->num_tile_rows_minus1 + 1);
+		}
+
+		pps->max_tile_height_in_ctbs_y = rowheight[0];
+	} else {
+		pps->max_tile_height_in_ctbs_y = 0;
+
+		colwidth[pps->num_tile_columns_minus1] = sps->pic_width_in_ctbs_y;
+		for (i = 0; i <= pps->num_tile_columns_minus1; ++i) {
+			colwidth[i] = pps->column_width_minus1[i] + 1;
+			colwidth[pps->num_tile_columns_minus1] -= colwidth[i];
+		}
+
+		rowheight[pps->num_tile_rows_minus1] = sps->pic_height_in_ctbs_y;
+		for (i = 0; i <= pps->num_tile_rows_minus1; ++i) {
+			rowheight[i] = pps->row_height_minus1[i] + 1;
+			rowheight[pps->num_tile_rows_minus1] -= rowheight[i];
+
+			if (rowheight[i] > pps->max_tile_height_in_ctbs_y)
+				pps->max_tile_height_in_ctbs_y = rowheight[i];
+		}
+
+		if (rowheight[pps->num_tile_rows_minus1] > pps->max_tile_height_in_ctbs_y)
+			pps->max_tile_height_in_ctbs_y =
+					rowheight[pps->num_tile_rows_minus1];
+	}
+
+	for (i = 0; i <= pps->num_tile_columns_minus1; ++i)
+		pps->col_bd[i + 1] = pps->col_bd[i] + colwidth[i];
+
+	for (i = 0; i <= pps->num_tile_rows_minus1; ++i)
+		pps->row_bd[i + 1] = pps->row_bd[i] + rowheight[i];
+}
+
+static enum bspp_error_type bspp_hevc_parse_slicesegmentheader
+		(void *sr_ctx, void *str_res,
+		 struct bspp_hevc_slice_segment_header *ssh,
+		 unsigned char nalunit_type,
+		 struct bspp_vps_info **vpsinfo,
+		 struct bspp_sequence_hdr_info **spsinfo,
+		 struct bspp_pps_info **ppsinfo)
+{
+	enum bspp_error_type parse_err = BSPP_ERROR_NONE;
+	struct bspp_hevc_pps *pps = NULL;
+	struct bspp_hevc_sps *sps = NULL;
+	struct bspp_hevc_vps *vps = NULL;
+
+	VDEC_ASSERT(sr_ctx);
+	VDEC_ASSERT(ssh);
+	VDEC_ASSERT(vpsinfo);
+	VDEC_ASSERT(spsinfo);
+	VDEC_ASSERT(ppsinfo);
+
+	memset(ssh, 0, sizeof(struct bspp_hevc_slice_segment_header));
+
+	HEVC_SWSR_U1("first_slice_segment_in_pic_flag",
+		     &ssh->first_slice_segment_in_pic_flag, sr_ctx);
+
+	if (bspp_hevc_picture_is_irap((enum hevc_nalunittype)nalunit_type))
+		HEVC_SWSR_U1("no_output_of_prior_pics_flag",
+			     &ssh->no_output_of_prior_pics_flag, sr_ctx);
+
+	HEVC_SWSR_UE("slice_pic_parameter_set_id", (unsigned int *)&ssh->slice_pic_parameter_set_id,
+		     sr_ctx);
+	HEVC_RANGEUCHECK("slice_pic_parameter_set_id", ssh->slice_pic_parameter_set_id, 0,
+			 HEVC_MAX_PPS_COUNT - 1, &parse_err);
+
+	if (ssh->slice_pic_parameter_set_id >= HEVC_MAX_PPS_COUNT) {
+		pr_warn("PPS Id invalid (%u), setting to 0",
+			ssh->slice_pic_parameter_set_id);
+		ssh->slice_pic_parameter_set_id = 0;
+		parse_err &= ~BSPP_ERROR_INVALID_VALUE;
+		parse_err |= BSPP_ERROR_CORRECTION_VALIDVALUE;
+	}
+
+	/* set PPS */
+	*ppsinfo = bspp_get_pps_hdr(str_res, ssh->slice_pic_parameter_set_id);
+	if (!(*ppsinfo)) {
+		parse_err |= BSPP_ERROR_NO_PPS;
+		goto error;
+	}
+	pps = (struct bspp_hevc_pps *)(*ppsinfo)->secure_pps_info;
+	if (!pps) {
+		parse_err |= BSPP_ERROR_NO_PPS;
+		goto error;
+	}
+	VDEC_ASSERT(pps->pps_pic_parameter_set_id == ssh->slice_pic_parameter_set_id);
+
+	*spsinfo = bspp_get_sequ_hdr(str_res, pps->pps_seq_parameter_set_id);
+	if (!(*spsinfo)) {
+		parse_err |= BSPP_ERROR_NO_SEQUENCE_HDR;
+		goto error;
+	}
+	sps = (struct bspp_hevc_sps *)(*spsinfo)->secure_sequence_info;
+	VDEC_ASSERT(sps->sps_seq_parameter_set_id == pps->pps_seq_parameter_set_id);
+
+	*vpsinfo = bspp_get_vpshdr(str_res, sps->sps_video_parameter_set_id);
+	if (!(*vpsinfo)) {
+		parse_err |= BSPP_ERROR_NO_VPS;
+		goto error;
+	}
+	vps = (struct bspp_hevc_vps *)(*vpsinfo)->secure_vpsinfo;
+	VDEC_ASSERT(vps->vps_video_parameter_set_id == sps->sps_video_parameter_set_id);
+
+	if (!ssh->first_slice_segment_in_pic_flag) {
+		if (pps->dependent_slice_segments_enabled_flag)
+			HEVC_SWSR_U1("dependent_slice_segment_flag",
+				     &ssh->dependent_slice_segment_flag, sr_ctx);
+
+		HEVC_SWSR_UN("slice_segment_address",
+			     (unsigned int *)&ssh->slice_segment_address,
+			     bspp_ceil_log2(sps->pic_size_in_ctbs_y), sr_ctx);
+	}
+
+error:
+	return parse_err;
+}
+
+static enum bspp_error_type bspp_hevc_parse_profiletierlevel
+		(void *sr_ctx,
+		 struct bspp_hevc_profile_tierlevel *ptl,
+		 unsigned char vps_maxsublayers_minus1)
+{
+	enum bspp_error_type parse_err = BSPP_ERROR_NONE;
+	unsigned char i, j;
+	unsigned int res = 0;
+
+	VDEC_ASSERT(sr_ctx);
+	VDEC_ASSERT(ptl);
+	VDEC_ASSERT(vps_maxsublayers_minus1 < HEVC_MAX_NUM_SUBLAYERS);
+
+	memset(ptl, 0, sizeof(struct bspp_hevc_profile_tierlevel));
+
+	HEVC_SWSR_UN("general_profile_space", (unsigned int *)&ptl->general_profile_space, 2,
+		     sr_ctx);
+	HEVC_SWSR_U1("general_tier_flag", &ptl->general_tier_flag, sr_ctx);
+	HEVC_SWSR_UN("general_profile_idc", (unsigned int *)&ptl->general_profile_idc, 5, sr_ctx);
+
+	for (j = 0; j < HEVC_MAX_NUM_PROFILE_IDC; ++j) {
+		HEVC_SWSR_U1("general_profile_compatibility_flag",
+			     &ptl->general_profile_compatibility_flag[j],
+			     sr_ctx);
+	}
+
+	HEVC_SWSR_U1("general_progressive_source_flag",
+		     &ptl->general_progressive_source_flag, sr_ctx);
+	HEVC_SWSR_U1("general_interlaced_source_flag",
+		     &ptl->general_interlaced_source_flag, sr_ctx);
+	HEVC_SWSR_U1("general_non_packed_constraint_flag",
+		     &ptl->general_non_packed_constraint_flag, sr_ctx);
+	HEVC_SWSR_U1("general_frame_only_constraint_flag",
+		     &ptl->general_frame_only_constraint_flag, sr_ctx);
+
+	if (ptl->general_profile_idc == 4 ||
+	    ptl->general_profile_compatibility_flag[4]) {
+		HEVC_SWSR_U1("general_max_12bit_constraint_flag",
+			     &ptl->general_max_12bit_constraint_flag, sr_ctx);
+		HEVC_SWSR_U1("general_max_10bit_constraint_flag",
+			     &ptl->general_max_10bit_constraint_flag, sr_ctx);
+		HEVC_SWSR_U1("general_max_8bit_constraint_flag",
+			     &ptl->general_max_8bit_constraint_flag, sr_ctx);
+		HEVC_SWSR_U1("general_max_422chroma_constraint_flag",
+			     &ptl->general_max_422chroma_constraint_flag,
+			     sr_ctx);
+		HEVC_SWSR_U1("general_max_420chroma_constraint_flag",
+			     &ptl->general_max_420chroma_constraint_flag,
+			     sr_ctx);
+		HEVC_SWSR_U1("general_max_monochrome_constraint_flag",
+			     &ptl->general_max_monochrome_constraint_flag,
+			     sr_ctx);
+		HEVC_SWSR_U1("general_intra_constraint_flag",
+			     &ptl->general_intra_constraint_flag, sr_ctx);
+		HEVC_SWSR_U1("general_one_picture_only_constraint_flag",
+			     &ptl->general_one_picture_only_constraint_flag,
+			     sr_ctx);
+		HEVC_SWSR_U1("general_lower_bit_rate_constraint_flag",
+			     &ptl->general_lower_bit_rate_constraint_flag,
+			     sr_ctx);
+		HEVC_SWSR_UN("general_reserved_zero_35bits", &res, 32, sr_ctx);
+		HEVC_UCHECK("general_reserved_zero_35bits", res, 0, &parse_err);
+		HEVC_SWSR_UN("general_reserved_zero_35bits", &res, 3, sr_ctx);
+		HEVC_UCHECK("general_reserved_zero_35bits", res, 0, &parse_err);
+	} else {
+		HEVC_SWSR_UN("general_reserved_zero_44bits (1)", &res, 32, sr_ctx);
+		HEVC_UCHECK("general_reserved_zero_44bits (1)", res, 0, &parse_err);
+		HEVC_SWSR_UN("general_reserved_zero_44bits (2)", &res, 12, sr_ctx);
+		HEVC_UCHECK("general_reserved_zero_44bits (2)", res, 0, &parse_err);
+	}
+
+	HEVC_SWSR_UN("general_level_idc", (unsigned int *)&ptl->general_level_idc, 8, sr_ctx);
+	HEVC_RANGEUCHECK("general_level_idc", ptl->general_level_idc,
+			 HEVC_LEVEL_IDC_MIN, HEVC_LEVEL_IDC_MAX, &parse_err);
+
+	for (i = 0; i < vps_maxsublayers_minus1; ++i) {
+		HEVC_SWSR_U1("sub_layer_profile_present_flag",
+			     &ptl->sub_layer_profile_present_flag[i], sr_ctx);
+		HEVC_SWSR_U1("sub_layer_level_present_flag",
+			     &ptl->sub_layer_level_present_flag[i], sr_ctx);
+	}
+
+	if (vps_maxsublayers_minus1 > 0) {
+		for (i = vps_maxsublayers_minus1; i < 8; ++i) {
+			HEVC_SWSR_UN("reserved_zero_2bits", &res, 2, sr_ctx);
+			HEVC_UCHECK("reserved_zero_2bits", res, 0, &parse_err);
+		}
+	}
+
+	for (i = 0; i < vps_maxsublayers_minus1; ++i) {
+		if (ptl->sub_layer_profile_present_flag[i]) {
+			HEVC_SWSR_UN("sub_layer_profile_space",
+				     (unsigned int *)&ptl->sub_layer_profile_space[i], 2, sr_ctx);
+			HEVC_SWSR_U1("sub_layer_tier_flag", &ptl->sub_layer_tier_flag[i], sr_ctx);
+			HEVC_SWSR_UN("sub_layer_profile_idc",
+				     (unsigned int *)&ptl->sub_layer_profile_idc[i], 5, sr_ctx);
+			for (j = 0; j < HEVC_MAX_NUM_PROFILE_IDC; ++j)
+				HEVC_SWSR_U1("sub_layer_profile_compatibility_flag",
+					     &ptl->sub_layer_profile_compatibility_flag[i][j],
+					     sr_ctx);
+
+			HEVC_SWSR_U1("sub_layer_progressive_source_flag",
+				     &ptl->sub_layer_progressive_source_flag[i],
+				     sr_ctx);
+			HEVC_SWSR_U1("sub_layer_interlaced_source_flag",
+				     &ptl->sub_layer_interlaced_source_flag[i],
+				     sr_ctx);
+			HEVC_SWSR_U1("sub_layer_non_packed_constraint_flag",
+				     &ptl->sub_layer_non_packed_constraint_flag[i],
+				     sr_ctx);
+			HEVC_SWSR_U1("sub_layer_frame_only_constraint_flag",
+				     &ptl->sub_layer_frame_only_constraint_flag[i],
+				     sr_ctx);
+
+			if (ptl->sub_layer_profile_idc[i] == 4 ||
+			    ptl->sub_layer_profile_compatibility_flag[i][4]) {
+				HEVC_SWSR_U1("sub_layer_max_12bit_constraint_flag",
+					     &ptl->sub_layer_max_12bit_constraint_flag[i],
+					     sr_ctx);
+				HEVC_SWSR_U1("sub_layer_max_10bit_constraint_flag",
+					     &ptl->sub_layer_max_10bit_constraint_flag[i],
+					     sr_ctx);
+				HEVC_SWSR_U1("sub_layer_max_8bit_constraint_flag",
+					     &ptl->sub_layer_max_8bit_constraint_flag[i],
+					     sr_ctx);
+				HEVC_SWSR_U1("sub_layer_max_422chroma_constraint_flag",
+					     &ptl->sub_layer_max_422chroma_constraint_flag[i],
+					     sr_ctx);
+				HEVC_SWSR_U1("sub_layer_max_420chroma_constraint_flag",
+					     &ptl->sub_layer_max_420chroma_constraint_flag[i],
+					     sr_ctx);
+				HEVC_SWSR_U1("sub_layer_max_monochrome_constraint_flag",
+					     &ptl->sub_layer_max_monochrome_constraint_flag[i],
+					     sr_ctx);
+				HEVC_SWSR_U1("sub_layer_intra_constraint_flag",
+					     &ptl->sub_layer_intra_constraint_flag[i],
+					     sr_ctx);
+				HEVC_SWSR_U1("sub_layer_one_picture_only_constraint_flag",
+					     &ptl->sub_layer_one_picture_only_constraint_flag[i],
+					     sr_ctx);
+				HEVC_SWSR_U1("sub_layer_lower_bit_rate_constraint_flag",
+					     &ptl->sub_layer_lower_bit_rate_constraint_flag[i],
+					     sr_ctx);
+				HEVC_SWSR_UN("sub_layer_reserved_zero_35bits",
+					     &res, 32, sr_ctx);
+				HEVC_UCHECK("sub_layer_reserved_zero_35bits",
+					    res, 0, &parse_err);
+				HEVC_SWSR_UN("sub_layer_reserved_zero_35bits",
+					     &res, 3, sr_ctx);
+				HEVC_UCHECK("sub_layer_reserved_zero_35bits",
+					    res, 0, &parse_err);
+			} else {
+				HEVC_SWSR_UN("sub_layer_reserved_zero_44bits (1)",
+					     &res, 32, sr_ctx);
+				HEVC_UCHECK("sub_layer_reserved_zero_44bits (1)",
+					    res, 0, &parse_err);
+				HEVC_SWSR_UN("sub_layer_reserved_zero_44bits (2)",
+					     &res, 12, sr_ctx);
+				HEVC_UCHECK("sub_layer_reserved_zero_44bits (2)",
+					    res, 0, &parse_err);
+			}
+		}
+		if (ptl->sub_layer_level_present_flag[i])
+			HEVC_SWSR_UN("sub_layer_level_idc",
+				     (unsigned int *)&ptl->sub_layer_level_idc[i], 8, sr_ctx);
+	}
+	return parse_err;
+}
+
+/* Default scaling lists */
+#define HEVC_SCALING_LIST_0_SIZE 16
+#define HEVC_SCALING_LIST_123_SIZE 64
+
+static const unsigned char def_4x4[HEVC_SCALING_LIST_0_SIZE] = {
+	16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16
+};
+
+static const unsigned char def_8x8_intra[HEVC_SCALING_LIST_123_SIZE] = {
+	16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 16, 17, 16, 17, 18,
+	17, 18, 18, 17, 18, 21, 19, 20, 21, 20, 19, 21, 24, 22, 22, 24,
+	24, 22, 22, 24, 25, 25, 27, 30, 27, 25, 25, 29, 31, 35, 35, 31,
+	29, 36, 41, 44, 41, 36, 47, 54, 54, 47, 65, 70, 65, 88, 88, 115
+};
+
+static const unsigned char def_8x8_inter[HEVC_SCALING_LIST_123_SIZE] = {
+	16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18,
+	18, 18, 18, 18, 18, 20, 20, 20, 20, 20, 20, 20, 24, 24, 24, 24,
+	24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 28, 28, 28, 28, 28,
+	28, 33, 33, 33, 33, 33, 41, 41, 41, 41, 54, 54, 54, 71, 71, 91
+};
+
+/*
+ * Scan order mapping when translating scaling lists from bitstream order
+ * to PVDEC order
+ */
+static const unsigned char HEVC_INV_ZZ_SCAN4[HEVC_SCALING_LIST_MATRIX_SIZE / 4]  = {
+	0,  1,  2,  4,  3,  6,  7, 10,  5,  8,  9, 12, 11, 13, 14, 15
+};
+
+static const unsigned char HEVC_INV_ZZ_SCAN8[HEVC_SCALING_LIST_MATRIX_SIZE] = {
+	0,  1,  2,  4,  3,  6,  7, 11,  5,  8,  9, 13, 12, 17, 18, 24,
+	10, 15, 16, 22, 21, 28, 29, 36, 23, 30, 31, 38, 37, 43, 44, 49,
+	14, 19, 20, 26, 25, 32, 33, 40, 27, 34, 35, 42, 41, 47, 48, 53,
+	39, 45, 46, 51, 50, 54, 55, 58, 52, 56, 57, 60, 59, 61, 62, 63
+};
+
+static void bspp_hevc_getdefault_scalinglist
+		(unsigned char size_id, unsigned char matrix_id,
+		 const unsigned char **default_scalinglist,
+		 unsigned int *size)
+{
+	static const unsigned char *defaultlists
+	[HEVC_SCALING_LIST_NUM_SIZES][HEVC_SCALING_LIST_NUM_MATRICES] = {
+		{ def_4x4, def_4x4, def_4x4, def_4x4, def_4x4, def_4x4 },
+		{ def_8x8_intra, def_8x8_intra, def_8x8_intra,
+		  def_8x8_inter, def_8x8_inter, def_8x8_inter },
+		{ def_8x8_intra, def_8x8_intra, def_8x8_intra,
+		  def_8x8_inter, def_8x8_inter, def_8x8_inter },
+		{ def_8x8_intra, def_8x8_inter, NULL, NULL, NULL, NULL }
+	};
+
+	static const unsigned int lists_sizes
+	[HEVC_SCALING_LIST_NUM_SIZES][HEVC_SCALING_LIST_NUM_MATRICES] = {
+		{ sizeof(def_4x4), sizeof(def_4x4), sizeof(def_4x4),
+		  sizeof(def_4x4), sizeof(def_4x4), sizeof(def_4x4) },
+		{ sizeof(def_8x8_intra), sizeof(def_8x8_intra),
+		  sizeof(def_8x8_intra), sizeof(def_8x8_inter),
+		  sizeof(def_8x8_inter), sizeof(def_8x8_inter) },
+		{ sizeof(def_8x8_intra), sizeof(def_8x8_intra),
+		  sizeof(def_8x8_intra), sizeof(def_8x8_inter),
+		  sizeof(def_8x8_inter), sizeof(def_8x8_inter) },
+		{ sizeof(def_8x8_intra), sizeof(def_8x8_inter), 0, 0, 0, 0 }
+	};
+
+	/* to assert that input to this function was correct */
+	VDEC_ASSERT(size_id < 4);
+	VDEC_ASSERT(size_id < 3 ? (matrix_id < 6) : (matrix_id < 2));
+
+	*default_scalinglist = defaultlists[size_id][matrix_id];
+	*size = lists_sizes[size_id][matrix_id];
+}
+
+static enum bspp_error_type bspp_hevc_parse_scalinglistdata
+			(void *sr_ctx,
+			 struct bspp_hevc_scalinglist_data *scaling_listdata)
+{
+	enum bspp_error_type parse_err = BSPP_ERROR_NONE;
+	unsigned char size_id, matrix_id;
+
+	for (size_id = 0; size_id < HEVC_SCALING_LIST_NUM_SIZES; ++size_id) {
+		for (matrix_id = 0; matrix_id < ((size_id == 3) ? 2 : 6);
+			++matrix_id) {
+			/*
+			 * Select scaling list on which we will operate in
+			 * the iteration
+			 */
+			unsigned char *scalinglist = scaling_listdata->lists[size_id][matrix_id];
+
+			unsigned char scaling_list_pred_mode_flag = 0;
+
+			HEVC_SWSR_U1("scaling_list_pred_mode_flag",
+				     &scaling_list_pred_mode_flag, sr_ctx);
+			if (!scaling_list_pred_mode_flag) {
+				unsigned char scaling_list_pred_matrix_id_delta = 0;
+				const unsigned char *defaultlist = NULL;
+				unsigned int listsize = 0;
+
+				HEVC_SWSR_UE("scaling_list_pred_matrixid_delta",
+					     (unsigned int *)&scaling_list_pred_matrix_id_delta,
+					     sr_ctx);
+
+				bspp_hevc_getdefault_scalinglist(size_id,
+								 matrix_id,
+								 &defaultlist,
+								 &listsize);
+
+				if (scaling_list_pred_matrix_id_delta == 0) {
+					/* use default one */
+					memcpy(scalinglist, defaultlist, listsize);
+					if (size_id > 1)
+						scaling_listdata->dccoeffs[size_id -
+						2][matrix_id] = 8 + 8;
+				} else {
+					unsigned char ref_matrix_id =
+						matrix_id - scaling_list_pred_matrix_id_delta;
+					unsigned char *refscalinglist =
+						scaling_listdata->lists[size_id][ref_matrix_id];
+					/*
+					 *  use reference list given by
+					 * scaling_list_pred_matrix_id_delta
+					 */
+					memcpy(scalinglist, refscalinglist, listsize);
+					if (size_id > 1)
+						scaling_listdata->dccoeffs[size_id - 2][matrix_id] =
+							scaling_listdata->dccoeffs[size_id -
+							2][ref_matrix_id];
+				}
+			} else {
+				/*
+				 * scaling list coefficients
+				 * signalled explicitly
+				 */
+				static const short coef_startvalue = 8;
+				static const unsigned char matrix_max_coef_num = 64;
+
+				short next_coef = coef_startvalue;
+				unsigned char coef_num =
+					HEVC_MIN(matrix_max_coef_num,
+						 (1 << (4 + (size_id << 1))), unsigned char);
+
+				unsigned char i;
+
+				if (size_id > 1) {
+					short scaling_list_dc_coef_minus8 = 0;
+
+					HEVC_SWSR_SE("scaling_list_dc_coef_minus8",
+						     (int *)&scaling_list_dc_coef_minus8,
+						     sr_ctx);
+					HEVC_RANGESCHECK("scaling_list_dc_coef_minus8",
+							 scaling_list_dc_coef_minus8,
+							 -7, 247, &parse_err);
+
+					next_coef = scaling_list_dc_coef_minus8 + 8;
+					scaling_listdata->dccoeffs[size_id - 2][matrix_id] =
+						(unsigned char)next_coef;
+				}
+				for (i = 0; i < coef_num; ++i) {
+					short scaling_list_delta_coef = 0;
+
+					HEVC_SWSR_SE("scaling_list_delta_coef",
+						     (int *)&scaling_list_delta_coef, sr_ctx);
+					HEVC_RANGESCHECK("scaling_list_delta_coef",
+							 scaling_list_delta_coef, -128, 127,
+							 &parse_err);
+
+					next_coef = (next_coef + scaling_list_delta_coef + 256) &
+											0xFF;
+					scalinglist[i] = next_coef;
+				}
+			}
+		}
+	}
+
+#ifdef DEBUG_DECODER_DRIVER
+	/* print calculated scaling lists */
+	for (size_id = 0; size_id < HEVC_SCALING_LIST_NUM_SIZES; ++size_id) {
+		for (matrix_id = 0; matrix_id < ((size_id == 3) ? 2 : 6);
+			++matrix_id) {
+			unsigned char i = 0;
+			/*
+			 * Select scaling list on which we will operate
+			 * in the iteration
+			 */
+			unsigned char *scalinglist = scaling_listdata->lists[size_id][matrix_id];
+
+			for (; i < ((size_id == 0) ? 16 : 64); ++i) {
+				BSPP_HEVC_SYNTAX("scalinglist[%u][%u][%u] = %u",
+						 size_id,
+						 matrix_id,
+						 i,
+						 scalinglist[i]);
+			}
+		}
+	}
+#endif
+
+	return parse_err;
+}
+
+static void
+bspp_hevc_usedefault_scalinglists(struct bspp_hevc_scalinglist_data *scaling_listdata)
+{
+	unsigned char size_id, matrix_id;
+
+	for (size_id = 0; size_id < HEVC_SCALING_LIST_NUM_SIZES; ++size_id) {
+		for (matrix_id = 0; matrix_id < ((size_id == 3) ? 2 : 6);
+			++matrix_id) {
+			unsigned char *list = scaling_listdata->lists[size_id][matrix_id];
+			const unsigned char *defaultlist = NULL;
+			unsigned int listsize = 0;
+
+			bspp_hevc_getdefault_scalinglist(size_id, matrix_id, &defaultlist,
+							 &listsize);
+
+			memcpy(list, defaultlist, listsize);
+		}
+	}
+
+	memset(scaling_listdata->dccoeffs, 8 + 8, sizeof(scaling_listdata->dccoeffs));
+}
+
+static enum bspp_error_type bspp_hevc_parse_shortterm_refpicset
+				(void *sr_ctx,
+				 struct bspp_hevc_shortterm_refpicset *st_refpicset,
+				 unsigned char st_rps_idx,
+				 unsigned char in_slice_header)
+{
+	/*
+	 * Note: unfortunately short term ref pic set has to be
+	 * "partially-decoded" and parsed at the same time because derived
+	 * syntax elements are used for prediction of subsequent
+	 * short term ref pic sets.
+	 */
+	enum bspp_error_type parse_err = BSPP_ERROR_NONE;
+
+	struct bspp_hevc_shortterm_refpicset *strps =
+		&st_refpicset[st_rps_idx];
+	unsigned char inter_ref_pic_set_prediction_flag = 0;
+	unsigned int i = 0;
+
+	memset(strps, 0, sizeof(*strps));
+
+	if (st_rps_idx != 0) {
+		HEVC_SWSR_U1("inter_ref_pic_set_prediction_flag",
+			     &inter_ref_pic_set_prediction_flag, sr_ctx);
+	}
+
+	if (inter_ref_pic_set_prediction_flag) {
+		signed char j = 0;
+		unsigned char j_8 = 0;
+		unsigned char ref_rps_idx = 0;
+		int delta_rps = 0;
+		unsigned char i = 0;
+		unsigned char delta_idx_minus1 = 0;
+		unsigned char delta_rps_sign = 0;
+		unsigned short abs_delta_rps_minus1 = 0;
+		unsigned char used_by_curr_pic_flag[HEVC_MAX_NUM_REF_PICS];
+		unsigned char use_delta_flag[HEVC_MAX_NUM_REF_PICS];
+
+		struct bspp_hevc_shortterm_refpicset *ref_strps = NULL;
+
+		if (in_slice_header) {
+			HEVC_SWSR_UE("delta_idx_minus1", (unsigned int *)&delta_idx_minus1, sr_ctx);
+			HEVC_RANGEUCHECK("delta_idx_minus1", delta_idx_minus1, 0, st_rps_idx - 1,
+					 &parse_err);
+		}
+
+		HEVC_SWSR_U1("delta_rps_sign", &delta_rps_sign, sr_ctx);
+		HEVC_SWSR_UE("abs_delta_rps_minus1", (unsigned int *)&abs_delta_rps_minus1, sr_ctx);
+		HEVC_RANGEUCHECK("abs_delta_rps_minus1", abs_delta_rps_minus1, 0, ((1 << 15) - 1),
+				 &parse_err);
+
+		ref_rps_idx = st_rps_idx - (delta_idx_minus1 + 1);
+		ref_strps = &st_refpicset[ref_rps_idx];
+
+		memset(use_delta_flag, 1, sizeof(use_delta_flag));
+
+		for (j_8 = 0; j_8 <= ref_strps->num_delta_pocs; ++j_8) {
+			HEVC_SWSR_U1("used_by_curr_pic_flag", &used_by_curr_pic_flag[j_8], sr_ctx);
+			if (!used_by_curr_pic_flag[j_8])
+				HEVC_SWSR_U1("use_delta_flag", &use_delta_flag[j_8], sr_ctx);
+		}
+
+		delta_rps =
+			(1 - 2 * delta_rps_sign) * (abs_delta_rps_minus1 + 1);
+
+		/*
+		 * predict delta POC values of current strps from
+		 * reference strps
+		 */
+		for (j = ref_strps->num_positive_pics - 1; j >= 0; --j) {
+			int dpoc = ref_strps->delta_poc_s1[j] + delta_rps;
+
+			if (dpoc < 0 && use_delta_flag[ref_strps->num_negative_pics + j]) {
+				strps->delta_poc_s0[i] = dpoc;
+				strps->used_bycurr_pic_s0[i++] =
+					used_by_curr_pic_flag[ref_strps->num_negative_pics + j];
+			}
+		}
+
+		if (delta_rps < 0 && use_delta_flag[ref_strps->num_delta_pocs]) {
+			strps->delta_poc_s0[i] = delta_rps;
+			strps->used_bycurr_pic_s0[i++] =
+				used_by_curr_pic_flag[ref_strps->num_delta_pocs];
+		}
+
+		for (j_8 = 0; j_8 < ref_strps->num_negative_pics; ++j_8) {
+			int dpoc = ref_strps->delta_poc_s0[j_8] + delta_rps;
+
+			if (dpoc < 0 && use_delta_flag[j_8]) {
+				strps->delta_poc_s0[i] = dpoc;
+				strps->used_bycurr_pic_s0[i++] = used_by_curr_pic_flag[j_8];
+			}
+		}
+
+		strps->num_negative_pics = i;
+
+		i = 0;
+		for (j = ref_strps->num_negative_pics - 1; j >= 0; --j) {
+			int dpoc = ref_strps->delta_poc_s0[j] + delta_rps;
+
+			if (dpoc > 0 && use_delta_flag[j]) {
+				strps->delta_poc_s1[i] = dpoc;
+				strps->used_bycurr_pic_s1[i++] =
+					used_by_curr_pic_flag[j];
+			}
+		}
+
+		if (delta_rps > 0 && use_delta_flag[ref_strps->num_delta_pocs]) {
+			strps->delta_poc_s1[i] = delta_rps;
+			strps->used_bycurr_pic_s1[i++] =
+				used_by_curr_pic_flag[ref_strps->num_delta_pocs];
+		}
+
+		for (j_8 = 0; j_8 < ref_strps->num_positive_pics; ++j_8) {
+			int dpoc = ref_strps->delta_poc_s1[j_8] + delta_rps;
+
+			if (dpoc > 0 && use_delta_flag[ref_strps->num_negative_pics + j_8]) {
+				strps->delta_poc_s1[i] = dpoc;
+				strps->used_bycurr_pic_s1[i++] =
+					used_by_curr_pic_flag[ref_strps->num_negative_pics + j_8];
+			}
+		}
+
+		strps->num_positive_pics = i;
+		strps->num_delta_pocs = strps->num_negative_pics + strps->num_positive_pics;
+		if (strps->num_delta_pocs > (HEVC_MAX_NUM_REF_PICS - 1)) {
+			strps->num_delta_pocs = HEVC_MAX_NUM_REF_PICS - 1;
+			parse_err |= BSPP_ERROR_CORRECTION_VALIDVALUE;
+		}
+	} else {
+		unsigned char num_negative_pics = 0;
+		unsigned char num_positive_pics = 0;
+		unsigned short delta_poc_s0_minus1[HEVC_MAX_NUM_REF_PICS];
+		unsigned char used_by_curr_pic_s0_flag[HEVC_MAX_NUM_REF_PICS];
+		unsigned short delta_poc_s1_minus1[HEVC_MAX_NUM_REF_PICS];
+		unsigned char used_by_curr_pic_s1_flag[HEVC_MAX_NUM_REF_PICS];
+		unsigned char j = 0;
+
+		HEVC_SWSR_UE("num_negative_pics", (unsigned int *)&num_negative_pics, sr_ctx);
+		if (num_negative_pics > HEVC_MAX_NUM_REF_PICS) {
+			num_negative_pics = HEVC_MAX_NUM_REF_PICS;
+			parse_err |= BSPP_ERROR_CORRECTION_VALIDVALUE;
+		}
+		HEVC_SWSR_UE("num_positive_pics", (unsigned int *)&num_positive_pics, sr_ctx);
+		if (num_positive_pics > HEVC_MAX_NUM_REF_PICS) {
+			num_positive_pics = HEVC_MAX_NUM_REF_PICS;
+			parse_err |= BSPP_ERROR_CORRECTION_VALIDVALUE;
+		}
+
+		for (j = 0; j < num_negative_pics; ++j) {
+			HEVC_SWSR_UE("delta_poc_s0_minus1",
+				     (unsigned int *)&delta_poc_s0_minus1[j], sr_ctx);
+			HEVC_RANGEUCHECK("delta_poc_s0_minus1", delta_poc_s0_minus1[j], 0,
+					 ((1 << 15) - 1), &parse_err);
+			HEVC_SWSR_U1("used_by_curr_pic_s0_flag",
+				     &used_by_curr_pic_s0_flag[j], sr_ctx);
+
+			if (j == 0)
+				strps->delta_poc_s0[j] =
+					-(delta_poc_s0_minus1[j] + 1);
+			else
+				strps->delta_poc_s0[j] = strps->delta_poc_s0[j - 1] -
+							(delta_poc_s0_minus1[j] + 1);
+
+			strps->used_bycurr_pic_s0[j] = used_by_curr_pic_s0_flag[j];
+		}
+
+		for (j = 0; j < num_positive_pics; j++) {
+			HEVC_SWSR_UE("delta_poc_s1_minus1",
+				     (unsigned int *)&delta_poc_s1_minus1[j], sr_ctx);
+			HEVC_RANGEUCHECK("delta_poc_s1_minus1", delta_poc_s1_minus1[j], 0,
+					 ((1 << 15) - 1), &parse_err);
+			HEVC_SWSR_U1("used_by_curr_pic_s1_flag",
+				     &used_by_curr_pic_s1_flag[j], sr_ctx);
+
+			if (j == 0)
+				strps->delta_poc_s1[j] =
+					(delta_poc_s1_minus1[j] + 1);
+			else
+				strps->delta_poc_s1[j] = strps->delta_poc_s1[j - 1] +
+							(delta_poc_s1_minus1[j] + 1);
+			strps->used_bycurr_pic_s1[j] = used_by_curr_pic_s1_flag[j];
+		}
+
+		strps->num_negative_pics = num_negative_pics;
+		strps->num_positive_pics = num_positive_pics;
+		strps->num_delta_pocs = strps->num_negative_pics + strps->num_positive_pics;
+		if (strps->num_delta_pocs > (HEVC_MAX_NUM_REF_PICS - 1)) {
+			strps->num_delta_pocs = HEVC_MAX_NUM_REF_PICS - 1;
+			parse_err |= BSPP_ERROR_CORRECTION_VALIDVALUE;
+		}
+	}
+
+	BSPP_HEVC_SYNTAX
+		("strps[%u]: num_delta_pocs: %u (%u (num_negative_pics) + %u (num_positive_pics))",
+		 st_rps_idx, strps->num_delta_pocs, strps->num_negative_pics,
+		 strps->num_positive_pics);
+
+	for (i = 0; i < strps->num_negative_pics; ++i) {
+		BSPP_HEVC_SYNTAX("StRps[%u][%u]: delta_poc_s0: %d, used_bycurr_pic_s0: %u",
+				 st_rps_idx, i, strps->delta_poc_s0[i],
+				 strps->used_bycurr_pic_s0[i]);
+	}
+
+	for (i = 0; i < strps->num_positive_pics; ++i) {
+		BSPP_HEVC_SYNTAX("StRps[%u][%u]: delta_poc_s1: %d, used_bycurr_pic_s1: %u",
+				 st_rps_idx, i, strps->delta_poc_s1[i],
+				 strps->used_bycurr_pic_s1[i]);
+	}
+
+	return parse_err;
+}
+
+static void bspp_hevc_fillcommonseqhdr(struct bspp_hevc_sps *sps,
+				       struct vdec_comsequ_hdrinfo *common_seq)
+{
+	struct bspp_hevc_vui_params *vui = &sps->vui_params;
+	unsigned char chroma_idc = sps->chroma_format_idc;
+	struct pixel_pixinfo *pixel_info = &common_seq->pixel_info;
+	unsigned int maxsub_layersmin1;
+	unsigned int maxdpb_size;
+	struct vdec_rect *rawdisp_region;
+
+	common_seq->codec_profile = sps->profile_tier_level.general_profile_idc;
+	common_seq->codec_level   = sps->profile_tier_level.general_level_idc;
+
+	if (sps->vui_parameters_present_flag &&
+	    vui->vui_timing_info_present_flag) {
+		common_seq->frame_rate_num = vui->vui_time_scale;
+		common_seq->frame_rate_den = vui->vui_num_units_in_tick;
+		common_seq->frame_rate =
+			1 * common_seq->frame_rate_num / common_seq->frame_rate_den;
+	}
+
+	if (vui->aspect_ratio_info_present_flag) {
+		common_seq->aspect_ratio_num = vui->sar_width;
+		common_seq->aspect_ratio_den = vui->sar_height;
+	}
+
+	common_seq->interlaced_frames = 0;
+
+	/* handle pixel format definitions */
+	pixel_info->chroma_fmt = chroma_idc == 0 ? 0 : 1;
+	pixel_info->chroma_fmt_idc = pixelformat_idc[chroma_idc];
+	pixel_info->chroma_interleave =
+		chroma_idc == 0 ? PIXEL_INVALID_CI : PIXEL_UV_ORDER;
+	pixel_info->bitdepth_y = sps->bit_depth_luma_minus8 + 8;
+	pixel_info->bitdepth_c = sps->bit_depth_chroma_minus8 + 8;
+
+	pixel_info->mem_pkg = (pixel_info->bitdepth_y > 8 ||
+		(pixel_info->bitdepth_c > 8 && pixel_info->chroma_fmt)) ?
+		PIXEL_BIT10_MSB_MP : PIXEL_BIT8_MP;
+	pixel_info->num_planes =
+		chroma_idc == 0 ? 1 : (sps->separate_colour_plane_flag ? 3 : 2);
+
+	pixel_info->pixfmt = pixel_get_pixfmt(pixel_info->chroma_fmt_idc,
+					      pixel_info->chroma_interleave,
+					      pixel_info->mem_pkg,
+					      pixel_info->bitdepth_y,
+					      pixel_info->chroma_fmt ?
+					      pixel_info->bitdepth_c : PIXEL_INVALID_BDC,
+					      pixel_info->num_planes);
+
+	common_seq->max_frame_size.width = sps->pic_width_in_ctbs_y * sps->ctb_size_y;
+	common_seq->max_frame_size.height = sps->pic_height_in_ctbs_y * sps->ctb_size_y;
+
+	common_seq->frame_size.width = sps->pic_width_in_luma_samples;
+	common_seq->frame_size.height = sps->pic_height_in_luma_samples;
+
+	/* Get HEVC max num ref pictures and pass to bspp info*/
+	vdecddutils_ref_pic_hevc_get_maxnum(common_seq, &common_seq->max_ref_frame_num);
+
+	common_seq->field_codec_mblocks = 0;
+
+	maxsub_layersmin1 = sps->sps_max_sub_layers_minus1;
+	maxdpb_size =
+		HEVC_MAX(sps->sps_max_dec_pic_buffering_minus1[maxsub_layersmin1] + 1,
+			 sps->sps_max_num_reorder_pics[maxsub_layersmin1], unsigned char);
+
+	if (sps->sps_max_latency_increase_plus1[maxsub_layersmin1]) {
+		maxdpb_size =
+			HEVC_MAX(maxdpb_size,
+				 sps->sps_max_latency_pictures[maxsub_layersmin1], unsigned int);
+	}
+
+	maxdpb_size = HEVC_MIN(maxdpb_size,
+			       HEVC_MAX_NUM_REF_IDX_ACTIVE + 1, unsigned int);
+
+	common_seq->min_pict_buf_num = HEVC_MAX(maxdpb_size, 6, unsigned int);
+
+	common_seq->picture_reordering = 1;
+	common_seq->post_processing = 0;
+
+	/* handle display region calculation */
+	rawdisp_region = &common_seq->raw_display_region;
+
+	rawdisp_region->width = sps->pic_width_in_luma_samples;
+	rawdisp_region->height = sps->pic_height_in_luma_samples;
+	rawdisp_region->top_offset = 0;
+	rawdisp_region->left_offset = 0;
+
+	if (sps->conformance_window_flag) {
+		struct vdec_rect *disp_region =
+			&common_seq->orig_display_region;
+
+		disp_region->top_offset =
+			sps->sub_height_c * sps->conf_win_top_offset;
+		disp_region->left_offset =
+			sps->sub_width_c * sps->conf_win_left_offset;
+		disp_region->width =
+			sps->pic_width_in_luma_samples -
+			disp_region->left_offset -
+			sps->sub_width_c * sps->conf_win_right_offset;
+		disp_region->height =
+			sps->pic_height_in_luma_samples -
+			disp_region->top_offset -
+			sps->sub_height_c * sps->conf_win_bottom_offset;
+	} else {
+		common_seq->orig_display_region =
+			common_seq->raw_display_region;
+	}
+}
+
+static void bspp_hevc_fillpicturehdr(struct vdec_comsequ_hdrinfo *common_seq,
+				     enum hevc_nalunittype nalunit_type,
+				     struct bspp_pict_hdr_info *picture_hdr,
+				     struct bspp_hevc_sps *sps,
+				     struct bspp_hevc_pps *pps,
+				     struct bspp_hevc_vps *vps)
+{
+	picture_hdr->intra_coded = (nalunit_type == HEVC_NALTYPE_IDR_W_RADL ||
+		nalunit_type == HEVC_NALTYPE_IDR_N_LP);
+	picture_hdr->field = 0;
+	picture_hdr->post_processing = 0;
+	picture_hdr->discontinuous_mbs = 0;
+	picture_hdr->pict_aux_data.id = BSPP_INVALID;
+	picture_hdr->second_pict_aux_data.id = BSPP_INVALID;
+	picture_hdr->pict_sgm_data.id = BSPP_INVALID;
+	picture_hdr->coded_frame_size.width =
+		HEVC_ALIGN(sps->pic_width_in_luma_samples, HEVC_MIN_CODED_UNIT_SIZE, unsigned int);
+	picture_hdr->coded_frame_size.height =
+		HEVC_ALIGN(sps->pic_height_in_luma_samples, HEVC_MIN_CODED_UNIT_SIZE, unsigned int);
+	picture_hdr->disp_info.enc_disp_region = common_seq->orig_display_region;
+	picture_hdr->disp_info.disp_region = common_seq->orig_display_region;
+	picture_hdr->disp_info.raw_disp_region = common_seq->raw_display_region;
+	picture_hdr->disp_info.num_pan_scan_windows = 0;
+	picture_hdr->hevc_pict_hdr_info.range_ext_present =
+			(sps->profile_tier_level.general_profile_idc == 4) ||
+			sps->profile_tier_level.general_profile_compatibility_flag[4];
+
+	picture_hdr->hevc_pict_hdr_info.is_full_range_ext = 0;
+	if (picture_hdr->hevc_pict_hdr_info.range_ext_present &&
+	    (bspp_hevc_checkppsrangeextensions(&pps->range_exts) ||
+	    bspp_hevc_checksps_range_extensions(&sps->range_exts)))
+		picture_hdr->hevc_pict_hdr_info.is_full_range_ext = 1;
+
+	memset(picture_hdr->disp_info.pan_scan_windows, 0,
+	       sizeof(picture_hdr->disp_info.pan_scan_windows));
+}
+
+static void bspp_hevc_fill_fwsps(struct bspp_hevc_sps *sps, struct hevcfw_sequence_ps *fwsps)
+{
+	unsigned char i;
+
+	fwsps->pic_width_in_luma_samples = sps->pic_width_in_luma_samples;
+	fwsps->pic_height_in_luma_samples = sps->pic_height_in_luma_samples;
+	fwsps->num_short_term_ref_pic_sets = sps->num_short_term_ref_pic_sets;
+	fwsps->num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps;
+	fwsps->sps_max_sub_layers_minus1 = sps->sps_max_sub_layers_minus1;
+	fwsps->max_transform_hierarchy_depth_inter =
+				sps->max_transform_hierarchy_depth_inter;
+	fwsps->max_transform_hierarchy_depth_intra =
+				sps->max_transform_hierarchy_depth_intra;
+	fwsps->log2_diff_max_min_transform_block_size =
+				sps->log2_diff_max_min_transform_block_size;
+	fwsps->log2_min_transform_block_size_minus2 =
+				sps->log2_min_transform_block_size_minus2;
+	fwsps->log2_diff_max_min_luma_coding_block_size =
+				sps->log2_diff_max_min_luma_coding_block_size;
+	fwsps->log2_min_luma_coding_block_size_minus3 =
+				sps->log2_min_luma_coding_block_size_minus3;
+
+	HEVC_STATIC_ASSERT(sizeof(sps->sps_max_dec_pic_buffering_minus1) ==
+			   sizeof(fwsps->sps_max_dec_pic_buffering_minus1));
+	memcpy(fwsps->sps_max_dec_pic_buffering_minus1, sps->sps_max_dec_pic_buffering_minus1,
+	       sizeof(fwsps->sps_max_dec_pic_buffering_minus1[0]) *
+	       (sps->sps_max_sub_layers_minus1 + 1));
+
+	HEVC_STATIC_ASSERT(sizeof(sps->sps_max_num_reorder_pics) ==
+			   sizeof(fwsps->sps_max_num_reorder_pics));
+	memcpy(fwsps->sps_max_num_reorder_pics, sps->sps_max_num_reorder_pics,
+	       sizeof(fwsps->sps_max_num_reorder_pics[0]) *
+	       (sps->sps_max_sub_layers_minus1 + 1));
+
+	HEVC_STATIC_ASSERT(sizeof(sps->sps_max_latency_increase_plus1) ==
+			   sizeof(fwsps->sps_max_latency_increase_plus1));
+	memcpy(fwsps->sps_max_latency_increase_plus1, sps->sps_max_latency_increase_plus1,
+	       sizeof(fwsps->sps_max_latency_increase_plus1[0]) *
+	       (sps->sps_max_sub_layers_minus1 + 1));
+
+	fwsps->chroma_format_idc = sps->chroma_format_idc;
+	fwsps->separate_colour_plane_flag = sps->separate_colour_plane_flag;
+	fwsps->log2_max_pic_order_cnt_lsb_minus4 =
+		sps->log2_max_pic_order_cnt_lsb_minus4;
+	fwsps->long_term_ref_pics_present_flag =
+		sps->long_term_ref_pics_present_flag;
+	fwsps->sample_adaptive_offset_enabled_flag =
+		sps->sample_adaptive_offset_enabled_flag;
+	fwsps->sps_temporal_mvp_enabled_flag =
+		sps->sps_temporal_mvp_enabled_flag;
+	fwsps->bit_depth_luma_minus8 = sps->bit_depth_luma_minus8;
+	fwsps->bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8;
+	fwsps->pcm_sample_bit_depth_luma_minus1 =
+		sps->pcm_sample_bit_depth_luma_minus1;
+	fwsps->pcm_sample_bit_depth_chroma_minus1 =
+		sps->pcm_sample_bit_depth_chroma_minus1;
+	fwsps->log2_min_pcm_luma_coding_block_size_minus3 =
+		sps->log2_min_pcm_luma_coding_block_size_minus3;
+	fwsps->log2_diff_max_min_pcm_luma_coding_block_size =
+		sps->log2_diff_max_min_pcm_luma_coding_block_size;
+	fwsps->pcm_loop_filter_disabled_flag =
+		sps->pcm_loop_filter_disabled_flag;
+	fwsps->amp_enabled_flag = sps->amp_enabled_flag;
+	fwsps->pcm_enabled_flag = sps->pcm_enabled_flag;
+	fwsps->strong_intra_smoothing_enabled_flag =
+		sps->strong_intra_smoothing_enabled_flag;
+	fwsps->scaling_list_enabled_flag = sps->scaling_list_enabled_flag;
+	fwsps->transform_skip_rotation_enabled_flag =
+		sps->range_exts.transform_skip_rotation_enabled_flag;
+	fwsps->transform_skip_context_enabled_flag =
+		sps->range_exts.transform_skip_context_enabled_flag;
+	fwsps->implicit_rdpcm_enabled_flag =
+		sps->range_exts.implicit_rdpcm_enabled_flag;
+	fwsps->explicit_rdpcm_enabled_flag =
+		sps->range_exts.explicit_rdpcm_enabled_flag;
+	fwsps->extended_precision_processing_flag =
+		sps->range_exts.extended_precision_processing_flag;
+	fwsps->intra_smoothing_disabled_flag =
+		sps->range_exts.intra_smoothing_disabled_flag;
+	/* high precision makes no sense for 8 bit luma & chroma,
+	 * so forward this parameter only when bitdepth > 8
+	 */
+	if (sps->bit_depth_luma_minus8 || sps->bit_depth_chroma_minus8)
+		fwsps->high_precision_offsets_enabled_flag =
+			sps->range_exts.high_precision_offsets_enabled_flag;
+
+	fwsps->persistent_rice_adaptation_enabled_flag =
+		sps->range_exts.persistent_rice_adaptation_enabled_flag;
+	fwsps->cabac_bypass_alignment_enabled_flag =
+		sps->range_exts.cabac_bypass_alignment_enabled_flag;
+
+	HEVC_STATIC_ASSERT(sizeof(sps->lt_ref_pic_poc_lsb_sps) ==
+			   sizeof(fwsps->lt_ref_pic_poc_lsb_sps));
+	HEVC_STATIC_ASSERT(sizeof(sps->used_by_curr_pic_lt_sps_flag) ==
+			   sizeof(fwsps->used_by_curr_pic_lt_sps_flag));
+	memcpy(fwsps->lt_ref_pic_poc_lsb_sps, sps->lt_ref_pic_poc_lsb_sps,
+	       sizeof(fwsps->lt_ref_pic_poc_lsb_sps[0]) *
+		sps->num_long_term_ref_pics_sps);
+	memcpy(fwsps->used_by_curr_pic_lt_sps_flag, sps->used_by_curr_pic_lt_sps_flag,
+	       sizeof(fwsps->used_by_curr_pic_lt_sps_flag[0]) * sps->num_long_term_ref_pics_sps);
+
+	for (i = 0; i < sps->num_short_term_ref_pic_sets; ++i)
+		bspp_hevc_fill_fwst_rps(&sps->rps_list[i], &fwsps->st_rps_list[i]);
+
+	/* derived elements */
+	fwsps->pic_size_in_ctbs_y = sps->pic_size_in_ctbs_y;
+	fwsps->pic_height_in_ctbs_y = sps->pic_height_in_ctbs_y;
+	fwsps->pic_width_in_ctbs_y = sps->pic_width_in_ctbs_y;
+	fwsps->ctb_size_y = sps->ctb_size_y;
+	fwsps->ctb_log2size_y = sps->ctb_log2size_y;
+	fwsps->max_pic_order_cnt_lsb = sps->max_pic_order_cnt_lsb;
+
+	HEVC_STATIC_ASSERT(sizeof(sps->sps_max_latency_pictures) ==
+			   sizeof(fwsps->sps_max_latency_pictures));
+	memcpy(fwsps->sps_max_latency_pictures, sps->sps_max_latency_pictures,
+	       sizeof(fwsps->sps_max_latency_pictures[0]) *
+	      (sps->sps_max_sub_layers_minus1 + 1));
+}
+
+static void bspp_hevc_fill_fwst_rps(struct bspp_hevc_shortterm_refpicset *strps,
+				    struct hevcfw_short_term_ref_picset *fwstrps)
+{
+	fwstrps->num_delta_pocs = strps->num_delta_pocs;
+	fwstrps->num_negative_pics = strps->num_negative_pics;
+	fwstrps->num_positive_pics = strps->num_positive_pics;
+
+	HEVC_STATIC_ASSERT(sizeof(strps->delta_poc_s0) ==
+			   sizeof(fwstrps->delta_poc_s0));
+	memcpy(fwstrps->delta_poc_s0, strps->delta_poc_s0,
+	       sizeof(fwstrps->delta_poc_s0[0]) * strps->num_negative_pics);
+
+	HEVC_STATIC_ASSERT(sizeof(strps->delta_poc_s1) ==
+			   sizeof(fwstrps->delta_poc_s1));
+	memcpy(fwstrps->delta_poc_s1, strps->delta_poc_s1,
+	       sizeof(fwstrps->delta_poc_s1[0]) * strps->num_positive_pics);
+
+	HEVC_STATIC_ASSERT(sizeof(strps->used_bycurr_pic_s0) ==
+			   sizeof(fwstrps->used_bycurr_pic_s0));
+	memcpy(fwstrps->used_bycurr_pic_s0, strps->used_bycurr_pic_s0,
+	       sizeof(fwstrps->used_bycurr_pic_s0[0]) * strps->num_negative_pics);
+
+	HEVC_STATIC_ASSERT(sizeof(strps->used_bycurr_pic_s1) ==
+			   sizeof(fwstrps->used_bycurr_pic_s1));
+	memcpy(fwstrps->used_bycurr_pic_s1, strps->used_bycurr_pic_s1,
+	       sizeof(fwstrps->used_bycurr_pic_s1[0]) * strps->num_positive_pics);
+}
+
+static void bspp_hevc_fill_fwpps(struct bspp_hevc_pps *pps, struct hevcfw_picture_ps *fw_pps)
+{
+	fw_pps->pps_pic_parameter_set_id = pps->pps_pic_parameter_set_id;
+	fw_pps->num_tile_columns_minus1 = pps->num_tile_columns_minus1;
+	fw_pps->num_tile_rows_minus1 = pps->num_tile_rows_minus1;
+	fw_pps->diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth;
+	fw_pps->init_qp_minus26 = pps->init_qp_minus26;
+	fw_pps->pps_beta_offset_div2 = pps->pps_beta_offset_div2;
+	fw_pps->pps_tc_offset_div2 = pps->pps_tc_offset_div2;
+	fw_pps->pps_cb_qp_offset = pps->pps_cb_qp_offset;
+	fw_pps->pps_cr_qp_offset = pps->pps_cr_qp_offset;
+	fw_pps->log2_parallel_merge_level_minus2 =
+		pps->log2_parallel_merge_level_minus2;
+
+	fw_pps->dependent_slice_segments_enabled_flag =
+		pps->dependent_slice_segments_enabled_flag;
+	fw_pps->output_flag_present_flag = pps->output_flag_present_flag;
+	fw_pps->num_extra_slice_header_bits = pps->num_extra_slice_header_bits;
+	fw_pps->lists_modification_present_flag =
+		pps->lists_modification_present_flag;
+	fw_pps->cabac_init_present_flag = pps->cabac_init_present_flag;
+	fw_pps->weighted_pred_flag = pps->weighted_pred_flag;
+	fw_pps->weighted_bipred_flag = pps->weighted_bipred_flag;
+	fw_pps->pps_slice_chroma_qp_offsets_present_flag =
+		pps->pps_slice_chroma_qp_offsets_present_flag;
+	fw_pps->deblocking_filter_override_enabled_flag =
+		pps->deblocking_filter_override_enabled_flag;
+	fw_pps->tiles_enabled_flag = pps->tiles_enabled_flag;
+	fw_pps->entropy_coding_sync_enabled_flag =
+		pps->entropy_coding_sync_enabled_flag;
+	fw_pps->slice_segment_header_extension_present_flag =
+		pps->slice_segment_header_extension_present_flag;
+	fw_pps->transquant_bypass_enabled_flag =
+		pps->transquant_bypass_enabled_flag;
+	fw_pps->cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag;
+	fw_pps->transform_skip_enabled_flag = pps->transform_skip_enabled_flag;
+	fw_pps->sign_data_hiding_enabled_flag =
+		pps->sign_data_hiding_enabled_flag;
+	fw_pps->num_ref_idx_l0_default_active_minus1 =
+		pps->num_ref_idx_l0_default_active_minus1;
+	fw_pps->num_ref_idx_l1_default_active_minus1 =
+		pps->num_ref_idx_l1_default_active_minus1;
+	fw_pps->constrained_intra_pred_flag =  pps->constrained_intra_pred_flag;
+	fw_pps->pps_deblocking_filter_disabled_flag =
+		pps->pps_deblocking_filter_disabled_flag;
+	fw_pps->pps_loop_filter_across_slices_enabled_flag =
+		pps->pps_loop_filter_across_slices_enabled_flag;
+	fw_pps->loop_filter_across_tiles_enabled_flag =
+		pps->loop_filter_across_tiles_enabled_flag;
+	fw_pps->log2_max_transform_skip_block_size_minus2 =
+		pps->range_exts.log2_max_transform_skip_block_size_minus2;
+	fw_pps->cross_component_prediction_enabled_flag =
+		pps->range_exts.cross_component_prediction_enabled_flag;
+	fw_pps->chroma_qp_offset_list_enabled_flag =
+		pps->range_exts.chroma_qp_offset_list_enabled_flag;
+	fw_pps->diff_cu_chroma_qp_offset_depth =
+		pps->range_exts.diff_cu_chroma_qp_offset_depth;
+	fw_pps->chroma_qp_offset_list_len_minus1 =
+		pps->range_exts.chroma_qp_offset_list_len_minus1;
+	memcpy(fw_pps->cb_qp_offset_list, pps->range_exts.cb_qp_offset_list,
+	       sizeof(pps->range_exts.cb_qp_offset_list));
+	memcpy(fw_pps->cr_qp_offset_list, pps->range_exts.cr_qp_offset_list,
+	       sizeof(pps->range_exts.cr_qp_offset_list));
+
+	/* derived elements */
+	HEVC_STATIC_ASSERT(sizeof(pps->col_bd) == sizeof(fw_pps->col_bd));
+	HEVC_STATIC_ASSERT(sizeof(pps->row_bd) == sizeof(fw_pps->row_bd));
+	memcpy(fw_pps->col_bd, pps->col_bd, sizeof(fw_pps->col_bd));
+	memcpy(fw_pps->row_bd, pps->row_bd, sizeof(fw_pps->row_bd));
+}
+
+static void bspp_hevc_fill_fw_scaling_lists(struct bspp_hevc_pps *pps,
+					    struct bspp_hevc_sps *sps,
+					    struct hevcfw_picture_ps *fw_pps)
+{
+	signed char size_id, matrix_id;
+	unsigned char *scalinglist;
+	/*
+	 * We are starting at 1 to leave space for addresses,
+	 * filled by lower layer
+	 */
+	unsigned int *scaling_lists = &fw_pps->scaling_lists[1];
+	unsigned char i;
+
+	struct bspp_hevc_scalinglist_data *scaling_listdata =
+		pps->pps_scaling_list_data_present_flag ?
+		&pps->scaling_list :
+		&sps->scalinglist_data;
+
+	if (!sps->scaling_list_enabled_flag)
+		return;
+
+	fw_pps->scaling_list_enabled_flag = sps->scaling_list_enabled_flag;
+
+	for (size_id = HEVC_SCALING_LIST_NUM_SIZES - 1;
+		size_id >= 0; --size_id) {
+		const unsigned char *zz =
+			(size_id == 0 ? HEVC_INV_ZZ_SCAN4 : HEVC_INV_ZZ_SCAN8);
+
+		for (matrix_id = 0; matrix_id < ((size_id == 3) ? 2 : 6);
+			++matrix_id) {
+			/*
+			 * Select scaling list on which we will operate
+			 * in the iteration
+			 */
+			scalinglist =
+				scaling_listdata->lists[size_id][matrix_id];
+
+			for (i = 0; i < ((size_id == 0) ? 16 : 64); i += 4) {
+				*scaling_lists =
+					scalinglist[zz[i + 3]] << 24 |
+					scalinglist[zz[i + 2]] << 16 |
+					scalinglist[zz[i + 1]] << 8 |
+					scalinglist[zz[i]];
+				scaling_lists += 2;
+			}
+		}
+	}
+
+	for (i = 0; i < 2; ++i) {
+		*scaling_lists = scaling_listdata->dccoeffs[1][i];
+		scaling_lists += 2;
+	}
+
+	for (i = 0; i < 6; ++i) {
+		*scaling_lists = scaling_listdata->dccoeffs[0][i];
+		scaling_lists += 2;
+	}
+}
+
+static unsigned int bspp_ceil_log2(unsigned int linear_val)
+{
+	unsigned int log_val = 0;
+
+	if (linear_val > 0)
+		--linear_val;
+
+	while (linear_val > 0) {
+		linear_val >>= 1;
+		++log_val;
+	}
+
+	return log_val;
+}
+
+static unsigned char bspp_hevc_picture_is_irap(enum hevc_nalunittype nalunit_type)
+{
+	return (nalunit_type >= HEVC_NALTYPE_BLA_W_LP) &&
+	       (nalunit_type <= HEVC_NALTYPE_RSV_IRAP_VCL23);
+}
+
+static unsigned char bspp_hevc_picture_is_cra(enum hevc_nalunittype nalunit_type)
+{
+	return (nalunit_type == HEVC_NALTYPE_CRA);
+}
+
+static unsigned char bspp_hevc_picture_is_idr(enum hevc_nalunittype nalunit_type)
+{
+	return (nalunit_type == HEVC_NALTYPE_IDR_N_LP) ||
+	       (nalunit_type == HEVC_NALTYPE_IDR_W_RADL);
+}
+
+static unsigned char bspp_hevc_picture_is_bla(enum hevc_nalunittype nalunit_type)
+{
+	return (nalunit_type >= HEVC_NALTYPE_BLA_W_LP) &&
+	       (nalunit_type <= HEVC_NALTYPE_BLA_N_LP);
+}
+
+static unsigned char bspp_hevc_picture_getnorasl_outputflag
+					(enum hevc_nalunittype nalunit_type,
+					 struct bspp_hevc_inter_pict_ctx *inter_pict_ctx)
+{
+	VDEC_ASSERT(inter_pict_ctx);
+
+	if (bspp_hevc_picture_is_idr(nalunit_type) ||
+	    bspp_hevc_picture_is_bla(nalunit_type) ||
+	    inter_pict_ctx->first_after_eos ||
+	    (bspp_hevc_picture_is_cra(nalunit_type) && inter_pict_ctx->seq_pic_count == 1))
+		return 1;
+
+	return 0;
+}
+
+static unsigned char bspp_hevc_range_extensions_is_enabled
+				(struct bspp_hevc_profile_tierlevel *profile_tierlevel)
+{
+	unsigned char is_enabled;
+
+	is_enabled = profile_tierlevel->general_profile_idc >= 4 ||
+		profile_tierlevel->general_profile_compatibility_flag[4];
+
+	return is_enabled;
+}
+
+static void bspp_hevc_parse_codec_config(void *hndl_swsr_ctx, unsigned int *unit_count,
+					 unsigned int *unit_array_count,
+					 unsigned int *delim_length,
+					 unsigned int *size_delim_length)
+{
+	unsigned long long value = 23;
+
+	/*
+	 * Set the shift-register up to provide next 23 bytes
+	 * without emulation prevention detection.
+	 */
+	swsr_consume_delim(hndl_swsr_ctx, SWSR_EMPREVENT_NONE, 0, &value);
+	/*
+	 * Codec config header must be read for size delimited data (HEVC)
+	 * to get to the start of each unit.
+	 * This parsing follows section 8.3.3.1.2 of ISO/IEC 14496-15:2013.
+	 */
+	swsr_read_bits(hndl_swsr_ctx, 8 * 4);
+	swsr_read_bits(hndl_swsr_ctx, 8 * 4);
+	swsr_read_bits(hndl_swsr_ctx, 8 * 4);
+	swsr_read_bits(hndl_swsr_ctx, 8 * 4);
+	swsr_read_bits(hndl_swsr_ctx, 8 * 4);
+	swsr_read_bits(hndl_swsr_ctx, 8);
+
+	*delim_length = ((swsr_read_bits(hndl_swsr_ctx, 8) & 0x3) + 1) * 8;
+	*unit_array_count = swsr_read_bits(hndl_swsr_ctx, 8);
+
+	/* Size delimiter is only 2 bytes for HEVC codec configuration. */
+	*size_delim_length = 2 * 8;
+}
+
+static void bspp_hevc_update_unitcounts(void *hndl_swsr_ctx, unsigned int *unit_count,
+					unsigned int *unit_array_count)
+{
+	if (*unit_array_count != 0) {
+		unsigned long long value = 3;
+
+		if (*unit_count == 0) {
+			/*
+			 * Set the shift-register up to provide next 3 bytes
+			 * without emulation prevention detection.
+			 */
+			swsr_consume_delim(hndl_swsr_ctx, SWSR_EMPREVENT_NONE, 0, &value);
+
+			swsr_read_bits(hndl_swsr_ctx, 8);
+			*unit_count = swsr_read_bits(hndl_swsr_ctx, 16);
+
+			(*unit_array_count)--;
+			(*unit_count)--;
+		}
+	}
+}
+
+void bspp_hevc_determine_unittype(unsigned char bitstream_unittype,
+				  int disable_mvc,
+				  enum bspp_unit_type *bspp_unittype)
+{
+	/* 6 bits for NAL Unit Type in HEVC */
+	unsigned char type = (bitstream_unittype >> 1) & 0x3f;
+
+	switch (type) {
+	case HEVC_NALTYPE_VPS:
+		*bspp_unittype = BSPP_UNIT_VPS;
+		break;
+
+	case HEVC_NALTYPE_SPS:
+		*bspp_unittype = BSPP_UNIT_SEQUENCE;
+		break;
+
+	case HEVC_NALTYPE_PPS:
+		*bspp_unittype = BSPP_UNIT_PPS;
+		break;
+
+	case HEVC_NALTYPE_TRAIL_N:
+	case HEVC_NALTYPE_TRAIL_R:
+	case HEVC_NALTYPE_TSA_N:
+	case HEVC_NALTYPE_TSA_R:
+	case HEVC_NALTYPE_STSA_N:
+	case HEVC_NALTYPE_STSA_R:
+	case HEVC_NALTYPE_RADL_N:
+	case HEVC_NALTYPE_RADL_R:
+	case HEVC_NALTYPE_RASL_N:
+	case HEVC_NALTYPE_RASL_R:
+	case HEVC_NALTYPE_BLA_W_LP:
+	case HEVC_NALTYPE_BLA_W_RADL:
+	case HEVC_NALTYPE_BLA_N_LP:
+	case HEVC_NALTYPE_IDR_W_RADL:
+	case HEVC_NALTYPE_IDR_N_LP:
+	case HEVC_NALTYPE_CRA:
+	case HEVC_NALTYPE_EOS:
+		/* Attach EOS to picture data, so it can be detected in FW */
+		*bspp_unittype = BSPP_UNIT_PICTURE;
+		break;
+
+	case HEVC_NALTYPE_AUD:
+	case HEVC_NALTYPE_PREFIX_SEI:
+	case HEVC_NALTYPE_SUFFIX_SEI:
+	case HEVC_NALTYPE_EOB:
+	case HEVC_NALTYPE_FD:
+		*bspp_unittype = BSPP_UNIT_NON_PICTURE;
+		break;
+
+	default:
+		*bspp_unittype = BSPP_UNIT_UNSUPPORTED;
+		break;
+	}
+}
+
+int bspp_hevc_set_parser_config(enum vdec_bstr_format bstr_format,
+				struct bspp_vid_std_features *pvidstd_features,
+				struct bspp_swsr_ctx *pswsr_ctx,
+				struct bspp_parser_callbacks *parser_callbacks,
+				struct bspp_inter_pict_data *pinterpict_data)
+{
+	/* set HEVC parser callbacks. */
+	parser_callbacks->parse_unit_cb         = bspp_hevc_unitparser;
+	parser_callbacks->release_data_cb       = bspp_hevc_releasedata;
+	parser_callbacks->reset_data_cb         = bspp_hevc_resetdata;
+	parser_callbacks->parse_codec_config_cb = bspp_hevc_parse_codec_config;
+	parser_callbacks->update_unit_counts_cb = bspp_hevc_update_unitcounts;
+	parser_callbacks->initialise_parsing_cb = bspp_hevc_initialiseparsing;
+	parser_callbacks->finalise_parsing_cb   = bspp_hevc_finaliseparsing;
+
+	/* Set HEVC specific features. */
+	pvidstd_features->seq_size = sizeof(struct bspp_hevc_sequ_hdr_info);
+	pvidstd_features->uses_vps  = 1;
+	pvidstd_features->vps_size = sizeof(struct bspp_hevc_vps);
+	pvidstd_features->uses_pps  = 1;
+	pvidstd_features->pps_size = sizeof(struct bspp_hevc_pps);
+
+	/* Set HEVC specific shift register config. */
+	pswsr_ctx->emulation_prevention = SWSR_EMPREVENT_00000300;
+
+	if (bstr_format == VDEC_BSTRFORMAT_DEMUX_BYTESTREAM ||
+	    bstr_format == VDEC_BSTRFORMAT_ELEMENTARY) {
+		pswsr_ctx->sr_config.delim_type = SWSR_DELIM_SCP;
+		pswsr_ctx->sr_config.delim_length = 3 * 8;
+		pswsr_ctx->sr_config.scp_value = 0x000001;
+	} else if (bstr_format == VDEC_BSTRFORMAT_DEMUX_SIZEDELIMITED) {
+		pswsr_ctx->sr_config.delim_type = SWSR_DELIM_SIZE;
+		pswsr_ctx->sr_config.delim_length = 4 * 8;
+	} else {
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/hevc_secure_parser.h b/drivers/media/platform/img/vxe-vxd/decoder/hevc_secure_parser.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/hevc_secure_parser.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/hevc_secure_parser.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,455 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * h.264 secure data unit parsing API.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef __HEVCSECUREPARSER_H__
+#define __HEVCSECUREPARSER_H__
+
+#include "bspp_int.h"
+
+#define HEVC_MAX_NUM_PROFILE_IDC        (32)
+#define HEVC_MAX_NUM_SUBLAYERS          (7)
+#define HEVC_MAX_VPS_OP_SETS_PLUS1      (1024)
+#define HEVC_MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1   (1)
+#define HEVC_MAX_NUM_REF_PICS           (16)
+#define HEVC_MAX_NUM_ST_REF_PIC_SETS    (65)
+#define HEVC_MAX_NUM_LT_REF_PICS        (32)
+#define HEVC_MAX_NUM_REF_IDX_ACTIVE     (15)
+#define HEVC_LEVEL_IDC_MIN              (30)
+#define HEVC_LEVEL_IDC_MAX              (186)
+#define HEVC_1_0_PROFILE_IDC_MAX        (3)
+#define HEVC_MAX_CPB_COUNT              (32)
+#define HEVC_MIN_CODED_UNIT_SIZE        (8)
+
+/* hevc scaling lists (all values are maximum possible ones) */
+#define HEVC_SCALING_LIST_NUM_SIZES     (4)
+#define HEVC_SCALING_LIST_NUM_MATRICES  (6)
+#define HEVC_SCALING_LIST_MATRIX_SIZE   (64)
+
+#define HEVC_MAX_TILE_COLS              (20)
+#define HEVC_MAX_TILE_ROWS              (22)
+
+#define HEVC_EXTENDED_SAR               (255)
+
+#define HEVC_MAX_CHROMA_QP              (6)
+
+enum hevc_nalunittype {
+	HEVC_NALTYPE_TRAIL_N        = 0,
+	HEVC_NALTYPE_TRAIL_R        = 1,
+	HEVC_NALTYPE_TSA_N          = 2,
+	HEVC_NALTYPE_TSA_R          = 3,
+	HEVC_NALTYPE_STSA_N         = 4,
+	HEVC_NALTYPE_STSA_R         = 5,
+	HEVC_NALTYPE_RADL_N         = 6,
+	HEVC_NALTYPE_RADL_R         = 7,
+	HEVC_NALTYPE_RASL_N         = 8,
+	HEVC_NALTYPE_RASL_R         = 9,
+	HEVC_NALTYPE_RSV_VCL_N10    = 10,
+	HEVC_NALTYPE_RSV_VCL_R11    = 11,
+	HEVC_NALTYPE_RSV_VCL_N12    = 12,
+	HEVC_NALTYPE_RSV_VCL_R13    = 13,
+	HEVC_NALTYPE_RSV_VCL_N14    = 14,
+	HEVC_NALTYPE_RSV_VCL_R15    = 15,
+	HEVC_NALTYPE_BLA_W_LP       = 16,
+	HEVC_NALTYPE_BLA_W_RADL     = 17,
+	HEVC_NALTYPE_BLA_N_LP       = 18,
+	HEVC_NALTYPE_IDR_W_RADL     = 19,
+	HEVC_NALTYPE_IDR_N_LP       = 20,
+	HEVC_NALTYPE_CRA            = 21,
+	HEVC_NALTYPE_RSV_IRAP_VCL22 = 22,
+	HEVC_NALTYPE_RSV_IRAP_VCL23 = 23,
+	HEVC_NALTYPE_VPS            = 32,
+	HEVC_NALTYPE_SPS            = 33,
+	HEVC_NALTYPE_PPS            = 34,
+	HEVC_NALTYPE_AUD            = 35,
+	HEVC_NALTYPE_EOS            = 36,
+	HEVC_NALTYPE_EOB            = 37,
+	HEVC_NALTYPE_FD             = 38,
+	HEVC_NALTYPE_PREFIX_SEI     = 39,
+	HEVC_NALTYPE_SUFFIX_SEI     = 40,
+	HEVC_NALTYPE_FORCE32BITS    = 0x7FFFFFFFU
+};
+
+enum bspp_hevcslicetype {
+	HEVC_SLICE_B           = 0,
+	HEVC_SLICE_P           = 1,
+	HEVC_SLICE_I           = 2,
+	HEVC_SLICE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* HEVC NAL unit header */
+struct bspp_hevcnalheader {
+	unsigned char nal_unit_type;
+	unsigned char nuh_layer_id;
+	unsigned char nuh_temporal_id_plus1;
+};
+
+/* HEVC video profile_tier_level */
+struct bspp_hevc_profile_tierlevel {
+	unsigned char general_profile_space;
+	unsigned char general_tier_flag;
+	unsigned char general_profile_idc;
+	unsigned char general_profile_compatibility_flag[HEVC_MAX_NUM_PROFILE_IDC];
+	unsigned char general_progressive_source_flag;
+	unsigned char general_interlaced_source_flag;
+	unsigned char general_non_packed_constraint_flag;
+	unsigned char general_frame_only_constraint_flag;
+	unsigned char general_max_12bit_constraint_flag;
+	unsigned char general_max_10bit_constraint_flag;
+	unsigned char general_max_8bit_constraint_flag;
+	unsigned char general_max_422chroma_constraint_flag;
+	unsigned char general_max_420chroma_constraint_flag;
+	unsigned char general_max_monochrome_constraint_flag;
+	unsigned char general_intra_constraint_flag;
+	unsigned char general_one_picture_only_constraint_flag;
+	unsigned char general_lower_bit_rate_constraint_flag;
+	unsigned char general_level_idc;
+	unsigned char sub_layer_profile_present_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_level_present_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_profile_space[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_tier_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_profile_idc[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_profile_compatibility_flag[HEVC_MAX_NUM_SUBLAYERS -
+						   1][HEVC_MAX_NUM_PROFILE_IDC];
+	unsigned char sub_layer_progressive_source_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_interlaced_source_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_non_packed_constraint_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_frame_only_constraint_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_max_12bit_constraint_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_max_10bit_constraint_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_max_8bit_constraint_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_max_422chroma_constraint_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_max_420chroma_constraint_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_max_monochrome_constraint_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_intra_constraint_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_one_picture_only_constraint_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_lower_bit_rate_constraint_flag[HEVC_MAX_NUM_SUBLAYERS - 1];
+	unsigned char sub_layer_level_idc[HEVC_MAX_NUM_SUBLAYERS - 1];
+};
+
+/* HEVC sub layer HRD parameters */
+struct bspp_hevc_sublayer_hrd_parameters {
+	unsigned char bit_rate_value_minus1[HEVC_MAX_CPB_COUNT];
+	unsigned char cpb_size_value_minus1[HEVC_MAX_CPB_COUNT];
+	unsigned char cpb_size_du_value_minus1[HEVC_MAX_CPB_COUNT];
+	unsigned char bit_rate_du_value_minus1[HEVC_MAX_CPB_COUNT];
+	unsigned char cbr_flag[HEVC_MAX_CPB_COUNT];
+};
+
+/* HEVC HRD parameters */
+struct bspp_hevc_hrd_parameters {
+	unsigned char nal_hrd_parameters_present_flag;
+	unsigned char vcl_hrd_parameters_present_flag;
+	unsigned char sub_pic_hrd_params_present_flag;
+	unsigned char tick_divisor_minus2;
+	unsigned char du_cpb_removal_delay_increment_length_minus1;
+	unsigned char sub_pic_cpb_params_in_pic_timing_sei_flag;
+	unsigned char dpb_output_delay_du_length_minus1;
+	unsigned char bit_rate_scale;
+	unsigned char cpb_size_scale;
+	unsigned char cpb_size_du_scale;
+	unsigned char initial_cpb_removal_delay_length_minus1;
+	unsigned char au_cpb_removal_delay_length_minus1;
+	unsigned char dpb_output_delay_length_minus1;
+	unsigned char fixed_pic_rate_general_flag[HEVC_MAX_NUM_SUBLAYERS];
+	unsigned char fixed_pic_rate_within_cvs_flag[HEVC_MAX_NUM_SUBLAYERS];
+	unsigned char elemental_duration_in_tc_minus1[HEVC_MAX_NUM_SUBLAYERS];
+	unsigned char low_delay_hrd_flag[HEVC_MAX_NUM_SUBLAYERS];
+	unsigned char cpb_cnt_minus1[HEVC_MAX_NUM_SUBLAYERS];
+	struct bspp_hevc_sublayer_hrd_parameters sublayhrdparams[HEVC_MAX_NUM_SUBLAYERS];
+};
+
+/* HEVC video parameter set */
+struct bspp_hevc_vps {
+	unsigned char is_different;
+	unsigned char is_sent;
+	unsigned char is_available;
+	unsigned char vps_video_parameter_set_id;
+	unsigned char vps_reserved_three_2bits;
+	unsigned char vps_max_layers_minus1;
+	unsigned char vps_max_sub_layers_minus1;
+	unsigned char vps_temporal_id_nesting_flag;
+	unsigned short vps_reserved_0xffff_16bits;
+	struct bspp_hevc_profile_tierlevel profiletierlevel;
+	unsigned char vps_max_dec_pic_buffering_minus1[HEVC_MAX_NUM_SUBLAYERS];
+	unsigned char vps_max_num_reorder_pics[HEVC_MAX_NUM_SUBLAYERS];
+	unsigned char vps_max_latency_increase_plus1[HEVC_MAX_NUM_SUBLAYERS];
+	unsigned char vps_sub_layer_ordering_info_present_flag;
+	unsigned char vps_max_layer_id;
+	unsigned char vps_num_layer_sets_minus1;
+	unsigned char layer_id_included_flag[HEVC_MAX_VPS_OP_SETS_PLUS1]
+		[HEVC_MAX_VPS_NUH_RESERVED_ZERO_LAYER_ID_PLUS1];
+	unsigned char vps_timing_info_present_flag;
+	unsigned int vps_num_units_in_tick;
+	unsigned int vps_time_scale;
+	unsigned char vps_poc_proportional_to_timing_flag;
+	unsigned char vps_num_ticks_poc_diff_one_minus1;
+	unsigned char vps_num_hrd_parameters;
+	unsigned char *hrd_layer_set_idx;
+	unsigned char *cprms_present_flag;
+	unsigned char vps_extension_flag;
+	unsigned char vps_extension_data_flag;
+};
+
+/* HEVC scaling lists */
+struct bspp_hevc_scalinglist_data {
+	unsigned char dccoeffs[HEVC_SCALING_LIST_NUM_SIZES - 2][HEVC_SCALING_LIST_NUM_MATRICES];
+	unsigned char lists[HEVC_SCALING_LIST_NUM_SIZES][HEVC_SCALING_LIST_NUM_MATRICES]
+		[HEVC_SCALING_LIST_MATRIX_SIZE];
+};
+
+/* HEVC short term reference picture set */
+struct bspp_hevc_shortterm_refpicset {
+	unsigned char num_negative_pics;
+	unsigned char num_positive_pics;
+	short delta_poc_s0[HEVC_MAX_NUM_REF_PICS];
+	short delta_poc_s1[HEVC_MAX_NUM_REF_PICS];
+	unsigned char used_bycurr_pic_s0[HEVC_MAX_NUM_REF_PICS];
+	unsigned char used_bycurr_pic_s1[HEVC_MAX_NUM_REF_PICS];
+	unsigned char num_delta_pocs;
+};
+
+/* HEVC video usability information */
+struct bspp_hevc_vui_params {
+	unsigned char aspect_ratio_info_present_flag;
+	unsigned char aspect_ratio_idc;
+	unsigned short sar_width;
+	unsigned short sar_height;
+	unsigned char overscan_info_present_flag;
+	unsigned char overscan_appropriate_flag;
+	unsigned char video_signal_type_present_flag;
+	unsigned char video_format;
+	unsigned char video_full_range_flag;
+	unsigned char colour_description_present_flag;
+	unsigned char colour_primaries;
+	unsigned char transfer_characteristics;
+	unsigned char matrix_coeffs;
+	unsigned char chroma_loc_info_present_flag;
+	unsigned char chroma_sample_loc_type_top_field;
+	unsigned char chroma_sample_loc_type_bottom_field;
+	unsigned char neutral_chroma_indication_flag;
+	unsigned char field_seq_flag;
+	unsigned char frame_field_info_present_flag;
+	unsigned char default_display_window_flag;
+	unsigned short def_disp_win_left_offset;
+	unsigned short def_disp_win_right_offset;
+	unsigned short def_disp_win_top_offset;
+	unsigned short def_disp_win_bottom_offset;
+	unsigned char vui_timing_info_present_flag;
+	unsigned int vui_num_units_in_tick;
+	unsigned int vui_time_scale;
+	unsigned char vui_poc_proportional_to_timing_flag;
+	unsigned int vui_num_ticks_poc_diff_one_minus1;
+	unsigned char vui_hrd_parameters_present_flag;
+	struct bspp_hevc_hrd_parameters vui_hrd_params;
+	unsigned char bitstream_restriction_flag;
+	unsigned char tiles_fixed_structure_flag;
+	unsigned char motion_vectors_over_pic_boundaries_flag;
+	unsigned char restricted_ref_pic_lists_flag;
+	unsigned short min_spatial_segmentation_idc;
+	unsigned char max_bytes_per_pic_denom;
+	unsigned char max_bits_per_min_cu_denom;
+	unsigned char log2_max_mv_length_horizontal;
+	unsigned char log2_max_mv_length_vertical;
+};
+
+/* HEVC sps range extensions */
+struct bspp_hevc_sps_range_exts {
+	unsigned char transform_skip_rotation_enabled_flag;
+	unsigned char transform_skip_context_enabled_flag;
+	unsigned char implicit_rdpcm_enabled_flag;
+	unsigned char explicit_rdpcm_enabled_flag;
+	unsigned char extended_precision_processing_flag;
+	unsigned char intra_smoothing_disabled_flag;
+	unsigned char high_precision_offsets_enabled_flag;
+	unsigned char persistent_rice_adaptation_enabled_flag;
+	unsigned char cabac_bypass_alignment_enabled_flag;
+};
+
+/* HEVC sequence parameter set */
+struct bspp_hevc_sps {
+	unsigned char is_different;
+	unsigned char is_sent;
+	unsigned char is_available;
+	unsigned char sps_video_parameter_set_id;
+	unsigned char sps_max_sub_layers_minus1;
+	unsigned char sps_temporal_id_nesting_flag;
+	struct bspp_hevc_profile_tierlevel profile_tier_level;
+	unsigned char sps_seq_parameter_set_id;
+	unsigned char chroma_format_idc;
+	unsigned char separate_colour_plane_flag;
+	unsigned int pic_width_in_luma_samples;
+	unsigned int pic_height_in_luma_samples;
+	unsigned char conformance_window_flag;
+	unsigned short conf_win_left_offset;
+	unsigned short conf_win_right_offset;
+	unsigned short conf_win_top_offset;
+	unsigned short conf_win_bottom_offset;
+	unsigned char bit_depth_luma_minus8;
+	unsigned char bit_depth_chroma_minus8;
+	unsigned char log2_max_pic_order_cnt_lsb_minus4;
+	unsigned char sps_sub_layer_ordering_info_present_flag;
+	unsigned char sps_max_dec_pic_buffering_minus1[HEVC_MAX_NUM_SUBLAYERS];
+	unsigned char sps_max_num_reorder_pics[HEVC_MAX_NUM_SUBLAYERS];
+	unsigned int sps_max_latency_increase_plus1[HEVC_MAX_NUM_SUBLAYERS];
+	unsigned char log2_min_luma_coding_block_size_minus3;
+	unsigned char log2_diff_max_min_luma_coding_block_size;
+	unsigned char log2_min_transform_block_size_minus2;
+	unsigned char log2_diff_max_min_transform_block_size;
+	unsigned char max_transform_hierarchy_depth_inter;
+	unsigned char max_transform_hierarchy_depth_intra;
+	unsigned char scaling_list_enabled_flag;
+	unsigned char sps_scaling_list_data_present_flag;
+	struct bspp_hevc_scalinglist_data scalinglist_data;
+	unsigned char amp_enabled_flag;
+	unsigned char sample_adaptive_offset_enabled_flag;
+	unsigned char pcm_enabled_flag;
+	unsigned char pcm_sample_bit_depth_luma_minus1;
+	unsigned char pcm_sample_bit_depth_chroma_minus1;
+	unsigned char log2_min_pcm_luma_coding_block_size_minus3;
+	unsigned char log2_diff_max_min_pcm_luma_coding_block_size;
+	unsigned char pcm_loop_filter_disabled_flag;
+	unsigned char num_short_term_ref_pic_sets;
+	struct bspp_hevc_shortterm_refpicset rps_list[HEVC_MAX_NUM_ST_REF_PIC_SETS];
+	unsigned char long_term_ref_pics_present_flag;
+	unsigned char num_long_term_ref_pics_sps;
+	unsigned short lt_ref_pic_poc_lsb_sps[HEVC_MAX_NUM_LT_REF_PICS];
+	unsigned char used_by_curr_pic_lt_sps_flag[HEVC_MAX_NUM_LT_REF_PICS];
+	unsigned char sps_temporal_mvp_enabled_flag;
+	unsigned char strong_intra_smoothing_enabled_flag;
+	unsigned char vui_parameters_present_flag;
+	struct bspp_hevc_vui_params vui_params;
+	unsigned char sps_extension_present_flag;
+	unsigned char sps_range_extensions_flag;
+	struct bspp_hevc_sps_range_exts range_exts;
+	unsigned char sps_extension_7bits;
+	unsigned char sps_extension_data_flag;
+	/* derived elements */
+	unsigned char sub_width_c;
+	unsigned char sub_height_c;
+	unsigned char ctb_log2size_y;
+	unsigned char ctb_size_y;
+	unsigned int pic_width_in_ctbs_y;
+	unsigned int pic_height_in_ctbs_y;
+	unsigned int pic_size_in_ctbs_y;
+	int max_pic_order_cnt_lsb;
+	unsigned int sps_max_latency_pictures[HEVC_MAX_NUM_SUBLAYERS];
+	/* raw vui data as extracted from bitstream. */
+	struct bspp_raw_bitstream_data *vui_raw_data;
+};
+
+/**
+ * struct bspp_hevc_sequ_hdr_info - This structure contains HEVC sequence
+ *					header information (VPS, SPS, VUI)
+ *					contains everything parsed from the
+ *					video/sequence header.
+ * @vps: HEVC sequence header information
+ * @sps:HEVC sequence header information
+ */
+struct bspp_hevc_sequ_hdr_info {
+	struct bspp_hevc_vps vps;
+	struct bspp_hevc_sps sps;
+};
+
+/* HEVC pps range extensions */
+struct bspp_hevc_pps_range_exts {
+	unsigned char log2_max_transform_skip_block_size_minus2;
+	unsigned char cross_component_prediction_enabled_flag;
+	unsigned char chroma_qp_offset_list_enabled_flag;
+	unsigned char diff_cu_chroma_qp_offset_depth;
+	unsigned char chroma_qp_offset_list_len_minus1;
+	unsigned char cb_qp_offset_list[HEVC_MAX_CHROMA_QP];
+	unsigned char cr_qp_offset_list[HEVC_MAX_CHROMA_QP];
+	unsigned char log2_sao_offset_scale_luma;
+	unsigned char log2_sao_offset_scale_chroma;
+};
+
+/* HEVC picture parameter set */
+struct bspp_hevc_pps {
+	unsigned char is_available;
+	unsigned char is_param_copied;
+	unsigned char pps_pic_parameter_set_id;
+	unsigned char pps_seq_parameter_set_id;
+	unsigned char dependent_slice_segments_enabled_flag;
+	unsigned char output_flag_present_flag;
+	unsigned char num_extra_slice_header_bits;
+	unsigned char sign_data_hiding_enabled_flag;
+	unsigned char cabac_init_present_flag;
+	unsigned char num_ref_idx_l0_default_active_minus1;
+	unsigned char num_ref_idx_l1_default_active_minus1;
+	unsigned char init_qp_minus26;
+	unsigned char constrained_intra_pred_flag;
+	unsigned char transform_skip_enabled_flag;
+	unsigned char cu_qp_delta_enabled_flag;
+	unsigned char diff_cu_qp_delta_depth;
+	int pps_cb_qp_offset;
+	int pps_cr_qp_offset;
+	unsigned char pps_slice_chroma_qp_offsets_present_flag;
+	unsigned char weighted_pred_flag;
+	unsigned char weighted_bipred_flag;
+	unsigned char transquant_bypass_enabled_flag;
+	unsigned char tiles_enabled_flag;
+	unsigned char entropy_coding_sync_enabled_flag;
+	unsigned char num_tile_columns_minus1;
+	unsigned char num_tile_rows_minus1;
+	unsigned char uniform_spacing_flag;
+	unsigned char column_width_minus1[HEVC_MAX_TILE_COLS];
+	unsigned char row_height_minus1[HEVC_MAX_TILE_ROWS];
+	unsigned char loop_filter_across_tiles_enabled_flag;
+	unsigned char pps_loop_filter_across_slices_enabled_flag;
+	unsigned char deblocking_filter_control_present_flag;
+	unsigned char deblocking_filter_override_enabled_flag;
+	unsigned char pps_deblocking_filter_disabled_flag;
+	unsigned char pps_beta_offset_div2;
+	unsigned char pps_tc_offset_div2;
+	unsigned char pps_scaling_list_data_present_flag;
+	struct bspp_hevc_scalinglist_data scaling_list;
+	unsigned char lists_modification_present_flag;
+	unsigned char log2_parallel_merge_level_minus2;
+	unsigned char slice_segment_header_extension_present_flag;
+	unsigned char pps_extension_present_flag;
+	unsigned char pps_range_extensions_flag;
+	struct bspp_hevc_pps_range_exts range_exts;
+	unsigned char pps_extension_7bits;
+	unsigned char pps_extension_data_flag;
+	/* derived elements */
+	unsigned short col_bd[HEVC_MAX_TILE_COLS + 1];
+	unsigned short row_bd[HEVC_MAX_TILE_ROWS + 1];
+	/* PVDEC derived elements */
+	unsigned int max_tile_height_in_ctbs_y;
+};
+
+/* HEVC slice segment header */
+struct bspp_hevc_slice_segment_header {
+	unsigned char bslice_is_idr;
+	unsigned char first_slice_segment_in_pic_flag;
+	unsigned char no_output_of_prior_pics_flag;
+	unsigned char slice_pic_parameter_set_id;
+	unsigned char dependent_slice_segment_flag;
+	unsigned int slice_segment_address;
+};
+
+/*
+ * @Function   bspp_hevc_set_parser_config
+ * sets the parser configuration.
+ */
+int bspp_hevc_set_parser_config(enum vdec_bstr_format bstr_format,
+				struct bspp_vid_std_features *pvidstd_features,
+				struct bspp_swsr_ctx *pswsr_ctx,
+				struct bspp_parser_callbacks *pparser_callbacks,
+				struct bspp_inter_pict_data *pinterpict_data);
+
+void bspp_hevc_determine_unittype(unsigned char bitstream_unittype,
+				  int disable_mvc,
+				  enum bspp_unit_type *bspp_unittype);
+
+#endif /*__H264SECUREPARSER_H__ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/hw_control.c b/drivers/media/platform/img/vxe-vxd/decoder/hw_control.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/hw_control.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/hw_control.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1233 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VXD DEC Hardware control implementation
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "decoder.h"
+#include "hw_control.h"
+#include "img_msvdx_vdmc_regs.h"
+#include "img_pvdec_core_regs.h"
+#include "img_pvdec_pixel_regs.h"
+#include "img_pvdec_test_regs.h"
+#include "img_vdec_fw_msg.h"
+#include "img_video_bus4_mmu_regs.h"
+#include "img_msvdx_core_regs.h"
+#include "reg_io2.h"
+#include "vdecdd_defs.h"
+#include "vxd_dec.h"
+#include "vxd_ext.h"
+#include "vxd_int.h"
+#include "vxd_pvdec_priv.h"
+
+#define MSG_GROUP_MASK  0xf0
+
+struct hwctrl_ctx {
+	unsigned int is_initialised;
+	unsigned int is_on_seq_replay;
+	unsigned int replay_tid;
+	unsigned int num_pipes;
+	struct vdecdd_dd_devconfig devconfig;
+	void *hndl_vxd;
+	void *dec_core;
+	void *comp_init_userdata;
+	struct vidio_ddbufinfo dev_ptd_bufinfo;
+	struct lst_t pend_pict_list;
+	struct hwctrl_msgstatus host_msg_status;
+	void *hmsg_task_event;
+	void *hmsg_task_kick;
+	void *hmsg_task;
+	unsigned int is_msg_task_active;
+	struct hwctrl_state state;
+	struct hwctrl_state prev_state;
+	unsigned int is_prev_hw_state_set;
+	unsigned int is_fatal_state;
+};
+
+struct vdeckm_context {
+	unsigned int core_num;
+	struct vxd_coreprops props;
+	unsigned short current_msgid;
+	unsigned char reader_active;
+	void *comms_ram_addr;
+	unsigned int state_offset;
+	unsigned int state_size;
+};
+
+/*
+ * Panic reason identifier.
+ */
+enum pvdec_panic_reason {
+	PANIC_REASON_OTHER = 0,
+	PANIC_REASON_WDT,
+	PANIC_REASON_READ_TIMEOUT,
+	PANIC_REASON_CMD_TIMEOUT,
+	PANIC_REASON_MMU_FAULT,
+	PANIC_REASON_MAX,
+	PANIC_REASON_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Panic reason strings.
+ * NOTE: Should match the pvdec_panic_reason ids.
+ */
+static unsigned char *apanic_reason[PANIC_REASON_MAX] = {
+	[PANIC_REASON_OTHER] = "Other",
+	[PANIC_REASON_WDT] = "Watch Dog Timeout",
+	[PANIC_REASON_READ_TIMEOUT] = "Read Timeout",
+	[PANIC_REASON_CMD_TIMEOUT] = "Command Timeout",
+	[PANIC_REASON_MMU_FAULT] = "MMU Page Fault"
+};
+
+/*
+ * Maximum length of the panic reason string.
+ */
+#define PANIC_REASON_LEN  (255)
+
+static struct vdeckm_context acore_ctx[VXD_MAX_CORES] = {0};
+
+static int vdeckm_getregsoffsets(const void *hndl_vxd,
+				 struct decoder_regsoffsets *regs_offsets)
+{
+	struct vdeckm_context *core_ctx = (struct vdeckm_context *)hndl_vxd;
+
+	if (!core_ctx)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	regs_offsets->vdmc_cmd_offset = MSVDX_CMD_OFFSET;
+	regs_offsets->vec_offset = MSVDX_VEC_OFFSET;
+	regs_offsets->entropy_offset = PVDEC_ENTROPY_OFFSET;
+	regs_offsets->vec_be_regs_offset = PVDEC_VEC_BE_OFFSET;
+	regs_offsets->vdec_be_codec_regs_offset = PVDEC_VEC_BE_CODEC_OFFSET;
+
+	return IMG_SUCCESS;
+}
+
+static int vdeckm_send_message(const void *hndl_vxd,
+			       struct hwctrl_to_kernel_msg *to_kernelmsg,
+			       void *vxd_dec_ctx)
+{
+	struct vdeckm_context *core_ctx = (struct vdeckm_context *)hndl_vxd;
+	unsigned int count = 0;
+	unsigned int *msg;
+
+	if (!core_ctx || !to_kernelmsg)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	msg = kzalloc(VXD_SIZE_MSG_BUFFER, GFP_KERNEL);
+	if (!msg)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	msg[count++] = to_kernelmsg->flags;
+	msg[count++] = to_kernelmsg->msg_size;
+
+	memcpy(&msg[count], to_kernelmsg->msg_hdr, to_kernelmsg->msg_size);
+
+	core_ctx->reader_active = 1;
+
+	if (!(to_kernelmsg->msg_hdr)) {
+		kfree(msg);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	pr_debug("[HWCTRL] adding message to vxd queue\n");
+	vxd_send_msg(vxd_dec_ctx, (struct vxd_fw_msg *)msg);
+
+	kfree(msg);
+
+	return 0;
+}
+
+static void vdeckm_return_msg(const void *hndl_vxd,
+			      struct hwctrl_to_kernel_msg *to_kernelmsg)
+{
+	if (to_kernelmsg)
+		kfree(to_kernelmsg->msg_hdr);
+}
+
+static int vdeckm_handle_mtxtohost_msg(unsigned int *msg, struct lst_t *pend_pict_list,
+				       enum vxd_msg_attr *msg_attr,
+				       struct dec_decpict  **decpict,
+				       unsigned char msg_type,
+				       unsigned int trans_id)
+{
+	struct dec_decpict *pdec_pict;
+
+	int ret = 0;
+	switch (msg_type) {
+	case FW_DEVA_COMPLETED:
+	{
+		struct dec_pict_attrs *pict_attrs = NULL;
+		unsigned short error_flags = 0;
+		unsigned int no_bewdts = 0;
+		unsigned int mbs_dropped = 0;
+		unsigned int mbs_recovered = 0;
+		unsigned char flag = 0;
+
+		error_flags = MEMIO_READ_FIELD(msg, FW_DEVA_COMPLETED_ERROR_FLAGS);
+
+		no_bewdts = MEMIO_READ_FIELD(msg, FW_DEVA_COMPLETED_NUM_BEWDTS);
+
+		mbs_dropped = MEMIO_READ_FIELD(msg, FW_DEVA_COMPLETED_NUM_MBSDROPPED);
+
+		mbs_recovered = MEMIO_READ_FIELD(msg, FW_DEVA_COMPLETED_NUM_MBSRECOVERED);
+
+		pdec_pict = lst_first(pend_pict_list);
+		while (pdec_pict) {
+			if (pdec_pict->transaction_id == trans_id)
+				break;
+			pdec_pict = lst_next(pdec_pict);
+		}
+		/*
+		 * We must have a picture in the list that matches
+		 * the transaction id
+		 */
+		if (!pdec_pict)
+			return IMG_ERROR_FATAL;
+
+		if (!(pdec_pict->first_fld_fwmsg) || !(pdec_pict->second_fld_fwmsg))
+			return IMG_ERROR_FATAL;
+
+		flag = pdec_pict->first_fld_fwmsg->pict_attrs.first_fld_rcvd;
+		if (flag) {
+			pict_attrs = &pdec_pict->second_fld_fwmsg->pict_attrs;
+		} else {
+			pict_attrs = &pdec_pict->first_fld_fwmsg->pict_attrs;
+			flag = 1;
+		}
+
+		pict_attrs->fe_err = (unsigned int)error_flags;
+		pict_attrs->no_be_wdt = no_bewdts;
+		pict_attrs->mbs_dropped = mbs_dropped;
+		pict_attrs->mbs_recovered = mbs_recovered;
+		/*
+		 * We may successfully replayed the picture,
+		 * so reset the error flags
+		 */
+		pict_attrs->pict_attrs.dwrfired = 0;
+		pict_attrs->pict_attrs.mmufault = 0;
+		pict_attrs->pict_attrs.deverror = 0;
+
+		*msg_attr = VXD_MSG_ATTR_DECODED;
+		*decpict = pdec_pict;
+		break;
+	}
+
+	case FW_DEVA_PANIC:
+	{
+		unsigned int panic_info =  MEMIO_READ_FIELD(msg, FW_DEVA_PANIC_ERROR_INT);
+		unsigned char panic_reason[PANIC_REASON_LEN] = "Reason(s): ";
+		unsigned char is_panic_reson_identified = 0;
+		/*
+		 * Create panic reason string.
+		 */
+		if (REGIO_READ_FIELD(panic_info, PVDEC_CORE, CR_PVDEC_HOST_INTERRUPT_STATUS,
+				     CR_HOST_SYS_WDT)) {
+			strncat(panic_reason, apanic_reason[PANIC_REASON_WDT],
+				PANIC_REASON_LEN - 1);
+			is_panic_reson_identified = 1;
+		}
+		if (REGIO_READ_FIELD(panic_info, PVDEC_CORE, CR_PVDEC_HOST_INTERRUPT_STATUS,
+				     CR_HOST_READ_TIMEOUT_PROC_IRQ)) {
+			strncat(panic_reason, apanic_reason[PANIC_REASON_READ_TIMEOUT],
+				PANIC_REASON_LEN - 1);
+			is_panic_reson_identified = 1;
+		}
+		if (REGIO_READ_FIELD(panic_info, PVDEC_CORE, CR_PVDEC_HOST_INTERRUPT_STATUS,
+				     CR_HOST_COMMAND_TIMEOUT_PROC_IRQ)) {
+			strncat(panic_reason, apanic_reason[PANIC_REASON_CMD_TIMEOUT],
+				PANIC_REASON_LEN - 1);
+			is_panic_reson_identified = 1;
+		}
+		if (!is_panic_reson_identified) {
+			strncat(panic_reason, apanic_reason[PANIC_REASON_OTHER],
+				PANIC_REASON_LEN - 1);
+		}
+		panic_reason[strlen(panic_reason) - 2] = 0;
+		if (trans_id != 0)
+			pr_err("TID=0x%08X [FIRMWARE PANIC %s]\n", trans_id, panic_reason);
+		else
+			pr_err("TID=NULL [GENERAL FIRMWARE PANIC %s]\n", panic_reason);
+		ret = IMG_ERROR_FATAL;
+
+		break;
+	}
+
+	case FW_ASSERT:
+	{
+		unsigned int fwfile_namehash = MEMIO_READ_FIELD(msg, FW_ASSERT_FILE_NAME_HASH);
+		unsigned int fwfile_line = MEMIO_READ_FIELD(msg, FW_ASSERT_FILE_LINE);
+
+		pr_err("ASSERT file name hash:0x%08X line number:%d\n",
+		       fwfile_namehash, fwfile_line);
+		ret = IMG_ERROR_FATAL;
+		break;
+	}
+
+	case FW_SO:
+	{
+		unsigned int task_name = MEMIO_READ_FIELD(msg, FW_SO_TASK_NAME);
+		unsigned char sztaskname[sizeof(unsigned int) + 1];
+
+		sztaskname[0] = task_name >> 24;
+		sztaskname[1] = (task_name >> 16) & 0xff;
+		sztaskname[2] = (task_name >> 8) & 0xff;
+		sztaskname[3] = task_name & 0xff;
+		if (sztaskname[3] != 0)
+			sztaskname[4] = 0;
+		pr_warn("STACK OVERFLOW for %s task\n", sztaskname);
+		break;
+	}
+
+	case FW_VXD_EMPTY_COMPL:
+		/*
+		 * Empty completion message sent as response to init,
+		 * configure etc The architecture of vxd.ko module
+		 * requires the firmware to send a reply for every
+		 * message submitted by the user space.
+		 */
+		break;
+
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static int vdeckm_handle_hosttomtx_msg(unsigned int *msg, struct lst_t *pend_pict_list,
+				       enum vxd_msg_attr *msg_attr,
+				       struct dec_decpict  **decpict,
+				       unsigned char msg_type,
+				       unsigned int trans_id,
+				       unsigned int msg_flags)
+{
+	struct dec_decpict *pdec_pict;
+
+	pr_debug("Received message from HOST\n");
+
+	switch (msg_type) {
+	case FW_DEVA_PARSE:
+	{
+		struct dec_pict_attrs *pict_attrs = NULL;
+		unsigned char flag = 0;
+
+		pdec_pict = lst_first(pend_pict_list);
+		while (pdec_pict) {
+			if (pdec_pict->transaction_id == trans_id)
+				break;
+
+			pdec_pict = lst_next(pdec_pict);
+		}
+
+		/*
+		 * We must have a picture in the list that matches
+		 * the transaction id
+		 */
+		if (!pdec_pict) {
+			pr_err("Firmware decoded message received\n");
+			pr_err("no pending picture\n");
+			return IMG_ERROR_FATAL;
+		}
+
+		if (!(pdec_pict->first_fld_fwmsg) || !(pdec_pict->second_fld_fwmsg)) {
+			pr_err("invalid pending picture struct\n");
+			return IMG_ERROR_FATAL;
+		}
+
+		flag = pdec_pict->first_fld_fwmsg->pict_attrs.first_fld_rcvd;
+		if (flag) {
+			pict_attrs = &pdec_pict->second_fld_fwmsg->pict_attrs;
+		} else {
+			pict_attrs = &pdec_pict->first_fld_fwmsg->pict_attrs;
+			flag = 1;
+		}
+
+		/*
+		 * The below info is fetched from firmware state
+		 * afterwards, so just set this to zero for now.
+		 */
+		pict_attrs->fe_err = 0;
+		pict_attrs->no_be_wdt = 0;
+		pict_attrs->mbs_dropped = 0;
+		pict_attrs->mbs_recovered = 0;
+
+		vxd_get_pictattrs(msg_flags, &pict_attrs->pict_attrs);
+		vxd_get_msgerrattr(msg_flags, msg_attr);
+
+		if (*msg_attr == VXD_MSG_ATTR_FATAL)
+			pr_err("[TID=0x%08X] [DECODE_FAILED]\n", trans_id);
+		if (*msg_attr == VXD_MSG_ATTR_CANCELED)
+			pr_err("[TID=0x%08X] [DECODE_CANCELED]\n", trans_id);
+
+		*decpict = pdec_pict;
+		break;
+	}
+
+	case FW_DEVA_PARSE_FRAGMENT:
+		/*
+		 * Do nothing - Picture holds the list of fragments.
+		 * So, in case of any error those would be replayed
+		 * anyway.
+		 */
+		break;
+	default:
+		pr_warn("Unknown message received 0x%02x\n", msg_type);
+		break;
+	}
+
+	return 0;
+}
+
+static int vdeckm_process_msg(const void *hndl_vxd, unsigned int *msg,
+			      struct lst_t *pend_pict_list,
+			      unsigned int msg_flags,
+			      enum vxd_msg_attr *msg_attr,
+			      struct dec_decpict  **decpict)
+{
+	struct vdeckm_context *core_ctx = (struct vdeckm_context *)hndl_vxd;
+	unsigned char msg_type;
+	unsigned char msg_group;
+	unsigned int trans_id = 0;
+	int ret = 0;
+	struct vdec_pict_hwcrc *pict_hwcrc = NULL;
+	struct dec_decpict *pdec_pict;
+
+	if (!core_ctx || !msg || !msg_attr || !pend_pict_list || !decpict)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	*msg_attr = VXD_MSG_ATTR_NONE;
+	*decpict = NULL;
+
+	trans_id = MEMIO_READ_FIELD(msg, FW_DEVA_GENMSG_TRANS_ID);
+	msg_type  = MEMIO_READ_FIELD(msg, FW_DEVA_GENMSG_MSG_TYPE);
+	msg_group = msg_type & MSG_GROUP_MASK;
+
+	switch (msg_group) {
+	case MSG_TYPE_START_PSR_MTXHOST_MSG:
+		ret = vdeckm_handle_mtxtohost_msg(msg, pend_pict_list, msg_attr,
+					    decpict, msg_type, trans_id);
+		break;
+	/*
+	 * Picture decode has been returned as unprocessed.
+	 * Locate the picture with corresponding TID and mark
+	 * it as decoded with errors.
+	 */
+	case MSG_TYPE_START_PSR_HOSTMTX_MSG:
+		ret = vdeckm_handle_hosttomtx_msg(msg, pend_pict_list, msg_attr,
+					    decpict, msg_type, trans_id,
+					    msg_flags);
+		break;
+
+	case FW_DEVA_SIGNATURES_HEVC:
+	case FW_DEVA_SIGNATURES_LEGACY:
+	{
+		unsigned int *signatures = msg + (FW_DEVA_SIGNATURES_SIGNATURES_OFFSET /
+				sizeof(unsigned int));
+		unsigned char sigcount  = MEMIO_READ_FIELD(msg, FW_DEVA_SIGNATURES_MSG_SIZE) -
+			((FW_DEVA_SIGNATURES_SIZE / sizeof(unsigned int)) - 1);
+		unsigned int selected = MEMIO_READ_FIELD(msg, FW_DEVA_SIGNATURES_SIGNATURE_SELECT);
+		unsigned char i, j = 0;
+
+		pdec_pict = lst_first(pend_pict_list);
+		while (pdec_pict) {
+			if (pdec_pict->transaction_id == trans_id)
+				break;
+			pdec_pict = lst_next(pdec_pict);
+		}
+
+		/* We must have a picture in the list that matches the tid */
+		VDEC_ASSERT(pdec_pict);
+		if (!pdec_pict) {
+			pr_err("Firmware signatures message received with no pending picture\n");
+			return IMG_ERROR_FATAL;
+		}
+
+		VDEC_ASSERT(pdec_pict->first_fld_fwmsg);
+		VDEC_ASSERT(pdec_pict->second_fld_fwmsg);
+		if (!pdec_pict->first_fld_fwmsg || !pdec_pict->second_fld_fwmsg) {
+			pr_err("Invalid pending picture struct\n");
+			return IMG_ERROR_FATAL;
+		}
+		if (pdec_pict->first_fld_fwmsg->pict_hwcrc.first_fld_rcvd) {
+			pict_hwcrc = &pdec_pict->second_fld_fwmsg->pict_hwcrc;
+		} else {
+			pict_hwcrc = &pdec_pict->first_fld_fwmsg->pict_hwcrc;
+			if (selected & (PVDEC_SIGNATURE_GROUP_20 | PVDEC_SIGNATURE_GROUP_24))
+				pdec_pict->first_fld_fwmsg->pict_hwcrc.first_fld_rcvd = TRUE;
+		}
+
+		for (i = 0; i < 32; i++) {
+			unsigned int group = selected & (1 << i);
+
+			switch (group) {
+			case PVDEC_SIGNATURE_GROUP_20:
+				pict_hwcrc->crc_vdmc_pix_recon = signatures[j++];
+				break;
+
+			case PVDEC_SIGNATURE_GROUP_24:
+				pict_hwcrc->vdeb_sysmem_wrdata = signatures[j++];
+				break;
+
+			default:
+				break;
+			}
+		}
+
+		/* sanity check */
+		sigcount -= j;
+		VDEC_ASSERT(sigcount == 0);
+
+		/*
+		 * suppress PVDEC_SIGNATURE_GROUP_1 and notify
+		 * only about groups used for verification
+		 */
+#ifdef DEBUG_DECODER_DRIVER
+		if (selected & (PVDEC_SIGNATURE_GROUP_20 | PVDEC_SIGNATURE_GROUP_24))
+			pr_info("[TID=0x%08X] [SIGNATURES]\n", trans_id);
+#endif
+
+		*decpict = pdec_pict;
+
+		break;
+	}
+
+	default: {
+#ifdef DEBUG_DECODER_DRIVER
+		unsigned short msg_size, i;
+
+		pr_warn("Unknown message type received: 0x%x", msg_type);
+
+		msg_size = MEMIO_READ_FIELD(msg, FW_DEVA_GENMSG_MSG_SIZE);
+
+		for (i = 0; i < msg_size; i++)
+			pr_info("0x%04x: 0x%08x\n", i, msg[i]);
+#endif
+		break;
+	}
+	}
+
+	return ret;
+}
+
+static void vdeckm_vlr_copy(void *dst, void *src, unsigned int size)
+{
+	unsigned int *pdst = (unsigned int *)dst;
+	unsigned int *psrc = (unsigned int *)src;
+
+	size /= 4;
+	while (size--)
+		*pdst++ = *psrc++;
+}
+
+static int vdeckm_get_core_state(const void *hndl_vxd, struct vxd_states *state)
+{
+	struct vdeckm_context *core_ctx = (struct vdeckm_context *)hndl_vxd;
+	struct vdecfw_pvdecfirmwarestate firmware_state;
+	unsigned char pipe = 0;
+
+#ifdef ERROR_RECOVERY_SIMULATION
+	/*
+	 * if disable_fw_irq_value is not zero, return error. If processed further
+	 * the kernel will crash because we have ignored the interrupt, but here
+	 * we will try to access comms_ram_addr which will result in crash.
+	 */
+	if (disable_fw_irq_value != 0)
+		return IMG_ERROR_INVALID_PARAMETERS;
+#endif
+
+	if (!core_ctx || !state)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/*
+	 * If state is requested for the first time.
+	 */
+	if (core_ctx->state_size == 0) {
+		unsigned int regval;
+		/*
+		 * get the state buffer info.
+		 */
+		regval = *((unsigned int *)core_ctx->comms_ram_addr +
+			(PVDEC_COM_RAM_STATE_BUF_SIZE_AND_OFFSET_OFFSET / sizeof(unsigned int)));
+		core_ctx->state_size = PVDEC_COM_RAM_BUF_GET_SIZE(regval, STATE);
+		core_ctx->state_offset = PVDEC_COM_RAM_BUF_GET_OFFSET(regval, STATE);
+	}
+
+	/*
+	 * If state buffer is available.
+	 */
+	if (core_ctx->state_size) {
+		/*
+		 * Determine the latest transaction to have passed each
+		 * checkpoint in the firmware.
+		 * Read the firmware state from VEC Local RAM
+		 */
+		vdeckm_vlr_copy(&firmware_state, (unsigned char *)core_ctx->comms_ram_addr +
+				core_ctx->state_offset, core_ctx->state_size);
+
+		for (pipe = 0; pipe < core_ctx->props.num_pixel_pipes; pipe++) {
+			/*
+			 * Set pipe presence.
+			 */
+			state->fw_state.pipe_state[pipe].is_pipe_present = 1;
+
+			/*
+			 * For checkpoints copy message ids here. These will
+			 * be translated into transaction ids later.
+			 */
+			memcpy(state->fw_state.pipe_state[pipe].acheck_point,
+			       firmware_state.pipestate[pipe].check_point,
+				sizeof(state->fw_state.pipe_state[pipe].acheck_point));
+			state->fw_state.pipe_state[pipe].firmware_action  =
+				firmware_state.pipestate[pipe].firmware_action;
+			state->fw_state.pipe_state[pipe].cur_codec =
+				firmware_state.pipestate[pipe].curr_codec;
+			state->fw_state.pipe_state[pipe].fe_slices =
+				firmware_state.pipestate[pipe].fe_slices;
+			state->fw_state.pipe_state[pipe].be_slices =
+				firmware_state.pipestate[pipe].be_slices;
+			state->fw_state.pipe_state[pipe].fe_errored_slices =
+				firmware_state.pipestate[pipe].fe_errored_slices;
+			state->fw_state.pipe_state[pipe].be_errored_slices =
+				firmware_state.pipestate[pipe].be_errored_slices;
+			state->fw_state.pipe_state[pipe].be_mbs_dropped =
+				firmware_state.pipestate[pipe].be_mbs_dropped;
+			state->fw_state.pipe_state[pipe].be_mbs_recovered =
+				firmware_state.pipestate[pipe].be_mbs_recovered;
+			state->fw_state.pipe_state[pipe].fe_mb.x =
+				firmware_state.pipestate[pipe].last_fe_mb_xy & 0xFF;
+			state->fw_state.pipe_state[pipe].fe_mb.y =
+				(firmware_state.pipestate[pipe].last_fe_mb_xy >> 16) & 0xFF;
+			state->fw_state.pipe_state[pipe].be_mb.x =
+				REGIO_READ_FIELD(firmware_state.pipestate[pipe].last_be_mb_xy,
+						 MSVDX_VDMC,
+						 CR_VDMC_MACROBLOCK_NUMBER,
+						 CR_VDMC_MACROBLOCK_X_OFFSET);
+			state->fw_state.pipe_state[pipe].be_mb.y =
+				REGIO_READ_FIELD(firmware_state.pipestate[pipe].last_be_mb_xy,
+						 MSVDX_VDMC,
+						 CR_VDMC_MACROBLOCK_NUMBER,
+						 CR_VDMC_MACROBLOCK_Y_OFFSET);
+		}
+	}
+
+	return 0;
+}
+
+static int vdeckm_prepare_batch(struct vdeckm_context *core_ctx,
+				const struct hwctrl_batch_msgdata *batch_msgdata,
+				unsigned char **msg)
+{
+	unsigned char vdec_flags = 0;
+	unsigned short flags = 0;
+	unsigned char *pmsg = kzalloc(FW_DEVA_DECODE_SIZE, GFP_KERNEL);
+	struct vidio_ddbufinfo *pbatch_msg_bufinfo = batch_msgdata->batchmsg_bufinfo;
+
+	if (!pmsg)
+		return IMG_ERROR_MALLOC_FAILED;
+
+	if (batch_msgdata->size_delimited_mode)
+		vdec_flags |= FW_VDEC_NAL_SIZE_DELIM;
+
+	flags |= FW_DEVA_RENDER_HOST_INT;
+
+	/*
+	 * Message type and stream ID
+	 */
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_GENMSG_MSG_TYPE, FW_DEVA_PARSE, unsigned char*);
+
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_CTRL_ALLOC_ADDR,
+			  (unsigned int)pbatch_msg_bufinfo->dev_virt, unsigned char*);
+
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_BUFFER_SIZE,
+			  batch_msgdata->ctrl_alloc_bytes / sizeof(unsigned int), unsigned char*);
+
+	/*
+	 * Operating mode and decode flags
+	 */
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_OPERATING_MODE, batch_msgdata->operating_mode,
+			  unsigned char*);
+
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_FLAGS, flags, unsigned char*);
+
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_VDEC_FLAGS, vdec_flags, unsigned char*);
+
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_GENC_ID, batch_msgdata->genc_id, unsigned char*);
+
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_MB_LOAD, batch_msgdata->mb_load, unsigned char*);
+
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_STREAMID,
+			  GET_STREAM_ID(batch_msgdata->transaction_id), unsigned char*);
+
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_EXT_STATE_BUFFER,
+			  (unsigned int)batch_msgdata->pvdec_fwctx->dev_virt, unsigned char*);
+
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_MSG_ID, ++core_ctx->current_msgid,
+			  unsigned char*);
+
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_TRANS_ID, batch_msgdata->transaction_id,
+			  unsigned char*);
+
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_TILE_CFG, batch_msgdata->tile_cfg, unsigned char*);
+
+	/*
+	 * size of message
+	 */
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_GENMSG_MSG_SIZE,
+			  FW_DEVA_DECODE_SIZE / sizeof(unsigned int), unsigned char*);
+
+	*msg = pmsg;
+
+	return 0;
+}
+
+static int vdeckm_prepare_fragment(struct vdeckm_context *core_ctx,
+				   const struct hwctrl_fragment_msgdata
+				   *fragment_msgdata,
+				   unsigned char **msg)
+{
+	struct vidio_ddbufinfo *pbatch_msg_bufinfo = NULL;
+	unsigned char *pmsg = NULL;
+
+	pbatch_msg_bufinfo = fragment_msgdata->batchmsg_bufinfo;
+
+	if (!(fragment_msgdata->batchmsg_bufinfo)) {
+		pr_err("Batch message info missing!\n");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	pmsg = kzalloc(FW_DEVA_DECODE_FRAGMENT_SIZE, GFP_KERNEL);
+	if (!pmsg)
+		return IMG_ERROR_MALLOC_FAILED;
+	/*
+	 * message type and stream id
+	 */
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_GENMSG_MSG_TYPE,
+			  FW_DEVA_PARSE_FRAGMENT, unsigned char*);
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_MSG_ID, ++core_ctx->current_msgid, unsigned char*);
+
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_FRAGMENT_CTRL_ALLOC_ADDR,
+			  (unsigned int)pbatch_msg_bufinfo->dev_virt
+			  + fragment_msgdata->ctrl_alloc_offset, unsigned char*);
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_DECODE_FRAGMENT_BUFFER_SIZE,
+			  fragment_msgdata->ctrl_alloc_bytes / sizeof(unsigned int),
+			  unsigned char*);
+
+	/*
+	 * size of message
+	 */
+	MEMIO_WRITE_FIELD(pmsg, FW_DEVA_GENMSG_MSG_SIZE,
+			  FW_DEVA_DECODE_FRAGMENT_SIZE / sizeof(unsigned int), unsigned char*);
+
+	*msg = pmsg;
+
+	return 0;
+}
+
+static int vdeckm_get_message(const void *hndl_vxd, const enum hwctrl_msgid msgid,
+			      const struct hwctrl_msgdata *msgdata,
+			      struct hwctrl_to_kernel_msg *to_kernelmsg)
+{
+	unsigned int result = 0;
+	struct vdeckm_context *core_ctx = (struct vdeckm_context *)hndl_vxd;
+
+	if (!core_ctx || !to_kernelmsg || !msgdata)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	switch (msgid) {
+	case HWCTRL_MSGID_BATCH:
+		result = vdeckm_prepare_batch(core_ctx, &msgdata->batch_msgdata,
+					      &to_kernelmsg->msg_hdr);
+		break;
+
+	case HWCTRL_MSGID_FRAGMENT:
+		result = vdeckm_prepare_fragment(core_ctx, &msgdata->fragment_msgdata,
+						 &to_kernelmsg->msg_hdr);
+		vxd_set_msgflag(VXD_MSG_FLAG_DROP, &to_kernelmsg->flags);
+		break;
+
+	default:
+		result = IMG_ERROR_GENERIC_FAILURE;
+		pr_err("got a message that is not supported by PVDEC");
+		break;
+	}
+
+	if (result == 0) {
+		/* Set the stream ID for the next message to be sent. */
+		to_kernelmsg->km_str_id = msgdata->km_str_id;
+		to_kernelmsg->msg_size = MEMIO_READ_FIELD(to_kernelmsg->msg_hdr,
+							  FW_DEVA_GENMSG_MSG_SIZE) *
+							  sizeof(unsigned int);
+	}
+
+	return result;
+}
+
+#ifdef DEBUG_DECODER_DRIVER
+static void hwctrl_dump_state(struct vxd_states *prev_state,
+			      struct vxd_states *cur_state,
+			      unsigned char pipe_minus1)
+{
+	pr_info("Back-End MbX                          [% 10d]",
+		prev_state->fw_state.pipe_state[pipe_minus1].be_mb.x);
+	pr_info("Back-End MbY                          [% 10d]",
+		prev_state->fw_state.pipe_state[pipe_minus1].be_mb.y);
+	pr_info("Front-End MbX                         [% 10d]",
+		prev_state->fw_state.pipe_state[pipe_minus1].fe_mb.x);
+	pr_info("Front-End MbY                         [% 10d]",
+		prev_state->fw_state.pipe_state[pipe_minus1].fe_mb.y);
+	pr_info("VDECFW_CHECKPOINT_BE_PICTURE_COMPLETE [0x%08X]",
+		cur_state->fw_state.pipe_state[pipe_minus1].acheck_point
+		[VDECFW_CHECKPOINT_BE_PICTURE_COMPLETE]);
+	pr_info("VDECFW_CHECKPOINT_BE_1SLICE_DONE      [0x%08X]",
+		cur_state->fw_state.pipe_state[pipe_minus1].acheck_point
+		[VDECFW_CHECKPOINT_BE_1SLICE_DONE]);
+	pr_info("VDECFW_CHECKPOINT_BE_PICTURE_STARTED  [0x%08X]",
+		cur_state->fw_state.pipe_state[pipe_minus1].acheck_point
+		[VDECFW_CHECKPOINT_BE_PICTURE_STARTED]);
+	pr_info("VDECFW_CHECKPOINT_FE_PICTURE_COMPLETE [0x%08X]",
+		cur_state->fw_state.pipe_state[pipe_minus1].acheck_point
+		[VDECFW_CHECKPOINT_FE_PICTURE_COMPLETE]);
+	pr_info("VDECFW_CHECKPOINT_FE_PARSE_DONE       [0x%08X]",
+		cur_state->fw_state.pipe_state[pipe_minus1].acheck_point
+		[VDECFW_CHECKPOINT_FE_PARSE_DONE]);
+	pr_info("VDECFW_CHECKPOINT_FE_1SLICE_DONE      [0x%08X]",
+		cur_state->fw_state.pipe_state[pipe_minus1].acheck_point
+		[VDECFW_CHECKPOINT_FE_1SLICE_DONE]);
+	pr_info("VDECFW_CHECKPOINT_ENTDEC_STARTED      [0x%08X]",
+		cur_state->fw_state.pipe_state[pipe_minus1].acheck_point
+		[VDECFW_CHECKPOINT_ENTDEC_STARTED]);
+	pr_info("VDECFW_CHECKPOINT_FIRMWARE_SAVED      [0x%08X]",
+		cur_state->fw_state.pipe_state[pipe_minus1].acheck_point
+		[VDECFW_CHECKPOINT_FIRMWARE_SAVED]);
+	pr_info("VDECFW_CHECKPOINT_PICMAN_COMPLETE     [0x%08X]",
+		cur_state->fw_state.pipe_state[pipe_minus1].acheck_point
+		[VDECFW_CHECKPOINT_PICMAN_COMPLETE]);
+	pr_info("VDECFW_CHECKPOINT_FIRMWARE_READY      [0x%08X]",
+		cur_state->fw_state.pipe_state[pipe_minus1].acheck_point
+		[VDECFW_CHECKPOINT_FIRMWARE_READY]);
+	pr_info("VDECFW_CHECKPOINT_PICTURE_STARTED     [0x%08X]",
+		cur_state->fw_state.pipe_state[pipe_minus1].acheck_point
+		[VDECFW_CHECKPOINT_PICTURE_STARTED]);
+}
+#endif
+
+static unsigned int hwctrl_calculate_load(struct bspp_pict_hdr_info *pict_hdr_info)
+{
+	return (((pict_hdr_info->coded_frame_size.width + 15) / 16)
+	       * ((pict_hdr_info->coded_frame_size.height + 15) / 16));
+}
+
+static int hwctrl_send_batch_message(struct hwctrl_ctx *hwctx,
+				     struct dec_decpict *decpict,
+				     void *vxd_dec_ctx)
+{
+	int result;
+	struct hwctrl_to_kernel_msg to_kernelmsg = {0};
+	struct vidio_ddbufinfo *batchmsg_bufinfo =
+		decpict->batch_msginfo->ddbuf_info;
+	struct hwctrl_msgdata msg_data;
+	struct hwctrl_batch_msgdata *batch_msgdata = &msg_data.batch_msgdata;
+
+	memset(&msg_data, 0, sizeof(msg_data));
+
+	msg_data.km_str_id = GET_STREAM_ID(decpict->transaction_id);
+
+	batch_msgdata->batchmsg_bufinfo  = batchmsg_bufinfo;
+
+	batch_msgdata->transaction_id    = decpict->transaction_id;
+	batch_msgdata->pvdec_fwctx       = decpict->str_pvdec_fw_ctxbuf;
+	batch_msgdata->ctrl_alloc_bytes  = decpict->ctrl_alloc_bytes;
+	batch_msgdata->operating_mode    = decpict->operating_op;
+	batch_msgdata->genc_id           = decpict->genc_id;
+	batch_msgdata->mb_load           = hwctrl_calculate_load(decpict->pict_hdr_info);
+	batch_msgdata->size_delimited_mode =
+		(decpict->pict_hdr_info->parser_mode != VDECFW_SCP_ONLY) ?
+		(1) : (0);
+
+	result = vdeckm_get_message(hwctx->hndl_vxd, HWCTRL_MSGID_BATCH,
+				    &msg_data, &to_kernelmsg);
+	if (result != 0) {
+		pr_err("failed to get decode message\n");
+		return result;
+	}
+
+	pr_debug("[HWCTRL] send batch message\n");
+	result = vdeckm_send_message(hwctx->hndl_vxd, &to_kernelmsg,
+				     vxd_dec_ctx);
+	if (result != 0)
+		return result;
+
+	vdeckm_return_msg(hwctx->hndl_vxd, &to_kernelmsg);
+
+	return 0;
+}
+
+int hwctrl_process_msg(void *hndl_hwctx, unsigned int msg_flags, unsigned int *msg,
+		       struct dec_decpict **decpict)
+{
+	int result;
+	struct hwctrl_ctx *hwctx;
+	enum vxd_msg_attr msg_attr = VXD_MSG_ATTR_NONE;
+	struct dec_decpict *pdecpict = NULL;
+	unsigned int val_first = 0;
+	unsigned int val_sec = 0;
+
+	if (!hndl_hwctx || !msg || !decpict) {
+		VDEC_ASSERT(0);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	hwctx = (struct hwctrl_ctx *)hndl_hwctx;
+
+	*decpict = NULL;
+
+	pr_debug("[HWCTRL] : process message\n");
+	result = vdeckm_process_msg(hwctx->hndl_vxd, msg, &hwctx->pend_pict_list, msg_flags,
+				    &msg_attr, &pdecpict);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* validate pointers before using them */
+	if (!pdecpict || !pdecpict->first_fld_fwmsg || !pdecpict->second_fld_fwmsg) {
+		VDEC_ASSERT(0);
+		return -EIO;
+	}
+
+	val_first = pdecpict->first_fld_fwmsg->pict_attrs.pict_attrs.deverror;
+	val_sec = pdecpict->second_fld_fwmsg->pict_attrs.pict_attrs.deverror;
+
+	if (val_first || val_sec)
+		pr_err("device signaled critical error!!!\n");
+
+	if (msg_attr == VXD_MSG_ATTR_DECODED) {
+		pdecpict->state = DECODER_PICTURE_STATE_DECODED;
+		/*
+		 * We have successfully decoded a picture as normally or
+		 * after the replay.
+		 * Mark HW is in good state.
+		 */
+		hwctx->is_fatal_state = 0;
+	} else if (msg_attr == VXD_MSG_ATTR_FATAL) {
+		struct hwctrl_state state;
+		unsigned char pipe_minus1 = 0;
+
+		memset(&state, 0, sizeof(state));
+
+		result = hwctrl_get_core_status(hwctx, &state);
+		if (result == 0) {
+			hwctx->is_prev_hw_state_set = 1;
+			memcpy(&hwctx->prev_state, &state, sizeof(struct hwctrl_state));
+
+			for (pipe_minus1 = 0; pipe_minus1 < hwctx->num_pipes;
+				pipe_minus1++) {
+#ifdef DEBUG_DECODER_DRIVER
+				hwctrl_dump_state(&state.core_state, &state.core_state,
+						  pipe_minus1);
+#endif
+			}
+		}
+		pdecpict->state = DECODER_PICTURE_STATE_TO_DISCARD;
+	}
+	*decpict = pdecpict;
+
+	return 0;
+}
+
+int hwctrl_getcore_cached_status(void *hndl_hwctx, struct hwctrl_state *state)
+{
+	struct hwctrl_ctx *hwctx = (struct hwctrl_ctx *)hndl_hwctx;
+
+	if (hwctx->is_prev_hw_state_set)
+		memcpy(state, &hwctx->prev_state, sizeof(struct hwctrl_state));
+	else
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	return 0;
+}
+
+int hwctrl_get_core_status(void *hndl_hwctx, struct hwctrl_state *state)
+{
+	struct hwctrl_ctx *hwctx = (struct hwctrl_ctx *)hndl_hwctx;
+	unsigned int result = IMG_ERROR_GENERIC_FAILURE;
+
+	if (!hwctx->is_fatal_state && state) {
+		struct vxd_states *pcorestate = NULL;
+
+		pcorestate  = &state->core_state;
+
+		memset(pcorestate, 0, sizeof(*(pcorestate)));
+
+		result = vdeckm_get_core_state(hwctx->hndl_vxd, pcorestate);
+	}
+
+	return result;
+}
+
+int hwctrl_is_on_seq_replay(void *hndl_hwctx)
+{
+	struct hwctrl_ctx *hwctx = (struct hwctrl_ctx *)hndl_hwctx;
+
+	return hwctx->is_on_seq_replay;
+}
+
+int hwctrl_picture_submitbatch(void *hndl_hwctx, struct dec_decpict  *decpict, void *vxd_dec_ctx)
+{
+	struct hwctrl_ctx *hwctx = (struct hwctrl_ctx *)hndl_hwctx;
+
+	if (hwctx->is_initialised) {
+		lst_add(&hwctx->pend_pict_list, decpict);
+		if (!hwctx->is_on_seq_replay)
+			return hwctrl_send_batch_message(hwctx, decpict, vxd_dec_ctx);
+	}
+
+	return 0;
+}
+
+int hwctrl_getpicpend_pictlist(void *hndl_hwctx, unsigned int transaction_id,
+			       struct dec_decpict  **decpict)
+{
+	struct hwctrl_ctx *hwctx = (struct hwctrl_ctx *)hndl_hwctx;
+	struct dec_decpict  *dec_pic;
+
+	dec_pic = lst_first(&hwctx->pend_pict_list);
+	while (dec_pic) {
+		if (dec_pic->transaction_id == transaction_id) {
+			*decpict = dec_pic;
+			break;
+		}
+		dec_pic = lst_next(dec_pic);
+	}
+
+	if (!dec_pic)
+		return IMG_ERROR_INVALID_ID;
+
+	return 0;
+}
+
+int hwctrl_peekheadpiclist(void *hndl_hwctx, struct dec_decpict **decpict)
+{
+	struct hwctrl_ctx *hwctx = (struct hwctrl_ctx *)hndl_hwctx;
+
+	if (hwctx)
+		*decpict = lst_first(&hwctx->pend_pict_list);
+
+	if (*decpict)
+		return 0;
+
+	return IMG_ERROR_GENERIC_FAILURE;
+}
+
+int hwctrl_getdecodedpicture(void *hndl_hwctx, struct dec_decpict **decpict)
+{
+	struct hwctrl_ctx *hwctx = (struct hwctrl_ctx *)hndl_hwctx;
+
+	if (hwctx) {
+		struct dec_decpict *cur_decpict;
+		/*
+		 * Ensure that this picture is in the list.
+		 */
+		cur_decpict = lst_first(&hwctx->pend_pict_list);
+		while (cur_decpict) {
+			if (cur_decpict->state == DECODER_PICTURE_STATE_DECODED) {
+				*decpict = cur_decpict;
+				return 0;
+			}
+
+			cur_decpict = lst_next(cur_decpict);
+		}
+	}
+
+	return IMG_ERROR_VALUE_OUT_OF_RANGE;
+}
+
+void hwctrl_removefrom_piclist(void *hndl_hwctx, struct dec_decpict  *decpict)
+{
+	struct hwctrl_ctx *hwctx = (struct hwctrl_ctx *)hndl_hwctx;
+
+	if (hwctx) {
+		struct dec_decpict *cur_decpict;
+		/*
+		 * Ensure that this picture is in the list.
+		 */
+		cur_decpict = lst_first(&hwctx->pend_pict_list);
+		while (cur_decpict) {
+			if (cur_decpict == decpict) {
+				lst_remove(&hwctx->pend_pict_list, decpict);
+				break;
+			}
+
+			cur_decpict = lst_next(cur_decpict);
+		}
+	}
+}
+
+int hwctrl_getregsoffset(void *hndl_hwctx, struct decoder_regsoffsets *regs_offsets)
+{
+	struct hwctrl_ctx *hwctx = (struct hwctrl_ctx *)hndl_hwctx;
+
+	return vdeckm_getregsoffsets(hwctx->hndl_vxd, regs_offsets);
+}
+
+static int pvdec_create(struct vxd_dev *vxd, struct vxd_coreprops *core_props,
+			void **hndl_vdeckm_context)
+{
+	struct vdeckm_context  *corectx;
+	struct vxd_core_props hndl_core_props;
+	int result;
+	int iMapSize, pageSize;
+	void *phy_addr;
+
+	if (!hndl_vdeckm_context || !core_props)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/*
+	 * Obtain core context.
+	 */
+	corectx = &acore_ctx[0];
+
+	memset(corectx, 0, sizeof(*corectx));
+
+	corectx->core_num = 0;
+
+	result = vxd_pvdec_get_props(vxd->dev, vxd->reg_base, &hndl_core_props);
+	if (result != 0)
+		return result;
+
+	vxd_get_coreproperties(&hndl_core_props, &corectx->props);
+
+	memcpy(core_props, &corectx->props, sizeof(*core_props));
+
+	pageSize = PAGE_SIZE;
+	/* end aligned to page (ceiling), in pages */
+	iMapSize = (PVDEC_COMMS_RAM_OFFSET + PVDEC_COMMS_RAM_SIZE + pageSize - 1) / pageSize;
+	/* subtract start aligned to page (floor), in pages */
+	iMapSize -= PVDEC_COMMS_RAM_OFFSET / pageSize;
+	/* convert to bytes */
+	iMapSize *= pageSize;
+	phy_addr = (void *)(0x4300000);
+	phy_addr += (PVDEC_COMMS_RAM_OFFSET);
+	corectx->comms_ram_addr = ioremap((phys_addr_t)phy_addr, iMapSize);
+	*hndl_vdeckm_context = corectx;
+
+	return 0;
+}
+
+int hwctrl_deinitialise(void *hndl_hwctx)
+{
+	struct hwctrl_ctx *hwctx = (struct hwctrl_ctx *)hndl_hwctx;
+
+	if (hwctx->is_initialised) {
+		kfree(hwctx);
+		hwctx = NULL;
+	}
+
+	return 0;
+}
+
+int hwctrl_initialise(void *dec_core, void *comp_int_userdata,
+		      const struct vdecdd_dd_devconfig  *dd_devconfig,
+		      struct vxd_coreprops *core_props, void **hndl_hwctx)
+{
+	struct hwctrl_ctx *hwctx = (struct hwctrl_ctx *)*hndl_hwctx;
+	int result;
+
+	if (!hwctx) {
+		hwctx = kzalloc(sizeof(*(hwctx)), GFP_KERNEL);
+		if (!hwctx)
+			return IMG_ERROR_OUT_OF_MEMORY;
+
+		*hndl_hwctx = hwctx;
+	}
+
+	if (!hwctx->is_initialised) {
+		hwctx->hndl_vxd = ((struct dec_core_ctx *)dec_core)->dec_ctx->dev_handle;
+		result = pvdec_create(hwctx->hndl_vxd, core_props, &hwctx->hndl_vxd);
+		if (result != 0)
+			goto error;
+
+		lst_init(&hwctx->pend_pict_list);
+
+		hwctx->devconfig = *dd_devconfig;
+		hwctx->num_pipes = core_props->num_pixel_pipes;
+		hwctx->comp_init_userdata = comp_int_userdata;
+		hwctx->dec_core = dec_core;
+		hwctx->is_initialised = 1;
+		hwctx->is_on_seq_replay = 0;
+		hwctx->is_fatal_state = 0;
+	}
+
+	return 0;
+error:
+	hwctrl_deinitialise(*hndl_hwctx);
+
+	return result;
+}
+
+static int hwctrl_send_fragment_message(struct hwctrl_ctx *hwctx,
+					struct dec_pict_fragment *pict_fragment,
+					struct dec_decpict *decpict,
+					void *vxd_dec_ctx)
+{
+	int result;
+	struct hwctrl_to_kernel_msg to_kernelmsg = {0};
+	struct hwctrl_msgdata msg_data;
+	struct hwctrl_fragment_msgdata *pfragment_msgdata =
+		&msg_data.fragment_msgdata;
+
+	msg_data.km_str_id = GET_STREAM_ID(decpict->transaction_id);
+
+	pfragment_msgdata->ctrl_alloc_bytes = pict_fragment->ctrl_alloc_bytes;
+
+	pfragment_msgdata->ctrl_alloc_offset = pict_fragment->ctrl_alloc_offset;
+
+	pfragment_msgdata->batchmsg_bufinfo = decpict->batch_msginfo->ddbuf_info;
+
+	result = vdeckm_get_message(hwctx->hndl_vxd, HWCTRL_MSGID_FRAGMENT, &msg_data,
+				    &to_kernelmsg);
+	if (result != 0) {
+		pr_err("Failed to get decode message\n");
+		return result;
+	}
+
+	result = vdeckm_send_message(hwctx->hndl_vxd, &to_kernelmsg, vxd_dec_ctx);
+	if (result != 0)
+		return result;
+
+	vdeckm_return_msg(hwctx->hndl_vxd, &to_kernelmsg);
+
+	return 0;
+}
+
+int hwctrl_picture_submit_fragment(void *hndl_hwctx,
+				   struct dec_pict_fragment  *pict_fragment,
+				   struct dec_decpict *decpict,
+				   void *vxd_dec_ctx)
+{
+	struct hwctrl_ctx *hwctx = (struct hwctrl_ctx *)hndl_hwctx;
+	unsigned int result = 0;
+
+	if (hwctx->is_initialised) {
+		result = hwctrl_send_fragment_message(hwctx, pict_fragment,
+						      decpict, vxd_dec_ctx);
+		if (result != 0)
+			pr_err("Failed to send fragment message to firmware !");
+	}
+
+	return result;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/hw_control.h b/drivers/media/platform/img/vxe-vxd/decoder/hw_control.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/hw_control.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/hw_control.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,144 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD DEC Hardware control implementation
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#ifndef _HW_CONTROL_H
+#define _HW_CONTROL_H
+
+#include "bspp.h"
+#include "decoder.h"
+#include "fw_interface.h"
+#include "img_dec_common.h"
+#include "img_errors.h"
+#include "lst.h"
+#include "mem_io.h"
+#include "vdecdd_defs.h"
+#include "vdecfw_shared.h"
+#include "vid_buf.h"
+#include "vxd_ext.h"
+#include "vxd_props.h"
+
+/* Size of additional buffers needed for each HEVC picture */
+#ifdef HAS_HEVC
+
+/* Empirically defined */
+#define MEM_TO_REG_BUF_SIZE 0x2000
+
+/*
+ * Max. no. of slices found in stream db: approx. 2200,
+ * set MAX_SLICES to 2368 to get buffer size page aligned
+ */
+#define MAX_SLICES 2368
+#define SLICE_PARAMS_SIZE 64
+#define SLICE_PARAMS_BUF_SIZE (MAX_SLICES * SLICE_PARAMS_SIZE)
+
+/*
+ * Size of buffer for "above params" structure, sufficient for stream of width 8192
+ * 192 * (8192/64) == 0x6000, see "above_param_size" in TRM
+ */
+#define ABOVE_PARAMS_BUF_SIZE 0x6000
+#endif
+
+enum hwctrl_msgid {
+	HWCTRL_MSGID_BATCH     = 0,
+	HWCTRL_MSGID_FRAGMENT  = 1,
+	CORE_MSGID_MAX,
+	CORE_MSGID_FORCE32BITS = 0x7FFFFFFFU
+};
+
+struct hwctrl_to_kernel_msg {
+	unsigned int msg_size;
+	unsigned int km_str_id;
+	unsigned int flags;
+	unsigned char *msg_hdr;
+};
+
+struct hwctrl_batch_msgdata {
+	struct vidio_ddbufinfo *batchmsg_bufinfo;
+	struct vidio_ddbufinfo *pvdec_fwctx;
+	unsigned int ctrl_alloc_bytes;
+	unsigned int operating_mode;
+	unsigned int transaction_id;
+	unsigned int tile_cfg;
+	unsigned int genc_id;
+	unsigned int mb_load;
+	unsigned int size_delimited_mode;
+};
+
+struct hwctrl_fragment_msgdata {
+	struct vidio_ddbufinfo *batchmsg_bufinfo;
+	unsigned int ctrl_alloc_offset;
+	unsigned int ctrl_alloc_bytes;
+};
+
+struct hwctrl_msgdata {
+	unsigned int km_str_id;
+	struct hwctrl_batch_msgdata batch_msgdata;
+	struct hwctrl_fragment_msgdata fragment_msgdata;
+};
+
+/*
+ * This structure contains MSVDX Message information.
+ */
+struct hwctrl_msgstatus {
+	unsigned char control_fence_id[VDECFW_MSGID_CONTROL_TYPES];
+	unsigned char decode_fence_id[VDECFW_MSGID_DECODE_TYPES];
+	unsigned char completion_fence_id[VDECFW_MSGID_COMPLETION_TYPES];
+};
+
+/*
+ * this structure contains the HWCTRL Core state.
+ */
+struct hwctrl_state {
+	struct vxd_states core_state;
+	struct hwctrl_msgstatus fwmsg_status;
+	struct hwctrl_msgstatus hostmsg_status;
+};
+
+int hwctrl_picture_submit_fragment(void *hndl_hwctx,
+				   struct dec_pict_fragment *pict_fragment,
+				   struct dec_decpict *decpict,
+				   void *vxd_dec_ctx);
+
+int hwctrl_process_msg(void *hndl_hwct, unsigned int msg_flags, unsigned int *msg,
+		       struct dec_decpict **decpict);
+
+int hwctrl_getcore_cached_status(void *hndl_hwctx, struct hwctrl_state *state);
+
+int hwctrl_get_core_status(void *hndl_hwctx, struct hwctrl_state *state);
+
+int hwctrl_is_on_seq_replay(void *hndl_hwctx);
+
+int hwctrl_picture_submitbatch(void *hndl_hwctx, struct dec_decpict *decpict,
+			       void *vxd_dec_ctx);
+
+int hwctrl_getpicpend_pictlist(void *hndl_hwctx, unsigned int transaction_id,
+			       struct dec_decpict **decpict);
+
+int hwctrl_peekheadpiclist(void *hndl_hwctx, struct dec_decpict **decpict);
+
+int hwctrl_getdecodedpicture(void *hndl_hwctx, struct dec_decpict **decpict);
+
+void hwctrl_removefrom_piclist(void *hndl_hwctx, struct dec_decpict *decpict);
+
+int hwctrl_getregsoffset(void *hndl_hwctx,
+			 struct decoder_regsoffsets *regs_offsets);
+
+int hwctrl_initialise(void *dec_core, void *comp_int_userdata,
+		      const struct vdecdd_dd_devconfig *dd_devconfig,
+		      struct vxd_coreprops *core_props, void **hndl_hwctx);
+
+int hwctrl_deinitialise(void *hndl_hwctx);
+
+#endif /* _HW_CONTROL_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/img_dec_common.h b/drivers/media/platform/img/vxe-vxd/decoder/img_dec_common.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/img_dec_common.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/img_dec_common.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,278 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG DEC common header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#ifndef _IMG_DEC_COMMON_H
+#define _IMG_DEC_COMMON_H
+
+#include <linux/types.h>
+
+#define VXD_MAX_PIPES 2
+#define MAX_DST_BUFFERS 32
+
+/* Helpers for parsing core properties. Based on HW registers layout. */
+#define VXD_GET_BITS(v, lb, rb, type) \
+	({                                \
+		type __rb = (rb);                                       \
+		(((v) >> (__rb)) & ((1 << ((lb) - __rb + 1)) - 1)); })
+#define VXD_GET_BIT(v, b) (((v) >> (b)) & 1)
+
+/* Get major core revision. */
+#define VXD_MAJ_REV(props) (VXD_GET_BITS((props).core_rev, 23, 16, unsigned int))
+/* Get minor core revision. */
+#define VXD_MIN_REV(props) (VXD_GET_BITS((props).core_rev, 15, 8, unsigned int))
+/* Get maint core revision. */
+#define VXD_MAINT_REV(props) (VXD_GET_BITS((props).core_rev, 7, 0, unsigned int))
+/* Get number of entropy pipes available (HEVC). */
+#define VXD_NUM_ENT_PIPES(props) ((props).pvdec_core_id & 0xF)
+/* Get number of pixel pipes available (other standards). */
+#define VXD_NUM_PIX_PIPES(props) (((props).pvdec_core_id & 0xF0) >> 4)
+/* Get number of bits used by external memory interface. */
+#define VXD_EXTRN_ADDR_WIDTH(props) ((((props).mmu_config0 & 0xF0) >> 4) + 32)
+
+/* Check whether specific standard is supported by the pixel pipe. */
+#define VXD_HAS_MPEG2(props, pipe) VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 0)
+#define VXD_HAS_MPEG4(props, pipe) VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 1)
+#define VXD_HAS_H264(props, pipe) VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 2)
+#define VXD_HAS_VC1(props, pipe) VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 3)
+#define VXD_HAS_WMV9(props, pipe) VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 4)
+#define VXD_HAS_JPEG(props, pipe) VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 5)
+#define VXD_HAS_MPEG4_DATA_PART(props, pipe) \
+	VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 6)
+#define VXD_HAS_AVS(props, pipe) VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 7)
+#define VXD_HAS_REAL(props, pipe) VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 8)
+#define VXD_HAS_VP6(props, pipe) VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 9)
+#define VXD_HAS_VP8(props, pipe) VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 10)
+#define VXD_HAS_SORENSON(props, pipe) \
+	VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 11)
+#define VXD_HAS_HEVC(props, pipe) VXD_GET_BIT(props.pixel_pipe_cfg[pipe], 22)
+
+/* Check whether specific feature is supported by the pixel pipe */
+
+/*
+ * Max picture size for HEVC still picture profile is 64k wide and/or 64k
+ * high.
+ */
+#define VXD_HAS_HEVC_64K_STILL(props, pipe) \
+	(VXD_GET_BIT((props).pixel_misc_cfg[pipe], 24))
+
+/* Pixel processing pipe index. */
+#define VXD_PIX_PIPE_ID(props, pipe) \
+	(VXD_GET_BITS((props).pixel_misc_cfg[pipe], 18, 16, unsigned int))
+
+/* Number of stream supported by the pixel pipe DMAC and shift register. */
+#define VXD_PIX_NUM_STRS(props, pipe) \
+	(VXD_GET_BITS((props).pixel_misc_cfg[pipe], 13, 12, unsigned int) + 1)
+
+/* Is scaling supported. */
+#define VXD_HAS_SCALING(props, pipe) \
+	(VXD_GET_BIT((props).pixel_misc_cfg[pipe], 9))
+
+/* Is rotation supported. */
+#define VXD_HAS_ROTATION(props, pipe) \
+	(VXD_GET_BIT((props).pixel_misc_cfg[pipe], 8))
+
+/* Are HEVC range extensions supported. */
+#define VXD_HAS_HEVC_REXT(props, pipe) \
+	(VXD_GET_BIT((props).pixel_misc_cfg[pipe], 7))
+
+/* Maximum bit depth supported by the pipe. */
+#define VXD_MAX_BIT_DEPTH(props, pipe) \
+	(VXD_GET_BITS((props).pixel_misc_cfg[pipe], 6, 4, unsigned int) + 8)
+
+/*
+ * Maximum chroma fomar supported by the pipe in HEVC mode.
+ * 0x1 - 4:2:0
+ * 0x2 - 4:2:2
+ * 0x3 - 4:4:4
+ */
+#define VXD_MAX_HEVC_CHROMA_FMT(props, pipe) \
+	(VXD_GET_BITS((props).pixel_misc_cfg[pipe], 3, 2, unsigned int))
+
+/*
+ * Maximum chroma format supported by the pipe in H264 mode.
+ * 0x1 - 4:2:0
+ * 0x2 - 4:2:2
+ * 0x3 - 4:4:4
+ */
+#define VXD_MAX_H264_CHROMA_FMT(props, pipe) \
+	(VXD_GET_BITS((props).pixel_misc_cfg[pipe], 1, 0, unsigned int))
+
+/*
+ * Maximum frame width and height supported in MSVDX pipeline.
+ */
+#define VXD_MAX_WIDTH_MSVDX(props) \
+	(2 << (VXD_GET_BITS((props).pixel_max_frame_cfg, 4, 0, unsigned int)))
+#define VXD_MAX_HEIGHT_MSVDX(props) \
+	(2 << (VXD_GET_BITS((props).pixel_max_frame_cfg, 12, 8, unsigned int)))
+
+/*
+ * Maximum frame width and height supported in PVDEC pipeline.
+ */
+#define VXD_MAX_WIDTH_PVDEC(props) \
+	(2 << (VXD_GET_BITS((props).pixel_max_frame_cfg, 20, 16, unsigned int)))
+#define VXD_MAX_HEIGHT_PVDEC(props) \
+	(2 << (VXD_GET_BITS((props).pixel_max_frame_cfg, 28, 24, unsigned int)))
+
+#define PVDEC_COMMS_RAM_OFFSET      0x00002000
+#define PVDEC_COMMS_RAM_SIZE        0x00001000
+#define PVDEC_ENTROPY_OFFSET        0x00003000
+#define PVDEC_ENTROPY_SIZE          0x1FF
+#define PVDEC_VEC_BE_OFFSET         0x00005000
+#define PVDEC_VEC_BE_SIZE           0x3FF
+#define PVDEC_VEC_BE_CODEC_OFFSET   0x00005400
+#define MSVDX_VEC_OFFSET            0x00006000
+#define MSVDX_VEC_SIZE              0x7FF
+#define MSVDX_CMD_OFFSET            0x00007000
+
+/*
+ * Virtual memory heap address ranges for tiled
+ * and non-tiled buffers. Addresses within each
+ * range should be assigned to the appropriate
+ * buffers by the UM driver and mapped into the
+ * device using the corresponding KM driver ioctl.
+ */
+#define PVDEC_HEAP_UNTILED_START    0x00400000ul
+#define PVDEC_HEAP_UNTILED_SIZE     0x3FC00000ul
+#define PVDEC_HEAP_TILE512_START    0x40000000ul
+#define PVDEC_HEAP_TILE512_SIZE     0x10000000ul
+#define PVDEC_HEAP_TILE1024_START   0x50000000ul
+#define PVDEC_HEAP_TILE1024_SIZE    0x20000000ul
+#define PVDEC_HEAP_TILE2048_START   0x70000000ul
+#define PVDEC_HEAP_TILE2048_SIZE    0x30000000ul
+#define PVDEC_HEAP_TILE4096_START   0xA0000000ul
+#define PVDEC_HEAP_TILE4096_SIZE    0x30000000ul
+#define PVDEC_HEAP_BITSTREAM_START  0xD2000000ul
+#define PVDEC_HEAP_BITSTREAM_SIZE   0x0A000000ul
+#define PVDEC_HEAP_STREAM_START     0xE4000000ul
+#define PVDEC_HEAP_STREAM_SIZE      0x1C000000ul
+
+/*
+ * Max size of the message payload, in bytes. There are 7 bits used to encode
+ * the message size in the firmware interface.
+ */
+#define VXD_MAX_PAYLOAD_SIZE (127 * sizeof(unsigned int))
+/* Max size of the input message in bytes. */
+#define VXD_MAX_INPUT_SIZE (VXD_MAX_PAYLOAD_SIZE + sizeof(struct vxd_fw_msg))
+/*
+ * Min size of the input message. Two words needed for message header and
+ * stream PTD
+ */
+#define VXD_MIN_INPUT_SIZE 2
+/*
+ * Offset of the stream PTD within message. This word has to be left null in
+ * submitted message, driver will fill it in with an appropriate value.
+ */
+#define VXD_PTD_MSG_OFFSET 1
+
+/* Read flags */
+#define VXD_FW_MSG_RD_FLAGS_MASK 0xffff
+/* Driver watchdog interrupted processing of the message. */
+#define VXD_FW_MSG_FLAG_DWR 0x1
+/* VXD MMU fault occurred when the message was processed. */
+#define VXD_FW_MSG_FLAG_MMU_FAULT 0x2
+/* Invalid input message, e.g. the message was too large. */
+#define VXD_FW_MSG_FLAG_INV 0x4
+/* I/O error occurred when the message was processed. */
+#define VXD_FW_MSG_FLAG_DEV_ERR 0x8
+/*
+ * Driver error occurred when the message was processed, e.g. failed to
+ * allocate memory.
+ */
+#define VXD_FW_MSG_FLAG_DRV_ERR 0x10
+/*
+ * Item was canceled, without being fully processed
+ * i.e. corresponding stream was destroyed.
+ */
+#define VXD_FW_MSG_FLAG_CANCELED 0x20
+/* Firmware internal error occurred when the message was processed */
+#define VXD_FW_MSG_FLAG_FATAL 0x40
+
+/* Write flags */
+#define VXD_FW_MSG_WR_FLAGS_MASK 0xffff0000
+/* Indicates that message shall be dropped after sending it to the firmware. */
+#define VXD_FW_MSG_FLAG_DROP 0x10000
+/*
+ * Indicates that message shall be exclusively handled by
+ * the firmware/hardware. Any other pending messages are
+ * blocked until such message is handled.
+ */
+#define VXD_FW_MSG_FLAG_EXCL 0x20000
+
+#define VXD_MSG_SIZE(msg) (sizeof(struct vxd_fw_msg) + ((msg).payload_size))
+
+/* Header included at the beginning of firmware binary */
+struct vxd_fw_hdr {
+	unsigned int core_size;
+	unsigned int blob_size;
+	unsigned int firmware_id;
+	unsigned int timestamp;
+};
+
+/*
+ * struct vxd_dev_fw - Core component will allocate a buffer for firmware.
+ *                     This structure holds the information about the firmware
+ *                     binary.
+ * @buf_id: The buffer id allocation
+ * @hdr: firmware header information
+ * @fw_size: The size of the fw. Set after successful firmware request.
+ */
+struct vxd_dev_fw {
+	int buf_id;
+	struct vxd_fw_hdr *hdr;
+	unsigned int fw_size;
+	unsigned char ready;
+};
+
+/*
+ * struct vxd_core_props - contains HW core properties
+ * @core_rev: Core revision based on register CR_PVDEC_CORE_REV
+ * @pvdec_core_id: PVDEC Core id based on register CR_PVDEC_CORE_ID
+ * @mmu_config0: MMU configuration 0 based on register MMU_CONFIG0
+ * @mmu_config1: MMU configuration 1 based on register MMU_CONFIG1
+ * @mtx_ram_size: size of the MTX RAM based on register CR_PROC_DEBUG
+ * @pixel_max_frame_cfg: indicates the max frame height and width for
+ *                       PVDEC pipeline and MSVDX pipeline based on register
+ *                       MAX_FRAME_CONFIG
+ * @pixel_pipe_cfg: pipe configuration which codecs are supported in a
+ *                  Pixel Processing Pipe, based on register
+ *                  PIXEL_PIPE_CONFIG
+ * @pixel_misc_cfg: Additional pipe configuration eg. supported scaling
+ *                  or rotation, based on register PIXEL_MISC_CONFIG
+ * @dbg_fifo_size: contains the depth of the Debug FIFO, based on
+ *                 register CR_PROC_DEBUG_FIFO_SIZE
+ */
+struct vxd_core_props {
+	unsigned int core_rev;
+	unsigned int pvdec_core_id;
+	unsigned int mmu_config0;
+	unsigned int mmu_config1;
+	unsigned int mtx_ram_size;
+	unsigned int pixel_max_frame_cfg;
+	unsigned int pixel_pipe_cfg[VXD_MAX_PIPES];
+	unsigned int pixel_misc_cfg[VXD_MAX_PIPES];
+	unsigned int dbg_fifo_size;
+};
+
+struct vxd_alloc_data {
+	unsigned int heap_id;       /* [IN] Heap ID of allocator                */
+	unsigned int size;          /* [IN] Size of device memory (in bytes)    */
+	unsigned int attributes;    /* [IN] Attributes of buffer */
+	unsigned int buf_id;        /* [OUT] Generated buffer ID                */
+};
+
+struct vxd_free_data {
+	unsigned int buf_id;        /* [IN] ID of device buffer to free */
+};
+#endif /* _IMG_DEC_COMMON_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_cmds.h b/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_cmds.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_cmds.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_cmds.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,279 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG MSVDX core Registers
+ * This file contains the MSVDX_CORE_REGS_H Definitions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _IMG_MSVDX_CMDS_H
+#define _IMG_MSVDX_CMDS_H
+
+#define MSVDX_CMDS_HORIZONTAL_LUMA_COEFFICIENTS_OFFSET          (0x0060)
+#define MSVDX_CMDS_VERTICAL_LUMA_COEFFICIENTS_OFFSET            (0x0070)
+/**
+ * MSVDX_CMDS_HORIZONTAL_CHROMA_COEFFICIENTS_OFFSET -
+ *		MSVDX_CMDS, VERTICAL_LUMA_COEFFICIENTS, VER_LUMA_COEFF_0
+ */
+#define MSVDX_CMDS_HORIZONTAL_CHROMA_COEFFICIENTS_OFFSET                (0x0080)
+/* MSVDX_CMDS, HORIZONTAL_CHROMA_COEFFICIENTS, HOR_CHROMA_COEFF_0 */
+#define MSVDX_CMDS_VERTICAL_CHROMA_COEFFICIENTS_OFFSET          (0x0090)
+/* MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_HEIGHT */
+#define MSVDX_CMDS_DISPLAY_PICTURE_SIZE_DISPLAY_PICTURE_HEIGHT_LSBMASK          (0x00000FFF)
+#define MSVDX_CMDS_DISPLAY_PICTURE_SIZE_DISPLAY_PICTURE_HEIGHT_SHIFT            (12)
+/* MSVDX_CMDS, DISPLAY_PICTURE_SIZE, DISPLAY_PICTURE_WIDTH */
+#define MSVDX_CMDS_DISPLAY_PICTURE_SIZE_DISPLAY_PICTURE_WIDTH_LSBMASK           (0x00000FFF)
+#define MSVDX_CMDS_DISPLAY_PICTURE_SIZE_DISPLAY_PICTURE_WIDTH_SHIFT             (0)
+#define MSVDX_CMDS_PVDEC_DISPLAY_PICTURE_SIZE_OFFSET            (0x00B0)
+#define MSVDX_CMDS_PVDEC_DISPLAY_PICTURE_SIZE_PVDEC_DISPLAY_PICTURE_HEIGHT_MIN1_LSBMASK \
+											(0x0000FFFF)
+#define MSVDX_CMDS_PVDEC_DISPLAY_PICTURE_SIZE_PVDEC_DISPLAY_PICTURE_HEIGHT_MIN1_SHIFT           (16)
+/* MSVDX_CMDS, PVDEC_DISPLAY_PICTURE_SIZE, PVDEC_DISPLAY_PICTURE_WIDTH_MIN1 */
+#define MSVDX_CMDS_PVDEC_DISPLAY_PICTURE_SIZE_PVDEC_DISPLAY_PICTURE_WIDTH_MIN1_LSBMASK \
+											(0x0000FFFF)
+#define MSVDX_CMDS_PVDEC_DISPLAY_PICTURE_SIZE_PVDEC_DISPLAY_PICTURE_WIDTH_MIN1_SHIFT            (0)
+/* MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_HEIGHT */
+#define MSVDX_CMDS_CODED_PICTURE_SIZE_CODED_PICTURE_HEIGHT_LSBMASK              (0x00000FFF)
+#define MSVDX_CMDS_CODED_PICTURE_SIZE_CODED_PICTURE_HEIGHT_SHIFT                (12)
+/* MSVDX_CMDS, CODED_PICTURE_SIZE, CODED_PICTURE_WIDTH */
+#define MSVDX_CMDS_CODED_PICTURE_SIZE_CODED_PICTURE_WIDTH_LSBMASK               (0x00000FFF)
+#define MSVDX_CMDS_CODED_PICTURE_SIZE_CODED_PICTURE_WIDTH_SHIFT         (0)
+#define MSVDX_CMDS_PVDEC_CODED_PICTURE_SIZE_OFFSET              (0x00B4)
+/* MSVDX_CMDS, OPERATING_MODE, USE_EXT_ROW_STRIDE */
+#define MSVDX_CMDS_OPERATING_MODE_USE_EXT_ROW_STRIDE_MASK               (0x10000000)
+#define MSVDX_CMDS_OPERATING_MODE_USE_EXT_ROW_STRIDE_LSBMASK            (0x00000001)
+#define MSVDX_CMDS_OPERATING_MODE_USE_EXT_ROW_STRIDE_SHIFT              (28)
+/* MSVDX_CMDS, OPERATING_MODE, CHROMA_INTERLEAVED */
+#define MSVDX_CMDS_OPERATING_MODE_CHROMA_INTERLEAVED_MASK               (0x08000000)
+#define MSVDX_CMDS_OPERATING_MODE_CHROMA_INTERLEAVED_LSBMASK            (0x00000001)
+#define MSVDX_CMDS_OPERATING_MODE_CHROMA_INTERLEAVED_SHIFT              (27)
+/* MSVDX_CMDS, OPERATING_MODE, ROW_STRIDE */
+#define MSVDX_CMDS_OPERATING_MODE_ROW_STRIDE_MASK               (0x07000000)
+#define MSVDX_CMDS_OPERATING_MODE_ROW_STRIDE_LSBMASK            (0x00000007)
+#define MSVDX_CMDS_OPERATING_MODE_ROW_STRIDE_SHIFT              (24)
+/* MSVDX_CMDS, OPERATING_MODE, CODEC_PROFILE */
+#define MSVDX_CMDS_OPERATING_MODE_CODEC_PROFILE_MASK            (0x00300000)
+#define MSVDX_CMDS_OPERATING_MODE_CODEC_PROFILE_LSBMASK         (0x00000003)
+#define MSVDX_CMDS_OPERATING_MODE_CODEC_PROFILE_SHIFT           (20)
+/* MSVDX_CMDS, OPERATING_MODE, CODEC_MODE */
+#define MSVDX_CMDS_OPERATING_MODE_CODEC_MODE_MASK               (0x000F0000)
+#define MSVDX_CMDS_OPERATING_MODE_CODEC_MODE_LSBMASK            (0x0000000F)
+#define MSVDX_CMDS_OPERATING_MODE_CODEC_MODE_SHIFT              (16)
+/* MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE */
+#define MSVDX_CMDS_OPERATING_MODE_ASYNC_MODE_MASK               (0x00006000)
+#define MSVDX_CMDS_OPERATING_MODE_ASYNC_MODE_LSBMASK            (0x00000003)
+#define MSVDX_CMDS_OPERATING_MODE_ASYNC_MODE_SHIFT              (13)
+/* MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT */
+#define MSVDX_CMDS_OPERATING_MODE_CHROMA_FORMAT_MASK            (0x00001000)
+#define MSVDX_CMDS_OPERATING_MODE_CHROMA_FORMAT_LSBMASK         (0x00000001)
+#define MSVDX_CMDS_OPERATING_MODE_CHROMA_FORMAT_SHIFT           (12)
+/* MSVDX_CMDS, OPERATING_MODE, PIC_QUANT */
+#define MSVDX_CMDS_PVDEC_OPERATING_MODE_OFFSET          (0x00A0)
+/* MSVDX_CMDS, EXT_OP_MODE, BIT_DEPTH_CHROMA_MINUS8 */
+#define MSVDX_CMDS_EXT_OP_MODE_BIT_DEPTH_CHROMA_MINUS8_MASK             (0x00003000)
+#define MSVDX_CMDS_EXT_OP_MODE_BIT_DEPTH_CHROMA_MINUS8_LSBMASK          (0x00000003)
+#define MSVDX_CMDS_EXT_OP_MODE_BIT_DEPTH_CHROMA_MINUS8_SHIFT            (12)
+/* MSVDX_CMDS, EXT_OP_MODE, BIT_DEPTH_LUMA_MINUS8 */
+#define MSVDX_CMDS_EXT_OP_MODE_BIT_DEPTH_LUMA_MINUS8_MASK               (0x00000300)
+#define MSVDX_CMDS_EXT_OP_MODE_BIT_DEPTH_LUMA_MINUS8_LSBMASK            (0x00000003)
+#define MSVDX_CMDS_EXT_OP_MODE_BIT_DEPTH_LUMA_MINUS8_SHIFT              (8)
+/* MSVDX_CMDS, EXT_OP_MODE, MEMORY_PACKING */
+#define MSVDX_CMDS_EXT_OP_MODE_MEMORY_PACKING_MASK              (0x00000008)
+#define MSVDX_CMDS_EXT_OP_MODE_MEMORY_PACKING_LSBMASK           (0x00000001)
+#define MSVDX_CMDS_EXT_OP_MODE_MEMORY_PACKING_SHIFT             (3)
+/* MSVDX_CMDS, EXT_OP_MODE, CHROMA_FORMAT_IDC */
+#define MSVDX_CMDS_EXT_OP_MODE_CHROMA_FORMAT_IDC_MASK           (0x00000003)
+#define MSVDX_CMDS_EXT_OP_MODE_CHROMA_FORMAT_IDC_LSBMASK                (0x00000003)
+#define MSVDX_CMDS_EXT_OP_MODE_CHROMA_FORMAT_IDC_SHIFT          (0)
+#define MSVDX_CMDS_LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES_OFFSET             (0x000C)
+/*
+ * MSVDX_CMDS, LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES,
+ * LUMA_RECON_BASE_ADDR
+ */
+#define MSVDX_CMDS_CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES_OFFSET           (0x0010)
+///* MSVDX_CMDS, AUX_MSB_BUFFER_BASE_ADDRESSES, AUX_MSB_BUFFER_BASE_ADDR */
+#define MSVDX_CMDS_INTRA_BUFFER_BASE_ADDRESS_OFFSET             (0x0018)
+/* MSVDX_CMDS, INTRA_BUFFER_BASE_ADDRESS, INTRA_BASE_ADDR */
+
+#define MSVDX_CMDS_MC_CACHE_CONFIGURATION_OFFSET                (0x001C)
+
+/* MSVDX_CMDS, MC_CACHE_CONFIGURATION, CONFIG_REF_CHROMA_ADJUST */
+#define MSVDX_CMDS_MC_CACHE_CONFIGURATION_CONFIG_REF_CHROMA_ADJUST_MASK         (0x01000000)
+#define MSVDX_CMDS_MC_CACHE_CONFIGURATION_CONFIG_REF_CHROMA_ADJUST_LSBMASK              (0x00000001)
+#define MSVDX_CMDS_MC_CACHE_CONFIGURATION_CONFIG_REF_CHROMA_ADJUST_SHIFT                (24)
+/* MSVDX_CMDS, MC_CACHE_CONFIGURATION, CONFIG_REF_OFFSET */
+#define MSVDX_CMDS_MC_CACHE_CONFIGURATION_CONFIG_REF_OFFSET_MASK                (0x00FFF000)
+#define MSVDX_CMDS_MC_CACHE_CONFIGURATION_CONFIG_REF_OFFSET_LSBMASK             (0x00000FFF)
+#define MSVDX_CMDS_MC_CACHE_CONFIGURATION_CONFIG_REF_OFFSET_SHIFT               (12)
+/* MSVDX_CMDS, MC_CACHE_CONFIGURATION, CONFIG_ROW_OFFSET */
+#define MSVDX_CMDS_MC_CACHE_CONFIGURATION_CONFIG_ROW_OFFSET_MASK                (0x0000003F)
+#define MSVDX_CMDS_MC_CACHE_CONFIGURATION_CONFIG_ROW_OFFSET_LSBMASK             (0x0000003F)
+#define MSVDX_CMDS_MC_CACHE_CONFIGURATION_CONFIG_ROW_OFFSET_SHIFT               (0)
+/* MSVDX_CMDS, H264_WEIGHTED_FACTOR_DENOMINATOR, Y_LOG2_WEIGHT_DENOM */
+#define MSVDX_CMDS_VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS_OFFSET           (0x0028)
+/* MSVDX_CMDS, VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS, LUMA_RANGE_BASE_ADDR */
+#define MSVDX_CMDS_VC1_CHROMA_RANGE_MAPPING_BASE_ADDRESS_OFFSET         (0x002C)
+/* MSVDX_CMDS, VC1_RANGE_MAPPING_FLAGS, LUMA_RANGE_MAP */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_OFFSET           (0x003C)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, EXT_ROT_ROW_STRIDE */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_EXT_ROT_ROW_STRIDE_MASK          (0xFFC00000)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_EXT_ROT_ROW_STRIDE_LSBMASK \
+									(0x000003FF)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_EXT_ROT_ROW_STRIDE_SHIFT         (22)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, PACKED_422_OUTPUT */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_PACKED_422_OUTPUT_MASK           (0x00000800)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_PACKED_422_OUTPUT_LSBMASK \
+									(0x00000001)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_PACKED_422_OUTPUT_SHIFT          (11)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, USE_AUX_LINE_BUF */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_USE_AUX_LINE_BUF_MASK            (0x00000400)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_USE_AUX_LINE_BUF_LSBMASK         (0x00000001)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_USE_AUX_LINE_BUF_SHIFT           (10)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, SCALE_INPUT_SIZE_SEL */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_SCALE_INPUT_SIZE_SEL_MASK \
+									(0x00000200)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_SCALE_INPUT_SIZE_SEL_LSBMASK \
+									(0x00000001)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_SCALE_INPUT_SIZE_SEL_SHIFT               (9)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, USE_EXT_ROT_ROW_STRIDE */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_USE_EXT_ROT_ROW_STRIDE_MASK \
+									(0x00000100)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_USE_EXT_ROT_ROW_STRIDE_LSBMASK \
+									(0x00000001)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_USE_EXT_ROT_ROW_STRIDE_SHIFT             (8)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, ROTATION_ROW_STRIDE */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_ROTATION_ROW_STRIDE_MASK         (0x00000070)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_ROTATION_ROW_STRIDE_LSBMASK \
+									(0x00000007)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_ROTATION_ROW_STRIDE_SHIFT                (4)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION, ROTATION_MODE */
+#define MSVDX_CMDS_EXTENDED_ROW_STRIDE_OFFSET           (0x0040)
+
+/* MSVDX_CMDS, EXTENDED_ROW_STRIDE, EXT_ROW_STRIDE */
+#define MSVDX_CMDS_EXTENDED_ROW_STRIDE_EXT_ROW_STRIDE_MASK              (0x0003FFC0)
+#define MSVDX_CMDS_EXTENDED_ROW_STRIDE_EXT_ROW_STRIDE_LSBMASK           (0x00000FFF)
+#define MSVDX_CMDS_EXTENDED_ROW_STRIDE_EXT_ROW_STRIDE_SHIFT             (6)
+/* MSVDX_CMDS, EXTENDED_ROW_STRIDE, REF_PIC_MMU_TILED */
+#define MSVDX_CMDS_CHROMA_ROW_STRIDE_OFFSET             (0x01AC)
+/* MSVDX_CMDS, CHROMA_ROW_STRIDE, ALT_CHROMA_ROW_STRIDE */
+#define MSVDX_CMDS_CHROMA_ROW_STRIDE_ALT_CHROMA_ROW_STRIDE_MASK         (0xFFC00000)
+#define MSVDX_CMDS_CHROMA_ROW_STRIDE_ALT_CHROMA_ROW_STRIDE_LSBMASK              (0x000003FF)
+#define MSVDX_CMDS_CHROMA_ROW_STRIDE_ALT_CHROMA_ROW_STRIDE_SHIFT                (22)
+/* MSVDX_CMDS, CHROMA_ROW_STRIDE, CHROMA_ROW_STRIDE */
+#define MSVDX_CMDS_CHROMA_ROW_STRIDE_CHROMA_ROW_STRIDE_MASK             (0x0003FFC0)
+#define MSVDX_CMDS_CHROMA_ROW_STRIDE_CHROMA_ROW_STRIDE_LSBMASK          (0x00000FFF)
+#define MSVDX_CMDS_CHROMA_ROW_STRIDE_CHROMA_ROW_STRIDE_SHIFT            (6)
+/* MSVDX_CMDS, RPR_PICTURE_SIZE, RPR_PICTURE_WIDTH */
+#define MSVDX_CMDS_SCALED_DISPLAY_SIZE_OFFSET           (0x0050)
+/* MSVDX_CMDS, SCALED_DISPLAY_SIZE, SCALE_DISPLAY_HEIGHT */
+#define MSVDX_CMDS_SCALED_DISPLAY_SIZE_SCALE_DISPLAY_HEIGHT_MASK                (0x00FFF000)
+#define MSVDX_CMDS_SCALED_DISPLAY_SIZE_SCALE_DISPLAY_HEIGHT_LSBMASK             (0x00000FFF)
+#define MSVDX_CMDS_SCALED_DISPLAY_SIZE_SCALE_DISPLAY_HEIGHT_SHIFT               (12)
+/* MSVDX_CMDS, SCALED_DISPLAY_SIZE, SCALE_DISPLAY_WIDTH */
+#define MSVDX_CMDS_SCALED_DISPLAY_SIZE_SCALE_DISPLAY_WIDTH_MASK         (0x00000FFF)
+#define MSVDX_CMDS_SCALED_DISPLAY_SIZE_SCALE_DISPLAY_WIDTH_LSBMASK              (0x00000FFF)
+#define MSVDX_CMDS_SCALED_DISPLAY_SIZE_SCALE_DISPLAY_WIDTH_SHIFT                (0)
+#define MSVDX_CMDS_PVDEC_SCALED_DISPLAY_SIZE_OFFSET             (0x00B8)
+/* MSVDX_CMDS, PVDEC_SCALED_DISPLAY_SIZE, PVDEC_SCALE_DISPLAY_HEIGHT */
+#define MSVDX_CMDS_PVDEC_SCALED_DISPLAY_SIZE_PVDEC_SCALE_DISPLAY_HEIGHT_MASK            (0xFFFF0000)
+#define MSVDX_CMDS_PVDEC_SCALED_DISPLAY_SIZE_PVDEC_SCALE_DISPLAY_HEIGHT_LSBMASK         (0x0000FFFF)
+#define MSVDX_CMDS_PVDEC_SCALED_DISPLAY_SIZE_PVDEC_SCALE_DISPLAY_HEIGHT_SHIFT           (16)
+/* MSVDX_CMDS, PVDEC_SCALED_DISPLAY_SIZE, PVDEC_SCALE_DISPLAY_WIDTH */
+#define MSVDX_CMDS_PVDEC_SCALED_DISPLAY_SIZE_PVDEC_SCALE_DISPLAY_WIDTH_MASK             (0x0000FFFF)
+#define MSVDX_CMDS_PVDEC_SCALED_DISPLAY_SIZE_PVDEC_SCALE_DISPLAY_WIDTH_LSBMASK          (0x0000FFFF)
+#define MSVDX_CMDS_PVDEC_SCALED_DISPLAY_SIZE_PVDEC_SCALE_DISPLAY_WIDTH_SHIFT            (0)
+#define MSVDX_CMDS_HORIZONTAL_SCALE_CONTROL_OFFSET              (0x0054)
+/* MSVDX_CMDS, HORIZONTAL_SCALE_CONTROL, HORIZONTAL_INITIAL_POS */
+#define MSVDX_CMDS_HORIZONTAL_SCALE_CONTROL_HORIZONTAL_INITIAL_POS_MASK         (0xFFFF0000)
+#define MSVDX_CMDS_HORIZONTAL_SCALE_CONTROL_HORIZONTAL_INITIAL_POS_LSBMASK              (0x0000FFFF)
+#define MSVDX_CMDS_HORIZONTAL_SCALE_CONTROL_HORIZONTAL_INITIAL_POS_SHIFT                (16)
+/* MSVDX_CMDS, HORIZONTAL_SCALE_CONTROL, HORIZONTAL_SCALE_PITCH */
+#define MSVDX_CMDS_HORIZONTAL_SCALE_CONTROL_HORIZONTAL_SCALE_PITCH_MASK         (0x0000FFFF)
+#define MSVDX_CMDS_HORIZONTAL_SCALE_CONTROL_HORIZONTAL_SCALE_PITCH_LSBMASK              (0x0000FFFF)
+#define MSVDX_CMDS_HORIZONTAL_SCALE_CONTROL_HORIZONTAL_SCALE_PITCH_SHIFT                (0)
+#define MSVDX_CMDS_VERTICAL_SCALE_CONTROL_OFFSET                (0x0058)
+/* MSVDX_CMDS, VERTICAL_SCALE_CONTROL, VERTICAL_INITIAL_POS */
+#define MSVDX_CMDS_VERTICAL_SCALE_CONTROL_VERTICAL_INITIAL_POS_MASK             (0xFFFF0000)
+#define MSVDX_CMDS_VERTICAL_SCALE_CONTROL_VERTICAL_INITIAL_POS_LSBMASK          (0x0000FFFF)
+#define MSVDX_CMDS_VERTICAL_SCALE_CONTROL_VERTICAL_INITIAL_POS_SHIFT            (16)
+/* MSVDX_CMDS, VERTICAL_SCALE_CONTROL, VERTICAL_SCALE_PITCH */
+#define MSVDX_CMDS_VERTICAL_SCALE_CONTROL_VERTICAL_SCALE_PITCH_MASK             (0x0000FFFF)
+#define MSVDX_CMDS_VERTICAL_SCALE_CONTROL_VERTICAL_SCALE_PITCH_LSBMASK          (0x0000FFFF)
+#define MSVDX_CMDS_VERTICAL_SCALE_CONTROL_VERTICAL_SCALE_PITCH_SHIFT            (0)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_OFFSET            (0x01B4)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, ALT_BIT_DEPTH_CHROMA_MINUS8 */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_ALT_BIT_DEPTH_CHROMA_MINUS8_MASK          (0x00007000)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_ALT_BIT_DEPTH_CHROMA_MINUS8_LSBMASK \
+									(0x00000007)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_ALT_BIT_DEPTH_CHROMA_MINUS8_SHIFT         (12)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, ALT_BIT_DEPTH_LUMA_MINUS8 */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_ALT_BIT_DEPTH_LUMA_MINUS8_MASK            (0x00000700)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_ALT_BIT_DEPTH_LUMA_MINUS8_LSBMASK         (0x00000007)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_ALT_BIT_DEPTH_LUMA_MINUS8_SHIFT           (8)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, SCALE_LUMA_BIFILTER_HORIZ */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_LUMA_BIFILTER_HORIZ_MASK            (0x00000080)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_LUMA_BIFILTER_HORIZ_LSBMASK         (0x00000001)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_LUMA_BIFILTER_HORIZ_SHIFT           (7)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, SCALE_LUMA_BIFILTER_VERT */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_LUMA_BIFILTER_VERT_MASK             (0x00000040)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_LUMA_BIFILTER_VERT_LSBMASK          (0x00000001)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_LUMA_BIFILTER_VERT_SHIFT            (6)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, SCALE_CHROMA_BIFILTER_HORIZ */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_CHROMA_BIFILTER_HORIZ_MASK          (0x00000020)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_CHROMA_BIFILTER_HORIZ_LSBMASK \
+									(0x00000001)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_CHROMA_BIFILTER_HORIZ_SHIFT         (5)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, SCALE_CHROMA_BIFILTER_VERT */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_CHROMA_BIFILTER_VERT_MASK           (0x00000010)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_CHROMA_BIFILTER_VERT_LSBMASK \
+									(0x00000001)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_CHROMA_BIFILTER_VERT_SHIFT          (4)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, ALT_MEMORY_PACKING */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_ALT_MEMORY_PACKING_MASK           (0x00000008)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_ALT_MEMORY_PACKING_LSBMASK                (0x00000001)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_ALT_MEMORY_PACKING_SHIFT          (3)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, SCALE_CHROMA_RESAMP_ONLY */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_CHROMA_RESAMP_ONLY_MASK             (0x00000004)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_CHROMA_RESAMP_ONLY_LSBMASK          (0x00000001)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_SCALE_CHROMA_RESAMP_ONLY_SHIFT            (2)
+/* MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, ALT_OUTPUT_FORMAT */
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_ALT_OUTPUT_FORMAT_MASK            (0x00000003)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_ALT_OUTPUT_FORMAT_LSBMASK         (0x00000003)
+#define MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_ALT_OUTPUT_FORMAT_SHIFT           (0)
+#define MSVDX_CMDS_SCALE_OUTPUT_SIZE_OFFSET             (0x01B8)
+/* MSVDX_CMDS, SCALE_OUTPUT_SIZE, SCALE_OUTPUT_HEIGHT_MIN1 */
+#define MSVDX_CMDS_SCALE_OUTPUT_SIZE_SCALE_OUTPUT_HEIGHT_MIN1_MASK              (0xFFFF0000)
+#define MSVDX_CMDS_SCALE_OUTPUT_SIZE_SCALE_OUTPUT_HEIGHT_MIN1_LSBMASK           (0x0000FFFF)
+#define MSVDX_CMDS_SCALE_OUTPUT_SIZE_SCALE_OUTPUT_HEIGHT_MIN1_SHIFT             (16)
+/* MSVDX_CMDS, SCALE_OUTPUT_SIZE, SCALE_OUTPUT_WIDTH_MIN1 */
+#define MSVDX_CMDS_SCALE_OUTPUT_SIZE_SCALE_OUTPUT_WIDTH_MIN1_MASK               (0x0000FFFF)
+#define MSVDX_CMDS_SCALE_OUTPUT_SIZE_SCALE_OUTPUT_WIDTH_MIN1_LSBMASK            (0x0000FFFF)
+#define MSVDX_CMDS_SCALE_OUTPUT_SIZE_SCALE_OUTPUT_WIDTH_MIN1_SHIFT              (0)
+#define MSVDX_CMDS_SCALE_HORIZONTAL_CHROMA_OFFSET               (0x01BC)
+/* MSVDX_CMDS, SCALE_HORIZONTAL_CHROMA, CHROMA_HORIZONTAL_INITIAL */
+#define MSVDX_CMDS_SCALE_HORIZONTAL_CHROMA_CHROMA_HORIZONTAL_INITIAL_MASK               (0xFFFF0000)
+#define MSVDX_CMDS_SCALE_HORIZONTAL_CHROMA_CHROMA_HORIZONTAL_INITIAL_LSBMASK            (0x0000FFFF)
+#define MSVDX_CMDS_SCALE_HORIZONTAL_CHROMA_CHROMA_HORIZONTAL_INITIAL_SHIFT              (16)
+#define MSVDX_CMDS_SCALE_HORIZONTAL_CHROMA_CHROMA_HORIZONTAL_PITCH_MASK         (0x0000FFFF)
+#define MSVDX_CMDS_SCALE_HORIZONTAL_CHROMA_CHROMA_HORIZONTAL_PITCH_LSBMASK              (0x0000FFFF)
+#define MSVDX_CMDS_SCALE_HORIZONTAL_CHROMA_CHROMA_HORIZONTAL_PITCH_SHIFT                (0)
+#define MSVDX_CMDS_SCALE_VERTICAL_CHROMA_OFFSET         (0x01C0)
+/* MSVDX_CMDS, SCALE_VERTICAL_CHROMA, CHROMA_VERTICAL_INITIAL */
+#define MSVDX_CMDS_SCALE_VERTICAL_CHROMA_CHROMA_VERTICAL_INITIAL_MASK           (0xFFFF0000)
+#define MSVDX_CMDS_SCALE_VERTICAL_CHROMA_CHROMA_VERTICAL_INITIAL_LSBMASK                (0x0000FFFF)
+#define MSVDX_CMDS_SCALE_VERTICAL_CHROMA_CHROMA_VERTICAL_INITIAL_SHIFT          (16)
+/* MSVDX_CMDS, SCALE_VERTICAL_CHROMA, CHROMA_VERTICAL_PITCH */
+#define MSVDX_CMDS_SCALE_VERTICAL_CHROMA_CHROMA_VERTICAL_PITCH_MASK             (0x0000FFFF)
+#define MSVDX_CMDS_SCALE_VERTICAL_CHROMA_CHROMA_VERTICAL_PITCH_LSBMASK          (0x0000FFFF)
+#define MSVDX_CMDS_SCALE_VERTICAL_CHROMA_CHROMA_VERTICAL_PITCH_SHIFT            (0)
+/* MSVDX_CMDS, MULTICORE_OPERATING_MODE, MBLK_ROW_OFFSET */
+#define MSVDX_CMDS_AUX_LINE_BUFFER_BASE_ADDRESS_OFFSET          (0x01EC)
+
+#endif /* _IMG_MSVDX_CMDS_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_core_regs.h b/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_core_regs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_core_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_core_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG MSVDX core Registers
+ * This file contains the MSVDX_CORE_REGS_H Definitions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _IMG_MSVDX_CORE_REGS_H
+#define _IMG_MSVDX_CORE_REGS_H
+
+#define MSVDX_CORE_CR_MMU_TILE_NO_ENTRIES               (4)
+#define MSVDX_CORE_CR_MMU_TILE_EXT_NO_ENTRIES           (4)
+
+#endif /* _IMG_MSVDX_CORE_REGS_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_vdmc_regs.h b/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_vdmc_regs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_vdmc_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_vdmc_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG MSVDX VDMC Registers
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _IMG_MSVDX_VDMC_REGS_H
+#define _IMG_MSVDX_VDMC_REGS_H
+
+/* MSVDX_VDMC, CR_VDMC_MACROBLOCK_NUMBER, CR_VDMC_MACROBLOCK_X_OFFSET */
+#define MSVDX_VDMC_CR_VDMC_MACROBLOCK_NUMBER_CR_VDMC_MACROBLOCK_X_OFFSET_MASK           (0x0000FFFF)
+#define MSVDX_VDMC_CR_VDMC_MACROBLOCK_NUMBER_CR_VDMC_MACROBLOCK_X_OFFSET_SHIFT          (0)
+
+/* MSVDX_VDMC, CR_VDMC_MACROBLOCK_NUMBER, CR_VDMC_MACROBLOCK_Y_OFFSET */
+#define MSVDX_VDMC_CR_VDMC_MACROBLOCK_NUMBER_CR_VDMC_MACROBLOCK_Y_OFFSET_MASK           (0xFFFF0000)
+#define MSVDX_VDMC_CR_VDMC_MACROBLOCK_NUMBER_CR_VDMC_MACROBLOCK_Y_OFFSET_SHIFT          (16)
+
+#endif /* _IMG_MSVDX_VDMC_REGS_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_vec_regs.h b/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_vec_regs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_vec_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/img_msvdx_vec_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG MSVDX VEC Registers
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#if !defined(__MSVDX_VEC_REGS_H__)
+#define __MSVDX_VEC_REGS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+	/* MSVDX_VEC, CR_VEC_VLR_COMMANDS_NUM, VLR_COMMANDS_STORE_NUMBER_OF_CMDS */
+#define MSVDX_VEC_CR_VEC_VLC_TABLE_ADDR0_OFFSET         (0x00EC)
+
+	/* MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0, VLC_TABLE_ADDR0 */
+#define MSVDX_VEC_CR_VEC_VLC_TABLE_ADDR0_VLC_TABLE_ADDR0_MASK           (0x000007FF)
+
+	/* MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR15, VLC_TABLE_ADDR31 */
+#define MSVDX_VEC_CR_VEC_VLC_TABLE_ADDR16_OFFSET                (0x01C0)
+
+	/* MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR15, VLC_TABLE_ADDR31 */
+#define MSVDX_VEC_CR_VEC_VLC_TABLE_ADDR16_OFFSET                (0x01C0)
+
+	/* MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR18, VLC_TABLE_ADDR37 */
+#define MSVDX_VEC_CR_VEC_VLC_TABLE_INITIAL_WIDTH0_OFFSET                (0x012C)
+
+	/* MSVDX_VEC, CR_VEC_VLC_TABLE_ADDR0, VLC_TABLE_ADDR1 */
+#define MSVDX_VEC_CR_VEC_VLC_TABLE_ADDR0_VLC_TABLE_ADDR1_SHIFT          (11)
+
+	/* MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH0 */
+#define MSVDX_VEC_CR_VEC_VLC_TABLE_INITIAL_WIDTH0_VLC_TABLE_INITIAL_WIDTH0_MASK         (0x00000007)
+
+	/* MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH0, VLC_TABLE_INITIAL_WIDTH1 */
+#define MSVDX_VEC_CR_VEC_VLC_TABLE_INITIAL_WIDTH0_VLC_TABLE_INITIAL_WIDTH1_SHIFT	(3)
+
+	/* MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE0 */
+#define MSVDX_VEC_CR_VEC_VLC_TABLE_INITIAL_OPCODE0_VLC_TABLE_INITIAL_OPCODE0_MASK \
+	(0x00000003)
+
+	/* MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_WIDTH3, VLC_TABLE_INITIAL_WIDTH37 */
+#define MSVDX_VEC_CR_VEC_VLC_TABLE_INITIAL_OPCODE0_OFFSET               (0x013C)
+
+	/* MSVDX_VEC, CR_VEC_VLC_TABLE_INITIAL_OPCODE0, VLC_TABLE_INITIAL_OPCODE1 */
+#define MSVDX_VEC_CR_VEC_VLC_TABLE_INITIAL_OPCODE0_VLC_TABLE_INITIAL_OPCODE1_SHIFT              (2)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MSVDX_VEC_REGS_H__ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/img_pixfmts.h b/drivers/media/platform/img/vxe-vxd/decoder/img_pixfmts.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/img_pixfmts.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/img_pixfmts.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD DEC SYSDEV and UI Interface header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ */
+
+#ifndef __IMG_PIXFMTS_H__
+#define __IMG_PIXFMTS_H__
+/*
+ * @brief Old pixel format definition
+ *
+ * @note These definitions are different in HW documentation(current to HW doc):
+ * @li PL8 is defined as PL111
+ * @li PL12 is sometime used wrongly for monochrome formats instead of PL_Y
+ */
+enum img_pixfmt {
+	IMG_PIXFMT_CLUT1              =   0,
+	IMG_PIXFMT_CLUT2              =   1,
+	IMG_PIXFMT_CLUT4              =   2,
+	IMG_PIXFMT_I4A4               =   3,
+	IMG_PIXFMT_I8A8               =   4,
+	IMG_PIXFMT_A8I8               =   51,
+	IMG_PIXFMT_RGB8               =   5,
+	IMG_PIXFMT_RGB332             =   6,
+	IMG_PIXFMT_RGB555             =   7,
+	IMG_PIXFMT_ARGB4444           =   8,
+	IMG_PIXFMT_ABGR4444           =   57,
+	IMG_PIXFMT_RGBA4444           =   58,
+	IMG_PIXFMT_BGRA4444           =   59,
+	IMG_PIXFMT_ARGB1555           =   9,
+	IMG_PIXFMT_ABGR1555           =   60,
+	IMG_PIXFMT_RGBA5551           =   61,
+	IMG_PIXFMT_BGRA5551           =   62,
+	IMG_PIXFMT_RGB565             =   10,
+	IMG_PIXFMT_BGR565             =   63,
+	IMG_PIXFMT_RGB888             =   11,
+	IMG_PIXFMT_RSGSBS888          =   68,
+	IMG_PIXFMT_ARGB8888           =   12,
+	IMG_PIXFMT_ABGR8888           =   41,
+	IMG_PIXFMT_BGRA8888           =   42,
+	IMG_PIXFMT_RGBA8888           =   56,
+	IMG_PIXFMT_ARGB8332           =   43,
+	IMG_PIXFMT_ARGB8161616        =   64,
+	IMG_PIXFMT_ARGB2101010        =   67,
+	IMG_PIXFMT_UYVY8888           =   13,
+	IMG_PIXFMT_VYUY8888           =   14,
+	IMG_PIXFMT_YVYU8888           =   15,
+	IMG_PIXFMT_YUYV8888           =   16,
+	IMG_PIXFMT_UYVY10101010       =   17,
+	IMG_PIXFMT_VYAUYA8888         =   18,
+	IMG_PIXFMT_YUV101010          =   19,
+	IMG_PIXFMT_AYUV4444           =   20,
+	IMG_PIXFMT_YUV888             =   21,
+	IMG_PIXFMT_AYUV8888           =   22,
+	IMG_PIXFMT_AYUV2101010        =   23,
+	IMG_PIXFMT_411PL111YUV8       =   120,
+	IMG_PIXFMT_411PL12YUV8        =   121,
+	IMG_PIXFMT_411PL12YVU8        =   24,
+	IMG_PIXFMT_420PL12YUV8        =   25,
+	IMG_PIXFMT_420PL12YVU8        =   26,
+	IMG_PIXFMT_422PL12YUV8        =   27,
+	IMG_PIXFMT_422PL12YVU8        =   28,
+	IMG_PIXFMT_420PL8YUV8         =   47,
+	IMG_PIXFMT_422PL8YUV8         =   48,
+	IMG_PIXFMT_420PL12YUV8_A8     = 31,
+	IMG_PIXFMT_422PL12YUV8_A8     = 32,
+	IMG_PIXFMT_PL12Y8             =   33,
+	IMG_PIXFMT_PL12YV8            =   35,
+	IMG_PIXFMT_PL12IMC2           =   36,
+	IMG_PIXFMT_A4                 =   37,
+	IMG_PIXFMT_A8                 =   38,
+	IMG_PIXFMT_YUV8               =   39,
+	IMG_PIXFMT_CVBS10             =   40,
+	IMG_PIXFMT_PL12YV12           =   44,
+#if ((!defined(METAG) && !defined(MTXG)) || defined(__linux__))
+	IMG_PIXFMT_F16                = 52,
+	IMG_PIXFMT_F32                = 53,
+	IMG_PIXFMT_F16F16F16F16       = 65,
+#endif
+	IMG_PIXFMT_L16                = 54,
+	IMG_PIXFMT_L32                = 55,
+	IMG_PIXFMT_Y1                 = 66,
+	IMG_PIXFMT_444PL111YUV8       = 69,
+	IMG_PIXFMT_444PL12YUV8        = 137,
+	IMG_PIXFMT_444PL12YVU8        = 138,
+	IMG_PIXFMT_PL12Y10            =   34,
+	IMG_PIXFMT_PL12Y10_LSB        =  96,
+	IMG_PIXFMT_PL12Y10_MSB        =  97,
+	IMG_PIXFMT_420PL8YUV10        =   49,
+	IMG_PIXFMT_420PL111YUV10_LSB  = 71,
+	IMG_PIXFMT_420PL111YUV10_MSB  = 72,
+	IMG_PIXFMT_420PL12YUV10       = 29,
+	IMG_PIXFMT_420PL12YUV10_LSB   = 74,
+	IMG_PIXFMT_420PL12YUV10_MSB   = 75,
+	IMG_PIXFMT_420PL12YVU10       = 45,
+	IMG_PIXFMT_420PL12YVU10_LSB   = 77,
+	IMG_PIXFMT_420PL12YVU10_MSB   = 78,
+	IMG_PIXFMT_422PL8YUV10        =   50,
+	IMG_PIXFMT_422PL111YUV10_LSB  = 122,
+	IMG_PIXFMT_422PL111YUV10_MSB  = 123,
+	IMG_PIXFMT_422PL12YUV10       = 30,
+	IMG_PIXFMT_422PL12YUV10_LSB   = 80,
+	IMG_PIXFMT_422PL12YUV10_MSB   = 81,
+	IMG_PIXFMT_422PL12YVU10       = 46,
+	IMG_PIXFMT_422PL12YVU10_LSB   = 83,
+	IMG_PIXFMT_422PL12YVU10_MSB   = 84,
+	IMG_PIXFMT_444PL111YUV10      = 85,
+	IMG_PIXFMT_444PL111YUV10_LSB  = 86,
+	IMG_PIXFMT_444PL111YUV10_MSB  = 87,
+	IMG_PIXFMT_444PL12YUV10       = 139,
+	IMG_PIXFMT_444PL12YUV10_LSB   = 141,
+	IMG_PIXFMT_444PL12YUV10_MSB   = 142,
+	IMG_PIXFMT_444PL12YVU10       = 140,
+	IMG_PIXFMT_444PL12YVU10_LSB   = 143,
+	IMG_PIXFMT_444PL12YVU10_MSB   = 144,
+	IMG_PIXFMT_420PL12Y8UV10      = 88,
+	IMG_PIXFMT_420PL12Y8UV10_LSB  = 98,
+	IMG_PIXFMT_420PL12Y8UV10_MSB  = 99,
+	IMG_PIXFMT_420PL12Y8VU10      = 89,
+	IMG_PIXFMT_420PL12Y8VU10_LSB  = 100,
+	IMG_PIXFMT_420PL12Y8VU10_MSB  = 101,
+	IMG_PIXFMT_420PL111Y8UV10     = 70,
+	IMG_PIXFMT_420PL111Y8UV10_LSB = 127,
+	IMG_PIXFMT_420PL111Y8UV10_MSB = 125,
+	IMG_PIXFMT_422PL12Y8UV10      = 90,
+	IMG_PIXFMT_422PL12Y8UV10_LSB  = 102,
+	IMG_PIXFMT_422PL12Y8UV10_MSB  = 103,
+	IMG_PIXFMT_422PL12Y8VU10      = 91,
+	IMG_PIXFMT_422PL12Y8VU10_LSB  = 104,
+	IMG_PIXFMT_422PL12Y8VU10_MSB  = 105,
+	IMG_PIXFMT_444PL12Y8UV10      = 151,
+	IMG_PIXFMT_444PL12Y8UV10_LSB  = 153,
+	IMG_PIXFMT_444PL12Y8UV10_MSB  = 154,
+	IMG_PIXFMT_444PL12Y8VU10      = 152,
+	IMG_PIXFMT_444PL12Y8VU10_LSB  = 155,
+	IMG_PIXFMT_444PL12Y8VU10_MSB  = 156,
+	IMG_PIXFMT_420PL12Y10UV8      = 92,
+	IMG_PIXFMT_420PL12Y10UV8_LSB  = 106,
+	IMG_PIXFMT_420PL12Y10UV8_MSB  = 107,
+
+	IMG_PIXFMT_420PL12Y10VU8      = 93,
+	IMG_PIXFMT_420PL12Y10VU8_LSB  = 108,
+	IMG_PIXFMT_420PL12Y10VU8_MSB  = 109,
+
+	IMG_PIXFMT_420PL111Y10UV8     = 129,
+	IMG_PIXFMT_420PL111Y10UV8_LSB = 133,
+	IMG_PIXFMT_420PL111Y10UV8_MSB = 131,
+	IMG_PIXFMT_422PL12Y10UV8      = 94,
+	IMG_PIXFMT_422PL12Y10UV8_LSB  = 110,
+	IMG_PIXFMT_422PL12Y10UV8_MSB  = 111,
+	IMG_PIXFMT_422PL12Y10VU8      = 95,
+	IMG_PIXFMT_422PL12Y10VU8_LSB  = 112,
+	IMG_PIXFMT_422PL12Y10VU8_MSB  = 113,
+
+	IMG_PIXFMT_444PL111Y10UV8     = 114,
+	IMG_PIXFMT_444PL111Y10UV8_LSB = 115,
+	IMG_PIXFMT_444PL111Y10UV8_MSB = 116,
+	IMG_PIXFMT_444PL111Y8UV10     = 117,
+	IMG_PIXFMT_444PL111Y8UV10_LSB = 118,
+	IMG_PIXFMT_444PL111Y8UV10_MSB = 119,
+	IMG_PIXFMT_444PL12Y10UV8      = 145,
+	IMG_PIXFMT_444PL12Y10UV8_LSB  = 147,
+	IMG_PIXFMT_444PL12Y10UV8_MSB  = 148,
+	IMG_PIXFMT_444PL12Y10VU8      = 146,
+	IMG_PIXFMT_444PL12Y10VU8_LSB  = 149,
+	IMG_PIXFMT_444PL12Y10VU8_MSB  = 150,
+	IMG_PIXFMT_422PL111Y8UV10     = 124,
+	IMG_PIXFMT_422PL111Y8UV10_MSB = 126,
+	IMG_PIXFMT_422PL111Y8UV10_LSB = 128,
+
+	IMG_PIXFMT_422PL111Y10UV8     = 130,
+	IMG_PIXFMT_422PL111Y10UV8_LSB = 134,
+	IMG_PIXFMT_422PL111Y10UV8_MSB = 132,
+	IMG_PIXFMT_420PL8YUV12        = 160,
+	IMG_PIXFMT_422PL8YUV12        = 161,
+	IMG_PIXFMT_444PL8YUV12        = 162,
+	IMG_PIXFMT_420PL8YUV14        = 163,
+	IMG_PIXFMT_422PL8YUV14        = 164,
+	IMG_PIXFMT_444PL8YUV14        = 165,
+	IMG_PIXFMT_420PL8YUV16        = 166,
+	IMG_PIXFMT_422PL8YUV16        = 167,
+	IMG_PIXFMT_444PL8YUV16        = 168,
+	IMG_PIXFMT_UNDEFINED          = 255,
+
+	IMG_PIXFMT_ARBPLANAR8         = 65536,
+	IMG_PIXFMT_ARBPLANAR8_LAST    = IMG_PIXFMT_ARBPLANAR8 + 0xffff,
+	IMG_PIXFMT_FORCE32BITS        = 0x7FFFFFFFU
+};
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/img_profiles_levels.h b/drivers/media/platform/img/vxe-vxd/decoder/img_profiles_levels.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/img_profiles_levels.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/img_profiles_levels.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD DEC SYSDEV and UI Interface header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef __IMG_PROFILES_LEVELS_H
+#define __IMG_PROFILES_LEVELS_H
+
+#include "vdecdd_utils.h"
+
+/* Minimum level value for h.264 */
+#define H264_LEVEL_MIN              (9)
+/* Maximum level value for h.264 */
+#define H264_LEVEL_MAX             (52)
+/* Number of major levels for h.264 (5 + 1 for special levels) */
+#define H264_LEVEL_MAJOR_NUM        (6)
+/* Number of minor levels for h.264 */
+#define H264_LEVEL_MINOR_NUM            (4)
+/* Number of major levels for HEVC */
+#define HEVC_LEVEL_MAJOR_NUM        (6)
+/* Number of minor levels for HEVC */
+#define HEVC_LEVEL_MINOR_NUM        (3)
+
+#endif /*__IMG_PROFILES_LEVELS_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/img_pvdec_core_regs.h b/drivers/media/platform/img/vxe-vxd/decoder/img_pvdec_core_regs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/img_pvdec_core_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/img_pvdec_core_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG PVDEC CORE Registers
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _IMG_PVDEC_CORE_REGS_H
+#define _IMG_PVDEC_CORE_REGS_H
+
+/* PVDEC_CORE, CR_PVDEC_HOST_INTERRUPT_STATUS, CR_HOST_SYS_WDT */
+#define PVDEC_CORE_CR_PVDEC_HOST_INTERRUPT_STATUS_CR_HOST_SYS_WDT_MASK          (0x10000000)
+
+#define PVDEC_CORE_CR_PVDEC_HOST_INTERRUPT_STATUS_CR_HOST_SYS_WDT_SHIFT         (28)
+
+/* PVDEC_CORE, CR_PVDEC_HOST_INTERRUPT_STATUS, CR_HOST_READ_TIMEOUT_PROC_IRQ */
+#define PVDEC_CORE_CR_PVDEC_HOST_INTERRUPT_STATUS_CR_HOST_READ_TIMEOUT_PROC_IRQ_MASK \
+									(0x08000000)
+
+/* PVDEC_CORE, CR_PVDEC_CORE_REV, CR_PVDEC_MAJOR_REV */
+#define PVDEC_CORE_CR_PVDEC_CORE_REV_CR_PVDEC_MAJOR_REV_MASK            (0x00FF0000)
+#define PVDEC_CORE_CR_PVDEC_CORE_REV_CR_PVDEC_MAJOR_REV_SHIFT           (16)
+
+/* PVDEC_CORE, CR_PVDEC_CORE_REV, CR_PVDEC_MINOR_REV */
+#define PVDEC_CORE_CR_PVDEC_CORE_REV_CR_PVDEC_MINOR_REV_MASK            (0x0000FF00)
+#define PVDEC_CORE_CR_PVDEC_CORE_REV_CR_PVDEC_MINOR_REV_SHIFT           (8)
+
+/* PVDEC_CORE, CR_PVDEC_HOST_INTERRUPT_STATUS, CR_HOST_READ_TIMEOUT_PROC_IRQ */
+#define PVDEC_CORE_CR_PVDEC_HOST_INTERRUPT_STATUS_CR_HOST_READ_TIMEOUT_PROC_IRQ_SHIFT           (27)
+
+/* PVDEC_CORE, CR_PVDEC_HOST_INTERRUPT_STATUS, CR_HOST_COMMAND_TIMEOUT_PROC_IRQ */
+#define PVDEC_CORE_CR_PVDEC_HOST_INTERRUPT_STATUS_CR_HOST_COMMAND_TIMEOUT_PROC_IRQ_MASK \
+										(0x04000000)
+#define PVDEC_CORE_CR_PVDEC_HOST_INTERRUPT_STATUS_CR_HOST_COMMAND_TIMEOUT_PROC_IRQ_SHIFT \
+											(26)
+
+/* PVDEC_CORE, CR_PVDEC_CORE_ID, CR_GROUP_ID */
+#define PVDEC_CORE_CR_PVDEC_CORE_ID_CR_GROUP_ID_MASK            (0xFF000000)
+#define PVDEC_CORE_CR_PVDEC_CORE_ID_CR_GROUP_ID_SHIFT           (24)
+
+/* PVDEC_CORE, CR_PVDEC_CORE_REV, CR_PVDEC_MAINT_REV */
+#define PVDEC_CORE_CR_PVDEC_CORE_REV_CR_PVDEC_MAINT_REV_MASK            (0x000000FF)
+#define PVDEC_CORE_CR_PVDEC_CORE_REV_CR_PVDEC_MAINT_REV_SHIFT           (0)
+
+/* PVDEC_CORE, CR_PVDEC_CORE_ID, CR_CORE_ID */
+#define PVDEC_CORE_CR_PVDEC_CORE_ID_CR_CORE_ID_MASK             (0x00FF0000)
+#define PVDEC_CORE_CR_PVDEC_CORE_ID_CR_CORE_ID_SHIFT            (16)
+
+/* PVDEC_CORE, CR_PVDEC_CORE_ID, CR_PVDEC_CORE_CONFIG */
+#define PVDEC_CORE_CR_PVDEC_CORE_ID_CR_PVDEC_CORE_CONFIG_MASK           (0x0000FFFF)
+#define PVDEC_CORE_CR_PVDEC_CORE_ID_CR_PVDEC_CORE_CONFIG_SHIFT          (0)
+
+#endif /* _IMG_PVDEC_CORE_REGS_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/img_pvdec_pixel_regs.h b/drivers/media/platform/img/vxe-vxd/decoder/img_pvdec_pixel_regs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/img_pvdec_pixel_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/img_pvdec_pixel_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG PVDEC pixel Registers
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _IMG_PVDEC_PIXEL_REGS_H
+#define _IMG_PVDEC_PIXEL_REGS_H
+
+/* PVDEC_PIXEL, CR_MAX_FRAME_CONFIG, CR_PVDEC_HOR_MSB */
+#define PVDEC_PIXEL_CR_MAX_FRAME_CONFIG_CR_PVDEC_HOR_MSB_MASK           (0x001F0000)
+
+#define PVDEC_PIXEL_CR_MAX_FRAME_CONFIG_CR_PVDEC_HOR_MSB_SHIFT          (16)
+
+/* PVDEC_PIXEL, CR_MAX_FRAME_CONFIG, CR_PVDEC_VER_MSB */
+#define PVDEC_PIXEL_CR_MAX_FRAME_CONFIG_CR_PVDEC_VER_MSB_MASK           (0x1F000000)
+#define PVDEC_PIXEL_CR_MAX_FRAME_CONFIG_CR_PVDEC_VER_MSB_SHIFT          (24)
+
+/* PVDEC_PIXEL, CR_MAX_FRAME_CONFIG, CR_MSVDX_HOR_MSB */
+#define PVDEC_PIXEL_CR_MAX_FRAME_CONFIG_CR_MSVDX_HOR_MSB_MASK           (0x0000001F)
+#define PVDEC_PIXEL_CR_MAX_FRAME_CONFIG_CR_MSVDX_HOR_MSB_SHIFT          (0)
+
+/* PVDEC_PIXEL, CR_MAX_FRAME_CONFIG, CR_MSVDX_VER_MSB */
+#define PVDEC_PIXEL_CR_MAX_FRAME_CONFIG_CR_MSVDX_VER_MSB_MASK           (0x00001F00)
+#define PVDEC_PIXEL_CR_MAX_FRAME_CONFIG_CR_MSVDX_VER_MSB_SHIFT          (8)
+
+#endif /* _IMG_PVDEC_PIXEL_REGS_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/img_pvdec_test_regs.h b/drivers/media/platform/img/vxe-vxd/decoder/img_pvdec_test_regs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/img_pvdec_test_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/img_pvdec_test_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG PVDEC test Registers
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _IMG_PVDEC_TEST_REGS_H
+#define _IMG_PVDEC_TEST_REGS_H
+
+/* PVDEC_TEST, RAND_STL_MEM_RDATA_CONFIG, STALL_ENABLE_MEM_RDATA */
+#define PVDEC_TEST_MEM_READ_LATENCY_OFFSET              (0x00F0)
+
+/* PVDEC_TEST, MEM_READ_LATENCY, READ_RESPONSE_RAND_LATENCY */
+#define PVDEC_TEST_MEM_WRITE_RESPONSE_LATENCY_OFFSET            (0x00F4)
+
+/* PVDEC_TEST, MEM_WRITE_RESPONSE_LATENCY, WRITE_RESPONSE_RAND_LATENCY */
+#define PVDEC_TEST_MEM_CTRL_OFFSET              (0x00F8)
+
+/* PVDEC_TEST, RAND_STL_MEM_WDATA_CONFIG, STALL_ENABLE_MEM_WDATA */
+#define PVDEC_TEST_RAND_STL_MEM_WRESP_CONFIG_OFFSET             (0x00E8)
+
+/* PVDEC_TEST, RAND_STL_MEM_WRESP_CONFIG, STALL_ENABLE_MEM_WRESP */
+#define PVDEC_TEST_RAND_STL_MEM_RDATA_CONFIG_OFFSET             (0x00EC)
+
+/* PVDEC_TEST, MEMORY_BUS2_MONITOR_2, BUS2_ADDR */
+#define PVDEC_TEST_RAND_STL_MEM_CMD_CONFIG_OFFSET               (0x00E0)
+
+/* PVDEC_TEST, RAND_STL_MEM_CMD_CONFIG, STALL_ENABLE_MEM_CMD */
+#define PVDEC_TEST_RAND_STL_MEM_WDATA_CONFIG_OFFSET             (0x00E4)
+
+#endif /* _IMG_PVDEC_TEST_REGS_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/img_vdec_fw_msg.h b/drivers/media/platform/img/vxe-vxd/decoder/img_vdec_fw_msg.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/img_vdec_fw_msg.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/img_vdec_fw_msg.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,192 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG VDEC firmware messages
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _IMG_VDEC_FW_MSG_H
+#define _IMG_VDEC_FW_MSG_H
+
+#include <linux/types.h>
+
+/* FW_DEVA_COMPLETED     ERROR_FLAGS */
+#define FW_DEVA_COMPLETED_ERROR_FLAGS_TYPE              unsigned short
+#define FW_DEVA_COMPLETED_ERROR_FLAGS_MASK		(0xFFFF)
+#define FW_DEVA_COMPLETED_ERROR_FLAGS_SHIFT		(0)
+#define FW_DEVA_COMPLETED_ERROR_FLAGS_OFFSET		(0x000C)
+
+/* FW_DEVA_COMPLETED     NUM_BEWDTS */
+#define FW_DEVA_COMPLETED_NUM_BEWDTS_TYPE               unsigned int
+#define FW_DEVA_COMPLETED_NUM_BEWDTS_MASK               (0xFFFFFFFF)
+#define FW_DEVA_COMPLETED_NUM_BEWDTS_SHIFT              (0)
+#define FW_DEVA_COMPLETED_NUM_BEWDTS_OFFSET		(0x0010)
+
+/* FW_DEVA_COMPLETED     NUM_MBSDROPPED */
+#define FW_DEVA_COMPLETED_NUM_MBSDROPPED_TYPE           unsigned int
+#define FW_DEVA_COMPLETED_NUM_MBSDROPPED_MASK           (0xFFFFFFFF)
+#define FW_DEVA_COMPLETED_NUM_MBSDROPPED_SHIFT          (0)
+#define FW_DEVA_COMPLETED_NUM_MBSDROPPED_OFFSET		(0x0014)
+
+/* FW_DEVA_COMPLETED     NUM_MBSRECOVERED */
+#define FW_DEVA_COMPLETED_NUM_MBSRECOVERED_TYPE         unsigned int
+#define FW_DEVA_COMPLETED_NUM_MBSRECOVERED_MASK         (0xFFFFFFFF)
+#define FW_DEVA_COMPLETED_NUM_MBSRECOVERED_SHIFT        (0)
+#define FW_DEVA_COMPLETED_NUM_MBSRECOVERED_OFFSET	(0x0018)
+
+/* FW_DEVA_PANIC     ERROR_INT */
+#define FW_DEVA_PANIC_ERROR_INT_TYPE            unsigned int
+#define FW_DEVA_PANIC_ERROR_INT_MASK            (0xFFFFFFFF)
+#define FW_DEVA_PANIC_ERROR_INT_SHIFT           (0)
+#define FW_DEVA_PANIC_ERROR_INT_OFFSET          (0x000C)
+
+/* FW_ASSERT     FILE_NAME_HASH */
+#define FW_ASSERT_FILE_NAME_HASH_TYPE           unsigned int
+#define FW_ASSERT_FILE_NAME_HASH_MASK           (0xFFFFFFFF)
+#define FW_ASSERT_FILE_NAME_HASH_SHIFT          (0)
+#define FW_ASSERT_FILE_NAME_HASH_OFFSET         (0x0004)
+
+/* FW_ASSERT     FILE_LINE */
+#define FW_ASSERT_FILE_LINE_TYPE                unsigned int
+#define FW_ASSERT_FILE_LINE_MASK                (0xFFFFFFFE)
+#define FW_ASSERT_FILE_LINE_SHIFT               (1)
+#define FW_ASSERT_FILE_LINE_OFFSET              (0x0008)
+
+/* FW_SO     TASK_NAME */
+#define FW_SO_TASK_NAME_TYPE            unsigned int
+#define FW_SO_TASK_NAME_MASK            (0xFFFFFFFF)
+#define FW_SO_TASK_NAME_SHIFT           (0)
+#define FW_SO_TASK_NAME_OFFSET          (0x0004)
+
+/* FW_DEVA_GENMSG     TRANS_ID */
+#define FW_DEVA_GENMSG_TRANS_ID_TYPE            unsigned int
+#define FW_DEVA_GENMSG_TRANS_ID_MASK            (0xFFFFFFFF)
+#define FW_DEVA_GENMSG_TRANS_ID_SHIFT           (0)
+#define FW_DEVA_GENMSG_TRANS_ID_OFFSET          (0x0008)
+
+/* FW_DEVA_GENMSG     MSG_TYPE */
+#define FW_DEVA_GENMSG_MSG_TYPE_TYPE            unsigned char
+#define FW_DEVA_GENMSG_MSG_TYPE_MASK            (0xFF)
+#define FW_DEVA_GENMSG_MSG_TYPE_SHIFT           (0)
+#define FW_DEVA_GENMSG_MSG_TYPE_OFFSET          (0x0001)
+
+/* FW_DEVA_SIGNATURES     SIGNATURES */
+#define FW_DEVA_SIGNATURES_SIGNATURES_OFFSET            (0x0010)
+
+/* FW_DEVA_SIGNATURES     MSG_SIZE */
+#define FW_DEVA_SIGNATURES_MSG_SIZE_TYPE                unsigned char
+#define FW_DEVA_SIGNATURES_MSG_SIZE_MASK                (0x7F)
+#define FW_DEVA_SIGNATURES_MSG_SIZE_SHIFT               (0)
+#define FW_DEVA_SIGNATURES_MSG_SIZE_OFFSET              (0x0000)
+
+/* FW_DEVA_CONTIGUITY_WARNING     BEGIN_MB_NUM */
+#define FW_DEVA_SIGNATURES_SIZE         (20)
+
+/* FW_DEVA_SIGNATURES     SIGNATURE_SELECT */
+#define FW_DEVA_SIGNATURES_SIGNATURE_SELECT_TYPE                unsigned int
+#define FW_DEVA_SIGNATURES_SIGNATURE_SELECT_MASK                (0xFFFFFFFF)
+#define FW_DEVA_SIGNATURES_SIGNATURE_SELECT_SHIFT               (0)
+#define FW_DEVA_SIGNATURES_SIGNATURE_SELECT_OFFSET              (0x000C)
+
+/* FW_DEVA_GENMSG     TRANS_ID */
+#define FW_DEVA_DECODE_SIZE             (52)
+
+/* FW_DEVA_DECODE     CTRL_ALLOC_ADDR */
+#define FW_DEVA_DECODE_CTRL_ALLOC_ADDR_TYPE             unsigned int
+#define FW_DEVA_DECODE_CTRL_ALLOC_ADDR_MASK             (0xFFFFFFFF)
+#define FW_DEVA_DECODE_CTRL_ALLOC_ADDR_SHIFT            (0)
+#define FW_DEVA_DECODE_CTRL_ALLOC_ADDR_OFFSET           (0x0010)
+
+/* FW_DEVA_DECODE     BUFFER_SIZE */
+#define FW_DEVA_DECODE_BUFFER_SIZE_TYPE         unsigned short
+#define FW_DEVA_DECODE_BUFFER_SIZE_MASK         (0xFFFF)
+#define FW_DEVA_DECODE_BUFFER_SIZE_SHIFT	(0)
+#define FW_DEVA_DECODE_BUFFER_SIZE_OFFSET	(0x000E)
+
+/* FW_DEVA_DECODE     OPERATING_MODE */
+#define FW_DEVA_DECODE_OPERATING_MODE_TYPE              unsigned int
+#define FW_DEVA_DECODE_OPERATING_MODE_MASK              (0xFFFFFFFF)
+#define FW_DEVA_DECODE_OPERATING_MODE_OFFSET            (0x0018)
+#define FW_DEVA_DECODE_OPERATING_MODE_SHIFT             (0)
+
+/* FW_DEVA_DECODE     FLAGS */
+#define FW_DEVA_DECODE_FLAGS_TYPE               unsigned short
+#define FW_DEVA_DECODE_FLAGS_MASK               (0xFFFF)
+#define FW_DEVA_DECODE_FLAGS_SHIFT              (0)
+#define FW_DEVA_DECODE_FLAGS_OFFSET             (0x000C)
+
+/* FW_DEVA_DECODE     VDEC_FLAGS */
+#define FW_DEVA_DECODE_VDEC_FLAGS_TYPE          unsigned char
+#define FW_DEVA_DECODE_VDEC_FLAGS_MASK          (0xFF)
+#define FW_DEVA_DECODE_VDEC_FLAGS_SHIFT         (0)
+#define FW_DEVA_DECODE_VDEC_FLAGS_OFFSET	(0x001E)
+
+/* FW_DEVA_DECODE     GENC_ID */
+#define FW_DEVA_DECODE_GENC_ID_TYPE             unsigned int
+#define FW_DEVA_DECODE_GENC_ID_MASK             (0xFFFFFFFF)
+#define FW_DEVA_DECODE_GENC_ID_SHIFT            (0)
+#define FW_DEVA_DECODE_GENC_ID_OFFSET           (0x0028)
+
+/* FW_DEVA_DECODE     MB_LOAD */
+#define FW_DEVA_DECODE_MB_LOAD_TYPE             unsigned int
+#define FW_DEVA_DECODE_MB_LOAD_MASK             (0xFFFFFFFF)
+#define FW_DEVA_DECODE_MB_LOAD_OFFSET           (0x0030)
+#define FW_DEVA_DECODE_MB_LOAD_SHIFT            (0)
+#define FW_DEVA_DECODE_FRAGMENT_SIZE            (16)
+
+/* FW_DEVA_DECODE     STREAMID */
+#define FW_DEVA_DECODE_STREAMID_TYPE            unsigned char
+#define FW_DEVA_DECODE_STREAMID_MASK            (0xFF)
+#define FW_DEVA_DECODE_STREAMID_OFFSET          (0x001F)
+#define FW_DEVA_DECODE_STREAMID_SHIFT           (0)
+
+/* FW_DEVA_DECODE     EXT_STATE_BUFFER */
+#define FW_DEVA_DECODE_EXT_STATE_BUFFER_TYPE            unsigned int
+#define FW_DEVA_DECODE_EXT_STATE_BUFFER_MASK            (0xFFFFFFFF)
+#define FW_DEVA_DECODE_EXT_STATE_BUFFER_OFFSET          (0x0020)
+#define FW_DEVA_DECODE_EXT_STATE_BUFFER_SHIFT           (0)
+
+/* FW_DEVA_DECODE     MSG_ID */
+#define FW_DEVA_DECODE_MSG_ID_TYPE              unsigned short
+#define FW_DEVA_DECODE_MSG_ID_MASK              (0xFFFF)
+#define FW_DEVA_DECODE_MSG_ID_OFFSET            (0x0002)
+#define FW_DEVA_DECODE_MSG_ID_SHIFT             (0)
+
+/* FW_DEVA_DECODE     TRANS_ID */
+#define FW_DEVA_DECODE_TRANS_ID_TYPE            unsigned int
+#define FW_DEVA_DECODE_TRANS_ID_MASK            (0xFFFFFFFF)
+#define FW_DEVA_DECODE_TRANS_ID_OFFSET          (0x0008)
+#define FW_DEVA_DECODE_TRANS_ID_SHIFT           (0)
+
+/* FW_DEVA_DECODE     TILE_CFG */
+#define FW_DEVA_DECODE_TILE_CFG_TYPE            unsigned int
+#define FW_DEVA_DECODE_TILE_CFG_MASK            (0xFFFFFFFF)
+#define FW_DEVA_DECODE_TILE_CFG_OFFSET          (0x0024)
+#define FW_DEVA_DECODE_TILE_CFG_SHIFT           (0)
+
+/* FW_DEVA_GENMSG     MSG_SIZE */
+#define FW_DEVA_GENMSG_MSG_SIZE_TYPE            unsigned char
+#define FW_DEVA_GENMSG_MSG_SIZE_MASK            (0x7F)
+#define FW_DEVA_GENMSG_MSG_SIZE_OFFSET          (0x0000)
+#define FW_DEVA_GENMSG_MSG_SIZE_SHIFT           (0)
+
+/* FW_DEVA_DECODE_FRAGMENT     CTRL_ALLOC_ADDR */
+#define FW_DEVA_DECODE_FRAGMENT_CTRL_ALLOC_ADDR_TYPE            unsigned int
+#define FW_DEVA_DECODE_FRAGMENT_CTRL_ALLOC_ADDR_MASK            (0xFFFFFFFF)
+#define FW_DEVA_DECODE_FRAGMENT_CTRL_ALLOC_ADDR_OFFSET          (0x000C)
+#define FW_DEVA_DECODE_FRAGMENT_CTRL_ALLOC_ADDR_SHIFT           (0)
+
+/* FW_DEVA_DECODE_FRAGMENT     BUFFER_SIZE */
+#define FW_DEVA_DECODE_FRAGMENT_BUFFER_SIZE_TYPE                unsigned short
+#define FW_DEVA_DECODE_FRAGMENT_BUFFER_SIZE_MASK                (0xFFFF)
+#define FW_DEVA_DECODE_FRAGMENT_BUFFER_SIZE_OFFSET              (0x000A)
+#define FW_DEVA_DECODE_FRAGMENT_BUFFER_SIZE_SHIFT               (0)
+
+#endif /* _IMG_VDEC_FW_MSG_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/img_video_bus4_mmu_regs.h b/drivers/media/platform/img/vxe-vxd/decoder/img_video_bus4_mmu_regs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/img_video_bus4_mmu_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/img_video_bus4_mmu_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,120 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG video bus4 mmu registers
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _IMG_VIDEO_BUS4_MMU_REGS_H
+#define _IMG_VIDEO_BUS4_MMU_REGS_H
+
+#define IMG_VIDEO_BUS4_MMU_MMU_DIR_BASE_ADDR_OFFSET             (0x0020)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_ADDRESS_CONTROL, MMU_BYPASS */
+#define IMG_VIDEO_BUS4_MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_MASK          (0x00000001)
+#define IMG_VIDEO_BUS4_MMU_MMU_ADDRESS_CONTROL_MMU_BYPASS_SHIFT         (0)
+
+/* IMG_VIDEO_BUS4_MMU, REQUEST_LIMITED_THROUGHPUT, REQUEST_GAP */
+#define IMG_VIDEO_BUS4_MMU_MMU_ADDRESS_CONTROL_OFFSET           (0x0070)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, MMU_SOFT_RESET */
+#define IMG_VIDEO_BUS4_MMU_MMU_BANK_INDEX_OFFSET                (0x0010)
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL1_MMU_SOFT_RESET_SHIFT    (28)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_TILE_MAX_ADDR, TILE_MAX_ADDR */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL0_OFFSET          (0x0000)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONTROL0, MMU_TILING_SCHEME */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL0_MMU_TILING_SCHEME_MASK          (0x00000001)
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL0_MMU_TILING_SCHEME_SHIFT         (0)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_TILE_CFG, TILE_STRIDE */
+#define IMG_VIDEO_BUS4_MMU_MMU_TILE_MIN_ADDR_STRIDE             (4)
+#define IMG_VIDEO_BUS4_MMU_MMU_TILE_MIN_ADDR_OFFSET             (0x0050)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_TILE_MIN_ADDR, TILE_MIN_ADDR */
+#define IMG_VIDEO_BUS4_MMU_MMU_TILE_MAX_ADDR_OFFSET             (0x0060)
+#define IMG_VIDEO_BUS4_MMU_MMU_TILE_MAX_ADDR_STRIDE             (4)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_STATUS1, MMU_FAULT_RNW */
+#define IMG_VIDEO_BUS4_MMU_MMU_MEM_REQ_OFFSET           (0x0090)
+#define IMG_VIDEO_BUS4_MMU_MMU_STATUS1_MMU_FAULT_RNW_MASK               (0x10000000)
+#define IMG_VIDEO_BUS4_MMU_MMU_STATUS1_MMU_FAULT_RNW_SHIFT              (28)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_MEM_REQ, TAG_OUTSTANDING */
+#define IMG_VIDEO_BUS4_MMU_MMU_MEM_REQ_TAG_OUTSTANDING_MASK             (0x000003FF)
+#define IMG_VIDEO_BUS4_MMU_MMU_MEM_REQ_TAG_OUTSTANDING_SHIFT            (0)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONTROL0, USE_TILE_STRIDE_PER_CONTEXT */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL1_OFFSET          (0x0008)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, MMU_SOFT_RESET */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL1_MMU_SOFT_RESET_MASK             (0x10000000)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, MMU_PAUSE_SET */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL1_MMU_PAUSE_SET_MASK              (0x01000000)
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL1_MMU_PAUSE_SET_SHIFT             (24)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, MMU_PAUSE_CLEAR */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL1_MMU_PAUSE_CLEAR_MASK            (0x02000000)
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL1_MMU_PAUSE_CLEAR_SHIFT           (25)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_ADDRESS_CONTROL, UPPER_ADDRESS_FIXED */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONFIG0_OFFSET           (0x0080)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_MEM_REQ, INT_PROTOCOL_FAULT */
+#define IMG_VIDEO_BUS4_MMU_MMU_MEM_EXT_OUTSTANDING_OFFSET               (0x0094)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONFIG0, TAGS_SUPPORTED */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONFIG1_OFFSET           (0x0084)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, MMU_INVALDC */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL1_MMU_INVALDC_MASK                (0x00000F00)
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL1_MMU_INVALDC_SHIFT               (8)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONFIG1, SUPPORT_SECURE */
+#define IMG_VIDEO_BUS4_MMU_MMU_STATUS0_OFFSET           (0x0088)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_STATUS0, MMU_FAULT_ADDR */
+#define IMG_VIDEO_BUS4_MMU_MMU_STATUS1_OFFSET           (0x008C)
+#define IMG_VIDEO_BUS4_MMU_MMU_STATUS0_MMU_FAULT_ADDR_SHIFT             (12)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_STATUS0, MMU_FAULT_ADDR */
+#define IMG_VIDEO_BUS4_MMU_MMU_STATUS0_MMU_FAULT_ADDR_MASK              (0xFFFFF000)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_STATUS0, MMU_PF_N_RW */
+#define IMG_VIDEO_BUS4_MMU_MMU_STATUS0_MMU_PF_N_RW_MASK         (0x00000001)
+#define IMG_VIDEO_BUS4_MMU_MMU_STATUS0_MMU_PF_N_RW_SHIFT        (0)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_STATUS1, MMU_FAULT_REQ_ID */
+#define IMG_VIDEO_BUS4_MMU_MMU_STATUS1_MMU_FAULT_REQ_ID_MASK            (0x003F0000)
+#define IMG_VIDEO_BUS4_MMU_MMU_STATUS1_MMU_FAULT_REQ_ID_SHIFT           (16)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_STATUS0, MMU_SECURE_FAULT */
+#define IMG_VIDEO_BUS4_MMU_MMU_STATUS0_MMU_SECURE_FAULT_MASK            (0x00000002)
+#define IMG_VIDEO_BUS4_MMU_MMU_STATUS0_MMU_SECURE_FAULT_SHIFT           (1)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONFIG1, SUPPORT_STRIDE_PER_CONTEXT */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONFIG1_SUPPORT_STRIDE_PER_CONTEXT_MASK          (0x20000000)
+#define IMG_VIDEO_BUS4_MMU_MMU_CONFIG1_SUPPORT_STRIDE_PER_CONTEXT_SHIFT         (29)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONFIG1, SUPPORT_SECURE */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONFIG1_SUPPORT_SECURE_MASK              (0x80000000)
+#define IMG_VIDEO_BUS4_MMU_MMU_CONFIG1_SUPPORT_SECURE_SHIFT             (31)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONFIG0, EXTENDED_ADDR_RANGE */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONFIG0_EXTENDED_ADDR_RANGE_MASK         (0x000000F0)
+#define IMG_VIDEO_BUS4_MMU_MMU_CONFIG0_EXTENDED_ADDR_RANGE_SHIFT        (4)
+
+/* IMG_VIDEO_BUS4_MMU, MMU_CONFIG0, GROUP_OVERRIDE_SIZE */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONFIG0_GROUP_OVERRIDE_SIZE_MASK         (0x00000700)
+#define IMG_VIDEO_BUS4_MMU_MMU_CONFIG0_GROUP_OVERRIDE_SIZE_SHIFT        (8)
+
+#endif /* _IMG_VIDEO_BUS4_MMU_REGS_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/jpegfw_data.h b/drivers/media/platform/img/vxe-vxd/decoder/jpegfw_data.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/jpegfw_data.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/jpegfw_data.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Public data structures for the h264 parser firmware module.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include "jpegfw_data_shared.h"
+
+#ifndef _JPEGFW_DATA_H_
+#define _JPEGFW_DATA_H_
+
+#define JPEG_VDEC_8x8_DCT_SIZE             64 //!< Number of elements in 8x8 DCT
+#define JPEG_VDEC_MAX_COMPONENTS           4  //!< Maximum number of component in JPEG
+#define JPEG_VDEC_MAX_SETS_HUFFMAN_TABLES  2  //!< Maximum set of huffman table in JPEG
+#define JPEG_VDEC_MAX_QUANT_TABLES         4  //!< Maximum set of quantisation table in JPEG
+#define JPEG_VDEC_TABLE_CLASS_NUM          2  //!< Maximum set of class of huffman table in JPEG
+#define JPEG_VDEC_PLANE_MAX                4  //!< Maximum number of planes
+
+struct hentry {
+	unsigned short code;
+	unsigned char codelen;
+	unsigned char value;
+};
+
+/**
+ * struct vdec_jpeg_huffman_tableinfo - This structure contains JPEG huffmant table
+ * @bits: number of bits
+ * @values: codeword value
+ *
+ * NOTE: Should only contain JPEG specific information.
+ * JPEG Huffman Table Information
+ */
+struct vdec_jpeg_huffman_tableinfo {
+	/* number of bits */
+	unsigned char bits[16];
+	/* codeword value */
+	unsigned char values[256];
+};
+
+/*
+ * This structure contains JPEG DeQunatisation table
+ * NOTE: Should only contain JPEG specific information.
+ * @brief  JPEG Dequantisation Table Information
+ */
+struct vdec_jpeg_de_quant_tableinfo {
+	/* Qunatisation precision */
+	unsigned char precision;
+	/* Qunatisation Value for 8x8 DCT  */
+	unsigned short elements[64];
+};
+
+/*
+ * This describes the JPEG parser component "Header data", shown in the
+ * Firmware Memory Layout diagram. This data is required by the JPEG firmware
+ * and should be supplied by the Host.
+ */
+struct jpegfw_header_data {
+	/* Primary decode buffer base addresses */
+	struct vdecfw_image_buffer primary;
+	/* Reference (output) picture base addresses */
+	unsigned int plane_offsets[JPEG_VDEC_PLANE_MAX];
+	/* SOS fields count value */
+	unsigned char hdr_sos_count;
+};
+
+/*
+ * This describes the JPEG  parser component "Context data".
+ * JPEG does not need any data to be saved between pictures, this structure
+ * is needed only to fit in firmware framework.
+ */
+struct jpegfw_context_data {
+	unsigned int dummy;
+};
+
+#endif /* _JPEGFW_DATA_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/jpegfw_data_shared.h b/drivers/media/platform/img/vxe-vxd/decoder/jpegfw_data_shared.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/jpegfw_data_shared.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/jpegfw_data_shared.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Public data structures for the hevc parser firmware module
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifdef USE_SHARING
+#endif
+
+#ifndef _JPEGFW_DATA_H_
+#define _JPEGFW_DATA_H_
+
+#include "vdecfw_share.h"
+#include "vdecfw_shared.h"
+
+#define JPEG_VDEC_8x8_DCT_SIZE             64 //!< Number of elements in 8x8 DCT
+#define JPEG_VDEC_MAX_COMPONENTS           4  //!< Maximum number of component in JPEG
+#define JPEG_VDEC_MAX_SETS_HUFFMAN_TABLES  2  //!< Maximum set of huffman table in JPEG
+#define JPEG_VDEC_MAX_QUANT_TABLES         4  //!< Maximum set of quantisation table in JPEG
+#define JPEG_VDEC_TABLE_CLASS_NUM          2  //!< Maximum set of class of huffman table in JPEG
+#define JPEG_VDEC_PLANE_MAX                4  //!< Maximum number of planes
+
+struct hentry {
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned short, code);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char, codelen);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char, value);
+};
+
+/*
+ * This structure contains JPEG huffmant table
+ * NOTE: Should only contain JPEG specific information.
+ * @brief  JPEG Huffman Table Information
+ */
+struct vdec_jpeg_huffman_tableinfo {
+	/* number of bits */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char, bits[16]);
+	/* codeword value */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char, values[256]);
+};
+
+/*
+ * This structure contains JPEG DeQunatisation table
+ * NOTE: Should only contain JPEG specific information.
+ * @brief  JPEG Dequantisation Table Information
+ */
+struct vdec_jpeg_de_quant_tableinfo {
+	/* Qunatisation precision */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char, precision);
+	/* Qunatisation Value for 8x8 DCT  */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned short, elements[64]);
+};
+
+/*
+ * This describes the JPEG parser component "Header data", shown in the
+ * Firmware Memory Layout diagram. This data is required by the JPEG firmware
+ * and should be supplied by the Host.
+ */
+struct jpegfw_header_data {
+	/* Primary decode buffer base addresses */
+	struct vdecfw_image_buffer primary;
+	/* Reference (output) picture base addresses */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int,
+			plane_offsets[JPEG_VDEC_PLANE_MAX]);
+	/* SOS fields count value */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned char, hdr_sos_count);
+};
+
+/*
+ * This describes the JPEG  parser component "Context data".
+ * JPEG does not need any data to be saved between pictures, this structure
+ * is needed only to fit in firmware framework.
+ */
+struct jpegfw_context_data {
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int, dummy);
+};
+
+#endif /* _JPEGFW_DATA_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/jpeg_secure_parser.c b/drivers/media/platform/img/vxe-vxd/decoder/jpeg_secure_parser.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/jpeg_secure_parser.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/jpeg_secure_parser.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,645 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * h.264 secure data unit parsing API.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "bspp_int.h"
+#include "jpeg_secure_parser.h"
+#include "jpegfw_data.h"
+#include "swsr.h"
+
+#define JPEG_MCU_SIZE 8
+
+#define JPEG_MAX_COMPONENTS 4
+#define MAX_SETS_HUFFMAN_TABLES 2
+#define MAX_QUANT_TABLES 4
+
+#define TABLE_CLASS_DC  0
+#define TABLE_CLASS_AC  1
+#define TABLE_CLASS_NUM 2
+
+/* Marker Codes */
+#define CODE_SOF_BASELINE 0xC0
+#define CODE_SOF1         0xC1
+#define CODE_SOF2         0xC2
+#define CODE_SOF3         0xC3
+#define CODE_SOF5         0xC5
+#define CODE_SOF6         0xC6
+#define CODE_SOF7         0xC7
+#define CODE_SOF8         0xC8
+#define CODE_SOF9         0xC9
+#define CODE_SOF10        0xCA
+#define CODE_SOF11        0xCB
+#define CODE_SOF13        0xCD
+#define CODE_SOF14        0xCE
+#define CODE_SOF15        0xCF
+#define CODE_DHT          0xC4
+#define CODE_RST0         0xD0
+#define CODE_RST1         0xD1
+#define CODE_RST2         0xD2
+#define CODE_RST3         0xD3
+#define CODE_RST4         0xD4
+#define CODE_RST5         0xD5
+#define CODE_RST6         0xD6
+#define CODE_RST7         0xD7
+#define CODE_SOI          0xD8
+#define CODE_EOI          0xD9
+#define CODE_SOS          0xDA
+#define CODE_DQT          0xDB
+#define CODE_DRI          0xDD
+#define CODE_APP0         0xE0
+#define CODE_APP1         0xE1
+#define CODE_APP2         0xE2
+#define CODE_APP3         0xE3
+#define CODE_APP4         0xE4
+#define CODE_APP5         0xE5
+#define CODE_APP6         0xE6
+#define CODE_APP7         0xE7
+#define CODE_APP8         0xE8
+#define CODE_APP9         0xE9
+#define CODE_APP10        0xEA
+#define CODE_APP11        0xEB
+#define CODE_APP12        0xEC
+#define CODE_APP13        0xED
+#define CODE_APP14        0xEE
+#define CODE_APP15        0xEF
+#define CODE_M_DAC        0xCC
+#define CODE_COMMENT      0xFE
+
+enum bspp_exception_handler {
+	/* BSPP parse exception handler */
+	BSPP_EXCEPTION_HANDLER_NONE = 0x00,
+	/* Jump at exception (external use) */
+	BSPP_EXCEPTION_HANDLER_JUMP,
+	BSPP_EXCEPTION_HANDLER_FORCE32BITS = 0x7FFFFFFFU
+};
+
+struct components {
+	unsigned char identifier;
+	unsigned char horz_factor;
+	unsigned char vert_factor;
+	unsigned char quant_table;
+};
+
+struct jpeg_segment_sof {
+	unsigned char precision;
+	unsigned short height;
+	unsigned short width;
+	unsigned char component;
+	struct components components[JPEG_VDEC_MAX_COMPONENTS];
+};
+
+struct jpeg_segment_header {
+	unsigned char type;
+	unsigned short payload_size;
+};
+
+/*
+ * Read bitstream data that may LOOK like SCP
+ * (but in fact is regular data and should be read as such)
+ * @return 8bits read from the bitstream
+ */
+static unsigned char bspp_jpeg_readbyte_asdata(void *swsr_ctx)
+{
+	if (swsr_check_delim_or_eod(swsr_ctx) == SWSR_FOUND_DELIM) {
+		swsr_consume_delim(swsr_ctx, SWSR_EMPREVENT_NONE, 8, NULL);
+		return 0xFF;
+	} else {
+		return swsr_read_bits(swsr_ctx, 8);
+	}
+}
+
+/*
+ * Read bitstream data that may LOOK like SCP
+ * (but in fact be regular data should be read as such)
+ * @return 16bits read from the bitstream
+ */
+static unsigned short bspp_jpeg_readword_asdata(void *swsr_ctx)
+{
+	unsigned short byte1 = bspp_jpeg_readbyte_asdata(swsr_ctx);
+	unsigned short byte2 = bspp_jpeg_readbyte_asdata(swsr_ctx);
+
+	return (byte1 << 8 | byte2);
+}
+
+/*
+ * Access regular bitstream data that may LOOK like SCP
+ * (but in fact be regular data)
+ */
+static void bspp_jpeg_consume_asdata(void *swsr_ctx, int len)
+{
+	while (len > 0) {
+		bspp_jpeg_readbyte_asdata(swsr_ctx);
+		len--;
+	}
+}
+
+/*
+ * Parse SOF segment
+ */
+static enum bspp_error_type bspp_jpeg_segment_parse_sof(void *swsr_ctx,
+							struct jpeg_segment_sof *sof_header)
+{
+	unsigned char comp_ind;
+
+	sof_header->precision = swsr_read_bits(swsr_ctx, 8);
+	if (sof_header->precision != 8) {
+		pr_warn("Sample precision has invalid value %d\n",
+			sof_header->precision);
+		return BSPP_ERROR_INVALID_VALUE;
+	}
+
+	sof_header->height = bspp_jpeg_readword_asdata(swsr_ctx);
+	sof_header->width = bspp_jpeg_readword_asdata(swsr_ctx);
+	if (sof_header->height < JPEG_MCU_SIZE || sof_header->width < JPEG_MCU_SIZE) {
+		pr_warn("Sample X/Y smaller than macroblock\n");
+		return BSPP_ERROR_INVALID_VALUE;
+	}
+	sof_header->component = swsr_read_bits(swsr_ctx, 8);
+	if (sof_header->component > JPEG_MAX_COMPONENTS) {
+		pr_warn("Number of components (%d) is greater than max allowed\n",
+			sof_header->component);
+		return BSPP_ERROR_INVALID_VALUE;
+	}
+	/* parse the component */
+	for (comp_ind = 0; comp_ind < sof_header->component; comp_ind++) {
+		sof_header->components[comp_ind].identifier = swsr_read_bits(swsr_ctx, 8);
+		sof_header->components[comp_ind].horz_factor = swsr_read_bits(swsr_ctx, 4);
+		sof_header->components[comp_ind].vert_factor = swsr_read_bits(swsr_ctx, 4);
+		sof_header->components[comp_ind].quant_table = swsr_read_bits(swsr_ctx, 8);
+
+		pr_debug("components[%d]=(identifier=%d; horz_factor=%d; vert_factor=%d; quant_table=%d)",
+			 comp_ind,
+			 sof_header->components[comp_ind].identifier,
+			 sof_header->components[comp_ind].horz_factor,
+			 sof_header->components[comp_ind].vert_factor,
+			 sof_header->components[comp_ind].quant_table);
+	}
+
+	return BSPP_ERROR_NONE;
+}
+
+/*
+ * Seeks to delimeter if we're not already on one
+ */
+static enum swsr_found bspp_jpeg_tryseek_delimeter(void *swsr_ctx)
+{
+	enum swsr_found was_delim_or_eod = swsr_check_delim_or_eod(swsr_ctx);
+
+	if (was_delim_or_eod != SWSR_FOUND_DELIM)
+		was_delim_or_eod = swsr_seek_delim_or_eod(swsr_ctx);
+
+	return was_delim_or_eod;
+}
+
+static enum swsr_found bspp_jpeg_tryconsume_delimeters(void *swsr_ctx)
+{
+	enum swsr_found is_delim_or_eod = swsr_check_delim_or_eod(swsr_ctx);
+
+	while (is_delim_or_eod == SWSR_FOUND_DELIM) {
+		swsr_consume_delim(swsr_ctx, SWSR_EMPREVENT_NONE, 8, NULL);
+		is_delim_or_eod = swsr_check_delim_or_eod(swsr_ctx);
+	}
+	return is_delim_or_eod;
+}
+
+static enum swsr_found bspp_jpeg_tryseek_and_consume_delimeters(void *swsr_ctx)
+{
+	enum swsr_found is_delim_or_eod;
+
+	bspp_jpeg_tryseek_delimeter(swsr_ctx);
+	is_delim_or_eod = bspp_jpeg_tryconsume_delimeters(swsr_ctx);
+	return is_delim_or_eod;
+}
+
+/*
+ * Read segment type and size
+ * @return IMG_TRUE when header is found,
+ * IMG_FALSE if it has to be called again
+ */
+static unsigned char bspp_jpeg_segment_read_header(void *swsr_ctx,
+						   struct bspp_unit_data *unit_data,
+						   struct jpeg_segment_header *jpeg_segment_header)
+{
+	bspp_jpeg_tryconsume_delimeters(swsr_ctx);
+	jpeg_segment_header->type = swsr_read_bits(swsr_ctx, 8);
+
+	if (jpeg_segment_header->type != 0)
+		pr_debug("NAL=0x%x\n", jpeg_segment_header->type);
+
+	jpeg_segment_header->payload_size = 0;
+
+	switch (jpeg_segment_header->type) {
+	case CODE_SOS:
+	case CODE_DRI:
+	case CODE_SOF_BASELINE:
+	case CODE_SOF1:
+	case CODE_SOF2:
+	case CODE_SOF3:
+	case CODE_SOF5:
+	case CODE_SOF6:
+	case CODE_SOF7:
+	case CODE_SOF8:
+	case CODE_SOF9:
+	case CODE_SOF10:
+	case CODE_SOF11:
+	case CODE_SOF13:
+	case CODE_SOF14:
+	case CODE_SOF15:
+	case CODE_APP0:
+	case CODE_APP1:
+	case CODE_APP2:
+	case CODE_APP3:
+	case CODE_APP4:
+	case CODE_APP5:
+	case CODE_APP6:
+	case CODE_APP7:
+	case CODE_APP8:
+	case CODE_APP9:
+	case CODE_APP10:
+	case CODE_APP11:
+	case CODE_APP12:
+	case CODE_APP13:
+	case CODE_APP14:
+	case CODE_APP15:
+	case CODE_DHT:
+	case CODE_DQT:
+	case CODE_COMMENT:
+	{
+		jpeg_segment_header->payload_size =
+			bspp_jpeg_readword_asdata(swsr_ctx) - 2;
+	}
+	break;
+	case CODE_EOI:
+	case CODE_SOI:
+	case CODE_RST0:
+	case CODE_RST1:
+	case CODE_RST2:
+	case CODE_RST3:
+	case CODE_RST4:
+	case CODE_RST5:
+	case CODE_RST6:
+	case CODE_RST7:
+		/*
+		 * jpeg_segment_header->payload_size reset to 0 previously,
+		 * so just break.
+		 */
+		break;
+	case 0:
+	{
+		/*
+		 * Emulation prevention is OFF which means that 0 after
+		 * 0xff will not be swallowed
+		 * and has to be treated as data
+		 */
+		bspp_jpeg_tryseek_and_consume_delimeters(swsr_ctx);
+		return 0;
+	}
+	default:
+	{
+		pr_err("BAD NAL=%#x\n", jpeg_segment_header->type);
+		unit_data->parse_error |= BSPP_ERROR_UNRECOVERABLE;
+	}
+	}
+
+	pr_debug("payloadSize=%#x\n", jpeg_segment_header->payload_size);
+	return 1;
+}
+
+static void bspp_jpeg_calculate_mcus(struct jpeg_segment_sof *data_sof,
+				     unsigned char *alignment_width,
+				     unsigned char *alignment_height)
+{
+	unsigned char i;
+	unsigned char max_horz_factor = 0;
+	unsigned char max_vert_factor = 0;
+	unsigned short mcu_width = 0;
+	unsigned short mcu_height = 0;
+
+	/* Determine maximum scale factors */
+	for (i = 0; i < data_sof->component; i++) {
+		unsigned char horz_factor = data_sof->components[i].horz_factor;
+		unsigned char vert_factor = data_sof->components[i].vert_factor;
+
+		max_horz_factor = horz_factor > max_horz_factor ? horz_factor : max_horz_factor;
+		max_vert_factor = vert_factor > max_vert_factor ? vert_factor : max_vert_factor;
+	}
+	/*
+	 * Alignment we want to have must be:
+	 * - mutliple of VDEC_MB_DIMENSION
+	 * - at least of the size that will fit whole MCUs
+	 */
+	*alignment_width =
+		VDEC_ALIGN_SIZE((8 * max_horz_factor), VDEC_MB_DIMENSION,
+				unsigned int, unsigned int);
+	*alignment_height =
+		VDEC_ALIGN_SIZE((8 * max_vert_factor), VDEC_MB_DIMENSION,
+				unsigned int, unsigned int);
+
+	/* Calculate dimensions in MCUs */
+	mcu_width += (data_sof->width + (8 * max_horz_factor) - 1) / (8 * max_horz_factor);
+	mcu_height += (data_sof->height + (8 * max_vert_factor) - 1) / (8 * max_vert_factor);
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s; w=%d; w[MCU]=%d\n", __func__, data_sof->width, mcu_width);
+	pr_info("%s; h=%d; h[MCU]=%d\n", __func__, data_sof->height, mcu_height);
+#endif
+}
+
+static int bspp_jpeg_common_seq_hdr_populate(struct jpeg_segment_sof *sof_header,
+					     struct vdec_comsequ_hdrinfo *com_sequ_hdr_info,
+					     unsigned char alignment_width,
+					     unsigned char alignment_height)
+{
+	unsigned short i;
+	int res;
+	struct img_pixfmt_desc format_desc;
+
+	memset(&format_desc, 0, sizeof(struct img_pixfmt_desc));
+	memset(com_sequ_hdr_info, 0, sizeof(*com_sequ_hdr_info));
+
+	com_sequ_hdr_info->max_frame_size.width = VDEC_ALIGN_SIZE(sof_header->width,
+								  alignment_width,
+								  unsigned int, unsigned int);
+	com_sequ_hdr_info->max_frame_size.height = VDEC_ALIGN_SIZE(sof_header->height,
+								   alignment_height, unsigned int,
+								   unsigned int);
+	com_sequ_hdr_info->frame_size.width = sof_header->width;
+	com_sequ_hdr_info->frame_size.height = sof_header->height;
+	com_sequ_hdr_info->orig_display_region.width = sof_header->width;
+	com_sequ_hdr_info->orig_display_region.height = sof_header->height;
+
+	com_sequ_hdr_info->pixel_info.bitdepth_y = 8;
+	com_sequ_hdr_info->pixel_info.bitdepth_c = 8;
+	com_sequ_hdr_info->pixel_info.num_planes = sof_header->component;
+	/*  actually we have to set foramt accroding to the following table
+	 * H1    V1    H2    V2    H3    V3    J:a:b     h/v
+	 * 1     1     1     1     1     1     4:4:4     1/1
+	 * 1     2     1     1     1     1     4:4:0     1/2
+	 * 1     4     1     1     1     1     4:4:1*     1/4
+	 * 1     4     1     2     1     2     4:4:0     1/2
+	 * 2     1     1     1     1     1     4:2:2     2/1
+	 * 2     2     1     1     1     1     4:2:0     2/2
+	 * 2     2     2     1     2     1     4:4:0     1/2
+	 * 2     4     1     1     1     1     4:2:1*     2/4
+	 * 4     1     1     1     1     1     4:1:1     4/1
+	 * 4     1     2     1     2     1     4:2:2     2/1
+	 * 4     2     1     1     1     1     4:1:0     4/2
+	 * 4     4     2     2     2     2     4:2:0     2/2
+	 */
+	if (sof_header->component == (JPEG_MAX_COMPONENTS - 1)) {
+		com_sequ_hdr_info->pixel_info.chroma_fmt = PIXEL_MULTICHROME;
+		if ((sof_header->components[1].horz_factor == 1 &&
+		     sof_header->components[1].vert_factor == 1) &&
+		    (sof_header->components[2].horz_factor == 1 &&
+		     sof_header->components[2].vert_factor == 1)) {
+			if (sof_header->components[0].horz_factor == 1 &&
+			    sof_header->components[0].vert_factor == 1) {
+				com_sequ_hdr_info->pixel_info.chroma_fmt_idc = PIXEL_FORMAT_444;
+			} else if (sof_header->components[0].horz_factor == 2) {
+				if (sof_header->components[0].vert_factor == 1) {
+					com_sequ_hdr_info->pixel_info.chroma_fmt_idc =
+						PIXEL_FORMAT_422;
+				} else if (sof_header->components[0].vert_factor == 2) {
+					com_sequ_hdr_info->pixel_info.chroma_fmt_idc =
+						PIXEL_FORMAT_420;
+				} else {
+					com_sequ_hdr_info->pixel_info.chroma_fmt_idc =
+						PIXEL_FORMAT_444;
+				}
+			} else if ((sof_header->components[0].horz_factor == 4) &&
+				   (sof_header->components[0].vert_factor == 1)) {
+				com_sequ_hdr_info->pixel_info.chroma_fmt_idc = PIXEL_FORMAT_411;
+			} else {
+				com_sequ_hdr_info->pixel_info.chroma_fmt_idc = PIXEL_FORMAT_444;
+			}
+		} else {
+			com_sequ_hdr_info->pixel_info.chroma_fmt_idc = PIXEL_FORMAT_444;
+		}
+	} else {
+		com_sequ_hdr_info->pixel_info.chroma_fmt = PIXEL_MONOCHROME;
+		com_sequ_hdr_info->pixel_info.chroma_fmt_idc = PIXEL_FORMAT_MONO;
+	}
+
+	for (i = 0; (i < sof_header->component) && (i < IMG_MAX_NUM_PLANES); i++) {
+		format_desc.planes[i] = 1;
+		format_desc.h_numer[i] = sof_header->components[i].horz_factor;
+		format_desc.v_numer[i] = sof_header->components[i].vert_factor;
+	}
+
+	res = pixel_gen_pixfmt(&com_sequ_hdr_info->pixel_info.pixfmt, &format_desc);
+	if (res != 0) {
+		pr_err("Failed to generate pixel format.\n");
+		return res;
+	}
+
+	return 0;
+}
+
+static void bspp_jpeg_pict_hdr_populate(struct jpeg_segment_sof *sof_header,
+					struct bspp_pict_hdr_info *pict_hdr_info)
+{
+	memset(pict_hdr_info, 0, sizeof(*pict_hdr_info));
+
+	pict_hdr_info->intra_coded = 1;
+	pict_hdr_info->ref = 0;
+
+	pict_hdr_info->coded_frame_size.width = (unsigned int)sof_header->width;
+	pict_hdr_info->coded_frame_size.height = (unsigned int)sof_header->height;
+	pict_hdr_info->disp_info.enc_disp_region.width = (unsigned int)sof_header->width;
+	pict_hdr_info->disp_info.enc_disp_region.height = (unsigned int)sof_header->height;
+
+	pict_hdr_info->pict_aux_data.id = BSPP_INVALID;
+	pict_hdr_info->second_pict_aux_data.id = BSPP_INVALID;
+	pict_hdr_info->pict_sgm_data.id = BSPP_INVALID;
+}
+
+static int bspp_jpeg_parse_picture_unit(void *swsr_ctx,
+					struct bspp_unit_data *unit_data)
+{
+	/* assume we'll be fine */
+	unit_data->parse_error = BSPP_ERROR_NONE;
+
+	while ((unit_data->parse_error == BSPP_ERROR_NONE) &&
+	       !(unit_data->slice || unit_data->extracted_all_data)) {
+		struct jpeg_segment_header segment_header;
+		/*
+		 *  Try hard to read segment header. The only limit we set here is EOD-
+		 *  if it happens, we will get an exception, to stop this madness.
+		 */
+		while (!bspp_jpeg_segment_read_header(swsr_ctx, unit_data, &segment_header) &&
+		       unit_data->parse_error == BSPP_ERROR_NONE)
+			;
+
+		switch (segment_header.type) {
+		case CODE_SOF1:
+		case CODE_SOF2:
+		case CODE_SOF3:
+		case CODE_SOF5:
+		case CODE_SOF6:
+		case CODE_SOF8:
+		case CODE_SOF9:
+		case CODE_SOF10:
+		case CODE_SOF11:
+		case CODE_SOF13:
+		case CODE_SOF14:
+		case CODE_SOF15:
+		{
+			bspp_jpeg_consume_asdata(swsr_ctx, segment_header.payload_size);
+			bspp_jpeg_tryseek_delimeter(swsr_ctx);
+			unit_data->extracted_all_data = 1;
+			unit_data->slice = 1;
+			unit_data->parse_error |= BSPP_ERROR_UNSUPPORTED;
+			return IMG_ERROR_NOT_SUPPORTED;
+		}
+		case CODE_SOI:
+		{
+			/*
+			 * Reinitialize context at the beginning of each image
+			 */
+		}
+		break;
+		case CODE_EOI:
+		{
+			/*
+			 * Some more frames can be concatenated after SOI,
+			 * but we'll discard it for now
+			 */
+			while (bspp_jpeg_tryseek_and_consume_delimeters(swsr_ctx) != SWSR_FOUND_EOD)
+				;
+			unit_data->extracted_all_data = 1;
+			return 0;
+		}
+		case CODE_SOF_BASELINE:
+		{
+			int res;
+			unsigned char alignment_width = 0;
+			unsigned char alignment_height = 0;
+			struct jpeg_segment_sof sof_data;
+
+			struct bspp_sequ_hdr_info *sequ_hdr_info =
+				&unit_data->impl_sequ_hdr_info->sequ_hdr_info;
+
+			memset(&sof_data, 0, sizeof(*&sof_data));
+
+			/* SOF is the only segment we are interested in- parse it */
+			unit_data->parse_error |= bspp_jpeg_segment_parse_sof(swsr_ctx, &sof_data);
+			/*
+			 * to correctly allocate size for frame we need to have correct MCUs to
+			 * get alignment info
+			 */
+			bspp_jpeg_calculate_mcus(&sof_data, &alignment_width, &alignment_height);
+
+			/* fill in headers expected by BSPP framework */
+			res = bspp_jpeg_common_seq_hdr_populate(&sof_data,
+								&sequ_hdr_info->com_sequ_hdr_info,
+								alignment_width,
+								alignment_height);
+			if (res != 0) {
+				unit_data->parse_error |= BSPP_ERROR_UNRECOVERABLE;
+				return res;
+			}
+
+			bspp_jpeg_pict_hdr_populate(&sof_data, unit_data->out.pict_hdr_info);
+
+			/* fill in sequence IDs for header and picture */
+			sequ_hdr_info->sequ_hdr_id = BSPP_DEFAULT_SEQUENCE_ID;
+			unit_data->pict_sequ_hdr_id = BSPP_DEFAULT_SEQUENCE_ID;
+
+			/* reset SOS fields counter value */
+			unit_data->out.pict_hdr_info->sos_count = 0;
+		}
+		break;
+		case CODE_SOS:
+		{
+			/* increment the SOS fields counter */
+			unit_data->out.pict_hdr_info->sos_count++;
+
+			unit_data->slice = 1;
+			bspp_jpeg_consume_asdata(swsr_ctx, segment_header.payload_size);
+			return 0;
+		}
+		case CODE_DRI:
+			break;
+		default:
+		{
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("Skipping over 0x%x bytes\n", segment_header.payload_size);
+#endif
+			bspp_jpeg_consume_asdata(swsr_ctx, segment_header.payload_size);
+		}
+		break;
+		}
+		/*
+		 * After parsing segment we should already be on delimeter.
+		 * Consume it, so header parsing can be started.
+		 */
+		bspp_jpeg_tryseek_and_consume_delimeters(swsr_ctx);
+	}
+	return 0;
+}
+
+int bspp_jpeg_unit_parser(void *swsr_ctx, struct bspp_unit_data *unit_data)
+{
+	int retval = 0;
+
+	switch (unit_data->unit_type) {
+	case BSPP_UNIT_PICTURE:
+	{
+		retval = bspp_jpeg_parse_picture_unit(swsr_ctx, unit_data);
+		unit_data->new_closed_gop = 1;
+	}
+	break;
+	default:
+	{
+		unit_data->parse_error = BSPP_ERROR_INVALID_VALUE;
+	}
+	break;
+	}
+
+	return retval;
+}
+
+int bspp_jpeg_setparser_config(enum vdec_bstr_format bstr_format,
+			       struct bspp_vid_std_features *pvidstd_features,
+			       struct bspp_swsr_ctx *pswsr_ctx,
+			       struct bspp_parser_callbacks *pparser_callbacks,
+			       struct bspp_inter_pict_data *pinterpict_data)
+{
+	/* Set JPEG parser callbacks. */
+	pparser_callbacks->parse_unit_cb = bspp_jpeg_unit_parser;
+
+	/* Set JPEG specific features. */
+	pvidstd_features->seq_size = sizeof(struct bspp_jpeg_sequ_hdr_info);
+	pvidstd_features->uses_vps  = 0;
+	pvidstd_features->uses_pps  = 0;
+
+	/* Set JPEG specific shift register config. */
+	pswsr_ctx->emulation_prevention = SWSR_EMPREVENT_NONE;
+	pswsr_ctx->sr_config.delim_type = SWSR_DELIM_SCP;
+	pswsr_ctx->sr_config.delim_length = 8;
+	pswsr_ctx->sr_config.scp_value = 0xFF;
+
+	return 0;
+}
+
+void bspp_jpeg_determine_unit_type(unsigned char bitstream_unittype,
+				   int disable_mvc,
+				   enum bspp_unit_type *bspp_unittype)
+{
+	*bspp_unittype = BSPP_UNIT_PICTURE;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/jpeg_secure_parser.h b/drivers/media/platform/img/vxe-vxd/decoder/jpeg_secure_parser.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/jpeg_secure_parser.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/jpeg_secure_parser.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * JPEG secure data unit parsing API.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef __JPEGSECUREPARSER_H__
+#define __JPEGSECUREPARSER_H__
+
+#include "bspp_int.h"
+
+/**
+ * struct bspp_jpeg_sequ_hdr_info - bspp_jpeg_sequ_hdr_info dummu structure
+ * @dummy: dummy structure
+ */
+struct bspp_jpeg_sequ_hdr_info {
+	unsigned int dummy;
+};
+
+int bspp_jpeg_setparser_config(enum vdec_bstr_format bstr_format,
+			       struct bspp_vid_std_features *pvidstd_features,
+			       struct bspp_swsr_ctx *pswsr_ctx,
+			       struct bspp_parser_callbacks *pparser_callbacks,
+			       struct bspp_inter_pict_data *pinterpict_data);
+
+void bspp_jpeg_determine_unit_type(unsigned char bitstream_unittype,
+				   int disable_mvc,
+				   enum bspp_unit_type *bspp_unittype);
+
+#endif /*__JPEGSECUREPARSER_H__ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/mem_io.h b/drivers/media/platform/img/vxe-vxd/decoder/mem_io.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/mem_io.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/mem_io.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG PVDEC pixel Registers
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _MEM_IO_H
+#define _MEM_IO_H
+
+#include <linux/types.h>
+
+#include "reg_io2.h"
+
+#define MEMIO_CHECK_ALIGNMENT(vpmem)        \
+	IMG_ASSERT((vpmem))
+
+#define MEMIO_READ_FIELD(vpmem, field) \
+	((((*((field ## _TYPE *)(((unsigned long)(vpmem)) + field ## _OFFSET))) & \
+	   field ## _MASK) >> field ## _SHIFT))
+
+#define MEMIO_WRITE_FIELD(vpmem, field, value, type) \
+	do { \
+		type __vpmem = vpmem; \
+		MEMIO_CHECK_ALIGNMENT(__vpmem); \
+		(*((field ## _TYPE *)(((unsigned long)(__vpmem)) + \
+				      field ## _OFFSET))) = \
+			(field ## _TYPE)(((*((field ## _TYPE *)(((unsigned long)(__vpmem)) + \
+								field ## _OFFSET))) & \
+					  ~(field ## _TYPE)field ## _MASK) | \
+					 (field ## _TYPE)(((value) << field ## _SHIFT) & \
+							  field ## _MASK)); \
+	} while (0) \
+
+#endif /* _MEM_IO_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/mmu_defs.h b/drivers/media/platform/img/vxe-vxd/decoder/mmu_defs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/mmu_defs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/mmu_defs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * V-DEC MMU Definitions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ */
+
+#ifndef _VXD_MMU_DEF_H_
+#define _VXD_MMU_DEF_H_
+
+/*
+ * This type defines MMU variant.
+ */
+enum mmu_etype {
+	MMU_TYPE_NONE        = 0,
+	MMU_TYPE_32BIT,
+	MMU_TYPE_36BIT,
+	MMU_TYPE_40BIT,
+	MMU_TYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/**
+ * enum mmu_eheap_id - This type defines the MMU heaps.
+ * @MMU_HEAP_IMAGE_BUFFERS_UNTILED: Heap for untiled video buffers
+ * @MMU_HEAP_BITSTREAM_BUFFERS : Heap for bitstream buffers
+ * @MMU_HEAP_STREAM_BUFFERS : Heap for Stream buffers
+ * @MMU_HEAP_MAX : Number of heaps
+ * @MMU_HEAP_FORCE32BITS: MMU_HEAP_FORCE32BITS
+ */
+enum mmu_eheap_id {
+	MMU_HEAP_IMAGE_BUFFERS_UNTILED = 0x00,
+	MMU_HEAP_BITSTREAM_BUFFERS,
+	MMU_HEAP_STREAM_BUFFERS,
+	MMU_HEAP_MAX,
+	MMU_HEAP_FORCE32BITS           = 0x7FFFFFFFU
+};
+
+#endif /* _VXD_MMU_DEFS_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/pixel_api.c b/drivers/media/platform/img/vxe-vxd/decoder/pixel_api.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/pixel_api.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/pixel_api.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,895 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pixel processing function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "img_errors.h"
+#include "img_pixfmts.h"
+#include "pixel_api.h"
+#include "vdec_defs.h"
+
+#define NUM_OF_FORMATS 17
+#define PIXNAME(x) /* Pixel name support not enabled */
+#define FACT_SPEC_FORMAT_NUM_PLANES 4
+#define FACT_SPEC_FORMAT_PLANE_UNUSED 0xf
+#define FACT_SPEC_FORMAT_PLANE_CODE_BITS 4
+#define FACT_SPEC_FORMAT_PLANE_CODE_MASK 3
+#define FACT_SPEC_FORMAT_MIN_FACT_VAL 1
+
+/*
+ * @brief Pointer to the default format in the asPixelFormats array
+ * default format is an invalid format
+ * @note pointer set by initSearch()
+ * This pointer is also used to know if the arrays were sorted
+ */
+static struct pixel_pixinfo *def_fmt;
+
+/*
+ * @brief Actual array storing the pixel formats information.
+ */
+static struct pixel_pixinfo pix_fmts[NUM_OF_FORMATS] = {
+	{
+		IMG_PIXFMT_420PL12YUV8,
+		PIXEL_UV_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT8_MP,
+		PIXEL_FORMAT_420,
+		8,
+		8,
+		2
+	},
+
+	{
+		IMG_PIXFMT_420PL12YVU8,
+		PIXEL_VU_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT8_MP,
+		PIXEL_FORMAT_420,
+		8,
+		8,
+		2
+	},
+
+	{
+		IMG_PIXFMT_420PL12YUV10,
+		PIXEL_UV_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT10_MP,
+		PIXEL_FORMAT_420,
+		10,
+		10,
+		2
+	},
+
+	{
+		IMG_PIXFMT_420PL12YVU10,
+		PIXEL_VU_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT10_MP,
+		PIXEL_FORMAT_420,
+		10,
+		10,
+		2
+	},
+
+	{
+		IMG_PIXFMT_420PL12YUV10_MSB,
+		PIXEL_UV_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT10_MSB_MP,
+		PIXEL_FORMAT_420,
+		10,
+		10,
+		2
+	},
+
+	{
+		IMG_PIXFMT_420PL12YVU10_MSB,
+		PIXEL_VU_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT10_MSB_MP,
+		PIXEL_FORMAT_420,
+		10,
+		10,
+		2
+	},
+
+	{
+		IMG_PIXFMT_420PL12YUV10_LSB,
+		PIXEL_UV_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT10_LSB_MP,
+		PIXEL_FORMAT_420,
+		10,
+		10,
+		2
+	},
+
+	{
+		IMG_PIXFMT_420PL12YVU10_LSB,
+		PIXEL_VU_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT10_LSB_MP,
+		PIXEL_FORMAT_420,
+		10,
+		10,
+		2
+	},
+
+	{
+		IMG_PIXFMT_422PL12YUV8,
+		PIXEL_UV_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT8_MP,
+		PIXEL_FORMAT_422,
+		8,
+		8,
+		2
+	},
+
+	{
+		IMG_PIXFMT_422PL12YVU8,
+		PIXEL_VU_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT8_MP,
+		PIXEL_FORMAT_422,
+		8,
+		8,
+		2
+	},
+
+	{
+		IMG_PIXFMT_422PL12YUV10,
+		PIXEL_UV_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT10_MP,
+		PIXEL_FORMAT_422,
+		10,
+		10,
+		2
+	},
+
+	{
+		IMG_PIXFMT_422PL12YVU10,
+		PIXEL_VU_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT10_MP,
+		PIXEL_FORMAT_422,
+		10,
+		10,
+		2
+	},
+
+	{
+		IMG_PIXFMT_422PL12YUV10_MSB,
+		PIXEL_UV_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT10_MSB_MP,
+		PIXEL_FORMAT_422,
+		10,
+		10,
+		2
+	},
+
+	{
+		IMG_PIXFMT_422PL12YVU10_MSB,
+		PIXEL_VU_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT10_MSB_MP,
+		PIXEL_FORMAT_422,
+		10,
+		10,
+		2
+	},
+
+	{
+		IMG_PIXFMT_422PL12YUV10_LSB,
+		PIXEL_UV_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT10_LSB_MP,
+		PIXEL_FORMAT_422,
+		10,
+		10,
+		2
+	},
+
+	{
+		IMG_PIXFMT_422PL12YVU10_LSB,
+		PIXEL_VU_ORDER,
+		PIXEL_MULTICHROME,
+		PIXEL_BIT10_LSB_MP,
+		PIXEL_FORMAT_422,
+		10,
+		10,
+		2
+	},
+
+	{
+		IMG_PIXFMT_UNDEFINED,
+		PIXEL_INVALID_CI,
+		0,
+		(enum pixel_mem_packing)0,
+		PIXEL_FORMAT_INVALID,
+		0,
+		0,
+		0
+	}
+};
+
+static struct pixel_pixinfo_table pixinfo_table[] = {
+	{
+		IMG_PIXFMT_420PL12YUV8_A8,
+		{
+			PIXNAME(IMG_PIXFMT_420PL12YUV8_A8)
+			16,
+			16,
+			16,
+			0,
+			16,
+			TRUE,
+			TRUE,
+			4,
+			TRUE
+		}
+	},
+
+	{
+		IMG_PIXFMT_422PL12YUV8_A8,
+		{
+			PIXNAME(IMG_PIXFMT_422PL12YUV8_A8)
+			16,
+			16,
+			16,
+			0,
+			16,
+			TRUE,
+			FALSE,
+			4,
+			TRUE
+		}
+	},
+
+	{
+		IMG_PIXFMT_420PL12YUV8,
+		{
+			PIXNAME(IMG_PIXFMT_420PL12YUV8)
+			16,
+			16,
+			16,
+			0,
+			0,
+			TRUE,
+			TRUE,
+			4,
+			FALSE
+		}
+	},
+
+	{
+		IMG_PIXFMT_420PL12YVU8,
+		{
+			PIXNAME(IMG_PIXFMT_420PL12YVU8)
+			16,
+			16,
+			16,
+			0,
+			0,
+			TRUE,
+			TRUE,
+			4,
+			FALSE
+		}
+	},
+
+	{
+		IMG_PIXFMT_420PL12YUV10,
+		{
+			PIXNAME(IMG_PIXFMT_420PL12YUV10)
+			12,
+			16,
+			16,
+			0,
+			0,
+			TRUE,
+			TRUE,
+			4,
+			FALSE
+		}
+	},
+
+	{
+		IMG_PIXFMT_420PL12YVU10,
+		{
+			PIXNAME(IMG_PIXFMT_420PL12YVU10)
+			12,
+			16,
+			16,
+			0,
+			0,
+			TRUE,
+			TRUE,
+			4,
+			FALSE
+		}
+	},
+
+	{
+		IMG_PIXFMT_420PL12YUV10_MSB,
+		{
+			PIXNAME(IMG_PIXFMT_420PL12YUV10_MSB)
+			8,
+			16,
+			16,
+			0,
+			0,
+			TRUE,
+			TRUE,
+			4,
+			FALSE
+		}
+	},
+
+	{
+		IMG_PIXFMT_420PL12YVU10_MSB,
+		{
+			PIXNAME(IMG_PIXFMT_420PL12YVU10_MSB)
+			8,
+			16,
+			16,
+			0,
+			0,
+			TRUE,
+			TRUE,
+			4,
+			FALSE
+		}
+	},
+
+	{
+		IMG_PIXFMT_422PL12YUV8,
+		{
+			PIXNAME(IMG_PIXFMT_422PL12YUV8)
+			16,
+			16,
+			16,
+			0,
+			0,
+			TRUE,
+			FALSE,
+			4,
+			FALSE
+		}
+	},
+
+	{
+		IMG_PIXFMT_422PL12YVU8,
+		{
+			PIXNAME(IMG_PIXFMT_422PL12YVU8)
+			16,
+			16,
+			16,
+			0,
+			0,
+			TRUE,
+			FALSE,
+			4,
+			FALSE
+		}
+	},
+
+	{
+		IMG_PIXFMT_422PL12YUV10,
+		{
+			PIXNAME(IMG_PIXFMT_422PL12YUV10)
+			12,
+			16,
+			16,
+			0,
+			0,
+			TRUE,
+			FALSE,
+			4,
+			FALSE
+		}
+	},
+
+	{
+		IMG_PIXFMT_422PL12YVU10,
+		{
+			PIXNAME(IMG_PIXFMT_422PL12YVU10)
+			12,
+			16,
+			16,
+			0,
+			0,
+			TRUE,
+			FALSE,
+			4,
+			FALSE
+		}
+	},
+
+	{
+		IMG_PIXFMT_422PL12YUV10_MSB,
+		{
+			PIXNAME(IMG_PIXFMT_422PL12YUV10_MSB)
+			8,
+			16,
+			16,
+			0,
+			0,
+			TRUE,
+			FALSE,
+			4,
+			FALSE
+		}
+	},
+
+	{
+		IMG_PIXFMT_422PL12YVU10_MSB,
+		{
+			PIXNAME(IMG_PIXFMT_422PL12YVU10_MSB)
+			8,
+			16,
+			16,
+			0,
+			0,
+			TRUE,
+			FALSE,
+			4,
+			FALSE
+		}
+	},
+};
+
+static struct pixel_pixinfo_table*
+pixel_get_pixelinfo_from_pixfmt(enum img_pixfmt pix_fmt)
+{
+	unsigned int i;
+	unsigned char found = FALSE;
+	struct pixel_pixinfo_table *this_pixinfo_table_entry = NULL;
+
+	for (i = 0;
+		i < (sizeof(pixinfo_table) / sizeof(struct pixel_pixinfo_table));
+		i++) {
+		if (pix_fmt ==  pixinfo_table[i].pix_color_fmt) {
+			/*
+			 * There must only be one entry per pixel colour format
+			 * in the table
+			 */
+			VDEC_ASSERT(!found);
+			found = TRUE;
+			this_pixinfo_table_entry = &pixinfo_table[i];
+
+			/*
+			 * We deliberately do NOT break here - scan rest of
+			 * table to ensure there are not duplicate entries
+			 */
+		}
+	}
+	return this_pixinfo_table_entry;
+}
+
+/*
+ * @brief Array containing string lookup of pixel format IDC.
+ * @warning this must be kept in step with PIXEL_FormatIdc.
+ */
+unsigned char pix_fmt_idc_names[6][16] = {
+	"Monochrome",
+	"4:1:1",
+	"4:2:0",
+	"4:2:2",
+	"4:4:4",
+	"Invalid",
+};
+
+static int pixel_compare_pixfmts(const void *a, const void *b)
+{
+	return ((struct pixel_pixinfo *)a)->pixfmt -
+	       ((struct pixel_pixinfo *)b)->pixfmt;
+}
+
+static struct pixel_info*
+pixel_get_bufinfo_from_pixfmt(enum img_pixfmt pix_fmt)
+{
+	struct pixel_pixinfo_table *pixinfo_table_entry = NULL;
+	struct pixel_info *pix_info = NULL;
+
+	pixinfo_table_entry = pixel_get_pixelinfo_from_pixfmt(pix_fmt);
+	VDEC_ASSERT(pixinfo_table_entry);
+	if (pixinfo_table_entry)
+		pix_info = &pixinfo_table_entry->info;
+
+	return pix_info;
+}
+
+/*
+ * @brief Search a pixel format based on its attributes rather than its format
+ * enum.
+ * @warning use PIXEL_Comparpix_fmts to search by enum
+ */
+static int pixel_compare_pixinfo(const void *a, const void *b)
+{
+	int result = 0;
+	const struct pixel_pixinfo *fmt_a = (struct pixel_pixinfo *)a;
+	const struct pixel_pixinfo *fmt_b = (struct pixel_pixinfo *)b;
+
+	result = fmt_a->chroma_fmt_idc - fmt_b->chroma_fmt_idc;
+	if (result != 0)
+		return result;
+
+	result = fmt_a->mem_pkg - fmt_b->mem_pkg;
+	if (result != 0)
+		return result;
+
+	result = fmt_a->chroma_interleave - fmt_b->chroma_interleave;
+	if (result != 0)
+		return result;
+
+	result = fmt_a->bitdepth_y - fmt_b->bitdepth_y;
+	if (result != 0)
+		return result;
+
+	result = fmt_a->bitdepth_c - fmt_b->bitdepth_c;
+	if (result != 0)
+		return result;
+
+	result = fmt_a->num_planes - fmt_b->num_planes;
+	if (result != 0)
+		return result;
+
+	return result;
+}
+
+static void pixel_init_search(void)
+{
+	static unsigned int search_inited;
+
+	search_inited++;
+	if (search_inited == 1) {
+		if (!def_fmt) {
+			int i = 0;
+
+			i = NUM_OF_FORMATS - 1;
+			while (i >= 0) {
+				if (IMG_PIXFMT_UNDEFINED ==
+					pix_fmts[i].pixfmt) {
+					def_fmt = &pix_fmts[i];
+					break;
+				}
+			}
+			VDEC_ASSERT(def_fmt);
+		}
+	} else {
+		search_inited--;
+	}
+}
+
+static struct pixel_pixinfo *pixel_search_fmt(const struct pixel_pixinfo *key,
+					      unsigned char enum_only)
+{
+	struct pixel_pixinfo *fmt_found = NULL;
+	int (*compar)(const void *pixfmt1, const void *pixfmt2);
+
+	if (enum_only)
+		compar = &pixel_compare_pixfmts;
+	else
+		compar = &pixel_compare_pixinfo;
+
+	{
+		unsigned int i;
+
+		for (i = 0; i < NUM_OF_FORMATS; i++) {
+			if (compar(key, &pix_fmts[i]) == 0) {
+				fmt_found = &pix_fmts[i];
+				break;
+			}
+		}
+	}
+	return fmt_found;
+}
+
+/*
+ * @brief Set a pixel format info structure to the default.
+ * @warning This MODIDIFES the pointer therefore you shouldn't
+ * call it on pointer you got from the library!
+ */
+static void pixel_pixinfo_defaults(struct pixel_pixinfo *to_def)
+{
+	if (!def_fmt)
+		pixel_init_search();
+
+	memcpy(to_def, def_fmt, sizeof(struct pixel_pixinfo));
+}
+
+enum img_pixfmt pixel_get_pixfmt(enum pixel_fmt_idc chroma_fmt_idc,
+				 enum pixel_chroma_interleaved
+				 chroma_interleaved,
+				 enum pixel_mem_packing mem_pkg,
+				 unsigned int bitdepth_y, unsigned int bitdepth_c,
+				 unsigned int num_planes)
+{
+	unsigned int internal_num_planes = (num_planes == 0 || num_planes > 4) ? 2 :
+		num_planes;
+	struct pixel_pixinfo key;
+	struct pixel_pixinfo *fmt_found = NULL;
+
+	if (chroma_fmt_idc != PIXEL_FORMAT_MONO &&
+	    chroma_fmt_idc != PIXEL_FORMAT_411 &&
+	    chroma_fmt_idc != PIXEL_FORMAT_420 &&
+	    chroma_fmt_idc != PIXEL_FORMAT_422 &&
+	    chroma_fmt_idc != PIXEL_FORMAT_444)
+		return IMG_PIXFMT_UNDEFINED;
+
+	/* valid bit depth 8, 9, 10, or 16/0 for 422 */
+	if (bitdepth_y < 8 || bitdepth_y > 10)
+		return IMG_PIXFMT_UNDEFINED;
+
+	/* valid bit depth 8, 9, 10, or 16/0 for 422 */
+	if (bitdepth_c < 8 || bitdepth_c > 10)
+		return IMG_PIXFMT_UNDEFINED;
+
+	key.pixfmt = IMG_PIXFMT_UNDEFINED;
+	key.chroma_fmt_idc = chroma_fmt_idc;
+	key.chroma_interleave = chroma_interleaved;
+	key.mem_pkg = mem_pkg;
+	key.bitdepth_y = bitdepth_y;
+	key.bitdepth_c = bitdepth_c;
+	key.num_planes = internal_num_planes;
+
+	/*
+	 * 9 and 10 bits formats are handled in the same way, and there is only
+	 * one entry in the PixelFormat table
+	 */
+	if (key.bitdepth_y == 9)
+		key.bitdepth_y = 10;
+
+	/*
+	 * 9 and 10 bits formats are handled in the same way, and there is only
+	 * one entry in the PixelFormat table
+	 */
+	if (key.bitdepth_c == 9)
+		key.bitdepth_c = 10;
+
+	pixel_init_search();
+
+	/* do not search by format */
+	fmt_found = pixel_search_fmt(&key, FALSE);
+	if (!fmt_found)
+		return IMG_PIXFMT_UNDEFINED;
+
+	return fmt_found->pixfmt;
+}
+
+static void pixel_get_internal_pixelinfo(struct pixel_pixinfo *pixinfo,
+					 struct pixel_info *pix_bufinfo)
+{
+	if (pixinfo->bitdepth_y == 8 && pixinfo->bitdepth_c == 8)
+		pix_bufinfo->pixels_in_bop = 16;
+	else if (pixinfo->mem_pkg == PIXEL_BIT10_MP)
+		pix_bufinfo->pixels_in_bop = 12;
+	else
+		pix_bufinfo->pixels_in_bop = 8;
+
+	if (pixinfo->bitdepth_y == 8)
+		pix_bufinfo->ybytes_in_bop = pix_bufinfo->pixels_in_bop;
+	else
+		pix_bufinfo->ybytes_in_bop = 16;
+
+	if (pixinfo->chroma_fmt_idc == PIXEL_FORMAT_MONO) {
+		pix_bufinfo->uvbytes_in_bop = 0;
+	} else if (pixinfo->bitdepth_c == 8) {
+		pix_bufinfo->uvbytes_in_bop = pix_bufinfo->pixels_in_bop;
+		if (pixinfo->chroma_fmt_idc == PIXEL_FORMAT_422 && pixinfo->num_planes == 1) {
+			pix_bufinfo->uvbytes_in_bop = 0;
+			pix_bufinfo->pixels_in_bop = 8;
+		}
+	} else {
+		pix_bufinfo->uvbytes_in_bop = 16;
+	}
+
+	if (pixinfo->chroma_fmt_idc == PIXEL_FORMAT_444)
+		pix_bufinfo->uvbytes_in_bop *= 2;
+
+	if (pixinfo->chroma_interleave == PIXEL_INVALID_CI) {
+		pix_bufinfo->uvbytes_in_bop /= 2;
+		pix_bufinfo->vbytes_in_bop = pix_bufinfo->uvbytes_in_bop;
+	} else {
+		pix_bufinfo->vbytes_in_bop = 0;
+	}
+
+	pix_bufinfo->alphabytes_in_bop = 0;
+
+	if (pixinfo->num_planes == 1)
+		pix_bufinfo->is_planar = FALSE;
+	else
+		pix_bufinfo->is_planar = TRUE;
+
+	if (pixinfo->chroma_fmt_idc == PIXEL_FORMAT_420)
+		pix_bufinfo->uv_height_halved = TRUE;
+	else
+		pix_bufinfo->uv_height_halved = FALSE;
+
+	if (pixinfo->chroma_fmt_idc == PIXEL_FORMAT_444)
+		pix_bufinfo->uv_stride_ratio_times4 = 8;
+	else
+		pix_bufinfo->uv_stride_ratio_times4 = 4;
+
+	if (pixinfo->chroma_interleave == PIXEL_INVALID_CI)
+		pix_bufinfo->uv_stride_ratio_times4 /= 2;
+
+	pix_bufinfo->has_alpha = FALSE;
+}
+
+static void pixel_yuv_get_descriptor_int(struct pixel_info *pixinfo,
+					 struct img_pixfmt_desc  *pix_desc)
+{
+	pix_desc->bop_denom = pixinfo->pixels_in_bop;
+	pix_desc->h_denom = (pixinfo->uv_stride_ratio_times4 == 2 ||
+		!pixinfo->is_planar) ? 2 : 1;
+	pix_desc->v_denom = (pixinfo->uv_height_halved || !pixinfo->is_planar)
+		? 2 : 1;
+
+	pix_desc->planes[0] = TRUE;
+	pix_desc->bop_numer[0] = pixinfo->ybytes_in_bop;
+	pix_desc->h_numer[0] = pix_desc->h_denom;
+	pix_desc->v_numer[0] = pix_desc->v_denom;
+
+	pix_desc->planes[1] = pixinfo->is_planar;
+	pix_desc->bop_numer[1] = pixinfo->uvbytes_in_bop;
+	pix_desc->h_numer[1] = (pix_desc->h_denom * pixinfo->uv_stride_ratio_times4) / 4;
+	pix_desc->v_numer[1] = 1;
+
+	pix_desc->planes[2] = (pixinfo->vbytes_in_bop > 0) ? TRUE : FALSE;
+	pix_desc->bop_numer[2] = pixinfo->vbytes_in_bop;
+	pix_desc->h_numer[2] = (pixinfo->vbytes_in_bop > 0) ? 1 : 0;
+	pix_desc->v_numer[2] = (pixinfo->vbytes_in_bop > 0) ? 1 : 0;
+
+	pix_desc->planes[3] = pixinfo->has_alpha;
+	pix_desc->bop_numer[3] = pixinfo->alphabytes_in_bop;
+	pix_desc->h_numer[3] = pix_desc->h_denom;
+	pix_desc->v_numer[3] = pix_desc->v_denom;
+}
+
+int pixel_yuv_get_desc(struct pixel_pixinfo *pix_info, struct img_pixfmt_desc *pix_desc)
+{
+	struct pixel_info int_pix_info;
+
+	struct pixel_info *int_pix_info_old = NULL;
+	enum img_pixfmt pix_fmt = pixel_get_pixfmt(pix_info->chroma_fmt_idc,
+			pix_info->chroma_interleave,
+			pix_info->mem_pkg,
+			pix_info->bitdepth_y,
+			pix_info->bitdepth_c,
+			pix_info->num_planes);
+
+	/* Validate the output from new function. */
+	if (pix_fmt != IMG_PIXFMT_UNDEFINED)
+		int_pix_info_old = pixel_get_bufinfo_from_pixfmt(pix_fmt);
+
+	pixel_get_internal_pixelinfo(pix_info, &int_pix_info);
+
+	if (int_pix_info_old) {
+		VDEC_ASSERT(int_pix_info_old->has_alpha ==
+			int_pix_info.has_alpha);
+		VDEC_ASSERT(int_pix_info_old->is_planar ==
+			int_pix_info.is_planar);
+		VDEC_ASSERT(int_pix_info_old->uv_height_halved ==
+			int_pix_info.uv_height_halved);
+		VDEC_ASSERT(int_pix_info_old->alphabytes_in_bop ==
+			int_pix_info.alphabytes_in_bop);
+		VDEC_ASSERT(int_pix_info_old->pixels_in_bop ==
+			int_pix_info.pixels_in_bop);
+		VDEC_ASSERT(int_pix_info_old->uvbytes_in_bop ==
+			int_pix_info.uvbytes_in_bop);
+		VDEC_ASSERT(int_pix_info_old->uv_stride_ratio_times4 ==
+			int_pix_info.uv_stride_ratio_times4);
+		VDEC_ASSERT(int_pix_info_old->vbytes_in_bop ==
+			int_pix_info.vbytes_in_bop);
+		VDEC_ASSERT(int_pix_info_old->ybytes_in_bop ==
+			int_pix_info.ybytes_in_bop);
+	}
+
+	pixel_yuv_get_descriptor_int(&int_pix_info, pix_desc);
+
+	return IMG_SUCCESS;
+}
+
+struct pixel_pixinfo *pixel_get_pixinfo(const enum img_pixfmt pix_fmt)
+{
+	struct pixel_pixinfo key;
+	struct pixel_pixinfo *fmt_found = NULL;
+
+	pixel_init_search();
+	pixel_pixinfo_defaults(&key);
+	key.pixfmt = pix_fmt;
+
+	fmt_found = pixel_search_fmt(&key, TRUE);
+	if (!fmt_found)
+		return def_fmt;
+	return fmt_found;
+}
+
+int pixel_get_fmt_desc(enum img_pixfmt pix_fmt, struct img_pixfmt_desc *pix_desc)
+{
+	if (pix_fmt >= IMG_PIXFMT_ARBPLANAR8 && pix_fmt <= IMG_PIXFMT_ARBPLANAR8_LAST) {
+		unsigned int i;
+		unsigned short spec;
+
+		pix_desc->bop_denom = 1;
+		pix_desc->h_denom = 1;
+		pix_desc->v_denom = 1;
+
+		spec = (pix_fmt - IMG_PIXFMT_ARBPLANAR8) & 0xffff;
+		for (i = 0; i < FACT_SPEC_FORMAT_NUM_PLANES; i++) {
+			unsigned char code = (spec >> FACT_SPEC_FORMAT_PLANE_CODE_BITS *
+				(FACT_SPEC_FORMAT_NUM_PLANES - 1 - i)) & 0xf;
+			pix_desc->bop_numer[i] = 1;
+			pix_desc->h_numer[i] = ((code >> 2) & FACT_SPEC_FORMAT_PLANE_CODE_MASK) +
+						FACT_SPEC_FORMAT_MIN_FACT_VAL;
+			pix_desc->v_numer[i] = (code & FACT_SPEC_FORMAT_PLANE_CODE_MASK) +
+						FACT_SPEC_FORMAT_MIN_FACT_VAL;
+			if (i == 0 || code != FACT_SPEC_FORMAT_PLANE_UNUSED) {
+				pix_desc->planes[i] = TRUE;
+
+				pix_desc->h_denom =
+					pix_desc->h_denom > pix_desc->h_numer[i] ?
+					pix_desc->h_denom : pix_desc->h_numer[i];
+
+				pix_desc->v_denom =
+					pix_desc->v_denom > pix_desc->v_numer[i] ?
+					pix_desc->v_denom : pix_desc->v_numer[i];
+			} else {
+				pix_desc->planes[i] = FALSE;
+			}
+		}
+	} else {
+		struct pixel_info *info =
+			pixel_get_bufinfo_from_pixfmt(pix_fmt);
+		if (!info) {
+			VDEC_ASSERT(0);
+			return -EINVAL;
+		}
+
+		pixel_yuv_get_descriptor_int(info, pix_desc);
+	}
+
+	return IMG_SUCCESS;
+}
+
+int pixel_gen_pixfmt(enum img_pixfmt *pix_fmt, struct img_pixfmt_desc *pix_desc)
+{
+	unsigned short spec = 0, i;
+	unsigned char code;
+
+	for (i = 0; i < FACT_SPEC_FORMAT_NUM_PLANES; i++) {
+		if (pix_desc->planes[i] != 1) {
+			code = FACT_SPEC_FORMAT_PLANE_UNUSED;
+		} else {
+			code = (((pix_desc->h_numer[i] - FACT_SPEC_FORMAT_MIN_FACT_VAL) &
+				FACT_SPEC_FORMAT_PLANE_CODE_MASK) << 2) |
+				((pix_desc->v_numer[i] - FACT_SPEC_FORMAT_MIN_FACT_VAL) &
+				FACT_SPEC_FORMAT_PLANE_CODE_MASK);
+		}
+		spec |= (code << FACT_SPEC_FORMAT_PLANE_CODE_BITS *
+			(FACT_SPEC_FORMAT_NUM_PLANES - 1 - i));
+	}
+
+	*pix_fmt = (enum img_pixfmt)(IMG_PIXFMT_ARBPLANAR8 | spec);
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/pixel_api.h b/drivers/media/platform/img/vxe-vxd/decoder/pixel_api.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/pixel_api.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/pixel_api.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,152 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Pixel processing functions header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef __PIXEL_API_H__
+#define __PIXEL_API_H__
+
+#include <linux/types.h>
+
+#include "img_errors.h"
+#include "img_pixfmts.h"
+
+#define PIXEL_MULTICHROME   TRUE
+#define PIXEL_MONOCHROME    FALSE
+#define IMG_MAX_NUM_PLANES  4
+#define PIXEL_INVALID_BDC   8
+
+extern unsigned char pix_fmt_idc_names[6][16];
+
+struct img_pixfmt_desc {
+	unsigned char planes[IMG_MAX_NUM_PLANES];
+	unsigned int bop_denom;
+	unsigned int bop_numer[IMG_MAX_NUM_PLANES];
+	unsigned int h_denom;
+	unsigned int v_denom;
+	unsigned int h_numer[IMG_MAX_NUM_PLANES];
+	unsigned int v_numer[IMG_MAX_NUM_PLANES];
+};
+
+/*
+ * @brief This type defines memory chroma interleaved order
+ */
+enum pixel_chroma_interleaved {
+	PIXEL_INVALID_CI        = 0,
+	PIXEL_UV_ORDER          = 1,
+	PIXEL_VU_ORDER          = 2,
+	PIXEL_YAYB_ORDER        = 4,
+	PIXEL_AYBY_ORDER        = 8,
+	PIXEL_ORDER_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * @brief This macro translates enum pixel_chroma_interleaved values into
+ * value that can be used to write HW registers directly.
+ */
+#define PIXEL_GET_HW_CHROMA_INTERLEAVED(value) \
+	((value) & PIXEL_VU_ORDER ? TRUE : FALSE)
+
+/*
+ * @brief This type defines memory packing types
+ */
+enum pixel_mem_packing {
+	PIXEL_BIT8_MP             = 0,
+	PIXEL_BIT10_MSB_MP        = 1,
+	PIXEL_BIT10_LSB_MP        = 2,
+	PIXEL_BIT10_MP            = 3,
+	PIXEL_DEFAULT_MP          = 0xff,
+	PIXEL_DEFAULT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+static inline unsigned char pixel_get_hw_memory_packing(enum pixel_mem_packing value)
+{
+	return value == PIXEL_BIT8_MP ? FALSE :
+	       value == PIXEL_BIT10_MSB_MP ? FALSE :
+	       value == PIXEL_BIT10_LSB_MP ? FALSE :
+	       value == PIXEL_BIT10_MP ? TRUE : FALSE;
+}
+
+/*
+ * @brief This type defines chroma formats
+ */
+enum pixel_fmt_idc {
+	PIXEL_FORMAT_MONO        = 0,
+	PIXEL_FORMAT_411         = 1,
+	PIXEL_FORMAT_420         = 2,
+	PIXEL_FORMAT_422         = 3,
+	PIXEL_FORMAT_444         = 4,
+	PIXEL_FORMAT_INVALID     = 0xFF,
+	PIXEL_FORMAT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+static inline int pixel_get_hw_chroma_format_idc(enum pixel_fmt_idc value)
+{
+	return value == PIXEL_FORMAT_MONO ? 0 :
+	       value == PIXEL_FORMAT_420 ? 1 :
+	       value == PIXEL_FORMAT_422 ? 2 :
+	       value == PIXEL_FORMAT_444 ? 3 :
+	       PIXEL_FORMAT_INVALID;
+}
+
+/*
+ * @brief This structure contains information about the pixel formats
+ */
+struct pixel_pixinfo {
+	enum img_pixfmt pixfmt;
+	enum pixel_chroma_interleaved chroma_interleave;
+	unsigned char chroma_fmt;
+	enum pixel_mem_packing mem_pkg;
+	enum pixel_fmt_idc chroma_fmt_idc;
+	unsigned int bitdepth_y;
+	unsigned int bitdepth_c;
+	unsigned int num_planes;
+};
+
+/*
+ * @brief This type defines the image in memory
+ */
+struct pixel_info {
+	unsigned int pixels_in_bop;
+	unsigned int ybytes_in_bop;
+	unsigned int uvbytes_in_bop;
+	unsigned int vbytes_in_bop;
+	unsigned int alphabytes_in_bop;
+	unsigned char is_planar;
+	unsigned char uv_height_halved;
+	unsigned int uv_stride_ratio_times4;
+	unsigned char has_alpha;
+};
+
+struct pixel_pixinfo_table {
+	enum img_pixfmt pix_color_fmt;
+	struct pixel_info info;
+};
+
+struct pixel_pixinfo *pixel_get_pixinfo(const enum img_pixfmt pixfmt);
+
+enum img_pixfmt pixel_get_pixfmt(enum pixel_fmt_idc chroma_fmt_idc,
+				 enum pixel_chroma_interleaved
+				 chroma_interleaved,
+				 enum pixel_mem_packing mem_packing,
+				 unsigned int bitdepth_y, unsigned int bitdepth_c,
+				 unsigned int num_planes);
+
+int pixel_yuv_get_desc(struct pixel_pixinfo *pix_info,
+		       struct img_pixfmt_desc *desc);
+
+int pixel_get_fmt_desc(enum img_pixfmt pixfmt,
+		       struct img_pixfmt_desc *fmt_desc);
+
+int pixel_gen_pixfmt(enum img_pixfmt *pix_fmt, struct img_pixfmt_desc *pix_desc);
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/pvdec_entropy_regs.h b/drivers/media/platform/img/vxe-vxd/decoder/pvdec_entropy_regs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/pvdec_entropy_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/pvdec_entropy_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD DEC Common low level core interface component
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef __PVDEC_ENTROPY_REGS_H__
+#define __PVDEC_ENTROPY_REGS_H__
+
+/*
+ * PVDEC_ENTROPY, CR_ENTROPY_SHIFTREG_CONTROL, SR_SW_RESET
+ */
+#define PVDEC_ENTROPY_CR_GENC_BUFFER_SIZE_OFFSET                (0x0100)
+
+/*
+ * PVDEC_ENTROPY, CR_GENC_BUFFER_SIZE, GENC_BUFFER_SIZE
+ */
+#define PVDEC_ENTROPY_CR_GENC_BUFFER_BASE_ADDRESS_OFFSET                (0x0110)
+
+/*
+ * PVDEC_ENTROPY, CR_ENTROPY_SLICE_PARAMETER_SIZE, SLICE_PARAMETER_SIZE
+ */
+#define PVDEC_ENTROPY_CR_GENC_FRAGMENT_BASE_ADDRESS_OFFSET              (0x0098)
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/pvdec_int.h b/drivers/media/platform/img/vxe-vxd/decoder/pvdec_int.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/pvdec_int.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/pvdec_int.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Low-level PVDEC interface component.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef __PVDEC_INT_H__
+#define __PVDEC_INT_H__
+
+#include "hw_control.h"
+#include "vxd_ext.h"
+#include "vxd_props.h"
+
+/* How many VLC IDX addresses fits in single address register */
+#define PVDECIO_VLC_IDX_ADDR_PARTS 2
+
+/* How many VLC IDX initial fits in single width register */
+#define PVDECIO_VLC_IDX_WIDTH_PARTS 10
+
+/* How many VLC IDX initial opcodes fits in single opcode register */
+#define PVDECIO_VLC_IDX_OPCODE_PARTS 16
+
+/*
+ * Length (shift) of VLC IDX opcode field. We're taking [0][1] here, as it
+ * corresponds to shift of one element
+ */
+#define PVDECIO_VLC_IDX_ADDR_ID 2
+
+/*
+ * Mask for VLC IDX address field. We're taking [0][0] here, as it corresponds
+ * to unshifted mask
+ */
+#define PVDECIO_VLC_IDX_ADDR_MASK	MSVDX_VEC_CR_VEC_VLC_TABLE_ADDR0_VLC_TABLE_ADDR0_MASK
+
+/*
+ * Length (shift) of VLC IDX address field. We're taking [0][1] here, as it
+ * corresponds to shift of one element
+ */
+#define PVDECIO_VLC_IDX_ADDR_SHIFT	MSVDX_VEC_CR_VEC_VLC_TABLE_ADDR0_VLC_TABLE_ADDR1_SHIFT
+#define PVDECIO_VLC_IDX_WIDTH_ID	1
+
+/*
+ * Mask for VLC IDX width field. We're taking [0][0] here, as it corresponds
+ * to unshifted mask
+ */
+#define PVDECIO_VLC_IDX_WIDTH_MASK      \
+	MSVDX_VEC_CR_VEC_VLC_TABLE_INITIAL_WIDTH0_VLC_TABLE_INITIAL_WIDTH0_MASK
+
+/*
+ * Length (shift) of VLC IDX width field. We're taking [0][1] here, as it
+ * corresponds to shift of one element
+ */
+#define PVDECIO_VLC_IDX_WIDTH_SHIFT     \
+	MSVDX_VEC_CR_VEC_VLC_TABLE_INITIAL_WIDTH0_VLC_TABLE_INITIAL_WIDTH1_SHIFT
+
+#define PVDECIO_VLC_IDX_OPCODE_ID	0
+
+/*
+ * Length (shift) of VLC IDX opcode field. We're taking [0][1] here, as it
+ * corresponds to shift of one element
+ */
+#define PVDECIO_VLC_IDX_OPCODE_SHIFT    \
+	MSVDX_VEC_CR_VEC_VLC_TABLE_INITIAL_OPCODE0_VLC_TABLE_INITIAL_OPCODE1_SHIFT
+
+/* This comes from DEVA PVDEC FW */
+#define CTRL_ALLOC_MAX_SEGMENT_SIZE 1024
+
+/*
+ * Mask for VLC IDX opcode field. We're taking [0][0] here, as it corresponds
+ * to unshifted mask
+ */
+#define PVDECIO_VLC_IDX_OPCODE_MASK     \
+	MSVDX_VEC_CR_VEC_VLC_TABLE_INITIAL_OPCODE0_VLC_TABLE_INITIAL_OPCODE0_MASK
+
+#endif /* __PVDEC_INT_H__ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/pvdec_vec_be_regs.h b/drivers/media/platform/img/vxe-vxd/decoder/pvdec_vec_be_regs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/pvdec_vec_be_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/pvdec_vec_be_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD DEC Common low level core interface component
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef __PVDEC_VEC_BE_REGS_H__
+#define __PVDEC_VEC_BE_REGS_H__
+
+#define PVDEC_VEC_BE_CR_GENC_BUFFER_SIZE_OFFSET         (0x0040)
+
+/*
+ * PVDEC_VEC_BE, CR_GENC_BUFFER_SIZE, GENC_BUFFER_SIZE
+ */
+#define PVDEC_VEC_BE_CR_GENC_BUFFER_BASE_ADDRESS_OFFSET         (0x0050)
+
+/*
+ * PVDEC_VEC_BE, CR_MEM_TO_REG_CONTROL, MEM_TO_REG_NUM_PAIRS
+ */
+#define PVDEC_VEC_BE_CR_GENC_FRAGMENT_BASE_ADDRESS_OFFSET               (0x0030)
+
+/*
+ * PVDEC_VEC_BE, CR_GENC_CONTEXT1, GENC_CONTEXT1_1
+ */
+#define PVDEC_VEC_BE_CR_ABOVE_PARAM_BASE_ADDRESS_OFFSET         (0x00C0)
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/reg_io2.h b/drivers/media/platform/img/vxe-vxd/decoder/reg_io2.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/reg_io2.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/reg_io2.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG MSVDX core Registers
+ * This file contains the MSVDX_CORE_REGS_H Definitions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef REG_IO2_H_
+#define REG_IO2_H_
+
+#define IMG_ASSERT(expected) \
+	((void)((expected) || \
+	       (pr_err("Assertion failed: %s, file %s, line %d\n", \
+			   #expected, __FILE__, __LINE__), dump_stack(), 0)))
+
+/* This macro is used to extract a field from a register. */
+#define REGIO_READ_FIELD(regval, group, reg, field)     \
+	(((regval) & group ## _ ## reg ## _ ## field ## _MASK) >> \
+	 group ## _ ## reg ## _ ## field ## _SHIFT)
+
+#if (defined WIN32 || defined __linux__) && !defined NO_REGIO_CHECK_FIELD_VALUE
+/*
+ * Only provide register field range checking for Windows and
+ * Linux builds
+ * Simple range check that ensures that if bits outside the valid field
+ * range are set, that the provided value is at least consistent with a
+ * negative value (i.e.: all top bits are set to 1).
+ * Cannot perform more comprehensive testing without knowing
+ * whether field
+ * should be interpreted as signed or unsigned.
+ */
+#define REGIO_CHECK_VALUE_FITS_WITHIN_FIELD(group, reg, field, value, type) \
+	{ \
+		type __value = value; \
+		unsigned int temp = (unsigned int)(__value); \
+		if (temp > group ## _ ## reg ## _ ## field ## _LSBMASK) { \
+			IMG_ASSERT((((unsigned int)__value) & \
+			(unsigned int)~(group ## _ ## reg ## _ ## field ## _LSBMASK)) == \
+			(unsigned int)~(group ## _ ## reg ## _ ## field ## _LSBMASK));  \
+		}                                                       \
+	}
+#else
+#define REGIO_CHECK_VALUE_FITS_WITHIN_FIELD(group, reg, field, value, type)
+#endif
+
+/* This macro is used to update the value of a field in a register. */
+#define REGIO_WRITE_FIELD(regval, group, reg, field, value, reg_type, val_type) \
+	{                                                               \
+		reg_type __regval = regval; \
+		val_type __value = value; \
+		REGIO_CHECK_VALUE_FITS_WITHIN_FIELD(group, reg, field, __value, val_type); \
+		(regval) =                                                      \
+		((__regval) & ~(group ## _ ## reg ## _ ## field ## _MASK)) |              \
+		(((unsigned int)(__value) << (group ## _ ## reg ## _ ## field ## _SHIFT)) & \
+		(group ## _ ## reg ## _ ## field ## _MASK));      \
+	}
+
+/* This macro is used to update the value of a field in a register. */
+#define REGIO_WRITE_FIELD_LITE(regval, group, reg, field, value, type)  \
+{                                                                       \
+	type __value = value; \
+	REGIO_CHECK_VALUE_FITS_WITHIN_FIELD(group, reg, field, __value, type); \
+	(regval) |= ((unsigned int)(__value) << (group ## _ ## reg ## _ ## field ## _SHIFT)); \
+}
+
+#endif /* REG_IO2_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/scaler_setup.h b/drivers/media/platform/img/vxe-vxd/decoder/scaler_setup.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/scaler_setup.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/scaler_setup.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD DEC constants calculation and scalling coefficients
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ */
+
+#ifndef _SCALER_SETUP_H
+#define _SCALER_SETUP_H
+
+#define LOWP                            11
+#define HIGHP                           14
+
+#define FIXED(a, digits)                ((int)((a) * (1 << (digits))))
+
+struct scaler_params {
+	unsigned int vert_pitch;
+	unsigned int vert_startpos;
+	unsigned int vert_pitch_chroma;
+	unsigned int vert_startpos_chroma;
+	unsigned int horz_pitch;
+	unsigned int horz_startpos;
+	unsigned int horz_pitch_chroma;
+	unsigned int horz_startpos_chroma;
+	unsigned char fixed_point_shift;
+};
+
+struct scaler_filter {
+	unsigned char bhoriz_bilinear;
+	unsigned char bvert_bilinear;
+};
+
+struct scaler_pitch {
+	int horiz_luma;
+	int vert_luma;
+	int horiz_chroma;
+	int vert_chroma;
+};
+
+struct scaler_config {
+	enum vdec_vid_std vidstd;
+	const struct vxd_coreprops *coreprops;
+	struct pixel_pixinfo *in_pixel_info;
+	const struct pixel_pixinfo *out_pixel_info;
+	unsigned char bfield_coded;
+	unsigned char bseparate_chroma_planes;
+	unsigned int recon_width;
+	unsigned int recon_height;
+	unsigned int mb_width;
+	unsigned int mb_height;
+	unsigned int scale_width;
+	unsigned int scale_height;
+};
+
+#endif /* _SCALER_SETUP_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/swsr.c b/drivers/media/platform/img/vxe-vxd/decoder/swsr.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/swsr.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/swsr.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1657 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Software Shift Register Access fucntions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ * Re-written for upstreming
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "swsr.h"
+#include "vdec_defs.h"
+
+#define NBIT_8BYTE_MASK(n)    ((1ULL << (n)) - 1)
+
+/* Input FIFO length (in bytes). */
+#define SWSR_INPUT_FIFO_LENGTH      8
+
+/* Output FIFO length (in bits). */
+#define SWSR_OUTPUT_FIFO_LENGTH     64
+
+#define SWSR_NALTYPE_LENGTH         8
+
+#define SWSR_MAX_SYNTAX_LENGTH      32
+
+#define SWSR_ASSERT(expected) ({WARN_ON(!(expected)); 0; })
+
+struct swsr_buffer {
+	void **lst_link;
+	/* Pointer to bitstream data. */
+	unsigned char *data;
+	/* Number of bytes of bitstream */
+	unsigned long long num_bytes;
+	/* Index (in bytes) to next data within the buffer */
+	unsigned long long byte_offset;
+	/* Number of bytes read from input FIFO */
+	unsigned long long num_bytes_read;
+};
+
+struct swsr_input {
+	/* Bitstream data (byte-based and pre emu prev) - left aligned. */
+	unsigned long long fifo;
+	/* Number of *bytes* in Input FIFO */
+	unsigned int num_bytes;
+	struct swsr_config config;
+	/* Emulation prevention mode used to process data in Input FIFO */
+	enum swsr_emprevent emprevent;
+	/* Number of bytes in emulation prevention sequence */
+	unsigned int emprev_seq_len;
+	/* Size of bitstream declared at initialisation */
+	unsigned long long bitstream_size;
+	/*
+	 * Number of bytes required from input buffer before checking
+	 * next emulation prevention sequence.
+	 */
+	unsigned int bytes_for_next_sequ;
+	/* Byte count read from size delimiter */
+	unsigned long long byte_count;
+	unsigned long long bytes_read_since_delim;
+	/* Cumulative offset (in bytes) into input buffer data */
+	unsigned long long bitstream_offset;
+	/* Bitstream delimiter found (see #SWSR_delim_type) */
+	unsigned char delim_found;
+	/*
+	 * No More Valid Data before next delimiter.
+	 * Set only for SWSR_EMPREVENT_00000300.
+	 */
+	unsigned char no_moredata;
+	/* Pointer to current input buffer in the context of Input FIFO */
+	struct swsr_buffer *buf;
+	/* Start offset within buffer of current delimited unit */
+	long delimited_unit_start_offset;
+	/* Size of current delimited unit (if already calculated) */
+	unsigned int delimited_unit_size;
+	/* Current bit offset within the current delimited unit */
+	unsigned int delimunit_bitofst;
+};
+
+struct swsr_output {
+	/*
+	 * Bitstream data (post emulation prevention removal
+	 * delimiter checking) - left aligned.
+	 */
+	unsigned long long fifo;
+	/* Number of *bits* in Output FIFO */
+	unsigned int num_bits;
+	unsigned long long totalbits_consumed;
+};
+
+struct swsr_buffer_ctx {
+	/*
+	 * Callback function to notify event and provide/request data.
+	 * See #SWSR_eCbEvent for event types and description
+	 * of CB argument usage.
+	 */
+	swsr_callback_fxn cb_fxn;
+	/* Caller supplied pointer for callback */
+	void *cb_param;
+	/* List of buffers */
+	struct lst_t free_buffer_list;
+	/*
+	 * List of buffers (#SWSR_sBufferCtx) whose data reside
+	 * in the Input/Output FIFOs.
+	 */
+	struct lst_t used_buffer_list;
+};
+
+struct swsr_context {
+	/* IMG_TRUE if the context is initialised */
+	unsigned char initialised;
+	/* A pointer to an exception handler */
+	swsr_except_handler_fxn exception_handler_fxn;
+	/* Caller supplied pointer */
+	void *pexception_param;
+	/* Last recorded exception */
+	enum swsr_exception exception;
+	/* Buffer context data */
+	struct swsr_buffer_ctx buffer_ctx;
+	/* Context of shift register input. */
+	struct swsr_input input;
+	/* Context of shift register output */
+	struct swsr_output output;
+};
+
+static unsigned long long left_aligned_nbit_8byte_mask(unsigned int mask, unsigned int nbits)
+{
+	return (((unsigned long long)mask << (64 - nbits)) |
+			(unsigned long long)NBIT_8BYTE_MASK(64 - nbits));
+}
+
+/*
+ * buffer has been exhausted and there is still more bytes declared in bitstream
+ */
+static int swsr_extractbyte(struct swsr_context *ctx, unsigned char *byte_ext)
+{
+	struct swsr_input *input;
+	struct swsr_buffer_ctx *buf_ctx;
+	unsigned char byte = 0;
+	unsigned long long cur_byte_offset;
+	unsigned int result = 0;
+
+	if (!ctx || !byte_ext)
+		return IMG_ERROR_FATAL;
+
+	input = &ctx->input;
+	buf_ctx = &ctx->buffer_ctx;
+
+	cur_byte_offset = input->bitstream_offset;
+
+	if (input->buf && input->buf->byte_offset < input->buf->num_bytes) {
+		input->bitstream_offset++;
+		byte = input->buf->data[input->buf->byte_offset++];
+	} else if (input->bitstream_offset < input->bitstream_size) {
+		struct swsr_buffer *buffer;
+
+		buffer = lst_removehead(&buf_ctx->free_buffer_list);
+		if (!buffer)
+			return IMG_ERROR_FATAL;
+
+		buffer->num_bytes_read = 0;
+		buffer->byte_offset = 0;
+
+		buf_ctx->cb_fxn(SWSR_EVENT_INPUT_BUFFER_START,
+			buf_ctx->cb_param, 0,
+			&buffer->data, &buffer->num_bytes);
+		SWSR_ASSERT(buffer->data && buffer->num_bytes > 0);
+
+		if (buffer->data && buffer->num_bytes > 0) {
+			input->buf = buffer;
+
+			/* Add input buffer to output buffer list. */
+			lst_add(&buf_ctx->used_buffer_list, input->buf);
+
+			input->bitstream_offset++;
+			byte = input->buf->data[input->buf->byte_offset++];
+		}
+	}
+
+	{
+		struct swsr_buffer *buffer = input->buf;
+
+		if (!buffer)
+			buffer = lst_first(&buf_ctx->used_buffer_list);
+
+		if (!buffer || buffer->num_bytes_read > buffer->num_bytes) {
+			input->delimited_unit_start_offset = -1;
+			input->delimited_unit_size = 0;
+		}
+	}
+	/* If the bitstream offset hasn't increased we failed to read a byte. */
+	if (cur_byte_offset == input->bitstream_offset) {
+		input->buf = NULL;
+		result = IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+	}
+
+	*byte_ext = byte;
+
+	return result;
+}
+
+static unsigned char swsr_checkfor_delimiter(struct swsr_context *ctx)
+{
+	struct swsr_input *input;
+	unsigned char delim_found = 0;
+
+	input = &ctx->input;
+
+	/* Check for delimiter. */
+	if (input->config.delim_type == SWSR_DELIM_SCP) {
+		unsigned int shift = (SWSR_INPUT_FIFO_LENGTH * 8)
+			- input->config.delim_length;
+		unsigned long long sequ = input->fifo >> shift;
+
+		/*
+		 * Check if the SCP value is matched outside of
+		 * emulation prevention data.
+		 */
+		if (sequ == input->config.scp_value && input->bytes_for_next_sequ == 0)
+			delim_found = 1;
+
+	} else if (input->config.delim_type == SWSR_DELIM_SIZE) {
+		delim_found = (input->bytes_read_since_delim >= input->byte_count) ? 1 : 0;
+	}
+
+	return delim_found;
+}
+
+static int swsr_increment_cur_bufoffset(struct swsr_context *ctx)
+{
+	struct swsr_buffer_ctx *buf_ctx;
+	struct swsr_buffer *cur_buf;
+
+	buf_ctx = &ctx->buffer_ctx;
+
+	/* Update the number of bytes read from input FIFO for current buffer */
+	cur_buf = lst_first(&buf_ctx->used_buffer_list);
+	if (cur_buf->num_bytes_read >= cur_buf->num_bytes) {
+		/* Mark current bitstream buffer as fully consumed */
+		cur_buf->num_bytes_read = cur_buf->num_bytes;
+
+		/* Notify the application that the old buffer is exhausted. */
+		buf_ctx->cb_fxn(SWSR_EVENT_OUTPUT_BUFFER_END,
+			buf_ctx->cb_param, 0,
+			NULL, NULL);
+
+		/*
+		 * Discard the buffer whose data was at the head of
+		 * the input FIFO.
+		 */
+		cur_buf = lst_removehead(&buf_ctx->used_buffer_list);
+		/* Add the buffer container to free list. */
+		lst_add(&buf_ctx->free_buffer_list, cur_buf);
+
+		/*
+		 * Since the byte that we read was actually from the next
+		 * buffer increment it's counter.
+		 */
+		cur_buf = lst_first(&buf_ctx->used_buffer_list);
+		cur_buf->num_bytes_read++;
+	} else {
+		cur_buf->num_bytes_read++;
+	}
+
+	return 0;
+}
+
+static enum swsr_found swsr_readbyte_from_inputfifo(struct swsr_context *ctx,
+						    unsigned char *byte)
+{
+	struct swsr_input *input;
+	enum swsr_found found = SWSR_FOUND_NONE;
+	unsigned int result = 0;
+
+	input = &ctx->input;
+
+	input->delim_found |= swsr_checkfor_delimiter(ctx);
+
+	/*
+	 * Refill the input FIFO before checking for emulation prevention etc.
+	 * The only exception is when there are no more bytes left to extract
+	 * from input buffer.
+	 */
+	while (input->num_bytes < SWSR_INPUT_FIFO_LENGTH && result == 0) {
+		unsigned char byte;
+
+		result = swsr_extractbyte(ctx, &byte);
+		if (result == 0) {
+			input->fifo |= ((unsigned long long)byte <<
+				((SWSR_INPUT_FIFO_LENGTH - 1 - input->num_bytes) * 8));
+			input->num_bytes += 1;
+		}
+	}
+
+	if (input->num_bytes == 0) {
+		found = SWSR_FOUND_EOD;
+	} else if (!input->delim_found) {
+		/*
+		 * Check for emulation prevention when enabled and enough
+		 * bytes are remaining in input FIFO.
+		 */
+		if (input->emprevent != SWSR_EMPREVENT_NONE &&
+		    /*
+		     * Ensure you have enough bytes to check for emulation
+		     * prevention.
+		     */
+		    input->num_bytes >= input->emprev_seq_len &&
+		    (input->config.delim_type != SWSR_DELIM_SIZE ||
+		    /*
+		     * Ensure that you don't remove emu bytes beyond current
+		     * delimited unit.
+		     */
+		     ((input->bytes_read_since_delim + input->emprev_seq_len) <
+		     input->byte_count)) && input->bytes_for_next_sequ == 0) {
+			unsigned char emprev_removed = 0;
+			unsigned int shift = (SWSR_INPUT_FIFO_LENGTH - input->emprev_seq_len) * 8;
+			unsigned long long sequ = input->fifo >> shift;
+
+			if (input->emprevent == SWSR_EMPREVENT_00000300) {
+				if ((sequ & 0xffffff00) == 0x00000300) {
+					if ((sequ & 0x000000ff) > 0x03)
+						pr_err("Invalid start code emulation preventionbytes found\n");
+
+					/*
+					 * Instead of trying to remove the emulation prevention
+					 * byte from the middle of the FIFO simply make it zero
+					 * and drop the next byte from the FIFO which will
+					 * also be zero.
+					 */
+					input->fifo &= left_aligned_nbit_8byte_mask
+							(0xffff00ff,
+							 input->emprev_seq_len * 8);
+					input->fifo <<= 8;
+
+					emprev_removed = 1;
+				} else if ((sequ & 0xffffffff) == 0x00000000 ||
+					(sequ & 0xffffffff) == 0x00000001) {
+					input->no_moredata = 1;
+				}
+			} else if (input->emprevent == SWSR_EMPREVENT_ff00) {
+				if (sequ == 0xff00) {
+					/* Remove the zero byte. */
+					input->fifo <<= 8;
+					input->fifo |= (0xff00ULL << shift);
+					emprev_removed = 1;
+				}
+			} else if (input->emprevent == SWSR_EMPREVENT_000002) {
+				/*
+				 * Remove the emulation prevention bytes
+				 * if we find 22 consecutive 0 bits
+				 * (from a byte-aligned position?!)
+				 */
+				if (sequ == 0x000002) {
+					/*
+					 * Appear to "remove" the 0x02 byte by clearing
+					 * it and then dropping the top (zero) byte.
+					 */
+					input->fifo &= left_aligned_nbit_8byte_mask
+							(0xffff00,
+							 input->emprev_seq_len * 8);
+					input->fifo <<= 8;
+					emprev_removed = 1;
+				}
+			}
+
+			if (emprev_removed) {
+				input->num_bytes--;
+				input->bytes_read_since_delim++;
+
+				/* Increment the buffer offset for the
+				 *  byte that has been removed.
+				 */
+				swsr_increment_cur_bufoffset(ctx);
+
+				/*
+				 * Signal that two more new bytes in the emulation
+				 * prevention sequence are required before another match
+				 * can be made.
+				 */
+				input->bytes_for_next_sequ = input->emprev_seq_len - 2;
+			}
+		}
+
+		if (input->bytes_for_next_sequ > 0)
+			input->bytes_for_next_sequ--;
+
+		/* return the first bytes from read data */
+		*byte = (unsigned char)(input->fifo >> ((SWSR_INPUT_FIFO_LENGTH - 1) * 8));
+		input->fifo <<= 8;
+
+		input->num_bytes--;
+		input->bytes_read_since_delim++;
+
+		/* Increment the buffer offset for byte that has been read. */
+		swsr_increment_cur_bufoffset(ctx);
+
+		found = SWSR_FOUND_DATA;
+	} else {
+		found = SWSR_FOUND_DELIM;
+	}
+
+	return found;
+}
+
+static enum swsr_found swsr_consumebyte_from_inputfifo
+	(struct swsr_context *ctx, unsigned char *byte)
+{
+	enum swsr_found found;
+
+	found = swsr_readbyte_from_inputfifo(ctx, byte);
+
+	if (found == SWSR_FOUND_DATA) {
+		/* Only whole bytes can be read from Input FIFO. */
+		ctx->output.totalbits_consumed += 8;
+		ctx->input.delimunit_bitofst += 8;
+	}
+
+	return found;
+}
+
+static int swsr_fill_outputfifo(struct swsr_context *ctx)
+{
+	unsigned char byte;
+	enum swsr_found found = SWSR_FOUND_DATA;
+
+	/* Fill output FIFO with whole bytes up to (but not over) max length */
+	while (ctx->output.num_bits <= (SWSR_OUTPUT_FIFO_LENGTH - 8) && found == SWSR_FOUND_DATA) {
+		found = swsr_readbyte_from_inputfifo(ctx, &byte);
+		if (found == SWSR_FOUND_DATA) {
+			ctx->output.fifo |= ((unsigned long long)byte <<
+				(SWSR_OUTPUT_FIFO_LENGTH - 8 - ctx->output.num_bits));
+			ctx->output.num_bits += 8;
+		}
+	}
+
+	return 0;
+}
+
+static unsigned int swsr_getbits_from_outputfifo(struct swsr_context *ctx,
+						 unsigned int numbits,
+						 unsigned char bconsume)
+{
+	unsigned int bitsread;
+
+	/*
+	 * Fetch more bits from the input FIFO if the output FIFO
+	 * doesn't have enough bits to satisfy the request on its own.
+	 */
+	if (numbits > ctx->output.num_bits)
+		swsr_fill_outputfifo(ctx);
+
+	/* Ensure that are now enough bits in the output FIFO. */
+	if (numbits > ctx->output.num_bits) {
+		/* Tried to access into an SCP or other delimiter. */
+		if (ctx->input.delim_found) {
+			ctx->exception = SWSR_EXCEPT_ACCESS_INTO_SCP;
+		} else {
+			/*
+			 * Data has been exhausted if after extracting bits
+			 * there are still not enough bits in the internal
+			 * storage to fulfil the number requested.
+			 */
+			ctx->exception = SWSR_EXCEPT_ACCESS_BEYOND_EOD;
+		}
+
+		ctx->exception_handler_fxn(ctx->exception, ctx->pexception_param);
+
+		/* Return zero if the bits couldn't be obtained */
+		bitsread = 0;
+	} else {
+		unsigned int shift;
+
+		/* Extract all the bits from the output FIFO */
+		shift = (SWSR_OUTPUT_FIFO_LENGTH - numbits);
+		bitsread = (unsigned int)(ctx->output.fifo >> shift);
+
+		if (bconsume) {
+			/* Update output FIFO. */
+			ctx->output.fifo <<= numbits;
+			ctx->output.num_bits -= numbits;
+		}
+	}
+
+	if (bconsume && ctx->exception == SWSR_EXCEPT_NO_EXCEPTION) {
+		ctx->output.totalbits_consumed += numbits;
+		ctx->input.delimunit_bitofst += numbits;
+	}
+
+	/* Return the bits */
+	return bitsread;
+}
+
+int swsr_read_signed_expgoulomb(void *ctx_hndl)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+	unsigned int exp_goulomb;
+	unsigned char unsign;
+
+	/* Validate input arguments. */
+	if (!ctx) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	/* Read unsigned value then convert to signed value */
+	exp_goulomb = swsr_read_unsigned_expgoulomb(ctx);
+
+	unsign = exp_goulomb & 1;
+	exp_goulomb >>= 1;
+	exp_goulomb = (unsign) ? exp_goulomb + 1 : -(int)exp_goulomb;
+
+	if (ctx->exception != SWSR_EXCEPT_NO_EXCEPTION)
+		ctx->exception_handler_fxn(ctx->exception, ctx->pexception_param);
+
+	/* Return the signed value */
+	return exp_goulomb;
+}
+
+static unsigned int swsr_readunsigned_expgoulomb(struct swsr_context *ctx)
+{
+	unsigned int numbits = 0;
+	unsigned int bitpeeked;
+	unsigned int bitread;
+	unsigned int setbits;
+	unsigned int expgoulomb;
+
+	/* Loop until we have found a non-zero nibble or reached 31 0-bits */
+	/* first read is 3 bits only to prevent an illegal 32-bit peek */
+	numbits = 1;
+	do {
+		bitpeeked = swsr_peekbits(ctx, numbits);
+		/* Check for non-zero nibble */
+		if (bitpeeked != 0)
+			break;
+
+		numbits++;
+
+	} while (numbits < 32);
+
+	/* Correct the number of leading zero bits */
+	numbits--;
+
+	if (bitpeeked) {
+		/* read leading zeros and 1-bit */
+		bitread = swsr_read_bits(ctx, numbits + 1);
+		if (bitread != 1)
+			ctx->exception = SWSR_EXCEPT_EXPGOULOMB_ERROR;
+	} else {
+		/*
+		 * read 31 zero bits - special case to deal with 31 or 32
+		 * leading zeros
+		 */
+		bitread = swsr_read_bits(ctx, 31);
+		if (bitread != 0)
+			ctx->exception = SWSR_EXCEPT_EXPGOULOMB_ERROR;
+
+		/*
+		 * next 3 bits make either 31 0-bit code:'1xx',
+		 * or 32 0-bit code:'010'
+		 */
+		/*
+		 * only valid 32 0-bit code is:'0..010..0'
+		 * and results in 0xffffffff
+		 */
+		bitpeeked = swsr_peekbits(ctx, 3);
+
+		if (ctx->exception == SWSR_EXCEPT_NO_EXCEPTION) {
+			if (0x4 & bitpeeked) {
+				bitread = swsr_read_bits(ctx, 1);
+				numbits = 31;
+			} else {
+				if (bitpeeked != 2)
+					ctx->exception = SWSR_EXCEPT_EXPGOULOMB_ERROR;
+
+				bitread = swsr_read_bits(ctx, 3);
+				bitread = swsr_read_bits(ctx, 31);
+				if (bitread != 0)
+					ctx->exception = SWSR_EXCEPT_EXPGOULOMB_ERROR;
+
+				return 0xffffffff;
+			}
+		} else {
+			/* encountered an exception while reading code */
+			/* just return a valid value */
+			return 0;
+		}
+	}
+
+	/* read data bits */
+	bitread = 0;
+	if (numbits)
+		bitread = swsr_read_bits(ctx, numbits);
+
+	/* convert exp-goulomb to value */
+	setbits = (1 << numbits) - 1;
+	expgoulomb = setbits + bitread;
+	/* Return the value */
+	return expgoulomb;
+}
+
+unsigned int swsr_read_unsigned_expgoulomb(void *ctx_hndl)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+	unsigned int value;
+
+	/* Validate input arguments. */
+	if (!ctx) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	value = swsr_readunsigned_expgoulomb(ctx);
+
+	if (ctx->exception != SWSR_EXCEPT_NO_EXCEPTION)
+		ctx->exception_handler_fxn(ctx->exception, ctx->pexception_param);
+
+	return value;
+}
+
+enum swsr_exception swsr_check_exception(void *ctx_hndl)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+	enum swsr_exception exception;
+
+	/* Validate input arguments. */
+	if (!ctx) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return (enum swsr_exception)IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	exception = ctx->exception;
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return (enum swsr_exception)IMG_ERROR_NOT_INITIALISED;
+	}
+
+	ctx->exception = SWSR_EXCEPT_NO_EXCEPTION;
+	return exception;
+}
+
+int swsr_check_more_rbsp_data(void *ctx_hndl, unsigned char *more_rbsp_data)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+
+	int rembitsinbyte;
+	unsigned char currentbyte;
+	int numof_aligned_rembits;
+	unsigned long long rest_alignedbytes;
+	unsigned char moredata = 0;
+
+	/* Validate input arguments. */
+	if (!ctx) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	if (ctx->input.emprevent != SWSR_EMPREVENT_00000300) {
+		pr_err("SWSR cannot determine More RBSP data for a stream without SWSR_EMPREVENT_00000300: %s\n",
+		       __func__);
+		return IMG_ERROR_OPERATION_PROHIBITED;
+	}
+
+	/*
+	 * Always fill the output FIFO to ensure the no_moredata flag is set
+	 * when there are enough remaining bytes
+	 */
+
+	swsr_fill_outputfifo(ctx);
+
+	if (ctx->output.num_bits != 0) {
+		/* Calculate the number of bits in the MS byte */
+		rembitsinbyte = (ctx->output.num_bits & 0x7);
+		if (rembitsinbyte == 0)
+			rembitsinbyte = 8;
+
+		numof_aligned_rembits = (ctx->output.num_bits - rembitsinbyte);
+
+		/* Peek the value of last byte. */
+		currentbyte = swsr_peekbits(ctx, rembitsinbyte);
+		rest_alignedbytes = (ctx->output.fifo >>
+			(64 - ctx->output.num_bits)) &
+			((1ULL << numof_aligned_rembits) - 1);
+
+		if ((currentbyte == (1 << (rembitsinbyte - 1))) &&
+		    (numof_aligned_rembits == 0 || (rest_alignedbytes == 0 &&
+		    ((((((unsigned int)numof_aligned_rembits >> 3)) <
+		    ctx->input.emprev_seq_len) &&
+		    ctx->input.num_bytes == 0) || ctx->input.no_moredata))))
+			moredata = 0;
+		else
+			moredata = 1;
+	}
+
+	*more_rbsp_data = moredata;
+
+	return 0;
+}
+
+unsigned int swsr_read_onebit(void *ctx_hndl)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+	unsigned int bitread;
+
+	/* Validate input arguments. */
+	if (!ctx_hndl) {
+		VDEC_ASSERT(0);
+		return -EIO;
+	}
+
+	ctx = (struct swsr_context *)ctx_hndl;
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	/* Optimize with inline code (specific version of call below). */
+	bitread = swsr_read_bits(ctx, 1);
+
+	return bitread;
+}
+
+unsigned int swsr_read_bits(void *ctx_hndl, unsigned int no_bits)
+{
+	struct swsr_context *ctx;
+
+	/* Validate input arguments. */
+	if (!ctx_hndl) {
+		VDEC_ASSERT(0);
+		return -EIO;
+	}
+
+	ctx = (struct swsr_context *)ctx_hndl;
+
+	/* Validate input arguments. */
+	if (!ctx->initialised) {
+		pr_err("%s: Invalid SWSR context\n", __func__);
+		ctx->exception = SWSR_EXCEPT_INVALID_CONTEXT;
+		ctx->exception_handler_fxn(ctx->exception, ctx->pexception_param);
+
+		return 0;
+	}
+
+	if (no_bits > SWSR_MAX_SYNTAX_LENGTH) {
+		pr_err("Maximum symbol length exceeded\n");
+		ctx->exception = SWSR_EXCEPT_WRONG_CODEWORD_ERROR;
+		ctx->exception_handler_fxn(ctx->exception, ctx->pexception_param);
+
+		return 0;
+	}
+
+	return swsr_getbits_from_outputfifo(ctx, no_bits, 1);
+}
+
+int swsr_read_signedbits(void *ctx_hndl, unsigned int no_bits)
+{
+	struct swsr_context *ctx;
+	int outbits = 0;
+
+	/* Validate input arguments. */
+	if (!ctx_hndl) {
+		VDEC_ASSERT(0);
+		return -EIO;
+	}
+
+	ctx = (struct swsr_context *)ctx_hndl;
+
+	/* Check if the context has been initialized. */
+	if (!ctx->initialised) {
+		pr_err("%s: Invalid SWSR context\n", __func__);
+		ctx->exception = SWSR_EXCEPT_INVALID_CONTEXT;
+		ctx->exception_handler_fxn(ctx->exception, ctx->pexception_param);
+
+		return 0;
+	}
+
+	if ((no_bits + 1) > SWSR_MAX_SYNTAX_LENGTH) {
+		pr_err("Maximum symbol length exceeded\n");
+		ctx->exception = SWSR_EXCEPT_WRONG_CODEWORD_ERROR;
+		ctx->exception_handler_fxn(ctx->exception, ctx->pexception_param);
+
+		return 0;
+	}
+	outbits = swsr_getbits_from_outputfifo(ctx, no_bits, 1);
+
+	return (swsr_getbits_from_outputfifo(ctx, 1, 1)) ? -outbits : outbits;
+}
+
+unsigned int swsr_peekbits(void *ctx_hndl, unsigned int no_bits)
+{
+	struct swsr_context *ctx;
+
+	/* validate input parameters */
+	if (!ctx_hndl) {
+		VDEC_ASSERT(0);
+		return -EIO;
+	}
+
+	ctx = (struct swsr_context *)ctx_hndl;
+
+	/* Validate input arguments. */
+	if (!ctx->initialised) {
+		pr_err("%s: Invalid SWSR context\n", __func__);
+		ctx->exception = SWSR_EXCEPT_INVALID_CONTEXT;
+		ctx->exception_handler_fxn(ctx->exception, ctx->pexception_param);
+
+		return 0;
+	}
+
+	if (no_bits > SWSR_MAX_SYNTAX_LENGTH) {
+		pr_err("Maximum symbol length exceeded\n");
+		ctx->exception = SWSR_EXCEPT_WRONG_CODEWORD_ERROR;
+		ctx->exception_handler_fxn(ctx->exception, ctx->pexception_param);
+
+		return 0;
+	}
+
+	return swsr_getbits_from_outputfifo(ctx, no_bits, 0);
+}
+
+int swsr_byte_align(void *ctx_hndl)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+	unsigned int numbits;
+
+	/* Validate input arguments. */
+	if (!ctx) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	numbits = (ctx->output.num_bits & 0x7);
+	/* Read the required number of bits if not already byte-aligned. */
+	if (numbits != 0)
+		swsr_read_bits(ctx, numbits);
+
+	SWSR_ASSERT((ctx->output.num_bits & 0x7) == 0);
+
+	return 0;
+}
+
+int swsr_get_total_bitsconsumed(void *ctx_hndl, unsigned long long *total_bitsconsumed)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+
+	/* Validate input arguments. */
+	if (!ctx || !total_bitsconsumed) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	*total_bitsconsumed = ctx->output.totalbits_consumed;
+
+	return 0;
+}
+
+int swsr_get_byte_offset_curbuf(void *ctx_hndl, unsigned long long *byte_offset)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+	struct swsr_buffer *outbuf;
+
+	/* Validate input arguments. */
+	if (!ctx || !byte_offset) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	if (ctx->output.num_bits != 0) {
+		pr_err("SWSR output FIFO not empty. First seek to next delimiter: %s\n",
+		       __func__);
+		return IMG_ERROR_OPERATION_PROHIBITED;
+	}
+
+	outbuf = lst_first(&ctx->buffer_ctx.used_buffer_list);
+	if (outbuf)
+		*byte_offset = outbuf->num_bytes_read;
+	else
+		return IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+
+	return 0;
+}
+
+static int swsr_update_emprevent(enum swsr_emprevent emprevent,
+				 struct swsr_context *ctx)
+{
+	struct swsr_input *input;
+
+	input = &ctx->input;
+
+	input->emprevent = emprevent;
+	switch (input->emprevent) {
+	case SWSR_EMPREVENT_00000300:
+		input->emprev_seq_len = 4;
+		break;
+
+	case SWSR_EMPREVENT_ff00:
+		input->emprev_seq_len = 2;
+		break;
+
+	case SWSR_EMPREVENT_000002:
+		input->emprev_seq_len = 3;
+		break;
+
+	default:
+		input->emprev_seq_len = 0;
+		break;
+	}
+
+	return 0;
+}
+
+int swsr_consume_delim(void *ctx_hndl, enum swsr_emprevent emprevent,
+		       unsigned int size_delim_length, unsigned long long *byte_count)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+	struct swsr_input *input;
+	unsigned long long delimiter = 0;
+
+	/* Validate input arguments. */
+	if (!ctx || emprevent >= SWSR_EMPREVENT_MAX ||
+	    (ctx->input.config.delim_type == SWSR_DELIM_SIZE &&
+	    size_delim_length > SWSR_MAX_DELIM_LENGTH)) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	if (ctx->input.config.delim_type == SWSR_DELIM_SIZE &&
+	    size_delim_length == 0 && !byte_count) {
+		pr_err("Byte count value must be provided when size delimiter is zero length: %s\n",
+		       __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	input = &ctx->input;
+
+	/*
+	 * Ensure that the input is at a delimiter since emulation prevention
+	 * removal will not have spanned into this next unit.
+	 * This allows emulation prevention detection modes to be changed.
+	 * Now check for delimiter.
+	 */
+	input->delim_found = swsr_checkfor_delimiter(ctx);
+
+	if (!input->delim_found)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	/* Output bitstream FIFOs should be empty. */
+	/* NOTE: flush output queue using seek function. */
+	SWSR_ASSERT(ctx->output.num_bits == 0);
+
+	/* Only update the delimiter length for size delimiters. */
+	if (input->config.delim_type == SWSR_DELIM_SIZE)
+		input->config.delim_length = size_delim_length;
+
+	/* Update the emulation prevention detection/removal scheme */
+	swsr_update_emprevent(emprevent, ctx);
+
+	/*
+	 * Peek at the NAL type and return in callback only
+	 * when delimiter is in bitstream.
+	 */
+	if (input->config.delim_length) {
+		unsigned int shift;
+		unsigned char naltype;
+
+		/*
+		 * Peek at the next 8-bits after the delimiter that
+		 * resides in internal FIFO.
+		 */
+		shift = SWSR_OUTPUT_FIFO_LENGTH -
+			(input->config.delim_length + SWSR_NALTYPE_LENGTH);
+		naltype = (input->fifo >> shift) & NBIT_8BYTE_MASK(SWSR_NALTYPE_LENGTH);
+
+		/*
+		 * Notify caller of NAL type so that bitstream segmentation
+		 * can take place before the delimiter is consumed
+		 */
+		ctx->buffer_ctx.cb_fxn(SWSR_EVENT_DELIMITER_NAL_TYPE, ctx->buffer_ctx.cb_param,
+			naltype, NULL, NULL);
+	}
+
+	/*
+	 * Clear the delimiter found flag and reset bytes read to allow
+	 * reading of data from input FIFO.
+	 */
+	input->delim_found = 0;
+
+	if (input->config.delim_length != 0) {
+		unsigned long long scpvalue = input->config.scp_value;
+		unsigned int i;
+		unsigned char byte = 0;
+
+		/*
+		 * Ensure that delimiter is not detected while delimiter
+		 * is read.
+		 */
+		if (input->config.delim_type == SWSR_DELIM_SIZE) {
+			input->bytes_read_since_delim = 0;
+			input->byte_count = (input->config.delim_length + 7) / 8;
+		} else if (input->config.delim_type == SWSR_DELIM_SCP) {
+			input->config.scp_value = 0xdeadbeefdeadbeefUL;
+		}
+
+		/*
+		 * Fill output FIFO only with bytes at least partially
+		 * used for delimiter.
+		 */
+		for (i = 0; i < ((input->config.delim_length + 7) / 8); i++) {
+			swsr_readbyte_from_inputfifo(ctx, &byte);
+
+			ctx->output.fifo |= ((unsigned long long)byte <<
+				(SWSR_OUTPUT_FIFO_LENGTH - 8 - ctx->output.num_bits));
+			ctx->output.num_bits += 8;
+		}
+
+		/*
+		 * Read delimiter from output FIFO leaving any remaining
+		 * non-byte-aligned bits behind.
+		 */
+		delimiter = swsr_getbits_from_outputfifo(ctx, input->config.delim_length, 1);
+
+		/* Restore SCP value. */
+		if (input->config.delim_type == SWSR_DELIM_SCP)
+			input->config.scp_value = scpvalue;
+	} else {
+		/*
+		 * For size delimited bitstreams without a delimiter use
+		 * the byte count provided.
+		 */
+		SWSR_ASSERT(*byte_count > 0);
+		delimiter = *byte_count;
+		SWSR_ASSERT(input->config.delim_type == SWSR_DELIM_SIZE);
+	}
+
+	if (input->config.delim_type == SWSR_DELIM_SCP)
+		SWSR_ASSERT((delimiter & NBIT_8BYTE_MASK(input->config.delim_length)) ==
+			input->config.scp_value);
+	else if (input->config.delim_type == SWSR_DELIM_SIZE) {
+		input->byte_count = delimiter;
+
+		/* Return byte count if argument provided. */
+		if (byte_count)
+			*byte_count = input->byte_count;
+	}
+
+	input->bytes_read_since_delim = 0;
+	{
+		struct swsr_buffer *buffer = input->buf;
+
+		if (!buffer)
+			buffer = lst_first(&ctx->buffer_ctx.used_buffer_list);
+		if (buffer)
+			input->delimited_unit_start_offset = (long)buffer->num_bytes_read;
+		else
+			input->delimited_unit_start_offset = 0;
+	}
+	input->delimited_unit_size = 0;
+	input->delimunit_bitofst = 0;
+
+	input->no_moredata = 0;
+
+	return 0;
+}
+
+enum swsr_found swsr_seek_delim_or_eod(void *ctx_hndl)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+	enum swsr_found found = SWSR_FOUND_DATA;
+	unsigned char byte;
+
+	/* Validate input arguments. */
+	if (!ctx) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return (enum swsr_found)IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return (enum swsr_found)IMG_ERROR_NOT_INITIALISED;
+	}
+
+	/* Read the residual contents of the output FIFO */
+	swsr_byte_align(ctx);
+	while (ctx->output.num_bits > 0) {
+		SWSR_ASSERT((ctx->output.num_bits & 0x7) == 0);
+		swsr_read_bits(ctx, 8);
+	}
+	SWSR_ASSERT(ctx->output.num_bits == 0);
+	if (ctx->input.config.delim_type == SWSR_DELIM_SCP) {
+		struct swsr_input *input = &ctx->input;
+		struct swsr_output *output = &ctx->output;
+
+		while (found == SWSR_FOUND_DATA) {
+			unsigned char *offset;
+			unsigned int delimlength_inbytes;
+			unsigned char *startoffset;
+			unsigned long long mask;
+			unsigned long long scp;
+			unsigned char scpfirstbyte;
+
+			/*
+			 * ensure that all the data in the input FIFO comes
+			 * from the current buffer
+			 */
+			if (input->buf && input->buf->byte_offset <= input->num_bytes) {
+				found = swsr_consumebyte_from_inputfifo(ctx, &byte);
+				continue;
+			}
+
+			/* consume remaining bytes from the FIFO */
+			if (!input->buf) {
+				found = swsr_consumebyte_from_inputfifo(ctx, &byte);
+				continue;
+			}
+
+			delimlength_inbytes = (input->config.delim_length + 7) / 8;
+
+			/*
+			 * Make the mask and the scp value byte aligned to
+			 * speed up things
+			 */
+			mask = ((1UL << input->config.delim_length) - 1) <<
+				(8 * delimlength_inbytes - input->config.delim_length);
+			scp = input->config.scp_value <<
+				(8 * delimlength_inbytes - input->config.delim_length);
+			scpfirstbyte = (scp >> 8 * (delimlength_inbytes - 1)) & 0xFF;
+
+			/* rollback the input FIFO */
+			input->buf->byte_offset -= input->num_bytes;
+			input->buf->num_bytes_read -= input->num_bytes;
+			input->bitstream_offset -= input->num_bytes;
+			input->num_bytes = 0;
+			input->fifo = 0;
+
+			startoffset = input->buf->data + input->buf->byte_offset;
+
+			while (found == SWSR_FOUND_DATA) {
+				offset = memchr(input->buf->data + input->buf->byte_offset,
+						scpfirstbyte,
+						input->buf->num_bytes -
+						(input->buf->byte_offset + delimlength_inbytes -
+						1));
+
+				if (offset) {
+					unsigned int i;
+
+					/*
+					 * load bytes that might be SCP into
+					 * the FIFO
+					 */
+					for (i = 0; i < delimlength_inbytes; i++) {
+						input->fifo <<= 8;
+						input->fifo |= offset[i];
+					}
+
+					input->buf->byte_offset = offset - input->buf->data;
+
+					if ((input->fifo & mask) == scp) {
+						unsigned long long bytesread = offset
+							- startoffset;
+
+						/*
+						 * Scp found, fill the rest of
+						 * the FIFO
+						 */
+					for (i = delimlength_inbytes;
+						i < SWSR_INPUT_FIFO_LENGTH &&
+						input->buf->byte_offset + i <
+						input->buf->num_bytes;
+						i++) {
+						input->fifo <<= 8;
+						input->fifo |= offset[i];
+					}
+
+						input->fifo <<= (SWSR_INPUT_FIFO_LENGTH - i) * 8;
+
+						input->bytes_for_next_sequ = 0;
+						input->num_bytes = i;
+
+						input->buf->byte_offset += i;
+
+						input->buf->num_bytes_read = offset -
+							input->buf->data;
+						input->bitstream_offset += bytesread + i;
+
+						output->totalbits_consumed += bytesread * 8;
+
+						input->delimunit_bitofst += bytesread * 8;
+
+						output->num_bits = 0;
+						output->fifo = 0;
+
+						SWSR_ASSERT(swsr_checkfor_delimiter(ctx));
+
+						found = SWSR_FOUND_DELIM;
+					} else {
+						input->buf->byte_offset++;
+					}
+				} else {
+					/* End of the current buffer */
+					unsigned int bytesread = input->buf->num_bytes -
+						(startoffset - input->buf->data);
+					unsigned int i;
+
+					/* update offsets */
+					input->bitstream_offset += bytesread;
+					output->totalbits_consumed += bytesread * 8;
+					input->delimunit_bitofst += bytesread * 8;
+
+					input->buf->byte_offset = input->buf->num_bytes;
+					input->buf->num_bytes_read = input->buf->num_bytes -
+						(delimlength_inbytes - 1);
+
+					/* load remaining bytes to FIFO */
+					offset = input->buf->data +
+						input->buf->num_bytes -
+						(delimlength_inbytes - 1);
+					for (i = 0; i < delimlength_inbytes - 1;
+						i++) {
+						input->fifo <<= 8;
+						input->fifo |= offset[i];
+					}
+
+					input->fifo <<= (SWSR_INPUT_FIFO_LENGTH - i) * 8;
+
+					input->bytes_for_next_sequ = 0;
+					input->num_bytes = delimlength_inbytes - 1;
+
+					output->num_bits = 0;
+					output->fifo = 0;
+
+					/*
+					 * Consume a few bytes from the next
+					 * byte to check if there is scp on
+					 * buffers boundary
+					 */
+					for (i = 0;
+						i < delimlength_inbytes && found == SWSR_FOUND_DATA;
+						i++) {
+						found = swsr_consumebyte_from_inputfifo(ctx, &byte);
+						SWSR_ASSERT(found != SWSR_FOUND_NONE);
+					}
+
+					break;
+				}
+			}
+		}
+	} else {
+		/*
+		 * Extract data from input FIFO until data is not found either
+		 * because we have run out or a SCP has been detected.
+		 */
+		while (found == SWSR_FOUND_DATA) {
+			found = swsr_consumebyte_from_inputfifo(ctx, &byte);
+			SWSR_ASSERT(found != SWSR_FOUND_NONE);
+		}
+	}
+
+	/*
+	 * When the end of data has been reached there should be no
+	 * more data in the input FIFO.
+	 */
+	if (found == SWSR_FOUND_EOD)
+		SWSR_ASSERT(ctx->input.num_bytes == 0);
+
+	SWSR_ASSERT(found != SWSR_FOUND_DATA);
+	return found;
+}
+
+enum swsr_found swsr_check_delim_or_eod(void *ctx_hndl)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+	enum swsr_found found = SWSR_FOUND_DATA;
+
+	/* Validate input arguments. */
+	if (!ctx) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+
+		return (enum swsr_found)IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+
+		return (enum swsr_found)IMG_ERROR_NOT_INITIALISED;
+	}
+
+	/*
+	 * End of data when all FIFOs are empty and there is nothing left to
+	 * read from the input buffers.
+	 */
+	if (ctx->output.num_bits == 0 && ctx->input.num_bytes == 0 &&
+	    ctx->input.bitstream_offset >= ctx->input.bitstream_size)
+		found = SWSR_FOUND_EOD;
+	else if (ctx->output.num_bits == 0 && swsr_checkfor_delimiter(ctx)) {
+		/*
+		 * Output queue is empty and delimiter is at the head of
+		 * input queue.
+		 */
+		found = SWSR_FOUND_DELIM;
+	}
+
+	return found;
+}
+
+int swsr_start_bitstream(void *ctx_hndl, const struct swsr_config *config,
+			 unsigned long long bitstream_size, enum swsr_emprevent emprevent)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+	struct swsr_buffer *buffer;
+	unsigned int result;
+
+	/* Validate input arguments. */
+	if (!ctx || !config || config->delim_type >= SWSR_DELIM_MAX ||
+	    config->delim_length > SWSR_MAX_DELIM_LENGTH ||
+	    config->scp_value > NBIT_8BYTE_MASK(config->delim_length) ||
+	    emprevent >= SWSR_EMPREVENT_MAX) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	/* Move all used buffers into free list */
+	buffer = lst_removehead(&ctx->buffer_ctx.used_buffer_list);
+	while (buffer) {
+		lst_add(&ctx->buffer_ctx.free_buffer_list, buffer);
+		buffer = lst_removehead(&ctx->buffer_ctx.used_buffer_list);
+	}
+
+	/* Clear all the shift-register state (except config) */
+	memset(&ctx->input, 0, sizeof(ctx->input));
+	memset(&ctx->output, 0, sizeof(ctx->output));
+
+	/* Update input FIFO configuration */
+	ctx->input.bitstream_size = bitstream_size;
+	ctx->input.config = *config;
+	result = swsr_update_emprevent(emprevent, ctx);
+	SWSR_ASSERT(result == 0);
+
+	/*
+	 * Signal delimiter found to ensure that no data is read out of
+	 * input FIFO
+	 * while fetching the first bitstream data into input FIFO.
+	 */
+	ctx->input.delim_found = 1;
+	result = swsr_fill_outputfifo(ctx);
+	SWSR_ASSERT(result == 0);
+
+	/* Now check for delimiter. */
+	ctx->input.delim_found = swsr_checkfor_delimiter(ctx);
+
+	return 0;
+}
+
+int swsr_deinitialise(void *ctx_hndl)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+	struct swsr_buffer *buffer;
+
+	/* Validate input arguments. */
+	if (!ctx) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	/* Free all used buffer containers */
+	buffer = lst_removehead(&ctx->buffer_ctx.used_buffer_list);
+	while (buffer) {
+		kfree(buffer);
+		buffer = lst_removehead(&ctx->buffer_ctx.used_buffer_list);
+	}
+
+	/* Free all free buffer containers. */
+	buffer = lst_removehead(&ctx->buffer_ctx.free_buffer_list);
+	while (buffer) {
+		kfree(buffer);
+		buffer = lst_removehead(&ctx->buffer_ctx.free_buffer_list);
+	}
+
+	ctx->initialised = 0;
+	kfree(ctx);
+
+	return 0;
+}
+
+int swsr_initialise(swsr_except_handler_fxn exception_handler_fxn,
+		    void *exception_cbparam, swsr_callback_fxn callback_fxn,
+		    void *cb_param, void **ctx_hndl)
+{
+	struct swsr_context *ctx;
+	struct swsr_buffer *buffer;
+	unsigned int i;
+	unsigned int result;
+
+	/* Validate input arguments. */
+	if (!exception_handler_fxn || !exception_cbparam || !callback_fxn ||
+	    !cb_param || !ctx_hndl) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Allocate and initialise shift-register context */
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx) {
+		VDEC_ASSERT(0);
+		return -EINVAL;
+	}
+
+	/* Setup shift-register context */
+	ctx->exception_handler_fxn = exception_handler_fxn;
+	ctx->pexception_param = exception_cbparam;
+
+	ctx->buffer_ctx.cb_fxn = callback_fxn;
+	ctx->buffer_ctx.cb_param = cb_param;
+
+	/*
+	 * Allocate a new buffer container for each byte in internal storage.
+	 * This is the theoretical maximum number of buffers in the SWSR at
+	 * any one time.
+	 */
+	for (i = 0; i < SWSR_INPUT_FIFO_LENGTH + (SWSR_OUTPUT_FIFO_LENGTH / 8);
+		i++) {
+		/* Allocate a buffer container */
+		buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+		SWSR_ASSERT(buffer);
+		if (!buffer) {
+			result = IMG_ERROR_OUT_OF_MEMORY;
+			goto error;
+		}
+
+		/* Add container to free list */
+		lst_add(&ctx->buffer_ctx.free_buffer_list, buffer);
+	}
+
+	SWSR_ASSERT(SWSR_MAX_SYNTAX_LENGTH <= (sizeof(unsigned int) * 8));
+
+	ctx->initialised = 1;
+	*ctx_hndl = ctx;
+
+	return 0;
+error:
+	buffer = lst_removehead(&ctx->buffer_ctx.free_buffer_list);
+	while (buffer) {
+		kfree(buffer);
+		buffer = lst_removehead(&ctx->buffer_ctx.free_buffer_list);
+	}
+	kfree(ctx);
+
+	return result;
+}
+
+static unsigned char swsr_israwdata_extraction_supported(struct swsr_context *ctx)
+{
+	/*
+	 * For now only h.264/HEVC like 0x000001 SCP delimited
+	 * bistreams are supported.
+	 */
+	if (ctx->input.config.delim_type == SWSR_DELIM_SCP &&
+	    ctx->input.config.delim_length == (3 * 8) &&
+	    ctx->input.config.scp_value == 0x000001)
+		return 1;
+
+	return 0;
+}
+
+static int swsr_getcurrent_delimited_unitsize(struct swsr_context *ctx, unsigned int *size)
+{
+	struct swsr_buffer *buf;
+
+	buf = ctx->input.buf;
+	if (!buf)
+		buf = lst_first(&ctx->buffer_ctx.used_buffer_list);
+
+	if (buf && ctx->input.delimited_unit_start_offset >= 0 &&
+	    ctx->input.delimited_unit_start_offset < buf->num_bytes) {
+		unsigned long long bufptr =
+			(unsigned long long)ctx->input.delimited_unit_start_offset;
+		unsigned int zeros = 0;
+
+		/* Scan the current buffer for the next SCP. */
+		while (1) {
+			/* Look for two consecutive 0 bytes. */
+			while ((bufptr < buf->num_bytes) && (zeros < 2)) {
+				if (buf->data[bufptr++] == 0)
+					zeros++;
+				else
+					zeros = 0;
+			}
+			/*
+			 * If we're not at the end of the buffer already and
+			 * the next byte is 1, we've got it.
+			 */
+			/*
+			 * If we're at the end of the buffer, just assume
+			 * we've got it too
+			 * as we do not support buffer spanning units.
+			 */
+			if (bufptr < buf->num_bytes && buf->data[bufptr] == 1) {
+				break;
+			} else if (bufptr == buf->num_bytes) {
+				zeros = 0;
+				break;
+			}
+			/*
+			 * Finally just decrease the number of 0s found
+			 * already and go on scanning.
+			 */
+			else
+				zeros = 1;
+		}
+		/* Calculate the unit size. */
+		ctx->input.delimited_unit_size = (unsigned int)(bufptr -
+			(unsigned long long)ctx->input.delimited_unit_start_offset) - zeros;
+		*size = ctx->input.delimited_unit_size;
+	} else {
+		return IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+	}
+
+	return 0;
+}
+
+int swsr_get_current_delimited_unitsize(void *ctx_hndl, unsigned int *size)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+
+	/* Validate input arguments. */
+	if (!ctx || !size) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	if (!swsr_israwdata_extraction_supported(ctx))
+		return IMG_ERROR_NOT_SUPPORTED;
+
+	return swsr_getcurrent_delimited_unitsize(ctx, size);
+}
+
+int swsr_get_current_delimited_unit(void *ctx_hndl, unsigned char *data, unsigned int *size)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+	struct swsr_buffer *buf;
+	unsigned int copysize;
+
+	/* Validate input arguments. */
+	if (!ctx || !data || !size || *size == 0) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	if (!swsr_israwdata_extraction_supported(ctx))
+		return IMG_ERROR_NOT_SUPPORTED;
+
+	buf = ctx->input.buf;
+	if (!buf)
+		buf = lst_first(&ctx->buffer_ctx.used_buffer_list);
+
+	if (buf && ctx->input.delimited_unit_start_offset >= 0) {
+		if (ctx->input.delimited_unit_size == 0)
+			swsr_getcurrent_delimited_unitsize(ctx, &copysize);
+
+		if (ctx->input.delimited_unit_size < *size)
+			*size = ctx->input.delimited_unit_size;
+
+		memcpy(data, buf->data + ctx->input.delimited_unit_start_offset, *size);
+	} else {
+		return IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+	}
+
+	return 0;
+}
+
+int swsr_get_current_delimited_unit_bit_offset(void *ctx_hndl, unsigned int *bit_offset)
+{
+	struct swsr_context *ctx = (struct swsr_context *)ctx_hndl;
+
+	/* Validate input arguments. */
+	if (!ctx || !bit_offset) {
+		pr_err("Invalid arguments to function: %s\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!ctx->initialised) {
+		pr_err("SWSR not yet initialised: %s\n", __func__);
+		return IMG_ERROR_NOT_INITIALISED;
+	}
+
+	if (!swsr_israwdata_extraction_supported(ctx))
+		return IMG_ERROR_NOT_SUPPORTED;
+
+	if (ctx->input.delimited_unit_start_offset >= 0)
+		*bit_offset = ctx->input.delimunit_bitofst;
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/swsr.h b/drivers/media/platform/img/vxe-vxd/decoder/swsr.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/swsr.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/swsr.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,278 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Software Shift Register Access fucntions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstreming
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef _SWSR_H
+#define _SWSR_H
+
+#include <linux/types.h>
+
+#include "img_errors.h"
+#include "lst.h"
+
+#define SWSR_MAX_DELIM_LENGTH   (8 * 8)
+
+enum swsr_exception {
+	SWSR_EXCEPT_NO_EXCEPTION = 0x00,
+	SWSR_EXCEPT_ENCAPULATION_ERROR1,
+	SWSR_EXCEPT_ENCAPULATION_ERROR2,
+	SWSR_EXCEPT_ACCESS_INTO_SCP,
+	SWSR_EXCEPT_ACCESS_BEYOND_EOD,
+	SWSR_EXCEPT_EXPGOULOMB_ERROR,
+	SWSR_EXCEPT_WRONG_CODEWORD_ERROR,
+	SWSR_EXCEPT_NO_SCP,
+	SWSR_EXCEPT_INVALID_CONTEXT,
+	SWSR_EXCEPT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum swsr_cbevent {
+	SWSR_EVENT_INPUT_BUFFER_START = 0,
+	SWSR_EVENT_OUTPUT_BUFFER_END,
+	SWSR_EVENT_DELIMITER_NAL_TYPE,
+	SWSR_EVENT_FORCE32BITS        = 0x7FFFFFFFU
+};
+
+enum swsr_found {
+	SWSR_FOUND_NONE        = 0,
+	SWSR_FOUND_EOD,
+	SWSR_FOUND_DELIM,
+	SWSR_FOUND_DATA,
+	SWSR_FOUND_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum swsr_delim_type {
+	SWSR_DELIM_NONE        = 0,
+	SWSR_DELIM_SCP,
+	SWSR_DELIM_SIZE,
+	SWSR_DELIM_MAX,
+	SWSR_DELIM_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum swsr_emprevent {
+	SWSR_EMPREVENT_NONE = 0x00,
+	SWSR_EMPREVENT_00000300,
+	SWSR_EMPREVENT_ff00,
+	SWSR_EMPREVENT_000002,
+	SWSR_EMPREVENT_MAX,
+	SWSR_EMPREVENT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+struct swsr_config {
+	enum swsr_delim_type delim_type;
+	unsigned int delim_length;
+	unsigned long long scp_value;
+};
+
+/*
+ * This is the function prototype for the caller supplier exception handler.
+ *
+ * NOTE: The internally recorded exception is reset to #SWSR_EXCEPT_NO_EXCEPTION
+ * on return from SWSR_CheckException() or a call to the caller supplied
+ * exception handler see #SWSR_pfnExceptHandler.
+ *
+ * NOTE: By defining an exception handler the caller can handle Shift Register
+ * errors as they occur - for example, using a structure exception mechanism
+ * such as setjmp/longjmp.
+ */
+typedef void (*swsr_except_handler_fxn)(enum swsr_exception exception,
+					void *callback_param);
+
+/*
+ * This is the function prototype for the caller supplier to retrieve the data
+ * from the application
+ */
+typedef void (*swsr_callback_fxn)(enum swsr_cbevent event,
+				  void *priv_data,
+				  unsigned char nal_type, unsigned char **data_buffer,
+				  unsigned long long *data_size);
+
+int swsr_get_total_bitsconsumed(void *context, unsigned long long *total_bitsconsumed);
+
+/*
+ * This function is used to return the offset into the current bitstream buffer
+ * on the shift-register output FIFO. Call after #SWSR_SeekDelimOrEOD to
+ * determine the offset of an delimiter.
+ */
+int swsr_get_byte_offset_curbuf(void *context, unsigned long long *byte_offset);
+
+/*
+ * This function is used to read a signed Exp-Goulomb value from the Shift
+ * Register.
+ *
+ * NOTE: If this function is used to attempt to read into a Start-Code-Prefix
+ * or beyond the End-Of-Data then and exception is generated which can be
+ * handled by the caller supplied exception handler see
+ * #SWSR_pfnExceptionHandler. If no exception handler has been supplied (or the
+ * exception handler returns) then the exception is recorded and can be obtained
+ * using SWSR_CheckException(). In this event the function returns 0.
+ */
+int swsr_read_signed_expgoulomb(void *context);
+
+/*
+ * This function is used to read a unsigned Exp-Goulomb value from the Shift
+ * Register.
+ *
+ * NOTE: If this function is used to attempt to read into a Start-Code-Prefix
+ * or beyond the End-Of-Data then and exception is generated which can be
+ * handled by the caller supplied exception handler see
+ * #SWSR_pfnExceptionHandler. If no exception handler has been supplied (or the
+ * exception handler returns) then the exception is recorded and can be obtained
+ * using SWSR_CheckException(). In this event the function returns 0.
+ */
+unsigned int swsr_read_unsigned_expgoulomb(void *context);
+
+/*
+ * This function is used to check for exceptions.
+ *
+ * NOTE: The internally recorded exception is reset to #SWSR_EXCEPT_NO_EXCEPTION
+ * on return from SWSR_CheckException() or a call to the caller supplied
+ * exception  handler see #SWSR_pfnExceptionHandler.
+ */
+enum swsr_exception swsr_check_exception(void *context);
+
+/*
+ * This function is used to check for bitstream data with
+ * SWSR_EMPREVENT_00000300 whether more RBSP data is present.
+ */
+int swsr_check_more_rbsp_data(void *context, unsigned char *more_rbsp_data);
+
+/*
+ * This function is used to read a single bit from the Shift Register.
+ *
+ * NOTE: If this function is used to attempt to read into a Start-Code-Prefix
+ * or beyond the End-Of-Data then and exception is generated which can be
+ * handled by the caller supplied exception handler see
+ * #SWSR_pfnExceptionHandler. If no exception handler has been supplied (or the
+ * exception handler returns) then the exception is recorded and can be obtained
+ * using SWSR_CheckException(). In this event the function returns 0.
+ */
+unsigned int swsr_read_onebit(void *context);
+
+/*
+ * This function is used to consume a number of bits from the Shift Register.
+ *
+ * NOTE: If this function is used to attempt to read into a Start-Code-Prefix
+ * or beyond the End-Of-Data then and exception is generated which can be
+ * handled by the caller supplied exception handler see
+ * #SWSR_pfnExceptionHandler. If no exception handler has been supplied (or the
+ * exception handler returns) then the exception is recorded and can be obtained
+ * using SWSR_CheckException(). In this event the function returns 0.
+ */
+unsigned int swsr_read_bits(void *context, unsigned int no_bits);
+
+int swsr_read_signedbits(void *context, unsigned int no_bits);
+
+/*
+ * This function is used to peek at number of bits from the Shift Register. The
+ * bits are not consumed.
+ *
+ * NOTE: If this function is used to attempt to read into a Start-Code-Prefix
+ * or beyond the End-Of-Data then and exception is generated which can be
+ * handled by the caller supplied exception handler see
+ * #SWSR_pfnExceptionHandler. If no exception handler has been supplied (or
+ * the exception handler returns) then the exception is recorded and can be
+ * obtained using SWSR_CheckException(). In this event the function returns 0.
+ */
+unsigned int swsr_peekbits(void *context, unsigned int no_bits);
+
+/*
+ * Makes the shift-register output byte-aligned by consuming the remainder of
+ * the current partially read byte.
+ */
+int swsr_byte_align(void *context);
+
+/*
+ * Consume the next delimiter whose length should be specified if delimiter type
+ * is #SWSR_DELIM_SIZE. The emulation prevention detection/removal scheme can
+ * also be specified for this and subsequent units.
+ *
+ * Consumes the unit delimiter from the bitstream buffer. The delimiter type
+ * depends upon the bitstream format.
+ */
+int swsr_consume_delim(void *context,
+		       enum swsr_emprevent emprevent,
+		       unsigned int size_delim_length,
+		       unsigned long long *byte_count);
+
+/*
+ * Seek for the next delimiter or end of bitstream data if no delimiter is
+ * found.
+ */
+enum swsr_found swsr_seek_delim_or_eod(void *context);
+
+/*
+ * Check if shift-register is at a delimiter or end of data.
+ */
+enum swsr_found swsr_check_delim_or_eod(void *context);
+
+/*
+ * This function automatically fetches the first bitstream buffer (using
+ * callback with event type #SWSR_EVENT_INPUT_BUFFER_START) before returning.
+ */
+int swsr_start_bitstream(void *context,
+			 const struct swsr_config *pconfig,
+			 unsigned long long bitstream_size,
+			 enum swsr_emprevent emprevent);
+
+/*
+ * This function is used to de-initialise the Shift Register.
+ */
+int swsr_deinitialise(void *context);
+
+/*
+ * This function is used to initialise the Shift Register.
+ *
+ * NOTE: If no exception handler is provided (pfnExceptionHandler == IMG_NULL)
+ * then the caller must check for exceptions using the function
+ * SWSR_CheckException().
+ *
+ * NOTE: If pui8RbduBuffer is IMG_NULL then the bit stream is not encapsulated
+ * so the Shift Register needn't perform and de-encapsulation.  However,
+ * if this is not IMG_NULL then, from time to time, the Shift Register APIs
+ * will de-encapsulate portions of the bit stream into this intermediate buffer
+ * - the larger the buffer the less frequent the de-encapsulation function
+ * needs to be called.
+ */
+int swsr_initialise(swsr_except_handler_fxn exception_handler_fxn,
+		    void *exception_cbparam,
+		    swsr_callback_fxn callback_fxn,
+		    void *cb_param,
+		    void **context);
+
+/*
+ *  This function is used to return the size in bytes of the delimited unit
+ *  that's currently being processed.
+ *
+ *  NOTE: This size includes all the emulation prevention bytes present
+ *  in the delimited unit.
+ */
+int swsr_get_current_delimited_unitsize(void *context, unsigned int *size);
+
+/*
+ * This function is used to copy the delimited unit that's currently being
+ * processed to the provided buffer.
+ *
+ * NOTE: This delimited unit includes all the emulation prevention bytes present
+ * in it.
+ */
+int swsr_get_current_delimited_unit(void *context, unsigned char *data, unsigned int *size);
+
+/*
+ * This function is used to return the bit offset the shift register is at
+ * in processing the current delimited unit.
+ *
+ * NOTE: This offset does not count emulation prevention bytes.
+ */
+int swsr_get_current_delimited_unit_bit_offset(void *context, unsigned int *bit_offset);
+
+#endif /* _SWSR_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/translation_api.c b/drivers/media/platform/img/vxe-vxd/decoder/translation_api.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/translation_api.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/translation_api.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1725 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VDECDD translation APIs.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+/* As of now we are defining HAS_H264 */
+#define HAS_H264
+#define VDEC_USE_PVDEC
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "fw_interface.h"
+#ifdef HAS_H264
+#include "h264fw_data.h"
+#endif /* HAS_H264 */
+#include "hw_control.h"
+#include "img_errors.h"
+#include "img_msvdx_cmds.h"
+#include "img_msvdx_vec_regs.h"
+#ifdef VDEC_USE_PVDEC
+#include "pvdec_int.h"
+#include "img_pvdec_core_regs.h"
+#endif
+#include "img_video_bus4_mmu_regs.h"
+#include "lst.h"
+#include "reg_io2.h"
+#include "rman_api.h"
+#include "translation_api.h"
+#include "vdecdd_defs.h"
+#include "vdecdd_utils.h"
+#include "vdecfw_share.h"
+#include "vxd_int.h"
+#include "vxd_props.h"
+
+#ifdef HAS_HEVC
+#include "hevcfw_data.h"
+#include "pvdec_entropy_regs.h"
+#include "pvdec_vec_be_regs.h"
+#endif
+
+#ifdef HAS_JPEG
+#include "jpegfw_data.h"
+#endif /* HAS_JPEG */
+
+#define NO_VALUE        0
+
+/*
+ * Discontinuity in layout of VEC_VLC_TABLE* registers.
+ * Address of VEC_VLC_TABLE_ADDR16 does not immediately follow
+ * VEC_VLC_TABLE_ADDR15, see TRM.
+ */
+#define VEC_VLC_TABLE_ADDR_PT1_SIZE  16 /* in 32-bit words */
+#define VEC_VLC_TABLE_ADDR_DISCONT   (VEC_VLC_TABLE_ADDR_PT1_SIZE * \
+	PVDECIO_VLC_IDX_ADDR_PARTS)
+
+/*
+ * now it can be done by VXD_GetCodecMode
+ * Imply standard from OperatingMode.
+ * As of now only H264 supported through the file.
+ */
+#define CODEC_MODE_JPEG     0x0
+#define CODEC_MODE_H264         0x1
+#define CODEC_MODE_REAL8        0x8
+#define CODEC_MODE_REAL9        0x9
+
+/*
+ * This enum defines values of ENTDEC_BE_MODE field of VEC_ENTDEC_BE_CONTROL
+ * register and ENTDEC_FE_MODE field of VEC_ENTDEC_FE_CONTROL register.
+ */
+enum decode_mode {
+	/* JPEG */
+	VDEC_ENTDEC_MODE_JPEG   = 0x0,
+	/* H264 (MPEG4/AVC) */
+	VDEC_ENTDEC_MODE_H264   = 0x1,
+	VDEC_ENTDEC_MODE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This has all that it needs to translate a Stream Unit for a picture into a
+ * transaction.
+ */
+static int translation_set_buffer(struct vdecdd_ddpict_buf *picbuf,
+				  struct vdecfw_image_buffer *image_buffer)
+{
+	unsigned int i;
+
+	for (i = 0; i < VDEC_PLANE_MAX; i++) {
+		image_buffer->byte_offset[i] =
+			(unsigned int)GET_HOST_ADDR(&picbuf->pict_buf->ddbuf_info) +
+			picbuf->rend_info.plane_info[i].offset;
+		pr_debug("%s image_buffer->byte_offset[%d] = 0x%x\n",
+			 __func__, i, image_buffer->byte_offset[i]);
+	}
+	return IMG_SUCCESS;
+}
+
+#ifdef HAS_HEVC
+/*
+ * @Function              translation_hevc_header
+ */
+static int translation_hevc_header(struct vdecdd_picture *picture,
+				   struct dec_decpict *dec_pict,
+				   struct hevcfw_headerdata *header_data)
+{
+	translation_set_buffer(dec_pict->recon_pict, &header_data->primary);
+
+	if (dec_pict->alt_pict)
+		translation_set_buffer(dec_pict->alt_pict, &header_data->alternate);
+
+	VDEC_ASSERT(picture);
+	VDEC_ASSERT(picture->pict_res_int);
+	VDEC_ASSERT(picture->pict_res_int->mb_param_buf);
+	header_data->temporal_outaddr = (unsigned int)GET_HOST_ADDR
+					(&picture->pict_res_int->mb_param_buf->ddbuf_info);
+
+	return IMG_SUCCESS;
+}
+#endif
+
+#ifdef HAS_H264
+static int translation_h264header(struct vdecdd_picture *pspicture,
+				  struct dec_decpict *dec_pict,
+				  struct h264fw_header_data *psheaderdata,
+				  struct vdec_str_configdata *psstrconfigdata)
+{
+	psheaderdata->two_pass_flag = dec_pict->pict_hdr_info->discontinuous_mbs;
+	psheaderdata->disable_mvc = psstrconfigdata->disable_mvc;
+
+	/*
+	 * As of now commenting the mb params base address as we are not using,
+	 * if needed in future please un comment and make the allocation for
+	 * pict_res_int.
+	 */
+	/* Obtain the MB parameter address from the stream unit. */
+	if (pspicture->pict_res_int->mb_param_buf) {
+		psheaderdata->mbparams_base_address =
+		(unsigned int)GET_HOST_ADDR(&pspicture->pict_res_int->mb_param_buf->ddbuf_info);
+		psheaderdata->mbparams_size_per_plane =
+			pspicture->pict_res_int->mb_param_buf->ddbuf_info.buf_size / 3;
+	} else {
+		psheaderdata->mbparams_base_address = 0;
+		psheaderdata->mbparams_size_per_plane = 0;
+	}
+	psheaderdata->slicegroupmap_base_address =
+		(unsigned int)GET_HOST_ADDR(&dec_pict->cur_pict_dec_res->h264_sgm_buf);
+
+	translation_set_buffer(dec_pict->recon_pict, &psheaderdata->primary);
+
+	if (dec_pict->alt_pict)
+		translation_set_buffer(dec_pict->alt_pict, &psheaderdata->alternate);
+
+	/* Signal whether we have PPS for the second field. */
+	if (pspicture->dec_pict_aux_info.second_pps_id == BSPP_INVALID)
+		psheaderdata->second_pps = 0;
+	else
+		psheaderdata->second_pps = 1;
+
+	return IMG_SUCCESS;
+}
+#endif /* HAS_H264 */
+
+#ifdef HAS_JPEG
+
+static int translation_jpegheader(const struct bspp_sequ_hdr_info *seq,
+				  const struct dec_decpict *dec_pict,
+				  const struct bspp_pict_hdr_info *pict_hdrinfo,
+				  struct jpegfw_header_data *header_data)
+{
+	unsigned int i;
+
+	/* Output picture planes addresses */
+	for (i = 0; i < seq->com_sequ_hdr_info.pixel_info.num_planes; i++) {
+		header_data->plane_offsets[i] =
+			(unsigned int)GET_HOST_ADDR(&dec_pict->recon_pict->pict_buf->ddbuf_info) +
+			dec_pict->recon_pict->rend_info.plane_info[i].offset;
+	}
+
+	/* copy the expected SOS fields number */
+	header_data->hdr_sos_count = pict_hdrinfo->sos_count;
+
+	translation_set_buffer(dec_pict->recon_pict, &header_data->primary);
+
+	return IMG_SUCCESS;
+}
+#endif /* HAS_JPEG */
+/*
+ * This function translates host video standard enum (VDEC_eVidStd) into
+ * firmware video standard enum (VDECFW_eCodecType);
+ */
+static int translation_get_codec(enum vdec_vid_std evidstd,
+				 enum vdecfw_codectype *pecodec)
+{
+	enum vdecfw_codectype ecodec = VDEC_CODEC_NONE;
+	unsigned int result = IMG_ERROR_NOT_SUPPORTED;
+
+	/* Translate from video standard to firmware codec. */
+	switch (evidstd) {
+	#ifdef HAS_H264
+	case VDEC_STD_H264:
+		ecodec = VDECFW_CODEC_H264;
+		result = IMG_SUCCESS;
+		break;
+	#endif /* HAS_H264 */
+#ifdef HAS_HEVC
+	case VDEC_STD_HEVC:
+		ecodec = VDECFW_CODEC_HEVC;
+		result = IMG_SUCCESS;
+		break;
+#endif /* HAS_HEVC */
+#ifdef HAS_JPEG
+	case VDEC_STD_JPEG:
+		ecodec = VDECFW_CODEC_JPEG;
+		result = IMG_SUCCESS;
+		break;
+#endif
+	default:
+		result = IMG_ERROR_NOT_SUPPORTED;
+		break;
+	}
+	*pecodec = ecodec;
+	return result;
+}
+
+/*
+ * This function is used to obtain buffer for sequence header.
+ */
+static int translation_get_seqhdr(struct vdecdd_str_unit *psstrunit,
+				  struct dec_decpict *psdecpict,
+				  unsigned int *puipseqaddr)
+{
+	/*
+	 * ending Sequence info only if its a First Pic of Sequence, or a Start
+	 * of Closed GOP
+	 */
+	if (psstrunit->pict_hdr_info->first_pic_of_sequence || psstrunit->closed_gop) {
+		struct vdecdd_ddbuf_mapinfo *ddbuf_map_info;
+		/* Get access to map info context */
+		int result = rman_get_resource(psstrunit->seq_hdr_info->bufmap_id,
+					       VDECDD_BUFMAP_TYPE_ID,
+					       (void **)&ddbuf_map_info, NULL);
+		VDEC_ASSERT(result == IMG_SUCCESS);
+		if (result != IMG_SUCCESS)
+			return result;
+
+		*puipseqaddr = GET_HOST_ADDR_OFFSET(&ddbuf_map_info->ddbuf_info,
+						    psstrunit->seq_hdr_info->buf_offset);
+	} else {
+		*puipseqaddr = 0;
+	}
+	return IMG_SUCCESS;
+}
+
+/*
+ * This function is used to obtain buffer for picture parameter set.
+ */
+static int translation_get_ppshdr(struct vdecdd_str_unit *psstrunit,
+				  struct dec_decpict *psdecpict,
+				  unsigned int *puipppsaddr)
+{
+	if (psstrunit->pict_hdr_info->pict_aux_data.id != BSPP_INVALID) {
+		struct vdecdd_ddbuf_mapinfo *ddbuf_map_info;
+		int result;
+
+		VDEC_ASSERT(psstrunit->pict_hdr_info->pict_aux_data.pic_data);
+		/* Get access to map info context */
+		result = rman_get_resource(psstrunit->pict_hdr_info->pict_aux_data.bufmap_id,
+					   VDECDD_BUFMAP_TYPE_ID,
+					   (void **)&ddbuf_map_info, NULL);
+		VDEC_ASSERT(result == IMG_SUCCESS);
+
+		if (result != IMG_SUCCESS)
+			return result;
+		*puipppsaddr =
+			GET_HOST_ADDR_OFFSET(&ddbuf_map_info->ddbuf_info,
+					     psstrunit->pict_hdr_info->pict_aux_data.buf_offset);
+	} else {
+		*puipppsaddr = 0;
+	}
+	return IMG_SUCCESS;
+}
+
+/*
+ * This function is used to obtain buffer for second picture parameter set.
+ */
+static int translation_getsecond_ppshdr(struct vdecdd_str_unit *psstrunit,
+					unsigned int *puisecond_ppshdr)
+{
+	if (psstrunit->pict_hdr_info->second_pict_aux_data.id !=
+		BSPP_INVALID) {
+		struct vdecdd_ddbuf_mapinfo *ddbuf_map_info;
+		int result;
+		void *pic_data =
+			psstrunit->pict_hdr_info->second_pict_aux_data.pic_data;
+
+		VDEC_ASSERT(pic_data);
+		result = rman_get_resource(psstrunit->pict_hdr_info->second_pict_aux_data.bufmap_id,
+					   VDECDD_BUFMAP_TYPE_ID,
+					   (void **)&ddbuf_map_info, NULL);
+		VDEC_ASSERT(result == IMG_SUCCESS);
+
+		if (result != IMG_SUCCESS)
+			return result;
+
+		*puisecond_ppshdr =
+			GET_HOST_ADDR_OFFSET
+				(&ddbuf_map_info->ddbuf_info,
+				 psstrunit->pict_hdr_info->second_pict_aux_data.buf_offset);
+	} else {
+		*puisecond_ppshdr = 0;
+	}
+	return IMG_SUCCESS;
+}
+
+/*
+ * Returns address from which FW should download its shared context.
+ */
+static unsigned int translation_getctx_loadaddr(struct dec_decpict *psdecpict)
+{
+	if (psdecpict->prev_pict_dec_res)
+		return GET_HOST_ADDR(&psdecpict->prev_pict_dec_res->fw_ctx_buf);
+
+	/*
+	 * No previous context exists, using current context leads to
+	 * problems on replay so just say to FW to use clean one.
+	 * This is NULL as integer to avoid pointer size warnings due
+	 * to type casting.
+	 */
+	return 0;
+}
+
+static void translation_setup_std_header
+	(struct vdec_str_configdata *str_configdata,
+	struct dec_decpict *dec_pict,
+	struct vdecdd_str_unit *str_unit, unsigned int *psr_hdrsize,
+	struct vdecdd_picture *picture, unsigned int *picture_cmds,
+	enum vdecfw_parsermode *parser_mode)
+{
+	switch (str_configdata->vid_std) {
+#ifdef HAS_H264
+	case VDEC_STD_H264:
+	{
+		struct h264fw_header_data *header_data =
+			(struct h264fw_header_data *)
+			dec_pict->hdr_info->ddbuf_info->cpu_virt;
+		*parser_mode = str_unit->pict_hdr_info->parser_mode;
+
+		if (str_unit->pict_hdr_info->parser_mode !=
+			VDECFW_SCP_ONLY) {
+			pr_warn("VDECFW_SCP_ONLY mode supported in PVDEC FW\n");
+		}
+		/* Reset header data. */
+		memset(header_data, 0, sizeof(*(header_data)));
+
+		/* Prepare active parameter sets. */
+		translation_h264header(picture, dec_pict, header_data, str_configdata);
+
+		/* Setup header size in the transaction. */
+		*psr_hdrsize = sizeof(struct h264fw_header_data);
+		break;
+	}
+#endif /* HAS_H264 */
+
+#ifdef HAS_HEVC
+	case VDEC_STD_HEVC:
+	{
+		struct hevcfw_headerdata *header_data =
+			(struct hevcfw_headerdata *)dec_pict->hdr_info->ddbuf_info->cpu_virt;
+		*parser_mode = str_unit->pict_hdr_info->parser_mode;
+
+		/* Reset header data. */
+		memset(header_data, 0, sizeof(*header_data));
+
+		/* Prepare active parameter sets. */
+		translation_hevc_header(picture, dec_pict, header_data);
+
+		/* Setup header size in the transaction. */
+		*psr_hdrsize = sizeof(struct hevcfw_headerdata);
+		break;
+	}
+#endif
+#ifdef HAS_JPEG
+	case VDEC_STD_JPEG:
+	{
+		struct jpegfw_header_data *header_data =
+			(struct jpegfw_header_data *)dec_pict->hdr_info->ddbuf_info->cpu_virt;
+		const struct bspp_sequ_hdr_info *seq = str_unit->seq_hdr_info;
+		const struct bspp_pict_hdr_info *pict_hdr_info = str_unit->pict_hdr_info;
+
+		/* Reset header data. */
+		memset(header_data, 0, sizeof(*(header_data)));
+
+		/* Prepare active parameter sets. */
+		translation_jpegheader(seq, dec_pict, pict_hdr_info, header_data);
+
+		/* Setup header size in the transaction. */
+		*psr_hdrsize = sizeof(struct jpegfw_header_data);
+		break;
+	}
+#endif
+	default:
+		VDEC_ASSERT(NULL == "Unknown standard!");
+		*psr_hdrsize = 0;
+		break;
+	}
+}
+
+#define VDEC_INITIAL_DEVA_DMA_CMD_SIZE 3
+#define VDEC_SINLGE_DEVA_DMA_CMD_SIZE 2
+
+#ifdef VDEC_USE_PVDEC
+/*
+ * Creates DEVA bitstream segments command and saves is to control allocation
+ * buffer.
+ */
+static int translation_pvdec_adddma_transfers
+	(struct lst_t *decpic_seglist, unsigned int **dma_cmdbuf,
+	int cmd_bufsize, struct dec_decpict *psdecpict, int eop)
+{
+	/*
+	 * DEVA's bitstream DMA command is made out of chunks with following
+	 * layout ('+' sign is used to mark actual words in command):
+	 *
+	 * + Bitstream HDR, type unsigned int, consists of:
+	 *	- command id (CMD_BITSTREAM_SEGMENTS),
+	 *	- number of segments in this chunk,
+	 *	- optional CMD_BITSTREAM_SEGMENTS_MORE_FOLLOW_MASK
+	 *
+	 * + Bitstream total size, type unsigned int,
+	 * represents size of all segments in all chunks
+	 *
+	 * Segments of following type (can repeat up to
+	 * CMD_BITSTREAM_SEGMENTS_MINUS1_MASK + 1 times)
+	 *
+	 *	+ Bitstream segment address, type unsigned int
+	 *
+	 *	+ Bitstream segment size, type unsigned int
+	 *
+	 * Subsequent chunks are present when
+	 * CMD_BITSTREAM_SEGMENTS_MORE_FOLLOW_MASK flag is set in Bitstream HDR.
+	 */
+	struct dec_decpict_seg *dec_picseg = (struct dec_decpict_seg *)lst_first(decpic_seglist);
+	unsigned int *cmd = *dma_cmdbuf;
+	unsigned int *dma_hdr = cmd;
+	unsigned int segcount = 0;
+	unsigned int bitstream_size = 0;
+
+	/*
+	 * Two words for DMA command header (setup later as we need to find out
+	 * count of BS segments).
+	 */
+	cmd += CMD_BITSTREAM_HDR_DW_SIZE;
+	cmd_bufsize -= CMD_BITSTREAM_HDR_DW_SIZE;
+	if (cmd_bufsize < 0) {
+		pr_err("Buffer for DMA command too small.\n");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!dec_picseg) {
+		/* No segments to be send to FW: preparing fake one */
+		cmd_bufsize -= VDEC_SINLGE_DEVA_DMA_CMD_SIZE;
+		if (cmd_bufsize < 0) {
+			pr_err("Buffer for DMA command too small.\n");
+			return IMG_ERROR_INVALID_PARAMETERS;
+		}
+		segcount++;
+
+		/* zeroing bitstream size and bitstream offset */
+		*(cmd++) = 0;
+		*(cmd++) = 0;
+	}
+
+	/* Loop through all bitstream segments */
+	while (dec_picseg) {
+		if (dec_picseg->bstr_seg && (dec_picseg->bstr_seg->bstr_seg_flag
+			& VDECDD_BSSEG_SKIP) == 0) {
+			unsigned int result;
+			struct vdecdd_ddbuf_mapinfo *ddbuf_map_info;
+
+			segcount++;
+			/* Two words for each added bitstream segment */
+			cmd_bufsize -= VDEC_SINLGE_DEVA_DMA_CMD_SIZE;
+			if (cmd_bufsize < 0) {
+				pr_err("Buffer for DMA command too small.\n");
+				return IMG_ERROR_INVALID_PARAMETERS;
+			}
+			/* Insert SCP/SC if needed */
+			if (dec_picseg->bstr_seg->bstr_seg_flag &
+				VDECDD_BSSEG_INSERTSCP) {
+				unsigned int startcode_length =
+					psdecpict->start_code_bufinfo->buf_size;
+
+				if (dec_picseg->bstr_seg->bstr_seg_flag &
+					VDECDD_BSSEG_INSERT_STARTCODE) {
+					unsigned char *start_code =
+						psdecpict->start_code_bufinfo->cpu_virt;
+					start_code[startcode_length - 1] =
+						dec_picseg->bstr_seg->start_code_suffix;
+				} else {
+					startcode_length -= 1;
+				}
+
+				segcount++;
+				*(cmd++) = startcode_length;
+				bitstream_size += startcode_length;
+
+				*(cmd++) = psdecpict->start_code_bufinfo->dev_virt;
+
+				if (((segcount %
+					(CMD_BITSTREAM_SEGMENTS_MINUS1_MASK + 1)) == 0))
+					/*
+					 * we have reached max number of
+					 * bitstream segments for current
+					 * command make pui32Cmd point to next
+					 * BS command
+					 */
+					cmd += CMD_BITSTREAM_HDR_DW_SIZE;
+			}
+			/* Get access to map info context */
+			result = rman_get_resource(dec_picseg->bstr_seg->bufmap_id,
+						   VDECDD_BUFMAP_TYPE_ID,
+						   (void **)&ddbuf_map_info, NULL);
+			VDEC_ASSERT(result == IMG_SUCCESS);
+			if (result != IMG_SUCCESS)
+				return result;
+
+			*(cmd++) = (dec_picseg->bstr_seg->data_size);
+			bitstream_size += dec_picseg->bstr_seg->data_size;
+
+			*(cmd++) = ddbuf_map_info->ddbuf_info.dev_virt +
+				dec_picseg->bstr_seg->data_byte_offset;
+
+			if (((segcount %
+				(CMD_BITSTREAM_SEGMENTS_MINUS1_MASK + 1)) == 0) &&
+				(lst_next(dec_picseg)))
+				/*
+				 * we have reached max number of bitstream
+				 * segments for current command make pui32Cmd
+				 * point to next BS command
+				 */
+				cmd += CMD_BITSTREAM_HDR_DW_SIZE;
+		}
+		dec_picseg = lst_next(dec_picseg);
+	}
+
+	if (segcount > CMD_BITSTREAM_SEGMENTS_MAX_NUM) {
+		pr_err("Too many bitstream segments to transfer.\n");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	while (segcount > (CMD_BITSTREAM_SEGMENTS_MINUS1_MASK + 1)) {
+		*dma_hdr++ = CMD_BITSTREAM_SEGMENTS |
+			CMD_BITSTREAM_SEGMENTS_MORE_FOLLOW_MASK |
+			CMD_BITSTREAM_SEGMENTS_MINUS1_MASK;
+		*dma_hdr++ = bitstream_size;
+		/*
+		 * make pui32DmaHdr point to next chunk by skipping bitstream
+		 * Segments
+		 */
+		dma_hdr += (2 * (CMD_BITSTREAM_SEGMENTS_MINUS1_MASK + 1));
+		segcount -= (CMD_BITSTREAM_SEGMENTS_MINUS1_MASK + 1);
+	}
+	*dma_hdr = eop ? CMD_BITSTREAM_EOP_MASK : 0;
+	*dma_hdr++ |= CMD_BITSTREAM_SEGMENTS | (segcount - 1);
+	*dma_hdr = bitstream_size;
+
+	/*
+	 * Let caller know where we finished. Pointer to location one word after
+	 * end of our command buffer
+	 */
+	*dma_cmdbuf = cmd;
+	return IMG_SUCCESS;
+}
+
+/*
+ * Creates DEVA control allocation buffer header.
+ */
+static void translation_pvdec_ctrl_setuphdr
+	(struct ctrl_alloc_header *ctrlalloc_hdr,
+	unsigned int *pic_cmds)
+{
+	ctrlalloc_hdr->cmd_additional_params = CMD_CTRL_ALLOC_HEADER;
+	ctrlalloc_hdr->ext_opmode = pic_cmds[VDECFW_CMD_EXT_OP_MODE];
+	ctrlalloc_hdr->chroma_strides =
+		pic_cmds[VDECFW_CMD_CHROMA_ROW_STRIDE];
+	ctrlalloc_hdr->alt_output_addr[0] =
+		pic_cmds[VDECFW_CMD_LUMA_ALTERNATIVE_PICTURE_BASE_ADDRESS];
+	ctrlalloc_hdr->alt_output_addr[1] =
+		pic_cmds[VDECFW_CMD_CHROMA_ALTERNATIVE_PICTURE_BASE_ADDRESS];
+	ctrlalloc_hdr->alt_output_flags =
+		pic_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION];
+}
+
+/*
+ * Creates DEVA VLC DMA command and saves is to control allocation buffer.
+ */
+static int translation_pvdecsetup_vlcdma
+	(struct vidio_ddbufinfo *vlctables_bufinfo,
+	unsigned int **dmacmd_buf, unsigned int cmdbuf_size)
+{
+	unsigned int cmd_dma;
+	unsigned int *cmd = *dmacmd_buf;
+
+	/* Check if VLC tables fit in one DMA transfer */
+	if (vlctables_bufinfo->buf_size > CMD_DMA_DMA_SIZE_MASK) {
+		pr_err("VLC tables won't fit into one DMA transfer!\n");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Check if we have enough space in control allocation buffer. */
+	if (cmdbuf_size < VDEC_SINLGE_DEVA_DMA_CMD_SIZE) {
+		pr_err("Buffer for DMA command too small.\n");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Construct DMA command */
+	cmd_dma = CMD_DMA | CMD_DMA_TYPE_VLC_TABLE |
+		vlctables_bufinfo->buf_size;
+
+	/* Add command to control allocation */
+	*cmd++ = cmd_dma;
+	*cmd++ = vlctables_bufinfo->dev_virt;
+
+	/*
+	 * Let caller know where we finished. Pointer to location one word after
+	 * end of our command buffer
+	 */
+	*dmacmd_buf = cmd;
+	return IMG_SUCCESS;
+}
+
+/*
+ * Creates DEVA commands for configuring VLC tables and saves them into
+ * control allocation buffer.
+ */
+static int translation_pvdecsetup_vlctables
+	(unsigned short vlc_index_data[][3], unsigned int num_tables,
+	unsigned int **ctrl_allocbuf, unsigned int ctrl_allocsize,
+	unsigned int msvdx_vecoffset)
+{
+	unsigned int i;
+	unsigned int word_count;
+	unsigned int reg_val;
+	unsigned int *ctrl_allochdr;
+
+	unsigned int *ctrl_alloc = *ctrl_allocbuf;
+
+	/* Calculate the number of words needed for VLC control allocations. */
+	/*
+	 * 3 words for control allocation headers (we are writing 3 chunks:
+	 * addresses, widths, opcodes)
+	 */
+	unsigned int req_elems = 3 +
+		(ALIGN(num_tables, PVDECIO_VLC_IDX_WIDTH_PARTS) /
+		PVDECIO_VLC_IDX_WIDTH_PARTS) +
+		(ALIGN(num_tables, PVDECIO_VLC_IDX_ADDR_PARTS) /
+		PVDECIO_VLC_IDX_ADDR_PARTS) +
+		(ALIGN(num_tables, PVDECIO_VLC_IDX_OPCODE_PARTS) /
+		PVDECIO_VLC_IDX_OPCODE_PARTS);
+
+	/*
+	 * Addresses chunk has to be split in two, if number of tables exceeds
+	 * VEC_VLC_TABLE_ADDR_DISCONT (see layout of VEC_VLC_TABLE_ADDR*
+	 * registers in TRM)
+	 */
+	if (num_tables > VEC_VLC_TABLE_ADDR_DISCONT)
+		/* We need additional control allocation header */
+		req_elems += 1;
+
+	if (ctrl_allocsize < req_elems) {
+		pr_err("Buffer for VLC IDX commands too small.\n");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/*
+	 * Write VLC IDX addresses. Chunks for VEC_VLC_TABLE_ADDR[0-15] and
+	 * VEC_VLC_TABLE_ADDR[16-18] registers.
+	 */
+	ctrl_allochdr = ctrl_alloc++;
+	*ctrl_allochdr = CMD_REGISTER_BLOCK | CMD_REGISTER_BLOCK_FLAG_VLC_DATA |
+		(MSVDX_VEC_CR_VEC_VLC_TABLE_ADDR0_OFFSET + msvdx_vecoffset);
+	/* Reset the word count. */
+	word_count = 0;
+
+	/* Process VLC index table. */
+	i = 0;
+	reg_val = 0;
+	while (i < num_tables) {
+		VDEC_ASSERT((vlc_index_data[i][PVDECIO_VLC_IDX_ADDR_ID] &
+			~PVDECIO_VLC_IDX_ADDR_MASK) == 0);
+		/* Pack the addresses into a word. */
+		reg_val |= ((vlc_index_data[i][PVDECIO_VLC_IDX_ADDR_ID] &
+			PVDECIO_VLC_IDX_ADDR_MASK) <<
+			((i % PVDECIO_VLC_IDX_ADDR_PARTS) *
+			PVDECIO_VLC_IDX_ADDR_SHIFT));
+
+		/* If we reached the end of VEC_VLC_TABLE_ADDR[0-15] area... */
+		if (i == VEC_VLC_TABLE_ADDR_DISCONT) {
+			/*
+			 * Finalize command header for VEC_VLC_TABLE_ADDR[0-15]
+			 * register chunk.
+			 */
+			*ctrl_allochdr |= word_count << 16;
+			/*
+			 * Reserve and preset command header for
+			 * VEC_VLC_TABLE_ADDR[16-18] register chunk.
+			 */
+			ctrl_allochdr = ctrl_alloc++;
+			*ctrl_allochdr = CMD_REGISTER_BLOCK |
+				CMD_REGISTER_BLOCK_FLAG_VLC_DATA |
+				(MSVDX_VEC_CR_VEC_VLC_TABLE_ADDR16_OFFSET +
+				msvdx_vecoffset);
+			/* Reset the word count. */
+			word_count = 0;
+		}
+
+		/*
+		 * If all the addresses are packed in this word or that's the
+		 * last iteration
+		 */
+		if (((i % PVDECIO_VLC_IDX_ADDR_PARTS) ==
+			(PVDECIO_VLC_IDX_ADDR_PARTS - 1)) ||
+			(i == (num_tables - 1))) {
+			/*
+			 * Add VLC table address to this chunk and increase
+			 * words count.
+			 */
+			*ctrl_alloc++ = reg_val;
+			word_count++;
+			/* Reset address value. */
+			reg_val = 0;
+		}
+
+		i++;
+	}
+
+	/*
+	 * Finalize the current command header for VEC_VLC_TABLE_ADDR register
+	 * chunk.
+	 */
+	*ctrl_allochdr |= word_count << 16;
+
+	/*
+	 * Start new commands chunk for VEC_VLC_TABLE_INITIAL_WIDTH[0-3]
+	 * registers.
+	 */
+
+	/*
+	 * Reserve and preset command header for
+	 * VEC_VLC_TABLE_INITIAL_WIDTH[0-3] register chunk.
+	 */
+	ctrl_allochdr = ctrl_alloc++;
+	*ctrl_allochdr = CMD_REGISTER_BLOCK | CMD_REGISTER_BLOCK_FLAG_VLC_DATA |
+		(MSVDX_VEC_CR_VEC_VLC_TABLE_INITIAL_WIDTH0_OFFSET +
+		msvdx_vecoffset);
+	/* Reset the word count. */
+	word_count = 0;
+
+	/* Process VLC index table. */
+	i = 0;
+	reg_val = 0;
+
+	while (i < num_tables) {
+		VDEC_ASSERT((vlc_index_data[i][PVDECIO_VLC_IDX_WIDTH_ID] &
+			~PVDECIO_VLC_IDX_WIDTH_MASK) == 0);
+		/* Pack the widths into a word. */
+		reg_val |= ((vlc_index_data[i][PVDECIO_VLC_IDX_WIDTH_ID] &
+			PVDECIO_VLC_IDX_WIDTH_MASK) <<
+			(i % PVDECIO_VLC_IDX_WIDTH_PARTS) *
+			PVDECIO_VLC_IDX_WIDTH_SHIFT);
+
+		/*
+		 * If all the widths are packed in this word or that's the last
+		 * iteration.
+		 */
+		if (((i % PVDECIO_VLC_IDX_WIDTH_PARTS) ==
+			(PVDECIO_VLC_IDX_WIDTH_PARTS - 1)) ||
+			(i == (num_tables - 1))) {
+			/*
+			 * Add VLC table width to this chunk and increase words
+			 * count.
+			 */
+			*ctrl_alloc++ = reg_val;
+			word_count++;
+			/* Reset width value. */
+			reg_val = 0;
+		}
+		i++;
+	}
+
+	/*
+	 * Finalize command header for VEC_VLC_TABLE_INITIAL_WIDTH[0-3] register
+	 * chunk.
+	 */
+	*ctrl_allochdr |= word_count << 16;
+
+	/*
+	 * Start new commands chunk for VEC_VLC_TABLE_INITIAL_OPCODE[0-2]
+	 * registers.
+	 * Reserve and preset command header for
+	 * VEC_VLC_TABLE_INITIAL_OPCODE[0-2] register chunk
+	 */
+	ctrl_allochdr = ctrl_alloc++;
+	*ctrl_allochdr = CMD_REGISTER_BLOCK | CMD_REGISTER_BLOCK_FLAG_VLC_DATA |
+		(MSVDX_VEC_CR_VEC_VLC_TABLE_INITIAL_OPCODE0_OFFSET +
+		msvdx_vecoffset);
+	/* Reset the word count. */
+	word_count = 0;
+
+	/* Process VLC index table. */
+	i = 0;
+	reg_val = 0;
+
+	while (i < num_tables) {
+		VDEC_ASSERT((vlc_index_data[i][PVDECIO_VLC_IDX_OPCODE_ID] &
+			~PVDECIO_VLC_IDX_OPCODE_MASK) == 0);
+		/* Pack the opcodes into a word. */
+		reg_val |= ((vlc_index_data[i][PVDECIO_VLC_IDX_OPCODE_ID] &
+			PVDECIO_VLC_IDX_OPCODE_MASK) <<
+			(i % PVDECIO_VLC_IDX_OPCODE_PARTS) *
+			PVDECIO_VLC_IDX_OPCODE_SHIFT);
+
+		/*
+		 * If all the opcodes are packed in this word or that's the last
+		 * iteration.
+		 */
+		if (((i % PVDECIO_VLC_IDX_OPCODE_PARTS) ==
+			(PVDECIO_VLC_IDX_OPCODE_PARTS - 1)) ||
+			(i == (num_tables - 1))) {
+			/*
+			 * Add VLC table opcodes to this chunk and increase
+			 * words count.
+			 */
+			*ctrl_alloc++ = reg_val;
+			word_count++;
+			/* Reset width value. */
+			reg_val = 0;
+		}
+		i++;
+	}
+
+	/*
+	 * Finalize command header for VEC_VLC_TABLE_INITIAL_OPCODE[0-2]
+	 * register chunk.
+	 */
+	*ctrl_allochdr |= word_count << 16;
+
+	/* Update caller with current location of control allocation pointer */
+	*ctrl_allocbuf = ctrl_alloc;
+	return IMG_SUCCESS;
+}
+
+/*
+ * fills in a rendec command chunk in the command buffer.
+ */
+static void fill_rendec_chunk(int num, ...)
+{
+	va_list valist;
+	unsigned int i, j = 0;
+	unsigned int chunk_word_count = 0;
+	unsigned int used_word_count = 0;
+	int aux_array_size = 0;
+	unsigned int *pic_cmds;
+	unsigned int **ctrl_allocbuf;
+	unsigned int ctrl_allocsize;
+	unsigned int vdmc_cmd_offset;
+	unsigned int offset;
+	unsigned int *buf;
+	/* 5 is the fixed arguments passed to fill_rendec_chunk function */
+	enum vdecfw_picture_cmds *aux_array = kmalloc((sizeof(unsigned int) *
+			(num - 5)), GFP_KERNEL);
+	if (!aux_array)
+		return;
+
+	/* initialize valist for num number of arguments */
+	va_start(valist, num);
+
+	pic_cmds = va_arg(valist, unsigned int *);
+	ctrl_allocbuf = va_arg(valist, unsigned int **);
+	ctrl_allocsize = va_arg(valist, unsigned int);
+	vdmc_cmd_offset = va_arg(valist, unsigned int);
+	offset = va_arg(valist, unsigned int);
+	buf = *ctrl_allocbuf;
+
+	aux_array_size = (sizeof(unsigned int) * (num - 5));
+	/*
+	 * access all the arguments assigned to valist, we have already
+	 * read till 5
+	 */
+	for (i = 6, j = 0; i <= num; i++, j++)
+		aux_array[j] = (enum vdecfw_picture_cmds)va_arg(valist, int);
+
+	/* clean memory reserved for valist */
+	va_end(valist);
+	chunk_word_count = aux_array_size /
+		sizeof(enum vdecfw_picture_cmds);
+	if ((chunk_word_count + 1) > (ctrl_allocsize - used_word_count)) {
+		kfree(aux_array);
+		return;
+	}
+	if ((chunk_word_count & ~(CMD_RENDEC_WORD_COUNT_MASK >>
+		CMD_RENDEC_WORD_COUNT_SHIFT)) != 0) {
+		kfree(aux_array);
+		return;
+	}
+	used_word_count += chunk_word_count + 1;
+	*buf++ = CMD_RENDEC_BLOCK | (chunk_word_count << 16) |
+		(vdmc_cmd_offset + offset);
+
+	for (i = 0; i < chunk_word_count; i++)
+		*buf++ = pic_cmds[aux_array[i]];
+
+	*ctrl_allocbuf = buf;
+	/* free the memory */
+	kfree(aux_array);
+}
+
+/*
+ * Creates DEVA commands for configuring rendec and writes them into control
+ * allocation buffer.
+ */
+static void translation_pvdec_setup_commands(unsigned int *pic_cmds,
+					     unsigned int **ctrl_allocbuf,
+					     unsigned int ctrl_allocsize,
+					     unsigned int vdmc_cmd_offset)
+{
+	unsigned int codec_mode;
+
+	codec_mode = REGIO_READ_FIELD(pic_cmds[VDECFW_CMD_OPERATING_MODE],
+				      MSVDX_CMDS, OPERATING_MODE, CODEC_MODE);
+
+	if (codec_mode != CODEC_MODE_H264)
+		/* chunk with cache settings at 0x01C */
+		/*
+		 * here first argument 6 says there are 6 number of arguments
+		 * being passed to fill_rendec_chunk function.
+		 */
+		fill_rendec_chunk(6, pic_cmds, ctrl_allocbuf, ctrl_allocsize,
+				  vdmc_cmd_offset,
+				  MSVDX_CMDS_MC_CACHE_CONFIGURATION_OFFSET,
+				  VDECFW_CMD_MC_CACHE_CONFIGURATION);
+
+	/* chunk with extended row stride at 0x03C */
+	/*
+	 * here first argument 6 says there are 6 number of arguments
+	 * being passed to fill_rendec_chunk function.
+	 */
+	fill_rendec_chunk(6, pic_cmds, ctrl_allocbuf, ctrl_allocsize,
+			  vdmc_cmd_offset,
+			  MSVDX_CMDS_EXTENDED_ROW_STRIDE_OFFSET,
+			  VDECFW_CMD_EXTENDED_ROW_STRIDE);
+
+	/* chunk with alternative output control at 0x1B4 */
+	/*
+	 * here first argument 6 says there are 6 number of arguments
+	 * being passed to fill_rendec_chunk function.
+	 */
+	fill_rendec_chunk(6, pic_cmds, ctrl_allocbuf, ctrl_allocsize,
+			  vdmc_cmd_offset,
+			  MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_OFFSET,
+			  VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL);
+
+	/* scaling chunks */
+	if (pic_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE]) {
+		if (codec_mode != CODEC_MODE_REAL8 && codec_mode != CODEC_MODE_REAL9) {
+			/*
+			 * chunk with scale display size, scale H/V control at
+			 * 0x0050
+			 */
+			/*
+			 * here first argument 8 says there are 8 number of
+			 * arguments being passed to fill_rendec_chunk function.
+			 */
+			fill_rendec_chunk(8, pic_cmds, ctrl_allocbuf,
+					  ctrl_allocsize, vdmc_cmd_offset,
+					  MSVDX_CMDS_SCALED_DISPLAY_SIZE_OFFSET,
+					  VDECFW_CMD_SCALED_DISPLAY_SIZE,
+					  VDECFW_CMD_HORIZONTAL_SCALE_CONTROL,
+					  VDECFW_CMD_VERTICAL_SCALE_CONTROL);
+
+			/* chunk with luma/chorma H/V coeffs at 0x0060 */
+			/*
+			 * here first argument 21 says there are 21 number of
+			 * arguments being passed to fill_rendec_chunk function.
+			 */
+			fill_rendec_chunk(21, pic_cmds, ctrl_allocbuf,
+					  ctrl_allocsize, vdmc_cmd_offset,
+					  MSVDX_CMDS_HORIZONTAL_LUMA_COEFFICIENTS_OFFSET,
+					  VDECFW_CMD_HORIZONTAL_LUMA_COEFFICIENTS_0,
+					  VDECFW_CMD_HORIZONTAL_LUMA_COEFFICIENTS_1,
+					  VDECFW_CMD_HORIZONTAL_LUMA_COEFFICIENTS_2,
+					  VDECFW_CMD_HORIZONTAL_LUMA_COEFFICIENTS_3,
+					  VDECFW_CMD_VERTICAL_LUMA_COEFFICIENTS_0,
+					  VDECFW_CMD_VERTICAL_LUMA_COEFFICIENTS_1,
+					  VDECFW_CMD_VERTICAL_LUMA_COEFFICIENTS_2,
+					  VDECFW_CMD_VERTICAL_LUMA_COEFFICIENTS_3,
+					  VDECFW_CMD_HORIZONTAL_CHROMA_COEFFICIENTS_0,
+					  VDECFW_CMD_HORIZONTAL_CHROMA_COEFFICIENTS_1,
+					  VDECFW_CMD_HORIZONTAL_CHROMA_COEFFICIENTS_2,
+					  VDECFW_CMD_HORIZONTAL_CHROMA_COEFFICIENTS_3,
+					  VDECFW_CMD_VERTICAL_CHROMA_COEFFICIENTS_0,
+					  VDECFW_CMD_VERTICAL_CHROMA_COEFFICIENTS_1,
+					  VDECFW_CMD_VERTICAL_CHROMA_COEFFICIENTS_2,
+					  VDECFW_CMD_VERTICAL_CHROMA_COEFFICIENTS_3);
+
+			/*
+			 * chunk with scale output size, scale H/V chroma at
+			 * 0x01B8
+			 */
+			/*
+			 * here first argument 8 says there are 8 number of
+			 * arguments being passed to fill_rendec_chunk function.
+			 */
+			fill_rendec_chunk(8, pic_cmds, ctrl_allocbuf,
+					  ctrl_allocsize, vdmc_cmd_offset,
+					  MSVDX_CMDS_SCALE_OUTPUT_SIZE_OFFSET,
+					  VDECFW_CMD_SCALE_OUTPUT_SIZE,
+					  VDECFW_CMD_SCALE_HORIZONTAL_CHROMA,
+					  VDECFW_CMD_SCALE_VERTICAL_CHROMA);
+		}
+	}
+}
+
+#ifdef HAS_HEVC
+/*
+ * @Function		translation_pvdec_setup_pvdec_commands
+ */
+static int translation_pvdec_setup_pvdec_commands(struct vdecdd_picture *picture,
+						  struct dec_decpict *dec_pict,
+						  struct vdecdd_str_unit *str_unit,
+						  struct decoder_regsoffsets *regs_offsets,
+						  unsigned int **ctrl_allocbuf,
+						  unsigned int ctrl_alloc_size,
+						  unsigned int *mem_to_reg_host_part,
+						  unsigned int *pict_cmds)
+{
+	const unsigned int genc_buf_cnt = 4;
+	/* We have two chunks: for GENC buffers addresses and sizes*/
+	const unsigned int genc_conf_items = 2;
+	const unsigned int pipe = 0xf << 16; /* Instruct H/W to write to current pipe */
+	/* We need to configure address and size of each GENC buffer */
+	const unsigned int genc_words_cnt = genc_buf_cnt * genc_conf_items;
+	struct vdecdd_ddbuf_mapinfo **genc_buffers =
+		picture->pict_res_int->seq_resint->genc_buffers;
+	unsigned int memto_reg_used;  /* in bytes */
+	unsigned int i;
+	unsigned int *ctrl_alloc = *ctrl_allocbuf;
+	unsigned int *mem_to_reg = (unsigned int *)dec_pict->pvdec_info->ddbuf_info->cpu_virt;
+	unsigned int reg = 0;
+
+	if (ctrl_alloc_size < genc_words_cnt + genc_conf_items) {
+		pr_err("Buffer for GENC config too small.");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Insert command header for GENC buffers sizes */
+	*ctrl_alloc++ = CMD_REGISTER_BLOCK | (genc_buf_cnt << 16) |
+		(PVDEC_ENTROPY_CR_GENC_BUFFER_SIZE_OFFSET + regs_offsets->entropy_offset);
+	for (i = 0; i < genc_buf_cnt; i++)
+		*ctrl_alloc++ = genc_buffers[i]->ddbuf_info.buf_size;
+
+	/* Insert command header for GENC buffers addresses */
+	*ctrl_alloc++ = CMD_REGISTER_BLOCK | (genc_buf_cnt << 16) |
+		(PVDEC_ENTROPY_CR_GENC_BUFFER_BASE_ADDRESS_OFFSET + regs_offsets->entropy_offset);
+	for (i = 0; i < genc_buf_cnt; i++)
+		*ctrl_alloc++ = genc_buffers[i]->ddbuf_info.dev_virt;
+
+	/* Insert GENC fragment buffer address */
+	*ctrl_alloc++ = CMD_REGISTER_BLOCK | (1 << 16) |
+		(PVDEC_ENTROPY_CR_GENC_FRAGMENT_BASE_ADDRESS_OFFSET + regs_offsets->entropy_offset);
+	*ctrl_alloc++ = picture->pict_res_int->genc_fragment_buf->ddbuf_info.dev_virt;
+
+	/* Return current location in control allocation buffer to caller */
+	*ctrl_allocbuf = ctrl_alloc;
+
+	reg = 0;
+	REGIO_WRITE_FIELD_LITE
+		(reg,
+		 MSVDX_CMDS, PVDEC_DISPLAY_PICTURE_SIZE, PVDEC_DISPLAY_PICTURE_WIDTH_MIN1,
+		 str_unit->pict_hdr_info->coded_frame_size.width - 1, unsigned int);
+	REGIO_WRITE_FIELD_LITE
+		(reg,
+		 MSVDX_CMDS, PVDEC_DISPLAY_PICTURE_SIZE, PVDEC_DISPLAY_PICTURE_HEIGHT_MIN1,
+		 str_unit->pict_hdr_info->coded_frame_size.height - 1, unsigned int);
+
+	/*
+	 * Pvdec operating mode needs to be submitted before any other commands.
+	 * This will be set in FW. Make sure it's the first command in Mem2Reg buffer.
+	 */
+	VDEC_ASSERT((unsigned int *)dec_pict->pvdec_info->ddbuf_info->cpu_virt == mem_to_reg);
+
+	*mem_to_reg++ = pipe |
+		(MSVDX_CMDS_PVDEC_OPERATING_MODE_OFFSET + regs_offsets->vdmc_cmd_offset);
+	*mem_to_reg++ = 0x0; /* has to be updated in the F/W */
+
+	*mem_to_reg++ = pipe |
+		(MSVDX_CMDS_MC_CACHE_CONFIGURATION_OFFSET + regs_offsets->vdmc_cmd_offset);
+	*mem_to_reg++ = 0x0; /* has to be updated in the F/W */
+
+	*mem_to_reg++ = pipe |
+		(MSVDX_CMDS_PVDEC_DISPLAY_PICTURE_SIZE_OFFSET + regs_offsets->vdmc_cmd_offset);
+	*mem_to_reg++ = reg;
+
+	*mem_to_reg++ = pipe |
+		(MSVDX_CMDS_PVDEC_CODED_PICTURE_SIZE_OFFSET + regs_offsets->vdmc_cmd_offset);
+	*mem_to_reg++ = reg;
+
+	/* scaling configuration */
+	if (pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE]) {
+		*mem_to_reg++ = pipe |
+			(MSVDX_CMDS_PVDEC_SCALED_DISPLAY_SIZE_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE];
+
+		*mem_to_reg++ = pipe |
+			(MSVDX_CMDS_HORIZONTAL_SCALE_CONTROL_OFFSET +
+			 regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_HORIZONTAL_SCALE_CONTROL];
+		*mem_to_reg++ = pipe |
+			(MSVDX_CMDS_VERTICAL_SCALE_CONTROL_OFFSET + regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_VERTICAL_SCALE_CONTROL];
+
+		*mem_to_reg++ = pipe |
+			(MSVDX_CMDS_SCALE_OUTPUT_SIZE_OFFSET + regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_SCALE_OUTPUT_SIZE];
+
+		*mem_to_reg++ = pipe |
+			(MSVDX_CMDS_SCALE_HORIZONTAL_CHROMA_OFFSET + regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_SCALE_HORIZONTAL_CHROMA];
+		*mem_to_reg++ = pipe |
+			(MSVDX_CMDS_SCALE_VERTICAL_CHROMA_OFFSET + regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_SCALE_VERTICAL_CHROMA];
+
+		*mem_to_reg++ = pipe |
+			(MSVDX_CMDS_HORIZONTAL_LUMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_HORIZONTAL_LUMA_COEFFICIENTS_0];
+		*mem_to_reg++ = pipe |
+			(4 + MSVDX_CMDS_HORIZONTAL_LUMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_HORIZONTAL_LUMA_COEFFICIENTS_1];
+		*mem_to_reg++ = pipe |
+			(8 + MSVDX_CMDS_HORIZONTAL_LUMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_HORIZONTAL_LUMA_COEFFICIENTS_2];
+		*mem_to_reg++ = pipe |
+			(12 + MSVDX_CMDS_HORIZONTAL_LUMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_HORIZONTAL_LUMA_COEFFICIENTS_3];
+
+		*mem_to_reg++ = pipe |
+			(MSVDX_CMDS_VERTICAL_LUMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_VERTICAL_LUMA_COEFFICIENTS_0];
+		*mem_to_reg++ = pipe |
+			(4 + MSVDX_CMDS_VERTICAL_LUMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_VERTICAL_LUMA_COEFFICIENTS_1];
+		*mem_to_reg++ = pipe |
+			(8 + MSVDX_CMDS_VERTICAL_LUMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_VERTICAL_LUMA_COEFFICIENTS_2];
+		*mem_to_reg++ = pipe |
+			(12 + MSVDX_CMDS_VERTICAL_LUMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_VERTICAL_LUMA_COEFFICIENTS_3];
+
+		*mem_to_reg++ = pipe |
+			(MSVDX_CMDS_HORIZONTAL_CHROMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_HORIZONTAL_CHROMA_COEFFICIENTS_0];
+		*mem_to_reg++ = pipe |
+			(4 + MSVDX_CMDS_HORIZONTAL_CHROMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_HORIZONTAL_CHROMA_COEFFICIENTS_1];
+		*mem_to_reg++ = pipe |
+			(8 + MSVDX_CMDS_HORIZONTAL_CHROMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_HORIZONTAL_CHROMA_COEFFICIENTS_2];
+		*mem_to_reg++ = pipe |
+			(12 + MSVDX_CMDS_HORIZONTAL_CHROMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_HORIZONTAL_CHROMA_COEFFICIENTS_3];
+
+		*mem_to_reg++ = pipe |
+			(MSVDX_CMDS_VERTICAL_CHROMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_VERTICAL_CHROMA_COEFFICIENTS_0];
+		*mem_to_reg++ = pipe |
+			(4 + MSVDX_CMDS_VERTICAL_CHROMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_VERTICAL_CHROMA_COEFFICIENTS_1];
+		*mem_to_reg++ = pipe |
+			(8 + MSVDX_CMDS_VERTICAL_CHROMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_VERTICAL_CHROMA_COEFFICIENTS_2];
+		*mem_to_reg++ = pipe |
+			(12 + MSVDX_CMDS_VERTICAL_CHROMA_COEFFICIENTS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_VERTICAL_CHROMA_COEFFICIENTS_3];
+	}
+
+	*mem_to_reg++ = pipe |
+		(MSVDX_CMDS_EXTENDED_ROW_STRIDE_OFFSET + regs_offsets->vdmc_cmd_offset);
+	*mem_to_reg++ = pict_cmds[VDECFW_CMD_EXTENDED_ROW_STRIDE];
+
+	*mem_to_reg++ = pipe |
+		(MSVDX_CMDS_ALTERNATIVE_OUTPUT_CONTROL_OFFSET + regs_offsets->vdmc_cmd_offset);
+	*mem_to_reg++ = pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL];
+
+	*mem_to_reg++ = pipe |
+		(MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION_OFFSET +
+		regs_offsets->vdmc_cmd_offset);
+	*mem_to_reg++ = pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION];
+
+	*mem_to_reg++ = pipe |
+		(MSVDX_CMDS_CHROMA_ROW_STRIDE_OFFSET + regs_offsets->vdmc_cmd_offset);
+	*mem_to_reg++ = pict_cmds[VDECFW_CMD_CHROMA_ROW_STRIDE];
+
+	/* Setup MEM_TO_REG buffer */
+	for (i = 0; i < genc_buf_cnt; i++) {
+		*mem_to_reg++ = pipe | (PVDEC_VEC_BE_CR_GENC_BUFFER_SIZE_OFFSET +
+			regs_offsets->vec_be_regs_offset + i * sizeof(unsigned int));
+		*mem_to_reg++ = genc_buffers[i]->ddbuf_info.buf_size;
+		*mem_to_reg++ = pipe | (PVDEC_VEC_BE_CR_GENC_BUFFER_BASE_ADDRESS_OFFSET +
+			regs_offsets->vec_be_regs_offset + i * sizeof(unsigned int));
+		*mem_to_reg++ = genc_buffers[i]->ddbuf_info.dev_virt;
+	}
+
+	*mem_to_reg++ = pipe |
+		(PVDEC_VEC_BE_CR_GENC_FRAGMENT_BASE_ADDRESS_OFFSET +
+		regs_offsets->vec_be_regs_offset);
+	*mem_to_reg++ = picture->pict_res_int->genc_fragment_buf->ddbuf_info.dev_virt;
+
+	*mem_to_reg++ = pipe |
+		(PVDEC_VEC_BE_CR_ABOVE_PARAM_BASE_ADDRESS_OFFSET +
+		regs_offsets->vec_be_regs_offset);
+
+	*mem_to_reg++ = dec_pict->pvdec_info->ddbuf_info->dev_virt +
+		MEM_TO_REG_BUF_SIZE + SLICE_PARAMS_BUF_SIZE;
+
+	*mem_to_reg++ = pipe |
+		(MSVDX_CMDS_LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES_OFFSET +
+		regs_offsets->vdmc_cmd_offset);
+	*mem_to_reg++ = pict_cmds[VDECFW_CMD_LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESS];
+
+	*mem_to_reg++ = pipe |
+		(MSVDX_CMDS_CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES_OFFSET +
+		regs_offsets->vdmc_cmd_offset);
+	*mem_to_reg++ = pict_cmds[VDECFW_CMD_CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESS];
+
+	/* alternative picture configuration */
+	if (dec_pict->alt_pict) {
+		*mem_to_reg++ = pipe |
+			(MSVDX_CMDS_VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_LUMA_ALTERNATIVE_PICTURE_BASE_ADDRESS];
+
+		*mem_to_reg++ = pipe |
+			(MSVDX_CMDS_VC1_CHROMA_RANGE_MAPPING_BASE_ADDRESS_OFFSET +
+			regs_offsets->vdmc_cmd_offset);
+		*mem_to_reg++ = pict_cmds[VDECFW_CMD_CHROMA_ALTERNATIVE_PICTURE_BASE_ADDRESS];
+	}
+
+	*mem_to_reg++ = pipe |
+		(MSVDX_CMDS_AUX_LINE_BUFFER_BASE_ADDRESS_OFFSET + regs_offsets->vdmc_cmd_offset);
+	*mem_to_reg++ = pict_cmds[VDECFW_CMD_AUX_LINE_BUFFER_BASE_ADDRESS];
+
+	*mem_to_reg++ = pipe |
+		(MSVDX_CMDS_INTRA_BUFFER_BASE_ADDRESS_OFFSET + regs_offsets->vdmc_cmd_offset);
+	*mem_to_reg++ = pict_cmds[VDECFW_CMD_INTRA_BUFFER_BASE_ADDRESS];
+
+	/* Make sure we fit in buffer */
+	memto_reg_used = (unsigned long)mem_to_reg -
+		(unsigned long)dec_pict->pvdec_info->ddbuf_info->cpu_virt;
+
+	VDEC_ASSERT(memto_reg_used < MEM_TO_REG_BUF_SIZE);
+
+	*mem_to_reg_host_part = memto_reg_used / sizeof(unsigned int);
+
+	return IMG_SUCCESS;
+}
+#endif
+
+/*
+ * Creates DEVA commands for configuring rendec and writes them into control
+ * allocation buffer.
+ */
+static int translation_pvdecsetup_vdecext
+	(struct vdec_ext_cmd *vdec_ext,
+	struct dec_decpict *dec_pict, unsigned int *pic_cmds,
+	struct vdecdd_str_unit *str_unit, enum vdec_vid_std vid_std,
+	enum vdecfw_parsermode parser_mode)
+{
+	int result;
+	unsigned int trans_id = dec_pict->transaction_id;
+
+	VDEC_ASSERT(dec_pict->recon_pict);
+
+	vdec_ext->cmd = CMD_VDEC_EXT;
+	vdec_ext->trans_id = trans_id;
+
+	result = translation_get_seqhdr(str_unit, dec_pict, &vdec_ext->seq_addr);
+	VDEC_ASSERT(result == IMG_SUCCESS);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	result = translation_get_ppshdr(str_unit, dec_pict, &vdec_ext->pps_addr);
+	VDEC_ASSERT(result == IMG_SUCCESS);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	result = translation_getsecond_ppshdr(str_unit, &vdec_ext->pps_2addr);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	vdec_ext->hdr_addr = GET_HOST_ADDR(dec_pict->hdr_info->ddbuf_info);
+
+	vdec_ext->ctx_load_addr = translation_getctx_loadaddr(dec_pict);
+	vdec_ext->ctx_save_addr = GET_HOST_ADDR(&dec_pict->cur_pict_dec_res->fw_ctx_buf);
+	vdec_ext->buf_ctrl_addr = GET_HOST_ADDR(&dec_pict->pict_ref_res->fw_ctrlbuf);
+	if (dec_pict->prev_pict_dec_res) {
+		/*
+		 * Copy the previous firmware context to the current one in case
+		 * picture management fails in firmware.
+		 */
+		memcpy(dec_pict->cur_pict_dec_res->fw_ctx_buf.cpu_virt,
+		       dec_pict->prev_pict_dec_res->fw_ctx_buf.cpu_virt,
+		       dec_pict->prev_pict_dec_res->fw_ctx_buf.buf_size);
+	}
+
+	vdec_ext->last_luma_recon =
+		pic_cmds[VDECFW_CMD_LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESS];
+	vdec_ext->last_chroma_recon =
+		pic_cmds[VDECFW_CMD_CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESS];
+
+	vdec_ext->luma_err_base =
+		pic_cmds[VDECFW_CMD_LUMA_ERROR_PICTURE_BASE_ADDRESS];
+	vdec_ext->chroma_err_base =
+		pic_cmds[VDECFW_CMD_CHROMA_ERROR_PICTURE_BASE_ADDRESS];
+
+	vdec_ext->scaled_display_size =
+		pic_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE];
+	vdec_ext->horz_scale_control =
+		pic_cmds[VDECFW_CMD_HORIZONTAL_SCALE_CONTROL];
+	vdec_ext->vert_scale_control =
+		pic_cmds[VDECFW_CMD_VERTICAL_SCALE_CONTROL];
+	vdec_ext->scale_output_size = pic_cmds[VDECFW_CMD_SCALE_OUTPUT_SIZE];
+
+	vdec_ext->intra_buf_base_addr =
+		pic_cmds[VDECFW_CMD_INTRA_BUFFER_BASE_ADDRESS];
+	vdec_ext->intra_buf_size_per_pipe =
+		pic_cmds[VDECFW_CMD_INTRA_BUFFER_SIZE_PER_PIPE];
+	vdec_ext->intra_buf_size_per_plane =
+		pic_cmds[VDECFW_CMD_INTRA_BUFFER_PLANE_SIZE];
+	vdec_ext->aux_line_buffer_base_addr =
+		pic_cmds[VDECFW_CMD_AUX_LINE_BUFFER_BASE_ADDRESS];
+	vdec_ext->aux_line_buf_size_per_pipe =
+		pic_cmds[VDECFW_CMD_AUX_LINE_BUFFER_SIZE_PER_PIPE];
+	vdec_ext->alt_output_pict_rotation =
+		pic_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION];
+	vdec_ext->chroma2reconstructed_addr =
+		pic_cmds[VDECFW_CMD_CHROMA2_RECONSTRUCTED_PICTURE_BASE_ADDRESS];
+	vdec_ext->luma_alt_addr =
+		pic_cmds[VDECFW_CMD_LUMA_ALTERNATIVE_PICTURE_BASE_ADDRESS];
+	vdec_ext->chroma_alt_addr =
+		pic_cmds[VDECFW_CMD_CHROMA_ALTERNATIVE_PICTURE_BASE_ADDRESS];
+	vdec_ext->chroma2alt_addr =
+		pic_cmds[VDECFW_CMD_CHROMA2_ALTERNATIVE_PICTURE_BASE_ADDRESS];
+
+	if (vid_std == VDEC_STD_VC1) {
+		struct vidio_ddbufinfo *vlc_idx_tables_bufinfo =
+			dec_pict->vlc_idx_tables_bufinfo;
+		struct vidio_ddbufinfo *vlc_tables_bufinfo =
+			dec_pict->vlc_tables_bufinfo;
+
+		vdec_ext->vlc_idx_table_size = vlc_idx_tables_bufinfo->buf_size;
+		vdec_ext->vlc_idx_table_addr = vlc_idx_tables_bufinfo->buf_size;
+		vdec_ext->vlc_tables_size = vlc_tables_bufinfo->buf_size;
+		vdec_ext->vlc_tables_size = vlc_tables_bufinfo->buf_size;
+	} else {
+		vdec_ext->vlc_idx_table_size = 0;
+		vdec_ext->vlc_idx_table_addr = 0;
+		vdec_ext->vlc_tables_size = 0;
+		vdec_ext->vlc_tables_size = 0;
+	}
+
+	vdec_ext->display_picture_size = pic_cmds[VDECFW_CMD_DISPLAY_PICTURE];
+	vdec_ext->parser_mode = parser_mode;
+
+	/* miscellaneous flags */
+	vdec_ext->is_chromainterleaved =
+		REGIO_READ_FIELD(pic_cmds[VDECFW_CMD_OPERATING_MODE], MSVDX_CMDS, OPERATING_MODE,
+				 CHROMA_INTERLEAVED);
+	vdec_ext->is_discontinuousmbs =
+		dec_pict->pict_hdr_info->discontinuous_mbs;
+
+#ifdef HAS_HEVC
+	if (dec_pict->pvdec_info) {
+		vdec_ext->mem_to_reg_addr = dec_pict->pvdec_info->ddbuf_info->dev_virt;
+		vdec_ext->slice_params_addr = dec_pict->pvdec_info->ddbuf_info->dev_virt +
+			MEM_TO_REG_BUF_SIZE;
+		vdec_ext->slice_params_size = SLICE_PARAMS_BUF_SIZE;
+	}
+	if (vid_std == VDEC_STD_HEVC) {
+		struct vdecdd_picture *picture = (struct vdecdd_picture *)str_unit->dd_pict_data;
+
+		VDEC_ASSERT(picture);
+		/* 10-bit packed output format indicator */
+		vdec_ext->is_packedformat = picture->op_config.pixel_info.mem_pkg ==
+			PIXEL_BIT10_MP ? 1 : 0;
+	}
+#endif
+	return IMG_SUCCESS;
+}
+
+/*
+ * NOTE :
+ * translation_configure_tiling is not supported as of now.
+ */
+int translation_ctrl_alloc_prepare(struct vdec_str_configdata *pstr_config_data,
+				   struct vdecdd_str_unit *str_unit,
+				   struct dec_decpict *dec_pict,
+				   const struct vxd_coreprops *core_props,
+				   struct decoder_regsoffsets *regs_offset)
+{
+	int result;
+	unsigned int *cmd_buf;
+	unsigned int hdr_size = 0;
+	unsigned int pict_cmds[VDECFW_CMD_MAX];
+	enum vdecfw_codectype codec;
+	struct vxd_buffers buffers;
+	struct vdec_ext_cmd *vdec_ext;
+	enum vdecfw_parsermode parser_mode = VDECFW_SCP_ONLY;
+	struct vidio_ddbufinfo *batch_msgbuf_info =
+		dec_pict->batch_msginfo->ddbuf_info;
+	struct lst_t *decpic_seg_list = &dec_pict->dec_pict_seg_list;
+	unsigned int memto_reg_host_part = 0;
+
+	unsigned long ctrl_alloc = (unsigned long)batch_msgbuf_info->cpu_virt;
+	unsigned long ctrl_alloc_end = ctrl_alloc + batch_msgbuf_info->buf_size;
+
+	struct vdecdd_picture *picture =
+		(struct vdecdd_picture *)str_unit->dd_pict_data;
+
+	memset(pict_cmds, 0, sizeof(pict_cmds));
+	memset(&buffers, 0, sizeof(buffers));
+
+	VDEC_ASSERT(batch_msgbuf_info->buf_size >= CTRL_ALLOC_MAX_SEGMENT_SIZE);
+	memset(batch_msgbuf_info->cpu_virt, 0, batch_msgbuf_info->buf_size);
+
+	/* Construct transaction based on new picture. */
+	VDEC_ASSERT(str_unit->str_unit_type == VDECDD_STRUNIT_PICTURE_START);
+
+	/* Obtain picture data. */
+	picture = (struct vdecdd_picture *)str_unit->dd_pict_data;
+	dec_pict->recon_pict = &picture->disp_pict_buf;
+
+	result = translation_get_codec(pstr_config_data->vid_std, &codec);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	translation_setup_std_header(pstr_config_data, dec_pict, str_unit, &hdr_size, picture,
+				     pict_cmds, &parser_mode);
+
+	buffers.recon_pict = dec_pict->recon_pict;
+	buffers.alt_pict = dec_pict->alt_pict;
+
+#ifdef HAS_HEVC
+	/* Set pipe offsets to device buffers */
+	if (pstr_config_data->vid_std == VDEC_STD_HEVC) {
+		/* FW in multipipe requires this buffers to be allocated per stream */
+		if (picture->pict_res_int && picture->pict_res_int->seq_resint &&
+		    picture->pict_res_int->seq_resint->intra_buffer &&
+		    picture->pict_res_int->seq_resint->aux_buffer) {
+			buffers.intra_bufinfo =
+				&picture->pict_res_int->seq_resint->intra_buffer->ddbuf_info;
+			buffers.auxline_bufinfo =
+				&picture->pict_res_int->seq_resint->aux_buffer->ddbuf_info;
+		}
+	} else {
+		buffers.intra_bufinfo = dec_pict->intra_bufinfo;
+		buffers.auxline_bufinfo = dec_pict->auxline_bufinfo;
+	}
+
+	if (buffers.intra_bufinfo)
+		buffers.intra_bufsize_per_pipe = buffers.intra_bufinfo->buf_size /
+			core_props->num_pixel_pipes;
+	if (buffers.auxline_bufinfo)
+		buffers.auxline_bufsize_per_pipe = buffers.auxline_bufinfo->buf_size /
+			core_props->num_pixel_pipes;
+#endif
+
+#ifdef ERROR_CONCEALMENT
+	if (picture->pict_res_int && picture->pict_res_int->seq_resint)
+		if (picture->pict_res_int->seq_resint->err_pict_buf)
+			buffers.err_pict_bufinfo =
+				&picture->pict_res_int->seq_resint->err_pict_buf->ddbuf_info;
+#endif
+
+	/*
+	 * Prepare Reconstructed Picture Configuration
+	 * Note: we are obtaining values of registers prepared basing on header
+	 * files generated from MSVDX *dev files.
+	 * That's allowed, as layout of registers: MSVDX_CMDS_OPERATING_MODE,
+	 * MSVDX_CMDS_EXTENDED_ROW_STRIDE,
+	 * MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION,
+	 * MSVDX_CMDS_CHROMA_ROW_STRIDE is the same for both MSVDX and PVDEC.
+	 */
+	vxd_set_reconpictcmds(str_unit, pstr_config_data, &picture->op_config, core_props,
+			      &buffers, pict_cmds);
+
+	/* Alternative Picture Configuration */
+	if (dec_pict->alt_pict) {
+		dec_pict->twopass = picture->op_config.force_oold;
+		buffers.btwopass = dec_pict->twopass;
+		/*
+		 * Alternative Picture Configuration
+		 * Note: we are obtaining values of registers prepared basing
+		 * on header files generated from MSVDX *dev files.
+		 * That's allowed, as layout of registers:
+		 * MSVDX_CMDS_OPERATING_MODE, MSVDX_CMDS_EXTENDED_ROW_STRIDE,
+		 * MSVDX_CMDS_ALTERNATIVE_OUTPUT_PICTURE_ROTATION,
+		 * MSVDX_CMDS_CHROMA_ROW_STRIDE is the same for both MSVDX and
+		 * PVDEC.
+		 */
+		/*
+		 * Configure second buffer for out-of-loop processing
+		 * (e.g. scaling etc.).
+		 */
+		vxd_set_altpictcmds(str_unit, pstr_config_data, &picture->op_config, core_props,
+				    &buffers, pict_cmds);
+	}
+
+	/*
+	 * Setup initial simple bitstream configuration to be used by parser
+	 * task
+	 */
+	cmd_buf = (unsigned int *)ctrl_alloc;
+	result = translation_pvdec_adddma_transfers
+			(decpic_seg_list, &cmd_buf,
+			 (ctrl_alloc_end - (unsigned long)cmd_buf) / sizeof(unsigned int),
+			 dec_pict, str_unit->eop);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	if ((unsigned long)(cmd_buf + (sizeof(struct ctrl_alloc_header) +
+		sizeof(struct vdec_ext_cmd)) / sizeof(unsigned int)) >=
+		ctrl_alloc_end)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/*
+	 * Setup regular control allocation message. Start with control
+	 * allocation header
+	 */
+	translation_pvdec_ctrl_setuphdr((struct ctrl_alloc_header *)cmd_buf, pict_cmds);
+	/* Setup additional params for VP8 */
+	cmd_buf += sizeof(struct ctrl_alloc_header) / sizeof(unsigned int);
+
+	/* Reserve space for VDEC extension command and fill it */
+	vdec_ext = (struct vdec_ext_cmd *)cmd_buf;
+	cmd_buf += sizeof(struct vdec_ext_cmd) / sizeof(unsigned int);
+
+	result = translation_pvdecsetup_vdecext(vdec_ext, dec_pict, pict_cmds,
+						str_unit,
+						pstr_config_data->vid_std,
+						parser_mode);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	vdec_ext->hdr_size = hdr_size;
+
+	/* Add VLC tables to control allocation, skip when VC1 */
+	if (pstr_config_data->vid_std != VDEC_STD_VC1 &&
+	    dec_pict->vlc_idx_tables_bufinfo &&
+	    dec_pict->vlc_idx_tables_bufinfo->cpu_virt) {
+		unsigned short *vlc_idx_tables = (unsigned short *)
+			dec_pict->vlc_idx_tables_bufinfo->cpu_virt;
+		/*
+		 * Get count of elements in VLC idx table. Each element is made
+		 * of 3 IMG_UINT16, see e.g. mpeg2_idx.c
+		 */
+		unsigned int vlc_idx_count =
+			dec_pict->vlc_idx_tables_bufinfo->buf_size /
+			(3 * sizeof(unsigned short));
+
+		/* Add command to DMA VLC */
+		result = translation_pvdecsetup_vlcdma
+				(dec_pict->vlc_tables_bufinfo, &cmd_buf,
+				(ctrl_alloc_end - (unsigned long)cmd_buf) / sizeof(unsigned int));
+
+		if (result != IMG_SUCCESS)
+			return result;
+
+		/* Add command to configure VLC tables */
+		result = translation_pvdecsetup_vlctables
+				((unsigned short (*)[3])vlc_idx_tables, vlc_idx_count, &cmd_buf,
+				 (ctrl_alloc_end - (unsigned long)cmd_buf) / sizeof(unsigned int),
+				 regs_offset->vec_offset);
+
+		if (result != IMG_SUCCESS)
+			return result;
+	}
+
+	/* Setup commands for standards other than HEVC */
+	if (pstr_config_data->vid_std != VDEC_STD_HEVC) {
+		translation_pvdec_setup_commands
+				(pict_cmds, &cmd_buf,
+				 (ctrl_alloc_end - (unsigned long)cmd_buf) / sizeof(unsigned int),
+				 regs_offset->vdmc_cmd_offset);
+	}
+
+	/* Setup commands for HEVC */
+	vdec_ext->mem_to_reg_size = 0;
+
+#ifdef HAS_HEVC
+	if (pstr_config_data->vid_std == VDEC_STD_HEVC) {
+		result = translation_pvdec_setup_pvdec_commands
+				(picture, dec_pict, str_unit,
+				 regs_offset, &cmd_buf,
+				 (ctrl_alloc_end - (unsigned long)cmd_buf) / sizeof(unsigned int),
+				 &memto_reg_host_part, pict_cmds);
+		if (result != IMG_SUCCESS) {
+			pr_err("Failed to setup VDMC & VDEB firmware commands.");
+			return result;
+		}
+
+		/* Set size of MemToReg buffer in VDEC extension command */
+		VDEC_ASSERT(MEM_TO_REG_BUF_SIZE <
+			(MEM2REG_SIZE_BUF_TOTAL_MASK >> MEM2REG_SIZE_BUF_TOTAL_SHIFT));
+		VDEC_ASSERT(memto_reg_host_part <
+			(MEM2REG_SIZE_HOST_PART_MASK >> MEM2REG_SIZE_HOST_PART_SHIFT));
+
+		vdec_ext->mem_to_reg_size = (MEM_TO_REG_BUF_SIZE << MEM2REG_SIZE_BUF_TOTAL_SHIFT) |
+			(memto_reg_host_part << MEM2REG_SIZE_HOST_PART_SHIFT);
+
+		dec_pict->genc_id = picture->pict_res_int->seq_resint->genc_buf_id;
+		dec_pict->genc_bufs = picture->pict_res_int->seq_resint->genc_buffers;
+	}
+#endif
+	/* Finally mark end of commands */
+	*(cmd_buf++) = CMD_COMPLETION;
+
+	/* Print message for debugging */
+	{
+		int i;
+
+		for (i = 0; i < ((unsigned long)cmd_buf - ctrl_alloc) / sizeof(unsigned int); i++)
+			pr_debug("ctrl_alloc_buf[%d] == %08x\n", i,
+				 ((unsigned int *)ctrl_alloc)[i]);
+	}
+	/* Transfer control allocation command to device memory */
+	dec_pict->ctrl_alloc_bytes = ((unsigned long)cmd_buf - ctrl_alloc);
+	dec_pict->ctrl_alloc_offset = dec_pict->ctrl_alloc_bytes;
+	dec_pict->operating_op = pict_cmds[VDECFW_CMD_OPERATING_MODE];
+
+	/*
+	 * NOTE : Nothing related to tiling will be used.
+	 * result = translation_ConfigureTiling(psStrUnit, psDecPict,
+	 * psCoreProps);
+	 */
+
+	return result;
+};
+
+int translation_fragment_prepare(struct dec_decpict *dec_pict,
+				 struct lst_t *decpic_seg_list, int eop,
+				 struct dec_pict_fragment *pict_fragement)
+{
+	int result;
+	unsigned int *cmd_buf;
+	struct vidio_ddbufinfo *batchmsg_bufinfo;
+	unsigned long ctrl_alloc;
+	unsigned long ctrl_alloc_end;
+
+	if (!dec_pict || !dec_pict->batch_msginfo ||
+	    !decpic_seg_list || !pict_fragement)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	batchmsg_bufinfo = dec_pict->batch_msginfo->ddbuf_info;
+
+	ctrl_alloc = (unsigned long)batchmsg_bufinfo->cpu_virt +
+		dec_pict->ctrl_alloc_offset;
+	ctrl_alloc_end = (unsigned long)batchmsg_bufinfo->cpu_virt +
+		batchmsg_bufinfo->buf_size;
+
+	/*
+	 * Setup initial simple bitstream configuration to be used by parser
+	 * task
+	 */
+	cmd_buf = (unsigned int *)ctrl_alloc;
+	result = translation_pvdec_adddma_transfers
+			(decpic_seg_list, &cmd_buf,
+			(ctrl_alloc_end - (unsigned long)cmd_buf) / sizeof(unsigned int),
+			dec_pict, eop);
+
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Finally mark end of commands */
+	*(cmd_buf++) = CMD_COMPLETION;
+
+	/* Transfer control allocation command to device memory */
+	pict_fragement->ctrl_alloc_offset = dec_pict->ctrl_alloc_offset;
+	pict_fragement->ctrl_alloc_bytes =
+		((unsigned long)cmd_buf - ctrl_alloc);
+
+	dec_pict->ctrl_alloc_offset += pict_fragement->ctrl_alloc_bytes;
+
+	return result;
+};
+#endif /* VDEC_USE_PVDEC */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/translation_api.h b/drivers/media/platform/img/vxe-vxd/decoder/translation_api.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/translation_api.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/translation_api.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VDECDD translation API's.
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+#ifndef __TRANSLATION_API_H__
+#define __TRANSLATION_API_H__
+
+#include "decoder.h"
+#include "hw_control.h"
+#include "vdecdd_defs.h"
+#include "vdec_defs.h"
+#include "vxd_props.h"
+
+/*
+ * This function submits a stream unit for translation
+ * into a control allocation buffer used in PVDEC operation.
+ */
+int translation_ctrl_alloc_prepare
+	(struct vdec_str_configdata *psstr_config_data,
+	struct vdecdd_str_unit *psstrunit,
+	struct dec_decpict *psdecpict,
+	const struct vxd_coreprops *core_props,
+	struct decoder_regsoffsets *regs_offset);
+
+/*
+ * TRANSLATION_FragmentPrepare.
+ */
+int translation_fragment_prepare(struct dec_decpict *psdecpict,
+				 struct lst_t *decpic_seg_list, int eop,
+				 struct dec_pict_fragment *pict_fragement);
+
+#endif /* __TRANSLATION_API_H__ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_defs.h b/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_defs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_defs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_defs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,446 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD Decoder device driver header definitions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com
+ */
+
+#ifndef __VDECDD_DEFS_H__
+#define __VDECDD_DEFS_H__
+
+#include "bspp.h"
+#include "lst.h"
+#include "vdec_defs.h"
+#include "vdecfw_shared.h"
+#include "vid_buf.h"
+#include "vxd_mmu_defs.h"
+
+/* RMAN type for streams.          */
+#define VDECDD_STREAM_TYPE_ID   (0xB0B00001)
+
+/* RMAN type for buffer mappings.  */
+#define VDECDD_BUFMAP_TYPE_ID   (0xB0B00002)
+
+/*
+ * This type contains core feature flags.
+ * @brief  Core Feature Flags
+ */
+enum vdecdd_core_feature_flags {
+	VDECDD_COREFEATURE_MPEG2       = (1 << 0),
+	VDECDD_COREFEATURE_MPEG4       = (1 << 1),
+	VDECDD_COREFEATURE_H264        = (1 << 2),
+	VDECDD_COREFEATURE_VC1         = (1 << 3),
+	VDECDD_COREFEATURE_AVS         = (1 << 4),
+	VDECDD_COREFEATURE_REAL        = (1 << 5),
+	VDECDD_COREFEATURE_JPEG        = (1 << 6),
+	VDECDD_COREFEATURE_VP6         = (1 << 7),
+	VDECDD_COREFEATURE_VP8         = (1 << 8),
+	VDECDD_COREFEATURE_HEVC        = (1 << 9),
+	VDECDD_COREFEATURE_HD_DECODE   = (1 << 10),
+	VDECDD_COREFEATURE_ROTATION    = (1 << 11),
+	VDECDD_COREFEATURE_SCALING     = (1 << 12),
+	VDECDD_COREFEATURE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This structure contains configuration relating to a device.
+ * @brief  Device Configuration
+ */
+struct vdecdd_dd_devconfig {
+	unsigned int num_slots_per_pipe;
+};
+
+/*
+ * This structure contains the Decoder decoding picture status.
+ * @brief Decoder Decoding Picture Status
+ */
+struct vdecdd_dec_pict_status {
+	unsigned int transaction_id;
+	enum vdecfw_progresscheckpoint fw_cp;
+	enum vdecfw_progresscheckpoint fehw_cp;
+	enum vdecfw_progresscheckpoint behw_cp;
+	unsigned int dmac_status;
+	unsigned int fe_mb_x;
+	unsigned int fe_mb_y;
+	unsigned int be_mb_x;
+	unsigned int be_mb_y;
+	unsigned char fw_control_msg[VDECFW_MSGID_CONTROL_TYPES];
+	unsigned char fw_decode_msg[VDECFW_MSGID_DECODE_TYPES];
+	unsigned char fw_completion_msg[VDECFW_MSGID_COMPLETION_TYPES];
+	unsigned char host_control_msg[VDECFW_MSGID_CONTROL_TYPES];
+	unsigned char host_decode_msg[VDECFW_MSGID_DECODE_TYPES];
+	unsigned char host_completion_msg[VDECFW_MSGID_COMPLETION_TYPES];
+};
+
+/*
+ * This structure contains the Decoder decoding picture status.
+ * @brief  Core Status
+ */
+struct vdecdd_core_status {
+	unsigned int mtx_pc;
+	unsigned int mtx_pcx;
+	unsigned int mtx_enable;
+	unsigned int mtx_st_bits;
+	unsigned int mtx_fault0;
+	unsigned int mtx_a0_stack_ptr;
+	unsigned int mtx_a0_frame_ptr;
+	unsigned int dma_setup[3];
+	unsigned int dma_count[3];
+	unsigned int dma_peripheral_addr[3];
+};
+
+/*
+ * This structure contains the Decoder component stream status.
+ * @brief   Decoder Component Stream Status
+ */
+struct vdecdd_decstr_status {
+	unsigned int num_pict_decoding;
+	struct vdecdd_dec_pict_status dec_pict_st[VDECFW_MAX_NUM_PICTURES];
+	unsigned int num_pict_decoded;
+	unsigned int decoded_picts[VDECFW_MAX_NUM_PICTURES];
+	unsigned int features;
+	struct vdecdd_core_status core_st;
+	unsigned int display_pics;
+	unsigned int release_pics;
+	unsigned int next_display_items[VDECFW_MAX_NUM_PICTURES];
+	unsigned int next_display_item_parent[VDECFW_MAX_NUM_PICTURES];
+	unsigned int next_release_items[VDECFW_MAX_NUM_PICTURES];
+	unsigned int next_release_item_parent[VDECFW_MAX_NUM_PICTURES];
+	unsigned int flds_as_frm_decodes;
+	unsigned int total_pict_decoded;
+	unsigned int total_pict_displayed;
+	unsigned int total_pict_finished;
+};
+
+/*
+ * This structure contains the device context.
+ * @brief  VDECDD Device Context
+ */
+struct vdecdd_dddev_context {
+	void *dev_handle;
+	void *dec_context;
+	unsigned int internal_heap_id;
+	void *res_buck_handle;
+};
+
+/*
+ * This type defines the stream state.
+ * @brief  VDEDD Stream State
+ */
+enum vdecdd_ddstr_state {
+	VDECDD_STRSTATE_STOPPED     = 0x00,
+	VDECDD_STRSTATE_PLAYING,
+	VDECDD_STRSTATE_STOPPING,
+	VDECDD_STRSTATE_MAX,
+	VDECDD_STRSTATE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This structure contains the mapped output buffer configuration.
+ * @brief  VDECDD Mapped Output Buffer Configuration
+ */
+struct vdecdd_mapbuf_info {
+	unsigned int buf_size;
+	unsigned int num_buf;
+	unsigned char byte_interleave;
+};
+
+struct vdecdd_ddstr_ctx;
+
+/*
+ * This structure contains the map info.
+ * @brief  VDECDD Map Info
+ */
+struct vdecdd_ddbuf_mapinfo {
+	void **link;    /* to be part of single linked list */
+	void *res_handle;
+	unsigned int buf_id;
+	unsigned int buf_map_id;
+	struct vdecdd_ddstr_ctx *ddstr_context;
+	void *buf_cb_param;
+	enum vdec_buf_type buf_type;
+	enum mmu_eheap_id mmuheap_id;
+	struct vidio_ddbufinfo ddbuf_info;
+};
+
+/*
+ * This structure contains the information about the picture buffer
+ * and its structure.
+ * @brief  VDECDD Picture Buffer Info
+ */
+struct vdecdd_ddpict_buf {
+	struct vdecdd_ddbuf_mapinfo *pict_buf;
+	struct vdec_pict_rendinfo rend_info;
+	struct vdec_pict_bufconfig buf_config;
+};
+
+/*
+ * This structure contains the stream context.
+ * @brief  VDECDD Stream Context
+ */
+struct vdecdd_ddstr_ctx {
+	void **link;    /* to be part of single linked list */
+	unsigned int res_str_id;
+	unsigned int km_str_id;
+	void *res_buck_handle;
+	void *res_handle;
+	struct vdecdd_dddev_context *dd_dev_context;
+	struct vdec_str_configdata str_config_data;
+	unsigned char preempt;
+	enum vdecdd_ddstr_state dd_str_state;
+	void *mmu_str_handle;
+	void *dec_ctx;
+	enum vdec_play_mode play_mode;
+	struct vdec_comsequ_hdrinfo comseq_hdr_info;
+	struct vdecdd_ddpict_buf disp_pict_buf;
+	struct vdecdd_mapbuf_info map_buf_info;
+	struct vdec_str_opconfig opconfig;
+	unsigned char str_op_configured;
+	struct vdec_comsequ_hdrinfo prev_comseq_hdr_info;
+	struct bspp_pict_hdr_info prev_pict_hdr_info;
+};
+
+/*
+ * This type defines the stream unit type.
+ * @brief  Stream Unit Type
+ */
+enum vdecdd_str_unit_type {
+	VDECDD_STRUNIT_ANONYMOUS = 0,
+	VDECDD_STRUNIT_SEQUENCE_START,
+	VDECDD_STRUNIT_CLOSED_GOP,
+	VDECDD_STRUNIT_SEQUENCE_END,
+	VDECDD_STRUNIT_PICTURE_PORTENT,
+	VDECDD_STRUNIT_PICTURE_START,
+	VDECDD_STRUNIT_PICTURE_FRAGMENT,
+	VDECDD_STRUNIT_PICTURE_END,
+	VDECDD_STRUNIT_FENCE,
+	VDECDD_STRUNIT_STOP,
+	VDECDD_STRUNIT_MAX,
+	VDECDD_STRUNIT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This structure contains a front end stream unit.
+ * @brief   Front End Stream Unit
+ */
+struct vdecdd_str_unit {
+	void *lst_padding;
+	enum vdecdd_str_unit_type str_unit_type;
+	void *str_unit_handle;
+	unsigned int err_flags;
+	struct lst_t bstr_seg_list;
+	void *dd_data;
+	struct bspp_sequ_hdr_info *seq_hdr_info;
+	unsigned int seq_hdr_id;
+	unsigned char closed_gop;
+	unsigned char eop;
+	struct bspp_pict_hdr_info *pict_hdr_info;
+	void *dd_pict_data;
+	unsigned char last_pict_in_seq;
+	void *str_unit_tag;
+	unsigned char decode;
+	unsigned int features;
+	unsigned char eos;
+};
+
+/*
+ * This structure contains a set of picture resources required at all the
+ * interim stages of decoding it as it flows around the internals. It originates
+ * in the plant.
+ * @brief   Picture Resources (stream)
+ */
+struct vdecdd_pict_resint {
+	void **link;    /* to be part of single linked list */
+	struct vdecdd_ddbuf_mapinfo *mb_param_buf;
+	unsigned int ref_cnt;
+
+#ifdef HAS_HEVC
+	/* GENC fragment buffer */
+	struct vdecdd_ddbuf_mapinfo *genc_fragment_buf;
+#endif
+#if defined(HAS_HEVC) || defined(ERROR_CONCEALMENT)
+	/* Sequence resources (GENC buffers) */
+	struct vdecdd_seq_resint *seq_resint;
+#endif
+};
+
+/*
+ * This structure contains the supplementary information for decoded picture.
+ * @brief   Event Callback Information
+ */
+struct vdecdd_pict_sup_data {
+	void *raw_vui_data;
+	void *raw_sei_list_first_fld;
+	void *raw_sei_list_second_fld;
+	unsigned char merged_flds;
+	union {
+		struct vdecdd_h264_pict_supl_data {
+			unsigned char nal_ref_idc;
+			unsigned short frame_num;
+		} h264_pict_supl_data;
+#ifdef HAS_HEVC
+		struct vdecdd_hevc_pict_supl_data {
+			unsigned int pic_order_cnt;
+		} hevc_pict_supl_data;
+#endif
+	};
+};
+
+/*
+ * This structure contains a set of resources representing a picture
+ * at all the stages of processing it.
+ * @brief   Picture
+ */
+struct vdecdd_picture {
+	unsigned int pict_id;
+	unsigned char last_pict_in_seq;
+	struct vdecdd_pict_resint *pict_res_int;
+	struct vdecdd_ddpict_buf disp_pict_buf;
+	struct vdec_str_opconfig op_config;
+	struct vdec_dec_pict_info *dec_pict_info;
+	struct vdecdd_pict_sup_data dec_pict_sup_data;
+	struct vdec_dec_pict_auxinfo dec_pict_aux_info;
+};
+
+/*
+ * This structure contains the information required to check Decoder support
+ * Only pointers that are non-null will be used in validation.
+ * @brief  VDECDD Support Check Information
+ */
+struct vdecdd_supp_check {
+	/* Inputs */
+	const struct vdec_comsequ_hdrinfo *comseq_hdrinfo;
+	const struct vdec_str_opconfig *op_cfg;
+	const struct vdecdd_ddpict_buf *disp_pictbuf;
+	const struct bspp_pict_hdr_info *pict_hdrinfo;
+	unsigned char non_cfg_req;
+
+	/* Outputs */
+	struct vdec_unsupp_flags unsupp_flags;
+	unsigned int features;
+};
+
+/*
+ * This type defines unsupported stream configuration features.
+ * @brief  Unsupported Stream Configuration Flags
+ */
+enum vdec_unsupp_strcfg {
+	VDECDD_UNSUPPORTED_STRCONFIG_STD         = (1 << 0),
+	VDECDD_UNSUPPORTED_STRCONFIG_BSTRFORMAT  = (1 << 1),
+	VDECDD_UNSUPPORTED_STRCONFIG_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This type defines unsupported output configuration features.
+ * @brief  Unsupported Output Configuration Flags
+ */
+enum vdec_unsupp_opcfg {
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_ROTATION                   = (1 << 0),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_ROTATION_WITH_FIELDS       = (1 << 1),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_ROTATION_WITH_SCALING      = (1 << 2),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_SCALING                    = (1 << 3),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_UP_DOWNSAMPLING            = (1 << 4),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_SCALING_WITH_OOLD          = (1 << 5),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_SCALING_MONOCHROME         = (1 << 6),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_SCALING_SIZE               = (1 << 7),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_X_WITH_JPEG                = (1 << 8),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_SCALESIZE                  = (1 << 9),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_PIXFORMAT                  = (1 << 10),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_ROTATION_WITH_HIGH_COLOUR  =
+		(1 << 11),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_DOWNSAMPLING_WITH_ROTATION =
+		(1 << 12),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_ROTATION_WITH_10BIT_PACKED =
+		(1 << 13),
+	VDECDD_UNSUPPORTED_OUTPUTCONFIG_FORCE32BITS                = 0x7FFFFFFFU
+};
+
+/*
+ * This type defines unsupported output configuration features.
+ * @brief  Unsupported Output Configuration Flags
+ */
+enum vdec_unsupp_op_bufcfg {
+	VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_EXTENDED_STRIDE = (1 << 0),
+	VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_64BYTE_STRIDE   = (1 << 1),
+	VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_FIXED_STRIDE    = (1 << 2),
+	VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_PICTURE_SIZE    = (1 << 3),
+	VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_BUFFER_SIZE     = (1 << 4),
+	VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_Y_SIZE          = (1 << 5),
+	VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_UV_SIZE         = (1 << 6),
+	VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_Y_STRIDE        = (1 << 7),
+	VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_UV_STRIDE       = (1 << 8),
+	VDECDD_UNSUPPORTED_OUTPUTBUFCONFIG_FORCE32BITS     = 0x7FFFFFFFU
+};
+
+/*
+ * This type defines unsupported sequence header features.
+ * @brief  Unsupported Sequence Header Flags
+ */
+enum vdec_unsupp_seqhdr {
+	VDECDD_UNSUPPORTED_SEQUHDR_PIXFORMAT_BIT_DEPTH = (1 << 0),
+	VDECDD_UNSUPPORTED_SEQUHDR_SCALING             = (1 << 1),
+	VDECDD_UNSUPPORTED_SEQUHDR_PIXEL_FORMAT        = (1 << 2),
+	VDECDD_UNSUPPORTED_SEQUHDR_NUM_OF_VIEWS        = (1 << 3),
+	VDECDD_UNSUPPORTED_SEQUHDR_CODED_HEIGHT        = (1 << 4),
+	VDECDD_UNSUPPORTED_SEQUHDR_SEP_COLOUR_PLANE    = (1 << 5),
+	VDECDD_UNSUPPORTED_SEQUHDR_SIZE                = (1 << 6),
+	VDECDD_UNSUPPORTED_SEQUHDR_FORCE32BITS         = 0x7FFFFFFFU
+};
+
+/*
+ * This type defines unsupported picture header features.
+ * @brief  Unsupported Picture Header Flags
+ */
+enum vdec_unsupp_picthdr {
+	VDECDD_UNSUPPORTED_PICTHDR_UPSCALING            = (1 << 0),
+	VDECDD_UNSUPPORTED_PICTHDR_OVERSIZED_SGM        = (1 << 1),
+	VDECDD_UNSUPPORTED_PICTHDR_DISCONTINUOUS_MBS    = (1 << 2),
+	VDECDD_UNSUPPORTED_PICTHDR_RESOLUTION           = (1 << 3),
+	VDECDD_UNSUPPORTED_PICTHDR_SCALING_ORIGINALSIZE = (1 << 4),
+	VDECDD_UNSUPPORTED_PICTHDR_SCALING_SIZE         = (1 << 5),
+	VDECDD_UNSUPPORTED_PICTHDR_HEVC_RANGE_EXT       = (1 << 6),
+	VDECDD_UNSUPPORTED_PICTHDR_FORCE32BITS          = 0x7FFFFFFFU
+};
+
+/*
+ * This type defines the Bitstream Segment type.
+ * @brief  Bitstream segment type
+ */
+enum vdecdd_bstr_segtype {
+	VDECDD_BSSEG_LASTINBUFF         = (1 << 0),
+	VDECDD_BSSEG_SKIP               = (1 << 1),
+	VDECDD_BSSEG_INSERTSCP          = (1 << 2),
+	VDECDD_BSSEG_INSERT_STARTCODE   = (1 << 3) | VDECDD_BSSEG_INSERTSCP,
+	VDECDD_BSSEG_INSERT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+struct vdecdd_seq_resint {
+	void **link;
+
+#ifdef HAS_HEVC
+	unsigned short genc_buf_id;
+	struct vdecdd_ddbuf_mapinfo *genc_buffers[4]; /* GENC buffers */
+	struct vdecdd_ddbuf_mapinfo *intra_buffer;    /* GENC buffers */
+	struct vdecdd_ddbuf_mapinfo *aux_buffer;      /* GENC buffers */
+#endif
+	struct vdecdd_ddbuf_mapinfo *err_pict_buf;    /* Pointer to "Error
+						       * Recovery Frame Store" buffer.
+						       */
+
+	/*
+	 * Ref. counter (number of users) of sequence resources
+	 * NOTE: Internal buffer reference counters are not used
+	 * for buffers allocated as sequence resources.
+	 */
+	unsigned int ref_count;
+};
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_utils_buf.c b/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_utils_buf.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_utils_buf.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_utils_buf.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,897 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VXD Decoder device driver buffer utility functions implementation
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "img_profiles_levels.h"
+#include "pixel_api.h"
+#include "vdecdd_utils.h"
+
+/*
+ * Tests if chroma offset (immediately after size of luma) is exactly
+ * aligned to buffer alignment constraint.
+ */
+static inline unsigned char is_packedbuf_chroma_aligned(unsigned int offset,
+							unsigned int color_plane,
+							unsigned int align)
+{
+	return(color_plane != VDEC_PLANE_VIDEO_Y ? TRUE :
+	       (offset == ALIGN(offset, align) ? TRUE : FALSE));
+}
+
+/*
+ * < h.264 MaxDpbMbs values per profile (see Table A-1 of Rec. ITU-T H.264
+ * (03/2010)).
+ *   NOTE: Level 1b will be treated as 1.1 in case of Baseline,
+ * Constrained Baseline, Main, and Extended profiles as the value of the
+ * constraint_set3_flag is not available in #VDEC_sComSequHdrInfo structure.
+ */
+static unsigned int h264_max_dpb_mbs[H264_LEVEL_MAJOR_NUM][H264_LEVEL_MINOR_NUM] = {
+	/* level: n/a     n/a     n/a     1.0b */
+	{ 396,    396,    396,    396  },
+	/* level: 1.0     1.1     1.2     1.3 */
+	{ 396,    900,    2376,   2376 },
+	/* level: 2.0     2.1     2.2     n/a */
+	{ 2376,   4752,   8100,   8100 },
+	/* level: 3.0     3.1     3.2     n/a */
+	{ 8100,   18000,  20480,  20480},
+	/* level: 4.0     4.1     4.2     n/a */
+	{ 32768,  32768,  34816,  34816},
+	/* level: 5.0     5.1     5.2     n/a */
+	{ 110400, 184320, 184320, 184320}
+};
+
+typedef int (*fn_ref_pic_get_max_num)(const struct vdec_comsequ_hdrinfo
+	*comseq_hdrinfo, unsigned int *max_ref_pic_num);
+
+void vdecddutils_buf_vxd_adjust_size(unsigned int *buf_size)
+{
+	/* Align the buffer size to VXD page size. */
+	*buf_size = ALIGN(*buf_size, VDEC_VXD_BUF_ALIGNMENT);
+}
+
+static int vdecddutils_ref_pic_h264_get_maxnum
+	(const struct vdec_comsequ_hdrinfo *comseq_hdrinfo,
+	unsigned int *max_ref_pic_num)
+{
+	unsigned int pic_width_mb;
+	unsigned int pic_height_mb;
+	unsigned int lvl_major = 0;
+	unsigned int lvl_minor = 0;
+
+	/* Pre-validate level. */
+	if (comseq_hdrinfo->codec_level < H264_LEVEL_MIN ||
+	    comseq_hdrinfo->codec_level > H264_LEVEL_MAX) {
+		pr_warn("Wrong H264 level value: %u",
+			comseq_hdrinfo->codec_level);
+	}
+
+	if (comseq_hdrinfo->max_reorder_picts) {
+		*max_ref_pic_num = comseq_hdrinfo->max_reorder_picts;
+	} else {
+		/* Calculate level major and minor. */
+		lvl_major = comseq_hdrinfo->codec_level / 10;
+		lvl_minor = comseq_hdrinfo->codec_level % 10;
+
+		/* Calculate picture sizes in MBs. */
+		pic_width_mb = (comseq_hdrinfo->max_frame_size.width +
+			(VDEC_MB_DIMENSION - 1)) / VDEC_MB_DIMENSION;
+		pic_height_mb = (comseq_hdrinfo->max_frame_size.height +
+			(VDEC_MB_DIMENSION - 1)) / VDEC_MB_DIMENSION;
+
+		/* Validate lvl_minor */
+		if (lvl_minor > 3) {
+			pr_warn("Wrong H264 lvl_minor level value: %u, overriding with 3",
+				lvl_minor);
+			lvl_minor = 3;
+		}
+		/* Validate lvl_major */
+		if (lvl_major > 5) {
+			pr_warn("Wrong H264 lvl_major level value: %u, overriding with 5",
+				lvl_major);
+			lvl_major = 5;
+		}
+
+		/*
+		 * Calculate the maximum number of reference pictures
+		 * required based on level.
+		 */
+		*max_ref_pic_num = h264_max_dpb_mbs[lvl_major][lvl_minor] /
+			(pic_width_mb * pic_height_mb);
+		if (*max_ref_pic_num > 16)
+			*max_ref_pic_num = 16;
+	}
+
+	/* Return success. */
+	return IMG_SUCCESS;
+}
+
+#ifdef HAS_HEVC
+/*
+ * @Function              vdecddutils_ref_pic_hevc_get_maxnum
+ */
+int vdecddutils_ref_pic_hevc_get_maxnum(const struct vdec_comsequ_hdrinfo *comseq_hdrinfo,
+					unsigned int *max_ref_picnum)
+{
+	static const unsigned int HEVC_LEVEL_IDC_MIN = 30;
+	static const unsigned int HEVC_LEVEL_IDC_MAX = 186;
+
+	static const unsigned int
+		max_luma_ps_list[HEVC_LEVEL_MAJOR_NUM][HEVC_LEVEL_MINOR_NUM] = {
+		/* level: 1.0       1.1       1.2       */
+		{ 36864,    0,        0,        },
+		/* level: 2.0       2.1       2.2       */
+		{ 122880,   245760,   0,        },
+		/* level: 3.0       3.1       3.2       */
+		{ 552960,   983040,   0,        },
+		/* level: 4.0       4.1       4.2       */
+		{ 2228224,  2228224,  0,        },
+		/* level: 5.0       5.1       5.2       */
+		{ 8912896,  8912896,  8912896,  },
+		/* level: 6.0       6.1       6.2       */
+		{ 35651584, 35651584, 35651584, }
+	};
+
+	/* ITU-T H.265 04/2013 A.4.1 */
+
+	const unsigned int max_dpb_picbuf = 6;
+
+	/* this is rounded to whole Ctbs */
+	unsigned int pic_size_in_samples_Y = comseq_hdrinfo->frame_size.height *
+		comseq_hdrinfo->frame_size.width;
+
+	signed char level_maj, level_min;
+	unsigned int max_luma_ps;
+
+	/* some error resilience */
+	if (comseq_hdrinfo->codec_level > HEVC_LEVEL_IDC_MAX ||
+	    comseq_hdrinfo->codec_level < HEVC_LEVEL_IDC_MIN) {
+		pr_warn("HEVC Codec level out of range: %u, falling back to %u",
+			comseq_hdrinfo->codec_level,
+			comseq_hdrinfo->min_pict_buf_num);
+
+		*max_ref_picnum = comseq_hdrinfo->min_pict_buf_num;
+		return IMG_SUCCESS;
+	}
+
+	level_maj = comseq_hdrinfo->codec_level / 30;
+	level_min = (comseq_hdrinfo->codec_level % 30) / 3;
+
+	if (level_maj > 0 && level_maj <= HEVC_LEVEL_MAJOR_NUM &&
+	    level_min >= 0 && level_min < HEVC_LEVEL_MINOR_NUM) {
+		max_luma_ps = max_luma_ps_list[level_maj - 1][level_min];
+	} else {
+		pr_err("%s: Invalid parameters\n", __func__);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (max_luma_ps == 0) {
+		pr_err("Wrong HEVC level value: %u.%u (general_level_idc: %u)",
+		       level_maj, level_min, comseq_hdrinfo->codec_level);
+
+		return IMG_ERROR_VALUE_OUT_OF_RANGE;
+	}
+
+	if (max_luma_ps < pic_size_in_samples_Y)
+		pr_warn("HEVC PicSizeInSamplesY too large for level (%u > %u)",
+			pic_size_in_samples_Y, max_luma_ps);
+
+	if (pic_size_in_samples_Y <= (max_luma_ps >> 2))
+		*max_ref_picnum = vdec_size_min(4 * max_dpb_picbuf, 16);
+	else if (pic_size_in_samples_Y <= (max_luma_ps >> 1))
+		*max_ref_picnum = vdec_size_min(2 * max_dpb_picbuf, 16);
+	else if (pic_size_in_samples_Y <= ((3 * max_luma_ps) >> 2))
+		*max_ref_picnum = vdec_size_min((4 * max_dpb_picbuf) / 3, 16);
+	else
+		*max_ref_picnum = max_dpb_picbuf;
+
+	/* Return success. */
+	return IMG_SUCCESS;
+}
+#endif
+
+#ifdef HAS_JPEG
+static int vdecddutils_ref_pic_jpeg_get_maxnum(const struct vdec_comsequ_hdrinfo *comseq_hdrinfo,
+					       unsigned int *max_ref_picnum)
+{
+	/* No reference frames for JPEG. */
+	*max_ref_picnum = 0;
+
+	/* Return success. */
+	return IMG_SUCCESS;
+}
+#endif
+
+/*
+ * The array of pointers to functions calculating the maximum number
+ * of reference pictures required for each supported video standard.
+ * NOTE: The table is indexed by #VDEC_eVidStd enum values.
+ */
+static fn_ref_pic_get_max_num ref_pic_get_maxnum[VDEC_STD_MAX - 1] = {
+	NULL,
+	NULL,
+	NULL,
+	vdecddutils_ref_pic_h264_get_maxnum,
+	NULL,
+	NULL,
+	NULL,
+#ifdef HAS_JPEG
+	vdecddutils_ref_pic_jpeg_get_maxnum,
+#else
+	NULL,
+#endif
+	NULL,
+	NULL,
+	NULL,
+#ifdef HAS_HEVC
+	vdecddutils_ref_pic_hevc_get_maxnum
+#else
+	NULL
+#endif
+};
+
+int
+vdecddutils_ref_pict_get_maxnum(const struct vdec_str_configdata *str_cfg_data,
+				const struct vdec_comsequ_hdrinfo *comseq_hdr_info,
+				unsigned int *num_picts)
+{
+	int ret = IMG_SUCCESS;
+
+	/* Validate input params. */
+	if (str_cfg_data->vid_std == VDEC_STD_UNDEFINED || str_cfg_data->vid_std >= VDEC_STD_MAX)
+		return IMG_ERROR_VALUE_OUT_OF_RANGE;
+
+	/* Call the function related to the provided video standard. */
+	ret = ref_pic_get_maxnum[str_cfg_data->vid_std - 1](comseq_hdr_info,
+			num_picts);
+	if (ret != IMG_SUCCESS)
+		pr_warn("[USERSID=0x%08X] Failed to get number of reference pictures",
+			str_cfg_data->user_str_id);
+
+	/*
+	 * For non-conformant stream use the
+	 * max(*pui32NumPicts,comseq_hdrinfo->ui32MinPicBufNum)
+	 */
+	if (*num_picts < comseq_hdr_info->min_pict_buf_num)
+		*num_picts = comseq_hdr_info->min_pict_buf_num;
+
+	/*
+	 * Increase for MVC: mvcScaleFactor = 2 (H.10.2) and additional pictures
+	 * for a StoreInterViewOnlyRef case (C.4.5.2)
+	 */
+	if (comseq_hdr_info->num_views > 1) {
+		*num_picts *= 2;
+		*num_picts += comseq_hdr_info->num_views - 1;
+	}
+
+	return ret;
+}
+
+static void vdecddutils_update_rend_pictsize(struct vdec_pict_size pict_size,
+					     struct vdec_pict_size *rend_pict_size)
+{
+	if (rend_pict_size->width == 0) {
+		rend_pict_size->width = pict_size.width;
+	} else {
+		/* Take the smallest resolution supported by all the planes */
+		rend_pict_size->width = (pict_size.width <
+			rend_pict_size->width) ?
+			pict_size.width :
+			rend_pict_size->width;
+	}
+	if (rend_pict_size->height == 0) {
+		rend_pict_size->height = pict_size.height;
+	} else {
+		/* Take the smallest resolution supported by all the planes. */
+		rend_pict_size->height = (pict_size.height <
+			rend_pict_size->height) ?
+			pict_size.height :
+			rend_pict_size->height;
+	}
+}
+
+int vdecddutils_convert_buffer_config(const struct vdec_str_configdata *str_cfg_data,
+				      const struct vdec_pict_bufconfig *pict_bufcfg,
+				      struct vdec_pict_rendinfo *pict_rend_info)
+{
+	const struct pixel_pixinfo      *pix_info;
+	struct  img_pixfmt_desc pixfmt;
+	unsigned int i;
+	unsigned int total_vert_samples = 0;
+	unsigned int vert_samples[IMG_MAX_NUM_PLANES];
+	unsigned int plane_size = 0;
+	unsigned int plane_offset = 0;
+	struct vdec_pict_size pict_size;
+
+	/* Validate inputs. */
+	VDEC_ASSERT(str_cfg_data);
+	VDEC_ASSERT(pict_bufcfg);
+	VDEC_ASSERT(pict_rend_info);
+
+	/* Reset picture buffer allocation data. */
+	memset(pict_rend_info, 0x0, sizeof(*pict_rend_info));
+
+	pr_debug("%s picture buffer pixel_fmt = %d\n", __func__, pict_bufcfg->pixel_fmt);
+	/* Get pixel format info for regular pixel formats... */
+	if (pict_bufcfg->pixel_fmt < IMG_PIXFMT_ARBPLANAR8) {
+		pix_info = pixel_get_pixinfo(pict_bufcfg->pixel_fmt);
+		pixel_yuv_get_desc((struct pixel_pixinfo *)pix_info, &pixfmt);
+	} else {
+		pixel_get_fmt_desc(pict_bufcfg->pixel_fmt, &pixfmt);
+	}
+
+	/*
+	 * Construct the render region information from the picture
+	 * buffer configuration.
+	 */
+	for (i = 0; i < IMG_MAX_NUM_PLANES; i++) {
+		if (pixfmt.planes[i]) {
+			unsigned int plane_align = VDEC_VXD_PICTBUF_ALIGNMENT;
+
+			/*
+			 * Determine the offset (in bytes) to this plane.
+			 * This is zero for the first (luma) plane and at the
+			 * end of the previous plane for all subsequent planes.
+			 */
+			plane_offset = plane_offset + plane_size;
+
+			/*
+			 * Calculate the minimum number of vertical samples
+			 * for this plane.
+			 */
+			vert_samples[i] =
+				((pict_bufcfg->coded_height +
+				pixfmt.v_denom - 1) / pixfmt.v_denom) *
+				pixfmt.v_numer[i];
+
+			/*
+			 * Calculate the mimimum plane size from the stride and
+			 * decode picture height. Packed buffers have the luma
+			 * and chroma exactly adjacent and consequently the
+			 * chroma plane offset is equal to this plane size.
+			 */
+			plane_size = pict_bufcfg->stride[i] * vert_samples[i];
+			plane_size = ALIGN(plane_size, plane_align);
+
+			if (!pict_bufcfg->packed && pict_bufcfg->chroma_offset[i]) {
+				unsigned int max_plane_size;
+
+				max_plane_size =
+					pict_bufcfg->chroma_offset[i] - plane_offset;
+
+				if (plane_size > max_plane_size) {
+					pr_err("Chroma offset [%d bytes] is not large enough to fit minimum plane data [%d bytes] at offset [%d]",
+					       pict_bufcfg->chroma_offset[i],
+					       plane_size, plane_offset);
+					return IMG_ERROR_INVALID_PARAMETERS;
+				}
+
+				plane_size = max_plane_size;
+
+				vert_samples[i] = plane_size /
+					pict_bufcfg->stride[i];
+			} else {
+				if (pict_bufcfg->chroma_offset[i] && (plane_offset + plane_size) !=
+				    pict_bufcfg->chroma_offset[i]) {
+					pr_err("Chroma offset specified [%d bytes] should match that required for plane size calculated from stride and height [%d bytes]",
+					       pict_bufcfg->chroma_offset[i],
+					       plane_offset + plane_size);
+					return IMG_ERROR_INVALID_PARAMETERS;
+				}
+			}
+
+			pict_rend_info->plane_info[i].offset = plane_offset;
+			pict_rend_info->plane_info[i].stride =
+				pict_bufcfg->stride[i];
+			pict_rend_info->plane_info[i].size = plane_size;
+
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("VDECDDUTILS_ConvertBufferConfig() plane %d stride %u size %u offset %u",
+				i, pict_rend_info->plane_info[i].stride,
+				pict_rend_info->plane_info[i].size,
+				pict_rend_info->plane_info[i].offset);
+#endif
+
+			pict_rend_info->rendered_size +=
+				pict_rend_info->plane_info[i].size;
+
+			total_vert_samples += vert_samples[i];
+
+			/* Calculate the render region maximum picture size. */
+			pict_size.width = (pict_rend_info->plane_info[i].stride *
+					   pixfmt.bop_denom) / pixfmt.bop_numer[i];
+			pict_size.height = (vert_samples[i] * pixfmt.v_denom) / pixfmt.v_numer[i];
+			vdecddutils_update_rend_pictsize(pict_size,
+							 &pict_rend_info->rend_pict_size);
+		}
+	}
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("VDECDDUTILS_ConvertBufferConfig() total required %u (inc. alignment for addressing/tiling) vs. buffer %u",
+		pict_rend_info->rendered_size, pict_bufcfg->buf_size);
+#endif
+
+	/* Ensure that the buffer size is large enough to hold the data */
+	if (pict_bufcfg->buf_size < pict_rend_info->rendered_size) {
+		pr_err("Buffer size [%d bytes] should be at least as large as rendered data (inc. any enforced gap between planes) [%d bytes]",
+		       pict_bufcfg->buf_size,
+		       pict_rend_info->rendered_size);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Whole buffer should be marked as rendered region */
+	pict_rend_info->rendered_size = pict_bufcfg->buf_size;
+	/* Use the actual stride alignment */
+	pict_rend_info->stride_alignment = pict_bufcfg->stride_alignment;
+
+	return IMG_SUCCESS;
+}
+
+static unsigned char vdecddutils_is_secondary_op_required(const struct vdec_comsequ_hdrinfo
+	*comseq_hdr_info,
+	const struct vdec_str_opconfig
+	*op_cfg)
+{
+	unsigned char result = TRUE;
+
+	if (!op_cfg->force_oold &&
+	    !comseq_hdr_info->post_processing &&
+	    comseq_hdr_info->pixel_info.chroma_fmt_idc ==
+	    op_cfg->pixel_info.chroma_fmt_idc &&
+	    comseq_hdr_info->pixel_info.bitdepth_y ==
+	    op_cfg->pixel_info.bitdepth_y &&
+	    comseq_hdr_info->pixel_info.bitdepth_c ==
+	    op_cfg->pixel_info.bitdepth_c)
+		/*
+		 * The secondary output is not required (if we have it we will
+		 * not use it for transformation (e.g. scaling. rotating or
+		 * up/down-sampling).
+		 */
+		result = FALSE;
+
+	return result;
+}
+
+int vdecddutils_get_minrequired_numpicts(const struct vdec_str_configdata *str_cfg_data,
+					 const struct vdec_comsequ_hdrinfo *comseq_hdr_info,
+					 const struct vdec_str_opconfig *op_cfg,
+					 unsigned int *num_picts)
+{
+	int ret;
+	unsigned int max_held_picnum;
+
+	/* If any operation requiring internal buffers is to be applied... */
+	if (vdecddutils_is_secondary_op_required(comseq_hdr_info, op_cfg)) {
+		/*
+		 * Reference picture buffers will be allocated internally,
+		 * but there may be a number of picture buffers to which
+		 * out-of-display-order pictures will be decoded. These
+		 * buffers need to be allocated externally, so there's a
+		 * need to calculate the number of out-of-(display)-order
+		 * pictures required for the provided video standard.
+		 */
+		ret = vdecddutils_ref_pict_get_maxnum(str_cfg_data, comseq_hdr_info,
+						      &max_held_picnum);
+		if (ret != IMG_SUCCESS)
+			return ret;
+	} else {
+		/*
+		 * All the reference picture buffers have to be allocated
+		 * externally, so there's a need to calculate the number of
+		 * reference picture buffers required for the provided video
+		 * standard.
+		 */
+		ret = vdecddutils_ref_pict_get_maxnum(str_cfg_data, comseq_hdr_info,
+						      &max_held_picnum);
+		if (ret != IMG_SUCCESS)
+			return ret;
+	}
+
+	/*
+	 * Calculate the number of picture buffers required as the maximum
+	 * number of picture buffers to be held onto by the driver plus the
+	 * current picture buffer.
+	 */
+	*num_picts = max_held_picnum +
+		(comseq_hdr_info->interlaced_frames ? 2 : 1);
+
+	return IMG_SUCCESS;
+}
+
+static void vdecddutils_get_codedsize(const struct vdec_pict_rend_config *pict_rend_cfg,
+				      struct vdec_pict_size *decoded_pict_size)
+{
+	decoded_pict_size->width = pict_rend_cfg->coded_pict_size.width;
+	decoded_pict_size->height = pict_rend_cfg->coded_pict_size.height;
+}
+
+static unsigned char vdecddutils_is_packed(const struct vdec_pict_rendinfo *pict_rend_info,
+					   const struct vdec_pict_rend_config *pict_rend_cfg)
+{
+	unsigned char packed = TRUE;
+	unsigned int pict_buf_align;
+
+	/* Validate inputs. */
+	VDEC_ASSERT(pict_rend_info);
+	VDEC_ASSERT(pict_rend_cfg);
+
+	pict_buf_align = VDEC_VXD_PICTBUF_ALIGNMENT;
+
+	if (pict_rend_info->plane_info[VDEC_PLANE_VIDEO_Y].size !=
+		pict_rend_info->plane_info[VDEC_PLANE_VIDEO_UV].offset) {
+		/* Planes that are not adjacent cannot be packed */
+		packed = FALSE;
+	} else if (!is_packedbuf_chroma_aligned(pict_rend_info->plane_info
+				[VDEC_PLANE_VIDEO_UV].offset,
+				VDEC_PLANE_VIDEO_Y,
+				pict_buf_align)) {
+		/* Chroma plane must be aligned for packed buffers. */
+		VDEC_ASSERT(pict_rend_info->plane_info[VDEC_PLANE_VIDEO_Y].size ==
+			pict_rend_info->plane_info[VDEC_PLANE_VIDEO_UV].offset);
+		packed = FALSE;
+	}
+
+	return packed;
+}
+
+static int vdecddutils_get_stride
+	(const struct vdec_str_configdata *str_cfg_data,
+	const struct vdec_pict_rend_config *pict_rend_cfg,
+	unsigned int vert_samples, unsigned int *h_stride,
+	enum vdec_color_planes color_planes)
+{
+	unsigned int hw_h_stride = *h_stride;
+
+	/*
+	 * If extended strides are to be used or indexed strides failed,
+	 * make extended stride alignment.
+	 */
+	hw_h_stride = ALIGN(hw_h_stride,
+			    pict_rend_cfg->stride_alignment > 0 ?
+			    pict_rend_cfg->stride_alignment :
+			    VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT);
+
+	/* A zero-value indicates unsupported stride */
+	if (hw_h_stride == 0)
+		/* No valid stride found */
+		return IMG_ERROR_NOT_SUPPORTED;
+
+	*h_stride = hw_h_stride;
+
+	return IMG_SUCCESS;
+}
+
+static int vdecddutils_get_render_info(const struct vdec_str_configdata *str_cfg_data,
+				       const struct vdec_pict_rend_config *pict_rend_cfg,
+				       const struct pixel_pixinfo *pix_info,
+				       struct vdec_pict_rendinfo *pict_rend_info)
+{
+	unsigned int i;
+	struct img_pixfmt_desc pixfmt;
+	struct vdec_pict_size coded_pict_size;
+	unsigned char single_stride = FALSE;
+	unsigned int vert_sample[IMG_MAX_NUM_PLANES] = {0};
+	unsigned int total_vert_samples;
+	unsigned int largest_stride;
+	unsigned int result;
+
+	/* Reset the output structure. */
+	memset(pict_rend_info, 0, sizeof(*pict_rend_info));
+
+	/* Ensure that the coded sizes are in whole macroblocks. */
+	if ((pict_rend_cfg->coded_pict_size.width  &
+		(VDEC_MB_DIMENSION - 1)) != 0 ||
+		(pict_rend_cfg->coded_pict_size.height &
+		(VDEC_MB_DIMENSION - 1)) != 0) {
+		pr_err("Invalid render configuration coded picture size [%d x %d]. It should be a whole number of MBs in each dimension",
+		       pict_rend_cfg->coded_pict_size.width,
+		       pict_rend_cfg->coded_pict_size.height);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Check if the stride alignment is multiple of default. */
+	if ((pict_rend_cfg->stride_alignment &
+		(VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT - 1)) != 0) {
+		pr_err("Invalid stride alignment %d used. It should be multiple of %d.",
+		       pict_rend_cfg->stride_alignment,
+		       VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Get pixel format info for regular pixel formats... */
+	if (pix_info->pixfmt < IMG_PIXFMT_ARBPLANAR8)
+		pixel_yuv_get_desc((struct pixel_pixinfo *)pix_info, &pixfmt);
+	else
+		pixel_get_fmt_desc(pix_info->pixfmt, &pixfmt);
+
+	/* Get the coded size for the appropriate orientation */
+	vdecddutils_get_codedsize(pict_rend_cfg, &coded_pict_size);
+
+	/*
+	 * Calculate the hardware (inc. constraints) strides and
+	 * number of vertical samples for each plane.
+	 */
+	total_vert_samples = 0;
+	largest_stride = 0;
+	for (i = 0; i < IMG_MAX_NUM_PLANES; i++) {
+		if (pixfmt.planes[i]) {
+			unsigned int h_stride;
+
+			/* Horizontal stride must be for a multiple of BOPs. */
+			h_stride = ((coded_pict_size.width +
+				pixfmt.bop_denom - 1) /
+				pixfmt.bop_denom) * pixfmt.bop_numer[i];
+
+			/*
+			 * Vertical only has to satisfy whole pixel of
+			 * samples.
+			 */
+			vert_sample[i] = ((coded_pict_size.height +
+				pixfmt.v_denom - 1) /
+				pixfmt.v_denom) * pixfmt.v_numer[i];
+
+			/*
+			 * Obtain a horizontal stride supported by the hardware
+			 * (inc. constraints).
+			 */
+			result = vdecddutils_get_stride(str_cfg_data, pict_rend_cfg, vert_sample[i],
+							&h_stride, (enum vdec_color_planes)i);
+			if (result != IMG_SUCCESS) {
+				VDEC_ASSERT(0);
+				pr_err("No valid VXD stride found for picture with decoded dimensions [%d x %d] and min stride [%d]",
+				       coded_pict_size.width, coded_pict_size.height, h_stride);
+				return result;
+			}
+
+			pict_rend_info->plane_info[i].stride = h_stride;
+			if (i == VDEC_PLANE_VIDEO_UV && (str_cfg_data->vid_std == VDEC_STD_H264 ||
+							 str_cfg_data->vid_std == VDEC_STD_HEVC)) {
+				struct pixel_pixinfo *info =
+					pixel_get_pixinfo(pix_info->pixfmt);
+				VDEC_ASSERT(PIXEL_FORMAT_INVALID !=
+					info->chroma_fmt_idc);
+			}
+
+			total_vert_samples += vert_sample[i];
+			if (h_stride > largest_stride)
+				largest_stride = h_stride;
+		}
+	}
+	pict_rend_info->stride_alignment =
+		pict_rend_cfg->stride_alignment > 0 ?
+		pict_rend_cfg->stride_alignment :
+		VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT;
+
+	if (pict_rend_cfg->packed)
+		single_stride = TRUE;
+
+#ifdef HAS_JPEG
+	/* JPEG hardware uses a single (luma) stride for all planes. */
+	if (str_cfg_data->vid_std == VDEC_STD_JPEG) {
+		single_stride = true;
+
+		/* Luma should be largest for this to be used for all planes. */
+		VDEC_ASSERT(largest_stride ==
+			pict_rend_info->plane_info[VDEC_PLANE_VIDEO_Y].stride);
+	}
+#endif
+
+	/* Calculate plane sizes. */
+	for (i = 0; i < IMG_MAX_NUM_PLANES; i++) {
+		if (pixfmt.planes[i]) {
+			struct vdec_pict_size pict_size;
+			unsigned int vert_samples = vert_sample[i];
+			unsigned int plane_align = VDEC_VXD_PICTBUF_ALIGNMENT;
+
+			if (single_stride)
+				pict_rend_info->plane_info[i].stride =
+					largest_stride;
+
+			pict_rend_info->plane_info[i].size =
+				pict_rend_info->plane_info[i].stride *
+				vert_samples;
+			pict_rend_info->plane_info[i].size =
+				ALIGN(pict_rend_info->plane_info[i].size, plane_align);
+			/*
+			 * Ensure that the total buffer rendered size is
+			 * rounded-up to the picture buffer alignment so that
+			 * this plane (within this single buffer) can be
+			 * correctly addressed by the hardware at this byte
+			 * offset.
+			 */
+			if (i == 1 && pict_rend_cfg->packed)
+				/*
+				 * Packed buffers must have chroma plane
+				 * already aligned since this was factored
+				 * into the stride/size calculation.
+				 */
+				VDEC_ASSERT(pict_rend_info->rendered_size ==
+					    ALIGN(pict_rend_info->rendered_size, plane_align));
+
+			pict_rend_info->plane_info[i].offset = pict_rend_info->rendered_size;
+
+			/* Update the total buffer size (inc. this plane). */
+			pict_rend_info->rendered_size +=
+				pict_rend_info->plane_info[i].size;
+
+			/*
+			 * Update the maximum render picture size supported
+			 * by all planes of this buffer.
+			 */
+			pict_size.width = (pict_rend_info->plane_info[i].stride *
+				pixfmt.bop_denom) / pixfmt.bop_numer[i];
+
+			pict_size.height = (vert_sample[i] * pixfmt.v_denom) / pixfmt.v_numer[i];
+
+			vdecddutils_update_rend_pictsize(pict_size,
+							 &pict_rend_info->rend_pict_size);
+
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("vdecddutils_GetRenderInfo() plane %d stride %u size %u offset %u",
+				i, pict_rend_info->plane_info[i].stride,
+				pict_rend_info->plane_info[i].size,
+				pict_rend_info->plane_info[i].offset);
+#endif
+		}
+	}
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("vdecddutils_GetRenderInfo() total %u (inc. alignment for addressing/tiling)",
+		pict_rend_info->rendered_size);
+#endif
+
+	return IMG_SUCCESS;
+}
+
+int vdecddutils_pictbuf_getconfig(const struct vdec_str_configdata *str_cfg_data,
+				  const struct vdec_pict_rend_config *pict_rend_cfg,
+				  const struct vdec_str_opconfig *str_opcfg,
+				  struct vdec_pict_bufconfig *pict_bufcfg)
+{
+	struct vdec_pict_rendinfo disp_pict_rendinfo;
+	struct vdec_pict_size coded_pict_size;
+	unsigned int ret, i;
+	unsigned int size0, size1;
+
+	/* Validate inputs. */
+	VDEC_ASSERT(str_cfg_data);
+	VDEC_ASSERT(pict_rend_cfg);
+	VDEC_ASSERT(str_opcfg);
+	VDEC_ASSERT(pict_bufcfg);
+
+	/* Clear the picture buffer config before populating */
+	memset(pict_bufcfg, 0, sizeof(struct vdec_pict_bufconfig));
+
+	/* Determine the rounded-up coded sizes (compatible with hardware) */
+	ret = vdecddutils_get_render_info(str_cfg_data,
+					  pict_rend_cfg,
+					  &str_opcfg->pixel_info,
+					  &disp_pict_rendinfo);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	/* Get the coded size for the appropriate orientation */
+	vdecddutils_get_codedsize(pict_rend_cfg, &coded_pict_size);
+
+	pict_bufcfg->coded_width = coded_pict_size.width;
+	pict_bufcfg->coded_height = coded_pict_size.height;
+
+	/*
+	 * Use the luma stride for all planes in buffer.
+	 * Additional chroma stride may be needed for other pixel formats.
+	 */
+	for (i = 0; i < VDEC_PLANE_MAX; i++)
+		pict_bufcfg->stride[i] = disp_pict_rendinfo.plane_info[i].stride;
+
+	/*
+	 * Pixel information is taken from that
+	 * specified for display.
+	 */
+	pict_bufcfg->pixel_fmt = str_opcfg->pixel_info.pixfmt;
+	pr_debug("picture buffer pixel_fmt = %d\n", pict_bufcfg->pixel_fmt);
+
+	/* Tiling scheme is taken from render configuration */
+	pict_bufcfg->byte_interleave = pict_rend_cfg->byte_interleave;
+	pr_debug("picture buffer byte_interleave = %d\n", pict_bufcfg->byte_interleave);
+	/* Stride alignment */
+	pict_bufcfg->stride_alignment = pict_rend_cfg->stride_alignment > 0 ?
+		pict_rend_cfg->stride_alignment : VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT;
+
+	pr_debug("picture buffer stride_alignment = %d\n", pict_bufcfg->stride_alignment);
+	/* Chroma offset taken as calculated for render configuration. */
+	pict_bufcfg->chroma_offset[0] = disp_pict_rendinfo.plane_info[VDEC_PLANE_VIDEO_UV].offset;
+	pict_bufcfg->chroma_offset[1] = disp_pict_rendinfo.plane_info[VDEC_PLANE_VIDEO_V].offset;
+
+	if (pict_rend_cfg->packed && str_opcfg->pixel_info.num_planes > 1) {
+		pict_bufcfg->packed = vdecddutils_is_packed(&disp_pict_rendinfo, pict_rend_cfg);
+		if (!pict_bufcfg->packed) {
+			/* Report if unable to meet request to pack. */
+			pr_err("Request for packed buffer could not be met");
+			return IMG_ERROR_NOT_SUPPORTED;
+		}
+
+		size0 = ALIGN(pict_bufcfg->chroma_offset[0], VDEC_VXD_PICTBUF_ALIGNMENT);
+		size1 = ALIGN(pict_bufcfg->chroma_offset[1], VDEC_VXD_PICTBUF_ALIGNMENT);
+
+		if (pict_bufcfg->chroma_offset[0] != size0 ||
+		    pict_bufcfg->chroma_offset[1] != size1)  {
+			pr_err("Chroma plane could not be located on a %d byte boundary (investigate stride calculations)",
+			       VDEC_VXD_PICTBUF_ALIGNMENT);
+			return IMG_ERROR_NOT_SUPPORTED;
+		}
+	} else {
+		pict_bufcfg->packed = FALSE;
+	}
+
+	pict_bufcfg->buf_size = disp_pict_rendinfo.rendered_size;
+
+	/* Return success */
+	return IMG_SUCCESS;
+}
+
+int vdecddutils_get_display_region(const struct vdec_pict_size *coded_size,
+				   const struct vdec_rect   *orig_disp_region,
+				   struct vdec_rect *disp_region)
+{
+	int ret = IMG_SUCCESS;
+
+	/* Validate inputs. */
+	VDEC_ASSERT(coded_size);
+	VDEC_ASSERT(orig_disp_region);
+	VDEC_ASSERT(disp_region);
+	if (!coded_size || !orig_disp_region || !disp_region)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/*
+	 * In the simplest case the display region is the same as
+	 * that defined in the bitstream.
+	 */
+	*disp_region = *orig_disp_region;
+
+	if (orig_disp_region->height == 0 || orig_disp_region->width == 0 ||
+	    coded_size->height == 0 || coded_size->width == 0) {
+		pr_err("Invalid params to calculate display region:");
+		pr_err("Display Size: [%d,%d]", orig_disp_region->width, orig_disp_region->height);
+		pr_err("Coded Size  : [%d,%d]", coded_size->width, coded_size->height);
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	return ret;
+}
+
+int vdecddutils_pictbuf_getinfo(const struct vdec_str_configdata *str_cfg_data,
+				const struct vdec_pict_rend_config *pict_rend_cfg,
+				const struct vdec_str_opconfig *str_op_cfg,
+				struct vdec_pict_rendinfo *pict_rend_info)
+{
+	unsigned int ret;
+
+	/* Validate inputs. */
+	VDEC_ASSERT(str_cfg_data);
+	VDEC_ASSERT(pict_rend_cfg);
+	VDEC_ASSERT(str_op_cfg);
+	VDEC_ASSERT(pict_rend_info);
+
+	ret = vdecddutils_get_render_info(str_cfg_data, pict_rend_cfg,
+					  &str_op_cfg->pixel_info,
+					  pict_rend_info);
+	VDEC_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	return IMG_SUCCESS;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_utils.c b/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_utils.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_utils.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_utils.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VXD Decoder device driver utility functions implementation
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "bspp.h"
+#include "vdecdd_utils.h"
+
+/*
+ * @Function              VDECDDUTILS_FreeStrUnit
+ */
+int vdecddutils_free_strunit(struct vdecdd_str_unit *str_unit)
+{
+	struct bspp_bitstr_seg *bstr_seg;
+
+	/* Loop over bit stream segments */
+	bstr_seg = (struct bspp_bitstr_seg *)lst_removehead(&str_unit->bstr_seg_list);
+	while (bstr_seg) {
+		/* Free segment. */
+		kfree(bstr_seg);
+
+		/* Get next segment. */
+		bstr_seg = (struct bspp_bitstr_seg *)lst_removehead(&str_unit->bstr_seg_list);
+	}
+
+	/* Free the sequence header */
+	if (str_unit->seq_hdr_info) {
+		str_unit->seq_hdr_info->ref_count--;
+		if (str_unit->seq_hdr_info->ref_count == 0) {
+			kfree(str_unit->seq_hdr_info);
+			str_unit->seq_hdr_info = NULL;
+		}
+	}
+
+	/* Free the picture header... */
+	if (str_unit->pict_hdr_info) {
+		kfree(str_unit->pict_hdr_info->pict_sgm_data.pic_data);
+		str_unit->pict_hdr_info->pict_sgm_data.pic_data = NULL;
+
+		kfree(str_unit->pict_hdr_info);
+		str_unit->pict_hdr_info = NULL;
+	}
+
+	/* Free stream unit. */
+	kfree(str_unit);
+	str_unit = NULL;
+
+	/* Return success */
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function: VDECDDUTILS_CreateStrUnit
+ * @Description: this function allocate a structure for a complete data unit
+ */
+int vdecddutils_create_strunit(struct vdecdd_str_unit **str_unit_handle,
+			       struct lst_t *bs_list)
+{
+	struct vdecdd_str_unit *str_unit;
+	struct bspp_bitstr_seg *bstr_seg;
+
+	str_unit = kzalloc(sizeof(*str_unit), GFP_KERNEL);
+	VDEC_ASSERT(str_unit);
+	if (!str_unit)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	if (bs_list) {
+		/* copy BS list to this list */
+		lst_init(&str_unit->bstr_seg_list);
+		for (bstr_seg = lst_first(bs_list); bstr_seg;
+			bstr_seg = lst_first(bs_list)) {
+			bstr_seg = lst_removehead(bs_list);
+			lst_add(&str_unit->bstr_seg_list, bstr_seg);
+		}
+	}
+
+	*str_unit_handle = str_unit;
+
+	return IMG_SUCCESS;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_utils.h b/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_utils.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_utils.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vdecdd_utils.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD Decoder device driver utility header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef __VDECDD_UTILS_H__
+#define __VDECDD_UTILS_H__
+
+#include "img_errors.h"
+#include "vdecdd_defs.h"
+
+/* The picture buffer alignment (in bytes) for VXD. */
+#define VDEC_VXD_PICTBUF_ALIGNMENT              (64)
+/* The buffer alignment (in bytes) for VXD. */
+#define VDEC_VXD_BUF_ALIGNMENT                  (4096)
+/* The extended stride alignment for VXD.  */
+#define VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT   (64)
+/* Macroblock dimension (width and height) in pixels. */
+#define VDEC_MB_DIMENSION                       (16)
+
+static inline unsigned int vdec_size_min(unsigned int a, unsigned int b)
+{
+	return a <= b ? a : b;
+}
+
+static inline unsigned char vdec_size_lt(struct vdec_pict_size sa, struct vdec_pict_size sb)
+{
+	return (sa.width < sb.width && sa.height <= sb.height) ||
+	       (sa.width <= sb.width && sa.height < sb.height);
+}
+
+static inline unsigned char vdec_size_ge(struct vdec_pict_size sa, struct vdec_pict_size sb)
+{
+	return sa.width >= sb.width && sa.height >= sb.height;
+}
+
+static inline unsigned char vdec_size_ne(struct vdec_pict_size sa, struct vdec_pict_size sb)
+{
+	return sa.width != sb.width || sa.height != sb.height;
+}
+
+static inline unsigned char vdec_size_nz(struct vdec_pict_size sa)
+{
+	return sa.width != 0 && sa.height != 0;
+}
+
+int vdecddutils_free_strunit(struct vdecdd_str_unit *str_unit);
+
+int vdecddutils_create_strunit(struct vdecdd_str_unit **str_unit_handle,
+			       struct lst_t *bs_list);
+
+int vdecddutils_ref_pict_get_maxnum(const struct vdec_str_configdata *str_cfg_data,
+				    const struct vdec_comsequ_hdrinfo *comseq_hdr_info,
+				    unsigned int *num_picts);
+
+int vdecddutils_get_minrequired_numpicts(const struct vdec_str_configdata *str_cfg_data,
+					 const struct vdec_comsequ_hdrinfo *comseq_hdr_info,
+					 const struct vdec_str_opconfig *op_cfg,
+					 unsigned int *num_picts);
+
+int vdecddutils_pictbuf_getconfig(const struct vdec_str_configdata *str_cfg_data,
+				  const struct vdec_pict_rend_config *pict_rend_cfg,
+				  const struct vdec_str_opconfig *str_opcfg,
+				  struct vdec_pict_bufconfig *pict_bufcfg);
+
+int vdecddutils_pictbuf_getinfo(const struct vdec_str_configdata *str_cfg_data,
+				const struct vdec_pict_rend_config *pict_rend_cfg,
+				const struct vdec_str_opconfig *str_opcfg,
+				struct vdec_pict_rendinfo *pict_rend_info);
+
+int vdecddutils_convert_buffer_config(const struct vdec_str_configdata *str_cfg_data,
+				      const struct vdec_pict_bufconfig *pict_bufcfg,
+				      struct vdec_pict_rendinfo *pict_rend_info);
+
+int vdecddutils_get_display_region(const struct vdec_pict_size *coded_size,
+				   const struct vdec_rect *orig_disp_region,
+				   struct vdec_rect *disp_region);
+
+void vdecddutils_buf_vxd_adjust_size(unsigned int *buf_size);
+
+int vdecddutils_ref_pic_hevc_get_maxnum(const struct vdec_comsequ_hdrinfo *comseq_hdrinfo,
+					unsigned int *max_ref_picnum);
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vdec_defs.h b/drivers/media/platform/img/vxe-vxd/decoder/vdec_defs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vdec_defs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vdec_defs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,555 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD Decoder common header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef __VDEC_DEFS_H__
+#define __VDEC_DEFS_H__
+
+#include "img_mem.h"
+#include "img_pixfmts.h"
+#ifdef HAS_JPEG
+#include "jpegfw_data.h"
+#endif
+#include "pixel_api.h"
+#include "vdecfw_shared.h"
+
+#define VDEC_MAX_PANSCAN_WINDOWS        4
+#define VDEC_MB_DIMENSION               (16)
+
+#define MAX_PICS_IN_SYSTEM      (8)
+#define SEQUENCE_SLOTS          (8)
+#define PPS_SLOTS               (8)
+/* Only for HEVC */
+#define VPS_SLOTS               (16)
+#define MAX_VPSS                (MAX_PICS_IN_SYSTEM + VPS_SLOTS)
+#define MAX_SEQUENCES           (MAX_PICS_IN_SYSTEM + SEQUENCE_SLOTS)
+#define MAX_PPSS                (MAX_PICS_IN_SYSTEM + PPS_SLOTS)
+
+#define VDEC_H264_MAXIMUMVALUEOFCPB_CNT 32
+#define VDEC_H264_MVC_MAX_VIEWS         (H264FW_MAX_NUM_VIEWS)
+
+#define VDEC_ASSERT(expected) ({ WARN_ON(!(expected)); 0; })
+
+#define VDEC_ALIGN_SIZE(_val, _alignment, val_type, align_type) \
+	({ \
+		val_type val = _val; \
+		align_type alignment = _alignment; \
+		(((val) + (alignment) - 1) & ~((alignment) - 1)); })
+
+/*
+ * This type defines the video standard.
+ * @brief  VDEC Video Standards
+ */
+enum vdec_vid_std {
+	VDEC_STD_UNDEFINED = 0,
+	VDEC_STD_MPEG2,
+	VDEC_STD_MPEG4,
+	VDEC_STD_H263,
+	VDEC_STD_H264,
+	VDEC_STD_VC1,
+	VDEC_STD_AVS,
+	VDEC_STD_REAL,
+	VDEC_STD_JPEG,
+	VDEC_STD_VP6,
+	VDEC_STD_VP8,
+	VDEC_STD_SORENSON,
+	VDEC_STD_HEVC,
+	VDEC_STD_MAX,
+	VDEC_STD_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This type defines the bitstream format. Should be done at the
+ * start of decoding.
+ * @brief  VDEC Bitstream Format
+ */
+enum vdec_bstr_format {
+	VDEC_BSTRFORMAT_UNDEFINED = 0,
+	VDEC_BSTRFORMAT_ELEMENTARY,
+	VDEC_BSTRFORMAT_DEMUX_BYTESTREAM,
+	VDEC_BSTRFORMAT_DEMUX_SIZEDELIMITED,
+	VDEC_BSTRFORMAT_MAX,
+	VDEC_BSTRFORMAT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This type defines the Type of payload. Could change with every buffer.
+ * @brief  VDEC Bitstream Element Type
+ */
+enum vdec_bstr_element_type {
+	VDEC_BSTRELEMENT_UNDEFINED = 0,
+	VDEC_BSTRELEMENT_UNSPECIFIED,
+	VDEC_BSTRELEMENT_CODEC_CONFIG,
+	VDEC_BSTRELEMENT_PICTURE_DATA,
+	VDEC_BSTRELEMENT_MAX,
+	VDEC_BSTRELEMENT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This structure contains the stream configuration details.
+ * @brief  VDEC Stream Configuration Information
+ */
+struct vdec_str_configdata {
+	enum vdec_vid_std vid_std;
+	enum vdec_bstr_format bstr_format;
+	unsigned int user_str_id;
+	unsigned char update_yuv;
+	unsigned char bandwidth_efficient;
+	unsigned char disable_mvc;
+	unsigned char full_scan;
+	unsigned char immediate_decode;
+	unsigned char intra_frame_closed_gop;
+
+	/*
+	 * constrain the amount of DPB's allowed
+	 * a value of 0 means let the firmware determine
+	 */
+	unsigned int max_dec_frame_buffering;
+};
+
+/*
+ * This type defines the buffer type categories.
+ * @brief  Buffer Types
+ */
+enum vdec_buf_type {
+	VDEC_BUFTYPE_BITSTREAM,
+	VDEC_BUFTYPE_PICTURE,
+	VDEC_BUFTYPE_ALL,
+	VDEC_BUFTYPE_MAX,
+	VDEC_BUFTYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This structure contains information related to a picture plane.
+ * @brief  Picture Plane Information
+ */
+struct vdec_plane_info {
+	unsigned int offset;
+	unsigned int stride;
+	unsigned int size;
+};
+
+/*
+ * This structure describes the VDEC picture dimensions.
+ * @brief  VDEC Picture Size
+ */
+struct vdec_pict_size {
+	unsigned int width;
+	unsigned int height;
+};
+
+/*
+ * This enumeration defines the colour plane indices.
+ * @brief  Colour Plane Indices
+ */
+enum vdec_color_planes {
+	VDEC_PLANE_VIDEO_Y     = 0,
+	VDEC_PLANE_VIDEO_YUV   = 0,
+	VDEC_PLANE_VIDEO_U     = 1,
+	VDEC_PLANE_VIDEO_UV    = 1,
+	VDEC_PLANE_VIDEO_V     = 2,
+	VDEC_PLANE_VIDEO_A     = 3,
+	VDEC_PLANE_LIGHT_R     = 0,
+	VDEC_PLANE_LIGHT_G     = 1,
+	VDEC_PLANE_LIGHT_B     = 2,
+	VDEC_PLANE_INK_C       = 0,
+	VDEC_PLANE_INK_M       = 1,
+	VDEC_PLANE_INK_Y       = 2,
+	VDEC_PLANE_INK_K       = 3,
+	VDEC_PLANE_MAX         = 4,
+	VDEC_PLANE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This structure describes the rendered region of a picture buffer (i.e. where
+ * the image data is written.
+ * @brief  Picture Buffer Render Information
+ */
+struct vdec_pict_rendinfo {
+	unsigned int rendered_size;
+	struct vdec_plane_info plane_info[VDEC_PLANE_MAX];
+	unsigned int stride_alignment;
+	struct vdec_pict_size rend_pict_size;
+};
+
+/*
+ * This structure contains information required to configure the picture
+ * buffers
+ * @brief  Picture Buffer Configuration
+ */
+struct vdec_pict_bufconfig {
+	unsigned int coded_width;
+	unsigned int coded_height;
+	enum img_pixfmt pixel_fmt;
+	unsigned int stride[IMG_MAX_NUM_PLANES];
+	unsigned int stride_alignment;
+	unsigned char byte_interleave;
+	unsigned int buf_size;
+	unsigned char packed;
+	unsigned int chroma_offset[IMG_MAX_NUM_PLANES];
+	unsigned int plane_size[IMG_MAX_NUM_PLANES];
+};
+
+/*
+ * This structure describes the VDEC Display Rectangle.
+ * @brief  VDEC Display Rectangle
+ */
+struct vdec_rect {
+	unsigned int top_offset;
+	unsigned int left_offset;
+	unsigned int width;
+	unsigned int height;
+};
+
+/*
+ * This structure contains the Color Space Description that may be present
+ * in SequenceDisplayExtn(MPEG2), VUI parameters(H264), Visual Object(MPEG4)
+ * for the application to use.
+ * @brief  Stream Color Space Properties
+ */
+struct vdec_color_space_desc {
+	unsigned char is_present;
+	unsigned char color_primaries;
+	unsigned char transfer_characteristics;
+	unsigned char matrix_coefficients;
+};
+
+/*
+ * This structure contains common (standard agnostic) sequence header
+ * information, which is required for image buffer allocation and display.
+ * @brief  Sequence Header Information (common)
+ */
+struct vdec_comsequ_hdrinfo {
+	unsigned int codec_profile;
+	unsigned int codec_level;
+	unsigned int bitrate;
+	long frame_rate;
+	unsigned int frame_rate_num;
+	unsigned int frame_rate_den;
+	unsigned int aspect_ratio_num;
+	unsigned int aspect_ratio_den;
+	unsigned char interlaced_frames;
+	struct pixel_pixinfo pixel_info;
+	struct vdec_pict_size max_frame_size;
+	unsigned int max_ref_frame_num;
+	struct vdec_pict_size frame_size;
+	unsigned char field_codec_mblocks;
+	unsigned int min_pict_buf_num;
+	unsigned char picture_reordering;
+	unsigned char post_processing;
+	struct vdec_rect orig_display_region;
+	struct vdec_rect raw_display_region;
+	unsigned int num_views;
+	unsigned int max_reorder_picts;
+	unsigned char separate_chroma_planes;
+	unsigned char not_dpb_flush;
+	struct vdec_color_space_desc color_space_info;
+};
+
+/*
+ * This structure contains the standard specific codec configuration
+ * @brief Codec configuration
+ */
+struct vdec_codec_config {
+	unsigned int default_height;
+	unsigned int default_width;
+};
+
+/*
+ * This structure describes the decoded picture attributes (relative to the
+ * encoded, where necessary, e.g. rotation angle).
+ * @brief  Stream Output Configuration
+ */
+struct vdec_str_opconfig {
+	struct pixel_pixinfo pixel_info;
+	unsigned char force_oold;
+};
+
+/*
+ * This type defines the "play" mode.
+ * @brief  Play Mode
+ */
+enum vdec_play_mode {
+	VDEC_PLAYMODE_PARSE_ONLY,
+	VDEC_PLAYMODE_NORMAL_DECODE,
+	VDEC_PLAYMODE_MAX,
+	VDEC_PLAYMODE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This type defines the bitstream processing error info.
+ * @brief  Bitstream Processing Error Info
+ */
+struct vdec_bstr_err_info {
+	unsigned int sequence_err;
+	unsigned int picture_err;
+	unsigned int other_err;
+};
+
+/*
+ * This structure describes the VDEC Pan Scan Window.
+ * @brief  VDEC Pan Scan Window
+ */
+struct vdec_window {
+	unsigned int ui32topoffset;
+	unsigned int ui32leftoffset;
+	unsigned int ui32width;
+	unsigned int ui32height;
+};
+
+/*
+ * This structure contains the VDEC picture display properties.
+ * @brief  VDEC Picture Display Properties
+ */
+struct vdec_pict_disp_info {
+	struct vdec_rect enc_disp_region;
+	struct vdec_rect disp_region;
+	struct vdec_rect raw_disp_region;
+	unsigned char top_fld_first;
+	unsigned char out_top_fld_first;
+	unsigned int max_frm_repeat;
+	unsigned int repeat_first_fld;
+	unsigned int num_pan_scan_windows;
+	struct vdec_window pan_scan_windows[VDEC_MAX_PANSCAN_WINDOWS];
+};
+
+/*
+ * This structure contains VXD hardware signatures.
+ * @brief  VXD Hardware signatures
+ */
+struct vdec_pict_hwcrc {
+	unsigned char first_fld_rcvd;
+	unsigned int crc_vdmc_pix_recon;
+	unsigned int vdeb_sysmem_wrdata;
+};
+
+struct vdec_features {
+	unsigned char valid;
+	unsigned char mpeg2;
+	unsigned char mpeg4;
+	unsigned char h264;
+	unsigned char vc1;
+	unsigned char avs;
+	unsigned char real;
+	unsigned char jpeg;
+	unsigned char vp6;
+	unsigned char vp8;
+	unsigned char hevc;
+	unsigned char hd;
+	unsigned char rotation;
+	unsigned char scaling;
+	unsigned char scaling_oold;
+	unsigned char scaling_extnd_strides;
+};
+
+/*
+ * This type defines the auxiliary info for picture queued for decoding.
+ * @brief  Auxiliary Decoding Picture Info
+ */
+struct vdec_dec_pict_auxinfo {
+	unsigned int seq_hdr_id;
+	unsigned int pps_id;
+	unsigned int second_pps_id;
+	unsigned char not_decoded;
+};
+
+/*
+ * This type defines the decoded picture state.
+ * @brief  Decoded Picture State
+ */
+enum vdec_pict_state {
+	VDEC_PICT_STATE_NOT_DECODED,
+	VDEC_PICT_STATE_DECODED,
+	VDEC_PICT_STATE_TERMINATED,
+	VDEC_PICT_STATE_MAX,
+	VDEC_PICT_STATE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This type defines the container for various picture tags.
+ * @brief  Picture Tag Container
+ */
+struct vdec_pict_tag_container {
+	enum img_buffer_type pict_type;
+	unsigned long long pict_tag_param;
+	unsigned long long sideband_info;
+	struct vdec_pict_hwcrc pict_hwcrc;
+};
+
+/*
+ * This structure describes raw bitstream data chunk.
+ * @brief  Raw Bitstream Data Chunk
+ */
+struct vdec_raw_bstr_data {
+	unsigned int size;
+	unsigned int bit_offset;
+	unsigned char *data;
+	struct vdec_raw_bstr_data *next;
+};
+
+/*
+ * This type defines the supplementary picture data.
+ * @brief  Supplementary Picture Data
+ */
+struct vdec_pict_supl_data {
+	struct vdec_raw_bstr_data *raw_vui_data;
+	struct vdec_raw_bstr_data *raw_sei_list_first_fld;
+	struct vdec_raw_bstr_data *raw_sei_list_second_fld;
+	union {
+		struct h264_pict_supl_data {
+			unsigned char nal_ref_idc;
+			unsigned short frame_num;
+		} data;
+	};
+};
+
+/*
+ * This structure contains decoded picture information for display.
+ * @brief  Decoded Picture Information
+ */
+struct vdec_dec_pict_info {
+	enum vdec_pict_state pict_state;
+	enum img_buffer_type buf_type;
+	unsigned char interlaced_flds;
+	unsigned int err_flags;
+	unsigned int err_level;
+	struct vdec_pict_tag_container first_fld_tag_container;
+	struct vdec_pict_tag_container second_fld_tag_container;
+	struct vdec_str_opconfig op_config;
+	struct vdec_pict_rendinfo rend_info;
+	struct vdec_pict_disp_info disp_info;
+	unsigned int last_in_seq;
+	unsigned int decode_id;
+	unsigned int id_for_hwcrc_chk;
+	unsigned short view_id;
+	unsigned int timestamp;
+	struct vdec_pict_supl_data pict_supl_data;
+};
+
+struct vdec_pict_rend_config {
+	struct vdec_pict_size coded_pict_size;
+	unsigned char packed;
+	unsigned char byte_interleave;
+	unsigned int stride_alignment;
+};
+
+/*
+ * This structure contains unsupported feature flags.
+ * @brief  Unsupported Feature Flags
+ */
+struct vdec_unsupp_flags {
+	unsigned int str_cfg;
+	unsigned int str_opcfg;
+	unsigned int op_bufcfg;
+	unsigned int seq_hdr;
+	unsigned int pict_hdr;
+};
+
+/*
+ * This type defines the error , error in parsing, error in decoding etc.
+ * @brief  VDEC parsing/decoding error  Information
+ */
+enum vdec_error_type {
+	VDEC_ERROR_NONE                 = (0),
+	VDEC_ERROR_SR_ERROR             = (1 << 0),
+	VDEC_ERROR_FEHW_TIMEOUT         = (1 << 1),
+	VDEC_ERROR_FEHW_DECODE          = (1 << 2),
+	VDEC_ERROR_BEHW_TIMEOUT         = (1 << 3),
+	VDEC_ERROR_SERVICE_TIMER_EXPIRY = (1 << 4),
+	VDEC_ERROR_MISSING_REFERENCES   = (1 << 5),
+	VDEC_ERROR_MMU_FAULT            = (1 << 6),
+	VDEC_ERROR_DEVICE               = (1 << 7),
+	VDEC_ERROR_CORRUPTED_REFERENCE  = (1 << 8),
+	VDEC_ERROR_MMCO                 = (1 << 9),
+	VDEC_ERROR_MBS_DROPPED          = (1 << 10),
+	VDEC_ERROR_MAX                  = (1 << 11),
+	VDEC_ERROR_FORCE32BITS          = 0x7FFFFFFFU
+};
+
+/*
+ * This structure contains information relating to a buffer.
+ * @brief  Buffer Information
+ */
+struct vdec_buf_info {
+	void *cpu_linear_addr;
+	unsigned int buf_id;
+	struct vdec_pict_bufconfig pictbuf_cfg;
+	int fd;
+	/* The following are fields used internally within VDEC... */
+	unsigned int buf_size;
+	enum sys_emem_attrib mem_attrib;
+	void *buf_alloc_handle;
+	void *buf_map_handle;
+	unsigned long  dma_addr;
+};
+
+#ifdef HAS_JPEG
+/*
+ * This structure contains JPEG sequence header information.
+ * NOTE: Should only contain JPEG specific information.
+ * @brief  JPEG sequence header Information
+ */
+struct vdec_jpeg_sequ_hdr_info {
+	/* total component in jpeg */
+	unsigned char num_component;
+	/* precision */
+	unsigned char precision;
+};
+
+/*
+ * This structure contains JPEG start of frame segment header
+ * NOTE: Should only contain JPEG specific information.
+ * @brief  JPEG SOF header Information
+ */
+struct vdec_jpeg_sof_component_hdr {
+	/* component identifier. */
+	unsigned char identifier;
+	/* Horizontal scaling. */
+	unsigned char horz_factor;
+	/* Verticale scaling */
+	unsigned char vert_factor;
+	/* Qunatisation tables . */
+	unsigned char quant_table;
+};
+
+/*
+ * This structure contains JPEG start of scan segment header
+ * NOTE: Should only contain JPEG specific information.
+ * @brief  JPEG SOS header Information
+ */
+struct vdec_jpeg_sos_component_hdr {
+	/* component identifier. */
+	unsigned char component_index;
+	/* Huffman DC tables. */
+	unsigned char dc_table;
+	/* Huffman AC table .*/
+	unsigned char ac_table;
+};
+
+struct vdec_jpeg_pict_hdr_info {
+	/* Start of frame component header */
+	struct vdec_jpeg_sof_component_hdr sof_comp[JPEG_VDEC_MAX_COMPONENTS];
+	/* Start of Scan component header */
+	struct vdec_jpeg_sos_component_hdr sos_comp[JPEG_VDEC_MAX_COMPONENTS];
+	/* Huffman tables */
+	struct vdec_jpeg_huffman_tableinfo huff_tables[JPEG_VDEC_TABLE_CLASS_NUM]
+						[JPEG_VDEC_MAX_SETS_HUFFMAN_TABLES];
+	/* Quantization tables */
+	struct vdec_jpeg_de_quant_tableinfo quant_tables[JPEG_VDEC_MAX_QUANT_TABLES];
+	/* Number of MCU in the restart interval */
+	unsigned short interval;
+	unsigned int test;
+};
+#endif
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vdecfw_shared.h b/drivers/media/platform/img/vxe-vxd/decoder/vdecfw_shared.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vdecfw_shared.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vdecfw_shared.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,893 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Public data structures and enums for the firmware
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifdef USE_SHARING
+#endif
+
+#ifndef _VDECFW_H_
+#define _VDECFW_H_
+
+#include "img_msvdx_core_regs.h"
+#include "vdecfw_share.h"
+
+/* brief This type defines the buffer type */
+enum img_buffer_type {
+	IMG_BUFFERTYPE_FRAME       = 0,
+	IMG_BUFFERTYPE_FIELD_TOP,
+	IMG_BUFFERTYPE_FIELD_BOTTOM,
+	IMG_BUFFERTYPE_PAIR,
+	IMG_BUFFERTYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Number of scaling coefficients */
+#define VDECFW_NUM_SCALE_COEFFS 4
+
+/*
+ * maximum number of pictures handled by the firmware
+ * for H.264 (largest requirement): 32 for 4 view MVC
+ */
+#define VDECFW_MAX_NUM_PICTURES 32
+#define VDECFW_MAX_NUM_VIEWS 4
+#define EMERALD_CORE    6
+
+/*
+ * maximum number of colocated pictures handled by
+ * firmware in FWBSP mode
+ */
+#define VDECFWBSP_MAX_NUM_COL_PICS 16
+
+/* Maximum number of colour planes. */
+#define VDECFW_PLANE_MAX 4
+
+#define VDECFW_NON_EXISTING_PICTURE_TID (0xffffffff)
+
+#define NO_VALUE    0
+
+/* Indicates whether a cyclic sequence number (x) has reached another (y). */
+#define HAS_X_REACHED_Y(x, y, range, type) \
+	({ \
+		type __x = x; \
+		type __y = y; \
+		type __range = range; \
+		(((((__x) - (__y) + (__range)) % (__range)) <= \
+		  (((__y) - (__x) + (__range)) % (__range))) ? TRUE : FALSE); })
+
+/* Indicates whether a cyclic sequence number (x) has passed another (y). */
+#define HAS_X_PASSED_Y(x, y, range, type) \
+	({ \
+		type __x = x; \
+		type __y = y; \
+		type __range = range; \
+		(((((__x) - (__y) + (__range)) % (__range)) < \
+		  (((__y) - (__x) + (__range)) % (__range))) ? TRUE : FALSE); })
+
+#define FWIF_BIT_MASK(num)                      ((1 << (num)) - 1)
+
+/*
+ * Number of bits in transaction ID used to represent picture number in stream.
+ */
+#define FWIF_NUMBITS_STREAM_PICTURE_ID          16
+/* Number of bits in transaction ID used to represent picture number in core. */
+#define FWIF_NUMBITS_CORE_PICTURE_ID            4
+/* Number of bits in transaction ID used to represent stream id. */
+#define FWIF_NUMBITS_STREAM_ID                  8
+/* Number of bits in transaction ID used to represent core id. */
+#define FWIF_NUMBITS_CORE_ID                    4
+
+/* Offset in transaction ID to picture number in stream. */
+#define FWIF_OFFSET_STREAM_PICTURE_ID           0
+/* Offset in transaction ID to picture number in core. */
+#define FWIF_OFFSET_CORE_PICTURE_ID                             \
+	(FWIF_OFFSET_STREAM_PICTURE_ID + FWIF_NUMBITS_STREAM_PICTURE_ID)
+/* Offset in transaction ID to stream id. */
+#define FWIF_OFFSET_STREAM_ID                                   \
+	(FWIF_OFFSET_CORE_PICTURE_ID + FWIF_NUMBITS_CORE_PICTURE_ID)
+/* Offset in transaction ID to core id. */
+#define FWIF_OFFSET_CORE_ID                                     \
+	(FWIF_OFFSET_STREAM_ID + FWIF_NUMBITS_STREAM_ID)
+
+/* Picture id (stream) from transaction id. */
+#define GET_STREAM_PICTURE_ID(transaction_id)                   \
+	((transaction_id) & FWIF_BIT_MASK(FWIF_NUMBITS_STREAM_PICTURE_ID))
+/* Picture id (core) from transaction id. */
+#define GET_CORE_PICTURE_ID(transaction_id)                     \
+	(((transaction_id) >> FWIF_OFFSET_CORE_PICTURE_ID) &    \
+	 FWIF_BIT_MASK(FWIF_NUMBITS_CORE_PICTURE_ID))
+/* Stream id from transaction id. */
+#define GET_STREAM_ID(transaction_id)                           \
+	(((transaction_id) >> FWIF_OFFSET_STREAM_ID) &          \
+	 FWIF_BIT_MASK(FWIF_NUMBITS_STREAM_ID))
+/* Core id from transaction id. */
+#define GET_CORE_ID(transaction_id)                             \
+	(((transaction_id) >> FWIF_OFFSET_CORE_ID) &            \
+	 FWIF_BIT_MASK(FWIF_NUMBITS_CORE_ID))
+
+/* Picture id (stream) for transaction id. */
+#define SET_STREAM_PICTURE_ID(str_pic_id)                       \
+	(((str_pic_id) & FWIF_BIT_MASK(FWIF_NUMBITS_STREAM_PICTURE_ID)) << \
+		FWIF_OFFSET_STREAM_PICTURE_ID)
+/* Picture id (core) for transaction id. */
+#define SET_CORE_PICTURE_ID(core_pic_id)                                \
+	(((core_pic_id) % (1 << FWIF_NUMBITS_CORE_PICTURE_ID)) <<       \
+		FWIF_OFFSET_CORE_PICTURE_ID)
+/* Stream id for transaction id. */
+#define SET_STREAM_ID(stream_id)                                \
+	(((stream_id) & FWIF_BIT_MASK(FWIF_NUMBITS_STREAM_ID)) <<       \
+		FWIF_OFFSET_STREAM_ID)
+/* Core id for transaction id. */
+#define SET_CORE_ID(core_id)                                    \
+	(((core_id) & FWIF_BIT_MASK(FWIF_NUMBITS_CORE_ID)) <<   \
+		FWIF_OFFSET_CORE_ID)
+/* flag checking */
+#define FLAG_MASK(_flagname_)                   ((1 << _flagname_ ## _SHIFT))
+#define FLAG_IS_SET(_flagsword_, _flagname_)                    \
+	(((_flagsword_) & FLAG_MASK(_flagname_)) ? TRUE : FALSE)
+
+/* This type defines the parser component types */
+enum vdecfw_codectype {
+	VDECFW_CODEC_H264 = 0,       /* H.264, AVC, MVC */
+	VDECFW_CODEC_MPEG4,          /* MPEG4, H.263, DivX, Sorenson */
+	VDECFW_CODEC_VP8,            /* VP8 */
+
+	VDECFW_CODEC_VC1,            /* VC1 (includes WMV9) */
+	VDECFW_CODEC_MPEG2,          /* MPEG2 */
+
+	VDECFW_CODEC_JPEG,           /* JPEG */
+
+	VDECFW_CODEC_VP6,            /* VP6 */
+	VDECFW_CODEC_AVS,            /* AVS */
+	VDECFW_CODEC_RV,             /* RV30, RV40 */
+
+	VDECFW_CODEC_HEVC,           /* HEVC/H265 */
+
+	VDECFW_CODEC_VP9,            /* VP9 */
+
+	VDECFW_CODEC_MAX,            /* End Marker */
+
+	VDEC_CODEC_NONE        = -1, /* No codec */
+	VDEC_CODEC_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* This type defines the FW parser mode - SCP, size delimited, etc. */
+enum vdecfw_parsermode {
+	/* Every NAL is expected to have SCP */
+	VDECFW_SCP_ONLY = 0,
+	/* Every NAL is expect to be size delimited with field size 4 */
+	VDECFW_SIZE_DELIMITED_4_ONLY,
+	/* Every NAL is expect to be size delimited with field size 2 */
+	VDECFW_SIZE_DELIMITED_2_ONLY,
+	/* Every NAL is expect to be size delimited with field size 1 */
+	VDECFW_SIZE_DELIMITED_1_ONLY,
+	/* Size of NAL is provided in the picture header */
+	VDECFW_SIZE_SIDEBAND,
+	/* Unit is a skipped picture with no data to process */
+	VDECFW_SKIPPED_PICTURE,
+	VDECFW_SKIPPED_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This enum defines values of ENTDEC_BE_MODE field of VEC_ENTDEC_BE_CONTROL
+ * register and ENTDEC_FE_MODE field of VEC_ENTDEC_FE_CONTROL register.
+ */
+enum vdecfw_msvdxentdecmode {
+	/* JPEG */
+	VDECFW_ENTDEC_MODE_JPEG        = 0x0,
+	/* H264 (MPEG4/AVC) */
+	VDECFW_ENTDEC_MODE_H264        = 0x1,
+	/* VC1 */
+	VDECFW_ENTDEC_MODE_VC1         = 0x2,
+	/* MPEG2 */
+	VDECFW_ENTDEC_MODE_MPEG2       = 0x3,
+	/* MPEG4 */
+	VDECFW_ENTDEC_MODE_MPEG4       = 0x4,
+	/* AVS */
+	VDECFW_ENTDEC_MODE_AVS         = 0x5,
+	/* WMV9 */
+	VDECFW_ENTDEC_MODE_WMV9        = 0x6,
+	/* MPEG1 */
+	VDECFW_ENTDEC_MODE_MPEG1       = 0x7,
+	/* RealVideo8, with ENTDEC_[BE|FE]_EXTENDED_MODE bit set */
+	VDECFW_ENTDEC_MODE_EXT_REAL8   = 0x0,
+	/* RealVideo9, with ENTDEC_[BE|FE]_EXTENDED_MODE bit set */
+	VDECFW_ENTDEC_MODE_EXT_REAL9   = 0x1,
+	/* VP6, with ENTDEC_[BE|FE]_EXTENDED_MODE bit set */
+	VDECFW_ENTDEC_MODE_EXT_VP6     = 0x2,
+	/* VP8, with ENTDEC_[BE|FE]_EXTENDED_MODE bit set */
+	VDECFW_ENTDEC_MODE_EXT_VP8     = 0x3,
+	/* SVC, with ENTDEC_[BE|FE]_EXTENDED_MODE bit set */
+	VDECFW_ENTDEC_MODE_EXT_SVC     = 0x4,
+	VDECFW_ENTDEC_MODE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This describes the Firmware Parser checkpoints in VEC Local RAM.
+ * Each checkpoint is updated with the TransactionID of the picture as it passes
+ * that point in its decode. Together they describe the current position of
+ * pictures in the VXD/Firmware pipeline.
+ *
+ * Numbers indicate point in the "VDEC Firmware Component Timing" diagram.
+ */
+enum vdecfw_progresscheckpoint {
+	/* Decode message has been read */
+	VDECFW_CHECKPOINT_PICTURE_STARTED     = 1,
+	/* Firmware has been loaded and bitstream DMA started */
+	VDECFW_CHECKPOINT_FIRMWARE_READY      = 2,
+	/* Picture management operations have completed */
+	VDECFW_CHECKPOINT_PICMAN_COMPLETE     = 3,
+	/* Firmware context for this picture has been saved */
+	VDECFW_CHECKPOINT_FIRMWARE_SAVED      = 4,
+	/*
+	 * 1st Picture/Slice header has been read,
+	 * registers written and Entdec started
+	 */
+	VDECFW_CHECKPOINT_ENTDEC_STARTED      = 5,
+	/* 1st Slice has been completed by Entdec */
+	VDECFW_CHECKPOINT_FE_1SLICE_DONE      = 6,
+	/* Parsing of picture has completed on FE */
+	VDECFW_CHECKPOINT_FE_PARSE_DONE       = 7,
+	/* Picture end code has been read and picture closed */
+	VDECFW_CHECKPOINT_FE_PICTURE_COMPLETE = 8,
+	/* Picture has started decoding on VXD Backend */
+	VDECFW_CHECKPOINT_BE_PICTURE_STARTED  = 9,
+	/* 1st Slice has completed on VXD Backend */
+	VDECFW_CHECKPOINT_BE_1SLICE_DONE      = 10,
+	/* Picture decode has completed and done message sent to the Host */
+	VDECFW_CHECKPOINT_BE_PICTURE_COMPLETE = 11,
+#ifndef FW_STACK_USAGE_TRACKING
+	/* General purpose check point 1 */
+	VDECFW_CHECKPOINT_AUX1                = 12,
+	/* General purpose check point 2 */
+	VDECFW_CHECKPOINT_AUX2                = 13,
+	/* General purpose check point 3 */
+	VDECFW_CHECKPOINT_AUX3                = 14,
+	/* General purpose check point 4 */
+	VDECFW_CHECKPOINT_AUX4                = 15,
+#endif  /* ndef FW_STACK_USAGE_TRACKING */
+	VDECFW_CHECKPOINT_MAX,
+	/*
+	 * Indicate which checkpoints mark the start and end of each
+	 * group (FW, FE and BE).
+	 * The start and end values should be updated if new checkpoints are
+	 * added before the current start or after the current end of any group.
+	 */
+	VDECFW_CHECKPOINT_FW_START            = VDECFW_CHECKPOINT_PICTURE_STARTED,
+	VDECFW_CHECKPOINT_FW_END              = VDECFW_CHECKPOINT_FIRMWARE_SAVED,
+	VDECFW_CHECKPOINT_FE_START            = VDECFW_CHECKPOINT_ENTDEC_STARTED,
+	VDECFW_CHECKPOINT_FE_END              = VDECFW_CHECKPOINT_FE_PICTURE_COMPLETE,
+	VDECFW_CHECKPOINT_BE_START            = VDECFW_CHECKPOINT_BE_PICTURE_STARTED,
+	VDECFW_CHECKPOINT_BE_END              = VDECFW_CHECKPOINT_BE_PICTURE_COMPLETE,
+	VDECFW_CHECKPOINT_FORCE32BITS         = 0x7FFFFFFFU
+};
+
+/* Number of auxiliary firmware checkpoints. */
+#define VDECFW_CHECKPOINT_AUX_COUNT  4
+/* This describes the action currently being done by the Firmware. */
+enum vdecfw_firmwareaction {
+	VDECFW_FWACT_IDLE = 1,           /* Firmware is currently doing nothing */
+	VDECFW_FWACT_BASE_LOADING_PSR,   /* Loading parser context */
+	VDECFW_FWACT_BASE_SAVING_PSR,    /* Saving parser context */
+	VDECFW_FWACT_BASE_LOADING_BEMOD, /* Loading Backend module */
+	VDECFW_FWACT_BASE_LOADING_FEMOD, /* Loading Frontend module */
+	VDECFW_FWACT_PARSER_SLICE,       /* Parser active: parsing slice */
+	VDECFW_FWACT_PARSER_PM,          /* Parser active: picture management */
+	VDECFE_FWACT_BEMOD_ACTIVE,       /* Backend module active */
+	VDECFE_FWACT_FEMOD_ACTIVE,       /* Frontend module active */
+	VDECFW_FWACT_MAX,
+	VDECFW_FWACT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This describes the FE_ERR flags word in the VDECFW_MSGID_PIC_DECODED message
+ */
+enum vdecfw_msgflagdecodedfeerror {
+	/* Front-end hardware watchdog timeout (FE_WDT_CM0) */
+	VDECFW_MSGFLAG_DECODED_FEERROR_HWWDT_SHIFT = 0,
+	/* Front-end entdec error (VEC_ERROR_DETECTED_ENTDEC) */
+	VDECFW_MSGFLAG_DECODED_FEERROR_ENTDECERROR_SHIFT,
+	/* Shift-register error (VEC_ERROR_DETECTED_SR) */
+	VDECFW_MSGFLAG_DECODED_FEERROR_SRERROR_SHIFT,
+	/* For cases when B frame comes after I without P. */
+	VDECFW_MSGFLAG_DECODED_MISSING_REFERENCES_SHIFT,
+	/* MMCO operation failed. */
+	VDECFW_MSGFLAG_DECODED_MMCO_ERROR_SHIFT,
+	/* Back-end WDT timeout */
+	VDECFW_MSGFLAG_DECODED_BEERROR_HWWDT_SHIFT,
+	/* Some macroblocks were dropped */
+	VDECFW_MSGFLAG_DECODED_MBS_DROPPED_ERROR_SHIFT,
+	VDECFW_MSGFLAG_DECODED_FEERROR_MAX,
+	VDECFW_MSGFLAG_DECODED_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This type defines the IDs of the messages used to communicate with the
+ * Firmware.
+ *
+ * The Firmware has 3 message buffers, each buffer uses a different set of IDs.
+ * The buffers are:
+ *   Host -> FW -Control messages(High Priority: processed in interrupt context)
+ *   Host -> FW -Decode commands and associated information
+ *   (Normal Priority: processed in baseloop)
+ *   FW -> Host -Completion message
+ */
+enum vdecfw_message_id {
+	/* Control Messages */
+	/*
+	 * Host -> FW Padding message
+	 * Sent to optionally pad the message buffer
+	 */
+	VDECFW_MSGID_BASE_PADDING = 0x01,
+	/*
+	 * Host -> FW Initialisation message Initialisation should be
+	 * sent *immediately* after loading the base component
+	 *  ie. while the FW is idle
+	 */
+	VDECFW_MSGID_FIRMWARE_INIT,
+	/*
+	 * Host -> FW Configuration message
+	 * Configuration should be setup after loading the base component
+	 * and before decoding the next picture ie. while the FW is idle
+	 */
+	VDECFW_MSGID_FIRMWARE_CONFIG,
+	/*
+	 * Host -> FW Control message
+	 * Firmware control command to have immediate affect
+	 * eg. Stop stream, return CRCs, return Performance Data
+	 */
+	VDECFW_MSGID_FIRMWARE_CONTROL,
+	VDECFW_MSGID_CONTROL_MAX,
+	/* Decode Commands */
+	/*
+	 * Host -> FW Padding message
+	 * Sent to optionally pad the message buffer
+	 */
+	VDECFW_MSGID_PSR_PADDING = 0x40,
+	/*
+	 * Host -> FW Decode message
+	 * Describes the picture to decode
+	 */
+	VDECFW_MSGID_DECODE_PICTURE,
+	/*
+	 * Host -> FW Bitstream buffer information
+	 * Information describing a bitstream buffer to DMA to VXD
+	 */
+	VDECFW_MSGID_BITSTREAM_BUFFER,
+	/*
+	 * Host -> FW Fence message
+	 * Generate an interrupt when this is read,
+	 * FenceID should be written to a location in VLR
+	 */
+	VDECFW_MSGID_FENCE,
+	/*
+	 * Host -> FW Batch message
+	 * Contains a pointer to a host memory buffer
+	 * containing a batch of decode command FW messages
+	 */
+	VDECFW_MSGID_BATCH,
+	VDECFW_MSGID_DECODE_MAX,
+	/* Completion Messages */
+	/*
+	 * FW -> Host Padding message
+	 * Sent to optionally pad the message buffer
+	 */
+	VDECFW_MSGID_BE_PADDING = 0x80,
+	/*
+	 * FW -> Host Decoded Picture message
+	 * Notification of decoded picture including errors recorded
+	 */
+	VDECFW_MSGID_PIC_DECODED,
+	/*
+	 * FW -> Host CRC message
+	 * Optionally sent with Decoded Picture message, contains VXD CRCs
+	 */
+	VDECFW_MSGID_PIC_CRCS,
+	/*
+	 * FW -> Host Performance message
+	 * Optional timestamps at the decode checkpoints and other information
+	 * about the image to assist in measuring performance
+	 */
+	VDECFW_MSGID_PIC_PERFORMANCE,
+	/* FW -> Host POST calculation test message */
+	VDECFW_MSGID_PIC_POST_RESP,
+	VDECFW_MSGID_COMPLETION_MAX,
+	VDECFW_MSGID_FORCE32BITS = 0x7FFFFFFFU
+};
+
+#define VDECFW_MSGID_CONTROL_TYPES \
+	(VDECFW_MSGID_CONTROL_MAX - VDECFW_MSGID_BASE_PADDING)
+#define VDECFW_MSGID_DECODE_TYPES \
+	(VDECFW_MSGID_DECODE_MAX - VDECFW_MSGID_PSR_PADDING)
+#define VDECFW_MSGID_COMPLETION_TYPES \
+	(VDECFW_MSGID_COMPLETION_MAX - VDECFW_MSGID_BE_PADDING)
+
+/* This describes the layout of PVDEC Firmware state indicators in Comms RAM. */
+
+/* Maximum number of PVDEC decoding pipes per core supported. */
+#define VDECFW_MAX_DP  3
+
+struct vdecfw_pvdecpipestate {
+	/* TransactionID at each checkpoint */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, check_point[VDECFW_CHECKPOINT_MAX]);
+	/* VDECFW_eFirmwareAction (UINT32 used to guarantee size) */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, firmware_action);
+	/* Number of FE Slices processed for the last picture in FE */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, fe_slices);
+	/* Number of BE Slices processed for the last picture in BE */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, be_slices);
+	/*
+	 * Number of FE Slices being detected as erroed for the last picture
+	 * in FE
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, fe_errored_slices);
+	/*
+	 * Number of BE Slices being detected as erroed for the last picture
+	 * in BE
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, be_errored_slices);
+	/* Number of BE macroblocks dropped for the last picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, be_mbs_dropped);
+	/* Number of BE macroblocks recovered for the last picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, be_mbs_recovered);
+	/* Number of FE macroblocks processed for the last picture in FE */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, last_fe_mb_xy);
+	/* Number of BE macroblocks processed for the last picture in BE */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, last_be_mb_xy);
+	/* VDECFW_eCodecType - Codec currently loaded */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, curr_codec);
+	/* TRUE if this pipe is available for processing */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, pipe_present);
+};
+
+#ifdef FW_STACK_USAGE_TRACKING
+/* Stack usage info array size. */
+#define VDECFW_STACK_INFO_SIZE (VDECFW_MAX_DP * VDECFW_CHECKPOINT_AUX_COUNT)
+#endif /* FW_STACK_USAGE_TRACKING */
+struct vdecfw_pvdecfirmwarestate {
+	/*
+	 * Indicates generic progress taken by firmware
+	 * (must be the first item)
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int, fwstep);
+	/* Pipe state array. */
+	struct vdecfw_pvdecpipestate pipestate[VDECFW_MAX_DP];
+#ifdef FW_STACK_USAGE_TRACKING
+	/* Stack usage info array. */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, unsigned int,
+			stackinfo[VDECFW_STACK_INFO_SIZE]);
+#endif  /* FW_STACK_USAGE_TRACKING */
+};
+
+/*
+ * This describes the flags word in the aui8DisplayFlags
+ * in VDECFW_sBufferControl
+ */
+enum vdecfw_bufflagdisplay {
+	/* TID has been flushed with a "no display" indication */
+	VDECFW_BUFFLAG_DISPLAY_NODISPLAY_SHIFT         = 0,
+	/* TID contains an unpaired field */
+	VDECFW_BUFFLAG_DISPLAY_SINGLE_FIELD_SHIFT      = 1,
+	/* TID contains field coded picture(s) - single field or pair */
+	VDECFW_BUFFLAG_DISPLAY_FIELD_CODED_SHIFT       = 2,
+	/* if TID contains a single field, this defines which field that is */
+	VDECFW_BUFFLAG_DISPLAY_BOTTOM_FIELD_SHIFT      = 3,
+	/* if TID contains a frame with two interlaced fields */
+	VDECFW_BUFFLAG_DISPLAY_INTERLACED_FIELDS_SHIFT = 4,
+	/* End marker */
+	VDECFW_BUFFLAG_DISPLAY_MAX                     = 8,
+	VDECFW_BUFFLAG_DISPLAY_FORCE32BITS             = 0x7FFFFFFFU
+};
+
+/*
+ * This describes the flags in the ui8PictMgmtFlags field in
+ * VDECFW_sBufferControl
+ */
+enum vdecfw_picmgmflags {
+	/* Picture management for this picture successfully executed */
+	VDECFW_PICMGMTFLAG_PICTURE_EXECUTED_SHIFT   = 0,
+	/*
+	 * Picture management for the first field of this picture
+	 * successfully executed
+	 */
+	VDECFW_PICMGMTFLAG_1ST_FIELD_EXECUTED_SHIFT = 0,
+	/*
+	 * Picture management for the second field of this picture
+	 * successfully executed
+	 */
+	VDECFW_PICMGMTFLAG_2ND_FIELD_EXECUTED_SHIFT = 1,
+	VDECFW_PICMGMTFLAG_FORCE32BITS              = 0x7FFFFFFFU
+};
+
+/*
+ * Macro for checking if picture management was successfully executed for
+ *  field coded picture
+ */
+#define VDECFW_PICMGMT_FIELD_CODED_PICTURE_EXECUTED(_flagsword_) \
+	((FLAG_IS_SET(buf_control->picmgmt_flags, \
+		      VDECFW_PICMGMTFLAG_1ST_FIELD_EXECUTED) && \
+	  FLAG_IS_SET(buf_control->picmgmt_flags, \
+		      VDECFW_PICMGMTFLAG_2ND_FIELD_EXECUTED)) ? \
+	 TRUE : FALSE)
+/* This describes the REAL related data for the current picture. */
+struct vdecfw_real_data {
+	/* Picture width */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, width);
+	/* Picture height */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, height);
+	/* Scaled Picture Width */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, scaled_width);
+	/* Scaled Picture Height */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, scaled_height);
+	/* Timestamp parsed in the firmware */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, timestamp);
+};
+
+/* This describes the HEVC related data for the current picture. */
+struct vdecfw_hevcdata {
+	/* POC */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT, int, pic_order_count);
+};
+
+/*
+ * This describes the buffer control structure that is used by the firmware to
+ * signal to the Host to control the display and release of buffers.
+ */
+struct vdecfw_buffer_control {
+	/*
+	 * List of TransactionIDs indicating buffers ready to display,
+	 * in display order
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, display_list[VDECFW_MAX_NUM_PICTURES]);
+	/*
+	 * List of TransactionIDs indicating buffers that are no longer
+	 * required for reference
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int,
+			release_list[VDECFW_MAX_NUM_PICTURES +
+				     VDECFW_MAX_NUM_VIEWS]);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short,
+			display_view_ids[VDECFW_MAX_NUM_PICTURES]);
+	/* List of flags for each TID in the DisplayList */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, display_flags[VDECFW_MAX_NUM_PICTURES]);
+	/* Number of TransactionIDs in aui32DisplayList */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, display_list_length);
+	/* Number of TransactionIDs in aui32ReleaseList */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, release_list_length);
+	union {
+		struct vdecfw_real_data real_data;
+		struct vdecfw_hevcdata hevc_data;
+	};
+	/*
+	 * Refers to the picture decoded with the current transaction ID
+	 * (not affected by merge with field of previous transaction ID)
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			enum img_buffer_type, dec_pict_type);
+	/* Set if the current field is a pair to the previous field */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, second_field_of_pair);
+	/*
+	 * Set if for a pair we decoded first the top field or
+	 * if we have only top field
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, top_field_first);
+	/* Top field is first to be displayed */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, out_top_field_first);
+	/* Picture management flags for this picture */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, picmgmt_flags);
+	/*
+	 * List of TransactionIDs indicating buffers used as references
+	 * when decoding current picture
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, ref_list[VDECFW_MAX_NUM_PICTURES]);
+};
+
+/*
+ * This describes an image buffer for one picture supplied to
+ * the firmware by the host
+ */
+struct vdecfw_image_buffer {
+	/* Virtual Address of each plane */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, byte_offset[VDECFW_PLANE_MAX]);
+};
+
+/* This type defines the picture commands that are prepared for the firmware. */
+enum vdecfw_picture_cmds {
+	/* Reconstructed buffer */
+	/* DISPLAY_PICTURE_SIZE */
+	VDECFW_CMD_DISPLAY_PICTURE,
+	/* CODED_PICTURE_SIZE */
+	VDECFW_CMD_CODED_PICTURE,
+	/* OPERATING_MODE */
+	VDECFW_CMD_OPERATING_MODE,
+	/* LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */
+	VDECFW_CMD_LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESS,
+	/* CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */
+	VDECFW_CMD_CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESS,
+	/* CHROMA2_RECONSTRUCTED_PICTURE_BASE_ADDRESSES */
+	VDECFW_CMD_CHROMA2_RECONSTRUCTED_PICTURE_BASE_ADDRESS,
+	/* VC1_LUMA_RANGE_MAPPING_BASE_ADDRESS */
+	VDECFW_CMD_LUMA_ALTERNATIVE_PICTURE_BASE_ADDRESS,
+	/* VC1_CHROMA_RANGE_MAPPING_BASE_ADDRESS */
+	VDECFW_CMD_CHROMA_ALTERNATIVE_PICTURE_BASE_ADDRESS,
+	/* CHROMA2_ALTERNATIVE_PICTURE_BASE_ADDRESS */
+	VDECFW_CMD_CHROMA2_ALTERNATIVE_PICTURE_BASE_ADDRESS,
+	/* LUMA_ERROR_PICTURE_BASE_ADDRESSES */
+	VDECFW_CMD_LUMA_ERROR_PICTURE_BASE_ADDRESS,
+	/* CHROMA_ERROR_PICTURE_BASE_ADDRESSES */
+	VDECFW_CMD_CHROMA_ERROR_PICTURE_BASE_ADDRESS,
+	/* AUX_MSB_BUFFER_BASE_ADDRESSES (VC-1 only) */
+	VDECFW_CMD_AUX_MSB_BUFFER,
+	/* INTRA_BUFFER_BASE_ADDRESS (various) */
+	VDECFW_CMD_INTRA_BUFFER_BASE_ADDRESS,
+	/* AUX_LINE_BUFFER_BASE_ADDRESS */
+	VDECFW_CMD_AUX_LINE_BUFFER_BASE_ADDRESS,
+	/* MBFLAGS_BUFFER_BASE_ADDRESSES (VP8 only) */
+	VDECFW_CMD_MBFLAGS_BUFFER_BASE_ADDRESS,
+	/* FIRST_PARTITION_BASE_ADDRESSES (VP8 only) */
+	VDECFW_CMD_FIRST_PARTITION_BUFFER_BASE_ADDRESS,
+	/* CURRENT_PICTURE_BUFFER_BASE_ADDRESSES (VP8 only) */
+	VDECFW_CMD_CURRENT_PICTURE_BUFFER_BASE_ADDRESS,
+	/* SEGMENTID_BUFFER_BASE_ADDRESSES (VP8 only) */
+	VDECFW_CMD_SEGMENTID_BASE_ADDRESS,
+	/* EXT_OP_MODE (H.264 only) */
+	VDECFW_CMD_EXT_OP_MODE,
+	/* MC_CACHE_CONFIGURATION */
+	VDECFW_CMD_MC_CACHE_CONFIGURATION,
+	/* Alternative output buffer (rotation etc.) */
+	/* ALTERNATIVE_OUTPUT_PICTURE_ROTATION */
+	VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION,
+	/* EXTENDED_ROW_STRIDE */
+	VDECFW_CMD_EXTENDED_ROW_STRIDE,
+	/* CHROMA_ROW_STRIDE (H.264 only) */
+	VDECFW_CMD_CHROMA_ROW_STRIDE,
+	/* ALTERNATIVE_OUTPUT_CONTROL */
+	VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL,
+	/* RPR specific commands */
+	/* RPR_AX_INITIAL */
+	VDECFW_CMD_RPR_AX_INITIAL,
+	/* RPR_AX_INCREMENT */
+	VDECFW_CMD_RPR_AX_INCREMENT,
+	/* RPR_AY_INITIAL */
+	VDECFW_CMD_RPR_AY_INITIAL,
+	/* RPR_AY_INCREMENT */
+	VDECFW_CMD_RPR_AY_INCREMENT,
+	/* RPR_PICTURE_SIZE */
+	VDECFW_CMD_RPR_PICTURE_SIZE,
+	/* Scaling specific params */
+	/* SCALED_DISPLAY_SIZE */
+	VDECFW_CMD_SCALED_DISPLAY_SIZE,
+	/* HORIZONTAL_SCALE_CONTROL */
+	VDECFW_CMD_HORIZONTAL_SCALE_CONTROL,
+	/* SCALE_HORIZONTAL_CHROMA (H.264 only) */
+	VDECFW_CMD_SCALE_HORIZONTAL_CHROMA,
+	/* VERTICAL_SCALE_CONTROL */
+	VDECFW_CMD_VERTICAL_SCALE_CONTROL,
+	/* SCALE_VERTICAL_CHROMA (H.264 only) */
+	VDECFW_CMD_SCALE_VERTICAL_CHROMA,
+	/* HORIZONTAL_LUMA_COEFFICIENTS_0 */
+	VDECFW_CMD_HORIZONTAL_LUMA_COEFFICIENTS_0,
+	/* HORIZONTAL_LUMA_COEFFICIENTS_1 */
+	VDECFW_CMD_HORIZONTAL_LUMA_COEFFICIENTS_1,
+	/* HORIZONTAL_LUMA_COEFFICIENTS_2 */
+	VDECFW_CMD_HORIZONTAL_LUMA_COEFFICIENTS_2,
+	/* HORIZONTAL_LUMA_COEFFICIENTS_3 */
+	VDECFW_CMD_HORIZONTAL_LUMA_COEFFICIENTS_3,
+	/* VERTICAL_LUMA_COEFFICIENTS_0 */
+	VDECFW_CMD_VERTICAL_LUMA_COEFFICIENTS_0,
+	/* VERTICAL_LUMA_COEFFICIENTS_1 */
+	VDECFW_CMD_VERTICAL_LUMA_COEFFICIENTS_1,
+	/* VERTICAL_LUMA_COEFFICIENTS_2 */
+	VDECFW_CMD_VERTICAL_LUMA_COEFFICIENTS_2,
+	/* VERTICAL_LUMA_COEFFICIENTS_3 */
+	VDECFW_CMD_VERTICAL_LUMA_COEFFICIENTS_3,
+	/* HORIZONTAL_CHROMA_COEFFICIENTS_0 */
+	VDECFW_CMD_HORIZONTAL_CHROMA_COEFFICIENTS_0,
+	/* HORIZONTAL_CHROMA_COEFFICIENTS_1 */
+	VDECFW_CMD_HORIZONTAL_CHROMA_COEFFICIENTS_1,
+	/* HORIZONTAL_CHROMA_COEFFICIENTS_2 */
+	VDECFW_CMD_HORIZONTAL_CHROMA_COEFFICIENTS_2,
+	/* HORIZONTAL_CHROMA_COEFFICIENTS_3 */
+	VDECFW_CMD_HORIZONTAL_CHROMA_COEFFICIENTS_3,
+	/* VERTICAL_CHROMA_COEFFICIENTS_0 */
+	VDECFW_CMD_VERTICAL_CHROMA_COEFFICIENTS_0,
+	/* VERTICAL_CHROMA_COEFFICIENTS_1 */
+	VDECFW_CMD_VERTICAL_CHROMA_COEFFICIENTS_1,
+	/* VERTICAL_CHROMA_COEFFICIENTS_2 */
+	VDECFW_CMD_VERTICAL_CHROMA_COEFFICIENTS_2,
+	/* VERTICAL_CHROMA_COEFFICIENTS_3 */
+	VDECFW_CMD_VERTICAL_CHROMA_COEFFICIENTS_3,
+	/* SCALE_OUTPUT_SIZE */
+	VDECFW_CMD_SCALE_OUTPUT_SIZE,
+	/* VDECFW_CMD_INTRA_BUFFER_PLANE_SIZE */
+	VDECFW_CMD_INTRA_BUFFER_PLANE_SIZE,
+	/* VDECFW_CMD_INTRA_BUFFER_SIZE_PER_PIPE */
+	VDECFW_CMD_INTRA_BUFFER_SIZE_PER_PIPE,
+	/* VDECFW_CMD_AUX_LINE_BUFFER_SIZE_PER_PIPE */
+	VDECFW_CMD_AUX_LINE_BUFFER_SIZE_PER_PIPE,
+	VDECFW_SLICE_X_MB_OFFSET,
+	VDECFW_SLICE_Y_MB_OFFSET,
+	VDECFW_SLICE_TYPE,
+	VDECFW_CMD_MAX,
+	VDECFW_CMD_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Size of relocation data attached to VDECFW_sTransaction message in words */
+#define VDECFW_RELOC_SIZE 125
+
+/* This structure defines the MMU Tile configuration. */
+struct vdecfw_mmu_tile_config {
+	/* MMU_CONTROL2 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned char, tilig_scheme);
+	/* MMU_TILE */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int,
+			mmu_tiling[MSVDX_CORE_CR_MMU_TILE_NO_ENTRIES]);
+	/* MMU_TILE_EXT */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int,
+			mmu_tiling_ext[MSVDX_CORE_CR_MMU_TILE_EXT_NO_ENTRIES]);
+};
+
+/*
+ * This structure contains the transaction attributes to be given to the
+ * firmware
+ * @brief  Transaction Attributes
+ */
+struct vdecfw_transaction {
+	/* Unique identifier for the picture (driver-wide). */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, transation_id);
+	/* Codec */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			enum vdecfw_codectype, codec);
+	/*
+	 * Flag to indicate that the stream needs to ge handled
+	 * in secure memory (if available)
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			int, secure_stream);
+	/* Unique identifier for the current stream */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, stream_id);
+	/* Dictates to the FW parser how the NALs are delimited */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			enum vdecfw_parsermode, parser_mode);
+	/* Address from which to load the parser context data. */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_PTR_ALIGNMENT,
+			unsigned int, ctx_load_addr);
+	/*
+	 * Address to save the parser state data including the updated
+	 * "parser context data".
+	 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_PTR_ALIGNMENT,
+			unsigned int, ctx_save_addr);
+	/* Size of the parser context data in bytes. */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, ctx_size);
+	/* Address to save the "buffer control" data. */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_PTR_ALIGNMENT,
+			unsigned int, ctrl_save_addr);
+	/* Size of the buffer control data in bytes. */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, ctrl_size);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, pict_cmds[VDECFW_CMD_MAX]);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, pic_width_inmbs);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, pic_height_inmbs);
+
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, mbparams_base_addr);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, mbparams_size_per_plane);
+	/* Address of VLC table data. */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_PTR_ALIGNMENT,
+			unsigned int, vlc_tables_addr);
+	/* Size of the VLC table data in bytes. */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, vlc_tables_size);
+	/* Address of VLC index table data. */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_PTR_ALIGNMENT,
+			unsigned int, vlc_index_table_addr);
+	/* Size of the VLC index table data in bytes. */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, vlc_index_table_size);
+	/* Address of parser picture header. */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_PTR_ALIGNMENT,
+			unsigned int, psr_hdr_addr);
+	/* Size of the parser picture header in bytes. */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, psr_hdr_size);
+	/* Address of Sequence Info in the Host (secure) */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_PTR_ALIGNMENT,
+			unsigned int, sequence_info_source);
+	/* Address of PPS Info in the Host (secure) */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_PTR_ALIGNMENT,
+			unsigned int, pps_info_source);
+	/* Address of Second PPS Info in the Host (secure) */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_PTR_ALIGNMENT,
+			unsigned int, second_pps_info_source);
+	/* MMU Tile config comes down with each transaction. */
+	struct vdecfw_mmu_tile_config mmu_tile_config;
+};
+
+/*
+ * This structure contains the info for extracting a subset of VLC tables
+ * indexed inside the index table.
+ * aui32VlcTablesOffset is the offset to the first table inside the index table
+ * aui32VlcConsecutiveTables indicates the consecutive number of entries (from
+ * aui32VlcTablesOffset to aui32VlcTablesOffset+aui32VlcConsecutiveTables)
+ * which will be copied.
+ */
+struct vdecfw_vlc_table_info {
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, vlc_table_offset);
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned short, vlc_consecutive_tables);
+};
+
+/* This structure defines the RENDEC buffer configuration. */
+struct vdecfw_rendec_config {
+	/* VEC_RENDEC_CONTROL0 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, regvec_rendec_control0);
+	/* VEC_RENDEC_CONTROL1 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, regvec_rendec_control1);
+	/* VEC_RENDEC_BASE_ADDR0 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, rendec_buffer_baseaddr0);
+	/* VEC_RENDEC_BASE_ADDR1 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, rendec_buffer_baseaddr1);
+	/* VEC_RENDEC_BUFFER_SIZE */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, regvec_rendec_buffer_size);
+	/* VEC_RENDEC_CONTEXT0 - VEC_RENDEC_CONTEXT5 */
+	IMG_ALIGN_FIELD(VDECFW_SHARE_DEFAULT_ALIGNMENT,
+			unsigned int, rendec_initial_ctx[6]);
+};
+
+#endif /* _VDECFW_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vdecfw_share.h b/drivers/media/platform/img/vxe-vxd/decoder/vdecfw_share.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vdecfw_share.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vdecfw_share.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD DEC SYSDEV and UI Interface header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+#ifndef _VDECFW_SHARE_H_
+#define _VDECFW_SHARE_H_
+
+/*
+ * This macro sets alignment for a field structure.
+ * Parameters :
+ * a - alignment value
+ * t - field type
+ * n - field name
+ */
+#define IMG_ALIGN_FIELD(a, t, n) t n  __aligned(a)
+
+/* END of vdecfw_share_macros.h */
+
+/*
+ * Field alignments in shared data structures
+ */
+/* Default field alignment */
+#define VDECFW_SHARE_DEFAULT_ALIGNMENT  4
+/* Pointer field alignment */
+#define VDECFW_SHARE_PTR_ALIGNMENT      4
+
+#endif /* _VDECFW_SHARE_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vdec_mmu_wrapper.c b/drivers/media/platform/img/vxe-vxd/decoder/vdec_mmu_wrapper.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/vdec_mmu_wrapper.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vdec_mmu_wrapper.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,829 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VDEC MMU Functions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include "img_dec_common.h"
+#include "lst.h"
+#include "talmmu_api.h"
+#include "vdec_defs.h"
+#include "vdec_mmu_wrapper.h"
+#include "vxd_dec.h"
+
+#define GUARD_BAND  0x1000
+
+struct mmuheap {
+	unsigned char *name;
+	enum mmu_eheap_id heap_id;
+	enum talmmu_heap_type heap_type;
+	unsigned int start_offset;
+	unsigned int size;
+	unsigned char *mem_space;
+	unsigned char use_guard_band;
+	unsigned char image_buffers;
+};
+
+static const struct mmuheap mmu_heaps[MMU_HEAP_MAX] = {
+	{ "Image untiled", MMU_HEAP_IMAGE_BUFFERS_UNTILED,
+	  TALMMU_HEAP_PERCONTEXT, PVDEC_HEAP_UNTILED_START,
+	  PVDEC_HEAP_UNTILED_SIZE, "MEMBE", 1, 1 },
+
+	{ "Bitstream", MMU_HEAP_BITSTREAM_BUFFERS,
+	  TALMMU_HEAP_PERCONTEXT, PVDEC_HEAP_BITSTREAM_START,
+	  PVDEC_HEAP_BITSTREAM_SIZE, "MEMDMAC_02", 1, 0 },
+
+	{ "Stream", MMU_HEAP_STREAM_BUFFERS,
+	  TALMMU_HEAP_PERCONTEXT, PVDEC_HEAP_STREAM_START,
+	  PVDEC_HEAP_STREAM_SIZE, "MEM", 1, 0 },
+};
+
+/*
+ * @Heap ID
+ * @Heap type
+ * @Heap flags
+ * @Memory space name
+ * @Start address (virtual)
+ * @Size of heap, in bytes
+ */
+static struct talmmu_heap_info heap_info = {
+	MMU_HEAP_IMAGE_BUFFERS_UNTILED,
+	TALMMU_HEAP_PERCONTEXT,
+	TALMMU_HEAPFLAGS_NONE,
+	"MEMBE",
+	0,
+	0,
+};
+
+/*
+ * This structure contains the device context.
+ * @brief  VDECDD MMU Device Context
+ * @devmem_template_hndl: Handle for MMU template.
+ * @devmem_ctx_hndl: Handle for MMU context.
+ * @str_list: List of streams.
+ */
+struct mmu_dev_context {
+	void *devmem_template_hndl;
+	void *devmem_ctx_hndl;
+	struct lst_t str_list;
+	unsigned int ctx_id;
+	unsigned int next_ctx_id;
+};
+
+/*
+ * This structure contains the stream context.
+ * @brief  VDECDD MMU Stream Context
+ * @LST_LINK: List link (allows the structure to be part of a MeOS list).
+ * @devmem_ctx_hndl: Handle for MMU context.
+ * @dev_ctx: Pointer to device context.
+ * @ctx_id: MMU context Id.
+ * km_str_id: Stream ID used in communication with new KM interface
+ */
+struct mmu_str_context {
+	void **link;
+	void *devmem_ctx_hndl;
+	struct mmu_dev_context *dev_ctx;
+	unsigned int ctx_id;
+	void *ptd_memspace_hndl;
+	unsigned int int_reg_num;
+	unsigned int km_str_id;
+	struct vxd_dec_ctx *vxd_dec_context;
+};
+
+static unsigned int set_attributes(enum sys_emem_attrib mem_attrib)
+{
+	unsigned int attrib = 0;
+
+	if (mem_attrib & SYS_MEMATTRIB_CACHED)
+		attrib |= MEM_ATTR_CACHED;
+
+	if (mem_attrib & SYS_MEMATTRIB_UNCACHED)
+		attrib |= MEM_ATTR_UNCACHED;
+
+	if (mem_attrib & SYS_MEMATTRIB_WRITECOMBINE)
+		attrib |= MEM_ATTR_WRITECOMBINE;
+
+	if (mem_attrib & SYS_MEMATTRIB_SECURE)
+		attrib |= MEM_ATTR_SECURE;
+
+	return attrib;
+}
+
+/*
+ * @Function	mmu_dev_mem_context_create
+ */
+static int mmu_devmem_context_create(struct mmu_dev_context *dev_ctx, void **mmu_ctx_hndl)
+{
+	int result;
+	void *devmem_heap_hndl;
+	union talmmu_heap_options heap_opt1;
+	unsigned int i;
+	unsigned char use_guardband;
+	enum talmmu_heap_option_id heap_option_id;
+
+	dev_ctx->next_ctx_id++;
+
+	/* Create a context from the template */
+	result = talmmu_devmem_ctx_create(dev_ctx->devmem_template_hndl, dev_ctx->next_ctx_id,
+					  mmu_ctx_hndl);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Apply options to heaps. */
+	heap_opt1.guardband_opt.guardband = GUARD_BAND;
+
+	for (i = 0; i < MMU_HEAP_MAX; i++) {
+		result = talmmu_get_heap_handle(mmu_heaps[i].heap_id, *mmu_ctx_hndl,
+						&devmem_heap_hndl);
+		if (result != IMG_SUCCESS)
+			return result;
+
+		use_guardband = mmu_heaps[i].use_guard_band;
+		heap_option_id = TALMMU_HEAP_OPT_ADD_GUARD_BAND;
+		if (use_guardband)
+			talmmu_devmem_heap_options(devmem_heap_hndl, heap_option_id, heap_opt1);
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	mmu_device_create
+ */
+int mmu_device_create(enum mmu_etype mmu_type_arg,
+		      unsigned int ptd_alignment,
+		      void **mmudev_handle)
+{
+	int result = IMG_SUCCESS;
+	enum talmmu_mmu_type talmmu_type =
+		TALMMU_MMUTYPE_4K_PAGES_32BIT_ADDR;
+	unsigned int i;
+	struct mmu_dev_context *dev_ctx;
+	struct talmmu_devmem_info dev_mem_info;
+
+	/* Set the TAL MMU type. */
+	switch (mmu_type_arg) {
+	case MMU_TYPE_32BIT:
+		talmmu_type = TALMMU_MMUTYPE_4K_PAGES_32BIT_ADDR;
+		break;
+
+	case MMU_TYPE_36BIT:
+		talmmu_type = TALMMU_MMUTYPE_4K_PAGES_36BIT_ADDR;
+		break;
+
+	case MMU_TYPE_40BIT:
+		talmmu_type = TALMMU_MMUTYPE_4K_PAGES_40BIT_ADDR;
+		break;
+
+	default:
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Allocate a device context structure */
+	dev_ctx = kzalloc(sizeof(*dev_ctx), GFP_KERNEL);
+	if (!dev_ctx)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	/* Initialise stream list. */
+	lst_init(&dev_ctx->str_list);
+
+	/* Initialise TALMMU. */
+	result = talmmu_init();
+	if (result != IMG_SUCCESS)
+		goto error_tal_init;
+
+	dev_mem_info.device_id = 0;
+	dev_mem_info.mmu_type = talmmu_type;
+	dev_mem_info.dev_flags = TALMMU_DEVFLAGS_NONE;
+	dev_mem_info.pagedir_memspace_name = "MEM";
+	dev_mem_info.pagetable_memspace_name = NULL;
+	dev_mem_info.page_size = DEV_MMU_PAGE_SIZE;
+	dev_mem_info.ptd_alignment = ptd_alignment;
+
+	result = talmmu_devmem_template_create(&dev_mem_info, &dev_ctx->devmem_template_hndl);
+	if (result != IMG_SUCCESS)
+		goto error_tal_template;
+
+	/* Add heaps to template */
+	for (i = 0; i < MMU_HEAP_MAX; i++) {
+		heap_info.heap_id = mmu_heaps[i].heap_id;
+		heap_info.heap_type = mmu_heaps[i].heap_type;
+		heap_info.memspace_name = mmu_heaps[i].name;
+		heap_info.size = mmu_heaps[i].size;
+		heap_info.basedev_virtaddr = mmu_heaps[i].start_offset;
+
+		result = talmmu_devmem_heap_add(dev_ctx->devmem_template_hndl, &heap_info);
+		if (result != IMG_SUCCESS)
+			goto error_tal_heap;
+	}
+
+	/* Create the device context. */
+	result = mmu_devmem_context_create(dev_ctx, &dev_ctx->devmem_ctx_hndl);
+	if (result != IMG_SUCCESS)
+		goto error_mmu_context;
+
+	dev_ctx->ctx_id = dev_ctx->next_ctx_id;
+
+	/* Return the device context. */
+	*mmudev_handle = dev_ctx;
+
+	return IMG_SUCCESS;
+
+	/* Roll back in case of errors. */
+error_mmu_context:
+error_tal_heap:
+	talmmu_devmem_template_destroy(dev_ctx->devmem_template_hndl);
+error_tal_template:
+	talmmu_deinit();
+error_tal_init:
+	kfree(dev_ctx);
+	return result;
+}
+
+/*
+ * @Function	mmu_device_destroy
+ */
+int mmu_device_destroy(void *mmudev_handle)
+{
+	struct mmu_dev_context *dev_ctx = mmudev_handle;
+	unsigned int result;
+	struct mmu_str_context *str_ctx;
+
+	/* Validate inputs. */
+	if (!mmudev_handle)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Destroy all streams associated with the device. */
+	str_ctx = lst_first(&dev_ctx->str_list);
+	while (str_ctx) {
+		result = mmu_stream_destroy(str_ctx);
+		if (result != IMG_SUCCESS)
+			return result;
+		/* See if there are more streams. */
+		str_ctx = lst_first(&dev_ctx->str_list);
+	}
+
+	/* Destroy the device context */
+	result = talmmu_devmem_ctx_destroy(dev_ctx->devmem_ctx_hndl);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Destroy the template. */
+	result = talmmu_devmem_template_destroy(dev_ctx->devmem_template_hndl);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	talmmu_deinit();
+
+	kfree(dev_ctx);
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	mmu_stream_create
+ * @Description
+ * This function is used to create and initialise the MMU stream context.
+ * @Input	mmudev_handle : The MMU device handle.
+ * @Input	km_str_id : Stream Id used in communication with KM driver.
+ * @Output	mmu_str_hndl : A pointer used to return the MMU stream
+ *		handle.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int mmu_stream_create(void *mmudev_handle,
+		      unsigned int km_str_id,
+		      void *vxd_dec_ctx_arg,
+		      void **mmu_str_hndl)
+{
+	struct mmu_dev_context *dev_ctx = mmudev_handle;
+	struct mmu_str_context *str_ctx;
+	int res;
+
+	/* Validate inputs. */
+	if (!mmudev_handle)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Allocate a stream context structure */
+	str_ctx = kzalloc(sizeof(*str_ctx), GFP_KERNEL);
+	if (!str_ctx)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	str_ctx->km_str_id = km_str_id;
+	str_ctx->dev_ctx = dev_ctx;
+	str_ctx->int_reg_num = 32;
+	str_ctx->vxd_dec_context = (struct vxd_dec_ctx *)vxd_dec_ctx_arg;
+
+	/* Create a stream context. */
+	res = mmu_devmem_context_create(dev_ctx, &str_ctx->devmem_ctx_hndl);
+	if (res != IMG_SUCCESS) {
+		kfree(str_ctx);
+		return res;
+	}
+
+	str_ctx->ctx_id = dev_ctx->next_ctx_id;
+
+	/* Add stream to list. */
+	lst_add(&dev_ctx->str_list, str_ctx);
+
+	*mmu_str_hndl = str_ctx;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	mmu_stream_destroy
+ * @Description
+ * This function is used to create and initialise the MMU stream context.
+ * NOTE: Destroy automatically frees and memory allocated using
+ *	mmu_stream_malloc().
+ * @Input	mmu_str_hndl : The MMU stream handle.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int mmu_stream_destroy(void *mmu_str_hndl)
+{
+	struct mmu_str_context *str_ctx = mmu_str_hndl;
+	int res;
+
+	/* Validate inputs. */
+	if (!mmu_str_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* remove stream to list. */
+	lst_remove(&str_ctx->dev_ctx->str_list, str_ctx);
+
+	/* Destroy the device context */
+	res = talmmu_devmem_ctx_destroy(str_ctx->devmem_ctx_hndl);
+	if (res != IMG_SUCCESS)
+		return res;
+
+	kfree(str_ctx);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	mmu_malloc
+ */
+static int mmu_alloc(void *devmem_ctx_hndl,
+		     struct vxd_dec_ctx *vxd_dec_ctx_arg,
+		     enum mmu_eheap_id heap_id,
+		     unsigned int mem_heap_id,
+		     enum sys_emem_attrib mem_attrib,
+		     unsigned int size,
+		     unsigned int alignment,
+		     struct vidio_ddbufinfo *ddbuf_info)
+{
+	int result;
+	void *devmem_heap_hndl;
+	struct vxd_free_data free_data;
+	struct vxd_dec_ctx *ctx;
+	struct vxd_dev *vxd;
+	struct vxd_alloc_data alloc_data;
+	unsigned int flags;
+
+	if (!devmem_ctx_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Set buffer size. */
+	ddbuf_info->buf_size = size;
+
+	/* Round size up to next multiple of physical pages */
+	if ((size % HOST_MMU_PAGE_SIZE) != 0)
+		size = ((size / HOST_MMU_PAGE_SIZE) + 1) * HOST_MMU_PAGE_SIZE;
+
+	/* Allocate memory */
+	ctx = vxd_dec_ctx_arg;
+	vxd = ctx->dev;
+
+	alloc_data.heap_id = mem_heap_id;
+	alloc_data.size = ddbuf_info->buf_size;
+
+	alloc_data.attributes = set_attributes(mem_attrib);
+
+	result = img_mem_alloc(vxd->dev, ctx->mem_ctx, alloc_data.heap_id, alloc_data.size,
+			       (enum mem_attr)alloc_data.attributes,
+			       (int *)&ddbuf_info->buff_id);
+	if (result != IMG_SUCCESS)
+		goto error_alloc;
+
+	ddbuf_info->is_internal = 1;
+
+	if (mem_attrib & SYS_MEMATTRIB_SECURE) {
+		ddbuf_info->cpu_virt = NULL;
+	} else {
+		/* Map the buffer to CPU */
+		result = img_mem_map_km(ctx->mem_ctx, ddbuf_info->buff_id);
+		if (result) {
+			dev_err(vxd->dev, "%s: failed to map buf to cpu!(%d)\n", __func__, result);
+			goto error_get_heap_handle;
+		}
+		ddbuf_info->cpu_virt = img_mem_get_kptr(ctx->mem_ctx, ddbuf_info->buff_id);
+	}
+
+	/* Get heap handle */
+	result = talmmu_get_heap_handle(heap_id, devmem_ctx_hndl, &devmem_heap_hndl);
+	if (result != IMG_SUCCESS)
+		goto error_get_heap_handle;
+
+	/* Allocate device "virtual" memory. */
+	result = talmmu_devmem_addr_alloc(devmem_ctx_hndl, devmem_heap_hndl, size, alignment,
+					  &ddbuf_info->hndl_memory);
+	if (result != IMG_SUCCESS)
+		goto error_mem_map_ext_mem;
+
+	/* Get the device virtual address. */
+	result = talmmu_get_dev_virt_addr(ddbuf_info->hndl_memory, &ddbuf_info->dev_virt);
+	if (result != IMG_SUCCESS)
+		goto error_get_dev_virt_addr;
+
+	flags = VXD_MAP_FLAG_NONE;
+
+	if (mem_attrib & SYS_MEMATTRIB_CORE_READ_ONLY)
+		flags |= VXD_MAP_FLAG_READ_ONLY;
+
+	if (mem_attrib & SYS_MEMATTRIB_CORE_WRITE_ONLY)
+		flags |= VXD_MAP_FLAG_WRITE_ONLY;
+
+	result = vxd_map_buffer(vxd, ctx, ddbuf_info->kmstr_id, ddbuf_info->buff_id,
+				ddbuf_info->dev_virt,
+				flags);
+
+	if (result != IMG_SUCCESS)
+		goto error_map_dev;
+
+	return IMG_SUCCESS;
+
+error_map_dev:
+error_get_dev_virt_addr:
+	talmmu_devmem_addr_free(ddbuf_info->hndl_memory);
+	ddbuf_info->hndl_memory = NULL;
+error_mem_map_ext_mem:
+error_get_heap_handle:
+	free_data.buf_id = ddbuf_info->buff_id;
+	img_mem_free(ctx->mem_ctx, free_data.buf_id);
+error_alloc:
+	return result;
+}
+
+/*
+ * @Function	mmu_stream_malloc
+ */
+int mmu_stream_alloc(void *mmu_str_hndl,
+		     enum mmu_eheap_id heap_id,
+		     unsigned int mem_heap_id,
+		     enum sys_emem_attrib mem_attrib,
+		     unsigned int size,
+		     unsigned int alignment,
+		     struct vidio_ddbufinfo *ddbuf_info)
+{
+	struct mmu_str_context *str_ctx =
+		(struct mmu_str_context *)mmu_str_hndl;
+	int result;
+
+	/* Validate inputs. */
+	if (!mmu_str_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Check if device level heap. */
+	switch (heap_id) {
+	case MMU_HEAP_IMAGE_BUFFERS_UNTILED:
+	case MMU_HEAP_BITSTREAM_BUFFERS:
+	case MMU_HEAP_STREAM_BUFFERS:
+		break;
+
+	default:
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	ddbuf_info->kmstr_id = str_ctx->km_str_id;
+
+	/* Allocate device memory. */
+	result = mmu_alloc(str_ctx->devmem_ctx_hndl, str_ctx->vxd_dec_context, heap_id, mem_heap_id,
+			   mem_attrib, size, alignment, ddbuf_info);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	mmu_stream_map_ext_sg
+ */
+int mmu_stream_map_ext_sg(void *mmu_str_hndl,
+			  enum mmu_eheap_id heap_id,
+			  void *sgt,
+			  unsigned int size,
+			  unsigned int alignment,
+			  enum sys_emem_attrib mem_attrib,
+			  void *cpu_linear_addr,
+			  struct vidio_ddbufinfo *ddbuf_info,
+			  unsigned int *buff_id)
+{
+	struct mmu_str_context *str_ctx =
+		(struct mmu_str_context *)mmu_str_hndl;
+	int result;
+	void *devmem_heap_hndl;
+	unsigned int flags;
+
+	struct vxd_dec_ctx *ctx = str_ctx->vxd_dec_context;
+	struct vxd_dev *vxd = ctx->dev;
+
+	/* Validate inputs. */
+	if (!mmu_str_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Check if device level heap. */
+	switch (heap_id) {
+	case MMU_HEAP_IMAGE_BUFFERS_UNTILED:
+	case MMU_HEAP_BITSTREAM_BUFFERS:
+	case MMU_HEAP_STREAM_BUFFERS:
+		break;
+
+	default:
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!str_ctx->devmem_ctx_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Set buffer size. */
+	ddbuf_info->buf_size = size;
+
+	/* Round size up to next multiple of physical pages */
+	if ((size % HOST_MMU_PAGE_SIZE) != 0)
+		size = ((size / HOST_MMU_PAGE_SIZE) + 1) * HOST_MMU_PAGE_SIZE;
+
+	result = img_mem_import(vxd->dev, ctx->mem_ctx, ddbuf_info->buf_size,
+				(enum mem_attr)set_attributes(mem_attrib),
+				(int *)buff_id);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	if (mem_attrib & SYS_MEMATTRIB_SECURE)
+		ddbuf_info->cpu_virt = NULL;
+
+	ddbuf_info->buff_id = *buff_id;
+	ddbuf_info->is_internal = 0;
+
+	ddbuf_info->kmstr_id = str_ctx->km_str_id;
+
+	/* Set buffer size. */
+	ddbuf_info->buf_size = size;
+
+	/* Ensure the address of the buffer is at least page aligned. */
+	ddbuf_info->cpu_virt = cpu_linear_addr;
+
+	/* Get heap handle */
+	result = talmmu_get_heap_handle(heap_id, str_ctx->devmem_ctx_hndl, &devmem_heap_hndl);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Allocate device "virtual" memory. */
+	result = talmmu_devmem_addr_alloc(str_ctx->devmem_ctx_hndl, devmem_heap_hndl, size,
+					  alignment,
+					  &ddbuf_info->hndl_memory);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Get the device virtual address. */
+	result = talmmu_get_dev_virt_addr(ddbuf_info->hndl_memory, &ddbuf_info->dev_virt);
+	if (result != IMG_SUCCESS)
+		goto error_get_dev_virt_addr;
+
+	/* Map memory to the device */
+	flags = VXD_MAP_FLAG_NONE;
+
+	if (mem_attrib & SYS_MEMATTRIB_CORE_READ_ONLY)
+		flags |= VXD_MAP_FLAG_READ_ONLY;
+
+	if (mem_attrib & SYS_MEMATTRIB_CORE_WRITE_ONLY)
+		flags |= VXD_MAP_FLAG_WRITE_ONLY;
+
+	result = vxd_map_buffer_sg(vxd, ctx, ddbuf_info->kmstr_id, ddbuf_info->buff_id, sgt,
+				   ddbuf_info->dev_virt,
+				   flags);
+
+	if (result != IMG_SUCCESS)
+		goto error_map_dev;
+
+	return IMG_SUCCESS;
+
+error_map_dev:
+error_get_dev_virt_addr:
+	talmmu_devmem_addr_free(ddbuf_info->hndl_memory);
+	ddbuf_info->hndl_memory = NULL;
+	return result;
+}
+
+/*
+ * @Function	mmu_stream_map_ext
+ */
+int mmu_stream_map_ext(void *mmu_str_hndl,
+		       enum mmu_eheap_id heap_id,
+		       unsigned int buff_id,
+		       unsigned int size,
+		       unsigned int alignment,
+		       enum sys_emem_attrib mem_attrib,
+		       void *cpu_linear_addr,
+		       struct vidio_ddbufinfo *ddbuf_info)
+{
+	struct mmu_str_context *str_ctx =
+		(struct mmu_str_context *)mmu_str_hndl;
+	int result;
+	void *devmem_heap_hndl;
+	struct vxd_dec_ctx *ctx;
+	struct vxd_dev *vxd;
+	unsigned int flags;
+
+	/* Validate inputs. */
+	if (!mmu_str_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Check if device level heap. */
+	switch (heap_id) {
+	case MMU_HEAP_IMAGE_BUFFERS_UNTILED:
+	case MMU_HEAP_BITSTREAM_BUFFERS:
+	case MMU_HEAP_STREAM_BUFFERS:
+		break;
+
+	default:
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Round size up to next multiple of physical pages */
+	if ((size % HOST_MMU_PAGE_SIZE) != 0)
+		size = ((size / HOST_MMU_PAGE_SIZE) + 1) * HOST_MMU_PAGE_SIZE;
+
+	ddbuf_info->buff_id = buff_id;
+	ddbuf_info->is_internal = 0;
+
+	ddbuf_info->kmstr_id = str_ctx->km_str_id;
+
+	/* Set buffer size. */
+	ddbuf_info->buf_size = size;
+
+	/* Ensure the address of the buffer is at least page aligned. */
+	ddbuf_info->cpu_virt = cpu_linear_addr;
+
+	/* Get heap handle */
+	result = talmmu_get_heap_handle(heap_id, str_ctx->devmem_ctx_hndl, &devmem_heap_hndl);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Allocate device "virtual" memory. */
+	result = talmmu_devmem_addr_alloc(str_ctx->devmem_ctx_hndl, devmem_heap_hndl, size,
+					  alignment,
+					  &ddbuf_info->hndl_memory);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Get the device virtual address. */
+	result = talmmu_get_dev_virt_addr(ddbuf_info->hndl_memory, &ddbuf_info->dev_virt);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/*
+	 * Map device memory (allocated from outside VDEC)
+	 * into the stream PTD.
+	 */
+	ctx = str_ctx->vxd_dec_context;
+	vxd = ctx->dev;
+
+	flags = VXD_MAP_FLAG_NONE;
+
+	if (mem_attrib & SYS_MEMATTRIB_CORE_READ_ONLY)
+		flags |= VXD_MAP_FLAG_READ_ONLY;
+
+	if (mem_attrib & SYS_MEMATTRIB_CORE_WRITE_ONLY)
+		flags |= VXD_MAP_FLAG_WRITE_ONLY;
+
+	result = vxd_map_buffer(vxd, ctx, ddbuf_info->kmstr_id, ddbuf_info->buff_id,
+				ddbuf_info->dev_virt,
+				flags);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * @Function	mmu_free_mem
+ */
+int mmu_free_mem(void *mmustr_hndl, struct vidio_ddbufinfo *ddbuf_info)
+{
+	int tmp_result;
+	int result = IMG_SUCCESS;
+	struct vxd_dec_ctx *ctx;
+	struct vxd_dev *vxd;
+
+	struct mmu_str_context *str_ctx =
+		(struct mmu_str_context *)mmustr_hndl;
+
+	/* Validate inputs. */
+	if (!ddbuf_info)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (!str_ctx)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Unmap the memory mapped to the device */
+	ctx = str_ctx->vxd_dec_context;
+	vxd = ctx->dev;
+
+	tmp_result = vxd_unmap_buffer(vxd, ctx, ddbuf_info->kmstr_id, ddbuf_info->buff_id);
+	if (tmp_result != IMG_SUCCESS)
+		result = tmp_result;
+
+	/*
+	 * Unmapping the memory mapped to the device - done
+	 * Free the memory.
+	 */
+	tmp_result = talmmu_devmem_addr_free(ddbuf_info->hndl_memory);
+	if (tmp_result != IMG_SUCCESS)
+		result = tmp_result;
+
+	if (ddbuf_info->is_internal) {
+		struct vxd_free_data free_data = { ddbuf_info->buff_id };
+
+		img_mem_free(ctx->mem_ctx, free_data.buf_id);
+	}
+
+	return result;
+}
+
+/*
+ * @Function	mmu_free_mem
+ */
+int mmu_free_mem_sg(void *mmustr_hndl, struct vidio_ddbufinfo *ddbuf_info)
+{
+	int tmp_result;
+	int result = IMG_SUCCESS;
+	struct vxd_dec_ctx *ctx;
+	struct vxd_dev *vxd;
+	struct vxd_free_data free_data;
+
+	struct mmu_str_context *str_ctx =
+		(struct mmu_str_context *)mmustr_hndl;
+
+	/* Validate inputs. */
+	if (!ddbuf_info)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	if (!str_ctx)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	free_data.buf_id = ddbuf_info->buff_id;
+	/* Unmap the memory mapped to the device */
+	ctx = str_ctx->vxd_dec_context;
+	vxd = ctx->dev;
+
+	tmp_result = vxd_unmap_buffer(vxd, ctx, ddbuf_info->kmstr_id, ddbuf_info->buff_id);
+	if (tmp_result != IMG_SUCCESS)
+		result = tmp_result;
+
+	/*
+	 * Unmapping the memory mapped to the device - done
+	 * Free the memory.
+	 */
+	tmp_result = talmmu_devmem_addr_free(ddbuf_info->hndl_memory);
+	if (tmp_result != IMG_SUCCESS)
+		result = tmp_result;
+
+	/*
+	 * for external mem manager buffers, just cleanup the idr list and
+	 * buffer objects
+	 */
+	img_mem_free_bufid(ctx->mem_ctx, free_data.buf_id);
+
+	return result;
+}
+
+/*
+ * @Function                MMU_GetHeap
+ */
+int mmu_get_heap(unsigned int image_stride, enum mmu_eheap_id *heap_id)
+{
+	unsigned int i;
+	unsigned char found = FALSE;
+
+	for (i = 0; i < MMU_HEAP_MAX; i++) {
+		if (mmu_heaps[i].image_buffers) {
+			*heap_id = mmu_heaps[i].heap_id;
+			found = TRUE;
+			break;
+		}
+	}
+
+	VDEC_ASSERT(found);
+	if (!found)
+		return IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+
+	return IMG_SUCCESS;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vdec_mmu_wrapper.h b/drivers/media/platform/img/vxe-vxd/decoder/vdec_mmu_wrapper.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vdec_mmu_wrapper.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vdec_mmu_wrapper.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,174 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VDEC MMU Functions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Lakshmi Sankar <lakshmisankar-t@ti.com>
+ *
+ * Re-written for upstream
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "img_errors.h"
+#include "img_mem.h"
+#include "lst.h"
+#include "mmu_defs.h"
+#include "vid_buf.h"
+
+#ifndef _VXD_MMU_H_
+#define _VXD_MMU_H_
+
+/* Page size of the device MMU */
+#define DEV_MMU_PAGE_SIZE (0x1000)
+/* Page alignment of the device MMU */
+#define DEV_MMU_PAGE_ALIGNMENT  (0x1000)
+
+#define HOST_MMU_PAGE_SIZE	PAGE_SIZE
+
+/*
+ * @Function	mmu_stream_get_ptd_handle
+ * @Description
+ * This function is used to obtain the stream PTD (Page Table Directory)handle
+ * @Input	mmu_str_handle : MMU stream handle.
+ * @Output	str_ptd : Pointer to stream PTD handle.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int mmu_stream_get_ptd_handle(void *mmu_str_handle, void **str_ptd);
+
+/*
+ * @Function	mmu_device_create
+ * @Description
+ * This function is used to create and initialise the MMU device context.
+ * @Input	mmu_type : MMU type.
+ * @Input	ptd_alignment : Alignment of Page Table directory.
+ * @Output	mmudev_hndl : A pointer used to return the
+ *		MMU device handle.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int mmu_device_create(enum mmu_etype mmu_type,
+		      unsigned int ptd_alignment,
+		      void **mmudev_hndl);
+
+/*
+ * @Function	mmu_device_destroy
+ * @Description
+ * This function is used to create and initialise the MMU device context.
+ * NOTE: Destroy device automatically destroys any streams and frees and
+ * memory allocated using MMU_StreamMalloc().
+ * @Input	mmudev_hndl : The MMU device handle.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int mmu_device_destroy(void *mmudev_hndl);
+
+/*
+ * @Function	mmu_stream_create
+ * @Description
+ * This function is used to create and initialise the MMU stream context.
+ * @Input	mmudev_hndl : The MMU device handle.
+ * @Input	km_str_id : Stream Id used in communication with KM driver.
+ * @Output	mmustr_hndl : A pointer used to return the MMU stream handle.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int mmu_stream_create(void *mmudev_hndl, unsigned int km_str_id, void *vxd_dec_ctx,
+		      void **mmustr_hndl);
+
+/**
+ * mmu_stream_destroy - This function is used to create and initialise the MMU stream context.
+ * @mmustr_hndl : The MMU stream handle.
+ * Return	IMG_SUCCESS or an error code.
+ *
+ * NOTE: Destroy automatically frees and memory allocated using
+ *	mmu_stream_malloc().
+ */
+int mmu_stream_destroy(void *mmustr_hndl);
+
+/*
+ * @Function	mmu_stream_alloc
+ * @Description
+ * This function is used to allocate stream memory.
+ * @Input	mmustr_hndl : The MMU stream handle.
+ * @Input	heap_id : The MMU heap Id.
+ * @Input	mem_heap_id : Memory heap id
+ * @Input	mem_attrib : Memory attributes
+ * @Input	size : The size, in bytes, to be allocated.
+ * @Input	alignment : The required byte alignment
+ *		(1, 2, 4, 8, 16 etc).
+ * @Output	ddbuf_info : A pointer to a #vidio_ddbufinfo structure
+ *		used to return the buffer info.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int  mmu_stream_alloc(void *mmustr_hndl,
+		      enum mmu_eheap_id heap_id,
+		      unsigned int mem_heap_id,
+		      enum sys_emem_attrib mem_attrib,
+		      unsigned int size,
+		      unsigned int alignment,
+		      struct vidio_ddbufinfo *ddbuf_info);
+
+/*
+ * @Function	mmu_stream_map_ext
+ * @Description
+ * This function is used to malloc device memory (virtual memory), but mapping
+ * this to memory that has already been allocated (externally).
+ * NOTE: Memory can be freed using MMU_Free().  However, this does not
+ *	free the memory provided by the caller via pvCpuLinearAddr.
+ * @Input	mmustr_hndl    : The MMU stream handle.
+ * @Input	heap_id : The heap Id.
+ * @Input	buff_id : The buffer Id.
+ * @Input	size : The size, in bytes, to be allocated.
+ * @Input	alignment : The required byte alignment (1, 2, 4, 8, 16 etc).
+ * @Input	mem_attrib : Memory attributes
+ * @Input	cpu_linear_addr : CPU linear address of the memory
+ *		to be allocated for the device.
+ * @Output	ddbuf_info : A pointer to a #vidio_ddbufinfo structure
+ *		used to return the buffer info.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int mmu_stream_map_ext(void *mmustr_hndl,
+		       enum mmu_eheap_id heap_id,
+		       unsigned int buff_id,
+		       unsigned int size,
+		       unsigned int alignment,
+		       enum sys_emem_attrib mem_attrib,
+		       void *cpu_linear_addr,
+		       struct vidio_ddbufinfo *ddbuf_info);
+
+int mmu_stream_map_ext_sg(void *mmustr_hndl,
+			  enum mmu_eheap_id heap_id,
+			  void *sgt,
+			  unsigned int size,
+			  unsigned int alignment,
+			  enum sys_emem_attrib mem_attrib,
+			  void *cpu_linear_addr,
+			  struct vidio_ddbufinfo *ddbuf_info,
+			  unsigned int *buff_id);
+
+/*
+ * @Function	mmu_free_mem
+ * @Description
+ * This function is used to free device memory.
+ * @Input	ps_dd_buf_info : A pointer to a #vidio_ddbufinfo structure.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int mmu_free_mem(void *mmustr_hndl, struct vidio_ddbufinfo *ddbuf_info);
+
+/*
+ * @Function	mmu_free_mem
+ * @Description
+ * This function is used to free device memory.
+ * @Input	ps_dd_buf_info : A pointer to a #vidio_ddbufinfo structure.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int mmu_free_mem_sg(void *mmustr_hndl, struct vidio_ddbufinfo *ddbuf_info);
+
+int mmu_get_heap(unsigned int image_stride, enum mmu_eheap_id *heap_id);
+
+#endif /* _VXD_MMU_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vxd_core.c b/drivers/media/platform/img/vxe-vxd/decoder/vxd_core.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/vxd_core.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vxd_core.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1689 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMG DEC VXD Core component function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include <linux/firmware.h>
+#include <linux/completion.h>
+#include <linux/slab.h>
+#include <linux/idr.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/time64.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "img_dec_common.h"
+#include "vxd_pvdec_priv.h"
+#include "img_errors.h"
+
+#define VXD_RENDEC_SIZE (5 * 1024 * 1024)
+
+#define VXD_MSG_CNT_SHIFT 8
+#define VXD_MSG_CNT_MASK 0xff00
+#define VXD_MAX_MSG_CNT ((1 << VXD_MSG_CNT_SHIFT) - 1)
+#define VXD_MSG_STR_MASK 0xff
+#define VXD_INVALID_ID (-1)
+
+#define MAP_FIRMWARE_TO_STREAM 1
+
+/* Has to be used with VXD->mutex acquired! */
+#define VXD_GEN_MSG_ID(VXD, STR_ID, MSG_ID, vxd_type, str_type) \
+	do { \
+		vxd_type __VXD = VXD; \
+		str_type __STR_ID = STR_ID; \
+		WARN_ON((__STR_ID) > VXD_MSG_STR_MASK); \
+		(__VXD)->msg_cnt = (__VXD)->msg_cnt + 1 % (VXD_MAX_MSG_CNT); \
+		(MSG_ID) = ((__VXD)->msg_cnt << VXD_MSG_CNT_SHIFT) | \
+			((__STR_ID) & VXD_MSG_STR_MASK); \
+	} while (0)
+
+/* Have to be used with VXD->mutex acquired! */
+#define VXD_RET_MSG_ID(VXD) ((VXD)->msg_cnt--)
+
+#define VXD_MSG_ID_GET_STR_ID(MSG_ID) \
+	((MSG_ID) & VXD_MSG_STR_MASK)
+
+#define VXD_MSG_ID_GET_CNT(MSG_ID) \
+	(((MSG_ID) & VXD_MSG_CNT_MASK) >> VXD_MSG_CNT_SHIFT)
+
+static const unsigned char *drv_fw_name = "pvdec_full_bin.fw";
+
+/* Driver context */
+static struct {
+	/* Available memory heaps. List of <struct vxd_heap> */
+	struct list_head heaps;
+	/* heap id for all internal allocations (rendec, firmware) */
+	int internal_heap_id;
+
+	/* Memory Management context for driver */
+	struct mem_ctx *mem_ctx;
+
+	/* List of associated <struct vxd_dev> */
+	struct list_head devices;
+
+	/* Virtual addresses of shared buffers, common for all streams. */
+	struct {
+		unsigned int fw_addr; /* Firmware blob */
+		unsigned int rendec_addr; /* Rendec buffer */
+	} virt_space;
+
+	int initialised;
+} vxd_drv;
+
+/*
+ * struct vxd_heap - node for heaps list
+ * @id:   heap id
+ * @list: Entry in <struct vxd_drv:heaps>
+ */
+struct vxd_heap {
+	int id;
+	struct list_head list;
+};
+
+static void img_mmu_callback(enum mmu_callback_type callback_type,
+			     int buff_id, void *data)
+{
+	struct vxd_dev *vxd = data;
+
+	if (!vxd)
+		return;
+
+	if (callback_type == MMU_CALLBACK_MAP)
+		return;
+
+	if (vxd->hw_on)
+		vxd_pvdec_mmu_flush(vxd->dev, vxd->reg_base);
+}
+
+static int vxd_is_apm_required(struct vxd_dev *vxd)
+{
+	return vxd->hw_on;
+}
+
+/*
+ * Power on the HW.
+ * Call with vxd->mutex acquired.
+ */
+static int vxd_make_hw_on_locked(struct vxd_dev *vxd, unsigned int fw_ptd)
+{
+	unsigned int fw_size;
+	struct vxd_fw_hdr *fw_hdr;
+	struct vxd_ena_params ena_params;
+	int ret;
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev, "%s:%d\n", __func__, __LINE__);
+#endif
+	if (vxd->hw_on)
+		return 0;
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev, "%s: enabling HW\n", __func__);
+#endif
+
+	fw_size = vxd->firmware.fw_size;
+	fw_hdr = vxd->firmware.hdr;
+	if (!fw_size || !fw_hdr) {
+		dev_err(vxd->dev, "%s: firmware missing!\n", __func__);
+		return -ENOENT;
+	}
+
+	memset(&ena_params, 0, sizeof(struct vxd_ena_params));
+
+	ena_params.fw_buf_size = fw_size - sizeof(struct vxd_fw_hdr);
+	ena_params.fw_buf_virt_addr = vxd_drv.virt_space.fw_addr;
+	ena_params.ptd = fw_ptd;
+	ena_params.boot_poll.msleep_cycles = 50;
+	ena_params.crc = 0;
+	ena_params.rendec_addr = vxd_drv.virt_space.rendec_addr;
+	ena_params.rendec_size = (VXD_NUM_PIX_PIPES(vxd->props) *
+		VXD_RENDEC_SIZE) / 4096u;
+
+	ena_params.secure = 0;
+	ena_params.wait_dbg_fifo = 0;
+	ena_params.mem_staller.data = NULL;
+	ena_params.mem_staller.size = 0;
+
+	ret = vxd_pvdec_ena(vxd->dev, vxd->reg_base, &ena_params,
+			    fw_hdr, &vxd->freq_khz);
+	/*
+	 * Ignore the return code, proceed as usual, it will be returned anyway.
+	 * The HW is turned on, so we can perform post mortem analysis,
+	 * and collect the fw logs when available.
+	 */
+
+	vxd->hw_on = 1;
+
+	return ret;
+}
+
+/*
+ * Power off the HW.
+ * Call with vxd->mutex acquired.
+ */
+static void vxd_make_hw_off_locked(struct vxd_dev *vxd, unsigned char suspending)
+{
+	int ret;
+
+	if (!vxd->hw_on)
+		return;
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev, "%s:%d\n", __func__, __LINE__);
+#endif
+
+	ret = vxd_pvdec_dis(vxd->dev, vxd->reg_base);
+	vxd->hw_on = 0;
+	if (ret)
+		dev_err(vxd->dev, "%s: failed to power off the VXD!\n", __func__);
+}
+
+/*
+ * Moves all valid items from the queue of items being currently processed to
+ * the pending queue.
+ * Call with vxd->mutex locked
+ */
+static void vxd_rewind_msgs_locked(struct vxd_dev *vxd)
+{
+	struct vxd_item *item, *tmp;
+
+	if (list_empty(&vxd->msgs))
+		return;
+
+	list_for_each_entry_safe(item, tmp, &vxd->msgs, list)
+		list_move(&item->list, &vxd->pend);
+}
+
+static void vxd_report_item_locked(struct vxd_dev *vxd,
+				   struct vxd_item *item,
+				   unsigned int flags)
+{
+	struct vxd_stream *stream;
+
+	__list_del_entry(&item->list);
+	stream = idr_find(vxd->streams, item->stream_id);
+	if (!stream) {
+		/*
+		 * Failed to find associated stream. Probably it was
+		 * already destroyed -- drop the item
+		 */
+#ifdef DEBUG_DECODER_DRIVER
+		dev_dbg(vxd->dev, "%s: drop item %p [0x%x]\n", __func__, item, item->msg_id);
+#endif
+		kfree(item);
+	} else {
+		item->msg.out_flags |= flags;
+		list_add_tail(&item->list, &stream->ctx->items_done);
+#ifdef DEBUG_DECODER_DRIVER
+		dev_dbg(vxd->dev, "%s: waking %p\n", __func__, stream->ctx);
+
+		dev_info(vxd->dev, "%s: signaling worker for %p\n", __func__, stream->ctx);
+#endif
+		schedule_work(stream->ctx->work);
+	}
+}
+
+/*
+ * Rewind all items to the pending queue and report those to listener.
+ * Postpone the reset.
+ * Call with vxd->mutex acquired.
+ */
+static void vxd_emrg_reset_locked(struct vxd_dev *vxd, unsigned int flags)
+{
+	cancel_delayed_work(vxd->dwork);
+
+	vxd->emergency = 1;
+
+#ifdef ERROR_RECOVERY_SIMULATION
+	if (disable_fw_irq_value != 0) {
+		/*
+		 * Previously we have disabled IRQ, now enable it. This
+		 * condition will occur only when the firmware non responsiveness
+		 * will be detected on vxd_worker thread. Once we reproduce the
+		 * issue we will enable the IRQ so that the code flow continues.
+		 */
+		enable_irq(g_module_irq);
+	}
+#endif
+
+	/*
+	 * If the firmware sends more than one reply per item, it's possible
+	 * that corresponding item was already removed from vxd-msgs, but the
+	 * HW was still processing it and MMU page fault could happen and
+	 * trigger execution of this function. So make sure that vxd->msgs
+	 * is not empty before rewinding items.
+	 */
+	if (!list_empty(&vxd->msgs))
+		/* Move all valid items to the pending queue */
+		vxd_rewind_msgs_locked(vxd);
+
+	{
+		struct vxd_item *item, *tmp;
+
+		list_for_each_entry_safe(item, tmp, &vxd->pend, list) {
+			/*
+			 * Exclusive items that were on the pending list
+			 * must be reported as canceled
+			 */
+			if ((item->msg.out_flags & VXD_FW_MSG_FLAG_EXCL) && !item->msg_id)
+				item->msg.out_flags |= VXD_FW_MSG_FLAG_CANCELED;
+
+			vxd_report_item_locked(vxd, item, flags);
+		}
+	}
+}
+
+static void vxd_handle_io_error_locked(struct vxd_dev *vxd)
+{
+	struct vxd_item *item, *tmp;
+	unsigned int pend_flags = !vxd->hw_on ? VXD_FW_MSG_FLAG_DEV_ERR :
+		VXD_FW_MSG_FLAG_CANCELED;
+
+	list_for_each_entry_safe(item, tmp, &vxd->msgs, list)
+		vxd_report_item_locked(vxd, item, VXD_FW_MSG_FLAG_DEV_ERR);
+
+	list_for_each_entry_safe(item, tmp, &vxd->pend, list)
+		vxd_report_item_locked(vxd, item, pend_flags);
+}
+
+static void vxd_sched_worker_locked(struct vxd_dev *vxd, unsigned int delay_ms)
+{
+	unsigned long long work_at = jiffies + msecs_to_jiffies(delay_ms);
+	int ret;
+
+	/*
+	 * Try to queue the work.
+	 * This may be also called from the worker context,
+	 * so we need to re-arm anyway in case of error
+	 */
+	ret = schedule_delayed_work(vxd->dwork, work_at - jiffies);
+	if (ret) {
+		/* Work is already in the queue */
+		/*
+		 * Check if new requested time is "before"
+		 * the last "time" we scheduled this work at,
+		 * if not, do nothing, the worker will do
+		 * recalculation for APM/DWR afterwards
+		 */
+		if (time_before((unsigned long)work_at, (unsigned long)vxd->work_sched_at)) {
+			/*
+			 * Canceling & rescheduling might be problematic,
+			 * so just modify it, when needed
+			 */
+			ret = mod_delayed_work(system_wq, vxd->dwork, work_at - jiffies);
+			if (!ret)
+				dev_err(vxd->dev, "%s: failed to modify work!\n", __func__);
+			/*
+			 * Record the 'time' this work
+			 * has been rescheduled at
+			 */
+			vxd->work_sched_at = work_at;
+		}
+	} else {
+		/* Record the 'time' this work has been scheduled at */
+		vxd->work_sched_at = work_at;
+	}
+}
+
+static void vxd_monitor_locked(struct vxd_dev *vxd)
+{
+	/* HW is dead, not much sense in rescheduling */
+	if (vxd->hw_dead)
+		return;
+
+	/*
+	 * We are not processing anything, but pending list is not empty
+	 * probably the message fifo is full, so retrigger the worker.
+	 */
+	if (!list_empty(&vxd->pend) && list_empty(&vxd->msgs))
+		vxd_sched_worker_locked(vxd, 1);
+
+	if (list_empty(&vxd->pend) && list_empty(&vxd->msgs) && vxd_is_apm_required(vxd)) {
+#ifdef DEBUG_DECODER_DRIVER
+		dev_dbg(vxd->dev, "%s: scheduling APM work (%d ms)!\n", __func__, vxd->hw_pm_delay);
+#endif
+		/*
+		 * No items to process and no items being processed -
+		 * disable the HW
+		 */
+		vxd->pm_start = jiffies;
+		vxd_sched_worker_locked(vxd, vxd->hw_pm_delay);
+		return;
+	}
+
+	if (vxd->hw_dwr_period > 0 && !list_empty(&vxd->msgs)) {
+#ifdef DEBUG_DECODER_DRIVER
+		dev_dbg(vxd->dev, "%s: scheduling DWR work (%d ms)!\n",
+			__func__, vxd->hw_dwr_period);
+#endif
+		vxd->dwr_start = jiffies;
+		vxd_sched_worker_locked(vxd, vxd->hw_dwr_period);
+	}
+}
+
+/*
+ * Take first item from pending list and submit it to the hardware.
+ * Has to be called with vxd->mutex locked.
+ */
+static int vxd_sched_single_locked(struct vxd_dev *vxd)
+{
+	struct vxd_item *item = NULL;
+	unsigned long msg_size;
+	int ret;
+
+	item = list_first_entry(&vxd->pend, struct vxd_item, list);
+
+	msg_size = item->msg.payload_size / sizeof(unsigned int);
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev, "%s: checking msg_size: %zu, item: %p\n", __func__, msg_size, item);
+#endif
+
+	/*
+	 * In case of exclusive item check if hw/fw is
+	 * currently processing anything.
+	 * If so we need to wait until items are returned back.
+	 */
+	if ((item->msg.out_flags & VXD_FW_MSG_FLAG_EXCL) && !list_empty(&vxd->msgs) &&
+	    /*
+	     * We can move forward if message
+	     * is about to be dropped.
+	     */
+	     !(item->msg.out_flags & VXD_FW_MSG_FLAG_DROP))
+
+		ret = -EBUSY;
+	else
+		/*
+		 * Check if there's enough space
+		 * in comms RAM to submit the message.
+		 */
+		ret = vxd_pvdec_msg_fit(vxd->dev, vxd->reg_base, msg_size);
+
+	if (ret == 0) {
+		unsigned short msg_id;
+
+		VXD_GEN_MSG_ID(vxd, item->stream_id, msg_id, struct vxd_dev*, unsigned int);
+
+		/* submit the message to the hardware */
+		ret = vxd_pvdec_send_msg(vxd->dev, vxd->reg_base,
+					 (unsigned int *)item->msg.payload, msg_size,
+					 msg_id, vxd);
+		if (ret) {
+			dev_err(vxd->dev, "%s: failed to send msg!\n", __func__);
+			VXD_RET_MSG_ID(vxd);
+		} else {
+			if (item->msg.out_flags & VXD_FW_MSG_FLAG_DROP) {
+				__list_del_entry(&item->list);
+				kfree(item);
+#ifdef DEBUG_DECODER_DRIVER
+				dev_dbg(vxd->dev, "%s: drop msg 0x%x! (user requested)\n",
+					__func__, msg_id);
+#endif
+			} else {
+				item->msg_id = msg_id;
+#ifdef DEBUG_DECODER_DRIVER
+				dev_dbg(vxd->dev,
+					"%s: moving item %p, id 0x%x to msgs\n",
+					__func__, item, item->msg_id);
+#endif
+				list_move(&item->list, &vxd->msgs);
+			}
+
+			vxd_monitor_locked(vxd);
+		}
+
+	} else if (ret == -EINVAL) {
+		dev_warn(vxd->dev, "%s: invalid msg!\n", __func__);
+		vxd_report_item_locked(vxd, item, VXD_FW_MSG_FLAG_INV);
+		/*
+		 * HW is ok, the message was invalid, so don't return an
+		 * error
+		 */
+		ret = 0;
+	} else if (ret == -EBUSY) {
+		/*
+		 * Not enough space. Message is already in the pending queue,
+		 * so it will be submitted once we've got space. Delayed work
+		 * might have been canceled (if we are currently processing
+		 * threaded irq), so make sure that DWR will trigger if it's
+		 * enabled.
+		 */
+		vxd_monitor_locked(vxd);
+	} else {
+		dev_err(vxd->dev, "%s: failed to check space for msg!\n", __func__);
+	}
+
+	return ret;
+}
+
+/*
+ * Take items from pending list and submit them to the hardware, if space is
+ * available in the ring buffer.
+ * Call with vxd->mutex locked
+ */
+static void vxd_schedule_locked(struct vxd_dev *vxd)
+{
+	unsigned char emergency = vxd->emergency;
+	int ret;
+
+	/* if HW is dead, inform the UM and skip */
+	if (vxd->hw_dead) {
+		vxd_handle_io_error_locked(vxd);
+		return;
+	}
+
+	if (!vxd->hw_on && !list_empty(&vxd->msgs))
+		dev_err(vxd->dev, "%s: msgs not empty when the HW is off!\n", __func__);
+
+	if (list_empty(&vxd->pend)) {
+		vxd_monitor_locked(vxd);
+		return;
+	}
+
+	/*
+	 * If the emergency routine was fired, the hw was left ON,so the UM
+	 * could do the post mortem analysis before submitting the next items.
+	 * Now we can switch off the hardware.
+	 */
+	if (emergency) {
+		vxd->emergency = 0;
+		vxd_make_hw_off_locked(vxd, FALSE);
+		usleep_range(1000, 2000);
+	}
+
+	/* Try to schedule */
+	ret = 0;
+	while (!list_empty(&vxd->pend) && ret == 0) {
+		struct vxd_item *item;
+		struct vxd_stream *stream;
+
+		item = list_first_entry(&vxd->pend, struct vxd_item, list);
+		stream = idr_find(vxd->streams, item->stream_id);
+
+		ret = vxd_make_hw_on_locked(vxd, stream->ptd);
+		if (ret) {
+			dev_err(vxd->dev, "%s: failed to start HW!\n", __func__);
+			vxd->hw_dead = 1;
+			vxd_handle_io_error_locked(vxd);
+			return;
+		}
+
+		ret = vxd_sched_single_locked(vxd);
+	}
+
+	if (ret != 0 && ret != -EBUSY) {
+		dev_err(vxd->dev, "%s: failed to schedule, emrg: %d!\n", __func__, emergency);
+		if (emergency) {
+			/*
+			 * Failed to schedule in the emergency mode --
+			 * there's no hope. Power off the HW, mark all
+			 * items as failed and return them.
+			 */
+			vxd_handle_io_error_locked(vxd);
+			return;
+		}
+		/* Let worker try to handle it */
+		vxd_sched_worker_locked(vxd, 0);
+	}
+}
+
+static void stream_worker(void *work)
+{
+	struct vxd_dec_ctx *ctx = NULL;
+	struct vxd_dev *vxd = NULL;
+	struct vxd_item *item;
+
+	work = get_work_buff(work, FALSE);
+	ctx = container_of(work, struct vxd_dec_ctx, work);
+	vxd = ctx->dev;
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev, "%s: got work for ctx %p\n", __func__, ctx);
+#endif
+
+	mutex_lock_nested(ctx->mutex, SUBCLASS_VXD_CORE);
+	/* don't let this run while device_run is still executing */
+	mutex_lock(ctx->mutex2);
+
+	while (!list_empty(&ctx->items_done)) {
+		item = list_first_entry(&ctx->items_done, struct vxd_item, list);
+
+		item->msg.out_flags &= VXD_FW_MSG_RD_FLAGS_MASK;
+
+#ifdef DEBUG_DECODER_DRIVER
+		dev_info(vxd->dev, "%s: item: %p, payload_size: %d, flags: 0x%x\n",
+			 __func__, item, item->msg.payload_size,
+			 item->msg.out_flags);
+#endif
+
+		if (ctx->cb)
+			ctx->cb(ctx->res_str_id, item->msg.payload,
+				item->msg.payload_size, item->msg.out_flags);
+
+		__list_del_entry(&item->list);
+		kfree(item);
+	}
+	mutex_unlock(ctx->mutex);
+	mutex_unlock(ctx->mutex2);
+}
+
+int vxd_create_ctx(struct vxd_dev *vxd, struct vxd_dec_ctx *ctx)
+{
+	int ret = 0;
+	unsigned int fw_load_retries = 2 * 1000;
+
+	while (!vxd->firmware.ready) {
+		usleep_range(1000, 2000);
+		fw_load_retries--;
+	}
+	if (vxd->firmware.buf_id == 0) {
+		dev_err(vxd->dev, "%s: request fw not yet done!\n", __func__);
+		return -EAGAIN;
+	}
+
+	/* Create memory management context for HW buffers */
+	ret = img_mem_create_ctx(&ctx->mem_ctx);
+	if (ret) {
+		dev_err(vxd->dev, "%s: failed to create mem context (err:%d)!\n", __func__, ret);
+		return ret;
+	}
+
+	ret = img_mmu_ctx_create(vxd->dev, vxd->mmu_config_addr_width,
+				 ctx->mem_ctx, vxd_drv.internal_heap_id,
+				 img_mmu_callback, vxd, &ctx->mmu_ctx);
+	if (ret) {
+		dev_err(vxd->dev, "%s:%d: failed to create mmu ctx\n", __func__, __LINE__);
+		ret = -EPERM;
+		goto out_destroy_ctx;
+	}
+
+	ret = img_mmu_map(ctx->mmu_ctx, vxd->mem_ctx, vxd->firmware.buf_id,
+			  vxd_drv.virt_space.fw_addr,
+			  VXD_MMU_PTD_FLAG_READ_ONLY);
+	if (ret) {
+		dev_err(vxd->dev, "%s:%d: failed to map firmware buffer\n", __func__, __LINE__);
+		ret = -EPERM;
+		goto out_destroy_mmu_ctx;
+	}
+
+	ret = img_mmu_map(ctx->mmu_ctx, vxd->mem_ctx, vxd->rendec_buf_id,
+			  vxd_drv.virt_space.rendec_addr,
+			  VXD_MMU_PTD_FLAG_NONE);
+	if (ret) {
+		dev_err(vxd->dev, "%s:%d: failed to map rendec buffer\n", __func__, __LINE__);
+		ret = -EPERM;
+		goto out_unmap_fw;
+	}
+
+	ret = img_mmu_get_ptd(ctx->mmu_ctx, &ctx->ptd);
+	if (ret) {
+		dev_err(vxd->dev, "%s:%d: failed to get PTD\n", __func__, __LINE__);
+		ret = -EPERM;
+		goto out_unmap_rendec;
+	}
+
+	/* load fw - turned Hw on */
+	ret = vxd_make_hw_on_locked(vxd, ctx->ptd);
+	if (ret) {
+		dev_err(vxd->dev, "%s:%d: failed to start HW\n", __func__, __LINE__);
+		ret = -EPERM;
+		vxd->hw_on = FALSE;
+		goto out_unmap_rendec;
+	}
+
+	init_work(&ctx->work, stream_worker, HWA_DECODER);
+	if (!ctx->work) {
+		ret = ENOMEM;
+		goto out_unmap_rendec;
+	}
+
+	vxd->fw_refcnt++;
+
+	return ret;
+
+out_unmap_rendec:
+	img_mmu_unmap(ctx->mmu_ctx, vxd->mem_ctx, vxd->rendec_buf_id);
+out_unmap_fw:
+	img_mmu_unmap(ctx->mmu_ctx, vxd->mem_ctx, vxd->firmware.buf_id);
+
+out_destroy_mmu_ctx:
+	img_mmu_ctx_destroy(ctx->mmu_ctx);
+out_destroy_ctx:
+	img_mem_destroy_ctx(ctx->mem_ctx);
+	return ret;
+}
+
+void vxd_destroy_ctx(struct vxd_dev *vxd, struct vxd_dec_ctx *ctx)
+{
+	vxd->fw_refcnt--;
+
+	flush_work(ctx->work);
+
+	img_mmu_unmap(ctx->mmu_ctx, vxd->mem_ctx, vxd->rendec_buf_id);
+
+	img_mmu_unmap(ctx->mmu_ctx, vxd->mem_ctx, vxd->firmware.buf_id);
+
+	img_mmu_ctx_destroy(ctx->mmu_ctx);
+
+	img_mem_destroy_ctx(ctx->mem_ctx);
+
+	if (vxd->fw_refcnt == 0) {
+#ifdef DEBUG_DECODER_DRIVER
+		dev_info(vxd->dev, "FW: put %s\n", drv_fw_name);
+#endif
+		/* Poke the monitor to finally switch off the hw, when needed */
+		vxd_monitor_locked(vxd);
+	}
+}
+
+/* Top half */
+irqreturn_t vxd_handle_irq(void *dev)
+{
+	struct vxd_dev *vxd = ((const struct device *)dev)->driver_data;
+	struct vxd_hw_state *hw_state = &vxd->state.hw_state;
+	int ret;
+
+	if (!vxd)
+		return IRQ_NONE;
+
+	ret = vxd_pvdec_clear_int(vxd->reg_base, &hw_state->irq_status);
+
+	if (!hw_state->irq_status || ret == IRQ_NONE)
+		dev_warn(dev, "Got spurious interrupt!\n");
+
+	return (irqreturn_t)ret;
+}
+
+static void vxd_drop_msg_locked(const struct vxd_dev *vxd)
+{
+	int ret;
+
+	ret = vxd_pvdec_recv_msg(vxd->dev, vxd->reg_base, NULL, 0, (struct vxd_dev *)vxd);
+	if (ret)
+		dev_warn(vxd->dev, "%s: failed to receive msg!\n", __func__);
+}
+
+#ifdef DEBUG_DECODER_DRIVER
+static void vxd_dbg_dump_msg(const void *dev, const unsigned char *func,
+			     const unsigned int *payload,
+			     unsigned long msg_size)
+{
+	unsigned int i;
+
+	for (i = 0; i < msg_size; i++)
+		dev_dbg(dev, "%s: msg %d: 0x%08x\n", func, i, payload[i]);
+}
+#endif
+
+static struct vxd_item *vxd_get_orphaned_item_locked(struct vxd_dev *vxd,
+						     unsigned short msg_id,
+						     unsigned long msg_size)
+{
+	struct vxd_stream *stream;
+	struct vxd_item *item;
+	unsigned short str_id = VXD_MSG_ID_GET_STR_ID(msg_id);
+
+	/* Try to find associated stream */
+	stream = idr_find(vxd->streams, str_id);
+	if (!stream) {
+		/* Failed to find associated stream. */
+#ifdef DEBUG_DECODER_DRIVER
+		dev_dbg(vxd->dev, "%s: failed to find str_id: %u\n", __func__, str_id);
+#endif
+		return NULL;
+	}
+
+	item = kzalloc(sizeof(*item) + (msg_size * sizeof(unsigned int)), GFP_KERNEL);
+	if (!item)
+		return NULL;
+
+	item->msg.out_flags = 0;
+	item->stream_id = str_id;
+	item->msg.payload_size = msg_size * sizeof(unsigned int);
+	if (vxd_pvdec_recv_msg(vxd->dev, vxd->reg_base, item->msg.payload, msg_size, vxd)) {
+		dev_err(vxd->dev, "%s: failed to receive msg from VXD!\n", __func__);
+		item->msg.out_flags |= VXD_FW_MSG_FLAG_DEV_ERR;
+	}
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev, "%s: item: %p str_id: %u\n", __func__, item, str_id);
+#endif
+	/*
+	 * Need to put this item on the vxd->msgs list.
+	 * It will be removed after.
+	 */
+	list_add_tail(&item->list, &vxd->msgs);
+
+#ifdef DEBUG_DECODER_DRIVER
+	vxd_dbg_dump_msg(vxd->dev, __func__, item->msg.payload, msg_size);
+#endif
+
+	return item;
+}
+
+/*
+ * Fetch and process a single message from the MTX->host ring buffer.
+ * <no_more> parameter is used to indicate if there are more messages pending.
+ * <fatal> parameter indicates if there is some serious situation detected.
+ * Has to be called with vxd->mutex locked.
+ */
+static void vxd_handle_single_msg_locked(struct vxd_dev *vxd,
+					 unsigned char *no_more,
+					 unsigned char *fatal)
+{
+	int ret;
+	unsigned short msg_id, str_id;
+	unsigned long msg_size; /* size in dwords */
+	struct vxd_item *item = NULL, *tmp, *it;
+	struct vxd_stream *stream;
+	void *dev = vxd->dev;
+	unsigned char not_last_msg;
+
+	/* get the message size and id */
+	ret = vxd_pvdec_pend_msg_info(dev, vxd->reg_base, &msg_size, &msg_id,
+				      &not_last_msg);
+	if (ret) {
+		dev_err(dev, "%s: failed to get pending msg size!\n", __func__);
+		*no_more = TRUE; /* worker will HW failure */
+		return;
+	}
+
+	if (msg_size == 0) {
+		*no_more = TRUE;
+		return;
+	}
+	*no_more = FALSE;
+
+	str_id = VXD_MSG_ID_GET_STR_ID(msg_id);
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: [msg] size: %zu, cnt: %u, str_id: %u, id: 0x%x\n",
+		__func__, msg_size, VXD_MSG_ID_GET_CNT(msg_id),
+		str_id, msg_id);
+	dev_dbg(dev, "%s: [msg] not last: %u\n", __func__, not_last_msg);
+#endif
+
+	cancel_delayed_work(vxd->dwork);
+
+	/* Find associated item */
+	list_for_each_entry_safe_reverse(it, tmp, &vxd->msgs, list) {
+#ifdef DEBUG_DECODER_DRIVER
+		dev_dbg(dev, "%s: checking item %p [0x%x] [des: %d]\n",
+			__func__, it, it->msg_id, it->destroy);
+#endif
+		if (it->msg_id == msg_id) {
+			item = it;
+			break;
+		}
+	}
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: found item %p [destroy: %d]\n",
+		__func__, item, item ? item->destroy : VXD_INVALID_ID);
+#endif
+
+	/* Find associated stream */
+	stream = idr_find(vxd->streams, str_id);
+	/*
+	 * Check for firmware condition in case
+	 * when unexpected item is received.
+	 */
+	if (!item && !stream && vxd_pvdec_check_fw_status(dev, vxd->reg_base)) {
+		struct vxd_item *orphan;
+		/*
+		 * Lets forward the fatal info to listeners first, relaying
+		 * on the head of the msg queue.
+		 */
+		/* TODO: forward fatal info to all attached processes */
+		item = list_entry(vxd->msgs.prev, struct vxd_item, list);
+		orphan = vxd_get_orphaned_item_locked(vxd, item->msg_id, msg_size);
+		if (!orphan) {
+			dev_warn(dev, "%s: drop msg 0x%x! (no orphan)\n", __func__, item->msg_id);
+			vxd_drop_msg_locked(vxd);
+		}
+
+		*fatal = TRUE;
+		return;
+	}
+
+	if ((item && item->destroy) || !stream) {
+		/*
+		 * Item was marked for destruction or we failed to find
+		 * associated stream. Probably it was already destroyed --
+		 * just ignore the message.
+		 */
+		if (item) {
+			__list_del_entry(&item->list);
+			kfree(item);
+			item = NULL;
+		}
+		dev_warn(dev, "%s: drop msg 0x%x! (no owner)\n", __func__, msg_id);
+		vxd_drop_msg_locked(vxd);
+		return;
+	}
+
+	/* Remove item from vxd->msgs list */
+	if (item && item->msg_id == msg_id && !not_last_msg)
+		__list_del_entry(&item->list);
+
+	/*
+	 * If there's no such item on a <being processed> list, or the one
+	 * found is too small to fit the output, or it's not supposed to be
+	 * released, allocate a new one.
+	 */
+	if (!item || (msg_size * sizeof(unsigned int) > item->msg.payload_size) || not_last_msg) {
+		struct vxd_item *new_item;
+
+		new_item = kzalloc(sizeof(*new_item) +
+				(msg_size * sizeof(unsigned int)), GFP_KERNEL);
+		if (item) {
+			if (!new_item) {
+				/*
+				 * Failed to allocate new item. Mark item as
+				 * errored and continue best effort, provide
+				 * only part of the message to the userspace
+				 */
+				dev_err(dev, "%s: failed to alloc new item!\n", __func__);
+				msg_size = item->msg.payload_size / sizeof(unsigned int);
+				item->msg.out_flags |= VXD_FW_MSG_FLAG_DRV_ERR;
+			} else {
+				*new_item = *item;
+				/*
+				 * Do not free the old item if subsequent
+				 * messages are expected (it also wasn't
+				 * removed from the vxd->msgs list, so we are
+				 * not losing a pointer here).
+				 */
+				if (!not_last_msg)
+					kfree(item);
+				item = new_item;
+			}
+		} else {
+			if (!new_item) {
+				/*
+				 * We have no place to put the message, we have
+				 * to drop it
+				 */
+				dev_err(dev, "%s: drop msg 0x%08x! (no mem)\n", __func__, msg_id);
+				vxd_drop_msg_locked(vxd);
+				return;
+			}
+			/*
+			 * There was no corresponding item on the
+			 * <being processed> list and we've allocated
+			 * a new one. Initialize it
+			 */
+			new_item->msg.out_flags = 0;
+			new_item->stream_id = str_id;
+			item = new_item;
+		}
+	}
+	ret = vxd_pvdec_recv_msg(dev, vxd->reg_base, item->msg.payload, msg_size, vxd);
+	if (ret) {
+		dev_err(dev, "%s: failed to receive msg from VXD!\n", __func__);
+		item->msg.out_flags |= VXD_FW_MSG_FLAG_DEV_ERR;
+	}
+	item->msg.payload_size = msg_size * sizeof(unsigned int);
+
+#ifdef DEBUG_DECODER_DRIVER
+	vxd_dbg_dump_msg(dev, __func__, item->msg.payload, msg_size);
+
+	dev_dbg(dev, "%s: adding to done list, item: %p, msg_size: %zu\n",
+		__func__, item, msg_size);
+#endif
+	list_add_tail(&item->list, &stream->ctx->items_done);
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_info(dev, "%s: signaling worker for %p\n", __func__, stream->ctx);
+#endif
+	schedule_work(stream->ctx->work);
+}
+
+/* Bottom half */
+irqreturn_t vxd_handle_thread_irq(void *dev)
+{
+	unsigned char no_more = FALSE;
+	unsigned char fatal = FALSE;
+	struct vxd_dev *vxd = ((const struct device *)dev)->driver_data;
+	struct vxd_hw_state *hw_state = &vxd->state.hw_state;
+	irqreturn_t ret = IRQ_HANDLED;
+
+	if (!vxd)
+		return IRQ_NONE;
+
+	mutex_lock(vxd->mutex);
+
+	/* Spurious interrupt? */
+	if (unlikely(!vxd->hw_on || vxd->hw_dead)) {
+		ret = IRQ_NONE;
+		goto out_unlock;
+	}
+
+	/* Check for critical exception - only MMU faults for now */
+	if (vxd_pvdec_check_irq(dev, vxd->reg_base, hw_state->irq_status) < 0) {
+#ifdef DEBUG_DECODER_DRIVER
+		dev_info(vxd->dev, "device MMU fault: resetting!!!\n");
+#endif
+		vxd_emrg_reset_locked(vxd, VXD_FW_MSG_FLAG_MMU_FAULT);
+		goto out_unlock;
+	}
+
+	/*
+	 * Single interrupt can correspond to multiple messages, handle them
+	 * all.
+	 */
+	while (!no_more)
+		vxd_handle_single_msg_locked(vxd, &no_more, &fatal);
+
+	if (fatal) {
+#ifdef DEBUG_DECODER_DRIVER
+		dev_info(vxd->dev, "fw fatal condition: resetting!!!\n");
+#endif
+		/* Try to recover ... */
+		vxd_emrg_reset_locked(vxd, VXD_FW_MSG_FLAG_FATAL);
+	} else {
+		/* Try to submit items to the HW */
+		vxd_schedule_locked(vxd);
+	}
+
+out_unlock:
+	hw_state->irq_status = 0;
+	mutex_unlock(vxd->mutex);
+
+	return ret;
+}
+
+static void vxd_worker(void *work)
+{
+	struct vxd_dev *vxd = NULL;
+	struct vxd_hw_state state = { 0 };
+	struct vxd_item *item_tail;
+
+	work = get_delayed_work_buff(work, FALSE);
+	vxd = container_of(work, struct vxd_dev, dwork);
+	mutex_lock(vxd->mutex);
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev, "%s: jif: %lu, pm: %llu dwr: %llu\n", __func__,
+		jiffies, vxd->pm_start, vxd->dwr_start);
+#endif
+
+	/*
+	 * Disable the hardware if it has been idle for vxd->hw_pm_delay
+	 * milliseconds. Or simply leave the function without doing anything
+	 * if the HW is not supposed to be turned off.
+	 */
+	if (list_empty(&vxd->pend) && list_empty(&vxd->msgs)) {
+		if (vxd_is_apm_required(vxd)) {
+			unsigned long long dst = vxd->pm_start +
+				msecs_to_jiffies(vxd->hw_pm_delay);
+
+			if (time_is_before_eq_jiffies((unsigned long)dst)) {
+#ifdef DEBUG_DECODER_DRIVER
+				dev_dbg(vxd->dev, "%s: pm, power off\n", __func__);
+#endif
+				vxd_make_hw_off_locked(vxd, FALSE);
+			} else {
+				unsigned long long targ = dst - jiffies;
+
+#ifdef DEBUG_DECODER_DRIVER
+				dev_dbg(vxd->dev, "%s: pm, reschedule: %llu\n", __func__, targ);
+#endif
+				vxd_sched_worker_locked(vxd, jiffies_to_msecs(targ));
+			}
+		}
+		goto out_unlock;
+	}
+
+	/*
+	 * We are not processing anything, but pending list is not empty (if it
+	 * was, we would enter <if statement> above. This can happen upon
+	 * specific conditions, when input message occupies almost whole
+	 * host->MTX ring buffer and is followed by large padding message.
+	 */
+	if (list_empty(&vxd->msgs)) {
+		vxd_schedule_locked(vxd);
+		goto out_unlock;
+	}
+
+	/* Skip emergency reset if it's disabled. */
+	if (vxd->hw_dwr_period <= 0) {
+#ifdef DEBUG_DECODER_DRIVER
+		dev_dbg(vxd->dev, "%s: skip watchdog\n", __func__);
+#endif
+		goto out_unlock;
+	} else {
+		/* Recalculate DWR when needed */
+		unsigned long long dst = vxd->dwr_start +
+			msecs_to_jiffies(vxd->hw_dwr_period);
+
+		if (time_is_after_jiffies((unsigned long)dst)) {
+			unsigned long long targ = dst - jiffies;
+
+#ifdef DEBUG_DECODER_DRIVER
+			dev_dbg(vxd->dev, "%s: dwr, reschedule: %llu\n", __func__, targ);
+#endif
+			vxd_sched_worker_locked(vxd, jiffies_to_msecs(targ));
+			goto out_unlock;
+		}
+	}
+
+	/* Get ID of the oldest item being processed by the HW */
+	item_tail = list_entry(vxd->msgs.prev, struct vxd_item, list);
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev, "%s: tail_item: %p, id: 0x%x\n", __func__, item_tail,
+		item_tail->msg_id);
+#endif
+
+	/* Get HW and firmware state */
+	vxd_pvdec_get_state(vxd->dev, vxd->reg_base, VXD_NUM_PIX_PIPES(vxd->props), &state);
+
+	if (vxd->state.msg_id_tail == item_tail->msg_id &&
+	    !memcmp(&state, &vxd->state.hw_state,
+	    sizeof(struct vxd_hw_state))) {
+		vxd->state.msg_id_tail = 0;
+		memset(&vxd->state.hw_state, 0, sizeof(vxd->state.hw_state));
+		dev_err(vxd->dev, "device DWR(%ums) expired: resetting!!!\n",
+			vxd->hw_dwr_period);
+		vxd_emrg_reset_locked(vxd, VXD_FW_MSG_FLAG_DWR);
+	} else {
+		/* Record current state */
+		vxd->state.msg_id_tail = item_tail->msg_id;
+		vxd->state.hw_state = state;
+
+		/* Submit items to the HW, if space is available.  */
+		vxd_schedule_locked(vxd);
+
+#ifdef DEBUG_DECODER_DRIVER
+		dev_dbg(vxd->dev, "%s: scheduling DWR work (%d ms)!\n",
+			__func__, vxd->hw_dwr_period);
+#endif
+		vxd_sched_worker_locked(vxd, vxd->hw_dwr_period);
+	}
+
+out_unlock:
+	mutex_unlock(vxd->mutex);
+}
+
+/*
+ * Lazy initialization of main driver context (when first core is probed -- we
+ * need heap configuration from sysdev to allocate firmware buffers.
+ */
+int vxd_init(void *dev, struct vxd_dev *vxd,
+	     const struct heap_config heap_configs[], int heaps)
+{
+	int ret, i;
+
+	INIT_LIST_HEAD(&vxd_drv.heaps);
+	vxd_drv.internal_heap_id = VXD_INVALID_ID;
+
+	vxd_drv.mem_ctx = NULL;
+
+	INIT_LIST_HEAD(&vxd_drv.devices);
+
+	vxd_drv.virt_space.fw_addr = 0x42000;
+	vxd_drv.virt_space.rendec_addr = 0xe0000000;
+
+	vxd_drv.initialised = 0;
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: vxd drv init, params:\n", __func__);
+#endif
+
+	/* Initialise memory management component */
+	for (i = 0; i < heaps; i++) {
+		struct vxd_heap *heap;
+
+#ifdef DEBUG_DECODER_DRIVER
+		dev_dbg(dev, "%s: adding heap of type %d\n",
+			__func__, heap_configs[i].type);
+#endif
+
+		heap = kzalloc(sizeof(*heap), GFP_KERNEL);
+		if (!heap) {
+			ret = -ENOMEM;
+			goto heap_add_failed;
+		}
+
+		ret = img_mem_add_heap(&heap_configs[i], &heap->id);
+		if (ret < 0) {
+			dev_err(dev, "%s: failed to init heap (type %d)!\n",
+				__func__, heap_configs[i].type);
+			kfree(heap);
+			goto heap_add_failed;
+		}
+		list_add(&heap->list, &vxd_drv.heaps);
+
+		/* Implicitly, first heap is used for internal allocations */
+		if (vxd_drv.internal_heap_id < 0) {
+			vxd_drv.internal_heap_id = heap->id;
+#ifdef DEBUG_DECODER_DRIVER
+			dev_dbg(dev, "%s: using heap %d for internal alloc\n",
+				__func__, vxd_drv.internal_heap_id);
+#endif
+		}
+	}
+
+	/* Do not proceed if internal heap not defined */
+	if (vxd_drv.internal_heap_id < 0) {
+		dev_err(dev, "%s: failed to locate heap for internal alloc\n", __func__);
+		ret = -EINVAL;
+		/* Loop registered heaps just for sanity */
+		goto heap_add_failed;
+	}
+
+	/* Create memory management context for HW buffers */
+	ret = img_mem_create_ctx(&vxd_drv.mem_ctx);
+	if (ret) {
+		dev_err(dev, "%s: failed to create mem context (err:%d)!\n", __func__, ret);
+		goto create_mem_context_failed;
+	}
+
+	vxd->mem_ctx = vxd_drv.mem_ctx;
+
+	/* Allocate rendec buffer */
+	ret = img_mem_alloc(dev, vxd_drv.mem_ctx, vxd_drv.internal_heap_id,
+			    VXD_RENDEC_SIZE * VXD_NUM_PIX_PIPES(vxd->props),
+			    (enum mem_attr)0, &vxd->rendec_buf_id);
+	if (ret) {
+		dev_err(dev, "%s: alloc rendec buffer failed (err:%d)!\n", __func__, ret);
+		goto create_mem_context_failed;
+	}
+
+	init_delayed_work(&vxd->dwork, vxd_worker, HWA_DECODER);
+	if (!vxd->dwork) {
+		ret = ENOMEM;
+		goto create_mem_context_failed;
+	}
+
+	vxd_drv.initialised = 1;
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: vxd drv init done\n", __func__);
+#endif
+	return 0;
+
+create_mem_context_failed:
+heap_add_failed:
+	while (!list_empty(&vxd_drv.heaps)) {
+		struct vxd_heap *heap;
+
+		heap = list_first_entry(&vxd_drv.heaps, struct vxd_heap, list);
+		__list_del_entry(&heap->list);
+		img_mem_del_heap(heap->id);
+		kfree(heap);
+	}
+	vxd_drv.internal_heap_id = VXD_INVALID_ID;
+	return ret;
+}
+
+/*
+ * Get internal_heap_id
+ * TODO: Only error checking is if < 0, so if the stored value is < 0, then
+ * just passing the value to caller still conveys error.
+ * Caller must error check.
+ */
+int vxd_g_internal_heap_id(void)
+{
+	return vxd_drv.internal_heap_id;
+}
+
+void vxd_deinit(struct vxd_dev *vxd)
+{
+	cancel_delayed_work_sync(vxd->dwork);
+	vxd_make_hw_off_locked(vxd, FALSE);
+
+	/* Destroy memory management context */
+	if (vxd_drv.mem_ctx) {
+		/* Deallocate rendec buffer */
+		img_mem_free(vxd_drv.mem_ctx, vxd->rendec_buf_id);
+
+		img_mem_destroy_ctx(vxd_drv.mem_ctx);
+		vxd_drv.mem_ctx = NULL;
+	}
+
+	/* Deinitialize memory management component */
+	while (!list_empty(&vxd_drv.heaps)) {
+		struct vxd_heap *heap;
+
+		heap = list_first_entry(&vxd_drv.heaps, struct vxd_heap, list);
+		__list_del_entry(&heap->list);
+		img_mem_del_heap(heap->id);
+		kfree(heap);
+	}
+
+	vxd_drv.internal_heap_id = VXD_INVALID_ID;
+	vxd_drv.mem_ctx = NULL;
+	vxd_drv.virt_space.fw_addr = 0x0;
+	vxd_drv.virt_space.rendec_addr = 0x0;
+	vxd_drv.initialised = 0;
+
+#ifdef ERROR_RECOVERY_SIMULATION
+	/* free the kernel object created to debug */
+	kobject_put(vxd_dec_kobject);
+#endif
+}
+
+static void vxd_fw_loaded(const struct firmware *fw, void *context)
+{
+	struct vxd_dev *vxd = context;
+	unsigned long bin_size;
+	int buf_id;
+	struct vxd_fw_hdr *hdr;
+	void *buf_kptr;
+	int ret;
+	unsigned long size = 0;
+	const unsigned char *data = NULL;
+
+	if (!fw) {
+		dev_err(vxd->dev, "Firmware binary is not present\n");
+		vxd->no_fw = 1;
+		return;
+	}
+
+	size = fw->size;
+	data = fw->data;
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_info(vxd->dev, "FW: acquired %s size %zu\n", drv_fw_name, size);
+#endif
+
+	/* Sanity verification of the firmware */
+	if (size < sizeof(struct vxd_fw_hdr)) {
+		dev_err(vxd->dev, "%s: firmware file too small!\n", __func__);
+		goto out;
+	}
+
+	bin_size = size - sizeof(struct vxd_fw_hdr);
+	ret = img_mem_alloc(vxd->dev, vxd_drv.mem_ctx, vxd_drv.internal_heap_id,
+			    bin_size, (enum mem_attr)0, &buf_id);
+	if (ret) {
+		dev_err(vxd->dev, "%s: failed to alloc fw buffer (err:%d)!\n", __func__, ret);
+		goto out;
+	}
+
+	hdr = kzalloc(sizeof(*hdr), GFP_KERNEL);
+	if (!hdr)
+		goto out_release_buf;
+
+	/* Store firmware header in vxd context */
+	memcpy(hdr, data, sizeof(struct vxd_fw_hdr));
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_info(vxd->dev, "FW: info cs: %u, bs: %u, id: 0x%08x, ts: %u\n",
+		 hdr->core_size, hdr->blob_size,
+		 hdr->firmware_id, hdr->timestamp);
+#endif
+
+	/* Check if header is consistent */
+	if (hdr->core_size > bin_size || hdr->blob_size > bin_size) {
+		dev_err(vxd->dev, "%s: got invalid firmware!\n", __func__);
+		goto out_release_hdr;
+	}
+
+	/* Map the firmware buffer to CPU */
+	ret = img_mem_map_km(vxd_drv.mem_ctx, buf_id);
+	if (ret) {
+		dev_err(vxd->dev, "%s: failed to map FW buf to cpu! (%d)\n", __func__, ret);
+		goto out_release_hdr;
+	}
+
+	/* Copy firmware to device buffer */
+	buf_kptr = img_mem_get_kptr(vxd_drv.mem_ctx, buf_id);
+	memcpy(buf_kptr, data + sizeof(struct vxd_fw_hdr), size - sizeof(struct vxd_fw_hdr));
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev, "%s: FW: copied to buffer %d kptr 0x%p\n", __func__, buf_id, buf_kptr);
+#endif
+
+	img_mem_sync_cpu_to_device(vxd_drv.mem_ctx, buf_id);
+
+	vxd->firmware.fw_size = size;
+	vxd->firmware.buf_id = buf_id;
+	vxd->firmware.hdr = hdr;
+	vxd->firmware.ready = TRUE;
+
+	release_firmware(fw);
+	complete_all(vxd->firmware_loading_complete);
+	pr_debug("Firmware loaded successfully ..!!\n");
+	return;
+
+out_release_hdr:
+	kfree(hdr);
+out_release_buf:
+	img_mem_free(vxd_drv.mem_ctx, buf_id);
+out:
+	release_firmware(fw);
+	complete_all(vxd->firmware_loading_complete);
+	kfree(vxd->firmware_loading_complete);
+	vxd->firmware_loading_complete = NULL;
+}
+
+/*
+ * Takes the firmware from the file system and allocates a buffer
+ */
+int vxd_prepare_fw(struct vxd_dev *vxd)
+{
+	int ret;
+
+	/* Fetch firmware from the file system */
+	struct completion **firmware_loading_complete =
+		(struct completion **)&vxd->firmware_loading_complete;
+
+	*firmware_loading_complete = kmalloc(sizeof(*firmware_loading_complete), GFP_KERNEL);
+	if (!(*firmware_loading_complete)) {
+		pr_err("Memory allocation failed for init_completion\n");
+		return -ENOMEM;
+	}
+	init_completion(*firmware_loading_complete);
+
+	if (!vxd->firmware_loading_complete)
+		return -ENOMEM;
+
+	vxd->firmware.ready = FALSE;
+	ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
+				      drv_fw_name, vxd->dev, GFP_KERNEL, vxd,
+				      vxd_fw_loaded);
+	if (ret < 0) {
+		dev_err(vxd->dev, "request_firmware_nowait err: %d\n", ret);
+		complete_all(vxd->firmware_loading_complete);
+		kfree(vxd->firmware_loading_complete);
+		vxd->firmware_loading_complete = NULL;
+	}
+
+	return ret;
+}
+
+/*
+ * Cleans firmware resources
+ */
+void vxd_clean_fw_resources(struct vxd_dev *vxd)
+{
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev, "%s:%d\n", __func__, __LINE__);
+#endif
+
+	wait_for_completion(vxd->firmware_loading_complete);
+	kfree(vxd->firmware_loading_complete);
+	vxd->firmware_loading_complete = NULL;
+
+	if (vxd->firmware.fw_size) {
+		img_mem_free(vxd_drv.mem_ctx, vxd->firmware.buf_id);
+		kfree(vxd->firmware.hdr);
+		vxd->firmware.hdr = NULL;
+#ifdef DEBUG_DECODER_DRIVER
+		dev_info(vxd->dev, "FW: released %s\n", drv_fw_name);
+#endif
+		vxd->firmware.buf_id = VXD_INVALID_ID;
+	}
+}
+
+/*
+ * Submit a message to the VXD.
+ * <ctx> is used to verify that requested stream id (item->stream_id) is valid
+ * for this ctx
+ */
+int vxd_send_msg(struct vxd_dec_ctx *ctx, struct vxd_fw_msg *msg)
+{
+	struct vxd_dev *vxd = ctx->dev;
+	unsigned long msg_size;
+	struct vxd_item *item;
+	struct vxd_stream *stream;
+	int ret;
+
+	if (msg->payload_size < VXD_MIN_INPUT_SIZE)
+		return -EINVAL;
+
+	if (msg->payload_size % sizeof(unsigned int)) {
+		dev_err(vxd->dev, "msg size not aligned! (%u)\n",
+			msg->payload_size);
+		return -EINVAL;
+	}
+
+	msg_size = VXD_MSG_SIZE(*msg);
+
+	if (msg_size > VXD_MAX_INPUT_SIZE)
+		return -EINVAL;
+
+	/* Verify that the gap was left for stream PTD */
+	if (msg->payload[VXD_PTD_MSG_OFFSET] != 0) {
+		dev_err(vxd->dev, "%s: PTD gap missing!\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = mutex_lock_interruptible_nested(ctx->mutex, SUBCLASS_VXD_CORE);
+	if (ret)
+		return ret;
+
+	stream = idr_find(vxd->streams, ctx->stream.id);
+	if (!stream) {
+		dev_warn(vxd->dev, "%s: invalid stream id requested! (%u)\n",
+			 __func__, ctx->stream.id);
+
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	item = kmalloc(sizeof(*item) + msg->payload_size, GFP_KERNEL);
+	if (!item) {
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
+
+	memcpy(&item->msg, msg, msg_size);
+
+	msg->out_flags &= VXD_FW_MSG_WR_FLAGS_MASK;
+	item->stream_id = ctx->stream.id;
+	item->msg_id = 0;
+	item->msg.out_flags = msg->out_flags;
+	item->destroy = 0;
+
+	/*
+	 * Inject the stream PTD into the message. It was already verified that
+	 * there is enough space.
+	 */
+	item->msg.payload[VXD_PTD_MSG_OFFSET] = stream->ptd;
+
+	list_add_tail(&item->list, &vxd->pend);
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev,
+		"%s: added item %p to pend, ptd: 0x%x, str: %u flags: 0x%x\n",
+		__func__, item, stream->ptd, stream->id, item->msg.out_flags);
+#endif
+
+	mutex_lock(vxd->mutex);
+	vxd_schedule_locked(vxd);
+	mutex_unlock(vxd->mutex);
+
+out_unlock:
+	mutex_unlock(ctx->mutex);
+
+	return ret;
+}
+
+int vxd_suspend_dev(void *dev)
+{
+	struct vxd_dev *vxd = platform_get_drvdata(to_platform_device(dev));
+
+	mutex_lock(vxd->mutex);
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: taking a nap!\n", __func__);
+#endif
+
+	/* Cancel the worker first */
+	cancel_delayed_work(vxd->dwork);
+
+	/* Forcing hardware disable */
+	vxd_make_hw_off_locked(vxd, TRUE);
+
+	/* Move all valid items to the pending queue */
+	vxd_rewind_msgs_locked(vxd);
+
+	mutex_unlock(vxd->mutex);
+
+	return 0;
+}
+
+int vxd_resume_dev(void *dev)
+{
+	struct vxd_dev *vxd = platform_get_drvdata(to_platform_device(dev));
+	int ret = 0;
+
+	mutex_lock(vxd->mutex);
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: waking up!\n", __func__);
+#endif
+
+	mutex_unlock(vxd->mutex);
+
+	return ret;
+}
+
+int vxd_map_buffer_sg(struct vxd_dev *vxd, struct vxd_dec_ctx *ctx,
+		      unsigned int str_id,
+		      unsigned int buff_id,
+		      void *sgt, unsigned int virt_addr,
+		      unsigned int map_flags)
+{
+	struct vxd_stream *stream;
+	unsigned int flags = VXD_MMU_PTD_FLAG_NONE;
+	int ret;
+
+	ret = mutex_lock_interruptible_nested(ctx->mutex, SUBCLASS_VXD_CORE);
+	if (ret)
+		return ret;
+
+	stream = idr_find(vxd->streams, str_id);
+	if (!stream) {
+		dev_err(vxd->dev, "%s: stream %d not found!\n", __func__, str_id);
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	if ((map_flags & (VXD_MAP_FLAG_READ_ONLY | VXD_MAP_FLAG_WRITE_ONLY))
+		== (VXD_MAP_FLAG_READ_ONLY | VXD_MAP_FLAG_WRITE_ONLY)) {
+		dev_err(vxd->dev, "%s: Bogus mapping flags 0x%x!\n", __func__,
+			map_flags);
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	/* Convert permission flags to internal definitions */
+	if (map_flags & VXD_MAP_FLAG_READ_ONLY)
+		flags |= VXD_MMU_PTD_FLAG_READ_ONLY;
+
+	if (map_flags & VXD_MAP_FLAG_WRITE_ONLY)
+		flags |= VXD_MMU_PTD_FLAG_WRITE_ONLY;
+
+	ret = img_mmu_map_sg(stream->mmu_ctx, ctx->mem_ctx, buff_id, sgt, virt_addr, flags);
+	if (ret) {
+		dev_err(vxd->dev, "%s: map failed!\n", __func__);
+		goto out_unlock;
+	}
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev,
+		"%s: mapped buf %u to 0x%08x, str_id: %u flags: 0x%x\n",
+		__func__, buff_id, virt_addr, str_id, flags);
+#endif
+
+out_unlock:
+	mutex_unlock(ctx->mutex);
+	return ret;
+}
+
+int vxd_map_buffer(struct vxd_dev *vxd, struct vxd_dec_ctx *ctx, unsigned int str_id,
+		   unsigned int buff_id,
+		   unsigned int virt_addr,
+		   unsigned int map_flags)
+{
+	struct vxd_stream *stream;
+	unsigned int flags = VXD_MMU_PTD_FLAG_NONE;
+	int ret;
+
+	ret = mutex_lock_interruptible_nested(ctx->mutex, SUBCLASS_VXD_CORE);
+	if (ret)
+		return ret;
+
+	stream = idr_find(vxd->streams, str_id);
+	if (!stream) {
+		dev_err(vxd->dev, "%s: stream %d not found!\n", __func__, str_id);
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	if ((map_flags & (VXD_MAP_FLAG_READ_ONLY | VXD_MAP_FLAG_WRITE_ONLY))
+		== (VXD_MAP_FLAG_READ_ONLY | VXD_MAP_FLAG_WRITE_ONLY)) {
+		dev_err(vxd->dev, "%s: Bogus mapping flags 0x%x!\n", __func__, map_flags);
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	/* Convert permission flags to internal definitions */
+	if (map_flags & VXD_MAP_FLAG_READ_ONLY)
+		flags |= VXD_MMU_PTD_FLAG_READ_ONLY;
+
+	if (map_flags & VXD_MAP_FLAG_WRITE_ONLY)
+		flags |= VXD_MMU_PTD_FLAG_WRITE_ONLY;
+
+	ret = img_mmu_map(stream->mmu_ctx, ctx->mem_ctx, buff_id, virt_addr, flags);
+	if (ret) {
+		dev_err(vxd->dev, "%s: map failed!\n", __func__);
+		goto out_unlock;
+	}
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev,
+		"%s: mapped buf %u to 0x%08x, str_id: %u flags: 0x%x\n",
+		__func__, buff_id, virt_addr, str_id, flags);
+#endif
+
+out_unlock:
+	mutex_unlock(ctx->mutex);
+	return ret;
+}
+
+int vxd_unmap_buffer(struct vxd_dev *vxd, struct vxd_dec_ctx *ctx,
+		     unsigned int str_id, unsigned int buff_id)
+{
+	struct vxd_stream *stream;
+	int ret;
+
+	ret = mutex_lock_interruptible_nested(ctx->mutex, SUBCLASS_VXD_CORE);
+	if (ret)
+		return ret;
+
+	stream = idr_find(vxd->streams, str_id);
+	if (!stream) {
+		dev_err(vxd->dev, "%s: stream %d not found!\n", __func__, str_id);
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	ret = img_mmu_unmap(stream->mmu_ctx, ctx->mem_ctx, buff_id);
+	if (ret) {
+		dev_err(vxd->dev, "%s: map failed!\n", __func__);
+		goto out_unlock;
+	}
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(vxd->dev, "%s: unmapped buf %u str_id: %u\n", __func__, buff_id, str_id);
+#endif
+
+out_unlock: mutex_unlock(ctx->mutex);
+	return ret;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vxd_dec.c b/drivers/media/platform/img/vxe-vxd/decoder/vxd_dec.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/vxd_dec.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vxd_dec.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMG DEC SYSDEV and UI Interface function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "core.h"
+#include "h264fw_data.h"
+#include "hevcfw_data.h"
+#include "img_dec_common.h"
+#include "vxd_pvdec_priv.h"
+
+unsigned int get_nbuffers(enum vdec_vid_std std, int w, int h,
+			  unsigned int max_num_ref_frames)
+{
+	unsigned int nbuffers;
+
+	switch (std) {
+	case VDEC_STD_H264:
+		/*
+		 * Request number of buffers from header bspp information
+		 * using formula N + Display Lag
+		 * Parser is passing (2*N)
+		 */
+		if (max_num_ref_frames == 0) {
+			nbuffers = DISPLAY_LAG + min(MAX_CAPBUFS_H264,
+					(184320 / ((w / 16) * (h / 16))));
+		} else {
+			nbuffers = max_num_ref_frames + DISPLAY_LAG;
+		}
+		break;
+	case VDEC_STD_HEVC:
+		if (max_num_ref_frames == 0) {
+			if ((w * h) <= (HEVC_MAX_LUMA_PS >> 2))
+				nbuffers = 16;
+			else if ((w * h) <= (HEVC_MAX_LUMA_PS >> 1))
+				nbuffers = 12;
+			else if ((w * h) <= ((3 * HEVC_MAX_LUMA_PS) >> 2))
+				nbuffers = 8;
+			else
+				nbuffers = 6;
+			nbuffers += DISPLAY_LAG;
+		} else {
+			nbuffers = max_num_ref_frames + DISPLAY_LAG;
+		}
+		break;
+#ifdef HAS_JPEG
+	case VDEC_STD_JPEG:
+		/*
+		 * Request number of output buffers based on h264 spec
+		 * + display delay
+		 */
+		nbuffers = DISPLAY_LAG + min(MAX_CAPBUFS_H264,
+				(184320 / ((w / 16) * (h / 16))));
+		break;
+#endif
+	default:
+		nbuffers = 0;
+	}
+
+	return nbuffers;
+}
+
+int vxd_dec_alloc_bspp_resource(struct vxd_dec_ctx *ctx, enum vdec_vid_std vid_std)
+{
+	struct vxd_dev *vxd_dev = ctx->dev;
+	struct device *dev = vxd_dev->v4l2_dev.dev;
+	struct vdec_buf_info buf_info;
+	struct bspp_ddbuf_array_info *fw_sequ = ctx->fw_sequ;
+	struct bspp_ddbuf_array_info *fw_pps = ctx->fw_pps;
+	int attributes = 0, heap_id = 0, size = 0;
+	int i, ret = 0;
+
+	attributes = SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE |
+		SYS_MEMATTRIB_INTERNAL | SYS_MEMATTRIB_CPU_WRITE;
+	heap_id = vxd_g_internal_heap_id();
+
+	size = vid_std == VDEC_STD_HEVC ?
+		sizeof(struct hevcfw_sequence_ps) : sizeof(struct h264fw_sequence_ps);
+
+#ifdef HAS_JPEG
+	if (vid_std == VDEC_STD_JPEG)
+		size = sizeof(struct vdec_jpeg_sequ_hdr_info);
+#endif
+
+	for (i = 0; i < MAX_SEQUENCES; i++) {
+		ret = img_mem_alloc(vxd_dev->dev, ctx->mem_ctx, heap_id,
+				    size, (enum mem_attr)attributes,
+				    (int *)&fw_sequ[i].ddbuf_info.buf_id);
+		if (ret) {
+			dev_err(dev, "Couldn't allocate sequ buffer %d\n", i);
+			return -ENOMEM;
+		}
+		ret = img_mem_map_km(ctx->mem_ctx, fw_sequ[i].ddbuf_info.buf_id);
+		if (ret) {
+			dev_err(dev, "Couldn't map sequ buffer %d\n", i);
+			return -ENOMEM;
+		}
+		fw_sequ[i].ddbuf_info.cpu_virt_addr = img_mem_get_kptr
+							(ctx->mem_ctx,
+							 fw_sequ[i].ddbuf_info.buf_id);
+		fw_sequ[i].buf_offset = 0;
+		fw_sequ[i].buf_element_size = size;
+		fw_sequ[i].ddbuf_info.buf_size = size;
+		fw_sequ[i].ddbuf_info.mem_attrib = (enum sys_emem_attrib)attributes;
+		memset(fw_sequ[i].ddbuf_info.cpu_virt_addr, 0, size);
+
+		buf_info.cpu_linear_addr =
+			fw_sequ[i].ddbuf_info.cpu_virt_addr;
+		buf_info.buf_size = size;
+		buf_info.fd = -1;
+		buf_info.buf_id = fw_sequ[i].ddbuf_info.buf_id;
+		buf_info.mem_attrib =
+			(enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE |
+			SYS_MEMATTRIB_INPUT | SYS_MEMATTRIB_CPU_WRITE);
+
+		ret = core_stream_map_buf(ctx->res_str_id, VDEC_BUFTYPE_BITSTREAM, &buf_info,
+					  &fw_sequ[i].ddbuf_info.bufmap_id);
+		if (ret) {
+			dev_err(dev, "sps core_stream_map_buf failed\n");
+			return ret;
+		}
+	}
+
+#ifdef HAS_JPEG
+	if (vid_std == VDEC_STD_JPEG)
+		return 0;
+#endif
+
+	size = vid_std == VDEC_STD_HEVC ?
+		sizeof(struct hevcfw_picture_ps) : sizeof(struct h264fw_picture_ps);
+
+	for (i = 0; i < MAX_PPSS; i++) {
+		ret = img_mem_alloc(vxd_dev->dev, ctx->mem_ctx, heap_id, size,
+				    (enum mem_attr)attributes,
+				    (int *)&fw_pps[i].ddbuf_info.buf_id);
+		if (ret) {
+			dev_err(dev, "Couldn't allocate sequ buffer %d\n", i);
+			return -ENOMEM;
+		}
+		ret = img_mem_map_km(ctx->mem_ctx, fw_pps[i].ddbuf_info.buf_id);
+		if (ret) {
+			dev_err(dev, "Couldn't map sequ buffer %d\n", i);
+			return -ENOMEM;
+		}
+		fw_pps[i].ddbuf_info.cpu_virt_addr = img_mem_get_kptr(ctx->mem_ctx,
+								      fw_pps[i].ddbuf_info.buf_id);
+		fw_pps[i].buf_offset = 0;
+		fw_pps[i].buf_element_size = size;
+		fw_pps[i].ddbuf_info.buf_size = size;
+		fw_pps[i].ddbuf_info.mem_attrib = (enum sys_emem_attrib)attributes;
+		memset(fw_pps[i].ddbuf_info.cpu_virt_addr, 0, size);
+
+		buf_info.cpu_linear_addr =
+			fw_pps[i].ddbuf_info.cpu_virt_addr;
+		buf_info.buf_size = size;
+		buf_info.fd = -1;
+		buf_info.buf_id = fw_pps[i].ddbuf_info.buf_id;
+		buf_info.mem_attrib =
+			(enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE |
+			SYS_MEMATTRIB_INPUT | SYS_MEMATTRIB_CPU_WRITE);
+
+		ret = core_stream_map_buf(ctx->res_str_id, VDEC_BUFTYPE_BITSTREAM, &buf_info,
+					  &fw_pps[i].ddbuf_info.bufmap_id);
+		if (ret) {
+			dev_err(dev, "pps core_stream_map_buf failed\n");
+			return ret;
+		}
+	}
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vxd_dec.h b/drivers/media/platform/img/vxe-vxd/decoder/vxd_dec.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vxd_dec.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vxd_dec.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,512 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * IMG DEC SYSDEV and UI Interface header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#ifndef _VXD_DEC_H
+#define _VXD_DEC_H
+
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <linux/types.h>
+
+#include "bspp.h"
+#include "img_dec_common.h"
+#include "img_mem_man.h"
+#include "img_pixfmts.h"
+#include "pixel_api.h"
+#include "vdecdd_defs.h"
+#include "vdec_defs.h"
+#include "work_queue.h"
+
+#define VXD_MIN_STREAM_ID 1
+#define VXD_MAX_STREAMS_PER_DEV 254
+#define VXD_MAX_STREAM_ID (VXD_MIN_STREAM_ID + VXD_MAX_STREAMS_PER_DEV)
+
+#define CODEC_NONE -1
+#define CODEC_H264_DEC 0
+#define CODEC_MPEG4_DEC 1
+#define CODEC_VP8_DEC 2
+#define CODEC_VC1_DEC 3
+#define CODEC_MPEG2_DEC 4
+#define CODEC_JPEG_DEC 5
+#define CODEC_VP9_DEC 6
+#define CODEC_HEVC_DEC 7
+
+#define MAX_SEGMENTS 6
+#define HW_ALIGN 64
+
+#define MAX_BUF_TRACE 30
+
+#define MAX_CAPBUFS_H264 16
+#define DISPLAY_LAG 3
+#define HEVC_MAX_LUMA_PS 35651584
+
+#define MAX_PLANES 3
+
+enum {
+	Q_DATA_SRC         = 0,
+	Q_DATA_DST         = 1,
+	Q_DATA_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum {
+	IMG_DEC_FMT_TYPE_CAPTURE     = 0x01,
+	IMG_DEC_FMT_TYPE_OUTPUT      = 0x10,
+	IMG_DEC_FMT_TYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum vxd_map_flags {
+	VXD_MAP_FLAG_NONE        = 0x0,
+	VXD_MAP_FLAG_READ_ONLY   = 0x1,
+	VXD_MAP_FLAG_WRITE_ONLY  = 0x2,
+	VXD_MAP_FLAG_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * struct vxd_fw_msg - This structure holds the information about the message
+ *                     exchanged in read/write between Kernel and firmware.
+ *
+ * @out_flags: indicating the type of message
+ * @payload_size: size of payload in bytes
+ * @payload: data which is send to firmware
+ */
+struct vxd_fw_msg {
+	unsigned int out_flags;
+	unsigned int payload_size;
+	unsigned int payload[0];
+};
+
+/* HW state */
+struct vxd_hw_state {
+	unsigned int fw_counter;
+	unsigned int fe_status[VXD_MAX_PIPES];
+	unsigned int be_status[VXD_MAX_PIPES];
+	unsigned int dmac_status[VXD_MAX_PIPES][2]; /* Cover DMA chan 2/3*/
+	unsigned int irq_status;
+};
+
+/*
+ * struct vxd_state - contains VXD HW state
+ *
+ * @hw_state: HW state
+ * @msg_id_tail: msg id of the oldest item being processed
+ */
+struct vxd_state {
+	struct vxd_hw_state hw_state;
+	unsigned short msg_id_tail;
+};
+
+/*
+ * struct vxd_dec_fmt - contains info for each of the supported video format
+ *
+ * @fourcc: V4L2 pixel format FCC identifier
+ * @num_planes: number of planes required for luma and chroma
+ * @type: CAPTURE or OUTPUT
+ * @std: VDEC video standard
+ * @pixfmt: IMG pixel format
+ * @interleave: Chroma interleave order
+ * @idc: Chroma format
+ * @size_num: Numberator used to calculate image size
+ * @size_den: Denominator used to calculate image size
+ * @bytes_pp: Bytes per pixel for this format
+ */
+struct vxd_dec_fmt {
+	unsigned int fourcc;
+	unsigned int num_planes;
+	unsigned char type;
+	enum vdec_vid_std std;
+	enum img_pixfmt pixfmt;
+	enum pixel_chroma_interleaved interleave;
+	enum pixel_fmt_idc idc;
+	int size_num;
+	int size_den;
+	int bytes_pp;
+};
+
+/*
+ * struct vxd_item - contains information about the item sent to fw
+ *
+ * @list: item to be linked list to items_done, msgs, or pend.
+ * @stream_id: stream id
+ * @msg_id: message id
+ * @destroy: item belongs to the stream which is destroyed
+ * @msg: contains msg between kernel and fw
+ */
+struct vxd_item {
+	struct list_head list;
+	unsigned int stream_id;
+	unsigned int msg_id;
+	struct {
+		unsigned destroy : 1;
+	};
+	struct vxd_fw_msg msg;
+};
+
+enum vxd_cb_type {
+	VXD_CB_STRUNIT_PROCESSED,
+	VXD_CB_SPS_RELEASE,
+	VXD_CB_PPS_RELEASE,
+	VXD_CB_PICT_DECODED,
+	VXD_CB_PICT_DISPLAY,
+	VXD_CB_PICT_RELEASE,
+	VXD_CB_PICT_END,
+	VXD_CB_STR_END,
+	VXD_CB_ERROR_FATAL,
+	VXD_CB_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * vxd_cb - Return a resource to vxd
+ *
+ * @ctx: the vxd stream context
+ * @type: the type of message
+ * @buf_map_id: the buf_map_id of the resource being returned
+ */
+typedef void (*vxd_cb)(void *ctx, enum vxd_cb_type type, unsigned int buf_map_id,
+						unsigned int error_code);
+
+/*
+ * struct vxd_return - contains information about items returning from core
+ *
+ * @type: Type of item being returned
+ * @buf_map_id: mmu mapped id of buffer being returned
+ */
+struct vxd_return {
+	void *work;
+	struct vxd_dec_ctx *ctx;
+	enum vxd_cb_type type;
+	unsigned int buf_map_id;
+};
+
+/*
+ * struct vxd_dec_q_data - contains queue data information
+ *
+ * @fmt: format info
+ * @width: frame width
+ * @height: frame height
+ * @bytesperline: bytes per line in memory
+ * @size_image: image size in memory
+ */
+struct vxd_dec_q_data {
+	struct vxd_dec_fmt *fmt;
+	unsigned int width;
+	unsigned int height;
+	unsigned int bytesperline[MAX_PLANES];
+	unsigned int size_image[MAX_PLANES];
+};
+
+/*
+ * struct time_prof - contains time taken by decoding information
+ *
+ * @id: id info
+ * @start_time: start time
+ * @end_time: end time
+ */
+struct time_prof {
+	unsigned int id;
+	long long start_time;
+	long long end_time;
+};
+
+/*
+ * struct vxd_dev - The struct containing decoder driver internal parameters.
+ *
+ * @v4l2_dev: main struct of V4L2 device drivers
+ * @dev: platform device driver
+ * @vfd_dec: video device structure to create and manage the V4L2 device node.
+ * @plat_dev: linux platform device
+ * @struct v4l2_m2m_dev: mem2mem device
+ * @mutex: mutex to protect certain ongoing operation.
+ * @module_irq: a threaded request IRQ for the device
+ * @reg_base: base address of the IMG VXD hw registers
+ * @props: contains HW properties
+ * @mmu_config_addr_width: indicates the number of extended address bits
+ *                         (above 32) that the external memory interface
+ *                         uses, based on EXTENDED_ADDR_RANGE field of
+ *                         MMU_CONFIG0
+ * @rendec_buf_id: buffer id for rendec buffer allocation
+ * @firmware: firmware information based on vxd_dev_fw structure
+ * @firmware_loading_complete: loading completion
+ * @no_fw: Just to check if firmware is present in /lib
+ * @fw_refcnt: firmware reference counter
+ * @hw_on: indication if hw is on or off
+ * @hw_dead: indication if hw is dead
+ * @lock: basic primitive for locking through spinlock
+ * @state: internal state handling of vxd state
+ * @msgs: linked list of msgs with vxd_item
+ * @pend: linked list of pending msgs to be sent to fw
+ * @msg_cnt: counter of messages submitted to VXD. Wraps every VXD_MSG_ID_MASK
+ * @freq_khz: Core clock frequency measured during boot of firmware
+ * @streams: unique id for the stream
+ * @mem_ctx: memory management context for HW buffers
+ * @dwork: use for Power Management and Watchdog
+ * @work_sched_at: the time of the last work has been scheduled at
+ * @emergency: indicates if emergency condition occurred
+ * @dbgfs_ctx: pointer to debug FS context.
+ * @hw_pm_delay: delay before performaing PM
+ * @hw_dwr_period: period for checking for dwr
+ * @pm_start: time, in jiffies, when core become idle
+ * @dwr_start: time, in jiffies, when dwr has been started
+ */
+struct vxd_dev {
+	struct v4l2_device v4l2_dev;
+	void *dev;
+	struct video_device *vfd_dec;
+	struct platform_device *plat_dev;
+	struct v4l2_m2m_dev *m2m_dev;
+	struct mutex  *mutex; /* Per device mutex */
+	struct mutex  *mutex_queue; /* Mutex for ioctl synchronization on queue */
+	int module_irq;
+	void __iomem *reg_base;
+	struct vxd_core_props props;
+	unsigned int mmu_config_addr_width;
+	int rendec_buf_id;
+	struct vxd_dev_fw firmware;
+	void *firmware_loading_complete;
+	unsigned char no_fw;
+	unsigned char fw_refcnt;
+	unsigned int hw_on;
+	unsigned int hw_dead;
+	void *lock; /* basic device level spinlock */
+	struct vxd_state state;
+	struct list_head msgs;
+	struct list_head pend;
+	int msg_cnt;
+	unsigned int freq_khz;
+	struct idr *streams;
+	struct mem_ctx *mem_ctx;
+	void *dwork;
+	unsigned long long work_sched_at;
+	unsigned int emergency;
+	void *dbgfs_ctx;
+	unsigned int hw_pm_delay;
+	unsigned int hw_dwr_period;
+	unsigned long long pm_start;
+	unsigned long long dwr_start;
+	struct time_prof time_fw[MAX_BUF_TRACE];
+	struct time_prof time_drv[MAX_BUF_TRACE];
+
+	/* The variables defined below are used in RTOS only. */
+	/* This variable holds queue handler */
+	void *vxd_worker_queue_handle;
+	void *vxd_worker_queue_sem_handle;
+};
+
+/*
+ * struct vxd_stream - holds stream-related info
+ *
+ * @ctx: associated vxd_dec_ctx
+ * @mmu_ctx: MMU context for this stream
+ * @ptd: ptd for the stream
+ * @id: unique stream id
+ */
+struct vxd_stream {
+	struct vxd_dec_ctx *ctx;
+	struct mmu_ctx *mmu_ctx;
+	unsigned int ptd;
+	unsigned int id;
+};
+
+
+/*
+ * struct vxd_buffer - holds per buffer info.
+ * @buffer: the vb2_v4l2_buffer
+ * @list: list head for gathering in linked list
+ * @mapped: is this buffer mapped yet
+ * @reuse: is the buffer ready for reuse
+ * @buf_map_id: the mapped buffer id
+ * @buf_info: the buffer info for submitting to map
+ * @bstr_info: the buffer info for submitting to bspp
+ * @seq_unit: the str_unit for submitting sps
+ * @seq_unit: the str_unit for submitting pps and segments
+ * @seq_unit: the str_unit for submitting picture_end
+ */
+struct vxd_buffer {
+	struct v4l2_m2m_buffer buffer;
+	struct list_head list;
+	unsigned char mapped;
+	unsigned char reuse;
+	unsigned int buf_map_id;
+	struct vxd_mapping *mapping;
+	struct vdec_buf_info buf_info;
+	struct bspp_ddbuf_info bstr_info;
+	struct vdecdd_str_unit seq_unit;
+	struct vdecdd_str_unit pic_unit;
+	struct vdecdd_str_unit end_unit;
+	struct bspp_preparsed_data preparsed_data;
+};
+
+struct vxd_mapping {
+	struct list_head list;
+	unsigned int buf_map_id;
+	unsigned char reuse;
+	unsigned long dma_addr;
+	struct vxd_buffer *buf; /* point to the mapped buffer */
+};
+
+typedef void (*decode_cb)(int res_str_id, unsigned int *msg, unsigned int msg_size,
+			  unsigned int msg_flags);
+
+/*
+ * struct vxd_dec_ctx - holds per stream data. Each playback has its own
+ *                      vxd_dec_ctx
+ *
+ * @fh: V4L2 file handler
+ * @dev: pointer to the device main information.
+ * @ctrl_hdl_dec: v4l2 custom control command for video decoder
+ * @mem_ctx: mem context for this stream
+ * @mmu_ctx: MMU context for this stream
+ * @ptd: page table information
+ * @items_done: linked list of items is ready
+ * @width: frame width
+ * @height: frame height
+ * @width_orig: original frame width (before padding)
+ * @height_orig: original frame height (before padding)
+ * @q_data: Queue data information of src[0] and dst[1]
+ * @stream: stream-related info
+ * @work: work queue for message handling
+ * @return_queue: list of resources returned from core
+ * @out_buffers: list of all output buffers
+ * @cap_buffers: list of all capture buffers except those in reuse_queue
+ * @cap_mappings: list of all capture buffers mapped to HW
+ * @reuse_queue: list of capture buffers waiting for core to signal reuse
+ * @res_str_id: Core stream id
+ * @stream_created: Core stream is created
+ * @stream_configured: Core stream is configured
+ * @opconfig_pending: Core opconfig is pending stream_create
+ * @src_streaming: V4L2 src stream is streaming
+ * @dst_streaming: V4L2 dst stream is streaming
+ * @core_streaming: core is streaming
+ * @aborting: signal job abort on next irq
+ * @str_opcfg: core output config
+ * @pict_bufcfg: core picture buffer config
+ * @bspp_context: BSPP Stream context handle
+ * @seg_list: list of bspp_bitstr_seg for submitting to BSPP
+ * @fw_sequ: BSPP sps resource
+ * @fw_pps: BSPP pps resource
+ * @cb: registered callback for incoming messages
+ * @mutex: mutex to protect context specific state machine
+ */
+struct vxd_dec_ctx {
+	struct v4l2_fh fh;
+	struct vxd_dev *dev;
+	struct mem_ctx *mem_ctx;
+	struct mmu_ctx *mmu_ctx;
+	unsigned int ptd;
+	struct list_head items_done;
+	unsigned int width;
+	unsigned int height;
+	unsigned int width_orig;
+	unsigned int height_orig;
+	struct vxd_dec_q_data q_data[2];
+	struct vxd_stream stream;
+	void *work;
+	struct list_head return_queue;
+	struct list_head out_buffers;
+	struct list_head cap_buffers;
+	struct list_head cap_mappings;
+	struct list_head reuse_queue;
+	unsigned int res_str_id;
+	unsigned char stream_created;
+	unsigned char stream_configured;
+	unsigned char opconfig_pending;
+	unsigned char src_streaming;
+	unsigned char dst_streaming;
+	unsigned char core_streaming;
+	unsigned char aborting;
+	unsigned char eos;
+	unsigned char stop_initiated;
+	unsigned char flag_last;
+	unsigned char num_decoding;
+	unsigned int max_num_ref_frames;
+	unsigned int cap_seq; /* sequence number for capture port */
+	unsigned int out_seq; /* sequence number for output port */
+	struct vdec_str_opconfig str_opcfg;
+	struct vdec_pict_bufconfig pict_bufcfg;
+
+	struct vdec_comsequ_hdrinfo comseq_hdr_info;
+	struct vdec_str_configdata strcfgdata;
+	struct vdecdd_dddev_context     *dev_ctx;
+
+	struct v4l2_ctrl_handler v4l2_ctrl_hdl;
+
+	/* The following are parameters from V4L2 extra-controls */
+
+	/*
+	 * used by the IMG firmware to constrain DPB's utilized
+	 * a value of 0 indicates to let the firmware decide
+	 */
+	unsigned int max_dec_frame_buffering;
+	int override_spec_dpb_buffers;
+	int img_extra_decode_buffers;
+	unsigned int display_pipeline_size;
+
+	void *bspp_context;
+	struct bspp_bitstr_seg bstr_segments[MAX_SEGMENTS];
+	struct lst_t seg_list;
+	struct bspp_ddbuf_array_info fw_sequ[MAX_SEQUENCES];
+	struct bspp_ddbuf_array_info fw_pps[MAX_PPSS];
+	decode_cb cb;
+	struct mutex *mutex; /* Per stream mutex */
+	struct mutex *mutex2; /* used as a sequencing mutex, so device_run runs to completion */
+
+	/* The below variable used only in Rtos */
+	void *mm_return_resource; /* Place holder for CB to application */
+	void *stream_worker_queue_handle;
+	void *stream_worker_queue_sem_handle;
+	// lock is used to synchronize the stream worker and process function
+	void *lock;
+	/* "sem_eos" this semaphore variable used to wait until all frame decoded */
+	void *sem_eos;
+};
+
+irqreturn_t vxd_handle_irq(void *dev);
+irqreturn_t vxd_handle_thread_irq(void *dev);
+int vxd_init(void *dev, struct vxd_dev *vxd, const struct heap_config heap_configs[], int heaps);
+int vxd_g_internal_heap_id(void);
+void vxd_deinit(struct vxd_dev *vxd);
+int vxd_prepare_fw(struct vxd_dev *vxd);
+void vxd_clean_fw_resources(struct vxd_dev *vxd);
+int vxd_send_msg(struct vxd_dec_ctx *ctx, struct vxd_fw_msg *msg);
+int vxd_suspend_dev(void *dev);
+int vxd_resume_dev(void *dev);
+
+int vxd_create_ctx(struct vxd_dev *vxd, struct vxd_dec_ctx *ctx);
+void vxd_destroy_ctx(struct vxd_dev *vxd, struct vxd_dec_ctx *ctx);
+
+int vxd_map_buffer_sg(struct vxd_dev *vxd, struct vxd_dec_ctx *ctx,
+		      unsigned int str_id, unsigned int buff_id,
+		      void *sgt, unsigned int virt_addr,
+		      unsigned int map_flags);
+int vxd_map_buffer(struct vxd_dev *vxd, struct vxd_dec_ctx *ctx, unsigned int str_id,
+		   unsigned int buff_id, unsigned int virt_addr, unsigned int map_flags);
+int vxd_unmap_buffer(struct vxd_dev *vxd, struct vxd_dec_ctx *ctx,
+		     unsigned int str_id, unsigned int buff_id);
+
+unsigned int get_nbuffers(enum vdec_vid_std std, int w, int h, unsigned int max_num_ref_frames);
+
+int vxd_dec_alloc_bspp_resource(struct vxd_dec_ctx *ctx, enum vdec_vid_std vid_std);
+
+#ifdef ERROR_RECOVERY_SIMULATION
+/* sysfs read write functions */
+ssize_t vxd_sysfs_show(struct kobject *vxd_dec_kobject,
+		       struct kobj_attribute *attr, char *buf);
+
+ssize_t vxd_sysfs_store(struct kobject *vxd_dec_kobject,
+			struct kobj_attribute *attr, const char *buf, unsigned long count);
+#endif
+#endif /* _VXD_DEC_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vxd_ext.h b/drivers/media/platform/img/vxe-vxd/decoder/vxd_ext.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vxd_ext.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vxd_ext.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD DEC Low-level device interface component
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ */
+
+#ifndef _VXD_EXT_H
+#define _VXD_EXT_H
+
+#define VLR_COMPLETION_COMMS_AREA_SIZE             476
+
+/* Word Size of buffer used to pass messages between LISR and HISR */
+#define VXD_SIZE_MSG_BUFFER   (1 * 1024)
+
+/* This structure describes macroblock coordinates. */
+struct vxd_mb_coords {
+	unsigned int x;
+	unsigned int y;
+};
+
+/* This structure contains firmware and decoding pipe state information. */
+struct vxd_pipestate {
+	unsigned char is_pipe_present;
+	unsigned char cur_codec;
+	unsigned int acheck_point[VDECFW_CHECKPOINT_MAX];
+	unsigned int firmware_action;
+	unsigned int fe_slices;
+	unsigned int be_slices;
+	unsigned int fe_errored_slices;
+	unsigned int be_errored_slices;
+	unsigned int be_mbs_dropped;
+	unsigned int be_mbs_recovered;
+	struct vxd_mb_coords fe_mb;
+	struct vxd_mb_coords be_mb;
+};
+
+/* This structure contains firmware and decoder core state information. */
+struct vxd_firmware_state {
+	unsigned int fw_step;
+	struct vxd_pipestate pipe_state[VDECFW_MAX_DP];
+};
+
+/* This structure contains the video decoder device state. */
+struct vxd_states {
+	struct vxd_firmware_state fw_state;
+};
+
+struct vxd_pict_attrs {
+	unsigned int dwrfired;
+	unsigned int mmufault;
+	unsigned int deverror;
+};
+
+/* This type defines the message attributes. */
+enum vxd_msg_attr {
+	VXD_MSG_ATTR_NONE        = 0,
+	VXD_MSG_ATTR_DECODED     = 1,
+	VXD_MSG_ATTR_FATAL       = 2,
+	VXD_MSG_ATTR_CANCELED    = 3,
+	VXD_MSG_ATTR_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum vxd_msg_flag {
+	VXD_MSG_FLAG_DROP        = 0,
+	VXD_MSG_FLAG_EXCL        = 1,
+	VXD_MSG_FLAG_FORCE32BITS = 0x7FFFFFFFU
+};
+
+#endif /* VXD_EXT_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vxd_int.c b/drivers/media/platform/img/vxe-vxd/decoder/vxd_int.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/vxd_int.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vxd_int.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1137 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VXD DEC Common low level core interface component
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "bspp.h"
+#include "fw_interface.h"
+#include "h264fw_data.h"
+#include "img_errors.h"
+#include "img_dec_common.h"
+#include "img_pvdec_core_regs.h"
+#include "img_pvdec_pixel_regs.h"
+#include "img_pvdec_test_regs.h"
+#include "img_vdec_fw_msg.h"
+#include "img_video_bus4_mmu_regs.h"
+#include "img_msvdx_core_regs.h"
+#include "img_msvdx_cmds.h"
+#include "reg_io2.h"
+#include "scaler_setup.h"
+#include "vdecdd_defs.h"
+#include "vdecdd_utils.h"
+#include "vdecfw_shared.h"
+#include "vdec_defs.h"
+#include "vxd_ext.h"
+#include "vxd_int.h"
+#include "vxd_props.h"
+
+#define MSVDX_CACHE_REF_OFFSET_V100     (72L)
+#define MSVDX_CACHE_ROW_OFFSET_V100     (4L)
+
+#define MSVDX_CACHE_REF_OFFSET_V550     (144L)
+#define MSVDX_CACHE_ROW_OFFSET_V550     (8L)
+
+#define GET_BITS(v, lb, n)       (((v) >> (lb)) & ((1 << (n)) - 1))
+#define IS_PVDEC_PIPELINE(std)   ((std) == VDEC_STD_HEVC ? 1 : 0)
+
+static int amsvdx_codecmode[VDEC_STD_MAX] = {
+	/* Invalid */
+	-1,
+	/* MPEG2 */
+	3,
+	/* MPEG4 */
+	4,
+	/* H263 */
+	4,
+	/* H264 */
+	1,
+	/* VC1 */
+	2,
+	/* AVS */
+	5,
+	/* RealVideo (8) */
+	8,
+	/* JPEG */
+	0,
+	/* On2 VP6 */
+	10,
+	/* On2 VP8 */
+	11,
+	/* Invalid */
+#ifdef HAS_VP9
+	/* On2 VP9 */
+	13,
+#endif
+	/* Sorenson */
+	4,
+	/* HEVC */
+	12,
+};
+
+struct msvdx_scaler_coeff_cmds {
+	unsigned int acmd_horizluma_coeff[VDECFW_NUM_SCALE_COEFFS];
+	unsigned int acmd_vertluma_coeff[VDECFW_NUM_SCALE_COEFFS];
+	unsigned int acmd_horizchroma_coeff[VDECFW_NUM_SCALE_COEFFS];
+	unsigned int acmd_vertchroma_coeff[VDECFW_NUM_SCALE_COEFFS];
+};
+
+static struct vxd_vidstd_props astd_props[] = {
+	{ VDEC_STD_MPEG2, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8,
+	  PIXEL_FORMAT_420 },
+	{ VDEC_STD_MPEG4, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8,
+	  PIXEL_FORMAT_420 },
+	{ VDEC_STD_H263, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8,
+	  PIXEL_FORMAT_420 },
+	{ VDEC_STD_H264, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0x10000, 8,
+	  8, PIXEL_FORMAT_420 },
+	{ VDEC_STD_VC1, CORE_REVISION(7, 0, 0), 80, 16, 4096, 4096, 0, 8, 8,
+	  PIXEL_FORMAT_420 },
+	{ VDEC_STD_AVS, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8,
+	  PIXEL_FORMAT_420 },
+	{ VDEC_STD_REAL, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8,
+	  PIXEL_FORMAT_420 },
+	{ VDEC_STD_JPEG, CORE_REVISION(7, 0, 0), 64, 16, 32768, 32768, 0, 8, 8,
+	  PIXEL_FORMAT_444 },
+	{ VDEC_STD_VP6, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8,
+	  PIXEL_FORMAT_420 },
+	{ VDEC_STD_VP8, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8, 8,
+	  PIXEL_FORMAT_420 },
+	{ VDEC_STD_SORENSON, CORE_REVISION(7, 0, 0), 64, 16, 4096, 4096, 0, 8,
+	  8, PIXEL_FORMAT_420 },
+	{ VDEC_STD_HEVC, CORE_REVISION(7, 0, 0), 64, 16, 8192, 8192, 0, 8, 8,
+	  PIXEL_FORMAT_420 },
+};
+
+enum vdec_msvdx_async_mode {
+	VDEC_MSVDX_ASYNC_NORMAL,
+	VDEC_MSVDX_ASYNC_VDMC,
+	VDEC_MSVDX_ASYNC_VDEB,
+	VDEC_MSVDX_ASYNC_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* MSVDX row strides for video buffers. */
+static const unsigned int amsvdx_64byte_row_stride[] = {
+	384, 768, 1280, 1920, 512, 1024, 2048, 4096
+};
+
+/* MSVDX row strides for jpeg buffers. */
+static const unsigned int amsvdx_jpeg_row_stride[] = {
+	256, 384, 512, 768, 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 32768
+};
+
+/* VXD Core major revision. */
+static unsigned int maj_rev;
+/* VXD Core minor revision. */
+static unsigned int min_rev;
+/* VXD Core maintenance revision. */
+static unsigned int maint_rev;
+
+static int get_stride_code(enum vdec_vid_std vidstd, unsigned int row_stride)
+{
+	unsigned int i;
+
+	if (vidstd == VDEC_STD_JPEG) {
+		for (i = 0; i < (sizeof(amsvdx_jpeg_row_stride) /
+			sizeof(amsvdx_jpeg_row_stride[0])); i++) {
+			if (amsvdx_jpeg_row_stride[i] == row_stride)
+				return i;
+		}
+	} else {
+		for (i = 0; i < (sizeof(amsvdx_64byte_row_stride) /
+			sizeof(amsvdx_64byte_row_stride[0])); i++) {
+			if (amsvdx_64byte_row_stride[i] == row_stride)
+				return i;
+		}
+	}
+
+	return -1;
+}
+
+/* Obtains the hardware defined video profile. */
+static unsigned int vxd_getprofile(enum vdec_vid_std vidstd, unsigned int std_profile)
+{
+	unsigned int profile = 0;
+
+	switch (vidstd) {
+	case VDEC_STD_H264:
+		switch (std_profile) {
+		case H264_PROFILE_BASELINE:
+			profile = 0;
+			break;
+
+		/*
+		 * Extended may be attempted as Baseline or
+		 * Main depending on the constraint_set_flags
+		 */
+		case H264_PROFILE_EXTENDED:
+		case H264_PROFILE_MAIN:
+			profile = 1;
+			break;
+
+		case H264_PROFILE_HIGH:
+		case H264_PROFILE_HIGH444:
+		case H264_PROFILE_HIGH422:
+		case H264_PROFILE_HIGH10:
+		case H264_PROFILE_CAVLC444:
+		case H264_PROFILE_MVC_HIGH:
+		case H264_PROFILE_MVC_STEREO:
+			profile = 2;
+			break;
+		default:
+			profile = 2;
+			break;
+		}
+		break;
+
+	default:
+		profile = 0;
+		break;
+	}
+
+	return profile;
+}
+
+static int vxd_getcoreproperties(struct vxd_coreprops *coreprops,
+				 unsigned int corerev,
+				 unsigned int pvdec_coreid, unsigned int mmu_config0,
+				 unsigned int mmu_config1, unsigned int *pixel_pipecfg,
+				 unsigned int *pixel_misccfg, unsigned int max_framecfg)
+{
+	unsigned int group_id;
+	unsigned int core_id;
+	unsigned int core_config;
+	unsigned int extended_address_range;
+	unsigned char group_size = 0;
+	unsigned char pipe_minus1 = 0;
+	unsigned int max_h264_hw_chromaformat = 0;
+	unsigned int max_hevc_hw_chromaformat = 0;
+	unsigned int max_bitdepth_luma = 0;
+	unsigned int i;
+
+	struct pvdec_core_rev core_rev;
+
+	if (!coreprops || !pixel_pipecfg || !pixel_misccfg)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* PVDEC Core Revision Information */
+	core_rev.maj_rev = REGIO_READ_FIELD(corerev, PVDEC_CORE, CR_PVDEC_CORE_REV,
+					    CR_PVDEC_MAJOR_REV);
+	core_rev.min_rev = REGIO_READ_FIELD(corerev, PVDEC_CORE, CR_PVDEC_CORE_REV,
+					    CR_PVDEC_MINOR_REV);
+	core_rev.maint_rev = REGIO_READ_FIELD(corerev, PVDEC_CORE, CR_PVDEC_CORE_REV,
+					      CR_PVDEC_MAINT_REV);
+
+	/* core id */
+	group_id = REGIO_READ_FIELD(pvdec_coreid, PVDEC_CORE, CR_PVDEC_CORE_ID, CR_GROUP_ID);
+	core_id = REGIO_READ_FIELD(pvdec_coreid, PVDEC_CORE, CR_PVDEC_CORE_ID, CR_CORE_ID);
+
+	/* Ensure that the core is IMG Video Decoder (PVDEC). */
+	if (group_id != 3 || core_id != 3)
+		return IMG_ERROR_DEVICE_NOT_FOUND;
+
+	core_config = REGIO_READ_FIELD(pvdec_coreid, PVDEC_CORE,
+				       CR_PVDEC_CORE_ID, CR_PVDEC_CORE_CONFIG);
+
+	memset(coreprops, 0, sizeof(*(coreprops)));
+
+	/*  Construct core version name. */
+	snprintf(coreprops->aversion, VER_STR_LEN, "%d.%d.%d",
+		 core_rev.maj_rev, core_rev.min_rev, core_rev.maint_rev);
+
+	coreprops->mmu_support_stride_per_context =
+			REGIO_READ_FIELD(mmu_config1, IMG_VIDEO_BUS4_MMU,
+					 MMU_CONFIG1,
+					 SUPPORT_STRIDE_PER_CONTEXT) == 1 ? 1 : 0;
+
+	coreprops->mmu_support_secure = REGIO_READ_FIELD(mmu_config1, IMG_VIDEO_BUS4_MMU,
+							 MMU_CONFIG1, SUPPORT_SECURE) == 1 ? 1 : 0;
+
+	extended_address_range = REGIO_READ_FIELD(mmu_config0, IMG_VIDEO_BUS4_MMU,
+						  MMU_CONFIG0, EXTENDED_ADDR_RANGE);
+
+	switch (extended_address_range) {
+	case 0:
+		coreprops->mmu_type = MMU_TYPE_32BIT;
+		break;
+	case 4:
+		coreprops->mmu_type = MMU_TYPE_36BIT;
+		break;
+	case 8:
+		coreprops->mmu_type = MMU_TYPE_40BIT;
+		break;
+	default:
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	group_size += REGIO_READ_FIELD(mmu_config0, IMG_VIDEO_BUS4_MMU,
+			MMU_CONFIG0, GROUP_OVERRIDE_SIZE);
+
+	coreprops->num_entropy_pipes = core_config & 0xF;
+	coreprops->num_pixel_pipes = core_config >> 4 & 0xF;
+#ifdef	DEBUG_DECODER_DRIVER
+	pr_info("PVDEC revision %08x detected, id %08x.\n", corerev, core_id);
+	pr_info("Found %d entropy pipe(s), %d pixel pipe(s), %d group size",
+		coreprops->num_entropy_pipes, coreprops->num_pixel_pipes,
+		group_size);
+#endif
+
+	/* Set global rev info variables used by macros */
+	maj_rev = core_rev.maj_rev;
+	min_rev = core_rev.min_rev;
+	maint_rev = core_rev.maint_rev;
+
+	/* Default settings */
+	for (i = 0; i < ARRAY_SIZE(astd_props); i++) {
+		struct vxd_vidstd_props *pvidstd_props =
+			&coreprops->vidstd_props[astd_props[i].vidstd];
+		/*
+		 * Update video standard properties if the core is beyond
+		 * specified version and the properties are for newer cores
+		 * than the previous.
+		 */
+		if (FROM_REV(MAJOR_REVISION((int)astd_props[i].core_rev),
+			     MINOR_REVISION((int)astd_props[i].core_rev),
+			     MAINT_REVISION((int)astd_props[i].core_rev), int) &&
+		    astd_props[i].core_rev >= pvidstd_props->core_rev) {
+			*pvidstd_props = astd_props[i];
+
+			if (pvidstd_props->vidstd != VDEC_STD_JPEG &&
+			    (FROM_REV(8, 0, 0, int)) && (pvidstd_props->vidstd ==
+			    VDEC_STD_HEVC ? 1 : 0)) {
+				/*
+				 * override default values with values
+				 * specified in HW (register does not
+				 * exist in previous cores)
+				 */
+				pvidstd_props->max_width =
+					2 << REGIO_READ_FIELD(max_framecfg,
+						PVDEC_PIXEL,
+						CR_MAX_FRAME_CONFIG,
+						CR_PVDEC_HOR_MSB);
+
+				pvidstd_props->max_height =
+					2 << REGIO_READ_FIELD(max_framecfg,
+						PVDEC_PIXEL,
+						CR_MAX_FRAME_CONFIG,
+						CR_PVDEC_VER_MSB);
+			} else if (pvidstd_props->vidstd != VDEC_STD_JPEG &&
+				(FROM_REV(8, 0, 0, int))) {
+				pvidstd_props->max_width =
+					2 << REGIO_READ_FIELD(max_framecfg,
+						PVDEC_PIXEL,
+						CR_MAX_FRAME_CONFIG,
+						CR_MSVDX_HOR_MSB);
+
+				pvidstd_props->max_height =
+					2 << REGIO_READ_FIELD(max_framecfg,
+						PVDEC_PIXEL,
+						CR_MAX_FRAME_CONFIG,
+						CR_MSVDX_VER_MSB);
+			}
+		}
+	}
+
+	/* Populate the core properties. */
+	if (GET_BITS(core_config, 11, 1))
+		coreprops->hd_support = 1;
+
+	for (pipe_minus1 = 0; pipe_minus1 < coreprops->num_pixel_pipes;
+		pipe_minus1++) {
+		unsigned int current_bitdepth =
+			GET_BITS(pixel_misccfg[pipe_minus1], 4, 3) + 8;
+		unsigned int current_h264_hw_chromaformat =
+			GET_BITS(pixel_misccfg[pipe_minus1], 0, 2);
+		unsigned int current_hevc_hw_chromaformat =
+			GET_BITS(pixel_misccfg[pipe_minus1], 2, 2);
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("cur_bitdepth: %d  cur_h264_hw_chromaformat: %d",
+			current_bitdepth, current_h264_hw_chromaformat);
+		pr_info("cur_hevc_hw_chromaformat: %d  pipe_minus1: %d\n",
+			current_hevc_hw_chromaformat, pipe_minus1);
+#endif
+
+		if (GET_BITS(pixel_misccfg[pipe_minus1], 8, 1))
+			coreprops->rotation_support[pipe_minus1] = 1;
+
+		if (GET_BITS(pixel_misccfg[pipe_minus1], 9, 1))
+			coreprops->scaling_support[pipe_minus1] = 1;
+
+		coreprops->num_streams[pipe_minus1] =
+			GET_BITS(pixel_misccfg[pipe_minus1], 12, 2) + 1;
+
+		/* Video standards. */
+		coreprops->mpeg2[pipe_minus1] =
+			GET_BITS(pixel_pipecfg[pipe_minus1], 0, 1) ? 1 : 0;
+		coreprops->mpeg4[pipe_minus1] =
+			GET_BITS(pixel_pipecfg[pipe_minus1], 1, 1) ? 1 : 0;
+		coreprops->h264[pipe_minus1] =
+			GET_BITS(pixel_pipecfg[pipe_minus1], 2, 1) ? 1 : 0;
+		coreprops->vc1[pipe_minus1] =
+			GET_BITS(pixel_pipecfg[pipe_minus1], 3, 1) ? 1 : 0;
+		coreprops->jpeg[pipe_minus1] =
+			GET_BITS(pixel_pipecfg[pipe_minus1], 5, 1) ? 1 : 0;
+		coreprops->avs[pipe_minus1] =
+			GET_BITS(pixel_pipecfg[pipe_minus1], 7, 1) ? 1 : 0;
+		coreprops->real[pipe_minus1] =
+			GET_BITS(pixel_pipecfg[pipe_minus1], 8, 1) ? 1 : 0;
+		coreprops->vp6[pipe_minus1] =
+			GET_BITS(pixel_pipecfg[pipe_minus1], 9, 1) ? 1 : 0;
+		coreprops->vp8[pipe_minus1] =
+			GET_BITS(pixel_pipecfg[pipe_minus1], 10, 1) ? 1 : 0;
+		coreprops->hevc[pipe_minus1] =
+			GET_BITS(pixel_pipecfg[pipe_minus1], 22, 1) ? 1 : 0;
+
+		max_bitdepth_luma = (max_bitdepth_luma > current_bitdepth ?
+			max_bitdepth_luma : current_bitdepth);
+		max_h264_hw_chromaformat = (max_h264_hw_chromaformat >
+			current_h264_hw_chromaformat ? max_h264_hw_chromaformat
+			: current_h264_hw_chromaformat);
+		max_hevc_hw_chromaformat = (max_hevc_hw_chromaformat >
+			current_hevc_hw_chromaformat ? max_hevc_hw_chromaformat
+			: current_hevc_hw_chromaformat);
+	}
+
+	/* Override default bit-depth with value signalled explicitly by core. */
+	coreprops->vidstd_props[0].max_luma_bitdepth = max_bitdepth_luma;
+	coreprops->vidstd_props[0].max_chroma_bitdepth =
+		coreprops->vidstd_props[0].max_luma_bitdepth;
+
+	for (i = 1; i < VDEC_STD_MAX; i++) {
+		coreprops->vidstd_props[i].max_luma_bitdepth =
+			coreprops->vidstd_props[0].max_luma_bitdepth;
+		coreprops->vidstd_props[i].max_chroma_bitdepth =
+			coreprops->vidstd_props[0].max_chroma_bitdepth;
+	}
+
+	switch (max_h264_hw_chromaformat) {
+	case 1:
+		coreprops->vidstd_props[VDEC_STD_H264].max_chroma_format =
+			PIXEL_FORMAT_420;
+		break;
+
+	case 2:
+		coreprops->vidstd_props[VDEC_STD_H264].max_chroma_format =
+			PIXEL_FORMAT_422;
+		break;
+
+	case 3:
+		coreprops->vidstd_props[VDEC_STD_H264].max_chroma_format =
+			PIXEL_FORMAT_444;
+		break;
+
+	default:
+		break;
+	}
+
+	switch (max_hevc_hw_chromaformat) {
+	case 1:
+		coreprops->vidstd_props[VDEC_STD_HEVC].max_chroma_format =
+			PIXEL_FORMAT_420;
+		break;
+
+	case 2:
+		coreprops->vidstd_props[VDEC_STD_HEVC].max_chroma_format =
+			PIXEL_FORMAT_422;
+		break;
+
+	case 3:
+		coreprops->vidstd_props[VDEC_STD_HEVC].max_chroma_format =
+			PIXEL_FORMAT_444;
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static unsigned char vxd_is_supported_byatleast_onepipe(const unsigned char *features,
+							unsigned int num_pipes)
+{
+	unsigned int i;
+
+	VDEC_ASSERT(features);
+	VDEC_ASSERT(num_pipes <= VDEC_MAX_PIXEL_PIPES);
+
+	for (i = 0; i < num_pipes; i++) {
+		if (features[i])
+			return 1;
+	}
+
+	return 0;
+}
+
+void vxd_set_reconpictcmds(const struct vdecdd_str_unit *str_unit,
+			   const struct vdec_str_configdata *str_configdata,
+			   const struct vdec_str_opconfig *output_config,
+			   const struct vxd_coreprops *coreprops,
+			   const struct vxd_buffers *buffers,
+			   unsigned int *pict_cmds)
+{
+	struct pixel_pixinfo  *pixel_info;
+	unsigned int row_stride_code;
+	unsigned char benable_auxline_buf = 1;
+
+	unsigned int coded_height;
+	unsigned int coded_width;
+	unsigned int disp_height;
+	unsigned int disp_width;
+	unsigned int profile;
+	unsigned char plane;
+	unsigned int y_stride;
+	unsigned int uv_stride;
+	unsigned int v_stride;
+	unsigned int cache_ref_offset;
+	unsigned int cache_row_offset;
+
+	if (str_configdata->vid_std == VDEC_STD_JPEG) {
+		disp_height = 0;
+		disp_width = 0;
+		coded_height = 0;
+		coded_width = 0;
+	} else {
+		coded_height = ALIGN(str_unit->pict_hdr_info->coded_frame_size.height,
+				     (str_unit->pict_hdr_info->field) ?
+				     2 * VDEC_MB_DIMENSION : VDEC_MB_DIMENSION);
+				     /*  Hardware field is coded size - 1 */
+				     coded_height -= 1;
+
+		coded_width = ALIGN(str_unit->pict_hdr_info->coded_frame_size.width,
+				    VDEC_MB_DIMENSION);
+		/*  Hardware field is coded size - 1 */
+		coded_width -= 1;
+
+		disp_height = str_unit->pict_hdr_info->disp_info.enc_disp_region.height
+			+ str_unit->pict_hdr_info->disp_info.enc_disp_region.left_offset - 1;
+		disp_width = str_unit->pict_hdr_info->disp_info.enc_disp_region.width +
+			str_unit->pict_hdr_info->disp_info.enc_disp_region.top_offset - 1;
+	}
+	/*
+	 * Display picture size (DISPLAY_PICTURE)
+	 * The display to be written is not the actual video size to be
+	 * displayed but a number that has to differ from the coded pixel size
+	 * by less than 1MB (coded_size-display_size <= 0x0F). Because H264 can
+	 * have a different display size, we need to check and write
+	 * the coded_size again in the display_size register if this condition
+	 * is not fulfilled.
+	 */
+	if (str_configdata->vid_std != VDEC_STD_VC1 && ((coded_height - disp_height) > 0x0F)) {
+		REGIO_WRITE_FIELD_LITE(pict_cmds[VDECFW_CMD_DISPLAY_PICTURE],
+				       MSVDX_CMDS, DISPLAY_PICTURE_SIZE,
+				       DISPLAY_PICTURE_HEIGHT,
+				       coded_height, unsigned int);
+	} else {
+		REGIO_WRITE_FIELD_LITE(pict_cmds[VDECFW_CMD_DISPLAY_PICTURE],
+				       MSVDX_CMDS, DISPLAY_PICTURE_SIZE,
+				       DISPLAY_PICTURE_HEIGHT,
+				       disp_height, unsigned int);
+	}
+
+	if (((coded_width - disp_width) > 0x0F)) {
+		REGIO_WRITE_FIELD_LITE(pict_cmds[VDECFW_CMD_DISPLAY_PICTURE],
+				       MSVDX_CMDS, DISPLAY_PICTURE_SIZE,
+				       DISPLAY_PICTURE_WIDTH,
+				       coded_width, unsigned int);
+	} else {
+		REGIO_WRITE_FIELD_LITE(pict_cmds[VDECFW_CMD_DISPLAY_PICTURE],
+				       MSVDX_CMDS, DISPLAY_PICTURE_SIZE,
+				       DISPLAY_PICTURE_WIDTH,
+				       disp_width, unsigned int);
+	}
+
+	REGIO_WRITE_FIELD_LITE(pict_cmds[VDECFW_CMD_CODED_PICTURE],
+			       MSVDX_CMDS, CODED_PICTURE_SIZE,
+			       CODED_PICTURE_HEIGHT,
+			       coded_height, unsigned int);
+	REGIO_WRITE_FIELD_LITE(pict_cmds[VDECFW_CMD_CODED_PICTURE],
+			       MSVDX_CMDS, CODED_PICTURE_SIZE,
+			       CODED_PICTURE_WIDTH,
+			       coded_width, unsigned int);
+
+	/*
+	 * For standards where dpb_diff != 1 and chroma format != 420
+	 * cache_ref_offset has to be calculated in the F/W.
+	 */
+	if (str_configdata->vid_std != VDEC_STD_HEVC && str_configdata->vid_std != VDEC_STD_H264) {
+		unsigned int log2_size, cache_size, luma_size;
+		unsigned char is_hevc_supported, is_hevc444_supported = 0;
+
+		is_hevc_supported =
+			vxd_is_supported_byatleast_onepipe(coreprops->hevc,
+							   coreprops->num_pixel_pipes);
+
+		if (is_hevc_supported) {
+			is_hevc444_supported =
+				coreprops->vidstd_props[VDEC_STD_HEVC].max_chroma_format ==
+				PIXEL_FORMAT_444 ? 1 : 0;
+		}
+
+		log2_size = 9 + (is_hevc_supported ? 1 : 0) + (is_hevc444_supported ? 1 : 0);
+		cache_size = 3 << log2_size;
+		luma_size = (cache_size * 2) / 3;
+		cache_ref_offset = (luma_size * 15) / 32;
+		cache_ref_offset = (cache_ref_offset + 7) & (~7);
+		cache_row_offset = 0x0C;
+
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_MC_CACHE_CONFIGURATION],
+				  MSVDX_CMDS, MC_CACHE_CONFIGURATION,
+				  CONFIG_REF_CHROMA_ADJUST, 1,
+				  unsigned int, unsigned int);
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_MC_CACHE_CONFIGURATION],
+				  MSVDX_CMDS, MC_CACHE_CONFIGURATION,
+				  CONFIG_REF_OFFSET, cache_ref_offset,
+				  unsigned int, unsigned int);
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_MC_CACHE_CONFIGURATION],
+				  MSVDX_CMDS, MC_CACHE_CONFIGURATION,
+				  CONFIG_ROW_OFFSET, cache_row_offset,
+				  unsigned int, unsigned int);
+	}
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE],
+			  MSVDX_CMDS, OPERATING_MODE, CODEC_MODE,
+			  amsvdx_codecmode[str_configdata->vid_std],
+			  unsigned int, unsigned int);
+
+	profile = str_unit->seq_hdr_info->com_sequ_hdr_info.codec_profile;
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE],
+			  MSVDX_CMDS, OPERATING_MODE, CODEC_PROFILE,
+			  vxd_getprofile(str_configdata->vid_std, profile),
+			  unsigned int, unsigned int);
+
+	plane = str_unit->seq_hdr_info->com_sequ_hdr_info.separate_chroma_planes;
+	pixel_info = &str_unit->seq_hdr_info->com_sequ_hdr_info.pixel_info;
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE],
+			  MSVDX_CMDS, OPERATING_MODE, CHROMA_FORMAT, plane ?
+			  0 : pixel_info->chroma_fmt, unsigned int, int);
+
+	if (str_configdata->vid_std != VDEC_STD_JPEG) {
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_EXT_OP_MODE],
+				  MSVDX_CMDS, EXT_OP_MODE, CHROMA_FORMAT_IDC, plane ?
+				  0 : pixel_get_hw_chroma_format_idc
+							(pixel_info->chroma_fmt_idc),
+				  unsigned int, int);
+
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_EXT_OP_MODE],
+				  MSVDX_CMDS, EXT_OP_MODE, MEMORY_PACKING,
+				  output_config->pixel_info.mem_pkg ==
+				  PIXEL_BIT10_MP ? 1 : 0, unsigned int, int);
+
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_EXT_OP_MODE],
+				  MSVDX_CMDS, EXT_OP_MODE, BIT_DEPTH_LUMA_MINUS8,
+				  pixel_info->bitdepth_y - 8,
+				  unsigned int, unsigned int);
+
+		if (pixel_info->chroma_fmt_idc == PIXEL_FORMAT_MONO) {
+			/*
+			 * For monochrome streams use the same bit depth for
+			 * chroma and luma.
+			 */
+			REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_EXT_OP_MODE],
+					  MSVDX_CMDS, EXT_OP_MODE,
+					  BIT_DEPTH_CHROMA_MINUS8,
+					  pixel_info->bitdepth_y - 8,
+					  unsigned int, unsigned int);
+		} else {
+			/*
+			 * For normal streams use the appropriate bit depth for chroma.
+			 */
+			REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_EXT_OP_MODE], MSVDX_CMDS,
+					  EXT_OP_MODE, BIT_DEPTH_CHROMA_MINUS8,
+					  pixel_info->bitdepth_c - 8,
+					  unsigned int, unsigned int);
+		}
+	} else {
+		pict_cmds[VDECFW_CMD_EXT_OP_MODE] = 0;
+	}
+
+	if (str_configdata->vid_std != VDEC_STD_JPEG) {
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE], MSVDX_CMDS,
+				  OPERATING_MODE, CHROMA_INTERLEAVED,
+				  PIXEL_GET_HW_CHROMA_INTERLEAVED
+				  (output_config->pixel_info.chroma_interleave),
+				  unsigned int, int);
+	}
+
+	if (str_configdata->vid_std == VDEC_STD_JPEG) {
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE],
+				  MSVDX_CMDS, OPERATING_MODE, ASYNC_MODE,
+				  VDEC_MSVDX_ASYNC_VDMC,
+				  unsigned int, unsigned int);
+	}
+
+	if (str_configdata->vid_std == VDEC_STD_H264) {
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE], MSVDX_CMDS,
+				  OPERATING_MODE, ASYNC_MODE,
+				  str_unit->pict_hdr_info->discontinuous_mbs ?
+				  VDEC_MSVDX_ASYNC_VDMC : VDEC_MSVDX_ASYNC_NORMAL,
+				  unsigned int, int);
+	}
+
+	y_stride = buffers->recon_pict->rend_info.plane_info[VDEC_PLANE_VIDEO_Y].stride;
+	uv_stride = buffers->recon_pict->rend_info.plane_info[VDEC_PLANE_VIDEO_UV].stride;
+	v_stride = buffers->recon_pict->rend_info.plane_info[VDEC_PLANE_VIDEO_V].stride;
+
+	if (((y_stride % (VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT)) == 0) &&
+	    ((uv_stride % (VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT)) == 0) &&
+	    ((v_stride % (VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT)) == 0)) {
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE],
+				  MSVDX_CMDS, OPERATING_MODE,
+				  USE_EXT_ROW_STRIDE, 1, unsigned int, int);
+
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_EXTENDED_ROW_STRIDE],
+				  MSVDX_CMDS, EXTENDED_ROW_STRIDE,
+				  EXT_ROW_STRIDE, y_stride >> 6, unsigned int, unsigned int);
+
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_CHROMA_ROW_STRIDE],
+				  MSVDX_CMDS, CHROMA_ROW_STRIDE,
+				  CHROMA_ROW_STRIDE, uv_stride >> 6, unsigned int, unsigned int);
+	} else {
+		row_stride_code = get_stride_code(str_configdata->vid_std, y_stride);
+
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE],
+				  MSVDX_CMDS, OPERATING_MODE, ROW_STRIDE,
+				  row_stride_code & 0x7, unsigned int, unsigned int);
+
+		if (str_configdata->vid_std == VDEC_STD_JPEG) {
+			/*
+			 * Use the unused chroma interleaved flag
+			 * to hold MSB of row stride code
+			 */
+			IMG_ASSERT(row_stride_code < 16);
+			REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_OPERATING_MODE],
+					  MSVDX_CMDS, OPERATING_MODE,
+					  CHROMA_INTERLEAVED,
+					  row_stride_code >> 3, unsigned int, unsigned int);
+		} else {
+			IMG_ASSERT(row_stride_code < 8);
+		}
+	}
+	pict_cmds[VDECFW_CMD_LUMA_RECONSTRUCTED_PICTURE_BASE_ADDRESS] =
+		(unsigned int)GET_HOST_ADDR(&buffers->recon_pict->pict_buf->ddbuf_info) +
+		buffers->recon_pict->rend_info.plane_info[0].offset;
+
+	pict_cmds[VDECFW_CMD_CHROMA_RECONSTRUCTED_PICTURE_BASE_ADDRESS] =
+		(unsigned int)GET_HOST_ADDR(&buffers->recon_pict->pict_buf->ddbuf_info) +
+		buffers->recon_pict->rend_info.plane_info[1].offset;
+
+	pict_cmds[VDECFW_CMD_CHROMA2_RECONSTRUCTED_PICTURE_BASE_ADDRESS] =
+		(unsigned int)GET_HOST_ADDR(&buffers->recon_pict->pict_buf->ddbuf_info) +
+		buffers->recon_pict->rend_info.plane_info[2].offset;
+
+	pict_cmds[VDECFW_CMD_LUMA_ERROR_PICTURE_BASE_ADDRESS] = 0;
+	pict_cmds[VDECFW_CMD_CHROMA_ERROR_PICTURE_BASE_ADDRESS] = 0;
+
+#ifdef ERROR_CONCEALMENT
+	/* update error concealment frame info if available */
+	if (buffers->err_pict_bufinfo) {
+		pict_cmds[VDECFW_CMD_LUMA_ERROR_PICTURE_BASE_ADDRESS] =
+			(unsigned int)GET_HOST_ADDR(buffers->err_pict_bufinfo) +
+			buffers->recon_pict->rend_info.plane_info[0].offset;
+
+		pict_cmds[VDECFW_CMD_CHROMA_ERROR_PICTURE_BASE_ADDRESS] =
+			(unsigned int)GET_HOST_ADDR(buffers->err_pict_bufinfo) +
+			buffers->recon_pict->rend_info.plane_info[1].offset;
+	}
+#endif
+
+	pict_cmds[VDECFW_CMD_INTRA_BUFFER_BASE_ADDRESS] =
+		(unsigned int)GET_HOST_ADDR(buffers->intra_bufinfo);
+	pict_cmds[VDECFW_CMD_INTRA_BUFFER_PLANE_SIZE] =
+		buffers->intra_bufsize_per_pipe / 3;
+	pict_cmds[VDECFW_CMD_INTRA_BUFFER_SIZE_PER_PIPE] =
+		buffers->intra_bufsize_per_pipe;
+	pict_cmds[VDECFW_CMD_AUX_LINE_BUFFER_BASE_ADDRESS] =
+		(unsigned int)GET_HOST_ADDR(buffers->auxline_bufinfo);
+	pict_cmds[VDECFW_CMD_AUX_LINE_BUFFER_SIZE_PER_PIPE] =
+		buffers->auxline_bufsize_per_pipe;
+
+	/*
+	 * for pvdec we need to set this registers even if we don't
+	 * use alternative output
+	 */
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  ALT_BIT_DEPTH_CHROMA_MINUS8,
+			  output_config->pixel_info.bitdepth_c - 8, unsigned int, unsigned int);
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  ALT_BIT_DEPTH_LUMA_MINUS8,
+			  output_config->pixel_info.bitdepth_y - 8, unsigned int, unsigned int);
+
+	/*
+	 * this is causing corruption in RV40 and VC1 streams with
+	 * scaling/rotation enabled on Coral, so setting to 0
+	 */
+	benable_auxline_buf = benable_auxline_buf &&
+		(str_configdata->vid_std != VDEC_STD_REAL) &&
+		(str_configdata->vid_std != VDEC_STD_VC1);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION,
+			  USE_AUX_LINE_BUF, benable_auxline_buf ? 1 : 0, unsigned int, int);
+}
+
+void vxd_set_altpictcmds(const struct vdecdd_str_unit *str_unit,
+			 const struct vdec_str_configdata *str_configdata,
+			 const struct vdec_str_opconfig *output_config,
+			 const struct vxd_coreprops *coreprops,
+			 const struct vxd_buffers *buffers,
+			 unsigned int *pict_cmds)
+{
+	unsigned int row_stride_code;
+	unsigned int y_stride;
+	unsigned int uv_stride;
+	unsigned int v_stride;
+
+	y_stride = buffers->alt_pict->rend_info.plane_info[VDEC_PLANE_VIDEO_Y].stride;
+	uv_stride = buffers->alt_pict->rend_info.plane_info[VDEC_PLANE_VIDEO_UV].stride;
+	v_stride = buffers->alt_pict->rend_info.plane_info[VDEC_PLANE_VIDEO_V].stride;
+
+	if (((y_stride % (VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT)) == 0) &&
+	    ((uv_stride % (VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT)) == 0) &&
+	    ((v_stride % (VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT)) == 0)) {
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION],
+				  MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION,
+				  USE_EXT_ROT_ROW_STRIDE, 1, unsigned int, int);
+
+		/* 64-byte (min) aligned luma stride value. */
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION],
+				  MSVDX_CMDS,
+				  ALTERNATIVE_OUTPUT_PICTURE_ROTATION,
+				  EXT_ROT_ROW_STRIDE, y_stride >> 6,
+				  unsigned int, unsigned int);
+
+		/* 64-byte (min) aligned chroma stride value. */
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_CHROMA_ROW_STRIDE],
+				  MSVDX_CMDS, CHROMA_ROW_STRIDE,
+				  ALT_CHROMA_ROW_STRIDE, uv_stride >> 6,
+				  unsigned int, unsigned int);
+	} else {
+		/*
+		 * Obtain the code for buffer stride
+		 * (must be less than 8, i.e. not JPEG strides)
+		 */
+		row_stride_code =
+			get_stride_code(str_configdata->vid_std, y_stride);
+
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION],
+				  MSVDX_CMDS,
+				  ALTERNATIVE_OUTPUT_PICTURE_ROTATION,
+				  ROTATION_ROW_STRIDE, row_stride_code & 0x7,
+				  unsigned int, unsigned int);
+	}
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION,
+			  SCALE_INPUT_SIZE_SEL,
+			  ((output_config->pixel_info.chroma_fmt_idc !=
+			  str_unit->seq_hdr_info->com_sequ_hdr_info.pixel_info.chroma_fmt_idc)) ?
+			  1 : 0, unsigned int, int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_PICTURE_ROTATION],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_PICTURE_ROTATION,
+			  PACKED_422_OUTPUT,
+			  (output_config->pixel_info.chroma_fmt_idc ==
+			  PIXEL_FORMAT_422 &&
+			  output_config->pixel_info.num_planes == 1) ? 1 : 0,
+			  unsigned int, int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  ALT_OUTPUT_FORMAT,
+			  str_unit->seq_hdr_info->com_sequ_hdr_info.separate_chroma_planes ?
+			  0 : pixel_get_hw_chroma_format_idc
+					(output_config->pixel_info.chroma_fmt_idc),
+			  unsigned int, int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  ALT_BIT_DEPTH_CHROMA_MINUS8,
+			  output_config->pixel_info.bitdepth_c - 8,
+			  unsigned int, unsigned int);
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  ALT_BIT_DEPTH_LUMA_MINUS8,
+			  output_config->pixel_info.bitdepth_y - 8,
+			  unsigned int, unsigned int);
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  ALT_MEMORY_PACKING,
+			  (output_config->pixel_info.mem_pkg ==
+			  PIXEL_BIT10_MP) ? 1 : 0, unsigned int, int);
+
+	pict_cmds[VDECFW_CMD_LUMA_ALTERNATIVE_PICTURE_BASE_ADDRESS] =
+		(unsigned int)GET_HOST_ADDR(&buffers->alt_pict->pict_buf->ddbuf_info) +
+		buffers->alt_pict->rend_info.plane_info[0].offset;
+
+	pict_cmds[VDECFW_CMD_CHROMA_ALTERNATIVE_PICTURE_BASE_ADDRESS] =
+		(unsigned int)GET_HOST_ADDR(&buffers->alt_pict->pict_buf->ddbuf_info) +
+		buffers->alt_pict->rend_info.plane_info[1].offset;
+
+	pict_cmds[VDECFW_CMD_CHROMA2_ALTERNATIVE_PICTURE_BASE_ADDRESS] =
+		(unsigned int)GET_HOST_ADDR(&buffers->alt_pict->pict_buf->ddbuf_info) +
+		buffers->alt_pict->rend_info.plane_info[2].offset;
+}
+
+int vxd_getscalercmds(const struct scaler_config *scaler_config,
+		      const struct scaler_pitch *pitch,
+		      const struct scaler_filter *filter,
+		      const struct pixel_pixinfo *out_loop_pixel_info,
+		      struct scaler_params *params,
+		      unsigned int *pict_cmds)
+{
+	const struct vxd_coreprops *coreprops = scaler_config->coreprops;
+	/*
+	 * Indirectly detect decoder core type (if HEVC is supported, it has
+	 * to be PVDEC core) and decide if to force luma re-sampling.
+	 */
+	unsigned char bforce_luma_resampling = coreprops->hevc[0];
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  ALT_OUTPUT_FORMAT,
+			  scaler_config->bseparate_chroma_planes ? 0 :
+			  pixel_get_hw_chroma_format_idc(out_loop_pixel_info->chroma_fmt_idc),
+			  unsigned int, int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  SCALE_CHROMA_RESAMP_ONLY, bforce_luma_resampling ? 0 :
+			  (pitch->horiz_luma == FIXED(1, HIGHP)) &&
+			  (pitch->vert_luma == FIXED(1, HIGHP)), unsigned int, int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL, ALT_MEMORY_PACKING,
+			  pixel_get_hw_memory_packing(out_loop_pixel_info->mem_pkg),
+			  unsigned int, int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  ALT_BIT_DEPTH_LUMA_MINUS8,
+			  out_loop_pixel_info->bitdepth_y - 8,
+			  unsigned int, unsigned int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  ALT_BIT_DEPTH_CHROMA_MINUS8,
+			  out_loop_pixel_info->bitdepth_c - 8,
+			  unsigned int, unsigned int);
+
+	/* Scale luma bifilter is always 0 for now */
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  SCALE_LUMA_BIFILTER_HORIZ,
+			  0, unsigned int, int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  SCALE_LUMA_BIFILTER_VERT,
+			  0, unsigned int, int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  SCALE_CHROMA_BIFILTER_HORIZ,
+			  filter->bhoriz_bilinear ? 1 : 0,
+			  unsigned int, int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_ALTERNATIVE_OUTPUT_CONTROL],
+			  MSVDX_CMDS, ALTERNATIVE_OUTPUT_CONTROL,
+			  SCALE_CHROMA_BIFILTER_VERT,
+			   filter->bvert_bilinear ? 1 : 0, unsigned int, int);
+
+	/* for cores 7.x.x and more, precision 3.13 */
+	params->fixed_point_shift = 13;
+
+	/* Calculate the fixed-point versions for use by the hardware. */
+	params->vert_pitch = (int)((pitch->vert_luma +
+		(1 << (HIGHP - params->fixed_point_shift - 1))) >>
+		(HIGHP - params->fixed_point_shift));
+	params->vert_startpos = params->vert_pitch >> 1;
+	params->vert_pitch_chroma = (int)((pitch->vert_chroma +
+		(1 << (HIGHP - params->fixed_point_shift - 1))) >>
+		(HIGHP - params->fixed_point_shift));
+	params->vert_startpos_chroma = params->vert_pitch_chroma >> 1;
+	params->horz_pitch = (int)(pitch->horiz_luma >>
+		(HIGHP - params->fixed_point_shift));
+	params->horz_startpos = params->horz_pitch >> 1;
+	params->horz_pitch_chroma = (int)(pitch->horiz_chroma >>
+		(HIGHP - params->fixed_point_shift));
+	params->horz_startpos_chroma = params->horz_pitch_chroma >> 1;
+
+#ifdef HAS_HEVC
+	if (scaler_config->vidstd == VDEC_STD_HEVC) {
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE],
+				  MSVDX_CMDS, PVDEC_SCALED_DISPLAY_SIZE,
+				  PVDEC_SCALE_DISPLAY_WIDTH,
+				  scaler_config->recon_width - 1,
+				  unsigned int, unsigned int);
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE],
+				  MSVDX_CMDS, PVDEC_SCALED_DISPLAY_SIZE,
+				  PVDEC_SCALE_DISPLAY_HEIGHT,
+				  scaler_config->recon_height - 1,
+				  unsigned int, unsigned int);
+	} else {
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE],
+				  MSVDX_CMDS, SCALED_DISPLAY_SIZE,
+				  SCALE_DISPLAY_WIDTH,
+				  scaler_config->recon_width - 1,
+				  unsigned int, unsigned int);
+		REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE],
+				  MSVDX_CMDS, SCALED_DISPLAY_SIZE,
+				  SCALE_DISPLAY_HEIGHT,
+				  scaler_config->recon_height - 1,
+				  unsigned int, unsigned int);
+	}
+#else
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE],
+			  MSVDX_CMDS, SCALED_DISPLAY_SIZE,
+			  SCALE_DISPLAY_WIDTH,
+			  scaler_config->recon_width - 1,
+			  unsigned int, unsigned int);
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALED_DISPLAY_SIZE],
+			  MSVDX_CMDS, SCALED_DISPLAY_SIZE, SCALE_DISPLAY_HEIGHT,
+			  scaler_config->recon_height - 1,
+			  unsigned int, unsigned int);
+#endif
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALE_OUTPUT_SIZE],
+			  MSVDX_CMDS, SCALE_OUTPUT_SIZE,
+			  SCALE_OUTPUT_WIDTH_MIN1,
+			  scaler_config->scale_width - 1,
+			  unsigned int, unsigned int);
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALE_OUTPUT_SIZE],
+			  MSVDX_CMDS, SCALE_OUTPUT_SIZE,
+			  SCALE_OUTPUT_HEIGHT_MIN1,
+			  scaler_config->scale_height - 1,
+			  unsigned int, unsigned int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_HORIZONTAL_SCALE_CONTROL],
+			  MSVDX_CMDS, HORIZONTAL_SCALE_CONTROL,
+			  HORIZONTAL_SCALE_PITCH, params->horz_pitch,
+			  unsigned int, unsigned int);
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_HORIZONTAL_SCALE_CONTROL],
+			  MSVDX_CMDS, HORIZONTAL_SCALE_CONTROL,
+			  HORIZONTAL_INITIAL_POS, params->horz_startpos,
+			  unsigned int, unsigned int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALE_HORIZONTAL_CHROMA],
+			  MSVDX_CMDS, SCALE_HORIZONTAL_CHROMA,
+			  CHROMA_HORIZONTAL_PITCH, params->horz_pitch_chroma,
+			  unsigned int, unsigned int);
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALE_HORIZONTAL_CHROMA],
+			  MSVDX_CMDS, SCALE_HORIZONTAL_CHROMA,
+			  CHROMA_HORIZONTAL_INITIAL,
+			  params->horz_startpos_chroma,
+			  unsigned int, unsigned int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_VERTICAL_SCALE_CONTROL],
+			  MSVDX_CMDS, VERTICAL_SCALE_CONTROL,
+			  VERTICAL_SCALE_PITCH, params->vert_pitch,
+			  unsigned int, unsigned int);
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_VERTICAL_SCALE_CONTROL],
+			  MSVDX_CMDS, VERTICAL_SCALE_CONTROL,
+			  VERTICAL_INITIAL_POS, params->vert_startpos,
+			  unsigned int, unsigned int);
+
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALE_VERTICAL_CHROMA],
+			  MSVDX_CMDS, SCALE_VERTICAL_CHROMA,
+			  CHROMA_VERTICAL_PITCH, params->vert_pitch_chroma,
+			  unsigned int, unsigned int);
+	REGIO_WRITE_FIELD(pict_cmds[VDECFW_CMD_SCALE_VERTICAL_CHROMA],
+			  MSVDX_CMDS, SCALE_VERTICAL_CHROMA,
+			  CHROMA_VERTICAL_INITIAL,
+			  params->vert_startpos_chroma,
+			  unsigned int, unsigned int);
+	return 0;
+}
+
+unsigned int vxd_get_codedpicsize(unsigned short width_min1, unsigned short height_min1)
+{
+	unsigned int reg = 0;
+
+	REGIO_WRITE_FIELD_LITE(reg, MSVDX_CMDS, CODED_PICTURE_SIZE,
+			       CODED_PICTURE_WIDTH, width_min1,
+			       unsigned short);
+	REGIO_WRITE_FIELD_LITE(reg, MSVDX_CMDS, CODED_PICTURE_SIZE,
+			       CODED_PICTURE_HEIGHT, height_min1,
+			       unsigned short);
+
+	return reg;
+}
+
+unsigned char vxd_get_codedmode(enum vdec_vid_std vidstd)
+{
+	return (unsigned char)amsvdx_codecmode[vidstd];
+}
+
+void vxd_get_coreproperties(void *hndl_coreproperties,
+			    struct vxd_coreprops *vxd_coreprops)
+{
+	struct vxd_core_props *props =
+		(struct vxd_core_props *)hndl_coreproperties;
+
+	vxd_getcoreproperties(vxd_coreprops, props->core_rev,
+			      props->pvdec_core_id,
+			      props->mmu_config0,
+			      props->mmu_config1,
+			      props->pixel_pipe_cfg,
+			      props->pixel_misc_cfg,
+			      props->pixel_max_frame_cfg);
+}
+
+int vxd_get_pictattrs(unsigned int flags, struct vxd_pict_attrs *pict_attrs)
+{
+	if (flags & (VXD_FW_MSG_FLAG_DWR | VXD_FW_MSG_FLAG_FATAL))
+		pict_attrs->dwrfired = 1;
+	if (flags & VXD_FW_MSG_FLAG_MMU_FAULT)
+		pict_attrs->mmufault = 1;
+	if (flags & VXD_FW_MSG_FLAG_DEV_ERR)
+		pict_attrs->deverror = 1;
+
+	return 0;
+}
+
+int vxd_get_msgerrattr(unsigned int flags, enum vxd_msg_attr *msg_attr)
+{
+	if ((flags & ~VXD_FW_MSG_FLAG_CANCELED))
+		*msg_attr = VXD_MSG_ATTR_FATAL;
+	else if ((flags & VXD_FW_MSG_FLAG_CANCELED))
+		*msg_attr = VXD_MSG_ATTR_CANCELED;
+	else
+		*msg_attr = VXD_MSG_ATTR_NONE;
+
+	return 0;
+}
+
+int vxd_set_msgflag(enum vxd_msg_flag input_flag, unsigned int *flags)
+{
+	switch (input_flag) {
+	case VXD_MSG_FLAG_DROP:
+		*flags |= VXD_FW_MSG_FLAG_DROP;
+		break;
+	case VXD_MSG_FLAG_EXCL:
+		*flags |= VXD_FW_MSG_FLAG_EXCL;
+		break;
+	default:
+		return IMG_ERROR_FATAL;
+	}
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vxd_int.h b/drivers/media/platform/img/vxe-vxd/decoder/vxd_int.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vxd_int.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vxd_int.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD DEC Common low level core interface component
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+#ifndef _VXD_INT_H
+#define _VXD_INT_H
+
+#include "fw_interface.h"
+#include "scaler_setup.h"
+#include "vdecdd_defs.h"
+#include "vdecfw_shared.h"
+#include "vdec_defs.h"
+#include "vxd_ext.h"
+#include "vxd_props.h"
+
+/*
+ * Size of buffer used for batching messages
+ */
+#define BATCH_MSG_BUFFER_SIZE           (8 * 4096)
+
+#define INTRA_BUF_SIZE                  (1024 * 32)
+#define AUX_LINE_BUFFER_SIZE            (512 * 1024)
+
+#define MAX_PICTURE_WIDTH               (4096)
+#define MAX_PICTURE_HEIGHT              (4096)
+
+/*
+ * this macro returns the host address of device buffer.
+ */
+#define GET_HOST_ADDR(buf) ((buf)->dev_virt)
+
+#define GET_HOST_ADDR_OFFSET(buf, offset) (((buf)->dev_virt) + (offset))
+
+/*
+ * The extended stride alignment for VXD.
+ */
+#define VDEC_VXD_EXT_STRIDE_ALIGNMENT_DEFAULT  (64)
+
+struct vxd_buffers {
+	struct vdecdd_ddpict_buf *recon_pict;
+	struct vdecdd_ddpict_buf *alt_pict;
+	struct vidio_ddbufinfo *intra_bufinfo;
+	struct vidio_ddbufinfo *auxline_bufinfo;
+	struct vidio_ddbufinfo *err_pict_bufinfo;
+	unsigned int intra_bufsize_per_pipe;
+	unsigned int auxline_bufsize_per_pipe;
+	struct vidio_ddbufinfo *msb_bufinfo;
+	unsigned char btwopass;
+};
+
+struct pvdec_core_rev {
+	unsigned int maj_rev;
+	unsigned int min_rev;
+	unsigned int maint_rev;
+	unsigned int int_rev;
+};
+
+/*
+ * this has all that it needs to translate a Stream Unit for a picture
+ * into a transaction.
+ */
+void vxd_set_altpictcmds(const struct vdecdd_str_unit *str_unit,
+			 const struct vdec_str_configdata *str_configdata,
+			 const struct vdec_str_opconfig *output_config,
+			 const struct vxd_coreprops *coreprops,
+			 const struct vxd_buffers *buffers,
+			 unsigned int *pict_cmds);
+
+/*
+ * this has all that it needs to translate a Stream Unit for
+ * a picture into a transaction.
+ */
+void vxd_set_reconpictcmds(const struct vdecdd_str_unit *str_unit,
+			   const struct vdec_str_configdata *str_configdata,
+			   const struct vdec_str_opconfig *output_config,
+			   const struct vxd_coreprops *coreprops,
+			   const struct vxd_buffers *buffers,
+			   unsigned int *pict_cmds);
+
+int vxd_getscalercmds(const struct scaler_config *scaler_config,
+		      const struct scaler_pitch *pitch,
+		      const struct scaler_filter *filter,
+		      const struct pixel_pixinfo *out_loop_pixel_info,
+		      struct scaler_params *params,
+		      unsigned int *pict_cmds);
+
+/*
+ * this creates value of MSVDX_CMDS_CODED_PICTURE_SIZE register.
+ */
+unsigned int vxd_get_codedpicsize(unsigned short width_min1, unsigned short height_min1);
+
+/*
+ * return HW codec mode based on video standard.
+ */
+unsigned char vxd_get_codedmode(enum vdec_vid_std vidstd);
+
+/*
+ * translates core properties to the form of the struct vxd_coreprops struct.
+ */
+void vxd_get_coreproperties(void *hndl_coreproperties,
+			    struct vxd_coreprops *vxd_coreprops);
+
+/*
+ * translates picture attributes to the form of the VXD_sPictAttrs struct.
+ */
+int vxd_get_pictattrs(unsigned int flags, struct vxd_pict_attrs *pict_attrs);
+
+/*
+ * translates message attributes to the form of the VXD_eMsgAttr struct.
+ */
+int vxd_get_msgerrattr(unsigned int flags, enum vxd_msg_attr *msg_attr);
+
+/*
+ * sets a message flag.
+ */
+int vxd_set_msgflag(enum vxd_msg_flag input_flag, unsigned int *flags);
+
+#endif /* _VXD_INT_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vxd_mmu_defs.h b/drivers/media/platform/img/vxe-vxd/decoder/vxd_mmu_defs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vxd_mmu_defs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vxd_mmu_defs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * V-DEC MMU Definitions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ */
+
+#ifndef _VXD_MMU_DEF_H_
+#define _VXD_MMU_DEF_H_
+
+/*
+ * This type defines the MMU heaps.
+ * @0:	Heap for untiled video buffers
+ * @1:	Heap for bitstream buffers
+ * @2:	Heap for Stream buffers
+ * @3:	Number of heaps
+ */
+enum mmu_eheap_id {
+	MMU_HEAP_IMAGE_BUFFERS_UNTILED = 0x00,
+	MMU_HEAP_BITSTREAM_BUFFERS,
+	MMU_HEAP_STREAM_BUFFERS,
+	MMU_HEAP_MAX,
+	MMU_HEAP_FORCE32BITS           = 0x7FFFFFFFU
+};
+
+#endif /* _VXD_MMU_DEFS_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vxd_props.h b/drivers/media/platform/img/vxe-vxd/decoder/vxd_props.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vxd_props.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vxd_props.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Low-level VXD interface component
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _VXD_PROPS_H
+#define _VXD_PROPS_H
+
+#include "vdec_defs.h"
+#include "imgmmu.h"
+
+#define VDEC_MAX_PIXEL_PIPES 2
+
+#define VXD_MAX_CORES    1
+#define VER_STR_LEN      64
+
+#define CORE_REVISION(maj, min, maint) \
+	((((maj) & 0xff) << 16) | (((min) & 0xff) << 8) | (((maint) & 0xff)))
+#define MAJOR_REVISION(rev)     (((rev) >> 16) & 0xff)
+#define MINOR_REVISION(rev)     (((rev) >> 8) & 0xff)
+#define MAINT_REVISION(rev)     ((rev) & 0xff)
+
+#define FROM_REV(maj, min, maint, type) \
+	({ \
+		type __maj = maj; \
+		type __min = min; \
+		(((maj_rev) > (__maj)) || \
+		 (((maj_rev) == (__maj)) && ((min_rev) > (__min))) || \
+		 (((maj_rev) == (__maj)) && ((min_rev) == (__min)) && \
+		  ((int)(maint_rev) >= (maint)))); })
+
+struct vxd_vidstd_props {
+	enum vdec_vid_std vidstd;
+	unsigned int core_rev;
+	unsigned int min_width;
+	unsigned int min_height;
+	unsigned int max_width;
+	unsigned int max_height;
+	unsigned int max_macroblocks;
+	unsigned int max_luma_bitdepth;
+	unsigned int max_chroma_bitdepth;
+	enum pixel_fmt_idc max_chroma_format;
+};
+
+struct vxd_coreprops {
+	unsigned char aversion[VER_STR_LEN];
+	unsigned char mpeg2[VDEC_MAX_PIXEL_PIPES];
+	unsigned char mpeg4[VDEC_MAX_PIXEL_PIPES];
+	unsigned char h264[VDEC_MAX_PIXEL_PIPES];
+	unsigned char vc1[VDEC_MAX_PIXEL_PIPES];
+	unsigned char avs[VDEC_MAX_PIXEL_PIPES];
+	unsigned char real[VDEC_MAX_PIXEL_PIPES];
+	unsigned char jpeg[VDEC_MAX_PIXEL_PIPES];
+	unsigned char vp6[VDEC_MAX_PIXEL_PIPES];
+	unsigned char vp8[VDEC_MAX_PIXEL_PIPES];
+	unsigned char hevc[VDEC_MAX_PIXEL_PIPES];
+	unsigned char rotation_support[VDEC_MAX_PIXEL_PIPES];
+	unsigned char scaling_support[VDEC_MAX_PIXEL_PIPES];
+	unsigned char hd_support;
+	unsigned int num_streams[VDEC_MAX_PIXEL_PIPES];
+	unsigned int num_entropy_pipes;
+	unsigned int num_pixel_pipes;
+	struct vxd_vidstd_props vidstd_props[VDEC_STD_MAX];
+	enum mmu_etype mmu_type;
+	unsigned char mmu_support_stride_per_context;
+	unsigned char mmu_support_secure;
+	/* Range extensions supported by hw -> used only by hevc */
+	unsigned char hevc_range_ext[VDEC_MAX_PIXEL_PIPES];
+};
+
+#endif /* _VXD_PROPS_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vxd_pvdec.c b/drivers/media/platform/img/vxe-vxd/decoder/vxd_pvdec.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/vxd_pvdec.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vxd_pvdec.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1745 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMG DEC PVDEC function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/time64.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "img_dec_common.h"
+#include "img_pvdec_test_regs.h"
+#include "img_video_bus4_mmu_regs.h"
+#include "vxd_pvdec_priv.h"
+#include "vxd_pvdec_regs.h"
+
+#ifdef PVDEC_SINGLETHREADED_IO
+static DEFINE_SPINLOCK(pvdec_irq_lock);
+static ulong pvdec_irq_flags;
+#endif
+
+static const ulong vxd_plat_poll_udelay = 100;
+
+/* This function will return reminder and quotient */
+static inline unsigned int do_divide(unsigned long long *n, unsigned int base)
+{
+	unsigned int remainder = *n % base;
+	*n = *n / base;
+	return remainder;
+}
+
+/*
+ * Reads PROC_DEBUG register and provides number of MTX RAM banks
+ * and their size
+ */
+static int pvdec_get_mtx_ram_info(void __iomem *reg_base, int *bank_cnt,
+				  unsigned long *bank_size,
+				  unsigned long *last_bank_size)
+{
+	unsigned int ram_bank_count, reg;
+
+	reg = VXD_RD_REG(reg_base, PVDEC_CORE, PROC_DEBUG);
+	ram_bank_count = VXD_RD_REG_FIELD(reg, PVDEC_CORE, PROC_DEBUG, MTX_RAM_BANKS);
+	if (!ram_bank_count)
+		return -EIO;
+
+	if (bank_cnt)
+		*bank_cnt = ram_bank_count;
+
+	if (bank_size) {
+		unsigned int ram_bank_size = VXD_RD_REG_FIELD(reg, PVDEC_CORE,
+				PROC_DEBUG, MTX_RAM_BANK_SIZE);
+		*bank_size = 1 << (ram_bank_size + 2);
+	}
+
+	if (last_bank_size) {
+		unsigned int last_bank = VXD_RD_REG_FIELD(reg, PVDEC_CORE, PROC_DEBUG,
+				MTX_LAST_RAM_BANK_SIZE);
+		unsigned char new_representation = VXD_RD_REG_FIELD(reg,
+				PVDEC_CORE, PROC_DEBUG, MTX_RAM_NEW_REPRESENTATION);
+		if (new_representation) {
+			*last_bank_size = 1024 * last_bank;
+		} else {
+			*last_bank_size = 1 << (last_bank + 2);
+			if (bank_cnt && last_bank == 13 && *bank_cnt == 4) {
+				/*
+				 * VXD hardware ambiguity:
+				 * old cores confuse 120k and 128k
+				 * So assume worst case.
+				 */
+				*last_bank_size -= 0x2000;
+			}
+		}
+	}
+
+	return 0;
+}
+
+/* Provides size of MTX RAM in bytes */
+static int pvdec_get_mtx_ram_size(void __iomem *reg_base, unsigned int *ram_size)
+{
+	int bank_cnt, ret;
+	unsigned long bank_size, last_bank_size;
+
+	ret = pvdec_get_mtx_ram_info(reg_base, &bank_cnt, &bank_size, &last_bank_size);
+	if (ret)
+		return ret;
+
+	*ram_size = (bank_cnt - 1) * bank_size + last_bank_size;
+
+	return 0;
+}
+
+/* Poll for single register-based transfer to/from MTX to complete */
+static unsigned int pvdec_wait_mtx_reg_access(void __iomem *reg_base, unsigned int *mtx_fault)
+{
+	unsigned int pvdec_timeout = PVDEC_TIMEOUT_COUNTER, reg;
+
+	do {
+		/* Check MTX is OK */
+		reg = VXD_RD_REG(reg_base, MTX_CORE, MTX_FAULT0);
+		if (reg != 0) {
+			*mtx_fault = reg;
+			return -EIO;
+		}
+
+		pvdec_timeout--;
+		reg = VXD_RD_REG(reg_base, MTX_CORE, MTX_REG_READ_WRITE_REQUEST);
+	} while ((VXD_RD_REG_FIELD(reg, MTX_CORE,
+		MTX_REG_READ_WRITE_REQUEST,
+		MTX_DREADY) == 0) &&
+		(pvdec_timeout != 0));
+
+	if (pvdec_timeout == 0)
+		return -EIO;
+
+	return 0;
+}
+
+static void pvdec_mtx_status_dump(void __iomem *reg_base, unsigned int *status)
+{
+	unsigned int reg;
+
+	pr_debug("%s: *** dumping status ***\n", __func__);
+
+#define READ_MTX_REG(_NAME_) \
+	do { \
+		unsigned int val; \
+		VXD_WR_REG(reg_base, MTX_CORE, \
+			MTX_REG_READ_WRITE_REQUEST, reg); \
+		if (pvdec_wait_mtx_reg_access(reg_base, &reg)) { \
+			pr_debug("%s: " \
+				"MTX REG RD fault: 0x%08x\n", __func__, reg); \
+			break; \
+		} \
+		val = VXD_RD_REG(reg_base, MTX_CORE, MTX_REG_READ_WRITE_DATA); \
+		if (status) \
+			*status++ = val; \
+		pr_debug("%s: " _NAME_ ": 0x%08x\n", __func__, val); \
+	} while (0)
+
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, /* Read */
+			       MTX_REG_READ_WRITE_REQUEST, MTX_RNW, 1);
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, /* PC or PCX */
+			       MTX_REG_READ_WRITE_REQUEST, MTX_USPECIFIER, 5);
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, /* PC */
+			       MTX_REG_READ_WRITE_REQUEST, MTX_RSPECIFIER, 0);
+	READ_MTX_REG("MTX PC");
+
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, /* Read */
+			       MTX_REG_READ_WRITE_REQUEST, MTX_RNW, 1);
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, /* PC or PCX */
+			       MTX_REG_READ_WRITE_REQUEST, MTX_USPECIFIER, 5);
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, /* PCX */
+			       MTX_REG_READ_WRITE_REQUEST, MTX_RSPECIFIER, 1);
+	READ_MTX_REG("MTX PCX");
+
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, /* Read */
+			       MTX_REG_READ_WRITE_REQUEST, MTX_RNW, 1);
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, /* A0StP */
+			       MTX_REG_READ_WRITE_REQUEST, MTX_USPECIFIER, 3);
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE,
+			       MTX_REG_READ_WRITE_REQUEST, MTX_RSPECIFIER, 0);
+	READ_MTX_REG("MTX A0STP");
+
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, /* Read */
+			       MTX_REG_READ_WRITE_REQUEST, MTX_RNW, 1);
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, /* A0FrP */
+			       MTX_REG_READ_WRITE_REQUEST, MTX_USPECIFIER, 3);
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, MTX_REG_READ_WRITE_REQUEST, MTX_RSPECIFIER, 1);
+	READ_MTX_REG("MTX A0FRP");
+#undef PRINT_MTX_REG
+
+	pr_debug("%s: *** status dump done ***\n", __func__);
+}
+
+static void pvdec_prep_fw_upload(const void *dev,
+				 void __iomem *reg_base,
+				 struct vxd_ena_params *ena_params,
+				 unsigned char dma_channel)
+{
+	unsigned int fw_vxd_virt_addr = ena_params->fw_buf_virt_addr;
+	unsigned int vxd_ptd_addr = ena_params->ptd;
+	unsigned int reg = 0;
+	int i;
+	unsigned int flags = PVDEC_FWFLAG_FORCE_FS_FLOW |
+		PVDEC_FWFLAG_DISABLE_GENC_FLUSHING |
+		PVDEC_FWFLAG_DISABLE_AUTONOMOUS_RESET |
+		PVDEC_FWFLAG_DISABLE_IDLE_GPIO |
+		PVDEC_FWFLAG_ENABLE_ERROR_CONCEALMENT;
+
+	if (ena_params->secure)
+		flags |= PVDEC_FWFLAG_BIG_TO_HOST_BUFFER;
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: fw_virt: 0x%x, ptd: 0x%x, dma ch: %u, flags: 0x%x\n",
+		__func__, fw_vxd_virt_addr, vxd_ptd_addr, dma_channel, flags);
+#endif
+
+	/* Reset MTX */
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, MTX_SOFT_RESET, MTX_RESET, 1);
+	VXD_WR_REG(reg_base, MTX_CORE, MTX_SOFT_RESET, reg);
+	/*
+	 * NOTE: The MTX reset bit is WRITE ONLY, so we cannot
+	 * check the reset procedure has finished, thus BEWARE to put
+	 * any MTX_CORE* access just after this line
+	 */
+
+	/* Clear COMMS RAM header */
+	for (i = 0; i < PVDEC_FW_COMMS_HDR_SIZE; i++)
+		VXD_WR_REG_ABS(reg_base, VLR_OFFSET + i * sizeof(unsigned int), 0);
+
+	VXD_WR_REG_ABS(reg_base, VLR_OFFSET + PVDEC_FW_FLAGS_OFFSET, flags);
+	/* Do not wait for debug FIFO flag - set it only when requested */
+	VXD_WR_REG_ABS(reg_base, VLR_OFFSET + PVDEC_FW_SIGNATURE_OFFSET,
+		       !ena_params->wait_dbg_fifo);
+
+	/*
+	 * Clear the bypass bits and enable extended addressing in MMU.
+	 * Firmware depends on this configuration, so we have to set it,
+	 * even if firmware is being uploaded via registers.
+	 */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_ADDRESS_CONTROL, UPPER_ADDR_FIXED, 0);
+	reg = VXD_WR_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_ADDRESS_CONTROL, MMU_ENA_EXT_ADDR, 1);
+	reg = VXD_WR_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_ADDRESS_CONTROL, MMU_BYPASS, 0);
+	VXD_WR_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_ADDRESS_CONTROL, reg);
+
+	/*
+	 * Buffer device virtual address.
+	 * This is an address of a firmware blob, firmware reads this base
+	 * address from DMAC_SETUP register and uses to load the modules, so it
+	 * has to be set even when uploading the FW via registers.
+	 */
+	VXD_WR_RPT_REG(reg_base, DMAC, DMAC_SETUP, fw_vxd_virt_addr, dma_channel);
+
+	/*
+	 * Set base address of PTD. Same as before, has to be configured even
+	 * when uploading the firmware via regs, FW uses it to execute DMA
+	 * before switching to stream MMU context.
+	 */
+	VXD_WR_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_DIR_BASE_ADDR, vxd_ptd_addr);
+
+	/* Configure MMU bank index - Use bank 0 */
+	VXD_WR_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_BANK_INDEX, 0);
+
+	/* Set the MTX timer divider register */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, MTX_SYSC_TIMERDIV, TIMER_EN, 1);
+	/*
+	 * Setting max freq - divide by 1 for better measurement accuracy
+	 * during fw upload stage
+	 */
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, MTX_SYSC_TIMERDIV, TIMER_DIV, 0);
+	VXD_WR_REG(reg_base, MTX_CORE, MTX_SYSC_TIMERDIV, reg);
+}
+
+static int pvdec_check_fw_sig(void __iomem *reg_base)
+{
+	unsigned int fw_sig = VXD_RD_REG_ABS(reg_base, VLR_OFFSET +
+			PVDEC_FW_SIGNATURE_OFFSET);
+
+	if (fw_sig != PVDEC_FW_READY_SIG)
+		return -EIO;
+
+	return 0;
+}
+
+static void pvdec_kick_mtx(void __iomem *reg_base)
+{
+	unsigned int reg = 0;
+
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, MTX_KICKI, MTX_KICKI, 1);
+	VXD_WR_REG(reg_base, MTX_CORE, MTX_KICKI, reg);
+}
+
+static int pvdec_write_vlr(void __iomem *reg_base, const unsigned int *buf,
+			   unsigned long size_dwrds, int off_dwrds)
+{
+	unsigned int i;
+
+	if (((off_dwrds + size_dwrds) * sizeof(unsigned int)) > VLR_SIZE)
+		return -EINVAL;
+
+	for (i = 0; i < size_dwrds; i++) {
+		int off = (off_dwrds + i) * sizeof(unsigned int);
+
+		VXD_WR_REG_ABS(reg_base, (VLR_OFFSET + off), *buf);
+		buf++;
+	}
+
+	return 0;
+}
+
+static int pvdec_poll_fw_boot(void __iomem *reg_base, struct vxd_boot_poll_params *poll_params)
+{
+	unsigned int i;
+
+	for (i = 0; i < 25; i++) {
+		if (!pvdec_check_fw_sig(reg_base))
+			return 0;
+		usleep_range(100, 110);
+	}
+	for (i = 0; i < poll_params->msleep_cycles; i++) {
+		if (!pvdec_check_fw_sig(reg_base))
+			return 0;
+		msleep(100);
+	}
+	return -EIO;
+}
+
+static int pvdec_read_vlr(void __iomem *reg_base, unsigned int *buf,
+			  unsigned long size_dwrds, int off_dwrds)
+{
+	unsigned int i;
+
+	if (((off_dwrds + size_dwrds) * sizeof(unsigned int)) > VLR_SIZE)
+		return -EINVAL;
+
+	for (i = 0; i < size_dwrds; i++) {
+		int off = (off_dwrds + i) * sizeof(unsigned int);
+		*buf++ = VXD_RD_REG_ABS(reg_base, (VLR_OFFSET + off));
+	}
+
+	return 0;
+}
+
+/* Get configuration of a ring buffer used to send messages to the MTX */
+static int pvdec_get_to_mtx_cfg(void __iomem *reg_base, unsigned long *size, int *off,
+				unsigned int *wr_idx, unsigned int *rd_idx)
+{
+	unsigned int to_mtx_cfg;
+	int to_mtx_off, ret;
+
+	ret = pvdec_check_fw_sig(reg_base);
+	if (ret)
+		return ret;
+
+	to_mtx_cfg = VXD_RD_REG_ABS(reg_base, VLR_OFFSET + PVDEC_FW_TO_MTX_BUF_CONF_OFFSET);
+
+	*size = PVDEC_FW_COM_BUF_SIZE(to_mtx_cfg);
+	to_mtx_off = PVDEC_FW_COM_BUF_OFF(to_mtx_cfg);
+
+	if (to_mtx_off % 4)
+		return -EIO;
+
+	to_mtx_off /= sizeof(unsigned int);
+	*off = to_mtx_off;
+
+	*wr_idx = VXD_RD_REG_ABS(reg_base, VLR_OFFSET + PVDEC_FW_TO_MTX_WR_IDX_OFFSET);
+	*rd_idx = VXD_RD_REG_ABS(reg_base, VLR_OFFSET + PVDEC_FW_TO_MTX_RD_IDX_OFFSET);
+
+	if ((*rd_idx >= *size) || (*wr_idx >= *size))
+		return -EIO;
+
+	return 0;
+}
+
+/* Submit a padding message to the host->MTX ring buffer */
+static int pvdec_send_pad_msg(void __iomem *reg_base)
+{
+	int ret, pad_size, to_mtx_off; /* offset in dwords */
+	unsigned int wr_idx, rd_idx; /* indicies in dwords */
+	unsigned long pad_msg_size = 1, to_mtx_size; /* size in dwords */
+	const unsigned long max_msg_size = VXD_MAX_PAYLOAD_SIZE / sizeof(unsigned int);
+	unsigned int pad_msg;
+
+	ret = pvdec_get_to_mtx_cfg(reg_base, &to_mtx_size, &to_mtx_off, &wr_idx, &rd_idx);
+	if (ret)
+		return ret;
+
+	pad_size = to_mtx_size - wr_idx; /* size in dwords */
+
+	if (pad_size <= 0) {
+		VXD_WR_REG_ABS(reg_base, VLR_OFFSET + PVDEC_FW_TO_MTX_WR_IDX_OFFSET, 0);
+		return 0;
+	}
+
+	while (pad_size > 0) {
+		int cur_pad_size = pad_size > max_msg_size ?
+			max_msg_size : pad_size;
+
+		pad_msg = 0;
+		pad_msg = VXD_WR_REG_FIELD(pad_msg, PVDEC_FW, DEVA_GENMSG, MSG_SIZE, cur_pad_size);
+		pad_msg = VXD_WR_REG_FIELD(pad_msg, PVDEC_FW, DEVA_GENMSG,
+					   MSG_TYPE, PVDEC_FW_MSG_TYPE_PADDING);
+
+		ret = pvdec_write_vlr(reg_base, &pad_msg, pad_msg_size, to_mtx_off + wr_idx);
+		if (ret)
+			return ret;
+
+		wr_idx += cur_pad_size;
+
+		VXD_WR_REG_ABS(reg_base, VLR_OFFSET + PVDEC_FW_TO_MTX_WR_IDX_OFFSET, wr_idx);
+
+		pad_size -= cur_pad_size;
+
+		pvdec_kick_mtx(reg_base);
+	}
+
+	wr_idx = 0;
+	VXD_WR_REG_ABS(reg_base, VLR_OFFSET + PVDEC_FW_TO_MTX_WR_IDX_OFFSET, wr_idx);
+
+	return 0;
+}
+
+/*
+ * Check if there is enough space in comms RAM to submit a <msg_size>
+ * dwords long message. Submit a padding message if necessary and requested.
+ *
+ * Returns 0 if there is space for a message.
+ * Returns -EINVAL when msg is too big or empty.
+ * Returns -EIO when there was a problem accessing the HW.
+ * Returns -EBUSY when there is not ennough space.
+ */
+static int pvdec_check_comms_space(void __iomem *reg_base, unsigned long msg_size,
+				   unsigned char send_padding)
+{
+	int ret, to_mtx_off; /* offset in dwords */
+	unsigned int wr_idx, rd_idx; /* indicies in dwords */
+	unsigned long to_mtx_size; /* size in dwords */
+
+	ret = pvdec_get_to_mtx_cfg(reg_base, &to_mtx_size, &to_mtx_off, &wr_idx, &rd_idx);
+	if (ret)
+		return ret;
+
+	/* Enormous or empty message, won't fit */
+	if (msg_size >= to_mtx_size || !msg_size)
+		return -EINVAL;
+
+	/* Buffer does not wrap */
+	if (wr_idx >= rd_idx) {
+		/* Is there enough space to put the message? */
+		if (wr_idx + msg_size < to_mtx_size)
+			return 0;
+
+		if (!send_padding)
+			return -EBUSY;
+
+		/* Check if it's ok to send a padding message */
+		if (rd_idx == 0)
+			return -EBUSY;
+
+		/* Send a padding message */
+		ret = pvdec_send_pad_msg(reg_base);
+		if (ret)
+			return ret;
+
+		/*
+		 * And check if there's enough space at the beginning
+		 * of a buffer
+		 */
+		if (msg_size >= rd_idx)
+			return -EBUSY; /* Not enough space at the beginning */
+
+	} else { /* Buffer wraps */
+		if (wr_idx + msg_size >= rd_idx)
+			return -EBUSY; /* Not enough space! */
+	}
+
+	return 0;
+}
+
+/* Get configuration of a ring buffer used to receive messages from the MTX */
+static int pvdec_get_to_host_cfg(void __iomem *reg_base, unsigned long *size, int *off,
+				 unsigned int *wr_idx, unsigned int *rd_idx)
+{
+	unsigned int to_host_cfg;
+	int to_host_off, ret;
+
+	ret = pvdec_check_fw_sig(reg_base);
+	if (ret)
+		return ret;
+
+	to_host_cfg = VXD_RD_REG_ABS(reg_base, VLR_OFFSET + PVDEC_FW_TO_HOST_BUF_CONF_OFFSET);
+
+	*size = PVDEC_FW_COM_BUF_SIZE(to_host_cfg);
+	to_host_off = PVDEC_FW_COM_BUF_OFF(to_host_cfg);
+
+	if (to_host_off % 4)
+		return -EIO;
+
+	to_host_off /= sizeof(unsigned int);
+	*off = to_host_off;
+
+	*wr_idx = VXD_RD_REG_ABS(reg_base, VLR_OFFSET + PVDEC_FW_TO_HOST_WR_IDX_OFFSET);
+	*rd_idx = VXD_RD_REG_ABS(reg_base, VLR_OFFSET + PVDEC_FW_TO_HOST_RD_IDX_OFFSET);
+
+	if ((*rd_idx >= *size) || (*wr_idx >= *size))
+		return -EIO;
+
+	return 0;
+}
+
+static void pvdec_select_pipe(void __iomem *reg_base, unsigned char pipe)
+{
+	unsigned int reg = 0;
+
+	reg = VXD_WR_REG_FIELD(reg, PVDEC_CORE, PVDEC_HOST_PIPE_SELECT, PIPE_SEL, pipe);
+	VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_HOST_PIPE_SELECT, reg);
+}
+
+static void pvdec_pre_boot_setup(const void *dev,
+				 void __iomem *reg_base,
+				 struct vxd_ena_params *ena_params)
+{
+	/* Memory staller pre boot settings */
+	if (ena_params->mem_staller.data) {
+		unsigned char size = ena_params->mem_staller.size;
+
+		if (size == PVDEC_CORE_MEMSTALLER_ELEMENTS) {
+			unsigned int *data = ena_params->mem_staller.data;
+
+#ifdef DEBUG_DECODER_DRIVER
+			dev_dbg(dev, "%s: Setting up memory staller", __func__);
+#endif
+			/*
+			 * Data structure represents PVDEC_TEST memory staller
+			 * registers according to TRM 5.25 section
+			 */
+			VXD_WR_REG(reg_base, PVDEC_TEST, MEM_READ_LATENCY, data[0]);
+			VXD_WR_REG(reg_base, PVDEC_TEST, MEM_WRITE_RESPONSE_LATENCY, data[1]);
+			VXD_WR_REG(reg_base, PVDEC_TEST, MEM_CTRL, data[2]);
+			VXD_WR_REG(reg_base, PVDEC_TEST, RAND_STL_MEM_CMD_CONFIG, data[3]);
+			VXD_WR_REG(reg_base, PVDEC_TEST, RAND_STL_MEM_WDATA_CONFIG, data[4]);
+			VXD_WR_REG(reg_base, PVDEC_TEST, RAND_STL_MEM_WRESP_CONFIG, data[5]);
+			VXD_WR_REG(reg_base, PVDEC_TEST, RAND_STL_MEM_RDATA_CONFIG, data[6]);
+		} else {
+			dev_warn(dev, "%s: Wrong layout of mem staller config (%u)!",
+				 __func__, size);
+		}
+	}
+}
+
+static void pvdec_post_boot_setup(const void *dev,
+				  void __iomem *reg_base,
+				  unsigned int freq_khz)
+{
+	int reg;
+
+	/*
+	 * Configure VXD MMU to use video tiles (256x16) and unique
+	 * strides per context as default. There is currently no
+	 * override mechanism.
+	 */
+	reg = VXD_RD_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_CONTROL0);
+	reg = VXD_WR_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_CONTROL0,
+			       MMU_TILING_SCHEME, 0);
+	reg = VXD_WR_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_CONTROL0,
+			       USE_TILE_STRIDE_PER_CTX, 1);
+	VXD_WR_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_CONTROL0, reg);
+
+	/*
+	 * Setup VXD MMU with the tile heap device virtual address
+	 * ranges.
+	 */
+	VXD_WR_RPT_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_TILE_MIN_ADDR,
+		       PVDEC_HEAP_TILE512_START, 0);
+	VXD_WR_RPT_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_TILE_MAX_ADDR,
+		       PVDEC_HEAP_TILE512_START + PVDEC_HEAP_TILE512_SIZE - 1, 0);
+	VXD_WR_RPT_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_TILE_MIN_ADDR,
+		       PVDEC_HEAP_TILE1024_START, 1);
+	VXD_WR_RPT_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_TILE_MAX_ADDR,
+		       PVDEC_HEAP_TILE1024_START + PVDEC_HEAP_TILE1024_SIZE - 1, 1);
+	VXD_WR_RPT_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_TILE_MIN_ADDR,
+		       PVDEC_HEAP_TILE2048_START, 2);
+	VXD_WR_RPT_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_TILE_MAX_ADDR,
+		       PVDEC_HEAP_TILE2048_START + PVDEC_HEAP_TILE2048_SIZE - 1, 2);
+	VXD_WR_RPT_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_TILE_MIN_ADDR,
+		       PVDEC_HEAP_TILE4096_START, 3);
+	VXD_WR_RPT_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_TILE_MAX_ADDR,
+		       PVDEC_HEAP_TILE4096_START + PVDEC_HEAP_TILE4096_SIZE - 1, 3);
+
+	/* Disable timer */
+	VXD_WR_REG(reg_base, MTX_CORE, MTX_SYSC_TIMERDIV, 0);
+
+	reg = 0;
+	if (freq_khz)
+		reg = VXD_WR_REG_FIELD(reg, MTX_CORE, MTX_SYSC_TIMERDIV, TIMER_DIV,
+				       PVDEC_CALC_TIMER_DIV(freq_khz / 1000));
+	else
+		reg = VXD_WR_REG_FIELD(reg, MTX_CORE, MTX_SYSC_TIMERDIV,
+				       TIMER_DIV, PVDEC_CLK_MHZ_DEFAULT - 1);
+
+	/* Enable the MTX timer with final settings */
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, MTX_SYSC_TIMERDIV, TIMER_EN, 1);
+	VXD_WR_REG(reg_base, MTX_CORE, MTX_SYSC_TIMERDIV, reg);
+}
+
+static void pvdec_clock_measure(void __iomem *reg_base,
+				struct timespec64 *start_time,
+				unsigned int *start_ticks)
+{
+	local_irq_disable();
+	ktime_get_real_ts64(start_time);
+	*start_ticks = VXD_RD_REG(reg_base, MTX_CORE, MTX_SYSC_TXTIMER);
+	local_irq_enable();
+}
+
+static int pvdec_clock_calculate(const void *dev,
+				 void __iomem *reg_base,
+				 struct timespec64 *start_time,
+				 unsigned int start_ticks,
+				 unsigned int *freq_khz)
+{
+	struct timespec64 end_time, dif_time;
+	long long span_nsec = 0;
+	unsigned int stop_ticks, tot_ticks;
+
+	local_irq_disable();
+	ktime_get_real_ts64(&end_time);
+
+	stop_ticks = VXD_RD_REG(reg_base, MTX_CORE, MTX_SYSC_TXTIMER);
+	local_irq_enable();
+
+	*(struct timespec64 *)(&dif_time) = timespec64_sub(*((struct timespec64 *)(&end_time)),
+							  *((struct timespec64 *)(&start_time)));
+
+	span_nsec = timespec64_to_ns((const struct timespec64 *)&dif_time);
+
+	/* Sanity check for mtx timer */
+	if (!stop_ticks || stop_ticks < start_ticks) {
+		dev_err(dev, "%s: invalid ticks (0x%x -> 0x%x)\n",
+			__func__, start_ticks, stop_ticks);
+		return -EIO;
+	}
+	tot_ticks = stop_ticks - start_ticks;
+
+	if (span_nsec) {
+		unsigned long long res = (unsigned long long)tot_ticks * 1000000UL;
+
+		do_divide(&res, span_nsec);
+		*freq_khz = (unsigned int)res;
+		if (*freq_khz < 1000)
+			*freq_khz = 1000;   /* 1MHz */
+	} else {
+		dev_err(dev, "%s: generic failure!\n", __func__);
+		*freq_khz = 0;
+		return -ERANGE;
+	}
+
+	return 0;
+}
+
+static int pvdec_wait_dma_done(const void *dev,
+			       void __iomem *reg_base,
+			       unsigned long size,
+			       unsigned char dma_channel)
+{
+	unsigned int reg, timeout = PVDEC_TIMEOUT_COUNTER, prev_count, count = size;
+
+	do {
+		usleep_range(300, 310);
+		prev_count = count;
+		reg = VXD_RD_RPT_REG(reg_base, DMAC, DMAC_COUNT, dma_channel);
+		count = VXD_RD_REG_FIELD(reg, DMAC, DMAC_COUNT, CNT);
+		/* Check for dma progress */
+		if (count == prev_count) {
+			/* There could be a bus lag, protect against that */
+			timeout--;
+			if (timeout == 0) {
+				dev_err(dev, "%s FW DMA failed! (0x%x)\n", __func__, count);
+				return -EIO;
+			}
+		} else {
+			/* Reset timeout counter */
+			timeout = PVDEC_TIMEOUT_COUNTER;
+		}
+	} while (count > 0);
+
+	return 0;
+}
+
+static int pvdec_start_fw_dma(const void *dev,
+			      void __iomem *reg_base,
+			      unsigned char dma_channel,
+			      unsigned long fw_buf_size,
+			      unsigned int *freq_khz)
+{
+	unsigned int reg = 0;
+	int ret = 0;
+
+	fw_buf_size = fw_buf_size / sizeof(unsigned int);
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: dma FW upload, fw_buf_size: %zu (dwords)\n", __func__, fw_buf_size);
+#endif
+
+	pvdec_select_pipe(reg_base, 1);
+
+	reg = VXD_RD_REG(reg_base, PVDEC_PIXEL, PIXEL_MAN_CLK_ENA);
+	reg = VXD_WR_REG_FIELD(reg, PVDEC_PIXEL, PIXEL_MAN_CLK_ENA, PIXEL_DMAC_MAN_CLK_ENA, 1);
+	reg = VXD_WR_REG_FIELD(reg, PVDEC_PIXEL, PIXEL_MAN_CLK_ENA, PIXEL_REG_MAN_CLK_ENA, 1);
+	VXD_WR_REG(reg_base, PVDEC_PIXEL, PIXEL_MAN_CLK_ENA, reg);
+
+	/*
+	 * Setup MTX to receive DMA
+	 * DMA transfers to/from the MTX have to be 32-bit aligned and
+	 * in multiples of 32 bits
+	 */
+	VXD_WR_REG(reg_base, MTX_CORE, MTX_SYSC_CDMAA, 0); /* MTX: 0x80900000 */
+
+	reg = 0;
+	/* Burst size in multiples of 64 bits (allowed values are 2 or 4) */
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, MTX_SYSC_CDMAC, BURSTSIZE, 0);
+	/* 0 - write to MTX memory */
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, MTX_SYSC_CDMAC, RNW, 0);
+	/* Begin transfer */
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, MTX_SYSC_CDMAC, ENABLE, 1);
+	/* Transfer size */
+	reg = VXD_WR_REG_FIELD(reg, MTX_CORE, MTX_SYSC_CDMAC, LENGTH,
+			       ((fw_buf_size + 7) & (~7)) + 8);
+	VXD_WR_REG(reg_base, MTX_CORE, MTX_SYSC_CDMAC, reg);
+
+	/* Boot MTX once transfer is done */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, PVDEC_CORE, PROC_DMAC_CONTROL,
+			       BOOT_ON_DMA_CH0, 1);
+	VXD_WR_REG(reg_base, PVDEC_CORE, PROC_DMAC_CONTROL, reg);
+
+	/* Toggle channel 0 usage between MTX and other PVDEC peripherals */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, PVDEC_PIXEL, PIXEL_CONTROL_0,
+			       DMAC_CH_SEL_FOR_MTX, 0);
+	VXD_WR_REG(reg_base, PVDEC_PIXEL, PIXEL_CONTROL_0, reg);
+
+	/* Reset DMA channel first */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, SRST, 1);
+	VXD_WR_RPT_REG(reg_base, DMAC, DMAC_COUNT, reg, dma_channel);
+
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, LIST_EN, 0);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, CNT, 0);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, EN, 0);
+	VXD_WR_RPT_REG(reg_base, DMAC, DMAC_COUNT, reg, dma_channel);
+
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, SRST, 0);
+	VXD_WR_RPT_REG(reg_base, DMAC, DMAC_COUNT, reg, dma_channel);
+
+	/*
+	 * Setup a Simple DMA for Ch0
+	 * Specify the holdover period to use for the channel
+	 */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_PER_HOLD, PER_HOLD, 7);
+	VXD_WR_RPT_REG(reg_base, DMAC, DMAC_PER_HOLD, reg, dma_channel);
+
+	/* Clear the DMAC Stats */
+	VXD_WR_RPT_REG(reg_base, DMAC, DMAC_IRQ_STAT, 0, dma_channel);
+
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_PERIPH_ADDR, ADDR,
+			       MTX_CORE_MTX_SYSC_CDMAT_OFFSET);
+	VXD_WR_RPT_REG(reg_base, DMAC, DMAC_PERIPH_ADDR, reg, dma_channel);
+
+	/* Clear peripheral register address */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_PERIPH, ACC_DEL, 0);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_PERIPH, INCR, DMAC_INCR_OFF);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_PERIPH, BURST, DMAC_BURST_1);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_PERIPH, EXT_BURST, DMAC_EXT_BURST_0);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_PERIPH, EXT_SA, 0);
+	VXD_WR_RPT_REG(reg_base, DMAC, DMAC_PERIPH, reg, dma_channel);
+
+	/*
+	 * Now start the transfer by setting the list enable bit in
+	 * the count register
+	 */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, TRANSFER_IEN, 1);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, PW, DMAC_PWIDTH_32_BIT);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, DIR, DMAC_MEM_TO_VXD);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, PI, DMAC_INCR_ON);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, LIST_FIN_CTL, 0);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, LIST_EN, 0);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, ENABLE_2D_MODE, 0);
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, CNT, fw_buf_size);
+	VXD_WR_RPT_REG(reg_base, DMAC, DMAC_COUNT, reg, dma_channel);
+
+	reg = VXD_WR_REG_FIELD(reg, DMAC, DMAC_COUNT, EN, 1);
+	VXD_WR_RPT_REG(reg_base, DMAC, DMAC_COUNT, reg, dma_channel);
+
+	/* NOTE: The MTX timer starts once DMA boot is triggered */
+	{
+		struct timespec64 host_time;
+		unsigned int mtx_time;
+
+		pvdec_clock_measure(reg_base, &host_time, &mtx_time);
+
+		ret = pvdec_wait_dma_done(dev, reg_base, fw_buf_size, dma_channel);
+		if (!ret) {
+			if (pvdec_clock_calculate(dev, reg_base, &host_time, mtx_time,
+						  freq_khz) < 0)
+				dev_dbg(dev, "%s: measure info not available!\n", __func__);
+		}
+	}
+
+	return ret;
+}
+
+static int pvdec_set_clocks(void __iomem *reg_base, unsigned int req_clocks)
+{
+	unsigned int clocks = 0, reg;
+	unsigned int pvdec_timeout;
+
+	/* Turn on core clocks only */
+	clocks = VXD_WR_REG_FIELD(clocks, PVDEC_CORE, PVDEC_MAN_CLK_ENA,
+				  PVDEC_REG_MAN_CLK_ENA, 1);
+	clocks = VXD_WR_REG_FIELD(clocks, PVDEC_CORE, PVDEC_MAN_CLK_ENA, CORE_MAN_CLK_ENA, 1);
+
+	/* Wait until core clocks set */
+	pvdec_timeout = PVDEC_TIMEOUT_COUNTER;
+	do {
+		VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_MAN_CLK_ENA, clocks);
+		udelay(vxd_plat_poll_udelay);
+		reg = VXD_RD_REG(reg_base, PVDEC_CORE, PVDEC_MAN_CLK_ENA);
+		pvdec_timeout--;
+	} while (reg != clocks && pvdec_timeout != 0);
+
+	if (pvdec_timeout == 0)
+		return -EIO;
+
+	/* Write requested clocks */
+	VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_MAN_CLK_ENA, req_clocks);
+
+	return 0;
+}
+
+static int pvdec_enable_clocks(void __iomem *reg_base)
+{
+	unsigned int clocks = 0;
+
+	clocks = VXD_WR_REG_FIELD(clocks, PVDEC_CORE, PVDEC_MAN_CLK_ENA,
+				  PVDEC_REG_MAN_CLK_ENA, 1);
+	clocks = VXD_WR_REG_FIELD(clocks, PVDEC_CORE, PVDEC_MAN_CLK_ENA,
+				  CORE_MAN_CLK_ENA, 1);
+	clocks = VXD_WR_REG_FIELD(clocks, PVDEC_CORE, PVDEC_MAN_CLK_ENA,
+				  MEM_MAN_CLK_ENA, 1);
+	clocks = VXD_WR_REG_FIELD(clocks, PVDEC_CORE, PVDEC_MAN_CLK_ENA,
+				  PROC_MAN_CLK_ENA, 1);
+	clocks = VXD_WR_REG_FIELD(clocks, PVDEC_CORE, PVDEC_MAN_CLK_ENA,
+				  PIXEL_PROC_MAN_CLK_ENA, 1);
+
+	return pvdec_set_clocks(reg_base, clocks);
+}
+
+static int pvdec_disable_clocks(void __iomem *reg_base)
+{
+	return pvdec_set_clocks(reg_base, 0);
+}
+
+static void pvdec_ena_mtx_int(void __iomem *reg_base)
+{
+	unsigned int reg = VXD_RD_REG(reg_base, PVDEC_CORE, PVDEC_HOST_INT_ENA);
+
+	reg = VXD_WR_REG_FIELD(reg, PVDEC_CORE, PVDEC_INT_STAT, HOST_PROC_IRQ, 1);
+	reg = VXD_WR_REG_FIELD(reg, PVDEC_CORE, PVDEC_INT_STAT, HOST_MMU_FAULT_IRQ, 1);
+	VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_HOST_INT_ENA, reg);
+}
+
+static void pvdec_check_mmu_requests(void __iomem *reg_base,
+				     unsigned int mmu_checks,
+				     unsigned int max_attempts)
+{
+	unsigned int reg, i, checks = 0;
+
+	for (i = 0; i < max_attempts; i++) {
+		reg = VXD_RD_REG(reg_base,
+				 IMG_VIDEO_BUS4_MMU, MMU_MEM_REQ);
+		reg = VXD_RD_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_MEM_REQ, TAG_OUTSTANDING);
+		if (reg) {
+			udelay(vxd_plat_poll_udelay);
+			continue;
+		}
+
+		/* Read READ_WORDS_OUTSTANDING */
+		reg = VXD_RD_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_MEM_EXT_OUTSTANDING);
+		reg = VXD_RD_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_MEM_EXT_OUTSTANDING,
+				       READ_WORDS);
+		if (!reg) {
+			checks++;
+			if (checks == mmu_checks)
+				break;
+		} else { /* Reset the counter and continue */
+			checks = 0;
+		}
+	}
+
+	if (checks != mmu_checks)
+		pr_warn("Checking for MMU outstanding requests failed!\n");
+}
+
+static int pvdec_reset(void __iomem *reg_base, unsigned char skip_pipe_clocks)
+{
+	unsigned int reg = 0;
+	unsigned char pipe, num_ent_pipes, num_pix_pipes;
+	unsigned int core_id, pvdec_timeout;
+
+	core_id = VXD_RD_REG(reg_base, PVDEC_CORE, PVDEC_CORE_ID);
+
+	num_ent_pipes = VXD_RD_REG_FIELD(core_id, PVDEC_CORE, PVDEC_CORE_ID, ENT_PIPES);
+	num_pix_pipes = VXD_RD_REG_FIELD(core_id, PVDEC_CORE, PVDEC_CORE_ID, PIX_PIPES);
+
+	if (num_pix_pipes == 0 || num_pix_pipes > VXD_MAX_PIPES)
+		return -EINVAL;
+
+	/* Clear interrupt enabled flag */
+	VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_HOST_INT_ENA, 0);
+
+	/* Clear any pending interrupt flags */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, PVDEC_CORE, PVDEC_INT_CLEAR, IRQ_CLEAR, 0xFFFF);
+	VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_INT_CLEAR, reg);
+
+	/* Turn all clocks on - don't touch reserved bits! */
+	pvdec_set_clocks(reg_base, 0xFFFF0113);
+
+	if (!skip_pipe_clocks) {
+		for (pipe = 1; pipe <= num_pix_pipes; pipe++) {
+			pvdec_select_pipe(reg_base, pipe);
+			/* Turn all available clocks on - skip reserved bits! */
+			VXD_WR_REG(reg_base, PVDEC_PIXEL, PIXEL_MAN_CLK_ENA, 0xFFBF0FFF);
+		}
+
+		for (pipe = 1; pipe <= num_ent_pipes; pipe++) {
+			pvdec_select_pipe(reg_base, pipe);
+			/* Turn all available clocks on - skip reserved bits! */
+			VXD_WR_REG(reg_base, PVDEC_ENTROPY, ENTROPY_MAN_CLK_ENA, 0x5);
+		}
+	}
+
+	/* 1st MMU outstanding requests check */
+	pvdec_check_mmu_requests(reg_base, 1000, 2000);
+
+	/* Make sure MMU is not under reset MMU_SOFT_RESET -> 0 */
+	pvdec_timeout = PVDEC_TIMEOUT_COUNTER;
+	do {
+		reg = VXD_RD_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1);
+		reg = VXD_RD_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, MMU_SOFT_RESET);
+		udelay(vxd_plat_poll_udelay);
+		pvdec_timeout--;
+	} while (reg != 0 && pvdec_timeout != 0);
+
+	if (pvdec_timeout == 0) {
+		pr_err("Waiting for MMU soft reset(1) timed out!\n");
+		pvdec_mtx_status_dump(reg_base, NULL);
+	}
+
+	/* Write 1 to MMU_PAUSE_SET */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, MMU_PAUSE_SET, 1);
+	VXD_WR_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, reg);
+
+	/* 2nd MMU outstanding requests check */
+	pvdec_check_mmu_requests(reg_base, 100, 1000);
+
+	/* Issue software reset for all but MMU/core */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, PVDEC_CORE, PVDEC_SOFT_RST, PVDEC_PIXEL_PROC_SOFT_RST, 0xFF);
+	reg = VXD_WR_REG_FIELD(reg, PVDEC_CORE, PVDEC_SOFT_RST, PVDEC_ENTROPY_SOFT_RST, 0xFF);
+	VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_SOFT_RST, reg);
+
+	VXD_RD_REG(reg_base, PVDEC_CORE, PVDEC_SOFT_RST);
+	VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_SOFT_RST, 0);
+
+	/* Write 1 to MMU_PAUSE_CLEAR in MMU_CONTROL1 reg */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, MMU_PAUSE_CLEAR, 1);
+	VXD_WR_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, reg);
+
+	/* Confirm MMU_PAUSE_SET is cleared */
+	pvdec_timeout = PVDEC_TIMEOUT_COUNTER;
+	do {
+		reg = VXD_RD_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1);
+		reg = VXD_RD_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, MMU_PAUSE_SET);
+		udelay(vxd_plat_poll_udelay);
+		pvdec_timeout--;
+	} while (reg != 0 && pvdec_timeout != 0);
+
+	if (pvdec_timeout == 0) {
+		pr_err("Waiting for MMU pause clear timed out!\n");
+		pvdec_mtx_status_dump(reg_base, NULL);
+		return -EIO;
+	}
+
+	/* Issue software reset for MMU */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, MMU_SOFT_RESET, 1);
+	VXD_WR_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, reg);
+
+	/* Wait until MMU_SOFT_RESET -> 0 */
+	pvdec_timeout = PVDEC_TIMEOUT_COUNTER;
+	do {
+		reg = VXD_RD_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1);
+		reg = VXD_RD_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, MMU_SOFT_RESET);
+		udelay(vxd_plat_poll_udelay);
+		pvdec_timeout--;
+	} while (reg != 0 && pvdec_timeout != 0);
+
+	if (pvdec_timeout == 0) {
+		pr_err("Waiting for MMU soft reset(2) timed out!\n");
+		pvdec_mtx_status_dump(reg_base, NULL);
+	}
+
+	/* Issue software reset for entire PVDEC */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, PVDEC_CORE, PVDEC_SOFT_RST, PVDEC_SOFT_RST, 0x1);
+	VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_SOFT_RST, reg);
+
+	/* Waiting for reset bit to be cleared */
+	pvdec_timeout = PVDEC_TIMEOUT_COUNTER;
+	do {
+		reg = VXD_RD_REG(reg_base, PVDEC_CORE, PVDEC_SOFT_RST);
+		reg = VXD_RD_REG_FIELD(reg, PVDEC_CORE, PVDEC_SOFT_RST, PVDEC_SOFT_RST);
+		udelay(vxd_plat_poll_udelay);
+		pvdec_timeout--;
+	} while (reg != 0 && pvdec_timeout != 0);
+
+	if (pvdec_timeout == 0) {
+		pr_err("Waiting for PVDEC soft reset timed out!\n");
+		pvdec_mtx_status_dump(reg_base, NULL);
+		return -EIO;
+	}
+
+	/* Clear interrupt enabled flag */
+	VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_HOST_INT_ENA, 0);
+
+	/* Clear any pending interrupt flags */
+	reg = 0;
+	reg = VXD_WR_REG_FIELD(reg, PVDEC_CORE, PVDEC_INT_CLEAR, IRQ_CLEAR, 0xFFFF);
+	VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_INT_CLEAR, reg);
+	return 0;
+}
+
+static int pvdec_get_properties(void __iomem *reg_base,
+				struct vxd_core_props *props)
+{
+	unsigned int major, minor, maint, group_id, core_id;
+	unsigned char num_pix_pipes, pipe;
+
+	if (!props)
+		return -EINVAL;
+
+	/* PVDEC Core Revision Information */
+	props->core_rev = VXD_RD_REG(reg_base, PVDEC_CORE, PVDEC_CORE_REV);
+	major = VXD_RD_REG_FIELD(props->core_rev, PVDEC_CORE, PVDEC_CORE_REV, PVDEC_MAJOR_REV);
+	minor = VXD_RD_REG_FIELD(props->core_rev, PVDEC_CORE, PVDEC_CORE_REV, PVDEC_MINOR_REV);
+	maint = VXD_RD_REG_FIELD(props->core_rev, PVDEC_CORE, PVDEC_CORE_REV, PVDEC_MAINT_REV);
+
+	/* Core ID */
+	props->pvdec_core_id = VXD_RD_REG(reg_base, PVDEC_CORE, PVDEC_CORE_ID);
+	group_id = VXD_RD_REG_FIELD(props->pvdec_core_id, PVDEC_CORE, PVDEC_CORE_ID, GROUP_ID);
+	core_id = VXD_RD_REG_FIELD(props->pvdec_core_id, PVDEC_CORE, PVDEC_CORE_ID, CORE_ID);
+
+	/* Ensure that the core is IMG Video Decoder (PVDEC). */
+	if (group_id != 3 || core_id != 3) {
+		pr_err("Wrong core revision %d.%d.%d !!!\n", major, minor, maint);
+		return -EIO;
+	}
+
+	props->mmu_config0 = VXD_RD_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_CONFIG0);
+	props->mmu_config1 = VXD_RD_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_CONFIG1);
+
+	num_pix_pipes = VXD_NUM_PIX_PIPES(*props);
+
+	if (unlikely(num_pix_pipes > VXD_MAX_PIPES)) {
+		pr_warn("Too many pipes detected!\n");
+		num_pix_pipes = VXD_MAX_PIPES;
+	}
+
+	for (pipe = 1; pipe <= num_pix_pipes; ++pipe) {
+		pvdec_select_pipe(reg_base, pipe);
+		if (pipe < VXD_MAX_PIPES) {
+			props->pixel_pipe_cfg[pipe - 1] =
+				VXD_RD_REG(reg_base, PVDEC_PIXEL, PIXEL_PIPE_CONFIG);
+			props->pixel_misc_cfg[pipe - 1] =
+				VXD_RD_REG(reg_base, PVDEC_PIXEL, PIXEL_MISC_CONFIG);
+			/*
+			 * Detect pipe access problems.
+			 * Pipe config shall always indicate
+			 * a non zero value (at least one standard supported)!
+			 */
+			if (!props->pixel_pipe_cfg[pipe - 1])
+				pr_warn("Pipe config info is wrong!\n");
+		}
+	}
+
+	pvdec_select_pipe(reg_base, 1);
+	props->pixel_max_frame_cfg = VXD_RD_REG(reg_base, PVDEC_PIXEL, MAX_FRAME_CONFIG);
+
+	{
+		unsigned int fifo_ctrl = VXD_RD_REG(reg_base, PVDEC_CORE, PROC_DBG_FIFO_CTRL0);
+
+		props->dbg_fifo_size = VXD_RD_REG_FIELD(fifo_ctrl,
+							PVDEC_CORE,
+							PROC_DBG_FIFO_CTRL0,
+							PROC_DBG_FIFO_SIZE);
+	}
+
+	return 0;
+}
+
+int vxd_pvdec_init(const void *dev, void __iomem *reg_base)
+{
+	int ret;
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: trying to reset VXD, reg base: %p\n", __func__, reg_base);
+#endif
+
+	ret = pvdec_enable_clocks(reg_base);
+	if (ret) {
+		dev_err(dev, "%s: failed to enable clocks!\n", __func__);
+		return ret;
+	}
+
+	ret = pvdec_reset(reg_base, FALSE);
+	if (ret) {
+		dev_err(dev, "%s: VXD reset failed!\n", __func__);
+		return ret;
+	}
+
+	pvdec_ena_mtx_int(reg_base);
+
+	return 0;
+}
+
+/* Send <msg_size> dwords long message */
+int vxd_pvdec_send_msg(const void *dev,
+		       void __iomem *reg_base,
+		       unsigned int *msg,
+		       unsigned long msg_size,
+		       unsigned short msg_id,
+		       struct vxd_dev *ctx)
+{
+	int ret, to_mtx_off; /* offset in dwords */
+	unsigned int wr_idx, rd_idx; /* indicies in dwords */
+	unsigned long to_mtx_size; /* size in dwords */
+	unsigned int msg_wrd;
+	struct timespec64 time;
+	static int cnt;
+
+	ktime_get_real_ts64(&time);
+
+	ctx->time_fw[cnt].start_time = timespec64_to_ns((const struct timespec64 *)&time);
+	ctx->time_fw[cnt].id = msg_id;
+	cnt++;
+
+	if (cnt >= ARRAY_SIZE(ctx->time_fw))
+		cnt = 0;
+
+	ret = pvdec_get_to_mtx_cfg(reg_base, &to_mtx_size, &to_mtx_off, &wr_idx, &rd_idx);
+	if (ret) {
+		dev_err(dev, "%s: failed to obtain mtx ring buffer config!\n", __func__);
+		return ret;
+	}
+
+	/* populate the size and id fields in the message header */
+	msg_wrd = VXD_RD_MSG_WRD(msg, PVDEC_FW, DEVA_GENMSG);
+	msg_wrd = VXD_WR_REG_FIELD(msg_wrd, PVDEC_FW, DEVA_GENMSG, MSG_SIZE, msg_size);
+	msg_wrd = VXD_WR_REG_FIELD(msg_wrd, PVDEC_FW, DEVA_GENMSG, MSG_ID, msg_id);
+	VXD_WR_MSG_WRD(msg, PVDEC_FW, DEVA_GENMSG, msg_wrd);
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: [msg out] size: %zu, id: 0x%x, type: 0x%x\n", __func__, msg_size, msg_id,
+		VXD_RD_REG_FIELD(msg_wrd, PVDEC_FW, DEVA_GENMSG, MSG_TYPE));
+	dev_dbg(dev, "%s: to_mtx: (%zu @ %d), wr_idx: %d, rd_idx: %d\n",
+		__func__, to_mtx_size, to_mtx_off, wr_idx, rd_idx);
+#endif
+
+	ret = pvdec_check_comms_space(reg_base, msg_size, FALSE);
+	if (ret) {
+		dev_err(dev, "%s: invalid message or not enough space (%d)!\n", __func__, ret);
+		return ret;
+	}
+
+	ret = pvdec_write_vlr(reg_base, msg, msg_size, to_mtx_off + wr_idx);
+	if (ret) {
+		dev_err(dev, "%s: failed to write msg to vlr!\n", __func__);
+		return ret;
+	}
+
+	wr_idx += msg_size;
+	if (wr_idx == to_mtx_size)
+		wr_idx = 0;
+	VXD_WR_REG_ABS(reg_base, VLR_OFFSET +
+		PVDEC_FW_TO_MTX_WR_IDX_OFFSET, wr_idx);
+
+	pvdec_kick_mtx(reg_base);
+
+	return 0;
+}
+
+/* Fetch size (in dwords) of message pending from MTX */
+int vxd_pvdec_pend_msg_info(const void *dev, void __iomem *reg_base,
+			    unsigned long *size,
+			    unsigned short *msg_id,
+			    unsigned char *not_last_msg)
+{
+	int ret, to_host_off; /* offset in dwords */
+	unsigned int wr_idx, rd_idx; /* indicies in dwords */
+	unsigned long to_host_size; /* size in dwords */
+	unsigned int val = 0;
+
+	ret = pvdec_get_to_host_cfg(reg_base, &to_host_size, &to_host_off, &wr_idx, &rd_idx);
+	if (ret) {
+		dev_err(dev, "%s: failed to obtain host ring buffer config!\n", __func__);
+		return ret;
+	}
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: to host: (%zu @ %d), wr: %u, rd: %u\n", __func__,
+		to_host_size, to_host_off, wr_idx, rd_idx);
+#endif
+
+	if (wr_idx == rd_idx) {
+		*size = 0;
+		*msg_id = 0;
+		return 0;
+	}
+
+	ret = pvdec_read_vlr(reg_base, &val, 1, to_host_off + rd_idx);
+	if (ret) {
+		dev_err(dev, "%s: failed to read first word!\n", __func__);
+		return ret;
+	}
+
+	*size = VXD_RD_REG_FIELD(val, PVDEC_FW, DEVA_GENMSG, MSG_SIZE);
+	*msg_id = VXD_RD_REG_FIELD(val, PVDEC_FW, DEVA_GENMSG, MSG_ID);
+	*not_last_msg = VXD_RD_REG_FIELD(val, PVDEC_FW, DEVA_GENMSG, NOT_LAST_MSG);
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: [msg in] rd_idx: %d, size: %zu, id: 0x%04x, type: 0x%x\n",
+		__func__, rd_idx, *size, *msg_id,
+		VXD_RD_REG_FIELD(val, PVDEC_FW, DEVA_GENMSG, MSG_TYPE));
+#endif
+
+	return 0;
+}
+
+/*
+ * Receive message from the MTX and place it in a <buf_size> dwords long
+ * buffer. If the provided buffer is too small to hold the message, only part
+ * of it will be placed in a buffer, but the ring buffer read index will be
+ * moved so that message is no longer available.
+ */
+int vxd_pvdec_recv_msg(const void *dev, void __iomem *reg_base,
+		       unsigned int *buf,
+		       unsigned long buf_size,
+		       struct vxd_dev *vxd)
+{
+	int ret, to_host_off; /* offset in dwords */
+	unsigned int wr_idx, rd_idx; /* indicies in dwords */
+	unsigned long to_host_size, msg_size, to_read; /* sizes in dwords */
+	unsigned int val = 0;
+	struct timespec64 time;
+	unsigned short msg_id;
+	int loop;
+
+	ret = pvdec_get_to_host_cfg(reg_base, &to_host_size,
+				    &to_host_off, &wr_idx, &rd_idx);
+	if (ret) {
+		dev_err(dev, "%s: failed to obtain host ring buffer config!\n", __func__);
+		return ret;
+	}
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: to host: (%zu @ %d), wr: %u, rd: %u\n", __func__,
+		to_host_size, to_host_off, wr_idx, rd_idx);
+#endif
+
+	/* Obtain the message size */
+	ret = pvdec_read_vlr(reg_base, &val, 1, to_host_off + rd_idx);
+	if (ret) {
+		dev_err(dev, "%s: failed to read first word!\n", __func__);
+		return ret;
+	}
+	msg_size = VXD_RD_REG_FIELD(val, PVDEC_FW, DEVA_GENMSG, MSG_SIZE);
+
+	to_read = (msg_size > buf_size) ? buf_size : msg_size;
+
+	/* Does the message wrap? */
+	if (to_read + rd_idx > to_host_size) {
+		unsigned long chunk_size = to_host_size - rd_idx;
+
+		ret = pvdec_read_vlr(reg_base, buf, chunk_size, to_host_off + rd_idx);
+		if (ret) {
+			dev_err(dev, "%s: failed to read chunk before wrap!\n", __func__);
+			return ret;
+		}
+		to_read -= chunk_size;
+		buf += chunk_size;
+		rd_idx = 0;
+		msg_size -= chunk_size;
+	}
+
+	/*
+	 * If the message wrapped, read the second chunk.
+	 * If it didn't, read first and only chunk
+	 */
+	ret = pvdec_read_vlr(reg_base, buf, to_read, to_host_off + rd_idx);
+	if (ret) {
+		dev_err(dev, "%s: failed to read message from vlr!\n", __func__);
+		return ret;
+	}
+
+	/* Update read index in the ring buffer */
+	rd_idx = (rd_idx + msg_size) % to_host_size;
+	VXD_WR_REG_ABS(reg_base, VLR_OFFSET +
+		PVDEC_FW_TO_HOST_RD_IDX_OFFSET, rd_idx);
+
+	msg_id = VXD_RD_REG_FIELD(val, PVDEC_FW, DEVA_GENMSG, MSG_ID);
+
+	ktime_get_real_ts64(&time);
+	for (loop = 0; loop < ARRAY_SIZE(vxd->time_fw); loop++) {
+		if (vxd->time_fw[loop].id == msg_id) {
+			vxd->time_fw[loop].end_time =
+				timespec64_to_ns((const struct timespec64 *)&time);
+#ifdef DEBUG_DECODER_DRIVER
+			dev_info(dev, "fw decode time is %llu us for msg_id x%0x\n",
+				 div_s64(vxd->time_fw[loop].end_time -
+				 vxd->time_fw[loop].start_time, 1000), msg_id);
+#endif
+					break;
+		}
+	}
+
+	if (loop == ARRAY_SIZE(vxd->time_fw))
+		dev_err(dev, "fw decode time for msg_id x%0x is not measured\n", msg_id);
+
+	return 0;
+}
+
+int vxd_pvdec_check_fw_status(const void *dev, void __iomem *reg_base)
+{
+	int ret;
+	unsigned int val = 0;
+
+	/* Obtain current fw status */
+	ret = pvdec_read_vlr(reg_base, &val, 1, PVDEC_FW_STATUS_OFFSET);
+	if (ret) {
+		dev_err(dev, "%s: failed to read fw status!\n", __func__);
+		return ret;
+	}
+
+	/* Check for fatal condition */
+	if (val == PVDEC_FW_STATUS_PANIC  || val == PVDEC_FW_STATUS_ASSERT ||
+	    val == PVDEC_FW_STATUS_SO)
+		return -1;
+
+	return 0;
+}
+
+static int pvdec_send_init_msg(const void *dev,
+			       void __iomem *reg_base,
+			       struct vxd_ena_params *ena_params)
+{
+	unsigned short msg_id = 0;
+	unsigned int msg[PVDEC_FW_DEVA_INIT_MSG_WRDS] = { 0 }, msg_wrd = 0;
+	struct vxd_dev *vxd;
+	int ret;
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: rendec: %d@0x%x, crc: 0x%x\n", __func__,
+		ena_params->rendec_size, ena_params->rendec_addr, ena_params->crc);
+#endif
+
+	vxd = kzalloc(sizeof(*vxd), GFP_KERNEL);
+	if (!vxd)
+		return -1;
+
+	/* message type */
+	msg_wrd = VXD_WR_REG_FIELD(msg_wrd, PVDEC_FW, DEVA_GENMSG, MSG_TYPE,
+				   PVDEC_FW_MSG_TYPE_INIT);
+	VXD_WR_MSG_WRD(msg, PVDEC_FW, DEVA_GENMSG, msg_wrd);
+
+	/* rendec address */
+	VXD_WR_MSG_WRD(msg, PVDEC_FW_DEVA_INIT, RENDEC_ADDR0, ena_params->rendec_addr);
+
+	/* rendec size */
+	msg_wrd = 0;
+	msg_wrd = VXD_WR_REG_FIELD(msg_wrd, PVDEC_FW, DEVA_INIT, RENDEC_SIZE0,
+				   ena_params->rendec_size);
+	VXD_WR_MSG_WRD(msg, PVDEC_FW_DEVA_INIT, RENDEC_SIZE0, msg_wrd);
+
+	/* HEVC configuration */
+	msg_wrd = 0;
+	msg_wrd = VXD_WR_REG_FIELD(msg_wrd, PVDEC_FW, DEVA_INIT,
+				   HEVC_CFG_MAX_H_FOR_PIPE_WAIT, 0xFFFF);
+	VXD_WR_MSG_WRD(msg, PVDEC_FW_DEVA_INIT, HEVC_CFG, msg_wrd);
+
+	/* signature select */
+	VXD_WR_MSG_WRD(msg, PVDEC_FW_DEVA_INIT, SIG_SELECT, ena_params->crc);
+
+	/* partial frame notification timer divider */
+	msg_wrd = 0;
+	msg_wrd = VXD_WR_REG_FIELD(msg_wrd, PVDEC_FW, DEVA_INIT, PFNT_DIV, PVDEC_PFNT_DIV);
+	VXD_WR_MSG_WRD(msg, PVDEC_FW_DEVA_INIT, PFNT_DIV, msg_wrd);
+
+	/* firmware watchdog timeout value */
+	msg_wrd = VXD_WR_REG_FIELD(msg_wrd, PVDEC_FW, DEVA_INIT, FWWDT_MS, ena_params->fwwdt_ms);
+	VXD_WR_MSG_WRD(msg, PVDEC_FW_DEVA_INIT, FWWDT_MS, msg_wrd);
+
+	ret = vxd_pvdec_send_msg(dev, reg_base, msg, ARRAY_SIZE(msg), msg_id, vxd);
+	kfree(vxd);
+
+	return ret;
+}
+
+int vxd_pvdec_ena(const void *dev, void __iomem *reg_base,
+		  struct vxd_ena_params *ena_params,
+		  struct vxd_fw_hdr *fw_hdr,
+		  unsigned int *freq_khz)
+{
+	int ret;
+	unsigned int mtx_ram_size = 0;
+	unsigned char dma_channel = 0;
+
+	ret = vxd_pvdec_init(dev, reg_base);
+	if (ret) {
+		dev_err(dev, "%s: PVDEC init failed!\n", __func__);
+		return ret;
+	}
+
+	ret = pvdec_get_mtx_ram_size(reg_base, &mtx_ram_size);
+	if (ret) {
+		dev_err(dev, "%s: failed to get MTX RAM size!\n", __func__);
+		return ret;
+	}
+
+	if (mtx_ram_size < fw_hdr->core_size) {
+		dev_err(dev, "%s: FW larger than MTX RAM size (%u < %d)!\n",
+			__func__, mtx_ram_size, fw_hdr->core_size);
+		return -EINVAL;
+	}
+
+	/* Apply pre boot settings - if any */
+	pvdec_pre_boot_setup(dev, reg_base, ena_params);
+
+	pvdec_prep_fw_upload(dev, reg_base, ena_params, dma_channel);
+
+	ret = pvdec_start_fw_dma(dev, reg_base, dma_channel, fw_hdr->core_size, freq_khz);
+
+	if (ret) {
+		dev_err(dev, "%s: failed to load FW! (%d)", __func__, ret);
+		pvdec_mtx_status_dump(reg_base, NULL);
+		return ret;
+	}
+
+	/* Apply final settings - if any */
+	pvdec_post_boot_setup(dev, reg_base, *freq_khz);
+
+	ret = pvdec_poll_fw_boot(reg_base, &ena_params->boot_poll);
+	if (ret) {
+		dev_err(dev, "%s: FW failed to boot! (%d)!\n", __func__, ret);
+		return ret;
+	}
+
+	ret = pvdec_send_init_msg(dev, reg_base, ena_params);
+	if (ret) {
+		dev_err(dev, "%s: failed to send init message! (%d)!\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int vxd_pvdec_dis(const void *dev, void __iomem *reg_base)
+{
+	int ret = pvdec_enable_clocks(reg_base);
+
+	if (ret) {
+		dev_err(dev, "%s: failed to enable clocks! (%d)\n", __func__, ret);
+		return ret;
+	}
+
+	ret = pvdec_reset(reg_base, TRUE);
+	if (ret) {
+		dev_err(dev, "%s: VXD reset failed! (%d)\n", __func__, ret);
+		return ret;
+	}
+
+	ret = pvdec_disable_clocks(reg_base);
+	if (ret) {
+		dev_err(dev, "%s: VXD disable clocks failed! (%d)\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Invalidate VXD's MMU cache.
+ */
+int vxd_pvdec_mmu_flush(const void *dev, void __iomem *reg_base)
+{
+	unsigned int reg = VXD_RD_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1);
+
+	if (reg == PVDEC_INVALID_HW_STATE) {
+		dev_err(dev, "%s: invalid HW state!\n", __func__);
+		return -EIO;
+	}
+
+	reg = VXD_WR_REG_FIELD(reg, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, MMU_INVALDC, 0xF);
+	VXD_WR_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_CONTROL1, reg);
+
+#ifdef DEBUG_DECODER_DRIVER
+	dev_dbg(dev, "%s: device MMU cache invalidated!\n", __func__);
+#endif
+
+	return 0;
+}
+
+irqreturn_t vxd_pvdec_clear_int(void __iomem *reg_base, unsigned int *irq_status)
+{
+	irqreturn_t ret = IRQ_NONE;
+	unsigned int enabled;
+	unsigned int status = VXD_RD_REG(reg_base, PVDEC_CORE, PVDEC_INT_STAT);
+
+	enabled = VXD_RD_REG(reg_base, PVDEC_CORE, PVDEC_HOST_INT_ENA);
+
+	status &= enabled;
+	/* Store the last irq status */
+	*irq_status |= status;
+
+	if (status & (PVDEC_CORE_PVDEC_INT_STAT_HOST_MMU_FAULT_IRQ_MASK |
+		PVDEC_CORE_PVDEC_INT_STAT_HOST_PROC_IRQ_MASK))
+		ret = IRQ_WAKE_THREAD;
+
+	/* Disable MMU interrupts - clearing is not enough */
+	if (status & PVDEC_CORE_PVDEC_INT_STAT_HOST_MMU_FAULT_IRQ_MASK) {
+		enabled &= ~PVDEC_CORE_PVDEC_INT_STAT_HOST_MMU_FAULT_IRQ_MASK;
+		VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_HOST_INT_ENA, enabled);
+	}
+
+	VXD_WR_REG(reg_base, PVDEC_CORE, PVDEC_INT_CLEAR, status);
+
+	return ret;
+}
+
+/*
+ * Check if there's enough space in comms RAM to submit <msg_size> dwords long
+ * message. This function also submits a padding message if it will be
+ * necessary for this particular message.
+ *
+ * return 0 if there is enough space,
+ * return -EBUSY if there is not enough space,
+ * return another fault code in case of an error.
+ */
+int vxd_pvdec_msg_fit(const void *dev, void __iomem *reg_base, unsigned long msg_size)
+{
+	int ret = pvdec_check_comms_space(reg_base, msg_size, TRUE);
+
+	/*
+	 * In specific environment, when to_mtx buffer is small, and messages
+	 * the userspace is submitting are large (e.g. FWBSP flow), it's
+	 * possible that firmware will consume the padding message sent by
+	 * vxd_pvdec_msg_fit() immediately. Retry the check.
+	 */
+	if (ret == -EBUSY) {
+		unsigned int flags = VXD_RD_REG_ABS(reg_base,
+				VLR_OFFSET + PVDEC_FW_FLAGS_OFFSET) |
+			PVDEC_FWFLAG_FAKE_COMPLETION;
+
+#ifdef DEBUG_DECODER_DRIVER
+		dev_dbg(dev, "comms space full, asking fw to send empty msg when space is available");
+#endif
+
+		VXD_WR_REG_ABS(reg_base, VLR_OFFSET + PVDEC_FW_FLAGS_OFFSET, flags);
+		ret = pvdec_check_comms_space(reg_base, msg_size, FALSE);
+	}
+
+	return ret;
+}
+
+void vxd_pvdec_get_state(const void *dev, void __iomem *reg_base,
+			 unsigned int num_pipes,
+			 struct vxd_hw_state *state)
+{
+	unsigned char pipe;
+#ifdef DEBUG_DECODER_DRIVER
+	unsigned int state_cfg = VXD_RD_REG_ABS(reg_base, (VLR_OFFSET +
+			PVDEC_FW_STATE_BUF_CFG_OFFSET));
+
+	unsigned short state_size = PVDEC_FW_COM_BUF_SIZE(state_cfg);
+	unsigned short state_off = PVDEC_FW_COM_BUF_OFF(state_cfg);
+
+	/*
+	 * The generic fw progress counter
+	 * is the first element in the fw state
+	 */
+	dev_dbg(dev, "%s: state off: 0x%x, size: 0x%x\n", __func__, state_off, state_size);
+	state->fw_counter = VXD_RD_REG_ABS(reg_base, (VLR_OFFSET + state_off));
+	dev_dbg(dev, "%s: fw_counter: 0x%x\n", __func__, state->fw_counter);
+#endif
+
+	/* We just combine the macroblocks being processed by the HW */
+	for (pipe = 0; pipe < num_pipes; pipe++) {
+		unsigned int p_off = VXD_GET_PIPE_OFF(num_pipes, pipe + 1);
+		unsigned int reg_val;
+
+		/* Front-end */
+		unsigned int reg_off = VXD_GET_REG_OFF(PVDEC_ENTROPY, ENTROPY_LAST_MB);
+
+		state->fe_status[pipe] = VXD_RD_REG_ABS(reg_base, reg_off + p_off);
+
+		reg_off = VXD_GET_REG_OFF(MSVDX_VEC, VEC_ENTDEC_INFORMATION);
+		state->fe_status[pipe] |= VXD_RD_REG_ABS(reg_base, reg_off + p_off);
+
+		/* Back-end */
+		reg_off = VXD_GET_REG_OFF(PVDEC_VEC_BE, VEC_BE_STATUS);
+		state->be_status[pipe] = VXD_RD_REG_ABS(reg_base, reg_off + p_off);
+		reg_off = VXD_GET_REG_OFF(MSVDX_VDMC, VDMC_MACROBLOCK_NUMBER);
+		state->be_status[pipe] |= VXD_RD_REG_ABS(reg_base, reg_off + p_off);
+
+		/*
+		 * Take DMAC channels 2/3 into consideration to cover
+		 * parser progress on SR1/2
+		 */
+		reg_off = VXD_GET_RPT_REG_OFF(DMAC, DMAC_COUNT, 2);
+		reg_val = VXD_RD_REG_ABS(reg_base, reg_off + p_off);
+		state->dmac_status[pipe][0] = VXD_RD_REG_FIELD(reg_val, DMAC, DMAC_COUNT, CNT);
+		reg_off = VXD_GET_RPT_REG_OFF(DMAC, DMAC_COUNT, 3);
+		reg_val = VXD_RD_REG_ABS(reg_base, reg_off + p_off);
+		state->dmac_status[pipe][1] = VXD_RD_REG_FIELD(reg_val, DMAC, DMAC_COUNT, CNT);
+	}
+}
+
+/*
+ * Check for the source of the last interrupt.
+ *
+ * return 0 if nothing serious happened,
+ * return -EFAULT if there was a critical interrupt detected.
+ */
+int vxd_pvdec_check_irq(const void *dev, void __iomem *reg_base, unsigned int irq_status)
+{
+	if (irq_status & PVDEC_CORE_PVDEC_INT_STAT_HOST_MMU_FAULT_IRQ_MASK) {
+		unsigned int status0 =
+			VXD_RD_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_STATUS0);
+		unsigned int status1 =
+			VXD_RD_REG(reg_base, IMG_VIDEO_BUS4_MMU, MMU_STATUS1);
+
+		unsigned int addr = VXD_RD_REG_FIELD(status0, IMG_VIDEO_BUS4_MMU,
+				MMU_STATUS0, MMU_FAULT_ADDR) << 12;
+		unsigned char reason = VXD_RD_REG_FIELD(status0, IMG_VIDEO_BUS4_MMU,
+				MMU_STATUS0, MMU_PF_N_RW);
+		unsigned char requestor = VXD_RD_REG_FIELD(status1, IMG_VIDEO_BUS4_MMU,
+				MMU_STATUS1, MMU_FAULT_REQ_ID);
+		unsigned char type = VXD_RD_REG_FIELD(status1, IMG_VIDEO_BUS4_MMU,
+				MMU_STATUS1, MMU_FAULT_RNW);
+		unsigned char secure = VXD_RD_REG_FIELD(status0, IMG_VIDEO_BUS4_MMU,
+				MMU_STATUS0, MMU_SECURE_FAULT);
+
+#ifdef DEBUG_DECODER_DRIVER
+		dev_dbg(dev, "%s: MMU Page Fault s0:%08x s1:%08x", __func__, status0, status1);
+#endif
+
+		dev_err(dev, "%s: MMU %s fault from %s while %s @ 0x%08X", __func__,
+			(reason) ? "Page" : "Protection",
+			(requestor & (0x1)) ? "dmac" :
+			(requestor & (0x2)) ? "vec"  :
+			(requestor & (0x4)) ? "vdmc" :
+			(requestor & (0x8)) ? "vdeb" : "unknown source",
+			(type) ? "reading" : "writing", addr);
+
+		if (secure)
+			dev_err(dev, "%s: MMU security policy violation detected!", __func__);
+
+		return -EFAULT;
+	}
+
+	return 0;
+}
+
+/*
+ * This functions enables the clocks, fetches the core properties, stores them
+ * in the <props> structure and DISABLES the clocks. Do not call when hardware
+ * is busy!
+ */
+int vxd_pvdec_get_props(const void *dev, void __iomem *reg_base, struct vxd_core_props *props)
+{
+#ifdef DEBUG_DECODER_DRIVER
+	unsigned char num_pix_pipes, pipe;
+#endif
+	int ret = pvdec_enable_clocks(reg_base);
+
+	if (ret) {
+		dev_err(dev, "%s: failed to enable clocks!\n", __func__);
+		return ret;
+	}
+
+	ret = pvdec_get_mtx_ram_size(reg_base, &props->mtx_ram_size);
+	if (ret) {
+		dev_err(dev, "%s: failed to get MTX ram size!\n", __func__);
+		return ret;
+	}
+
+	ret = pvdec_get_properties(reg_base, props);
+	if (ret) {
+		dev_err(dev, "%s: failed to get VXD props!\n", __func__);
+		return ret;
+	}
+
+	if (pvdec_disable_clocks(reg_base))
+		dev_err(dev, "%s: failed to disable clocks!\n", __func__);
+
+#ifdef DEBUG_DECODER_DRIVER
+	num_pix_pipes = VXD_NUM_PIX_PIPES(*props);
+
+	/* Warning already raised in pvdec_get_properties() */
+	if (unlikely(num_pix_pipes > VXD_MAX_PIPES))
+		num_pix_pipes = VXD_MAX_PIPES;
+	dev_dbg(dev, "%s: core_rev: 0x%08x\n", __func__, props->core_rev);
+	dev_dbg(dev, "%s: pvdec_core_id: 0x%08x\n", __func__, props->pvdec_core_id);
+	dev_dbg(dev, "%s: mmu_config0: 0x%08x\n", __func__, props->mmu_config0);
+	dev_dbg(dev, "%s: mmu_config1: 0x%08x\n", __func__, props->mmu_config1);
+	dev_dbg(dev, "%s: mtx_ram_size: %u\n", __func__, props->mtx_ram_size);
+	dev_dbg(dev, "%s: pix max frame: 0x%08x\n", __func__, props->pixel_max_frame_cfg);
+
+	for (pipe = 1; pipe <= num_pix_pipes; ++pipe)
+		dev_dbg(dev, "%s:  pipe %u, 0x%08x, misc 0x%08x\n",
+			__func__, pipe, props->pixel_pipe_cfg[pipe - 1],
+			props->pixel_misc_cfg[pipe - 1]);
+	dev_dbg(dev, "%s: dbg fifo size: %u\n", __func__, props->dbg_fifo_size);
+#endif
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vxd_pvdec_priv.h b/drivers/media/platform/img/vxe-vxd/decoder/vxd_pvdec_priv.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vxd_pvdec_priv.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vxd_pvdec_priv.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD PVDEC Private header file
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Amit Makani <amit.makani@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#ifndef _VXD_PVDEC_PRIV_H
+#define _VXD_PVDEC_PRIV_H
+#include <linux/interrupt.h>
+
+#include "img_dec_common.h"
+#include "vxd_pvdec_regs.h"
+#include "vxd_dec.h"
+
+#ifdef ERROR_RECOVERY_SIMULATION
+/* kernel object used to debug. Declared in v4l2_int.c */
+extern struct kobject *vxd_dec_kobject;
+extern int disable_fw_irq_value;
+extern int g_module_irq;
+#endif
+
+struct vxd_boot_poll_params {
+	unsigned int msleep_cycles;
+};
+
+struct vxd_ena_params {
+	struct vxd_boot_poll_params boot_poll;
+
+	unsigned long fw_buf_size;
+	unsigned int fw_buf_virt_addr;
+	/*
+	 * VXD's MMU virtual address of a firmware
+	 * buffer.
+	 */
+	unsigned int ptd; /* Shifted physical address of PTD */
+
+	/* Required for firmware upload via registers. */
+	struct {
+		const unsigned char *buf; /* Firmware blob buffer */
+
+	} regs_data;
+
+	struct {
+		unsigned secure : 1;        /* Secure flow indicator. */
+		unsigned wait_dbg_fifo : 1; /*
+					     * Indicates that fw shall use
+					     * blocking mode when putting logs
+					     * into debug fifo
+					     */
+	};
+
+	/* Structure containing memory staller configuration */
+	struct {
+		unsigned int *data;          /* Configuration data array */
+		unsigned char size;            /* Configuration size in dwords */
+
+	} mem_staller;
+
+	unsigned int fwwdt_ms;    /* Firmware software watchdog timeout value */
+
+	unsigned int crc;         /* HW signatures to be enabled by firmware */
+	unsigned int rendec_addr; /* VXD's virtual address of a rendec buffer */
+	unsigned short rendec_size; /* Size of a rendec buffer in 4K pages */
+};
+
+int vxd_pvdec_init(const void *dev, void __iomem *reg_base);
+
+int vxd_pvdec_ena(const void *dev, void __iomem *reg_base,
+		  struct vxd_ena_params *ena_params, struct vxd_fw_hdr *hdr,
+		  unsigned int *freq_khz);
+
+int vxd_pvdec_dis(const void *dev, void __iomem *reg_base);
+
+int vxd_pvdec_mmu_flush(const void *dev, void __iomem *reg_base);
+
+int vxd_pvdec_send_msg(const void *dev, void __iomem *reg_base,
+		       unsigned int *msg, unsigned long msg_size, unsigned short msg_id,
+		       struct vxd_dev *ctx);
+
+int vxd_pvdec_pend_msg_info(const void *dev, void __iomem *reg_base,
+			    unsigned long *size, unsigned short *msg_id,
+			    unsigned char *not_last_msg);
+
+int vxd_pvdec_recv_msg(const void *dev, void __iomem *reg_base,
+		       unsigned int *buf, unsigned long buf_size, struct vxd_dev *ctx);
+
+int vxd_pvdec_check_fw_status(const void *dev, void __iomem *reg_base);
+
+unsigned long vxd_pvdec_peek_mtx_fifo(const void *dev,
+				      void __iomem *reg_base);
+
+unsigned long vxd_pvdec_read_mtx_fifo(const void *dev, void __iomem *reg_base,
+				      unsigned int *buf, unsigned long size);
+
+irqreturn_t vxd_pvdec_clear_int(void __iomem *reg_base, unsigned int *irq_status);
+
+int vxd_pvdec_check_irq(const void *dev, void __iomem *reg_base,
+			unsigned int irq_status);
+
+int vxd_pvdec_msg_fit(const void *dev, void __iomem *reg_base,
+		      unsigned long msg_size);
+
+void vxd_pvdec_get_state(const void *dev, void __iomem *reg_base,
+			 unsigned int num_pipes, struct vxd_hw_state *state);
+
+int vxd_pvdec_get_props(const void *dev, void __iomem *reg_base,
+			struct vxd_core_props *props);
+
+unsigned long vxd_pvdec_get_dbg_fifo_size(void __iomem *reg_base);
+
+int vxd_pvdec_dump_mtx_ram(const void *dev, void __iomem *reg_base,
+			   unsigned int addr, unsigned int count, unsigned int *buf);
+
+int vxd_pvdec_dump_mtx_status(const void *dev, void __iomem *reg_base,
+			      unsigned int *array, unsigned int array_size);
+
+#endif /* _VXD_PVDEC_PRIV_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vxd_pvdec_regs.h b/drivers/media/platform/img/vxe-vxd/decoder/vxd_pvdec_regs.h
--- a/drivers/media/platform/img/vxe-vxd/decoder/vxd_pvdec_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vxd_pvdec_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,779 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * VXD PVDEC registers header file
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *
+ * Re-written for upstreamimg
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ */
+
+#ifndef VXD_PVDEC_REGS_H
+#define VXD_PVDEC_REGS_H
+
+/* ************************* VXD-specific values *************************** */
+/* 0x10 for code, 0x18 for data. */
+#define PVDEC_MTX_CORE_MEM 0x18
+/* Iteration time out counter for MTX I/0. */
+#define PVDEC_TIMEOUT_COUNTER 1000
+/* Partial frame notification timer divider. */
+#define PVDEC_PFNT_DIV 0
+/* Value returned by register reads when HW enters invalid state (FPGA) */
+#define PVDEC_INVALID_HW_STATE 0x000dead1
+
+/* Default core clock for pvdec */
+#define PVDEC_CLK_MHZ_DEFAULT 200
+
+/* Offsets of registers groups within VXD. */
+#define PVDEC_PROC_OFFSET 0x0000
+/* 0x34c: Skip DMA registers when running against CSIM (vritual platform) */
+#define PVDEC_PROC_SIZE 0x34C  /* 0x3FF */
+
+#define PVDEC_CORE_OFFSET 0x0400
+#define PVDEC_CORE_SIZE 0x3FF
+
+#define MTX_CORE_OFFSET PVDEC_PROC_OFFSET
+#define MTX_CORE_SIZE PVDEC_PROC_SIZE
+
+#define VIDEO_BUS4_MMU_OFFSET 0x1000
+#define VIDEO_BUS4_MMU_SIZE 0x1FF
+
+#define IMG_VIDEO_BUS4_MMU_OFFSET VIDEO_BUS4_MMU_OFFSET
+#define IMG_VIDEO_BUS4_MMU_SIZE VIDEO_BUS4_MMU_SIZE
+
+#define VLR_OFFSET 0x2000
+#define VLR_SIZE 0x1000
+
+/* PVDEC_ENTROPY defined in uapi/vxd_pvdec.h */
+
+#define PVDEC_PIXEL_OFFSET 0x4000
+#define PVDEC_PIXEL_SIZE 0x1FF
+
+/* PVDEC_VEC_BE defined in uapi/vxd_pvdec.h */
+
+/* MSVDX_VEC defined in uapi/vxd_pvdec.h */
+
+#define MSVDX_VDMC_OFFSET 0x6800
+#define MSVDX_VDMC_SIZE 0x7F
+
+#define DMAC_OFFSET 0x6A00
+#define DMAC_SIZE 0x1FF
+
+#define PVDEC_TEST_OFFSET 0xFF00
+#define PVDEC_TEST_SIZE 0xFF
+
+/* *********************** firmware specific values ************************* */
+
+/* layout of COMMS RAM */
+
+#define PVDEC_FW_COMMS_HDR_SIZE 0x38
+
+#define PVDEC_FW_STATUS_OFFSET 0x00
+#define PVDEC_FW_TASK_STATUS_OFFSET 0x04
+#define PVDEC_FW_ID_OFFSET 0x08
+#define PVDEC_FW_MTXPC_OFFSET 0x0c
+#define PVDEC_FW_MSG_COUNTER_OFFSET 0x10
+#define PVDEC_FW_SIGNATURE_OFFSET 0x14
+#define PVDEC_FW_TO_HOST_BUF_CONF_OFFSET 0x18
+#define PVDEC_FW_TO_HOST_RD_IDX_OFFSET 0x1c
+#define PVDEC_FW_TO_HOST_WR_IDX_OFFSET 0x20
+#define PVDEC_FW_TO_MTX_BUF_CONF_OFFSET 0x24
+#define PVDEC_FW_TO_MTX_RD_IDX_OFFSET 0x28
+#define PVDEC_FW_FLAGS_OFFSET 0x2c
+#define PVDEC_FW_TO_MTX_WR_IDX_OFFSET 0x30
+#define PVDEC_FW_STATE_BUF_CFG_OFFSET 0x34
+
+/* firmware status */
+
+#define PVDEC_FW_STATUS_PANIC  0x2
+#define PVDEC_FW_STATUS_ASSERT 0x3
+#define PVDEC_FW_STATUS_SO     0x8
+
+/* firmware flags */
+
+#define PVDEC_FWFLAG_BIG_TO_HOST_BUFFER 0x00000002
+#define PVDEC_FWFLAG_FORCE_FS_FLOW 0x00000004
+#define PVDEC_FWFLAG_DISABLE_WATCHDOGS 0x00000008
+#define PVDEC_FWFLAG_DISABLE_AUTONOMOUS_RESET 0x00000040
+#define PVDEC_FWFLAG_DISABLE_IDLE_GPIO 0x00002000
+#define PVDEC_FWFLAG_ENABLE_ERROR_CONCEALMENT 0x00100000
+#define PVDEC_FWFLAG_DISABLE_GENC_FLUSHING 0x00800000
+#define PVDEC_FWFLAG_FAKE_COMPLETION 0x20000000
+#define PVDEC_FWFLAG_DISABLE_COREWDT_TIMERS 0x01000000
+
+/* firmware message header */
+
+#define PVDEC_FW_DEVA_GENMSG_OFFSET 0
+
+#define PVDEC_FW_DEVA_GENMSG_MSG_ID_MASK 0xFFFF0000
+#define PVDEC_FW_DEVA_GENMSG_MSG_ID_SHIFT 16
+
+#define PVDEC_FW_DEVA_GENMSG_MSG_TYPE_MASK 0xFF00
+#define PVDEC_FW_DEVA_GENMSG_MSG_TYPE_SHIFT 8
+
+#define PVDEC_FW_DEVA_GENMSG_NOT_LAST_MSG_MASK 0x80
+#define PVDEC_FW_DEVA_GENMSG_NOT_LAST_MSG_SHIFT 7
+
+#define PVDEC_FW_DEVA_GENMSG_MSG_SIZE_MASK 0x7F
+#define PVDEC_FW_DEVA_GENMSG_MSG_SIZE_SHIFT 0
+
+/* firmware init message */
+
+#define PVDEC_FW_DEVA_INIT_MSG_WRDS 9
+
+#define PVDEC_FW_DEVA_INIT_RENDEC_ADDR0_OFFSET 0xC
+
+#define PVDEC_FW_DEVA_INIT_RENDEC_SIZE0_OFFSET 0x10
+#define PVDEC_FW_DEVA_INIT_RENDEC_SIZE0_MASK 0xFFFF
+#define PVDEC_FW_DEVA_INIT_RENDEC_SIZE0_SHIFT 0
+
+#define PVDEC_FW_DEVA_INIT_HEVC_CFG_OFFSET 0x14
+#define PVDEC_FW_DEVA_INIT_HEVC_CFG_MAX_H_FOR_PIPE_WAIT_MASK 0xFFFF0000
+#define PVDEC_FW_DEVA_INIT_HEVC_CFG_MAX_H_FOR_PIPE_WAIT_SHIFT 16
+#define PVDEC_FW_DEVA_INIT_HEVC_CFG_MIN_H_FOR_DUAL_PIPE_MASK 0xFFFF
+#define PVDEC_FW_DEVA_INIT_HEVC_CFG_MIN_H_FOR_DUAL_PIPE_SHIFT 0
+
+#define PVDEC_FW_DEVA_INIT_SIG_SELECT_OFFSET 0x18
+
+#define PVDEC_FW_DEVA_INIT_DBG_DELAYS_OFFSET 0x1C
+
+#define PVDEC_FW_DEVA_INIT_PFNT_DIV_OFFSET 0x20
+#define PVDEC_FW_DEVA_INIT_PFNT_DIV_MASK 0xFFFF0000
+#define PVDEC_FW_DEVA_INIT_PFNT_DIV_SHIFT 16
+
+#define PVDEC_FW_DEVA_INIT_FWWDT_MS_OFFSET 0x20
+#define PVDEC_FW_DEVA_INIT_FWWDT_MS_MASK 0xFFFF
+#define PVDEC_FW_DEVA_INIT_FWWDT_MS_SHIFT 0
+
+/* firmware message types */
+#define PVDEC_FW_MSG_TYPE_PADDING 0
+#define PVDEC_FW_MSG_TYPE_INIT 0x80
+
+/* miscellaneous */
+
+#define PVDEC_FW_READY_SIG 0xa5a5a5a5
+
+#define PVDEC_FW_COM_BUF_SIZE(cfg) ((cfg) & 0x0000ffff)
+#define PVDEC_FW_COM_BUF_OFF(cfg) (((cfg) & 0xffff0000) >> 16)
+
+/*
+ * Timer divider calculation macro.
+ * NOTE: The Timer divider is only 8bit field
+ * so we set it for 2MHz timer base to cover wider
+ * range of core frequencies on real platforms (freq > 255MHz)
+ */
+#define PVDEC_CALC_TIMER_DIV(val) (((val) - 1) / 2)
+
+#define MTX_CORE_STATUS_ELEMENTS 4
+
+#define PVDEC_CORE_MEMSTALLER_ELEMENTS 7
+
+/* ********************** PVDEC_CORE registers group ************************ */
+
+/* register PVDEC_SOFT_RESET */
+#define PVDEC_CORE_PVDEC_SOFT_RST_OFFSET 0x0000
+
+#define PVDEC_CORE_PVDEC_SOFT_RST_PVDEC_PIXEL_PROC_SOFT_RST_MASK 0xFF000000
+#define PVDEC_CORE_PVDEC_SOFT_RST_PVDEC_PIXEL_PROC_SOFT_RST_SHIFT 24
+
+#define PVDEC_CORE_PVDEC_SOFT_RST_PVDEC_ENTROPY_SOFT_RST_MASK 0x00FF0000
+#define PVDEC_CORE_PVDEC_SOFT_RST_PVDEC_ENTROPY_SOFT_RST_SHIFT 16
+
+#define PVDEC_CORE_PVDEC_SOFT_RST_PVDEC_MMU_SOFT_RST_MASK 0x00000002
+#define PVDEC_CORE_PVDEC_SOFT_RST_PVDEC_MMU_SOFT_RST_SHIFT 1
+
+#define PVDEC_CORE_PVDEC_SOFT_RST_PVDEC_SOFT_RST_MASK 0x00000001
+#define PVDEC_CORE_PVDEC_SOFT_RST_PVDEC_SOFT_RST_SHIFT 0
+
+/* register PVDEC_HOST_INTERRUPT_STATUS */
+#define PVDEC_CORE_PVDEC_INT_STAT_OFFSET 0x0010
+
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_SYS_WDT_MASK 0x10000000
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_SYS_WDT_SHIFT 28
+
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_READ_TIMEOUT_PROC_IRQ_MASK 0x08000000
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_READ_TIMEOUT_PROC_IRQ_SHIFT 27
+
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_COMMAND_TIMEOUT_PROC_IRQ_MASK 0x04000000
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_COMMAND_TIMEOUT_PROC_IRQ_SHIFT 26
+
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_READ_TIMEOUT_HOST_IRQ_MASK 0x02000000
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_READ_TIMEOUT_HOST_IRQ_SHIFT 25
+
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_COMMAND_TIMEOUT_HOST_IRQ_MASK 0x01000000
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_COMMAND_TIMEOUT_HOST_IRQ_SHIFT 24
+
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_PROC_GPIO_IRQ_MASK 0x00200000
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_PROC_GPIO_IRQ_SHIFT 21
+
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_PROC_IRQ_MASK 0x00100000
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_PROC_IRQ_SHIFT 20
+
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_MMU_FAULT_IRQ_MASK 0x00010000
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_MMU_FAULT_IRQ_SHIFT 16
+
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_PIXEL_PROCESSING_IRQ_MASK 0x0000FF00
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_PIXEL_PROCESSING_IRQ_SHIFT 8
+
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_ENTROPY_PIPE_IRQ_MASK 0x000000FF
+#define PVDEC_CORE_PVDEC_INT_STAT_HOST_ENTROPY_PIPE_IRQ_SHIFT 0
+
+/* register PVDEC_INTERRUPT_CLEAR */
+#define PVDEC_CORE_PVDEC_INT_CLEAR_OFFSET 0x0014
+
+#define PVDEC_CORE_PVDEC_INT_CLEAR_IRQ_CLEAR_MASK 0xFFFF0000
+#define PVDEC_CORE_PVDEC_INT_CLEAR_IRQ_CLEAR_SHIFT 16
+
+/* register PVDEC_HOST_INTERRUPT_ENABLE */
+#define PVDEC_CORE_PVDEC_HOST_INT_ENA_OFFSET 0x0018
+
+#define PVDEC_CORE_PVDEC_HOST_INT_ENA_HOST_IRQ_ENABLE_MASK 0xFFFF0000
+#define PVDEC_CORE_PVDEC_HOST_INT_ENA_HOST_IRQ_ENABLE_SHIFT 16
+
+/* Register PVDEC_MAN_CLK_ENABLE */
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_OFFSET 0x0040
+
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_PIXEL_PROC_MAN_CLK_ENA_MASK 0xFF000000
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_PIXEL_PROC_MAN_CLK_ENA_SHIFT 24
+
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_ENTROPY_PIPE_MAN_CLK_ENA_MASK 0x00FF0000
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_ENTROPY_PIPE_MAN_CLK_ENA_SHIFT 16
+
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_MEM_MAN_CLK_ENA_MASK 0x00000100
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_MEM_MAN_CLK_ENA_SHIFT 8
+
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_PVDEC_REG_MAN_CLK_ENA_MASK 0x00000010
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_PVDEC_REG_MAN_CLK_ENA_SHIFT 4
+
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_PROC_MAN_CLK_ENA_MASK 0x00000002
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_PROC_MAN_CLK_ENA_SHIFT 1
+
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_CORE_MAN_CLK_ENA_MASK 0x00000001
+#define PVDEC_CORE_PVDEC_MAN_CLK_ENA_CORE_MAN_CLK_ENA_SHIFT 0
+
+/* register PVDEC_HOST_PIPE_SELECT */
+#define PVDEC_CORE_PVDEC_HOST_PIPE_SELECT_OFFSET 0x0060
+
+#define PVDEC_CORE_PVDEC_HOST_PIPE_SELECT_PIPE_SEL_MASK 0x0000000F
+#define PVDEC_CORE_PVDEC_HOST_PIPE_SELECT_PIPE_SEL_SHIFT 0
+
+/* register PROC_DEBUG */
+#define PVDEC_CORE_PROC_DEBUG_OFFSET 0x0100
+
+#define PVDEC_CORE_PROC_DEBUG_MTX_LAST_RAM_BANK_SIZE_MASK 0xFF000000
+#define PVDEC_CORE_PROC_DEBUG_MTX_LAST_RAM_BANK_SIZE_SHIFT 24
+
+#define PVDEC_CORE_PROC_DEBUG_MTX_RAM_BANK_SIZE_MASK 0x000F0000
+#define PVDEC_CORE_PROC_DEBUG_MTX_RAM_BANK_SIZE_SHIFT 16
+
+#define PVDEC_CORE_PROC_DEBUG_MTX_RAM_BANKS_MASK 0x00000F00
+#define PVDEC_CORE_PROC_DEBUG_MTX_RAM_BANKS_SHIFT 8
+
+#define PVDEC_CORE_PROC_DEBUG_MTX_RAM_NEW_REPRESENTATION_MASK 0x00000080
+#define PVDEC_CORE_PROC_DEBUG_MTX_RAM_NEW_REPRESENTATION_SHIFT 7
+
+#define PVDEC_CORE_PROC_DEBUG_PROC_DBG_GPIO_OUT_MASK 0x00000018
+#define PVDEC_CORE_PROC_DEBUG_PROC_DBG_GPIO_OUT_SHIFT 3
+
+#define PVDEC_CORE_PROC_DEBUG_PROC_DBG_IS_SLAVE_MASK 0x00000004
+#define PVDEC_CORE_PROC_DEBUG_PROC_DBG_IS_SLAVE_SHIFT 2
+
+#define PVDEC_CORE_PROC_DEBUG_PROC_DBG_GPIO_IN_MASK 0x00000003
+#define PVDEC_CORE_PROC_DEBUG_PROC_DBG_GPIO_IN_SHIFT 0
+
+/* register PROC_DMAC_CONTROL */
+#define PVDEC_CORE_PROC_DMAC_CONTROL_OFFSET 0x0104
+
+#define PVDEC_CORE_PROC_DMAC_CONTROL_BOOT_ON_DMA_CH0_MASK 0x80000000
+#define PVDEC_CORE_PROC_DMAC_CONTROL_BOOT_ON_DMA_CH0_SHIFT 31
+
+/* register PROC_DEBUG_FIFO */
+#define PVDEC_CORE_PROC_DBG_FIFO_OFFSET 0x0108
+
+#define PVDEC_CORE_PROC_DBG_FIFO_PROC_DBG_FIFO_MASK 0xFFFFFFFF
+#define PVDEC_CORE_PROC_DBG_FIFO_PROC_DBG_FIFO_SHIFT 0
+
+/* register PROC_DEBUG_FIFO_CTRL_0 */
+#define PVDEC_CORE_PROC_DBG_FIFO_CTRL0_OFFSET 0x010C
+
+#define PVDEC_CORE_PROC_DBG_FIFO_CTRL0_PROC_DBG_FIFO_COUNT_MASK 0xFFFF0000
+#define PVDEC_CORE_PROC_DBG_FIFO_CTRL0_PROC_DBG_FIFO_COUNT_SHIFT 16
+
+#define PVDEC_CORE_PROC_DBG_FIFO_CTRL0_PROC_DBG_FIFO_SIZE_MASK 0x0000FFFF
+#define PVDEC_CORE_PROC_DBG_FIFO_CTRL0_PROC_DBG_FIFO_SIZE_SHIFT 0
+
+/* register PVDEC_CORE_ID */
+#define PVDEC_CORE_PVDEC_CORE_ID_OFFSET 0x0230
+
+#define PVDEC_CORE_PVDEC_CORE_ID_GROUP_ID_MASK 0xFF000000
+#define PVDEC_CORE_PVDEC_CORE_ID_GROUP_ID_SHIFT 24
+
+#define PVDEC_CORE_PVDEC_CORE_ID_CORE_ID_MASK 0x00FF0000
+#define PVDEC_CORE_PVDEC_CORE_ID_CORE_ID_SHIFT 16
+
+#define PVDEC_CORE_PVDEC_CORE_ID_PVDEC_CORE_CONFIG_MASK 0x0000FFFF
+#define PVDEC_CORE_PVDEC_CORE_ID_PVDEC_CORE_CONFIG_SHIFT 0
+
+#define PVDEC_CORE_PVDEC_CORE_ID_ENT_PIPES_MASK 0x0000000F
+#define PVDEC_CORE_PVDEC_CORE_ID_ENT_PIPES_SHIFT 0
+
+#define PVDEC_CORE_PVDEC_CORE_ID_PIX_PIPES_MASK 0x000000F0
+#define PVDEC_CORE_PVDEC_CORE_ID_PIX_PIPES_SHIFT 4
+
+/* register PVDEC_CORE_REV */
+#define PVDEC_CORE_PVDEC_CORE_REV_OFFSET 0x0240
+
+#define PVDEC_CORE_PVDEC_CORE_REV_PVDEC_DESIGNER_MASK 0xFF000000
+#define PVDEC_CORE_PVDEC_CORE_REV_PVDEC_DESIGNER_SHIFT 24
+
+#define PVDEC_CORE_PVDEC_CORE_REV_PVDEC_MAJOR_REV_MASK 0x00FF0000
+#define PVDEC_CORE_PVDEC_CORE_REV_PVDEC_MAJOR_REV_SHIFT 16
+
+#define PVDEC_CORE_PVDEC_CORE_REV_PVDEC_MINOR_REV_MASK 0x0000FF00
+#define PVDEC_CORE_PVDEC_CORE_REV_PVDEC_MINOR_REV_SHIFT 8
+
+#define PVDEC_CORE_PVDEC_CORE_REV_PVDEC_MAINT_REV_MASK 0x000000FF
+#define PVDEC_CORE_PVDEC_CORE_REV_PVDEC_MAINT_REV_SHIFT 0
+
+/* *********************** MTX_CORE registers group ************************* */
+
+/* register MTX_ENABLE  */
+#define MTX_CORE_MTX_ENABLE_OFFSET 0x0000
+
+/* register MTX_SYSC_TXTIMER. Note: it's not defined in PVDEC TRM. */
+#define MTX_CORE_MTX_SYSC_TXTIMER_OFFSET 0x0010
+
+/* register MTX_KICKI */
+#define MTX_CORE_MTX_KICKI_OFFSET 0x0088
+
+#define MTX_CORE_MTX_KICKI_MTX_KICKI_MASK 0x0000FFFF
+#define MTX_CORE_MTX_KICKI_MTX_KICKI_SHIFT 0
+
+/* register MTX_FAULT0 */
+#define MTX_CORE_MTX_FAULT0_OFFSET 0x0090
+
+/* register MTX_REGISTER_READ_WRITE_DATA */
+#define MTX_CORE_MTX_REG_READ_WRITE_DATA_OFFSET 0x00F8
+
+/* register MTX_REGISTER_READ_WRITE_REQUEST */
+#define MTX_CORE_MTX_REG_READ_WRITE_REQUEST_OFFSET 0x00FC
+
+#define MTX_CORE_MTX_REG_READ_WRITE_REQUEST_MTX_DREADY_MASK 0x80000000
+#define MTX_CORE_MTX_REG_READ_WRITE_REQUEST_MTX_DREADY_SHIFT 31
+
+#define MTX_CORE_MTX_REG_READ_WRITE_REQUEST_MTX_RNW_MASK 0x00010000
+#define MTX_CORE_MTX_REG_READ_WRITE_REQUEST_MTX_RNW_SHIFT 16
+
+#define MTX_CORE_MTX_REG_READ_WRITE_REQUEST_MTX_RSPECIFIER_MASK 0x00000070
+#define MTX_CORE_MTX_REG_READ_WRITE_REQUEST_MTX_RSPECIFIER_SHIFT 4
+
+#define MTX_CORE_MTX_REG_READ_WRITE_REQUEST_MTX_USPECIFIER_MASK 0x0000000F
+#define MTX_CORE_MTX_REG_READ_WRITE_REQUEST_MTX_USPECIFIER_SHIFT 0
+
+/* register MTX_RAM_ACCESS_DATA_EXCHANGE */
+#define MTX_CORE_MTX_RAM_ACCESS_DATA_EXCHANGE_OFFSET 0x0100
+
+/* register MTX_RAM_ACCESS_DATA_TRANSFER */
+#define MTX_CORE_MTX_RAM_ACCESS_DATA_TRANSFER_OFFSET 0x0104
+
+/* register MTX_RAM_ACCESS_CONTROL */
+#define MTX_CORE_MTX_RAM_ACCESS_CONTROL_OFFSET 0x0108
+
+#define MTX_CORE_MTX_RAM_ACCESS_CONTROL_MTX_MCMID_MASK 0x0FF00000
+#define MTX_CORE_MTX_RAM_ACCESS_CONTROL_MTX_MCMID_SHIFT 20
+
+#define MTX_CORE_MTX_RAM_ACCESS_CONTROL_MTX_MCM_ADDR_MASK 0x000FFFFC
+#define MTX_CORE_MTX_RAM_ACCESS_CONTROL_MTX_MCM_ADDR_SHIFT 2
+
+#define MTX_CORE_MTX_RAM_ACCESS_CONTROL_MTX_MCMAI_MASK 0x00000002
+#define MTX_CORE_MTX_RAM_ACCESS_CONTROL_MTX_MCMAI_SHIFT 1
+
+#define MTX_CORE_MTX_RAM_ACCESS_CONTROL_MTX_MCMR_MASK 0x00000001
+#define MTX_CORE_MTX_RAM_ACCESS_CONTROL_MTX_MCMR_SHIFT 0
+
+/* register MTX_RAM_ACCESS_STATUS */
+#define MTX_CORE_MTX_RAM_ACCESS_STATUS_OFFSET 0x010C
+
+#define MTX_CORE_MTX_RAM_ACCESS_STATUS_MTX_MTX_MCM_STAT_MASK 0x00000001
+#define MTX_CORE_MTX_RAM_ACCESS_STATUS_MTX_MTX_MCM_STAT_SHIFT 0
+
+/* register MTX_SOFT_RESET */
+#define MTX_CORE_MTX_SOFT_RESET_OFFSET 0x0200
+
+#define MTX_CORE_MTX_SOFT_RESET_MTX_RESET_MASK 0x00000001
+#define MTX_CORE_MTX_SOFT_RESET_MTX_RESET_SHIFT 0
+
+/* register MTX_SYSC_TIMERDIV */
+#define MTX_CORE_MTX_SYSC_TIMERDIV_OFFSET 0x0208
+
+#define MTX_CORE_MTX_SYSC_TIMERDIV_TIMER_EN_MASK 0x00010000
+#define MTX_CORE_MTX_SYSC_TIMERDIV_TIMER_EN_SHIFT 16
+
+#define MTX_CORE_MTX_SYSC_TIMERDIV_TIMER_DIV_MASK 0x000000FF
+#define MTX_CORE_MTX_SYSC_TIMERDIV_TIMER_DIV_SHIFT 0
+
+/* register MTX_SYSC_CDMAA */
+#define MTX_CORE_MTX_SYSC_CDMAA_OFFSET 0x0344
+
+#define MTX_CORE_MTX_SYSC_CDMAA_CDMAA_ADDRESS_MASK 0x03FFFFFC
+#define MTX_CORE_MTX_SYSC_CDMAA_CDMAA_ADDRESS_SHIFT 2
+
+/* register MTX_SYSC_CDMAC */
+#define MTX_CORE_MTX_SYSC_CDMAC_OFFSET 0x0340
+
+#define MTX_CORE_MTX_SYSC_CDMAC_BURSTSIZE_MASK 0x07000000
+#define MTX_CORE_MTX_SYSC_CDMAC_BURSTSIZE_SHIFT 24
+
+#define MTX_CORE_MTX_SYSC_CDMAC_RNW_MASK 0x00020000
+#define MTX_CORE_MTX_SYSC_CDMAC_RNW_SHIFT 17
+
+#define MTX_CORE_MTX_SYSC_CDMAC_ENABLE_MASK 0x00010000
+#define MTX_CORE_MTX_SYSC_CDMAC_ENABLE_SHIFT 16
+
+#define MTX_CORE_MTX_SYSC_CDMAC_LENGTH_MASK 0x0000FFFF
+#define MTX_CORE_MTX_SYSC_CDMAC_LENGTH_SHIFT 0
+
+/* register MTX_SYSC_CDMAT */
+#define MTX_CORE_MTX_SYSC_CDMAT_OFFSET 0x0350
+
+/* ****************** IMG_VIDEO_BUS4_MMU registers group ******************** */
+
+/* register MMU_CONTROL0_ */
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL0_USE_TILE_STRIDE_PER_CTX_MASK 0x00010000
+#define IMG_VIDEO_BUS4_MMU_MMU_CONTROL0_USE_TILE_STRIDE_PER_CTX_SHIFT 16
+
+#define IMG_VIDEO_BUS4_MMU_MMU_ADDRESS_CONTROL_MMU_ENA_EXT_ADDR_MASK 0x00000010
+#define IMG_VIDEO_BUS4_MMU_MMU_ADDRESS_CONTROL_MMU_ENA_EXT_ADDR_SHIFT 4
+
+#define IMG_VIDEO_BUS4_MMU_MMU_ADDRESS_CONTROL_UPPER_ADDR_FIXED_MASK 0x00FF0000
+#define IMG_VIDEO_BUS4_MMU_MMU_ADDRESS_CONTROL_UPPER_ADDR_FIXED_SHIFT 16
+
+#define IMG_VIDEO_BUS4_MMU_MMU_MEM_EXT_OUTSTANDING_READ_WORDS_MASK 0x0000FFFF
+#define IMG_VIDEO_BUS4_MMU_MMU_MEM_EXT_OUTSTANDING_READ_WORDS_SHIFT 0
+
+/* *************************** MMU-related values ************************** */
+
+/* MMU page size */
+
+enum {
+	VXD_MMU_SOFT_PAGE_SIZE_PAGE_64K    = 0x4,
+	VXD_MMU_SOFT_PAGE_SIZE_PAGE_16K    = 0x2,
+	VXD_MMU_SOFT_PAGE_SIZE_PAGE_4K     = 0x0,
+	VXD_MMU_SOFT_PAGE_SIZE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* MMU PTD entry flags */
+enum {
+	VXD_MMU_PTD_FLAG_NONE            = 0x0,
+	VXD_MMU_PTD_FLAG_VALID           = 0x1,
+	VXD_MMU_PTD_FLAG_WRITE_ONLY      = 0x2,
+	VXD_MMU_PTD_FLAG_READ_ONLY       = 0x4,
+	VXD_MMU_PTD_FLAG_CACHE_COHERENCY = 0x8,
+	VXD_MMU_PTD_FLAG_FORCE32BITS     = 0x7FFFFFFFU
+};
+
+/* ********************* PVDEC_PIXEL registers group *********************** */
+
+/* register PVDEC_PIXEL_PIXEL_CONTROL_0 */
+#define PVDEC_PIXEL_PIXEL_CONTROL_0_OFFSET 0x0004
+
+#define PVDEC_PIXEL_PIXEL_CONTROL_0_DMAC_CH_SEL_FOR_MTX_MASK 0x0000000E
+#define PVDEC_PIXEL_PIXEL_CONTROL_0_DMAC_CH_SEL_FOR_MTX_SHIFT 1
+
+#define PVDEC_PIXEL_PIXEL_CONTROL_0_PROC_DMAC_CH0_SEL_MASK 0x00000001
+#define PVDEC_PIXEL_PIXEL_CONTROL_0_PROC_DMAC_CH0_SEL_SHIFT 0
+
+/* register PVDEC_PIXEL_MAN_CLK_ENABLE */
+#define PVDEC_PIXEL_PIXEL_MAN_CLK_ENA_OFFSET 0x0020
+
+#define PVDEC_PIXEL_PIXEL_MAN_CLK_ENA_PIXEL_REG_MAN_CLK_ENA_MASK 0x00020000
+#define PVDEC_PIXEL_PIXEL_MAN_CLK_ENA_PIXEL_REG_MAN_CLK_ENA_SHIFT 17
+
+#define PVDEC_PIXEL_PIXEL_MAN_CLK_ENA_PIXEL_DMAC_MAN_CLK_ENA_MASK 0x00010000
+#define PVDEC_PIXEL_PIXEL_MAN_CLK_ENA_PIXEL_DMAC_MAN_CLK_ENA_SHIFT 16
+
+/* register PIXEL_PIPE_CONFIG */
+#define PVDEC_PIXEL_PIXEL_PIPE_CONFIG_OFFSET 0x00C0
+
+/* register PIXEL_MISC_CONFIG */
+#define PVDEC_PIXEL_PIXEL_MISC_CONFIG_OFFSET 0x00C4
+
+/* register MAX_FRAME_CONFIG */
+#define PVDEC_PIXEL_MAX_FRAME_CONFIG_OFFSET 0x00C8
+
+/* ********************* PVDEC_ENTROPY registers group ********************* */
+
+/* Register PVDEC_ENTROPY_MAN_CLK_ENABLE */
+#define PVDEC_ENTROPY_ENTROPY_MAN_CLK_ENA_OFFSET 0x0020
+
+/* Register PVDEC_ENTROPY_LAST_LAST_MB */
+#define PVDEC_ENTROPY_ENTROPY_LAST_MB_OFFSET 0x00BC
+
+/* ********************* PVDEC_VEC_BE registers group ********************** */
+
+/* Register PVDEC_VEC_BE_VEC_BE_STATUS */
+#define PVDEC_VEC_BE_VEC_BE_STATUS_OFFSET 0x0018
+
+/* ********************* MSVDX_VEC registers group ************************* */
+
+/* Register MSVDX_VEC_VEC_ENTDEC_INFORMATION */
+#define MSVDX_VEC_VEC_ENTDEC_INFORMATION_OFFSET 0x00AC
+
+/* ********************* MSVDX_VDMC registers group ************************ */
+
+/* Register MSVDX_VDMC_VDMC_MACROBLOCK_NUMBER */
+#define MSVDX_VDMC_VDMC_MACROBLOCK_NUMBER_OFFSET 0x0048
+
+/* ************************** DMAC registers group ************************* */
+
+/* register DMAC_SETUP */
+#define DMAC_DMAC_SETUP_OFFSET 0x0000
+#define DMAC_DMAC_SETUP_STRIDE 32
+#define DMAC_DMAC_SETUP_NO_ENTRIES 6
+
+/* register DMAC_COUNT */
+#define DMAC_DMAC_COUNT_OFFSET 0x0004
+#define DMAC_DMAC_COUNT_STRIDE 32
+#define DMAC_DMAC_COUNT_NO_ENTRIES 6
+
+#define DMAC_DMAC_COUNT_LIST_IEN_MASK 0x80000000
+#define DMAC_DMAC_COUNT_LIST_IEN_SHIFT 31
+
+#define DMAC_DMAC_COUNT_BSWAP_MASK 0x40000000
+#define DMAC_DMAC_COUNT_BSWAP_SHIFT 30
+
+#define DMAC_DMAC_COUNT_TRANSFER_IEN_MASK 0x20000000
+#define DMAC_DMAC_COUNT_TRANSFER_IEN_SHIFT 29
+
+#define DMAC_DMAC_COUNT_PW_MASK 0x18000000
+#define DMAC_DMAC_COUNT_PW_SHIFT 27
+
+#define DMAC_DMAC_COUNT_DIR_MASK 0x04000000
+#define DMAC_DMAC_COUNT_DIR_SHIFT 26
+
+#define DMAC_DMAC_COUNT_PI_MASK 0x03000000
+#define DMAC_DMAC_COUNT_PI_SHIFT 24
+
+#define DMAC_DMAC_COUNT_LIST_FIN_CTL_MASK 0x00400000
+#define DMAC_DMAC_COUNT_LIST_FIN_CTL_SHIFT 22
+
+#define DMAC_DMAC_COUNT_DREQ_MASK 0x00100000
+#define DMAC_DMAC_COUNT_DREQ_SHIFT 20
+
+#define DMAC_DMAC_COUNT_SRST_MASK 0x00080000
+#define DMAC_DMAC_COUNT_SRST_SHIFT 19
+
+#define DMAC_DMAC_COUNT_LIST_EN_MASK 0x00040000
+#define DMAC_DMAC_COUNT_LIST_EN_SHIFT 18
+
+#define DMAC_DMAC_COUNT_ENABLE_2D_MODE_MASK 0x00020000
+#define DMAC_DMAC_COUNT_ENABLE_2D_MODE_SHIFT 17
+
+#define DMAC_DMAC_COUNT_EN_MASK 0x00010000
+#define DMAC_DMAC_COUNT_EN_SHIFT 16
+
+#define DMAC_DMAC_COUNT_CNT_MASK 0x0000FFFF
+#define DMAC_DMAC_COUNT_CNT_SHIFT 0
+
+/* register DMAC_PERIPH */
+#define DMAC_DMAC_PERIPH_OFFSET 0x0008
+#define DMAC_DMAC_PERIPH_STRIDE 32
+#define DMAC_DMAC_PERIPH_NO_ENTRIES 6
+
+#define DMAC_DMAC_PERIPH_ACC_DEL_MASK 0xE0000000
+#define DMAC_DMAC_PERIPH_ACC_DEL_SHIFT 29
+
+#define DMAC_DMAC_PERIPH_INCR_MASK 0x08000000
+#define DMAC_DMAC_PERIPH_INCR_SHIFT 27
+
+#define DMAC_DMAC_PERIPH_BURST_MASK 0x07000000
+#define DMAC_DMAC_PERIPH_BURST_SHIFT 24
+
+#define DMAC_DMAC_PERIPH_EXT_BURST_MASK 0x000F0000
+#define DMAC_DMAC_PERIPH_EXT_BURST_SHIFT 16
+
+#define DMAC_DMAC_PERIPH_EXT_SA_MASK 0x0000000F
+#define DMAC_DMAC_PERIPH_EXT_SA_SHIFT 0
+
+/* register DMAC_IRQ_STAT */
+#define DMAC_DMAC_IRQ_STAT_OFFSET 0x000C
+#define DMAC_DMAC_IRQ_STAT_STRIDE 32
+#define DMAC_DMAC_IRQ_STAT_NO_ENTRIES 6
+
+/* register DMAC_PERIPHERAL_ADDR */
+#define DMAC_DMAC_PERIPH_ADDR_OFFSET 0x0014
+#define DMAC_DMAC_PERIPH_ADDR_STRIDE 32
+#define DMAC_DMAC_PERIPH_ADDR_NO_ENTRIES 6
+
+#define DMAC_DMAC_PERIPH_ADDR_ADDR_MASK 0x007FFFFF
+#define DMAC_DMAC_PERIPH_ADDR_ADDR_SHIFT 0
+
+/* register DMAC_PER_HOLD */
+#define DMAC_DMAC_PER_HOLD_OFFSET 0x0018
+#define DMAC_DMAC_PER_HOLD_STRIDE 32
+#define DMAC_DMAC_PER_HOLD_NO_ENTRIES 6
+
+#define DMAC_DMAC_PER_HOLD_PER_HOLD_MASK 0x0000001F
+#define DMAC_DMAC_PER_HOLD_PER_HOLD_SHIFT 0
+
+#define DMAC_DMAC_SOFT_RESET_OFFSET 0x00C0
+
+/* ************************** DMAC-related values *************************** */
+
+/*
+ * This type defines whether the peripheral address is static or
+ * auto-incremented. (see the TRM "Transfer Sequence Linked-list - INCR")
+ */
+enum {
+	DMAC_INCR_OFF         = 0, /* No action, no increment. */
+	DMAC_INCR_ON          = 1, /* Generate address increment. */
+	DMAC_INCR_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Burst size settings (see the TRM "Transfer Sequence Linked-list - BURST"). */
+enum {
+	DMAC_BURST_0           = 0x0, /* burst size of 0 */
+	DMAC_BURST_1           = 0x1, /* burst size of 1 */
+	DMAC_BURST_2           = 0x2, /* burst size of 2 */
+	DMAC_BURST_3           = 0x3, /* burst size of 3 */
+	DMAC_BURST_4           = 0x4, /* burst size of 4 */
+	DMAC_BURST_5           = 0x5, /* burst size of 5 */
+	DMAC_BURST_6           = 0x6, /* burst size of 6 */
+	DMAC_BURST_7           = 0x7, /* burst size of 7 */
+	DMAC_BURST_8           = 0x8, /* burst size of 8 */
+	DMAC_BURST_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Extended burst size settings (see TRM "Transfer Sequence Linked-list -
+ * EXT_BURST").
+ */
+enum {
+	DMAC_EXT_BURST_0           = 0x0, /* no extension */
+	DMAC_EXT_BURST_1           = 0x1, /* extension of 8 */
+	DMAC_EXT_BURST_2           = 0x2, /* extension of 16 */
+	DMAC_EXT_BURST_3           = 0x3, /* extension of 24 */
+	DMAC_EXT_BURST_4           = 0x4, /* extension of 32 */
+	DMAC_EXT_BURST_5           = 0x5, /* extension of 40 */
+	DMAC_EXT_BURST_6           = 0x6, /* extension of 48 */
+	DMAC_EXT_BURST_7           = 0x7, /* extension of 56 */
+	DMAC_EXT_BURST_8           = 0x8, /* extension of 64 */
+	DMAC_EXT_BURST_9           = 0x9, /* extension of 72 */
+	DMAC_EXT_BURST_10          = 0xa, /* extension of 80 */
+	DMAC_EXT_BURST_11          = 0xb, /* extension of 88 */
+	DMAC_EXT_BURST_12          = 0xc, /* extension of 96 */
+	DMAC_EXT_BURST_13          = 0xd, /* extension of 104 */
+	DMAC_EXT_BURST_14          = 0xe, /* extension of 112 */
+	DMAC_EXT_BURST_15          = 0xf, /* extension of 120 */
+	DMAC_EXT_BURST_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Transfer direction. */
+enum {
+	DMAC_MEM_TO_VXD         = 0x0,
+	DMAC_VXD_TO_MEM         = 0x1,
+	DMAC_VXD_TO_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* How much to increment the peripheral address. */
+enum {
+	DMAC_PI_1           = 0x2, /* increment by 1 */
+	DMAC_PI_2           = 0x1, /* increment by 2 */
+	DMAC_PI_4           = 0x0, /* increment by 4 */
+	DMAC_PI_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* Peripheral width settings (see TRM "Transfer Sequence Linked-list - PW"). */
+enum {
+	DMAC_PWIDTH_32_BIT      = 0x0, /* Peripheral width 32-bit. */
+	DMAC_PWIDTH_16_BIT      = 0x1, /* Peripheral width 16-bit. */
+	DMAC_PWIDTH_8_BIT       = 0x2, /* Peripheral width 8-bit. */
+	DMAC_PWIDTH_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/* ******************************* macros ********************************** */
+
+#ifdef PVDEC_SINGLETHREADED_IO
+/* Write to the register */
+#define VXD_WR_REG_ABS(base, addr, val) \
+	({ spin_lock_irqsave(&pvdec_irq_lock, pvdec_irq_flags); \
+	   iowrite32((val), (addr) + (base)); \
+	   spin_unlock_irqrestore(&pvdec_irq_lock, (unsigned long)pvdec_irq_flags); })
+
+/* Read the register */
+#define VXD_RD_REG_ABS(base, addr) \
+	({ unsigned int reg; \
+	   spin_lock_irqsave(&pvdec_irq_lock, pvdec_irq_flags); \
+	   reg = ioread32((addr) + (base)); \
+	   spin_unlock_irqrestore(&pvdec_irq_lock, (unsigned long)pvdec_irq_flags); \
+	   reg; })
+#else /* ndef PVDEC_SINGLETHREADED_IO */
+
+/* Write to the register */
+#define VXD_WR_REG_ABS(base, addr, val) \
+	(iowrite32((val), (addr) + (base)))
+
+/* Read the register */
+#define VXD_RD_REG_ABS(base, addr) \
+	(ioread32((addr) + (base)))
+
+#endif
+
+/* Get offset of a register */
+#define VXD_GET_REG_OFF(group, reg) \
+	(group ## _OFFSET + group ## _ ## reg ## _OFFSET)
+
+/* Get offset of a repated register */
+#define VXD_GET_RPT_REG_OFF(group, reg, index) \
+	(VXD_GET_REG_OFF(group, reg) + ((index) * group ## _ ## reg ## _STRIDE))
+
+/* Extract field from a register */
+#define VXD_RD_REG_FIELD(val, group, reg, field) \
+	(((val) & group ## _ ## reg ## _ ## field ## _MASK) >> \
+	 group ## _ ## reg ## _ ## field ## _SHIFT)
+
+/* Shift provided value by number of bits relevant to register specification */
+#define VXD_ENC_REG_FIELD(group, reg, field, val) \
+	((unsigned int)(val) << (group ## _ ## reg ## _ ## field ## _SHIFT))
+
+/* Update the field in a register */
+#define VXD_WR_REG_FIELD(reg_val, group, reg, field, val) \
+	(((reg_val) & ~(group ## _ ## reg ## _ ## field ## _MASK)) | \
+	 (VXD_ENC_REG_FIELD(group, reg, field, val) & \
+	  (group ## _ ## reg ## _ ## field ## _MASK)))
+
+/* Write to a register */
+#define VXD_WR_REG(base, group, reg, val) \
+	VXD_WR_REG_ABS(base, VXD_GET_REG_OFF(group, reg), val)
+
+/* Write to a repeated register */
+#define VXD_WR_RPT_REG(base, group, reg, val, index) \
+	VXD_WR_REG_ABS(base, VXD_GET_RPT_REG_OFF(group, reg, index), val)
+
+/* Read a register */
+#define VXD_RD_REG(base, group, reg) \
+	VXD_RD_REG_ABS(base, VXD_GET_REG_OFF(group, reg))
+
+/* Read a repeated register */
+#define VXD_RD_RPT_REG(base, group, reg, index) \
+	VXD_RD_REG_ABS(base, VXD_GET_RPT_REG_OFF(group, reg, index))
+
+/* Insert word into the message buffer */
+#define VXD_WR_MSG_WRD(buf, msg_type, wrd, val) \
+	(((unsigned int *)buf)[(msg_type ## _ ## wrd ## _OFFSET) / sizeof(unsigned int)] = \
+		 val)
+
+/* Get a word from the message buffer */
+#define VXD_RD_MSG_WRD(buf, msg_type, wrd) \
+	(((unsigned int *)buf)[(msg_type ## _ ## wrd ## _OFFSET) / sizeof(unsigned int)])
+
+/* Get offset for pipe register */
+#define VXD_GET_PIPE_OFF(num_pipes, pipe) \
+	((num_pipes) > 1 ? ((pipe) << 16) : 0)
+
+#endif /* VXD_PVDEC_REGS_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/decoder/vxd_v4l2.c b/drivers/media/platform/img/vxe-vxd/decoder/vxd_v4l2.c
--- a/drivers/media/platform/img/vxe-vxd/decoder/vxd_v4l2.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/decoder/vxd_v4l2.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,2424 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMG DEC V4L2 Interface function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Angela Stegmaier <angelabaker@ti.com>
+ *	David Huang <d-huang@ti.com>
+ *
+ * Re-written for upstreaming
+ *	Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com>
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/videodev2.h>
+#include <linux/idr.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+
+#ifdef ERROR_RECOVERY_SIMULATION
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/types.h>
+#endif
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-sg.h>
+#ifdef CAPTURE_CONTIG_ALLOC
+#include <media/videobuf2-dma-contig.h>
+#endif
+
+#include "core.h"
+#include "h264fw_data.h"
+#include "hevcfw_data.h"
+#include "img_dec_common.h"
+#include "vxd_pvdec_priv.h"
+#include "vxd_dec.h"
+#include "img_errors.h"
+#include "vdecdd_utils.h"
+
+#define VXD_DEC_SPIN_LOCK_NAME  "vxd-dec"
+#define IMG_VXD_DEC_MODULE_NAME "vxd-dec"
+
+#define V4L2_CID_VXD_SET_DEC_BUFS (V4L2_CID_USER_BASE + 0x1001)
+#define V4L2_CID_VXD_SET_DISP_BUFS (V4L2_CID_USER_BASE + 0x1002)
+#define V4L2_CID_VXD_SET_IMG_BUFS (V4L2_CID_USER_BASE + 0x1003)
+#define V4L2_CID_VXD_SET_SPEC_BUFS (V4L2_CID_USER_BASE + 0x1004)
+
+#ifdef ERROR_RECOVERY_SIMULATION
+/* This code should be execute only in debug flag */
+/*
+ * vxd decoder kernel object to create sysfs to debug error recovery and firmware
+ * watchdog timer. This kernel object will create a directory under /sys/kernel,
+ * containing two files fw_error_value and disable_fw_irq.
+ */
+struct kobject *vxd_dec_kobject;
+
+/* fw_error_value is the variable used to handle fw_error_attr */
+int fw_error_value = VDEC_ERROR_MAX;
+
+/* irq for the module, stored globally so can be accessed from sysfs */
+int g_module_irq;
+
+/*
+ * fw_error_attr. Application can set the value of this attribute, based on the
+ * firmware error that needs to be reproduced.
+ */
+struct kobj_attribute fw_error_attr =
+	__ATTR(fw_error_value, 0660, vxd_sysfs_show, vxd_sysfs_store);
+
+/* disable_fw_irq_value is variable to handle disable_fw_irq_attr */
+int disable_fw_irq_value;
+
+/*
+ * disable_fw_irq_attr. Application can set the value of this attribute. 1 to
+ * disable irq. 0 to enable irq.
+ */
+struct kobj_attribute disable_fw_irq_attr =
+	__ATTR(disable_fw_irq_value, 0660, vxd_sysfs_show, vxd_sysfs_store);
+
+/*
+ * Group attribute so that we can create and destroy all of them at once.
+ */
+struct attribute *attrs[] = {
+	&fw_error_attr.attr,
+	&disable_fw_irq_attr.attr,
+	NULL,         /* Terminate list of attributes with NULL */
+};
+
+/*
+ * An unnamed attribute group will put all of the attributes directly in
+ * the kobject directory.  If we specify a name, a sub directory will be
+ * created for the attributes with the directory being the name of the
+ * attribute group
+ */
+struct attribute_group attr_group = {
+	.attrs = attrs,
+};
+
+#endif
+
+static struct heap_config vxd_dec_heap_configs[] = {
+	{
+		.type = MEM_HEAP_TYPE_UNIFIED,
+		.options.unified = {
+			.gfp_type = __GFP_DMA32 | __GFP_ZERO,
+		},
+		.to_dev_addr = NULL,
+	},
+};
+
+static inline struct vxd_dec_ctx *vxd_ctrl_to_ctx(struct v4l2_ctrl *vctrl)
+{
+	return container_of(vctrl->handler, struct vxd_dec_ctx, v4l2_ctrl_hdl);
+}
+
+static int vxd_dec_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct vxd_dec_ctx *ctx = vxd_ctrl_to_ctx(ctrl);
+
+	pr_debug("%s: name: %s | value: %d\n",
+		__func__, ctrl->name, ctrl->val);
+
+	switch (ctrl->id) {
+	case V4L2_CID_VXD_SET_DEC_BUFS:
+		ctx->max_dec_frame_buffering = ctrl->val;
+		break;
+	case V4L2_CID_VXD_SET_SPEC_BUFS:
+		ctx->override_spec_dpb_buffers = ctrl->val;
+		break;
+	case V4L2_CID_VXD_SET_IMG_BUFS:
+		ctx->img_extra_decode_buffers = ctrl->val;
+		break;
+	case V4L2_CID_VXD_SET_DISP_BUFS:
+		ctx->display_pipeline_size = ctrl->val;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops vxd_dec_ctrl_ops = {
+	.s_ctrl = vxd_dec_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config vxd_max_dec_frame_buffering = {
+	.ops = &vxd_dec_ctrl_ops,
+	.id = V4L2_CID_VXD_SET_DEC_BUFS,
+	.name = "max_dec_frame_buffering",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = 0,
+	.min = 0,
+	.max = 16,
+	.step = 1,
+	.flags = 0,
+};
+
+static const struct v4l2_ctrl_config vxd_img_extra_decode_buffers = {
+	.ops = &vxd_dec_ctrl_ops,
+	.id = V4L2_CID_VXD_SET_IMG_BUFS,
+	.name = "img_extra_decode_buffers",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = -1,
+	.min = -1,
+	.max = 3,
+	.step = 1,
+	.flags = 0,
+};
+
+static const struct v4l2_ctrl_config vxd_display_pipeline_size = {
+	.ops = &vxd_dec_ctrl_ops,
+	.id = V4L2_CID_VXD_SET_DISP_BUFS,
+	.name = "display_pipeline_size",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = DISPLAY_LAG,
+	.min = 0,
+	.max = 6,
+	.step = 1,
+	.flags = 0,
+};
+
+static const struct v4l2_ctrl_config vxd_override_spec_dpb_buffers = {
+	.ops = &vxd_dec_ctrl_ops,
+	.id = V4L2_CID_VXD_SET_SPEC_BUFS,
+	.name = "override_spec_dpb_buffers",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.def = -1,
+	.min = -1,
+	.max = 16,
+	.step = 1,
+	.flags = 0,
+};
+
+static struct vxd_dec_fmt vxd_dec_formats[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_NV12,
+		.num_planes = 1,
+		.type = IMG_DEC_FMT_TYPE_CAPTURE,
+		.std = VDEC_STD_UNDEFINED,
+		.pixfmt = IMG_PIXFMT_420PL12YUV8,
+		.interleave = PIXEL_UV_ORDER,
+		.idc = PIXEL_FORMAT_420,
+		.size_num = 3,
+		.size_den = 2,
+		.bytes_pp = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_NV16,
+		.num_planes = 1,
+		.type = IMG_DEC_FMT_TYPE_CAPTURE,
+		.std = VDEC_STD_UNDEFINED,
+		.pixfmt = IMG_PIXFMT_422PL12YUV8,
+		.interleave = PIXEL_UV_ORDER,
+		.idc = PIXEL_FORMAT_422,
+		.size_num = 2,
+		.size_den = 1,
+		.bytes_pp = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_TI1210,
+		.num_planes = 1,
+		.type = IMG_DEC_FMT_TYPE_CAPTURE,
+		.std = VDEC_STD_UNDEFINED,
+		.pixfmt = IMG_PIXFMT_420PL12YUV10_MSB,
+		.interleave = PIXEL_UV_ORDER,
+		.idc = PIXEL_FORMAT_420,
+		.size_num = 3,
+		.size_den = 2,
+		.bytes_pp = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_TI1610,
+		.num_planes = 1,
+		.type = IMG_DEC_FMT_TYPE_CAPTURE,
+		.std = VDEC_STD_UNDEFINED,
+		.pixfmt = IMG_PIXFMT_422PL12YUV10_MSB,
+		.interleave = PIXEL_UV_ORDER,
+		.idc = PIXEL_FORMAT_422,
+		.size_num = 2,
+		.size_den = 1,
+		.bytes_pp = 2,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_H264,
+		.num_planes = 1,
+		.type = IMG_DEC_FMT_TYPE_OUTPUT,
+		.std = VDEC_STD_H264,
+		.pixfmt = IMG_PIXFMT_UNDEFINED,
+		.interleave = PIXEL_INVALID_CI,
+		.idc = PIXEL_FORMAT_INVALID,
+		.size_num = 1,
+		.size_den = 1,
+		.bytes_pp = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_HEVC,
+		.num_planes = 1,
+		.type = IMG_DEC_FMT_TYPE_OUTPUT,
+		.std = VDEC_STD_HEVC,
+		.pixfmt = IMG_PIXFMT_UNDEFINED,
+		.interleave = PIXEL_INVALID_CI,
+		.idc = PIXEL_FORMAT_INVALID,
+		.size_num = 1,
+		.size_den = 1,
+		.bytes_pp = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_MJPEG,
+		.num_planes = 1,
+		.type = IMG_DEC_FMT_TYPE_OUTPUT,
+		.std = VDEC_STD_JPEG,
+		.pixfmt = IMG_PIXFMT_UNDEFINED,
+		.interleave = PIXEL_INVALID_CI,
+		.idc = PIXEL_FORMAT_INVALID,
+		.size_num = 1,
+		.size_den = 1,
+		.bytes_pp = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YUV420M,
+		.num_planes = 3,
+		.type = IMG_DEC_FMT_TYPE_CAPTURE,
+		.std = VDEC_STD_UNDEFINED,
+		.pixfmt = 86031,
+		.interleave = PIXEL_UV_ORDER,
+		.idc = PIXEL_FORMAT_420,
+		.size_num = 2,
+		.size_den = 1,
+		.bytes_pp = 1,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_YUV422M,
+		.num_planes = 3,
+		.type = IMG_DEC_FMT_TYPE_CAPTURE,
+		.std = VDEC_STD_UNDEFINED,
+		.pixfmt = 81935,
+		.interleave = PIXEL_UV_ORDER,
+		.idc = PIXEL_FORMAT_422,
+		.size_num = 3,
+		.size_den = 1,
+		.bytes_pp = 1,
+	},
+};
+
+#ifdef ERROR_RECOVERY_SIMULATION
+ssize_t vxd_sysfs_show(struct kobject *vxd_dec_kobject,
+		       struct kobj_attribute *attr, char *buf)
+
+{
+	int var = 0;
+
+	if (strcmp(attr->attr.name, "fw_error_value") == 0)
+		var = fw_error_value;
+
+	else
+		var = disable_fw_irq_value;
+
+	return sprintf(buf, "%d\n", var);
+}
+
+ssize_t vxd_sysfs_store(struct kobject *vxd_dec_kobject,
+			struct kobj_attribute *attr,
+			const char *buf, unsigned long count)
+{
+	int var = 0, rv = 0;
+
+	rv = sscanf(buf, "%du", &var);
+
+	if (strcmp(attr->attr.name, "fw_error_value") == 0) {
+		fw_error_value = var;
+	} else {
+		disable_fw_irq_value = var;
+		/*
+		 * if disable_fw_irq_value is not zero, disable the irq to reproduce
+		 * firmware non responsiveness in vxd_worker.
+		 */
+		if (disable_fw_irq_value != 0) {
+			/* just ignore the irq */
+			disable_irq(g_module_irq);
+		}
+	}
+	return sprintf((char *)buf, "%d\n", var);
+}
+#endif
+
+static struct vxd_dec_ctx *file2ctx(struct file *file)
+{
+	return container_of(file->private_data, struct vxd_dec_ctx, fh);
+}
+
+static irqreturn_t soft_thread_irq(int irq, void *dev_id)
+{
+	struct platform_device *pdev = (struct platform_device *)dev_id;
+
+	if (!pdev)
+		return IRQ_NONE;
+
+	return vxd_handle_thread_irq(&pdev->dev);
+}
+
+static irqreturn_t hard_isrcb(int irq, void *dev_id)
+{
+	struct platform_device *pdev = (struct platform_device *)dev_id;
+
+	if (!pdev)
+		return IRQ_NONE;
+
+	return vxd_handle_irq(&pdev->dev);
+}
+
+static struct vxd_mapping *find_mapping(unsigned int buf_map_id, struct list_head *head)
+{
+	struct list_head *list;
+	struct vxd_mapping *mapping = NULL;
+
+	list_for_each(list, head) {
+		mapping = list_entry(list, struct vxd_mapping, list);
+		if (!mapping)
+			continue;
+		if (mapping->buf_map_id == buf_map_id)
+			break;
+		mapping = NULL;
+	}
+	return mapping;
+}
+
+static struct vxd_buffer *find_buffer(unsigned int buf_map_id, struct list_head *head)
+{
+	struct list_head *list;
+	struct vxd_buffer *buf = NULL;
+
+	list_for_each(list, head) {
+		buf = list_entry(list, struct vxd_buffer, list);
+		if (!buf)
+			continue;
+		if (buf->buf_map_id == buf_map_id)
+			break;
+		buf = NULL;
+	}
+	return buf;
+}
+
+static void return_worker(void *work)
+{
+	struct vxd_dec_ctx *ctx;
+	struct vxd_return *res;
+	struct device *dev;
+	struct timespec64 time;
+	int loop;
+
+	work = get_work_buff(work, TRUE);
+
+	res = container_of(work, struct vxd_return, work);
+	ctx = res->ctx;
+	dev = ctx->dev->dev;
+	switch (res->type) {
+	case VXD_CB_PICT_DECODED:
+		v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
+		ktime_get_real_ts64(&time);
+		for (loop = 0; loop < ARRAY_SIZE(ctx->dev->time_drv); loop++) {
+			if (ctx->dev->time_drv[loop].id == res->buf_map_id) {
+				ctx->dev->time_drv[loop].end_time =
+				timespec64_to_ns(&time);
+#ifdef DEBUG_DECODER_DRIVER
+				dev_info(dev, "picture buf decode time is %llu us for buf_map_id 0x%x\n",
+					 div_s64(ctx->dev->time_drv[loop].end_time -
+						 ctx->dev->time_drv[loop].start_time, 1000),
+					 res->buf_map_id);
+#endif
+				break;
+				}
+			}
+
+		if (loop == ARRAY_SIZE(ctx->dev->time_drv))
+			dev_err(dev, "picture buf decode for buf_map_id x%0x is not measured\n",
+				res->buf_map_id);
+		break;
+
+	default:
+		break;
+	}
+	kfree(res->work);
+	kfree(res);
+}
+
+#ifdef ERROR_RECOVERY_SIMULATION
+static void vxd_error_recovery(struct vxd_dec_ctx *ctx)
+{
+	int ret = -1;
+
+	/*
+	 * In the previous frame decoding fatal error has been detected
+	 * so we need to reload the firmware to make it alive.
+	 */
+	pr_debug("Reloading the firmware because of previous error\n");
+	vxd_clean_fw_resources(ctx->dev);
+	ret = vxd_prepare_fw(ctx->dev);
+	if (ret)
+		pr_err("Reloading the firmware failed!!");
+}
+#endif /* ERROR_RECOVERY_SIMULATION */
+
+static struct vxd_dec_q_data *get_q_data(struct vxd_dec_ctx *ctx,
+					 enum v4l2_buf_type type)
+{
+	switch (type) {
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		return &ctx->q_data[Q_DATA_SRC];
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		return &ctx->q_data[Q_DATA_DST];
+	default:
+		return NULL;
+	}
+	return NULL;
+}
+
+static void vxd_return_resource(void *ctx_handle, enum vxd_cb_type type,
+				unsigned int buf_map_id, unsigned int err_flags)
+{
+	struct vxd_return *res;
+	struct vxd_buffer *buf = NULL;
+	struct vb2_v4l2_buffer *vb;
+	struct vxd_mapping *mapping = NULL;
+	struct vxd_dec_ctx *ctx = (struct vxd_dec_ctx *)ctx_handle;
+	struct v4l2_event event = {};
+	struct device *dev = ctx->dev->dev;
+	int i;
+	struct vxd_dec_q_data *q_data;
+
+	switch (type) {
+	case VXD_CB_STRUNIT_PROCESSED:
+
+		buf = find_buffer(buf_map_id, &ctx->out_buffers);
+		if (!buf) {
+			dev_err(dev, "Could not locate buf_map_id=0x%x in OUTPUT buffers list\n",
+				buf_map_id);
+			break;
+		}
+		buf->buffer.vb.field = V4L2_FIELD_NONE;
+
+		q_data = get_q_data(ctx, buf->buffer.vb.vb2_buf.vb2_queue->type);
+		if (!q_data)
+			return;
+
+		for (i = 0; i < q_data->fmt->num_planes; i++)
+			vb2_set_plane_payload(&buf->buffer.vb.vb2_buf, i,
+					      ctx->pict_bufcfg.plane_size[i]);
+
+		v4l2_m2m_buf_done(&buf->buffer.vb, VB2_BUF_STATE_DONE);
+		break;
+	case VXD_CB_SPS_RELEASE:
+		break;
+	case VXD_CB_PPS_RELEASE:
+		break;
+	case VXD_CB_PICT_DECODED:
+		res = kzalloc(sizeof(*res), GFP_KERNEL);
+		if (!res)
+			return;
+		res->ctx = ctx;
+		res->type = type;
+		res->buf_map_id = buf_map_id;
+
+		init_work(&res->work, return_worker, HWA_DECODER);
+		if (!res->work)
+			return;
+
+		/* this is done because the v4l2 spec says can't call m2m_done from */
+		/* device_run,  this callback could come from device_run */
+		schedule_work(res->work);
+
+		break;
+	case VXD_CB_PICT_DISPLAY:
+		buf = find_buffer(buf_map_id, &ctx->cap_buffers);
+		if (!buf) {
+			dev_err(dev, "Could not locate buf_map_id=0x%x in CAPTURE buffers list\n",
+				buf_map_id);
+			break;
+		}
+		buf->mapping->reuse = FALSE;
+		buf->buffer.vb.field = V4L2_FIELD_NONE;
+
+		q_data = get_q_data(ctx, buf->buffer.vb.vb2_buf.vb2_queue->type);
+		if (!q_data)
+			return;
+
+		for (i = 0; i < q_data->fmt->num_planes; i++)
+			vb2_set_plane_payload(&buf->buffer.vb.vb2_buf, i,
+					      ctx->pict_bufcfg.plane_size[i]);
+
+		/*
+		 * for fatal errors we will use the FATAL callback
+		 * however this will signal to v4l2 that this frame
+		 * has a (potentially concealled) error
+		 */
+		if (err_flags)
+			v4l2_m2m_buf_done(&buf->buffer.vb, VB2_BUF_STATE_ERROR);
+		else
+			v4l2_m2m_buf_done(&buf->buffer.vb, VB2_BUF_STATE_DONE);
+
+		break;
+	case VXD_CB_PICT_RELEASE:
+		buf = find_buffer(buf_map_id, &ctx->reuse_queue);
+		if (buf) {
+			buf->mapping->reuse = TRUE;
+			list_move_tail(&buf->list, &ctx->cap_buffers);
+
+			v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, &buf->buffer.vb);
+			break;
+		}
+		mapping = find_mapping(buf_map_id, &ctx->cap_mappings);
+		if (!mapping) {
+			dev_err(dev, "Could not locate buf_map_id=0x%x in CAPTURE buffers list\n",
+				buf_map_id);
+			break;
+		}
+		mapping->reuse = TRUE;
+
+		break;
+	case VXD_CB_PICT_END:
+		break;
+	case VXD_CB_STR_END:
+		event.type = V4L2_EVENT_EOS;
+		v4l2_event_queue_fh(&ctx->fh, &event);
+		if (v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) > 0) {
+			vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+			vb->flags |= V4L2_BUF_FLAG_LAST;
+
+			q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+			if (!q_data)
+				break;
+
+			for (i = 0; i < q_data->fmt->num_planes; i++)
+				vb2_set_plane_payload(&vb->vb2_buf, i, 0);
+
+			v4l2_m2m_buf_done(vb, VB2_BUF_STATE_DONE);
+		} else {
+			ctx->flag_last = TRUE;
+		}
+		break;
+	case VXD_CB_ERROR_FATAL:
+		/*
+		 * There has been FW error, so we need to reload the firmware.
+		 */
+#ifdef ERROR_RECOVERY_SIMULATION
+		vxd_error_recovery(ctx);
+#endif
+
+		if (ctx->dev->emergency)
+			ctx->eos = TRUE;
+		/*
+		 * Just send zero size buffer to v4l2 application,
+		 * informing the error condition.
+		 */
+		if (v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) > 0) {
+			vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+			vb->flags |= V4L2_BUF_FLAG_LAST;
+
+			q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+			if (!q_data)
+				break;
+
+			// terminal error, set planes to zero size and tell v4l2 layer
+			for (i = 0; i < q_data->fmt->num_planes; i++)
+				vb2_set_plane_payload(&vb->vb2_buf, i, 0);
+
+			v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
+		} else {
+			ctx->flag_last = TRUE;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static int vxd_dec_submit_opconfig(struct vxd_dec_ctx *ctx)
+{
+	int ret = 0;
+
+	if (ctx->stream_created) {
+		ret = core_stream_set_output_config(ctx->res_str_id,
+						    &ctx->str_opcfg,
+						    &ctx->pict_bufcfg);
+		if (ret) {
+			dev_err(ctx->dev->dev, "core_stream_set_output_config failed\n");
+			ctx->opconfig_pending = TRUE;
+			return ret;
+		}
+		ctx->opconfig_pending = FALSE;
+		ctx->stream_configured = TRUE;
+	} else {
+		ctx->opconfig_pending = TRUE;
+	}
+	return ret;
+}
+
+static int vxd_dec_queue_setup(struct vb2_queue *vq,
+			       unsigned int *nbuffers,
+			       unsigned int *nplanes,
+			       unsigned int sizes[],
+			       struct device *alloc_devs[])
+{
+	struct vxd_dec_ctx *ctx = vb2_get_drv_priv(vq);
+	struct vxd_dec_q_data *q_data;
+	struct vxd_dec_q_data *src_q_data;
+	int i;
+	unsigned int hw_nbuffers = 0;
+
+	q_data = get_q_data(ctx, vq->type);
+	if (!q_data)
+		return -EINVAL;
+
+	if (*nplanes) {
+		/* This is being called from CREATEBUFS, perform validation */
+		if (*nplanes != q_data->fmt->num_planes)
+			return -EINVAL;
+
+		for (i = 0; i < *nplanes; i++) {
+			if (sizes[i] != q_data->size_image[i])
+				return -EINVAL;
+		}
+
+		return 0;
+	}
+
+	*nplanes = q_data->fmt->num_planes;
+
+	if (!V4L2_TYPE_IS_OUTPUT(vq->type)) {
+		src_q_data = &ctx->q_data[Q_DATA_SRC];
+		if (src_q_data) {
+			if (src_q_data->fmt->std == VDEC_STD_H264) {
+				if (ctx->override_spec_dpb_buffers == -1)
+					vdecddutils_get_minrequired_numpicts(
+						&ctx->strcfgdata,
+						&ctx->comseq_hdr_info,
+						&ctx->str_opcfg, &hw_nbuffers);
+				else
+					hw_nbuffers =
+						ctx->override_spec_dpb_buffers;
+
+				/*
+				 * IMG Spec says need:
+				 * vdecddutils_get_minrequired_numpicts()
+				 *			+ ((num_cores * slots_per_core) - 1)
+				 *			+ display_pipeline_length
+				 */
+				if (ctx->img_extra_decode_buffers == -1)
+					hw_nbuffers +=
+					 (CORE_NUM_DECODE_SLOTS *
+					 ((struct dec_ctx *)ctx->dev_ctx->dec_context)->num_pipes) -
+					 1;
+				else
+					hw_nbuffers +=
+						ctx->img_extra_decode_buffers;
+
+				hw_nbuffers += ctx->display_pipeline_size;
+
+				pr_debug(
+					"DPB allocation algorithm has requested %d buffers\n",
+					hw_nbuffers);
+			} else {
+				hw_nbuffers = get_nbuffers(src_q_data->fmt->std,
+									q_data->width,
+									q_data->height,
+									ctx->max_num_ref_frames);
+			}
+		}
+	}
+
+	*nbuffers = max(*nbuffers, hw_nbuffers);
+
+	pr_debug("telling the framework to allocate %d buffers\n", *nbuffers);
+
+	for (i = 0; i < *nplanes; i++)
+		sizes[i] = q_data->size_image[i];
+
+	return 0;
+}
+
+static int vxd_dec_buf_prepare(struct vb2_buffer *vb)
+{
+	struct vxd_dec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct device *dev = ctx->dev->dev;
+	struct vxd_dec_q_data *q_data;
+	void *sgt;
+#ifdef CAPTURE_CONTIG_ALLOC
+	struct page *new_page;
+#else
+	void *sgl;
+#endif
+	struct sg_table *sgt_new;
+	void *sgl_new;
+	int pages;
+	int nents = 0;
+	int size = 0;
+	int plane, num_planes, ret = 0;
+	unsigned long dma_addr;
+	struct vxd_mapping *mapping;
+	struct list_head *list;
+	struct vxd_buffer *buf =
+		container_of(vb, struct vxd_buffer, buffer.vb.vb2_buf);
+
+	q_data = get_q_data(ctx, vb->vb2_queue->type);
+	if (!q_data)
+		return -EINVAL;
+
+	num_planes = q_data->fmt->num_planes;
+
+	for (plane = 0; plane < num_planes; plane++) {
+		if (vb2_plane_size(vb, plane) < q_data->size_image[plane]) {
+			dev_err(dev, "data will not fit into plane (%lu < %lu)\n",
+				vb2_plane_size(vb, plane),
+				(long)q_data->size_image[plane]);
+			return -EINVAL;
+		}
+	}
+
+	if (buf->mapped && !V4L2_TYPE_IS_OUTPUT(vb->type)) {
+#ifdef CAPTURE_CONTIG_ALLOC
+		dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+#else
+		sgt = vb2_dma_sg_plane_desc(vb, 0);
+		if (!sgt)
+			return -EFAULT;
+
+		dma_addr = sg_phys(img_mmu_get_sgl(sgt));
+#endif
+		if (buf->buf_info.dma_addr != dma_addr) {
+			list_for_each(list, &ctx->cap_mappings) {
+				mapping = list_entry(list, struct vxd_mapping, list);
+				if (dma_addr == mapping->dma_addr)
+					break;
+
+				mapping = NULL;
+			}
+			if (mapping) {
+				/* skip the mapping, buf update buf_map_id */
+				buf->buf_info.dma_addr = mapping->dma_addr;
+				buf->buf_map_id = mapping->buf_map_id;
+				buf->buf_info.cpu_linear_addr = vb2_plane_vaddr(vb, 0);
+				buf->mapping = mapping;
+				return 0;
+			}
+		} else {
+			return 0;
+		}
+	} else if (buf->mapped) {
+		return 0;
+	}
+
+	buf->buf_info.cpu_linear_addr = vb2_plane_vaddr(vb, 0);
+	buf->buf_info.buf_size = vb2_plane_size(vb, 0);
+	buf->buf_info.fd = -1;
+	sgt = vb2_dma_sg_plane_desc(vb, 0);
+	if (!sgt) {
+		dev_err(dev, "Could not get sg_table from plane 0\n");
+		return -EINVAL;
+	}
+
+	if (V4L2_TYPE_IS_OUTPUT(vb->type)) {
+		buf->buf_info.dma_addr = sg_phys(img_mmu_get_sgl(sgt));
+		ret = core_stream_map_buf_sg(ctx->res_str_id,
+					     VDEC_BUFTYPE_BITSTREAM,
+					     &buf->buf_info, sgt,
+					     &buf->buf_map_id);
+		if (ret) {
+			dev_err(dev, "OUTPUT core_stream_map_buf_sg failed\n");
+			return ret;
+		}
+
+		buf->bstr_info.buf_size = q_data->size_image[0];
+		buf->bstr_info.cpu_virt_addr = buf->buf_info.cpu_linear_addr;
+		buf->bstr_info.mem_attrib =
+			SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE |
+			SYS_MEMATTRIB_INPUT | SYS_MEMATTRIB_CPU_WRITE;
+		buf->bstr_info.bufmap_id = buf->buf_map_id;
+		lst_init(&buf->seq_unit.bstr_seg_list);
+		lst_init(&buf->pic_unit.bstr_seg_list);
+		lst_init(&buf->end_unit.bstr_seg_list);
+
+		list_add_tail(&buf->list, &ctx->out_buffers);
+	} else {
+#ifdef CAPTURE_CONTIG_ALLOC
+		buf->buf_info.dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+#else
+		buf->buf_info.dma_addr = sg_phys(img_mmu_get_sgl(sgt));
+#endif
+		/* Create a single sgt from the plane(s) */
+		sgt_new = kmalloc(sizeof(*sgt_new), GFP_KERNEL);
+		if (!sgt_new)
+			return -EINVAL;
+
+		for (plane = 0; plane < num_planes; plane++) {
+			size += ALIGN(vb2_plane_size(vb, plane), PAGE_SIZE);
+			sgt = vb2_dma_sg_plane_desc(vb, plane);
+			if (!sgt) {
+				dev_err(dev, "Could not get sg_table from plane %d\n", plane);
+				kfree(sgt_new);
+				return -EINVAL;
+			}
+#ifdef CAPTURE_CONTIG_ALLOC
+			nents += 1;
+#else
+			nents += sg_nents(img_mmu_get_sgl(sgt));
+#endif
+		}
+		buf->buf_info.buf_size = size;
+
+		pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+		ret = sg_alloc_table(sgt_new, nents, GFP_KERNEL);
+		if (ret) {
+			kfree(sgt_new);
+			return -EINVAL;
+		}
+		sgl_new = img_mmu_get_sgl(sgt_new);
+
+		for (plane = 0; plane < num_planes; plane++) {
+			sgt = vb2_dma_sg_plane_desc(vb, plane);
+			if (!sgt) {
+				dev_err(dev, "Could not get sg_table from plane %d\n", plane);
+				sg_free_table(sgt_new);
+				kfree(sgt_new);
+				return -EINVAL;
+			}
+#ifdef CAPTURE_CONTIG_ALLOC
+			new_page = phys_to_page(vb2_dma_contig_plane_dma_addr(vb, plane));
+			sg_set_page(sgl_new, new_page, ALIGN(vb2_plane_size(vb, plane),
+							     PAGE_SIZE), 0);
+			sgl_new = sg_next(sgl_new);
+#else
+			sgl = img_mmu_get_sgl(sgt);
+
+			while (sgl) {
+				sg_set_page(sgl_new, sg_page(sgl), img_mmu_get_sgl_length(sgl), 0);
+				sgl = sg_next(sgl);
+				sgl_new = sg_next(sgl_new);
+			}
+#endif
+		}
+
+		buf->buf_info.pictbuf_cfg = ctx->pict_bufcfg;
+		ret = core_stream_map_buf_sg(ctx->res_str_id,
+					     VDEC_BUFTYPE_PICTURE,
+					     &buf->buf_info, sgt_new,
+					     &buf->buf_map_id);
+		sg_free_table(sgt_new);
+		kfree(sgt_new);
+		if (ret) {
+			dev_err(dev, "CAPTURE core_stream_map_buf_sg failed\n");
+			return ret;
+		}
+		if (buf->mapped == FALSE)
+			list_add_tail(&buf->list, &ctx->cap_buffers);
+
+		/* Add this to the mappings */
+		mapping = kzalloc(sizeof(*mapping), GFP_KERNEL);
+
+		mapping->reuse = TRUE;
+		mapping->dma_addr = buf->buf_info.dma_addr;
+		mapping->buf_map_id = buf->buf_map_id;
+		list_add_tail(&mapping->list, &ctx->cap_mappings);
+		buf->mapping = mapping;
+		mapping->buf = buf;
+	}
+	buf->mapped = TRUE;
+
+	return 0;
+}
+
+static void vxd_dec_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vxd_dec_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vxd_buffer *buf =
+		container_of(vb, struct vxd_buffer, buffer.vb.vb2_buf);
+	struct vxd_dec_q_data *q_data;
+	int i;
+
+	if (V4L2_TYPE_IS_OUTPUT(vb->type)) {
+		vbuf->sequence = ctx->out_seq++;
+		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+	} else {
+		vbuf->sequence = ctx->cap_seq++;
+		mutex_lock_nested(ctx->mutex, SUBCLASS_VXD_V4L2);
+		if (buf->mapping->reuse) {
+			mutex_unlock(ctx->mutex);
+			if (ctx->flag_last) {
+				q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+				vbuf->flags |= V4L2_BUF_FLAG_LAST;
+
+				for (i = 0; i < q_data->fmt->num_planes; i++)
+					vb2_set_plane_payload(&vbuf->vb2_buf, i, 0);
+
+				v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
+			} else {
+				v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+			}
+		} else {
+			list_move_tail(&buf->list, &ctx->reuse_queue);
+			mutex_unlock(ctx->mutex);
+		}
+	}
+}
+
+static void vxd_dec_return_all_buffers(struct vxd_dec_ctx *ctx,
+				       struct vb2_queue *q,
+				       enum vb2_buffer_state state)
+{
+	struct vb2_v4l2_buffer *vb;
+	unsigned long flags;
+
+	for (;;) {
+		if (V4L2_TYPE_IS_OUTPUT(q->type))
+			vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+		else
+			vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+
+		if (!vb)
+			break;
+
+		spin_lock_irqsave(ctx->dev->lock, flags);
+		v4l2_m2m_buf_done(vb, state);
+		spin_unlock_irqrestore(ctx->dev->lock, (unsigned long)flags);
+	}
+}
+
+static int vxd_dec_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	int ret = 0;
+	struct vxd_dec_ctx *ctx = vb2_get_drv_priv(vq);
+
+	if (V4L2_TYPE_IS_OUTPUT(vq->type))
+		ctx->src_streaming = TRUE;
+	else
+		ctx->dst_streaming = TRUE;
+
+	if (ctx->dst_streaming && ctx->src_streaming && !ctx->core_streaming) {
+		if (!ctx->stream_configured) {
+			vxd_dec_return_all_buffers(ctx, vq, VB2_BUF_STATE_ERROR);
+			return -EINVAL;
+		}
+		ctx->eos = FALSE;
+		ctx->stop_initiated = FALSE;
+		ctx->flag_last = FALSE;
+		ret = core_stream_play(ctx->res_str_id);
+		if (ret) {
+			vxd_dec_return_all_buffers(ctx, vq, VB2_BUF_STATE_ERROR);
+			return ret;
+		}
+		ctx->core_streaming = TRUE;
+		ctx->aborting = 0;
+	}
+
+	return 0;
+}
+
+static void vxd_dec_stop_streaming(struct vb2_queue *vq)
+{
+	struct vxd_dec_ctx *ctx = vb2_get_drv_priv(vq);
+	struct list_head *list;
+	struct list_head *temp;
+	struct vxd_buffer *buf = NULL;
+	struct vxd_mapping *mapping = NULL;
+
+	if (V4L2_TYPE_IS_OUTPUT(vq->type))
+		ctx->src_streaming = FALSE;
+	else
+		ctx->dst_streaming = FALSE;
+
+	if (!ctx->stream_created) {
+		vxd_dec_return_all_buffers(ctx, vq, VB2_BUF_STATE_ERROR);
+		return;
+	}
+
+	if (ctx->core_streaming) {
+		core_stream_stop(ctx->res_str_id);
+		ctx->core_streaming = FALSE;
+
+		core_stream_flush(ctx->res_str_id, TRUE);
+	}
+	/* unmap all the output and capture plane buffers */
+	if (V4L2_TYPE_IS_OUTPUT(vq->type)) {
+		list_for_each(list, &ctx->out_buffers) {
+			buf = list_entry(list, struct vxd_buffer, list);
+			core_stream_unmap_buf_sg(buf->buf_map_id);
+			buf->mapped = FALSE;
+			__list_del_entry(&buf->list);
+		}
+	} else {
+		list_for_each_safe(list, temp, &ctx->reuse_queue) {
+			buf = list_entry(list, struct vxd_buffer, list);
+			list_move_tail(&buf->list, &ctx->cap_buffers);
+			v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, &buf->buffer.vb);
+		}
+
+		list_for_each(list, &ctx->cap_buffers) {
+			buf = list_entry(list, struct vxd_buffer, list);
+			__list_del_entry(&buf->list);
+		}
+
+		list_for_each(list, &ctx->cap_mappings) {
+			mapping = list_entry(list, struct vxd_mapping, list);
+			core_stream_unmap_buf_sg(mapping->buf_map_id);
+			mapping->buf->mapped = FALSE;
+			__list_del_entry(&mapping->list);
+		}
+	}
+
+	ctx->flag_last = FALSE;
+	vxd_dec_return_all_buffers(ctx, vq, VB2_BUF_STATE_ERROR);
+}
+
+static const struct vb2_ops vxd_dec_video_ops = {
+	.queue_setup = vxd_dec_queue_setup,
+	.buf_prepare = vxd_dec_buf_prepare,
+	.buf_queue = vxd_dec_buf_queue,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.start_streaming = vxd_dec_start_streaming,
+	.stop_streaming = vxd_dec_stop_streaming,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
+{
+	struct vxd_dec_ctx *ctx = priv;
+	struct vxd_dev *vxd = ctx->dev;
+	int ret = 0;
+
+	/* src_vq */
+	memset(src_vq, 0, sizeof(*src_vq));
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	src_vq->drv_priv = ctx;
+	src_vq->buf_struct_size = sizeof(struct vxd_buffer);
+	src_vq->ops = &vxd_dec_video_ops;
+	src_vq->mem_ops = &vb2_dma_sg_memops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock = vxd->mutex_queue;
+	src_vq->dev = vxd->v4l2_dev.dev;
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	/* dst_vq */
+	memset(dst_vq, 0, sizeof(*dst_vq));
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	dst_vq->drv_priv = ctx;
+	dst_vq->buf_struct_size = sizeof(struct vxd_buffer);
+	dst_vq->ops = &vxd_dec_video_ops;
+#ifdef CAPTURE_CONTIG_ALLOC
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+#else
+	dst_vq->mem_ops = &vb2_dma_sg_memops;
+#endif
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock = vxd->mutex_queue;
+	dst_vq->dev = vxd->v4l2_dev.dev;
+	ret = vb2_queue_init(dst_vq);
+	if (ret) {
+		vb2_queue_release(src_vq);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int vxd_dec_open(struct file *file)
+{
+	struct vxd_dev *vxd = video_drvdata(file);
+	struct vxd_dec_ctx *ctx;
+	struct vxd_dec_q_data *s_q_data;
+	struct v4l2_ctrl_handler *v4l2_ctrl_hdl;
+
+	int i, ret = 0;
+
+	dev_dbg(vxd->dev, "%s:%d vxd %p\n", __func__, __LINE__, vxd);
+
+	if (vxd->no_fw) {
+		dev_err(vxd->dev, "Error!! fw binary is not present");
+		return -1;
+	}
+
+	mutex_lock_nested(vxd->mutex, SUBCLASS_BASE);
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx) {
+		mutex_unlock(vxd->mutex);
+		return -ENOMEM;
+	}
+	ctx->dev = vxd;
+
+	v4l2_ctrl_hdl = &ctx->v4l2_ctrl_hdl;
+
+	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	file->private_data = &ctx->fh;
+
+	s_q_data = &ctx->q_data[Q_DATA_SRC];
+	s_q_data->fmt = &vxd_dec_formats[0];
+	s_q_data->width = 1920;
+	s_q_data->height = 1080;
+	for (i = 0; i < s_q_data->fmt->num_planes; i++) {
+		s_q_data->bytesperline[i] = s_q_data->width;
+		s_q_data->size_image[i] = s_q_data->bytesperline[i] * s_q_data->height;
+	}
+
+	ctx->q_data[Q_DATA_DST] = *s_q_data;
+
+	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(vxd->m2m_dev, ctx, &queue_init);
+	if (IS_ERR_VALUE((unsigned long)ctx->fh.m2m_ctx)) {
+		ret = (long)(ctx->fh.m2m_ctx);
+		goto exit;
+	}
+
+	v4l2_fh_add(&ctx->fh);
+
+	v4l2_ctrl_handler_init(v4l2_ctrl_hdl, 6);
+	v4l2_ctrl_new_custom(v4l2_ctrl_hdl, &vxd_max_dec_frame_buffering, NULL);
+	v4l2_ctrl_new_custom(v4l2_ctrl_hdl, &vxd_override_spec_dpb_buffers, NULL);
+	v4l2_ctrl_new_custom(v4l2_ctrl_hdl, &vxd_img_extra_decode_buffers, NULL);
+	v4l2_ctrl_new_custom(v4l2_ctrl_hdl, &vxd_display_pipeline_size, NULL);
+	if (ctx->v4l2_ctrl_hdl.error) {
+		dev_err(vxd->dev, "failed to create custom controls\n");
+		ret = -ENODEV;
+		goto exit;
+	}
+
+	ctx->fh.ctrl_handler = &ctx->v4l2_ctrl_hdl;
+	v4l2_ctrl_handler_setup(&ctx->v4l2_ctrl_hdl);
+
+	ret = idr_alloc_cyclic(vxd->streams, &ctx->stream, VXD_MIN_STREAM_ID, VXD_MAX_STREAM_ID,
+			       GFP_KERNEL);
+	if (ret < VXD_MIN_STREAM_ID || ret > VXD_MAX_STREAM_ID) {
+		dev_err(vxd->dev, "%s: stream id creation failed!\n",
+			__func__);
+		ret = -EFAULT;
+		goto exit;
+	}
+
+	ctx->stream.id = ret;
+	ctx->stream.ctx = ctx;
+
+	ctx->stream_created = FALSE;
+	ctx->stream_configured = FALSE;
+	ctx->src_streaming = FALSE;
+	ctx->dst_streaming = FALSE;
+	ctx->core_streaming = FALSE;
+	ctx->eos = FALSE;
+	ctx->stop_initiated = FALSE;
+	ctx->flag_last = FALSE;
+
+	lst_init(&ctx->seg_list);
+	for (i = 0; i < MAX_SEGMENTS; i++)
+		lst_add(&ctx->seg_list, &ctx->bstr_segments[i]);
+
+	if (vxd_create_ctx(vxd, ctx))
+		goto out_idr_remove;
+
+	ctx->stream.mmu_ctx = ctx->mmu_ctx;
+	ctx->stream.ptd = ctx->ptd;
+
+	ctx->mutex = kzalloc(sizeof(*ctx->mutex), GFP_KERNEL);
+	if (!ctx->mutex) {
+		ret = -ENOMEM;
+		goto out_idr_remove;
+	}
+	mutex_init(ctx->mutex);
+
+	ctx->mutex2 = kzalloc(sizeof(*ctx->mutex), GFP_KERNEL);
+	if (!ctx->mutex2) {
+		ret = -ENOMEM;
+		goto out_idr_remove;
+	}
+	mutex_init(ctx->mutex2);
+
+	INIT_LIST_HEAD(&ctx->items_done);
+	INIT_LIST_HEAD(&ctx->reuse_queue);
+	INIT_LIST_HEAD(&ctx->return_queue);
+	INIT_LIST_HEAD(&ctx->out_buffers);
+	INIT_LIST_HEAD(&ctx->cap_buffers);
+	INIT_LIST_HEAD(&ctx->cap_mappings);
+
+	mutex_unlock(vxd->mutex);
+
+	return 0;
+
+out_idr_remove:
+	idr_remove(vxd->streams, ctx->stream.id);
+
+exit:
+	v4l2_fh_exit(&ctx->fh);
+	get_work_buff(ctx->work, TRUE);
+	kfree(ctx->work);
+	kfree(ctx);
+	mutex_unlock(vxd->mutex);
+	return ret;
+}
+
+static int vxd_dec_release(struct file *file)
+{
+	struct vxd_dev *vxd = video_drvdata(file);
+	struct vxd_dec_ctx *ctx = file2ctx(file);
+	struct bspp_ddbuf_array_info *fw_sequ = ctx->fw_sequ;
+	struct bspp_ddbuf_array_info *fw_pps = ctx->fw_pps;
+	int i, ret = 0;
+	struct vxd_dec_q_data *s_q_data;
+	struct list_head *list;
+	struct list_head *temp;
+	struct vxd_buffer *buf = NULL;
+	struct vxd_mapping *mapping = NULL;
+
+	s_q_data = &ctx->q_data[Q_DATA_SRC];
+	if (ctx->core_streaming) {
+		core_stream_stop(ctx->res_str_id);
+		ctx->core_streaming = FALSE;
+
+		core_stream_flush(ctx->res_str_id, TRUE);
+	}
+
+	list_for_each(list, &ctx->out_buffers) {
+		buf = list_entry(list, struct vxd_buffer, list);
+		core_stream_unmap_buf_sg(buf->buf_map_id);
+		buf->mapped = FALSE;
+		__list_del_entry(&buf->list);
+	}
+
+	list_for_each(list, &ctx->cap_buffers) {
+		buf = list_entry(list, struct vxd_buffer, list);
+		__list_del_entry(&buf->list);
+	}
+
+	list_for_each_safe(list, temp, &ctx->reuse_queue) {
+		buf = list_entry(list, struct vxd_buffer, list);
+		core_stream_unmap_buf_sg(buf->buf_map_id);
+		buf->mapped = FALSE;
+		__list_del_entry(&buf->list);
+	}
+
+	list_for_each(list, &ctx->cap_mappings) {
+		mapping = list_entry(list, struct vxd_mapping, list);
+		core_stream_unmap_buf_sg(mapping->buf_map_id);
+		__list_del_entry(&mapping->list);
+	}
+	if (ctx->stream_created) {
+		bspp_stream_destroy(ctx->bspp_context);
+
+		for (i = 0; i < MAX_SEQUENCES; i++) {
+			core_stream_unmap_buf(fw_sequ[i].ddbuf_info.bufmap_id);
+			img_mem_free(ctx->mem_ctx, fw_sequ[i].ddbuf_info.buf_id);
+		}
+
+		if (s_q_data->fmt->std != VDEC_STD_JPEG) {
+			for (i = 0; i < MAX_PPSS; i++) {
+				core_stream_unmap_buf(fw_pps[i].ddbuf_info.bufmap_id);
+				img_mem_free(ctx->mem_ctx, fw_pps[i].ddbuf_info.buf_id);
+			}
+		}
+		core_stream_destroy(ctx->res_str_id);
+		ctx->stream_created = FALSE;
+	}
+
+	mutex_lock_nested(vxd->mutex, SUBCLASS_BASE);
+
+	vxd_destroy_ctx(vxd, ctx);
+
+	idr_remove(vxd->streams, ctx->stream.id);
+
+	v4l2_fh_del(&ctx->fh);
+
+	v4l2_fh_exit(&ctx->fh);
+
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+
+	mutex_destroy(ctx->mutex);
+	kfree(ctx->mutex);
+	ctx->mutex = NULL;
+
+	get_work_buff(ctx->work, TRUE);
+	kfree(ctx->work);
+	kfree(ctx);
+
+	mutex_unlock(vxd->mutex);
+
+	return ret;
+}
+
+static int vxd_dec_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
+{
+	strncpy(cap->driver, IMG_VXD_DEC_MODULE_NAME, sizeof(cap->driver) - 1);
+	strncpy(cap->card, IMG_VXD_DEC_MODULE_NAME, sizeof(cap->card) - 1);
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", IMG_VXD_DEC_MODULE_NAME);
+	cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+	return 0;
+}
+
+static int __enum_fmt(struct v4l2_fmtdesc *f, unsigned int type)
+{
+	int i, index;
+	struct vxd_dec_fmt *fmt = NULL;
+	index = 0;
+	for (i = 0; i < ARRAY_SIZE(vxd_dec_formats); ++i) {
+		if (vxd_dec_formats[i].type & type) {
+			if (index == f->index) {
+				fmt = &vxd_dec_formats[i];
+				break;
+			}
+			index++;
+		}
+	}
+
+	if (!fmt)
+		return -EINVAL;
+
+	f->pixelformat = fmt->fourcc;
+	return 0;
+}
+
+static int vxd_dec_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f)
+{
+	if (V4L2_TYPE_IS_OUTPUT(f->type))
+		return __enum_fmt(f, IMG_DEC_FMT_TYPE_OUTPUT);
+
+	return __enum_fmt(f, IMG_DEC_FMT_TYPE_CAPTURE);
+}
+
+static struct vxd_dec_fmt *find_format(struct v4l2_format *f, unsigned int type)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(vxd_dec_formats); ++i) {
+		if (vxd_dec_formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
+		    vxd_dec_formats[i].type == type)
+			return &vxd_dec_formats[i];
+	}
+	return NULL;
+}
+
+static unsigned int get_sizeimage(int w, int h, struct vxd_dec_fmt *fmt, int plane)
+{
+	switch (fmt->fourcc) {
+	case V4L2_PIX_FMT_YUV420M:
+		return ((plane == 0) ? (w * h) : (w * h / 2));
+	case V4L2_PIX_FMT_YUV422M:
+		return (w * h);
+	default:
+		return (w * h * fmt->size_num / fmt->size_den);
+	}
+
+	return 0;
+}
+
+static unsigned int get_stride(int w, struct vxd_dec_fmt *fmt)
+{
+	return (ALIGN(w, HW_ALIGN) * fmt->bytes_pp);
+}
+
+/*
+ * @ Function vxd_get_header_info
+ * Run bspp stream submit and preparse once before device_run
+ * To retrieve header information
+ */
+static int vxd_get_header_info(void *priv)
+{
+	struct vxd_dec_ctx *ctx = priv;
+	struct vxd_dev *vxd_dev = ctx->dev;
+	struct device *dev = vxd_dev->v4l2_dev.dev;
+	struct vb2_v4l2_buffer  *src_vb;
+	struct vxd_buffer *src_vxdb;
+	struct vxd_buffer *dst_vxdb;
+	struct bspp_preparsed_data *preparsed_data;
+	unsigned int data_size;
+	int ret;
+
+	/*
+	 * Checking for queued buffer.
+	 * If no next buffer present, do not get information from header.
+	 * Else, get header information and store for later use.
+	 */
+	src_vb =  v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
+	if (!src_vb) {
+		dev_warn(dev, "get_header_info Next src buffer is null\n");
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+	mutex_lock_nested(ctx->mutex, SUBCLASS_VXD_V4L2);
+
+	src_vxdb = container_of(src_vb, struct vxd_buffer, buffer.vb);
+	/* Setting dst_vxdb to arbitrary value (using src_vb) for now */
+	dst_vxdb = container_of(src_vb, struct vxd_buffer, buffer.vb);
+
+	preparsed_data = &dst_vxdb->preparsed_data;
+
+	data_size = vb2_get_plane_payload(&src_vxdb->buffer.vb.vb2_buf, 0);
+
+	ret = bspp_stream_submit_buffer(ctx->bspp_context,
+					&src_vxdb->bstr_info,
+					src_vxdb->buf_map_id,
+					data_size, NULL,
+					VDEC_BSTRELEMENT_UNSPECIFIED);
+	if (ret) {
+		dev_err(dev, "get_header_info bspp_stream_submit_buffer failed %d\n", ret);
+		return ret;
+	}
+	mutex_unlock(ctx->mutex);
+
+	ret = bspp_stream_preparse_buffers(ctx->bspp_context, NULL, 0,
+					   &ctx->seg_list,
+					   preparsed_data, ctx->eos);
+	if (ret) {
+		dev_err(dev, "get_header_info bspp_stream_preparse_buffers failed %d\n", ret);
+		return ret;
+	}
+
+	if (preparsed_data->sequ_hdr_info.com_sequ_hdr_info.max_frame_size.height &&
+	    preparsed_data->sequ_hdr_info.com_sequ_hdr_info.max_ref_frame_num) {
+		ctx->height = preparsed_data->sequ_hdr_info.com_sequ_hdr_info.max_frame_size.height;
+		ctx->max_num_ref_frames =
+			preparsed_data->sequ_hdr_info.com_sequ_hdr_info.max_ref_frame_num;
+
+		/* save off the sequence header to the context structure */
+		memcpy(&ctx->comseq_hdr_info, &(preparsed_data->sequ_hdr_info.com_sequ_hdr_info),
+					sizeof(struct vdec_comsequ_hdrinfo));
+	} else {
+		dev_err(dev, "get_header_info preparsed data is null %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int vxd_dec_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct vxd_dec_ctx *ctx = file2ctx(file);
+	struct vxd_dec_q_data *q_data;
+	struct vxd_dev *vxd_dev = ctx->dev;
+	unsigned int i = 0;
+	int ret = 0;
+
+	q_data = get_q_data(ctx, f->type);
+	if (!q_data)
+		return -EINVAL;
+
+	pix_mp->field = V4L2_FIELD_NONE;
+	pix_mp->pixelformat = q_data->fmt->fourcc;
+	pix_mp->num_planes = q_data->fmt->num_planes;
+
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		/* The buffer contains compressed image. */
+		pix_mp->width = ctx->width;
+		pix_mp->height = ctx->height;
+		pix_mp->plane_fmt[0].bytesperline = 0;
+		pix_mp->plane_fmt[0].sizeimage = q_data->size_image[0];
+	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		/* The buffer contains decoded YUV image. */
+		pix_mp->width = ctx->width;
+		pix_mp->height = ctx->height;
+		for (i = 0; i < q_data->fmt->num_planes; i++) {
+			pix_mp->plane_fmt[i].bytesperline = get_stride(pix_mp->width, q_data->fmt);
+			pix_mp->plane_fmt[i].sizeimage = get_sizeimage
+							(pix_mp->plane_fmt[i].bytesperline,
+							 ctx->height, q_data->fmt, i);
+		}
+	} else {
+		dev_err(vxd_dev->v4l2_dev.dev, "Wrong V4L2_format type\n");
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+static int vxd_dec_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+	struct vxd_dec_ctx *ctx = file2ctx(file);
+	struct vxd_dev *vxd_dev = ctx->dev;
+	struct vxd_dec_fmt *fmt;
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
+	unsigned int i = 0;
+	int ret = 0;
+
+	pix_mp->width = ALIGN(pix_mp->width, HW_ALIGN);
+	pix_mp->height = ALIGN(pix_mp->height, HW_ALIGN);
+
+	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+		fmt = find_format(f, IMG_DEC_FMT_TYPE_OUTPUT);
+		if (!fmt) {
+			dev_err(vxd_dev->v4l2_dev.dev, "Unsupported format for source.\n");
+			return -EINVAL;
+		}
+		/*
+		 * Allocation for NV12 input frame size:
+		 */
+		plane_fmt[0].sizeimage = (ALIGN(pix_mp->width, HW_ALIGN) *
+			ALIGN(pix_mp->height, HW_ALIGN) * 3)/2;
+	} else {
+		fmt = find_format(f, IMG_DEC_FMT_TYPE_CAPTURE);
+		if (!fmt) {
+			dev_err(vxd_dev->v4l2_dev.dev, "Unsupported format for dest.\n");
+			return -EINVAL;
+		}
+		for (i = 0; i < fmt->num_planes; i++) {
+			plane_fmt[i].bytesperline = get_stride(pix_mp->width, fmt);
+			plane_fmt[i].sizeimage = get_sizeimage(pix_mp->width,
+							       pix_mp->height, fmt, i);
+		}
+		pix_mp->num_planes = fmt->num_planes;
+		pix_mp->flags = 0;
+	}
+
+	if (pix_mp->field == V4L2_FIELD_ANY)
+		pix_mp->field = V4L2_FIELD_NONE;
+
+	return ret;
+}
+
+static int vxd_dec_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+	struct v4l2_pix_format_mplane *pix_mp;
+	struct vxd_dec_ctx *ctx = file2ctx(file);
+	struct vxd_dev *vxd_dev = ctx->dev;
+	struct device *dev = vxd_dev->v4l2_dev.dev;
+	struct vxd_dec_q_data *q_data;
+	struct vb2_queue *vq;
+	struct vxd_dec_fmt *fmt;
+
+	int ret = 0;
+	unsigned char i = 0, j = 0;
+
+	pix_mp = &f->fmt.pix_mp;
+
+	if (!V4L2_TYPE_IS_OUTPUT(f->type)) {
+		int res = vxd_get_header_info(ctx);
+
+		if (res == 0)
+			pix_mp->height = ctx->height;
+	} else {
+		ctx->width_orig = pix_mp->width;
+		ctx->height_orig = pix_mp->height;
+	}
+
+	ret = vxd_dec_try_fmt(file, priv, f);
+	if (ret)
+		return ret;
+
+	vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
+	if (!vq)
+		return -EINVAL;
+
+	if (vb2_is_busy(vq)) {
+		dev_err(dev, "Queue is busy\n");
+		return -EBUSY;
+	}
+
+	q_data = get_q_data(ctx, f->type);
+
+	if (!q_data)
+		return -EINVAL;
+
+	ctx->width = pix_mp->width;
+	ctx->height = pix_mp->height;
+
+	q_data->width = pix_mp->width;
+	q_data->height = pix_mp->height;
+
+	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+		q_data->fmt = find_format(f, IMG_DEC_FMT_TYPE_OUTPUT);
+		q_data->size_image[0] = pix_mp->plane_fmt[0].sizeimage;
+
+		if (!ctx->stream_created) {
+			ctx->strcfgdata.vid_std = q_data->fmt->std;
+
+			if (ctx->strcfgdata.vid_std == VDEC_STD_UNDEFINED) {
+				dev_err(dev, "Invalid input format\n");
+				return -EINVAL;
+			}
+			ctx->strcfgdata.bstr_format = VDEC_BSTRFORMAT_ELEMENTARY;
+			ctx->strcfgdata.user_str_id = ctx->stream.id;
+			ctx->strcfgdata.update_yuv = FALSE;
+			ctx->strcfgdata.bandwidth_efficient = FALSE;
+			ctx->strcfgdata.disable_mvc = FALSE;
+			ctx->strcfgdata.full_scan = FALSE;
+			ctx->strcfgdata.immediate_decode = TRUE;
+			ctx->strcfgdata.intra_frame_closed_gop = TRUE;
+
+			ctx->strcfgdata.max_dec_frame_buffering = ctx->max_dec_frame_buffering;
+
+			ret = core_stream_create(ctx, &ctx->strcfgdata, &ctx->res_str_id);
+			if (ret) {
+				dev_err(dev, "Core stream create failed\n");
+				return -EINVAL;
+			}
+			ctx->stream_created = TRUE;
+			if (ctx->opconfig_pending) {
+				ret = vxd_dec_submit_opconfig(ctx);
+				if (ret) {
+					dev_err(dev, "Output config failed\n");
+					return -EINVAL;
+				}
+			}
+
+			vxd_dec_alloc_bspp_resource(ctx, ctx->strcfgdata.vid_std);
+			ret = bspp_stream_create(&ctx->strcfgdata,
+						 &ctx->bspp_context,
+						 ctx->fw_sequ,
+						 ctx->fw_pps);
+			if (ret) {
+				dev_err(dev, "BSPP stream create failed %d\n", ret);
+				return ret;
+			}
+		} else if (q_data->fmt !=
+			find_format(f, IMG_DEC_FMT_TYPE_OUTPUT)) {
+			dev_err(dev, "Input format already set\n");
+			return -EBUSY;
+		}
+	} else {
+		fmt = find_format(f, IMG_DEC_FMT_TYPE_CAPTURE);
+		for (i = 0; i < pix_mp->num_planes; i++) {
+			pix_mp->plane_fmt[i].sizeimage =
+				get_sizeimage(ctx->width_orig,
+					ctx->height_orig, fmt, i);
+		}
+		q_data->fmt = fmt;
+		for (i = 0; i < q_data->fmt->num_planes; i++) {
+			q_data->size_image[i] =
+				get_sizeimage(get_stride(pix_mp->width, q_data->fmt),
+					      ctx->height, q_data->fmt, i);
+		}
+
+		ctx->str_opcfg.pixel_info.pixfmt = q_data->fmt->pixfmt;
+		ctx->str_opcfg.pixel_info.chroma_interleave = q_data->fmt->interleave;
+		ctx->str_opcfg.pixel_info.chroma_fmt = TRUE;
+		ctx->str_opcfg.pixel_info.chroma_fmt_idc = q_data->fmt->idc;
+
+		if (q_data->fmt->pixfmt == IMG_PIXFMT_420PL12YUV10_MSB ||
+		    q_data->fmt->pixfmt == IMG_PIXFMT_422PL12YUV10_MSB) {
+			ctx->str_opcfg.pixel_info.mem_pkg = PIXEL_BIT10_MSB_MP;
+			ctx->str_opcfg.pixel_info.bitdepth_y = 10;
+			ctx->str_opcfg.pixel_info.bitdepth_c = 10;
+		} else {
+			ctx->str_opcfg.pixel_info.mem_pkg = PIXEL_BIT8_MP;
+			ctx->str_opcfg.pixel_info.bitdepth_y = 8;
+			ctx->str_opcfg.pixel_info.bitdepth_c = 8;
+		}
+
+		ctx->str_opcfg.force_oold = FALSE;
+
+		ctx->pict_bufcfg.coded_width = pix_mp->width;
+		ctx->pict_bufcfg.coded_height = pix_mp->height;
+		ctx->pict_bufcfg.pixel_fmt = q_data->fmt->pixfmt;
+		for (i = 0; i < pix_mp->num_planes; i++) {
+			q_data->bytesperline[i] = get_stride(q_data->width, q_data->fmt);
+			if (q_data->bytesperline[i] <
+				pix_mp->plane_fmt[0].bytesperline)
+				q_data->bytesperline[i] =
+					ALIGN(pix_mp->plane_fmt[0].bytesperline, HW_ALIGN);
+			pix_mp->plane_fmt[0].bytesperline =
+				q_data->bytesperline[i];
+			ctx->pict_bufcfg.stride[i] = q_data->bytesperline[i];
+		}
+		for (j = i; j < IMG_MAX_NUM_PLANES; j++) {
+			if ((i - 1) < 0)
+				i++;
+			ctx->pict_bufcfg.stride[j] =
+				q_data->bytesperline[i - 1];
+		}
+		ctx->pict_bufcfg.stride_alignment = HW_ALIGN;
+		ctx->pict_bufcfg.byte_interleave = FALSE;
+		for (i = 0; i < pix_mp->num_planes; i++) {
+			unsigned int plane_size =
+				get_sizeimage(ctx->pict_bufcfg.stride[i],
+					      ctx->pict_bufcfg.coded_height,
+					      q_data->fmt, i);
+			ctx->pict_bufcfg.buf_size += ALIGN(plane_size, PAGE_SIZE);
+			ctx->pict_bufcfg.plane_size[i] = plane_size;
+		}
+		if (q_data->fmt->pixfmt == 86031 ||
+		    q_data->fmt->pixfmt == 81935) {
+			/* Handle the v4l2 multi-planar formats */
+			ctx->str_opcfg.pixel_info.num_planes = 3;
+			ctx->pict_bufcfg.packed = FALSE;
+			for (i = 0; i < pix_mp->num_planes; i++) {
+				ctx->pict_bufcfg.chroma_offset[i] =
+					ALIGN(pix_mp->plane_fmt[i].sizeimage, PAGE_SIZE);
+				ctx->pict_bufcfg.chroma_offset[i] +=
+					(i ? ctx->pict_bufcfg.chroma_offset[i - 1] : 0);
+			}
+		} else {
+			/* IMG Decoders support only multi-planar formats */
+			ctx->str_opcfg.pixel_info.num_planes = 2;
+			ctx->pict_bufcfg.packed = TRUE;
+			ctx->pict_bufcfg.chroma_offset[0] = 0;
+			ctx->pict_bufcfg.chroma_offset[1] = 0;
+		}
+
+		vxd_dec_submit_opconfig(ctx);
+	}
+
+	return ret;
+}
+
+static int vxd_dec_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
+{
+	if (sub->type != V4L2_EVENT_EOS)
+		return -EINVAL;
+
+	v4l2_event_subscribe(fh, sub, 0, NULL);
+	return 0;
+}
+
+static int vxd_dec_try_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
+{
+	if (cmd->cmd != V4L2_DEC_CMD_STOP)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int vxd_dec_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd)
+{
+	struct vxd_dec_ctx *ctx = file2ctx(file);
+
+	if (cmd->cmd != V4L2_DEC_CMD_STOP)
+		return -EINVAL;
+
+#ifdef DEBUG_DECODER_DRIVER
+	pr_info("%s CMD_STOP\n", __func__);
+#endif
+	/*
+	 * When stop command is received, notify device_run if it is
+	 * scheduled to run, or tell the decoder that eos has
+	 * happened.
+	 */
+	mutex_lock_nested(ctx->mutex, SUBCLASS_VXD_V4L2);
+	if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) {
+#ifdef DEBUG_DECODER_DRIVER
+		pr_info("V4L2 src bufs not empty, set a flag to notify device_run\n");
+#endif
+		ctx->stop_initiated = TRUE;
+		mutex_unlock(ctx->mutex);
+	} else {
+		if (ctx->num_decoding) {
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("buffers are still being decoded, so just set eos flag\n");
+#endif
+			ctx->eos = TRUE;
+			mutex_unlock(ctx->mutex);
+		} else {
+			mutex_unlock(ctx->mutex);
+#ifdef DEBUG_DECODER_DRIVER
+			pr_info("All buffers are decoded, so issue dummy stream end\n");
+#endif
+			vxd_return_resource((void *)ctx, VXD_CB_STR_END, 0, 0);
+		}
+	}
+
+	return 0;
+}
+
+static int vxd_g_selection(struct file *file, void *fh, struct v4l2_selection *s)
+{
+	struct vxd_dec_ctx *ctx = file2ctx(file);
+
+	if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	switch (s->target) {
+	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+	case V4L2_SEL_TGT_COMPOSE_PADDED:
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = ctx->width;
+		s->r.height = ctx->height;
+		break;
+	case V4L2_SEL_TGT_COMPOSE:
+	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+		s->r.left = 0;
+		s->r.top = 0;
+		s->r.width = ctx->width_orig;
+		s->r.height = ctx->height_orig;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops vxd_dec_ioctl_ops = {
+	.vidioc_querycap = vxd_dec_querycap,
+
+	.vidioc_enum_fmt_vid_cap = vxd_dec_enum_fmt,
+	.vidioc_g_fmt_vid_cap_mplane = vxd_dec_g_fmt,
+	.vidioc_try_fmt_vid_cap_mplane = vxd_dec_try_fmt,
+	.vidioc_s_fmt_vid_cap_mplane = vxd_dec_s_fmt,
+
+	.vidioc_enum_fmt_vid_out = vxd_dec_enum_fmt,
+	.vidioc_g_fmt_vid_out_mplane = vxd_dec_g_fmt,
+	.vidioc_try_fmt_vid_out_mplane = vxd_dec_try_fmt,
+	.vidioc_s_fmt_vid_out_mplane = vxd_dec_s_fmt,
+
+	.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+	.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+
+	.vidioc_streamon = v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+	.vidioc_log_status = v4l2_ctrl_log_status,
+	.vidioc_subscribe_event = vxd_dec_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+	.vidioc_try_decoder_cmd = vxd_dec_try_cmd,
+	.vidioc_decoder_cmd = vxd_dec_cmd,
+
+	.vidioc_g_selection = vxd_g_selection,
+};
+
+static const struct v4l2_file_operations vxd_dec_fops = {
+	.owner = THIS_MODULE,
+	.open = vxd_dec_open,
+	.release = vxd_dec_release,
+	.poll = v4l2_m2m_fop_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.mmap = v4l2_m2m_fop_mmap,
+};
+
+static void device_run(void *priv)
+{
+	struct vxd_dec_ctx *ctx = priv;
+	struct vxd_dev *vxd_dev = ctx->dev;
+	struct device *dev = vxd_dev->v4l2_dev.dev;
+	struct vb2_v4l2_buffer  *src_vb;
+	struct vb2_v4l2_buffer  *dst_vb;
+	struct vxd_buffer *src_vxdb;
+	struct vxd_buffer *dst_vxdb;
+	struct bspp_bitstr_seg *item = NULL, *next = NULL;
+	struct bspp_preparsed_data *preparsed_data;
+	unsigned int data_size;
+	int ret;
+	struct timespec64 time;
+	static int cnt;
+	int i;
+
+	mutex_lock(ctx->mutex2);
+	mutex_lock_nested(ctx->mutex, SUBCLASS_VXD_V4L2);
+	ctx->num_decoding++;
+
+	src_vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+	if (!src_vb) {
+		dev_err(dev, "Next src buffer is null\n");
+		mutex_unlock(ctx->mutex);
+		mutex_unlock(ctx->mutex2);
+		return;
+	}
+
+	dst_vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+	if (!dst_vb) {
+		dev_err(dev, "Next dst buffer is null\n");
+		mutex_unlock(ctx->mutex);
+		mutex_unlock(ctx->mutex2);
+		return;
+	}
+
+
+	dst_vb->vb2_buf.timestamp = src_vb->vb2_buf.timestamp;
+
+	src_vxdb = container_of(src_vb, struct vxd_buffer, buffer.vb);
+	dst_vxdb = container_of(dst_vb, struct vxd_buffer, buffer.vb);
+
+	preparsed_data = &dst_vxdb->preparsed_data;
+
+	data_size = vb2_get_plane_payload(&src_vxdb->buffer.vb.vb2_buf, 0);
+
+	ret = bspp_stream_submit_buffer(ctx->bspp_context,
+					&src_vxdb->bstr_info,
+					src_vxdb->buf_map_id,
+					data_size, NULL,
+					VDEC_BSTRELEMENT_UNSPECIFIED);
+	if (ret)
+		dev_err(dev, "bspp_stream_submit_buffer failed %d\n", ret);
+
+	if (ctx->stop_initiated &&
+			(v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) == 0))
+		ctx->eos = TRUE;
+
+	mutex_unlock(ctx->mutex);
+
+	ret = bspp_stream_preparse_buffers(ctx->bspp_context, NULL, 0, &ctx->seg_list,
+					   preparsed_data, ctx->eos);
+	if (ret)
+		dev_err(dev, "bspp_stream_preparse_buffers failed %d\n", ret);
+
+	ktime_get_real_ts64(&time);
+	vxd_dev->time_drv[cnt].start_time = timespec64_to_ns(&time);
+	vxd_dev->time_drv[cnt].id = dst_vxdb->buf_map_id;
+	cnt++;
+
+	if (cnt >= ARRAY_SIZE(vxd_dev->time_drv))
+		cnt = 0;
+
+	core_stream_fill_pictbuf(dst_vxdb->buf_map_id);
+
+	if (preparsed_data->new_sequence) {
+		src_vxdb->seq_unit.str_unit_type =
+			VDECDD_STRUNIT_SEQUENCE_START;
+		src_vxdb->seq_unit.str_unit_handle = ctx;
+		src_vxdb->seq_unit.err_flags = 0;
+		src_vxdb->seq_unit.dd_data = NULL;
+		src_vxdb->seq_unit.seq_hdr_info =
+			&preparsed_data->sequ_hdr_info;
+		src_vxdb->seq_unit.seq_hdr_id = 0;
+		src_vxdb->seq_unit.closed_gop = TRUE;
+		src_vxdb->seq_unit.eop = FALSE;
+		src_vxdb->seq_unit.pict_hdr_info = NULL;
+		src_vxdb->seq_unit.dd_pict_data = NULL;
+		src_vxdb->seq_unit.last_pict_in_seq = FALSE;
+		src_vxdb->seq_unit.str_unit_tag = NULL;
+		src_vxdb->seq_unit.decode = FALSE;
+		src_vxdb->seq_unit.features = 0;
+		core_stream_submit_unit(ctx->res_str_id, &src_vxdb->seq_unit);
+	}
+
+	src_vxdb->pic_unit.str_unit_type = VDECDD_STRUNIT_PICTURE_START;
+	src_vxdb->pic_unit.str_unit_handle = ctx;
+	src_vxdb->pic_unit.err_flags = 0;
+	/* Move the processed segments to the submission buffer */
+	for (i = 0; i < BSPP_MAX_PICTURES_PER_BUFFER; i++) {
+		item = lst_first(&preparsed_data->picture_data.pre_pict_seg_list[i]);
+		while (item) {
+			next = lst_next(item);
+			lst_remove(&preparsed_data->picture_data.pre_pict_seg_list[i], item);
+			lst_add(&src_vxdb->pic_unit.bstr_seg_list, item);
+			item = next;
+		}
+		/* Move the processed segments to the submission buffer */
+		item = lst_first(&preparsed_data->picture_data.pict_seg_list[i]);
+		while (item) {
+			next = lst_next(item);
+			lst_remove(&preparsed_data->picture_data.pict_seg_list[i], item);
+			lst_add(&src_vxdb->pic_unit.bstr_seg_list, item);
+			item = next;
+		}
+	}
+
+	src_vxdb->pic_unit.dd_data = NULL;
+	src_vxdb->pic_unit.seq_hdr_info = NULL;
+	src_vxdb->pic_unit.seq_hdr_id = 0;
+	if (preparsed_data->new_sequence)
+		src_vxdb->pic_unit.closed_gop = TRUE;
+	else
+		src_vxdb->pic_unit.closed_gop = FALSE;
+	src_vxdb->pic_unit.eop = TRUE;
+	src_vxdb->pic_unit.eos = ctx->eos;
+	src_vxdb->pic_unit.pict_hdr_info =
+		&preparsed_data->picture_data.pict_hdr_info;
+	src_vxdb->pic_unit.dd_pict_data = NULL;
+	src_vxdb->pic_unit.last_pict_in_seq = FALSE;
+	src_vxdb->pic_unit.str_unit_tag = NULL;
+	src_vxdb->pic_unit.decode = FALSE;
+	src_vxdb->pic_unit.features = 0;
+	core_stream_submit_unit(ctx->res_str_id, &src_vxdb->pic_unit);
+
+	src_vxdb->end_unit.str_unit_type = VDECDD_STRUNIT_PICTURE_END;
+	src_vxdb->end_unit.str_unit_handle = ctx;
+	src_vxdb->end_unit.err_flags = 0;
+	src_vxdb->end_unit.dd_data = NULL;
+	src_vxdb->end_unit.seq_hdr_info = NULL;
+	src_vxdb->end_unit.seq_hdr_id = 0;
+	src_vxdb->end_unit.closed_gop = FALSE;
+	src_vxdb->end_unit.eop = FALSE;
+	src_vxdb->end_unit.eos = ctx->eos;
+	src_vxdb->end_unit.pict_hdr_info = NULL;
+	src_vxdb->end_unit.dd_pict_data = NULL;
+	src_vxdb->end_unit.last_pict_in_seq = FALSE;
+	src_vxdb->end_unit.str_unit_tag = NULL;
+	src_vxdb->end_unit.decode = FALSE;
+	src_vxdb->end_unit.features = 0;
+	core_stream_submit_unit(ctx->res_str_id, &src_vxdb->end_unit);
+	mutex_unlock(ctx->mutex2);
+
+}
+
+static int job_ready(void *priv)
+{
+	struct vxd_dec_ctx *ctx = priv;
+
+	if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < 1 ||
+	    v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < 1 ||
+	    !ctx->core_streaming)
+		return 0;
+
+	return 1;
+}
+
+static void job_abort(void *priv)
+{
+	struct vxd_dec_ctx *ctx = priv;
+
+	/* Cancel the transaction at next callback */
+	ctx->aborting = 1;
+}
+
+static const struct v4l2_m2m_ops m2m_ops = {
+	.device_run = device_run,
+	.job_ready = job_ready,
+	.job_abort = job_abort,
+};
+
+static const struct of_device_id vxd_dec_of_match[] = {
+	{.compatible = "img,d5500-vxd"},
+	{ /* end */},
+};
+MODULE_DEVICE_TABLE(of, vxd_dec_of_match);
+
+static int vxd_dec_probe(struct platform_device *pdev)
+{
+	struct vxd_dev *vxd;
+	struct resource *res;
+	const struct of_device_id *of_dev_id;
+	int ret;
+	int module_irq;
+	struct video_device *vfd;
+
+	struct heap_config *heap_configs;
+	int num_heaps;
+	unsigned int i_heap_id;
+	/* Protect structure fields */
+	spinlock_t **lock;
+
+	of_dev_id = of_match_device(vxd_dec_of_match, &pdev->dev);
+	if (!of_dev_id) {
+		dev_err(&pdev->dev, "%s: Unable to match device\n", __func__);
+		return -ENODEV;
+	}
+
+	dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
+
+	vxd = devm_kzalloc(&pdev->dev, sizeof(*vxd), GFP_KERNEL);
+	if (!vxd)
+		return -ENOMEM;
+
+	vxd->dev = &pdev->dev;
+	vxd->plat_dev = pdev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	vxd->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR_VALUE((unsigned long)vxd->reg_base))
+		return (long)(vxd->reg_base);
+
+	module_irq = platform_get_irq(pdev, 0);
+	if (module_irq < 0)
+		return -ENXIO;
+	vxd->module_irq = module_irq;
+#ifdef ERROR_RECOVERY_SIMULATION
+	g_module_irq = module_irq;
+#endif
+
+	heap_configs = vxd_dec_heap_configs;
+	num_heaps = ARRAY_SIZE(vxd_dec_heap_configs);
+
+	vxd->mutex = kzalloc(sizeof(*vxd->mutex), GFP_KERNEL);
+	if (!vxd->mutex)
+		return -ENOMEM;
+
+	mutex_init(vxd->mutex);
+
+	vxd->mutex_queue = kzalloc(sizeof(*vxd->mutex_queue), GFP_KERNEL);
+	if (!vxd->mutex_queue)
+		return -ENOMEM;
+
+	mutex_init(vxd->mutex_queue);
+
+	platform_set_drvdata(pdev, vxd);
+
+	pm_runtime_enable(&pdev->dev);
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s: failed to enable clock, status = %d\n", __func__, ret);
+		goto exit;
+	}
+
+	/* Read HW properties */
+	ret = vxd_pvdec_get_props(vxd->dev, vxd->reg_base, &vxd->props);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: failed to fetch core properties!\n", __func__);
+		ret = -ENXIO;
+		goto out_put_sync;
+	}
+	vxd->mmu_config_addr_width = VXD_EXTRN_ADDR_WIDTH(vxd->props);
+#ifdef DEBUG_DECODER_DRIVER
+	dev_info(&pdev->dev, "hw:%u.%u.%u, num_pix: %d, num_ent: %d, mmu: %d, MTX RAM: %d\n",
+		 VXD_MAJ_REV(vxd->props),
+		 VXD_MIN_REV(vxd->props),
+		 VXD_MAINT_REV(vxd->props),
+		 VXD_NUM_PIX_PIPES(vxd->props),
+		 VXD_NUM_ENT_PIPES(vxd->props),
+		 VXD_EXTRN_ADDR_WIDTH(vxd->props),
+		 vxd->props.mtx_ram_size);
+#endif
+
+	INIT_LIST_HEAD(&vxd->msgs);
+	INIT_LIST_HEAD(&vxd->pend);
+
+	/* initialize memory manager */
+	ret = img_mem_init(&pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to initialize memory\n");
+		ret = -ENOMEM;
+		goto out_put_sync;
+	}
+	vxd->streams = kzalloc(sizeof(*vxd->streams), GFP_KERNEL);
+	if (!vxd->streams) {
+		ret = -ENOMEM;
+		goto out_init;
+	}
+
+	idr_init(vxd->streams);
+
+	ret = vxd_init(&pdev->dev, vxd, heap_configs, num_heaps);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: main component initialisation failed!\n", __func__);
+		goto out_idr_init;
+	}
+
+	/* initialize core */
+	i_heap_id = vxd_g_internal_heap_id();
+	if (i_heap_id < 0) {
+		dev_err(&pdev->dev, "%s: Invalid internal heap id", __func__);
+		goto out_vxd_init;
+	}
+	ret = core_initialise(vxd, i_heap_id, vxd_return_resource);
+	if (ret) {
+		dev_err(&pdev->dev, "%s: core initialization failed!", __func__);
+		goto out_vxd_init;
+	}
+
+	vxd->fw_refcnt = 0;
+	vxd->hw_on = 0;
+
+#ifdef DEBUG_DECODER_DRIVER
+	vxd->hw_pm_delay = 10000;
+	vxd->hw_dwr_period = 10000;
+#else
+	vxd->hw_pm_delay = 1000;
+	vxd->hw_dwr_period = 1000;
+#endif
+	ret = vxd_prepare_fw(vxd);
+	if (ret) {
+		dev_err(&pdev->dev, "%s fw acquire failed!", __func__);
+		goto out_core_init;
+	}
+
+	if (vxd->no_fw) {
+		dev_err(&pdev->dev, "%s fw acquire failed!", __func__);
+		goto out_core_init;
+	}
+
+	 lock = (spinlock_t **)&vxd->lock;
+	*lock = kzalloc(sizeof(spinlock_t), GFP_KERNEL);
+
+	if (!(*lock)) {
+		pr_err("Memory allocation failed for spin-lock\n");
+		ret = ENOMEM;
+		goto out_core_init;
+	}
+	spin_lock_init(*lock);
+
+	ret = v4l2_device_register(&pdev->dev, &vxd->v4l2_dev);
+	if (ret)
+		goto out_clean_fw;
+
+#ifdef ERROR_RECOVERY_SIMULATION
+	/*
+	 * create a sysfs entry here, to debug firmware error recovery.
+	 */
+	vxd_dec_kobject = kobject_create_and_add("vxd_decoder", kernel_kobj);
+	if (!vxd_dec_kobject) {
+		dev_err(&pdev->dev, "Failed to create kernel object\n");
+		goto out_clean_fw;
+	}
+
+	ret = sysfs_create_group(vxd_dec_kobject, &attr_group);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to create sysfs files\n");
+		kobject_put(vxd_dec_kobject);
+	}
+#endif
+
+	vfd = video_device_alloc();
+	if (!vfd) {
+		dev_err(&pdev->dev, "Failed to allocate video device\n");
+		ret = -ENOMEM;
+		goto out_v4l2_device;
+	}
+
+	snprintf(vfd->name, sizeof(vfd->name), "%s", IMG_VXD_DEC_MODULE_NAME);
+	vfd->fops = &vxd_dec_fops;
+	vfd->ioctl_ops = &vxd_dec_ioctl_ops;
+	vfd->minor = -1;
+	vfd->release = video_device_release;
+	vfd->vfl_dir = VFL_DIR_M2M;
+	vfd->v4l2_dev = &vxd->v4l2_dev;
+	vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+	vfd->lock = vxd->mutex;
+
+	vxd->vfd_dec = vfd;
+	video_set_drvdata(vfd, vxd);
+
+	ret = devm_request_threaded_irq(&pdev->dev, module_irq, (irq_handler_t)hard_isrcb,
+					(irq_handler_t)soft_thread_irq, IRQF_SHARED,
+					IMG_VXD_DEC_MODULE_NAME, pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request irq\n");
+		goto out_vid_dev;
+	}
+
+	vxd->m2m_dev = v4l2_m2m_init(&m2m_ops);
+	if (IS_ERR_VALUE((unsigned long)vxd->m2m_dev)) {
+		dev_err(&pdev->dev, "Failed to init mem2mem device\n");
+		ret = -EINVAL;
+		goto out_vid_dev;
+	}
+
+	ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register video device\n");
+		goto out_vid_reg;
+	}
+	v4l2_info(&vxd->v4l2_dev, "decoder registered as /dev/video%d\n", vfd->num);
+
+	return 0;
+
+out_vid_reg:
+	v4l2_m2m_release(vxd->m2m_dev);
+
+out_vid_dev:
+	video_device_release(vfd);
+
+out_v4l2_device:
+	v4l2_device_unregister(&vxd->v4l2_dev);
+
+out_clean_fw:
+	vxd_clean_fw_resources(vxd);
+
+out_core_init:
+	core_deinitialise();
+
+out_vxd_init:
+	vxd_deinit(vxd);
+
+out_idr_init:
+	idr_destroy(vxd->streams);
+	kfree(vxd->streams);
+
+out_init:
+	img_mem_exit();
+
+out_put_sync:
+	pm_runtime_put_sync(&pdev->dev);
+
+exit:
+	pm_runtime_disable(&pdev->dev);
+	mutex_destroy(vxd->mutex);
+	kfree(vxd->mutex);
+	vxd->mutex = NULL;
+
+	return ret;
+}
+
+static int vxd_dec_remove(struct platform_device *pdev)
+{
+	struct vxd_dev *vxd = platform_get_drvdata(pdev);
+
+	core_deinitialise();
+
+	vxd_clean_fw_resources(vxd);
+	vxd_deinit(vxd);
+	idr_destroy(vxd->streams);
+	kfree(vxd->streams);
+	get_delayed_work_buff(&vxd->dwork, TRUE);
+	kfree(&vxd->lock);
+	img_mem_exit();
+
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+	kfree(vxd->dwork);
+	mutex_destroy(vxd->mutex);
+	mutex_destroy(vxd->mutex_queue);
+	kfree(vxd->mutex);
+	kfree(vxd->mutex_queue);
+	vxd->mutex = NULL;
+	vxd->mutex_queue = NULL;
+
+	video_unregister_device(vxd->vfd_dec);
+	v4l2_m2m_release(vxd->m2m_dev);
+	v4l2_device_unregister(&vxd->v4l2_dev);
+
+	return 0;
+}
+
+static int __maybe_unused vxd_dec_suspend(struct device *dev)
+{
+	int ret = 0;
+
+	ret = vxd_suspend_dev(dev);
+	if (ret)
+		dev_err(dev, "failed to suspend core hw!\n");
+
+	return ret;
+}
+
+static int __maybe_unused vxd_dec_resume(struct device *dev)
+{
+	int ret = 0;
+
+	ret = vxd_resume_dev(dev);
+	if (ret)
+		dev_err(dev, "failed to resume core hw!\n");
+
+	return ret;
+}
+
+static UNIVERSAL_DEV_PM_OPS(vxd_dec_pm_ops,
+	vxd_dec_suspend, vxd_dec_resume, NULL);
+
+static struct platform_driver vxd_dec_driver = {
+	.probe = vxd_dec_probe,
+	.remove = vxd_dec_remove,
+	.driver = {
+		.name = "img_dec",
+		.pm = &vxd_dec_pm_ops,
+		.of_match_table = vxd_dec_of_match,
+	},
+};
+module_platform_driver(vxd_dec_driver);
+
+MODULE_AUTHOR("Prashanth Kumar Amai <prashanth.ka@pathpartnertech.com> Sidraya Jayagond <sidraya.bj@pathpartnertech.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("IMG D5520 video decoder driver");
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/fw_binaries/ALL_CODECS_FW_ALL_pipes_2_contexts_8_hwconfig_1_bin.c b/drivers/media/platform/img/vxe-vxd/encoder/fw_binaries/ALL_CODECS_FW_ALL_pipes_2_contexts_8_hwconfig_1_bin.c
--- a/drivers/media/platform/img/vxe-vxd/encoder/fw_binaries/ALL_CODECS_FW_ALL_pipes_2_contexts_8_hwconfig_1_bin.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/fw_binaries/ALL_CODECS_FW_ALL_pipes_2_contexts_8_hwconfig_1_bin.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,29013 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Encoder FW binary file
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+/* note that order of defines has to match the structure declaration!
+ */
+
+unsigned char *all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_define_names_array[] = {
+	"TOPAZHP_NUM_PIPES",
+	"TOPAZHP_MAX_BU_SUPPORT",
+	"MAX_REF_B_LEVELS_FW",
+	"SEI_INSERTION",
+	"TOPAZHP_MAX_NUM_STREAMS",
+};
+
+unsigned int all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_define_values_array[] = {
+	2,
+	(TOPAZHP_MAX_BU_SUPPORT_HD),
+	0,
+	1,
+	8,
+};
+
+unsigned int all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_text[] = {
+	0x9040c001,
+	0xc80993fe,
+	0xc0000e42,
+	0xc8290e00,
+	0xcc3e8426,
+	0xc8298420,
+	0xceea8622,
+	0x9e838660,
+	0xc8099e43,
+	0xcdd40d46,
+	0xc8090d40,
+	0xcdd60946,
+	0xc8090900,
+	0xc00a0e42,
+	0xc8090e40,
+	0xc00e87c2,
+	0x9c1887c0,
+	0x0c020802,
+	0x09820d82,
+	0x09020d02,
+	0x08820c82,
+	0x9320fffe,
+	0xa401c838,
+	0x0dc6c809,
+	0x0d80cdd4,
+	0x0e42c809,
+	0x0c66b080,
+	0x0882a992,
+	0x9ff3a48d,
+	0x93e0ffff,
+	0x80819d13,
+	0xa205f839,
+	0x03070707,
+	0x9e970685,
+	0xc8090383,
+	0xcdd60ac6,
+	0xc8090aa0,
+	0xcdd61ac4,
+	0x060f1a80,
+	0x07fac101,
+	0x018d058d,
+	0x9c62008f,
+	0x9320ffff,
+	0xc101060b,
+	0x9c6206da,
+	0x9380ffff,
+	0x018d058d,
+	0x460cb700,
+	0x4594b780,
+	0xa6059c01,
+	0xc8090687,
+	0xcdd60ac6,
+	0xc8090aa0,
+	0xcdd61ac4,
+	0x060b1a80,
+	0x06dac101,
+	0xffff9c62,
+	0xf9f89380,
+	0xf9f8aa9d,
+	0x9c22aa1d,
+	0x420cb700,
+	0xc000587c,
+	0xe0003800,
+	0xc0003800,
+	0x9c22901a,
+	0x9c8fc127,
+	0x080a9c22,
+	0x9c81c017,
+	0x9c80c071,
+	0x9c80c017,
+	0x0d849c22,
+	0x9e5a5db0,
+	0x4018b960,
+	0x0900c021,
+	0x0940c00e,
+	0xaa45f031,
+	0xf0009dad,
+	0x0910a261,
+	0x9341ffff,
+	0xc3fe9e5c,
+	0xc02129c0,
+	0xc0010a00,
+	0xc00e3988,
+	0x9dcd0a30,
+	0xa1e1f000,
+	0xc0219c22,
+	0xd1100d80,
+	0x9d3d05b7,
+	0x2244aa61,
+	0xffff7115,
+	0x9c229384,
+	0xd011a605,
+	0xc3fe0eb2,
+	0xc28029c0,
+	0x020b5ab0,
+	0x0a00c021,
+	0x398cc001,
+	0xc00e0685,
+	0x9dcd0a30,
+	0xa1e1f000,
+	0xc00e9eab,
+	0x0d020992,
+	0x0902cff0,
+	0x0a80c021,
+	0x9bdbfff4,
+	0x0ac0c00e,
+	0x4018b960,
+	0xaa619d5d,
+	0xa225f231,
+	0xffff0a90,
+	0xb79f9361,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xfffd9c22,
+	0xf0129040,
+	0x9e582d36,
+	0xc0009e5a,
+	0xc18093a4,
+	0x9e515a0b,
+	0xd2247500,
+	0x9e825988,
+	0x9c83c810,
+	0x0106c101,
+	0x4418b313,
+	0x9080c000,
+	0xa0c5f031,
+	0x93c1ffff,
+	0x11b6c101,
+	0x90c0c000,
+	0xa146d029,
+	0x9120c000,
+	0x9e540d02,
+	0xb33474c0,
+	0xc8104436,
+	0xffff9c83,
+	0x9c2292a1,
+	0xa285f839,
+	0xc00272d7,
+	0x70d79022,
+	0xc0009e59,
+	0x0a8690a6,
+	0x9100c000,
+	0xd0101d04,
+	0xc10104b4,
+	0x0aff01b4,
+	0xc0017c46,
+	0xf0139124,
+	0xc0012936,
+	0xd12290a4,
+	0x9e885e0b,
+	0x5808c200,
+	0x9e99610b,
+	0x00947500,
+	0xc81001b4,
+	0xc2809c83,
+	0xb3235908,
+	0xc0004c18,
+	0x9e9590e0,
+	0xaa29e059,
+	0xa209e059,
+	0x9361ffff,
+	0x1520c101,
+	0x9100c000,
+	0xa966c059,
+	0xa126c059,
+	0x9100c000,
+	0x0a029e52,
+	0x7088d012,
+	0x9c83c810,
+	0x9281ffff,
+	0xf9f89e58,
+	0x9c22aa9d,
+	0x59300904,
+	0x9d299da9,
+	0x9e919e90,
+	0x76c00005,
+	0x8700c021,
+	0x0da2c020,
+	0x8500c021,
+	0x0800c021,
+	0x0c00c021,
+	0x0c80c021,
+	0x1db0d021,
+	0x08820d08,
+	0x8730c00e,
+	0x8540c00e,
+	0x0850c00e,
+	0x0c60c00e,
+	0x0cf0c00e,
+	0x92a0c001,
+	0xaa41d9d0,
+	0xa95dd990,
+	0x5a40c200,
+	0x9e2e3244,
+	0xa261f000,
+	0xaa49d9d0,
+	0xa945d9d0,
+	0x5a40c200,
+	0x9d8d3244,
+	0xa261f000,
+	0xaa51d9d0,
+	0xa94dd9d0,
+	0x5a40c200,
+	0x9d8e3244,
+	0xa261f000,
+	0xaa59d9d0,
+	0xa955d9d0,
+	0x5a40c200,
+	0x9d9e3244,
+	0xa261f000,
+	0x5e10d1a2,
+	0xc3fe08a0,
+	0xc0012a40,
+	0x83853a08,
+	0xa261f000,
+	0x70460d84,
+	0xfffe0d40,
+	0x9c229166,
+	0x8420a61d,
+	0x0b820307,
+	0xc001a19a,
+	0xf04892a0,
+	0xa91aaac6,
+	0x9e6b7740,
+	0xc001672b,
+	0xf0489162,
+	0x05d6a9ce,
+	0xc3b41d84,
+	0xc1019924,
+	0xf208628b,
+	0x018ba34a,
+	0xc3b4058d,
+	0x628b991c,
+	0x6979d031,
+	0x16ebd110,
+	0xa041f208,
+	0xa2c5f208,
+	0x430cb780,
+	0x0679d110,
+	0xaa09f248,
+	0xf2086009,
+	0xb780a041,
+	0x0128430c,
+	0xa945f008,
+	0x000a6005,
+	0xa049f208,
+	0x0b300b84,
+	0x430cb780,
+	0x5b90d3a4,
+	0x0579d110,
+	0xaa15f288,
+	0xfffe71c8,
+	0xb79f9086,
+	0xb7bf7dee,
+	0xb7df7e6e,
+	0xb7ff7eee,
+	0xc0027f6e,
+	0x9c228c20,
+	0xb7a0a60d,
+	0x9e5e430c,
+	0xf2489e9e,
+	0xf248a9ae,
+	0xd120aaa5,
+	0x018b01d7,
+	0xc3b41d84,
+	0x9e8598da,
+	0xc101636b,
+	0x9eb366db,
+	0xf2109e6b,
+	0xc3b4a349,
+	0xd13298d0,
+	0xf210628b,
+	0xc101a041,
+	0xf210136a,
+	0xb780a345,
+	0xf248430c,
+	0x6009aa09,
+	0xa041f210,
+	0x430cb780,
+	0xaa05f208,
+	0x000c6009,
+	0xa049f210,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0x9c228c60,
+	0x5db00d84,
+	0xc0219e5c,
+	0xc0100a00,
+	0x9dcd0a00,
+	0xa162f000,
+	0x592809bc,
+	0xcff05990,
+	0xc00f2980,
+	0xc021297c,
+	0x31260d80,
+	0x0d80c00e,
+	0xf0009dbe,
+	0x9c22a161,
+	0x5db00d84,
+	0x0992c00e,
+	0xcff00d02,
+	0xfff20902,
+	0xaa1d91c0,
+	0x09bc0405,
+	0xd0117500,
+	0xd0120e32,
+	0xd0a2299e,
+	0xc0015cc0,
+	0xd2249004,
+	0x9e545930,
+	0x0a00c021,
+	0x0a00c010,
+	0xf0009dcd,
+	0xc100a062,
+	0x9e525a18,
+	0x2a00cffc,
+	0x0900c021,
+	0x0930c010,
+	0xf0009dad,
+	0xc180a261,
+	0xcff05a10,
+	0xc0112a00,
+	0xc0003a00,
+	0xd22492e0,
+	0x9e545930,
+	0x0a00c021,
+	0x0a10c010,
+	0xf0009dcd,
+	0x5958a062,
+	0x9dcd0a20,
+	0xa161f000,
+	0x5a10c180,
+	0x2a00cff0,
+	0x3a00c031,
+	0xc00f9e5a,
+	0x324428fc,
+	0x0d00c021,
+	0xc00e3242,
+	0x9dae0d00,
+	0xa261f000,
+	0xa61d9c22,
+	0x8400c00a,
+	0x430cb7c0,
+	0x0802c004,
+	0xb55fa011,
+	0x74807dec,
+	0xa945f208,
+	0x7decb79f,
+	0x7d74b57f,
+	0x5b99c100,
+	0x4422b340,
+	0x5a18c380,
+	0xa0117104,
+	0x7c74b55f,
+	0x7cecb53f,
+	0xf248000d,
+	0xf248a94d,
+	0x9e4dab46,
+	0xb7809e9f,
+	0xb7a040cd,
+	0xd0125eb4,
+	0xc006136c,
+	0xd0209244,
+	0x9e7311a8,
+	0x9811c3b4,
+	0x701b9e6c,
+	0x4434b304,
+	0xb347711f,
+	0xf2084454,
+	0xf208a9c1,
+	0x657daa29,
+	0xb740008d,
+	0xd0f2572b,
+	0xd0200eae,
+	0xb77f0138,
+	0x74887468,
+	0x2e81cffc,
+	0x293ed3f1,
+	0x9172c000,
+	0x9e93a892,
+	0x0a029e6b,
+	0x0892010f,
+	0xc000a21d,
+	0xa8929120,
+	0x9e6b0a02,
+	0xa21d9e93,
+	0x0896010f,
+	0x9b57fff4,
+	0x7468b79f,
+	0x29ced3f2,
+	0x9b48fff4,
+	0xaa25f208,
+	0x0659d110,
+	0xa225f208,
+	0xa94df248,
+	0xc0007104,
+	0x0a029186,
+	0xa225f208,
+	0xa949f248,
+	0xaa21f208,
+	0xf2080244,
+	0xb740a221,
+	0xf208430c,
+	0xf208aa21,
+	0xf008a926,
+	0x6129a945,
+	0x0124c101,
+	0xa129f208,
+	0x4314b700,
+	0x574ab780,
+	0xc0007506,
+	0x750a90a2,
+	0x9144c000,
+	0xaa11a911,
+	0x0a08090c,
+	0x00899e91,
+	0x9100c000,
+	0xa911aa11,
+	0x090c0a08,
+	0x00859ea1,
+	0x7decb71f,
+	0x5dccb780,
+	0x7c6cb77f,
+	0xa8110100,
+	0x6679d131,
+	0xcffe9e83,
+	0xcffe28fc,
+	0xd0202cfc,
+	0xd0200334,
+	0xd0101110,
+	0xda101516,
+	0x5d18a241,
+	0xcffe5930,
+	0xc2002a7c,
+	0xc1015a48,
+	0xd1100524,
+	0xb79f0729,
+	0x71887cec,
+	0x9322c001,
+	0x8c80f292,
+	0x8c84f271,
+	0x0c029e68,
+	0x91a0c000,
+	0x7c6ab77f,
+	0xa1b1da31,
+	0x7eb2b57f,
+	0x7f32b55f,
+	0xa231da29,
+	0x9e44a111,
+	0xa9c1da10,
+	0xcffea911,
+	0xd0202a7c,
+	0x09100142,
+	0x0242c101,
+	0xcffe7217,
+	0xcffe2a7c,
+	0xcffe2d7c,
+	0x0c10297c,
+	0xc0200820,
+	0xc0103a00,
+	0xd0123d00,
+	0xfffe19a6,
+	0xb77f9366,
+	0xb75f7df4,
+	0xe2927d6c,
+	0xfff48d00,
+	0x000d99b3,
+	0x746eb79f,
+	0x74eeb7bf,
+	0x756eb7df,
+	0x75eeb7ff,
+	0x8c00c00c,
+	0xa61d9c22,
+	0x8400c00c,
+	0x430cb7c0,
+	0x40d5b700,
+	0x000d9e4f,
+	0x5732b720,
+	0xaa4df248,
+	0xaac5f248,
+	0x76400f86,
+	0x79f4b57f,
+	0x11c1d120,
+	0xd002040f,
+	0x9e9d0c72,
+	0xb51f018b,
+	0xb55f7874,
+	0xb55f7d6c,
+	0xb53f78f4,
+	0xb51f796c,
+	0xc3947b74,
+	0x9eb09b14,
+	0xa946f208,
+	0x5eccb780,
+	0xa941f208,
+	0x7d6cb77f,
+	0xb3047008,
+	0x711b4434,
+	0x4454b345,
+	0x9e695d19,
+	0x7bf4b5bf,
+	0xaa69f208,
+	0xb71f629b,
+	0xd0326670,
+	0x74c00ade,
+	0xb55f0128,
+	0xc0047af4,
+	0xb3300802,
+	0x9e924422,
+	0x7a6cb55f,
+	0xb75f2ec1,
+	0xc00e7aec,
+	0x9e6b2c7c,
+	0x9e799e81,
+	0x05810a02,
+	0xa015a21d,
+	0xfff4a012,
+	0xa9929a54,
+	0x5a8dc280,
+	0x9a46fff4,
+	0xaa49f248,
+	0xc0017510,
+	0xf2089114,
+	0xf248aa61,
+	0x0a20a951,
+	0xc0017104,
+	0xa8159008,
+	0x4314b740,
+	0x7a74b71f,
+	0xf010020a,
+	0x9ea6a946,
+	0x7aecb75f,
+	0xcffea992,
+	0x9e792f7c,
+	0x5d0c9e6b,
+	0x05200a02,
+	0xa21d048d,
+	0x9a2bfff4,
+	0xfff4a992,
+	0xb5df9a1f,
+	0xc0007df4,
+	0xab1690a0,
+	0x7df4b5df,
+	0xaa65f208,
+	0x0659d110,
+	0xa265f208,
+	0xa94df248,
+	0xc0007104,
+	0x0a029186,
+	0xa265f208,
+	0xa949f248,
+	0xaa61f208,
+	0xf2080244,
+	0xb780a261,
+	0xf208430c,
+	0xf208a961,
+	0xf208a966,
+	0x6245aa05,
+	0x0244c101,
+	0xa269f208,
+	0x4314b7e0,
+	0xa971f210,
+	0x5819d124,
+	0xb51f9e44,
+	0xc2007cf4,
+	0x71045a18,
+	0x90e2c000,
+	0xb53f0882,
+	0xc00a7c6c,
+	0xf2509140,
+	0xb77faa75,
+	0xd0327bec,
+	0xd1100af8,
+	0x6239056b,
+	0xa92af210,
+	0xa9edf210,
+	0xd0319e96,
+	0xb75f0b4e,
+	0xa9927cec,
+	0x7b6cb73f,
+	0xd1202b41,
+	0xcffe0135,
+	0x0a062f7c,
+	0x048d018d,
+	0xfff4a21d,
+	0xf21099cc,
+	0x0268aa25,
+	0xa225f210,
+	0xa97df250,
+	0xc0007104,
+	0x0a029186,
+	0xa225f210,
+	0xa979f250,
+	0xaa21f210,
+	0xf2100244,
+	0xb720a221,
+	0xf210430c,
+	0xf210aa21,
+	0xb740a926,
+	0x6129422d,
+	0x0124c101,
+	0xa129f210,
+	0x572bb780,
+	0xc0007502,
+	0xd0119144,
+	0x040d0e62,
+	0xcffe9ea1,
+	0xc0022cfc,
+	0x750491a0,
+	0x9144c000,
+	0x0e62d011,
+	0x9ea0048d,
+	0x2c7ccffe,
+	0x9040c002,
+	0x0af0d072,
+	0x5a0dc300,
+	0x0669d110,
+	0x432db7a0,
+	0xa929f210,
+	0x0389a992,
+	0xcffe02d4,
+	0xfff42bfc,
+	0xb75f9979,
+	0xb73f7cec,
+	0xa9927b6c,
+	0x9eb99eaa,
+	0x018d8506,
+	0xfff4a11f,
+	0xf2109976,
+	0x0268aa25,
+	0xa225f210,
+	0xa97df250,
+	0xc0007104,
+	0x0a029186,
+	0xa225f210,
+	0xa979f250,
+	0xaa21f210,
+	0xf2100244,
+	0xb740a221,
+	0xf210430c,
+	0xf210aa21,
+	0xf008a926,
+	0x9eb9a95d,
+	0x6129040d,
+	0x0124c101,
+	0xa129f210,
+	0x7d6cb71f,
+	0x78ecb75f,
+	0x430cb720,
+	0x02a80200,
+	0x5dadb720,
+	0x7becb79f,
+	0x7df4b77f,
+	0xd01060c3,
+	0xda081516,
+	0x0203a0a1,
+	0xcffea815,
+	0xc2002a7c,
+	0x9e595a48,
+	0x12401506,
+	0x797cb75f,
+	0x02425d18,
+	0x0244c101,
+	0x02445930,
+	0xb59f7135,
+	0xc0007c6c,
+	0xb71f9182,
+	0xb740706a,
+	0x0d824304,
+	0x287ccffe,
+	0xc0029d8d,
+	0xa9929020,
+	0x9914fff4,
+	0x9320c003,
+	0x7d6ab75f,
+	0x0d34d012,
+	0x0624d010,
+	0xa121da10,
+	0xa041da08,
+	0xa949f040,
+	0xcffe9d4d,
+	0xe31328fc,
+	0x74908d00,
+	0xf010a095,
+	0xc0008026,
+	0xb71f9254,
+	0xd0127b6a,
+	0xda080d38,
+	0xda10a001,
+	0xcffea1c1,
+	0xd01129fc,
+	0xcffe0a32,
+	0xb59f2a7c,
+	0xd0107dec,
+	0xd0110524,
+	0x9d2d0e22,
+	0xe3130248,
+	0xe0108d00,
+	0x9d4d8126,
+	0xa3c1d808,
+	0x8026f010,
+	0x0da4d012,
+	0xa382da08,
+	0x0536d010,
+	0x0e32d011,
+	0xe3139d2d,
+	0x02488d00,
+	0x7decb75f,
+	0x80a6f020,
+	0xd0119d4d,
+	0x09040e36,
+	0xf0100248,
+	0x01858126,
+	0xda089d4d,
+	0xd010a922,
+	0xd0100607,
+	0xa8150517,
+	0x9e47a895,
+	0x9ea00783,
+	0x72c49e91,
+	0xf0200804,
+	0x08888126,
+	0x3b80c010,
+	0x3f80c020,
+	0x2c7ccffe,
+	0x2cfccffe,
+	0x9306fffc,
+	0xfff4a992,
+	0xb77f98a5,
+	0xda087d74,
+	0xb75fa9a1,
+	0xe31279ec,
+	0xffd48d00,
+	0xb71f9b9d,
+	0xb79f7c6c,
+	0xb7bf726e,
+	0xb7df72ee,
+	0xb7ff736e,
+	0xc00e73ee,
+	0x9c228c00,
+	0xa6059c22,
+	0x4c8cb7a0,
+	0x6da2c146,
+	0x06bbd110,
+	0x008b099a,
+	0x6031b76d,
+	0xc3940d84,
+	0x008b9961,
+	0x60a9b78d,
+	0x287cc00e,
+	0x08027100,
+	0x0802d001,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0xb7409e5c,
+	0xc1464c8c,
+	0x02446a22,
+	0x0902c021,
+	0x430cb580,
+	0x4490b560,
+	0x0920c030,
+	0xaa619d2d,
+	0xc0015dc0,
+	0x9e5b2dbc,
+	0x2a42cfff,
+	0x9dad3246,
+	0xa261f000,
+	0xb7209c22,
+	0x9e58430c,
+	0x4829b78a,
+	0x71172208,
+	0x90c4c000,
+	0x48a9b78a,
+	0x9c222008,
+	0x4588b780,
+	0x9c222008,
+	0xb720a60d,
+	0x0b06430c,
+	0x4731b7aa,
+	0x46a9b7aa,
+	0x90e0c000,
+	0x0a52d011,
+	0xc00e0289,
+	0xd2242afc,
+	0x715b51d4,
+	0x2dfcc00e,
+	0x90e8c000,
+	0x9bd9fff4,
+	0xffff7400,
+	0x000b9224,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0x9c228c60,
+	0x430cb720,
+	0x4cadb782,
+	0x5b2db743,
+	0xb5823244,
+	0xb7204cad,
+	0xb782430c,
+	0xc0104cad,
+	0xb5822a04,
+	0xb7204cad,
+	0xb782430c,
+	0xc0204cad,
+	0xb3407d00,
+	0x3a0448a2,
+	0x4cadb582,
+	0x0d849c22,
+	0x9e5c5db0,
+	0x0a00c021,
+	0x0a00c010,
+	0xf0009dcd,
+	0x09bca162,
+	0x59285990,
+	0x2980cff0,
+	0x297cc00f,
+	0x3980c011,
+	0x0d80c021,
+	0xc00e31b4,
+	0x9dbe0d80,
+	0xa1e1f000,
+	0xa61d9c22,
+	0x8400c002,
+	0x0abed031,
+	0x2ac19e9f,
+	0xa119a192,
+	0xc001a116,
+	0xc1fc9300,
+	0xc0fc7562,
+	0xb3560f02,
+	0xa9164446,
+	0x9e73a992,
+	0xfff40902,
+	0xa9929bce,
+	0x068d0b82,
+	0x9bcaffd4,
+	0x010fab19,
+	0x92e0c000,
+	0xc0007dde,
+	0xa9929144,
+	0x8d00e092,
+	0xffd4018f,
+	0xe0919a1d,
+	0x77c08d00,
+	0xc0000b84,
+	0xd02990e2,
+	0x1f84aa45,
+	0xa241d208,
+	0x1e840b04,
+	0xffff777f,
+	0xa91a9124,
+	0x12dcc101,
+	0xa11a052c,
+	0x052ca916,
+	0x7540a116,
+	0x9124fffe,
+	0x7c6eb79f,
+	0x7ceeb7bf,
+	0x7d6eb7df,
+	0x7deeb7ff,
+	0x8c00c004,
+	0xa61d9c22,
+	0x8400c002,
+	0x9e9f9e5c,
+	0x5a30c200,
+	0x0a00c021,
+	0xc110a19a,
+	0x09820a30,
+	0xf0009dcd,
+	0xd032a1e1,
+	0x2ec10efe,
+	0xa115a112,
+	0x9180c002,
+	0x7762c1fc,
+	0x0f02c0fc,
+	0x4846b356,
+	0x9e760d02,
+	0x7df4b55f,
+	0x7d74b55f,
+	0x7cf4b55f,
+	0x7c74b55f,
+	0xe0920b82,
+	0x77c08d80,
+	0x0534d010,
+	0x9162c000,
+	0x1f84a991,
+	0xaa65d029,
+	0xd008a191,
+	0xc000a241,
+	0xd0089080,
+	0x0b84a3c2,
+	0x2afef031,
+	0xc0000d04,
+	0xa99a9244,
+	0x8d00e092,
+	0x19f0d051,
+	0x9987ffd4,
+	0xb5bf9eaa,
+	0xb5bf7dec,
+	0xb5bf7d6c,
+	0xb5bf7cec,
+	0xe0007c6c,
+	0xfffe1b04,
+	0xa91692c4,
+	0x9e73a99a,
+	0xffd4010d,
+	0xa99a9b23,
+	0xffd416dc,
+	0xa9969b39,
+	0xa19605bc,
+	0xfffd7740,
+	0xb79f92a4,
+	0xb7bf7c6e,
+	0xb7df7cee,
+	0xb7ff7d6e,
+	0xc0047dee,
+	0x9c228c00,
+	0x430cb720,
+	0x0992c144,
+	0x5badb743,
+	0x6c31b76d,
+	0xfffc9e8a,
+	0xf8399100,
+	0x9e90a285,
+	0xaa4df008,
+	0x0caed091,
+	0xa949f008,
+	0x5815c080,
+	0x0244c101,
+	0x76400120,
+	0x41ccb580,
+	0x414cb540,
+	0x9202c000,
+	0x40ccb780,
+	0x404cb740,
+	0x4254b740,
+	0x0a061128,
+	0x5208c200,
+	0x35229ea1,
+	0x4254b540,
+	0x5e30d1a2,
+	0x08fec00f,
+	0xcff19ea3,
+	0xc0210d02,
+	0xc0100d80,
+	0xc1409c83,
+	0xc00e0de0,
+	0xcff008fc,
+	0xc0000d00,
+	0xf0299200,
+	0x9e55aa65,
+	0x2242214a,
+	0xc2005921,
+	0x32445a20,
+	0x4006ba24,
+	0xf0009dbe,
+	0xffffa261,
+	0xb7809241,
+	0x0a04404c,
+	0x404cb580,
+	0xaa9df9f8,
+	0xa6859c22,
+	0x87029e91,
+	0x85220685,
+	0x0b7ec00e,
+	0x882bf210,
+	0xc2007640,
+	0xc0025153,
+	0xf0089182,
+	0x9e69aa61,
+	0x2a1ce000,
+	0xc28022a2,
+	0xb4235920,
+	0xf0084442,
+	0xd010aa61,
+	0x2a1ca962,
+	0x8821f310,
+	0x1242c101,
+	0x400aba0c,
+	0x52411003,
+	0x5921c200,
+	0xc00e9e95,
+	0xd0312a7c,
+	0xc2000910,
+	0x3454520b,
+	0x2aced3f2,
+	0x92eac000,
+	0x5224c200,
+	0x32429e51,
+	0xa261d010,
+	0xa961f008,
+	0x2a2ed011,
+	0x0619d110,
+	0xd110750e,
+	0xd0090615,
+	0xf0080db2,
+	0xc000a261,
+	0xd0109240,
+	0xf008a062,
+	0xd110aa61,
+	0x9e810619,
+	0xf0080242,
+	0xcffea261,
+	0xd0322cfc,
+	0xfffda164,
+	0x9e589220,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0x9c228c40,
+	0x9e58a60d,
+	0x9e569e9e,
+	0x709b0ee2,
+	0x923cc000,
+	0x9eb39e6d,
+	0x2afccffe,
+	0x112a5575,
+	0x9e739e83,
+	0x297ccffe,
+	0x2d7cc00e,
+	0x9b8dfff4,
+	0x1ea0010b,
+	0xffff7771,
+	0xb79f9184,
+	0xb7bf7eee,
+	0xb7df7f6e,
+	0x8c607fee,
+	0xa60d9c22,
+	0x9e589e56,
+	0x09069e9e,
+	0xc0000d02,
+	0x13649080,
+	0xd0110124,
+	0x710c1a22,
+	0x2eaed3f2,
+	0xffff0d04,
+	0x9e6d9306,
+	0x9080c000,
+	0x9b69fff4,
+	0x0a52d011,
+	0x9e837510,
+	0x0d029e73,
+	0x1aa00922,
+	0x92d2ffff,
+	0x294ed3f1,
+	0xfff40d04,
+	0xc0009b5a,
+	0xd3f291e0,
+	0x9e6c2ace,
+	0x52d1c200,
+	0x295ed3f2,
+	0x9b4ffff4,
+	0xc2009e6c,
+	0x136a52b0,
+	0xd0317750,
+	0x9e831e50,
+	0x09229e73,
+	0x91b2ffff,
+	0x296ed3f2,
+	0xb79f9e6a,
+	0xb7bf7eee,
+	0xb7df7f6e,
+	0x8c607fee,
+	0x92e0fff9,
+	0x1d20f011,
+	0xd01d9e9a,
+	0xd00d0224,
+	0xc0001a42,
+	0x1205909a,
+	0x9e531244,
+	0xfffd9ea2,
+	0x02079140,
+	0xa1c1d010,
+	0x9ea29e53,
+	0xfff60c82,
+	0xa6059240,
+	0x02870d0a,
+	0x9b9dfff4,
+	0x430cb720,
+	0x7ea9b785,
+	0xc0007500,
+	0x02039122,
+	0x0a00c098,
+	0xaa01d208,
+	0x3a040248,
+	0x9ea29e83,
+	0xb79f018b,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0x90a0fffc,
+	0xb720a605,
+	0xf011430c,
+	0xc0020ea0,
+	0xb7450a02,
+	0xb3547ea9,
+	0x02894424,
+	0x9e9d7480,
+	0x90a2c000,
+	0xba2c0248,
+	0x75404000,
+	0x9116c000,
+	0x0d02120b,
+	0x4000ba2c,
+	0x9060c000,
+	0xfff40d06,
+	0x9e839b66,
+	0xd0129e6b,
+	0xb79f1952,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0x9360fffa,
+	0x8460a60d,
+	0x8c88e051,
+	0xa2190a02,
+	0xa211a215,
+	0x7d6cb59f,
+	0x402db580,
+	0xa9e1f008,
+	0x07059e5e,
+	0xc004198c,
+	0xd01274c4,
+	0xc0020a92,
+	0xd1a691b2,
+	0x8520590c,
+	0x8044e050,
+	0x9120c002,
+	0x91c0c002,
+	0x9360c002,
+	0x9140c003,
+	0x91e0c003,
+	0x9300c003,
+	0x90c0c017,
+	0x9280c016,
+	0x93a0c015,
+	0x9280c001,
+	0x9120c011,
+	0x9220c011,
+	0x9320c011,
+	0x9060c013,
+	0x91a0c013,
+	0x93c0c013,
+	0x90c0c014,
+	0x9340c011,
+	0x9020c019,
+	0x9280c018,
+	0x9000c017,
+	0x9180c017,
+	0x9300c017,
+	0x90e0c003,
+	0x92a0c003,
+	0x9360c006,
+	0x9120c007,
+	0x93c0c007,
+	0x9200c00d,
+	0x9180c000,
+	0x9140c000,
+	0x9240c018,
+	0x9240c01a,
+	0x9320c01a,
+	0x92e0c01b,
+	0xc01d0802,
+	0xd0729000,
+	0xe0711924,
+	0x058b8d80,
+	0x91a0c000,
+	0x430cb780,
+	0x8d80e071,
+	0xc09c058b,
+	0xd2080a1c,
+	0xd120a902,
+	0xfff41125,
+	0xc01c9b2b,
+	0xd3f19020,
+	0xe0712aae,
+	0x9eaa8d80,
+	0x0916058b,
+	0x9a55fff4,
+	0x430cb780,
+	0x0a1cc09c,
+	0xa281d208,
+	0x9200c01b,
+	0x292ed3f2,
+	0x8d80e071,
+	0xc016058b,
+	0xf01091a0,
+	0x0d06aacd,
+	0x8d80e071,
+	0x9e524afd,
+	0x2a9c058b,
+	0x93e0c013,
+	0xaacdf010,
+	0x8d80e071,
+	0x0d02058b,
+	0xfff40906,
+	0x4afd9a32,
+	0x9e832a9c,
+	0x8d80e071,
+	0xc00e010b,
+	0xc01a0d7e,
+	0xb7809120,
+	0x0d02430c,
+	0x8d80e071,
+	0x0a40c09a,
+	0xaa01d208,
+	0x090a058b,
+	0xd0027500,
+	0xc0190d22,
+	0xb7209320,
+	0x7640430c,
+	0xb7840a82,
+	0xd002752d,
+	0x75000ad2,
+	0x9204c000,
+	0xc0007540,
+	0xb74491a2,
+	0xb78475ad,
+	0xe0716fad,
+	0x058b8d80,
+	0x090a7104,
+	0x9060c013,
+	0x6fadb744,
+	0x75adb784,
+	0xc0027088,
+	0x0d069004,
+	0x8d80e071,
+	0x058b9e52,
+	0x99f1fff4,
+	0xc0007540,
+	0xb72093a2,
+	0xb785430c,
+	0x75007ea9,
+	0x91c2c000,
+	0x6cadb784,
+	0xc0007502,
+	0x9e839122,
+	0x8d80e071,
+	0x0d2ec002,
+	0x90e0c000,
+	0xe0719e83,
+	0xc0028d80,
+	0x09220d2a,
+	0x99d3fff4,
+	0xe0719e83,
+	0x09168d80,
+	0xfff40d1e,
+	0xb78099cc,
+	0x9e83430c,
+	0x8d80e071,
+	0x0a04c098,
+	0xa902d208,
+	0x9a43fff4,
+	0x9e830d06,
+	0x8d80e071,
+	0xc0169e52,
+	0x02039360,
+	0x0a40c09a,
+	0xaa01d208,
+	0xc0167500,
+	0xc00992a2,
+	0xb7809180,
+	0x0d02430c,
+	0x8d80e071,
+	0x0a14c098,
+	0xaa01d208,
+	0x0906058b,
+	0xd0017500,
+	0xc0160d22,
+	0xb7809020,
+	0xc098430c,
+	0xd2080a10,
+	0x7500aa01,
+	0x9122c000,
+	0x8d80e071,
+	0x0d2a058b,
+	0xc0150912,
+	0x9ea29220,
+	0x8d80e071,
+	0x0906058b,
+	0x9140c015,
+	0x4314b720,
+	0x6ccdb784,
+	0xd0227504,
+	0xc0011524,
+	0x9e4c93a4,
+	0xc0969e4a,
+	0xd2080a54,
+	0xb744aa01,
+	0xc09875d5,
+	0xc2000910,
+	0xc1015a08,
+	0xb76400c2,
+	0xd008722d,
+	0xd011a941,
+	0x72990a32,
+	0xd0020d02,
+	0x74800d22,
+	0x9042c001,
+	0x7ec9b785,
+	0xd0127500,
+	0xc0001124,
+	0x9e4c9244,
+	0xc0960902,
+	0xd2080a58,
+	0xc200aa01,
+	0xc1015a08,
+	0xb72400c2,
+	0x0884722d,
+	0xd00270c2,
+	0x9e4c0922,
+	0xc0989e51,
+	0xd2080a0c,
+	0x3218aa01,
+	0x3144d020,
+	0x9e529e4c,
+	0x0a08c098,
+	0xaa01d208,
+	0x3228e000,
+	0x91a2fffd,
+	0xe0710d06,
+	0x9e528d80,
+	0xfff4058b,
+	0xb7209934,
+	0x0203430c,
+	0x0a08c098,
+	0xaa01d208,
+	0xc0007500,
+	0x9e839122,
+	0x8d80e071,
+	0x9a07fff4,
+	0x92e0c000,
+	0xc0960203,
+	0xd2080a54,
+	0xb744aa01,
+	0x9e8375b5,
+	0x5a08c200,
+	0xb72400c2,
+	0xe071722d,
+	0xd1208d80,
+	0xba121115,
+	0xfff44001,
+	0xb7209a0d,
+	0x0203430c,
+	0x0a10c098,
+	0xaa01d208,
+	0xc0037500,
+	0x02039342,
+	0x0a0cc098,
+	0xaa01d208,
+	0xc0027500,
+	0x020392c4,
+	0x0a08c098,
+	0xaa01d208,
+	0xc0960103,
+	0x75000958,
+	0x90c2c000,
+	0xaa41d008,
+	0x9260c002,
+	0xc0960203,
+	0xd2080a54,
+	0xd008aa01,
+	0x9e83a941,
+	0x5a08c200,
+	0x00c2d020,
+	0x00a25908,
+	0x722db724,
+	0x7255b724,
+	0x8d80e071,
+	0x1113d120,
+	0x90e0c002,
+	0x430cb720,
+	0xc0980203,
+	0xd2080a0c,
+	0x7500aa01,
+	0x9284c000,
+	0x6f2db784,
+	0xc0027500,
+	0x02039044,
+	0x0a54c096,
+	0xaa01d208,
+	0x5a08c200,
+	0xb78400c2,
+	0x7500722d,
+	0x92a4c001,
+	0xe0710d06,
+	0x9e528d80,
+	0xfff4058b,
+	0xb72098b2,
+	0x0203430c,
+	0x0a0cc098,
+	0xaa01d208,
+	0xc0007500,
+	0x9e839122,
+	0x8d80e071,
+	0x9985fff4,
+	0x92e0c000,
+	0xc0960203,
+	0xd2080a58,
+	0xc200aa01,
+	0xb7445a08,
+	0x00c275b5,
+	0x722db724,
+	0xe0719e83,
+	0xd1208d80,
+	0xba121115,
+	0xfff44001,
+	0x9e83998b,
+	0x8d80e071,
+	0xc0020d0e,
+	0xe0719200,
+	0x058b8d80,
+	0xfff70d02,
+	0xb72092c0,
+	0xe071430c,
+	0x058b8d80,
+	0x75b5b744,
+	0xc0060916,
+	0xb72091a0,
+	0xe071430c,
+	0x058b8d80,
+	0x75b5b744,
+	0xc0060922,
+	0xb7209060,
+	0xe071430c,
+	0x058b8d80,
+	0x75b5b744,
+	0x5d21090a,
+	0x9300c005,
+	0x430cb720,
+	0x67adb784,
+	0xd01a7502,
+	0xc0001248,
+	0xb7619174,
+	0x9ea34d2d,
+	0x9811c374,
+	0x0a027400,
+	0x0a42d001,
+	0x09c0f012,
+	0x04850d0a,
+	0x1ca2d001,
+	0x76c09e4a,
+	0x8d80e071,
+	0x4842b332,
+	0xc00b058b,
+	0xb7209020,
+	0xe071430c,
+	0x058b8d80,
+	0x6d35b744,
+	0xfff42d04,
+	0xc00a98b8,
+	0xb72092e0,
+	0x7640430c,
+	0xb7240d02,
+	0xd001752d,
+	0xe0710d22,
+	0x00928d80,
+	0x0522c101,
+	0xc00e058b,
+	0x091a2d7c,
+	0x9040c00a,
+	0x430cb720,
+	0x8d80e071,
+	0xb744058b,
+	0x090a7535,
+	0x91c0c003,
+	0x430cb720,
+	0x4d2db761,
+	0x67b5b764,
+	0xc00074c0,
+	0x0a8690a4,
+	0x9220c000,
+	0xc0029e9a,
+	0xc0000902,
+	0xd0119100,
+	0x01091a22,
+	0xc00e0524,
+	0x7680297c,
+	0x9336ffff,
+	0xc3540285,
+	0x9e829bb8,
+	0x8d80e071,
+	0xc00e058b,
+	0xd3f12d7c,
+	0xc008295e,
+	0xb7209220,
+	0xe071430c,
+	0x058b8d80,
+	0x75adb7a4,
+	0xc03e090a,
+	0xd2a42afc,
+	0xffd45921,
+	0x9e839be2,
+	0x8d80e071,
+	0x295ed3f2,
+	0x91e0c000,
+	0x8d80e071,
+	0xc00e058b,
+	0x09220d7e,
+	0x9bd3ffd4,
+	0xe0719e83,
+	0xc00e8d80,
+	0x09220d7e,
+	0x9180c007,
+	0xaa4df010,
+	0xd0114a7d,
+	0x754e2ace,
+	0x90c2c007,
+	0x8d80e071,
+	0x0d02058b,
+	0xffd40906,
+	0x9e839bbc,
+	0x8d80e071,
+	0x0d02010b,
+	0x92c0c006,
+	0x5614b740,
+	0x8d80e071,
+	0x9e54058b,
+	0xc2400922,
+	0x0d04a946,
+	0x2d7cc00e,
+	0x9100c006,
+	0x430cb720,
+	0x8d80e071,
+	0xb784058b,
+	0x09066cad,
+	0x0d027502,
+	0x0d22d001,
+	0x9340c005,
+	0x430cb720,
+	0x7ea9b785,
+	0xd0017500,
+	0xc0000a46,
+	0xb78590e2,
+	0x9e497f29,
+	0x0a044242,
+	0x294ed3f2,
+	0x8d80e071,
+	0x090a058b,
+	0x9080c005,
+	0x5614b740,
+	0x8d80e071,
+	0x9e52058b,
+	0xa946c220,
+	0xc0040916,
+	0xb7209320,
+	0xe071430c,
+	0x058b8d80,
+	0x7f31b745,
+	0x45220906,
+	0x91c0c004,
+	0x430cb720,
+	0x67adb780,
+	0xc0007500,
+	0xb78690c4,
+	0xc00050ad,
+	0xb7819380,
+	0x75045dad,
+	0x9164c000,
+	0xb7860902,
+	0xd0126bad,
+	0xc8127088,
+	0xb5407088,
+	0xb72067ad,
+	0xb781430c,
+	0x75045dad,
+	0x9122c000,
+	0xb7460a02,
+	0xd0126dad,
+	0xb5807104,
+	0xb7a067ad,
+	0x0d82430c,
+	0xb760008b,
+	0xfa0867ad,
+	0xc354a921,
+	0x008b9a64,
+	0x67b5b500,
+	0x430cb720,
+	0x8d80e071,
+	0xb740058b,
+	0xb72067b5,
+	0x095e682d,
+	0x1115d120,
+	0x90e0c001,
+	0x430cb720,
+	0x8d80e071,
+	0xb740058b,
+	0xc00067b5,
+	0xb78093a0,
+	0xb720558c,
+	0xc240430c,
+	0x0103aa45,
+	0x4ab5b746,
+	0xc0c47500,
+	0xc0000960,
+	0xd00890c2,
+	0xc000aa41,
+	0xd00890c0,
+	0xc101aa41,
+	0xe0710244,
+	0xb5868d80,
+	0x058b4aad,
+	0xffd4095e,
+	0xc0019b63,
+	0xb72090a0,
+	0xb784430c,
+	0x75066cad,
+	0x1124d011,
+	0x9282c000,
+	0x67adb784,
+	0xc0c40103,
+	0x75000960,
+	0x9142c000,
+	0x4badb781,
+	0xa941d008,
+	0x61290a04,
+	0x9080c000,
+	0xa941d008,
+	0x8d80e071,
+	0x292ed3f2,
+	0x091e058b,
+	0x9adfffd4,
+	0x7d6cb77f,
+	0x9e729eb3,
+	0x8d08e052,
+	0x9bb1ffd4,
+	0xb79f0806,
+	0xb7bf7d6e,
+	0xb7df7dee,
+	0xc0027e6e,
+	0x9c228c40,
+	0xc002a61d,
+	0x9e5f8440,
+	0xabc6f031,
+	0x0a72d011,
+	0x5a30c200,
+	0x0d829ea6,
+	0x0a00c040,
+	0x0f00c021,
+	0xa191a215,
+	0x7decb55f,
+	0x7d74b53f,
+	0xb57fa099,
+	0x9e567c74,
+	0x7a74b57f,
+	0x7af4b57f,
+	0x7b74b57f,
+	0x7bf4b57f,
+	0x0f50c040,
+	0x0a02c801,
+	0xf0009dee,
+	0x0687a261,
+	0xc002a19e,
+	0xf2089200,
+	0x028daa41,
+	0x75000b10,
+	0x9102c000,
+	0xc0007504,
+	0x750290a2,
+	0x9284c000,
+	0x09d8d011,
+	0xa962d008,
+	0x0c827504,
+	0xe0d19ebb,
+	0xd0028d00,
+	0xffd40c92,
+	0x58089a38,
+	0x08060360,
+	0x9200c000,
+	0x7decb75f,
+	0x7d74b73f,
+	0xe0d29ebb,
+	0x018b8d00,
+	0x9ba0ffd4,
+	0x1e72d011,
+	0x03c0d020,
+	0xa9a1f208,
+	0xc00074c0,
+	0xa19d90a4,
+	0x91e0c000,
+	0xc00074d8,
+	0xa9199124,
+	0x0e860d06,
+	0xa142d808,
+	0x9220c000,
+	0xc0007740,
+	0xa91d9144,
+	0x02200e82,
+	0x2a7cc00e,
+	0xc000a21d,
+	0xd11090c0,
+	0xd3f20651,
+	0xb79f2ace,
+	0x711f7a6c,
+	0x91e6fffd,
+	0xc0007740,
+	0xa91d9322,
+	0x1e52d011,
+	0xc1f05920,
+	0x2a7c2900,
+	0xa9113244,
+	0x32445940,
+	0xc021a915,
+	0xc0080900,
+	0x9dad0900,
+	0xa261f000,
+	0x0a06a91a,
+	0xa241d810,
+	0xd808a919,
+	0x7500aa41,
+	0x9284c000,
+	0xb79fa915,
+	0xc0217c6c,
+	0x09700900,
+	0x2a7ec7ff,
+	0xf0009dad,
+	0xb79fa261,
+	0xd1107aec,
+	0x9dee1679,
+	0xa261f000,
+	0x7becb71f,
+	0x7b6eb79f,
+	0x7beeb7bf,
+	0x7c6eb7df,
+	0x7ceeb7ff,
+	0x8c40c004,
+	0xa61d9c22,
+	0xc1800d84,
+	0x9e745f30,
+	0xc0409e76,
+	0x9ea50a00,
+	0xc021078d,
+	0xc0210b00,
+	0x02870f80,
+	0x0e80c021,
+	0x0b82c008,
+	0xc0400b40,
+	0xc0000fd0,
+	0xc03c93e0,
+	0xc01e757e,
+	0xb3540a7e,
+	0xc2004434,
+	0x12d85914,
+	0x2900c3fe,
+	0xf0009dfe,
+	0x9d5ea161,
+	0x9dedaa61,
+	0xa3e1f000,
+	0x9dde3a40,
+	0xa261f000,
+	0x09929eba,
+	0x010f058d,
+	0x9afbff94,
+	0xffff7540,
+	0xc0089044,
+	0x9ded0a02,
+	0xa261f000,
+	0x7e6eb79f,
+	0x7eeeb7bf,
+	0x7f6eb7df,
+	0x7feeb7ff,
+	0x8c00c002,
+	0xa6059c22,
+	0x5db00d84,
+	0xc0089e5d,
+	0xc0210e82,
+	0x0ac00a80,
+	0xf0009ddd,
+	0x9e5aa2e2,
+	0x0900c021,
+	0x0900c040,
+	0xa9629d2d,
+	0xd05174c0,
+	0xc0003e20,
+	0xd0d19082,
+	0x9dad3e20,
+	0xa261f000,
+	0x09929e6a,
+	0xff94050b,
+	0x9ddd9ac6,
+	0xa2e2f000,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0xc008a61d,
+	0xf2128420,
+	0x9e5e8c88,
+	0x03850705,
+	0x9e6a9e9a,
+	0xc0080a82,
+	0xb5bf0982,
+	0xffd45e6a,
+	0x9eb39872,
+	0x9eb99e72,
+	0x8c80e231,
+	0x050b018b,
+	0x9ab6fff4,
+	0x018b9eb3,
+	0x9bb9fff4,
+	0x75eeb79f,
+	0x766eb7bf,
+	0x76eeb7df,
+	0x776eb7ff,
+	0x8c20c00a,
+	0xb7209c22,
+	0x09824f0c,
+	0xb9600c96,
+	0x9e8a4038,
+	0x01030203,
+	0x0a39cfca,
+	0x0929cfdc,
+	0x0d09cfac,
+	0x40a9b57f,
+	0x4129b57f,
+	0x4029b560,
+	0x64a9b575,
+	0xa082f208,
+	0xa0c2f008,
+	0xa1c1f010,
+	0x08a0c146,
+	0x90e1ffff,
+	0x0c7f9e99,
+	0x4608b560,
+	0x91c0c000,
+	0x430cb740,
+	0x04a5d110,
+	0x6fadb789,
+	0x02446a32,
+	0x0a20c138,
+	0xa012d208,
+	0x2e1ed3f1,
+	0x71170c84,
+	0x5908d224,
+	0x91d8ffff,
+	0x588cb740,
+	0xb9600a02,
+	0x9ea24058,
+	0xa106c220,
+	0xffff0a04,
+	0x9c229381,
+	0x588cb720,
+	0x09029e5b,
+	0x0d34d012,
+	0x4038b960,
+	0xd2080222,
+	0x7115aa09,
+	0x90c4c000,
+	0x297cc00e,
+	0x90c0c000,
+	0xffff0904,
+	0x090292a1,
+	0x588cb780,
+	0x01280904,
+	0x0a049ea2,
+	0x11a8d000,
+	0x90e0c000,
+	0xaa41d008,
+	0xa245d008,
+	0xffff1904,
+	0xd0119361,
+	0xd0100a34,
+	0x9c22a249,
+	0xc912a61d,
+	0xc9129cc4,
+	0xb7a09cce,
+	0xb7a05814,
+	0xf010478c,
+	0x0507a1ed,
+	0x1fd6d032,
+	0xd0510b86,
+	0x0f020b50,
+	0x167ad010,
+	0x4a7d9e6a,
+	0x9c83c810,
+	0xaa5dd1e9,
+	0xd0206a52,
+	0xf01001ca,
+	0x7500aa6d,
+	0x93a4c000,
+	0x0e20d051,
+	0xa003f208,
+	0xa3edf010,
+	0x0e38d011,
+	0xa803f208,
+	0xaa61d050,
+	0xa961f010,
+	0x4508b580,
+	0x9c629e94,
+	0xa843f208,
+	0xb5c09eaa,
+	0xf2084510,
+	0xfffea3ad,
+	0x750292e0,
+	0x91c4c000,
+	0x0e20d051,
+	0xa003f208,
+	0x0e30d051,
+	0xa803f208,
+	0xaa61d050,
+	0x9240c000,
+	0x9181fffe,
+	0x9200c003,
+	0x0e20d051,
+	0xa003f208,
+	0x4b8cb780,
+	0xa803f208,
+	0x478cb780,
+	0xaa01d248,
+	0x4508b580,
+	0x9120c003,
+	0x0a02c021,
+	0x9d4d0a10,
+	0xdfe0aa61,
+	0xc0007d00,
+	0xc10090c2,
+	0xc0010a82,
+	0xb7609120,
+	0x0b0a4688,
+	0x74c0010d,
+	0x0a02c021,
+	0x0a00c030,
+	0x1962d001,
+	0xa9629d4d,
+	0x9e512d71,
+	0x3122290c,
+	0xf0009dcd,
+	0xc100a161,
+	0xc017080a,
+	0x74c09c81,
+	0x90a4c000,
+	0xff949e9b,
+	0xc171996d,
+	0xc8179c81,
+	0x9eb39c84,
+	0x2afccffe,
+	0x9964ff94,
+	0xff940d8a,
+	0xc0219961,
+	0xc0300902,
+	0x9d2d0900,
+	0x3a0caa61,
+	0xf0009dad,
+	0xb740a261,
+	0x018b4a8c,
+	0x2954d012,
+	0x2980c100,
+	0xb9600d86,
+	0xf0084050,
+	0x7506aa41,
+	0x90a4c000,
+	0xc00074c0,
+	0x750490c0,
+	0x90a4c000,
+	0xb41a7680,
+	0x19504a24,
+	0x9221ffff,
+	0x9160c000,
+	0x478cb780,
+	0xaa0df208,
+	0xfffc7502,
+	0xfffc93a4,
+	0xb79f9160,
+	0xb7bf7e6e,
+	0xb7df7eee,
+	0xb7ff7f6e,
+	0xc0027fee,
+	0x9c228c00,
+	0xb780a605,
+	0x9e5b4508,
+	0x4794b760,
+	0xb7a06a52,
+	0xd1204488,
+	0xfff401c7,
+	0x9eab9b23,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0xffb38c40,
+	0xa60592e0,
+	0x9080c000,
+	0x9be8fff4,
+	0x430cb720,
+	0x47a9b7aa,
+	0xffb49eab,
+	0x700a9a86,
+	0xffff0d92,
+	0xb79f92a2,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0x9180ffb4,
+	0xc002a61d,
+	0x9e5e8400,
+	0xa116a199,
+	0xc000a111,
+	0xfff49080,
+	0xb7809bcb,
+	0x0d924408,
+	0x7d3ec01c,
+	0x9324ffff,
+	0x4408b780,
+	0x0d02c021,
+	0x0d10c010,
+	0xb5800a04,
+	0x9d2e4408,
+	0xc021ab62,
+	0xc0100902,
+	0xd0720920,
+	0x9d2d2eee,
+	0x9e55aa61,
+	0x29ced071,
+	0xc0000385,
+	0xfff49180,
+	0x9d5d9ba9,
+	0xd072ab62,
+	0x9d7d2eee,
+	0xd071aa61,
+	0xd01229ce,
+	0xd0710fd2,
+	0x0d8a2e7e,
+	0xffff7106,
+	0x0a029202,
+	0x7c6cb59f,
+	0x7cecb59f,
+	0x7d6cb59f,
+	0x7decb59f,
+	0xb9600389,
+	0xaa154078,
+	0xe0939d7d,
+	0xc2708d00,
+	0xf010a905,
+	0x0b848026,
+	0xa101d208,
+	0x92a1ffff,
+	0x9eb39dcb,
+	0xff940982,
+	0x9eb398aa,
+	0x8d00e092,
+	0xff940982,
+	0xaa9198cd,
+	0x4c8cb780,
+	0x5e88c280,
+	0x6aa2c146,
+	0x02d89eb3,
+	0x0aa0c050,
+	0xa922f208,
+	0x7decb79f,
+	0xe050018f,
+	0x0902a94a,
+	0xff94a21d,
+	0x9eb39a3d,
+	0x2f01cffe,
+	0x9a52ff94,
+	0x9eb3aa1d,
+	0x8d00e092,
+	0x09824a7d,
+	0x7decb59f,
+	0x987fff94,
+	0xaaa1f208,
+	0x9eb39e6c,
+	0xa926e240,
+	0x0902018f,
+	0x9a3dffb4,
+	0xff949eb3,
+	0xc0049a3b,
+	0x0a0277c0,
+	0x4824b374,
+	0x2a7c9e72,
+	0xc0213244,
+	0xc0100902,
+	0x9dad0910,
+	0xa261f000,
+	0xe0929eb3,
+	0x09828d00,
+	0x9886ff94,
+	0xb79fa91f,
+	0x71357dec,
+	0x92c4ffff,
+	0x4408b780,
+	0x1a04a919,
+	0xb5807480,
+	0xc0004408,
+	0xb7809164,
+	0xc0a4430c,
+	0xd2080a10,
+	0x7500aa01,
+	0x9102c000,
+	0xff940d8e,
+	0x0d8a9837,
+	0x9834ff94,
+	0x7c6eb79f,
+	0x7ceeb7bf,
+	0x7d6eb7df,
+	0x7deeb7ff,
+	0x8c00c004,
+	0xf8399c22,
+	0x8440a205,
+	0x9e9b9e5a,
+	0x5a20c100,
+	0xc7f09e53,
+	0xe0522a00,
+	0xc0018d00,
+	0xa2113a04,
+	0xfff4a096,
+	0xf9f89b1f,
+	0x9c22aa15,
+	0xa205f839,
+	0x0a028440,
+	0x0a20c146,
+	0x4c8cb720,
+	0x00c26229,
+	0x5aadb783,
+	0x5ca0c180,
+	0x5b35b703,
+	0x2a7cc006,
+	0xb7039ea3,
+	0xc7f05bad,
+	0xb7232c80,
+	0x34965c2d,
+	0x9e539e9b,
+	0x8d00e052,
+	0xa019a016,
+	0xa092a09d,
+	0x9af8fff4,
+	0xaa15f9f8,
+	0xa6059c22,
+	0x0d80c021,
+	0x06b7d110,
+	0xc0000685,
+	0xb78091c0,
+	0x0a044688,
+	0x4688b580,
+	0x9abafff4,
+	0x4688b780,
+	0xb5801a04,
+	0x9d5d4688,
+	0x791baa61,
+	0xffff0d8e,
+	0xb79f9202,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xa6059c22,
+	0xc4019e5c,
+	0xc0210902,
+	0x9e5d0a00,
+	0x0900c008,
+	0x9dcd0a20,
+	0xa161f000,
+	0xc0080992,
+	0xc0210d02,
+	0xfff40a80,
+	0x0ac09bce,
+	0x0a02c008,
+	0xf0009ddd,
+	0xb79fa261,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xa61d9c22,
+	0xb7208440,
+	0xd132430c,
+	0x06876f31,
+	0x46b1b76a,
+	0x04e3d110,
+	0x05d60b02,
+	0x4294b560,
+	0x4c2bb5c1,
+	0x430cb780,
+	0xd0120c06,
+	0xd1100d32,
+	0x5d300669,
+	0x0a48c012,
+	0xa301da08,
+	0x430cb720,
+	0xd1109e52,
+	0xc02104e3,
+	0xb5c00900,
+	0xb78066ad,
+	0xc01a430c,
+	0xd1100920,
+	0xc0120669,
+	0xf2080a60,
+	0xb720a301,
+	0xd110430c,
+	0xb50004e3,
+	0xb78065b5,
+	0xd110430c,
+	0xc0120669,
+	0xd2080a20,
+	0x9dada301,
+	0xa361f000,
+	0xc0089e54,
+	0xc0210902,
+	0x0a400a00,
+	0xf0009dcd,
+	0xb7a0a161,
+	0x9e51430c,
+	0x0d00c040,
+	0x046ac101,
+	0x0d80d3f1,
+	0x604cb780,
+	0xa965f008,
+	0x0880c021,
+	0x08c0c046,
+	0x9d9d0244,
+	0xa261f000,
+	0x0d00c021,
+	0xf0009dae,
+	0xb702a361,
+	0xd0105450,
+	0xe0530636,
+	0xc1018d00,
+	0xc2000240,
+	0x9d4d5a08,
+	0xf010008b,
+	0x050d81a6,
+	0x5cadb700,
+	0xa9e1f008,
+	0xa8e1f208,
+	0x00ddd120,
+	0x0d40c012,
+	0x0155d120,
+	0xc0109e42,
+	0x9e840c90,
+	0xb7209c62,
+	0x7740430c,
+	0x04e3d110,
+	0x67adb5c0,
+	0x4314b720,
+	0x04e2d010,
+	0x714db780,
+	0x5f2db720,
+	0xb5800242,
+	0xc000714d,
+	0x9eb790e4,
+	0xa061f208,
+	0x9240c008,
+	0x4294b760,
+	0xd0110d7f,
+	0xc2000e32,
+	0x01095a30,
+	0x0900c021,
+	0x0940c00e,
+	0xf0009dad,
+	0x0910a162,
+	0xf0009dad,
+	0x0910a361,
+	0xf0009dad,
+	0xc021a361,
+	0xc00e0a00,
+	0x9dcd0a70,
+	0xa361f000,
+	0x430cb720,
+	0x2dfcc00e,
+	0xd110010d,
+	0x09c204e3,
+	0x5fadb720,
+	0x1910d052,
+	0x7d6eb79f,
+	0x7deeb7bf,
+	0x7e6eb7df,
+	0x7eeeb7ff,
+	0x8c40c002,
+	0x9280ff84,
+	0x4729b7ea,
+	0xc380070f,
+	0x02895a30,
+	0x0a80c021,
+	0x0a80c116,
+	0x9100c002,
+	0x5f4db780,
+	0xc0027500,
+	0xb7809002,
+	0x750067cd,
+	0x9162c000,
+	0xb5e09eab,
+	0xcfdf67d5,
+	0xcfea0dfc,
+	0xfff40d80,
+	0xb7409af0,
+	0xd0914314,
+	0xc1016e59,
+	0xb74200e4,
+	0x02445429,
+	0x74800248,
+	0x00c5d120,
+	0x91e2c000,
+	0x4c4bb781,
+	0x0902c201,
+	0x0900c004,
+	0x5a40c200,
+	0x2a7cc00f,
+	0xc0003244,
+	0xb7819140,
+	0xc2004c2b,
+	0xc00f5a40,
+	0xc2012a7c,
+	0xb5803a00,
+	0xb78066ad,
+	0xd131430c,
+	0x00986cd1,
+	0x66adb720,
+	0xf0009ddd,
+	0x0f04a0e1,
+	0x0a81cf00,
+	0x430cb720,
+	0x117cc101,
+	0x46a9b78a,
+	0x12a8d020,
+	0xd1317088,
+	0xd0206f51,
+	0xfffd00e2,
+	0xb7ca91b6,
+	0xc0034729,
+	0xd0209200,
+	0xd1321368,
+	0xd0916ee1,
+	0xd0106d69,
+	0x9ea806d2,
+	0x5f4cb780,
+	0xc0037500,
+	0xb7229022,
+	0xb7605448,
+	0x00a25e4d,
+	0xc1010092,
+	0xb7610092,
+	0xc3344c33,
+	0x008b98c4,
+	0x67adb500,
+	0x430cb720,
+	0x04d3d110,
+	0x0910d3f1,
+	0xaa41f008,
+	0x67adb720,
+	0xf0081242,
+	0xb720a241,
+	0xd0104314,
+	0xb78004d2,
+	0xb720714d,
+	0x124267ad,
+	0x714db580,
+	0x430cb780,
+	0x0659d110,
+	0xc0120089,
+	0xb78008a0,
+	0x75004029,
+	0x90c2c000,
+	0x4031b5e0,
+	0x90a0c000,
+	0xb5400906,
+	0xb7004029,
+	0xd1324314,
+	0xd0106d61,
+	0xb76004a0,
+	0x74c05f2d,
+	0x9382c000,
+	0x5429b742,
+	0xe053026c,
+	0x02448d00,
+	0x5a08c200,
+	0xb7009d4d,
+	0xf0105ccc,
+	0x048480a6,
+	0xa8a1f208,
+	0x0d40c012,
+	0xc0109eb3,
+	0x05040c90,
+	0x9c629e84,
+	0xa021f208,
+	0xb7201b04,
+	0xb78a4314,
+	0x718846c9,
+	0x91b6fffc,
+	0x430cb720,
+	0x712db740,
+	0xfff97480,
+	0xb78a9024,
+	0x028546a9,
+	0x9220c000,
+	0x67adb780,
+	0xc0007500,
+	0xd0129122,
+	0xb5a009a2,
+	0x5db067ad,
+	0x9a1dfff4,
+	0x428cb780,
+	0xb7200a04,
+	0xb580430c,
+	0xb740428c,
+	0xb78a428c,
+	0xb74a4729,
+	0x708846b1,
+	0x2e2ed3f1,
+	0xc0041228,
+	0x00c26a22,
+	0x9014ffff,
+	0x2e2ed3f1,
+	0x0f8ec001,
+	0xc0020b02,
+	0xc0010bc2,
+	0xce000f0a,
+	0xb5800f80,
+	0xc005428c,
+	0xb78a93a0,
+	0x122846a9,
+	0x6ac1d132,
+	0x04d3d110,
+	0x65adb780,
+	0xc0057500,
+	0xd0129182,
+	0xb5c009a2,
+	0x5db067ad,
+	0xc0219e5c,
+	0xc0400a00,
+	0x9dcd0a00,
+	0xa3e1f000,
+	0x99ddfff4,
+	0x428cb7a0,
+	0x0952d011,
+	0x02055930,
+	0x0a00c021,
+	0x0a20c040,
+	0xaa619d4d,
+	0x430cb720,
+	0x9e929e7b,
+	0x04d3d110,
+	0x0d00c021,
+	0x65adb580,
+	0x430cb720,
+	0x0d40c046,
+	0x04d3d110,
+	0x65adb780,
+	0xc2002246,
+	0xb5805a35,
+	0x9d2e672d,
+	0xb720a962,
+	0x9e91430c,
+	0x04d3d110,
+	0x0c80c021,
+	0x65b5b540,
+	0x430cb720,
+	0x0cc0c00e,
+	0x04d3d110,
+	0xb7409e8b,
+	0xc01065b5,
+	0xf0100d80,
+	0xb760aa61,
+	0xb720672d,
+	0xc1015fad,
+	0x12460244,
+	0xf0101242,
+	0xb720a261,
+	0xd110430c,
+	0xb78004d3,
+	0x9d9e602d,
+	0xa261f000,
+	0xc0210205,
+	0xc00e0a00,
+	0x9dcd0a50,
+	0xa361f000,
+	0x9dcd0a10,
+	0xa361f000,
+	0x9dcd0a10,
+	0xa361f000,
+	0x0900c021,
+	0x0930c00e,
+	0xf0009dad,
+	0xb720a362,
+	0xc00e5fad,
+	0x9eab2afc,
+	0x1910d052,
+	0x010d09c2,
+	0x9af2ff74,
+	0xff749eab,
+	0xb7809b09,
+	0xd110430c,
+	0xc0100659,
+	0xf2080a00,
+	0xb780a301,
+	0xd110430c,
+	0xc00e0659,
+	0xf2080a60,
+	0xb780a305,
+	0xd110430c,
+	0xc00e0659,
+	0xf2080a60,
+	0xb720a301,
+	0xd110430c,
+	0xb5c004d3,
+	0xb72067ad,
+	0xb5c0430c,
+	0xb720712d,
+	0xd110430c,
+	0xb5c004d3,
+	0xb78065ad,
+	0x0a04428c,
+	0x428cb580,
+	0x430cb720,
+	0x428cb740,
+	0x4729b78a,
+	0xfff97088,
+	0xb79f93d4,
+	0xb7bf7d6e,
+	0xb7df7dee,
+	0xb7ff7e6e,
+	0xc0027eee,
+	0x9c228c40,
+	0xb720a605,
+	0x9e5d430c,
+	0x4829b78a,
+	0x22d8d020,
+	0xc0007346,
+	0xc0009244,
+	0xffd49080,
+	0xb7209bc1,
+	0x0d92430c,
+	0x48a9b78a,
+	0xffff7b59,
+	0xc0009304,
+	0xffd49380,
+	0xb7209bb5,
+	0xb740430c,
+	0x0d924588,
+	0x4829b78a,
+	0x22444a7d,
+	0xffff790a,
+	0x322a9284,
+	0x4588b580,
+	0x4829b78a,
+	0xb58a3258,
+	0xb7204829,
+	0xb78a430c,
+	0x325848a9,
+	0x0d82c021,
+	0x48a9b58a,
+	0x0da0c030,
+	0xa9629d3e,
+	0x4488b740,
+	0x59080a3e,
+	0x5208c200,
+	0x51a8c200,
+	0x4a7d21b8,
+	0x25229ea1,
+	0x35229e99,
+	0xf0009dbe,
+	0xb79fa162,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xa6059c22,
+	0x478cb780,
+	0xb7400906,
+	0xf2084c14,
+	0xf010a10d,
+	0x0a10a043,
+	0xa803f208,
+	0x4a8cb7a0,
+	0xb5800a02,
+	0xd3724508,
+	0x010b1ad8,
+	0xaa4df1e9,
+	0xc000750c,
+	0x0d9290e2,
+	0x9b60ffd4,
+	0x92e0ffff,
+	0xffff709b,
+	0xb78092a4,
+	0xf2084c0c,
+	0xb79fa803,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xb7409c22,
+	0x0d064b0c,
+	0x4058b960,
+	0xaa41f008,
+	0xb4127508,
+	0x09504a22,
+	0x9341ffff,
+	0xb7209c22,
+	0xb785430c,
+	0x750044ab,
+	0x9142c000,
+	0x48a9b78a,
+	0x42289e5a,
+	0x48a9b58a,
+	0x9300c000,
+	0xb74a9e5c,
+	0x4a7d4829,
+	0x4000ba24,
+	0xb54a2144,
+	0xb7204829,
+	0xb74a430c,
+	0x224448a9,
+	0x48a9b58a,
+	0x4588b780,
+	0x42289e5a,
+	0x4588b580,
+	0x0982c021,
+	0x09a0c030,
+	0xa9629d3d,
+	0x4488b740,
+	0x2e3ed031,
+	0xc2005908,
+	0x4a7d5208,
+	0x25269ea3,
+	0xf0009dbd,
+	0xfffda162,
+	0xf8399340,
+	0xb720a205,
+	0xb783430c,
+	0xb58a5b2d,
+	0xb72047a9,
+	0xb783430c,
+	0xc2005b2d,
+	0xb58a5a21,
+	0xb7204729,
+	0xb786430c,
+	0xb58a76ab,
+	0xb72046a9,
+	0xb78d430c,
+	0xb58a6da9,
+	0xb7204629,
+	0xb76a430c,
+	0xfff447b1,
+	0xb7209b19,
+	0x0982430c,
+	0xb74a0dff,
+	0xba1246b1,
+	0xc0004001,
+	0xb7899140,
+	0x6a326fcd,
+	0xc1380242,
+	0xd2080a20,
+	0xb720a192,
+	0xc101430c,
+	0xc2000234,
+	0xd0205908,
+	0xb74a00a2,
+	0x09844729,
+	0xffff7104,
+	0xb76a919c,
+	0xf9f847b1,
+	0xfffcaa1d,
+	0xa60d9000,
+	0x8400c004,
+	0xc0210705,
+	0x03070d02,
+	0xc0309e95,
+	0x9d2e0d00,
+	0x0205a961,
+	0x2a70c03e,
+	0xcfc00a10,
+	0xc03e290d,
+	0x32442a70,
+	0xf0009dae,
+	0xc021a261,
+	0xc0300902,
+	0x9d2d0920,
+	0xc180aa61,
+	0x9e515d60,
+	0x2a7ec00f,
+	0x9dad3242,
+	0xa261f000,
+	0x76d6097f,
+	0xa121d210,
+	0x90a4c002,
+	0x2a3ed3f1,
+	0xd1a4750c,
+	0xc0105921,
+	0xd2269312,
+	0xb720590c,
+	0x8520430c,
+	0x8044e050,
+	0x91c0c000,
+	0x91a0c010,
+	0x91c0c000,
+	0x9340c000,
+	0x9380c000,
+	0x90a0c010,
+	0x9380c000,
+	0x4835b545,
+	0x93e0c00f,
+	0x0a060103,
+	0x0970c0a2,
+	0xa241d008,
+	0x430cb780,
+	0x0a74c0a2,
+	0xa102d208,
+	0x9220c00f,
+	0x6735b544,
+	0x91a0c00f,
+	0x68b5b544,
+	0x9120c00f,
+	0x5e30d122,
+	0x2d7cc03e,
+	0x5d18d122,
+	0x2a00cffd,
+	0xb5813244,
+	0xc00e482d,
+	0x76d89380,
+	0x9084c002,
+	0x430cb720,
+	0x5e2db781,
+	0xc0017500,
+	0xd3f191a2,
+	0xc01c2a3e,
+	0xb59f753e,
+	0xc0006268,
+	0xc18091c2,
+	0xc2005a21,
+	0xb59f5a0c,
+	0xb55f786c,
+	0xb55f6368,
+	0xc00062e8,
+	0xd1a491e0,
+	0x09025941,
+	0x5a21c180,
+	0x62e8b59f,
+	0x6370b55f,
+	0x6268b55f,
+	0x786cb55f,
+	0x430cb720,
+	0x8d80e112,
+	0x6cadb729,
+	0x9c629e8c,
+	0x90e0c00d,
+	0x67a9b566,
+	0x430cb720,
+	0x5a21c180,
+	0x5941c180,
+	0x6829b586,
+	0x430cb720,
+	0x68a9b546,
+	0x92e0c00c,
+	0xc00476da,
+	0xffd49124,
+	0x9e839a1c,
+	0x9eaa0a86,
+	0x2dfcc00e,
+	0xd21055cc,
+	0xc00ea021,
+	0xfff42dfc,
+	0xd2109a2d,
+	0xe111a9a2,
+	0x050d8d00,
+	0x09a2c002,
+	0x9905ff94,
+	0xaa21d210,
+	0x52b0c200,
+	0x29ded3f2,
+	0x9aa9fff4,
+	0x8c80e111,
+	0x430cb780,
+	0x50a9b740,
+	0xb75f0244,
+	0xc0987068,
+	0xd2080a60,
+	0xb780a115,
+	0xb72050a9,
+	0xc200430c,
+	0x00c25a08,
+	0x796cb79f,
+	0x63adb582,
+	0x8c80e111,
+	0x50a9b780,
+	0x430cb720,
+	0x5a08c200,
+	0xb79f00c2,
+	0xb58279ec,
+	0xe111682d,
+	0xb7808c80,
+	0xb72050a9,
+	0xc200430c,
+	0x00c25a08,
+	0x7a6cb79f,
+	0x6cadb582,
+	0x8c80e111,
+	0x50a9b780,
+	0x430cb720,
+	0x5a08c200,
+	0xb79f00c2,
+	0xb5827aec,
+	0xe111712d,
+	0xb7808c80,
+	0xb72050a9,
+	0xc200430c,
+	0x00c25a08,
+	0x7b6cb79f,
+	0x75adb582,
+	0x8c80e111,
+	0x50a9b780,
+	0x430cb720,
+	0x5a08c200,
+	0xb79f00c2,
+	0xb5827bec,
+	0xe1117a2d,
+	0xb75f8c80,
+	0xb7807c6e,
+	0xb72050a9,
+	0xc200430c,
+	0x00c25a0c,
+	0x61afb541,
+	0x91a0c008,
+	0xc00176dc,
+	0xd3f192e4,
+	0x75022a3e,
+	0x90c2c001,
+	0xc0007502,
+	0x750492e6,
+	0x93e4c007,
+	0x430cb720,
+	0x5a21c180,
+	0x5941c180,
+	0x4535b5c2,
+	0x430cb720,
+	0x6c29b588,
+	0x430cb720,
+	0x6ca9b548,
+	0x91a0c007,
+	0x430cb720,
+	0x5a41c180,
+	0x45b5b5c2,
+	0x430cb720,
+	0x6d29b588,
+	0x9020c007,
+	0x430cb720,
+	0x5a41c180,
+	0x4635b5c2,
+	0x430cb720,
+	0x6da9b588,
+	0x92a0c006,
+	0xc00376de,
+	0xffd49164,
+	0x9e85995a,
+	0xc00e0a86,
+	0x9e6b2efc,
+	0x52acc200,
+	0x2afcc00e,
+	0xfff49eab,
+	0xe111996b,
+	0x050d8d00,
+	0x0982c004,
+	0xff94058b,
+	0x058b9844,
+	0x9826ff74,
+	0xfff49eab,
+	0xb78099ea,
+	0xd032430c,
+	0x0982296e,
+	0x0629d110,
+	0xc1369e9b,
+	0xd2080a20,
+	0xb720a18d,
+	0xc300430c,
+	0xcfc05a18,
+	0xb5822a01,
+	0xb7807ead,
+	0xd031430c,
+	0x00986ca9,
+	0x78ecb79f,
+	0x712db589,
+	0x0624d010,
+	0x796cb75f,
+	0x0045d120,
+	0x430cb780,
+	0x2900c01e,
+	0xc1365915,
+	0xd2080a28,
+	0xc000a101,
+	0xb78090c0,
+	0xb589404d,
+	0xd3f170ad,
+	0xb7602d3e,
+	0xc100430c,
+	0x9d4d5a08,
+	0xc1360207,
+	0xd2080a28,
+	0xd110a902,
+	0xe1130605,
+	0xc2008d00,
+	0x72955a08,
+	0x80a6e020,
+	0x0d8400c6,
+	0x90b2ffff,
+	0x9120c003,
+	0xc00176ea,
+	0xf01190a4,
+	0xc0002a32,
+	0xffd49362,
+	0x9e8398ea,
+	0x9eaa0a86,
+	0x2dfcc00e,
+	0xc00e55cc,
+	0xd2102dfc,
+	0xfff4a021,
+	0xb74098fb,
+	0xd210430c,
+	0x050da9a2,
+	0x0920c046,
+	0x09d2c002,
+	0x9040c001,
+	0x430cb720,
+	0x4f2db582,
+	0x9060c002,
+	0xc00176ec,
+	0xffd490a4,
+	0x9e8398c8,
+	0x9eaa0a86,
+	0x2dfcc00e,
+	0xc00e55cc,
+	0xd2102dfc,
+	0xfff4a021,
+	0xb74098d9,
+	0xd210430c,
+	0x050da9a2,
+	0x0970c048,
+	0x0982c002,
+	0x9bafff74,
+	0xaa21d210,
+	0x52b0c200,
+	0x29ded3f2,
+	0x9953fff4,
+	0x93a0c000,
+	0xc00076e0,
+	0xb7809164,
+	0x0906430c,
+	0x0a10c0a4,
+	0xa101d208,
+	0x9220c000,
+	0xc00076c6,
+	0xc2d490c4,
+	0xc0009a1f,
+	0xb7409140,
+	0xd1a2598c,
+	0xe2205e08,
+	0x9ea4aa05,
+	0xb7209c62,
+	0x0203430c,
+	0x0a10c0a4,
+	0xaa01d208,
+	0xc0007500,
+	0x0a029222,
+	0x44abb585,
+	0x430cb720,
+	0x4829b78a,
+	0x48b1b76a,
+	0x45b49ea2,
+	0x2dfcc00e,
+	0x991dfff4,
+	0x7aeeb79f,
+	0x7b6eb7bf,
+	0x7beeb7df,
+	0x8c60c004,
+	0xa61d9c22,
+	0x8400c002,
+	0xd050a192,
+	0x0c82aa61,
+	0x0ca0c146,
+	0x9ea51a08,
+	0x4c8cb780,
+	0x2efcc00e,
+	0xb7e064d3,
+	0x9e4a4794,
+	0x03a8a096,
+	0x9eba9eb9,
+	0x0882010f,
+	0x0c80c06c,
+	0x0960c06c,
+	0x0d00c06e,
+	0xa09d028f,
+	0xb55fa09a,
+	0xb55f7dec,
+	0x058b7d74,
+	0x9ab6ff74,
+	0x430cb780,
+	0x0a38c0a2,
+	0xab01d208,
+	0x90a0c000,
+	0xffd40d92,
+	0xa99a9821,
+	0xb78d008f,
+	0xd01060a9,
+	0xb7c0a961,
+	0x70884c94,
+	0x9282ffff,
+	0xc0007580,
+	0xb7209164,
+	0xb76a430c,
+	0xff7447b1,
+	0x74009ab2,
+	0x9104ffff,
+	0xff74058b,
+	0xa9199a91,
+	0xd0089ea9,
+	0xb76daa41,
+	0x710660c9,
+	0x9102c001,
+	0xc180aa15,
+	0xb73f5890,
+	0x00987df4,
+	0x009cc101,
+	0x4cadb783,
+	0x4db5b743,
+	0x4c2db743,
+	0x4d2db723,
+	0x404db580,
+	0xd0129ea9,
+	0xb52309b2,
+	0xb79f5bcd,
+	0x099a7d6c,
+	0x5acdb543,
+	0xa102f208,
+	0x297cc006,
+	0xc2f4a11d,
+	0x008b9bb5,
+	0x60a9b50d,
+	0xff74058b,
+	0xb7209a5f,
+	0xa99e430c,
+	0x8d00e091,
+	0x5bb5b743,
+	0x5b2db763,
+	0x990bfff4,
+	0x7068b79f,
+	0x753ec01c,
+	0x90c4c000,
+	0x9a78ff74,
+	0x7068b51f,
+	0x7070b77f,
+	0x55ac0c86,
+	0x2dfcc00e,
+	0x9beaffd4,
+	0x4490b760,
+	0x4c8cb740,
+	0x7068b77f,
+	0xc1469e5c,
+	0x00c46a22,
+	0x5ab5b743,
+	0x5d3d9e5a,
+	0xffd42d04,
+	0xb77f98b9,
+	0x0d067070,
+	0xc00e55cc,
+	0xfff42dfc,
+	0xf250985e,
+	0x7508aa61,
+	0x90a4c000,
+	0xf2500d86,
+	0xb720a1e2,
+	0xb740430c,
+	0xb7604914,
+	0xf0104e8c,
+	0x7508aa41,
+	0x91c4c000,
+	0x47a9b78a,
+	0xa961d008,
+	0xc01c2244,
+	0xc0007d3e,
+	0x0a0690a2,
+	0xa241f010,
+	0x4894b720,
+	0xc1460d50,
+	0x728209a0,
+	0x9124ffff,
+	0x7482a91d,
+	0x90e4fffa,
+	0x4794b740,
+	0xa141f050,
+	0x4608b780,
+	0x0a04a992,
+	0x4608b580,
+	0xf0100a1a,
+	0xb79fa26d,
+	0xb7bf7c6e,
+	0xb7df7cee,
+	0xb7ff7d6e,
+	0xc0047dee,
+	0x9c228c00,
+	0xc006a61d,
+	0xb7208440,
+	0xf1d2430c,
+	0xb7838d00,
+	0xb7c35c2d,
+	0xa2155b2d,
+	0x5badb783,
+	0x0a06a219,
+	0x5218c200,
+	0xb7239ea5,
+	0xc00e5aad,
+	0x058b2efc,
+	0xffd4a091,
+	0xb7209b73,
+	0xe1d14314,
+	0xb9608d00,
+	0xb7ed4028,
+	0xb7ed6049,
+	0x9e4960d1,
+	0x4c2db783,
+	0xa241f008,
+	0x4cadb783,
+	0xa245f008,
+	0x4d2db783,
+	0xa249f008,
+	0x4dadb783,
+	0xf00808c0,
+	0x0940a24d,
+	0x91c1ffff,
+	0xb5aa0a82,
+	0xb7204849,
+	0xd3f2430c,
+	0xc00629ee,
+	0xb5aa0992,
+	0xa91a48a9,
+	0x430cb740,
+	0x9a25ff74,
+	0x430cb720,
+	0xb5aa058b,
+	0xb7204831,
+	0xb5aa430c,
+	0xb78048b1,
+	0xc0a4430c,
+	0xd2080a10,
+	0xb720a281,
+	0xb5a5430c,
+	0xffd444ab,
+	0xb7209bbc,
+	0x9eaa430c,
+	0x4028b960,
+	0x6029b5ed,
+	0x430cb720,
+	0x60b1b5ed,
+	0x430cb720,
+	0xaa41f210,
+	0x5c90c100,
+	0x0493d110,
+	0xb5830d04,
+	0xb7204c2d,
+	0xf210430c,
+	0xd110aa45,
+	0xb5830493,
+	0xb7204cad,
+	0xf210430c,
+	0xd110aa49,
+	0xb5830493,
+	0xb7804d2d,
+	0xf210430c,
+	0x0f40a94d,
+	0x0498c101,
+	0x4dcdb543,
+	0x9381fffe,
+	0x430cb720,
+	0xb583aa11,
+	0xb7205aad,
+	0xb5c3430c,
+	0xb7205b2d,
+	0xaa19430c,
+	0x5badb583,
+	0x430cb720,
+	0xb583aa15,
+	0xb7205c2d,
+	0xb780430c,
+	0xb58a70a9,
+	0xb72047a9,
+	0xb780430c,
+	0xb58a7029,
+	0xb7204729,
+	0xb780430c,
+	0xb58a6fa9,
+	0xb72046a9,
+	0xb780430c,
+	0xb58a6f29,
+	0xb7204629,
+	0xb780430c,
+	0x7504572b,
+	0x91d2c001,
+	0x0a42c809,
+	0x0a30c0ec,
+	0x5cadb580,
+	0x430cb720,
+	0x0a42c809,
+	0x0a40c06c,
+	0x5d2db580,
+	0x430cb720,
+	0x44b5b760,
+	0x46b5b740,
+	0x452db740,
+	0x472db780,
+	0x572bb760,
+	0x6127c101,
+	0x6245c101,
+	0xd02074c0,
+	0xc00102c4,
+	0xb7409024,
+	0xb78048ad,
+	0x6245492d,
+	0x06d8c101,
+	0x9300c000,
+	0x0a42c809,
+	0x0a30c0aa,
+	0x5cadb580,
+	0x430cb720,
+	0x0a42c809,
+	0x0a40c080,
+	0x5d2db580,
+	0x430cb780,
+	0xa905f248,
+	0xaa09f248,
+	0x62c4d032,
+	0x430cb720,
+	0x0a02c100,
+	0xb5809e6b,
+	0xb7a05ead,
+	0x008b430c,
+	0x5eb5b760,
+	0x99d7c2f4,
+	0xb500008b,
+	0xb7a05ead,
+	0xf248430c,
+	0x7500aa35,
+	0x9242c000,
+	0xb760008b,
+	0x01895eb5,
+	0x61c7d132,
+	0x2d81cffc,
+	0x99c3c2f4,
+	0xc0007400,
+	0x008b90a2,
+	0x5eadb500,
+	0x430cb720,
+	0x5e19d2a2,
+	0x5dadb580,
+	0x4314b740,
+	0xaa4df050,
+	0xa945f050,
+	0x1a040244,
+	0xa24df050,
+	0x430cb7a0,
+	0xaaa6f248,
+	0xa9aef248,
+	0xc2f49e6b,
+	0xc10199a4,
+	0xf248600b,
+	0xb720a02d,
+	0xb720430c,
+	0xb78046b5,
+	0xb740472d,
+	0xb7604535,
+	0xb74044b5,
+	0xb760492d,
+	0xc10148ad,
+	0x65276243,
+	0xc1016127,
+	0x02440244,
+	0x5a19c200,
+	0x5e2db580,
+	0x430cb740,
+	0xaa45f008,
+	0x7d3ec004,
+	0x90e4c001,
+	0xaa51f008,
+	0x2a7ce002,
+	0x9024c001,
+	0x01899ea2,
+	0x91c0c000,
+	0x5f4db560,
+	0x430cb720,
+	0xb56000a2,
+	0xb72067ad,
+	0x00a2430c,
+	0x65adb560,
+	0x430cb720,
+	0x6d21d131,
+	0x4629b78a,
+	0x00a2d020,
+	0x0d047299,
+	0x9146ffff,
+	0xb5800a02,
+	0xb79f712d,
+	0xb7bf776e,
+	0xb7df77ee,
+	0xb7ff786e,
+	0xc00878ee,
+	0x9c228c40,
+	0xb7a0a605,
+	0x0e86430c,
+	0xb763008b,
+	0xb7a35b35,
+	0xc2005bad,
+	0xc00e55ac,
+	0xffd42dfc,
+	0xb72099e5,
+	0x9eaa430c,
+	0x0982c008,
+	0x6c31b76d,
+	0x0918d191,
+	0x98bbff74,
+	0x430cb720,
+	0x5b35b743,
+	0x56a8c200,
+	0x2dded3f2,
+	0x9a5dffd4,
+	0x430cb720,
+	0x0a18d191,
+	0x612db582,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0xb7a0a605,
+	0x0e86430c,
+	0xb763008b,
+	0xb7a35b35,
+	0xc2005bad,
+	0xc00e55ac,
+	0xffd42dfc,
+	0xb72099b5,
+	0x9eaa430c,
+	0x0982c008,
+	0x6c31b76d,
+	0xc0180103,
+	0xff740930,
+	0xb720988a,
+	0xb743430c,
+	0xc2005b35,
+	0xd3f256a8,
+	0xb79f2dde,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0x90e0ffd1,
+	0xb7a0a60d,
+	0xb7204994,
+	0x09024c8c,
+	0x0d96050b,
+	0xb9600185,
+	0x0a024038,
+	0x0a20c146,
+	0x02426229,
+	0x0a18c144,
+	0xa182f208,
+	0xf0310904,
+	0xffffa1d5,
+	0xb7409281,
+	0xc809478c,
+	0xcbdc0a46,
+	0xf0480a30,
+	0xf008a1c1,
+	0x0287a255,
+	0xffd40b06,
+	0xf23199c6,
+	0xd3f1aa35,
+	0x0d82295e,
+	0x9eb27500,
+	0xc0000a84,
+	0x9e5b90e2,
+	0x4508b5c0,
+	0x9a44ffb4,
+	0xffff7550,
+	0xb79f9204,
+	0xb7bf7eee,
+	0xb7df7f6e,
+	0x8c607fee,
+	0x5db09c22,
+	0x0d80c021,
+	0x0da0c102,
+	0xaa619d3e,
+	0xc40059b8,
+	0xcbfe2980,
+	0x32462a7d,
+	0xf0009dbe,
+	0x9c22a261,
+	0x430cb720,
+	0x9e5b0926,
+	0x6735b744,
+	0xd0110802,
+	0x75101e22,
+	0x4826b322,
+	0x9c8bc010,
+	0x9160c000,
+	0xaa01d208,
+	0xc0007106,
+	0xc00e90a4,
+	0x9c22287c,
+	0x02030804,
+	0x0a74c098,
+	0xffff0884,
+	0xc00e9261,
+	0x9c22087e,
+	0xb740a605,
+	0xd1a2430c,
+	0x00d45e88,
+	0x6fadb789,
+	0x02446a32,
+	0x0a20c138,
+	0xa911d208,
+	0xd2080904,
+	0xb740a111,
+	0x00d4430c,
+	0x6fadb789,
+	0x02446a32,
+	0x0a20c138,
+	0xaa11d208,
+	0xc0007502,
+	0xc00e90d4,
+	0xc001087e,
+	0xc10192c0,
+	0x090200a6,
+	0x4829b54c,
+	0x430cb720,
+	0x5e18d1a2,
+	0x0982c004,
+	0x04b3d110,
+	0x5914b760,
+	0x4929b54c,
+	0x01c7d120,
+	0x430cb780,
+	0xc05e0258,
+	0xf2080a60,
+	0xb720a101,
+	0xb543430c,
+	0xb720402d,
+	0x00d2430c,
+	0x40adb543,
+	0x430cb720,
+	0x41adb543,
+	0x9a2fff34,
+	0x430cb740,
+	0xb78900d4,
+	0x6a326fad,
+	0xc1380244,
+	0xd2080a20,
+	0xb79fa811,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xb7609c22,
+	0x0d02430c,
+	0x4078b960,
+	0x0134c101,
+	0xc1360205,
+	0xd2080a2c,
+	0x7500aa01,
+	0x92a4c000,
+	0x0920c136,
+	0xd0080a04,
+	0xb740a24d,
+	0xd031430c,
+	0xc00e6e29,
+	0x02442d7c,
+	0x0a20c138,
+	0xd208097f,
+	0xc000a111,
+	0x0d0490e0,
+	0x9041ffff,
+	0x0d7ec00e,
+	0x9c229e50,
+	0xb720a61d,
+	0x9e5f430c,
+	0xc0a40203,
+	0xd2080a10,
+	0xb7caaa01,
+	0x75004729,
+	0x93a4c005,
+	0x5a88c300,
+	0x02d2d020,
+	0xb7899e69,
+	0xc01c6fad,
+	0xc001753e,
+	0x9eb39004,
+	0xfff49eae,
+	0x9e699bbc,
+	0x9180c000,
+	0x984cffb4,
+	0x430cb7a0,
+	0xd1109eb3,
+	0xfff406eb,
+	0x008b9bb0,
+	0x6fadb509,
+	0x430cb720,
+	0xd1100d92,
+	0xb78904e3,
+	0xc01c6fad,
+	0xffff753e,
+	0xb7209162,
+	0xc300430c,
+	0xd0205908,
+	0x9e8a00a2,
+	0x6fcdb789,
+	0x0d10c09c,
+	0x00c26a32,
+	0x712db729,
+	0x568cb780,
+	0xe0409e8b,
+	0xd010a1c6,
+	0x7500aa41,
+	0x9284c003,
+	0xc0009eb3,
+	0xffb491c0,
+	0xb7809819,
+	0x9eb3430c,
+	0x0a10c0a4,
+	0xaa01d208,
+	0xc0037500,
+	0xfff49184,
+	0xc01c9b1b,
+	0x0d92743e,
+	0x91e2ffff,
+	0xc00175c0,
+	0xb7209062,
+	0x0982430c,
+	0xb76a9e9a,
+	0xb72a46b1,
+	0xd1a24729,
+	0x01095e30,
+	0x0900c021,
+	0x0930c140,
+	0x91a0c000,
+	0xf0009dad,
+	0xd011a162,
+	0x9dcd0a28,
+	0xa162f000,
+	0xc1000984,
+	0xc1010900,
+	0x71020236,
+	0x925cffff,
+	0x4314b720,
+	0x5988d324,
+	0x59b0c300,
+	0x04b2d010,
+	0x0980c021,
+	0x6fb5b749,
+	0x09c0c146,
+	0x6d29d031,
+	0x0624d010,
+	0x0122c101,
+	0x0920c138,
+	0xa951d008,
+	0x0244c101,
+	0xc2000244,
+	0xc1015a08,
+	0xb78000c2,
+	0xb7294f8c,
+	0x9ea270ad,
+	0xa0e9e020,
+	0xf0009dbd,
+	0xb786a0e1,
+	0x750040c9,
+	0x9184c000,
+	0x53cbb78c,
+	0xc0007500,
+	0xb76690e2,
+	0x9eb34a4d,
+	0x99cbff94,
+	0x430cb780,
+	0xc09c0906,
+	0xd2080a10,
+	0xb79fa101,
+	0xb7bf7e6e,
+	0xb7df7eee,
+	0xb7ff7f6e,
+	0xc0027fee,
+	0x9c228c00,
+	0xb720a605,
+	0x9e5d430c,
+	0x63adb744,
+	0xc0017ca0,
+	0xb7819202,
+	0x75045dad,
+	0x90e4c000,
+	0x5a21c100,
+	0xb5842a04,
+	0xb7207e2b,
+	0xb781430c,
+	0x1a105dad,
+	0xc0007502,
+	0x0a0690b2,
+	0x7f2bb584,
+	0x430cb720,
+	0x6e29b788,
+	0x9e8b0183,
+	0x5333b741,
+	0x6aadb749,
+	0x098cc026,
+	0xc04a01b8,
+	0x9e940df0,
+	0xb7209c62,
+	0xb784430c,
+	0xcffe63ad,
+	0xb5842a3d,
+	0xb72063ad,
+	0xb78c430c,
+	0x7500532b,
+	0x9222c001,
+	0x6cadb744,
+	0xc0007484,
+	0xb7819124,
+	0x75004bad,
+	0x9084c001,
+	0x9140c000,
+	0xc0007482,
+	0xb78190e4,
+	0x75024b2d,
+	0x9344c000,
+	0xc09c0203,
+	0xd2080a14,
+	0x7500aa01,
+	0x9244c000,
+	0xc0007486,
+	0x02039144,
+	0x0a40c09a,
+	0xaa01d208,
+	0xc0007500,
+	0xb78190e4,
+	0x750a5dad,
+	0x90a4c000,
+	0xb58c0a02,
+	0xb720532b,
+	0x0203430c,
+	0x0a18c0a4,
+	0xaa01d208,
+	0x6cb5b764,
+	0xc0007500,
+	0xb74193e2,
+	0xb70953ab,
+	0xb76c6c2d,
+	0x9eaa532b,
+	0x9c629e84,
+	0x430cb720,
+	0x5dadb781,
+	0x75021a10,
+	0x90f2c000,
+	0x532bb78c,
+	0xc0017500,
+	0x02039064,
+	0x0a20c09c,
+	0xa001d208,
+	0x9380c000,
+	0xc00076c4,
+	0xb7499164,
+	0x020375a9,
+	0x0a20c09c,
+	0xa101d208,
+	0x9200c000,
+	0x76c60103,
+	0x0920c09c,
+	0x90c4c000,
+	0x7629b789,
+	0x9080c000,
+	0x7529b789,
+	0xa241d008,
+	0x430cb720,
+	0x5dadb781,
+	0x75021a10,
+	0x90f2c000,
+	0x532bb78c,
+	0xc0007500,
+	0xb74a9344,
+	0xb76046a9,
+	0x01835514,
+	0x09a0c09c,
+	0x9140c000,
+	0xaa61d008,
+	0x9e529e91,
+	0xa229c030,
+	0x297cc00e,
+	0x4729b78a,
+	0x0922d012,
+	0xffff7104,
+	0xb79f9268,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xb7209c22,
+	0x05964314,
+	0x0da0c098,
+	0xa8edd010,
+	0x6e4db704,
+	0x4000ba09,
+	0xd001747f,
+	0xb3401802,
+	0x009248a2,
+	0x0092c101,
+	0x532bb789,
+	0x2a60c00e,
+	0x5a0fc200,
+	0x9c220040,
+	0xb7a0a61d,
+	0x0687430c,
+	0x020b9e9e,
+	0x0a58c096,
+	0xa982d208,
+	0xfff49e57,
+	0x020b9bda,
+	0x0a54c096,
+	0xa982d208,
+	0xfff40301,
+	0x020b9bd2,
+	0x0a50c096,
+	0xaa01d208,
+	0x9e819ea8,
+	0xc0980258,
+	0xd2080a20,
+	0xb744aa0d,
+	0xba246e4c,
+	0x753f4000,
+	0x19a2d001,
+	0x9202c000,
+	0xc096020b,
+	0xd2080a30,
+	0x0092a881,
+	0xb789009a,
+	0xc00e532b,
+	0xc2002a60,
+	0x01c45a0f,
+	0xc0007780,
+	0x9eaa9102,
+	0xc0260d82,
+	0xc0010d50,
+	0x75c69320,
+	0x91e2c000,
+	0xd01d7186,
+	0xd01e1266,
+	0xd012123c,
+	0xd03119c2,
+	0xc0286e39,
+	0xc0010a00,
+	0x020b90e0,
+	0x0a08c098,
+	0xaa01d208,
+	0xc0007500,
+	0x9e699222,
+	0x0a02c409,
+	0x622db580,
+	0x0a42c001,
+	0x0a00c010,
+	0x6335b5c0,
+	0x62adb580,
+	0x9220c001,
+	0x0c0270d3,
+	0x1617d11e,
+	0x1233d11d,
+	0x1942d012,
+	0x7280cc12,
+	0x6e39d031,
+	0x0a60c09c,
+	0x0158d020,
+	0xaa49f010,
+	0x76c09e69,
+	0x622db580,
+	0xaa45f010,
+	0x62adb580,
+	0xaa41f010,
+	0x632db580,
+	0x9236c000,
+	0x5d60d0a2,
+	0x2a6ed3f1,
+	0x5a20c200,
+	0xd3f13244,
+	0xc00e293e,
+	0x59403a7c,
+	0xb5803244,
+	0xb79f622d,
+	0xb7bf7e6e,
+	0xb7df7eee,
+	0xb7ff7f6e,
+	0xc0027fee,
+	0x9c228c00,
+	0x8420a605,
+	0x430cb720,
+	0xb5bf0a82,
+	0xb72a7e6a,
+	0xb72046a9,
+	0x04075514,
+	0x02079e8b,
+	0xa969c010,
+	0x04859e43,
+	0x8c80e031,
+	0xff749ea2,
+	0xb7209b4b,
+	0x018b430c,
+	0x46b1b76a,
+	0x984bff94,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x9c228c60,
+	0x4314b720,
+	0x5cb0d1a2,
+	0xb7859e9a,
+	0xc1407ec9,
+	0xc0210880,
+	0xc2000880,
+	0xc0205a24,
+	0x3a042a00,
+	0xf0009d9d,
+	0x0185a261,
+	0xff820906,
+	0xf8399320,
+	0x8420a205,
+	0x430cb720,
+	0xb59f0a02,
+	0xb7417e6a,
+	0x02035f2b,
+	0x0a20c09c,
+	0xd2087480,
+	0xc000a981,
+	0xb7409104,
+	0xe0326ead,
+	0xfff48d00,
+	0xf9f89bd3,
+	0x9c22aa19,
+	0xa205f839,
+	0xb7208420,
+	0x0a02430c,
+	0x7e6ab59f,
+	0x5f2bb741,
+	0x74809ea2,
+	0x9204c000,
+	0xc0a40203,
+	0xd2080a14,
+	0xb720a102,
+	0xe032430c,
+	0x09ea8d00,
+	0x6cadb740,
+	0x9bb4fff4,
+	0xaa19f9f8,
+	0xa6059c22,
+	0x430cb720,
+	0xb7810687,
+	0x75045dad,
+	0x93c4c000,
+	0x558cb780,
+	0xc0409e5a,
+	0x7500aa45,
+	0x9142c000,
+	0x2ebed3f1,
+	0xfff49eab,
+	0x9eab9bb2,
+	0x9180c000,
+	0xc0a40203,
+	0xd2080a14,
+	0x7500aa01,
+	0x90c2c000,
+	0x2dfcc00e,
+	0x9bbefff4,
+	0x430cb720,
+	0xc09c0203,
+	0xd2080a18,
+	0x7500aa01,
+	0x9162c001,
+	0x5dadb781,
+	0xc0017504,
+	0xb78690c4,
+	0x75004129,
+	0x9022c001,
+	0x558cb780,
+	0xc0409e6a,
+	0x7500aa45,
+	0x9142c000,
+	0x68adb760,
+	0x2dded3f2,
+	0x09060d02,
+	0x9bd6ff74,
+	0x430cb720,
+	0x2dded3f2,
+	0xb7600d02,
+	0x0906692d,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0xff7e8c40,
+	0xb79f90e0,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xa61d9c22,
+	0x558cb740,
+	0x4314b720,
+	0x9e920a02,
+	0xc0200687,
+	0xb741a269,
+	0xd0115dcd,
+	0x75021a28,
+	0x9172c000,
+	0x534bb78c,
+	0xc0007500,
+	0xb74090c2,
+	0xc0006e55,
+	0xb7849140,
+	0xc2006ccd,
+	0xc1015a08,
+	0xb74000c2,
+	0x748a6cb5,
+	0x90a2c000,
+	0xc0000906,
+	0xb78090e0,
+	0x9e6b500c,
+	0xa965c040,
+	0x46d1b76a,
+	0xb7409e53,
+	0xc0205514,
+	0xff74a96a,
+	0xb7209b8b,
+	0xb7814314,
+	0x1a105dcd,
+	0xc0037502,
+	0xb78c91b2,
+	0x7500534b,
+	0x9102c003,
+	0x0ed2d011,
+	0x0b02c008,
+	0x5ab0c280,
+	0xc0219eae,
+	0x0f400f00,
+	0xf0009dee,
+	0x010ba361,
+	0x0900c040,
+	0x0900c021,
+	0xaa619d2d,
+	0x3a40c002,
+	0xf0009dad,
+	0xd2a2a261,
+	0x9ead5c88,
+	0x0092c101,
+	0x6fb5b749,
+	0x0e80c021,
+	0xd0310ea0,
+	0xd0106d29,
+	0xc1010624,
+	0xc1380122,
+	0xd0080920,
+	0xc101a951,
+	0x02440244,
+	0x5a08c200,
+	0x00c2c101,
+	0x0a02c401,
+	0x70adb7e9,
+	0x0a00c008,
+	0xf0009dde,
+	0x9eaba261,
+	0x09929eb2,
+	0xff14010d,
+	0x0a0299f6,
+	0xf0009dde,
+	0x9deea261,
+	0xa361f000,
+	0xc021020b,
+	0xc0400a00,
+	0x9d4d0a20,
+	0x1a10a962,
+	0xaa619d4d,
+	0x0a80c021,
+	0x0ac0c046,
+	0xa9619d5d,
+	0xc0007480,
+	0xd12290e2,
+	0x112e5e35,
+	0x11282a7c,
+	0x430cb720,
+	0x76adb544,
+	0x7e6eb79f,
+	0x7eeeb7bf,
+	0x7f6eb7df,
+	0x7feeb7ff,
+	0x8c00c002,
+	0xa6059c22,
+	0x068774c0,
+	0x9324c000,
+	0x500cb780,
+	0xc0409e5a,
+	0x7500aa45,
+	0x9222c000,
+	0x430cb720,
+	0xc09c0203,
+	0xd2080a10,
+	0x7500aa01,
+	0x90e2c000,
+	0x4729b78a,
+	0xc0017117,
+	0xb7209302,
+	0x0203430c,
+	0x0a38c0a2,
+	0xaa01d208,
+	0xc0007500,
+	0x010393c4,
+	0x4729b78a,
+	0x091cc0a4,
+	0xa941d008,
+	0x4629b76a,
+	0x124ac101,
+	0xd0126245,
+	0xc10119b2,
+	0xc0a2029a,
+	0xc1010ac0,
+	0xd20805b8,
+	0xc2b4aaa5,
+	0x08049bcf,
+	0xc0007140,
+	0xb7409244,
+	0xd2a24f94,
+	0xd2a25e30,
+	0x9e535d08,
+	0x0a00c021,
+	0xa945e030,
+	0x0a40c146,
+	0xf0009dcd,
+	0xb79fa161,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xa60d9c22,
+	0x030774c6,
+	0xc0009e5d,
+	0x74c490a2,
+	0x90a4c000,
+	0xc0009eb6,
+	0xb74092c0,
+	0x0205430c,
+	0x0a14c09c,
+	0xaa01d208,
+	0xc0007500,
+	0x0f0690a4,
+	0x9120c000,
+	0xc06e0205,
+	0x71480a10,
+	0xd0020f02,
+	0xf2080f62,
+	0xb720aa31,
+	0x73994314,
+	0x9344c000,
+	0x58cdb783,
+	0xa221f208,
+	0x430cb720,
+	0x592db723,
+	0xa0a5f208,
+	0x430cb720,
+	0x59adb723,
+	0xa0a9f208,
+	0x430cb720,
+	0x5a2db723,
+	0xa0adf208,
+	0x90e0c001,
+	0x5c88d322,
+	0x46d1b76a,
+	0x0092c101,
+	0x6a35b740,
+	0x09c2c010,
+	0xff34010b,
+	0xb7209aea,
+	0xf208430c,
+	0xb583aa21,
+	0xb72058ad,
+	0xf208430c,
+	0xb583aa25,
+	0xb720592d,
+	0xf208430c,
+	0xb583aa29,
+	0xb72059ad,
+	0xf208430c,
+	0xb583aa2d,
+	0xb7205a2d,
+	0xd0524314,
+	0xb7880ad8,
+	0xba0c6c49,
+	0xc0004008,
+	0x5888922a,
+	0x0092c101,
+	0x46d1b76a,
+	0x46b5b742,
+	0xc00e9e6a,
+	0xff3409f2,
+	0x0a169abc,
+	0xa231f208,
+	0xaa21d210,
+	0x0982c400,
+	0x0902c200,
+	0xa221f210,
+	0xa92ef208,
+	0x2d7dc9fe,
+	0xa12ef208,
+	0x430cb720,
+	0x752db784,
+	0xb3437500,
+	0x75004422,
+	0x4422b342,
+	0x9e533126,
+	0xf2083126,
+	0xb720a12d,
+	0xb784430c,
+	0x75026cad,
+	0x90c2c000,
+	0x3900c020,
+	0xa12df208,
+	0xaa2df208,
+	0x3a00c010,
+	0xa22df208,
+	0x430cb720,
+	0x6cadb784,
+	0xc0007506,
+	0xf20891c4,
+	0xc080aa21,
+	0xc0007d00,
+	0x010391c2,
+	0x0914c098,
+	0xc0000a02,
+	0x010390c0,
+	0x0914c098,
+	0xd0080a0a,
+	0xf208a241,
+	0xc040aa21,
+	0xc0027d00,
+	0xb72093a2,
+	0xb784430c,
+	0x75046cad,
+	0x92c4c002,
+	0xc0980183,
+	0xd0080990,
+	0x7480a961,
+	0x91c4c002,
+	0x702db784,
+	0x7d3edffd,
+	0x92c2c000,
+	0xc0980203,
+	0xd2080a08,
+	0x7500aa01,
+	0x9082c001,
+	0xc0980203,
+	0xd2080a0c,
+	0x7500aa01,
+	0x9382c000,
+	0xa161d008,
+	0x90a0c001,
+	0x01030203,
+	0x0a58c096,
+	0x0954c096,
+	0xa902d208,
+	0xaa41d008,
+	0xc0007299,
+	0xb7859164,
+	0x75007ea9,
+	0x90c4c000,
+	0xa261d008,
+	0x91e0c000,
+	0xc0980103,
+	0x0a060910,
+	0xa241d008,
+	0x430cb780,
+	0xc0980902,
+	0xd2080a14,
+	0xb780a101,
+	0xc098430c,
+	0xd2080a10,
+	0x7500aa01,
+	0x9102c000,
+	0xaa2df208,
+	0x2a7dcfbe,
+	0xa22df208,
+	0x430cb720,
+	0x5dadb781,
+	0xc0007504,
+	0xf2089102,
+	0xcfdeaa2d,
+	0xf2082a7d,
+	0xb720a22d,
+	0xb781430c,
+	0x75045dad,
+	0x9304c001,
+	0xa92df208,
+	0x0a5ecfff,
+	0x0a7cc7fe,
+	0x2128d020,
+	0xa12ef208,
+	0x430cb720,
+	0xc09a0203,
+	0xd2080a40,
+	0x7500aa01,
+	0x90e2c000,
+	0x4b2db781,
+	0xc0007502,
+	0xb78690e4,
+	0x75004029,
+	0x9142c000,
+	0xc8009e53,
+	0x32262900,
+	0x3a20c001,
+	0xa22df208,
+	0x430cb720,
+	0x4b2db781,
+	0xc0007502,
+	0xf2089164,
+	0xcfffaa2d,
+	0xc8fe0962,
+	0x2244097c,
+	0xa22df208,
+	0x430cb780,
+	0xa9adf208,
+	0x0d02c011,
+	0x0a08c098,
+	0xa901d208,
+	0xc0215964,
+	0x31262900,
+	0xa12df208,
+	0x430cb780,
+	0x0a0cc098,
+	0xaa01d208,
+	0x5a68c200,
+	0x2a00c041,
+	0xf2083128,
+	0xb780a12d,
+	0xcfef430c,
+	0xc098297e,
+	0xd2080a14,
+	0x7500aa01,
+	0xb3420a02,
+	0x9e544444,
+	0xf2083144,
+	0xb720a12d,
+	0xb781430c,
+	0x7500612d,
+	0x90c2c000,
+	0x3940c001,
+	0xa12df208,
+	0x430cb720,
+	0x5e2db781,
+	0xc0007508,
+	0xb78191a4,
+	0x75045dad,
+	0x9104c000,
+	0xaa2df208,
+	0x3a00c201,
+	0xa22df208,
+	0x9eab7780,
+	0x09829eb2,
+	0x09b2d001,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0xffdd8c60,
+	0xf8399320,
+	0x04b6a285,
+	0xb7600407,
+	0x9e485114,
+	0x518cb780,
+	0xa8aac030,
+	0x5094b760,
+	0xc00f59c0,
+	0xc84029fc,
+	0xc030aa05,
+	0x9e9da98a,
+	0x5a20c200,
+	0x76c0349a,
+	0xe0329e48,
+	0xcff08d80,
+	0x32082a00,
+	0xa9f9d9d0,
+	0x90c2c000,
+	0x3a00c201,
+	0x90e0c000,
+	0xc0007680,
+	0xc1019082,
+	0x74803a00,
+	0x9082c000,
+	0x3a00c011,
+	0xc0007440,
+	0x74c09122,
+	0x3a00c021,
+	0x9082c000,
+	0x3a00c041,
+	0x5d08d028,
+	0x549cb740,
+	0xe0209e2d,
+	0xf9f8a26d,
+	0x9c22aa9d,
+	0x8420a61d,
+	0x558cb780,
+	0xb7c09e5e,
+	0xc2404314,
+	0xa199aa45,
+	0x9e8f9e73,
+	0x8c80e0b1,
+	0x09c4c09a,
+	0x9e937500,
+	0xabe1d008,
+	0x7e29b7bf,
+	0x7e33b7bf,
+	0x7d33b73f,
+	0x9244c000,
+	0xb7849e71,
+	0x7500752d,
+	0x90e4c000,
+	0x6cadb784,
+	0xc0007502,
+	0x9e7190e2,
+	0x6cadb704,
+	0x9060c000,
+	0x77400802,
+	0x9142c000,
+	0xb7849e71,
+	0xd1106c2d,
+	0x9ea30639,
+	0x2dfccffe,
+	0xc09c9e74,
+	0xd2080a18,
+	0x7480a901,
+	0x90a4c000,
+	0xc0019e90,
+	0x9e749100,
+	0x0a38c0a2,
+	0xaa01d208,
+	0xc0007500,
+	0x0c0690a2,
+	0x93a0c000,
+	0xc1019e71,
+	0xb78a01ec,
+	0x710c4729,
+	0x9124c000,
+	0xc0a20207,
+	0xd2080a20,
+	0xc000a812,
+	0x010791c0,
+	0xc0a20207,
+	0xc0a20924,
+	0xd2080a20,
+	0xd008aa11,
+	0xd020a951,
+	0x75421044,
+	0x90d2c000,
+	0x00ecc101,
+	0x4a31b56a,
+	0xc0007640,
+	0x9e719104,
+	0x6729b786,
+	0xc0067500,
+	0xb7209062,
+	0x5d184314,
+	0x5908c380,
+	0x049dd110,
+	0x684db784,
+	0x4a31b76a,
+	0x2d00c03c,
+	0x5a38c200,
+	0x2a00cc00,
+	0x4b29b76a,
+	0x2970c002,
+	0x31289e51,
+	0xb78c5de0,
+	0x3122534b,
+	0x59c09e59,
+	0x31263122,
+	0xd0117500,
+	0xd0202a06,
+	0xc00031a8,
+	0xc0809082,
+	0x9e4c3d80,
+	0x0a18c09c,
+	0xaa01d208,
+	0xc0007500,
+	0xc0409082,
+	0x77c03d80,
+	0x9082c000,
+	0x3d80c100,
+	0x570cb780,
+	0x5938d324,
+	0x5d40d022,
+	0xaa45c240,
+	0x2d00cc00,
+	0xc2009e51,
+	0xc2805a08,
+	0x324259e0,
+	0xc00f3246,
+	0xd020297c,
+	0x9e4c3144,
+	0xc0967740,
+	0xd2080a50,
+	0xb740aa01,
+	0xd002590c,
+	0xc2003d24,
+	0xc1015a08,
+	0xf208024c,
+	0xc380aa11,
+	0xc101588c,
+	0x75000092,
+	0x5a18c300,
+	0xa9190244,
+	0x3d22d002,
+	0xf2080289,
+	0xb721a109,
+	0xc12461af,
+	0xf2080e82,
+	0xf208a18e,
+	0xfa08a112,
+	0x9e6ba081,
+	0x9eb39eaa,
+	0xfef40ec0,
+	0xc2509a52,
+	0x0ac07740,
+	0x92e4ffff,
+	0x568cb780,
+	0x5a88d324,
+	0xd1109eb3,
+	0xc00406d9,
+	0xf2080982,
+	0xc124a922,
+	0xfef40902,
+	0x9eb39bed,
+	0x9804ff14,
+	0xb7869e71,
+	0x75006729,
+	0x92c2c000,
+	0x4f8cb740,
+	0xf208aa19,
+	0xd110a922,
+	0x0a3c0555,
+	0xa9c1f008,
+	0x0d00c004,
+	0xa122f208,
+	0x2a410246,
+	0xa241f008,
+	0x9300c000,
+	0xa922f208,
+	0xc0049eb3,
+	0xc1240982,
+	0xff140902,
+	0x9eb39be0,
+	0x7deeb79f,
+	0x7e6eb7bf,
+	0x7eeeb7df,
+	0x7f6eb7ff,
+	0x8c20c002,
+	0x9280fefe,
+	0x7deeb79f,
+	0x7e6eb7bf,
+	0x7eeeb7df,
+	0x7f6eb7ff,
+	0x8c20c002,
+	0xb7209c22,
+	0x9e5a430c,
+	0xc0a20203,
+	0xd2080a38,
+	0x7500aa01,
+	0x9222c000,
+	0x02039e8a,
+	0x0d20c0a4,
+	0x0a40c0a2,
+	0xa901d208,
+	0xaa41d010,
+	0x70880802,
+	0x0802d003,
+	0xb7859c22,
+	0x75007ea9,
+	0x9162c000,
+	0x500cb780,
+	0xaa45c040,
+	0xc0007500,
+	0x08069082,
+	0x02229c22,
+	0xc0a20109,
+	0xc0a20920,
+	0xd2080a40,
+	0xd008aa05,
+	0x0802a951,
+	0xd0037104,
+	0x9c220802,
+	0x430cb720,
+	0x02030c06,
+	0x0a20c136,
+	0xa902d208,
+	0x46b1b76a,
+	0xa886d228,
+	0x19049e52,
+	0xc0007097,
+	0xb74a9096,
+	0x9e404729,
+	0x29aed3f1,
+	0x7913520c,
+	0x90a4c000,
+	0xffff7095,
+	0xd0319244,
+	0x6a520a24,
+	0x478cb740,
+	0xd0310244,
+	0xf0080948,
+	0x7508aa41,
+	0xc1360203,
+	0xb4020a20,
+	0xd2084a22,
+	0x9c22a181,
+	0x430cb740,
+	0xc1360205,
+	0xd2080a24,
+	0x7500aa01,
+	0x90e4c000,
+	0xc1360205,
+	0xd2080a20,
+	0x9e5aa182,
+	0xc2000a06,
+	0xb7405208,
+	0xc136430c,
+	0xd0080924,
+	0x9e53a942,
+	0xd0083246,
+	0x9c22a241,
+	0x9e5da605,
+	0x9080c000,
+	0x9846ff74,
+	0x430cb780,
+	0xc1360d92,
+	0xd2080a20,
+	0x710aaa01,
+	0x92c4ffff,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0x550cb780,
+	0xb7209e5a,
+	0xc040430c,
+	0x5db0aa45,
+	0x67adb741,
+	0x2a7cc002,
+	0x0d80c021,
+	0xc1163244,
+	0x9dbe0df0,
+	0xa261f000,
+	0xa60d9c22,
+	0x430cb720,
+	0x02039e5e,
+	0x0a30c096,
+	0xaa01d208,
+	0xc0047500,
+	0xb7a49344,
+	0xb76468ad,
+	0x7540672d,
+	0x9222c000,
+	0x67b5b744,
+	0xc000729b,
+	0x02039188,
+	0x0a34c096,
+	0xa901d208,
+	0x1254c101,
+	0xc0007104,
+	0x74c090c6,
+	0x9022c004,
+	0x01030287,
+	0x67adb784,
+	0x0934c096,
+	0xa941d008,
+	0x71041258,
+	0x92a8c003,
+	0x46b1b76a,
+	0xc2000e86,
+	0xc00e55ac,
+	0xff942dfc,
+	0xb7209819,
+	0xc004430c,
+	0xb78409d2,
+	0xc09667ad,
+	0x125808b4,
+	0x4029b580,
+	0x430cb720,
+	0xc0960203,
+	0xd2080a34,
+	0x1a04aa01,
+	0x4badb581,
+	0x430cb720,
+	0xc0960203,
+	0xb7410a34,
+	0xd2085c35,
+	0xb76aaa01,
+	0x010346b1,
+	0x5a1cc200,
+	0x0d01cff0,
+	0x0528c101,
+	0x0960c09c,
+	0x9acfff14,
+	0x430cb720,
+	0x46b1b76a,
+	0x55acc200,
+	0x2dfcc00e,
+	0x9871ff94,
+	0x478cb740,
+	0xaa41f048,
+	0xc0007508,
+	0xf0489084,
+	0xb720a2c2,
+	0x0203430c,
+	0x0a34c096,
+	0xaa01d208,
+	0x532bb749,
+	0xc2001a04,
+	0xcff05a0c,
+	0xc00e291d,
+	0x32442a60,
+	0x532bb589,
+	0x430cb740,
+	0xc09c0205,
+	0xd2080a14,
+	0x7500aa01,
+	0x9224c000,
+	0xc0960205,
+	0xd2080a30,
+	0x0092a881,
+	0xb7890094,
+	0xc00e532b,
+	0xc2002a60,
+	0xd2085a0f,
+	0xb720a241,
+	0xd208430c,
+	0xb744aa41,
+	0xba246e2d,
+	0x02444000,
+	0x752db584,
+	0x430cb720,
+	0x752db784,
+	0x08f0c098,
+	0x4029b580,
+	0x430cb720,
+	0x752db784,
+	0x6d2db744,
+	0xb5841244,
+	0xb79f752d,
+	0xb7bf7eee,
+	0xb7df7f6e,
+	0x8c607fee,
+	0xa61d9c22,
+	0x8460c010,
+	0x4314b7a0,
+	0x9e699e6c,
+	0x0a10c0a4,
+	0xa902d208,
+	0x5e35b7e1,
+	0xc0337680,
+	0x0a069184,
+	0x44abb585,
+	0x430cb780,
+	0x0585096a,
+	0x0a1cc09c,
+	0xa101d208,
+	0x430cb720,
+	0xb5440405,
+	0xb72079b5,
+	0xb76a430c,
+	0xba1b46a9,
+	0xc0004000,
+	0xb5049080,
+	0xb7207a55,
+	0xd110430c,
+	0x0d840637,
+	0x4731b74a,
+	0x5908c200,
+	0x00a2d020,
+	0xffff7115,
+	0x0203925c,
+	0x0a40c09a,
+	0xaa01d208,
+	0xc0007500,
+	0xb78490e2,
+	0x0a0475ad,
+	0x75adb584,
+	0x430cb740,
+	0x0930c096,
+	0xaa41d008,
+	0xd0080a04,
+	0xb780a241,
+	0x9ea2430c,
+	0xc0960109,
+	0xc0960d30,
+	0xd0100934,
+	0xd008aa41,
+	0x7104a941,
+	0x1248d011,
+	0x4442b422,
+	0x430cb720,
+	0x692db784,
+	0xb5841a04,
+	0xb740692d,
+	0x0205430c,
+	0x0a30c096,
+	0xa881d208,
+	0x00929e92,
+	0xb7890094,
+	0xc09a532b,
+	0x2a100d40,
+	0x5a0bc200,
+	0xa241d010,
+	0x4314b720,
+	0xc0969e4c,
+	0xd2080a30,
+	0x0092a881,
+	0x0092c101,
+	0x532bb789,
+	0xc0f00109,
+	0xd1242900,
+	0xc2005821,
+	0x9e435831,
+	0x70c0c812,
+	0xb5842a0c,
+	0xb7206ccd,
+	0x09044314,
+	0x9e4a0385,
+	0x0930c096,
+	0xa8c1d008,
+	0xc1010092,
+	0xb7890092,
+	0xc00e532b,
+	0xc2002a60,
+	0xb59d5a0f,
+	0xd0087468,
+	0x7500aa41,
+	0x9084c006,
+	0x67cdb784,
+	0x6e4db584,
+	0x430cb720,
+	0x4835b745,
+	0xc0027684,
+	0xb7449182,
+	0x748067ad,
+	0x9242c000,
+	0x4b2db781,
+	0xc0007500,
+	0xb78490e2,
+	0x7500692d,
+	0x911cc000,
+	0xc0007682,
+	0x768090a2,
+	0x92e4c001,
+	0x6d2db784,
+	0x1128e000,
+	0x9142c000,
+	0x4aadb781,
+	0xc0007088,
+	0x768090a8,
+	0x93c4c000,
+	0xc09c0103,
+	0x0a060914,
+	0xa241d008,
+	0x430cb720,
+	0xb5440902,
+	0xb72075ad,
+	0xb544430c,
+	0xb720752d,
+	0xb784430c,
+	0xb58467ad,
+	0xb7206d2d,
+	0x0a7f430c,
+	0x7468b55d,
+	0x6fadb584,
+	0x430cb720,
+	0xb5840a06,
+	0xb7206cad,
+	0xb781430c,
+	0xb5844b2d,
+	0xb720692d,
+	0xc00e430c,
+	0xb5850a7e,
+	0xb720482d,
+	0xb781430c,
+	0x75065dad,
+	0x9144c000,
+	0xc09c0203,
+	0xd2080a18,
+	0x7500aa01,
+	0x9342c002,
+	0xc0980103,
+	0xd008091c,
+	0x0d86aa41,
+	0xd0080a04,
+	0xb780a241,
+	0x9ea2430c,
+	0xc0980109,
+	0xc0980d1c,
+	0xd0100918,
+	0xd008aa41,
+	0x7104a941,
+	0x1244d014,
+	0x4448b422,
+	0x93a0c000,
+	0xaa41d010,
+	0x0639d110,
+	0xa25dd008,
+	0x430cb780,
+	0x0146c101,
+	0xc0980185,
+	0xc0980a18,
+	0xd2080980,
+	0xd008a901,
+	0x0d84aa7d,
+	0xd0207104,
+	0xc0001144,
+	0xd0089086,
+	0xb720a17e,
+	0xc101430c,
+	0x01090216,
+	0xc0980203,
+	0xd2080a18,
+	0x9e8aaa01,
+	0x0900c098,
+	0x0d1cc098,
+	0xfffe72d9,
+	0xb78892b8,
+	0x02186e29,
+	0x0a00c098,
+	0xaa1dd208,
+	0xc0980218,
+	0xd2080a20,
+	0x1904a90d,
+	0xa10dd208,
+	0x4314b740,
+	0xc09a9e54,
+	0xd2080a40,
+	0x7500aa01,
+	0x91c2c001,
+	0x2bfcc00e,
+	0x062fd110,
+	0xc0989e52,
+	0xd2080a00,
+	0xc096aa1d,
+	0xd0080950,
+	0xb780a241,
+	0x0109430c,
+	0x0950c096,
+	0xa942d008,
+	0xa941d1e8,
+	0x0244c101,
+	0x0a20c098,
+	0xa10dd208,
+	0x430cb720,
+	0xc0960203,
+	0xd2080a50,
+	0xb744aa01,
+	0xc20075ad,
+	0x00c25a08,
+	0x722db544,
+	0x92a0c001,
+	0xc0989e54,
+	0xd2080a18,
+	0xd110a901,
+	0xc0980525,
+	0xd0080900,
+	0x0a04aa5d,
+	0xa25dd008,
+	0x430cb780,
+	0xc0980109,
+	0xd0080918,
+	0x0228a941,
+	0x09089ea2,
+	0x0d00c098,
+	0xaa5dd010,
+	0xc0007104,
+	0x1a0890b8,
+	0xa25dd010,
+	0x430cb780,
+	0xc0980109,
+	0xd0080918,
+	0x9ea2a941,
+	0xc0980244,
+	0xd2080a00,
+	0xc096aa1d,
+	0xd0100d50,
+	0xb740a241,
+	0xc101430c,
+	0xc0980220,
+	0xd2080a00,
+	0xc096aa1d,
+	0xd0080954,
+	0xb720a241,
+	0xb748430c,
+	0xb7846e29,
+	0x9e8a75ad,
+	0xc0967104,
+	0xc0000d58,
+	0x02109134,
+	0x0a00c098,
+	0xaa1dd208,
+	0x90e0c000,
+	0xc0960203,
+	0xd2080a54,
+	0xd010aa01,
+	0xb740a241,
+	0x9e69430c,
+	0xc0980d02,
+	0xb7850910,
+	0xd0087e29,
+	0xb720a142,
+	0x75004314,
+	0x6ccdb764,
+	0x90c2c000,
+	0x6acdb781,
+	0x9080c000,
+	0x6b4db781,
+	0xb58474c6,
+	0xc00063cd,
+	0x74c29182,
+	0x9222c000,
+	0x430cb720,
+	0x63adb784,
+	0xc0003a04,
+	0xb7209100,
+	0xb784430c,
+	0xc00863ad,
+	0xb5843a00,
+	0xb78063ad,
+	0xc096430c,
+	0xd2080a50,
+	0xc200aa01,
+	0xc1015a08,
+	0xf2080242,
+	0x7480a911,
+	0x9222c000,
+	0xa111f248,
+	0x430cb780,
+	0xc0960902,
+	0xd2080a50,
+	0xc200aa01,
+	0xc1015a08,
+	0xf2080242,
+	0xb742a111,
+	0x76804555,
+	0x9102c002,
+	0x430cb780,
+	0x6cc9b748,
+	0x0a50c096,
+	0xaa01d208,
+	0xc2007480,
+	0xc1015a08,
+	0xf2480242,
+	0xf208a911,
+	0xb780a111,
+	0x0902430c,
+	0x454db542,
+	0x0a50c096,
+	0xaa01d208,
+	0x5a08c200,
+	0x0242c101,
+	0xa112f248,
+	0x90c2c001,
+	0x430cb720,
+	0x7ea9b785,
+	0xc0007500,
+	0x74c29202,
+	0x91a2c000,
+	0xc0980203,
+	0xd2080a00,
+	0x0103aa01,
+	0x0904c098,
+	0xc0004a04,
+	0x010390c0,
+	0x0904c098,
+	0xd0080a02,
+	0xb720a241,
+	0x0a02430c,
+	0x6cc9b588,
+	0x75adb784,
+	0x6fadb584,
+	0x430cb720,
+	0x45cdb742,
+	0xc0960203,
+	0xd2080a50,
+	0x7480aa01,
+	0x5a08c200,
+	0x0242c101,
+	0xaa11f248,
+	0x642db584,
+	0x430cb720,
+	0x9262c000,
+	0xb5440a02,
+	0xb582652d,
+	0xb74045cd,
+	0xb748430c,
+	0xb5886d51,
+	0xc0986d49,
+	0xd0080908,
+	0xc001a142,
+	0x020390c0,
+	0x0a54c096,
+	0xaa01d208,
+	0x5a08c200,
+	0x0242c101,
+	0xaa11f248,
+	0x652db584,
+	0x430cb720,
+	0xc0960203,
+	0xd2080a54,
+	0xb744aa01,
+	0x9e8a6f2d,
+	0x5a08c200,
+	0xb72400c2,
+	0x0a02722d,
+	0x0d08c098,
+	0xd0017082,
+	0xd0100a42,
+	0xb742a241,
+	0xb720464d,
+	0x7480430c,
+	0x9262c000,
+	0xb5440a02,
+	0xb582662d,
+	0xb740464d,
+	0xb748430c,
+	0xb5886dd1,
+	0xc0986dc9,
+	0xd008090c,
+	0xc001a142,
+	0x020390c0,
+	0x0a58c096,
+	0xaa01d208,
+	0x5a08c200,
+	0x0242c101,
+	0xaa11f248,
+	0x662db584,
+	0x430cb720,
+	0xc0960203,
+	0xd2080a58,
+	0xb744aa01,
+	0x9e8a6f2d,
+	0x5a08c200,
+	0xb72400c2,
+	0x0a02722d,
+	0x0d0cc098,
+	0xd0017082,
+	0xd0100a42,
+	0xb720a241,
+	0xb740430c,
+	0x048b4155,
+	0x6badb744,
+	0xb7845d10,
+	0x5910642d,
+	0xcffe097c,
+	0xc1012901,
+	0xb7426125,
+	0x02285b53,
+	0x64adb584,
+	0x430cb720,
+	0x5bcbb762,
+	0x652db784,
+	0x61b4c101,
+	0x193ed012,
+	0xb5840228,
+	0xb72065ad,
+	0x769c430c,
+	0x662db784,
+	0xb5440128,
+	0xc00066ad,
+	0x0d3a90bc,
+	0x90a0c000,
+	0xc8120d82,
+	0xb7207286,
+	0xb780430c,
+	0xd031500c,
+	0xb70a2dae,
+	0x0b0246a9,
+	0xba000f06,
+	0x02884000,
+	0x5a30c000,
+	0xc0219ea3,
+	0xc1c80d80,
+	0xc0050d90,
+	0x9e699140,
+	0xa322d208,
+	0x4f35b702,
+	0xc0037600,
+	0xb7429022,
+	0xd2114dad,
+	0x9dcd1e38,
+	0xa161f000,
+	0x4e2db742,
+	0x1e38d1f1,
+	0xf0009dcd,
+	0xb742a161,
+	0xd2114ead,
+	0x9dcd1e30,
+	0xa161f000,
+	0x4018b960,
+	0xd152048b,
+	0xb7821d38,
+	0x9dae4fad,
+	0xa261f000,
+	0x0d20d051,
+	0xf0009dad,
+	0xb742a261,
+	0xd09151ad,
+	0x9dcd1e20,
+	0xa161f000,
+	0x1e20d051,
+	0xf0009dcd,
+	0x0890a161,
+	0xffff0d10,
+	0x9e699101,
+	0x1e38d071,
+	0x4d2db742,
+	0xf0009dcd,
+	0x7e04a161,
+	0x9042c001,
+	0x1d30d072,
+	0x53cdb782,
+	0xf0009dae,
+	0xb742a261,
+	0xd011564d,
+	0x9dcd0e28,
+	0xa161f000,
+	0x72860d20,
+	0xffff0c90,
+	0x048b9224,
+	0x554db782,
+	0xf0009dbe,
+	0xb742a261,
+	0xd01155cd,
+	0x9dcd0e38,
+	0xa161f000,
+	0x1e30d091,
+	0xf0009dcd,
+	0xb720a062,
+	0xf210430c,
+	0x0507a929,
+	0x6badb724,
+	0xc00e1904,
+	0xd011297c,
+	0xc2001a12,
+	0xc00f5a40,
+	0xcf4a2a7c,
+	0x32440d01,
+	0xf0009dae,
+	0x9e69a261,
+	0xb7419e5c,
+	0xcf8068ad,
+	0x9dcd0a01,
+	0xa161f000,
+	0x692db741,
+	0x9dcd0a20,
+	0xa161f000,
+	0x682db741,
+	0x1a30c008,
+	0xf0009dcd,
+	0xb781a161,
+	0x1a0c5dad,
+	0xc0007504,
+	0x9e5c9112,
+	0x0a41cf6a,
+	0xf0009dcd,
+	0x0b04a1e1,
+	0xc1000a84,
+	0xb7200d80,
+	0x0260430c,
+	0x4729b72a,
+	0xfffa7102,
+	0x77c0925c,
+	0x9182c000,
+	0xb785048b,
+	0x75007e49,
+	0x9024c001,
+	0x59cdb582,
+	0x93a0c000,
+	0x048b9e69,
+	0x67a9b786,
+	0x6829b746,
+	0x68b1b746,
+	0x7529b589,
+	0x75a9b549,
+	0x7631b549,
+	0x430cb720,
+	0x5bcbb782,
+	0x5b4bb742,
+	0x6c2db724,
+	0xb5246244,
+	0xb582714b,
+	0xb740584d,
+	0xf048478c,
+	0x7508aa41,
+	0x90a4c000,
+	0xf0481a0c,
+	0xb720a241,
+	0x9d8f430c,
+	0x68b5b7c4,
+	0x672db7c4,
+	0x0da1cfee,
+	0x9360c000,
+	0x9b08ff34,
+	0x430cb720,
+	0x02039d8f,
+	0x0a10c0a4,
+	0xaa01d208,
+	0x0da1cfee,
+	0xc0107500,
+	0xb78493c4,
+	0x7188672d,
+	0x90e4c000,
+	0x68adb784,
+	0xc0007399,
+	0xffd49082,
+	0xb7809ad0,
+	0xc098430c,
+	0xd2080a70,
+	0xff94a982,
+	0xc01c99d3,
+	0x0281743e,
+	0xfffe0d92,
+	0xb7809322,
+	0x0906430c,
+	0x0a18c09c,
+	0xa101d208,
+	0x430cb720,
+	0xc0a20203,
+	0xd2080a70,
+	0x7500aa01,
+	0x9082c000,
+	0x532bb54c,
+	0x430cb720,
+	0x2bfcc00e,
+	0x6e29b728,
+	0xd01210f2,
+	0xcffe1992,
+	0xff942dfc,
+	0x9e699b29,
+	0x7e29b785,
+	0xc0007500,
+	0xb7209162,
+	0x0a16430c,
+	0x5eadb583,
+	0x430cb720,
+	0x422db584,
+	0x048b0d02,
+	0x7e51b545,
+	0x430cb720,
+	0x532bb78c,
+	0xc0007500,
+	0x010392e2,
+	0x0970c0a2,
+	0xaa41d008,
+	0xc0007500,
+	0xd00891e2,
+	0xb740a142,
+	0x0205430c,
+	0x0a74c0a2,
+	0xaa01d208,
+	0x0918c09c,
+	0xa241d008,
+	0x430cb720,
+	0x532bb78c,
+	0xc0007500,
+	0xb78191a2,
+	0x75065dad,
+	0x9104c000,
+	0xc09c0103,
+	0x1a0c0918,
+	0xa241d008,
+	0x430cb720,
+	0xc09c0203,
+	0xd2080a18,
+	0x7500aa01,
+	0x9302c001,
+	0x67adb784,
+	0xc0007500,
+	0x9ea190a4,
+	0x9080c000,
+	0x6135b721,
+	0x4badb786,
+	0x61adb741,
+	0x46b1b74a,
+	0x2a7cc00e,
+	0x4731b70a,
+	0x31c4d020,
+	0xc0000802,
+	0x9dcd9260,
+	0xa0e2f000,
+	0xc0210205,
+	0xc0320a00,
+	0x9dcd0a70,
+	0xa1e2f000,
+	0x9dcd0a10,
+	0xa061f000,
+	0x293ed3f2,
+	0x0da2d011,
+	0xc1807280,
+	0x02055930,
+	0x0a00c021,
+	0x0a60c032,
+	0x90b4ffff,
+	0xb5840a02,
+	0xb72079ad,
+	0x9ea3430c,
+	0xb76a9ea1,
+	0xba1b46a9,
+	0xc0004000,
+	0xf0089080,
+	0xb720a0c2,
+	0xd110430c,
+	0x0d840637,
+	0x4731b74a,
+	0x5908c200,
+	0xc09c0122,
+	0x71150940,
+	0x923cffff,
+	0x47b1b76a,
+	0x9a50ff54,
+	0xb7809e69,
+	0xb743430c,
+	0xc09a572b,
+	0x74800a44,
+	0xa281d208,
+	0x9262c008,
+	0x4314b7c0,
+	0xc09c9e74,
+	0xd2080a18,
+	0x7500aa01,
+	0x9182c007,
+	0x048d9e74,
+	0x0a44c09a,
+	0xaa01d208,
+	0xb76a9d17,
+	0xc20046d1,
+	0xc1015a08,
+	0xb74000cc,
+	0xcfee7035,
+	0xc0100ab1,
+	0x010b0986,
+	0x9905fef4,
+	0x430cb780,
+	0xa921d208,
+	0xc0a4030b,
+	0xd2080a1c,
+	0xb720a101,
+	0xd229430c,
+	0xb785a945,
+	0xc0a47ea9,
+	0x750008a0,
+	0xd0020a02,
+	0x51500a42,
+	0x4029b540,
+	0x430cb720,
+	0x582db762,
+	0x4135b760,
+	0x995fc274,
+	0x9ea80982,
+	0xc00e9e9b,
+	0xc001287c,
+	0xd20893c0,
+	0x7480aac1,
+	0xc10100da,
+	0xb56a0092,
+	0xd030532b,
+	0xb720a90a,
+	0xc000430c,
+	0xb78a9164,
+	0xba2452ab,
+	0x62094002,
+	0x0629d110,
+	0x9240c000,
+	0xc0a40203,
+	0xd2080a1c,
+	0x1a04aa01,
+	0xc0007088,
+	0xb78a9184,
+	0xba2452ab,
+	0x62094002,
+	0x1629d110,
+	0xc00e9ea2,
+	0x9e712d7c,
+	0x430cb780,
+	0x5babb742,
+	0x29fccffe,
+	0x009800da,
+	0x0627d110,
+	0x6124c101,
+	0x532bb54b,
+	0x0d840189,
+	0xb7200b08,
+	0xd3f14314,
+	0x9e4c2d3e,
+	0x0a1cc0a4,
+	0xaa01d208,
+	0xfffd7104,
+	0xb7829352,
+	0xb7425bcb,
+	0x61465c53,
+	0xc0007295,
+	0x00da9188,
+	0x0092c101,
+	0x532bb78b,
+	0x1124c101,
+	0xb58b1244,
+	0x048b532b,
+	0x5dcdb781,
+	0xc0007508,
+	0x750a90a2,
+	0x91e4c000,
+	0x430cb720,
+	0x532bb78c,
+	0xc0007500,
+	0x9e8b9102,
+	0xc06e098e,
+	0xc0000d90,
+	0xb7209120,
+	0x9e8b430c,
+	0x6cadb764,
+	0x0d90c06e,
+	0x9931ffb4,
+	0xb7859e69,
+	0x75007ea9,
+	0x9082c001,
+	0x430cb720,
+	0xc09c0203,
+	0xd2080a14,
+	0x9e8baa01,
+	0xc0807500,
+	0xc0000d80,
+	0xb7649102,
+	0xffb46cad,
+	0xc000991a,
+	0x9e8a9220,
+	0xc06e0109,
+	0xb9600d10,
+	0x9e5348d8,
+	0xc0209e91,
+	0x0904aa65,
+	0xa269c010,
+	0x9321ffff,
+	0x430cb720,
+	0x09020a7f,
+	0x6c29b588,
+	0x430cb780,
+	0x0a3cc0a2,
+	0xa101d208,
+	0x430cb720,
+	0x47b1b76a,
+	0x99d7ff54,
+	0x430cb720,
+	0xb78a0902,
+	0xc1364729,
+	0xb58008a0,
+	0xb7804029,
+	0xc136430c,
+	0xd2080a24,
+	0xb780a101,
+	0xc0a2430c,
+	0xd2080a38,
+	0xc001a101,
+	0x9e929080,
+	0x4030b960,
+	0x430cb720,
+	0x5c8cc100,
+	0xd1100d04,
+	0xb5430493,
+	0xb7207bab,
+	0xd110430c,
+	0xb5430493,
+	0xb7207c2b,
+	0xd110430c,
+	0xb5430493,
+	0xb7807cab,
+	0xc101430c,
+	0xb5430498,
+	0xffff7d4b,
+	0xfff690a1,
+	0xb79f91e0,
+	0xb7bf6cee,
+	0xb7df6d6e,
+	0xb7ff6dee,
+	0xcfec6e6e,
+	0x9c228421,
+	0xa205f839,
+	0x430cb720,
+	0x0d860902,
+	0x6e29b788,
+	0x0898c098,
+	0xb5800a08,
+	0xb7804029,
+	0xc098430c,
+	0xd2080a1c,
+	0xc000a101,
+	0xd0089320,
+	0xb780a1de,
+	0xc101430c,
+	0x01850146,
+	0x0a18c098,
+	0x0980c098,
+	0xa901d208,
+	0xaa7dd008,
+	0x71040d84,
+	0x1144d020,
+	0x9086c000,
+	0xa17ed008,
+	0x430cb720,
+	0x0216c101,
+	0x02030109,
+	0x0a18c098,
+	0xaa01d208,
+	0x0900c098,
+	0xfffe72d9,
+	0xb7819398,
+	0x01034bad,
+	0x0934c096,
+	0xd0080a04,
+	0xb780a241,
+	0x097f430c,
+	0xc09609c2,
+	0xd2080a30,
+	0xb720a101,
+	0xb76a430c,
+	0xb74046b1,
+	0x010374b5,
+	0x0930c094,
+	0x9b91fed4,
+	0x430cb720,
+	0x4badb781,
+	0x532bb749,
+	0x5a0cc200,
+	0x291dcff0,
+	0x2a60c00e,
+	0xb5893244,
+	0xb720532b,
+	0x0a02430c,
+	0x68adb584,
+	0xaa1df9f8,
+	0xa61d9c22,
+	0x8420c006,
+	0x430cb720,
+	0x0a060902,
+	0x4829b54a,
+	0x4314b720,
+	0x5ab5b703,
+	0x5b35b7a3,
+	0xb54aa01a,
+	0xb72048c9,
+	0x9e6b4314,
+	0x5bb5b7e3,
+	0x44cbb545,
+	0x520cc200,
+	0xb7800389,
+	0xb723430c,
+	0xc00e5c2d,
+	0xc0a42bfc,
+	0x9ebb0a10,
+	0xa101d208,
+	0xff54a09d,
+	0xb720986f,
+	0x9e4c4314,
+	0x0a10c0a4,
+	0xaa01d208,
+	0xc0157500,
+	0xf1b192a4,
+	0xb7cd8c80,
+	0xb7cd6049,
+	0x9e4960d1,
+	0xb960010b,
+	0xb7834028,
+	0xf0084c2d,
+	0xb783a241,
+	0xf0084cad,
+	0xb783a245,
+	0xf0084d2d,
+	0xb783a249,
+	0x08c04dad,
+	0xa24df008,
+	0xffff0940,
+	0xb74391c1,
+	0x9e4a5bd5,
+	0x2dded3f2,
+	0x0992c144,
+	0x9b1ffed4,
+	0x430cb720,
+	0xb9600d02,
+	0xb5cd4028,
+	0xb7206029,
+	0xb5cd430c,
+	0xb72060b1,
+	0xf208430c,
+	0xc100aa21,
+	0xd1105c90,
+	0x0d040493,
+	0x4c2db583,
+	0x430cb720,
+	0xaa25f208,
+	0x0493d110,
+	0x4cadb583,
+	0x430cb720,
+	0xaa29f208,
+	0x0493d110,
+	0x4d2db583,
+	0x430cb780,
+	0xa92df208,
+	0xc1010ac0,
+	0xb5430498,
+	0xfffe4dcd,
+	0xb7209381,
+	0xaa19430c,
+	0x5a0cb700,
+	0x5a94b700,
+	0x5aadb583,
+	0x430cb720,
+	0x0c82c021,
+	0x0d82c021,
+	0x5b35b5a3,
+	0x430cb720,
+	0x0c80c014,
+	0x0d90c014,
+	0x5bb5b5e3,
+	0x430cb720,
+	0xb960a99d,
+	0xb5634038,
+	0xb7a05c2d,
+	0x9e694314,
+	0x0dd8d2f1,
+	0x7029b788,
+	0x6fa9b748,
+	0x6f31b748,
+	0x47a9b58a,
+	0x430cb7a0,
+	0x6ea9b788,
+	0xb54a008b,
+	0xb7204729,
+	0xb54a430c,
+	0xb72046b1,
+	0xb58a430c,
+	0xb7204629,
+	0xb562430c,
+	0xb720612d,
+	0xd9e9430c,
+	0x9d9eaa1d,
+	0xa261f000,
+	0xaa1dd9f1,
+	0xf0009dbe,
+	0xffffa261,
+	0x048b92c1,
+	0x7e49b785,
+	0xc0067500,
+	0xc00e91c2,
+	0xb5850a7e,
+	0xb720482d,
+	0x0a82430c,
+	0xb5a40906,
+	0xb72067ad,
+	0xb5a4430c,
+	0xb720682d,
+	0xb5a4430c,
+	0xb720692d,
+	0xb544430c,
+	0xb7206cad,
+	0xb5a4430c,
+	0xb7806d2d,
+	0xc09c430c,
+	0xd2080a10,
+	0xb780a281,
+	0xc09c430c,
+	0xd2080a18,
+	0xfff4a101,
+	0xb7809a8d,
+	0x0109430c,
+	0x0918c098,
+	0xa941d008,
+	0xc0980244,
+	0xd2080a00,
+	0xb720a11d,
+	0xb781430c,
+	0x75004bad,
+	0x9262c000,
+	0x5c35b741,
+	0x46b1b76a,
+	0x5a1cc200,
+	0x1d00c008,
+	0xc1010103,
+	0xc09c0528,
+	0xc0040960,
+	0xfed409d2,
+	0xb7809a4e,
+	0x090a430c,
+	0xa9aef210,
+	0x0a40c09a,
+	0xa281d208,
+	0x430cb720,
+	0xb762040b,
+	0xb5a65b4a,
+	0xb7804aad,
+	0xb742430c,
+	0xf2105bd2,
+	0xc0c4a8aa,
+	0xd2080a60,
+	0xb720a101,
+	0xd111430c,
+	0xb56465a7,
+	0xb7a06bb5,
+	0x008b430c,
+	0x6bb5b764,
+	0xc25465b3,
+	0x048b9aa0,
+	0x5f4bb781,
+	0x75009ea8,
+	0x6c4cb504,
+	0x4314b740,
+	0x9142c000,
+	0x0a6a9e52,
+	0x091cc09c,
+	0xa241d008,
+	0x9140c000,
+	0x9e549e69,
+	0x67a9b746,
+	0x0a1cc09c,
+	0xa101d208,
+	0x430cb720,
+	0x087f0d82,
+	0x67a9b786,
+	0x08a0c09c,
+	0x0c7ec00e,
+	0x4029b580,
+	0x430cb720,
+	0x46b1b74a,
+	0x4001ba12,
+	0x91e0c000,
+	0x6fcdb789,
+	0x02426a32,
+	0x0a20c138,
+	0xa011d208,
+	0x430cb720,
+	0xb50900b2,
+	0xb7206fb5,
+	0xd010430c,
+	0x0d840534,
+	0x4729b78a,
+	0x5988c100,
+	0x00b2d020,
+	0xffff7088,
+	0x090290fc,
+	0xb9600d7f,
+	0xb7804040,
+	0x0228430c,
+	0x0a60c098,
+	0xa116d208,
+	0xffff0904,
+	0x048b9301,
+	0x5e55b741,
+	0x430cb780,
+	0x76800902,
+	0x0a18c0a4,
+	0x0922d002,
+	0xa101d208,
+	0x430cb720,
+	0x76860a02,
+	0x52abb58a,
+	0x9102c009,
+	0xc0017684,
+	0xb7819304,
+	0x1a0c5dcd,
+	0xc0017504,
+	0xb7209252,
+	0xc809430c,
+	0xccf00a42,
+	0xb5890a20,
+	0xb7206aad,
+	0xc809430c,
+	0xc9be0a46,
+	0xb5890a60,
+	0xb7206b2d,
+	0xc809430c,
+	0xccf80a42,
+	0xb5890a50,
+	0xb7206a2d,
+	0xc809430c,
+	0xc5f80a46,
+	0xb5890a20,
+	0xb7206c2d,
+	0xc809430c,
+	0xc40a0a46,
+	0xb5890a10,
+	0xb7206bad,
+	0xc809430c,
+	0xcd0a0a42,
+	0xb5890a10,
+	0x040b6cad,
+	0x5dccb781,
+	0xc0017504,
+	0xb78192e4,
+	0x75045e4c,
+	0x9244c001,
+	0x430cb720,
+	0x0a42c809,
+	0x0a70cf1a,
+	0x6aadb589,
+	0x430cb720,
+	0x0a46c809,
+	0x0a30cac6,
+	0x6b2db589,
+	0x430cb720,
+	0x0a42c809,
+	0x0a70cd0c,
+	0x6a2db589,
+	0x430cb720,
+	0x0a46c809,
+	0x0a30cb92,
+	0x6c2db589,
+	0x430cb720,
+	0x0a46c809,
+	0x0a50cc94,
+	0x6badb589,
+	0x430cb720,
+	0x0a42c809,
+	0x0a20cd2e,
+	0x6cadb589,
+	0xb7819e69,
+	0x75025e2d,
+	0x92e4c001,
+	0x5dadb781,
+	0xc0017504,
+	0xb7209244,
+	0xc809430c,
+	0xcf1a0a42,
+	0xb5890a70,
+	0xb7206aad,
+	0xc809430c,
+	0xcb360a46,
+	0xb5890a00,
+	0xb7206b2d,
+	0xc809430c,
+	0xc9dc0a46,
+	0xb5890a10,
+	0xb7206a2d,
+	0xc809430c,
+	0xcb0a0a46,
+	0xb5890a30,
+	0xb7206c2d,
+	0xc809430c,
+	0xcc940a46,
+	0xb5890a50,
+	0xb7206bad,
+	0xc809430c,
+	0xcd2e0a42,
+	0xb5890a20,
+	0x048b6cad,
+	0x5e4db781,
+	0xc0017508,
+	0xb78192e4,
+	0x75045dcd,
+	0x9244c001,
+	0x430cb720,
+	0x0a46c809,
+	0x0a40caca,
+	0x6aadb589,
+	0x430cb720,
+	0x0a46c809,
+	0x0a00cb36,
+	0x6b2db589,
+	0x430cb720,
+	0x0a46c809,
+	0x0a10c9dc,
+	0x6a2db589,
+	0x430cb720,
+	0x0a46c809,
+	0x0a30cb0a,
+	0x6c2db589,
+	0x430cb720,
+	0x0a46c809,
+	0x0a50cc94,
+	0x6badb589,
+	0x430cb720,
+	0x0a46c809,
+	0x0a70cab8,
+	0x6cadb589,
+	0xb781040b,
+	0x75025e4c,
+	0x9304c001,
+	0x5dccb781,
+	0x75041a0c,
+	0x9252c001,
+	0x430cb720,
+	0x0a46c809,
+	0x0a30c050,
+	0x6aadb589,
+	0x430cb720,
+	0x0a46c809,
+	0x0a50c9c8,
+	0x6b2db589,
+	0x430cb720,
+	0x0a42c809,
+	0x0a10cd38,
+	0x6a2db589,
+	0x430cb720,
+	0x0a46c809,
+	0x0a60c1a0,
+	0x6c2db589,
+	0x430cb720,
+	0x0a46c809,
+	0x0a00c0aa,
+	0x6badb589,
+	0x430cb720,
+	0x0a42c809,
+	0x0a20cd68,
+	0x6cadb589,
+	0x430cb720,
+	0xb5ea9ebb,
+	0xb7204829,
+	0xb5ea430c,
+	0xb79f48a9,
+	0xb7bf77ee,
+	0xb7df786e,
+	0xb7ff78ee,
+	0xc008796e,
+	0xff318c20,
+	0xa60d9140,
+	0xb7208440,
+	0x0203430c,
+	0x0a10c0a4,
+	0xaa01d208,
+	0xc0107500,
+	0x02039104,
+	0x0a18c09c,
+	0xaa01d208,
+	0xc0017500,
+	0xb7aa90c2,
+	0xb7c046a9,
+	0xc000478c,
+	0xd0319320,
+	0xc00e0a54,
+	0x6a522a7c,
+	0xd032024c,
+	0xc0000ac8,
+	0xff149080,
+	0xf2109945,
+	0x0d92aa21,
+	0xffff750c,
+	0xd0119344,
+	0x02890a52,
+	0x2afcc00e,
+	0x430cb720,
+	0x4729b78a,
+	0xffff710a,
+	0xb7209088,
+	0x0203430c,
+	0x0a18c09c,
+	0xaa01d208,
+	0xc0027500,
+	0x9ea39304,
+	0x4731b7ca,
+	0x98b8ff74,
+	0x430cb780,
+	0x0a10c0a4,
+	0xab01d208,
+	0xc00e7580,
+	0x0a869084,
+	0x56d89eaa,
+	0x2efcc00e,
+	0xff34058b,
+	0x9eb29945,
+	0x018d9eb1,
+	0x010d008b,
+	0xa31d058d,
+	0xa295a319,
+	0x9af4ff94,
+	0x4314b700,
+	0x5e88d322,
+	0x4490b760,
+	0x00d0c101,
+	0x6fb5b729,
+	0x6c50b74d,
+	0xd0319e73,
+	0xc00e6d19,
+	0xc1012cfc,
+	0xc1380120,
+	0xd0080920,
+	0x1b04a951,
+	0x99ebff14,
+	0x430cb740,
+	0x00d4058b,
+	0x6fadb789,
+	0x02446a32,
+	0x0a20c138,
+	0xa311d208,
+	0x430cb780,
+	0x008b02d8,
+	0x0a7ec00e,
+	0x6fadb589,
+	0x9997ff34,
+	0x560cb780,
+	0xc2209ea2,
+	0xb720a349,
+	0x0203430c,
+	0x0a18c0a4,
+	0xaa01d208,
+	0xc0007500,
+	0xb78991a2,
+	0xb7646bad,
+	0x018379b5,
+	0x09b0c0c4,
+	0x9c629ea4,
+	0x9080c000,
+	0x532bb58c,
+	0x430cb720,
+	0x67adb784,
+	0xb5840a04,
+	0xb7a067ad,
+	0x008b430c,
+	0x612db781,
+	0xc0017500,
+	0xb7849122,
+	0x750067ad,
+	0x9082c001,
+	0x46a9b74a,
+	0x4729b76a,
+	0xc0000d82,
+	0x9d4d9100,
+	0xd3f1aa61,
+	0xc1012d2e,
+	0xd01205b8,
+	0x70860922,
+	0x5e30d122,
+	0x0a00c021,
+	0x0a00c034,
+	0x9234ffff,
+	0xaa2df208,
+	0xa9a9f208,
+	0xc25461c7,
+	0x008b9816,
+	0x4badb506,
+	0x430cb720,
+	0xb5a50a82,
+	0xb72044ab,
+	0xb76a430c,
+	0xff344831,
+	0xb720993a,
+	0x0203430c,
+	0x0a18c09c,
+	0xaa01d208,
+	0xc0027500,
+	0xb7849162,
+	0x0a04682d,
+	0x682db584,
+	0x430cb740,
+	0x0914c09c,
+	0xaa41d008,
+	0xc0007500,
+	0xd0089322,
+	0xb720a2c1,
+	0x097f430c,
+	0x6e29b788,
+	0xc0980218,
+	0xd2080a04,
+	0x0098aa1d,
+	0x08a0c098,
+	0x41a9b5a0,
+	0x430cb780,
+	0x0a30c096,
+	0xa101d208,
+	0x430cb720,
+	0x6cadb784,
+	0xc0007506,
+	0xb7849182,
+	0xb584782d,
+	0xb720772d,
+	0xb784430c,
+	0xb58477ad,
+	0xb720782d,
+	0xb784430c,
+	0xb5846fad,
+	0xb7406f2d,
+	0x0205430c,
+	0x0a04c098,
+	0xaa01d208,
+	0x0900c098,
+	0xa241d008,
+	0x9180c000,
+	0xc0c40203,
+	0xd2080a60,
+	0xb786a901,
+	0x02444aad,
+	0x4aadb586,
+	0x430cb780,
+	0xc09c0a82,
+	0xd2080a10,
+	0xb720a281,
+	0xb744430c,
+	0x748068ad,
+	0x91a2c000,
+	0x67adb784,
+	0xc0007088,
+	0xffd49104,
+	0xb7209b37,
+	0xb5a5430c,
+	0xb720482d,
+	0xb743430c,
+	0x76805733,
+	0x93c4c004,
+	0x5eadb783,
+	0x09020e82,
+	0xd00a7502,
+	0x75040ed2,
+	0x0922d001,
+	0x0a027508,
+	0x0a42d001,
+	0x31287740,
+	0x90a2c000,
+	0xc0009e55,
+	0x748090c0,
+	0xd0010a86,
+	0x08020ad2,
+	0x5b14b7c0,
+	0x49049e83,
+	0x0b7ec03e,
+	0x4018b960,
+	0x9000c004,
+	0xaa49c060,
+	0x430cb760,
+	0x5c88c100,
+	0x4000ba24,
+	0x0058d020,
+	0xd0220496,
+	0x04925c88,
+	0x0096c101,
+	0x0496c101,
+	0xb7830092,
+	0x00967bcb,
+	0x57abb723,
+	0x4002ba24,
+	0x0242e000,
+	0x90acc000,
+	0xc0000201,
+	0xd0109080,
+	0xd022710c,
+	0xc1015c88,
+	0x00920096,
+	0xb5830096,
+	0xd12257ab,
+	0xb7805c88,
+	0xc101430c,
+	0x00920096,
+	0x00980d04,
+	0xb5037688,
+	0xfffe7bab,
+	0x77409124,
+	0x9364c001,
+	0xaa49c060,
+	0x430cb760,
+	0x5c88c100,
+	0x4000ba24,
+	0x0028d020,
+	0xd0220496,
+	0x04925c88,
+	0x0096c101,
+	0x0496c101,
+	0xb7830092,
+	0x00967bcb,
+	0x57abb723,
+	0x4002ba24,
+	0x0242e000,
+	0x90acc000,
+	0xc0000201,
+	0xd0109080,
+	0xd022710c,
+	0xc1015c88,
+	0x00920096,
+	0xb5830096,
+	0xd12257ab,
+	0xb7805c88,
+	0xc101430c,
+	0x00920096,
+	0x00980d04,
+	0xb503768e,
+	0xfffe7bab,
+	0x0d849124,
+	0x9101c000,
+	0x4490b760,
+	0x9a60fef4,
+	0x90a0c000,
+	0xfffc9e82,
+	0xb79f9020,
+	0xb7bf7dee,
+	0xb7df7e6e,
+	0xc0027eee,
+	0x9c228c20,
+	0x430cb720,
+	0x5dadb781,
+	0x7eadb742,
+	0xc1007504,
+	0xc000580c,
+	0xcd8e90a4,
+	0x9c220841,
+	0x0850cfff,
+	0x0800c480,
+	0x9e589c22,
+	0xe0000c86,
+	0xd0054030,
+	0x9e511c94,
+	0x72c0c814,
+	0x70c0c814,
+	0x7480c008,
+	0x483cb323,
+	0x445cb323,
+	0x927cc000,
+	0x5a1be100,
+	0x90ccc000,
+	0x0a02c002,
+	0x90e0c000,
+	0x7100d002,
+	0xba240a04,
+	0x9e504000,
+	0x51d3d024,
+	0xc0055193,
+	0xc00074c0,
+	0xe180923c,
+	0xc0005a57,
+	0xc00290cc,
+	0xc0000a02,
+	0xd00290e0,
+	0x0a047100,
+	0x4000ba24,
+	0x51f30098,
+	0x470cb740,
+	0xd0109e58,
+	0xc0200636,
+	0xb740a906,
+	0x7293468c,
+	0xaa05ca20,
+	0xd11d6039,
+	0xd11e1623,
+	0xd01a1215,
+	0xd01c5013,
+	0xc1015010,
+	0x9c226003,
+	0xb7a0a60d,
+	0x0707430c,
+	0xb781008b,
+	0x75045dad,
+	0x93c4c007,
+	0x9b94fff4,
+	0x5c88d322,
+	0x009a0d06,
+	0x7f2db722,
+	0x10029e52,
+	0x7080d812,
+	0xb781008b,
+	0x9eb55e2d,
+	0xc0007502,
+	0x750890a2,
+	0x93a4c000,
+	0xb787008b,
+	0x75004e2d,
+	0x92e2c000,
+	0x402db743,
+	0xb3207104,
+	0xc0004834,
+	0x008b9154,
+	0x4629b76a,
+	0x11c4d020,
+	0xfff40d02,
+	0x0a069b7e,
+	0x7100d012,
+	0x7188c810,
+	0xb7209e95,
+	0xb7804314,
+	0x0b1e448c,
+	0x75009e4a,
+	0x0938c0a2,
+	0xa941d008,
+	0x4422b346,
+	0xc0007480,
+	0xb7809282,
+	0xb764414d,
+	0xb7436bd5,
+	0xb76a41cd,
+	0xc1014649,
+	0x0d0265b9,
+	0x15b4c101,
+	0x9b59fff4,
+	0xc0009e82,
+	0xd3229180,
+	0xc1015c88,
+	0xb7830092,
+	0xb72540ad,
+	0x109846ad,
+	0xcffe9e8a,
+	0x76802d7c,
+	0x9382c004,
+	0x7740c080,
+	0x9094c000,
+	0x0e81cfc0,
+	0x4314b720,
+	0x5e4db781,
+	0xc0007508,
+	0xb78192c4,
+	0x1a045ecd,
+	0xc0007502,
+	0xb7449192,
+	0x0a1a6ccd,
+	0x74829e69,
+	0x1a46d009,
+	0xc00052b1,
+	0xd2a29140,
+	0xc0005e85,
+	0xd2a290c0,
+	0xd1105e0d,
+	0x9e5316d9,
+	0x15dac101,
+	0xfff40d02,
+	0x09869b1c,
+	0x70c0c812,
+	0x4314b700,
+	0x5c88d322,
+	0x5e4cb781,
+	0x0090c101,
+	0x7f35b742,
+	0xd0127508,
+	0xc0001248,
+	0xc10090c4,
+	0xd0125a05,
+	0xc03e70c8,
+	0xc41009fe,
+	0x0a067106,
+	0x9ea39e89,
+	0x7246c412,
+	0x7086cc10,
+	0x70c8cc12,
+	0x0a7ec00f,
+	0x0a7ccffe,
+	0x0155d120,
+	0xc8109ea3,
+	0x0d827286,
+	0x7286c812,
+	0x5c88d322,
+	0x5918c300,
+	0x0090c101,
+	0x40adb723,
+	0x9e4c5cd8,
+	0x2900c01c,
+	0x04877440,
+	0xd0013904,
+	0x31280cb4,
+	0xc0037440,
+	0xcf000a7e,
+	0xd0010a00,
+	0x59b00db8,
+	0x9e5c21b8,
+	0xd0113126,
+	0x31280de2,
+	0x59b09e4c,
+	0x02073128,
+	0x0a00c021,
+	0x0a40c01e,
+	0xf0009dcd,
+	0xc0ffa161,
+	0xcffe0a7e,
+	0x9ea30a40,
+	0x0a0a7440,
+	0x1a44d002,
+	0x25265d10,
+	0x3d049ea3,
+	0x0980c021,
+	0xc01e3526,
+	0x9dbd09d0,
+	0xa162f000,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0x9c228c60,
+	0x8440a61d,
+	0x0a32d011,
+	0x5b30c200,
+	0x6931d0d1,
+	0x540cb780,
+	0xa1969e9e,
+	0x03a8d020,
+	0xc021010d,
+	0xa1120900,
+	0x0930c03c,
+	0xa9619d2d,
+	0xda109e92,
+	0xcff0aa61,
+	0x5d212d00,
+	0x0629d110,
+	0x5e88d322,
+	0xa261da10,
+	0x430cb720,
+	0x297cc00e,
+	0x00d2018d,
+	0x40adb783,
+	0x0980c021,
+	0x0980c03a,
+	0x0629d110,
+	0x40adb583,
+	0x430cb720,
+	0x41adb783,
+	0x0244c101,
+	0x41adb583,
+	0xaa65da10,
+	0xda100228,
+	0xb720a265,
+	0x00d2430c,
+	0x40adb783,
+	0xb5830228,
+	0xb72040ad,
+	0xb783430c,
+	0x024441ad,
+	0x41adb583,
+	0xa9e19d3d,
+	0xaa65f210,
+	0x29fec7ff,
+	0x0246010d,
+	0x0900c021,
+	0x0920c03a,
+	0xa265f210,
+	0xa9619d2d,
+	0xaa69f210,
+	0xc7ff9eb2,
+	0x0244297e,
+	0x0d00c021,
+	0x0d10c03a,
+	0xa269f210,
+	0xa9629d2e,
+	0xaa61f250,
+	0xc021010d,
+	0xc1010900,
+	0xc03a0244,
+	0xf2500930,
+	0x9d2da261,
+	0xf250a961,
+	0x9eb3aa65,
+	0xc040000d,
+	0x02440800,
+	0x0d80c021,
+	0xc042a019,
+	0xf2500dc0,
+	0x9d3ea265,
+	0xf210a9e2,
+	0xc00faa71,
+	0x018d2dfe,
+	0x0246c101,
+	0x0980c021,
+	0x09d0c042,
+	0xa271f210,
+	0xa9e19d3d,
+	0xaa75f210,
+	0x29fec00f,
+	0x0246038d,
+	0x0b80c021,
+	0x0ba0c042,
+	0xa275f210,
+	0xa8e19d7d,
+	0xaa7df210,
+	0x28fccffe,
+	0x0242010d,
+	0x0900c021,
+	0x0930c042,
+	0xa27df210,
+	0xa9619d2d,
+	0xaa79f210,
+	0xc00f9eb2,
+	0x0244297e,
+	0x0d00c021,
+	0x0d40c048,
+	0xa279f210,
+	0xa9629d2e,
+	0x01b6c101,
+	0x020d01b2,
+	0xc00f01b4,
+	0xc0212d7e,
+	0xc1010a00,
+	0xc04601b4,
+	0x9d4d0a60,
+	0x9ea2aa61,
+	0xa979da10,
+	0x2d7cc3ff,
+	0xda105d41,
+	0xc101a9fe,
+	0xb7400524,
+	0xc3fe430c,
+	0xc1012a7c,
+	0x01540246,
+	0xa17ada10,
+	0xa27dda10,
+	0x0960c05e,
+	0xaa41f008,
+	0x0238058d,
+	0xa241f008,
+	0x430cb720,
+	0x402db783,
+	0xb5830246,
+	0xb7a0402d,
+	0xfff44314,
+	0xc1019999,
+	0xc05e02da,
+	0xf2080ae0,
+	0x7140aaa1,
+	0x90e6c000,
+	0x04dcd010,
+	0xb58c0a06,
+	0xb7204829,
+	0xb747430c,
+	0x74804e2d,
+	0x9222c000,
+	0x402db783,
+	0xc0007104,
+	0xb78c9186,
+	0x750065ab,
+	0x90e4c000,
+	0x009cc101,
+	0xb58c0a04,
+	0xb7204929,
+	0xb781430c,
+	0x75045dad,
+	0x92c4c002,
+	0xc021020d,
+	0xc01e0a00,
+	0x9d4d0a60,
+	0x9e79aa61,
+	0xb7009e78,
+	0x9ea25431,
+	0x54b1b760,
+	0x55b0b720,
+	0x5529b720,
+	0xc2000109,
+	0xcff059e1,
+	0xc1012900,
+	0xc00f0240,
+	0xb5802d7c,
+	0x59215428,
+	0x5d41020d,
+	0x0126c101,
+	0x0522c101,
+	0x01b2c101,
+	0x0a00c021,
+	0x54a8b540,
+	0x5530b540,
+	0x55a8b560,
+	0x0a70c01e,
+	0xaa619d4d,
+	0xb7009ea2,
+	0xb7605630,
+	0xb72056b0,
+	0xb7205728,
+	0x010957b0,
+	0x2900cff0,
+	0x2d7cc00f,
+	0x59e1c200,
+	0x5d415921,
+	0x0126c101,
+	0x0522c101,
+	0x01b2c101,
+	0x0240c101,
+	0x5628b580,
+	0x56a8b540,
+	0x5730b540,
+	0x57a8b560,
+	0x2deed3f2,
+	0x9978fff4,
+	0x7600a812,
+	0x9322c005,
+	0xb780a919,
+	0xc300590c,
+	0xc0215d18,
+	0xc0020900,
+	0xd1300910,
+	0x9d2d0529,
+	0x9e92a961,
+	0xa9cad858,
+	0xa8cdd858,
+	0xa8d2d858,
+	0xa856d858,
+	0xcff00205,
+	0xc00f2a00,
+	0xc1002d7c,
+	0xc20059e1,
+	0x5d415a21,
+	0x297cc00e,
+	0x0246c101,
+	0x05220122,
+	0x01b0c101,
+	0xa249d858,
+	0xa14dd858,
+	0xa152d858,
+	0xa1d5d858,
+	0xaa619d7d,
+	0xabf9da10,
+	0xa87ef210,
+	0xa941f058,
+	0xa879f210,
+	0xaaf1f210,
+	0xaaf6f210,
+	0xab7dda10,
+	0xa9dbd858,
+	0xa946f058,
+	0xa9c9f058,
+	0xa9cef058,
+	0xa8d5f058,
+	0xa8d2f058,
+	0xc101a39d,
+	0xf0580120,
+	0xa81eabd9,
+	0xa964f212,
+	0x5a61c200,
+	0x9eb80490,
+	0x0246c301,
+	0xc1014c7d,
+	0x01ba0520,
+	0x009c05ba,
+	0xd8587205,
+	0xf058a259,
+	0xf058a141,
+	0xf058a146,
+	0xf058a1c9,
+	0xf058a1ce,
+	0xf058a0d5,
+	0xc000a0d2,
+	0xd0d891b2,
+	0xe010aa59,
+	0x0a048b21,
+	0xa159f058,
+	0xa259d0d8,
+	0x90c0c000,
+	0x0274c001,
+	0xa259f058,
+	0xaa5df058,
+	0xa969f210,
+	0x4d7d9ea2,
+	0xc0007295,
+	0xd0d891b2,
+	0xc101aa5d,
+	0xf0581124,
+	0x0a04a15d,
+	0xa25dd0d8,
+	0x90a0c000,
+	0xf0580244,
+	0xb720a25d,
+	0x0203430c,
+	0x0a18c0a4,
+	0xaa01d208,
+	0xc0007500,
+	0xb7899122,
+	0xa9966a2d,
+	0x050f9e73,
+	0x9c629ea4,
+	0xc002058f,
+	0xb79f09c2,
+	0xb7bf7d6e,
+	0xb7df7dee,
+	0xb7ff7e6e,
+	0xc0027eee,
+	0xfe698c40,
+	0xb79f9200,
+	0xb7bf7d6e,
+	0xb7df7dee,
+	0xb7ff7e6e,
+	0xc0027eee,
+	0x9c228c40,
+	0x430cb740,
+	0x0d020487,
+	0xc0c60185,
+	0xb9600980,
+	0xc0204258,
+	0x9e9baa29,
+	0xa269c020,
+	0xffff0d04,
+	0xc0d29341,
+	0x0a060960,
+	0xa241d008,
+	0x430cb720,
+	0x0a70c002,
+	0x792bb58c,
+	0x5749b780,
+	0x430cb720,
+	0x4aabb58d,
+	0xb7209c22,
+	0x9e53430c,
+	0xa95df010,
+	0xa956f010,
+	0x712db786,
+	0x0124c101,
+	0xb5860244,
+	0xb720712d,
+	0xf008430c,
+	0xf008a972,
+	0xb786a979,
+	0xc10170ad,
+	0x02440124,
+	0x70adb586,
+	0x430cb720,
+	0xa966f008,
+	0xa969f008,
+	0x71adb786,
+	0x0124c101,
+	0xb5860244,
+	0xb72071ad,
+	0xd808430c,
+	0xd808a961,
+	0xb786a966,
+	0xc101702d,
+	0x02440124,
+	0x702db586,
+	0x430cb720,
+	0x64adb786,
+	0xb3407502,
+	0xd80848a4,
+	0xb786a965,
+	0x02446fad,
+	0x6fadb586,
+	0xf0109c22,
+	0xb720a9e2,
+	0x0906430c,
+	0x6435b566,
+	0x430cb780,
+	0x0a70c0d0,
+	0xa101d208,
+	0xa6059c22,
+	0x430cb7a0,
+	0xaa41d810,
+	0xa945d810,
+	0x0685008b,
+	0x5e35b741,
+	0x00890244,
+	0xf2107684,
+	0xcffea9b1,
+	0xc00028fc,
+	0x9ea99224,
+	0x5a4bb78d,
+	0x6dcdb746,
+	0xb58d0238,
+	0xf2105a4b,
+	0x0128aa35,
+	0x6dcdb546,
+	0x9120c000,
+	0xb56d9ea9,
+	0xf2105a4b,
+	0xb586aa35,
+	0x9ea96dcd,
+	0xa9a1f250,
+	0x6fcdb786,
+	0x704db746,
+	0x6ed5b746,
+	0xb5860246,
+	0xf2506fcd,
+	0xb786a9a5,
+	0xb7666f4d,
+	0x01265ad5,
+	0x704db546,
+	0xa925da10,
+	0xb5860242,
+	0xc1016f4d,
+	0xb5460524,
+	0xf2106ed5,
+	0xf210a931,
+	0xd0a4aa35,
+	0x01835905,
+	0xc1010244,
+	0xb56605b8,
+	0xda105ad5,
+	0xda10aa39,
+	0xc101a9be,
+	0x05b405b8,
+	0x9a5ec214,
+	0xb786008b,
+	0xb74c69ad,
+	0x02406d2b,
+	0xb5860904,
+	0xb54c69ad,
+	0xb7806d2b,
+	0x7500448c,
+	0x90a4c000,
+	0xc0000109,
+	0x9e699180,
+	0xb9600902,
+	0xb7804030,
+	0x088454a9,
+	0xffff0128,
+	0x9ea99381,
+	0x614bb54d,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0xaa61f010,
+	0xb7209e5a,
+	0x7500430c,
+	0x9082c000,
+	0x76adb586,
+	0xa956d008,
+	0x76bec01c,
+	0x90e2c000,
+	0xc0da0203,
+	0xd2080a64,
+	0xd008a102,
+	0xc01ca959,
+	0xc00074be,
+	0x020390e2,
+	0x0a68c0da,
+	0xa101d208,
+	0xc0da0103,
+	0x0a060940,
+	0xa241d008,
+	0xa6059c22,
+	0xf0109e55,
+	0xf010a955,
+	0xf010aa51,
+	0xf208a95a,
+	0xb720a9bd,
+	0x0244430c,
+	0x0244c101,
+	0xb5860246,
+	0xf208752d,
+	0xf208a929,
+	0xda08a9a6,
+	0xda08aa25,
+	0xb7a0a9a1,
+	0xd1204314,
+	0x01c601a7,
+	0xffd40d02,
+	0x9e699b22,
+	0x712db506,
+	0x430cb720,
+	0xa935f208,
+	0x702db786,
+	0xb5860244,
+	0xb720702d,
+	0xf208430c,
+	0xb786a935,
+	0x0244722d,
+	0x722db586,
+	0x430cb720,
+	0xa925f208,
+	0x6fadb786,
+	0xb5860244,
+	0xb7206fad,
+	0xda08430c,
+	0xb78da939,
+	0x0244612b,
+	0x612bb58d,
+	0x430cb720,
+	0xa921da08,
+	0x61abb78d,
+	0xb58d0244,
+	0xb72061ab,
+	0xf208430c,
+	0xb786a929,
+	0x0244732d,
+	0x732db586,
+	0x430cb720,
+	0xa93dda08,
+	0x652bb78d,
+	0xb58d0244,
+	0xb720652b,
+	0xda08430c,
+	0xb78da925,
+	0x024465ab,
+	0x65abb58d,
+	0x430cb720,
+	0xaa25f208,
+	0xa92af208,
+	0x73adb746,
+	0xc1010244,
+	0xb5860244,
+	0xb72073ad,
+	0xf208430c,
+	0xb786a939,
+	0x0244742d,
+	0x742db586,
+	0x430cb720,
+	0xa93df208,
+	0x74adb786,
+	0xb5860244,
+	0xb72074ad,
+	0xda08430c,
+	0xda08a93a,
+	0xb786a93d,
+	0xc10175ad,
+	0x02440124,
+	0x75adb586,
+	0x430cb720,
+	0xaa21da08,
+	0xa926da08,
+	0x632bb74d,
+	0xc1010244,
+	0xb58d0244,
+	0xb720632b,
+	0xb787430c,
+	0xb746462d,
+	0x0244752d,
+	0x462db587,
+	0x430cb720,
+	0xa939da08,
+	0xaabdda08,
+	0x492db787,
+	0x024a02d4,
+	0x492db587,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0xa9e2f010,
+	0x430cb720,
+	0xb5660906,
+	0xb7806435,
+	0xc0d0430c,
+	0xd2080a70,
+	0x9c22a101,
+	0x430cb720,
+	0xb78e9e58,
+	0x11095bab,
+	0x9060c000,
+	0x70080004,
+	0x93d6ffff,
+	0x9060c000,
+	0x74000008,
+	0x93d8ffff,
+	0x287ccffe,
+	0xa6059c22,
+	0x430cb7a0,
+	0xb78e008b,
+	0xc2005b2b,
+	0x009a5888,
+	0x7eb5b7a6,
+	0x7eb5b566,
+	0x09c2d012,
+	0x9bdcfff4,
+	0xb50e008b,
+	0x9e685b2b,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0x430cb720,
+	0x5e2db781,
+	0xc0007502,
+	0xb78691c4,
+	0x750040a9,
+	0x9122c000,
+	0x5aabb78c,
+	0x75020802,
+	0x0802d002,
+	0x08029c22,
+	0xa60d9c22,
+	0x4314b7a0,
+	0xb7669e69,
+	0xfff45ab5,
+	0x03019bca,
+	0x9be2fff4,
+	0xc0007400,
+	0x9e6991c2,
+	0x6cadb786,
+	0x5aadb746,
+	0x4e35b746,
+	0xc1010128,
+	0xb5461124,
+	0xb7a06cad,
+	0x008b430c,
+	0x75adb786,
+	0xc0017500,
+	0xfff49264,
+	0x74009bc9,
+	0x91a2c000,
+	0xb78e008b,
+	0xb7445bab,
+	0x708867ad,
+	0xd0040a02,
+	0xc0000a42,
+	0x008b9360,
+	0x5e2db781,
+	0xc0007502,
+	0x750890a2,
+	0x9204c000,
+	0xb784008b,
+	0xb74667ad,
+	0xb7464e2d,
+	0x624550b5,
+	0x0a027115,
+	0x0a42d00b,
+	0x9080c000,
+	0x008b0a06,
+	0x75adb586,
+	0xb706008b,
+	0x740075ad,
+	0x93a2c000,
+	0x9b98fff4,
+	0xc0007400,
+	0x9e6992a2,
+	0x532db786,
+	0x7188c010,
+	0x5b2bb78e,
+	0x5a08c200,
+	0x00cac101,
+	0x7eadb786,
+	0x12400268,
+	0x7eadb586,
+	0x90a0c000,
+	0xb7069e69,
+	0xb79f4e2d,
+	0xb7bf7eee,
+	0xb7df7f6e,
+	0x8c607fee,
+	0xf8399c22,
+	0xfff4a205,
+	0x74009b73,
+	0x430cb700,
+	0x91e2c000,
+	0x5b2ab78e,
+	0x532cb746,
+	0x5a08c200,
+	0xb78600c0,
+	0xc0107ead,
+	0xc0017104,
+	0xb74192a0,
+	0x74885e2c,
+	0x9164c000,
+	0x5b2ab78e,
+	0x5a08c200,
+	0xb70600c0,
+	0xc0017ead,
+	0xb78690e0,
+	0x750075ac,
+	0x9004c001,
+	0xc0007482,
+	0x748890a2,
+	0x91e4c000,
+	0x67acb784,
+	0x4e2cb746,
+	0x50b4b746,
+	0x71156245,
+	0xd00b0a02,
+	0xc0000a42,
+	0x0a069060,
+	0x75acb586,
+	0x75acb786,
+	0xc0007500,
+	0x000990a4,
+	0x9080c000,
+	0x4e2cb706,
+	0xaa1df9f8,
+	0xf0109c22,
+	0xf010a966,
+	0x9e5ca9e2,
+	0x7100c814,
+	0x7080c802,
+	0x0e22d011,
+	0x753c0244,
+	0x915cc000,
+	0x087ec7ff,
+	0xcffe76c0,
+	0xd00e087c,
+	0x9c220804,
+	0xc0007680,
+	0xd02290bc,
+	0x9c225468,
+	0xc1019e5a,
+	0x50531205,
+	0x76e69c22,
+	0x1000d01e,
+	0x48bcb340,
+	0x76c0c380,
+	0x1524d02e,
+	0x913cc000,
+	0x084ec002,
+	0xd0119c22,
+	0xd2240e32,
+	0x9e525987,
+	0x76c8c004,
+	0x4002ba12,
+	0xffff0d04,
+	0xb78092da,
+	0x9e5b5d8c,
+	0xc040691a,
+	0x0244aa65,
+	0xba000009,
+	0x9c224002,
+	0xa205f839,
+	0x1cb0f011,
+	0x9e539e99,
+	0x90d6c000,
+	0x0902c002,
+	0x9100c000,
+	0x7040d002,
+	0x01090a04,
+	0x4000ba12,
+	0x19400d02,
+	0xc8129e50,
+	0x0a067004,
+	0xcc1251eb,
+	0xc00270c8,
+	0xcc100dce,
+	0xcc127246,
+	0xba1b72c4,
+	0xb7804003,
+	0x05b65d0c,
+	0x512b9e58,
+	0xa986c840,
+	0x4003ba1b,
+	0x65b5c101,
+	0x9bc4c1f4,
+	0xfff49e83,
+	0xf9f89baa,
+	0x9c22aa1d,
+	0x0e30f011,
+	0x4314b760,
+	0x92e2c000,
+	0xc10100c8,
+	0xb74c0096,
+	0x750273b3,
+	0xba120912,
+	0xd0024003,
+	0xd0311926,
+	0xd0100e20,
+	0xc10170c8,
+	0xd0120124,
+	0xba1c7104,
+	0x9e5c4002,
+	0x0a48c0c8,
+	0xa801d208,
+	0x70c0c010,
+	0xaa1dd3e8,
+	0x7008c012,
+	0x287ccffe,
+	0xf8399c22,
+	0xb720a205,
+	0x0a02430c,
+	0x9e8b0992,
+	0x702bb58c,
+	0x0db0c0d4,
+	0x6d2bb58c,
+	0x5aadb586,
+	0x542bb58d,
+	0x672db586,
+	0x67adb586,
+	0x692db586,
+	0x64adb586,
+	0x996ffe54,
+	0x4314b760,
+	0x0982c002,
+	0x0da0c0d6,
+	0xaa1df9f8,
+	0x90a0fe4b,
+	0x430cb780,
+	0xd11005b6,
+	0xb78c04b9,
+	0x01b87cab,
+	0x4002ba1b,
+	0x70c0d014,
+	0x753ec7fc,
+	0x48bab340,
+	0x7cabb56c,
+	0xa6059c22,
+	0x430cb7a0,
+	0xb781008b,
+	0xb7a65e2d,
+	0x75026bb5,
+	0x9184c000,
+	0x9a40fff4,
+	0xc0007400,
+	0x008b90e4,
+	0x50adb706,
+	0x9060c000,
+	0xd1100802,
+	0xb79f1451,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xa6059c22,
+	0x430cb7a0,
+	0xb766008b,
+	0xfff45ab5,
+	0x008b9a0c,
+	0x6cadb746,
+	0x5aadb786,
+	0x12400244,
+	0x6cadb586,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0xb7a0a60d,
+	0x097a430c,
+	0xb786008b,
+	0xd010502d,
+	0x196c7104,
+	0x7104cc12,
+	0x4e2db786,
+	0xb76c9e9d,
+	0x9ea35a2b,
+	0x6a7ac006,
+	0x5bb3b5ae,
+	0x0d025988,
+	0x5b1fc200,
+	0x983fffd4,
+	0x7740008b,
+	0x4eadb506,
+	0x9c87c820,
+	0x9116c000,
+	0x4000b960,
+	0x9080c000,
+	0x7e2db5c6,
+	0xffff0890,
+	0x008b93a1,
+	0x4e2db786,
+	0x655dd131,
+	0x6659d131,
+	0x6cadb546,
+	0x4fadb586,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0x9c228c60,
+	0x8420a61d,
+	0x430cb7a0,
+	0x0787a199,
+	0xb7869ea8,
+	0x7502714c,
+	0x1092d019,
+	0x9132c000,
+	0x08829ea8,
+	0x634ab78d,
+	0xd00a7502,
+	0x9ea80892,
+	0xb786a09d,
+	0x7504564c,
+	0x9364c001,
+	0x5e4cb781,
+	0x734ab7cc,
+	0x594cb7e6,
+	0xc0007502,
+	0xfff49284,
+	0x740099b1,
+	0x91e4c000,
+	0xb786008b,
+	0xb74650ad,
+	0xc2006bad,
+	0x70885a08,
+	0x90bcc000,
+	0xc0000f32,
+	0x0f129060,
+	0xb7819ea8,
+	0x75025e4c,
+	0x9104c006,
+	0x4e4cb786,
+	0x4fccb746,
+	0x70886a1e,
+	0x9016c006,
+	0x5e05d322,
+	0x9ea50268,
+	0x2efccffe,
+	0x9180c001,
+	0xc0c8020b,
+	0xd2080a38,
+	0xc001aa82,
+	0x77c090a0,
+	0x91e4c000,
+	0xb78c008b,
+	0x75006e2b,
+	0x9122c000,
+	0xc0c8020b,
+	0xd2080a38,
+	0xc003ab01,
+	0xd01092e0,
+	0x9ea804fe,
+	0xc380009a,
+	0xb78c5c88,
+	0xb7cc654a,
+	0xc101742b,
+	0xb7e6049a,
+	0x752a5b4d,
+	0x9eb50f0e,
+	0x1f62d009,
+	0x7440a89d,
+	0x9004c003,
+	0xc00075c0,
+	0x020b9124,
+	0x0a48c0c8,
+	0xa902d208,
+	0x9100c004,
+	0x9ebba91a,
+	0x4002ba1e,
+	0x9a6afff4,
+	0x430cb720,
+	0xb7819e82,
+	0xcffe5e2d,
+	0x75042d7c,
+	0x9304c003,
+	0xb7869ea8,
+	0x7504564c,
+	0x9242c003,
+	0x5c88d3a2,
+	0xb746009a,
+	0xb7865f2d,
+	0xb726602d,
+	0xb7666135,
+	0xe0006235,
+	0xc0030244,
+	0xc2009062,
+	0x01a85905,
+	0x6525d131,
+	0xc18005b2,
+	0xc1015a05,
+	0xc10105b8,
+	0xc1f405b4,
+	0x9e829a2a,
+	0x2d7ccffe,
+	0x9200c002,
+	0x5eadb781,
+	0x75021a04,
+	0x9192c000,
+	0x066cd010,
+	0xc1019e51,
+	0xd010024a,
+	0x9e6a7048,
+	0x9120c000,
+	0x066ad010,
+	0xd0109e51,
+	0xd0107048,
+	0xd012155c,
+	0x03097104,
+	0x2b7ccffe,
+	0x4314b7a0,
+	0xb781040b,
+	0x75025e4c,
+	0x92a4c001,
+	0x98f4fff4,
+	0xc0017400,
+	0x008b9204,
+	0x562db786,
+	0xc0017504,
+	0x040b9144,
+	0x64cab78d,
+	0x7510c004,
+	0x9074c001,
+	0x50adb786,
+	0x6badb746,
+	0x5a08c200,
+	0xc0007088,
+	0x020b9356,
+	0x0a38c0c8,
+	0xab01d208,
+	0x9260c000,
+	0xb7ac008b,
+	0x774073b3,
+	0x9204fffb,
+	0x9080fffa,
+	0x430cb720,
+	0x5e2db781,
+	0xfffd7508,
+	0xfffd93a4,
+	0x058f9160,
+	0x4002ba1e,
+	0x9a12fff4,
+	0x7deeb79f,
+	0x7e6eb7bf,
+	0x7eeeb7df,
+	0x7f6eb7ff,
+	0x8c20c002,
+	0xa60d9c22,
+	0x430cb7a0,
+	0xb786008b,
+	0x750075ad,
+	0x9264c001,
+	0x98a8fff4,
+	0xc0007400,
+	0x008b91a2,
+	0x5babb78e,
+	0x67adb744,
+	0x0a027088,
+	0x0a42d004,
+	0x9360c000,
+	0xb781008b,
+	0x75025e2d,
+	0x90a2c000,
+	0xc0007508,
+	0x008b9204,
+	0x67adb784,
+	0x4e2db746,
+	0x50b5b746,
+	0x71156245,
+	0xd00b0a02,
+	0xc0000a42,
+	0x0a069080,
+	0xb586008b,
+	0x008b75ad,
+	0x75adb786,
+	0xc0037500,
+	0x008b9042,
+	0x5e2db781,
+	0xc0027508,
+	0x75029382,
+	0x9224c000,
+	0x986efff4,
+	0x0a80f012,
+	0x9164c000,
+	0xb786008b,
+	0xb7464e2d,
+	0x6a1e4fad,
+	0xc0017088,
+	0x008b93f6,
+	0x53abb78c,
+	0xc0027500,
+	0x008b9082,
+	0x7433b7ac,
+	0x6badb786,
+	0xd8120906,
+	0xb7817104,
+	0x75025e2d,
+	0x9184c000,
+	0x984cfff4,
+	0xc0007400,
+	0x008b90e4,
+	0x50adb786,
+	0x9060c000,
+	0xba2d0a02,
+	0x9ea24003,
+	0x9eb39e6b,
+	0x995afff4,
+	0x15d1d110,
+	0x59870a0e,
+	0x70c8cc10,
+	0xcc121a08,
+	0x008b70c8,
+	0x6db3b76c,
+	0xba1b1187,
+	0xb79f4002,
+	0xb7bf7eee,
+	0xb7df7f6e,
+	0x8c607fee,
+	0x90c0ffee,
+	0x99d7fff4,
+	0x9e6c1001,
+	0x7008c012,
+	0xfffe7400,
+	0xfffd905a,
+	0xb79f9340,
+	0xb7bf7eee,
+	0xb7df7f6e,
+	0x8c607fee,
+	0xa6059c22,
+	0x4314b7a0,
+	0xb78c9e69,
+	0x75025aab,
+	0x1a42d001,
+	0x90c2c000,
+	0xb78c9e69,
+	0x0a045b2b,
+	0x652bb58d,
+	0xb74c9e69,
+	0xd0115aab,
+	0xcffe1a22,
+	0xc07c2a7c,
+	0xc000753e,
+	0x097f91f4,
+	0x0a7ecffe,
+	0x63abb54d,
+	0x732db586,
+	0x642bb54d,
+	0x64abb54d,
+	0x9120c001,
+	0x9e939e69,
+	0x5b2bb7ac,
+	0x09d2d011,
+	0x98f0c1f4,
+	0x75401804,
+	0x09029e69,
+	0x287ccffe,
+	0x0922d002,
+	0xb50d0104,
+	0x0a06642b,
+	0x7088c812,
+	0x652bb78d,
+	0x4e35b746,
+	0x62400a84,
+	0xb5ad02d8,
+	0xcffe64ab,
+	0xc1012afc,
+	0xb54d62d5,
+	0xb5a663ab,
+	0x9e69732d,
+	0x652bb78d,
+	0x4e2db746,
+	0xb5866245,
+	0xb79f73ad,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xa61d9c22,
+	0xb7c08440,
+	0x008d430c,
+	0x5e2db781,
+	0x76adb726,
+	0xc0087508,
+	0x744092e4,
+	0x90c2c006,
+	0x0d029eb1,
+	0x654bb76d,
+	0x64cbb78d,
+	0x4e4db746,
+	0x5985d1a4,
+	0xc1011094,
+	0xa09905b8,
+	0x99d7ffb4,
+	0x008da015,
+	0x652bb7ed,
+	0x68abb78d,
+	0x76b5b7c6,
+	0x6333b7ed,
+	0x1a041278,
+	0x7780c005,
+	0xc0009ea5,
+	0xb7669152,
+	0xc0054e2d,
+	0xd31474c0,
+	0xc0005da8,
+	0x9eb190f4,
+	0xb766058d,
+	0x59ab4e4d,
+	0x987fc1f4,
+	0xcffea916,
+	0xa9992efc,
+	0x162ed010,
+	0xba249e6a,
+	0x624f4002,
+	0x0659d110,
+	0xb766008d,
+	0xb7466ab5,
+	0xba246b35,
+	0xba124002,
+	0x62474002,
+	0xb76c6127,
+	0xc1015a2b,
+	0xc10105b8,
+	0xb5660524,
+	0xb5466ab5,
+	0xb5c66b35,
+	0x058d4e35,
+	0x02815988,
+	0x985cc1f4,
+	0xb786008d,
+	0xb506532d,
+	0xc0054ead,
+	0xc0007500,
+	0xc20090f4,
+	0x61595a2b,
+	0x90a0c000,
+	0xc2006259,
+	0x9eb15929,
+	0x4fcdb786,
+	0x534db546,
+	0x7500c005,
+	0x90f4c000,
+	0x5a2bc200,
+	0xc0006159,
+	0x625990a0,
+	0x5929c200,
+	0xb786008d,
+	0xb5466bad,
+	0xc0054fad,
+	0xc0007500,
+	0xc20090f4,
+	0x62595a2b,
+	0x90a0c000,
+	0xc2006259,
+	0x9eb15a29,
+	0x6ccdb706,
+	0x6bcdb586,
+	0x7400c005,
+	0x90f4c000,
+	0x5a2bc000,
+	0xc0006059,
+	0x625190a0,
+	0x5829c200,
+	0xb7a6008d,
+	0xb7a64e2d,
+	0xb5064fb5,
+	0xd2a46cad,
+	0xd01059fd,
+	0xc101065a,
+	0xc10105ba,
+	0xc200024a,
+	0x5d875a13,
+	0x01c7d120,
+	0x50adb586,
+	0xc1d4018b,
+	0x600b9bff,
+	0xb5069eb1,
+	0xc01250cd,
+	0x0a02700a,
+	0x16d0c101,
+	0x5155b5a6,
+	0x76cdb586,
+	0x50cdb506,
+	0xc0da9eb2,
+	0xd0100d60,
+	0x7480a941,
+	0x9142c000,
+	0xc0c8020d,
+	0xd2080a38,
+	0x0a02a101,
+	0xa241d010,
+	0xc0da9eb2,
+	0xd0100d68,
+	0xc01ca941,
+	0xc00074be,
+	0xc0029222,
+	0xd0100a4e,
+	0x09027088,
+	0x7104d012,
+	0xc0c8010d,
+	0xd0080948,
+	0x0a7fa241,
+	0xa241d010,
+	0xc0da9eb2,
+	0xd0100d64,
+	0xc01ca941,
+	0xc00074be,
+	0xc0029222,
+	0xd0100a4e,
+	0x09027088,
+	0x7104d012,
+	0xc0c8010d,
+	0xd0080944,
+	0x0a7fa241,
+	0xa241d010,
+	0x9a8ffff4,
+	0x7d6eb79f,
+	0x7deeb7bf,
+	0x7e6eb7df,
+	0x7eeeb7ff,
+	0x8c40c002,
+	0x9380ffe3,
+	0xc0067440,
+	0x9eb190c2,
+	0xb76d0d02,
+	0xb78d654b,
+	0xb74664cb,
+	0xd1a44e4d,
+	0x10945985,
+	0x05b8c101,
+	0xffb4a09d,
+	0xa01198c2,
+	0xb7ed008d,
+	0xb78d652b,
+	0xb7c668ab,
+	0xb7ed76b5,
+	0x12786333,
+	0xc0051a04,
+	0x9ea57780,
+	0x9152c000,
+	0x4e2db766,
+	0x74c0c005,
+	0x5da8d314,
+	0x90f4c000,
+	0x058d9eb1,
+	0x4e4db766,
+	0xc1d459ab,
+	0xa9129b6a,
+	0x2efccffe,
+	0xd010a99d,
+	0x9e6a162e,
+	0x4002ba24,
+	0xd110624f,
+	0x008d0659,
+	0x6ab5b766,
+	0x6b35b746,
+	0x4002ba24,
+	0x4002ba12,
+	0x61276247,
+	0x5a2bb76c,
+	0x05b8c101,
+	0x0524c101,
+	0x6ab5b566,
+	0x6b35b546,
+	0x4e35b5c6,
+	0x5988058d,
+	0xc1d40281,
+	0x008d9b47,
+	0x532db786,
+	0x4eadb506,
+	0x7500c005,
+	0x90f4c000,
+	0x5a2bc200,
+	0xc0006159,
+	0x625990a0,
+	0x5929c200,
+	0xb7869eb1,
+	0xb5464fcd,
+	0xc005534d,
+	0xc0007500,
+	0xc20090f4,
+	0x61595a2b,
+	0x90a0c000,
+	0xc2006259,
+	0x008d5929,
+	0x6badb786,
+	0x4fadb546,
+	0x7500c005,
+	0x90f4c000,
+	0x5a2bc200,
+	0xc0006259,
+	0x625990a0,
+	0x5a29c200,
+	0xb7069eb1,
+	0xb5866ccd,
+	0xc0056bcd,
+	0xc0007400,
+	0xc00090f4,
+	0x60595a2b,
+	0x90a0c000,
+	0xc2006251,
+	0x008d5829,
+	0x4e2db7a6,
+	0x4fb5b7a6,
+	0x6cadb506,
+	0x59fdd2a4,
+	0x065ad010,
+	0x05bac101,
+	0x024ac101,
+	0x5a13c200,
+	0xd1205d87,
+	0xb58601c7,
+	0x018b50ad,
+	0x9aeac1d4,
+	0x9eb1600b,
+	0x50cdb506,
+	0x700ac012,
+	0xc1010a02,
+	0xb5a616d0,
+	0xb5865155,
+	0xb50676cd,
+	0x9eb250cd,
+	0x0d60c0da,
+	0xa941d010,
+	0xc0007480,
+	0x020d9142,
+	0x0a38c0c8,
+	0xa101d208,
+	0xd0100a02,
+	0x9eb2a241,
+	0x0d68c0da,
+	0xa941d010,
+	0x74bec01c,
+	0x9222c000,
+	0x0a4ec002,
+	0x7088d010,
+	0xd0120902,
+	0x010d7104,
+	0x0948c0c8,
+	0xa241d008,
+	0xd0100a7f,
+	0x9eb2a241,
+	0x0d64c0da,
+	0xa941d010,
+	0x74bec01c,
+	0x9222c000,
+	0x0a4ec002,
+	0x7088d010,
+	0xd0120902,
+	0x010d7104,
+	0x0944c0c8,
+	0xa241d008,
+	0xd0100a7f,
+	0xb79fa241,
+	0xb7bf7d6e,
+	0xb7df7dee,
+	0xb7ff7e6e,
+	0xc0027eee,
+	0xffeb8c40,
+	0x9e5a9200,
+	0x70c0d014,
+	0x1a0476c0,
+	0x0244d01b,
+	0x1228d01c,
+	0xff9d9ea3,
+	0xa60d92c0,
+	0x4314b7a0,
+	0x03079e5d,
+	0xc0d8058b,
+	0xc00e0da0,
+	0xfe3409b2,
+	0xb760986c,
+	0xc00a4314,
+	0xc0ca0992,
+	0xfe340dc0,
+	0xb7609864,
+	0xc0024314,
+	0xc0d60982,
+	0xfe340da0,
+	0xb760985c,
+	0x09d24314,
+	0x0dd0c0d4,
+	0x9855fe34,
+	0x4314b760,
+	0x09f2c04c,
+	0x0dd0c0e6,
+	0x984dfe34,
+	0x018b058b,
+	0x0d80c0c6,
+	0x0d32c004,
+	0x9870fe34,
+	0x9e699e68,
+	0x4facb786,
+	0x040b097f,
+	0x7520c001,
+	0xc0c89e6c,
+	0xc0da0c38,
+	0xc0de0a64,
+	0xd20808a0,
+	0x0a22a101,
+	0x4029b580,
+	0x4050b760,
+	0xd00d9e6b,
+	0x0c821a48,
+	0xb421050b,
+	0x9e69443a,
+	0x09e8c0da,
+	0x0d60c0da,
+	0xd0089e4d,
+	0x9d0aa161,
+	0xb56c018d,
+	0xd0107332,
+	0xb526a0c2,
+	0x040b76b4,
+	0x08e0c12a,
+	0x0b02c010,
+	0xa961d008,
+	0x9e689e44,
+	0x0a6cc0da,
+	0xa101d208,
+	0xaa61d008,
+	0x6fb2b74d,
+	0xa9c2d018,
+	0x0a027500,
+	0x0a42d002,
+	0x0244c101,
+	0x6faab58d,
+	0x7e7edffc,
+	0x0d38d012,
+	0x430cb740,
+	0x05a2d022,
+	0xc0c80205,
+	0xd2080a48,
+	0x9e58aa01,
+	0x7008d010,
+	0x0944c0c8,
+	0xa941d008,
+	0x7104d012,
+	0x76440c84,
+	0x462bb59a,
+	0x402bb5c0,
+	0x412bb5a0,
+	0x0c040984,
+	0xfffe0888,
+	0xb7209124,
+	0xb78c430c,
+	0x752a652b,
+	0x9112c000,
+	0x0a169e69,
+	0x7b2bb58d,
+	0x90a0c000,
+	0xb52d9e68,
+	0x9e697b32,
+	0xb7660d02,
+	0xb76650b5,
+	0xfff44e2d,
+	0xcffe9b40,
+	0x0a7a287c,
+	0x7008c010,
+	0xc0121a74,
+	0x9e697008,
+	0x5babb50e,
+	0x98a1fff4,
+	0xb78c9e68,
+	0x750065aa,
+	0xd0010a02,
+	0xb5800a42,
+	0xb79f448c,
+	0xb7bf7eee,
+	0xb7df7f6e,
+	0x8c607fee,
+	0xb7209c22,
+	0x0a02430c,
+	0x4aabb72d,
+	0xa271f010,
+	0xa269f010,
+	0xa0e1f010,
+	0xa265f010,
+	0xa27dd810,
+	0xa279d810,
+	0xa279f010,
+	0xa271f050,
+	0xa261f050,
+	0xa27dd850,
+	0xa279d850,
+	0xa269d850,
+	0xa26df050,
+	0xa269f050,
+	0xa265f050,
+	0xa275f050,
+	0x430cb720,
+	0x4aabb74d,
+	0x6f2db546,
+	0x430cb720,
+	0x712db586,
+	0x430cb720,
+	0x702db586,
+	0x430cb720,
+	0x6fadb586,
+	0x430cb720,
+	0x61abb58d,
+	0x430cb720,
+	0x612bb58d,
+	0x430cb720,
+	0x722db586,
+	0x430cb720,
+	0x732db586,
+	0x430cb720,
+	0x65abb58d,
+	0x430cb720,
+	0x652bb58d,
+	0x430cb720,
+	0x632bb58d,
+	0x430cb720,
+	0x74adb586,
+	0x430cb720,
+	0x742db586,
+	0x430cb720,
+	0x73adb586,
+	0x430cb720,
+	0x75adb586,
+	0x430cb720,
+	0x752db586,
+	0x74c29c22,
+	0xc0019e98,
+	0xb78091a4,
+	0x0902430c,
+	0x0a00c0e2,
+	0xa101d208,
+	0x4314b720,
+	0x684bb78c,
+	0xc0017500,
+	0xb7269104,
+	0xb74d54cd,
+	0xb7876353,
+	0xb766464d,
+	0xb7466dcd,
+	0xb766514d,
+	0xc10150d5,
+	0x02466523,
+	0x1244c101,
+	0x1126c101,
+	0xc0007104,
+	0x9e4c925c,
+	0x0a00c0e2,
+	0xa002d208,
+	0x9160c000,
+	0xc00074c0,
+	0xf0109104,
+	0xb720aa61,
+	0xb58d430c,
+	0xb7804aab,
+	0xc0e2430c,
+	0xd2080a00,
+	0x9c22a801,
+	0x8420a61d,
+	0xa1199e57,
+	0x9e4a9e9f,
+	0xcc120d02,
+	0xd0317286,
+	0xaa1966be,
+	0x7540d001,
+	0x020b134e,
+	0x4828b334,
+	0xc0007580,
+	0x9ea3935c,
+	0xff94018d,
+	0xaa199a22,
+	0xc2009e86,
+	0x71885a0b,
+	0x931ac000,
+	0x5990d3a4,
+	0x01fec101,
+	0xff940d02,
+	0xc1019a14,
+	0xd024600d,
+	0xc0005b13,
+	0xb7209160,
+	0x0d02430c,
+	0x4c2db726,
+	0xff941194,
+	0x9e869a06,
+	0x77400e82,
+	0x913ac000,
+	0xc0007740,
+	0xcfff90e4,
+	0xc000757e,
+	0x676f9074,
+	0xb79f9e70,
+	0xb7bf7dee,
+	0xb7df7e6e,
+	0xb7ff7eee,
+	0xc0027f6e,
+	0x9c228c20,
+	0xb720a61d,
+	0x0d02430c,
+	0x4c2db766,
+	0x45b5b767,
+	0x5ab3b7cc,
+	0x632bb7ad,
+	0x712db7e6,
+	0x73b5b7e6,
+	0x99dbff94,
+	0x430cb720,
+	0xb7860301,
+	0xb70764ad,
+	0x7504462d,
+	0x9264c001,
+	0x45adb787,
+	0xd0207540,
+	0xc00012c0,
+	0xb7669282,
+	0x018b74b5,
+	0xff940d02,
+	0xb72099c4,
+	0x0a02430c,
+	0x4c2db726,
+	0x6003109a,
+	0x1451d110,
+	0x7100c812,
+	0xb7209e95,
+	0xb786430c,
+	0x750265ad,
+	0x91b4c000,
+	0xc00077ba,
+	0x9ea99152,
+	0x49adb747,
+	0x4003ba09,
+	0xc001058b,
+	0xb76690c0,
+	0x058b4c2d,
+	0xc0010d02,
+	0xb7879120,
+	0x754044ad,
+	0x11c0d020,
+	0x9142c000,
+	0x4c2db786,
+	0x4aadb747,
+	0x6245124a,
+	0x15b8c101,
+	0x65adb786,
+	0xc0007502,
+	0xb78d90f2,
+	0x75004a2b,
+	0x91a2c000,
+	0xb7479ea9,
+	0xba094a2d,
+	0x018f4003,
+	0xfff4050f,
+	0xc0009b45,
+	0xb7669100,
+	0x9ea24c2d,
+	0xff9411ba,
+	0x0a029976,
+	0x7100d012,
+	0x000c006c,
+	0x7008c010,
+	0x7e6eb79f,
+	0x7eeeb7bf,
+	0x7f6eb7df,
+	0x7feeb7ff,
+	0x8c00c002,
+	0xf8399c22,
+	0xb740a205,
+	0xd0105c8c,
+	0x02440624,
+	0xaa1ddbc8,
+	0x9e5b0107,
+	0x70886a0c,
+	0x4834b320,
+	0x91b4c001,
+	0xc00076c0,
+	0xb760927c,
+	0xc18040d5,
+	0x0d025a07,
+	0x61a7d132,
+	0xc1015d99,
+	0xff9405b8,
+	0x582b9944,
+	0x4002ba00,
+	0x90c0c000,
+	0x0e22d011,
+	0x4002ba04,
+	0x430cb740,
+	0xc0e40205,
+	0xd2080a14,
+	0x7008aa01,
+	0x443ab340,
+	0x913ac000,
+	0xc0e40205,
+	0xd2080a10,
+	0xc012aa01,
+	0xf9f87008,
+	0x9c22aa1d,
+	0xa205f839,
+	0x430cb720,
+	0x64adb786,
+	0xc0007504,
+	0xc0e690c4,
+	0xc0000890,
+	0xc0e69080,
+	0xb78008d0,
+	0xdffc43ab,
+	0xc0007d3e,
+	0x9e5090a4,
+	0x90a0c000,
+	0xfff49e89,
+	0xb7209ba8,
+	0xb78d430c,
+	0x75024dab,
+	0x91c4c000,
+	0xc0c80203,
+	0xd2080a60,
+	0x7500aa01,
+	0x90c4c000,
+	0x0a04d011,
+	0x4002ba04,
+	0xc0d20203,
+	0xd2080a60,
+	0x7502aa01,
+	0x90c4c000,
+	0x0a02d011,
+	0x4002ba04,
+	0x522bb74d,
+	0x0a28d011,
+	0xc0007008,
+	0xd01190fa,
+	0x70081a28,
+	0x9096c000,
+	0x4002ba04,
+	0xc0e40203,
+	0xd2080a0c,
+	0x097ba902,
+	0xc1010183,
+	0xba241204,
+	0xd0124002,
+	0x09107104,
+	0x7104d010,
+	0x0994c0e4,
+	0x0528c101,
+	0xa961d008,
+	0xba009e50,
+	0x70044002,
+	0x443ab320,
+	0x913ac000,
+	0xc0e40203,
+	0xd2080a10,
+	0xc012aa01,
+	0xf9f87008,
+	0x9c22aa1d,
+	0x76c0a61d,
+	0x430cb720,
+	0x9264c000,
+	0x65abb74d,
+	0x61abb78d,
+	0xb7a69e8d,
+	0xb766702d,
+	0xb72d6fad,
+	0xd0206133,
+	0xc0e60128,
+	0xc0000ed0,
+	0x9e8d91a0,
+	0x65b3b74d,
+	0x722db7a6,
+	0x732db766,
+	0x6533b72d,
+	0x0e90c0e6,
+	0x7680c008,
+	0x92bcc000,
+	0x5e1bf122,
+	0x90ccc000,
+	0x0a02c002,
+	0x90e0c000,
+	0x7100d002,
+	0xba240a04,
+	0x9ea34000,
+	0x52b3c200,
+	0x554f54af,
+	0x768051f3,
+	0x93a2c002,
+	0x468cb780,
+	0x0524d010,
+	0xc8409e51,
+	0xb780ab46,
+	0xda10470c,
+	0xc100a931,
+	0xc0405d87,
+	0xd131aba5,
+	0x09046667,
+	0xda109e53,
+	0xc200a131,
+	0x05b2531f,
+	0xff940d02,
+	0xc00c985e,
+	0x9e877588,
+	0xa935da10,
+	0x937cc001,
+	0x4002ba12,
+	0x12440a6e,
+	0x65ebc101,
+	0x02899eba,
+	0x4002ba2d,
+	0xc07e55eb,
+	0xcc100d7e,
+	0x9eaa72c4,
+	0x5a07c300,
+	0xc10155e8,
+	0x018d05b8,
+	0xff940d02,
+	0x9e83983e,
+	0xaa21f210,
+	0xa9b1da10,
+	0xc10165bf,
+	0xf21005b8,
+	0xba1ba1a2,
+	0x0d024002,
+	0x982fff94,
+	0xf210755e,
+	0xd04da025,
+	0xd01a1a50,
+	0xc0005213,
+	0x0a4290ba,
+	0x5210124a,
+	0xa225f210,
+	0xda100a06,
+	0xb79fa23d,
+	0xb7bf7e6e,
+	0xb7df7eee,
+	0xb7ff7f6e,
+	0xc0027fee,
+	0x9c228c00,
+	0x76c2a605,
+	0x91e4c001,
+	0x430cb720,
+	0x64adb786,
+	0xd0227504,
+	0xfff415b6,
+	0xb7209b53,
+	0xb74d430c,
+	0xb786632b,
+	0x70884c2d,
+	0x93a2c000,
+	0x712db7a6,
+	0x9a0efff4,
+	0x430cb780,
+	0x018b9e83,
+	0xc0c80109,
+	0xd0080938,
+	0xc0e4a941,
+	0x9e920a0c,
+	0xa101d208,
+	0xfff40916,
+	0xb7809ac5,
+	0xc0c8430c,
+	0xd2080a38,
+	0xb780a001,
+	0xc0c8430c,
+	0xd2080a38,
+	0xb79fa801,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xa6059c22,
+	0x4314b720,
+	0x05839e5b,
+	0x0d88c0e2,
+	0xa961d010,
+	0x4655b747,
+	0x6dcdb786,
+	0xd1107480,
+	0xc0000529,
+	0xb7869102,
+	0x02484e4d,
+	0xc00110c4,
+	0xb7809060,
+	0xc101440c,
+	0xb5400528,
+	0xb7864414,
+	0x729950cd,
+	0x91b8c000,
+	0xd0100a06,
+	0xb720a261,
+	0xb726430c,
+	0x00924e2d,
+	0xc0001094,
+	0xb78d91a0,
+	0xb7464a4b,
+	0x0a084e4d,
+	0x729360c5,
+	0x9216c000,
+	0x1094c101,
+	0xc0007440,
+	0xd071917c,
+	0xc2000a1e,
+	0xf0085a17,
+	0x0a06a265,
+	0x90a0c000,
+	0xf0080a02,
+	0xd808a265,
+	0xb7a0a265,
+	0x0d02430c,
+	0xb78d008b,
+	0xb76d65ab,
+	0xb74761ab,
+	0x01b8492d,
+	0x5985d1a4,
+	0x05b4c101,
+	0x9b7bff74,
+	0xb50c008b,
+	0xb7206a2b,
+	0xb78c430c,
+	0xc0c86a2b,
+	0xb58008b8,
+	0xb7204029,
+	0xb787430c,
+	0xb587452d,
+	0xb72044ad,
+	0xb786430c,
+	0x750464ad,
+	0x9024c001,
+	0x65adb786,
+	0xc0007502,
+	0xb7879284,
+	0x09964b2d,
+	0xc2000d02,
+	0xb5875a0b,
+	0xb7a04bad,
+	0x008b430c,
+	0x7d35b766,
+	0x9b4fff74,
+	0xb506008b,
+	0xb7207d2d,
+	0xb786430c,
+	0xb58773ad,
+	0xc00149ad,
+	0xb7869040,
+	0xb587742d,
+	0xb7204bad,
+	0xb786430c,
+	0xb58773ad,
+	0xb7204a2d,
+	0xb787430c,
+	0xb58644ad,
+	0xb7207d2d,
+	0xb78d430c,
+	0xb74c52ab,
+	0x02446a2b,
+	0x52abb58d,
+	0x430cb720,
+	0x4a2bb78d,
+	0xb58d0a04,
+	0xb79f4a2b,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0x9e9a9c22,
+	0xd1220906,
+	0x52445c87,
+	0x72d91a04,
+	0x933cc000,
+	0x1a32d011,
+	0x19045250,
+	0x9160c000,
+	0xc0007917,
+	0xd11090c2,
+	0xc0001627,
+	0xc2009360,
+	0xba1a5a07,
+	0x70c24002,
+	0xffff0904,
+	0x08029278,
+	0xd0119c22,
+	0x75001a12,
+	0xc8100d02,
+	0x51509c83,
+	0x4818b323,
+	0x9160c000,
+	0xc0007897,
+	0x121890e2,
+	0xba000009,
+	0x9c224002,
+	0x9e545907,
+	0xba240d04,
+	0xffff4002,
+	0x08069261,
+	0xa6059c22,
+	0x430cb7a0,
+	0x09020687,
+	0xb9609eaa,
+	0xc0c64258,
+	0x9e690d00,
+	0xc0209e93,
+	0x0904aa25,
+	0xa249c030,
+	0x9321ffff,
+	0xc0020d82,
+	0xfff40982,
+	0x74009bae,
+	0x0a02010b,
+	0x0a42d002,
+	0x0964c0c8,
+	0xa241d008,
+	0x430cb7a0,
+	0x008b09ba,
+	0x4c35b766,
+	0x9b9dfff4,
+	0xb50e008b,
+	0xb7205bab,
+	0x0902430c,
+	0x5babb78e,
+	0x5fabb58e,
+	0x430cb720,
+	0x0a06c001,
+	0x5cabb54e,
+	0x430cb720,
+	0x60abb54e,
+	0x430cb720,
+	0x4d2db587,
+	0x430cb720,
+	0x4e2db786,
+	0x6e2db586,
+	0xb7809e69,
+	0xb7205729,
+	0xb58d430c,
+	0xb79f4aab,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0x0a029c22,
+	0xa261d810,
+	0x430cb720,
+	0x632bb78c,
+	0xb3407500,
+	0xb74648a4,
+	0xb7664e2d,
+	0xb7464fad,
+	0x02246db5,
+	0xc1010244,
+	0xc20011b4,
+	0xb7465a07,
+	0xd0126e2d,
+	0xb7477104,
+	0xb74c46b5,
+	0x70c85aab,
+	0x1124c101,
+	0xc0001904,
+	0x0a0690b6,
+	0xa261d810,
+	0x430cb720,
+	0x6035b746,
+	0xc0007680,
+	0x748691e2,
+	0x919ac000,
+	0x4e2db786,
+	0x02466229,
+	0xc0007115,
+	0x0a0690b6,
+	0xa261d810,
+	0x430cb720,
+	0x4e2db786,
+	0x6dadb746,
+	0x70880248,
+	0x1248d01c,
+	0x4459b423,
+	0xa6059c22,
+	0x430cb720,
+	0xb7870687,
+	0x1a04472d,
+	0x472db587,
+	0xa961d810,
+	0x430cb720,
+	0xc0007482,
+	0x0a029164,
+	0x44adb587,
+	0x430cb720,
+	0x4dabb54d,
+	0x9160c000,
+	0xb58d0a02,
+	0xb7204dab,
+	0xb787430c,
+	0xb58746ad,
+	0xb72047ad,
+	0x9e8b430c,
+	0x4e35b746,
+	0x0d84c0e2,
+	0xa9e1d010,
+	0xc00074c0,
+	0x058590a2,
+	0x9280c000,
+	0x67adb784,
+	0x50adb746,
+	0x6629d131,
+	0xb3337104,
+	0xc0004458,
+	0x0a069138,
+	0xa261d010,
+	0x430cb720,
+	0x4e35b766,
+	0x430cb720,
+	0x0d02091e,
+	0x6dadb766,
+	0x462db787,
+	0xc1010246,
+	0xb5861246,
+	0xb7206dad,
+	0xb786430c,
+	0xb76776ad,
+	0x1246462d,
+	0x76adb586,
+	0x430cb720,
+	0x4e35b726,
+	0x462db787,
+	0x5e2fb763,
+	0x1419d110,
+	0x587fd024,
+	0x01b0e000,
+	0xd00305b0,
+	0xb5630db2,
+	0xb7205e2f,
+	0xb787430c,
+	0xb726462d,
+	0xb7634e35,
+	0xd1105d2f,
+	0xd0241419,
+	0xe000587f,
+	0x05b001b0,
+	0x0db2d003,
+	0x5d2fb563,
+	0x430cb7a0,
+	0xb763008b,
+	0xc1b45d2f,
+	0xd022984e,
+	0x01015e74,
+	0x3144590d,
+	0x597fd124,
+	0xb543008b,
+	0xb7205daf,
+	0xb786430c,
+	0xb74764ad,
+	0x75044635,
+	0x9344c000,
+	0x6035b546,
+	0x430cb720,
+	0xb7860d02,
+	0xb5866dad,
+	0xb7a0762d,
+	0x008b430c,
+	0x5aabb76c,
+	0x6db5b766,
+	0xff741984,
+	0x008b999a,
+	0x4c2db507,
+	0x9180c000,
+	0x6e2db746,
+	0x02440224,
+	0x0244c101,
+	0x5a09c200,
+	0x6e2db586,
+	0xfff4058b,
+	0xb7209afc,
+	0x0a02430c,
+	0x462db587,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0xb7a0a60d,
+	0x0687430c,
+	0x03070d86,
+	0x9964fff4,
+	0xb506008b,
+	0xb7606f2d,
+	0x09864314,
+	0x0de0c0d6,
+	0x9af3ffd4,
+	0x430cb720,
+	0x4635b5a7,
+	0xaa41da08,
+	0xc0007500,
+	0x9eb390a4,
+	0x998bfff4,
+	0x4314b700,
+	0xc0d09e44,
+	0xd2080a70,
+	0x7502aa01,
+	0x9044c002,
+	0x6454b746,
+	0x4e54b726,
+	0x5acab74c,
+	0x4e54b546,
+	0x430cb720,
+	0x4a52b76d,
+	0xb7661522,
+	0xb78c642d,
+	0x19045aab,
+	0x1126c101,
+	0xc1016247,
+	0xb5866125,
+	0xb72053ad,
+	0xb786430c,
+	0x024476ad,
+	0x76adb586,
+	0x430cb7a0,
+	0xb76c008b,
+	0xb7665a2b,
+	0x59884e35,
+	0x9bf8c194,
+	0xb506008b,
+	0xb7a04ead,
+	0x008b430c,
+	0x4eb5b766,
+	0x4cadb766,
+	0x9be7c194,
+	0xb506008b,
+	0xb78054ad,
+	0x0902430c,
+	0x0a70c0d0,
+	0xa101d208,
+	0xb79f9eb3,
+	0xb7bf7eee,
+	0xb7df7f6e,
+	0x8c607fee,
+	0x90e0fff6,
+	0x6e3bd331,
+	0xd2249e5a,
+	0xd0115921,
+	0x72991a26,
+	0x90bcc000,
+	0xba129ea2,
+	0xd0114003,
+	0x0d8a09a6,
+	0xc8120124,
+	0x70867286,
+	0x9096c000,
+	0x4002ba13,
+	0xd0100a7e,
+	0xb7407088,
+	0xc0e4430c,
+	0xd0080914,
+	0xb780a241,
+	0xc0e4430c,
+	0xd2080a10,
+	0x9c22a102,
+	0xb720a60d,
+	0x76c2430c,
+	0x46adb787,
+	0xb5870a04,
+	0xb72046ad,
+	0xb566430c,
+	0xc00a64b5,
+	0xb7209364,
+	0x0d02430c,
+	0xb7860a82,
+	0xb747762d,
+	0xb7674c2d,
+	0xb76746b5,
+	0x124447ad,
+	0x762db586,
+	0x4314b720,
+	0x1737d110,
+	0x4bb5b7a7,
+	0x474db767,
+	0x76d5b766,
+	0x98b9ff74,
+	0x430cb720,
+	0x6dadb746,
+	0x7635b746,
+	0x4e2db786,
+	0x1124c101,
+	0x12445907,
+	0x7148d012,
+	0x08040008,
+	0xb5075807,
+	0xb72045ad,
+	0xb787430c,
+	0xb74645ad,
+	0xd0127c2d,
+	0xb5877104,
+	0xb72045ad,
+	0xb747430c,
+	0xb78645ad,
+	0xc8107b2d,
+	0x75827088,
+	0x45adb547,
+	0x93dcc000,
+	0x430cb720,
+	0x058b9eaa,
+	0x4c2db766,
+	0x9887ff74,
+	0x430cb720,
+	0x02030936,
+	0x0a64c0c8,
+	0xa902d208,
+	0x4c2db726,
+	0xc1011d04,
+	0x02401264,
+	0x7104d010,
+	0x0244c101,
+	0x62c2d032,
+	0x430cb720,
+	0x45adb787,
+	0x124ac101,
+	0x44adb587,
+	0x430cb720,
+	0x4b2db787,
+	0x44adb747,
+	0x5a1bc200,
+	0xc0007088,
+	0xb5879096,
+	0xb72044ad,
+	0x9eaa430c,
+	0x4c2db786,
+	0x5a05c200,
+	0x0659d110,
+	0x4aadb587,
+	0x430cb7a0,
+	0xb767008b,
+	0xb7664ab5,
+	0xff744c2d,
+	0x008b984a,
+	0x4aadb507,
+	0x430cb720,
+	0x44adb787,
+	0x0659d110,
+	0x45adb587,
+	0x430cb720,
+	0x65adb786,
+	0xc0007502,
+	0xb78d90f2,
+	0x75004a2b,
+	0x92a2c001,
+	0x4d2bb74d,
+	0x6a2bb70c,
+	0xd0027480,
+	0xc0010a02,
+	0xb7869264,
+	0xcffe7d2d,
+	0x7500287c,
+	0x919cc000,
+	0x44adb767,
+	0x9e926209,
+	0x5987d1a4,
+	0x01c7d120,
+	0x9819ff74,
+	0x430cb720,
+	0x6a33b74c,
+	0x1204c101,
+	0x7100d014,
+	0xc0007504,
+	0xb50c90da,
+	0xc0006a2b,
+	0x729192a0,
+	0x0a7acffe,
+	0xb324090a,
+	0xc101443c,
+	0xc0000244,
+	0xb74c9120,
+	0xb78c6a2b,
+	0x02446aab,
+	0x5a07c200,
+	0x6a2bb58c,
+	0x430cb720,
+	0x4d2bb78d,
+	0xc0007500,
+	0xb78c9204,
+	0x753e6a2b,
+	0x90b4c000,
+	0xc0000a7e,
+	0x750090c0,
+	0x90a4c000,
+	0xb58c0a04,
+	0xb7206a2b,
+	0xb786430c,
+	0x750265ad,
+	0x90f2c000,
+	0x4a2bb78d,
+	0xc0007500,
+	0xb78d91e2,
+	0x75004d2b,
+	0x92e4c000,
+	0x6a33b76c,
+	0x2dfcc00e,
+	0x9ac2fff4,
+	0x91e0c000,
+	0xc0e40103,
+	0x0a0a0910,
+	0xa241d008,
+	0x430cb780,
+	0xc0e4097e,
+	0xd2080a14,
+	0xb720a101,
+	0xb78e430c,
+	0x7502502b,
+	0x91e4c000,
+	0xc0c80203,
+	0xd2080a60,
+	0x7500aa01,
+	0x90e4c000,
+	0x6a2bb78c,
+	0xb58c0a08,
+	0xb7206a2b,
+	0xb78c430c,
+	0xc0c86a2b,
+	0x0a0408b8,
+	0x4029b580,
+	0x430cb740,
+	0x02059e92,
+	0x0d38c0c8,
+	0x0a14c0e4,
+	0xaa01d208,
+	0xa9c1d010,
+	0xc00070c8,
+	0x02059152,
+	0x0a10c0e4,
+	0xaa01d208,
+	0xc00070c8,
+	0xd0109088,
+	0xb740a241,
+	0x0205430c,
+	0x0a38c0c8,
+	0xaa01d208,
+	0x090cc0e4,
+	0xa241d008,
+	0x430cb720,
+	0xb5870a02,
+	0xb7204cad,
+	0xb58e430c,
+	0xb7205b2b,
+	0xb58e430c,
+	0xb7205c2b,
+	0xb587430c,
+	0xb7204ead,
+	0xb58e430c,
+	0xb7205f2b,
+	0xb58e430c,
+	0xb720602b,
+	0xb587430c,
+	0xb720462d,
+	0xb587430c,
+	0xb720452d,
+	0xb587430c,
+	0xb720492d,
+	0x0203430c,
+	0x0a0cc0e4,
+	0xaa01d208,
+	0x522bb58d,
+	0x430cb720,
+	0xc0c80203,
+	0xd2080a38,
+	0xb58daa01,
+	0xb79f4aab,
+	0xb7bf7eee,
+	0xb7df7f6e,
+	0x8c607fee,
+	0xa6059c22,
+	0x430cb720,
+	0xb7860d02,
+	0x0a0465ad,
+	0x65adb586,
+	0x430cb720,
+	0x46b5b547,
+	0x430cb720,
+	0x5aabb78c,
+	0x472db587,
+	0x430cb720,
+	0x5033b54e,
+	0x430cb780,
+	0x5aabb76c,
+	0x0a60c0d2,
+	0xa102d208,
+	0x430cb720,
+	0x65adb786,
+	0xc0007502,
+	0xb5469184,
+	0xb72076b5,
+	0xb78c430c,
+	0xb58d6aab,
+	0xc00052ab,
+	0xb7869120,
+	0xb74650ad,
+	0x12446dad,
+	0x76adb586,
+	0x430cb720,
+	0x76adb746,
+	0x4e2db786,
+	0xd1240144,
+	0xb543597f,
+	0xb7205e2f,
+	0xb746430c,
+	0xb78676ad,
+	0x0144512d,
+	0x597fd124,
+	0x5d2fb543,
+	0x430cb720,
+	0x5d2fb743,
+	0x5dafb543,
+	0x430cb720,
+	0x76adb786,
+	0x53adb746,
+	0xb5860244,
+	0xb72076ad,
+	0xb786430c,
+	0xb74653ad,
+	0xc20076ad,
+	0x70885a07,
+	0x93f6c000,
+	0xc0d20203,
+	0x0d060a60,
+	0xa102d208,
+	0x430cb720,
+	0x53adb786,
+	0x76adb746,
+	0xc2006a16,
+	0x70885a13,
+	0x91b6c000,
+	0x5033b54e,
+	0x430cb720,
+	0x53adb786,
+	0xc2006a16,
+	0xb5865a13,
+	0xb7a076ad,
+	0x0990430c,
+	0x9ea80d02,
+	0x76d4b766,
+	0x9aafff54,
+	0xb507008b,
+	0xb7204b2d,
+	0xb787430c,
+	0x6a164b2d,
+	0x45adb587,
+	0x430cb720,
+	0x76adb786,
+	0xc0007500,
+	0x0a0290b6,
+	0x45adb587,
+	0x430cb7a0,
+	0x094ec002,
+	0x9ea80d02,
+	0x4f4cb766,
+	0x59ffd1a4,
+	0x991dc194,
+	0xb767008b,
+	0xd02245ad,
+	0xc0005e64,
+	0x30c2589d,
+	0xc00070c2,
+	0x9ea890bc,
+	0x45ccb527,
+	0x430cb720,
+	0x45adb787,
+	0x7c2db746,
+	0x7104d012,
+	0x45adb587,
+	0x430cb720,
+	0x45adb787,
+	0x7b2db746,
+	0x7104d010,
+	0x45adb587,
+	0x430cb720,
+	0x45adb787,
+	0x44adb587,
+	0x430cb7a0,
+	0xb76d008b,
+	0x74c04a2b,
+	0x9142c000,
+	0x52b3b76d,
+	0xff540d02,
+	0x9ea89a5a,
+	0x52cab50d,
+	0x430cb720,
+	0x65adb786,
+	0xc0007502,
+	0x018393b4,
+	0x09e0c0c8,
+	0xa962d008,
+	0xc0007680,
+	0xb78d92a2,
+	0x753052ab,
+	0x9212c000,
+	0x53adb786,
+	0x76adb746,
+	0xc2006a1e,
+	0x70885a0f,
+	0x90dcc000,
+	0x1e22d011,
+	0xa261d008,
+	0x430cb720,
+	0x6a2bb78c,
+	0xd0097506,
+	0xd3e91a44,
+	0xc0002ace,
+	0x0a8a9072,
+	0x65adb786,
+	0xc0007502,
+	0x757a9194,
+	0xb3540a72,
+	0x9ea34426,
+	0xfff40289,
+	0xc0009913,
+	0x010391e0,
+	0x0910c0e4,
+	0xd0080a0a,
+	0xb780a241,
+	0x097e430c,
+	0x0a14c0e4,
+	0xa101d208,
+	0x430cb720,
+	0x502bb78e,
+	0xc0007502,
+	0x020391c4,
+	0x0a60c0c8,
+	0xaa01d208,
+	0xd0017500,
+	0xd3e10a54,
+	0xc000294e,
+	0x010b9062,
+	0xc0d20203,
+	0xd2080a60,
+	0x7502aa01,
+	0x0a24d001,
+	0x294ed3e1,
+	0xc0e40203,
+	0xd2080a14,
+	0x7097a982,
+	0x4832b332,
+	0x91f2c000,
+	0xc0e40203,
+	0xd2080a10,
+	0x9e92a981,
+	0x2a3ed3f1,
+	0xb3327088,
+	0xd3f14446,
+	0xb78c2d2e,
+	0xd0206a2b,
+	0x76bd1128,
+	0x1a44d00c,
+	0x90d8c000,
+	0xc0007684,
+	0x0a0890bc,
+	0x294ed3f1,
+	0xc0007097,
+	0x020391f2,
+	0x0a10c0e4,
+	0xa981d208,
+	0xd3f19e92,
+	0x70882a3e,
+	0x4446b332,
+	0x2daed3f2,
+	0xc0e40203,
+	0xd2080a0c,
+	0xb780a182,
+	0x0902430c,
+	0x0a38c0c8,
+	0xa182d208,
+	0x430cb720,
+	0x4a2bb54d,
+	0x430cb720,
+	0x52abb54d,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0xa205f839,
+	0x430cb720,
+	0xb56d76c2,
+	0xc0004d2b,
+	0xb72091f2,
+	0x0982430c,
+	0xb72c9e9a,
+	0xd0125aab,
+	0xfff41992,
+	0x0d8a9a52,
+	0x90c0c000,
+	0xc00076c4,
+	0x0d8690a4,
+	0x98a2fff4,
+	0x4314b760,
+	0x0de0c0d6,
+	0x9a9dffb4,
+	0x430cb700,
+	0x6f2cb706,
+	0xaa1df9f8,
+	0xa60d9c22,
+	0x4314b740,
+	0x09760687,
+	0x0d48c0c8,
+	0xaa41d010,
+	0x7104d010,
+	0xa241d010,
+	0x430cb720,
+	0xd0110a02,
+	0xb5860932,
+	0xd01158ad,
+	0xb7200e32,
+	0x6129430c,
+	0x77adb546,
+	0x430cb720,
+	0x6a2db786,
+	0x5d2db586,
+	0x430cb720,
+	0x5b2bb56c,
+	0x430cb720,
+	0x65adb786,
+	0xc0007500,
+	0xb78690e2,
+	0xb7466dad,
+	0x124450ad,
+	0x59adb586,
+	0x430cb720,
+	0x76adb786,
+	0x512db746,
+	0xd1240128,
+	0xb543597f,
+	0xb7205d2f,
+	0xb786430c,
+	0xc20065ad,
+	0x749c5908,
+	0x90f2c000,
+	0xc0ca0103,
+	0xc000094c,
+	0x02489260,
+	0xc000751c,
+	0x01039112,
+	0x094cc0ca,
+	0xc0000a0e,
+	0xc00491a0,
+	0x01037498,
+	0x094cc0ca,
+	0x90b2c000,
+	0xc0000a0a,
+	0x0a069060,
+	0xa241d008,
+	0x430cb720,
+	0x4f35b766,
+	0xc0ca0203,
+	0xd2080a4c,
+	0xc101a902,
+	0xb7661207,
+	0xd13159ad,
+	0xc1806629,
+	0x70885910,
+	0x91f6c000,
+	0xc0ca0203,
+	0xd2080a50,
+	0x7500aa01,
+	0x90e4c000,
+	0x792bb78c,
+	0xc0000a04,
+	0xd0319280,
+	0xc1806526,
+	0x71045a0c,
+	0x931cc000,
+	0xc0ca0203,
+	0xd2080a50,
+	0x7500aa01,
+	0x9204c000,
+	0x792bb78c,
+	0xb58c1a04,
+	0xb780792b,
+	0x0906430c,
+	0x0a50c0ca,
+	0xa101d208,
+	0x9100c000,
+	0xc0ca0103,
+	0x0a020950,
+	0xa241d008,
+	0x430cb720,
+	0x792bb78c,
+	0x4002ba24,
+	0x752ac004,
+	0x90dac000,
+	0x0a5ac002,
+	0x9100c000,
+	0x7502c008,
+	0x90dcc000,
+	0x0a06c004,
+	0x792bb58c,
+	0x430cb720,
+	0xb78c0902,
+	0xb546792b,
+	0xb74676ad,
+	0xb7204e2d,
+	0xba244314,
+	0xb7264002,
+	0x624577ad,
+	0x40cbb74e,
+	0x74826243,
+	0x0a00c002,
+	0x5999c200,
+	0x9184c000,
+	0x76cdb746,
+	0x59cdb786,
+	0xd2187480,
+	0x12285a07,
+	0x93e0c000,
+	0x59d5b746,
+	0x4f4db786,
+	0x5d10d122,
+	0x70881209,
+	0x90b8c000,
+	0xc0007680,
+	0xd010921c,
+	0xb7460624,
+	0xc10176cd,
+	0xc2000244,
+	0x11285a13,
+	0xb5460126,
+	0xc00076cd,
+	0xb78690e0,
+	0x024676cd,
+	0x76cdb586,
+	0x430cb720,
+	0x7735b5a6,
+	0x430cb720,
+	0x65adb786,
+	0xc000751c,
+	0x0a0490b2,
+	0x65adb586,
+	0x430cb720,
+	0x65adb786,
+	0xc0007502,
+	0x02039224,
+	0x0a38c0c8,
+	0xaa01d208,
+	0x6aabb58c,
+	0x430cb720,
+	0x6aabb78c,
+	0x512bb58d,
+	0x9380c007,
+	0x50abb78d,
+	0xc0007500,
+	0xb78e9184,
+	0x750040ab,
+	0x9142c000,
+	0x532bb78d,
+	0xc0007504,
+	0x0a0690b4,
+	0x9060c000,
+	0xb58d0a02,
+	0xb7204f2b,
+	0x0b02430c,
+	0x662db746,
+	0x4a2bb76d,
+	0xc0c80203,
+	0x11b40a4c,
+	0xa902d208,
+	0x5fadb726,
+	0x5987d1a4,
+	0xc1010524,
+	0x55eb05b2,
+	0x9825ff54,
+	0x430cb720,
+	0x5fadb5c6,
+	0x430cb720,
+	0x5db5b746,
+	0x65adb786,
+	0x1944d011,
+	0x6125c101,
+	0xc2001a04,
+	0x02445a05,
+	0xb5860240,
+	0xb7a05dad,
+	0x020b430c,
+	0x0a4cc0c8,
+	0xaa01d208,
+	0xb766008b,
+	0xb7665db5,
+	0x9ea265ad,
+	0x55eb1984,
+	0x9bffff34,
+	0xb5069ea9,
+	0xb7005dcd,
+	0xb74d430c,
+	0x748050aa,
+	0x9342c000,
+	0x51aab78d,
+	0xc0007500,
+	0xb76d90e2,
+	0x74c0532a,
+	0x90c4c000,
+	0x4aaab70d,
+	0x92e0c000,
+	0x5985d1a4,
+	0xc1019eb2,
+	0xff3405b8,
+	0x18049be0,
+	0x91a0c000,
+	0x4a2ab76d,
+	0x422ab78e,
+	0xd1a49e92,
+	0xc1015985,
+	0xff3405b8,
+	0xb7209bd2,
+	0xb766430c,
+	0x74c465ad,
+	0x93d4c000,
+	0x512bb74d,
+	0x0a04d011,
+	0xc0007088,
+	0xb74c913a,
+	0xd0116f33,
+	0x72991a24,
+	0x90b6c000,
+	0xc0001804,
+	0xd01191a0,
+	0x70881a04,
+	0x90f8c000,
+	0x0a24d011,
+	0xc0007299,
+	0x0804907c,
+	0x0e52d031,
+	0x5a13c200,
+	0x0a027502,
+	0x0a42d00d,
+	0x1108d020,
+	0xc0007696,
+	0xb74c921c,
+	0xd0116f2b,
+	0x72991a24,
+	0x0d22d00e,
+	0x90fcc000,
+	0x0a24d011,
+	0xd00d7299,
+	0x74c41d22,
+	0x9334c000,
+	0x652bb78c,
+	0xc000752c,
+	0xb76c9292,
+	0xb78d6f2b,
+	0xd01152ab,
+	0xba241938,
+	0x71044002,
+	0x9136c000,
+	0x6a2bb74c,
+	0x1a34d011,
+	0xd00d7088,
+	0x02031d24,
+	0x0a48c0c8,
+	0xa901d208,
+	0xc8109e54,
+	0x02037088,
+	0x0a44c0c8,
+	0xaa01d208,
+	0x7104d012,
+	0x6a2bb58c,
+	0x430cb720,
+	0x6a2bb78c,
+	0x6aabb58c,
+	0x430cb720,
+	0x6aabb78c,
+	0x512bb58d,
+	0x430cb720,
+	0x6a2bb78c,
+	0x4aabb58d,
+	0x430cb720,
+	0xb78c0902,
+	0xb58d6aab,
+	0xb72052ab,
+	0xb546430c,
+	0xb720662d,
+	0xb78c430c,
+	0xc0d25b2b,
+	0x0a0408e0,
+	0x4029b580,
+	0x430cb720,
+	0x6aabb78c,
+	0x59abb58d,
+	0x430cb720,
+	0x6aabb78c,
+	0x592bb58d,
+	0x430cb720,
+	0x40abb54e,
+	0x430cb720,
+	0x502bb54d,
+	0x430cb720,
+	0x402bb54e,
+	0x430cb720,
+	0x50abb54d,
+	0x430cb720,
+	0x422bb54e,
+	0x430cb720,
+	0x4a2bb54d,
+	0x430cb720,
+	0x51abb54d,
+	0x430cb720,
+	0x532bb54d,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0x9c228c60,
+	0xb720a605,
+	0xb566430c,
+	0xb72064b5,
+	0xb786430c,
+	0x750264ad,
+	0x9004c006,
+	0xb5460902,
+	0xb7206fad,
+	0xb786430c,
+	0xc00477ad,
+	0xc0037510,
+	0xb7669092,
+	0xb76659b5,
+	0x9e9258ad,
+	0xff3405b6,
+	0x0a229af0,
+	0x7008c010,
+	0xcc121a40,
+	0xb7207008,
+	0xb78d430c,
+	0x75004a2b,
+	0x92e2c000,
+	0x58adb786,
+	0x6badb586,
+	0x430cb720,
+	0x4e35b746,
+	0x6badb746,
+	0x02246d7e,
+	0x0a080244,
+	0xc1015d17,
+	0xc2000244,
+	0xb5865a0b,
+	0xb7206bad,
+	0xb746430c,
+	0xb74658ad,
+	0x02246bb5,
+	0xc2000244,
+	0x9e525a0b,
+	0x7104d012,
+	0x6badb586,
+	0x430cb720,
+	0x50abb78d,
+	0xc0007500,
+	0xb78e91c2,
+	0x750040ab,
+	0x9124c000,
+	0x6badb786,
+	0xc2006a26,
+	0xb5865a0f,
+	0xb7206bad,
+	0xb746430c,
+	0x62356bad,
+	0x5a17c200,
+	0xb5461128,
+	0xb7206bad,
+	0xb786430c,
+	0xb7466bad,
+	0xd0107b2d,
+	0xb5867104,
+	0xc0006bad,
+	0xb7469280,
+	0xb78650ad,
+	0x12446dad,
+	0x59adb586,
+	0x430cb720,
+	0x59adb786,
+	0x4e2db746,
+	0x5a17c200,
+	0xb5461128,
+	0xb7206bad,
+	0xb78c430c,
+	0x75005b2b,
+	0x9342c001,
+	0x78adb786,
+	0xc0007500,
+	0xb7669302,
+	0x74c0792d,
+	0x9262c000,
+	0x0d029ea3,
+	0x9a6fff34,
+	0x9e857420,
+	0x90b4c000,
+	0xc0000ec2,
+	0x74029120,
+	0x90d2c000,
+	0xc0000e8a,
+	0x0e969060,
+	0x430cb7a0,
+	0x008b0d02,
+	0x6bb5b766,
+	0x5b2bb76c,
+	0xd11065d7,
+	0xff3405d7,
+	0x008b9a54,
+	0x6badb506,
+	0x430cb7a0,
+	0x0d029e6b,
+	0xb766008b,
+	0xff346bb5,
+	0x008b9a48,
+	0x6c2db506,
+	0x430cb720,
+	0xb5860a02,
+	0xb72070ad,
+	0xb586430c,
+	0xb720712d,
+	0xb586430c,
+	0xb7206fad,
+	0xb586430c,
+	0xb720712d,
+	0xb586430c,
+	0xb72070ad,
+	0xb586430c,
+	0xb79f7e2d,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xa6059c22,
+	0xaa61d810,
+	0x430cb720,
+	0xb58d0687,
+	0xb7204dab,
+	0xb786430c,
+	0xb74676ad,
+	0x12447e2d,
+	0x76adb586,
+	0x430cb720,
+	0xb7469e8b,
+	0xc0e24e35,
+	0xd0100d84,
+	0x74c0a9e1,
+	0x9284c000,
+	0x67adb784,
+	0x50adb746,
+	0x6629d131,
+	0xb3327104,
+	0xc0004458,
+	0x0a069138,
+	0xa261d010,
+	0x430cb720,
+	0x4e35b746,
+	0x430cb720,
+	0x6dadb746,
+	0x7e2db786,
+	0xc1010244,
+	0xb5861244,
+	0xb7206dad,
+	0xb746430c,
+	0xb78659b5,
+	0xb7467e2d,
+	0xc1014e2d,
+	0x12440244,
+	0x59adb586,
+	0x430cb720,
+	0x59adb786,
+	0x7500de01,
+	0x90d6c000,
+	0x0a02cf01,
+	0x59adb586,
+	0x430cb720,
+	0x0d02091e,
+	0x7e2db786,
+	0x4e35b726,
+	0x5d2fb763,
+	0x1419d110,
+	0x587fd024,
+	0x01b0e000,
+	0xd00305b0,
+	0xb5630db2,
+	0xb7a05d2f,
+	0x008b430c,
+	0x5d2fb763,
+	0x9845c174,
+	0x5e74d022,
+	0x590d0101,
+	0xd1243144,
+	0x008b597f,
+	0x5dafb543,
+	0x430cb720,
+	0x64adb786,
+	0xc0027504,
+	0xb7869124,
+	0xc00477ad,
+	0xc0017510,
+	0xb74693b2,
+	0x768076b5,
+	0x909cc001,
+	0x772db786,
+	0xc0c80103,
+	0xd008094c,
+	0xc200a941,
+	0xc1015a05,
+	0xc2000244,
+	0xb5865209,
+	0xb7a058ad,
+	0x020b430c,
+	0xc0c8008b,
+	0xb7660a4c,
+	0xb76658b5,
+	0xd208772d,
+	0xff34a902,
+	0x008b997e,
+	0x58adb506,
+	0x9100c000,
+	0x4e2db786,
+	0x5a0bc200,
+	0x58adb586,
+	0x430cb720,
+	0x4e2db786,
+	0x58adb746,
+	0x5a0bc200,
+	0x7088c812,
+	0x58adb546,
+	0x9300c001,
+	0x4e2db786,
+	0x58adb586,
+	0x9240c001,
+	0xb58d0a02,
+	0xb7204eab,
+	0xb746430c,
+	0x768264b5,
+	0x9024c001,
+	0x772db786,
+	0xb5861a04,
+	0xb720772d,
+	0xb74c430c,
+	0xb7865aab,
+	0x7104772d,
+	0x9094c000,
+	0x7735b546,
+	0x430cb720,
+	0x4a2bb78d,
+	0xb58d0a04,
+	0xb7204a2b,
+	0xb786430c,
+	0xb5867e2d,
+	0xc00078ad,
+	0x76809120,
+	0x90c4c000,
+	0x7e2db786,
+	0x792db586,
+	0x430cb720,
+	0x6dadb746,
+	0xc0007480,
+	0xb7869196,
+	0x024476ad,
+	0x76adb586,
+	0x430cb720,
+	0xb5860a02,
+	0xb7206dad,
+	0xb78c430c,
+	0x7500632b,
+	0x9184c001,
+	0x6dadb746,
+	0x4fadb786,
+	0xc0017088,
+	0x0203905c,
+	0x0a48c0c8,
+	0x4aabb74d,
+	0xaa01d208,
+	0xc0007088,
+	0x0a069306,
+	0xa221da10,
+	0x430cb720,
+	0x772db786,
+	0xc0007500,
+	0x02039222,
+	0x0a48c0c8,
+	0x422bb74e,
+	0xaa01d208,
+	0xb58e0244,
+	0xc000422b,
+	0x0a0290a0,
+	0xa221da10,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0x430cb720,
+	0x64adb786,
+	0xc0087502,
+	0xb78d9284,
+	0x75004a2b,
+	0x90e2c000,
+	0x4eb3b76d,
+	0xc00076c0,
+	0xb7869102,
+	0xb5866fad,
+	0xc0015c2d,
+	0xb74691c0,
+	0xb7664c35,
+	0xd0106fad,
+	0xd0110624,
+	0xc101693b,
+	0x70880244,
+	0x9154c000,
+	0x5c2db786,
+	0x5908c180,
+	0x70886a16,
+	0x9132c000,
+	0x6e27d3f1,
+	0x5a21c200,
+	0xc00070c8,
+	0x0a069214,
+	0x402bb58e,
+	0x430cb720,
+	0x5b2bb78c,
+	0x08e0c0d2,
+	0xb5800a0c,
+	0xc0004029,
+	0xb56e9080,
+	0xb7204033,
+	0xb786430c,
+	0xc00477ad,
+	0xc0047510,
+	0xb78693b2,
+	0x750265ad,
+	0x9364c000,
+	0x4a2bb74d,
+	0xc0007480,
+	0xb54d92c4,
+	0xb7204fab,
+	0xb786430c,
+	0xb5867e2d,
+	0xb7205a2d,
+	0xb786430c,
+	0xb5866fad,
+	0xb720582d,
+	0xb54d430c,
+	0xc003502b,
+	0xb76d93e0,
+	0xb746502b,
+	0x74c06fb5,
+	0x93e2c000,
+	0x582db746,
+	0x0624d010,
+	0x0244c101,
+	0xc2000244,
+	0xb5865a09,
+	0xb720582d,
+	0xb786430c,
+	0xb5867e2d,
+	0xb7205a2d,
+	0x0a02430c,
+	0x502bb58d,
+	0x430cb720,
+	0xb58d0a04,
+	0xc0024fab,
+	0xb7869360,
+	0xd0314c2d,
+	0x6a266d25,
+	0xc0017088,
+	0xb78691f4,
+	0xb7465a2d,
+	0x01487e35,
+	0x05240128,
+	0xc0017295,
+	0x0d0690bc,
+	0x5033b54d,
+	0x430cb720,
+	0x50b3b54d,
+	0x430cb720,
+	0x51abb56d,
+	0x430cb720,
+	0x532bb56d,
+	0x430cb720,
+	0x5aabb78c,
+	0x4a2bb74d,
+	0xc2006a14,
+	0x70885a0f,
+	0x90dac000,
+	0x40abb56e,
+	0x9140c001,
+	0x40b3b54e,
+	0x90c0c001,
+	0xb58d0a02,
+	0xb720502b,
+	0xb78e430c,
+	0x7500402b,
+	0x9384c000,
+	0x582db746,
+	0x6fb5b746,
+	0x02440224,
+	0x0244c101,
+	0x5a09c200,
+	0x582db586,
+	0x430cb720,
+	0x5a2db746,
+	0x7e35b746,
+	0x02440224,
+	0x0244c101,
+	0x5a0bc200,
+	0x5a2db586,
+	0x430cb720,
+	0x6fadb786,
+	0x5c2db586,
+	0x430cb720,
+	0x50abb78d,
+	0xc0007500,
+	0xb78d9382,
+	0x7500502b,
+	0x91e2c000,
+	0x40abb78e,
+	0xc0007500,
+	0xb78c9144,
+	0x01035b2b,
+	0x0960c0d2,
+	0xc0000a0c,
+	0xb78c9100,
+	0x01035b2b,
+	0x0960c0d2,
+	0xd0080a08,
+	0xb720a241,
+	0xb78d430c,
+	0x75004a2b,
+	0x48a4b340,
+	0x70adb786,
+	0x5eadb586,
+	0x75049c22,
+	0x48a4b340,
+	0x7e2db766,
+	0x5a4be180,
+	0x90ccc000,
+	0x0d82c002,
+	0x9100c000,
+	0x7100d002,
+	0x9ea30a04,
+	0x4001ba1b,
+	0x6aabb78c,
+	0xba24097e,
+	0xd0104002,
+	0x0c867104,
+	0xd0129e48,
+	0xba247100,
+	0x9e584002,
+	0x5a18c200,
+	0x65b5b746,
+	0xba245163,
+	0x62454002,
+	0xc1010936,
+	0x76841126,
+	0x518bc200,
+	0x9054c006,
+	0xb58d0a02,
+	0xb7204eab,
+	0xb78d430c,
+	0x75004f2b,
+	0x92c4c005,
+	0x592db746,
+	0x590cd1a4,
+	0x6a2bd031,
+	0xc0007299,
+	0xd01190f6,
+	0x72996a2b,
+	0x911ac005,
+	0x4eb3b52d,
+	0x430cb720,
+	0x592db746,
+	0x022470c4,
+	0x921cc002,
+	0xc00070c8,
+	0x023690d6,
+	0xc0017104,
+	0xb78c90ba,
+	0x0a18792b,
+	0x792bb58c,
+	0x430cb720,
+	0x77b5b746,
+	0x4e2db786,
+	0x76adb746,
+	0x6245c101,
+	0xc2000a20,
+	0x01285a11,
+	0x76adb546,
+	0x430cb780,
+	0xc0d2091a,
+	0xd2080a60,
+	0xb780a101,
+	0x190c430c,
+	0x0a48c0ca,
+	0x9240c003,
+	0x792bb78c,
+	0xb58c0a08,
+	0xb720792b,
+	0xb746430c,
+	0xb78677b5,
+	0xb7464e2d,
+	0xc10176ad,
+	0x0a406245,
+	0x5a15c200,
+	0xb5460128,
+	0xb78076ad,
+	0x090e430c,
+	0x0a60c0d2,
+	0xa101d208,
+	0x430cb780,
+	0x0a48c0ca,
+	0xa082d208,
+	0x9200c002,
+	0xc00070c8,
+	0x023690d6,
+	0xc0017104,
+	0xb78c90ba,
+	0x1a08792b,
+	0x792bb58c,
+	0x430cb720,
+	0x77b5b746,
+	0x4e2db786,
+	0x76adb746,
+	0x6245c101,
+	0xc2000a40,
+	0x11285a15,
+	0x76adb546,
+	0x430cb780,
+	0xc0d2091a,
+	0xd2080a60,
+	0xb780a101,
+	0x1920430c,
+	0x0a48c0ca,
+	0x9080c001,
+	0x792bb78c,
+	0xb58c1a04,
+	0xb720792b,
+	0xb746430c,
+	0xb78677b5,
+	0xb7464e2d,
+	0xc10176ad,
+	0xc0026245,
+	0xc2000a00,
+	0x11285a19,
+	0x76adb546,
+	0x430cb780,
+	0xc0d2090e,
+	0xd2080a60,
+	0xb780a101,
+	0x1910430c,
+	0x0a48c0ca,
+	0xa101d208,
+	0x430cb720,
+	0x592db566,
+	0x430cb720,
+	0x4eabb78d,
+	0x50abb58d,
+	0xa60d9c22,
+	0x430cb720,
+	0xb7460307,
+	0x768464b5,
+	0x90c4c000,
+	0x6ab3b74c,
+	0x9020c00a,
+	0xc0077682,
+	0xb78d9364,
+	0x75004a2b,
+	0x9224c000,
+	0x4eabb78d,
+	0xc0007500,
+	0xb78c9184,
+	0xb74e6aab,
+	0x9ea2422b,
+	0xb58e0244,
+	0xc009422b,
+	0xb78d9140,
+	0x75004eab,
+	0x90c2c001,
+	0x01030203,
+	0x0a48c0ca,
+	0xaa01d208,
+	0x0938c0c8,
+	0xa942d008,
+	0x4000ba24,
+	0xc1010910,
+	0xd0080244,
+	0xd010a941,
+	0x01037104,
+	0x0944c0c8,
+	0xa941d008,
+	0x7104c812,
+	0x4dabb78d,
+	0x4233b74e,
+	0xd0027500,
+	0x75000922,
+	0x9000c001,
+	0x502bb78d,
+	0xc0017500,
+	0x020392c2,
+	0x0a38c0c8,
+	0xaa01d208,
+	0xc0c80103,
+	0xd0080948,
+	0x0a04a941,
+	0x7104d010,
+	0xc0c80103,
+	0xd0080944,
+	0xc812a941,
+	0xb78d7104,
+	0xb74e4dab,
+	0x75004233,
+	0x0a28d002,
+	0x4422b324,
+	0x2a7ccffe,
+	0x0244c101,
+	0x422bb58e,
+	0x430cb720,
+	0xb78d9e92,
+	0x022851ab,
+	0x51abb58d,
+	0x430cb720,
+	0x532bb78d,
+	0xb58d0a04,
+	0xc006532b,
+	0xb7869100,
+	0xb5865f2d,
+	0xb7a05e2d,
+	0x9e694314,
+	0x6badb746,
+	0xc0007480,
+	0xb78e9316,
+	0x750040ab,
+	0x09e2d002,
+	0x9104c000,
+	0xc0d29e6c,
+	0xd2080a60,
+	0x01e8aa01,
+	0xc0c89e6c,
+	0xd2080a48,
+	0xcc10aa01,
+	0xc00170c8,
+	0x9e6990e0,
+	0x5e2db766,
+	0x4e2db786,
+	0x6a35b746,
+	0xc20011a6,
+	0xcc125a0b,
+	0x9e6c70c8,
+	0xc0c89e6a,
+	0xd2080a4c,
+	0xc0d2aa01,
+	0xd0080960,
+	0x0a14aac1,
+	0x554c9ea3,
+	0x5987d1a4,
+	0xc15405b4,
+	0x581998d6,
+	0xc010026a,
+	0x12ea7008,
+	0x700acc12,
+	0xb78d9e69,
+	0x9e694dab,
+	0xb74e7500,
+	0xd002422b,
+	0x750009b2,
+	0x0a38d002,
+	0x4422b334,
+	0xcffe9e69,
+	0x02442a7c,
+	0x422bb58e,
+	0x430cb720,
+	0x50abb78d,
+	0xc0007500,
+	0xb78d91c2,
+	0x023851ab,
+	0x51abb58d,
+	0x430cb720,
+	0x532bb78d,
+	0xb58d0a04,
+	0xb720532b,
+	0x0203430c,
+	0x0a48c0c8,
+	0xaa01d208,
+	0x70c8d010,
+	0xc0c80103,
+	0xd0080944,
+	0xd012a941,
+	0x9ea27104,
+	0x6f2bb58c,
+	0x90a0c002,
+	0xc0007680,
+	0x000790a2,
+	0x93c0c001,
+	0x6c2db766,
+	0x5aadb746,
+	0x4e2db786,
+	0xc20011b4,
+	0xcc125a0b,
+	0x020370c8,
+	0x0a4cc0c8,
+	0xaa01d208,
+	0x6aadb746,
+	0x5a05c200,
+	0x515051f3,
+	0x5987d1a4,
+	0xc1015914,
+	0xff1405b4,
+	0xb72099a8,
+	0x5819430c,
+	0xb74d0810,
+	0xb78d59ab,
+	0x0244592b,
+	0x5a07c200,
+	0x094ed011,
+	0x7004c010,
+	0xc0120a04,
+	0x02037008,
+	0x0a48c0c8,
+	0xaa01d208,
+	0x7008c010,
+	0x08c4c0c8,
+	0x4029b780,
+	0x7008c012,
+	0x9e509e82,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0x9c228c60,
+	0xb720a605,
+	0x0687430c,
+	0x64adb786,
+	0xc00a7502,
+	0xb7469144,
+	0xb76d712d,
+	0xe1004a33,
+	0xc0005a4b,
+	0xc00290cc,
+	0xc0000982,
+	0xd0029100,
+	0x0a047100,
+	0xba1b0189,
+	0x9e6c4000,
+	0x514fd024,
+	0x4002ba24,
+	0xd010097e,
+	0x19787104,
+	0x7104d012,
+	0xc0c80103,
+	0xba24094c,
+	0xd0084002,
+	0xc200a941,
+	0xba245a18,
+	0xc1014002,
+	0x09146245,
+	0x76c01126,
+	0x510bd224,
+	0x90e2c000,
+	0x4eabb78d,
+	0xc0007500,
+	0xb78693c2,
+	0xc1015fad,
+	0xb5860244,
+	0xb7205fad,
+	0xb546430c,
+	0xb7206a35,
+	0xb546430c,
+	0xb7206ab5,
+	0xb786430c,
+	0xb58670ad,
+	0xb7205ead,
+	0xb786430c,
+	0xb5865ead,
+	0xc0065f2d,
+	0xb78d9260,
+	0x7500502b,
+	0x9124c006,
+	0x402bb78e,
+	0xc0067500,
+	0xb7869084,
+	0xc1015fad,
+	0xb5860244,
+	0xb7205fad,
+	0xb78d430c,
+	0xb7664fab,
+	0x750070ad,
+	0x90c2c000,
+	0x5eadb566,
+	0x9180c000,
+	0x5eadb746,
+	0x02460236,
+	0x02446916,
+	0x5a0dc200,
+	0x5eadb586,
+	0x430cb720,
+	0x5eadb786,
+	0x5f2db586,
+	0x430cb720,
+	0x4fabb78d,
+	0xc0007500,
+	0xb54690c2,
+	0xc0016a35,
+	0xb78d91e0,
+	0xb74650ab,
+	0x75006a2d,
+	0x9182c001,
+	0x532bb78d,
+	0x62451a04,
+	0x0629d110,
+	0x6a2db586,
+	0x430cb720,
+	0x532bb78d,
+	0x6a2db746,
+	0x5a05c200,
+	0xb5460128,
+	0xb7a06a2d,
+	0x020b430c,
+	0x0a4cc0c8,
+	0xaa01d208,
+	0xb766008b,
+	0x9ea26a35,
+	0x532bb76d,
+	0xff1455eb,
+	0x9ea998c2,
+	0x6a4db506,
+	0x430cb720,
+	0x9100c001,
+	0x662db786,
+	0x4a2bb76d,
+	0xd01111b8,
+	0x62451a32,
+	0x0629d110,
+	0x5907c180,
+	0x6a2db586,
+	0x430cb720,
+	0x6a2db786,
+	0xb5860244,
+	0xb7a06a2d,
+	0x008b430c,
+	0x6a35b766,
+	0x9b6cc134,
+	0xb5069ea9,
+	0xb7206a4d,
+	0xb786430c,
+	0x750265ad,
+	0x90c4c000,
+	0x6a2db786,
+	0x9280c000,
+	0x4a33b74d,
+	0x5aabb74c,
+	0x6a35b766,
+	0x0624d010,
+	0x71041904,
+	0x5d2db766,
+	0x9156c000,
+	0x0236c101,
+	0x5a07c200,
+	0x6aadb586,
+	0x9140c001,
+	0x1224c101,
+	0x6526d031,
+	0x02446247,
+	0x6aadb586,
+	0x430cb720,
+	0x5aabb78c,
+	0x6aadb746,
+	0xc2001a04,
+	0x01285a07,
+	0x6aadb546,
+	0x430cb7a0,
+	0xb76c008b,
+	0xb7665aab,
+	0x19846ab5,
+	0x9b2ac134,
+	0xb5069ea9,
+	0xc0006acd,
+	0xb78690e0,
+	0x0a04662d,
+	0x662db586,
+	0x430cb720,
+	0x6ab5b746,
+	0x5dadb746,
+	0x6b35b546,
+	0x430cb720,
+	0x65adb786,
+	0xc0007502,
+	0x022491d4,
+	0xb7460244,
+	0xc1016aad,
+	0xc2000244,
+	0xc8105a0b,
+	0xb5467088,
+	0xb7206aad,
+	0xb78d430c,
+	0xb58d592b,
+	0xb72059ab,
+	0xb5ad430c,
+	0xb7205933,
+	0xb786430c,
+	0x750064ad,
+	0x90c4c000,
+	0x70adb786,
+	0x5aadb586,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0x430cb720,
+	0x6435b746,
+	0x4e2db746,
+	0x5aabb78c,
+	0x4e35b546,
+	0x4314b720,
+	0x4a2bb72d,
+	0x1524c101,
+	0xb7461a04,
+	0x124276cd,
+	0x6245c101,
+	0xb5460128,
+	0xb78076cd,
+	0x0902430c,
+	0x0a70c0d0,
+	0xa101d208,
+	0xa6059c22,
+	0x430cb720,
+	0xb5660287,
+	0xd8087e35,
+	0x7500aa61,
+	0x9144c000,
+	0x430cb720,
+	0x6f35b766,
+	0x9a6efff4,
+	0x9b04ffd4,
+	0x430cb780,
+	0x0a70c0d0,
+	0xaa01d208,
+	0xc0007502,
+	0xfff49084,
+	0x9eab9bc3,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0xffcd8c40,
+	0x01079240,
+	0xa9e1f010,
+	0x70c0d014,
+	0x753ec03f,
+	0x90dcc000,
+	0x4226e000,
+	0x48acb340,
+	0xf0100226,
+	0x9c22a261,
+	0xb7c0a60d,
+	0x008d430c,
+	0x5b33b7ae,
+	0x1dd2d012,
+	0x9948ff34,
+	0x028c5808,
+	0xd0129ea9,
+	0xb7a61dd4,
+	0xff347ecd,
+	0x5808993f,
+	0xb726008c,
+	0x9eb17ead,
+	0xc2000252,
+	0xb7665a05,
+	0x9ea25ad5,
+	0x72c4cc12,
+	0x4e4db766,
+	0x0d025d9c,
+	0x9b9ffef4,
+	0xc0dc020d,
+	0xd2080a50,
+	0xc006a901,
+	0x11c00a7a,
+	0xc0007480,
+	0x9e9390a4,
+	0x90e0c000,
+	0xb786008d,
+	0xd0207a2d,
+	0x9eb111b8,
+	0xb7460a02,
+	0x592779cd,
+	0x7088c810,
+	0xc0dc020d,
+	0xd2080a60,
+	0xc180aa01,
+	0x9eb25a8f,
+	0xd01102d8,
+	0x9eb36e3f,
+	0x0d50c0dc,
+	0x02d40e86,
+	0x5a23c200,
+	0xa2c2d010,
+	0x7a4db566,
+	0x0db0c0dc,
+	0xfff402d8,
+	0xc0089b96,
+	0xd4100a02,
+	0x9e6c7148,
+	0x7148d412,
+	0x2afcc00e,
+	0xb79f000b,
+	0xb7bf7eee,
+	0xb7df7f6e,
+	0x8c607fee,
+	0xa60d9c22,
+	0x430cb7a0,
+	0xb786008b,
+	0xb741562d,
+	0x75045e2d,
+	0x92a4c005,
+	0xc0007488,
+	0xb78190e4,
+	0x75045ead,
+	0x9322c005,
+	0xb746008b,
+	0xb7464fad,
+	0xb7616bb5,
+	0xd1205e2d,
+	0xc02111a5,
+	0xc00076c0,
+	0x74c29354,
+	0x93e4c009,
+	0x4e2db786,
+	0x70886a1e,
+	0x9336c009,
+	0x5e15d1a2,
+	0x6ac5d072,
+	0x9060c001,
+	0xc00074c2,
+	0xd1a293e2,
+	0xd0325e15,
+	0xc0006acd,
+	0x74c29340,
+	0x9184c009,
+	0xb786008b,
+	0x6a1e4e2d,
+	0xc0097088,
+	0xd07190b6,
+	0xc0006e35,
+	0x74c290e0,
+	0x9102c000,
+	0x6e3dd031,
+	0x5a97d224,
+	0x9060c000,
+	0x008b0e82,
+	0x5ab3b7cc,
+	0xc0027782,
+	0xff3491c4,
+	0x008b9a72,
+	0x4e35b7a6,
+	0xc0109e6b,
+	0xc1017006,
+	0xd812120b,
+	0xb7867008,
+	0x750075ad,
+	0x92e4c001,
+	0x98acff34,
+	0xc0007400,
+	0x008b91a2,
+	0x5babb78e,
+	0x67adb744,
+	0x0a027088,
+	0x0a42d004,
+	0x92c0c000,
+	0xb781008b,
+	0x75025e2d,
+	0x90a2c000,
+	0xc0007508,
+	0x008b9224,
+	0x67adb784,
+	0x50adb746,
+	0x6659d131,
+	0x0a027104,
+	0x0a42d00b,
+	0x75adb586,
+	0x90a0c000,
+	0xb5c6008b,
+	0x008b75b5,
+	0x75adb786,
+	0xc0007500,
+	0xc81290c4,
+	0xc000710c,
+	0x010d9060,
+	0xb786008b,
+	0xd0204e2d,
+	0x008b12c4,
+	0x5e2db781,
+	0xc0007502,
+	0xff349264,
+	0x7400986b,
+	0x91c4c000,
+	0xb786008b,
+	0xb74650ad,
+	0xc2006bad,
+	0x70885a08,
+	0x909cc000,
+	0x73b5b7a6,
+	0xd4120d06,
+	0xc0047344,
+	0x748291e0,
+	0x92c2c001,
+	0xc0047488,
+	0x008b9024,
+	0x5eadb781,
+	0xc0007500,
+	0xb7a690c2,
+	0xc0034e35,
+	0x008b93e0,
+	0x65abb78c,
+	0x75009ead,
+	0xd0010a02,
+	0xb5800a42,
+	0xb78c448c,
+	0xc0dc71ab,
+	0x75000ee0,
+	0x90c2c000,
+	0xa922d210,
+	0x90e0c000,
+	0x9ab0fff4,
+	0xd2109e82,
+	0x008ba021,
+	0x4e2db786,
+	0xd131092a,
+	0xc2006629,
+	0xcc125a1f,
+	0x9e9d7104,
+	0x9300c002,
+	0xb78c008b,
+	0xc2006dab,
+	0x00ca5a08,
+	0x5cb5b7a6,
+	0x9816ff34,
+	0x0b00f011,
+	0x90e4c001,
+	0xb786008b,
+	0x750075ad,
+	0x9244c000,
+	0x67adb784,
+	0x4e2db746,
+	0x50b5b746,
+	0x61450802,
+	0xd00b7095,
+	0x74000802,
+	0x75adb506,
+	0x9122c000,
+	0x99afff34,
+	0xc0121001,
+	0xc000700c,
+	0x008b9100,
+	0x6badb786,
+	0xc0121228,
+	0xc1017100,
+	0x008b06d0,
+	0x5e2db781,
+	0xc0007502,
+	0xff1493e4,
+	0x74009be5,
+	0x9344c000,
+	0xb78d008b,
+	0xc00464ab,
+	0xc0007510,
+	0xb7869274,
+	0xc2004e2d,
+	0x9ea25a0f,
+	0x7344d412,
+	0x9140c000,
+	0xb78c008b,
+	0xc2006dab,
+	0x00ca5a08,
+	0x5cb5b7a6,
+	0x430cb720,
+	0x5e2db781,
+	0xc0007508,
+	0x750290a2,
+	0x92e4c000,
+	0xb787008b,
+	0x75004e2d,
+	0x9222c000,
+	0xd4109ea2,
+	0xc0007344,
+	0x72959180,
+	0x9238fff6,
+	0x9180fff6,
+	0xfff77295,
+	0xfff69078,
+	0x9e6893c0,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0x9c228c60,
+	0xb7a0a60d,
+	0x9e5e430c,
+	0xb781008b,
+	0x75025e2d,
+	0x91a6c004,
+	0xc0007504,
+	0x750890f4,
+	0x90e4c004,
+	0x93a0c001,
+	0x76c2008b,
+	0x5635b566,
+	0x6db3b7ac,
+	0x9084c000,
+	0x9ad5ff34,
+	0x9a71fff4,
+	0xb506008b,
+	0x01815dad,
+	0xff34058b,
+	0x9e8299a7,
+	0x0902008b,
+	0x9100c000,
+	0x7c2bb78c,
+	0x4002ba24,
+	0x0528c101,
+	0x0888709b,
+	0xffff0904,
+	0xb74092fc,
+	0x9e53430c,
+	0xc0c80205,
+	0xd2080a48,
+	0xd010aa01,
+	0xc0c870c8,
+	0xd0080944,
+	0xc412a941,
+	0x9e8d7104,
+	0xb5ac008b,
+	0xff347c33,
+	0xc00298d4,
+	0x008b9140,
+	0xb56676c2,
+	0xb7ac5635,
+	0xc0006db3,
+	0xff349084,
+	0xfff49a9a,
+	0x008b9a36,
+	0x5dadb506,
+	0x058b0181,
+	0x996cff34,
+	0x008b9e82,
+	0xc0000902,
+	0xb78c9100,
+	0xba247c2b,
+	0xc1014002,
+	0x709b0528,
+	0x09040888,
+	0x92fcffff,
+	0x430cb740,
+	0x02059e53,
+	0x0a48c0c8,
+	0xaa01d208,
+	0x70c8d010,
+	0x0944c0c8,
+	0xa941d008,
+	0x7104c412,
+	0x008b9e8d,
+	0x7c33b5ac,
+	0x9899ff34,
+	0xc0007584,
+	0xb72091c4,
+	0xb781430c,
+	0x75045ead,
+	0x90e2c000,
+	0xc0c80203,
+	0xd2080a38,
+	0x9e68aa82,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0x9c228c60,
+	0x8440a61d,
+	0x4314b7a0,
+	0x1236c101,
+	0x9e699ea2,
+	0xb72c9e6a,
+	0xc0de712b,
+	0xd0080920,
+	0xa095ab42,
+	0x55d89e69,
+	0x73adb726,
+	0xc114a099,
+	0x9e6c9bfd,
+	0xc0de0301,
+	0xd2080a10,
+	0x7480a901,
+	0x90c2c000,
+	0xb7869e69,
+	0x11087c2d,
+	0xb78d9e69,
+	0xb7ac64ab,
+	0xc0046e2b,
+	0xc0007510,
+	0xd3249114,
+	0x0b825b93,
+	0xc000a391,
+	0x9e699180,
+	0xb7866916,
+	0x590f7bad,
+	0x5b87d324,
+	0x5b97c200,
+	0x9e69a111,
+	0xb7467780,
+	0x0a22712d,
+	0x4824b364,
+	0x9ea67482,
+	0x9332c003,
+	0x632bb78d,
+	0xc0037502,
+	0xc0019292,
+	0xa91593c0,
+	0x3154e000,
+	0x9324c001,
+	0xb7869e69,
+	0x750075ad,
+	0x9144c002,
+	0x9aa8ff14,
+	0xc0007400,
+	0x9e6991a2,
+	0x5babb78e,
+	0x67adb744,
+	0x0a027088,
+	0x0a42d004,
+	0x9360c000,
+	0xb7819e69,
+	0x75025e2d,
+	0x90a2c000,
+	0xc0007508,
+	0x9e699204,
+	0x67adb784,
+	0x4e2db746,
+	0x50b5b746,
+	0x71156245,
+	0xd00b0a02,
+	0xc0000a42,
+	0x9e699080,
+	0xb5860a06,
+	0x9e6975ad,
+	0x75adb786,
+	0xc0007500,
+	0x75409324,
+	0x9104c000,
+	0xb78d9e69,
+	0x7500632b,
+	0x9104c000,
+	0x0a029e6a,
+	0x0910c0de,
+	0xa241d008,
+	0xaa19a915,
+	0x74800802,
+	0x4422b340,
+	0x90e0c001,
+	0x9e699e6c,
+	0x0a10c0de,
+	0x058b0a86,
+	0xa281d208,
+	0x7c2db5c6,
+	0x0df0c0dc,
+	0xfff4018d,
+	0xa91298c2,
+	0xa9199e71,
+	0x0674d010,
+	0x52a4c200,
+	0x024a024e,
+	0xc2006245,
+	0xc0005007,
+	0x9e699140,
+	0x632bb78d,
+	0xfffe7500,
+	0xfffc9102,
+	0xb79f9140,
+	0xb7bf7d6e,
+	0xb7df7dee,
+	0xb7ff7e6e,
+	0xc0027eee,
+	0x9c228c40,
+	0xb7a0a60d,
+	0x008b430c,
+	0x5e2db781,
+	0xc0047502,
+	0xff149004,
+	0xf0119a27,
+	0xc0000880,
+	0x9ea99184,
+	0x4e55b766,
+	0x4fcdb746,
+	0x6e3fd011,
+	0xc0017088,
+	0x008b91d6,
+	0x64abb78d,
+	0x6cadb7c6,
+	0x73b5b7a6,
+	0x7510c004,
+	0x9332c002,
+	0x63b3b76d,
+	0x6333b74d,
+	0x4e2db786,
+	0x592db746,
+	0x15b49e5b,
+	0xba1b7088,
+	0x1d844003,
+	0x1248d01a,
+	0x1228d019,
+	0x61c7d132,
+	0x4002ba1b,
+	0x5a07c180,
+	0x05b8c101,
+	0xfef40d02,
+	0xc1019834,
+	0xc00106d0,
+	0x9ea99300,
+	0x64cbb78d,
+	0x6bcdb7c6,
+	0x50d5b7a6,
+	0x7510c004,
+	0x9012c001,
+	0x594db706,
+	0x63cbb74d,
+	0x6353b74d,
+	0x01857017,
+	0x1007d119,
+	0x11a5d120,
+	0x4434b310,
+	0x4003ba1b,
+	0xba1b1d84,
+	0xd1324002,
+	0xc1806187,
+	0xc1015a07,
+	0x0d0205b8,
+	0x9809fef4,
+	0x06d0c101,
+	0xb78c008b,
+	0x75006eab,
+	0x9122c000,
+	0x065ad010,
+	0x024ac101,
+	0xd224024c,
+	0x9eb35a8b,
+	0xfff49e6b,
+	0x0a029ab1,
+	0x7100d012,
+	0xb5869ea9,
+	0xc0016b4d,
+	0x008b90a0,
+	0x64abb78d,
+	0x63b3b74d,
+	0x632bb74d,
+	0x7510c004,
+	0x6aadb706,
+	0x90d4c000,
+	0x73adb706,
+	0x9220c000,
+	0x1625d110,
+	0xba1b0189,
+	0x74c24002,
+	0x913cc000,
+	0x5987d1a4,
+	0xc1010d02,
+	0xfed405b0,
+	0x9ea99bce,
+	0x6b4db506,
+	0x430cb7a0,
+	0x008b0902,
+	0x632bb78d,
+	0x7135b746,
+	0x68abb54d,
+	0x76820a04,
+	0x632bb58d,
+	0x5b2bb74c,
+	0x9192c005,
+	0x2a7ccffe,
+	0xc0057502,
+	0xb74d90f2,
+	0x76806833,
+	0x9144c005,
+	0xc0017480,
+	0xb78693c2,
+	0x74826b2d,
+	0x5907c200,
+	0x5cadb546,
+	0x9104c000,
+	0x02440224,
+	0x5a07c200,
+	0x5cadb586,
+	0x0e869ea9,
+	0x6b55b766,
+	0x5ccdb786,
+	0x6fcbb76d,
+	0x15b8c101,
+	0xfed41984,
+	0x03019b90,
+	0x9200c000,
+	0xa9cdd008,
+	0x9b89fed4,
+	0x0e52d011,
+	0x5c88d2a2,
+	0x009a9ea5,
+	0x5cadb506,
+	0x2efccffe,
+	0x025ac101,
+	0x0109008b,
+	0x6fabb78d,
+	0x0960c0da,
+	0x711b9eb3,
+	0xffff0d02,
+	0xc00390f2,
+	0x9ea99160,
+	0xb76d9e92,
+	0xb78664cb,
+	0x19846acd,
+	0x29fccffe,
+	0x5985d1a4,
+	0x05b8c101,
+	0x9b61fed4,
+	0xb506008b,
+	0xc0025cad,
+	0x9ea992e0,
+	0x64cbb78d,
+	0x7510c004,
+	0x9194c000,
+	0x4e4db786,
+	0xb7460904,
+	0x61296c55,
+	0x1124c101,
+	0x6b4db546,
+	0x0902008b,
+	0x6b2db786,
+	0x7088d812,
+	0x5b33b7ac,
+	0xc0017740,
+	0xb78691c2,
+	0x75005b2d,
+	0x9262c000,
+	0x5badb766,
+	0xc00074c0,
+	0x9ea391c2,
+	0xfed49e92,
+	0x0a429b32,
+	0x7008c010,
+	0xcc121a38,
+	0xc0007008,
+	0x09969060,
+	0x61bcd032,
+	0xc1010d02,
+	0xfed401ba,
+	0x9ea99b22,
+	0x11e0d020,
+	0xb5069e6b,
+	0x0d025ccd,
+	0x9b19fed4,
+	0xb506008b,
+	0xc0005d2d,
+	0x9ea991e0,
+	0x5ccdb5c6,
+	0x9140c000,
+	0xb781008b,
+	0x75085e2d,
+	0x9004fffe,
+	0x91a0fffd,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0x9c228c60,
+	0xb7a0a605,
+	0x008b430c,
+	0x752db766,
+	0xc00074c0,
+	0x008b91c2,
+	0x74adb786,
+	0x5985d1a4,
+	0x05b8c101,
+	0x99b5c114,
+	0xcffe0181,
+	0x008b29fc,
+	0x5e2db781,
+	0x73abb56c,
+	0xc0007504,
+	0x75089142,
+	0x9302c001,
+	0xc0047502,
+	0xc00193c4,
+	0xff149260,
+	0x74009895,
+	0xb746008b,
+	0xc0007335,
+	0xb74690c2,
+	0xc0006cad,
+	0x008b90a0,
+	0x6badb746,
+	0xb781008b,
+	0x75025e2d,
+	0x9124c000,
+	0xc0007400,
+	0xb78690c4,
+	0xc00050ad,
+	0x0a029060,
+	0x9e521228,
+	0x7104d010,
+	0x1105c101,
+	0x7104d012,
+	0x5a07c200,
+	0x1629d110,
+	0xb586008b,
+	0x0a0a6aad,
+	0x7b2bb58d,
+	0x9160c003,
+	0x9864ff14,
+	0x008b7400,
+	0x7335b746,
+	0x9222c000,
+	0x6cadb786,
+	0xd0109e52,
+	0xc1017104,
+	0xd0121105,
+	0xc2007104,
+	0xd1105a07,
+	0xc0011429,
+	0x008b92e0,
+	0x5e2db781,
+	0xc0007502,
+	0x008b90a4,
+	0x50adb706,
+	0xb786008b,
+	0xb746712d,
+	0x75006bad,
+	0x90e4c000,
+	0x50adb786,
+	0xc0001040,
+	0x008b93e0,
+	0x64abb78d,
+	0xc0041020,
+	0xc0007510,
+	0x740092f2,
+	0x5807d018,
+	0x9258c000,
+	0xb786008b,
+	0xc2004fad,
+	0x70885a07,
+	0x1000d01e,
+	0x911cc000,
+	0xb786008b,
+	0x6209542d,
+	0x5833c200,
+	0x1421d110,
+	0xb781008b,
+	0x75025e2d,
+	0x90a4c000,
+	0xb5871a04,
+	0x008b4e2d,
+	0x5e2db781,
+	0xc0007508,
+	0xb7819144,
+	0x75045ead,
+	0x90a2c000,
+	0xb5870a02,
+	0x0a024e2d,
+	0x7100d012,
+	0xb586008b,
+	0x008b6aad,
+	0x712db786,
+	0x09b29eab,
+	0xb5860a04,
+	0xc0ca712d,
+	0xfd540de0,
+	0x9eab9af6,
+	0xc0cc0992,
+	0xfd540d90,
+	0x9eab9af0,
+	0xc0ce0992,
+	0xfd540dc8,
+	0x9eab9aea,
+	0xc0da09a2,
+	0xfd540d90,
+	0x0a029ae4,
+	0xb58d008b,
+	0xb58d68ab,
+	0xb58d632b,
+	0xb79f682b,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0x9000ffed,
+	0xd0149e52,
+	0xd00270c0,
+	0xf0127100,
+	0xc0000942,
+	0x9e5290a4,
+	0x9120c000,
+	0xc1010a7a,
+	0xd0101244,
+	0x11287104,
+	0xf01051f0,
+	0xf010a165,
+	0x9c22a1e1,
+	0xaa65f010,
+	0xa961f010,
+	0xc4129e50,
+	0xd1207100,
+	0x12181115,
+	0x9e545153,
+	0x51f39e8a,
+	0xfffe11a6,
+	0x0d029320,
+	0x91c0ffff,
+	0xa966f008,
+	0xa9e1f008,
+	0x9100ffff,
+	0xaa65f010,
+	0xa8e1f010,
+	0xc4129ea0,
+	0xd1107204,
+	0x15141619,
+	0x9e5450b3,
+	0xc81451f3,
+	0xc8027040,
+	0xd0147080,
+	0xd00270c0,
+	0x09047100,
+	0xc8120a04,
+	0x19747088,
+	0x9e900d02,
+	0x7280c812,
+	0x5d070d04,
+	0x05249e54,
+	0x51f350b3,
+	0x052201b2,
+	0x9100fffd,
+	0xfffe0d02,
+	0xf01092e0,
+	0xf010aa65,
+	0x9ea0a8e1,
+	0x7204c412,
+	0x1619d110,
+	0x50b31514,
+	0x51f39e54,
+	0x7040c814,
+	0x7080c802,
+	0x70c0d014,
+	0x7100d002,
+	0x196c0128,
+	0x9e900d02,
+	0x7280c812,
+	0x5d070d04,
+	0x05249e54,
+	0x51f350b3,
+	0x052261b3,
+	0x9000fffc,
+	0xa966f008,
+	0xa9e1f008,
+	0x92e0fffe,
+	0xfffe0d02,
+	0xa60d9280,
+	0xaae5f010,
+	0x9e5e0685,
+	0xf0107155,
+	0xd11ca962,
+	0x0107165b,
+	0x4458b343,
+	0x4838b355,
+	0x554fd018,
+	0xd0120986,
+	0x9ea370c4,
+	0x70c4cc12,
+	0x05b45d87,
+	0x983ac114,
+	0xd1209eb3,
+	0x0181115b,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0xfffa8c60,
+	0xf00891e0,
+	0xf008a966,
+	0xfffea9e1,
+	0x0d029280,
+	0x9220fffe,
+	0xa966f010,
+	0xaa61f010,
+	0xc8109e51,
+	0x11b47046,
+	0x518fc200,
+	0x1524c101,
+	0x9300fff9,
+	0xc002a61d,
+	0xd1718420,
+	0xb7c06e35,
+	0x0246430c,
+	0x06b6d010,
+	0x5a08c200,
+	0x00cca199,
+	0xb7e702dc,
+	0xc12a502d,
+	0xda080ac0,
+	0xc180aab1,
+	0xc1015e88,
+	0x9e6906dc,
+	0xc00f0707,
+	0xe0b22bfe,
+	0x09028d80,
+	0x4002ba2d,
+	0xb7a6018f,
+	0xb55f6835,
+	0xb5bf7bec,
+	0xfff47b6c,
+	0xe0b29b95,
+	0x09a28d80,
+	0x9bc4fff4,
+	0x0e62d011,
+	0x8d80f092,
+	0x5a0cc200,
+	0xa21d01e8,
+	0x0980c0d2,
+	0x058f0a02,
+	0xa2e1f210,
+	0x7cecb59f,
+	0x9b78fff4,
+	0x09a2058f,
+	0x9baefff4,
+	0xb786008d,
+	0xf0515dad,
+	0x9e6b8c80,
+	0x09029eab,
+	0xa221f208,
+	0xfff4a115,
+	0x008d9b6d,
+	0x5a2bb78c,
+	0x6d2bb76c,
+	0x11c69eab,
+	0x9b95fff4,
+	0x09a29eab,
+	0x9b94fff4,
+	0x7b6cb79f,
+	0xc0007500,
+	0xf21090fc,
+	0x7500aa61,
+	0x923ac000,
+	0x0902aa1d,
+	0x7becb55f,
+	0xb5ff00cc,
+	0xb7867b6c,
+	0xb72664ad,
+	0xb59f642d,
+	0xf2107cec,
+	0xb79fa0e1,
+	0x75007b6c,
+	0x913cc000,
+	0x8c80f092,
+	0xaa21f210,
+	0xc0007500,
+	0x008d919a,
+	0x4eadb746,
+	0xb59f0a06,
+	0xb55f7dec,
+	0xc0007d6c,
+	0x008d9340,
+	0x5dadb786,
+	0x8c80f071,
+	0x8d80e051,
+	0xf2089eab,
+	0x0a02a221,
+	0x7decb59f,
+	0x9ac6fff4,
+	0xe0b19eab,
+	0xfff48d80,
+	0x9eab9b17,
+	0xfff49e6b,
+	0xa9199b44,
+	0x6e65d171,
+	0x04ecd010,
+	0x02480244,
+	0xc114024c,
+	0x009c0a20,
+	0xa991da08,
+	0x5f2bb72e,
+	0xd02a7046,
+	0xd02901b6,
+	0xd0090192,
+	0xd00a0a32,
+	0xd1200a12,
+	0x098e01c7,
+	0x9b4dc0f4,
+	0x8d80e0b2,
+	0xfff40181,
+	0xe0719af7,
+	0xe0b28d80,
+	0xfff48d80,
+	0xe0b29b1c,
+	0xfef48d80,
+	0x9e839b0a,
+	0x9b29fef4,
+	0x7beeb79f,
+	0x7c6eb7bf,
+	0x7ceeb7df,
+	0x7d6eb7ff,
+	0x8c20c004,
+	0xa6059c22,
+	0x430cb720,
+	0x0d829e5d,
+	0x4aabb76d,
+	0x998dffb4,
+	0xa021f208,
+	0x430cb720,
+	0x64adb786,
+	0xc0007500,
+	0xb50d9082,
+	0x0a024aab,
+	0xa225f208,
+	0xa22df208,
+	0xa231f208,
+	0xa235f208,
+	0xa229f208,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0xb720a605,
+	0x76c2430c,
+	0xb56d9e5c,
+	0xc0004d2b,
+	0xb7209292,
+	0xb7ac430c,
+	0xb76c5b2b,
+	0xd0115ab3,
+	0xc0f409d2,
+	0x9e839afd,
+	0x1d84018b,
+	0x9ab7ff74,
+	0xc0000d8a,
+	0x76c69160,
+	0x15b6d021,
+	0x90c2c000,
+	0xc0007504,
+	0x0d8690a4,
+	0x9910ff94,
+	0x4314b760,
+	0x0de0c0d6,
+	0x9bb1fff4,
+	0x430cb700,
+	0x6f2cb706,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0x8420a60d,
+	0x430cb720,
+	0xb5850a06,
+	0xb72044ab,
+	0xb76a430c,
+	0xfdd447b1,
+	0xb7209b6d,
+	0x0982430c,
+	0x46b1b76a,
+	0x4731b74a,
+	0x5e30d1a2,
+	0xc0219e5a,
+	0xc1120a00,
+	0xc0000a10,
+	0x9dcd90e0,
+	0xa1e1f000,
+	0x0a00c100,
+	0x09047095,
+	0x9334ffff,
+	0x5badb7c3,
+	0x8d00e031,
+	0x9eb209a2,
+	0x9a2dfd74,
+	0xb720aa19,
+	0x09024314,
+	0x2ac6d011,
+	0x68d1d131,
+	0x46d1b7aa,
+	0x0092c101,
+	0x602db540,
+	0x430cb720,
+	0x9e889d29,
+	0xb76a9e89,
+	0xb70a46b1,
+	0xc0184729,
+	0xc01c0c30,
+	0xc0010cb0,
+	0xd1a29020,
+	0x9dcb5e30,
+	0xc0210189,
+	0xc1280980,
+	0xe0200980,
+	0x9dbdaa09,
+	0xa261f000,
+	0xa929e020,
+	0x0a30d111,
+	0xf0009dcd,
+	0x0d10a161,
+	0x7680c008,
+	0xffff0990,
+	0xd0119204,
+	0x9ea30e32,
+	0x2dfcc00e,
+	0xffff72d1,
+	0xaa1d9014,
+	0xc0017d02,
+	0xd1319342,
+	0xa99a69d1,
+	0x5d2db780,
+	0x5d890196,
+	0x0990c010,
+	0x9c629ea4,
+	0x025ac101,
+	0xc2000a04,
+	0x01095a30,
+	0x0900c021,
+	0xc0260d02,
+	0x9dad0970,
+	0xa162f000,
+	0x0a00c021,
+	0x0a60c026,
+	0xf0009dcd,
+	0xb720a162,
+	0x098e430c,
+	0x46a9b74a,
+	0x4731b74a,
+	0x5a30c100,
+	0x0a00c021,
+	0x0a50c114,
+	0x90e0c000,
+	0xf0009dcd,
+	0xc100a1e1,
+	0x70950a00,
+	0xffff0904,
+	0xb7209334,
+	0xd132430c,
+	0xd05168d1,
+	0xd1100a60,
+	0x9eab0493,
+	0x5fadb580,
+	0x430cb780,
+	0x0498c101,
+	0xc200aa1d,
+	0xb5805a05,
+	0xfdd45f4d,
+	0x75409802,
+	0x90c4c000,
+	0x430cb720,
+	0x44abb5a5,
+	0x430cb720,
+	0x47b1b76a,
+	0x9b3bfdd4,
+	0xfd340d8e,
+	0x0d8a9b9d,
+	0x9b9afd34,
+	0x7e6eb79f,
+	0x7eeeb7bf,
+	0x7f6eb7df,
+	0x8c00c002,
+	0xa60d9c22,
+	0x430cb720,
+	0xc0a40203,
+	0xd2080a10,
+	0xb7caaa82,
+	0x77404729,
+	0x92a4c002,
+	0xb5a50a86,
+	0xb72044ab,
+	0xb76a430c,
+	0xfdd447b1,
+	0x9eab9a89,
+	0x99e8fe14,
+	0x430cb720,
+	0x5dadb781,
+	0x75061a08,
+	0x4832b353,
+	0x92d2c000,
+	0x5908d226,
+	0xe0508520,
+	0x94088044,
+	0x940c940a,
+	0xc1019401,
+	0xc0000982,
+	0x09869120,
+	0x90c0c000,
+	0xc000098e,
+	0x098a9060,
+	0x7eb1b745,
+	0x0a02c020,
+	0x5930c300,
+	0xb3247680,
+	0xc1404822,
+	0x32460900,
+	0x0900c021,
+	0xf0009dad,
+	0x0203a261,
+	0x0a20c09c,
+	0x5badb763,
+	0xa902d208,
+	0x09069eb3,
+	0x98acfdb4,
+	0x430cb720,
+	0x47b1b76a,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0xfdd68c60,
+	0xb79f9180,
+	0xb7bf7eee,
+	0xb7df7f6e,
+	0x8c607fee,
+	0xa61d9c22,
+	0x8420c016,
+	0x6f74b57f,
+	0xaa61d050,
+	0xa9e6d050,
+	0x03091a28,
+	0xc00e1d88,
+	0xc00e2b7c,
+	0xfd742dfc,
+	0xd031987d,
+	0xd0116869,
+	0xd2240a62,
+	0x02015b30,
+	0x0a20c014,
+	0x5808d324,
+	0x0a00c021,
+	0x6aecb59f,
+	0x568cb780,
+	0x6e6cb51f,
+	0x9e400101,
+	0x020801ec,
+	0x57ecb59f,
+	0x4f8cb780,
+	0x0930c014,
+	0x0900c021,
+	0xb59f0208,
+	0xb7806b6c,
+	0xb55f558c,
+	0x9e716a6c,
+	0xb59f0268,
+	0xb780576c,
+	0xd0d1500c,
+	0x02686961,
+	0x7c6cb59f,
+	0x518cb780,
+	0x0880c040,
+	0x59ecb53f,
+	0xb59f0238,
+	0xb78071ec,
+	0xb51f540c,
+	0xb7207b74,
+	0x0128430c,
+	0x596cb55f,
+	0x59f4b71f,
+	0xb7800906,
+	0x9e91570c,
+	0x7becb57f,
+	0xc24000e2,
+	0xc021a0c6,
+	0x0a020c00,
+	0xb51f9e72,
+	0x9e737974,
+	0x4c29b58a,
+	0x9e749e70,
+	0xc0219e71,
+	0x050d0900,
+	0x078d058d,
+	0x048d040d,
+	0x0900c01e,
+	0x0d00c021,
+	0x0980c021,
+	0x0d80c021,
+	0x0a00c021,
+	0x0f80c021,
+	0x0800c021,
+	0x0c00c021,
+	0x0880c021,
+	0x0c80c021,
+	0x756cb55f,
+	0x0d10c01e,
+	0x09a0c01e,
+	0x0df0c014,
+	0x0a00c010,
+	0x0f90c010,
+	0x0820c010,
+	0x0c30c010,
+	0x0880c004,
+	0x0ca0c012,
+	0x1950c00a,
+	0x75f4b55f,
+	0x776cb57f,
+	0x5a74b57f,
+	0x5cecb59f,
+	0x5bf4b5ff,
+	0x5b6cb51f,
+	0x5af4b51f,
+	0x61ecb53f,
+	0x6174b53f,
+	0x60ecb55f,
+	0x1d50c00c,
+	0x19d0c00c,
+	0x1d90c004,
+	0xc0080a70,
+	0xc0020f90,
+	0xc0020830,
+	0xc00e0c30,
+	0x0cf008f0,
+	0xb55f0950,
+	0xb57f72f4,
+	0xb57f726c,
+	0xb59f7174,
+	0xb5ff70ec,
+	0xc0026074,
+	0xb51f0d60,
+	0x09f05fec,
+	0x7074b51f,
+	0x78ecb53f,
+	0x5ef4b53f,
+	0x5e6cb55f,
+	0x0db0c034,
+	0x0a50c004,
+	0xc0041fd0,
+	0xc00c0810,
+	0xc0240c20,
+	0xc00e08d0,
+	0xc0121cd0,
+	0xb55f0900,
+	0xb57f5df4,
+	0xb57f5d6c,
+	0xb59f7374,
+	0xb5ff73ec,
+	0xb51f69f4,
+	0xb51f696c,
+	0xb53f68f4,
+	0xb53f746c,
+	0xb55f6874,
+	0xc03074ec,
+	0xc0320d50,
+	0xcfd009c0,
+	0xc01e0da1,
+	0x1ff00a40,
+	0x0850c06a,
+	0x0c50c026,
+	0x08e1cfe0,
+	0x0cf0c014,
+	0x0931cfee,
+	0x67f4b55f,
+	0x676cb57f,
+	0x66f4b57f,
+	0x666cb59f,
+	0x65f4b5ff,
+	0x656cb51f,
+	0x64f4b51f,
+	0x646cb53f,
+	0x63f4b53f,
+	0x766cb55f,
+	0x0d31cfd0,
+	0x09c1cfce,
+	0xcfe21de0,
+	0xcfea0a01,
+	0xcf7c0fe1,
+	0x0c200871,
+	0x08d0c01e,
+	0x0cf0c024,
+	0x0910c032,
+	0x76f4b55f,
+	0x77ecb57f,
+	0x62f4b57f,
+	0x626cb59f,
+	0x7a74b5ff,
+	0x79ecb51f,
+	0x6df4b51f,
+	0x6d6cb53f,
+	0x6cf4b53f,
+	0x6c6cb55f,
+	0x9060c059,
+	0x09829eb3,
+	0x9b91fdf4,
+	0x4314b740,
+	0xb55f9e50,
+	0xb7437af4,
+	0x7480572a,
+	0x9364c003,
+	0x6cacb784,
+	0x0e820b82,
+	0xd00a7502,
+	0x75040bf2,
+	0x0ed2d001,
+	0xc00075c0,
+	0x774090c4,
+	0xd0010906,
+	0xb73f0922,
+	0xc1007aec,
+	0x69635a0c,
+	0x0118d020,
+	0xc0010802,
+	0x04050abe,
+	0x03a8d020,
+	0xcfc09d09,
+	0xc0340a80,
+	0xb9600c78,
+	0xd0114018,
+	0xb75f4e52,
+	0xc2007aec,
+	0xd0105a08,
+	0x024004f0,
+	0xd0200248,
+	0xb78000c4,
+	0xb7405a2b,
+	0x75c0502b,
+	0x4002ba24,
+	0x5a28c200,
+	0xc03e224a,
+	0x9dcb297c,
+	0xb76031c4,
+	0xb7204052,
+	0xc000462b,
+	0xb78392a4,
+	0xb7436dcb,
+	0xb74377cb,
+	0xba2463d3,
+	0xc2004002,
+	0x224a5a28,
+	0x9ea15950,
+	0x2940c3ff,
+	0x2d7cc03e,
+	0x351431b4,
+	0x2a0ed3f1,
+	0xc0007506,
+	0xb75f90e2,
+	0x9dad756c,
+	0xa1e1f000,
+	0x4002ba21,
+	0x2dfcc03e,
+	0xc2009e5b,
+	0x224a5a28,
+	0xb77f3246,
+	0x9dbe75f4,
+	0xa261f000,
+	0x776cb79f,
+	0xf0009dcd,
+	0x0804a162,
+	0xfffd0c08,
+	0x9eb391c1,
+	0x9be6fe34,
+	0x430cb720,
+	0x4cadb742,
+	0x7c80c020,
+	0x90e2c000,
+	0x438cb780,
+	0xc0005158,
+	0x7c8291e0,
+	0x438cb740,
+	0x91a2c000,
+	0x0a02c010,
+	0x5218c200,
+	0x22444a7d,
+	0x51580906,
+	0xc0003244,
+	0xc0109100,
+	0xc2000a06,
+	0x4a7d5218,
+	0xb5802228,
+	0xc021438c,
+	0xb7400a02,
+	0xc020438c,
+	0x9dcd0a00,
+	0xa161f000,
+	0x430cb780,
+	0x7b6cb71f,
+	0x9ea80288,
+	0x6fccb789,
+	0x753ec01c,
+	0x9164c001,
+	0xfdf49eb3,
+	0x008b9b5e,
+	0x6fadb509,
+	0x91e0c000,
+	0x9becfd94,
+	0xb7a09eb3,
+	0xfdf4430c,
+	0xb75f9b52,
+	0x02aa7b6c,
+	0xb5099ea8,
+	0xb7806fcc,
+	0xb75f430c,
+	0x0d927b6c,
+	0xb72900a8,
+	0xc01c6fad,
+	0xffff747e,
+	0x68b29122,
+	0x57f4b75f,
+	0xb7290098,
+	0xf010712d,
+	0xb740a0c1,
+	0xb77f430c,
+	0x00b47b6c,
+	0x6fadb789,
+	0x02446a32,
+	0x0a20c138,
+	0xaa11d208,
+	0x753ec01c,
+	0x9084c001,
+	0xfdf49eb3,
+	0xb7209ac7,
+	0xb77f4314,
+	0xd0107b74,
+	0xb74904b2,
+	0xd0316fb5,
+	0xd0106d29,
+	0xc1010624,
+	0xc1380122,
+	0xd0080920,
+	0xc101a951,
+	0x02440244,
+	0x5a08c200,
+	0x00c3d120,
+	0x6b6cb79f,
+	0x70d5b729,
+	0xa082f208,
+	0xfe349eb3,
+	0x74009ac8,
+	0x90c4c000,
+	0x097ec00e,
+	0x9020c004,
+	0x430cb740,
+	0xc0a20205,
+	0xd2080a38,
+	0x7680a902,
+	0x90e2c001,
+	0x01859e93,
+	0x09c0c0a2,
+	0x0d9cc0a4,
+	0xa962d008,
+	0xaa61d010,
+	0xc0007115,
+	0xb7ff91f2,
+	0x0a027c74,
+	0xa261d210,
+	0xaa61d008,
+	0xa961d010,
+	0x9ea21244,
+	0x2d7cc00e,
+	0x430cb740,
+	0x0940c0a2,
+	0xaa41d008,
+	0xd0080a04,
+	0xc001a241,
+	0x00ac9380,
+	0x02030103,
+	0x0940c0a2,
+	0x0a20c0a2,
+	0xa945d008,
+	0xaa11d208,
+	0xc0017088,
+	0xb71f9064,
+	0xb5407c6c,
+	0xb54a4030,
+	0xb7a04c31,
+	0x9ea8430c,
+	0xc0a4020b,
+	0xb76a0a1c,
+	0xd2084750,
+	0xb76aaa01,
+	0xc1014648,
+	0x02dc15bc,
+	0x65b9c101,
+	0x1a32d011,
+	0x01c7d120,
+	0x0ac0c0a2,
+	0x9ac6c0d4,
+	0xa025d208,
+	0x430cb780,
+	0xc0a2024c,
+	0xd2080a40,
+	0xd011a906,
+	0xd2080d22,
+	0xb780a105,
+	0xc09c430c,
+	0xd2080a14,
+	0x7500aa01,
+	0x9142c000,
+	0x7c6cb73f,
+	0x4029b780,
+	0x0a027500,
+	0x0a42d002,
+	0x5774b73f,
+	0xb5809e52,
+	0xb7804049,
+	0xc00e430c,
+	0xb760297c,
+	0x9e93560c,
+	0xc23000cc,
+	0xb78aa1c6,
+	0x75004c29,
+	0x9304c000,
+	0x4b29b54a,
+	0x7c74b7ff,
+	0xaa61d210,
+	0xc0007500,
+	0xb72091e4,
+	0x0103430c,
+	0x091cc0a4,
+	0xb78a009c,
+	0xd0084b29,
+	0x0244a941,
+	0x4b29b58a,
+	0x560cb700,
+	0xaa45c200,
+	0xc0007500,
+	0x9eb390a4,
+	0x9957fe14,
+	0x7c74b71f,
+	0x430cb7a0,
+	0x4048b780,
+	0xc0007500,
+	0x9eaf90e2,
+	0x0f90c06e,
+	0x90a0c000,
+	0xc0809eaf,
+	0x9eb30f80,
+	0x9be2fe94,
+	0x7aecb73f,
+	0xa9e1f210,
+	0x6835b741,
+	0x2d4d7cc2,
+	0x9202c000,
+	0x430cb780,
+	0xc0983d10,
+	0xd2080a10,
+	0x7500aa01,
+	0x92c2c000,
+	0x3d00c200,
+	0x9240c000,
+	0x7cc0c010,
+	0x91c2c000,
+	0x430cb780,
+	0xc0983d20,
+	0xd2080a14,
+	0x7500aa01,
+	0x9084c000,
+	0x3d00c100,
+	0x430cb720,
+	0x5dadb781,
+	0xc001750a,
+	0xb7859084,
+	0x75007ea9,
+	0x93e2c000,
+	0x7f29b785,
+	0xc0007500,
+	0xb73f9202,
+	0xc8007c74,
+	0xb7800902,
+	0x75004049,
+	0xb3420a02,
+	0x9e934424,
+	0xc0003526,
+	0xb71f9180,
+	0xb7807c6c,
+	0xc2004028,
+	0xc8005a3c,
+	0x9ea02a00,
+	0xb73f3520,
+	0x9d9d796c,
+	0xa162f000,
+	0x560cb740,
+	0x7cc2c010,
+	0x508cb780,
+	0xb55f0164,
+	0xd008636c,
+	0x0902aac2,
+	0x0922d001,
+	0xb71f9e92,
+	0xc2407aec,
+	0xb780a146,
+	0x06da430c,
+	0x5baab742,
+	0x06d8c101,
+	0xb74a040b,
+	0xb7825352,
+	0xb7205b2a,
+	0xb7a0412c,
+	0x6244510c,
+	0x63c5c101,
+	0x01839ebb,
+	0x6fecb53f,
+	0x99d9c0d4,
+	0x71f4b73f,
+	0x6fecb77f,
+	0xb5009ebb,
+	0xb75f404b,
+	0x02aa7bec,
+	0x9a29c0d4,
+	0xa021da08,
+	0xb73f9e68,
+	0xb74b7bec,
+	0xb780532a,
+	0x0d02520c,
+	0xb7409e91,
+	0xc840538c,
+	0xb780a0a6,
+	0xb77f528c,
+	0x01145974,
+	0xa126c840,
+	0x5332b7aa,
+	0x530cb780,
+	0x09c2c002,
+	0xa142d808,
+	0xa2a6c840,
+	0x9ba5fd14,
+	0x4314b720,
+	0xc0a49e4c,
+	0xd2080a18,
+	0x7500aa01,
+	0x9202c001,
+	0x636cb75f,
+	0x7c74b75f,
+	0xa8c1d008,
+	0xaa41d010,
+	0xc1010092,
+	0x75000092,
+	0x532bb74a,
+	0x9104c000,
+	0x6c4db784,
+	0x01090228,
+	0x297ccffe,
+	0x6b4db709,
+	0x018d9e93,
+	0x9c629e84,
+	0x430cb720,
+	0x5dadb781,
+	0x75021a10,
+	0x90f2c000,
+	0x532bb78c,
+	0xc0007500,
+	0xb78090e4,
+	0x9e83550c,
+	0xa1c6c240,
+	0x7aecb71f,
+	0x5dacb781,
+	0xc0007506,
+	0xb7209204,
+	0x00e2430c,
+	0x4829b78c,
+	0xc0007500,
+	0x097e9102,
+	0x550cb780,
+	0xc2409e90,
+	0xb73fa046,
+	0xb7817aec,
+	0x1a085dad,
+	0xc0037506,
+	0xd22691f2,
+	0x8520590c,
+	0x8044e050,
+	0x9100c000,
+	0x9240c002,
+	0x9260c001,
+	0x9280c001,
+	0x7af4b73f,
+	0x4149b786,
+	0xc0007500,
+	0xb7409202,
+	0xc220560c,
+	0x7500aa45,
+	0x9124c000,
+	0x7c74b75f,
+	0xaa41d010,
+	0xc0007500,
+	0x9eb390c4,
+	0xfe14018f,
+	0xb77f992a,
+	0xb7407c6c,
+	0x9d07550c,
+	0xa8e2d008,
+	0xa945c220,
+	0x0a029eb3,
+	0xd052018f,
+	0xcfe80d78,
+	0xb59e08e1,
+	0xfd74666a,
+	0xc0019aef,
+	0x0d829260,
+	0x9080c001,
+	0x560cb700,
+	0xaa45c200,
+	0xc0007500,
+	0x9ea390a4,
+	0x9853fe14,
+	0x430cb720,
+	0xb76a018f,
+	0xfe1446b1,
+	0xb71f9900,
+	0x9ebb7c74,
+	0x0df8d051,
+	0x4050b740,
+	0x9280c000,
+	0x560cb720,
+	0xaa45c210,
+	0xc0007500,
+	0x9ea390e4,
+	0x9839fe14,
+	0x9140c000,
+	0x430cb760,
+	0x0d060d82,
+	0x09e0c06e,
+	0x9b5cfdf4,
+	0xfe349eb3,
+	0xb7a09925,
+	0xb780430c,
+	0x9ea9550c,
+	0xaa45c240,
+	0x70c9b744,
+	0x2a7cc002,
+	0xc0305920,
+	0x32442900,
+	0x5a6cb75f,
+	0xf0009dad,
+	0xb75fa261,
+	0x020b7c74,
+	0x5dc5b741,
+	0xabc1d010,
+	0x0a44c09a,
+	0xc00075c0,
+	0xd20891e2,
+	0xc200aa01,
+	0x00ca5a08,
+	0x6cb5b742,
+	0x63adb742,
+	0x682db782,
+	0x91a0c000,
+	0xaa01d208,
+	0x5a08c200,
+	0xb74200ca,
+	0xb7427a35,
+	0xb782712d,
+	0xb77f75ad,
+	0x9dbd5cec,
+	0xa161f000,
+	0x5bf4b77f,
+	0xf0009dbe,
+	0xb79fa261,
+	0x9dcd5b6c,
+	0xa162f000,
+	0xb781000b,
+	0xb71f482c,
+	0x9d8e5af4,
+	0xa261f000,
+	0xa8a9f208,
+	0xb53f75c0,
+	0xb7496eec,
+	0x0203573a,
+	0x5a10c200,
+	0xc0029d4b,
+	0xcffc0a7c,
+	0x59102a01,
+	0x0148d020,
+	0xcffe097c,
+	0xc1012901,
+	0x02030528,
+	0x6525c101,
+	0x2a710a0c,
+	0x5890c200,
+	0xc0005d05,
+	0xb78391a2,
+	0x0e825e2c,
+	0xe003048b,
+	0xb3152a00,
+	0x05834442,
+	0x92e0c000,
+	0xc3019ea9,
+	0xb7846115,
+	0xd0f241cd,
+	0xc00508ae,
+	0xcffc7d00,
+	0xc0002c81,
+	0x068390a2,
+	0x9080c000,
+	0x0692c101,
+	0x0092c101,
+	0x020b0585,
+	0x0a10c098,
+	0xd2089ea8,
+	0xb781a801,
+	0x09c24b4c,
+	0xd0217400,
+	0x750209b8,
+	0x1124d011,
+	0x9102c000,
+	0xc1800207,
+	0xc0815920,
+	0x31443a20,
+	0x61ecb77f,
+	0xf0009dbd,
+	0x9ea8a161,
+	0x7ec8b785,
+	0x664cb764,
+	0x66ccb744,
+	0xc0007500,
+	0x740092e2,
+	0x9282c000,
+	0xc00075c0,
+	0xb7649102,
+	0xb744654c,
+	0xc00065cc,
+	0x9ea89100,
+	0xb7649eba,
+	0xb744644c,
+	0x858664cc,
+	0x9080c000,
+	0x05078582,
+	0xb7849ea8,
+	0xb71f644c,
+	0xd1106174,
+	0x9d8e0639,
+	0xa261f000,
+	0xb7849ea8,
+	0xb71f64cc,
+	0xd11060f4,
+	0x9d8e0639,
+	0xa261f000,
+	0xb7849ea8,
+	0xb71f654c,
+	0xd11072f4,
+	0x9d8e0639,
+	0xa261f000,
+	0xb7849ea8,
+	0xd11065cc,
+	0xb77f0639,
+	0x9dbe7274,
+	0xa261f000,
+	0x0627d110,
+	0x7174b71f,
+	0xf0009d8e,
+	0xd110a261,
+	0xb75f0625,
+	0x9dad70ec,
+	0xa261f000,
+	0x75c09ea8,
+	0x7f48b785,
+	0x9102c000,
+	0x7d3ec01c,
+	0x9104c000,
+	0x9140c000,
+	0x7d3ec01c,
+	0x90c4c000,
+	0x0a060d02,
+	0x9080c000,
+	0x0a020d0a,
+	0x74809d6b,
+	0x9102c000,
+	0xc0007500,
+	0x090690a2,
+	0x9100c000,
+	0x09029d6f,
+	0x31c6e000,
+	0x0922d001,
+	0x4a049e53,
+	0x59083238,
+	0xb77f3244,
+	0x9dbe6074,
+	0xa261f000,
+	0xc096020b,
+	0xd2080a58,
+	0xb71fa901,
+	0xc1005ff4,
+	0x024a5a08,
+	0xaa11f288,
+	0x0619d110,
+	0xf0009d8e,
+	0x590ca261,
+	0xf0c8012a,
+	0x0114a951,
+	0x706cb73f,
+	0xf0009d9d,
+	0xb75fa161,
+	0x9dae78f4,
+	0xa161f000,
+	0xc096020b,
+	0xd2080a50,
+	0xb77fa901,
+	0xd0205eec,
+	0xd1220124,
+	0x024a5e08,
+	0xaa11f2c8,
+	0x0659d110,
+	0xf0009dbd,
+	0x5908a261,
+	0xf088012a,
+	0xb77fa951,
+	0xd1105e74,
+	0x9dbe0515,
+	0xa161f000,
+	0x5d080d04,
+	0x052ac101,
+	0xa952f0d0,
+	0x5decb79f,
+	0x9dcd0554,
+	0xa162f000,
+	0x7b6cb75f,
+	0x5d74b75f,
+	0xb72100aa,
+	0x9dae48ad,
+	0xa0e1f000,
+	0xb7849ea8,
+	0xf21163cc,
+	0xc00128c0,
+	0x74009004,
+	0x93a4c000,
+	0x72f4b73f,
+	0xaa619d1e,
+	0x716cb75f,
+	0xf0009dad,
+	0xb75fa261,
+	0x9d2e7274,
+	0xb77faa61,
+	0x9dbd70ec,
+	0xa261f000,
+	0x7074b77f,
+	0xaa619d3e,
+	0x78ecb71f,
+	0xf0009d8d,
+	0xb71fa261,
+	0xb75f7aec,
+	0xb7807bec,
+	0xb722510c,
+	0x000b5b32,
+	0x622cb701,
+	0xa9c7c840,
+	0x520cb780,
+	0xb51f9dc0,
+	0x7604566c,
+	0x71f4b75f,
+	0xa846c840,
+	0xa965f210,
+	0xaac2d810,
+	0x56ecb55f,
+	0x9104c001,
+	0x5b8cb760,
+	0x5c14b740,
+	0xb9600902,
+	0xe0304018,
+	0xb77faa45,
+	0x9dbe6af4,
+	0xa261f000,
+	0xb77f9e50,
+	0xe0006a74,
+	0x9dbeaa45,
+	0xa261f000,
+	0xffff0910,
+	0xb79f9201,
+	0xc0746e6c,
+	0xc0140976,
+	0xc0210a40,
+	0x9dcd0a00,
+	0xa161f000,
+	0x9060c001,
+	0x75069d50,
+	0x93e4c000,
+	0x0906c001,
+	0x0a02c021,
+	0x0900c4d0,
+	0x0a20c014,
+	0xf0009dcd,
+	0xc02ca161,
+	0x0a100932,
+	0xf0009dcd,
+	0xc002a161,
+	0x0a10097e,
+	0xf0009dcd,
+	0x0a02a161,
+	0x736cb71f,
+	0xf0009d8d,
+	0xf011a261,
+	0x75028e28,
+	0x9072c001,
+	0x0906c001,
+	0x0a02c021,
+	0x0900cca0,
+	0x0a20c014,
+	0xf0009dcd,
+	0xc040a161,
+	0x0a10091a,
+	0xf0009dcd,
+	0xc002a161,
+	0x0a10097e,
+	0xf0009dcd,
+	0x000ba161,
+	0x60acb781,
+	0x736cb75f,
+	0x2a1c1a04,
+	0xf0009dad,
+	0x9e78a261,
+	0x73f4b75f,
+	0x622cb740,
+	0xc1010205,
+	0x9dae3a00,
+	0xa261f000,
+	0xf0009dae,
+	0xb780a161,
+	0xb77f62ac,
+	0x9dbd69ec,
+	0xa261f000,
+	0x632cb780,
+	0x6974b77f,
+	0xf0009dbe,
+	0xf210a261,
+	0xb71faa69,
+	0x9d8d68ec,
+	0xa261f000,
+	0xc098020b,
+	0xd2080a0c,
+	0x7500aa01,
+	0x9222c000,
+	0xc0007440,
+	0x008b91c2,
+	0x62adb781,
+	0x746cb75f,
+	0x3a00c020,
+	0xf0009dad,
+	0xc000a261,
+	0x000b9140,
+	0x62acb781,
+	0x746cb73f,
+	0xf0009d9d,
+	0x000ba261,
+	0x632cb781,
+	0x686cb73f,
+	0xf0009d9d,
+	0xb78ca261,
+	0xb741532a,
+	0x750063ac,
+	0x90c2c001,
+	0x7c82c001,
+	0x90c4c000,
+	0x9e92097e,
+	0x9220c000,
+	0x292ed3f2,
+	0x9ea30a7e,
+	0x2900cff0,
+	0x592176be,
+	0x4846b323,
+	0xb32474be,
+	0x05074426,
+	0xc0010109,
+	0x9e503d04,
+	0x5a20c100,
+	0xb73f3208,
+	0x9d9d74ec,
+	0xa261f000,
+	0x90e0c000,
+	0x74f4b75f,
+	0xf0009dae,
+	0x000ba161,
+	0x652cb781,
+	0x67ecb73f,
+	0xf0009d9d,
+	0xb781a261,
+	0xb75f65ac,
+	0x9dad676c,
+	0xa261f000,
+	0x6602d011,
+	0x8db2e012,
+	0x6fecb77f,
+	0x05b8c101,
+	0x7d7cb55f,
+	0x7de4b55f,
+	0x9a17c0b4,
+	0x0451d110,
+	0x566cb77f,
+	0xcff05820,
+	0x30062800,
+	0x66f4b77f,
+	0xf0009dbe,
+	0x000ba061,
+	0x662cb781,
+	0x6674b71f,
+	0xf0009d8e,
+	0xd2a2a261,
+	0xb73f5e20,
+	0xcff056ec,
+	0xb73f2a00,
+	0x324265f4,
+	0xf0009d9e,
+	0xb781a261,
+	0xb75f672c,
+	0x9dad656c,
+	0xa261f000,
+	0x532ab783,
+	0x64f4b75f,
+	0xf0009dae,
+	0xc021a261,
+	0xc0120902,
+	0x9dad0950,
+	0xa261f000,
+	0x7decb77f,
+	0x7d7cb75f,
+	0xc00074c4,
+	0xb7819204,
+	0xb77f642c,
+	0x9dbe6474,
+	0xa261f000,
+	0x64acb781,
+	0x63ecb71f,
+	0xf0009d8d,
+	0x020ba261,
+	0xc09a75c0,
+	0xc0000a44,
+	0xd20893c2,
+	0xb71faa01,
+	0xc2007674,
+	0x00ca5a08,
+	0x7aadb780,
+	0xf0009d8e,
+	0xb780a261,
+	0xb73f7f2d,
+	0x9d9e76f4,
+	0xa261f000,
+	0x43adb721,
+	0x77ecb75f,
+	0xf0009dad,
+	0xc001a0e1,
+	0xd2089380,
+	0xb77ea902,
+	0xb77f7a68,
+	0x5d087674,
+	0x293ed3f1,
+	0x5a0cc100,
+	0x04abd110,
+	0x0a7cc002,
+	0x7ab5b740,
+	0x2a01cffc,
+	0x6245c301,
+	0x0244c101,
+	0xf0009dbe,
+	0xd012a261,
+	0x9d53692b,
+	0x5d0b0d0c,
+	0x7f2db760,
+	0x5a18c200,
+	0x6245c101,
+	0x76ecb71f,
+	0x9d8d0246,
+	0xa261f000,
+	0x6125c301,
+	0x43adb721,
+	0xc0020124,
+	0xcffc097c,
+	0x01222901,
+	0x77f4b71f,
+	0xf0009d8e,
+	0xf210a161,
+	0xb73fa96d,
+	0x9d9d62ec,
+	0xa161f000,
+	0xb75f9ea9,
+	0xb7816274,
+	0x9dae66cd,
+	0xa261f000,
+	0x7aecb71f,
+	0x7fa8b785,
+	0xc0007500,
+	0xb78a9164,
+	0x75024649,
+	0x90c4c000,
+	0x3900c080,
+	0xa16df210,
+	0x0a7ec7fe,
+	0x7a74b71f,
+	0xf0009d8e,
+	0xc401a261,
+	0xc5000a02,
+	0xb73f0a00,
+	0x9d9d79ec,
+	0xa261f000,
+	0x991afe14,
+	0x7becb75f,
+	0x528cb780,
+	0x7b6cb77f,
+	0xb59f0228,
+	0xb780786c,
+	0x0228520c,
+	0x5c6cb59f,
+	0x510cb780,
+	0x03a8d020,
+	0x548cb780,
+	0xb59f0238,
+	0xb780586c,
+	0x03a8538c,
+	0x560cb780,
+	0xb59f0268,
+	0xc0095f6c,
+	0x74809380,
+	0x08021a04,
+	0x0802d001,
+	0x70880c02,
+	0x0c02d001,
+	0xb51f7400,
+	0xc0006bec,
+	0x008b9142,
+	0x5b2bb762,
+	0x5333b74c,
+	0xc0020906,
+	0xb73f9080,
+	0x020b5f74,
+	0x0a1cc0a4,
+	0xa901d208,
+	0x4049b780,
+	0xc0017104,
+	0x00dc93c8,
+	0x4929b78c,
+	0x08c0c060,
+	0xc0007500,
+	0xb7809204,
+	0x75004029,
+	0x9164c000,
+	0xb78c000b,
+	0x0d02532a,
+	0xd0027500,
+	0xc0000d22,
+	0x0d069060,
+	0xda10008b,
+	0xb742aa61,
+	0x02445b2b,
+	0xa261da10,
+	0x9160c000,
+	0x71f4b73f,
+	0xa1e1da10,
+	0x404bb780,
+	0xb5800a04,
+	0xf208404b,
+	0xda10a929,
+	0x7104aa61,
+	0xffff11c4,
+	0x000b9228,
+	0x5b2ab762,
+	0x9eb30902,
+	0x9e419e91,
+	0xfdf4a01e,
+	0xb71f9ada,
+	0x9e745874,
+	0x0a00c021,
+	0x404cb740,
+	0x0a00c016,
+	0xf0009dcd,
+	0x9eb3a161,
+	0x98dafe14,
+	0x0992058d,
+	0x0d02c400,
+	0x9a57fd74,
+	0x0a02c400,
+	0x7a6cb73f,
+	0xf0009d9d,
+	0xb73fa261,
+	0xda087874,
+	0x000baa61,
+	0x404bb740,
+	0xda080a04,
+	0x0904a261,
+	0x404bb540,
+	0x5baab742,
+	0x2a7ccffe,
+	0xc0007088,
+	0x0a0291e4,
+	0xa261da08,
+	0x7becb73f,
+	0x530cb740,
+	0xd8080114,
+	0x0a04aa41,
+	0xa241d808,
+	0x7c74b73f,
+	0x530cb780,
+	0x7becb75f,
+	0x4051b760,
+	0xaa45c840,
+	0xc00076c0,
+	0x9ea590a2,
+	0x9100c000,
+	0x430cb720,
+	0x6c2db724,
+	0x02c2d020,
+	0x6bf4b75f,
+	0xc0017680,
+	0xda089024,
+	0x000ba961,
+	0x5baab762,
+	0x0d027482,
+	0x0d22d001,
+	0xd00174c2,
+	0xb3321a44,
+	0xc0004442,
+	0x748290a2,
+	0x1a42d00a,
+	0xc00076c0,
+	0xb72090e4,
+	0xb724430c,
+	0x02426c2d,
+	0x018d9ea3,
+	0x9adefe74,
+	0x430cb720,
+	0xc0a40203,
+	0xd2080a18,
+	0x7500aa01,
+	0x9322c001,
+	0x5f74b71f,
+	0xc0a40203,
+	0xd2080a1c,
+	0xb780a901,
+	0x71044048,
+	0x91e8c002,
+	0x7874b73f,
+	0x5c74b75f,
+	0x404bb740,
+	0xaa41d810,
+	0xc0027088,
+	0xda089088,
+	0x7500aa61,
+	0x93e4c001,
+	0x6b2db709,
+	0x018d058b,
+	0x9c629e84,
+	0x430cb720,
+	0x5dadb781,
+	0x75021a10,
+	0x90f2c000,
+	0x532bb78c,
+	0xc0017500,
+	0xb7809184,
+	0x9e80550c,
+	0xc2409eb3,
+	0xc001a046,
+	0x009c9040,
+	0x4829b78c,
+	0xc0007500,
+	0x008b93c2,
+	0x5dadb781,
+	0x550cb740,
+	0xc0007504,
+	0xc0029124,
+	0x9ea10a44,
+	0xa0c6c220,
+	0x9180c000,
+	0xd2080264,
+	0x0d7ea901,
+	0x9e930908,
+	0x7286c810,
+	0xa102d208,
+	0xfe149eb3,
+	0xfdf49825,
+	0xb79f9bbf,
+	0xb71f786c,
+	0xb7a05c6c,
+	0xda08430c,
+	0xb780a901,
+	0x7088402a,
+	0x9366fff5,
+	0xc0a2020b,
+	0xd2080a38,
+	0x7500aa01,
+	0x90a2c000,
+	0xc0000a06,
+	0x025c9200,
+	0xc0a20109,
+	0xc0a20920,
+	0xd2080a40,
+	0xd008aa05,
+	0x7104a951,
+	0xd0010a02,
+	0x9eb30a42,
+	0xfdf40389,
+	0x058d9be3,
+	0xc1000992,
+	0xfd740d02,
+	0xcffe9960,
+	0xc1002bfc,
+	0xb71f0a02,
+	0x9d8e7a74,
+	0xa261f000,
+	0xb73f0a86,
+	0x9d9d6dec,
+	0xa2e1f000,
+	0x6d74b73f,
+	0xf0009d9e,
+	0xb77fa2e1,
+	0xc00659f4,
+	0x0d0209f2,
+	0xfcf4010b,
+	0xc0389958,
+	0x0d0209f2,
+	0x058d010b,
+	0x9951fcf4,
+	0x7c74b75f,
+	0x530cb780,
+	0x7becb77f,
+	0xa941d010,
+	0xaa65c840,
+	0x1a047480,
+	0x9144c000,
+	0x430cb720,
+	0x2a7ccffe,
+	0x6c2db724,
+	0x020300c2,
+	0x2a7ccffe,
+	0x9eaa9ea3,
+	0xfe74018d,
+	0x75c09a09,
+	0x90a4c000,
+	0xc000010f,
+	0xb7209280,
+	0xb785430c,
+	0x75007ea9,
+	0x90a4c000,
+	0xc000010b,
+	0xb77f9140,
+	0x09027c74,
+	0xaa61d010,
+	0xd0017500,
+	0x9e950922,
+	0xcffe75c0,
+	0xc0002efc,
+	0xb7209124,
+	0xb786430c,
+	0x75006729,
+	0x9042c002,
+	0x0a82c008,
+	0x7a6cb79f,
+	0xf0009dcd,
+	0xb7ffa2e1,
+	0x9d7e7974,
+	0xc002aa61,
+	0x9dfe3a40,
+	0xa261f000,
+	0x0a02c401,
+	0x0a00c008,
+	0x79ecb71f,
+	0xf0009d8d,
+	0x9eaaa261,
+	0x058d0992,
+	0x98ddfd74,
+	0xb71f0a02,
+	0x9d8e79f4,
+	0xa261f000,
+	0x7a6cb73f,
+	0xf0009d9d,
+	0xb73fa2e1,
+	0x9d1e6cf4,
+	0xb75faa61,
+	0x9d2d6c6c,
+	0x7680a962,
+	0x91c2c000,
+	0x6b6cb77f,
+	0x5a35c200,
+	0xf0082a7c,
+	0xd110a961,
+	0x12a81525,
+	0x9060c000,
+	0xb7400a82,
+	0x9eb3430c,
+	0xc0a20986,
+	0xd008093c,
+	0x0a04aa41,
+	0xa241d008,
+	0x430cb740,
+	0xc050012c,
+	0xd0080960,
+	0x0a04aa41,
+	0xa241d008,
+	0x9a45fdb4,
+	0xc00075c0,
+	0xb7209322,
+	0xd2a4430c,
+	0xb784590c,
+	0xc10179ad,
+	0xb5840244,
+	0xb78079ad,
+	0xb71f430c,
+	0x02087b6c,
+	0x0a40c09c,
+	0xa901f208,
+	0x0524c101,
+	0xa102f208,
+	0xc0007740,
+	0xb7809242,
+	0x9ea2430c,
+	0x0a3cc0a2,
+	0x0d20c0a4,
+	0xa901d208,
+	0xaa41d010,
+	0x0a027088,
+	0x4828b354,
+	0xb7009ea5,
+	0xb7814314,
+	0x1a105dcc,
+	0xc0007502,
+	0xb78c9132,
+	0x7500534a,
+	0x9082c000,
+	0x76ccb7a4,
+	0x560cb740,
+	0x7bf4b75f,
+	0x7c6cb77f,
+	0xa8c5c220,
+	0xb7209e44,
+	0x00925314,
+	0x0a50c096,
+	0x0090c101,
+	0x532bb72a,
+	0xa8cac810,
+	0xa902d208,
+	0xaa61d008,
+	0x040cc101,
+	0x4c50b70a,
+	0xc1017500,
+	0x01031492,
+	0x9e699eb3,
+	0xd0010a02,
+	0xcffe0a42,
+	0x018b2cfc,
+	0xa219a01e,
+	0xfdf4a395,
+	0x75c098ed,
+	0x9042c001,
+	0x4314b720,
+	0x7b74b7ff,
+	0x9eb39d0b,
+	0x04f2d010,
+	0xb7290992,
+	0xcfe86fad,
+	0xd0320971,
+	0x02126919,
+	0xc1380522,
+	0xd0100d20,
+	0x0242a952,
+	0x0244c101,
+	0x5a08c200,
+	0x00c3d120,
+	0x70d5b749,
+	0x99f1fd14,
+	0x430cb720,
+	0x5733b743,
+	0xc0067680,
+	0xb7839184,
+	0x87825ead,
+	0x75020902,
+	0x87b2e00a,
+	0x75049d60,
+	0x0922d001,
+	0x0a027508,
+	0x0a42d001,
+	0xd0407400,
+	0xc0003128,
+	0x9e5490a2,
+	0x90e0c000,
+	0x0a069dc0,
+	0xd0017600,
+	0xc0010a42,
+	0xc200853e,
+	0x0e825a08,
+	0x8500cfc0,
+	0x58ecb59f,
+	0x4018b960,
+	0x2e5ed3f1,
+	0xd0117506,
+	0xc00012da,
+	0xb73f90c2,
+	0x9d1d756c,
+	0xb73faae1,
+	0x9d1e75f4,
+	0xb75fa9e1,
+	0x9d2d776c,
+	0xb75fa9e2,
+	0xb72058f4,
+	0xd0104314,
+	0x042a045a,
+	0xd0100400,
+	0xd1200482,
+	0xb7230083,
+	0xb78357ab,
+	0x9e9a7bcb,
+	0xc03e9d48,
+	0x12422d7c,
+	0x0244c101,
+	0x7bcbb583,
+	0x4314b720,
+	0x59084904,
+	0x0482d010,
+	0x0083d120,
+	0x012ac101,
+	0x7dcbb783,
+	0x5dabb723,
+	0x0124d020,
+	0x12429d4b,
+	0x59a921b4,
+	0xb5830246,
+	0xb7207dcb,
+	0x010b4314,
+	0x297cc03e,
+	0x0482d010,
+	0x0083d120,
+	0x67abb723,
+	0x7fcbb783,
+	0xc03e0787,
+	0x12422ffc,
+	0xb5830244,
+	0xb7207fcb,
+	0x9d4f430c,
+	0xc1019d7e,
+	0x00820402,
+	0xb7849ddf,
+	0xb70341ab,
+	0x215671d2,
+	0x9dfc25be,
+	0xc1015929,
+	0xc3ff1240,
+	0x02442ac0,
+	0x5da977c0,
+	0xc2800e84,
+	0xb58459d1,
+	0xc00141ab,
+	0xb72091c4,
+	0xd0104314,
+	0xd12004a2,
+	0xb7230083,
+	0xb78463ab,
+	0x124243cb,
+	0x0246c301,
+	0x43cbb584,
+	0x4314b720,
+	0x04a2d010,
+	0x0083d120,
+	0x6dabb723,
+	0x45cbb784,
+	0xc1011242,
+	0xb5840246,
+	0xb72045cb,
+	0xd0104314,
+	0xd12004a2,
+	0xb7230083,
+	0xb78477ab,
+	0x124247cb,
+	0xb5840246,
+	0xfffa47cb,
+	0xb70093e1,
+	0x9e444314,
+	0x0a38c0a2,
+	0xaa01d208,
+	0xc0007500,
+	0xd1109204,
+	0xb700060d,
+	0xc0a2560c,
+	0xd2080a20,
+	0xc200aa11,
+	0x1a04a945,
+	0xc0027088,
+	0x75c09038,
+	0x9202c001,
+	0x7b74b73f,
+	0x6c50b74d,
+	0x4490b760,
+	0x0490d010,
+	0xb729018d,
+	0xd0316fb5,
+	0xc00e6d19,
+	0xc1012cfc,
+	0xc1380120,
+	0xd0080920,
+	0xfd54a951,
+	0xb7409ad8,
+	0xb77f430c,
+	0x00b47b6c,
+	0x6fadb789,
+	0x02446a32,
+	0x0a20c138,
+	0xd208097f,
+	0xb720a111,
+	0xc00e430c,
+	0x00b20a7e,
+	0x6fadb589,
+	0x9200c000,
+	0x7b74b77f,
+	0xd010097f,
+	0xb78904b0,
+	0x6a326fad,
+	0x0240c101,
+	0x0a20c138,
+	0xa111d208,
+	0x430cb740,
+	0xb7000a7f,
+	0x9ea0560c,
+	0xc2000205,
+	0xc0a2a046,
+	0xd2080a38,
+	0x7500aa01,
+	0x92a4c000,
+	0x02059e92,
+	0x0a3cc0a2,
+	0x0d20c0a4,
+	0xa901d208,
+	0xaa41d010,
+	0xc0007088,
+	0x9eb39108,
+	0x98c7fdf4,
+	0xffa67400,
+	0xb73f9364,
+	0x0a1a6f6c,
+	0x41adb580,
+	0x430cb720,
+	0xc0a20203,
+	0xd2080a38,
+	0x7500aa01,
+	0x9044c001,
+	0x4729b76a,
+	0x46a9b74a,
+	0x4794b720,
+	0x0d069ea3,
+	0x9120c000,
+	0x5aadb780,
+	0x750c0787,
+	0x4842b327,
+	0xd051050f,
+	0x70866a29,
+	0x00c2c101,
+	0x0a22d011,
+	0xc00e0109,
+	0xffff297c,
+	0x768091f4,
+	0x9162c000,
+	0x4488b780,
+	0x478cb740,
+	0x02446a52,
+	0xf2480906,
+	0x9e72a115,
+	0x0a02c002,
+	0x0900c021,
+	0xf0009dad,
+	0xc002a261,
+	0x9dad1a00,
+	0xa261f000,
+	0x430cb740,
+	0xc2000a86,
+	0xc13652b8,
+	0xd0080924,
+	0x0a7fa942,
+	0x9e50424a,
+	0xd0082240,
+	0xfdf4a241,
+	0xd3f298a5,
+	0xfd7429de,
+	0xb79f99f8,
+	0xb7bf67ee,
+	0xb7df686e,
+	0xb7ff68ee,
+	0xcfe6696e,
+	0x9c228461,
+	0xfcd4a605,
+	0xc0219a45,
+	0x09060a02,
+	0x0a00c010,
+	0xf0009dcd,
+	0x0d82a161,
+	0x9baafcf4,
+	0xfcd40d8a,
+	0x09029a41,
+	0x0a02c021,
+	0x438cb540,
+	0x0a00c020,
+	0xf0009dcd,
+	0xc01ca161,
+	0x9d4d0a40,
+	0xc021aa61,
+	0xc00f0a82,
+	0xb5802a7e,
+	0xc004450c,
+	0x9d5d0ae0,
+	0x2afcaae1,
+	0xfd349eab,
+	0xb7809bbc,
+	0xb9604e0c,
+	0xd2084038,
+	0xc146a281,
+	0xffff0a20,
+	0xc0219381,
+	0xc0060a02,
+	0x9d4d0a50,
+	0x7d1eaa61,
+	0x92c2c000,
+	0x0a02c021,
+	0x0a40c006,
+	0xa9629d4d,
+	0xc008090a,
+	0x9dcd0a40,
+	0xa161f000,
+	0xc00076bf,
+	0xc00c90e2,
+	0x9dcd1a70,
+	0xa162f000,
+	0x0a02c401,
+	0x0902c021,
+	0x0a00cff0,
+	0x9dad0920,
+	0xa261f000,
+	0x578cb720,
+	0xb7400a02,
+	0x9ea34a14,
+	0x4588b580,
+	0x4688b580,
+	0x018928e1,
+	0xc03c851a,
+	0xc0580ac2,
+	0xc01c0802,
+	0xc0140c02,
+	0xb9600c82,
+	0xd3f14058,
+	0xf0102d3e,
+	0x7480a147,
+	0xa141d010,
+	0x90e4c000,
+	0xf1d09e4b,
+	0xc000a0dd,
+	0xf1d09240,
+	0x7482aa49,
+	0x02460a1c,
+	0xf1d02a61,
+	0xb303a25d,
+	0xc0004822,
+	0x749290c2,
+	0xb303018b,
+	0x0d844432,
+	0xffff0d50,
+	0xc0219001,
+	0x0a820a02,
+	0x0a10c010,
+	0xf0009dcd,
+	0x0a10a2e1,
+	0xf0009dcd,
+	0x090aa2e1,
+	0x0a30c104,
+	0xf0009dcd,
+	0xc123a161,
+	0xc5660952,
+	0xcefa0960,
+	0x9dcd0a31,
+	0xa161f000,
+	0x99fffcd4,
+	0x0926c829,
+	0x0900cc3e,
+	0xaa41f008,
+	0xc0007500,
+	0x0a0490a2,
+	0xa241f008,
+	0x9b06fd94,
+	0xfcd49eab,
+	0x000b998d,
+	0x7f6eb79f,
+	0x7feeb7bf,
+	0x9c228c40,
+	0x4314b720,
+	0xd0109e9a,
+	0xb78c0494,
+	0x75004829,
+	0x9342c000,
+	0x6f4db746,
+	0xc0c89e4c,
+	0xd2080a48,
+	0x0908aa01,
+	0x7104d010,
+	0x6f4db586,
+	0x430cb720,
+	0x550cb780,
+	0x6f2db746,
+	0xaa65c040,
+	0x7104d012,
+	0x6f2db586,
+	0x430cb700,
+	0x6f2cb706,
+	0xa6059c22,
+	0x430cb7a0,
+	0x9e9d0d86,
+	0x98e8fed4,
+	0xb506008b,
+	0xb7206f2d,
+	0xd0104314,
+	0xb78c049a,
+	0x75004829,
+	0x9082c001,
+	0x6f4db786,
+	0xc0c89e4a,
+	0xd0080948,
+	0x0a08a941,
+	0x7104d010,
+	0x6f4db586,
+	0x430cb720,
+	0x550cb740,
+	0xb7869e6b,
+	0xc0206f2d,
+	0xd012a965,
+	0xb5867088,
+	0xb7206f2d,
+	0x0908430c,
+	0x6f2db786,
+	0x7104d010,
+	0x6f2db586,
+	0x4314b760,
+	0xc0d60986,
+	0xfeb40de0,
+	0xb7209a4c,
+	0xb786430c,
+	0xb58d6f2d,
+	0xb7004aab,
+	0xb706430c,
+	0xb79f6f2c,
+	0xb7bf7f6e,
+	0x8c407fee,
+	0xa61d9c22,
+	0x8420c002,
+	0x430cb7e0,
+	0xaa41d810,
+	0xa945d810,
+	0x9eb9008f,
+	0xb7419e55,
+	0xb57f5e35,
+	0xb7267c6c,
+	0x024469d5,
+	0x00897684,
+	0x7d74b53f,
+	0xcffe9e5e,
+	0xf20828fc,
+	0xc000a932,
+	0x9eb99244,
+	0x5a4bb78d,
+	0x6dcdb746,
+	0x0629d110,
+	0x5a4bb58d,
+	0xaa35f208,
+	0xb5460128,
+	0xc0006dcd,
+	0x9eb99120,
+	0x5a53b54d,
+	0xaa35f208,
+	0x6dcdb586,
+	0xf2489eb9,
+	0xb786a9a1,
+	0xb7466fcd,
+	0xb746704d,
+	0x02466ed5,
+	0x6fcdb586,
+	0xa9a5f248,
+	0x6f4db786,
+	0x5ad5b766,
+	0xb5460126,
+	0xda08704d,
+	0x0242a925,
+	0x6f4db586,
+	0x0524c101,
+	0x6ed5b546,
+	0xa931f208,
+	0xaa35f208,
+	0x5905d0a4,
+	0x02440183,
+	0x05b8c101,
+	0x5ad5b566,
+	0xaa39da08,
+	0xa9beda08,
+	0x05b8c101,
+	0xc07405b4,
+	0x008f9b19,
+	0x69adb786,
+	0x6d2bb74c,
+	0x09040240,
+	0x69adb586,
+	0x6d2bb54c,
+	0x448cb780,
+	0x4314b720,
+	0xc0007500,
+	0x010990a4,
+	0x9180c000,
+	0x0902008b,
+	0x4030b960,
+	0x54a9b780,
+	0x01280884,
+	0x9381ffff,
+	0x614bb54d,
+	0xf2089eb9,
+	0xb786a935,
+	0xf2085dcd,
+	0xb766a932,
+	0x1244564d,
+	0x1244c101,
+	0x5dcdb586,
+	0x69d5b726,
+	0xb53f74c4,
+	0xc0167cf4,
+	0x008f91e2,
+	0x71abb78c,
+	0xc0167500,
+	0xb7a09124,
+	0xf2084314,
+	0xf208a925,
+	0x048baa29,
+	0x4ccdb766,
+	0x6dd3b7cc,
+	0xd1a40244,
+	0x9eb75985,
+	0x01c7d120,
+	0x2ffccffe,
+	0x9ac3c074,
+	0x6e65d171,
+	0x5c88d322,
+	0x024ec101,
+	0x5a08c200,
+	0x024ac101,
+	0xc101a01d,
+	0xc0e6009a,
+	0xd2480a60,
+	0xb746ab0d,
+	0x048b682d,
+	0x5a4bb76d,
+	0x5c53b74d,
+	0x6d53b72c,
+	0xba12112c,
+	0xa0924003,
+	0x682db546,
+	0x9e69a892,
+	0x066cd010,
+	0xa11a1514,
+	0xb72d9e9b,
+	0xc101612b,
+	0xba1b024a,
+	0xc12a4003,
+	0x76c00a40,
+	0xaa99da08,
+	0x7decb53f,
+	0x917cc001,
+	0xb786048b,
+	0x75006dcd,
+	0x90bcc001,
+	0x05b9d110,
+	0xc0745da0,
+	0x75409a87,
+	0x90a4c000,
+	0xc0000101,
+	0x025a90e0,
+	0x0240024a,
+	0x590bc200,
+	0x066cd010,
+	0xc1017580,
+	0xc12a024a,
+	0xda080a40,
+	0xc000a119,
+	0x028190a4,
+	0x90e0c000,
+	0x02400200,
+	0xc200024c,
+	0xc00e5a8b,
+	0xc810097e,
+	0xd1717144,
+	0x9e696e65,
+	0x01cec101,
+	0x5a08c180,
+	0x024ac101,
+	0x0a60c0e6,
+	0xa10dd248,
+	0x7df4b73f,
+	0x5433b74d,
+	0x76400a02,
+	0x0a42d002,
+	0x692db746,
+	0x0244c101,
+	0x012aa91e,
+	0x692db546,
+	0xb58d7680,
+	0xc000542b,
+	0xb7869122,
+	0x9e494cad,
+	0x70481a04,
+	0x9326c000,
+	0x04ecd010,
+	0xb74d048b,
+	0xc1015c4b,
+	0xb72e009a,
+	0x02365f2b,
+	0x024ac101,
+	0xc1140904,
+	0x0d060a20,
+	0xda08a116,
+	0xb54da091,
+	0xc0045c4b,
+	0x9e6990e0,
+	0x6dadb746,
+	0xc0007480,
+	0x0a169204,
+	0x7b6cb59f,
+	0x7becb55f,
+	0x5c2bb78d,
+	0xa0960c86,
+	0xb58d0a04,
+	0xc0005c2b,
+	0x0a029100,
+	0x7b6cb55f,
+	0x7becb59f,
+	0xb79fa215,
+	0xb75f7d6c,
+	0x11a87cec,
+	0x4002ba1b,
+	0x0a4ec002,
+	0x70c8cc10,
+	0x1a4cc002,
+	0x70c8cc12,
+	0x5d0cb780,
+	0x4002ba1b,
+	0xc84001b6,
+	0xe0b2a9e5,
+	0xba1b8d80,
+	0xff744002,
+	0xa99d9999,
+	0x8d80e0b2,
+	0x99c5ff74,
+	0x8d80e0b2,
+	0x99adfe74,
+	0xc0120a16,
+	0xd1717008,
+	0xcffe6e65,
+	0xc101287c,
+	0x0248024e,
+	0x024ac101,
+	0xc1140289,
+	0xda080aa0,
+	0x7580ab31,
+	0x9142c000,
+	0x01ecd020,
+	0x0d88098e,
+	0x05b0c101,
+	0x99cac074,
+	0x6de5d172,
+	0x5c88d322,
+	0x05b605be,
+	0xda0805ba,
+	0xc101a031,
+	0xc114009a,
+	0xd8100da0,
+	0xb787a9f2,
+	0x048b4ead,
+	0x5a4bb76c,
+	0x05b8c101,
+	0x15bcc101,
+	0xcc129e9a,
+	0xd01072c4,
+	0xc18006ec,
+	0xb5675a05,
+	0xc1014eb5,
+	0xc10102da,
+	0xc07405b8,
+	0x008b999e,
+	0x5f2bb50e,
+	0x6e65d171,
+	0x5d8cc300,
+	0x024ec101,
+	0x5a08c200,
+	0x00cac101,
+	0x502db7a7,
+	0xc0d205d6,
+	0xc00f0da0,
+	0x018b2afe,
+	0x98d7ff74,
+	0x7640a896,
+	0x93e4c000,
+	0x6e69d091,
+	0x4038b960,
+	0x0659d110,
+	0xc12c9ea2,
+	0xf0100d70,
+	0xf090aa41,
+	0xf010a949,
+	0xf090a245,
+	0x1d10a14d,
+	0x92e1ffff,
+	0x6ce9d091,
+	0x009ac101,
+	0x612db5a9,
+	0xb549a91d,
+	0xd171582d,
+	0xa91d6e65,
+	0x024ec101,
+	0x5a08c200,
+	0x00cac101,
+	0x502db787,
+	0x297ec00f,
+	0xcff1a99d,
+	0x32442a00,
+	0xb587058b,
+	0xc0d2502d,
+	0xff740de0,
+	0xa91a98cf,
+	0xc0027680,
+	0x9e69917c,
+	0x682bb74d,
+	0x5a2bb78c,
+	0xa9116244,
+	0x75080244,
+	0x901cc002,
+	0x0a040205,
+	0x75062a0c,
+	0x9344c001,
+	0x9e510a18,
+	0x7102d010,
+	0x6d69d091,
+	0x4002ba24,
+	0x0555d110,
+	0x75020982,
+	0xd0109e92,
+	0x9e9b19c2,
+	0x0d30c130,
+	0x4418b333,
+	0x9140c000,
+	0xaa41f010,
+	0xa959f150,
+	0x01b80d10,
+	0x05b4c101,
+	0x9301ffff,
+	0xd01074c0,
+	0xc00004ec,
+	0xc1019184,
+	0xc12a021a,
+	0xc0100a40,
+	0xda080902,
+	0xc000a111,
+	0xc1019160,
+	0x5da0029a,
+	0x0ac0c12a,
+	0x9903c074,
+	0xa031da08,
+	0xb7869eb9,
+	0x7502564d,
+	0x9184c007,
+	0x430cb7a0,
+	0xb7cc0a10,
+	0x008b6d4b,
+	0x652bb74c,
+	0x6f2db726,
+	0xd00374ae,
+	0x61441a44,
+	0xd0137044,
+	0xc0001124,
+	0x9ea99146,
+	0x4ccdb786,
+	0x70480228,
+	0xd0030902,
+	0x9ea90922,
+	0x674bb78c,
+	0x6dd3b7ac,
+	0xc0067500,
+	0x74809124,
+	0x9222c003,
+	0x6f53b76c,
+	0xc00276c0,
+	0xb7669324,
+	0xb746704d,
+	0xb7866fd5,
+	0xd110644d,
+	0x02480527,
+	0xc0027104,
+	0xd05191a8,
+	0x70c86e29,
+	0x9114c002,
+	0x6ecdb786,
+	0x6917d051,
+	0x71046a52,
+	0x9006c002,
+	0x7c4bb78c,
+	0xc0c8010b,
+	0xd0080938,
+	0x0a08a941,
+	0x19149ea2,
+	0x2d7ccffe,
+	0x72950a06,
+	0x6ecbb58c,
+	0x704bb58c,
+	0x90f6c000,
+	0x0e28d011,
+	0xcffe9ea2,
+	0xb79f2d7c,
+	0x9e52786a,
+	0x2a7ccffe,
+	0x00ca0248,
+	0x7c2bb72d,
+	0x0992d011,
+	0x7086cc12,
+	0x430cb740,
+	0xc0c80205,
+	0xd2080a48,
+	0xcc10aa01,
+	0xc0c870c8,
+	0xd0080944,
+	0xcc12aa41,
+	0xba1b70c8,
+	0xfe744002,
+	0x008b98c7,
+	0x472bb50d,
+	0x7c2bb50c,
+	0xb7469ea9,
+	0xb7866455,
+	0xb7666fcd,
+	0xd010704d,
+	0x02460524,
+	0x0124c101,
+	0xc2000244,
+	0xb5865a09,
+	0xc002644d,
+	0x008b92e0,
+	0x702bb78c,
+	0xc0027500,
+	0xd2a29222,
+	0x9ea95c88,
+	0xb766009a,
+	0xb76c5cb5,
+	0xc0745a4b,
+	0x008b985b,
+	0xb766600d,
+	0xc0005aad,
+	0xb74d5a08,
+	0x70c84733,
+	0x91fcc000,
+	0x04dad010,
+	0xb72c009a,
+	0x08a0742b,
+	0xc0017293,
+	0xd0119036,
+	0xc0000e22,
+	0x02009340,
+	0xc00070c8,
+	0x9ea99336,
+	0x6bcdb786,
+	0x514db746,
+	0x71040238,
+	0x9216c000,
+	0x04dad010,
+	0xb72c009a,
+	0x1890742b,
+	0xc0007293,
+	0xd01190fc,
+	0x9ea21e22,
+	0x2d7ccffe,
+	0xc0c8020b,
+	0xd2080a48,
+	0x9e52aa01,
+	0x7088d010,
+	0xc0c8010b,
+	0xd0080944,
+	0xd012a941,
+	0x008b7104,
+	0x472bb58d,
+	0x7beeb79f,
+	0x7c6eb7bf,
+	0x7ceeb7df,
+	0x7d6eb7ff,
+	0x8c20c004,
+	0xf0109c22,
+	0x9e5baa61,
+	0x430cb720,
+	0xc0007500,
+	0xb5869082,
+	0xd00876ad,
+	0xc01ca975,
+	0xc00074be,
+	0x020390e2,
+	0x0a64c0da,
+	0xa101d208,
+	0xa979d008,
+	0x74bec01c,
+	0x90e2c000,
+	0xc0da0203,
+	0xd2080a68,
+	0x0103a101,
+	0xc0da9e8a,
+	0x0a060940,
+	0xa241d008,
+	0x0d50c0dc,
+	0xd0101a04,
+	0xd008a241,
+	0x0203a971,
+	0x0a60c0da,
+	0xa101d208,
+	0xb7209c22,
+	0xd1104314,
+	0xb70c0497,
+	0xb78c7c4b,
+	0x75004829,
+	0x48a2b340,
+	0xc0c89e4c,
+	0xd2080a48,
+	0x9c22a801,
+	0xb7a0a60d,
+	0x9e5d4314,
+	0x058b0307,
+	0x0da0c0d8,
+	0x09b2c00e,
+	0x99affcb4,
+	0x4314b760,
+	0x0992c00a,
+	0x0dc0c0ca,
+	0x99a7fcb4,
+	0x4314b760,
+	0x0982c002,
+	0x0da0c0d6,
+	0x999ffcb4,
+	0x4314b760,
+	0xc0d409d2,
+	0xfcb40dd0,
+	0xb7609998,
+	0xc04c4314,
+	0xc0e609f2,
+	0xfcb40dd0,
+	0x058b9990,
+	0xc0c6018b,
+	0xc0040d80,
+	0xfcb40d32,
+	0x9e6899b3,
+	0xb7869e69,
+	0x097f4fac,
+	0xc001040b,
+	0x9e6c7520,
+	0x0c38c0c8,
+	0x0a64c0da,
+	0x08a0c0de,
+	0xa101d208,
+	0xb5800a22,
+	0xb7604029,
+	0x9e6b4050,
+	0x1a48d00d,
+	0x050b0c82,
+	0x443ab421,
+	0xc0da9e69,
+	0xc0da09e8,
+	0x9e4d0d60,
+	0xa161d008,
+	0x018d9d0a,
+	0x7332b56c,
+	0xa0c2d010,
+	0x76b4b526,
+	0xc12a040b,
+	0xc01008e0,
+	0xd0080b02,
+	0x9e44a961,
+	0xc0da9e68,
+	0xd2080a6c,
+	0xd008a101,
+	0xb74daa61,
+	0xd0186fb2,
+	0x7500a9c2,
+	0xd0020a02,
+	0xc1010a42,
+	0xb58d0244,
+	0xdffc6faa,
+	0xd0127e7e,
+	0xb7400d38,
+	0xd022430c,
+	0x020505a2,
+	0x0a48c0c8,
+	0xaa01d208,
+	0xd0109e58,
+	0xc0c87008,
+	0xd0080944,
+	0xd012a941,
+	0x0c847104,
+	0xb59a7644,
+	0xb5c0462b,
+	0xb5a0402b,
+	0x0984412b,
+	0x08880c04,
+	0x9124fffe,
+	0x430cb720,
+	0x652bb78c,
+	0xc000752a,
+	0x9e699112,
+	0xb58d0a16,
+	0xc0007b2b,
+	0x9e6890a0,
+	0x7b32b52d,
+	0x0d029e69,
+	0x50b5b766,
+	0x4e2db766,
+	0x9883fe94,
+	0x287ccffe,
+	0xc0100a7a,
+	0x1a747008,
+	0x7008c012,
+	0xb50e9e69,
+	0xfe745bab,
+	0x9e6899e4,
+	0xb78c9e6a,
+	0xc0dc65aa,
+	0x75000960,
+	0xd0010a02,
+	0xb5800a42,
+	0xc006448c,
+	0xd0080a02,
+	0xb720a241,
+	0xb781430c,
+	0x75045ead,
+	0x93c4c000,
+	0x5f35b761,
+	0x4e2cb7a6,
+	0x0992c006,
+	0xd1320d02,
+	0xb5a761d7,
+	0xc0024e2c,
+	0xfe340dc8,
+	0x9e699810,
+	0xb746000a,
+	0xb5074e2d,
+	0x02244e2d,
+	0x7100d010,
+	0x7088c812,
+	0x4e2db547,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0xfe5d8c60,
+	0xa60d9020,
+	0x430cb7a0,
+	0x07079e9d,
+	0x030b008b,
+	0x712bb78c,
+	0x0b40c0da,
+	0xa941d208,
+	0x31c6e000,
+	0xd0020a02,
+	0x74800a42,
+	0x6db3b54c,
+	0x712bb58c,
+	0x71b3b5ac,
+	0x90e2c000,
+	0x99e9fe74,
+	0xd2080a02,
+	0x7786a241,
+	0x92d2c001,
+	0x5d08d326,
+	0xe0508520,
+	0x94298044,
+	0x94059428,
+	0x0d829401,
+	0x90e0c001,
+	0xb78c008b,
+	0xb5ac5b2b,
+	0x75007133,
+	0x9162c000,
+	0x430cb720,
+	0x67adb784,
+	0xc0007502,
+	0xc0009204,
+	0x9ea99100,
+	0x684bb78d,
+	0xc0007500,
+	0x008b9104,
+	0x632bb78d,
+	0xb58d1a04,
+	0xff34632b,
+	0x0d869b39,
+	0x90a0c000,
+	0x98aaff54,
+	0xff340d8a,
+	0x9e8599c1,
+	0x430cb720,
+	0x02039e6a,
+	0x0a48c0c8,
+	0xaa01d208,
+	0x7088d010,
+	0xc0c80103,
+	0xd0080944,
+	0xcc12a941,
+	0x9ea97104,
+	0xb74c0207,
+	0xcffe694b,
+	0x9e9a2a7c,
+	0xb58d7480,
+	0xb58d7ccb,
+	0xc0017c4b,
+	0x020b91a2,
+	0x0a1cc0ca,
+	0xaa01d208,
+	0xc0017299,
+	0x020390bc,
+	0x0a1cc0a4,
+	0xa901d208,
+	0xc0007482,
+	0xb78a93b4,
+	0x71044629,
+	0x9304c000,
+	0x52abb78a,
+	0xc0ca010b,
+	0x0a040918,
+	0x52abb58a,
+	0x430cb720,
+	0xa941d008,
+	0x52abb78a,
+	0x4002ba24,
+	0xc0007104,
+	0x1205911c,
+	0x9060c000,
+	0xb58a0a02,
+	0x9e5052ab,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0x9c228c60,
+	0x8420a61d,
+	0x4314b7a0,
+	0x00b6a19d,
+	0xb78c040b,
+	0xc10171ca,
+	0x9e5b009a,
+	0xb7cd7500,
+	0xb76c7c2b,
+	0xb72c6dd2,
+	0xc0005a4a,
+	0xb7869184,
+	0x7502714c,
+	0x91b2c000,
+	0x634ab78d,
+	0xc0007502,
+	0x048b9112,
+	0x564db786,
+	0xc0087504,
+	0x040b92a4,
+	0x564cb786,
+	0xc0007502,
+	0x750490f4,
+	0x9184c008,
+	0x9360c005,
+	0xc00074c0,
+	0x9e6991c4,
+	0x5dadb786,
+	0x7c2bb7cc,
+	0xd00e7500,
+	0xc0070a62,
+	0xc007935c,
+	0x048b9360,
+	0x704bb78c,
+	0xc0007500,
+	0xb7cd90c2,
+	0xc0014753,
+	0x040b93e0,
+	0x5dccb786,
+	0xd00e7500,
+	0xc0010a62,
+	0xba1b929c,
+	0xff544003,
+	0xb72099b1,
+	0x9e82430c,
+	0x5e2db781,
+	0xc0007508,
+	0xb7819344,
+	0x1a045ead,
+	0xc0007502,
+	0xcffe9292,
+	0xd0d12d7c,
+	0x9e510964,
+	0x7044c810,
+	0xb78d048b,
+	0xba247b4b,
+	0x12684002,
+	0x7088c812,
+	0xc0009e96,
+	0x040b9220,
+	0x7b4ab74d,
+	0x2d7ccffe,
+	0xba129e51,
+	0x02644002,
+	0x7048d010,
+	0xd0121164,
+	0x9ea67104,
+	0x2f7ccffe,
+	0x430cb720,
+	0xb78c048b,
+	0xb741654b,
+	0x0b9a5e2d,
+	0xd009752a,
+	0x74881bf6,
+	0x92c4c000,
+	0x5eadb781,
+	0x75021a04,
+	0x9212c000,
+	0x7c4bb78c,
+	0x03fed020,
+	0xd019753c,
+	0xb374027e,
+	0xd0194434,
+	0x0389024e,
+	0x9060c000,
+	0x040b9ebf,
+	0x4e4cb7a7,
+	0xc0017540,
+	0xb72c9222,
+	0xa09a5a52,
+	0x6d4ab76c,
+	0xc2009e4c,
+	0x70c85a0d,
+	0x90d4c001,
+	0x402db743,
+	0x5a0cc100,
+	0xc000710a,
+	0xd1a493f4,
+	0xc1015985,
+	0xc05405b4,
+	0xa919994e,
+	0x700a6005,
+	0x9286c000,
+	0xb74c040b,
+	0xd0117c4a,
+	0x9ea60e68,
+	0xcffe7184,
+	0xc0002f7c,
+	0xc00290d2,
+	0xc0000fca,
+	0x126490a0,
+	0x0bc4d0d2,
+	0x9e739e69,
+	0x7c2bb74c,
+	0x0675d110,
+	0x70c8d010,
+	0xc002112e,
+	0x040b9180,
+	0x5e4cb781,
+	0xc0027508,
+	0xb78d9162,
+	0xb7465a4a,
+	0xb74c6dcc,
+	0xba246d52,
+	0xe0004002,
+	0xc10103c4,
+	0xc0011194,
+	0x74c093a2,
+	0x9342c001,
+	0x5dd4b766,
+	0xcc120f06,
+	0xc18072cc,
+	0xc1015a05,
+	0xc05405b8,
+	0x9e82990a,
+	0x4002ba2e,
+	0x018b9ebb,
+	0x9916fe54,
+	0x6a67d011,
+	0xc2000208,
+	0x9ea25a0b,
+	0x2d7ccffe,
+	0xc000729d,
+	0x700c91e4,
+	0x9182c000,
+	0x0a7ecffe,
+	0xb346700c,
+	0xd110444a,
+	0x9ea2066d,
+	0x2d7ccffe,
+	0x9e539e69,
+	0x7c2bb74c,
+	0x0a26d011,
+	0x70c8d010,
+	0xd012190c,
+	0x03097104,
+	0x2b7ccffe,
+	0x430cb760,
+	0xc0c80207,
+	0xd2080a48,
+	0xd010aa01,
+	0x01077188,
+	0x0944c0c8,
+	0xa941d008,
+	0x7104d012,
+	0x040baa9d,
+	0x64ccb746,
+	0x00bad020,
+	0xb74c0009,
+	0xcffe4851,
+	0x00da287c,
+	0x009ac101,
+	0x76800120,
+	0x64ccb546,
+	0x7c2bb50d,
+	0x90e4c000,
+	0x4949b78c,
+	0xc0007500,
+	0x020790e2,
+	0x0a48c0c8,
+	0xa801d208,
+	0x7deeb79f,
+	0x7e6eb7bf,
+	0x7eeeb7df,
+	0x7f6eb7ff,
+	0x8c20c002,
+	0xa61d9c22,
+	0x4314b7c0,
+	0x07850287,
+	0x9e769e71,
+	0x712bb78c,
+	0x0b40c0da,
+	0x04a4d010,
+	0xa941d208,
+	0x009cc101,
+	0x3246e000,
+	0x742bb7ec,
+	0x9e710a02,
+	0x0a42d002,
+	0xb58c7480,
+	0x0687712b,
+	0x71abb56c,
+	0x6db3b54c,
+	0x90e2c000,
+	0x9bc1fe54,
+	0xd2080a02,
+	0x7746a241,
+	0x92d2c001,
+	0x5d08d2a6,
+	0xe0508520,
+	0x94298044,
+	0x94059428,
+	0x0d829401,
+	0x90e0c001,
+	0xb78c9e71,
+	0xb5ac5b2b,
+	0x7500712b,
+	0x9162c000,
+	0x430cb720,
+	0x67adb784,
+	0xc0007502,
+	0xc0009204,
+	0x9e719100,
+	0x682bb78d,
+	0xc0007500,
+	0x9e719104,
+	0x632bb78d,
+	0xb58d1a04,
+	0xff34632b,
+	0x0d869911,
+	0x90a0c000,
+	0x9a82ff34,
+	0xff140d8a,
+	0x02819b99,
+	0x4314b7a0,
+	0xc0c89e6c,
+	0xd2080a48,
+	0xd010aa01,
+	0x9e6a7148,
+	0x0944c0c8,
+	0xa941d008,
+	0x7104d012,
+	0xba349e69,
+	0xb7464002,
+	0x7482712d,
+	0x9172c003,
+	0x632bb78d,
+	0xc0037502,
+	0xc00390d2,
+	0x9e6992c0,
+	0x6cadb766,
+	0x90a0c000,
+	0xb7669e69,
+	0x9e696bad,
+	0x5e2db781,
+	0xc0007502,
+	0x76809124,
+	0x90c4c000,
+	0x50adb746,
+	0x9060c000,
+	0x11340902,
+	0xcc120a02,
+	0x9e697088,
+	0xb78c9e9b,
+	0xb7466dab,
+	0xb766562d,
+	0xc2004fad,
+	0xc1015a08,
+	0x748200ca,
+	0x5b35b746,
+	0x9172c002,
+	0xb7869e69,
+	0x75005dad,
+	0x92dac000,
+	0x4e2db746,
+	0xc0007295,
+	0x7540923a,
+	0x90e2c000,
+	0x5a07c180,
+	0xc00072d9,
+	0xc10090fc,
+	0x71485a07,
+	0x9094c000,
+	0x4002ba37,
+	0xb78c9e69,
+	0x752a652b,
+	0x9152c000,
+	0x0a78d011,
+	0x7188d010,
+	0x1978d011,
+	0x9160c000,
+	0xb74d9e69,
+	0xba127b2b,
+	0x02744002,
+	0x7188d010,
+	0xd0121174,
+	0xba347104,
+	0xc0004002,
+	0x9e699280,
+	0xb7860902,
+	0xb7466c2d,
+	0xc1016bb5,
+	0xd4121244,
+	0xfe347088,
+	0xf0129aab,
+	0xfffc0900,
+	0xfffc9204,
+	0x9e6c9260,
+	0x0a48c0c8,
+	0xaa81d208,
+	0x718ad410,
+	0xaa1dd3e8,
+	0x7148d412,
+	0x4002ba2d,
+	0x058f018b,
+	0x9be8fe34,
+	0x0a029e71,
+	0x6dadb586,
+	0x5a2bb58d,
+	0x7c2bb50c,
+	0x430cb740,
+	0x2afccffe,
+	0xc0c80205,
+	0xd2080a48,
+	0xd410aa01,
+	0xc0c87148,
+	0xd0080944,
+	0xd412aa41,
+	0x000b7148,
+	0x7e6eb79f,
+	0x7eeeb7bf,
+	0x7f6eb7df,
+	0x7feeb7ff,
+	0x8c00c002,
+	0xa61d9c22,
+	0xb7808460,
+	0x09024d8c,
+	0x4038b960,
+	0xa101d208,
+	0xa105d208,
+	0x0a20c146,
+	0x9341ffff,
+	0x0882c021,
+	0x08d0c006,
+	0xaa619d1d,
+	0x2a7cc00e,
+	0xc0007506,
+	0x0d8a90f2,
+	0x9bd0fcf4,
+	0x9240ffff,
+	0x0902c021,
+	0x0940c006,
+	0xab629d2d,
+	0xabe29d2d,
+	0xa9629d2d,
+	0x9d2da11a,
+	0x9e74a9e2,
+	0x478cb720,
+	0x2a00c7f0,
+	0x5aa1d224,
+	0xd011a196,
+	0x6a520e54,
+	0xd0310242,
+	0xf2080b48,
+	0x750caa41,
+	0x9204c000,
+	0x6e59d051,
+	0x498cb740,
+	0x0dc2c809,
+	0x02440d02,
+	0x0db0c5c2,
+	0xa10ef208,
+	0xa182f208,
+	0x7f80c010,
+	0x9322c003,
+	0xfcb4058b,
+	0xa91a9a23,
+	0xe0719e7b,
+	0xd1f28d00,
+	0xfd342dee,
+	0xb79f98d2,
+	0xc01c7468,
+	0xc000753e,
+	0xfcf490c4,
+	0xb51f9b9e,
+	0xb77f7468,
+	0x0d067470,
+	0xc00e55cc,
+	0xfd142dfc,
+	0x9e6c9bb1,
+	0x4c8cb720,
+	0x6a22c146,
+	0x7468b77f,
+	0x008b02c2,
+	0x5aadb723,
+	0x9ead058b,
+	0xc06ca091,
+	0x008b0ee0,
+	0x5ab5b5c3,
+	0xaba1f210,
+	0xa3a2f210,
+	0xc300a919,
+	0xb7c35d3d,
+	0xb5435bb5,
+	0xaa155bad,
+	0xc06e030b,
+	0x9e5a0b00,
+	0xabc2f208,
+	0xf2082d04,
+	0xfd14a241,
+	0x008b9867,
+	0x7470b77f,
+	0xa3a1f210,
+	0x5bb5b5c3,
+	0xa3c2f208,
+	0x0d06aa11,
+	0xc00e55cc,
+	0xb5832dfc,
+	0xfd345aad,
+	0xb7409802,
+	0xb740490c,
+	0xf0084d14,
+	0x7508aa41,
+	0x9142c000,
+	0xc0007504,
+	0xd0109144,
+	0x7500aa41,
+	0x90a2c000,
+	0xf0080886,
+	0xb760a0c1,
+	0x09504894,
+	0x0d20c146,
+	0xfffa7097,
+	0xffff9162,
+	0x058b9100,
+	0x998ffcb4,
+	0xc0017400,
+	0x9e6c9044,
+	0x4c8cb720,
+	0x6a22c146,
+	0x4c8cb740,
+	0xc06c02c2,
+	0xd2080a80,
+	0xa916a9a2,
+	0xd1a2099a,
+	0x0d845c90,
+	0x00940098,
+	0x4db5b543,
+	0x4c35b5c3,
+	0x4cb5b5e3,
+	0xb583aa19,
+	0xc0344d2d,
+	0xd2089adb,
+	0xf208a021,
+	0x7508aa41,
+	0x9124c000,
+	0xf2080886,
+	0xc000a0c1,
+	0xfcf49080,
+	0x058b9af3,
+	0x995dfcb4,
+	0x0d927400,
+	0x9324ffff,
+	0x91c0fff8,
+	0xb740a60d,
+	0x0205430c,
+	0x0a10c0a4,
+	0xaa01d208,
+	0xc0037500,
+	0x9e9292a4,
+	0x0d38c0a2,
+	0xa941d010,
+	0xc0007480,
+	0x0a0492e4,
+	0xa241d010,
+	0x430cb780,
+	0xc0a29e93,
+	0xd2080a40,
+	0xfd54a101,
+	0xb7809a5f,
+	0xc0a4430c,
+	0xd2080a10,
+	0x7500aa01,
+	0x9304c002,
+	0x430cb720,
+	0xc09c0203,
+	0xd2080a18,
+	0x7500aa01,
+	0x91c2c002,
+	0x4729b7aa,
+	0x4814b7c0,
+	0x9220c001,
+	0xaa2df210,
+	0xc000750c,
+	0x9eaa93e4,
+	0x55e80d86,
+	0x2dfcc00e,
+	0x9ad8fd14,
+	0x478cb720,
+	0x4508b780,
+	0x29ded3f2,
+	0xb58100e2,
+	0xfd9468a9,
+	0x0a029a33,
+	0xa22df210,
+	0x0a46c809,
+	0x0a30c656,
+	0xa221f210,
+	0x90c0c001,
+	0x46a9b78a,
+	0x02857148,
+	0x9124c000,
+	0xfcf40d92,
+	0xb7209a87,
+	0xb7aa430c,
+	0xb7204729,
+	0xba2d430c,
+	0xd0514000,
+	0x02036b59,
+	0xc0a20103,
+	0xc0a40a40,
+	0xd2080920,
+	0xd008a902,
+	0xd120aa41,
+	0xd01102ed,
+	0x72991952,
+	0x9386fffd,
+	0x7eeeb79f,
+	0x7f6eb7bf,
+	0x7feeb7df,
+	0x9c228c60,
+	0x8440a61d,
+	0x430cb780,
+	0x0a10c0a4,
+	0xaa01d208,
+	0xc00a7500,
+	0xfd9490a4,
+	0xb7209b00,
+	0x0203430c,
+	0x0a10c0a4,
+	0xa901d208,
+	0xc0097480,
+	0xc0069324,
+	0xd2081a78,
+	0x7500aa01,
+	0x91a2c005,
+	0xc0a40203,
+	0xb7ca0a1c,
+	0xd2084629,
+	0x9e97ab81,
+	0x1962d011,
+	0xd020627d,
+	0x068f0328,
+	0xba26110f,
+	0xa1194000,
+	0xc002a211,
+	0xb78a9000,
+	0xc10146a9,
+	0x02d8029a,
+	0x99bcc034,
+	0x0e72d011,
+	0x0aa0c0a2,
+	0x75889ea7,
+	0x4001ba3f,
+	0xa031d208,
+	0x9324c000,
+	0xba249e6c,
+	0x75044000,
+	0x9264c000,
+	0xc00075c4,
+	0xb7209204,
+	0xb78a430c,
+	0xd11046a9,
+	0x02420659,
+	0x0a20c0a2,
+	0xa911d208,
+	0xd2080904,
+	0xb720a111,
+	0xb78a430c,
+	0xf11046a9,
+	0x0e840659,
+	0x9ea20242,
+	0xc0a20109,
+	0xc0a20d20,
+	0xc000093c,
+	0xd01090c2,
+	0xd008aa51,
+	0xa911a245,
+	0x058da91a,
+	0x73d5018d,
+	0xb7200764,
+	0xfffd430c,
+	0xb78a9344,
+	0x09024729,
+	0x02189e93,
+	0x0a40c0a2,
+	0x9c8bc810,
+	0xd2080005,
+	0xc002a105,
+	0xb7209000,
+	0xb78a430c,
+	0xd11046a9,
+	0xc2000639,
+	0x00c25a08,
+	0x46adb505,
+	0x430cb720,
+	0x46a9b78a,
+	0x0096c101,
+	0xc0a20098,
+	0xb76008c0,
+	0xc00040a9,
+	0xb78b91a0,
+	0xb742534a,
+	0xb7455b2b,
+	0x624446d5,
+	0x0244c101,
+	0x46cdb585,
+	0x430cb720,
+	0xd0120136,
+	0xb78a0932,
+	0xd02046a9,
+	0xd1100022,
+	0xc2000639,
+	0x02425908,
+	0x0a20c0a2,
+	0xaa11d208,
+	0x00a2d020,
+	0x9e537106,
+	0x29fcc00e,
+	0x93b2fffe,
+	0xfffe0d84,
+	0x0d829041,
+	0x992cfd54,
+	0x430cb720,
+	0xc0a40203,
+	0xd2080a10,
+	0x7680a902,
+	0x9344c003,
+	0x1a78c006,
+	0xaa01d208,
+	0xc0037500,
+	0x020390e2,
+	0x0a1cc0a4,
+	0xaa01d208,
+	0x4629b74a,
+	0x4731b7aa,
+	0x71040705,
+	0x4001ba2d,
+	0x0d7ecfff,
+	0xcffe0189,
+	0xd0510d30,
+	0xb3236e59,
+	0x65554432,
+	0x478cb740,
+	0x0528c101,
+	0x01449e6e,
+	0x1fa2d031,
+	0x29fcc00e,
+	0x0aa2d351,
+	0x0fa6d012,
+	0xc000a195,
+	0xfd149360,
+	0xb780998f,
+	0xd3f24508,
+	0xd20829ee,
+	0xfd94a221,
+	0xc80998ed,
+	0xc6560d46,
+	0x9e7a0d30,
+	0xa166e250,
+	0x1a62d011,
+	0xe0500d02,
+	0xba34a146,
+	0x1ad04000,
+	0x430cb720,
+	0x165cd010,
+	0xd0240906,
+	0xb72a51d0,
+	0xa9154729,
+	0x2dfcc00e,
+	0x10940f04,
+	0xfffe7102,
+	0xc000931a,
+	0xfcf49080,
+	0xb7809931,
+	0x0d92430c,
+	0xc0a29ea2,
+	0xc0a40a3c,
+	0xd2080d1c,
+	0xd010a901,
+	0x7088aa41,
+	0x9226ffff,
+	0x7d6eb79f,
+	0x7deeb7bf,
+	0x7e6eb7df,
+	0x7eeeb7ff,
+	0x8c40c002,
+	0x91a0fddd,
+	0x7d6eb79f,
+	0x7deeb7bf,
+	0x7e6eb7df,
+	0x7eeeb7ff,
+	0x8c40c002,
+	0xa61d9c22,
+	0xb7c08460,
+	0xa1954314,
+	0xaae1d808,
+	0xb706040d,
+	0x9e715654,
+	0xa012048d,
+	0x6dabb72c,
+	0x7540068d,
+	0xb72da099,
+	0x9e5e5453,
+	0x0ec8c0c8,
+	0x7d74b53f,
+	0x9102c000,
+	0xaaa2d210,
+	0x7df4b5bf,
+	0x9380c000,
+	0xb76c040d,
+	0xb7866d4a,
+	0xb75f69cc,
+	0xd1a47d6c,
+	0x59085985,
+	0x05b8c101,
+	0x05b4c101,
+	0x9867c034,
+	0xaa21d210,
+	0x7008c010,
+	0x700ac012,
+	0x287ccffe,
+	0x7decb51f,
+	0xb5c69e71,
+	0xb7205aad,
+	0xb781430c,
+	0x75025e2d,
+	0x90c4c000,
+	0x9b5bfe14,
+	0x90e0c000,
+	0xc0007508,
+	0xfe3490e4,
+	0x9e839912,
+	0x90a0c000,
+	0xb766048d,
+	0x040d4e55,
+	0x5accb746,
+	0x6accb786,
+	0x6b54b746,
+	0x6bccb766,
+	0xc1011244,
+	0x01261524,
+	0x6accb586,
+	0x6b54b546,
+	0x1126c101,
+	0x6c4cb566,
+	0x0a02c201,
+	0x7088c810,
+	0x0a02ce01,
+	0x7088c812,
+	0x6bccb546,
+	0xb740a895,
+	0x7480402b,
+	0x92a4c009,
+	0x430cb7e0,
+	0xb7869eb9,
+	0x7502564d,
+	0x9024c005,
+	0x6e4bb78c,
+	0x6e4bb54c,
+	0x7d3edffc,
+	0x6f4bb58c,
+	0x9144c004,
+	0x674bb78c,
+	0xc0047500,
+	0xb76690a4,
+	0xb78c5acd,
+	0xd1a4744b,
+	0xc8025949,
+	0x0d047280,
+	0x4002ba24,
+	0x094cc002,
+	0x7104d010,
+	0x194cc002,
+	0x7104d012,
+	0x5d0cb740,
+	0x4002ba24,
+	0xca200248,
+	0xba12aa05,
+	0x9e524001,
+	0x7053b76c,
+	0xba2451e9,
+	0x62474002,
+	0xc1010936,
+	0x76c01124,
+	0x5389d224,
+	0x9084c001,
+	0x6fcbb78c,
+	0xc0027506,
+	0xb74692d4,
+	0xb7666fd5,
+	0xd051704d,
+	0x70c86e27,
+	0x90f4c000,
+	0x5c4db786,
+	0xc00073d9,
+	0x9eb89232,
+	0x5e05d3a2,
+	0x5c4cb746,
+	0xc0027104,
+	0xd0109014,
+	0xc1010624,
+	0x70c80244,
+	0x9334c001,
+	0x430cb7c0,
+	0xc0020a06,
+	0x008d09b2,
+	0x6eabb58c,
+	0x6e2bb58c,
+	0x430cb7a0,
+	0xc0de9eab,
+	0xc0dc0aa0,
+	0xd2080d80,
+	0xfc74aaa2,
+	0x9eb199a0,
+	0xb7869eb3,
+	0xb74c5acd,
+	0xd208744b,
+	0xb586a2a2,
+	0x0a02594d,
+	0x6fcbb58c,
+	0x734bb54c,
+	0x0d90c0da,
+	0xfc7409a2,
+	0xb720998c,
+	0xb781430c,
+	0x75045e2d,
+	0x9124c000,
+	0x0a049eb0,
+	0x7b4ab58d,
+	0x9060c000,
+	0x008f0f82,
+	0x5c2db786,
+	0x6d7bd012,
+	0x01280148,
+	0x0524c101,
+	0xb5465d0d,
+	0xa9195c35,
+	0x9e9b0982,
+	0xd1100224,
+	0x00870669,
+	0xc0ce9ea2,
+	0xc0000d48,
+	0xd8109120,
+	0xd831aa41,
+	0xba24a0c5,
+	0x01b84002,
+	0x040da89a,
+	0x6fcab74d,
+	0x0632d010,
+	0x71040d84,
+	0x9238ffff,
+	0xc0007640,
+	0x05839142,
+	0xcffe1d84,
+	0xba1b2dfc,
+	0xfe144002,
+	0x040d9be7,
+	0x6e4ab78c,
+	0xc0037500,
+	0xa8919002,
+	0xc0027442,
+	0xfe149384,
+	0x74009a39,
+	0x430cb720,
+	0x90c2c000,
+	0x6cadb746,
+	0x9080c000,
+	0x6badb746,
+	0x5e2db781,
+	0xc0007502,
+	0x74009124,
+	0x90c4c000,
+	0x50adb786,
+	0x9060c000,
+	0x12440a02,
+	0xd0120a82,
+	0x7500710a,
+	0x93fcc001,
+	0xb766048d,
+	0xb7664fcd,
+	0xb78d6bd5,
+	0xb746654b,
+	0xd1204e55,
+	0xb74d11b7,
+	0xc101634b,
+	0xb78d65b9,
+	0x65b563cb,
+	0x12449eaa,
+	0x65b9c101,
+	0x9845fdf4,
+	0xb786040d,
+	0x9e836acc,
+	0xc0007500,
+	0xb5a69096,
+	0x9e716acc,
+	0x6aadb786,
+	0x632bb74d,
+	0x6b35b746,
+	0x5aadb766,
+	0x0246c101,
+	0xc1011904,
+	0xb5861526,
+	0xb54d6aad,
+	0xb546632b,
+	0xfef46b35,
+	0xc0009bb3,
+	0xa89290c0,
+	0xc0017640,
+	0x040d90c2,
+	0xb77fa891,
+	0xb7867dec,
+	0xb74674cc,
+	0x7442754c,
+	0x09040246,
+	0x74ccb586,
+	0x754cb546,
+	0x9142c000,
+	0xc0007442,
+	0x74449246,
+	0x9184c007,
+	0x9300c004,
+	0xb78d040d,
+	0xb74c684a,
+	0x0a046fca,
+	0xb58d0904,
+	0xb54c684a,
+	0xaa196fca,
+	0x048d9e71,
+	0x67adb746,
+	0x6735b746,
+	0xc2000a04,
+	0xc1015a0c,
+	0xb54600cc,
+	0xb54664ad,
+	0xaa196435,
+	0x694db746,
+	0xc200040d,
+	0xd1205a08,
+	0x0a0200cd,
+	0x684db546,
+	0x694cb586,
+	0x674cb586,
+	0x67ccb586,
+	0xb780a895,
+	0x7500402b,
+	0x9344c002,
+	0x5accb746,
+	0xb546a999,
+	0xb79f5b4d,
+	0x00b67b6a,
+	0x009cc101,
+	0x742bb58c,
+	0x430cb720,
+	0x5e2db781,
+	0xc0027504,
+	0xb76690e4,
+	0x74c05dcc,
+	0x90c4c000,
+	0x0d82c010,
+	0x9080c001,
+	0xc1807086,
+	0xc0005a07,
+	0xd02091bc,
+	0x5da811a6,
+	0x05b8c101,
+	0x9a7ac014,
+	0x0800c040,
+	0x9180c000,
+	0x11b4d020,
+	0xc1015da8,
+	0xc01405b8,
+	0xc0409a6f,
+	0x10400a02,
+	0x0a02c100,
+	0x7008d010,
+	0xc4120902,
+	0x9e8b7104,
+	0xb71fa89a,
+	0x05127df4,
+	0xc0d0052c,
+	0xd8100d60,
+	0x9e49a941,
+	0x65b0d031,
+	0x02420224,
+	0x5a08c200,
+	0xc1010904,
+	0x290400cc,
+	0x612db566,
+	0xa141d810,
+	0x5f35b566,
+	0x7640a892,
+	0x9384c002,
+	0xb78d040d,
+	0x0a0468ca,
+	0x68cab58d,
+	0x9280c002,
+	0x7d6cb73f,
+	0xc0007440,
+	0xb7209282,
+	0xb781430c,
+	0x75025e2d,
+	0x91a4c000,
+	0xb746048d,
+	0xc1005acd,
+	0x02445a7d,
+	0x5a07c200,
+	0xb5860244,
+	0x040d5acd,
+	0x7b6ab73f,
+	0x5ad4b7a6,
+	0x734ab52c,
+	0x5954b5a6,
+	0x430cb7a0,
+	0xb7819ea9,
+	0x75025e4d,
+	0x92a4c000,
+	0x9904fe14,
+	0xc0007400,
+	0x9ea89204,
+	0x64cab78d,
+	0x7510c004,
+	0x9134c000,
+	0xb5a69e71,
+	0xb73f5b35,
+	0xb52c7b72,
+	0x040d7433,
+	0x714cb786,
+	0xc0007502,
+	0xb7669264,
+	0xb7665ad4,
+	0xc0144e4c,
+	0x741099f7,
+	0x915cc000,
+	0x1980d031,
+	0x5987a99a,
+	0x4002ba1b,
+	0x9a7efe14,
+	0x430cb720,
+	0x5e2db781,
+	0xc0017508,
+	0x9e719302,
+	0x712db786,
+	0xc0017502,
+	0xb7869244,
+	0x7504562d,
+	0x91a2c001,
+	0x542bb78d,
+	0xc0007500,
+	0xa89992a4,
+	0xb746048d,
+	0x58885acd,
+	0x009cc101,
+	0x5cadb726,
+	0x02125908,
+	0x70880242,
+	0x90d6c000,
+	0x09ffa99a,
+	0x9260c000,
+	0x040da899,
+	0x5accb746,
+	0xc1015888,
+	0xb726009c,
+	0x01245cad,
+	0x02420212,
+	0xc0007088,
+	0xa99a90dc,
+	0xfe140986,
+	0xa8959a41,
+	0xb5800a02,
+	0xb58040ab,
+	0xb7a040ad,
+	0x9ea9430c,
+	0x5e55b7a1,
+	0xc0037744,
+	0x774893a2,
+	0x9342c003,
+	0x75cdb786,
+	0xc0017500,
+	0xfe149284,
+	0x74009887,
+	0x91e2c000,
+	0xb78e9ea8,
+	0xb7445bca,
+	0x708867cc,
+	0xd0040a02,
+	0xb5860a42,
+	0xc00075cc,
+	0x77429380,
+	0x90a2c000,
+	0xc0007748,
+	0x008b9244,
+	0x67adb784,
+	0x4e2db746,
+	0x50b5b746,
+	0x71156245,
+	0xd00b0a02,
+	0xb5860a42,
+	0xc00075ad,
+	0x9ea990c0,
+	0xb5860a06,
+	0x9ea875cd,
+	0x75ccb786,
+	0xc0027500,
+	0xb7209062,
+	0xb781430c,
+	0x75025e2d,
+	0x91a4c008,
+	0x4e35b746,
+	0x4fadb746,
+	0x6e2fd011,
+	0xc0087088,
+	0xd0119096,
+	0x76800e2e,
+	0x4458b342,
+	0x5d0fd122,
+	0x9140c000,
+	0x5b2bb78c,
+	0xc0007500,
+	0x02249082,
+	0x59070144,
+	0x50adb786,
+	0x5a07c200,
+	0x7088c810,
+	0x6badb786,
+	0xc0007104,
+	0xa89590d6,
+	0xb5801228,
+	0xa89640ad,
+	0x40cdb740,
+	0xc0007480,
+	0x0a0691a2,
+	0x40cbb580,
+	0xd0121a04,
+	0x0a7c7088,
+	0x5a17c200,
+	0x40cdb580,
+	0x0902a916,
+	0x4314b7c0,
+	0xa141d810,
+	0x4314b7a0,
+	0xb721040b,
+	0xb7cc5e54,
+	0x76486dca,
+	0x9084c002,
+	0x5eccb781,
+	0x75021a04,
+	0x9032c001,
+	0x4e4cb7a6,
+	0xc0069e92,
+	0xb5a70992,
+	0xb7204e4c,
+	0xb721430c,
+	0x60d35f2d,
+	0x0994d0d2,
+	0x9a33fdd4,
+	0x000a9e69,
+	0x4e2db746,
+	0x4e2db507,
+	0xd0100224,
+	0xc8127100,
+	0xb5477088,
+	0xc0044e2d,
+	0x048b9100,
+	0x6ccdb786,
+	0x4fcdb7a6,
+	0xfe1412d8,
+	0x000a9864,
+	0x0a02c040,
+	0x7008c012,
+	0xb786040b,
+	0xb5074e4c,
+	0xc2004e4c,
+	0x70085a07,
+	0x9228c003,
+	0x0a06a895,
+	0x402bb580,
+	0x9160c003,
+	0xb746040b,
+	0xb74c4e54,
+	0xba2e6e4a,
+	0xd0104002,
+	0x74800624,
+	0x0244c101,
+	0x5987c200,
+	0x9144c000,
+	0x5888c280,
+	0x009ac101,
+	0x5b2db786,
+	0x70c8cc12,
+	0x76429e69,
+	0x4fb5b766,
+	0x6badb786,
+	0x1539d110,
+	0x92e4c000,
+	0x6e2fd011,
+	0xc00072d9,
+	0xd0119136,
+	0x76800e26,
+	0x4458b342,
+	0x5d8bd122,
+	0x0a02c040,
+	0x7088d012,
+	0xb587048b,
+	0xc0004e4d,
+	0xc1019080,
+	0x70860124,
+	0x91d6c000,
+	0x448cb780,
+	0xc0007500,
+	0x748090a2,
+	0x90dac000,
+	0x0a06a915,
+	0xa241d808,
+	0x992ffe14,
+	0x10010d02,
+	0xc0129e53,
+	0x74007006,
+	0x92dac000,
+	0x430cb720,
+	0x5e2db781,
+	0xc0007504,
+	0x9e6c9244,
+	0xc10100da,
+	0xc0c8009a,
+	0xb74c0a48,
+	0xd208742b,
+	0x7088aa01,
+	0x90a8c000,
+	0xda08aa15,
+	0xa816a102,
+	0x404ab780,
+	0xc0007500,
+	0x9eb390c2,
+	0xfe140992,
+	0x9e7198f3,
+	0x632bb78c,
+	0xc0007500,
+	0xa8969222,
+	0xb5800a02,
+	0xc000404b,
+	0xb7869160,
+	0xb746562d,
+	0x75024e2d,
+	0x9124fff8,
+	0x9000fff8,
+	0x7ceeb79f,
+	0x7d6eb7bf,
+	0x7deeb7df,
+	0x7e6eb7ff,
+	0x8c60c002,
+	0xa68d9c22,
+	0x02059e9d,
+	0x29fccffe,
+	0x2a7ccffe,
+	0xd1240705,
+	0xd0325941,
+	0x07876046,
+	0x5dc1c280,
+	0xd1310285,
+	0xc1016527,
+	0xd02260c7,
+	0x01145e41,
+	0x704601a8,
+	0x6426d031,
+	0x9094c000,
+	0x0804c001,
+	0x665cd031,
+	0x615fd132,
+	0x5941c180,
+	0xc1010104,
+	0xcffe0244,
+	0xcffe29fc,
+	0x02442c7c,
+	0xc10159c0,
+	0x9ea001b0,
+	0xb7bf0007,
+	0xb7df7eee,
+	0xb7ff7f6e,
+	0x8c607fee,
+	0x9e989c22,
+	0x09020802,
+	0x9140c000,
+	0x08029e98,
+	0x4530d010,
+	0x72c0cc14,
+	0x7200c014,
+	0xc18072c0,
+	0xe0095d09,
+	0xf0127204,
+	0xc0005d04,
+	0x72c49254,
+	0x0804d004,
+	0x15b4d024,
+	0xd00472c0,
+	0xd0240802,
+	0xe00015b0,
+	0x11813124,
+	0x442ab330,
+	0x72c09c22,
+	0xffff0886,
+	0xc40293a6,
+	0xd06572c0,
+	0xd0652c9e,
+	0xc8023c9e,
+	0xd0657200,
+	0xd0652d2e,
+	0xe0003d2e,
+	0x9e531514,
+	0x5408d01a,
+	0x50acd01a,
+	0xd01472c0,
+	0xd0240002,
+	0xe08015b0,
+	0x5c055885,
+	0x9304ffff,
+	0x3124e000,
+	0xb3301181,
+	0x9c22442a,
+	0x9d3a9e64,
+	0x0e46c809,
+	0x1e06b09b,
+	0x9dc39ea4,
+	0xe0009e58,
+	0x15873400,
+	0x482ab330,
+	0x9e649c22,
+	0x0e46c809,
+	0x1d66b09b,
+	0x9e589ea4,
+	0x00009c22,
+	0x87c2c809,
+	0x0e60b060,
+	0x87c2c809,
+	0x0b80b060,
+	0x87c2c809,
+	0x0ac0b060,
+};
+
+unsigned int all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_data[] = {
+	0x00000000,
+	0x00000000,
+	0x0000ff00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x809000b0,
+	0x809198c8,
+	0x8288f08a,
+	0x8288f10c,
+	0x8288f1e0,
+	0x8288f2a8,
+	0x8288f2b4,
+	0x8288f214,
+	0x8288f208,
+	0x8288f1e8,
+	0x8288f2c8,
+	0x8288f1ec,
+	0x8288f1f0,
+	0x8288f2d0,
+	0x8288f2d8,
+	0x8288fd1c,
+	0x8288f998,
+	0x8288f7e4,
+	0x8288f7e7,
+	0x8288fd1e,
+	0x82899618,
+	0x82899620,
+	0x82899624,
+	0x82899626,
+	0x8289962a,
+	0x8289962e,
+	0x82899632,
+	0x82899636,
+	0x8289963a,
+	0x82899640,
+	0x828996a0,
+	0x828996a8,
+	0x828996ac,
+	0x828996b0,
+	0x828996b4,
+	0x828996bc,
+	0x828996c7,
+	0x8289c35b,
+	0x8289c350,
+	0x8289c360,
+	0x8288efa8,
+	0x8288f012,
+	0x8288f022,
+	0x8288f024,
+	0x8288f02c,
+	0x8288f03c,
+	0x8288f04c,
+	0x8288f14e,
+	0x8288f1b8,
+	0x80901728,
+	0x80901728,
+	0x809163cc,
+	0x8091c3f0,
+	0x8090901c,
+	0x8091c1d8,
+	0x8090b7d4,
+	0x8090abe4,
+	0x80901cc0,
+	0x8090515c,
+	0x809018e0,
+	0x80901728,
+	0x80901728,
+	0x80901728,
+	0x80901728,
+	0x80901728,
+	0x80901728,
+	0x80906738,
+	0x80906678,
+	0x80916060,
+	0x80906010,
+	0x80901728,
+	0x80901728,
+	0x01030004,
+	0x01010102,
+	0x02010101,
+	0x04000301,
+	0x01030004,
+	0x01010102,
+	0x02010101,
+	0x04000301,
+	0x0d080300,
+	0x00100b06,
+	0x00584aaf,
+	0x007f1410,
+	0x005030c6,
+	0x007f500c,
+	0x00027dac,
+	0x000021f5,
+	0x000308d1,
+	0x0000057a,
+	0x00260019,
+	0x003f0032,
+	0x0058004b,
+	0x00710064,
+	0x008a007d,
+	0x00a30096,
+	0x00bc00af,
+	0x00d500c8,
+	0x00ee00e1,
+	0x010700fa,
+	0x01070107,
+	0x01070107,
+	0x01070107,
+	0x01070107,
+	0x01070107,
+	0x00000107,
+	0x00200040,
+	0x001002ab,
+	0x015500cd,
+	0x00080249,
+	0x00cd01c7,
+	0x0155005d,
+	0x0249013b,
+	0x00040111,
+	0x01c700f1,
+	0x00cd01af,
+	0x005d00c3,
+	0x01550059,
+	0x013b0029,
+	0x0249025f,
+	0x01110235,
+	0x00020021,
+	0x00f1001f,
+	0x01c70075,
+	0x01af006f,
+	0x00cd0069,
+	0x00c30019,
+	0x005d017d,
+	0x0059005b,
+	0x015502b9,
+	0x002900a7,
+	0x013b0283,
+	0x025f0135,
+	0x02490095,
+	0x0235023f,
+	0x0111008b,
+	0x00210219,
+	0x00010041,
+	0x0b060600,
+	0x0c0b0a06,
+	0x0a0b0c06,
+	0x0c0d0c0c,
+	0x0d0d0c06,
+	0x0b0b0c0c,
+	0x0e0d0a0d,
+	0x0a0d0e0e,
+	0x0c0d0a06,
+	0x0c0e0c0e,
+	0x0e0d0a0d,
+	0x0f0c0c0c,
+	0x0f0b0d0e,
+	0x0d0f0e0e,
+	0x0d0f0f0f,
+	0x0c0b0f0e,
+	0x00140006,
+	0x001a0016,
+	0x0020001c,
+	0x00280024,
+	0x0034002c,
+	0x00400038,
+	0x00500048,
+	0x00680058,
+	0x00800070,
+	0x00a00090,
+	0x00d000b0,
+	0x010000e0,
+	0x01400120,
+	0x01a00160,
+	0x020001c0,
+	0x02800240,
+	0x034002c0,
+	0x04000380,
+	0x05000480,
+	0x06800580,
+	0x08000700,
+	0x0a000900,
+	0x0d000b00,
+	0x10000e00,
+	0x14001200,
+	0x1a001600,
+	0x00001c00,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x01010000,
+	0x02020201,
+	0x04030303,
+	0x05040404,
+	0x00000005,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x00000000,
+	0x1234baac,
+};
+
+unsigned int all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_textreloc[] = {
+	0x00000000,
+};
+
+unsigned int all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_datareloc[] = {
+	0x00000000,
+};
+
+unsigned int all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_textrelocfulladdr[] = {
+	0x00000000,
+};
+
+unsigned int all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_textreloctype[] = {
+	0x00000000,
+};
+
+struct IMG_COMPILED_FW_BIN_RECORD simg_compiled_all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1 = {
+	/* unsigned int ui32TextSize, ui32DataSize; */
+	15278, 13643,
+	/* unsigned int ui32DataOrigin, ui32TextOrigin; */
+	0x8288eeb8, 0x80900000,
+	/* unsigned int ui32TextRelocSize, ui32DataRelocSize; */
+	0, 0,
+
+	/*
+	 * unsigned int ui32Pipes;
+	 * unsigned char   *sFormat, *rcMode;
+	 * unsigned int ui32FormatsMask, ui32HwConfig;
+	 */
+	2, "ALL_CODECS", "ALL", 31, 1,
+
+	/* unsigned int ui32IntDefineCount; */
+	5,
+	/* unsigned char   **pscIntDefineNames; */
+	all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_define_names_array,
+	/* unsigned int *pui32IntDefines; */
+	all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_define_values_array,
+
+	/*
+	 * unsigned int *pui32Text, *pui32Data;
+	 * unsigned int *pui32TextReloc, *pui32DataDeloc;
+	 * unsigned int *pui32TextRelocFullAddr, *pui32TextRelocType;
+	 */
+
+	all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_text,
+	all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_data,
+	all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_textreloc,
+	all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_datareloc,
+	all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_textrelocfulladdr,
+	all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1_textreloctype,
+};
+
+/* Py_Return simg_compiled_all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1 */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/fw_binaries/include_all_fw_variants.h b/drivers/media/platform/img/vxe-vxd/encoder/fw_binaries/include_all_fw_variants.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/fw_binaries/include_all_fw_variants.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/fw_binaries/include_all_fw_variants.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef __INCLUDE_ALL_VARIANTS_INC_INCLUDED__
+#define __INCLUDE_ALL_VARIANTS_INC_INCLUDED__
+
+#define INCLUDE_ALL_VARIANTS_TEMPLATE_VERSION (1)
+
+#define FW_BIN_FORMAT_VERSION (2)
+
+struct IMG_COMPILED_FW_BIN_RECORD {
+	unsigned int text_size, data_size;
+	unsigned int data_origin, text_origin;
+	unsigned int text_reloc_size, data_reloc_size;
+
+	unsigned int pipes;
+	unsigned char *fmt, *rc_mode;
+	unsigned int formats_mask, hw_config;
+
+	unsigned int int_define_cnt;
+	unsigned char **int_define_names;
+	unsigned int *int_defines;
+
+	unsigned int *text, *data;
+	unsigned int *text_reloc, *data_reloc;
+	unsigned int *text_reloc_full_addr, *text_reloc_type;
+};
+
+#include "ALL_CODECS_FW_ALL_pipes_2_contexts_8_hwconfig_1_bin.c"
+
+unsigned int all_fw_binaries_cnt = 1;
+struct IMG_COMPILED_FW_BIN_RECORD *all_fw_binaries[] = {
+	&simg_compiled_all_codecs_fw_all_pipes_2_contexts_8_hwconfig_1,
+};
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/coreflags.h b/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/coreflags.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/coreflags.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/coreflags.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _COREFLAGS_H_
+#define _COREFLAGS_H_
+
+#define SERIALIZED_PIPES (1)
+
+/* The number of TOPAZ cores present in the system */
+#define TOPAZHP_MAX_NUM_PIPES	(4)
+
+#define TOPAZHP_MAX_POSSIBLE_STREAMS (8)
+#define TOPAZHP_MAX_BU_SUPPORT_HD	90
+#define TOPAZHP_MAX_BU_SUPPORT_4K	128
+
+#define USE_VCM_HW_SUPPORT (1)
+/* controls the firmwares ability to support the optional hardware input scaler */
+#define INPUT_SCALER_SUPPORTED (1)
+/* controls the firmwares ability to support secure mode firmware upload */
+#define SECURE_MODE_POSSIBLE (1)
+
+/* controls the firmwares ability to support secure input/output ports */
+#define SECURE_IO_PORTS (1)
+
+/* Line counter feature is not ready for Onyx yet
+ * (comment the define to remove the feature from builds)
+ */
+#define LINE_COUNTER_SUPPORTED (1)
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/defs.h b/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/defs.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/defs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/defs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#if !defined DEFS_H_
+#define DEFS_H_
+
+#include <linux/types.h>
+
+/*
+ * MACROS to insert values into fields within a word. The basename of the
+ * field must have MASK_BASENAME and SHIFT_BASENAME constants.
+ */
+#define F_MASK(basename)  (MASK_##basename)
+#define F_SHIFT(basename) (SHIFT_##basename)
+/*
+ * Extract a value from an instruction word.
+ */
+#define F_EXTRACT(val, basename) (((val) & (F_MASK(basename))) >> (F_SHIFT(basename)))
+
+/*
+ * Mask and shift a value to the position of a particular field.
+ */
+#define F_ENCODE(val, basename)  (((val) << (F_SHIFT(basename))) & (F_MASK(basename)))
+#define F_DECODE(val, basename)  (((val) & (F_MASK(basename))) >> (F_SHIFT(basename)))
+
+/*
+ * Insert a value into a word.
+ */
+#define F_INSERT(word, val, basename) (((word) & ~(F_MASK(basename))) | (F_ENCODE((val), basename)))
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/mtx_fwif.h b/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/mtx_fwif.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/mtx_fwif.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/mtx_fwif.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _MTX_FWIF_H_
+#define _MTX_FWIF_H_
+
+#include "vxe_common.h"
+#include "topazscfwif.h"
+
+//#define VXE_MEASURE_MTX_CLK_FREQ
+
+/*
+ * enum describing the MTX load method
+ */
+enum mtx_load_method {
+	MTX_LOADMETHOD_NONE = 0,        /* don't load MTX code */
+	MTX_LOADMETHOD_BACKDOOR,        /* backdoor - writes MTX load data direct to out.res */
+	MTX_LOADMETHOD_REGIF,           /* load mtx code via register interface */
+	MTX_LOADMETHOD_DMA,             /* load mtx code via DMA */
+	MTX_LOADMETHOD_FORCE32BITS = 0x7FFFFFFFU
+
+};
+
+/*
+ * defines that should come from auto generated headers
+ */
+#define MTX_DMA_MEMORY_BASE (0x82880000)
+#define PC_START_ADDRESS    (0x80900000)
+
+#define MTX_CORE_CODE_MEM   (0x10)
+#define MTX_CORE_DATA_MEM   (0x18)
+
+#define MTX_PC              (0x05)
+
+/*
+ * MTX Firmware Context Structure
+ */
+
+/*
+ * struct img_fw_int_defines_table - contains info for the fw int defines
+ *
+ * @length: length of the table
+ * @names: array of names of entries
+ * @values: array of values of entries
+ */
+struct img_fw_int_defines_table {
+	unsigned int length;
+	unsigned char **names;
+	unsigned int *values;
+};
+
+/*
+ * struct img_fw_context - contains info for the context of the loaded firmware
+ *
+ * @initialized: TRUE if MTX core is initialized
+ * @populated: TRUE if MTX firmware context had been populated with data
+ * @active_ctx_mask: A bit mask of active encode contexts in the firmware
+ * @dev_ctx: Pointer to the device context
+ * @load_method: method used to load this MTX
+ * @supported_codecs: Codec mask
+ * @mtx_debug_val: Value in MTX Debug register (for RAM config)
+ * @mtx_ram_size: Size of MTX RAM
+ * @mtx_bank_size: Size of MTX RAM banks
+ * @mtx_reg_mem_space_addr: Memspace ID for MTX registers
+ * @topaz_reg_mem_space_addr: Memspace ID for TOPAZ registers
+ * @topaz_multicore_reg_addr: Memspace ID for TOPAZ multicore control registers
+ * @core_rev: Hardware core revision ID
+ * @core_des1: Hardware core designer (feature bits)
+ * @drv_has_mtx_ctrl: TRUE if driver (not DASH) has control of MTX
+ * @access_control: Use to get read/write access to MTX
+ * @hw_num_pipes: Number of pipes available in hardware
+ * @num_pipes: Number of pipes supported by firmware
+ * @num_contexts: Number of contexts supported by firmware
+ * @mtx_context_data_copy: Copy of MTX Context Data during hibernate
+ * @mtx_reg_copy: Copy of MTX Register block during hibernate
+ * @mtx_topaz_fw_text_size: Size of MTX Firmware Text Section in words
+ * @mtx_topaz_fw_text: Pointer to MTX Firmware Text Section
+ * @mtx_topaz_fw_data_size: Size of MTX Firmware Data Section in words
+ * @mtx_topaz_fw_data: Pointer to MTX Firmware Data Section
+ * @mtx_topaz_fw_data_origin: Offset to location of Data section
+ * @int_defines: table of int defines
+ */
+struct img_fw_context {
+	unsigned short initialized;
+	unsigned short populated;
+	unsigned char  active_ctx_mask;
+
+	void *dev_ctx;
+
+	enum mtx_load_method load_method;
+
+	unsigned int supported_codecs;
+
+	unsigned int mtx_debug_val;
+	unsigned int mtx_ram_size;
+	unsigned int mtx_bank_size;
+
+	void  *mtx_reg_mem_space_addr;
+	void  *topaz_reg_mem_space_addr[TOPAZHP_MAX_NUM_PIPES];
+	void  *topaz_multicore_reg_addr;
+	unsigned int core_rev;
+	unsigned int core_des1;
+
+	unsigned short drv_has_mtx_ctrl;
+	unsigned int access_control;
+
+	unsigned int hw_num_pipes;
+	unsigned int num_pipes;
+	unsigned int num_contexts;
+
+	struct vidio_ddbufinfo *mtx_context_data_copy[TOPAZHP_MAX_POSSIBLE_STREAMS];
+	unsigned int *mtx_reg_copy;
+
+	unsigned int mtx_topaz_fw_text_size;
+	unsigned int *mtx_topaz_fw_text;
+
+	unsigned int mtx_topaz_fw_data_size;
+	unsigned int *mtx_topaz_fw_data;
+
+	unsigned int mtx_topaz_fw_data_origin;
+
+	struct img_fw_int_defines_table int_defines;
+};
+
+/*
+ * Populates MTX context structure
+ * @param    codec         : version of codec specific firmware to associate with this MTX
+ * @param    fw_ctx       : Output context
+ * @return   int : Standard IMG_ERRORCODE
+ */
+int mtx_populate_fw_ctx(enum img_codec codec,
+			struct img_fw_context  *fw_ctx);
+
+/*
+ * Initialise the hardware using given (populated) MTX context structure
+ * @param    fw_ctx       : Pointer to the context of the target MTX
+ * @return   None
+ */
+void mtx_initialize(void *dev_ctx, struct img_fw_context *fw_ctx);
+
+/*
+ * Return the integer define used to compile given version of firmware.
+ * @param    fw_ctx       : Pointer to the context of the target MTX
+ * @param    name       : Name of a define (string)
+ * @return   Value of define or -1 if not found.
+ */
+int mtx_get_fw_config_int(struct img_fw_context const * const fw_ctx,
+			  unsigned char const * const name);
+
+/*
+ * Load text and data sections onto an MTX.
+ * @param    fw_ctx         : Pointer to the context of the target MTX
+ * @param    load_method      : Method to use for loading code
+ * @return   None
+ */
+void mtx_load(void  *dev_ctx, struct img_fw_context *fw_ctx,
+	      enum mtx_load_method load_method);
+
+/*
+ * Deinitialises MTX and MTX control structure
+ */
+void mtx_deinitialize(struct img_fw_context *fw_ctx);
+
+/*
+ * Saves MTX State -- Registers and Data Memory
+ */
+void mtx_save_state(struct img_fw_context *fw_ctx);
+
+/*
+ * Restores MTX State -- Registers and Data Memory
+ */
+void mtx_restore_state(void  *ctx, struct img_fw_context *fw_ctx);
+
+/*
+ * mtx_start
+ */
+void mtx_start(struct img_fw_context *fw_ctx);
+
+/*
+ * mtx_stop
+ */
+void mtx_stop(struct img_fw_context  *fw_ctx);
+
+/*
+ * Kicks MTX
+ */
+void mtx_kick(struct img_fw_context *fw_ctx, unsigned int kick_count);
+
+/*
+ * Waits for MTX to halt
+ */
+void mtx_wait_for_completion(struct img_fw_context *fw_ctx);
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/topazscfwif.h b/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/topazscfwif.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/topazscfwif.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/topazscfwif.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1104 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _TOPAZSCFWIF_H_
+#define _TOPAZSCFWIF_H_
+
+#include "coreflags.h"
+#include <linux/types.h>
+
+#define MAX_QP_H264			(51)
+
+/*
+ * The number of bytes used by each MVEA MV param & above param region
+ */
+#define MVEA_MV_PARAM_REGION_SIZE 16
+#define MVEA_ABOVE_PARAM_REGION_SIZE 96
+
+/*
+ * Macros to align to the correct number of bytes
+ */
+#define ALIGN_4(X)  (((X) + 3) & ~3)
+#define ALIGN_16(X)  (((X) + 15) & ~15)
+#define ALIGN_64(X)  (((X) + 63) & ~63)
+#define ALIGN_128(X)  (((X) + 127) & ~127)
+#define ALIGN_1024(X)	(((X) + 1023) & ~1023)
+
+/*
+ * Context size allocated from host application
+ */
+#define MTX_CONTEXT_SIZE (13 * 1024)
+
+/*
+ * SEI (Buffering Period and Picture Timing) Constants shared
+ * between host and firmware
+ */
+#define BPH_SEI_NAL_INITIAL_CPB_REMOVAL_DELAY_SIZE 23
+#define PTH_SEI_NAL_CPB_REMOVAL_DELAY_SIZE 23
+#define PTH_SEI_NAL_DPB_OUTPUT_DELAY_SIZE 7
+
+/*
+ * Size of the header in output coded buffer. This varies based on
+ *              whether data logging is enabled/disabled
+ */
+#if defined(INCLUDE_CRC_REGISTER_CHECKS)
+#define CRC_REGISTER_FEEDBACK_SIZE	(80 * 4)
+#else
+#define CRC_REGISTER_FEEDBACK_SIZE	0
+#endif
+
+/* MUST be aligned to the DMA 64 byte boundary condition
+ * (CRC data is DMA'd after the coded buffer header)
+ */
+#define CODED_BUFFER_HEADER_SIZE    64
+#define CODED_BUFFER_INFO_SECTION_SIZE (CODED_BUFFER_HEADER_SIZE + CRC_REGISTER_FEEDBACK_SIZE)
+
+/*
+ * Mask defines for the -ui8EnableSelStatsFlags variable
+ */
+#define ESF_FIRST_STAGE_STATS 1
+#define ESF_MP_BEST_MB_DECISION_STATS 2
+#define ESF_MP_BEST_MOTION_VECTOR_STATS 4
+
+#define CUSTOM_QUANT_PARAMSIZE_8x8 2
+
+/*
+ * Combined size of H.264 quantization lists (6 * 16 + {2 or 6} * 64)
+ */
+#define QUANT_LISTS_SIZE		(6 * 16 + CUSTOM_QUANT_PARAMSIZE_8x8 * 64)
+
+/*
+ * Size in bytes and words of memory to transfer partially coded header data
+ */
+#define MAX_HEADERSIZEBYTES		(128)
+#define MAX_HEADERSIZEWORDS		(32)
+
+/*
+ * Maximum number of slices per field
+ */
+#define MAX_SLICESPERPIC		(128)
+
+/*
+ * Picture parameter flags used in the PIC_PARAM structure
+ */
+#define ISINTERP_FLAGS					(0x00000001)
+#define ISRC_FLAGS					(0x00000010)
+#define ISRC_I16BIAS					(0x00000020)
+#define ISINTERB_FLAGS					(0x00000080)
+#define ISSCENE_DISABLED				(0x00000100)
+#define ISMULTIREF_FLAGS				(0x00000200)
+#define SPATIALDIRECT_FLAGS				(0x00000400)
+
+/*
+ * Enum describing contents of scratch registers
+ */
+enum mtx_scratch_regdata {
+	MTX_SCRATCHREG_BOOTSTATUS = 0,
+	MTX_SCRATCHREG_UNUSED = 0,
+	MTX_SCRATCHREG_TOHOST,			//!< Reg for MTX->Host data
+	MTX_SCRATCHREG_TOMTX,			//!< Reg for Host->MTX data
+
+	MTX_SCRATCHREG_SIZE,				//!< End marker for enum
+	MTX_SCRATCHREG_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * `MTX_SCRATCHREG_IDLE` register that is used for synchronous communication and debug.
+ *
+ * Current register usage:
+ * <bits, inclusive boundaries> : <usage>
+ * 2-10 : Number of executed commands (mod 255)
+ * 0-1 : FW idle status
+ */
+#define MTX_SCRATCHREG_IDLE	TOPAZHP_TOP_CR_FIRMWARE_REG_4 //!< Reg for firmware IDLE status
+
+/* Flags relating to MTX_SCRATCHREG_IDLE */
+/* Bits [10-22] are used for the line information */
+/* TOPAZHP_LINE_COUNTER (see TRM 8.1.1) uses 12 bits for the line count */
+#define SHIFT_FW_IDLE_REG_STATUS		(0)
+#define MASK_FW_IDLE_REG_STATUS			(3)
+#define FW_IDLE_STATUS_IDLE			(1)
+
+/*
+ * In secure FW mode the first value written to the command FIFO is copied to MMU_CONTROL_0
+ * by the firmware. When we don't want that to happen we can write this value instead.
+ * The firmware will know to ignore it as
+ * long as it is written BEFORE the firmware starts up
+ */
+#define TOPAZHP_NON_SECURE_FW_MARKER	(0xffffffff)
+
+/*
+ * This value is an arbitrary value that the firmware will write to TOPAZHP_TOP_CR_FIRMWARE_REG_1
+ * (MTX_SCRATCHREG_BOOTSTATUS)
+ * when it has completed the boot process to indicate that it is ready
+ */
+#define TOPAZHP_FW_BOOT_SIGNAL		(0x12345678)
+
+/*
+ * Sizes for arrays that depend on reference usage pattern
+ */
+#define MAX_REF_B_LEVELS		3
+#define MAX_REF_SPACING			1
+#define MAX_REF_I_OR_P_LEVELS	(MAX_REF_SPACING + 2)
+#define MAX_REF_LEVELS		(MAX_REF_B_LEVELS + MAX_REF_I_OR_P_LEVELS)
+#define MAX_PIC_NODES		(MAX_REF_LEVELS + 2)
+#define MAX_MV			(MAX_PIC_NODES * 2)
+
+#define MAX_BFRAMES	7           //B-frame count limit for Hierarchical mode
+#define MAX_GOP_SIZE		(MAX_BFRAMES + 1)
+#define MAX_SOURCE_SLOTS_SL	(MAX_GOP_SIZE + 1)
+
+#define MV_ROW_STRIDE (ALIGN_64(sizeof(struct img_mv_settings) * MAX_BFRAMES))
+
+/*
+ * MTX -> host message FIFO
+ */
+#define LOG2_WB_FIFO_SIZE	(5)
+
+#define WB_FIFO_SIZE		(1 << (LOG2_WB_FIFO_SIZE))
+
+#define SHIFT_WB_PRODUCER	(0)
+#define MASK_WB_PRODUCER	(((1 << LOG2_WB_FIFO_SIZE) - 1) << SHIFT_WB_PRODUCER)
+
+#define SHIFT_WB_CONSUMER	(0)
+#define MASK_WB_CONSUMER	(((1 << LOG2_WB_FIFO_SIZE) - 1) << SHIFT_WB_CONSUMER)
+
+/*
+ * Number of buffers per encode task (default: 2 - double bufferring)
+ */
+#define CODED_BUFFERING_CNT 2 //default to double-buffering
+
+/*
+ * Calculates the ideal minimum coded buffers for a frame level encode
+ */
+#define CALC_OPTIMAL_CODED_PACKAGES_FRAME_ENCODE(numcores, isinterlaced) \
+	((((isinterlaced) ? 2 : 1) * (numcores)) * CODED_BUFFERING_CNT)
+
+/*
+ * Calculates the ideal minimum coded buffers for a slice level encode
+ */
+#define CALC_OPTIMAL_CODED_PACKAGES_SLICE_ENCODE(slicesperpic) \
+						((slicesperpic) * CODED_BUFFERING_CNT)
+
+/*
+ * Calculates the ideal minimum coded buffers for an encode
+ */
+#define CALC_OPTIMAL_CODED_PACKAGES_ENCODE(bis_slice_level, slicesperpic, numcores, isinterlaced) \
+	(bis_slice_level ? CALC_OPTIMAL_CODED_PACKAGES_SLICE_ENCODE(slicesperpic) \
+	 : CALC_OPTIMAL_CODED_PACKAGES_FRAME_ENCODE(numcores, isinterlaced))
+
+/*
+ * Calculates the actual number of coded buffers that can be used for an encode
+ */
+#define CALC_NUM_CODED_PACKAGES_ENCODE(bis_slice_level, slicesperpic, numcores, isinterlaced) \
+	(CALC_OPTIMAL_CODED_PACKAGES_ENCODE(bis_slice_level, slicesperpic, numcores, isinterlaced))
+
+/*
+ * Maximum number of coded packages
+ */
+#define MAX_CODED_PACKAGES	CALC_NUM_CODED_PACKAGES_ENCODE(0, 0, TOPAZHP_MAX_NUM_PIPES, 1)
+
+/*
+ * DMA configuration parameters
+ */
+#define MTX_DMA_BURSTSIZE_BYTES 32
+
+/*
+ * types that should be in DMAC header file
+ */
+enum dmac_acc_del {
+	DMAC_ACC_DEL_0 = 0x0,			//!< Access delay zero clock cycles
+	DMAC_ACC_DEL_256 = 0x1,			//!< Access delay 256 clock cycles
+	DMAC_ACC_DEL_512 = 0x2,			//!< Access delay 512 clock cycles
+	DMAC_ACC_DEL_768 = 0x3,			//!< Access delay 768 clock cycles
+	DMAC_ACC_DEL_1024 = 0x4,		//!< Access delay 1024 clock cycles
+	DMAC_ACC_DEL_1280 = 0x5,		//!< Access delay 1280 clock cycles
+	DMAC_ACC_DEL_1536 = 0x6,		//!< Access delay 1536 clock cycles
+	DMAC_ACC_DEL_1792 = 0x7,		//!< Access delay 1792 clock cycles
+	DMAC_ACC_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum dmac_bswap {
+	DMAC_BSWAP_NO_SWAP = 0x0,		//!< No byte swapping will be performed.
+	DMAC_BSWAP_REVERSE = 0x1,		//!< Byte order will be reversed.
+	DMAC_BSWAP_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum dmac_burst {
+	DMAC_BURST_0 = 0x0,				//!< burst size of 0
+	DMAC_BURST_1 = 0x1,				//!< burst size of 1
+	DMAC_BURST_2 = 0x2,				//!< burst size of 2
+	DMAC_BURST_3 = 0x3,				//!< burst size of 3
+	DMAC_BURST_4 = 0x4,				//!< burst size of 4
+	DMAC_BURST_5 = 0x5,				//!< burst size of 5
+	DMAC_BURST_6 = 0x6,				//!< burst size of 6
+	DMAC_BURST_7 = 0x7,				//!< burst size of 7
+	DMAC_BURST_FORCE32BITS = 0x7FFFFFFFU
+};
+
+#define DMAC_VALUE_COUNT(BSWAP, PW, DIR, PERIPH_INCR, COUNT)			 \
+	((((BSWAP)		<< SHIFT_IMG_SOC_BSWAP)	& MASK_IMG_SOC_BSWAP)	|\
+	(((PW)			<< SHIFT_IMG_SOC_PW)	& MASK_IMG_SOC_PW)		|\
+	(((DIR)			<< SHIFT_IMG_SOC_DIR)	& MASK_IMG_SOC_DIR)		|\
+	(((PERIPH_INCR)	<< SHIFT_IMG_SOC_PI)	& MASK_IMG_SOC_PI)		|\
+	(((COUNT)		<< SHIFT_IMG_SOC_CNT)	& MASK_IMG_SOC_CNT))
+
+#define DMAC_VALUE_PERIPH_PARAM(ACC_DEL, INCR, BURST)					 \
+	((((ACC_DEL)	<< SHIFT_IMG_SOC_ACC_DEL)	& MASK_IMG_SOC_ACC_DEL)	|\
+	(((INCR)	<< SHIFT_IMG_SOC_INCR)		& MASK_IMG_SOC_INCR)	|\
+	(((BURST)	<< SHIFT_IMG_SOC_BURST)		& MASK_IMG_SOC_BURST))
+
+enum dmac_pw {
+	DMAC_PWIDTH_32_BIT = 0x0,		//!< Peripheral width 32-bit.
+	DMAC_PWIDTH_16_BIT = 0x1,		//!< Peripheral width 16-bit.
+	DMAC_PWIDTH_8_BIT = 0x2,		//!< Peripheral width 8-bit.
+	DMAC_PWIDTH_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Enum describing Command IDs.  Some commands require data to be DMA'd in
+ * from the Host, with the base address of the data specified in the Command
+ * Data Address word of the command.  The data required is specific to each
+ * command type.
+ */
+enum mtx_cmd_id {
+	// Common Commands
+	MTX_CMDID_NULL,			//!< (no data)\n Null command does nothing\n
+	MTX_CMDID_SHUTDOWN,		//!< (no data)\n shutdown the MTX\n
+
+	// Video Commands
+	/* !< (extra data: #MTX_HEADER_PARAMS) Command for Sequence, Picture and Slice headers */
+	MTX_CMDID_DO_HEADER,
+	/* !< (data: low latency encode activation, HBI usage) Encode frame data*/
+	MTX_CMDID_ENCODE_FRAME,
+	MTX_CMDID_START_FRAME,				//!< (no data)\n Prepare to encode frame\n
+	MTX_CMDID_ENCODE_SLICE,				//!< (no data)\n Encode slice data\n
+	MTX_CMDID_END_FRAME,				//!< (no data)\n Complete frame encoding\n
+	/* !< (data: pipe number, extra data: #IMG_MTX_VIDEO_CONTEXT)\n Set MTX Video Context */
+	MTX_CMDID_SETVIDEO,
+	/* !< (data: pipe number, extra data: #IMG_MTX_VIDEO_CONTEXT)
+	 * Get MTX Video Context
+	 */
+	MTX_CMDID_GETVIDEO,
+	/* !< (data: new pipe allocations for the context)
+	 * Change pipe allocation for a Video Context
+	 */
+	MTX_CMDID_DO_CHANGE_PIPEWORK,
+#if SECURE_IO_PORTS
+	MTX_CMDID_SECUREIO,					//!< (data: )\n Change IO security\n
+#endif
+	/* !< (data: subtype and parameters, extra data: #IMG_PICMGMT_CUSTOM_QUANT_DATA
+	 * (optional))\n Change encoding parameters
+	 */
+	MTX_CMDID_PICMGMT,
+	/* !< (data: QP and bitrate)\n Change encoding parameters */
+	MTX_CMDID_RC_UPDATE,
+	/* !< (extra data: #IMG_SOURCE_BUFFER_PARAMS)
+	 * Transfer source buffer from host
+	 */
+	MTX_CMDID_PROVIDE_SOURCE_BUFFER,
+	/* !< (data: buffer parameters, extra data: reference buffer)
+	 * Transfer reference buffer from host
+	 */
+	MTX_CMDID_PROVIDE_REF_BUFFER,
+	/* !< (data: slot and size, extra data: coded package)\n Transfer coded package from host
+	 *(coded package contains addresses of header and coded output buffers/1st linked list node)
+	 */
+	MTX_CMDID_PROVIDE_CODEDPACKAGE_BUFFER,
+	MTX_CMDID_ABORT,		//!< (no data)\n Stop encoding and release all buffers\n
+
+	// JPEG commands
+	MTX_CMDID_SETQUANT,			//!< (extra data: #JPEG_MTX_QUANT_TABLE)\n
+	MTX_CMDID_SETUP_INTERFACE,		//!< (extra data: #JPEG WRITEBACK POINTERS)\n
+	MTX_CMDID_ISSUEBUFF,			//!< (extra data: #MTX_ISSUE_BUFFERS)\n
+	MTX_CMDID_SETUP,			//!< (extra data: #JPEG_MTX_DMA_SETUP)\n\n
+	/* !< (extra data: #IMG_VXE_SCALER_SETUP)\nChange source
+	 * pixel format after context creation\
+	 */
+	MTX_CMDID_UPDATE_SOURCE_FORMAT,
+	/* !< (extra data: #IMG_VXE_CSC_SETUP)\nChange Colour Space Conversion setup dynamically */
+	MTX_CMDID_UPDATE_CSC,
+
+	MTX_CMDID_ENDMARKER,					//!< end marker for enum
+	MTX_CMDID_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Priority for the command.
+ * Each Command ID will only work with the correct priority.
+ */
+#define MTX_CMDID_PRIORITY 0x80
+
+/*
+ * Indicates whether or not to issue an interrupt when the firmware sends the
+ * command's writeback message.
+ */
+#define MTX_CMDID_WB_INTERRUPT 0x8000
+
+/*
+ * Enum describing response IDs
+ */
+enum mtx_message_id {
+	MTX_MESSAGE_ACK,
+	MTX_MESSAGE_CODED,
+	MTX_MESSAGE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Mask and shift values for command word
+ */
+#define SHIFT_MTX_MSG_CMD_ID		(0)
+#define MASK_MTX_MSG_CMD_ID			(0x7f << SHIFT_MTX_MSG_CMD_ID)
+#define SHIFT_MTX_MSG_PRIORITY		(7)
+#define MASK_MTX_MSG_PRIORITY		(0x1 << SHIFT_MTX_MSG_PRIORITY)
+#define SHIFT_MTX_MSG_CORE			(8)
+#define MASK_MTX_MSG_CORE			(0x7f << SHIFT_MTX_MSG_CORE)
+#define SHIFT_MTX_MSG_COUNT			(16)
+#define MASK_MTX_MSG_COUNT			(0xffffU << SHIFT_MTX_MSG_COUNT)
+#define SHIFT_MTX_MSG_MESSAGE_ID	(16)
+#define MASK_MTX_MSG_MESSAGE_ID		(0xff << SHIFT_MTX_MSG_MESSAGE_ID)
+
+/*
+ * Mask and shift values for data word
+ */
+#define SHIFT_MTX_MSG_ENCODE_CODED_INTERRUPT		(0)
+#define MASK_MTX_MSG_ENCODE_CODED_INTERRUPT \
+	(0xff << SHIFT_MTX_MSG_ENCODE_CODED_INTERRUPT)
+#define SHIFT_MTX_MSG_ENCODE_USE_LINE_COUNTER		(20)
+#define MASK_MTX_MSG_ENCODE_USE_LINE_COUNTER \
+	(0x1 << SHIFT_MTX_MSG_ENCODE_USE_LINE_COUNTER)
+
+#define SHIFT_MTX_MSG_PICMGMT_SUBTYPE			(0)
+#define MASK_MTX_MSG_PICMGMT_SUBTYPE			(0xff << SHIFT_MTX_MSG_PICMGMT_SUBTYPE)
+#define SHIFT_MTX_MSG_PICMGMT_DATA			(8)
+#define MASK_MTX_MSG_PICMGMT_DATA			(0xffffffU << SHIFT_MTX_MSG_PICMGMT_DATA)
+#define SHIFT_MTX_MSG_PICMGMT_STRIDE_Y			(0)
+#define MASK_MTX_MSG_PICMGMT_STRIDE_Y			(0x3ff << SHIFT_MTX_MSG_PICMGMT_STRIDE_Y)
+#define SHIFT_MTX_MSG_PICMGMT_STRIDE_UV			(10)
+#define MASK_MTX_MSG_PICMGMT_STRIDE_UV			(0x3ff << SHIFT_MTX_MSG_PICMGMT_STRIDE_UV)
+
+/*Values for updating static Qp values when Rate Control is disabled*/
+#define SHIFT_MTX_MSG_NUM_CODED_BUFFERS_PER_HEADER			(5)
+#define MASK_MTX_MSG_NUM_CODED_BUFFERS_PER_HEADER \
+	(0xf << SHIFT_MTX_MSG_NUM_CODED_BUFFERS_PER_HEADER)
+
+#define SHIFT_MTX_MSG_PROVIDE_CODEDPACKAGE_BUFFER_SLOT	(0)
+#define MASK_MTX_MSG_PROVIDE_CODEDPACKAGE_BUFFER_SLOT \
+	(0x0f << SHIFT_MTX_MSG_PROVIDE_CODEDPACKAGE_BUFFER_SLOT)
+#define SHIFT_MTX_MSG_PROVIDE_CODED_BUFFER_SIZE		(4)
+#define MASK_MTX_MSG_PROVIDE_CODED_BUFFER_SIZE \
+	(0x3fffff << SHIFT_MTX_MSG_PROVIDE_CODED_BUFFER_SIZE)
+
+/*
+ * Enum describing partially coded header element types
+ */
+enum header_element_type {
+	ELEMENT_STARTCODE_RAWDATA = 0,	//!< Raw data that includes a start code
+	/*!< Raw data that includes a start code in the middle of the header */
+	ELEMENT_STARTCODE_MIDHDR,
+	ELEMENT_RAWDATA,	//!< Raw data
+	ELEMENT_QP,		//!< Insert the H264 Picture Header QP parameter
+	ELEMENT_SQP,		//!< Insert the H264 Slice Header QP parameter
+	/* Insert the H263/MPEG4 Frame Q_scale parameter (vob_quant field) */
+	ELEMENT_FRAMEQSCALE,
+	/* !< Insert the H263/MPEG4 Slice Q_scale parameter (quant_scale field) */
+	ELEMENT_SLICEQSCALE,
+	ELEMENT_INSERTBYTEALIGN_H264,	//!< Insert the byte alignment bits for H264
+	ELEMENT_INSERTBYTEALIGN_MPG4,	//!< Insert the byte alignment bits for MPEG4
+	ELEMENT_INSERTBYTEALIGN_MPG2,	//!< Insert the byte alignment bits for MPEG2
+	ELEMENT_VBV_MPG2,
+	ELEMENT_TEMPORAL_REF_MPG2,
+	ELEMENT_CURRMBNR,	//!< Insert the current macrloblock number for a slice.
+
+	/* !< Insert frame_num field (used as ID for ref. pictures in H264) */
+	ELEMENT_FRAME_NUM,	//!< Insert frame_num field (used as ID for ref. pictures in H264)
+	/* !< Insert Temporal Reference field (used as ID for ref. pictures in H263) */
+	ELEMENT_TEMPORAL_REFERENCE,
+	ELEMENT_EXTENDED_TR,		//!< Insert Extended Temporal Reference field
+	/*//!< Insert idr_pic_id field (used to distinguish consecutive IDR frames) */
+	ELEMENT_IDR_PIC_ID,
+	/* !< Insert pic_order_cnt_lsb field (used for display ordering in H264) */
+	ELEMENT_PIC_ORDER_CNT,
+	/* !< Insert gob_frame_id field (used for display ordering in H263) */
+	ELEMENT_GOB_FRAME_ID,
+	/* !< Insert vop_time_increment field (used for display ordering in MPEG4) */
+	ELEMENT_VOP_TIME_INCREMENT,
+	/* !< Insert modulo_time_base used in MPEG4 (depends on vop_time_increment_resolution) */
+	ELEMENT_MODULO_TIME_BASE,
+
+	ELEMENT_BOTTOM_FIELD,			//!< Insert bottom_field flag
+	ELEMENT_SLICE_NUM,			//!< Insert slice num (used for GOB headers in H263)
+	ELEMENT_MPEG2_SLICE_VERTICAL_POS,	//!< Insert slice vertical pos (MPEG2 slice header)
+	/* !< Insert 1 bit flag indicating if slice is Intra or not (MPEG2 slice header) */
+	ELEMENT_MPEG2_IS_INTRA_SLICE,
+	/* !< Insert 2 bit field indicating if the current header is for a frame picture (11),
+	 * top field (01) or bottom field (10) - (MPEG2 picture header
+	 */
+	ELEMENT_MPEG2_PICTURE_STRUCTURE,
+	/* !< Insert flag indicating whether or not this picture is a reference */
+	ELEMENT_REFERENCE,
+	ELEMENT_ADAPTIVE,		//!< Insert reference picture marking
+	ELEMENT_DIRECT_SPATIAL_MV_FLAG,	//!< Insert spatial direct mode flag
+	ELEMENT_NUM_REF_IDX_ACTIVE,	//!< Insert number of active references
+	ELEMENT_REORDER_L0,		//!< Insert reference list 0 reordering
+	ELEMENT_REORDER_L1,		//!< Insert reference list 1 reordering
+	ELEMENT_TEMPORAL_ID,		//!< Insert temporal ID of the picture, used for MVC header
+	/*!< Insert flag indicating whether or not this picture is an anchor picture */
+	ELEMENT_ANCHOR_PIC_FLAG,
+
+	BPH_SEI_NAL_INITIAL_CPB_REMOVAL_DELAY,	//!< Insert nal_initial_cpb_removal_delay
+	/* !< Insert nal_initial_cpb_removal_delay_offset */
+	BPH_SEI_NAL_INITIAL_CPB_REMOVAL_DELAY_OFFSET,
+	PTH_SEI_NAL_CPB_REMOVAL_DELAY,				//!< Insert cpb_removal_delay
+	PTH_SEI_NAL_DPB_OUTPUT_DELAY,				//!< Insert dpb_output_delay
+
+	ELEMENT_SLICEWEIGHTEDPREDICTIONSTRUCT,	//!< Insert weighted prediciton parameters
+	ELEMENT_CUSTOM_QUANT,			//!< Insert custom quantization values
+	ELEMENT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Struct describing a partially coded header element
+ */
+struct mtx_header_element {
+	enum header_element_type element_type;	//!< Element type
+	/* !< Number of bits of coded data to be inserted */
+	unsigned char			size;
+	unsigned char			bits;		//!< Raw data to be inserted.
+};
+
+/*
+ * Struct describing partially coded header parameters
+ */
+struct mtx_header_params {
+	unsigned int		elements;	//!< Number of header elements
+	/*!< array of element data */
+	struct mtx_header_element element_stream[MAX_HEADERSIZEWORDS - 1];
+};
+
+/*
+ * Enum describing threshold values for skipped MB biasing
+ */
+enum th_skip_scale {
+	TH_SKIP_0 = 0,		//!< Bias threshold for QP 0 to 12
+	TH_SKIP_12 = 1,		//!< Bias threshold for QP 12 to 24
+	TH_SKIP_24 = 2,		//!< Bias threshold for QP 24 and above
+	TH_SKIP_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Struct describing rate control input parameters
+ */
+struct in_rc_params {
+	unsigned int	mb_per_frm;		//!< Number of MBs Per Frame
+	unsigned int	mb_per_bu;		//!< Number of MBs Per BU
+	unsigned short	bu_per_frm;		//!< Number of BUs Per Frame
+
+	unsigned short	intra_period;	//!< Intra frame frequency
+	unsigned short	bframes;		//!< B frame frequency
+
+	int	bits_per_frm;		//!< Bits Per Frame
+	int	bits_per_bu;		//!< Bits Per BU
+
+	int	bit_rate;			//!< Bit Rate (bps)
+	int	buffer_size;		//!< Size of Buffer in bits
+	int	buffer_size_frames;//!< Size of Buffer in frames, to be used in VCM
+	int	initial_level;	//!< Initial Level of Buffer
+	int	initial_delay;	//!< Initial Delay of Buffer
+
+	unsigned short	frm_skip_disable;	//!< Disable Frame skipping
+
+	unsigned char	se_init_qp_i;		//!< Initial QP for sequence (I frames)
+	unsigned char	se_init_qp_p;		//!< Initial QP for sequence (P frames)
+	unsigned char	se_init_qp_b;		//!< Initial QP for sequence (B frames)
+
+	unsigned char	min_qp;		//!< Minimum QP value to use
+	unsigned char	max_qp;		//!< Maximum QP value to use
+
+	/* !< Scale Factor used to limit the range
+	 * of arithmetic with high resolutions and bitrates
+	 */
+	unsigned char	scale_factor;
+	unsigned short	mb_per_row;		//!< Number of MBs Per Row
+
+	unsigned short	disable_vcm_hardware; //!< Disable using vcm hardware in RC modes.
+
+	union {
+		struct {
+			/* !< Rate at which bits are sent from encoder
+			 * to the output after each frame finished encoding
+			 */
+			int	transfer_rate;
+			/* !< Disable Scene Change detection */
+			unsigned short	sc_detect_disable;
+			/* !< Flag indicating Hierarchical B Pic or Flat mode rate control */
+			unsigned short	hierarchical_mode;
+			/* !< Constant used in rate control =
+			 * (GopSize/(BufferSize-InitialLevel))*256
+			 */
+			unsigned int	rc_scale_factor;
+			/* !< Enable movement of slice boundary when Qp is high */
+			unsigned short	enable_slice_bob;
+			/* !< Maximum number of rows the slice boundary can be moved */
+			unsigned char  max_slice_bob;
+			/* !< Minimum Qp at which slice bobbing should take place */
+			unsigned char  slice_bob_qp;
+		} h264;
+		struct {
+			unsigned char	half_framerate;	//!< Half Frame Rate (MP4 only)
+			unsigned char	f_code;			//!< F Code (MP4 only)
+			int	bits_pergop;		//!< Bits Per GOP (MP4 only)
+			unsigned short	bu_skip_disable;		//!< Disable BU skipping
+			int	bits_per_mb;		//!< Bits Per MB
+			unsigned short	avg_qp_val;		//!< Average QP in Current Picture
+			unsigned short	initial_qp;		//!< Initial Quantizer
+		} other;
+	} mode;
+};
+
+/*
+ * Enum describing MTX firmware version (codec and rate control)
+ */
+enum img_codec {
+	IMG_CODEC_NONE = 0,		//!< There is no FW in MTX memory
+	IMG_CODEC_JPEG,			//!< JPEG
+	IMG_CODEC_H264_NO_RC,		//!< H264 with no rate control
+	IMG_CODEC_H264_VBR,		//!< H264 variable bitrate
+	IMG_CODEC_H264_CBR,		//!< H264 constant bitrate
+	IMG_CODEC_H264_VCM,		//!< H264 video conferance mode
+	IMG_CODEC_H263_NO_RC,		//!< H263 with no rate control
+	IMG_CODEC_H263_VBR,		//!< H263 variable bitrate
+	IMG_CODEC_H263_CBR,		//!< H263 constant bitrate
+	IMG_CODEC_MPEG4_NO_RC,		//!< MPEG4 with no rate control
+	IMG_CODEC_MPEG4_VBR,		//!< MPEG4 variable bitrate
+	IMG_CODEC_MPEG4_CBR,		//!< MPEG4 constant bitrate
+	IMG_CODEC_MPEG2_NO_RC,		//!< MPEG2 with no rate control
+	IMG_CODEC_MPEG2_VBR,		//!< MPEG2 variable bitrate
+	IMG_CODEC_MPEG2_CBR,		//!< MPEG2 constant bitrate
+	IMG_CODEC_H264_ERC,		//!< H264 example rate control
+	IMG_CODEC_H263_ERC,		//!< H263 example rate control
+	IMG_CODEC_MPEG4_ERC,		//!< MPEG4 example rate control
+	IMG_CODEC_MPEG2_ERC,		//!< MPEG2 example rate control
+	IMG_CODEC_H264MVC_NO_RC,	//!< MVC H264 with no rate control
+	IMG_CODEC_H264MVC_CBR,		//!< MVC H264 constant bitrate
+	IMG_CODEC_H264MVC_VBR,		//!< MVC H264 variable bitrate
+	IMG_CODEC_H264MVC_ERC,		//!< MVC H264 example rate control
+	IMG_CODEC_H264_ALL_RC,		//!< H264 with multiple rate control modes
+	IMG_CODEC_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Enum describing encoding standard (codec)
+ */
+enum img_standard {
+	IMG_STANDARD_NONE = 0,	//!< There is no FW in MTX memory
+	IMG_STANDARD_JPEG,		//!< JPEG
+	IMG_STANDARD_H264,		//!< H264 with no rate control
+	IMG_STANDARD_H263,		//!< H263 with no rate control
+	IMG_STANDARD_MPEG4,		//!< MPEG4 with no rate control
+	IMG_STANDARD_MPEG2,		//!< MPEG2 with no rate control
+	IMG_STANDARD_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Enum describing image surface format types
+ */
+enum img_format {
+	IMG_CODEC_420_YUV = 100,			//!< Planar Y U V
+	IMG_CODEC_420_YV12 = 44,			//!< YV12 format Data
+	IMG_CODEC_420_IMC2 = 36,			//!< IMC2 format Data
+	IMG_CODEC_420_PL8 = 47,			//!< PL8 format YUV data
+	IMG_CODEC_420_PL12 = 101,		//!< PL12 format YUV data
+	/* |< PL12 format packed into a single plane (not currently supported by JPEG) */
+	IMG_CODEC_420_PL12_PACKED = 25,
+	/* !< PL21 format packed into a single plane (not currently supported by JPEG) */
+	IMG_CODEC_420_PL21_PACKED = 26,
+	/* !< YUV format 4:2:2 data; start the incrementing auto enumeration
+	 * values after the last ones we have used.
+	 */
+	IMG_CODEC_422_YUV = 102,
+	IMG_CODEC_422_YV12,			//!< YV12 format 4:2:2 data
+	IMG_CODEC_422_PL8,			//!< PL8 format 4:2:2 data
+	IMG_CODEC_422_IMC2,			//!< IMC2 format 4:2:2 data
+	IMG_CODEC_422_PL12,			//!< PL12 format 4:2:2 data
+	IMG_CODEC_Y0UY1V_8888,		//!< 4:2:2 YUYV data
+	IMG_CODEC_Y0VY1U_8888,		//!< 4:2:2 YVYU data
+	IMG_CODEC_UY0VY1_8888,		//!< 4:2:2 UYVY data
+	IMG_CODEC_VY0UY1_8888,		//!< 4:2:2 VYUY data
+	IMG_CODEC_444_YUV,	//!< YUV format 4:4:4 data (not currently supported by JPEG)
+	IMG_CODEC_444_YV12,	//!< YV12 format 4:4:4 data (not currently supported by JPEG)
+	IMG_CODEC_444_PL8,	//!< PL8 format 4:4:4 data (not currently supported by JPEG)
+	IMG_CODEC_444_IMC2,	//!< PL8 format 4:4:4 data (not currently supported by JPEG)
+	IMG_CODEC_444_PL12,	//!< PL12 format 4:4:4 data (not currently supported by JPEG)
+	IMG_CODEC_ABCX,		//!< Interleaved 4:4:4 data (not currently supported by JPEG)
+	IMG_CODEC_XBCA,		//!< Interleaved 4:4:4 data (not currently supported by JPEG)
+	IMG_CODEC_ABC565,	//!< Packed 4:4:4 data (not currently supported by JPEG)
+
+	IMG_CODEC_420_PL21,		//!< PL21 format YUV data
+	IMG_CODEC_422_PL21,		//!< 4:2:2 PL21 format YUV data
+	/* !< 4:4:4 PL21 format YUV data (not currently supported by JPEG) */
+	IMG_CODEC_444_PL21,
+
+	PVR_SURF_UNSPECIFIED,		//!< End of the enum
+	IMG_CODEC_FORMAT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Enum describing presets for source image colour space conversion
+ */
+enum img_csc_preset {
+	IMG_CSC_NONE,			//!< No colour space conversion
+	IMG_CSC_709_TO_601,		//!< ITU BT.709 YUV to be converted to ITU BT.601 YUV
+	IMG_CSC_601_TO_709,		//!< ITU BT.601 YUV to be converted to ITU BT.709 YUV
+	IMG_CSC_RGB_TO_601_ANALOG,	//!< RGB to be converted to ITU BT.601 YUV
+	/* !< RGB to be converted to ITU BT.601 YCbCr for SDTV (reduced scale - 16-235) */
+	IMG_CSC_RGB_TO_601_DIGITAL,
+	/*  !< RGB to be converted to ITU BT.601 YCbCr for HDTV (full range - 0-255) */
+	IMG_CSC_RGB_TO_601_DIGITAL_FS,
+	IMG_CSC_RGB_TO_709,		//!< RGB to be converted to ITU BT.709 YUV
+	IMG_CSC_YIQ_TO_601,		//!< YIQ to be converted to ITU BT.601 YUV
+	IMG_CSC_YIQ_TO_709,		//!< YIQ to be converted to ITU BT.709 YUV
+	IMG_CSC_BRG_TO_601,		//!< BRG to be converted to ITU BT.601 YUV (for XRGB format)
+	IMG_CSC_RBG_TO_601,		//!< RBG to be converted to ITU BT.601 YUV (for XBGR format)
+	IMG_CSC_BGR_TO_601,     //!< BGR to be converted to ITU BT.601 YUV (for BGRX format)
+	IMG_CSC_UYV_TO_YUV,     //!< UYV to be converted to YUV (BT.601 or BT.709)
+	IMG_CSC_PRESETS,			//!< End of the enum
+	IMG_CSC_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * GOP structure information
+ */
+#define SHIFT_GOP_FRAMETYPE		(0)
+#define MASK_GOP_FRAMETYPE		(0x3 << SHIFT_GOP_FRAMETYPE)
+#define SHIFT_GOP_REFERENCE		(2)
+#define MASK_GOP_REFERENCE		(0x1 << SHIFT_GOP_REFERENCE)
+#define SHIFT_GOP_POS			(3)
+#define MASK_GOP_POS			(0x1f << SHIFT_GOP_POS)
+#define SHIFT_GOP_REF0			(0 + 8)
+#define MASK_GOP_REF0			(0xf << SHIFT_GOP_REF0)
+#define SHIFT_GOP_REF1			(4 + 8)
+#define MASK_GOP_REF1			(0xf << SHIFT_GOP_REF1)
+
+/*
+ * Frame types
+ */
+enum img_frame_type {
+	IMG_INTRA_IDR = 0,
+	IMG_INTRA_FRAME,
+	IMG_INTER_P,
+	IMG_INTER_B,
+	IMG_INTER_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Motion vector calculation register settings
+ */
+struct img_mv_settings {
+	unsigned int	mv_calc_below;
+	unsigned int	mv_calc_colocated;
+	unsigned int	mv_calc_config;
+};
+
+/*
+ * Frame template types
+ */
+enum img_frame_template_type {
+	IMG_FRAME_IDR = 0,
+	IMG_FRAME_INTRA,
+	IMG_FRAME_INTER_P,
+	IMG_FRAME_INTER_B,
+	IMG_FRAME_INTER_P_IDR,
+	IMG_FRAME_UNDEFINED,
+	IMG_FRAME_TYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Rate control modes
+ */
+enum img_rcmode {
+	IMG_RCMODE_NONE = 0,
+	IMG_RCMODE_CBR,
+	IMG_RCMODE_VBR,
+	IMG_RCMODE_ERC,			// Example Rate Control
+	IMG_RCMODE_VCM,
+	IMG_RCMODE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Video Conferencing Mode (VCM) rate control method's sub modes
+ */
+enum img_rc_vcm_mode {
+	IMG_RC_VCM_MODE_DEFAULT = 0,
+	IMG_RC_VCM_MODE_CFS_NONIFRAMES,
+	IMG_RC_VCM_MODE_CFS_ALLFRAMES,
+	IMG_RC_VCM_MODE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Weighted prediction values
+ */
+struct weighted_prediction_values {
+	unsigned char	frame_type;
+	unsigned char	weighted_pred_flag;	// Corresponds to field in the pps
+	unsigned char	weighted_bipred_idc;
+	unsigned int	luma_log2_weight_denom;
+	unsigned int	chroma_log2_weight_denom;
+	/*  Y, Cb, Cr Support for 2 ref pictures on P, or 1 pic in each direction on B. */
+	unsigned char	weight_flag[3][2];
+	int		weight[3][2];
+	int		offset[3][2];
+};
+
+enum weighted_bipred_idc {
+	WBI_NONE = 0x0,
+	WBI_EXPLICIT,
+	WBI_IMPLICIT,
+	WBI_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Registers required to configure input scaler
+ */
+struct img_vxe_scaler_setup {
+	unsigned int	input_scaler_control;
+	unsigned int	scaler_input_size_reg;
+	unsigned int	scaler_crop_reg;
+	unsigned int	scaler_pitch_reg;
+	unsigned int	scaler_control;
+	unsigned int	hor_scaler_coeff_regs[4];
+	unsigned int	ver_scaler_coeff_regs[4];
+};
+
+/*
+ * Registers required to configure input Colour Space conversion
+ */
+struct img_vxe_csc_setup {
+	unsigned int	csc_source_y[3];
+	unsigned int	csc_output_clip[2];
+	unsigned int	csc_source_cbcr[3];
+};
+
+/*
+ * SETVIDEO & GETVIDEO - Video encode context
+ */
+struct img_mtx_video_context {
+	/* // keep this at the top as it has alignment issues */
+	unsigned long long	clock_div_bitrate;
+	unsigned int	width_in_mbs;		//!< target output width
+	unsigned int	picture_height_in_mbs;	//!< target output height
+	unsigned int	tmp_reconstructed[MAX_PIC_NODES];
+	unsigned int	reconstructed[MAX_PIC_NODES];
+	unsigned int	colocated[MAX_PIC_NODES];
+	unsigned int	mv[MAX_MV];
+	unsigned int	inter_view_mv[2];
+	/* !< Send debug information from Register CRCs to Host with the coded buffer */
+	unsigned int	debug_crcs;
+	unsigned int	writeback_regions[WB_FIFO_SIZE];		//!< Data section
+	unsigned int	initial_cpb_removal_delayoffset;
+	unsigned int	max_buffer_mult_clock_div_bitrate;
+	unsigned int	sei_buffering_period_template;
+	unsigned int	sei_picture_timing_template;
+	unsigned short	enable_mvc;
+	unsigned short	mvc_view_idx;
+	unsigned int	slice_params_templates[5];
+	unsigned int	pichdr_templates[4];
+	unsigned int	seq_header;
+	unsigned int	subset_seq_header;
+	unsigned short	no_sequence_headers;
+
+	/* !< Slice map of the source picture */
+	unsigned int	slice_map[MAX_SOURCE_SLOTS_SL];
+	unsigned int	flat_gop_struct;	//!< Address of Flat MiniGop structure
+	unsigned char	weighted_prediction_enabled;
+	unsigned char	mtx_weighted_implicit_bi_pred;
+	unsigned int	weighted_prediction_virt_addr[MAX_SOURCE_SLOTS_SL];
+	/* !< Address of hierarchical MiniGop structure */
+	unsigned int	hierar_gop_struct;
+	/* Output Parameters of the First Pass */
+	unsigned int	firstpass_out_param_addr[MAX_SOURCE_SLOTS_SL];
+	/* !< Selectable Output Best MV Parameters data of the First Pass */
+	unsigned int	firstpass_out_best_multipass_param_addr[MAX_SOURCE_SLOTS_SL];
+	/* !< Input Parameters to the second pass */
+	unsigned int	mb_ctrl_in_params_addr[MAX_SOURCE_SLOTS_SL];
+	/* !< Strides of source Y data and chroma data */
+	unsigned int	pic_row_stride_bytes;
+	/* !< Picture level parameters (supplied by driver) */
+	unsigned int	above_params[TOPAZHP_MAX_NUM_PIPES];
+	unsigned int	idr_period;
+	unsigned int	intra_loop_cnt;
+	unsigned int	bframe_count;
+	unsigned char	hierarchical;
+	/* !< Only used in MPEG2, 2 bit field (0 = 8 bit, 1 = 9 bit, 2 = 10 bit and 3=11 bit
+	 * precision). Set to zero for other encode standards.
+	 */
+	unsigned char	mpeg2_intra_dc_precision;
+	unsigned char	pic_on_level[MAX_REF_LEVELS];
+	unsigned int	vop_time_resolution;
+	unsigned short	kick_size;		//!< Number of Macroblocks per kick
+	unsigned short	kicks_per_bu;		//!< Number of kicks per BU
+	unsigned short	kicks_per_picture;	//!< Number of kicks per picture
+	struct img_mv_settings mv_settings_idr;
+	struct img_mv_settings mv_settings_non_b[MAX_BFRAMES + 1];
+	unsigned int	mv_settings_b_table;
+	unsigned int	mv_settings_hierarchical;
+	enum img_format format;		//!< Pixel format of the source surface
+	enum img_standard standard;	//!< Encoder standard (H264 / H263 / MPEG4 / JPEG)
+	enum img_rcmode rc_mode;	//!< RC flavour
+	enum img_rc_vcm_mode rc_vcm_mode;	//!< RC VCM flavour
+	/* !< RC VCM maximum frame size percentage allowed to exceed in CFS */
+	unsigned int	rc_cfs_max_margin_perc;
+	unsigned char	first_pic;
+	unsigned char	is_interlaced;
+	unsigned char	top_field_first;
+	unsigned char	arbitrary_so;
+	unsigned char	output_reconstructed;
+	unsigned char	disable_bit_stuffing;
+	unsigned char	insert_hrd_params;
+	unsigned char	max_slices_per_picture;
+	unsigned int	f_code;
+	/* Contents Adaptive Rate Control parameters*/
+	unsigned int	jmcomp_rc_reg0;
+	unsigned int	jmcomp_rc_reg1;
+	/* !< Value to use for MVClip_Config  register */
+	unsigned int	mv_clip_config;
+	/* !< Value to use for Predictor combiner register */
+	unsigned int	pred_comb_control;
+	/*  !< Value to use for LRITC_Cache_Chunk_Config register */
+	unsigned int	lritc_cache_chunk_config;
+	/* !< Value to use for IPEVectorClipping register */
+	unsigned int	ipe_vector_clipping;
+	/* !< Value to use for H264CompControl register */
+	unsigned int	h264_comp_control;
+	/* !< Value to use for H264CompIntraPredMode register */
+	unsigned int	h264_comp_intra_pred_modes;
+	/* !< Value to use for IPCM_0 Config register */
+	unsigned int	ipcm_0_config;
+	/* !< Value to use for IPCM_1 Config register */
+	unsigned int	ipcm_1_config;
+	/* !< Value to use for SPEMvdClipRange register */
+	unsigned int	spe_mvd_clip_range;
+	/* !< Value to use for MB_HOST_CONTROL register */
+	unsigned int	mb_host_ctrl;
+	/* !< Value for the CR_DB_DISABLE_DEBLOCK_IDC register */
+	unsigned int	deblock_ctrl;
+	/* !< Value for the CR_DB_DISABLE_DEBLOCK_IDC register */
+	unsigned int	skip_coded_inter_intra;
+	unsigned int	vlc_control;
+	/* !< Slice control register value. Configures the size of a slice */
+	unsigned int	vlc_slice_control;
+	/* !< Slice control register value. Configures the size of a slice */
+	unsigned int	vlc_slice_mb_control;
+	/* !< Chroma QP offset to use (when PPS id = 0)*/
+	unsigned short	cqp_offset;
+	unsigned char	coded_header_per_slice;
+	unsigned char	initial_qp_i;			//!< Initial QP I frames
+	unsigned char	initial_qp_p;			//!< Initial QP P frames
+	unsigned char	initial_qp_b;			//!< Initial QP B frames
+	unsigned int	first_pic_flags;
+	unsigned int	non_first_pic_flags;
+	unsigned char	mc_adaptive_rounding_disable;
+#define AR_REG_SIZE	18
+#define AR_DELTA_SIZE 7
+	unsigned short	mc_adaptive_rounding_offsets[AR_REG_SIZE][4];
+	short		mc_adaptive_rounding_offsets_delta[AR_DELTA_SIZE][4];
+	/* !< Reconstructed address to allow host picture management */
+	unsigned int	patched_recon_address;
+	/* !< Reference 0 address to allow host picture management */
+	unsigned int	patched_ref0_address;
+	/* !< Reference 1 address to allow host picture management */
+	unsigned int	patched_ref1_address;
+	unsigned int	ltref_header[MAX_SOURCE_SLOTS_SL];
+	signed char	slice_header_slot_num;
+	unsigned char	recon_is_longterm;
+	unsigned char	ref0_is_longterm;
+	unsigned char	ref1_is_longterm;
+	unsigned char	ref_spacing;
+	unsigned char	fw_num_pipes;
+	unsigned char	fw_first_pipe;
+	unsigned char	fw_last_pipe;
+	unsigned char	fw_pipes_to_use_flags;
+#if SECURE_IO_PORTS
+	unsigned int	secure_io_control;
+#endif
+	struct img_vxe_scaler_setup scaler_setup;
+	struct img_vxe_csc_setup csc_setup;
+
+	struct in_rc_params in_params;
+};
+
+/*
+ * PICMGMT - Command sub-type
+ */
+enum img_picmgmt_type {
+	IMG_PICMGMT_REF_TYPE = 0,
+	IMG_PICMGMT_GOP_STRUCT,
+	IMG_PICMGMT_SKIP_FRAME,
+	IMG_PICMGMT_EOS,
+	IMG_PICMGMT_FLUSH,
+	IMG_PICMGMT_QUANT,
+	IMG_PICMGMT_STRIDE,
+	IMG_PICMGMT_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * MTX- > host message structure
+ */
+struct img_writeback_msg {
+	unsigned int cmd_word;
+	union {
+		struct {
+			unsigned int	data;
+			unsigned int	extra_data;
+			unsigned int	writeback_val;
+		};
+		unsigned int	coded_package_consumed_idx;
+	};
+};
+
+/*
+ * PROVIDE_SOURCE_BUFFER - Details of the source picture buffer
+ */
+struct img_source_buffer_params {
+	/* !< Host context value. Keep at start for alignment. */
+	unsigned long long	host_context;
+	unsigned int	phys_addr_y_plane_field_0;	//!< Source pic phys addr (Y plane, Field 0)
+	unsigned int	phys_addr_u_plane_field_0;	//!< Source pic phys addr (U plane, Field 0)
+	unsigned int	phys_addr_v_plane_field_0;	//!< Source pic phys addr (V plane, Field 0)
+	unsigned int	phys_addr_y_plane_field_1;	//!< Source pic phys addr (Y plane, Field 1)
+	unsigned int	phys_addr_u_plane_field_1;	//!< Source pic phys addr (U plane, Field 1)
+	unsigned int	phys_addr_v_plane_field_1;	//!< Source pic phys addr (V plane, Field 1)
+	/* !< Number of frames in the stream (incl. skipped) */
+	unsigned char	display_order_num;
+	unsigned char	slot_num;					//!< Source slot number
+	unsigned char   reserved1;
+	unsigned char   reserved2;
+};
+
+/*
+ * Struct describing input parameters to encode a video slice
+ */
+struct slice_params {
+	unsigned int	flags;					//!< Flags for slice encode
+
+	/* Config registers. These are passed straight
+	 *  through from drivers to hardware.
+	 */
+	unsigned int	slice_config;			//!< Value to use for Slice Config register
+	unsigned int	ipe_control;			//!< Value to use for IPEControl register
+	/* !<Value to use for Sequencer Config register */
+	unsigned int	seq_config;
+
+	enum img_frame_template_type template_type;	//!< Slice header template type
+	/* !< Template of corresponding slice header */
+	struct mtx_header_params slice_hdr_tmpl;
+};
+
+/*
+ * Structure describing coded header data returned by the firmware.
+ * The size of the structure should not be more than 64 bytes (needs to have 64 byte alignment)
+ *              (i.e. CODED_BUFFER_HEADER_SIZE)
+ */
+struct coded_data_hdr {
+	unsigned long long	host_ctx;	//!< Host context value. Keep at top for alignment.
+	unsigned int	bytes_written;	//!< Bytes in this coded buffer excluding this header
+	unsigned int	feedback;		//!< Feedback word for this coded buffers
+	unsigned int	extra_feedback;	//!< Extra feedback word for this coded buffers
+
+	unsigned short	i_mb_cnt;	//!< Number of MBs coded as I-macroblocks in this slice
+	unsigned short	p_mb_cnt;	//!< Number of MBs coded as P-macroblocks in this slice
+
+	unsigned short	b_mb_cnt;	//!< Number of MBs coded as B-macroblocks in this slice
+	unsigned short	skip_mb_cnt;	//!< Number of MBs coded as skipped in this slice
+
+	unsigned short	ipcm_mb_cnt;	//!< Number of macroblocks coded as IPCM in this slice
+	unsigned char	inter_sum_satd_hi;	//!< High 8 bits for the inter sum satd
+	unsigned char	intra_sum_satd_hi;	//!< High 8 bits for the intra sum satd
+	/* !< Number of bits use for coding DC coefficients in this slice  */
+	unsigned int	dc_bits;
+	/* !< Number of bits used for coding all Motion vector data in this slice  */
+	unsigned int	mv_bits;
+	/* !< Number of bits used for coding all MB level symbols in this slice */
+	unsigned int	symbols_bits;
+	/* !< Number of bits used for coding residual data in all MBs in this slice  */
+	unsigned int	residual_bits;
+
+	/* !< Sum of QPy/Qscale for all Inter-MBs in the slice */
+	unsigned int	qpy_inter;
+	/* !< Sum of QPy/Qscale for all Intra-MBs in the slice */
+	unsigned int	qpy_intra;
+	unsigned int	inter_sum_satd;	//!< Sum of SATD for all Inter-MBs in the slice
+	unsigned int	intra_sum_satd;	//!< Sum of SATD for all Intra-MBs in the slice
+};
+
+#define MAX_CODED_BUFFERS_PER_PACKAGE_FW 1
+#define MAX_CODED_BUFFERS_PER_PACKAGE 1
+
+// This structure is temporarily used during the 64 byte minimum DMA transfer from driver to FW
+struct coded_package_dma_info {
+	unsigned int coded_mem_addr[MAX_CODED_BUFFERS_PER_PACKAGE_FW];
+	//////////////////
+	// 2 Info words //
+	//////////////////
+	unsigned int coded_header_addr;
+	/* Combined field Host->MTX = IsLinkedList, list segment
+	 * (CB memory) size, number of list segments per coded buffer
+	 */
+	unsigned int coded_buffer_info;
+
+	// PAD TO 64 BYTES
+	unsigned int padding[16 - MAX_CODED_BUFFERS_PER_PACKAGE_FW - 2];
+};
+
+/*
+ * Contents of the coded data buffer header feedback word
+ */
+#define SHIFT_CODED_FIRST_BU			(24)
+#define MASK_CODED_FIRST_BU			(0xFFU << SHIFT_CODED_FIRST_BU)
+#define SHIFT_CODED_SLICE_NUM			(16)
+#define MASK_CODED_SLICE_NUM			(0xFF << SHIFT_CODED_SLICE_NUM)
+#define SHIFT_CODED_STORAGE_FRAME_NUM		(14)
+#define MASK_CODED_STORAGE_FRAME_NUM		(0x03 << SHIFT_CODED_STORAGE_FRAME_NUM)
+#define SHIFT_CODED_ENTIRE_FRAME		(12)
+#define MASK_CODED_ENTIRE_FRAME			(0x01 << SHIFT_CODED_ENTIRE_FRAME)
+#define SHIFT_CODED_IS_SKIPPED			(11)
+#define MASK_CODED_IS_SKIPPED			(0x01 << SHIFT_CODED_IS_SKIPPED)
+#define SHIFT_CODED_IS_CODED			(10)
+#define MASK_CODED_IS_CODED			(0x01 << SHIFT_CODED_IS_CODED)
+#define SHIFT_CODED_RECON_IDX			(6)
+#define MASK_CODED_RECON_IDX			(0x0F << SHIFT_CODED_RECON_IDX)
+#define SHIFT_CODED_SOURCE_SLOT			(2)
+#define MASK_CODED_SOURCE_SLOT			(0x0F << SHIFT_CODED_SOURCE_SLOT)
+#define SHIFT_CODED_FRAME_TYPE			(0)
+#define MASK_CODED_FRAME_TYPE			(0x03 << SHIFT_CODED_FRAME_TYPE)
+
+/*
+ * Contents of the coded data buffer header extra feedback word
+ */
+#define SHIFT_CODED_SLICES_SO_FAR		(24)
+#define MASK_CODED_SLICES_SO_FAR		(0xFFU << SHIFT_CODED_SLICES_SO_FAR)
+
+#define SHIFT_CODED_SLICES_IN_BUFFER		(16)
+#define MASK_CODED_SLICES_IN_BUFFER		(0xFF << SHIFT_CODED_SLICES_IN_BUFFER)
+
+#define SHIFT_CODED_BUFFER_NUMBER_USED		(2)
+#define MASK_CODED_BUFFER_NUMBER_USED		(0xFF << SHIFT_CODED_BUFFER_NUMBER_USED)
+
+#define SHIFT_CODED_FIELD			(1)
+#define MASK_CODED_FIELD			(0x01 << SHIFT_CODED_FIELD)
+
+#define SHIFT_CODED_PATCHED_RECON		(0)
+#define MASK_CODED_PATCHED_RECON		(0x01 << SHIFT_CODED_PATCHED_RECON)
+
+#endif /* _TOPAZSCFWIF_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/vxe_common.h b/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/vxe_common.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/vxe_common.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/fw_headers/vxe_common.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,165 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _VXECOMMON_H_
+#define _VXECOMMON_H_
+
+#include "topazscfwif.h"
+#include "../common/vid_buf.h"
+
+/*
+ * Enum describing buffer lock status
+ */
+enum lock_status {
+	BUFFER_FREE	= 1,  //!< Buffer is not locked
+	HW_LOCK,          //!< Buffer is locked by hardware
+	SW_LOCK,          //!< Buffer is locked by software
+	NOTDEVICEMEMORY,  //!< Buffer is not a device memory buffer
+	LOCK_ST_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Struct describing a data buffer
+ */
+struct img_buffer {
+	struct vidio_ddbufinfo mem_info;	//!< Pointer to the memory handle for the buffer
+	enum lock_status lock;                  //!< Lock status for the buffer
+	unsigned int	size;               //!< Size in bytes of the buffer
+	unsigned int	bytes_written;       //!< Number of bytes written into buffer
+};
+
+/*
+ * Struct describing a coded data buffer
+ */
+struct img_coded_buffer {
+	struct vidio_ddbufinfo mem_info;	//!< Pointer to the memory handle for the buffer
+	enum lock_status lock;                  //!< Lock status for the buffer
+	unsigned int	size;               //!< Size in bytes of the buffer
+	unsigned int	bytes_written;       //!< Number of bytes written into buffer
+};
+
+struct coded_info {
+	struct img_buffer *code_package_fw_buffer;
+	struct coded_package_dma_info *coded_package_fw;
+};
+
+// This structure is used by the Drivers
+struct coded_package_host {
+	struct coded_info mtx_info;
+	/* Array of pointers to buffers */
+	struct img_coded_buffer *coded_buffer[MAX_CODED_BUFFERS_PER_PACKAGE];
+	struct img_buffer *header_buffer;
+	unsigned char num_coded_buffers;
+	unsigned char busy;
+};
+
+/*
+ * Struct describing surface component info
+ */
+struct img_surf_component_info {
+	unsigned int	step;
+	unsigned int	width;
+	unsigned int	height;
+	unsigned int	phys_width;
+	unsigned int	phys_height;
+};
+
+/*
+ * Struct describing a frame
+ */
+struct img_frame {
+	struct	img_buffer *y_plane_buffer;		//!< pointer to the image buffer
+	struct	img_buffer *u_plane_buffer;		//!< pointer to the image buffer
+	struct	img_buffer *v_plane_buffer;		//!< pointer to the image buffer
+	unsigned int	width_bytes;			//!< stride of pBuffer
+	unsigned int	height;				//!< height of picture in pBuffer
+
+	unsigned int	component_count;	//!< number of colour components used
+	enum img_format	format;
+	unsigned int	component_offset[3];
+	unsigned int	bottom_component_offset[3];
+	struct img_surf_component_info	component_info[3];
+	int	y_component_offset;
+	int	u_component_offset;
+	int	v_component_offset;
+	int	field0_y_offset, field1_y_offset;
+	int	field0_u_offset, field1_u_offset;
+	int	field0_v_offset, field1_v_offset;
+	unsigned short	src_y_stride_bytes, src_uv_stride_bytes;
+	unsigned char	imported;
+};
+
+/*
+ * Struct describing an array of frames
+ */
+struct img_frame_array {
+	unsigned int array_size;   //!< Number of frames in array
+	struct img_frame *frame;          //!< Pointer to start of frame array
+};
+
+/*
+ * Struct describing list items
+ */
+struct list_item {
+	struct list_item *next;		//!< Next item in the list
+	void *data;				//!< pointer to list item data
+};
+
+/*
+ * Struct describing rate control params
+ */
+struct img_rc_params {
+	unsigned int	bits_per_second;		//!< Bit rate
+	/* !< Transfer rate of encoded data from encoder to the output */
+	unsigned int	transfer_bits_per_second;
+	unsigned int	initial_qp_i;		//!< Initial QP I frames (only field used by JPEG)
+	unsigned int	initial_qp_p;		//!< Initial QP P frames (only field used by JPEG)
+	unsigned int	initial_qp_b;		//!< Initial QP B frames (only field used by JPEG)
+	unsigned int	bu_size;					//!< Basic unit size
+	unsigned int	frame_rate;
+	unsigned int	buffer_size;
+	unsigned int	intra_freq;
+	short	min_qp;
+	short	max_qp;
+	unsigned char rc_enable;
+	int	initial_level;
+	int	initial_delay;
+	unsigned short	bframes;
+	unsigned char	hierarchical;
+
+	/* !< Enable movement of slice boundary when Qp is high */
+	unsigned char  enable_slice_bob;
+	/* !< Maximum number of rows the slice boundary can be moved */
+	unsigned char  max_slice_bob;
+	/* !< Minimum Qp at which slice bobbing should take place */
+	unsigned char  slice_bob_qp;
+
+	signed char	qcp_offset;
+	unsigned char	sc_detect_disable;
+	unsigned int	slice_byte_limit;
+	unsigned int	slice_mb_limit;
+	enum img_rcmode rc_mode;
+	enum img_rc_vcm_mode rc_vcm_mode;
+	unsigned int	rc_cfs_max_margin_perc;
+	unsigned char	disable_frame_skipping;
+	unsigned char	disable_vcm_hardware;
+};
+
+/*
+ * Bit fields for ui32MmuFlags
+ */
+#define MMU_USE_MMU_FLAG	0x00000001
+#define MMU_EXTENDED_ADDR_FLAG	0x00000004
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/header_gen.c b/drivers/media/platform/img/vxe-vxd/encoder/header_gen.c
--- a/drivers/media/platform/img/vxe-vxd/encoder/header_gen.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/header_gen.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1751 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Encoder coded header generation function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/types.h>
+#include "fw_headers/topazscfwif.h"
+#include "fw_headers/defs.h"
+#include "header_gen.h"
+#include "img_errors.h"
+#include "reg_headers/topazhp_core_regs.h"
+#include "topaz_api.h"
+
+#define ELEMENTS_EMPTY 9999
+#define MAXNUMBERELEMENTS 32
+#define _1080P_30FPS (((1920 * 1088) / 256) * 30)
+
+void insert_element_token(struct mtx_header_params *mtx_header,
+			  struct mtx_header_element **element_pointers,
+			  enum header_element_type token)
+{
+	unsigned char offset;
+	unsigned char *p;
+
+	if (mtx_header->elements != ELEMENTS_EMPTY) {
+		if (element_pointers[mtx_header->elements]->element_type ==
+			ELEMENT_STARTCODE_RAWDATA ||
+			element_pointers[mtx_header->elements]->element_type == ELEMENT_RAWDATA ||
+			element_pointers[mtx_header->elements]->element_type ==
+			ELEMENT_STARTCODE_MIDHDR) {
+			/*
+			 * Add a new element aligned to word boundary
+			 * Find RAWBit size in bytes (rounded to word boundary))
+			 * NumberofRawbits (excluding size of bit count field)+
+			 * size of the bitcount field
+			 */
+			offset = element_pointers[mtx_header->elements]->size + 8 + 31;
+			offset /= 32; /*Now contains rawbits size in words */
+			offset += 1; /*Now contains rawbits+element_type size in words */
+			/* Convert to number of bytes (total size of structure
+			 * in bytes, aligned to word boundary).
+			 */
+			offset *= 4;
+		} else {
+			offset = 4;
+		}
+
+		mtx_header->elements++;
+		p = (unsigned char *)element_pointers[mtx_header->elements - 1];
+		p += offset;
+		element_pointers[mtx_header->elements] = (struct mtx_header_element *)p;
+	} else {
+		mtx_header->elements = 0;
+	}
+
+	element_pointers[mtx_header->elements]->element_type = token;
+	element_pointers[mtx_header->elements]->size = 0;
+}
+
+unsigned int write_upto_8bits_to_elements(struct mtx_header_params *mtx_header,
+					  struct mtx_header_element **element_pointers,
+					  unsigned int write_bits, unsigned short bit_cnt)
+{
+	/* This is the core function to write bits/bytes to a header stream,
+	 * it writes them directly to ELEMENT structures.
+	 */
+	unsigned char *write_bytes;
+	unsigned char *size_bits;
+	union input_value {
+		unsigned int input16;
+		unsigned char input8[2];
+	} input_val;
+
+	unsigned char out_byte_index;
+	short shift;
+
+	if (bit_cnt == 0)
+		return 0;
+
+	/* First ensure that unused bits in ui32WriteBits are zeroed */
+	write_bits &= (0x00ff >> (8 - bit_cnt));
+	input_val.input16 = 0;
+	/*Pointer to the bit count field */
+	size_bits = &element_pointers[mtx_header->elements]->size;
+	/*Pointer to the space where header bits are to be written */
+	write_bytes = &element_pointers[mtx_header->elements]->bits;
+	out_byte_index = (size_bits[0] / 8);
+
+	if (!(size_bits[0] & 7)) {
+		if (size_bits[0] >= 120) {
+			/*Element maximum bits send to element, time to start a new one */
+			mtx_header->elements++; /* Increment element index */
+			/*Element pointer set to position of next element (120/8 = 15 bytes) */
+			element_pointers[mtx_header->elements] =
+				(struct mtx_header_element *)&write_bytes[15];
+			/*Write ELEMENT_TYPE */
+			element_pointers[mtx_header->elements]->element_type = ELEMENT_RAWDATA;
+			/* Set new element size (bits) to zero */
+			element_pointers[mtx_header->elements]->size = 0;
+			/* Begin writing to the new element */
+			write_upto_8bits_to_elements(mtx_header, element_pointers, write_bits,
+						     bit_cnt);
+			return (unsigned int)bit_cnt;
+		}
+		write_bytes[out_byte_index] = 0; /* Beginning a new byte, clear byte */
+	}
+
+	shift = (short)((8 - bit_cnt) - (size_bits[0] & 7));
+
+	if (shift >= 0) {
+		write_bits <<= shift;
+		write_bytes[out_byte_index] |= write_bits;
+		size_bits[0] = size_bits[0] + bit_cnt;
+	} else {
+		input_val.input8[1] = (unsigned char)write_bits + 256;
+		input_val.input16 >>= -shift;
+		write_bytes[out_byte_index] |= input_val.input8[1];
+
+		size_bits[0] = size_bits[0] + bit_cnt;
+		size_bits[0] = size_bits[0] - ((unsigned char)-shift);
+		input_val.input8[0] = input_val.input8[0] >> (8 + shift);
+		write_upto_8bits_to_elements(mtx_header, element_pointers, input_val.input8[0],
+					     (unsigned short)-shift);
+	}
+
+	return (unsigned int)bit_cnt;
+}
+
+unsigned int write_upto_32bits_to_elements(struct mtx_header_params *mtx_header,
+					   struct mtx_header_element **element_pointers,
+					   unsigned int write_bits, unsigned int bit_cnt)
+{
+	unsigned int bit_lp;
+	unsigned int end_byte;
+	unsigned char bytes[4];
+
+	for (bit_lp = 0; bit_lp < 4; bit_lp++) {
+		bytes[bit_lp] = (unsigned char)(write_bits & 255);
+		write_bits = write_bits >> 8;
+	}
+
+	end_byte = ((bit_cnt + 7) / 8);
+	if ((bit_cnt) % 8)
+		write_upto_8bits_to_elements(mtx_header, element_pointers, bytes[end_byte - 1],
+					     (unsigned char)((bit_cnt) % 8));
+	else
+		write_upto_8bits_to_elements(mtx_header, element_pointers, bytes[end_byte - 1], 8);
+
+	if (end_byte > 1)
+		for (bit_lp = end_byte - 1; bit_lp > 0; bit_lp--)
+			write_upto_8bits_to_elements(mtx_header, element_pointers,
+						     bytes[bit_lp - 1], 8);
+
+	return bit_cnt;
+}
+
+void h264_write_bits_startcode_prefix_element(struct mtx_header_params *mtx_header,
+					      struct mtx_header_element **element_pointers,
+	unsigned int byte_size)
+{
+	/* GENERATES THE FIRST ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE */
+	unsigned int lp;
+	/*
+	 * Byte aligned (bit 0)
+	 * (3 bytes in slice header when slice is first in
+	 * a picture without sequence/picture_header before picture
+	 */
+	for (lp = 0; lp < byte_size - 1; lp++)
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 8);
+
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 8);
+	/* Byte aligned (bit 32 or 24) */
+}
+
+unsigned int generate_ue(struct mtx_header_params *mtx_header,
+			 struct mtx_header_element **element_pointers, unsigned int val)
+{
+	unsigned int lp;
+	unsigned char zeros;
+	unsigned int chunk;
+	unsigned int bit_cnter = 0;
+
+	for (lp = 1, zeros = 0; (lp - 1) < val; lp = lp + lp, zeros++)
+		val = val - lp;
+
+	/*
+	 * zeros = number of preceding zeros required
+	 * Val = value to append after zeros and 1 bit
+	 * Write preceding zeros
+	 */
+	for (lp = (unsigned int)zeros; lp + 1 > 8; lp -= 8)
+		bit_cnter += write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 8);
+
+	/* Write zeros and 1 bit set */
+	bit_cnter +=
+		write_upto_8bits_to_elements(mtx_header, element_pointers, (unsigned char)1,
+					     (unsigned char)(lp + 1));
+
+	/* Write Numeric part  */
+	while (zeros > 8) {
+		zeros -= 8;
+		chunk = (val >> zeros);
+		bit_cnter += write_upto_8bits_to_elements(mtx_header, element_pointers,
+				(unsigned char)chunk, 8);
+		val = val - (chunk << zeros);
+	}
+
+	bit_cnter += write_upto_8bits_to_elements(mtx_header,
+				element_pointers, (unsigned char)val, zeros);
+
+	return bit_cnter;
+}
+
+unsigned int generate_se(struct mtx_header_params *mtx_header,
+			 struct mtx_header_element **element_pointers, int val)
+{
+	unsigned int bit_cnter;
+	unsigned int code_num;
+
+	bit_cnter = 0;
+
+	if (val > 0)
+		code_num = (unsigned int)(val + val - 1);
+	else
+		code_num = (unsigned int)(-val - val);
+
+	bit_cnter = generate_ue(mtx_header, element_pointers, code_num);
+
+	return bit_cnter;
+}
+
+void h264_write_bits_scaling_lists(struct mtx_header_params *mtx_header,
+				   struct mtx_header_element **element_pointers,
+				   struct h264_scaling_matrix_params *scaling_matrix,
+				   unsigned char write_8x8)
+{
+	/* Used by H264_WriteBits_SequenceHeader and H264_WriteBits_PictureHeader */
+	unsigned int list, index;
+	int cur_scale, delta_scale;
+
+	if (!scaling_matrix) {
+		insert_element_token(mtx_header, element_pointers, ELEMENT_CUSTOM_QUANT);
+		return;
+	}
+
+	for (list = 0; list < 6; list++) {
+		/* seq_scaling_list_present_flag[ui32List] = 1 */
+		if (scaling_matrix->list_mask & (1 << list)) {
+			write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+
+			cur_scale = 8;
+			for (index = 0; index < 16; index++) {
+				delta_scale =
+					((int)scaling_matrix->scaling_lists4x4[list][index]) -
+					cur_scale;
+				cur_scale += delta_scale;
+				/* delta_scale */
+				generate_se(mtx_header, element_pointers, delta_scale);
+			}
+		} else {
+			/* seq_scaling_list_present_flag[ui32List] = 0 */
+			write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+		}
+	}
+
+	if (!write_8x8)
+		return;
+
+	for (; list < 8; list++) {
+		/* seq_scaling_list_present_flag[ui32List] = 1 */
+		if (scaling_matrix->list_mask & (1 << list)) {
+			write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+
+			cur_scale = 8;
+			for (index = 0; index < 64; index++) {
+				delta_scale =
+					((int)scaling_matrix->scaling_lists8x8[list - 6][index]) -
+					cur_scale;
+				cur_scale += delta_scale;
+				/* delta_scale */
+				generate_se(mtx_header, element_pointers, delta_scale);
+			}
+		} else {
+			/* seq_scaling_list_present_flag[ui32List] = 0 */
+			write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+		}
+	}
+}
+
+void h264_write_bits_vui_params(struct mtx_header_params *mtx_header,
+				struct mtx_header_element **element_pointers,
+				struct h264_vui_params *vui_params)
+{
+	/* Builds VUI Params for the Sequence Header (only present in the 1st sequence of stream) */
+
+	if (vui_params->aspect_ratio_info_present_flag == 1) {
+		/* aspect_ratio_info_present_flag = 1 in Topaz */
+		write_upto_8bits_to_elements(mtx_header, element_pointers,
+					     vui_params->aspect_ratio_info_present_flag, 1);
+		/* aspect_ratio_idc (8 bits) = vui_params->aspect_ratio_idc in Topaz */
+		write_upto_8bits_to_elements(mtx_header, element_pointers,
+					     vui_params->aspect_ratio_idc, 8);
+
+		if (vui_params->aspect_ratio_idc == 255) {
+			write_upto_8bits_to_elements(mtx_header, element_pointers,
+						     (vui_params->sar_width >> 8), 8);
+			write_upto_8bits_to_elements(mtx_header, element_pointers,
+						     vui_params->sar_width, 8);
+			write_upto_8bits_to_elements(mtx_header, element_pointers,
+						     (vui_params->sar_height >> 8), 8);
+			write_upto_8bits_to_elements(mtx_header, element_pointers,
+						     vui_params->sar_height, 8);
+		}
+	} else {
+		/* aspect_ratio_info_present_flag = 0 in Topaz */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	}
+
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     /* overscan_info_present_flag (1 bit) = 0 in Topaz */
+				     (0 << 3) |
+				     /* video_signal_type_present_flag (1 bit) = 0 in Topaz */
+				     (0 << 2) |
+				     /* chroma_loc_info_present_flag (1 bit) = 0 in Topaz */
+				     (0 << 1) |
+				     /* timing_info_present_flag (1 bit) = 1 in Topaz */
+				     (1),
+				     /* num_units_in_tick (32 bits) = 1 in Topaz */
+				     4);
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 8);
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 8);
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 8);
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 8);
+
+	/* time_scale (32 bits) = frame rate */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 8);
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 8);
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 8);
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     (unsigned char)vui_params->time_scale, 8);
+	/* fixed_frame_rate_flag (1 bit) = 1 in Topaz */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+	/* nal_hrd_parameters_present_flag (1 bit) = 1 in Topaz */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+	/* Definitions for nal_hrd_parameters() contained in VUI structure for Topaz
+	 * cpb_cnt_minus1 ue(v) = 0 in Topaz = 1b
+	 */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+	/* bit_rate_scale (4 bits) = 0 in Topaz */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 4);
+	/* cpb_size_scale (4 bits) = 2 in Topaz */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 2, 4);
+	/* bit_rate_value_minus1[0] ue(v) = (Bitrate/64)-1 [RANGE:0 to (2^32)-2] */
+	generate_ue(mtx_header, element_pointers, vui_params->bit_rate_value_minus1);
+	/* cpb_size_value_minus1[0] ue(v) = (CPB_Bits_Size/16)-
+	 * 1 where CPB_Bits_Size = 1.5 * Bitrate  [RANGE:0 to (2^32)-2]
+	 */
+	generate_ue(mtx_header, element_pointers, vui_params->cbp_size_value_minus1);
+	/* cbr_flag[0] (1 bit) = 0 for VBR, 1 for CBR */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, vui_params->cbr, 1);
+	/*initial_cpb_removal_delay_length_minus1 (5 bits) */
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     vui_params->initial_cpb_removal_delay_length_minus1, 5);
+	/* cpb_removal_delay_length_minus1 (5 bits) */
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     vui_params->cpb_removal_delay_length_minus1, 5);
+	/* dpb_output_delay_length_minus1 (5 bits) */
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     vui_params->dpb_output_delay_length_minus1, 5);
+	/* time_offst_length (5 bits) */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, vui_params->time_offset_length,
+				     5);
+
+	/* End of nal_hrd_parameters() */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	/* low_delay_hrd_flag */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	/* pic_struct_present_flag (1 bit) = 0 in Topaz */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     /* bitstream_restriction_flag (1 bit) = 1 in Topaz */
+				     (1 << 1) |
+				     /* motion_vectors_over_pic_boundaries_flag (1 bit) = 1
+				      * in Topaz;
+				      */
+				     (1 << 0),
+				     2);
+	/* max_bytes_per_pic_denom ue(v) = 0 */
+	generate_ue(mtx_header, element_pointers, 0);
+	/* max_bits_per_mb_denom ue(v) = 0 */
+	generate_ue(mtx_header, element_pointers, 0);
+	/* log2_max_mv_length_horizontal ue(v) = 9(max horizontal vector is 128 integer samples) */
+	generate_ue(mtx_header, element_pointers, 9);
+	/* log2_max_mv_length_vertical ue(v) = 9 (max vertical vecotr is 103 integer samples) */
+	generate_ue(mtx_header, element_pointers, 9);
+	/* num_reorder_frames ue(v) = 0 */
+	generate_ue(mtx_header, element_pointers, vui_params->num_reorder_frames);
+	/* max_dec_frame_buffering ue(v) = 0 */
+	generate_ue(mtx_header, element_pointers, vui_params->max_dec_frame_buffering);
+}
+
+void h264_write_bits_sequence_header(struct mtx_header_params *mtx_header,
+				     struct mtx_header_element **element_pointers,
+				     struct h264_sequence_header_params *sh_params,
+				     struct h264_crop_params *crop,
+				     struct h264_scaling_matrix_params *scaling_matrix,
+				     unsigned char aso)
+{
+	/* calculate some of the VUI parameters here */
+	if (sh_params->profile == SH_PROFILE_BP) {
+		/* for Baseline profile we never re-roder frames */
+		sh_params->vui_params.num_reorder_frames = 0;
+		sh_params->vui_params.max_dec_frame_buffering = sh_params->max_num_ref_frames;
+	} else {
+		/* in higher profiles we can do up to 3 level hierarchical B frames */
+		if (!sh_params->vui_params.num_reorder_frames)
+			sh_params->vui_params.num_reorder_frames = sh_params->max_num_ref_frames;
+		sh_params->vui_params.max_dec_frame_buffering =
+						max(sh_params->max_num_ref_frames,
+						    sh_params->vui_params.num_reorder_frames);
+	}
+
+	insert_element_token(mtx_header, element_pointers, ELEMENT_STARTCODE_RAWDATA);
+	h264_write_bits_startcode_prefix_element(mtx_header, element_pointers, 4);
+
+	/* GENERATES THE FIRST ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE */
+	/*
+	 * 4 Byte StartCodePrefix Pregenerated in: H264_WriteBits_StartCodePrefix_Element()
+	 * Byte aligned (bit 32)
+	 * forbidden_zero_bit=0
+	 */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, (0 << 7) |
+		(0x3 << 5) |		/* nal_ref_idc=01 (may be 11) */
+		(7),			/* nal_unit_type=00111 */
+		8);
+
+	/* Byte aligned (bit 40) */
+	switch (sh_params->profile) {
+	case SH_PROFILE_BP:
+		/* profile_idc = 8 bits = 66 for BP (PROFILE_IDC_BP) */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 66, 8);
+
+		/* Byte	aligned	(bit 48) */
+		write_upto_8bits_to_elements(mtx_header, element_pointers,
+					     /* constraint_set0_flag = 1 for BP constra ints */
+					     (1 << 7) |
+					     /* constraint_set1_flag = 1 for MP constraints */
+					     ((aso ? 0 : 1) << 6) |
+					     /* constraint_set2_flag = 1 for EP constra ints */
+					     (1 << 5) |
+					     /* constraint_set3_flag = 1
+					      * for level 1b, 0 for others
+					      */
+					     ((sh_params->level == SH_LEVEL_1B ? 1 : 0) << 4),
+					     /* reserved_zero_4bits = 0 */
+					     8);
+		break;
+
+	case SH_PROFILE_MP:
+		/* profile_idc = 8 bits = 77 for MP (PROFILE_IDC_MP) */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 77, 8);
+
+		/* Byte	aligned	(bit 48) */
+		write_upto_8bits_to_elements(mtx_header, element_pointers,
+					     /* constraint_set0_flag = 0 for no BP constraints */
+					     (0 << 7) |
+					     /* constraint_set1_flag = 1 for MP constraints */
+					     (1 << 6) |
+					     /* constraint_set2_flag = 1 for EP constraints */
+					     (1 << 5) |
+					     /* constraint_set3_flag = 1
+					      * for level 1b, 0 for others
+					      */
+					     ((sh_params->level == SH_LEVEL_1B ? 1 : 0) << 4),
+					     /* reserved_zero_4bits = 0 */
+					     8);
+		break;
+
+	case SH_PROFILE_HP:
+		/* profile_idc = 8 bits = 100 for HP (PROFILE_IDC_HP) */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 100, 8);
+
+		/* Byte aligned (bit 48) */
+		write_upto_8bits_to_elements(mtx_header, element_pointers,
+					     /* constraint_set0_flag = 0 for no BP constraints */
+					     (0 << 7) |
+					     /* constraint_set1_flag = 0 for no MP constraints */
+					     (0 << 6) |
+					     /* constraint_set2_flag = 0 for no EP constraints */
+					     (0 << 5) |
+					     /* constraint_set3_flag = 0 */
+					     (0 << 4),
+					     /* reserved_zero_4bits = 0 */
+					     8);
+		break;
+
+	case SH_PROFILE_H444P:
+		/* profile_idc = 8 bits = 244 for H444P (PROFILE_IDC_H444P) */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 244, 8);
+
+		/* Byte aligned (bit 48) */
+		write_upto_8bits_to_elements(mtx_header, element_pointers,
+					     /* constraint_set0_flag = 0 for no BP constraints */
+					     (0 << 7) |
+					     /* constraint_set1_flag = 0 for no MP constraints */
+					     (0 << 6) |
+					     /* constraint_set2_flag = 0 for no EP constraints */
+					     (0 << 5) |
+					     /* constraint_set3_flag = 0 */
+					     (0 << 4),
+					     /* reserved_zero_4bits = 0 */
+					     8);
+		break;
+
+	default:
+		break;
+	}
+
+	/*
+	 * Byte aligned (bit 56)
+	 * level_idc should be set to 9 in the sps in case of
+	 * level is Level 1B and the profile is High or High 4:4:4 Profile
+	 */
+	if (sh_params->profile == SH_PROFILE_HP || sh_params->profile == SH_PROFILE_H444P)
+		/* level_idc (8 bits) = 9 for 1b, 10xlevel for others */
+		write_upto_8bits_to_elements(mtx_header, element_pointers,
+					     (sh_params->level == SH_LEVEL_1B) ? 9 :
+					     (unsigned char)sh_params->level, 8);
+
+	else
+		/* level_idc (8 bits) = 11 for 1b, 10xlevel for others */
+		write_upto_8bits_to_elements(mtx_header, element_pointers,
+					     (sh_params->level == SH_LEVEL_1B) ? 11 :
+					     (unsigned char)sh_params->level, 8);
+
+	generate_ue(mtx_header, element_pointers, 0);           /* seq_parameter_set_id = 0 */
+
+	if (sh_params->profile == SH_PROFILE_HP || sh_params->profile == SH_PROFILE_H444P) {
+		generate_ue(mtx_header, element_pointers, 1);           /* chroma_format_idc = 1 */
+		/* bit_depth_luma_minus8 = 0 */
+		generate_ue(mtx_header, element_pointers, 0);
+		/* bit_depth_chroma_minus8 = 0 */
+		generate_ue(mtx_header, element_pointers, 0);
+
+		write_upto_8bits_to_elements(mtx_header, element_pointers,
+					     /* qpprime_y_zero_transform_bypass_flag = 1
+					      * if lossless
+					      */
+					     sh_params->is_lossless ? 1 : 0, 1);
+
+		if (sh_params->use_default_scaling_list ||
+		    sh_params->seq_scaling_matrix_present_flag) {
+			/* seq_scaling_matrix_present_flag */
+			write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+			if (!sh_params->use_default_scaling_list) {
+				h264_write_bits_scaling_lists(mtx_header, element_pointers,
+							      scaling_matrix, TRUE);
+				insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+			} else {
+				/* seq_scaling_list_present_flag[i] = 0; 0 < i < 8 */
+				write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 8);
+			}
+		} else {
+			/* seq_scaling_matrix_present_flag */
+			write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+		}
+	}
+
+	generate_ue(mtx_header, element_pointers, 1);           /* log2_max_frame_num_minus4 = 1 */
+	generate_ue(mtx_header, element_pointers, 0);           /* pic_order_cnt_type = 0 */
+	/* log2_max_pic_order_cnt_Isb_minus4 = 2 */
+	generate_ue(mtx_header, element_pointers, sh_params->log2_max_pic_order_cnt - 4);
+	/*num_ref_frames ue(2), typically 2 */
+	generate_ue(mtx_header, element_pointers, sh_params->max_num_ref_frames);
+
+	/* Bytes aligned (bit 72) */
+	/* gaps_in_frame_num_value_allowed_Flag      - (1 bit) */
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     (sh_params->gaps_in_frame_num_value), 1);
+
+	/*
+	 * GENERATES THE SECOND, VARIABLE LENGTH, ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE
+	 * ELEMENT BITCOUNT: xx
+	 */
+	/*pic_width_in_mbs_minus1: ue(v) from 10 to 44 (176 to 720 pixel per row) */
+	generate_ue(mtx_header, element_pointers, sh_params->width_in_mbs_minus1);
+	/* pic_height_in_maps_units_minus1:
+	 * ue(v) Value from 8 to 35 (144 to 576 pixels per column)
+	 */
+	generate_ue(mtx_header, element_pointers, sh_params->height_in_maps_units_minus1);
+	/* We don't know the alignment at this point, so will have to use bit writing functions */
+	/* frame_mb_only_flag 1=frame encoding, 0=field encoding */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, sh_params->frame_mbs_only_flag,
+				     1);
+
+	if (!sh_params->frame_mbs_only_flag) /* in the case of interlaced encoding */
+	/* mb_adaptive_frame_field_flag = 0 in Topaz(field encoding at the sequence level) */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+
+	/* direct_8x8_inference_flag=1 in Topaz */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+
+	if (crop->clip) {
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+		generate_ue(mtx_header, element_pointers, crop->left_crop_offset);
+		generate_ue(mtx_header, element_pointers, crop->right_crop_offset);
+		generate_ue(mtx_header, element_pointers, crop->top_crop_offset);
+		generate_ue(mtx_header, element_pointers, crop->bottom_crop_offset);
+	} else {
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	}
+
+	/*
+	 * GENERATES THE THIRD ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE
+	 * ELEMENT BITCOUNT: xx
+	 */
+	/* vui_parameters_present_flag (VUI only in 1st sequence of stream) */
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     (sh_params->vui_params_present),
+		1);
+	if (sh_params->vui_params_present > 0)
+		h264_write_bits_vui_params(mtx_header, element_pointers, &sh_params->vui_params);
+
+	/* Finally we need to align to the next byte */
+	/* Tell MTX to insert the byte align field (we don't know
+	 * final stream size for alignment at this point)
+	 */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_INSERTBYTEALIGN_H264);
+}
+
+/*
+ * Prepare an H264 SPS in a form for the MTX to encode into a bitstream.
+ */
+void h264_prepare_sequence_header(struct mtx_header_params *mtx_header,
+				  unsigned int pic_width_in_mbs,
+				  unsigned int pic_height_in_mbs,
+				  unsigned char vui_params_present,
+				  struct h264_vui_params *params,
+				  struct h264_crop_params *crop,
+				  struct h264_sequence_header_params *sh_params,
+				  unsigned char aso)
+{
+	struct mtx_header_element *this_element;
+	struct mtx_header_element *element_pointers[MAXNUMBERELEMENTS];
+
+	/*
+	 * Builds a sequence, picture and slice header with from the given inputs
+	 * parameters (start of new frame) Essential we initialise our header
+	 * structures before building
+	 */
+	mtx_header->elements = ELEMENTS_EMPTY;
+	this_element = (struct mtx_header_element *)mtx_header->element_stream;
+	element_pointers[0] = this_element;
+
+	h264_write_bits_sequence_header(mtx_header, element_pointers, sh_params, crop, NULL, aso);
+	/*Has been used as an index, so need to add 1 for a valid element count */
+	mtx_header->elements++;
+}
+
+void h264_write_bits_picture_header(struct mtx_header_params *mtx_header,
+				    struct mtx_header_element **element_pointers,
+				    struct h264_picture_header_params *ph_params,
+				    struct h264_scaling_matrix_params *scaling_matrix)
+{
+	/* Begin building the picture header element */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_STARTCODE_RAWDATA);
+
+	h264_write_bits_startcode_prefix_element(mtx_header, element_pointers, 4);
+
+	/* GENERATES THE FIRST (STATIC) ELEMENT OF THE H264_PICTURE_HEADER() STRUCTURE
+	 * ELEMENT BITCOUNT: 18
+	 * 4 Byte StartCodePrefix Pregenerated in: H264_WriteBits_StartCodePrefix_Element()
+	 * Byte aligned (bit 32)
+	 */
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     (0 << 7) | /* forbidden_zero_bit */
+				     (1 << 5) | /* nal_ref_idc (2 bits) = 1 */
+				     (8),       /* nal_unit_tpye (5 bits) = 8 */
+				     8);
+
+	/* Byte aligned (bit 40) */
+	/* pic_parameter_set_id ue(v) */
+	generate_ue(mtx_header, element_pointers, ph_params->pic_parameter_set_id);
+	/* seq_parameter_set_id ue(v) */
+	generate_ue(mtx_header, element_pointers, ph_params->seq_parameter_set_id);
+
+	/* entropy_coding_mode_flag (1 bit) 0 for CAVLC */
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     (ph_params->entropy_coding_mode_flag << 4) |
+				     (0 << 3) |	/* pic_order_present_flag (1 bit) = 0 */
+				     (1 << 2) |	/* num_slice_group_minus1 ue(v) = 0 in Topaz */
+				     (1 << 1) | /* num_ref_idx_l0_active_minus1 ue(v) = 0 in Topaz*/
+				     (1),/* num_ref_idx_l1_active_minus1 ue(v) = 0 in Topaz */
+				     5);
+
+	/* WEIGHTED PREDICTION */
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     /* weighted_pred_flag (1 bit) */
+				     (ph_params->weighted_pred_flag << 2) |
+				     /* weighted_bipred_flag (2 bits) */
+				     (ph_params->weighted_bipred_idc), 3);
+
+	/*MTX fills this value in */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_QP);
+	insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+
+	/*
+	 * GENERATES THE SECOND ELEMENT OF THE H264_PICTURE_HEADER() STRUCTURE
+	 * ELEMENT BITCOUNT: 5
+	 * The following field will be generated as a special case by MTX - so not here
+	 * Generate_se(mtx_header, ph_params->pic_init_qp_minus26); pic_int_qp_minus26
+	 * se(v) = -26 to 25 in Topaz
+	 */
+	generate_se(mtx_header, element_pointers, 0); /* pic_int_qs_minus26 se(v) = 0 in Topaz */
+	/* chroma_qp_index_offset se(v) = 0 in Topaz */
+	generate_se(mtx_header, element_pointers, ph_params->chroma_qp_index_offset);
+	/* deblocking_filter_control_present_flag (1 bit) = 1 in Topaz */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, (1 << 2) |
+			/* constrained_intra_pred_Flag (1 bit) = 0 in Topaz */
+			(ph_params->constrained_intra_pred_flag << 1) |
+			/* redundant_pic_cnt_present_flag (1 bit) = 0 in Topaz */
+			(0),
+			3);
+
+	if (ph_params->transform_8x8_mode_flag ||
+	    ph_params->second_chroma_qp_index_offset != ph_params->chroma_qp_index_offset ||
+		ph_params->pic_scaling_matrix_present_flag) {
+		/* 8x8 transform flag */
+		write_upto_8bits_to_elements(mtx_header, element_pointers,
+					     ph_params->transform_8x8_mode_flag, 1);
+		if (ph_params->pic_scaling_matrix_present_flag) {
+			/* pic_scaling_matrix_present_flag */
+			write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+			if (!ph_params->use_default_scaling_list) {
+				h264_write_bits_scaling_lists(mtx_header, element_pointers,
+							      scaling_matrix,
+							      ph_params->transform_8x8_mode_flag);
+				insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+			} else {
+				unsigned char scaling_list_size =
+					ph_params->transform_8x8_mode_flag ? 8 : 6;
+
+				/* pic_scaling_list_present_flag[i] = 0;
+				 * 0 < i < 6 (+ 2 ( +4 for chroma444) for 8x8)
+				 */
+				write_upto_8bits_to_elements(mtx_header, element_pointers, 0,
+							     scaling_list_size);
+			}
+		} else {
+			/* pic_scaling_matrix_present_flag */
+			write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+		}
+		/* second_chroma_qp_index_offset se(v) = 0 in Topaz */
+		generate_se(mtx_header, element_pointers, ph_params->second_chroma_qp_index_offset);
+	}
+	/* Tell MTX to insert the byte align field (we don't know final
+	 * stream size for alignment at this point)
+	 */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_INSERTBYTEALIGN_H264);
+}
+
+/*
+ * Prepare an H264 PPS in a form for the MTX to encode into a bitstream
+ */
+void h264_prepare_picture_header(struct mtx_header_params *mtx_header,
+				 unsigned char cabac_enabled,
+				 unsigned char transform_8x8,
+				 unsigned char intra_constrained,
+				 signed char cqp_offset,
+				 unsigned char weighted_prediction,
+				 unsigned char weighted_bi_pred,
+				 unsigned char mvc_pps,
+				 unsigned char scaling_matrix,
+				 unsigned char scaling_lists)
+{
+	/*
+	 * Builds a picture header with from the given inputs parameters (start of new frame)
+	 * Essential we initialise our header structures before building
+	 */
+	struct h264_picture_header_params ph_params;
+	struct mtx_header_element *this_element;
+	struct mtx_header_element *element_pointers[MAXNUMBERELEMENTS];
+
+	mtx_header->elements = ELEMENTS_EMPTY;
+	this_element = (struct mtx_header_element *)mtx_header->element_stream;
+	element_pointers[0] = this_element;
+
+	ph_params.pic_parameter_set_id = mvc_pps ? MVC_PPS_ID : 0;
+	ph_params.seq_parameter_set_id = mvc_pps ? MVC_SPS_ID : 0;
+	ph_params.entropy_coding_mode_flag = cabac_enabled ? 1 : 0;
+	ph_params.weighted_pred_flag = weighted_prediction;
+	ph_params.weighted_bipred_idc = weighted_bi_pred;
+	ph_params.chroma_qp_index_offset = cqp_offset;
+	ph_params.constrained_intra_pred_flag = intra_constrained ? 1 : 0;
+	ph_params.transform_8x8_mode_flag = transform_8x8 ? 1 : 0;
+	ph_params.pic_scaling_matrix_present_flag = scaling_matrix ? 1 : 0;
+	ph_params.use_default_scaling_list = !scaling_lists;
+	ph_params.second_chroma_qp_index_offset = cqp_offset;
+
+	h264_write_bits_picture_header(mtx_header, element_pointers, &ph_params, NULL);
+	/*Has been used as an index, so need to add 1 for a valid element count */
+	mtx_header->elements++;
+}
+
+/* SEI_INSERTION */
+void h264_write_bits_aud_header(struct mtx_header_params *mtx_header,
+				struct mtx_header_element **element_pointers)
+{
+	/* Essential we insert the element before we try to fill it! */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_STARTCODE_RAWDATA);
+	/* 00 00 00 01 start code prefix */
+	h264_write_bits_startcode_prefix_element(mtx_header, element_pointers, 4);
+	/* AUD nal_unit_type = 09 */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 9, 8);
+
+	/* primary_pic_type	 u(3) 0=I slice, 1=P or I slice, 2=P,B or I slice */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 2, 3);
+	/* rbsp_trailing_bits */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 1 << 4, 5);
+
+	/* Write terminator */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0x80, 8);
+}
+
+void h264_prepare_aud_header(struct mtx_header_params *mtx_header)
+{
+	/* Essential we initialise our header structures before building */
+	struct mtx_header_element *this_element;
+	struct mtx_header_element *element_pointers[MAXNUMBERELEMENTS];
+
+	mtx_header->elements = ELEMENTS_EMPTY;
+	this_element = (struct mtx_header_element *)mtx_header->element_stream;
+	element_pointers[0] = this_element;
+
+	h264_write_bits_aud_header(mtx_header, element_pointers);
+	/*Has been used as an index, so need to add 1 for a valid element count */
+	mtx_header->elements++;
+}
+
+static void insert_prefix_nal_header(struct mtx_header_params *mtx_header,
+				     struct mtx_header_element **element_pointers,
+				     struct h264_slice_header_params *slh_params,
+				     unsigned char cabac_enabled)
+{
+	insert_element_token(mtx_header, element_pointers, ELEMENT_STARTCODE_RAWDATA);
+	/*Can be 3 or 4 bytes - always 4 bytes in our implementations */
+	h264_write_bits_startcode_prefix_element(mtx_header, element_pointers,
+						 slh_params->startcode_prefix_size_bytes);
+
+	insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+	/* forbidden_zero_bit */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	/*MTX fills this value in */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_REFERENCE);
+	insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+	/* nal unit type */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 14, 5);
+	/* SVC extension flag */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	/* non_idr_flag flag */
+	if (slh_params->slice_frame_type == SLHP_IDR_SLICEFRAME_TYPE)
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	else
+		/* non_idr_flag flag */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+	/* priority_id flag */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 6);
+	/* view_id flag */
+	write_upto_32bits_to_elements(mtx_header, element_pointers, 0, 10);
+	/* temporal_id flag */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_TEMPORAL_ID);
+	/* anchor_pic_flag */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_ANCHOR_PIC_FLAG);
+
+	insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+	/* interview flag */
+	if (slh_params->slice_frame_type == SLHP_B_SLICEFRAME_TYPE)
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	else
+		/* interview flag */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+	/* reserved one bit */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+}
+
+/* helper function to start new raw data block */
+static unsigned char start_next_rawdata_element = FALSE;
+static void check_start_rawdata_element(struct mtx_header_params *mtx_header,
+					struct mtx_header_element **element_pointers)
+{
+	if (start_next_rawdata_element) {
+		insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+		start_next_rawdata_element = FALSE;
+	}
+}
+
+void h264_write_bits_extension_slice_header(struct mtx_header_params *mtx_header,
+					    struct mtx_header_element **element_pointers,
+					    struct h264_slice_header_params *slh_params,
+					    unsigned char cabac_enabled,
+					    unsigned char is_idr)
+{
+	start_next_rawdata_element = FALSE;
+
+	insert_element_token(mtx_header, element_pointers, ELEMENT_STARTCODE_RAWDATA);
+	/*Can be 3 or 4 bytes - always 4 bytes in our implementations */
+	h264_write_bits_startcode_prefix_element(mtx_header, element_pointers,
+						 slh_params->startcode_prefix_size_bytes);
+
+	/* GENERATES THE FIRST ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE
+	 * ELEMENT BITCOUNT: 8
+
+	 * StartCodePrefix Pregenerated in: Build_H264_4Byte_StartCodePrefix_Element()
+	 * (4 or 3 bytes) (3 bytes when slice is first in a picture without
+	 * sequence/picture_header before picture Byte aligned (bit 32 or 24)
+	 * NOTE: Slice_Type and Frame_Type are always the same, hence slice_frame_type
+	 */
+	 /* forbidden_zero_bit */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	/*MTX fills this value in */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_REFERENCE);
+	insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+	/* nal_unit_type for coded_slice_extension */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 20, 5);
+	/* SVC extension flag */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+
+	if (slh_params->slice_frame_type == SLHP_IDR_SLICEFRAME_TYPE)
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+		/* non_idr_flag flag */
+	else if ((slh_params->slice_frame_type == SLHP_P_SLICEFRAME_TYPE) && is_idr)
+		/* non_idr_flag flag */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	else
+		/* non_idr_flag flag */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+	/* priority_id flag */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 6);
+	/* view_id = hardcoded to 1 for dependent view */
+	write_upto_32bits_to_elements(mtx_header, element_pointers, 1, 10);
+	/* temporal_id flag */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_TEMPORAL_ID);
+	/* anchor_pic_flag */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_ANCHOR_PIC_FLAG);
+
+	insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+	/* interview flag is always FALSE for dependent frames */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	/* reserved one bit */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+
+	/* slice header */
+	/*MTX fills this value in */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_CURRMBNR);
+
+	insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+
+	/* GENERATES THE SECOND ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE */
+
+	generate_ue(mtx_header, element_pointers,
+		    (unsigned int)((slh_params->slice_frame_type ==
+				   SLHP_IDR_SLICEFRAME_TYPE) ? SLHP_I_SLICEFRAME_TYPE :
+				   slh_params->slice_frame_type));
+	/*slice_type ue(v): 0 for P-slice, 1 for B-slice, 2 for I-slice */
+
+	/* pic_parameter_set_id = 1 for dependent view */
+	generate_ue(mtx_header, element_pointers, 1);
+
+	/* Insert token to tell MTX to insert frame_num */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_FRAME_NUM);
+	start_next_rawdata_element = TRUE;
+
+	if (slh_params->pic_interlace ||
+	    slh_params->slice_frame_type == SLHP_IDR_SLICEFRAME_TYPE) {
+		/* interlaced encoding */
+		if (slh_params->pic_interlace) {
+			check_start_rawdata_element(mtx_header, element_pointers);
+			/* field_pic_flag = 1 */
+			write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+			/* Insert token to tell MTX to insert BOTTOM_FIELD flag if required */
+			insert_element_token(mtx_header, element_pointers, ELEMENT_BOTTOM_FIELD);
+			start_next_rawdata_element = TRUE;
+		}
+	}
+
+	if (slh_params->slice_frame_type == SLHP_IDR_SLICEFRAME_TYPE || (is_idr)) {
+		check_start_rawdata_element(mtx_header, element_pointers);
+		/* idr_pic_id ue(v) = 0 (1b) in Topaz */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+	}
+	/* Insert token to tell MTX to insert pic_order_cnt_lsb */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_PIC_ORDER_CNT);
+	start_next_rawdata_element = TRUE;
+
+	if (slh_params->slice_frame_type == SLHP_B_SLICEFRAME_TYPE)
+		/* Insert token to tell MTX to insert direct_spatial_mv_pred_flag */
+		insert_element_token(mtx_header, element_pointers, ELEMENT_DIRECT_SPATIAL_MV_FLAG);
+
+	if (slh_params->slice_frame_type == SLHP_P_SLICEFRAME_TYPE) {
+		insert_element_token(mtx_header, element_pointers, ELEMENT_NUM_REF_IDX_ACTIVE);
+		start_next_rawdata_element = TRUE;
+	} else if (slh_params->slice_frame_type == SLHP_B_SLICEFRAME_TYPE) {
+		check_start_rawdata_element(mtx_header, element_pointers);
+		/* num_ref_idx_active_override_flag (1 bit) = 0 in Topaz */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	}
+
+	/* reference picture list modification */
+	if (slh_params->slice_frame_type != SLHP_I_SLICEFRAME_TYPE &&
+	    slh_params->slice_frame_type != SLHP_IDR_SLICEFRAME_TYPE) {
+		/* Insert token to tell MTX to insert BOTTOM_FIELD flag if required */
+		insert_element_token(mtx_header, element_pointers, ELEMENT_REORDER_L0);
+		start_next_rawdata_element = TRUE;
+	}
+
+	if (slh_params->slice_frame_type == SLHP_B_SLICEFRAME_TYPE) {
+		check_start_rawdata_element(mtx_header, element_pointers);
+		/* ref_pic_list_ordering_flag_l1 (1 bit) = 0, no reference
+		 * picture ordering in Topaz
+		 */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	}
+
+	if (slh_params->slice_frame_type == SLHP_IDR_SLICEFRAME_TYPE || (is_idr)) {
+		check_start_rawdata_element(mtx_header, element_pointers);
+		/* no_output_of_prior_pics_flag (1 bit) = 0 */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+		/* long_term_reference_flag (1 bit) = 0 */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	} else {
+		/*MTX fills this value in */
+		insert_element_token(mtx_header, element_pointers, ELEMENT_ADAPTIVE);
+		start_next_rawdata_element = TRUE;
+	}
+
+	if (cabac_enabled && (slh_params->slice_frame_type == SLHP_P_SLICEFRAME_TYPE ||
+			      slh_params->slice_frame_type == SLHP_B_SLICEFRAME_TYPE)) {
+		check_start_rawdata_element(mtx_header, element_pointers);
+		/* hard code cabac_init_idc value of 0 */
+		generate_ue(mtx_header, element_pointers, 0);
+	}
+
+	/*MTX fills this value in */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_SQP);
+	insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+
+	/* GENERATES ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE
+	 * ELEMENT BITCOUNT: 11
+	 */
+	/*disable_deblocking_filter_idc ue(v) = 2? */
+	generate_ue(mtx_header, element_pointers, slh_params->disable_deblocking_filter_idc);
+	if (slh_params->disable_deblocking_filter_idc != 1) {
+		/*slice_alpha_c0_offset_div2 se(v) = 0 (1b) in Topaz */
+		generate_se(mtx_header, element_pointers, slh_params->deb_alpha_offset_div2);
+		/*slice_beta_offset_div2 se(v) = 0 (1b) in Topaz */
+		generate_se(mtx_header, element_pointers, slh_params->deb_beta_offset_div2);
+	}
+	/*
+	 * num_slice_groups_minus1 ==0 in Topaz, so no slice_group_change_cycle field here
+	 * no byte alignment at end of slice headers
+	 */
+}
+
+void h264_write_bits_slice_header(struct mtx_header_params *mtx_header,
+				  struct mtx_header_element **element_pointers,
+				  struct h264_slice_header_params *slh_params,
+				  unsigned char cabac_enabled, unsigned char is_idr)
+{
+	start_next_rawdata_element = FALSE;
+	if (slh_params->mvc_view_idx == (unsigned short)(NON_MVC_VIEW)) {
+		insert_element_token(mtx_header, element_pointers, ELEMENT_STARTCODE_RAWDATA);
+	} else if (slh_params->mvc_view_idx == MVC_BASE_VIEW_IDX) {
+		insert_prefix_nal_header(mtx_header, element_pointers, slh_params, cabac_enabled);
+		insert_element_token(mtx_header, element_pointers, ELEMENT_STARTCODE_MIDHDR);
+	} else {
+		/*Insert  */
+		h264_write_bits_extension_slice_header(mtx_header, element_pointers,
+						       slh_params, cabac_enabled, is_idr);
+		return;
+	}
+
+	h264_write_bits_startcode_prefix_element(mtx_header, element_pointers,
+						 /*Can be 3 or 4 bytes - always 4
+						  * bytes in our implementations
+						  */
+						 slh_params->startcode_prefix_size_bytes);
+
+	/* GENERATES THE FIRST ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE
+	 * ELEMENT BITCOUNT: 8
+
+	 * StartCodePrefix Pregenerated in: Build_H264_4Byte_StartCodePrefix_Element()
+	 * (4 or 3 bytes) (3 bytes when slice is first in a picture without
+	 * sequence/picture_header before picture Byte aligned (bit 32 or 24)
+	 * NOTE: Slice_Type and Frame_Type are always the same, hence slice_frame_type
+	 */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);   /* forbidden_zero_bit */
+
+	/*MTX fills this value in */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_REFERENCE);
+	insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     /* nal_unit_tpye (5 bits) = I-frame IDR, and 1 for  rest */
+				     ((slh_params->slice_frame_type == SLHP_IDR_SLICEFRAME_TYPE ?
+				       5 : 1)), 5);
+
+	/*MTX fills this value in */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_CURRMBNR);
+
+	insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+
+	/* GENERATES THE SECOND ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE */
+
+	generate_ue(mtx_header, element_pointers,
+		    (unsigned int)((slh_params->slice_frame_type == SLHP_IDR_SLICEFRAME_TYPE) ?
+			/*slice_type ue(v): 0 for P-slice, 1 for B-slice, 2 for I-slice */
+				   SLHP_I_SLICEFRAME_TYPE : slh_params->slice_frame_type));
+
+	if (slh_params->mvc_view_idx != (unsigned short)(NON_MVC_VIEW))
+		/* pic_parameter_set_id = 0 */
+		generate_ue(mtx_header, element_pointers, slh_params->mvc_view_idx);
+	else
+		generate_ue(mtx_header, element_pointers, 0);  /* pic_parameter_set_id = 0 */
+	/* Insert token to tell MTX to insert frame_num */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_FRAME_NUM);
+
+	if (slh_params->pic_interlace ||
+	    slh_params->slice_frame_type == SLHP_IDR_SLICEFRAME_TYPE) {
+		insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+		/* interlaced encoding */
+		if (slh_params->pic_interlace) {
+			/* field_pic_flag = 1 */
+			write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+			/* Insert token to tell MTX to insert BOTTOM_FIELD flag if required */
+			insert_element_token(mtx_header, element_pointers, ELEMENT_BOTTOM_FIELD);
+			insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+		}
+
+		if (slh_params->slice_frame_type == SLHP_IDR_SLICEFRAME_TYPE)
+			/* idr_pic_id ue(v) */
+			insert_element_token(mtx_header, element_pointers, ELEMENT_IDR_PIC_ID);
+	}
+	/* Insert token to tell MTX to insert pic_order_cnt_lsb */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_PIC_ORDER_CNT);
+
+	if (slh_params->slice_frame_type == SLHP_B_SLICEFRAME_TYPE)
+		/* Insert token to tell MTX to insert direct_spatial_mv_pred_flag */
+		insert_element_token(mtx_header, element_pointers, ELEMENT_DIRECT_SPATIAL_MV_FLAG);
+
+	if (slh_params->slice_frame_type == SLHP_P_SLICEFRAME_TYPE) {
+		/* Insert token to tell MTX to insert override for number of active references */
+		insert_element_token(mtx_header, element_pointers, ELEMENT_NUM_REF_IDX_ACTIVE);
+	} else if (slh_params->slice_frame_type == SLHP_B_SLICEFRAME_TYPE) {
+		insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+		/* num_ref_idx_active_override_flag (1 bit) = 0 */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	}
+
+	if (slh_params->slice_frame_type != SLHP_I_SLICEFRAME_TYPE &&
+	    slh_params->slice_frame_type != SLHP_IDR_SLICEFRAME_TYPE) {
+		/* Insert token to tell MTX to insert reference list 0 reordering */
+		insert_element_token(mtx_header, element_pointers, ELEMENT_REORDER_L0);
+
+		if (slh_params->slice_frame_type == SLHP_B_SLICEFRAME_TYPE)
+			/* Insert token to tell MTX to insert reference list 1 reordering */
+			insert_element_token(mtx_header, element_pointers, ELEMENT_REORDER_L1);
+	}
+
+	/* WEIGHTED PREDICTION */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_SLICEWEIGHTEDPREDICTIONSTRUCT);
+	insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+
+	if (slh_params->reference_picture && slh_params->is_longterm_ref) {
+		/* adaptive_ref_pic_marking_mode_flag (1 bit) = 0 */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+
+		/* Clear any existing long-term reference */
+		/* memory_management_control_operation */
+		generate_ue(mtx_header, element_pointers, 5);
+
+		/* Allow a single long-term reference */
+		/* memory_management_control_operation */
+		generate_ue(mtx_header, element_pointers, 4);
+		/* max_long_term_frame_idx_plus1 */
+		generate_ue(mtx_header, element_pointers, 1);
+
+		/* Set current picture as the long-term reference */
+		/* memory_management_control_operation */
+		generate_ue(mtx_header, element_pointers, 6);
+		/* long_term_frame_idx */
+		generate_ue(mtx_header, element_pointers, 0);
+
+		/* End */
+		/* memory_management_control_operation */
+		generate_ue(mtx_header, element_pointers, 0);
+	} else {
+		/*MTX fills this value in */
+		insert_element_token(mtx_header, element_pointers, ELEMENT_ADAPTIVE);
+		insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+	}
+
+	if (cabac_enabled && (slh_params->slice_frame_type == SLHP_P_SLICEFRAME_TYPE ||
+			      slh_params->slice_frame_type == SLHP_B_SLICEFRAME_TYPE))
+		/* hard code cabac_init_idc value of 0 */
+		generate_ue(mtx_header, element_pointers, 0);
+
+	/*MTX fills this value in */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_SQP);
+	insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+
+	/* GENERATES ELEMENT OF THE H264_SLICE_HEADER() STRUCTURE
+	 * ELEMENT BITCOUNT: 11
+	 */
+		/*disable_deblocking_filter_idc ue(v) = 2? */
+	generate_ue(mtx_header, element_pointers, slh_params->disable_deblocking_filter_idc);
+	if (slh_params->disable_deblocking_filter_idc != 1) {
+		/*slice_alpha_c0_offset_div2 se(v) = 0 (1b) in Topaz */
+		generate_se(mtx_header, element_pointers, slh_params->deb_alpha_offset_div2);
+		/*slice_beta_offset_div2 se(v) = 0 (1b) in Topaz */
+		generate_se(mtx_header, element_pointers, slh_params->deb_beta_offset_div2);
+	}
+
+	/*
+	 * num_slice_groups_minus1 ==0 in Topaz, so no slice_group_change_cycle field here
+	 * no byte alignment at end of slice headers
+	 */
+}
+
+/*
+ * Prepare an H264 slice header in a form for the MTX to encode into a
+ * bitstream.
+ */
+void h264_prepare_slice_header(struct mtx_header_params *mtx_header,
+			       unsigned char intra_slice, unsigned char inter_b_slice,
+			       unsigned char disable_deblocking_filter_idc,
+			       unsigned int first_mb_address, unsigned int mb_skip_run,
+			       unsigned char cabac_enabled, unsigned char is_interlaced,
+			       unsigned char is_idr, unsigned short mvc_view_idx,
+			       unsigned char is_longterm_ref)
+{
+	struct h264_slice_header_params slh_params;
+	struct mtx_header_element *this_element;
+	struct mtx_header_element *element_pointers[MAXNUMBERELEMENTS];
+
+	slh_params.startcode_prefix_size_bytes  = 4;
+	/* pcb -  I think that this is more correct now  -- This should also
+	 * work for IDR-P frames which will be marked as SLHP_P_SLICEFRAME_TYPE
+	 */
+	slh_params.slice_frame_type = intra_slice ? (is_idr ? SLHP_IDR_SLICEFRAME_TYPE :
+						     SLHP_I_SLICEFRAME_TYPE) :
+						     (inter_b_slice ? SLHP_B_SLICEFRAME_TYPE :
+						      SLHP_P_SLICEFRAME_TYPE);
+
+	slh_params.first_mb_address = first_mb_address;
+	slh_params.disable_deblocking_filter_idc = (unsigned char)disable_deblocking_filter_idc;
+	slh_params.pic_interlace = is_interlaced;
+	slh_params.deb_alpha_offset_div2 = 0;
+	slh_params.deb_beta_offset_div2 = 0;
+	/* setup the new flags used for B frame as reference */
+	slh_params.reference_picture = inter_b_slice ? 0 : 1;
+	slh_params.mvc_view_idx = mvc_view_idx;
+	slh_params.is_longterm_ref = is_longterm_ref;
+	slh_params.log2_max_pic_order_cnt = 2;
+	slh_params.longterm_ref_num = 0;
+	slh_params.ref_is_longterm_ref[0] = 0;
+	slh_params.ref_longterm_ref_num[0] = 0;
+	slh_params.ref_is_longterm_ref[1] = 0;
+	slh_params.ref_longterm_ref_num[1] = 0;
+	/*
+	 * Builds a single slice header from the given parameters (mid frame)
+	 * Essential we initialise our header structures before building
+	 */
+	mtx_header->elements = ELEMENTS_EMPTY;
+	this_element = (struct mtx_header_element *)mtx_header->element_stream;
+	element_pointers[0] = this_element;
+
+	h264_write_bits_slice_header(mtx_header, element_pointers, &slh_params, cabac_enabled,
+				     is_idr);
+	/*Has been used as an index, so need to add 1 for a valid element count */
+	mtx_header->elements++;
+}
+
+/*
+ * PrepareEncodeSliceParams
+ */
+unsigned int prepare_encode_slice_params(void *enc_ctx, struct slice_params *slice_params,
+					 unsigned char is_intra, unsigned short current_row,
+					 unsigned char deblock_idc, unsigned short slice_height,
+					 unsigned char is_bpicture, unsigned char field_mode,
+					 int fine_y_search_size)
+{
+	struct img_enc_context *enc;
+	struct img_video_context *video;
+	unsigned int frame_store_format;
+	unsigned char swap_chromas;
+	unsigned int mbs_per_kick, kicks_per_slice;
+	unsigned int ipe_control;
+	enum img_ipe_minblock_size blk_sz;
+	struct img_mtx_video_context *mtx_enc_context = NULL;
+	unsigned char restrict_4x4_search_size;
+	unsigned int lritc_boundary;
+
+	if (!enc_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	enc = (struct img_enc_context *)enc_ctx;
+	video = enc->video;
+
+	if (video->mtx_enc_ctx_mem.cpu_virt)
+		mtx_enc_context = (struct img_mtx_video_context *)(&video->mtx_enc_ctx_mem);
+
+	/* We want multiple ones of these so we can submit multiple
+	 * slices without having to wait for the next
+	 */
+	slice_params->flags = 0;
+	ipe_control = video->ipe_control;
+
+	/* extract block size */
+	blk_sz = (enum img_ipe_minblock_size)F_EXTRACT(ipe_control, TOPAZHP_CR_IPE_BLOCKSIZE);
+
+	/* mask-out the block size bits from ipe_control */
+	ipe_control &= ~(F_MASK(TOPAZHP_CR_IPE_BLOCKSIZE));
+
+	switch (video->standard) {
+	case IMG_STANDARD_H264:
+		if (blk_sz > 2)
+			blk_sz = (enum img_ipe_minblock_size)2;
+		if (is_bpicture && blk_sz > 1)
+			blk_sz = (enum img_ipe_minblock_size)1;
+
+		if (video->mbps >= _1080P_30FPS)
+			ipe_control |= F_ENCODE(fine_y_search_size, TOPAZHP_CR_IPE_LRITC_BOUNDARY) |
+				F_ENCODE(fine_y_search_size, TOPAZHP_CR_IPE_Y_FINE_SEARCH);
+		else
+			ipe_control |= F_ENCODE(fine_y_search_size + 1,
+					TOPAZHP_CR_IPE_LRITC_BOUNDARY) |
+				F_ENCODE(fine_y_search_size, TOPAZHP_CR_IPE_Y_FINE_SEARCH);
+
+		if (video->limit_num_vectors)
+			ipe_control |= F_ENCODE(1, TOPAZHP_CR_IPE_MV_NUMBER_RESTRICTION);
+		break;
+	default:
+		break;
+	}
+
+	if (video->mbps >= _1080P_30FPS)
+		restrict_4x4_search_size = 1;
+	else
+		restrict_4x4_search_size = 0;
+
+	ipe_control |= F_ENCODE(blk_sz, TOPAZHP_CR_IPE_BLOCKSIZE);
+
+	lritc_boundary =
+		(blk_sz !=
+		BLK_SZ_16x16) ? (fine_y_search_size + (restrict_4x4_search_size ? 0 : 1)) : 1;
+	if (lritc_boundary > 3)
+		IMG_DBG_ASSERT(0);
+
+	/* Minimum sub block size to calculate motion vectors for. 0=16x16, 1=8x8, 2=4x4 */
+	ipe_control = F_INSERT(ipe_control, blk_sz, TOPAZHP_CR_IPE_BLOCKSIZE);
+	ipe_control = F_INSERT(ipe_control, fine_y_search_size, TOPAZHP_CR_IPE_Y_FINE_SEARCH);
+	ipe_control = F_INSERT(ipe_control, video->limit_num_vectors,
+			       TOPAZHP_CR_IPE_MV_NUMBER_RESTRICTION);
+
+	/* 8x8 search  */
+	ipe_control = F_INSERT(ipe_control, lritc_boundary, TOPAZHP_CR_IPE_LRITC_BOUNDARY);
+	ipe_control = F_INSERT(ipe_control, restrict_4x4_search_size ? 0 : 1,
+			       TOPAZHP_CR_IPE_4X4_SEARCH);
+
+	ipe_control = F_INSERT(ipe_control, video->high_latency, TOPAZHP_CR_IPE_HIGH_LATENCY);
+
+	slice_params->ipe_control = ipe_control;
+
+	if (!is_intra) {
+		if (is_bpicture)
+			slice_params->flags |= ISINTERB_FLAGS;
+		else
+			slice_params->flags |= ISINTERP_FLAGS;
+	}
+
+	if (video->multi_reference_p && !(is_intra || is_bpicture))
+		slice_params->flags |= ISMULTIREF_FLAGS;
+
+	if (video->spatial_direct && is_bpicture)
+		slice_params->flags |= SPATIALDIRECT_FLAGS;
+
+	if (is_intra) {
+		slice_params->slice_config = F_ENCODE(TOPAZHP_CR_SLICE_TYPE_I_SLICE,
+						      TOPAZHP_CR_SLICE_TYPE);
+	} else {
+		if (is_bpicture)
+			slice_params->slice_config = F_ENCODE(TOPAZHP_CR_SLICE_TYPE_B_SLICE,
+							      TOPAZHP_CR_SLICE_TYPE);
+		else /* p frame */
+			slice_params->slice_config = F_ENCODE(TOPAZHP_CR_SLICE_TYPE_P_SLICE,
+							      TOPAZHP_CR_SLICE_TYPE);
+	}
+
+	mbs_per_kick = video->kick_size;
+
+	/*
+	 * we need to figure out the number of kicks and mb's per kick to use.
+	 * on H.264 we will use a MB's per kick of basic unit
+	 * on other rc varients we will use mb's per kick of width
+	 */
+	kicks_per_slice = ((slice_height / 16) * (video->width / 16)) / mbs_per_kick;
+
+	IMG_DBG_ASSERT((kicks_per_slice * mbs_per_kick) ==
+		((slice_height / 16) * (video->width / 16)));
+
+	/*
+	 * need some sensible ones don't look to be implemented yet...
+	 * change per stream
+	 */
+	if (video->format == IMG_CODEC_UY0VY1_8888 || video->format == IMG_CODEC_VY0UY1_8888)
+		frame_store_format = 3;
+	else if ((video->format == IMG_CODEC_Y0UY1V_8888) ||
+		 (video->format == IMG_CODEC_Y0VY1U_8888))
+		frame_store_format = 2;
+	else if (video->format == IMG_CODEC_420_PL12 || video->format == IMG_CODEC_422_PL12 ||
+		 video->format == IMG_CODEC_420_PL12_PACKED ||
+		 video->format == IMG_CODEC_420_PL21_PACKED ||
+		 video->format == IMG_CODEC_420_PL21 || video->format == IMG_CODEC_422_PL21)
+		frame_store_format = 1;
+	else
+		frame_store_format = 0;
+
+	if (video->format == IMG_CODEC_VY0UY1_8888 || video->format == IMG_CODEC_Y0VY1U_8888 ||
+	    ((video->format == IMG_CODEC_420_PL21 ||
+	      video->format == IMG_CODEC_420_PL21_PACKED) && mtx_enc_context &&
+	     mtx_enc_context->scaler_setup.scaler_control == 0))
+		swap_chromas = 1;
+	else
+		swap_chromas = 0;
+
+	switch (video->standard) {
+	case IMG_STANDARD_H264:
+		/* H264 */
+		slice_params->seq_config = F_ENCODE(0, TOPAZHP_CR_TEMPORAL_PIC0_BELOW_IN_VALID) |
+			F_ENCODE(0, TOPAZHP_CR_TEMPORAL_PIC1_BELOW_IN_VALID) |
+			F_ENCODE(0, TOPAZHP_CR_ABOVE_OUT_OF_SLICE_VALID) |
+			F_ENCODE(1, TOPAZHP_CR_WRITE_TEMPORAL_PIC0_BELOW_VALID) |
+			F_ENCODE(0, TOPAZHP_CR_REF_PIC0_VALID) |
+			F_ENCODE(0, TOPAZHP_CR_REF_PIC1_VALID) |
+			F_ENCODE(!is_bpicture, TOPAZHP_CR_REF_PIC1_EQUAL_PIC0) |
+			F_ENCODE(field_mode ? 1 : 0, TOPAZHP_CR_FIELD_MODE) |
+			F_ENCODE(swap_chromas, TOPAZHP_CR_FRAME_STORE_CHROMA_SWAP) |
+			F_ENCODE(frame_store_format, TOPAZHP_CR_FRAME_STORE_FORMAT) |
+			F_ENCODE(TOPAZHP_CR_ENCODER_STANDARD_H264, TOPAZHP_CR_ENCODER_STANDARD) |
+			F_ENCODE(deblock_idc == 1 ? 0 : 1, TOPAZHP_CR_DEBLOCK_ENABLE);
+
+		if (video->rc_params.bframes) {
+			slice_params->seq_config |=
+				F_ENCODE(1, TOPAZHP_CR_WRITE_TEMPORAL_COL_VALID);
+			if ((slice_params->flags & ISINTERB_FLAGS) == ISINTERB_FLAGS)
+				slice_params->seq_config |= F_ENCODE(1,
+						TOPAZHP_CR_TEMPORAL_COL_IN_VALID);
+		}
+		if (!is_bpicture)
+			slice_params->seq_config |=
+				F_ENCODE(1, TOPAZHP_CR_WRITE_TEMPORAL_COL_VALID);
+		break;
+
+	default:
+		break;
+	}
+
+	if (is_bpicture) {
+		slice_params->seq_config |= F_ENCODE(0, TOPAZHP_CR_TEMPORAL_PIC1_BELOW_IN_VALID) |
+			F_ENCODE(0, TOPAZHP_CR_WRITE_TEMPORAL_PIC1_BELOW_VALID) |
+			F_ENCODE(1, TOPAZHP_CR_REF_PIC1_VALID) |
+			F_ENCODE(1, TOPAZHP_CR_TEMPORAL_COL_IN_VALID);
+	}
+
+	if (video->enable_sel_stats_flags & ESF_FIRST_STAGE_STATS)
+		slice_params->seq_config |= F_ENCODE(1, TOPAZHP_CR_WRITE_MB_FIRST_STAGE_VALID);
+
+	if (video->enable_sel_stats_flags & ESF_MP_BEST_MB_DECISION_STATS ||
+	    video->enable_sel_stats_flags & ESF_MP_BEST_MOTION_VECTOR_STATS) {
+		slice_params->seq_config |= F_ENCODE(1, TOPAZHP_CR_BEST_MULTIPASS_OUT_VALID);
+
+		if (!(video->enable_sel_stats_flags & ESF_MP_BEST_MOTION_VECTOR_STATS))
+			/* 64 Byte Best Multipass Motion Vector output disabled by default */
+			slice_params->seq_config |= F_ENCODE(1, TOPAZHP_CR_BEST_MVS_OUT_DISABLE);
+	}
+
+	if (video->enable_inp_ctrl)
+		slice_params->seq_config |= F_ENCODE(1, TOPAZHP_CR_MB_CONTROL_IN_VALID);
+
+	return 0;
+}
+
+/*
+ * Generates the slice params template
+ */
+void generate_slice_params_template(struct img_enc_context *enc,
+				    struct vidio_ddbufinfo *mem_info,
+				    enum img_frame_template_type slice_type,
+				    unsigned char is_interlaced, int fine_y_search_size)
+{
+	unsigned char is_intra = ((slice_type == IMG_FRAME_IDR) || (slice_type == IMG_FRAME_INTRA));
+	unsigned char is_bframe = (slice_type == IMG_FRAME_INTER_B);
+	unsigned char is_idr = ((slice_type == IMG_FRAME_IDR) ||
+			(slice_type == IMG_FRAME_INTER_P_IDR));
+	struct img_video_context *video = enc->video;
+	unsigned short mvc_view_idx = (unsigned short)(NON_MVC_VIEW);
+	/* Initialize Slice Params */
+	struct slice_params *slice_params_dest;
+	unsigned int slice_height = video->picture_height / video->slices_per_picture;
+
+	slice_height &= ~15;
+
+	slice_params_dest = (struct slice_params *)(mem_info->cpu_virt);
+
+	mvc_view_idx = video->mvc_view_idx;
+
+	prepare_encode_slice_params(enc, slice_params_dest, is_intra,
+				    0, video->deblock_idc, slice_height, is_bframe,
+				    is_interlaced, fine_y_search_size);
+
+	slice_params_dest->template_type = slice_type;
+
+	/* Prepare Slice Header Template */
+	switch (video->standard) {
+	case IMG_STANDARD_H264:
+		h264_prepare_slice_header(&slice_params_dest->slice_hdr_tmpl, is_intra,
+					  is_bframe, video->deblock_idc, 0, 0, video->cabac_enabled,
+					  is_interlaced, is_idr, mvc_view_idx, FALSE);
+		break;
+
+	default:
+		break;
+	}
+}
+
+void h264_write_bits_mvc_sequence_header(struct mtx_header_params *mtx_header,
+					 struct mtx_header_element **element_pointers,
+					 struct h264_sequence_header_params *sh_params,
+					 struct h264_crop_params *crop,
+					 struct h264_scaling_matrix_params *scaling_matrix)
+{
+	int view_idx = 0;
+	int num_views = MAX_MVC_VIEWS;
+
+	insert_element_token(mtx_header, element_pointers, ELEMENT_STARTCODE_RAWDATA);
+	h264_write_bits_startcode_prefix_element(mtx_header, element_pointers, 4);
+
+	/*
+	 * 4 Byte StartCodePrefix Pregenerated in: H264_WriteBits_StartCodePrefix_Element()
+	 * Byte aligned (bit 32)
+	 */
+	/* forbidden_zero_bit=0 */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, (0 << 7) |
+		(0x3 << 5) |				/* nal_ref_idc=01 (may be 11) */
+		(15),					/* nal_unit_type=15 */
+		8);
+
+	/*
+	 * Byte aligned (bit 40)
+	 * profile_idc = 8 bits = 66 for BP (PROFILE_IDC_BP), 77 for MP (PROFILE_IDC_MP)
+	 */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 118, 8);
+
+	/* Byte aligned (bit 48) */
+	/* constrain_set0_flag = 1 for MP + BP constraints */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, (0 << 7) |
+		(0 << 6) |		/* constrain_set1_flag  = 1 for MP + BP constraints */
+		(0 << 5) |		/* constrain_set2_flag = always 0 in BP/MP */
+		(0 << 4),		/* constrain_set3_flag = 1 for level 1b, 0 for others */
+		/* reserved_zero_4bits = 0 */
+		8);
+
+	/*
+	 * Byte aligned (bit 56)
+	 * level_idc should be set to 9 in the sps in case of level is Level 1B and the profile
+	 * is Multiview High or Stereo High profiles
+	 */
+	/* level_idc (8 bits) = 9 for 1b, 10xlevel for others */
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     (sh_params->level == SH_LEVEL_1B) ? 9 :
+				     (unsigned char)sh_params->level, 8);
+
+	/* seq_parameter_Set_id = 1 FOR subset-SPS */
+	generate_ue(mtx_header, element_pointers, MVC_SPS_ID);
+	generate_ue(mtx_header, element_pointers, 1);           /* chroma_format_idc = 1 */
+	generate_ue(mtx_header, element_pointers, 0);           /* bit_depth_luma_minus8 = 0 */
+	generate_ue(mtx_header, element_pointers, 0);           /* bit_depth_chroma_minus8 = 0 */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, sh_params->is_lossless ? 1 : 0,
+				     1);       /* qpprime_y_zero_transform_bypass_flag = 0 */
+
+	if (sh_params->use_default_scaling_list || sh_params->seq_scaling_matrix_present_flag) {
+		/* seq_scaling_matrix_present_flag */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+		if (!sh_params->use_default_scaling_list) {
+			h264_write_bits_scaling_lists(mtx_header, element_pointers, scaling_matrix,
+						      TRUE);
+			insert_element_token(mtx_header, element_pointers, ELEMENT_RAWDATA);
+		} else {
+			/* seq_scaling_list_present_flag[i] = 0; 0 < i < 8 */
+			write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 8);
+		}
+	} else {
+		/* seq_scaling_matrix_present_flag */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	}
+
+	generate_ue(mtx_header, element_pointers, 1);           /* log2_max_frame_num_minus4 = 1 */
+	generate_ue(mtx_header, element_pointers, 0);           /* pic_order_cnt_type = 0 */
+	/* log2_max_pic_order_cnt_Isb_minus4 = 2 */
+	generate_ue(mtx_header, element_pointers, 2);
+
+	/*num_ref_frames ue(2), typically 2 */
+	generate_ue(mtx_header, element_pointers, sh_params->max_num_ref_frames);
+	/* Bytes aligned (bit 72) */
+	/* gaps_in_frame_num_value_allowed_Flag   - (1 bit) */
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     sh_params->gaps_in_frame_num_value, 1);
+
+	/*
+	 * GENERATES THE SECOND, VARIABLE LENGTH, ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE
+	 * ELEMENT BITCOUNT: xx
+	 */
+	/*pic_width_in_mbs_minus1: ue(v) from 10 to 44 (176 to 720 pixel per row) */
+	generate_ue(mtx_header, element_pointers, sh_params->width_in_mbs_minus1);
+	/*pic_height_in_maps_units_minus1: ue(v) Value from 8 to 35 (144 to 576 pixels per column)
+	 */
+	generate_ue(mtx_header, element_pointers, sh_params->height_in_maps_units_minus1);
+	/* We don't know the alignment at this point, so will have to use bit writing functions */
+	/* frame_mb_only_flag 1=frame encoding, 0=field encoding */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, sh_params->frame_mbs_only_flag,
+				     1);
+
+	if (!sh_params->frame_mbs_only_flag) /* in the case of interlaced encoding */
+	/* mb_adaptive_frame_field_flag = 0 in Topaz(field encoding at the sequence level) */
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+
+	/* direct_8x8_inference_flag=1 in Topaz */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+
+	if (crop->clip) {
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1);
+		generate_ue(mtx_header, element_pointers, crop->left_crop_offset);
+		generate_ue(mtx_header, element_pointers, crop->right_crop_offset);
+		generate_ue(mtx_header, element_pointers, crop->top_crop_offset);
+		generate_ue(mtx_header, element_pointers, crop->bottom_crop_offset);
+
+	} else {
+		write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 1);
+	}
+
+	/*
+	 * GENERATES THE THIRD ELEMENT OF THE H264_SEQUENCE_HEADER() STRUCTURE
+	 * ELEMENT BITCOUNT: xx
+	 * vui_parameters_present_flag (VUI only in 1st sequence of stream)
+	 */
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     (sh_params->vui_params_present), 1);
+	if (sh_params->vui_params_present > 0)
+		h264_write_bits_vui_params(mtx_header, element_pointers, &sh_params->vui_params);
+
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 1, 1); /*bit_equal_to_one */
+
+	/* sequence parameter set MVC extension */
+	generate_ue(mtx_header, element_pointers, (num_views - 1));     /*num_views_minus1 */
+	for (view_idx = 0; view_idx < num_views; view_idx++)
+		generate_ue(mtx_header, element_pointers, view_idx);
+
+	/* anchor references */
+	for (view_idx = 1; view_idx < num_views; view_idx++) {
+		/* num_anchor_refs_l0  = 1; view-1 refers to view-0 */
+		generate_ue(mtx_header, element_pointers, 1);
+		generate_ue(mtx_header, element_pointers, 0);     /* anchor_ref_l0 = 0 */
+		generate_ue(mtx_header, element_pointers, 0);     /* num_anchor_refs_l1  = 0 */
+	}
+
+	/* non-anchor references */
+	for (view_idx = 1; view_idx < num_views; view_idx++) {
+		generate_ue(mtx_header, element_pointers, 1);     /* num_non_anchor_refs_l0  = 0 */
+		generate_ue(mtx_header, element_pointers, 0);     /* non_anchor_refs_l0  = 0 */
+		generate_ue(mtx_header, element_pointers, 0);     /* num_non_anchor_refs_l1  = 0 */
+	}
+
+	generate_ue(mtx_header, element_pointers, 0);/* num_level_values_signaled_minus1  = 0 */
+
+	/* level_idc should be set to 9 in the sps in case of level is
+	 * Level 1B and the profile is Multiview High or Stereo High profiles
+	 */
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     (sh_params->level == SH_LEVEL_1B) ? 9 :
+				     (unsigned char)sh_params->level,
+				     8);/* level_idc (8 bits) = 9 for 1b, 10xlevel for others */
+	generate_ue(mtx_header, element_pointers, 0);/* num_applicable_ops_minus1  = 0 */
+	/* applicable_ops_temporal_id  = 0 */
+	write_upto_8bits_to_elements(mtx_header, element_pointers, 0, 3);
+	/* applicable_op_num_target_views_minus1  = 0 */
+	generate_ue(mtx_header, element_pointers, 0);
+	generate_ue(mtx_header, element_pointers, 0);	/* applicable_op_target_view_id  = 0 */
+	generate_ue(mtx_header, element_pointers, 0);	/* applicable_op_num_views_minus1  = 0 */
+
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     0,                    /* mvc_vui_parameters_present_flag =0 */
+				     1);
+
+	write_upto_8bits_to_elements(mtx_header, element_pointers,
+				     0,                 /* additional_extension2_flag =0 */
+				     1);
+
+	/* Finally we need to align to the next byte */
+	/* Tell MTX to insert the byte align field
+	 *  (we don't know final stream size for alignment at this point)
+	 */
+	insert_element_token(mtx_header, element_pointers, ELEMENT_INSERTBYTEALIGN_H264);
+}
+
+/*
+ * Prepare an H264 SPS in a form for the MTX to encode into a bitstream.
+ */
+void h264_prepare_mvc_sequence_header(struct mtx_header_params *mtx_header,
+				      unsigned int pic_width_in_mbs,
+				      unsigned int pic_height_in_mbs,
+				      unsigned char vui_params_present,
+				      struct h264_vui_params *params,
+				      struct h264_crop_params *crop,
+				      struct h264_sequence_header_params *sh_params)
+{
+	struct mtx_header_element *this_element;
+	struct mtx_header_element *element_pointers[MAXNUMBERELEMENTS];
+
+	/*
+	 * Builds a sequence, picture and slice header with from the given inputs
+	 * parameters (start of new frame) Essential we initialise our header
+	 * structures before building
+	 */
+	mtx_header->elements = ELEMENTS_EMPTY;
+	this_element = (struct mtx_header_element *)mtx_header->element_stream;
+	element_pointers[0] = this_element;
+
+	h264_write_bits_mvc_sequence_header(mtx_header, element_pointers, sh_params, crop, NULL);
+	/* Has been used as an index, so need to add 1 for a valid element count */
+	mtx_header->elements++;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/header_gen.h b/drivers/media/platform/img/vxe-vxd/encoder/header_gen.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/header_gen.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/header_gen.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,111 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * encoder header generation interface header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include "fw_headers/topazscfwif.h"
+#include <linux/types.h>
+#include "topaz_api.h"
+#include "vid_buf.h"
+
+/*
+ * enum describing slice/frame type (H264)
+ */
+enum slhp_sliceframe_type {
+	SLHP_P_SLICEFRAME_TYPE,
+	SLHP_B_SLICEFRAME_TYPE,
+	SLHP_I_SLICEFRAME_TYPE,
+	SLHP_SP_SLICEFRAME_TYPE,
+	SLHP_SI_SLICEFRAME_TYPE,
+	SLHP_IDR_SLICEFRAME_TYPE,
+	SLHP_SLICE_FRAME_TYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * struct describing scaling lists (H264)
+ */
+struct h264_scaling_matrix_params {
+	unsigned char scaling_lists4x4[6][16];
+	unsigned char scaling_lists8x8[2][64];
+	unsigned int list_mask;
+};
+
+/*
+ * struct describing picture parameter set (H264)
+ */
+struct h264_picture_header_params {
+	unsigned char pic_parameter_set_id;
+	unsigned char seq_parameter_set_id;
+	unsigned char entropy_coding_mode_flag;
+	unsigned char weighted_pred_flag;
+	unsigned char weighted_bipred_idc;
+	signed char chroma_qp_index_offset;
+	unsigned char constrained_intra_pred_flag;
+	unsigned char transform_8x8_mode_flag;
+	unsigned char pic_scaling_matrix_present_flag;
+	unsigned char use_default_scaling_list;
+	signed char second_chroma_qp_index_offset;
+};
+
+/*
+ * struct describing slice header (H264)
+ */
+struct h264_slice_header_params {
+	unsigned char startcode_prefix_size_bytes;
+	enum slhp_sliceframe_type slice_frame_type;
+	unsigned int first_mb_address;
+	unsigned char log2_max_pic_order_cnt;
+	unsigned char disable_deblocking_filter_idc;
+	unsigned char pic_interlace;
+	unsigned char reference_picture;
+	signed char deb_alpha_offset_div2;
+	signed char deb_beta_offset_div2;
+	unsigned short mvc_view_idx;
+	unsigned char is_longterm_ref;
+	unsigned char longterm_ref_num;
+	/* Long term reference info for reference frames */
+	unsigned char ref_is_longterm_ref[2];
+	unsigned char ref_longterm_ref_num[2];
+};
+
+void generate_slice_params_template(struct img_enc_context *enc,
+				    struct vidio_ddbufinfo *mem_info,
+				    enum img_frame_template_type slice_type,
+				    unsigned char is_interlaced, int fine_y_search_size);
+
+void h264_prepare_sequence_header(struct mtx_header_params *mtx_header,
+				  unsigned int pic_width_in_mbs,
+				  unsigned int pic_height_in_mbs, unsigned char vui_params_present,
+				  struct h264_vui_params *params,
+				  struct h264_crop_params *crop,
+				  struct h264_sequence_header_params *sh_params,
+				  unsigned char aso);
+
+void h264_prepare_mvc_sequence_header(struct mtx_header_params *mtx_header,
+				      unsigned int pic_width_in_mbs, unsigned int pic_height_in_mbs,
+				      unsigned char vui_params_present,
+				      struct h264_vui_params *params,
+				      struct h264_crop_params *crop,
+				      struct h264_sequence_header_params *sh_params);
+
+void h264_prepare_aud_header(struct mtx_header_params *mtx_header);
+
+void h264_prepare_picture_header(struct mtx_header_params *mtx_header,
+				 unsigned char cabac_enabled,
+				 unsigned char transform_8x8,
+				 unsigned char intra_constrained,
+				 signed char cqp_offset,
+				 unsigned char weighted_prediction,
+				 unsigned char weighted_bi_pred,
+				 unsigned char mvc_pps,
+				 unsigned char scaling_matrix,
+				 unsigned char scaling_lists);
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/mtx_fwif.c b/drivers/media/platform/img/vxe-vxd/encoder/mtx_fwif.c
--- a/drivers/media/platform/img/vxe-vxd/encoder/mtx_fwif.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/mtx_fwif.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,990 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MTX Firmware Interface
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+
+#include "fw_headers/mtx_fwif.h"
+#include "fw_headers/defs.h"
+#include "fw_binaries/include_all_fw_variants.h"
+#include "img_errors.h"
+#include "reg_headers/mtx_regs.h"
+/* still used for DMAC regs */
+#include "reg_headers/img_soc_dmac_regs.h"
+#include "target_config.h"
+#include "topaz_device.h"
+#include "topazmmu.h"
+#include "vxe_public_regdefs.h"
+
+extern struct mem_space topaz_mem_space[];
+
+/*
+ * Static Function Decl
+ */
+static void mtx_get_mtx_ctrl_from_dash(struct img_fw_context *fw_ctx);
+
+static unsigned int mtx_read_core_reg(struct img_fw_context *fw_ctx,
+				      const unsigned int reg);
+
+static void mtx_write_core_reg(struct img_fw_context *fw_ctx,
+			       const unsigned int reg,
+			       const unsigned int val);
+
+static int mtx_select_fw_build(struct img_fw_context *fw_ctx, enum img_codec codec);
+
+static void mtx_reg_if_upload(struct img_fw_context *fw_ctx,
+			      const unsigned int data_mem, unsigned int addr,
+			      const unsigned int words, const unsigned int *const data);
+
+/*
+ * Polling Configuration for TAL
+ */
+#define TAL_REG_RD_WR_TRIES     1000 /* => try 1000 times before giving up */
+
+/*
+ * defines that should come from auto generated headers
+ */
+#define MTX_DMA_MEMORY_BASE (0x82880000)
+#define PC_START_ADDRESS    (0x80900000)
+
+#define MTX_CORE_CODE_MEM   (0x10)
+#define MTX_CORE_DATA_MEM   (0x18)
+
+#define MTX_PC              (0x05)
+
+/*
+ * Get control of the MTX.
+ * @Input    fw_ctx         : Pointer to the context of the target MTX
+ * @Return   None
+ */
+static void mtx_get_mtx_ctrl_from_dash(struct img_fw_context *fw_ctx)
+{
+	unsigned int reg = 0;
+
+	IMG_DBG_ASSERT(!fw_ctx->drv_has_mtx_ctrl);
+
+	/* Request the bus from the Dash...*/
+	reg = F_ENCODE(1, TOPAZHP_TOP_CR_MTX_MSTR_DBG_IS_SLAVE) |
+		       F_ENCODE(0x2, TOPAZHP_TOP_CR_MTX_MSTR_DBG_GPIO_IN);
+	VXE_WR_REG32(fw_ctx->topaz_multicore_reg_addr, TOPAZHP_TOP_CR_MTX_DEBUG_MSTR, reg);
+
+	do {
+		reg = VXE_RD_REG32(fw_ctx->topaz_multicore_reg_addr, TOPAZHP_TOP_CR_MTX_DEBUG_MSTR);
+
+	} while ((reg & 0x18) != 0);
+
+	/* Save the access control register...*/
+	fw_ctx->drv_has_mtx_ctrl = VXE_RD_REG32(fw_ctx->mtx_reg_mem_space_addr,
+						MTX_CR_MTX_RAM_ACCESS_CONTROL);
+
+	fw_ctx->drv_has_mtx_ctrl = TRUE;
+}
+
+/*
+ * Release control of the MTX.
+ * @Input    fw_ctx         : Pointer to the context of the target MTX
+ * @Return   None
+ */
+static void mtx_release_mtx_ctrl_from_dash(struct img_fw_context *fw_ctx)
+{
+	unsigned int reg = 0;
+
+	IMG_DBG_ASSERT(fw_ctx->drv_has_mtx_ctrl);
+
+	/* Restore the access control register...*/
+	VXE_WR_REG32(fw_ctx->mtx_reg_mem_space_addr, MTX_CR_MTX_RAM_ACCESS_CONTROL,
+		     fw_ctx->access_control);
+
+	/* Release the bus...*/
+	reg = F_ENCODE(1, TOPAZHP_TOP_CR_MTX_MSTR_DBG_IS_SLAVE);
+	VXE_WR_REG32(fw_ctx->topaz_multicore_reg_addr, TOPAZHP_TOP_CR_MTX_DEBUG_MSTR, reg);
+
+	fw_ctx->drv_has_mtx_ctrl = FALSE;
+}
+
+/*
+ * Read an MTX register.
+ * @Input    fw_ctx         : Pointer to the context of the target MTX
+ * @Input    reg : Offset of register to read
+ * @Return   unsigned int       : Register value
+ */
+static unsigned int mtx_read_core_reg(struct img_fw_context *fw_ctx, const unsigned int reg)
+{
+	unsigned int ret = 0;
+
+	mtx_get_mtx_ctrl_from_dash(fw_ctx);
+
+	/* Issue read request */
+	VXE_WR_REG32(fw_ctx->mtx_reg_mem_space_addr, MTX_CR_MTX_REGISTER_READ_WRITE_REQUEST,
+		     MASK_MTX_MTX_RNW | (reg & ~MASK_MTX_MTX_DREADY));
+
+	/* Wait for done */
+	VXE_POLL_REG32_ISEQ(fw_ctx->mtx_reg_mem_space_addr,
+			    MTX_CR_MTX_REGISTER_READ_WRITE_REQUEST,
+			    MASK_MTX_MTX_DREADY,
+			    MASK_MTX_MTX_DREADY,
+			    TAL_REG_RD_WR_TRIES);
+
+	/* Read */
+	ret = VXE_RD_REG32(fw_ctx->mtx_reg_mem_space_addr, MTX_CR_MTX_REGISTER_READ_WRITE_DATA);
+
+	mtx_release_mtx_ctrl_from_dash(fw_ctx);
+
+	return ret;
+}
+
+/*
+ * Write an MTX register.
+ * @Input    fw_ctx         : Pointer to the context of the target MTX
+ * @Input    reg : Offset of register to write
+ * @Input    val : Value to write to register
+ */
+static void mtx_write_core_reg(struct img_fw_context *fw_ctx,
+			       const unsigned int reg, const unsigned int val)
+{
+	mtx_get_mtx_ctrl_from_dash(fw_ctx);
+
+	/* Put data in MTX_RW_DATA */
+	VXE_WR_REG32(fw_ctx->mtx_reg_mem_space_addr, MTX_CR_MTX_REGISTER_READ_WRITE_DATA, val);
+
+	/* DREADY is set to 0 and request a write*/
+	VXE_WR_REG32(fw_ctx->mtx_reg_mem_space_addr, MTX_CR_MTX_REGISTER_READ_WRITE_REQUEST,
+		     (reg & ~MASK_MTX_MTX_DREADY));
+
+	/* Wait for DREADY to become set*/
+	VXE_POLL_REG32_ISEQ(fw_ctx->mtx_reg_mem_space_addr,
+			    MTX_CR_MTX_REGISTER_READ_WRITE_REQUEST,
+			    MASK_MTX_MTX_DREADY,
+			    MASK_MTX_MTX_DREADY,
+			    TAL_REG_RD_WR_TRIES);
+
+	mtx_release_mtx_ctrl_from_dash(fw_ctx);
+}
+
+/* ****** Utility macroses for `mtx_select_fw_build` ************** */
+
+#if FW_BIN_FORMAT_VERSION != 2
+#       error Unsupported firmware format version
+#endif
+
+/*
+ * Assign a firmware binary to an MTX.
+ * @Input    fw_ctx         : Pointer to the context of the target MTX
+ * @Input    codec           : Firmware version to use
+ */
+static int mtx_select_fw_build(struct img_fw_context *fw_ctx, enum img_codec codec)
+{
+	unsigned char *fmt, *rc_mode;
+	unsigned int target_fw_pipes = 0;
+	unsigned int codec_mask = 0;
+	unsigned int cur_hw_config;
+	unsigned char force_specific_pipe_cnt = FALSE;
+
+#       define HW_CONFIG_ALL_FEATURES 0
+#       define HW_CONFIG_8CONTEXT         1
+
+#define CORE_REV_CONFIG_1_MIN 0x00030906
+#define CORE_REV_CONFIG_1_MAX 0x0003090a
+
+#       define CODEC_MASK_JPEG          0x0001
+#       define CODEC_MASK_MPEG2         0x0002
+#       define CODEC_MASK_MPEG4         0x0004
+#       define CODEC_MASK_H263          0x0008
+#       define CODEC_MASK_H264          0x0010
+#       define CODEC_MASK_H264MVC       0x0020
+#       define CODEC_MASK_VP8           0x0040
+#       define CODEC_MASK_H265          0x0080
+#       define CODEC_MASK_FAKE          0x007F
+
+#define _MVC_CODEC_CASE(RC) { case IMG_CODEC_H264MVC_ ## RC: fmt = "H264MVC"; rc_mode = #RC; \
+	force_specific_pipe_cnt = TRUE; codec_mask = CODEC_MASK_H264MVC; break; }
+
+	switch (codec) {
+	case IMG_CODEC_H264_NO_RC:
+	case IMG_CODEC_H264_VBR:
+	case IMG_CODEC_H264_CBR:
+
+	case IMG_CODEC_H264_VCM:
+		fmt = "H264";
+		rc_mode = "ALL";
+		force_specific_pipe_cnt = TRUE;
+		codec_mask = CODEC_MASK_H264;
+	break;
+	case IMG_CODEC_H263_NO_RC:
+	case IMG_CODEC_H263_VBR:
+	case IMG_CODEC_H263_CBR:
+		fmt = "LEGACY_VIDEO";
+		rc_mode = "ALL";
+		codec_mask = CODEC_MASK_H263;
+	break;
+	case IMG_CODEC_MPEG2_NO_RC:
+	case IMG_CODEC_MPEG2_VBR:
+	case IMG_CODEC_MPEG2_CBR:
+		fmt = "LEGACY_VIDEO";
+		rc_mode = "ALL";
+		codec_mask = CODEC_MASK_MPEG2;
+	break;
+	case IMG_CODEC_MPEG4_NO_RC:
+	case IMG_CODEC_MPEG4_VBR:
+	case IMG_CODEC_MPEG4_CBR:
+		fmt = "LEGACY_VIDEO";
+		rc_mode = "ALL";
+		codec_mask = CODEC_MASK_MPEG4;
+	break;
+	_MVC_CODEC_CASE(NO_RC);
+	_MVC_CODEC_CASE(VBR);
+	_MVC_CODEC_CASE(CBR);
+	_MVC_CODEC_CASE(ERC);
+	case IMG_CODEC_JPEG:
+		fmt = "JPEG";
+		rc_mode = "NO_RC";
+		codec_mask = CODEC_MASK_JPEG;
+	break;
+	default:
+		pr_err("Failed to locate firmware for codec %d\n", codec);
+		return IMG_ERROR_UNDEFINED;
+	}
+#undef _MVC_CODEC_CASE
+
+	/* rc mode name fix */
+	if (strcmp(rc_mode, "NO_RC") == 0)
+		rc_mode = "NONE";
+
+	{
+		/*
+		 * Pick firmware type (done implicitly via determining number
+		 * of pipes given firmware is expected to have
+		 */
+		const unsigned int core_id = fw_ctx->core_rev;
+#define  IS_REV(name) ((core_id >= MIN_ ## name ## _REV) && \
+	(core_id <= MAX_ ## name ## _REV))
+
+		if (core_id >= CORE_REV_CONFIG_1_MIN && core_id <= CORE_REV_CONFIG_1_MAX) {
+			/*
+			 * For now, it is assumed that this revision ID means 8
+			 * context 2 pipe variant
+			 */
+			cur_hw_config = HW_CONFIG_8CONTEXT;
+			target_fw_pipes = 2;
+		} else {
+			cur_hw_config = HW_CONFIG_ALL_FEATURES;
+			if (fw_ctx->hw_num_pipes < 3 && force_specific_pipe_cnt)
+				target_fw_pipes = 2;
+			else
+				target_fw_pipes = 4;
+		}
+#undef IS_REV
+	}
+
+	{
+		/* Search for matching firmwares */
+
+		unsigned int fmts_included = 0;
+		unsigned int ii;
+		unsigned char preferred_fw_located = FALSE;
+		unsigned int req_size = 0;
+		struct IMG_COMPILED_FW_BIN_RECORD *selected, *iter;
+
+		selected = NULL;
+
+		for (ii = 0; ii < all_fw_binaries_cnt; ii++) {
+			iter = all_fw_binaries[ii];
+			/*
+			 * With HW_3_6, we want to allow 3 pipes if it was
+			 * required, this is mainly for test purposes
+			 */
+			if ((strcmp("JPEG_H264", iter->fmt) == 0) && target_fw_pipes != 3) {
+				preferred_fw_located = TRUE;
+				req_size = (4 * iter->data_size + (iter->data_origin -
+								   MTX_DMA_MEMORY_BASE));
+				break;
+			}
+		}
+
+		if (preferred_fw_located && req_size <= fw_ctx->mtx_ram_size &&
+		    cur_hw_config == iter->hw_config && iter->pipes >= target_fw_pipes &&
+		    (codec_mask == CODEC_MASK_JPEG || codec_mask == CODEC_MASK_H264) &&
+		    ((iter->formats_mask & codec_mask) != 0)) {
+			selected = iter;
+		} else {
+			for (ii = 0; ii < all_fw_binaries_cnt; ii++) {
+				iter = all_fw_binaries[ii];
+				/* The hardware config modes need to match */
+				if (cur_hw_config != iter->hw_config) {
+					pr_err("cur_hw_config %x iter->hw_config %x mismatch\n",
+					       cur_hw_config, iter->hw_config);
+					continue;
+				}
+
+				fmts_included = iter->formats_mask;
+
+				if (((fmts_included & codec_mask) != 0) &&
+				    (codec_mask == CODEC_MASK_JPEG ||
+					 /* no need to match RC for JPEG */
+					strcmp(rc_mode, iter->rc_mode) == 0)) {
+					/*
+					 * This firmware matches by format/mode
+					 * combination, now to check if it fits
+					 * better than current best
+					 */
+					if (!selected && iter->pipes >= target_fw_pipes) {
+						/*
+						 * Select firmware ether if it
+						 * is first matchin one we've
+						 * encountered or if it better
+						 * matches desired number of
+						 * pipes.
+						 */
+						selected = iter;
+					}
+
+					if (iter->pipes == target_fw_pipes) {
+						/* Found ideal firmware version */
+						selected = iter;
+						break;
+					}
+				}
+			}
+		}
+
+		if (!selected) {
+			pr_err("Failed to locate firmware for format '%s' and RC mode '%s'.\n",
+			       fmt, rc_mode);
+			return IMG_ERROR_UNDEFINED;
+		}
+#ifdef DEBUG_ENCODER_DRIVER
+		pr_info("Using firmware: %s with %i pipes, hwconfig=%i (text size = %i, data size = %i) for requested codec: %s RC mode %s\n",
+			selected->fmt, selected->pipes,
+			selected->hw_config, selected->text_size,
+			selected->data_size, fmt, rc_mode);
+#endif
+
+		/* Export selected firmware to the fw context */
+		fw_ctx->mtx_topaz_fw_text_size = selected->text_size;
+		fw_ctx->mtx_topaz_fw_data_size = selected->data_size;
+		fw_ctx->mtx_topaz_fw_text = selected->text;
+		fw_ctx->mtx_topaz_fw_data = selected->data;
+		fw_ctx->mtx_topaz_fw_data_origin = selected->data_origin;
+		fw_ctx->num_pipes = selected->pipes;
+		fw_ctx->int_defines.length = selected->int_define_cnt;
+		fw_ctx->int_defines.names = selected->int_define_names;
+		fw_ctx->int_defines.values = selected->int_defines;
+		fw_ctx->supported_codecs = selected->formats_mask;
+		fw_ctx->num_contexts = mtx_get_fw_config_int(fw_ctx, "TOPAZHP_MAX_NUM_STREAMS");
+	}
+	return IMG_SUCCESS;
+}
+
+/*
+ * Upload MTX text and data sections via register interface
+ * @Input    fw_ctx         : Pointer to the context of the target MTX
+ * @Input    data_mem : RAM ID for text/data section
+ * @Input    address : Address to upload data to
+ * @Input    words : Number of words of data to upload
+ * @Input    data : Pointer to data to upload
+ */
+static void mtx_reg_if_upload(struct img_fw_context *fw_ctx, const unsigned int data_mem,
+			      unsigned int address, const unsigned int words,
+			      const unsigned int *const data)
+{
+	unsigned int loop;
+	unsigned int ctrl;
+	unsigned int ram_id;
+	unsigned int addr;
+	unsigned int curr_bank = ~0;
+	unsigned int uploaded = 0;
+
+	mtx_get_mtx_ctrl_from_dash(fw_ctx);
+
+	VXE_POLL_REG32_ISEQ(fw_ctx->mtx_reg_mem_space_addr,
+			    MTX_CR_MTX_RAM_ACCESS_STATUS,
+			    MASK_MTX_MTX_MTX_MCM_STAT,
+			    MASK_MTX_MTX_MTX_MCM_STAT,
+			    TAL_REG_RD_WR_TRIES);
+
+	for (loop = 0; loop < words; loop++) {
+		ram_id = data_mem + (address / fw_ctx->mtx_bank_size);
+		if (ram_id != curr_bank) {
+			addr = address >> 2;
+			ctrl = 0;
+			ctrl = F_ENCODE(ram_id, MTX_MTX_MCMID) |
+				F_ENCODE(addr, MTX_MTX_MCM_ADDR) |
+				F_ENCODE(1, MTX_MTX_MCMAI);
+			VXE_WR_REG32(fw_ctx->mtx_reg_mem_space_addr,
+				     MTX_CR_MTX_RAM_ACCESS_CONTROL, ctrl);
+			curr_bank = ram_id;
+		}
+		address += 4;
+
+		if (uploaded > (1024 * 24)) /* should this be RAM bank size?? */
+			break;
+		uploaded += 4;
+
+		VXE_WR_REG32(fw_ctx->mtx_reg_mem_space_addr,
+			     MTX_CR_MTX_RAM_ACCESS_DATA_TRANSFER,
+			     data[loop]);
+
+		VXE_POLL_REG32_ISEQ(fw_ctx->mtx_reg_mem_space_addr,
+				    MTX_CR_MTX_RAM_ACCESS_STATUS,
+				    MASK_MTX_MTX_MTX_MCM_STAT,
+				    MASK_MTX_MTX_MTX_MCM_STAT,
+				    TAL_REG_RD_WR_TRIES);
+	}
+
+	mtx_release_mtx_ctrl_from_dash(fw_ctx);
+}
+
+/*
+ * Transfer memory between the Host and MTX via DMA.
+ * @Input    fw_ctx         : Pointer to the context of the target MTX
+ * @Input    channel          : DMAC channel to use (0 for TopazSC)
+ * @Input    hHostMemTransfer : void * for the host memory
+ * @Input    hostMemOffset    : offset into the host memory
+ * @Input    mtx_addr : Address on MTX
+ * @Input    numWords         : size of transfer in 32-bit words (PW units)
+ * @Input    bRNW             : Read not Write (FALSE to write to the MTX)
+ */
+void mtx_dmac_transfer(struct img_fw_context *fw_ctx, unsigned int channel,
+		       struct vidio_ddbufinfo *host_mem_transfer,
+		       unsigned int host_mem_offset, unsigned int mtx_addr,
+		       unsigned int words, unsigned char rnw)
+{
+	unsigned int irq_stat;
+	unsigned int count_reg;
+	void *dmac_reg_addr;
+	void *reg_addr;
+	unsigned int config_reg;
+	unsigned int mmu_status = 0;
+
+	unsigned int dmac_burst_size = DMAC_BURST_2; /* 2 * 128 bits = 32 bytes */
+	unsigned int mtx_burst_size = 4; /* 4 * 2 * 32 bits = 32 bytes */
+
+	/* check the burst sizes */
+	IMG_DBG_ASSERT(dmac_burst_size * 16 == MTX_DMA_BURSTSIZE_BYTES);
+	IMG_DBG_ASSERT(mtx_burst_size * 8 == MTX_DMA_BURSTSIZE_BYTES);
+
+	/* check transfer size matches burst width */
+	IMG_DBG_ASSERT(0 == (words & ((MTX_DMA_BURSTSIZE_BYTES >> 2) - 1)));
+
+	/* check DMA channel */
+	IMG_DBG_ASSERT(channel < DMAC_MAX_CHANNELS);
+
+	/* check that no transfer is currently in progress */
+	dmac_reg_addr = (void *)topaz_mem_space[REG_DMAC].cpu_addr;
+	count_reg = VXE_RD_REG32(dmac_reg_addr, IMG_SOC_DMAC_COUNT(channel));
+	IMG_DBG_ASSERT(0 == (count_reg &
+		(MASK_IMG_SOC_EN | MASK_IMG_SOC_LIST_EN)));
+
+	/* check we don't already have a page fault condition */
+	reg_addr = (void *)topaz_mem_space[REG_TOPAZHP_MULTICORE].cpu_addr;
+	mmu_status = VXE_RD_REG32(reg_addr, TOPAZHP_TOP_CR_MMU_STATUS);
+
+	IMG_DBG_ASSERT(mmu_status == 0);
+
+	if (mmu_status || (count_reg & (MASK_IMG_SOC_EN |
+					MASK_IMG_SOC_LIST_EN))) {
+		/* DMA engine not idle or pre-existing page fault condition */
+		pr_err("DMA engine not idle or pre-existing page fault condition!\n");
+		fw_ctx->initialized = FALSE;
+		return;
+	}
+
+	/* clear status of any previous interrupts */
+	VXE_WR_REG32(dmac_reg_addr, IMG_SOC_DMAC_IRQ_STAT(channel), 0);
+
+	/* and that no interrupts are outstanding */
+	irq_stat = VXE_RD_REG32(dmac_reg_addr, IMG_SOC_DMAC_IRQ_STAT(channel));
+	IMG_DBG_ASSERT(irq_stat == 0);
+
+	/* Write MTX DMAC registers (for current MTX) */
+	/* MTX Address */
+	VXE_WR_REG32(fw_ctx->mtx_reg_mem_space_addr, MTX_CR_MTX_SYSC_CDMAA,
+		     mtx_addr);
+
+	/* MTX DMAC Config */
+	config_reg = F_ENCODE(mtx_burst_size, MTX_BURSTSIZE) |
+		F_ENCODE((rnw ? 1 : 0), MTX_RNW) |
+		F_ENCODE(1, MTX_ENABLE) |
+		F_ENCODE(words, MTX_LENGTH);
+	VXE_WR_REG32(fw_ctx->mtx_reg_mem_space_addr, MTX_CR_MTX_SYSC_CDMAC,
+		     config_reg);
+
+	/* Write System DMAC registers */
+	/* per hold - allow HW to sort itself out */
+	VXE_WR_REG32(dmac_reg_addr, IMG_SOC_DMAC_PER_HOLD(channel), 16);
+
+	VXE_WR_REG32(dmac_reg_addr, IMG_SOC_DMAC_SETUP(channel),
+		     host_mem_transfer->dev_virt + host_mem_offset);
+
+	/* count reg */
+	count_reg = DMAC_VALUE_COUNT(DMAC_BSWAP_NO_SWAP, DMAC_PWIDTH_32_BIT,
+				     rnw, DMAC_PWIDTH_32_BIT, words);
+	count_reg |= MASK_IMG_SOC_TRANSFER_IEN; /* generate an interrupt at end of transfer */
+	VXE_WR_REG32(dmac_reg_addr, IMG_SOC_DMAC_COUNT(channel), count_reg);
+
+	/* don't inc address, set burst size */
+	VXE_WR_REG32(dmac_reg_addr, IMG_SOC_DMAC_PERIPH(channel),
+		     DMAC_VALUE_PERIPH_PARAM(DMAC_ACC_DEL_0, FALSE, dmac_burst_size));
+
+	/* Target correct MTX DMAC port */
+	VXE_WR_REG32(dmac_reg_addr, IMG_SOC_DMAC_PERIPHERAL_ADDR(channel),
+		     MTX_CR_MTX_SYSC_CDMAT + REG_START_TOPAZ_MTX_HOST);
+
+	/*
+	 * Finally, rewrite the count register with the enable bit set to kick
+	 * off the transfer
+	 */
+	VXE_WR_REG32(dmac_reg_addr, IMG_SOC_DMAC_COUNT(channel),
+		     (count_reg | MASK_IMG_SOC_EN));
+
+	/* Wait for it to finish */
+	VXE_POLL_REG32_ISEQ(dmac_reg_addr, IMG_SOC_DMAC_IRQ_STAT(channel),
+			    F_ENCODE(1, IMG_SOC_TRANSFER_FIN),
+		F_ENCODE(1, IMG_SOC_TRANSFER_FIN),
+		TAL_REG_RD_WR_TRIES);
+	count_reg = VXE_RD_REG32(dmac_reg_addr, IMG_SOC_DMAC_COUNT(channel));
+	mmu_status = VXE_RD_REG32(reg_addr, TOPAZHP_TOP_CR_MMU_STATUS);
+	if (mmu_status || (count_reg &
+				(MASK_IMG_SOC_EN | MASK_IMG_SOC_LIST_EN))) {
+		pr_err("DMA has failed or page faulted\n");
+		/* DMA has failed or page faulted */
+		fw_ctx->initialized = FALSE;
+	}
+
+	/* Clear the interrupt */
+	VXE_WR_REG32(dmac_reg_addr, IMG_SOC_DMAC_IRQ_STAT(channel), 0);
+}
+
+/*
+ * Sets target MTX for DMA and register writes
+ * @Input    fw_ctx         : Pointer to the context of the target MTX
+ * @Input    bTargetAll       : TRUE indicates register and DMA writes go to all MTX
+ */
+void mtx_set_target(struct img_fw_context *fw_ctx)
+{
+	unsigned int reg = 0;
+
+	reg = F_ENCODE(0, TOPAZHP_TOP_CR_WRITES_CORE_ALL);
+	VXE_WR_REG32(fw_ctx->topaz_multicore_reg_addr,
+		     TOPAZHP_TOP_CR_MULTICORE_CORE_SEL_0, reg);
+}
+
+/*
+ * Upload text and data sections via DMA
+ * @Input    fw_ctx         : Pointer to the context of the target MTX
+ */
+static void mtx_uploadfw(void *dev_ctx, struct img_fw_context *fw_ctx)
+{
+	struct topaz_dev_ctx *ctx = (struct topaz_dev_ctx *)dev_ctx;
+	struct vidio_ddbufinfo text, data;
+	void *add_lin_text, *add_lin_data;
+	unsigned int text_size = fw_ctx->mtx_topaz_fw_text_size;
+	unsigned int data_size = fw_ctx->mtx_topaz_fw_data_size;
+
+	if (topaz_mmu_alloc(ctx->topaz_mmu_ctx.mmu_context_handle,
+			    ctx->vxe_arg, MMU_GENERAL_HEAP_ID, 1,
+			    (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+				    SYS_MEMATTRIB_WRITECOMBINE),
+			    text_size * 4 + MTX_DMA_BURSTSIZE_BYTES, 64, &text)) {
+		pr_err("mmu_alloc for text failed!\n");
+		fw_ctx->initialized = FALSE;
+		return;
+	}
+	if (topaz_mmu_alloc(ctx->topaz_mmu_ctx.mmu_context_handle,
+			    ctx->vxe_arg, MMU_GENERAL_HEAP_ID, 1,
+			    (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+				    SYS_MEMATTRIB_WRITECOMBINE),
+			    data_size * 4 + MTX_DMA_BURSTSIZE_BYTES, 64, &data)) {
+		pr_err("mmu_alloc for data failed!\n");
+		topaz_mmu_free(ctx->vxe_arg, &text);
+		fw_ctx->initialized = FALSE;
+	}
+
+	add_lin_text = text.cpu_virt;
+	memcpy((void *)add_lin_text, fw_ctx->mtx_topaz_fw_text, text_size * 4);
+	add_lin_data = data.cpu_virt;
+	memcpy((void *)add_lin_data, fw_ctx->mtx_topaz_fw_data, data_size * 4);
+
+	topaz_update_device_mem(ctx->vxe_arg, &text);
+	topaz_update_device_mem(ctx->vxe_arg, &data);
+
+	/* adjust transfer sizes of text and data sections to match burst size */
+	text_size =
+		((text_size * 4 + (MTX_DMA_BURSTSIZE_BYTES - 1)) & ~(MTX_DMA_BURSTSIZE_BYTES - 1)) /
+		4;
+	data_size =
+		((data_size * 4 + (MTX_DMA_BURSTSIZE_BYTES - 1)) & ~(MTX_DMA_BURSTSIZE_BYTES - 1)) /
+		4;
+
+	/* ensure that data section (+stack) will not wrap in memory */
+	IMG_DBG_ASSERT(fw_ctx->mtx_ram_size >=
+		(fw_ctx->mtx_topaz_fw_data_origin + (data_size * 4) - MTX_DMA_MEMORY_BASE));
+	if (fw_ctx->mtx_ram_size <
+		(fw_ctx->mtx_topaz_fw_data_origin + (data_size * 4) - MTX_DMA_MEMORY_BASE))
+		fw_ctx->initialized = FALSE;
+
+	/* data section is already prepared/cached */
+	/* Transfer the text section */
+	if (fw_ctx->initialized) {
+		mtx_dmac_transfer(fw_ctx, 0, &text, 0, MTX_DMA_MEMORY_BASE,
+				  text_size, FALSE);
+	}
+	/* Transfer the data section */
+	if (fw_ctx->initialized) {
+		mtx_dmac_transfer(fw_ctx, 0, &data, 0,
+				  fw_ctx->mtx_topaz_fw_data_origin, data_size,
+				  FALSE);
+	}
+
+	topaz_mmu_free(ctx->vxe_arg, &text);
+	topaz_mmu_free(ctx->vxe_arg, &data);
+
+	/* Flush the MMU table cache used during code download */
+	topaz_core_mmu_flush_cache();
+#ifdef DEBUG_ENCODER_DRIVER
+	if (fw_ctx->initialized)
+		pr_info("%s complete!\n", __func__);
+#endif
+}
+
+/*
+ * Load text and data sections onto an MTX.
+ * @Input    fw_ctx         : Pointer to the context of the target MTX
+ * @Input    load_method      : Method to use for loading code
+ * @Input    bTargetAll       : Load to one (FALSE) or all (TRUE) MTX
+ */
+void mtx_load(void *dev_ctx, struct img_fw_context *fw_ctx,
+	      enum mtx_load_method load_method)
+{
+	struct topaz_dev_ctx *ctx = (struct topaz_dev_ctx *)dev_ctx;
+	unsigned int reg;
+	unsigned short i;
+
+	IMG_DBG_ASSERT(fw_ctx->initialized);
+	if (!fw_ctx->initialized)
+		return;
+
+	fw_ctx->load_method = load_method;
+
+	/* set target to current or all MTXs */
+	mtx_set_target(fw_ctx);
+
+	/* MTX Reset */
+	VXE_WR_REG32(fw_ctx->mtx_reg_mem_space_addr, MTX_CR_MTX_SOFT_RESET,
+		     MASK_MTX_MTX_RESET);
+	ndelay(300);
+
+	switch (load_method) {
+	case MTX_LOADMETHOD_REGIF:
+		/* Code Upload */
+		mtx_reg_if_upload(fw_ctx, MTX_CORE_CODE_MEM, 0,
+				  fw_ctx->mtx_topaz_fw_text_size,
+				  fw_ctx->mtx_topaz_fw_text);
+
+		/* Data Upload */
+		mtx_reg_if_upload(fw_ctx, MTX_CORE_DATA_MEM,
+				  fw_ctx->mtx_topaz_fw_data_origin - MTX_DMA_MEMORY_BASE,
+				  fw_ctx->mtx_topaz_fw_data_size,
+				  fw_ctx->mtx_topaz_fw_data);
+		break;
+
+	case MTX_LOADMETHOD_DMA:
+		mtx_uploadfw(ctx, fw_ctx);
+		break;
+
+	case MTX_LOADMETHOD_NONE:
+		break;
+
+	default:
+		IMG_DBG_ASSERT(FALSE);
+	}
+
+	/* if we have had any failures up to this point then return now */
+	if (!fw_ctx->initialized)
+		return;
+
+	if (load_method != MTX_LOADMETHOD_NONE) {
+		for (i = 5; i < 8; i++)
+			mtx_write_core_reg(fw_ctx, 0x1 | (i << 4), 0);
+
+		/* Restore 8 Registers of D1 Bank */
+		/* D1Re0, D1Ar5, D1Ar3, D1Ar1, D1RtP, D1.5, D1.6 and D1.7 */
+		for (i = 5; i < 8; i++)
+			mtx_write_core_reg(fw_ctx, 0x2 | (i << 4), 0);
+
+		/* Set Starting PC address */
+		mtx_write_core_reg(fw_ctx, MTX_PC, PC_START_ADDRESS);
+
+		/* Verify Starting PC */
+		reg = mtx_read_core_reg(fw_ctx, MTX_PC);
+
+#ifdef DEBUG_ENCODER_DRIVER
+		pr_info("PC_START_ADDRESS = 0x%08X\n", reg);
+#endif
+		IMG_DBG_ASSERT(reg == PC_START_ADDRESS);
+	}
+}
+
+/*
+ * Deinitialise the given MTX context structure
+ * @Input    fw_ctx         : Pointer to the context of the target MTX
+ */
+void mtx_deinitialize(struct img_fw_context *fw_ctx)
+{
+	struct topaz_dev_ctx *ctx = (struct topaz_dev_ctx *)fw_ctx->dev_ctx;
+	unsigned int i;
+
+	if (!fw_ctx->initialized)
+		pr_warn("Warning detected multi de-initialiseations\n");
+
+	for (i = 0; i < TOPAZHP_MAX_POSSIBLE_STREAMS; i++) {
+		if (fw_ctx->mtx_context_data_copy[i])
+			topaz_mmu_free(ctx->vxe_arg, fw_ctx->mtx_context_data_copy[i]);
+		fw_ctx->mtx_context_data_copy[i] = NULL;
+	}
+
+	kfree(fw_ctx->mtx_reg_copy);
+	fw_ctx->mtx_reg_copy = NULL;
+	fw_ctx->initialized = FALSE;
+}
+
+/*
+ * Initialise the given MTX context structure
+ * @Input    fw_ctx       : Pointer to the context of the target MTX
+ * @Input    core_num : Core number of the MTX to target
+ * @Input    codec         : version of codec specific firmware to associate with this MTX
+ */
+int mtx_populate_fw_ctx(enum img_codec codec, struct img_fw_context *fw_ctx)
+{
+	unsigned int pipe_cnt;
+	unsigned int size;
+	unsigned int i;
+
+	if (fw_ctx->initialized || fw_ctx->populated)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	/* initialise Context structure */
+	fw_ctx->mtx_reg_mem_space_addr = (void *)topaz_mem_space[REG_MTX].cpu_addr;
+	fw_ctx->topaz_multicore_reg_addr = (void *)topaz_mem_space[REG_TOPAZHP_MULTICORE].cpu_addr;
+
+	fw_ctx->core_rev = VXE_RD_REG32(fw_ctx->topaz_multicore_reg_addr,
+					TOPAZHP_TOP_CR_TOPAZHP_CORE_REV);
+	fw_ctx->core_rev &= (MASK_TOPAZHP_TOP_CR_TOPAZHP_MAINT_REV |
+			     MASK_TOPAZHP_TOP_CR_TOPAZHP_MINOR_REV |
+			     MASK_TOPAZHP_TOP_CR_TOPAZHP_MAJOR_REV);
+	fw_ctx->core_des1 = VXE_RD_REG32(fw_ctx->topaz_multicore_reg_addr,
+					 TOPAZHP_TOP_CR_TOPAZHP_CORE_DES1);
+
+	/* Number of hw pipes */
+	pipe_cnt = VXE_RD_REG32(fw_ctx->topaz_multicore_reg_addr, TOPAZHP_TOP_CR_MULTICORE_HW_CFG);
+	pipe_cnt = (pipe_cnt & MASK_TOPAZHP_TOP_CR_NUM_CORES_SUPPORTED);
+	fw_ctx->hw_num_pipes = pipe_cnt;
+
+	IMG_DBG_ASSERT(fw_ctx->hw_num_pipes > 0 && fw_ctx->hw_num_pipes <= TOPAZHP_MAX_NUM_PIPES);
+
+	if (fw_ctx->hw_num_pipes <= 0 || fw_ctx->hw_num_pipes > TOPAZHP_MAX_NUM_PIPES)
+		return IMG_ERROR_INVALID_ID;
+
+	for (i = 0; i < fw_ctx->hw_num_pipes; i++)
+		fw_ctx->topaz_reg_mem_space_addr[i] =
+			(void *)topaz_mem_space[REG_TOPAZHP_CORE_0 + (4 * i)].cpu_addr;
+
+	fw_ctx->mtx_debug_val = VXE_RD_REG32(fw_ctx->topaz_multicore_reg_addr,
+					     TOPAZHP_TOP_CR_MTX_DEBUG_MSTR);
+
+	/* last bank size */
+	size = 0x1 <<
+		(F_EXTRACT(fw_ctx->mtx_debug_val, TOPAZHP_TOP_CR_MTX_MSTR_LAST_RAM_BANK_SIZE) + 2);
+	/* all other banks */
+	fw_ctx->mtx_bank_size = 0x1 <<
+		(F_EXTRACT(fw_ctx->mtx_debug_val, TOPAZHP_TOP_CR_MTX_MSTR_RAM_BANK_SIZE) + 2);
+	/* total RAM size */
+	fw_ctx->mtx_ram_size = size +
+		(fw_ctx->mtx_bank_size *
+		(F_EXTRACT(fw_ctx->mtx_debug_val, TOPAZHP_TOP_CR_MTX_MSTR_RAM_BANKS) - 1));
+
+	fw_ctx->drv_has_mtx_ctrl = FALSE;
+	fw_ctx->access_control = 0;
+
+	fw_ctx->active_ctx_mask = 0;
+
+	if (mtx_select_fw_build(fw_ctx, codec) != IMG_SUCCESS) {
+		fw_ctx->populated = FALSE;
+		fw_ctx->initialized = FALSE;
+		return IMG_ERROR_UNDEFINED;
+	}
+
+	if (fw_ctx->mtx_topaz_fw_data_size != 0) {
+		/* check FW fits in memory */
+		/* could also add stack size estimate */
+		size = 4 * fw_ctx->mtx_topaz_fw_data_size;
+		size += (fw_ctx->mtx_topaz_fw_data_origin - MTX_DMA_MEMORY_BASE);
+		if (size > fw_ctx->mtx_ram_size) {
+			IMG_DBG_ASSERT(fw_ctx->mtx_ram_size > size);
+			return IMG_ERROR_OUT_OF_MEMORY;
+		}
+	}
+
+	fw_ctx->populated = TRUE;
+	return IMG_SUCCESS;
+}
+
+void mtx_initialize(void *dev_ctx, struct img_fw_context *fw_ctx)
+{
+	struct topaz_dev_ctx *ctx = (struct topaz_dev_ctx *)dev_ctx;
+	unsigned int i = 0;
+
+	if (fw_ctx->initialized)
+		return;
+
+	if (fw_ctx->mtx_topaz_fw_data_size != 0) {
+		fw_ctx->mtx_reg_copy = kmalloc((53 * 4), GFP_KERNEL);
+		for (i = 0; i < TOPAZHP_MAX_POSSIBLE_STREAMS; i++) {
+			fw_ctx->mtx_context_data_copy[i] = kmalloc
+							(sizeof(*fw_ctx->mtx_context_data_copy[i]),
+								GFP_KERNEL);
+			if (!fw_ctx->mtx_context_data_copy[i])
+				goto alloc_failed;
+
+			if (topaz_mmu_alloc(ctx->topaz_mmu_ctx.mmu_context_handle,
+					    ctx->vxe_arg, MMU_GENERAL_HEAP_ID, 1,
+					    (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						    SYS_MEMATTRIB_WRITECOMBINE),
+					    MTX_CONTEXT_SIZE, 64,
+					    fw_ctx->mtx_context_data_copy[i])) {
+				pr_err("mmu_alloc for data copy failed!\n");
+				kfree(fw_ctx->mtx_context_data_copy[i]);
+				fw_ctx->mtx_context_data_copy[i] = NULL;
+				goto alloc_failed;
+			}
+		}
+
+		fw_ctx->dev_ctx = dev_ctx;
+		fw_ctx->initialized = TRUE;
+	}
+
+	return;
+
+alloc_failed:
+	while (i > 0) {
+		topaz_mmu_free(ctx->vxe_arg, fw_ctx->mtx_context_data_copy[i - 1]);
+		kfree(fw_ctx->mtx_context_data_copy[i - 1]);
+		fw_ctx->mtx_context_data_copy[i - 1] = NULL;
+		i--;
+	}
+}
+
+int mtx_get_fw_config_int(struct img_fw_context const * const fw_ctx,
+			  unsigned char const * const name)
+{
+	const unsigned long max_len = 1024;
+	unsigned int ii;
+
+	if (fw_ctx->mtx_topaz_fw_data_size == 0) {
+		IMG_DBG_ASSERT("FW context structure is not initialised!" == NULL);
+		return -1;
+	}
+
+	for (ii = 0; ii < fw_ctx->int_defines.length; ii++) {
+		if (strncmp(fw_ctx->int_defines.names[ii], name, max_len) == 0)
+			return fw_ctx->int_defines.values[ii];
+	}
+
+	return -1;
+}
+
+/*
+ * Start an MTX.
+ * @Input    fw_ctx       : Pointer to the context of the target MTX
+ */
+void mtx_start(struct img_fw_context *fw_ctx)
+{
+	IMG_DBG_ASSERT(fw_ctx->initialized);
+	if (!fw_ctx->initialized)
+		return;
+
+	/* target only the current MTX */
+	mtx_set_target(fw_ctx);
+
+	/* Turn on the thread */
+	VXE_WR_REG32(fw_ctx->mtx_reg_mem_space_addr, MTX_CR_MTX_ENABLE,
+		     MASK_MTX_MTX_ENABLE);
+}
+
+/*
+ * Stop an MTX.
+ * @Input    fw_ctx       : Pointer to the context of the target MTX
+ */
+void mtx_stop(struct img_fw_context *fw_ctx)
+{
+	IMG_DBG_ASSERT(fw_ctx->initialized);
+
+	/* target only the current MTX */
+	mtx_set_target(fw_ctx);
+
+	/*
+	 * Turn off the thread by writing one to the MTX_TOFF field of the MTX_ENABLE
+	 * register.
+	 */
+	VXE_WR_REG32(fw_ctx->mtx_reg_mem_space_addr, MTX_CR_MTX_ENABLE,
+		     MASK_MTX_MTX_TOFF);
+}
+
+/*
+ * Kick an MTX.
+ * @Input    fw_ctx     : Pointer to the context of the target MTX
+ * @Input    kick_count : The number of kicks to register
+ */
+void mtx_kick(struct img_fw_context *fw_ctx, unsigned int kick_count)
+{
+	IMG_DBG_ASSERT(fw_ctx->initialized);
+	if (!fw_ctx->initialized)
+		return;
+
+	/* target only the current MTX */
+	mtx_set_target(fw_ctx);
+
+	VXE_WR_REG32(fw_ctx->mtx_reg_mem_space_addr, MTX_CR_MTX_KICK,
+		     kick_count);
+}
+
+/*
+ * Wait for MTX to halt
+ * @Input    fw_ctx        : Pointer to the MTX context
+ */
+void mtx_wait_for_completion(struct img_fw_context *fw_ctx)
+{
+	IMG_DBG_ASSERT(fw_ctx->initialized);
+
+	if (fw_ctx->load_method != MTX_LOADMETHOD_NONE) {
+		/* target only the current MTX */
+		mtx_set_target(fw_ctx);
+
+		/* Wait for the Completion */
+		VXE_POLL_REG32_ISEQ(fw_ctx->mtx_reg_mem_space_addr,
+				    MTX_CR_MTX_ENABLE, MASK_MTX_MTX_TOFF,
+				    (MASK_MTX_MTX_TOFF | MASK_MTX_MTX_ENABLE),
+				    TAL_REG_RD_WR_TRIES);
+	}
+}
+
+unsigned int poll_hw_inactive(struct img_fw_context *fw_ctx)
+{
+	return VXE_POLL_REG32_ISEQ(fw_ctx->topaz_multicore_reg_addr,
+		       MTX_SCRATCHREG_IDLE,
+		       F_ENCODE(FW_IDLE_STATUS_IDLE, FW_IDLE_REG_STATUS),
+		       MASK_FW_IDLE_REG_STATUS,
+		       TAL_REG_RD_WR_TRIES);
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/img_soc_dmac_regs.h b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/img_soc_dmac_regs.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/img_soc_dmac_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/img_soc_dmac_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _REGCONV_H_img_soc_dmac_regs_h
+#define _REGCONV_H_img_soc_dmac_regs_h
+
+/* Register DMAC_COUNT */
+#define IMG_SOC_DMAC_COUNT(X)       (0x0004 + (32 * (X)))
+#define MASK_IMG_SOC_BSWAP          0x40000000
+#define SHIFT_IMG_SOC_BSWAP         30
+#define SHIFT_IMG_SOC_PW            27
+#define MASK_IMG_SOC_PW             0x18000000
+#define MASK_IMG_SOC_DIR            0x04000000
+#define SHIFT_IMG_SOC_DIR           26
+
+/* Register DMAC_COUNT */
+#define MASK_IMG_SOC_EN             0x00010000
+#define MASK_IMG_SOC_LIST_EN        0x00040000
+
+/* Register DMAC_COUNT */
+#define MASK_IMG_SOC_PI             0x03000000
+#define SHIFT_IMG_SOC_PI            24
+#define MASK_IMG_SOC_CNT            0x0000FFFF
+#define SHIFT_IMG_SOC_CNT           0
+#define MASK_IMG_SOC_TRANSFER_IEN   0x20000000
+
+/* Register DMAC_IRQ_STAT */
+#define IMG_SOC_DMAC_IRQ_STAT(X)    (0x000C + (32 * (X)))
+#define MASK_IMG_SOC_TRANSFER_FIN   0x00020000
+#define SHIFT_IMG_SOC_TRANSFER_FIN  17
+
+/* Register DMAC_PER_HOLD */
+#define IMG_SOC_DMAC_PER_HOLD(X)    (0x0018 + (32 * (X)))
+
+/* Register DMAC_SETUP */
+#define IMG_SOC_DMAC_SETUP(X)       (0x0000 + (32 * (X)))
+
+/* Register DMAC_PERIPH */
+#define IMG_SOC_DMAC_PERIPH(X)      (0x0008 + (32 * (X)))
+#define MASK_IMG_SOC_ACC_DEL        0xE0000000
+#define SHIFT_IMG_SOC_ACC_DEL       29
+#define MASK_IMG_SOC_INCR           0x08000000
+#define SHIFT_IMG_SOC_INCR          27
+#define MASK_IMG_SOC_BURST          0x07000000
+#define SHIFT_IMG_SOC_BURST         24
+
+/* Register DMAC_PERIPHERAL_ADDR */
+#define IMG_SOC_DMAC_PERIPHERAL_ADDR(X) (0x0014 + (32 * (X)))
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/mtx_regs.h b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/mtx_regs.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/mtx_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/mtx_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _REGCONV_H_mtx_regs_h
+#define _REGCONV_H_mtx_regs_h
+
+/* Register CR_MTX_ENABLE */
+#define MTX_CR_MTX_ENABLE           0x0000
+#define MASK_MTX_MTX_ENABLE         0x00000001
+#define MASK_MTX_MTX_TOFF           0x00000002
+
+/* Register CR_MTX_KICK */
+#define MTX_CR_MTX_KICK             0x0080
+
+/* Register CR_MTX_REGISTER_READ_WRITE_DATA */
+#define MTX_CR_MTX_REGISTER_READ_WRITE_DATA 0x00F8
+
+/* Register CR_MTX_REGISTER_READ_WRITE_REQUEST */
+#define MTX_CR_MTX_REGISTER_READ_WRITE_REQUEST 0x00FC
+#define MASK_MTX_MTX_RNW            0x00010000
+#define MASK_MTX_MTX_DREADY         0x80000000
+
+/* Register CR_MTX_RAM_ACCESS_DATA_TRANSFER */
+#define MTX_CR_MTX_RAM_ACCESS_DATA_TRANSFER 0x0104
+
+/* Register CR_MTX_RAM_ACCESS_CONTROL */
+#define MTX_CR_MTX_RAM_ACCESS_CONTROL 0x0108
+#define MASK_MTX_MTX_MCMR           0x00000001
+#define MASK_MTX_MTX_MCMAI          0x00000002
+#define SHIFT_MTX_MTX_MCMAI         1
+#define MASK_MTX_MTX_MCM_ADDR       0x000FFFFC
+#define SHIFT_MTX_MTX_MCM_ADDR      2
+#define MASK_MTX_MTX_MCMID          0x0FF00000
+#define SHIFT_MTX_MTX_MCMID         20
+
+/* Register CR_MTX_RAM_ACCESS_STATUS */
+#define MTX_CR_MTX_RAM_ACCESS_STATUS 0x010C
+#define MASK_MTX_MTX_MTX_MCM_STAT   0x00000001
+
+/* Register CR_MTX_SOFT_RESET */
+#define MTX_CR_MTX_SOFT_RESET       0x0200
+#define MASK_MTX_MTX_RESET          0x00000001
+
+/* Register CR_MTX_SYSC_CDMAC */
+#define MTX_CR_MTX_SYSC_CDMAC       0x0340
+#define MASK_MTX_LENGTH             0x0000FFFF
+#define SHIFT_MTX_LENGTH            0
+#define MASK_MTX_ENABLE             0x00010000
+#define SHIFT_MTX_ENABLE            16
+#define MASK_MTX_RNW                0x00020000
+#define SHIFT_MTX_RNW               17
+#define MASK_MTX_BURSTSIZE          0x07000000
+#define SHIFT_MTX_BURSTSIZE         24
+
+/* Register CR_MTX_SYSC_CDMAA */
+#define MTX_CR_MTX_SYSC_CDMAA       0x0344
+
+/* Register CR_MTX_SYSC_CDMAT */
+#define MTX_CR_MTX_SYSC_CDMAT       0x0350
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topaz_coreext_regs.h b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topaz_coreext_regs.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topaz_coreext_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topaz_coreext_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _REGCONV_H_topazhp_coreext_regs_h
+#define _REGCONV_H_topazhp_coreext_regs_h
+
+/* Register CR_SCALER_INPUT_SIZE */
+#define MASK_TOPAZHP_EXT_CR_SCALER_INPUT_WIDTH_MIN1 0x00000FFF
+#define SHIFT_TOPAZHP_EXT_CR_SCALER_INPUT_WIDTH_MIN1 0
+#define MASK_TOPAZHP_EXT_CR_SCALER_INPUT_HEIGHT_MIN1 0x0FFF0000
+#define SHIFT_TOPAZHP_EXT_CR_SCALER_INPUT_HEIGHT_MIN1 16
+
+/* Register CR_SCALER_PITCH */
+#define MASK_TOPAZHP_EXT_CR_SCALER_INPUT_HOR_PITCH 0x00007FFF
+#define SHIFT_TOPAZHP_EXT_CR_SCALER_INPUT_HOR_PITCH 0
+#define MASK_TOPAZHP_EXT_CR_SCALER_HOR_BILINEAR_FILTER 0x00008000
+#define SHIFT_TOPAZHP_EXT_CR_SCALER_HOR_BILINEAR_FILTER 15
+#define MASK_TOPAZHP_EXT_CR_SCALER_INPUT_VER_PITCH 0x7FFF0000
+#define SHIFT_TOPAZHP_EXT_CR_SCALER_INPUT_VER_PITCH 16
+#define MASK_TOPAZHP_EXT_CR_SCALER_VER_BILINEAR_FILTER 0x80000000
+#define SHIFT_TOPAZHP_EXT_CR_SCALER_VER_BILINEAR_FILTER 31
+
+/* Register CR_SCALER_CROP */
+#define MASK_TOPAZHP_EXT_CR_SCALER_INPUT_CROP_VER 0x000000FF
+#define SHIFT_TOPAZHP_EXT_CR_SCALER_INPUT_CROP_VER 0
+#define MASK_TOPAZHP_EXT_CR_SCALER_INPUT_CROP_HOR 0x0000FF00
+#define SHIFT_TOPAZHP_EXT_CR_SCALER_INPUT_CROP_HOR 8
+
+/* Register CR_SCALER_CONTROL */
+#define MASK_TOPAZHP_EXT_CR_SCALER_ENABLE 0x00000001
+#define SHIFT_TOPAZHP_EXT_CR_SCALER_ENABLE 0
+#define MASK_TOPAZHP_EXT_CR_ENABLE_COLOUR_SPACE_CONVERSION 0x00000002
+#define SHIFT_TOPAZHP_EXT_CR_ENABLE_COLOUR_SPACE_CONVERSION 1
+#define MASK_TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT 0x007F0000
+#define SHIFT_TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT 16
+
+/* 4:4:4, Any 3 colour space components plus reserved byte (e.g.
+ * RGB), 8-bit components, packed 32-bit per pixel in a single plane, 8 LSBits not used
+ */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_444IL4XBCA8		0x0000007E
+
+/* 4:4:4, Any 3 colour space components plus reserved byte (e.g.
+ * RGB), 8-bit components, packed 32-bit per pixel in a single plane, 8 MSBits not used
+ */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_444IL4ABCX8		0x0000007C
+
+/* RGB with 5 bits for R, 6 bits for G and 5 bits for B */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_444IL3RGB565		0x00000070
+
+/* 4:4:4, Y in 1 plane, CrCb interleaved in 2nd plane, 8-bit components */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_444PL12YCRCB8		0x0000006A
+
+/* 4:4:4, Y in 1 plane, CbCr interleaved in 2nd plane, 8-bit components */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_444PL12YCBCR8		0x00000068
+
+/* 4:4:4, Y Cb Cr in 3 separate planes, 8-bit components
+ * (could also be ABC, but colour space conversion is not supported by input scaler
+ */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_444PL111YCBCR8		0x00000060
+
+/* 4:2:2, CrYCbY interleaved in a single plane, 8-bit components */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422IL3CRYCBY8		0x00000056
+
+/* 4:2:2, CbYCrY interleaved in a single plane, 8-bit components */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422IL3CBYCRY8		0x00000054
+
+/* 4:2:2, YCrYCb interleaved in a single plane, 8-bit components */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422IL3YCRYCB8		0x00000052
+
+/* 4:2:2, YCbYCr interleaved in a single plane, 8-bit components */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422IL3YCBYCR8		0x00000050
+
+/* 4:2:2, Y in 1 plane, CrCb interleaved in 2nd plane, 8-bit components */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422PL12YCRCB8		0x0000004A
+
+/* 4:2:2, Y in 1 plane, CbCr interleaved in 2nd plane, 8-bit components */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422PL12YCBCR8		0x00000048
+
+/* 4:2:2, Y Cb Cr in 3 separate planes, 8-bit components */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422PL111YCBCR8		0x00000040
+
+/* 4:2:0, Y in 1 plane, CrCb interleaved in 2nd plane, 8-bit components */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_420PL12YCRCB8		0x0000002A
+
+/* 4:2:0, Y in 1 plane, CbCr interleaved in 2nd plane, 8-bit components */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_420PL12YCBCR8		0x00000028
+
+/* 4:2:0, Y Cb Cr in 3 separate planes, 8-bit components */
+#define TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_420PL111YCBCR8		0x00000020
+
+/* Register CR_CSC_SOURCE_MOD_Y_0 */
+#define MASK_TOPAZHP_EXT_CR_CSC_SOURCE_MOD_00 0x00000003
+#define SHIFT_TOPAZHP_EXT_CR_CSC_SOURCE_MOD_00 0
+
+/* Subtract 1/2 maximum value from unsigned pixel component */
+#define TOPAZHP_EXT_CR_CSC_SOURCE_MOD_00_MINUS_1_2		0x00000003
+
+/* Subtract 1/16th maximum value from unsigned pixel component */
+#define TOPAZHP_EXT_CR_CSC_SOURCE_MOD_00_MINUS_1_16		0x00000002
+
+/* Source pixel component is unsigned */
+#define TOPAZHP_EXT_CR_CSC_SOURCE_MOD_00_UNSIGNED		0x00000000
+
+/* Register CR_CSC_SOURCE_MOD_Y_1 */
+#define MASK_TOPAZHP_EXT_CR_CSC_SOURCE_MOD_01 0x00000003
+#define SHIFT_TOPAZHP_EXT_CR_CSC_SOURCE_MOD_01 0
+
+/* Subtract 1/2 maximum value from unsigned pixel component */
+#define TOPAZHP_EXT_CR_CSC_SOURCE_MOD_01_MINUS_1_2		0x00000003
+
+/* Subtract 1/16th maximum value from unsigned pixel component */
+#define TOPAZHP_EXT_CR_CSC_SOURCE_MOD_01_MINUS_1_16		0x00000002
+
+/* Source pixel component is unsigned */
+#define TOPAZHP_EXT_CR_CSC_SOURCE_MOD_01_UNSIGNED		0x00000000
+
+/* Register CR_CSC_SOURCE_CB_CR_1 */
+#define MASK_TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_CB_01 0x00000FFF
+#define SHIFT_TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_CB_01 0
+#define SHIFT_TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_CR_01 16
+
+/* Register CR_CSC_SOURCE_MOD_Y_2 */
+#define MASK_TOPAZHP_EXT_CR_CSC_SOURCE_MOD_02 0x00000003
+#define SHIFT_TOPAZHP_EXT_CR_CSC_SOURCE_MOD_02 0
+
+/* Subtract 1/2 maximum value from unsigned pixel component */
+#define TOPAZHP_EXT_CR_CSC_SOURCE_MOD_02_MINUS_1_2		0x00000003
+
+/* Subtract 1/16th maximum value from unsigned pixel component */
+#define TOPAZHP_EXT_CR_CSC_SOURCE_MOD_02_MINUS_1_16		0x00000002
+
+/* Source pixel component is unsigned */
+#define TOPAZHP_EXT_CR_CSC_SOURCE_MOD_02_UNSIGNED		0x00000000
+
+/* Register CR_CSC_SOURCE_CB_CR_2 */
+#define MASK_TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_CB_02 0x00000FFF
+#define SHIFT_TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_CR_02 16
+
+/* Register CR_CSC_OUTPUT_COEFF_0 */
+#define SHIFT_TOPAZHP_EXT_CR_CSC_OUTPUT_MIN_CLIP_00 0
+#define SHIFT_TOPAZHP_EXT_CR_CSC_OUTPUT_MAX_CLIP_00 16
+#define MASK_TOPAZHP_EXT_CR_CSC_OUTPUT_MOD_00 0x30000000
+#define SHIFT_TOPAZHP_EXT_CR_CSC_OUTPUT_MOD_00 28
+
+/* Add 1/16th maximum value prior to applying unsigned clamping */
+#define TOPAZHP_EXT_CR_CSC_OUTPUT_MOD_00_ADD_1_16		0x00000002
+
+/* Register CR_CSC_OUTPUT_COEFF_1 */
+#define MASK_TOPAZHP_EXT_CR_CSC_OUTPUT_MIN_CLIP_01 0x000003FF
+#define SHIFT_TOPAZHP_EXT_CR_CSC_OUTPUT_MIN_CLIP_01 0
+#define SHIFT_TOPAZHP_EXT_CR_CSC_OUTPUT_MAX_CLIP_01 16
+#define MASK_TOPAZHP_EXT_CR_CSC_OUTPUT_MOD_01 0x30000000
+#define SHIFT_TOPAZHP_EXT_CR_CSC_OUTPUT_MOD_01 28
+
+/* Add 1/2 maximum value prior to applying unsigned clamping */
+#define TOPAZHP_EXT_CR_CSC_OUTPUT_MOD_01_ADD_1_2		0x00000003
+#define MASK_TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_Y 0x0FFF0000
+#define SHIFT_TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_Y 16
+
+/* Register CR_CSC_SOURCE_CB_CR */
+#define MASK_TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_CB 0x00000FFF
+#define SHIFT_TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_CB 0
+#define MASK_TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_CR 0x0FFF0000
+#define SHIFT_TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_CR 16
+
+/* Register CR_CSC_OUTPUT_COEFF */
+#define MASK_TOPAZHP_EXT_CR_CSC_OUTPUT_MIN_CLIP 0x000003FF
+#define SHIFT_TOPAZHP_EXT_CR_CSC_OUTPUT_MIN_CLIP 0
+#define MASK_TOPAZHP_EXT_CR_CSC_OUTPUT_MAX_CLIP 0x03FF0000
+#define SHIFT_TOPAZHP_EXT_CR_CSC_OUTPUT_MAX_CLIP 16
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topaz_db_regs.h b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topaz_db_regs.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topaz_db_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topaz_db_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _REGCONV_H_topaz_db_regs_h
+#define _REGCONV_H_topaz_db_regs_h
+
+/* Register CR_DB_DISABLE_DEBLOCK_IDC */
+#define MASK_TOPAZ_DB_CR_DISABLE_DEBLOCK_IDC 0x00000003
+#define SHIFT_TOPAZ_DB_CR_DISABLE_DEBLOCK_IDC 0
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topazhp_core_regs.h b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topazhp_core_regs.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topazhp_core_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topazhp_core_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,232 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _REGCONV_H_topazhp_core_regs_h
+#define _REGCONV_H_topazhp_core_regs_h
+
+/* Register CR_LRITC_CACHE_CHUNK_CONFIG */
+#define MASK_TOPAZHP_CR_CACHE_CHUNKS_PRIORITY 0x000000FF
+#define SHIFT_TOPAZHP_CR_CACHE_CHUNKS_PRIORITY 0
+#define MASK_TOPAZHP_CR_CACHE_CHUNKS_MAX 0x0000FF00
+#define SHIFT_TOPAZHP_CR_CACHE_CHUNKS_MAX 8
+#define MASK_TOPAZHP_CR_CACHE_CHUNKS_PER_MB 0x00FF0000
+#define SHIFT_TOPAZHP_CR_CACHE_CHUNKS_PER_MB 16
+
+/* Register CR_SEQ_CUR_PIC_ROW_STRIDE */
+#define MASK_TOPAZHP_CR_CUR_PIC_LUMA_STRIDE 0x0000FFC0
+#define SHIFT_TOPAZHP_CR_CUR_PIC_LUMA_STRIDE 6
+#define MASK_TOPAZHP_CR_CUR_PIC_CHROMA_STRIDE 0xFFC00000
+#define SHIFT_TOPAZHP_CR_CUR_PIC_CHROMA_STRIDE 22
+
+/* Register CR_SEQUENCER_CONFIG */
+#define MASK_TOPAZHP_CR_ENCODER_STANDARD 0x00000007
+#define SHIFT_TOPAZHP_CR_ENCODER_STANDARD 0
+#define TOPAZHP_CR_ENCODER_STANDARD_H264		0x00000002		/* H264 encode */
+#define MASK_TOPAZHP_CR_FRAME_STORE_FORMAT 0x00000030
+#define SHIFT_TOPAZHP_CR_FRAME_STORE_FORMAT 4
+
+/* 4:2:0 frame, with Luma, Cb and Cr all in separate planes (if the frame
+ * store actually contains 4:2:2 chroma, the chroma stride can be doubled
+ * so that it is read as 4:2:0)
+ */
+#define MASK_TOPAZHP_CR_FRAME_STORE_CHROMA_SWAP 0x00000040
+#define SHIFT_TOPAZHP_CR_FRAME_STORE_CHROMA_SWAP 6
+#define MASK_TOPAZHP_CR_FIELD_MODE  0x00000080
+#define SHIFT_TOPAZHP_CR_FIELD_MODE 7
+#define MASK_TOPAZHP_CR_REF_PIC0_VALID 0x00000100
+#define SHIFT_TOPAZHP_CR_REF_PIC0_VALID 8
+#define MASK_TOPAZHP_CR_REF_PIC1_VALID 0x00000200
+#define SHIFT_TOPAZHP_CR_REF_PIC1_VALID 9
+#define MASK_TOPAZHP_CR_REF_PIC1_EQUAL_PIC0 0x00000400
+#define SHIFT_TOPAZHP_CR_REF_PIC1_EQUAL_PIC0 10
+#define MASK_TOPAZHP_CR_ABOVE_OUT_OF_SLICE_VALID 0x00000800
+#define SHIFT_TOPAZHP_CR_ABOVE_OUT_OF_SLICE_VALID 11
+#define MASK_TOPAZHP_CR_TEMPORAL_COL_IN_VALID 0x00001000
+#define SHIFT_TOPAZHP_CR_TEMPORAL_COL_IN_VALID 12
+#define MASK_TOPAZHP_CR_TEMPORAL_PIC0_BELOW_IN_VALID 0x00002000
+#define SHIFT_TOPAZHP_CR_TEMPORAL_PIC0_BELOW_IN_VALID 13
+#define MASK_TOPAZHP_CR_TEMPORAL_PIC1_BELOW_IN_VALID 0x00004000
+#define SHIFT_TOPAZHP_CR_TEMPORAL_PIC1_BELOW_IN_VALID 14
+#define MASK_TOPAZHP_CR_DEBLOCK_ENABLE 0x00008000
+#define SHIFT_TOPAZHP_CR_DEBLOCK_ENABLE 15
+#define MASK_TOPAZHP_CR_WRITE_TEMPORAL_COL_VALID 0x00010000
+#define SHIFT_TOPAZHP_CR_WRITE_TEMPORAL_COL_VALID 16
+#define MASK_TOPAZHP_CR_WRITE_TEMPORAL_PIC0_BELOW_VALID 0x00020000
+#define SHIFT_TOPAZHP_CR_WRITE_TEMPORAL_PIC0_BELOW_VALID 17
+#define MASK_TOPAZHP_CR_WRITE_TEMPORAL_PIC1_BELOW_VALID 0x00040000
+#define SHIFT_TOPAZHP_CR_WRITE_TEMPORAL_PIC1_BELOW_VALID 18
+#define MASK_TOPAZHP_CR_WRITE_MB_FIRST_STAGE_VALID 0x00200000
+#define SHIFT_TOPAZHP_CR_WRITE_MB_FIRST_STAGE_VALID 21
+#define MASK_TOPAZHP_CR_MB_CONTROL_IN_VALID 0x00800000
+#define SHIFT_TOPAZHP_CR_MB_CONTROL_IN_VALID 23
+#define MASK_TOPAZHP_CR_BEST_MULTIPASS_OUT_VALID 0x10000000
+#define SHIFT_TOPAZHP_CR_BEST_MULTIPASS_OUT_VALID 28
+#define MASK_TOPAZHP_CR_BEST_MVS_OUT_DISABLE 0x40000000
+#define SHIFT_TOPAZHP_CR_BEST_MVS_OUT_DISABLE 30
+#define MASK_TOPAZHP_CR_SLICE_TYPE  0x00030000
+#define SHIFT_TOPAZHP_CR_SLICE_TYPE 16
+#define TOPAZHP_CR_SLICE_TYPE_B_SLICE		0x00000002		/* B-slice */
+#define TOPAZHP_CR_SLICE_TYPE_P_SLICE		0x00000001		/* P-slice */
+#define TOPAZHP_CR_SLICE_TYPE_I_SLICE		0x00000000		/* I-slice */
+#define MASK_TOPAZHP_CR_MVCALC_RESTRICT_PICTURE 0x00010000
+#define SHIFT_TOPAZHP_CR_MVCALC_RESTRICT_PICTURE 16
+
+/* Register CR_MVCALC_CONFIG */
+#define MASK_TOPAZHP_CR_MVCALC_GRID_MB_X_STEP 0x0000000F
+#define SHIFT_TOPAZHP_CR_MVCALC_GRID_MB_X_STEP 0
+#define MASK_TOPAZHP_CR_MVCALC_GRID_MB_Y_STEP 0x00000F00
+#define SHIFT_TOPAZHP_CR_MVCALC_GRID_MB_Y_STEP 8
+#define MASK_TOPAZHP_CR_MVCALC_GRID_SUB_STEP 0x000F0000
+#define SHIFT_TOPAZHP_CR_MVCALC_GRID_SUB_STEP 16
+#define MASK_TOPAZHP_CR_MVCALC_GRID_DISABLE 0x00800000
+#define SHIFT_TOPAZHP_CR_MVCALC_GRID_DISABLE 23
+#define MASK_TOPAZHP_CR_MVCALC_IPE0_JITTER_FACTOR 0x03000000
+#define SHIFT_TOPAZHP_CR_MVCALC_IPE0_JITTER_FACTOR 24
+#define MASK_TOPAZHP_CR_MVCALC_IPE1_JITTER_FACTOR 0x0C000000
+#define SHIFT_TOPAZHP_CR_MVCALC_IPE1_JITTER_FACTOR 26
+#define MASK_TOPAZHP_CR_MVCALC_JITTER_POINTER_RST 0x10000000
+#define MASK_TOPAZHP_CR_MVCALC_NO_PSEUDO_DUPLICATES 0x20000000
+#define SHIFT_TOPAZHP_CR_MVCALC_NO_PSEUDO_DUPLICATES 29
+#define MASK_TOPAZHP_CR_MVCALC_DUP_VEC_MARGIN 0xC0000000
+#define SHIFT_TOPAZHP_CR_MVCALC_DUP_VEC_MARGIN 30
+
+/* Register CR_MVCALC_COLOCATED */
+#define MASK_TOPAZHP_CR_COL_DIST_SCALE_FACT 0x000007FF
+#define SHIFT_TOPAZHP_CR_COL_DIST_SCALE_FACT 0
+
+/* Register CR_MVCALC_BELOW */
+#define MASK_TOPAZHP_CR_PIC0_DIST_SCALE_FACTOR 0x000007FF
+#define SHIFT_TOPAZHP_CR_PIC0_DIST_SCALE_FACTOR 0
+#define MASK_TOPAZHP_CR_PIC1_DIST_SCALE_FACTOR 0x07FF0000
+#define SHIFT_TOPAZHP_CR_PIC1_DIST_SCALE_FACTOR 16
+
+/* Register CR_PREFETCH_QP */
+#define MASK_TOPAZHP_CR_SKIPPED_CODED_SCALE_IDX 0x00007000
+#define SHIFT_TOPAZHP_CR_SKIPPED_CODED_SCALE_IDX 12
+#define MASK_TOPAZHP_CR_INTER_INTRA_SCALE_IDX 0x00000700
+#define SHIFT_TOPAZHP_CR_INTER_INTRA_SCALE_IDX 8
+
+/* Register CR_MB_HOST_CONTROL */
+#define MASK_TOPAZHP_CR_MB_HOST_QP  0x00000001
+#define SHIFT_TOPAZHP_CR_MB_HOST_QP 0
+#define MASK_TOPAZHP_CR_MB_HOST_SKIPPED_CODED_SCALE 0x00000002
+#define SHIFT_TOPAZHP_CR_MB_HOST_SKIPPED_CODED_SCALE 1
+#define MASK_TOPAZHP_CR_MB_HOST_INTER_INTRA_SCALE 0x00000004
+#define SHIFT_TOPAZHP_CR_MB_HOST_INTER_INTRA_SCALE 2
+#define MASK_TOPAZHP_CR_H264COMP_8X8_TRANSFORM 0x00000001
+#define SHIFT_TOPAZHP_CR_H264COMP_8X8_TRANSFORM 0
+#define MASK_TOPAZHP_CR_H264COMP_CONSTRAINED_INTRA 0x00000002
+#define SHIFT_TOPAZHP_CR_H264COMP_CONSTRAINED_INTRA 1
+#define MASK_TOPAZHP_CR_H264COMP_8X8_CAVLC 0x00000004
+#define SHIFT_TOPAZHP_CR_H264COMP_8X8_CAVLC 2
+#define MASK_TOPAZHP_CR_H264COMP_DEFAULT_SCALING_LIST 0x00000008
+#define SHIFT_TOPAZHP_CR_H264COMP_DEFAULT_SCALING_LIST 3
+#define MASK_TOPAZHP_CR_H264COMP_ADAPT_ROUND_ENABLE 0x00000010
+#define SHIFT_TOPAZHP_CR_H264COMP_ADAPT_ROUND_ENABLE 4
+#define MASK_TOPAZHP_CR_H264COMP_VIDEO_CONF_ENABLE 0x00000020
+#define SHIFT_TOPAZHP_CR_H264COMP_VIDEO_CONF_ENABLE 5
+#define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_8X8_INTER_LUMA_ENABLE 0x00000080
+#define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_8X8_INTER_LUMA_ENABLE 7
+#define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTER_CR_ENABLE 0x00000100
+#define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTER_CR_ENABLE 8
+#define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTER_CB_ENABLE 0x00000200
+#define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTER_CB_ENABLE 9
+#define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTER_LUMA_ENABLE 0x00000400
+#define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTER_LUMA_ENABLE 10
+#define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_8X8_INTRA_LUMA_ENABLE 0x00000800
+#define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_8X8_INTRA_LUMA_ENABLE 11
+#define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTRA_CR_ENABLE 0x00001000
+#define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTRA_CR_ENABLE 12
+#define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTRA_CB_ENABLE 0x00002000
+#define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTRA_CB_ENABLE 13
+#define MASK_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTRA_LUMA_ENABLE 0x00004000
+#define SHIFT_TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTRA_LUMA_ENABLE 14
+#define MASK_TOPAZHP_CR_H264COMP_LOSSLESS 0x00010000
+#define SHIFT_TOPAZHP_CR_H264COMP_LOSSLESS 16
+#define MASK_TOPAZHP_CR_H264COMP_LOSSLESS_8X8_PREFILTER 0x00020000
+#define SHIFT_TOPAZHP_CR_H264COMP_LOSSLESS_8X8_PREFILTER 17
+
+/* The Intra8x8 Pre-filter is performed in Lossless Mode. H.264 standard lossless. */
+#define TOPAZHP_CR_H264COMP_LOSSLESS_8X8_PREFILTER_FILTER		0x00000001
+
+/* The Intra8x8 Pre-filter is bypassed in Lossless Mode. x264  compatibility mode for lossless. */
+#define TOPAZHP_CR_H264COMP_LOSSLESS_8X8_PREFILTER_BYPASS		0x00000000
+
+/* Register CR_IPE_CONTROL */
+#define MASK_TOPAZHP_CR_IPE_BLOCKSIZE 0x00000003
+#define SHIFT_TOPAZHP_CR_IPE_BLOCKSIZE 0
+#define MASK_TOPAZHP_CR_IPE_16X8_ENABLE 0x00000004
+#define SHIFT_TOPAZHP_CR_IPE_16X8_ENABLE 2
+#define MASK_TOPAZHP_CR_IPE_8X16_ENABLE 0x00000008
+#define SHIFT_TOPAZHP_CR_IPE_8X16_ENABLE 3
+#define MASK_TOPAZHP_CR_IPE_Y_FINE_SEARCH 0x00000030
+#define SHIFT_TOPAZHP_CR_IPE_Y_FINE_SEARCH 4
+#define MASK_TOPAZHP_CR_IPE_4X4_SEARCH 0x00000040
+#define SHIFT_TOPAZHP_CR_IPE_4X4_SEARCH 6
+#define MASK_TOPAZHP_CR_IPE_LRITC_BOUNDARY 0x00000300
+#define SHIFT_TOPAZHP_CR_IPE_LRITC_BOUNDARY 8
+#define MASK_TOPAZHP_CR_IPE_HIGH_LATENCY 0x00001000
+#define SHIFT_TOPAZHP_CR_IPE_HIGH_LATENCY 12
+#define MASK_TOPAZHP_CR_IPE_MV_NUMBER_RESTRICTION 0x00004000
+#define SHIFT_TOPAZHP_CR_IPE_MV_NUMBER_RESTRICTION 14
+
+/* Register CR_IPE_VECTOR_CLIPPING */
+#define MASK_TOPAZHP_CR_IPE_VECTOR_CLIPPING_X 0x000000FF
+#define SHIFT_TOPAZHP_CR_IPE_VECTOR_CLIPPING_X 0
+#define MASK_TOPAZHP_CR_IPE_VECTOR_CLIPPING_Y 0x0000FF00
+#define SHIFT_TOPAZHP_CR_IPE_VECTOR_CLIPPING_Y 8
+#define MASK_TOPAZHP_CR_IPE_VECTOR_CLIPPING_ENABLED 0x00010000
+#define SHIFT_TOPAZHP_CR_IPE_VECTOR_CLIPPING_ENABLED 16
+
+/* Register CR_JMCOMP_CARC_CONTROL_0 */
+#define MASK_TOPAZHP_CR_CARC_NEG_SCALE 0x3F000000
+#define SHIFT_TOPAZHP_CR_CARC_NEG_SCALE 24
+#define MASK_TOPAZHP_CR_CARC_NEG_RANGE 0x001F0000
+#define SHIFT_TOPAZHP_CR_CARC_NEG_RANGE 16
+#define MASK_TOPAZHP_CR_CARC_POS_SCALE 0x00003F00
+#define SHIFT_TOPAZHP_CR_CARC_POS_SCALE 8
+#define MASK_TOPAZHP_CR_CARC_POS_RANGE 0x0000001F
+#define SHIFT_TOPAZHP_CR_CARC_POS_RANGE 0
+
+/* Register CR_JMCOMP_CARC_CONTROL_1 */
+#define MASK_TOPAZHP_CR_CARC_SHIFT  0x03000000
+#define SHIFT_TOPAZHP_CR_CARC_SHIFT 24
+#define MASK_TOPAZHP_CR_CARC_CUTOFF 0x00F00000
+#define SHIFT_TOPAZHP_CR_CARC_CUTOFF 20
+#define MASK_TOPAZHP_CR_CARC_THRESHOLD 0x0007FF00
+#define SHIFT_TOPAZHP_CR_CARC_THRESHOLD 8
+#define MASK_TOPAZHP_CR_SPE_MVD_CLIP_ENABLE 0x80000000
+#define SHIFT_TOPAZHP_CR_SPE_MVD_CLIP_ENABLE 31
+
+/* Register CR_PRED_COMB_CONTROL */
+#define MASK_TOPAZHP_CR_INTRA4X4_DISABLE 0x00000001
+#define SHIFT_TOPAZHP_CR_INTRA4X4_DISABLE 0
+#define MASK_TOPAZHP_CR_INTRA8X8_DISABLE 0x00000002
+#define SHIFT_TOPAZHP_CR_INTRA8X8_DISABLE 1
+#define MASK_TOPAZHP_CR_INTRA16X16_DISABLE 0x00000004
+#define SHIFT_TOPAZHP_CR_INTRA16X16_DISABLE 2
+#define MASK_TOPAZHP_CR_INTER8X8_DISABLE 0x00000010
+#define SHIFT_TOPAZHP_CR_INTER8X8_DISABLE 4
+#define MASK_TOPAZHP_CR_B_PIC0_DISABLE 0x00000100
+#define SHIFT_TOPAZHP_CR_B_PIC0_DISABLE 8
+#define MASK_TOPAZHP_CR_B_PIC1_DISABLE 0x00000200
+#define SHIFT_TOPAZHP_CR_B_PIC1_DISABLE 9
+#define MASK_TOPAZHP_CR_INTER_INTRA_SCALE_ENABLE 0x00001000
+#define SHIFT_TOPAZHP_CR_INTER_INTRA_SCALE_ENABLE 12
+#define MASK_TOPAZHP_CR_CUMULATIVE_BIASES_ENABLE 0x00000800
+#define SHIFT_TOPAZHP_CR_CUMULATIVE_BIASES_ENABLE 11
+#define MASK_TOPAZHP_CR_SKIPPED_CODED_SCALE_ENABLE 0x00002000
+#define SHIFT_TOPAZHP_CR_SKIPPED_CODED_SCALE_ENABLE 13
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topazhp_multicore_regs_old.h b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topazhp_multicore_regs_old.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topazhp_multicore_regs_old.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topazhp_multicore_regs_old.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _REGCONV_H_topazhp_multicore_regs_old_h
+#define _REGCONV_H_topazhp_multicore_regs_old_h
+
+///* Register CR_LAMBDA_DC_TABLE */
+#define MASK_TOPAZHP_CR_TEMPORAL_BLEND 0x001F0000
+#define SHIFT_TOPAZHP_CR_TEMPORAL_BLEND 16
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topaz_vlc_regs.h b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topaz_vlc_regs.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topaz_vlc_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/reg_headers/topaz_vlc_regs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * firmware header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _REGCONV_H_topaz_vlc_regs_h
+#define _REGCONV_H_topaz_vlc_regs_h
+
+///* Register CR_VLC_CONTROL */
+#define MASK_TOPAZ_VLC_CR_CODEC     0x00000003
+#define SHIFT_TOPAZ_VLC_CR_CODEC    0
+#define MASK_TOPAZ_VLC_CR_CABAC_ENABLE		0x00000100
+#define SHIFT_TOPAZ_VLC_CR_CABAC_ENABLE		8
+#define MASK_TOPAZ_VLC_CR_VLC_FIELD_CODED	0x00000200
+#define SHIFT_TOPAZ_VLC_CR_VLC_FIELD_CODED	9
+#define MASK_TOPAZ_VLC_CR_VLC_8X8_TRANSFORM	0x00000400
+#define SHIFT_TOPAZ_VLC_CR_VLC_8X8_TRANSFORM	10
+#define MASK_TOPAZ_VLC_CR_VLC_CONSTRAINED_INTRA	0x00000800
+#define SHIFT_TOPAZ_VLC_CR_VLC_CONSTRAINED_INTRA	11
+#define MASK_TOPAZ_VLC_CR_CODEC_EXTEND	0x10000000
+#define SHIFT_TOPAZ_VLC_CR_CODEC_EXTEND	28
+
+///* Register CR_VLC_IPCM_0 */
+#define MASK_TOPAZ_VLC_CR_CABAC_DB_MARGIN	0x03FF0000
+#define SHIFT_TOPAZ_VLC_CR_CABAC_DB_MARGIN	16
+#define MASK_TOPAZ_VLC_CR_CABAC_BIN_FLEX	0x00001FFF
+#define SHIFT_TOPAZ_VLC_CR_CABAC_BIN_FLEX	0
+#define MASK_TOPAZ_VLC_CR_IPCM_THRESHOLD	0x00000FFF
+#define SHIFT_TOPAZ_VLC_CR_IPCM_THRESHOLD	0
+#define MASK_TOPAZ_VLC_CR_CABAC_BIN_LIMIT	0x1FFF0000
+#define SHIFT_TOPAZ_VLC_CR_CABAC_BIN_LIMIT	16
+#define MASK_TOPAZ_VLC_CR_SLICE_SIZE_LIMIT	0x00FFFFFF
+#define SHIFT_TOPAZ_VLC_CR_SLICE_SIZE_LIMIT	0
+#define MASK_TOPAZ_VLC_CR_SLICE_MBS_LIMIT	0x00003FFF
+#define SHIFT_TOPAZ_VLC_CR_SLICE_MBS_LIMIT	0
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/target_config.h b/drivers/media/platform/img/vxe-vxd/encoder/target_config.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/target_config.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/target_config.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Device specific memory configuration
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef __TARGET_CONFIG_H__
+#define __TARGET_CONFIG_H__
+
+#include "target.h"
+
+/* Order MUST match with topaz_mem_space definition */
+enum topaz_mem_space_idx {
+	REG_TOPAZHP_MULTICORE = 0,
+	REG_DMAC,
+	REG_COMMS,
+	REG_MTX,
+	REG_MMU,
+	REG_TOPAZHP_TEST,
+	REG_MTX_RAM,
+	REG_TOPAZHP_CORE_0,
+	REG_TOPAZHP_VLC_CORE_0,
+	REG_TOPAZHP_DEBLOCKER_CORE_0,
+	REG_TOPAZHP_COREEXT_0,
+	REG_TOPAZHP_CORE_1,
+	REG_TOPAZHP_VLC_CORE_1,
+	REG_TOPAZHP_DEBLOCKER_CORE_1,
+	REG_TOPAZHP_COREEXT_1,
+	REG_TOPAZHP_CORE_2,
+	REG_TOPAZHP_VLC_CORE_2,
+	REG_TOPAZHP_DEBLOCKER_CORE_2,
+	REG_TOPAZHP_COREEXT_2,
+	REG_TOPAZHP_CORE_3,
+	REG_TOPAZHP_VLC_CORE_3,
+	REG_TOPAZHP_DEBLOCKER_CORE_3,
+	REG_TOPAZHP_COREEXT_3,
+	FW,
+	SYSMEM,
+	MEMSYSMEM,
+	MEM,
+	FB,
+	MEMDMAC_00,
+	MEMDMAC_01,
+	MEMDMAC_02,
+	MEM_SPACE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/target.h b/drivers/media/platform/img/vxe-vxd/encoder/target.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/target.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/target.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * target interface header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#if !defined(__TARGET_H__)
+#define __TARGET_H__
+
+#include <linux/types.h>
+
+#define TARGET_NO_IRQ   (999) /* Interrupt number when no interrupt exists */
+
+/*
+ * The memory space types
+ */
+enum mem_space_type {
+	MEMSPACE_REGISTER,  /* Memory space is mapped to device registers */
+	MEMSPACE_MEMORY,    /* Memory space is mapped to device memory */
+	MEMSPACE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * This structure contains all information about a device register
+ */
+struct mem_space_reg {
+	unsigned long long addr;     /* Base address of device registers */
+	unsigned int size;     /* Size of device register block */
+	unsigned int intr_num; /* The interrupt number */
+};
+
+/*
+ * This structure contains all information about a device memory region
+ */
+struct mem_space_mem {
+	unsigned long long addr;       /* Base address of memory region */
+	unsigned long long size;       /* Size of memory region */
+	unsigned long long guard_band; /* Memory guard band */
+};
+
+/*
+ * This structure contains all information about the device memory space
+ */
+struct mem_space {
+	unsigned char *name;               /* Memory space name */
+	enum mem_space_type type;          /* Memory space type */
+	union {
+		struct mem_space_reg reg;  /* Device register info */
+		struct mem_space_mem mem;  /* Device memory region info */
+	};
+
+	unsigned long cpu_addr;      /* Cpu KM address for the mem space */
+};
+
+struct target_config {
+	unsigned int num_mem_spaces;
+	struct mem_space *mem_spaces;
+};
+
+#endif /* __TARGET_H__    */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/topaz_api.c b/drivers/media/platform/img/vxe-vxd/encoder/topaz_api.c
--- a/drivers/media/platform/img/vxe-vxd/encoder/topaz_api.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/topaz_api.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,3891 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Encoder Core API function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+#include "fw_headers/coreflags.h"
+#include "fw_headers/topazscfwif.h"
+#include "header_gen.h"
+#include "img_errors.h"
+#include "img_mem_man.h"
+#include "lst.h"
+#include "reg_headers/topaz_coreext_regs.h"
+#include "reg_headers/topazhp_core_regs.h"
+#include "reg_headers/topaz_vlc_regs.h"
+#include "reg_headers/topaz_db_regs.h"
+#include "topaz_color_formats.h"
+#include "topaz_device.h"
+#include "topaz_api.h"
+#include "topaz_api_utils.h"
+#include "topazmmu.h"
+#include "vxe_public_regdefs.h"
+#include "img_errors.h"
+
+#define TOPAZ_TIMEOUT_RETRIES (5000000)
+#define TOPAZ_TIMEOUT_WAIT_FOR_SPACE (500)
+
+#define COMM_WB_DATA_BUF_SIZE (64)
+
+/*
+ * All contexts should be able to send as many commands as possible before waiting for a response.
+ * There must be enough command memory buffers for all applicable commands, that is:
+ * -To fill all source slots
+ * -To supply custom quant data
+ */
+#define TOPAZ_CMD_DATA_BUF_NUM  ((MAX_SOURCE_SLOTS_SL + 1) * TOPAZHP_MAX_POSSIBLE_STREAMS)
+#define TOPAZ_CMD_DATA_BUF_SIZE (64)
+#define COMM_CMD_DATA_BUF_SLOT_NONE 0xFF
+
+struct topaz_core_context *global_topaz_core_context;
+
+static unsigned char global_cmd_data_busy[TOPAZ_CMD_DATA_BUF_NUM];
+struct vidio_ddbufinfo global_cmd_data_dev_addr; /* Data section */
+struct vidio_ddbufinfo global_cmd_data_info[TOPAZ_CMD_DATA_BUF_NUM]; /* Data section */
+static unsigned char global_pipe_usage[TOPAZHP_MAX_NUM_PIPES] = { 0 };
+
+struct vidio_ddbufinfo *global_wb_data_info;
+static unsigned char is_topaz_core_initialized;
+
+/*
+ * Get a buffer reference
+ */
+static int topaz_get_buffer(struct topaz_stream_context *str_ctx,
+			    struct img_buffer *buffer, void **lin_address,
+	unsigned char update_host_memory)
+{
+	if (buffer->lock == NOTDEVICEMEMORY) {
+		*lin_address = buffer->mem_info.cpu_virt;
+		return IMG_SUCCESS;
+	}
+
+	if (buffer->lock == SW_LOCK)
+		return IMG_ERROR_SURFACE_LOCKED;
+
+	if (update_host_memory)
+		topaz_update_host_mem(str_ctx->vxe_ctx, &buffer->mem_info);
+
+	*lin_address    = buffer->mem_info.cpu_virt;
+	buffer->lock    = SW_LOCK;
+
+	return IMG_SUCCESS;
+}
+
+static int topaz_release_buffer(struct topaz_stream_context *str_ctx,
+				struct img_buffer *buffer, unsigned char update_device_memory)
+{
+	if (buffer->lock == NOTDEVICEMEMORY)
+		return IMG_SUCCESS;
+
+	if (buffer->lock == HW_LOCK)
+		return IMG_ERROR_SURFACE_LOCKED;
+
+	buffer->lock = BUFFER_FREE;
+
+	if (update_device_memory)
+		topaz_update_device_mem(str_ctx->vxe_ctx, &buffer->mem_info);
+
+	return IMG_SUCCESS;
+}
+
+static int topaz_get_cmd_data_buffer(struct vidio_ddbufinfo **mem_info)
+{
+	int index = 0;
+	int res = IMG_SUCCESS;
+
+	mutex_lock_nested(global_topaz_core_context->mutex, SUBCLASS_TOPAZ_API);
+
+	do {
+		if (!global_cmd_data_busy[index])
+			break;
+		index++;
+	} while (index < ARRAY_SIZE(global_cmd_data_info));
+
+	if (index == ARRAY_SIZE(global_cmd_data_info)) {
+		res = IMG_ERROR_UNEXPECTED_STATE;
+	} else {
+		global_cmd_data_busy[index] = TRUE;
+		*mem_info = &global_cmd_data_info[index];
+	}
+
+	mutex_unlock((struct mutex *)global_topaz_core_context->mutex);
+
+	return res;
+}
+
+static int topaz_release_cmd_data_buffer(struct vidio_ddbufinfo *mem_info)
+{
+	int index = 0;
+	int res = IMG_ERROR_UNEXPECTED_STATE;
+
+	mutex_lock_nested(global_topaz_core_context->mutex, SUBCLASS_TOPAZ_API);
+
+	do {
+		if (mem_info == &global_cmd_data_info[index]) {
+			global_cmd_data_busy[index] = FALSE;
+			res = IMG_SUCCESS;
+			break;
+		}
+		index++;
+	} while (index < ARRAY_SIZE(global_cmd_data_info));
+
+	mutex_unlock((struct mutex *)global_topaz_core_context->mutex);
+
+	return res;
+}
+
+/*
+ * Get a buffer reference
+ */
+static int get_coded_buffer(struct topaz_stream_context *str_ctx, void **lin_address,
+			    unsigned char update_host_memory, unsigned char coded_package_idx)
+{
+	struct img_enc_context *enc;
+	struct img_video_context *video;
+	unsigned char coded_buffer_idx;
+	unsigned char found = FALSE;
+	unsigned int *address;
+	struct coded_data_hdr *coded_datahdr = NULL;
+	unsigned int offset_buffer_header = 0, offset_coded_buffer = 0;
+	/* Tells if all the slices have been retrieved */
+	unsigned char all_slice_retrieved = FALSE;
+	/* Tells if we have reach the last coded buffer used or not */
+	unsigned char slice_break = FALSE;
+	/* Tells if we are at the beginning of a slice or not */
+	unsigned char new_coded_header = TRUE;
+	/* Tells the number of bytes remaining to be retrieved */
+	unsigned int total_byte_written = 0;
+	unsigned int coded_slices_so_far = 0;
+	unsigned int coded_slices_in_buffer = 0;
+
+	enc = str_ctx->enc_ctx;
+	video = enc->video;
+
+	if (video->coded_package[coded_package_idx]->header_buffer->lock == SW_LOCK)
+		return IMG_ERROR_UNDEFINED;
+
+	/* Retrieve the FW Package memory. Get linear address */
+	video->coded_package[coded_package_idx]->mtx_info.coded_package_fw =
+		(struct coded_package_dma_info *)(&video->coded_package[coded_package_idx]->mtx_info
+		.code_package_fw_buffer->mem_info);
+
+	if (update_host_memory) {
+		/* Go through all the coded buffers */
+		for (coded_buffer_idx = 0; coded_buffer_idx < MAX_CODED_BUFFERS_PER_PACKAGE;
+			coded_buffer_idx++) {
+			/* Reset the Offset */
+			offset_coded_buffer = 0;
+			do {
+				if (new_coded_header) { // beginning of a slice
+					slice_break = FALSE;
+					/* Get the coded header information */
+					*lin_address = video->coded_package
+					[coded_package_idx]->header_buffer->mem_info.cpu_virt;
+					address = *lin_address;
+					/* Getting the nth buffer header */
+					coded_datahdr = (struct coded_data_hdr *)(address +
+							(offset_buffer_header / 4));
+					total_byte_written = coded_datahdr->bytes_written;
+					coded_slices_so_far =
+						F_DECODE(coded_datahdr->extra_feedback,
+							 CODED_SLICES_SO_FAR);
+					coded_slices_in_buffer =
+						F_DECODE(coded_datahdr->extra_feedback,
+							 CODED_SLICES_IN_BUFFER);
+
+					/* Increment the offset in the coded header information
+					 * buffer in order to point on the next header
+					 */
+					offset_buffer_header += CODED_BUFFER_INFO_SECTION_SIZE;
+				}
+
+				if (!new_coded_header) {
+					/* Retrieve the last coded data */
+					offset_coded_buffer = ALIGN_16(offset_coded_buffer +
+								       total_byte_written);
+					slice_break = TRUE;
+					/* On next loop we will be at the start of a new slice */
+					new_coded_header = TRUE;
+				} else {
+					/*
+					 * New slice : Read all the bytes written for this slice
+					 * Go after what we read, next 16bit align address
+					 */
+					offset_coded_buffer =
+						ALIGN_16(offset_coded_buffer +
+							 coded_datahdr->bytes_written);
+					if (F_DECODE(coded_datahdr->extra_feedback,
+						     CODED_SLICES_SO_FAR) ==
+							F_DECODE(coded_datahdr->extra_feedback,
+								 CODED_SLICES_IN_BUFFER)) {
+						/* We now have all the slices for this coded buffer,
+						 * we should not try to read further.
+						 */
+						all_slice_retrieved = TRUE;
+						break;
+					}
+				}
+			} while (coded_slices_so_far != coded_slices_in_buffer);
+
+			if (all_slice_retrieved || slice_break) {
+				/* If we are NOT in the middle of a slice */
+				found = TRUE;
+				/* We lock this last buffer */
+				video->coded_package[coded_package_idx]->coded_buffer
+								[coded_buffer_idx]->lock = SW_LOCK;
+				/* This function will do nothing if -debugCRCs (1 or 2) has not
+				 * been specified on the command line
+				 */
+				break;
+			}
+		}
+
+		if (!found)
+			topaz_update_host_mem(str_ctx->vxe_ctx, &video->coded_package
+						[coded_package_idx]->header_buffer->mem_info);
+	}
+
+	/* address of first  header if all buffer finish in middle of
+	 * slice or !bUpdateHostMemory, last red header otherwise
+	 */
+	*lin_address = video->coded_package[coded_package_idx]->header_buffer->mem_info.cpu_virt;
+	/* Lock-it */
+	video->coded_package[coded_package_idx]->header_buffer->lock = SW_LOCK;
+
+	return IMG_SUCCESS;
+}
+
+static void combine_feedback(struct topaz_stream_context *str_ctx,
+			     unsigned char active_coded_package_idx, unsigned int *feedback,
+			     unsigned int *extra_feedback, unsigned int *bytes_coded)
+{
+	struct img_enc_context *enc = str_ctx->enc_ctx;
+	struct coded_data_hdr *coded_datahdr;
+	unsigned int offset = 0;
+	unsigned int min_bu = 0xFFFFFFFF;
+	unsigned int coded_bytes = 0;
+	unsigned int bu;
+	unsigned int coded_slices_so_far;
+	unsigned int coded_slices_in_buffer;
+
+	do {
+		/* we should be able to rely on the linear pointer here
+		 * as the coded data header should have been updated.
+		 */
+		coded_datahdr = (struct coded_data_hdr *)((unsigned long)(enc->video->coded_package
+				[active_coded_package_idx]->header_buffer->mem_info.cpu_virt) +
+				offset);
+
+		IMG_DBG_ASSERT(coded_datahdr);
+		if (!coded_datahdr)
+			return;
+
+		bu = F_DECODE(coded_datahdr->feedback, CODED_FIRST_BU);
+		coded_slices_so_far = F_DECODE(coded_datahdr->extra_feedback, CODED_SLICES_SO_FAR);
+		coded_slices_in_buffer = F_DECODE(coded_datahdr->extra_feedback,
+						  CODED_SLICES_IN_BUFFER);
+
+		if (bu < min_bu)
+			min_bu = bu;
+
+		coded_bytes += coded_datahdr->bytes_written;
+		offset += CODED_BUFFER_INFO_SECTION_SIZE;
+	} while (coded_slices_so_far != coded_slices_in_buffer);
+
+	*bytes_coded = coded_bytes;
+	*feedback = F_INSERT(coded_datahdr->feedback, min_bu, CODED_FIRST_BU);
+	*extra_feedback = coded_datahdr->extra_feedback;
+}
+
+/*
+ * Move around the reconstructed data and handle the list for frame reordering
+ */
+static void process_reconstructed(struct topaz_stream_context *str_ctx, unsigned char is_coded,
+				  enum img_frame_type frame_type, struct list_item **recon_list)
+{
+	struct img_video_context *video = str_ctx->enc_ctx->video;
+	unsigned char *tmp_buffer;
+	unsigned short width, height;
+	struct list_item *new_item;
+	struct img_recon_node *new_node;
+	struct list_item *current_item;
+
+	*recon_list = NULL;
+
+	if (!video->output_reconstructed)
+		return;
+
+	/* Create new reconstructed node */
+	new_item = kzalloc(sizeof(*new_item), GFP_KERNEL);
+	if (!new_item)
+		return;
+
+	new_item->data = kzalloc(sizeof(*new_node), GFP_KERNEL);
+	if (!new_item->data) {
+		kfree(new_item);
+		new_item = NULL;
+		return;
+	}
+
+	new_node = (struct img_recon_node *)new_item->data;
+
+	if (is_coded) {
+		topaz_update_host_mem(str_ctx->vxe_ctx, video->recon_buffer);
+		tmp_buffer = (unsigned char *)video->recon_buffer->cpu_virt;
+		width = ALIGN_64(video->width);
+		height = ALIGN_64(video->frame_height);
+
+		new_node->buffer = kzalloc(width * height * 3 / 2, GFP_KERNEL);
+		if (!new_node->buffer) {
+			kfree(new_item->data);
+			kfree(new_item);
+			new_item = NULL;
+			new_node = NULL;
+			return;
+		}
+		memcpy(new_node->buffer, tmp_buffer, width * height * 3 / 2);
+
+	} else {
+		new_node->buffer = NULL;
+	}
+	new_node->poc = video->recon_poc;
+
+	/* Add new node to the queue */
+	if (!video->ref_frame) {
+		/* First element */
+		new_item->next = NULL;
+		video->ref_frame = new_item;
+	} else if (new_node->poc == 0) {
+		/* First element after aborted sequence */
+		current_item = video->ref_frame;
+
+		while (current_item->next)
+			current_item = current_item->next;
+
+		/* Insert at end */
+		new_item->next = NULL;
+		current_item->next = new_item;
+	} else {
+		struct img_recon_node *head_node = (struct img_recon_node *)video->ref_frame->data;
+
+		if (head_node->poc > new_node->poc) {
+			/* Insert at start */
+			new_item->next = video->ref_frame;
+			video->ref_frame = new_item;
+		} else {
+			struct img_recon_node *next_node = NULL;
+
+			current_item = video->ref_frame;
+			while (current_item->next) {
+				next_node = (struct img_recon_node *)current_item->next->data;
+
+				if (next_node->poc > new_node->poc) {
+					/* Insert between current and next */
+					new_item->next = current_item->next;
+					current_item->next = new_item;
+					break;
+				}
+				current_item = current_item->next;
+			}
+
+			if (!current_item->next) {
+				/* Insert at end */
+				new_item->next = NULL;
+				current_item->next = new_item;
+			}
+		}
+	}
+
+	if (video->next_recon == 0) {
+		video->next_recon++;
+		/* Flush all frames */
+		*recon_list = video->ref_frame;
+		video->ref_frame = NULL;
+	} else if (new_node->poc == video->next_recon) {
+		struct list_item *flush_tail = video->ref_frame;
+		struct img_recon_node *next_node;
+
+		video->next_recon++;
+
+		/* Find all flushable frames */
+		while (flush_tail->next) {
+			next_node = (struct img_recon_node *)flush_tail->next->data;
+
+			/* Flushing sequence ends when POCs no longer match */
+			if (next_node->poc != video->next_recon)
+				break;
+
+			video->next_recon++;
+
+			flush_tail = flush_tail->next;
+		}
+
+		/* Flush consecutive sequence */
+		*recon_list = video->ref_frame;
+
+		/* Set new head */
+		video->ref_frame = flush_tail->next;
+
+		/* Separate sequences */
+		flush_tail->next = NULL;
+	}
+}
+
+int topaz_process_message(struct topaz_stream_context *str_ctx, struct mtx_tohost_msg tohost_msg)
+{
+	struct driver_tohost_msg *driver_msg;
+	struct list_item *current_el = NULL;
+	struct img_enc_context *enc;
+	struct img_video_context *video;
+	struct list_item *message_list = NULL;
+	unsigned int index = 0;
+
+	enc = str_ctx->enc_ctx;
+	video = enc->video;
+
+	/* add a new element */
+	current_el = kzalloc(sizeof(*current_el), GFP_KERNEL);
+	if (!current_el)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	current_el->data = kzalloc(sizeof(*driver_msg), GFP_KERNEL);
+	if (!current_el->data) {
+		kfree(current_el);
+		current_el = NULL;
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* adding to head */
+	current_el->next = message_list;
+	message_list = current_el;
+
+	driver_msg = (struct driver_tohost_msg *)current_el->data;
+	driver_msg->cmd_id = tohost_msg.cmd_id;
+	driver_msg->data = tohost_msg.data;
+	driver_msg->command_data_buf = tohost_msg.command_data_buf;
+
+	switch (tohost_msg.cmd_id) {
+	case MTX_MESSAGE_ACK:
+		driver_msg->input_cmd_id = (enum mtx_cmd_id)F_DECODE(tohost_msg.input_cmd_word,
+					    MTX_MSG_CMD_ID);
+		break;
+
+	case MTX_MESSAGE_CODED:
+	{
+		struct coded_data_hdr *coded_datahdr = NULL;
+		unsigned int feedback, extra_feedback;
+		unsigned char active_coded_package_idx;
+		struct img_feedback_element *feedback_struct;
+
+		active_coded_package_idx = tohost_msg.coded_pkg_idx;
+
+		get_coded_buffer(str_ctx, (void **)&coded_datahdr, TRUE,
+				 active_coded_package_idx);
+
+		feedback = coded_datahdr->feedback;
+		extra_feedback = coded_datahdr->extra_feedback;
+
+		/* detect the FrameNum of the coded buffer */
+		feedback_struct = (struct img_feedback_element *)&driver_msg->feedback;
+
+		combine_feedback(str_ctx, active_coded_package_idx, &feedback, &extra_feedback,
+				 &feedback_struct->bytes_coded);
+
+		feedback_struct->coded_buffer_count = F_DECODE(extra_feedback,
+							       CODED_BUFFER_NUMBER_USED);
+
+		/* Give the header buffer to the feedback structure */
+		feedback_struct->coded_package = video->coded_package[active_coded_package_idx];
+		feedback_struct->active_coded_package_idx       = active_coded_package_idx;
+		/* update this frame, using the info from the coded buffer */
+		feedback_struct->coded_package->coded_buffer[feedback_struct->coded_slot_num] =
+			video->coded_package[active_coded_package_idx]->coded_buffer[feedback_struct
+			->coded_slot_num];
+
+		feedback_struct->first_bu = F_DECODE(feedback, CODED_FIRST_BU);
+		feedback_struct->storage_frame_num = F_DECODE(feedback, CODED_STORAGE_FRAME_NUM);
+		feedback_struct->entire_frame = F_DECODE(feedback, CODED_ENTIRE_FRAME);
+		feedback_struct->is_skipped = F_DECODE(feedback, CODED_IS_SKIPPED);
+		feedback_struct->is_coded = F_DECODE(feedback, CODED_IS_CODED);
+		feedback_struct->recon_idx = F_DECODE(feedback, CODED_RECON_IDX);
+		feedback_struct->source_slot = F_DECODE(feedback, CODED_SOURCE_SLOT);
+		feedback_struct->frame_type = (enum img_frame_type)F_DECODE
+						(feedback, CODED_FRAME_TYPE);
+		feedback_struct->slice_num = F_DECODE(feedback, CODED_SLICE_NUM);
+		feedback_struct->poc = video->source_slot_poc[feedback_struct->source_slot];
+
+		feedback_struct->slices_in_buffer = F_DECODE(extra_feedback,
+							     CODED_SLICES_IN_BUFFER);
+		feedback_struct->field = F_DECODE(extra_feedback, CODED_FIELD);
+		feedback_struct->patched_recon = F_DECODE(extra_feedback,
+							  CODED_PATCHED_RECON);
+		feedback_struct->bytes_coded = coded_datahdr->bytes_written;
+		feedback_struct->host_ctx = coded_datahdr->host_ctx;
+
+		if (video->highest_storage_number != feedback_struct->storage_frame_num &&
+		    video->standard != IMG_STANDARD_H263) {
+			if (feedback_struct->storage_frame_num ==
+				((video->highest_storage_number + 1) & 0x03)) {
+				/* it is piece of the next frame */
+				video->highest_storage_number = feedback_struct->storage_frame_num;
+				/* retrieve next WB */
+				video->encode_pic_processing--;
+				video->extra_wb_retrieved++;
+			} else if (feedback_struct->storage_frame_num ==
+				((video->highest_storage_number + 2) & 0x03)) {
+				/* it is piece of the next frame */
+				video->highest_storage_number = feedback_struct->storage_frame_num;
+
+				video->encode_pic_processing -= 2;
+				video->extra_wb_retrieved += 2;
+			}
+		}
+
+		while (index < feedback_struct->coded_buffer_count) {
+			if (video->coded_package
+			[active_coded_package_idx]->coded_buffer[index]->lock == SW_LOCK)
+				/* Unlock coded buffers used*/
+				topaz_release_buffer(str_ctx,
+						     (struct img_buffer *)(video->coded_package
+						[active_coded_package_idx]->coded_buffer[index]),
+					FALSE);
+			index++;
+		}
+
+		/* Unlock header buffer */
+		topaz_release_buffer(str_ctx, video->coded_package
+				     [feedback_struct->active_coded_package_idx]->header_buffer,
+				     FALSE);
+
+		/* Release the coded slot */
+		video->coded_package[feedback_struct->active_coded_package_idx]->busy = FALSE;
+
+		feedback_struct->src_frame = video->source_slot_buff[feedback_struct->source_slot];
+
+		/* Detect the slice number based on the Slice Map and the first BU in a slice */
+		if (feedback_struct->bytes_coded) {
+			struct img_buffer *output_slice_map;
+			unsigned char *src_buffer = NULL;
+			unsigned char slices_per_picture;
+			unsigned short first_bu_in_slice;
+			unsigned char slice_number;
+			unsigned char index;
+			unsigned char slice_size_in_bu[MAX_SLICESPERPIC];
+
+			/* postion the start of the slice map */
+			output_slice_map = &video->slice_map[feedback_struct->source_slot];
+
+			topaz_get_buffer(str_ctx, output_slice_map, (void **)&src_buffer, FALSE);
+
+			/* retrieve slices per field */
+			slices_per_picture = *src_buffer;
+			src_buffer++;
+
+			/* retrieve first BU in slices and Slice sizes in BUs */
+			first_bu_in_slice = 0;
+
+			for (index = 0; index < slices_per_picture; index++) {
+				slice_number = src_buffer[index * 2];
+				slice_size_in_bu[slice_number] = src_buffer[index * 2 + 1];
+
+				first_bu_in_slice += slice_size_in_bu[slice_number];
+			}
+			topaz_release_buffer(str_ctx, output_slice_map, FALSE);
+
+			feedback_struct->slices_per_picture = slices_per_picture;
+		}
+
+		if (feedback_struct->entire_frame) {
+			/* we encoded the entire frame  */
+			video->frames_encoded++;
+#ifdef DEBUG_ENCODER_DRIVER
+			pr_info("FRAMES_CODED[%d]\n", video->frames_encoded);
+#endif
+
+			if (feedback_struct->coded_package->coded_buffer[0]) {
+				/* Send callback for coded_buffer ready */
+				global_topaz_core_context->vxe_str_processed_cb(str_ctx->vxe_ctx,
+					VXE_CB_CODED_BUFF_READY,
+					(void *)(feedback_struct->coded_package->coded_buffer[0]),
+					feedback_struct->bytes_coded, video->frames_encoded,
+					feedback_struct->frame_type);
+			}
+
+			if (!str_ctx->vxe_ctx->eos) {
+				if (feedback_struct->src_frame) {
+					/* Send callback for src ready */
+					global_topaz_core_context->vxe_str_processed_cb(
+						str_ctx->vxe_ctx,
+						VXE_CB_SRC_FRAME_RELEASE,
+						(void *)(feedback_struct
+								 ->src_frame),
+						0, 0, 0);
+				}
+			}
+			if (video->flush_at_frame > 0 &&
+			    video->frames_encoded >= video->flush_at_frame)
+				feedback_struct->last_frame_encoded = TRUE;
+
+			if (feedback_struct->patched_recon && video->patched_recon_buffer) {
+				video->recon_buffer = video->patched_recon_buffer;
+				video->patched_recon_buffer = NULL;
+			} else {
+				video->recon_buffer =
+					&video->recon_pictures[feedback_struct->recon_idx];
+			}
+			video->recon_poc = feedback_struct->poc;
+
+			video->frame_type = feedback_struct->frame_type;
+
+			process_reconstructed(str_ctx, feedback_struct->is_coded, video->frame_type,
+					      &feedback_struct->recon_list);
+
+			/* If there are more frames to be encoded, release the source slot */
+			if (video->frame_count == 0 ||
+			    video->encode_requested < video->frame_count)
+				video->source_slot_buff[feedback_struct->source_slot] = NULL;
+
+			if (!video->extra_wb_retrieved) {
+				video->encode_pic_processing--;
+				video->highest_storage_number =
+					(video->highest_storage_number + 1) & 0x03;
+			} else {
+				video->extra_wb_retrieved--;
+			}
+		} else {
+			if (feedback_struct->coded_package->coded_buffer[0]) {
+				/* Send callback for coded_buffer ready */
+				global_topaz_core_context->vxe_str_processed_cb(str_ctx->vxe_ctx,
+					VXE_CB_CODED_BUFF_READY,
+					(void *)(feedback_struct->coded_package->coded_buffer[0]),
+					feedback_struct->bytes_coded, video->frames_encoded,
+					feedback_struct->frame_type);
+			}
+		}
+
+		if (feedback_struct->entire_frame &&
+		    (video->enable_sel_stats_flags & ESF_FIRST_STAGE_STATS))
+			feedback_struct->motion_search_statistics_buf =
+			&video->firstpass_out_param_buf[feedback_struct->source_slot];
+		else
+			feedback_struct->motion_search_statistics_buf = NULL;
+
+		if (video->frame_count > 0 && video->frames_encoded >= video->frame_count)
+			feedback_struct->last_frame_encoded = TRUE;
+
+		if (feedback_struct->entire_frame &&
+		    (video->enable_sel_stats_flags & ESF_MP_BEST_MB_DECISION_STATS ||
+		     video->enable_sel_stats_flags & ESF_MP_BEST_MOTION_VECTOR_STATS))
+			feedback_struct->best_multipass_statistics_buf =
+				&video->firstpass_out_best_multipass_param_buf
+							[feedback_struct->source_slot];
+		else
+			feedback_struct->best_multipass_statistics_buf = NULL;
+		break;
+	}
+	default:
+		break;
+	}
+
+	kfree(current_el->data);
+	kfree(current_el);
+
+	return IMG_SUCCESS;
+}
+
+void handle_encoder_firmware_response(struct img_writeback_msg *wb_msg, void *priv)
+{
+	struct topaz_stream_context *str_ctx;
+	struct mtx_tohost_msg tohost_msg;
+	int index;
+	unsigned int cmd_buf_slot = COMM_CMD_DATA_BUF_SLOT_NONE;
+	unsigned int *cmdbuf_devaddr;
+
+	str_ctx = (struct topaz_stream_context *)priv;
+
+	if (!str_ctx)
+		return;
+
+	memset(&tohost_msg, 0, sizeof(tohost_msg));
+	tohost_msg.cmd_id = (enum mtx_message_id)F_DECODE(wb_msg->cmd_word, MTX_MSG_MESSAGE_ID);
+
+	switch (tohost_msg.cmd_id) {
+	case MTX_MESSAGE_ACK:
+#ifdef DEBUG_ENCODER_DRIVER
+		pr_info("MTX_MESSAGE_ACK received\n");
+#endif
+
+		tohost_msg.wb_val = wb_msg->writeback_val;
+		tohost_msg.input_cmd_word = wb_msg->cmd_word;
+		tohost_msg.data = wb_msg->data;
+		break;
+	case MTX_MESSAGE_CODED:
+#ifdef DEBUG_ENCODER_DRIVER
+		pr_info("MTX_MESSAGE_CODED Received\n");
+#endif
+		tohost_msg.input_cmd_word = wb_msg->cmd_word;
+		tohost_msg.coded_pkg_idx = wb_msg->coded_package_consumed_idx;
+		break;
+	default:
+		break;
+	}
+
+	cmdbuf_devaddr = global_cmd_data_dev_addr.cpu_virt;
+
+	for (index = 0; index < TOPAZ_CMD_DATA_BUF_NUM; index++) {
+		if (*cmdbuf_devaddr == wb_msg->extra_data) {
+			/* Input cmd buffer found */
+			cmd_buf_slot = index;
+			break;
+		}
+		cmdbuf_devaddr++;
+	}
+
+	if (cmd_buf_slot != COMM_CMD_DATA_BUF_SLOT_NONE) {
+		tohost_msg.command_data_buf = &global_cmd_data_info[cmd_buf_slot];
+		topaz_release_cmd_data_buffer(tohost_msg.command_data_buf);
+
+	} else {
+		tohost_msg.command_data_buf = NULL;
+	}
+
+	mutex_lock_nested(str_ctx->vxe_ctx->mutex, SUBCLASS_VXE_V4L2);
+	topaz_process_message(str_ctx, tohost_msg);
+	mutex_unlock(str_ctx->vxe_ctx->mutex);
+}
+
+static inline void populate_firmware_message(struct vidio_ddbufinfo *dest, unsigned int dest_offset,
+					     struct vidio_ddbufinfo *src, unsigned int src_offset)
+{
+	*(unsigned int *)((unsigned long)dest->cpu_virt + dest_offset) =
+		src->dev_virt + src_offset;
+}
+
+/*
+ * init_hardware
+ */
+int init_topaz_core(void *device_handle, unsigned int *num_pipes,
+		    unsigned int mmu_flags, void *callback)
+{
+	unsigned int index;
+
+	if (is_topaz_core_initialized)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	is_topaz_core_initialized = TRUE;
+
+	global_topaz_core_context = kzalloc(sizeof(*global_topaz_core_context), GFP_KERNEL);
+	if (!global_topaz_core_context) {
+		is_topaz_core_initialized = FALSE;
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* Initialise device context. */
+	global_topaz_core_context->dev_handle = (struct topaz_dev_ctx *)device_handle;
+	global_topaz_core_context->vxe_str_processed_cb = (vxe_cb)callback;
+
+	lst_init(&global_topaz_core_context->topaz_stream_list);
+
+	*num_pipes = topazdd_get_num_pipes(device_handle);
+
+	/* allocate memory for HighCmd FIFO data section */
+	if (topaz_mmu_alloc(global_topaz_core_context->dev_handle->topaz_mmu_ctx.mmu_context_handle,
+			    global_topaz_core_context->dev_handle->vxe_arg, MMU_GENERAL_HEAP_ID,
+			    1, (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						      SYS_MEMATTRIB_WRITECOMBINE),
+			    4 * TOPAZ_CMD_DATA_BUF_NUM, 64, &global_cmd_data_dev_addr)) {
+		IMG_DBG_ASSERT("Global command data info buff alloc failed\n" != NULL);
+		kfree(global_topaz_core_context);
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	for (index = 0; index < ARRAY_SIZE(global_cmd_data_info); index++) {
+		if (topaz_mmu_alloc
+			(global_topaz_core_context->dev_handle->topaz_mmu_ctx.mmu_context_handle,
+			 global_topaz_core_context->dev_handle->vxe_arg, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+				 SYS_MEMATTRIB_WRITECOMBINE),
+			 TOPAZ_CMD_DATA_BUF_SIZE, 64, &global_cmd_data_info[index])) {
+			IMG_DBG_ASSERT("Global command data info buff alloc failed\n" != NULL);
+			topaz_mmu_free(global_topaz_core_context->dev_handle->vxe_arg,
+				       &global_cmd_data_dev_addr);
+			kfree(global_topaz_core_context);
+			return IMG_ERROR_OUT_OF_MEMORY;
+		}
+		populate_firmware_message(&global_cmd_data_dev_addr, 4 * index,
+					  &global_cmd_data_info[index], 0);
+		global_cmd_data_busy[index] = FALSE;
+	}
+
+	/*Lock for locking critical section in TopazAPI*/
+	global_topaz_core_context->mutex = kzalloc(sizeof(*global_topaz_core_context->mutex),
+						   GFP_KERNEL);
+	if (!global_topaz_core_context->mutex)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	mutex_init(global_topaz_core_context->mutex);
+	return IMG_SUCCESS;
+}
+
+/*
+ * deinit_topaz_core
+ */
+int deinit_topaz_core(void)
+{
+	unsigned int index;
+
+	mutex_destroy(global_topaz_core_context->mutex);
+	kfree(global_topaz_core_context->mutex);
+	global_topaz_core_context->mutex = NULL;
+
+	if (topaz_mmu_free(global_topaz_core_context->dev_handle->vxe_arg,
+			   &global_cmd_data_dev_addr))
+		IMG_DBG_ASSERT("Free failed" == NULL);
+
+	for (index = 0; index < ARRAY_SIZE(global_cmd_data_info); index++)
+		if (topaz_mmu_free(global_topaz_core_context->dev_handle->vxe_arg,
+				   &global_cmd_data_info[index]))
+			IMG_DBG_ASSERT("Free failed"  == NULL);
+
+	return IMG_SUCCESS;
+}
+
+static unsigned short create_gop_frame(unsigned char *level, unsigned char reference,
+				       unsigned char pos, unsigned char ref0_level,
+				       unsigned char ref1_level, enum img_frame_type frame_type)
+{
+	*level = max(ref0_level, ref1_level) + 1;
+
+	return F_ENCODE(reference, GOP_REFERENCE) |
+	       F_ENCODE(pos, GOP_POS) |
+	       F_ENCODE(ref0_level, GOP_REF0) |
+	       F_ENCODE(ref1_level, GOP_REF1) |
+	       F_ENCODE(frame_type, GOP_FRAMETYPE);
+}
+
+static void gop_split(unsigned short **gop_structure, signed char ref0,
+		      signed char ref1, unsigned char ref0_level,
+		      unsigned char ref1_level, unsigned char pic_on_level[])
+{
+	unsigned char distance = ref1 - ref0;
+	unsigned char position = ref0 + (distance >> 1);
+	unsigned char level;
+
+	if (distance == 1)
+		return;
+
+	/* mark middle as this level */
+	(*gop_structure)++;
+	**gop_structure = create_gop_frame(&level, distance >= 3, position, ref0_level, ref1_level,
+					   IMG_INTER_B);
+	pic_on_level[level]++;
+
+	if (distance >= 4)
+		gop_split(gop_structure, ref0, position, ref0_level, level, pic_on_level);
+
+	if (distance >= 3)
+		gop_split(gop_structure, position, ref1, level, ref1_level, pic_on_level);
+}
+
+static void mini_gop_generate_hierarchical(unsigned short gop_structure[],
+					   unsigned int bframe_count,
+					   unsigned int ref_spacing,
+					   unsigned char pic_on_level[])
+{
+	unsigned char level;
+
+	gop_structure[0] = create_gop_frame(&level, TRUE, bframe_count, ref_spacing, 0,
+					    IMG_INTER_P);
+	pic_on_level[level]++;
+
+	gop_split(&gop_structure, -1, bframe_count, ref_spacing, ref_spacing + 1, pic_on_level);
+}
+
+static void mini_gop_generate_flat(unsigned short gop_structure[],
+				   unsigned int bframe_count,
+				   unsigned int ref_spacing,
+	unsigned char pic_on_level[])
+{
+	/* B B B B P */
+	unsigned char encode_order_pos;
+	unsigned char level;
+
+	gop_structure[0] = create_gop_frame(&level, TRUE, MAX_BFRAMES, ref_spacing, 0,
+					    IMG_INTER_P);
+	pic_on_level[level]++;
+
+	for (encode_order_pos = 1; encode_order_pos < MAX_GOP_SIZE; encode_order_pos++) {
+		gop_structure[encode_order_pos] = create_gop_frame(&level,
+								   FALSE, encode_order_pos - 1,
+								   ref_spacing, ref_spacing + 1,
+								   IMG_INTER_B);
+		pic_on_level[level] = bframe_count;
+	}
+}
+
+/*
+ * Create the MTX-side encoder context
+ */
+static int topaz_video_create_mtx_context(struct topaz_stream_context *str_ctx,
+					  struct img_video_params *video_params)
+{
+	struct img_video_context *video;
+	struct img_enc_context *enc;
+	int index, i, j;
+	void *mtx_enc_context_mem;
+	struct img_mtx_video_context *mtx_enc_context;
+	unsigned char flag;
+	unsigned int max_cores;
+	unsigned int bit_limit;
+	unsigned int vert_mv_limit;
+	unsigned int packed_strides;
+	unsigned short *gop_structure;
+
+	max_cores = topazdd_get_num_pipes(global_topaz_core_context->dev_handle);
+
+	enc = str_ctx->enc_ctx;
+	video = enc->video;
+
+	mtx_enc_context = (struct img_mtx_video_context *)(video->mtx_enc_ctx_mem.cpu_virt);
+
+	/* clear the context region */
+	memset(mtx_enc_context, 0x00, MTX_CONTEXT_SIZE);
+
+	mtx_enc_context_mem = (void *)(&enc->video->mtx_enc_ctx_mem);
+
+	mtx_enc_context->initial_qp_i = video->rc_params.initial_qp_i;
+	mtx_enc_context->initial_qp_p = video->rc_params.initial_qp_p;
+	mtx_enc_context->initial_qp_b = video->rc_params.initial_qp_b;
+
+	mtx_enc_context->cqp_offset = (video->rc_params.qcp_offset & 0x1f) |
+				       ((video->rc_params.qcp_offset & 0x1f) << 8);
+	mtx_enc_context->standard = video->standard;
+	mtx_enc_context->width_in_mbs = video->width >> 4;
+	mtx_enc_context->picture_height_in_mbs = video->picture_height >> 4;
+
+	mtx_enc_context->kick_size = video->kick_size;
+	mtx_enc_context->kicks_per_bu = video->kicks_per_bu;
+	mtx_enc_context->kicks_per_picture = (mtx_enc_context->width_in_mbs *
+		mtx_enc_context->picture_height_in_mbs) / video->kick_size;
+
+	mtx_enc_context->output_reconstructed = video->output_reconstructed;
+
+	mtx_enc_context->vop_time_resolution = video->vop_time_resolution;
+
+	mtx_enc_context->max_slices_per_picture = video->slices_per_picture;
+
+	mtx_enc_context->is_interlaced = video->is_interlaced;
+	mtx_enc_context->top_field_first = video->top_field_first;
+	mtx_enc_context->arbitrary_so = video->arbitrary_so;
+
+	mtx_enc_context->idr_period = video->idr_period;
+	mtx_enc_context->bframe_count = video->rc_params.bframes;
+	mtx_enc_context->hierarchical = (unsigned char)video->rc_params.hierarchical;
+	mtx_enc_context->intra_loop_cnt = video->intra_cnt;
+	mtx_enc_context->ref_spacing = video_params->ref_spacing;
+
+	mtx_enc_context->debug_crcs = video_params->debug_crcs;
+
+	mtx_enc_context->fw_num_pipes = enc->pipes_to_use;
+	mtx_enc_context->fw_first_pipe = enc->base_pipe;
+	mtx_enc_context->fw_last_pipe = enc->base_pipe + enc->pipes_to_use - 1;
+	mtx_enc_context->fw_pipes_to_use_flags = 0;
+
+	flag = 0x1 << mtx_enc_context->fw_first_pipe;
+	/* Pipes used MUST be contiguous from the BasePipe offset */
+	for (index = 0; index < mtx_enc_context->fw_num_pipes; index++, flag <<= 1)
+		mtx_enc_context->fw_pipes_to_use_flags |= flag;
+
+	mtx_enc_context->format = video_params->format;
+
+	/* copy scaler values to context in case we need them later */
+	video->enable_scaler            = video_params->enable_scaler;
+	video->crop_left                = video_params->crop_left;
+	video->crop_right               = video_params->crop_right;
+	video->crop_top                 = video_params->crop_top;
+	video->crop_bottom              = video_params->crop_bottom;
+	video->source_width             = video_params->source_width;
+	video->source_frame_height      = video_params->source_frame_height;
+	video->intra_pred_modes         = video_params->intra_pred_modes;
+
+	topaz_setup_input_format(video, &mtx_enc_context->scaler_setup);
+	topaz_setup_input_csc(video, &mtx_enc_context->scaler_setup, &mtx_enc_context->csc_setup,
+			      video_params->csc_preset);
+
+	mtx_enc_context->enable_mvc = video->enable_mvc;
+	mtx_enc_context->mvc_view_idx = video->mvc_view_idx;
+
+	if (video->standard == IMG_STANDARD_H264)
+		mtx_enc_context->no_sequence_headers = video->no_sequence_headers;
+
+	mtx_enc_context->coded_header_per_slice = video->coded_header_per_slice;
+
+	packed_strides = topaz_get_packed_buffer_strides
+		(video->buffer_stride_bytes, video->format, video_params->enable_scaler,
+		 video_params->is_interlaced, video_params->is_interleaved);
+
+	mtx_enc_context->pic_row_stride_bytes =
+		F_ENCODE(F_DECODE(packed_strides, MTX_MSG_PICMGMT_STRIDE_Y),
+			 TOPAZHP_CR_CUR_PIC_LUMA_STRIDE) |
+		F_ENCODE(F_DECODE(packed_strides, MTX_MSG_PICMGMT_STRIDE_UV),
+			 TOPAZHP_CR_CUR_PIC_CHROMA_STRIDE);
+
+	mtx_enc_context->rc_mode = video->rc_params.rc_mode;
+	if (mtx_enc_context->rc_mode == IMG_RCMODE_VCM) {
+		mtx_enc_context->rc_vcm_mode = video->rc_params.rc_vcm_mode;
+		mtx_enc_context->rc_cfs_max_margin_perc = video->rc_params.rc_cfs_max_margin_perc;
+	}
+
+	mtx_enc_context->disable_bit_stuffing = (unsigned char)video_params->disable_bit_stuffing;
+
+	mtx_enc_context->first_pic = TRUE;
+
+	/*Content Adaptive Rate Control Parameters*/
+	if (video_params->carc) {
+		mtx_enc_context->jmcomp_rc_reg0 =
+			F_ENCODE(video_params->carc_pos_range, TOPAZHP_CR_CARC_POS_RANGE)  |
+			F_ENCODE(video_params->carc_pos_scale,  TOPAZHP_CR_CARC_POS_SCALE)   |
+			F_ENCODE(video_params->carc_neg_range, TOPAZHP_CR_CARC_NEG_RANGE)    |
+			F_ENCODE(video_params->carc_neg_scale,  TOPAZHP_CR_CARC_NEG_SCALE);
+
+		mtx_enc_context->jmcomp_rc_reg1 =
+			F_ENCODE(video_params->carc_threshold, TOPAZHP_CR_CARC_THRESHOLD) |
+			F_ENCODE(video_params->carc_cutoff, TOPAZHP_CR_CARC_CUTOFF)  |
+			F_ENCODE(video_params->carc_shift, TOPAZHP_CR_CARC_SHIFT);
+	} else {
+		mtx_enc_context->jmcomp_rc_reg0 = 0;
+		mtx_enc_context->jmcomp_rc_reg1 = 0;
+	}
+
+	mtx_enc_context->mv_clip_config =
+		F_ENCODE(video_params->no_offscreen_mv, TOPAZHP_CR_MVCALC_RESTRICT_PICTURE);
+
+	mtx_enc_context->lritc_cache_chunk_config = 0;
+
+	mtx_enc_context->ipcm_0_config =
+		F_ENCODE(enc->video->cabac_bin_flex, TOPAZ_VLC_CR_CABAC_BIN_FLEX) |
+		F_ENCODE(DEFAULT_CABAC_DB_MARGIN, TOPAZ_VLC_CR_CABAC_DB_MARGIN);
+
+	bit_limit = 3100;
+
+	mtx_enc_context->ipcm_1_config = F_ENCODE(bit_limit, TOPAZ_VLC_CR_IPCM_THRESHOLD) |
+		F_ENCODE(enc->video->cabac_bin_limit, TOPAZ_VLC_CR_CABAC_BIN_LIMIT);
+
+	/* leave alone until high profile and constrained modes are defined. */
+	mtx_enc_context->h264_comp_control  = F_ENCODE((video->cabac_enabled ? 0 : 1),
+						       TOPAZHP_CR_H264COMP_8X8_CAVLC);
+	mtx_enc_context->h264_comp_control |=
+		F_ENCODE(video_params->use_default_scaling_list ? 1 : 0,
+			 TOPAZHP_CR_H264COMP_DEFAULT_SCALING_LIST);
+	mtx_enc_context->h264_comp_control |= F_ENCODE(video->h264_8x8_transform ? 1 : 0,
+						       TOPAZHP_CR_H264COMP_8X8_TRANSFORM);
+	mtx_enc_context->h264_comp_control |= F_ENCODE(video->h264_intra_constrained ? 1 : 0,
+						       TOPAZHP_CR_H264COMP_CONSTRAINED_INTRA);
+
+	mtx_enc_context->mc_adaptive_rounding_disable = video_params->vp_adaptive_rounding_disable;
+	mtx_enc_context->h264_comp_control |=
+		F_ENCODE(mtx_enc_context->mc_adaptive_rounding_disable ? 0 : 1,
+			 TOPAZHP_CR_H264COMP_ADAPT_ROUND_ENABLE);
+
+	if (!mtx_enc_context->mc_adaptive_rounding_disable)
+		for (i = 0; i < 4; i++)
+			for (j = 0; j < AR_REG_SIZE; j++)
+				mtx_enc_context->mc_adaptive_rounding_offsets[j][i] =
+					video_params->vp_adaptive_rounding_offsets[j][i];
+
+	if (video->standard == IMG_STANDARD_H264)
+		mtx_enc_context->h264_comp_control |=
+			F_ENCODE(USE_VCM_HW_SUPPORT, TOPAZHP_CR_H264COMP_VIDEO_CONF_ENABLE);
+
+	mtx_enc_context->h264_comp_control |=
+		F_ENCODE(video_params->use_custom_scaling_lists & 0x01 ? 1 : 0,
+			 TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTRA_LUMA_ENABLE) |
+		F_ENCODE(video_params->use_custom_scaling_lists & 0x02 ? 1 : 0,
+			 TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTRA_CB_ENABLE) |
+		F_ENCODE(video_params->use_custom_scaling_lists & 0x04 ? 1 : 0,
+			 TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTRA_CR_ENABLE) |
+		F_ENCODE(video_params->use_custom_scaling_lists & 0x08 ? 1 : 0,
+			 TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTER_LUMA_ENABLE) |
+		F_ENCODE(video_params->use_custom_scaling_lists & 0x10 ? 1 : 0,
+			 TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTER_CB_ENABLE) |
+		F_ENCODE(video_params->use_custom_scaling_lists & 0x20 ? 1 : 0,
+			 TOPAZHP_CR_H264COMP_CUSTOM_QUANT_4X4_INTER_CR_ENABLE) |
+		F_ENCODE(video_params->use_custom_scaling_lists & 0x40 ? 1 : 0,
+			 TOPAZHP_CR_H264COMP_CUSTOM_QUANT_8X8_INTRA_LUMA_ENABLE) |
+		F_ENCODE(video_params->use_custom_scaling_lists & 0x80 ? 1 : 0,
+			 TOPAZHP_CR_H264COMP_CUSTOM_QUANT_8X8_INTER_LUMA_ENABLE);
+
+	mtx_enc_context->h264_comp_control |=
+		F_ENCODE(video_params->enable_lossless ? 1 : 0, TOPAZHP_CR_H264COMP_LOSSLESS) |
+		F_ENCODE(video_params->lossless_8x8_prefilter ?
+			 TOPAZHP_CR_H264COMP_LOSSLESS_8X8_PREFILTER_BYPASS :
+			 TOPAZHP_CR_H264COMP_LOSSLESS_8X8_PREFILTER_FILTER,
+			 TOPAZHP_CR_H264COMP_LOSSLESS_8X8_PREFILTER);
+
+	mtx_enc_context->h264_comp_intra_pred_modes = 0x3ffff;// leave at default for now.
+
+	if (video->intra_pred_modes != 0)
+		mtx_enc_context->h264_comp_intra_pred_modes = video->intra_pred_modes;
+
+	mtx_enc_context->pred_comb_control = video->pred_comb_control;
+
+	mtx_enc_context->skip_coded_inter_intra =
+		F_ENCODE(video->inter_intra_index, TOPAZHP_CR_INTER_INTRA_SCALE_IDX) |
+		F_ENCODE(video->coded_skipped_index, TOPAZHP_CR_SKIPPED_CODED_SCALE_IDX);
+
+	if (video->enable_inp_ctrl) {
+		mtx_enc_context->mb_host_ctrl =
+			F_ENCODE(video->enable_host_qp, TOPAZHP_CR_MB_HOST_QP) |
+			F_ENCODE(video->enable_host_bias, TOPAZHP_CR_MB_HOST_SKIPPED_CODED_SCALE) |
+			F_ENCODE(video->enable_host_bias, TOPAZHP_CR_MB_HOST_INTER_INTRA_SCALE);
+		mtx_enc_context->pred_comb_control |= F_ENCODE(1,
+				TOPAZHP_CR_INTER_INTRA_SCALE_ENABLE)
+			| F_ENCODE(1, TOPAZHP_CR_SKIPPED_CODED_SCALE_ENABLE);
+	}
+
+	if (video_params->enable_cumulative_biases)
+		mtx_enc_context->pred_comb_control |=
+					F_ENCODE(1, TOPAZHP_CR_CUMULATIVE_BIASES_ENABLE);
+
+	mtx_enc_context->pred_comb_control |=
+		F_ENCODE((((video->inter_intra_index == 3) && (video->coded_skipped_index == 3))
+					? 0 : 1), TOPAZHP_CR_INTER_INTRA_SCALE_ENABLE) |
+		F_ENCODE((video->coded_skipped_index == 3 ? 0 : 1),
+			 TOPAZHP_CR_SKIPPED_CODED_SCALE_ENABLE);
+
+	mtx_enc_context->deblock_ctrl =
+		F_ENCODE(video->deblock_idc, TOPAZ_DB_CR_DISABLE_DEBLOCK_IDC);
+
+	/* Set up VLC Control Register */
+	mtx_enc_context->vlc_control = 0;
+
+	switch (video->standard) {
+	case IMG_STANDARD_H264:
+		/* 1 for H.264 note this is inconsistent with the sequencer value */
+		mtx_enc_context->vlc_control |= F_ENCODE(1, TOPAZ_VLC_CR_CODEC);
+		mtx_enc_context->vlc_control |= F_ENCODE(0, TOPAZ_VLC_CR_CODEC_EXTEND);
+		break;
+
+	default:
+		break;
+	}
+
+	if (video->cabac_enabled)
+		/* 2 for Mpeg4 note this is inconsistent with the sequencer value */
+		mtx_enc_context->vlc_control |= F_ENCODE(1, TOPAZ_VLC_CR_CABAC_ENABLE);
+
+	mtx_enc_context->vlc_control |= F_ENCODE(video->is_interlaced ? 1 : 0,
+						 TOPAZ_VLC_CR_VLC_FIELD_CODED);
+	mtx_enc_context->vlc_control |= F_ENCODE(video->h264_8x8_transform ? 1 : 0,
+						 TOPAZ_VLC_CR_VLC_8X8_TRANSFORM);
+	mtx_enc_context->vlc_control |= F_ENCODE(video->h264_intra_constrained ? 1 : 0,
+						 TOPAZ_VLC_CR_VLC_CONSTRAINED_INTRA);
+
+	mtx_enc_context->vlc_slice_control = F_ENCODE(video->rc_params.slice_byte_limit,
+						      TOPAZ_VLC_CR_SLICE_SIZE_LIMIT);
+	mtx_enc_context->vlc_slice_mb_control = F_ENCODE(video->rc_params.slice_mb_limit,
+							 TOPAZ_VLC_CR_SLICE_MBS_LIMIT);
+
+	switch (video->standard) {
+	case IMG_STANDARD_H264:
+		vert_mv_limit = 255; /* default to no clipping */
+		if (video->vert_mv_limit)
+			vert_mv_limit = enc->video->vert_mv_limit;
+
+		/* as topaz can only cope with at most 255 (in the register field) */
+		vert_mv_limit = min(255U, vert_mv_limit);
+		mtx_enc_context->ipe_vector_clipping =
+			F_ENCODE(1, TOPAZHP_CR_IPE_VECTOR_CLIPPING_ENABLED) |
+			F_ENCODE(255, TOPAZHP_CR_IPE_VECTOR_CLIPPING_X) |
+			F_ENCODE(vert_mv_limit, TOPAZHP_CR_IPE_VECTOR_CLIPPING_Y);
+
+		mtx_enc_context->spe_mvd_clip_range = F_ENCODE(0, TOPAZHP_CR_SPE_MVD_CLIP_ENABLE);
+		break;
+	default:
+		break;
+	}
+
+	/* Update MV Scaling settings: IDR */
+	memcpy(&mtx_enc_context->mv_settings_idr, &video->mv_settings_idr,
+	       sizeof(struct img_mv_settings));
+
+	/* NonB (I or P) */
+	for (i = 0; i <= MAX_BFRAMES; i++)
+		memcpy(&mtx_enc_context->mv_settings_non_b[i], &video->mv_settings_non_b[i],
+		       sizeof(struct img_mv_settings));
+
+	/* WEIGHTED PREDICTION */
+	mtx_enc_context->weighted_prediction_enabled = video_params->weighted_prediction;
+	mtx_enc_context->mtx_weighted_implicit_bi_pred = video_params->vp_weighted_implicit_bi_pred;
+
+	/* SEI_INSERTION */
+	mtx_enc_context->insert_hrd_params = video_params->insert_hrd_params;
+	if (mtx_enc_context->insert_hrd_params & enc->video->rc_params.bits_per_second)
+		/* HRD parameters are meaningless without a bitrate */
+		mtx_enc_context->insert_hrd_params = FALSE;
+
+	if (mtx_enc_context->insert_hrd_params) {
+		mtx_enc_context->clock_div_bitrate = (90000 * 0x100000000LL);
+		mtx_enc_context->clock_div_bitrate /= enc->video->rc_params.bits_per_second;
+		mtx_enc_context->max_buffer_mult_clock_div_bitrate =
+			(unsigned int)(((unsigned long long)(video->rc_params.buffer_size) *
+						90000ULL) /
+			(unsigned long long)enc->video->rc_params.bits_per_second);
+	}
+
+	memcpy(&mtx_enc_context->in_params, &video->pic_params.in_params,
+	       sizeof(struct in_rc_params));
+
+	mtx_enc_context->lritc_cache_chunk_config =
+		F_ENCODE(enc->video->chunks_per_mb,
+			 TOPAZHP_CR_CACHE_CHUNKS_PER_MB)
+		| F_ENCODE(enc->video->max_chunks, TOPAZHP_CR_CACHE_CHUNKS_MAX)
+		| F_ENCODE(enc->video->max_chunks - enc->video->priority_chunks,
+			   TOPAZHP_CR_CACHE_CHUNKS_PRIORITY);
+
+	mtx_enc_context->first_pic_flags = video->first_pic_flags;
+	mtx_enc_context->non_first_pic_flags = video->non_first_pic_flags;
+
+	mtx_enc_context->slice_header_slot_num = -1;
+
+	memset(mtx_enc_context->pic_on_level, 0, sizeof(mtx_enc_context->pic_on_level));
+
+	gop_structure = (unsigned short *)(video->flat_gop_struct.cpu_virt);
+
+	mini_gop_generate_flat(gop_structure, mtx_enc_context->bframe_count,
+			       mtx_enc_context->ref_spacing, mtx_enc_context->pic_on_level);
+	topaz_update_device_mem(str_ctx->vxe_ctx, &video->flat_gop_struct);
+
+	if (video->rc_params.hierarchical) {
+		memset(mtx_enc_context->pic_on_level, 0, sizeof(mtx_enc_context->pic_on_level));
+		gop_structure = (unsigned short *)(video->hierar_gop_struct.cpu_virt);
+
+		mini_gop_generate_hierarchical(gop_structure, mtx_enc_context->bframe_count,
+					       mtx_enc_context->ref_spacing,
+					       mtx_enc_context->pic_on_level);
+		topaz_update_device_mem(str_ctx->vxe_ctx, &video->hierar_gop_struct);
+	}
+
+	topaz_update_device_mem(str_ctx->vxe_ctx, &video->mtx_enc_ctx_mem);
+
+	populate_firmware_message
+		(mtx_enc_context_mem,
+		 (unsigned int)((unsigned char *)&mtx_enc_context->mv_settings_b_table -
+		(unsigned char *)mtx_enc_context),
+		&video->mv_settings_btable, 0);
+
+	if (video->rc_params.hierarchical)
+		populate_firmware_message
+		(mtx_enc_context_mem,
+		 (unsigned int)((unsigned char *)&mtx_enc_context->mv_settings_hierarchical -
+			 (unsigned char *)mtx_enc_context),
+		 &video->mv_settings_hierarchical, 0);
+
+	for (i = 0; i < video->pic_nodes; i++) {
+		populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)&mtx_enc_context->reconstructed[i] -
+				 (unsigned char *)mtx_enc_context),
+			 &video->recon_pictures[i], 0);
+
+		populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)&mtx_enc_context->colocated[i] -
+				 (unsigned char *)mtx_enc_context),
+			 &video->colocated[i], 0);
+	}
+
+	for (i = 0; i < WB_FIFO_SIZE; i++)
+		populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)&mtx_enc_context->writeback_regions[i] -
+				 (unsigned char *)mtx_enc_context),
+			 &global_wb_data_info[i], 0);
+
+	for (i = 0; i < video->mv_stores; i++)
+		populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)
+				 &mtx_enc_context->mv[i] - (unsigned char *)mtx_enc_context),
+			 &video->mv[i], 0);
+
+	if (video->enable_mvc) {
+		for (i = 0; i < 2; i++)
+			populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)&mtx_enc_context->inter_view_mv[i] -
+				 (unsigned char *)mtx_enc_context),
+			 &video->inter_view_mv[i], 0);
+	}
+
+	for (i = 0; i < (int)max_cores; i++)
+		populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)&mtx_enc_context->above_params[i] -
+				 (unsigned char *)mtx_enc_context),
+			 &video->above_params[i], 0);
+
+	/* SEI insertion */
+	if (video_params->insert_hrd_params) {
+		populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)
+				 &mtx_enc_context->sei_buffering_period_template -
+				 (unsigned char *)mtx_enc_context),
+			 &video->sei_buffering_period_header_mem, 0);
+
+		populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)
+				 &mtx_enc_context->sei_picture_timing_template -
+				 (unsigned char *)mtx_enc_context),
+			 &video->sei_picture_timing_header_mem, 0);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(video->slice_params_template_mem); i++)
+		populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)
+				 &mtx_enc_context->slice_params_templates[i] -
+				 (unsigned char *)mtx_enc_context),
+			 &video->slice_params_template_mem[i], 0);
+
+	for (i = 0; i < video->slots_in_use; i++) {
+		populate_firmware_message
+		(mtx_enc_context_mem,
+		 (unsigned int)((unsigned char *)&mtx_enc_context->slice_map[i] -
+			 (unsigned char *)mtx_enc_context),
+		 &video->slice_map[i].mem_info, 0);
+
+		/* WEIGHTED PREDICTION */
+		if (video_params->weighted_prediction ||
+		    video_params->vp_weighted_implicit_bi_pred == WBI_EXPLICIT) {
+			populate_firmware_message
+				(mtx_enc_context_mem,
+				 (unsigned int)((unsigned char *)
+					 &mtx_enc_context->weighted_prediction_virt_addr[i] -
+					 (unsigned char *)mtx_enc_context),
+				 &video->weighted_prediction_mem[i], 0);
+		}
+	}
+
+	populate_firmware_message
+		(mtx_enc_context_mem,
+		 (unsigned int)((unsigned char *)&mtx_enc_context->flat_gop_struct -
+			(unsigned char *)mtx_enc_context), &video->flat_gop_struct, 0);
+
+	populate_firmware_message
+		(mtx_enc_context_mem,
+		 (unsigned int)((unsigned char *)&mtx_enc_context->flat_gop_struct -
+			(unsigned char *)mtx_enc_context),
+			&video->flat_gop_struct, 0);
+
+	for (i = 0; i < video->slots_in_use; i++) {
+		populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)&mtx_enc_context->ltref_header[i] -
+			(unsigned char *)mtx_enc_context),
+			&video->ltref_header[i], 0);
+	}
+
+	if (mtx_enc_context->hierarchical)
+		populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)&mtx_enc_context->hierar_gop_struct -
+			(unsigned char *)mtx_enc_context),
+			&video->hierar_gop_struct, 0);
+
+	for (i = 0; i < ARRAY_SIZE(video->pichdr_template_mem); i++)
+		populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)&mtx_enc_context->pichdr_templates[i] -
+			(unsigned char *)mtx_enc_context),
+			&video->pichdr_template_mem[i], 0);
+
+	if (video->standard == IMG_STANDARD_H264) {
+		populate_firmware_message(mtx_enc_context_mem, (unsigned int)((unsigned char *)
+			&mtx_enc_context->seq_header - (unsigned char *)mtx_enc_context),
+			&video->seq_header_mem, 0);
+
+		if (video->enable_mvc)
+			populate_firmware_message
+			(mtx_enc_context_mem,
+			 (unsigned int)((unsigned char *)&mtx_enc_context->subset_seq_header -
+				 (unsigned char *)mtx_enc_context),
+				&video->subset_seq_header_mem, 0);
+	}
+
+	/* Store the feedback memory address for all "5" slots in the context */
+	if (video->enable_sel_stats_flags & ESF_FIRST_STAGE_STATS) {
+		for (i = 0; i < video->slots_in_use; i++)
+			populate_firmware_message
+				(mtx_enc_context_mem,
+				 (unsigned int)((unsigned char *)
+					 &mtx_enc_context->firstpass_out_param_addr[i] -
+				(unsigned char *)mtx_enc_context),
+				&video->firstpass_out_param_buf[i].mem_info, 0);
+	}
+
+	/* Store the feedback memory address for all "5" slots in the context */
+	if (video->enable_sel_stats_flags & ESF_MP_BEST_MB_DECISION_STATS ||
+	    video->enable_sel_stats_flags & ESF_MP_BEST_MOTION_VECTOR_STATS) {
+		for (i = 0; i < video->slots_in_use; i++) {
+			populate_firmware_message
+				(mtx_enc_context_mem,
+				 (unsigned int)((unsigned char *)
+				 &mtx_enc_context->firstpass_out_best_multipass_param_addr[i] -
+				(unsigned char *)mtx_enc_context),
+				&video->firstpass_out_best_multipass_param_buf[i].mem_info, 0);
+		}
+	}
+
+	/* Store the MB-Input control parameter memory for all the 5-slots in the context */
+	if (video->enable_inp_ctrl) {
+		for (i = 0; i < video->slots_in_use; i++)
+			populate_firmware_message
+		(mtx_enc_context_mem,
+		 (unsigned int)((unsigned char *)&mtx_enc_context->mb_ctrl_in_params_addr[i] -
+			 (unsigned char *)mtx_enc_context),
+				&video->mb_ctrl_in_params_buf[i].mem_info, 0);
+	}
+
+	topaz_update_device_mem(str_ctx->vxe_ctx, &video->mtx_enc_ctx_mem);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Prepares the header templates for the encode for H.264
+ */
+static int h264_prepare_templates(struct topaz_stream_context *str_ctx,
+				  struct img_rc_params *rc_params,
+				  int fine_y_search_size)
+{
+	struct img_enc_context *enc;
+	struct img_video_context *video_ctx;
+	struct pic_params *pic_params;
+
+	enc = str_ctx->enc_ctx;
+	video_ctx = enc->video;
+
+	prepare_mv_estimates(enc);
+
+	pic_params = &enc->video->pic_params;
+
+	pic_params->flags = 0;
+
+	if (rc_params->rc_enable) {
+		pic_params->flags |= ISRC_FLAGS;
+		setup_rc_data(enc->video, pic_params, rc_params);
+	} else {
+		pic_params->in_params.se_init_qp_i = rc_params->initial_qp_i;
+		pic_params->in_params.mb_per_row   = (enc->video->width >> 4);
+		pic_params->in_params.mb_per_bu    = rc_params->bu_size;
+		pic_params->in_params.mb_per_frm   = ((unsigned int)(enc->video->width >> 4)) *
+			(enc->video->frame_height >> 4);
+		pic_params->in_params.bu_per_frm   = (pic_params->in_params.mb_per_frm) /
+			rc_params->bu_size;
+	}
+
+	/* Prepare Slice header templates */
+	generate_slice_params_template(enc, &enc->video->slice_params_template_mem[IMG_FRAME_IDR],
+				       IMG_FRAME_IDR, enc->video->is_interlaced,
+				       fine_y_search_size);
+	topaz_update_device_mem(str_ctx->vxe_ctx, &enc->video->slice_params_template_mem
+									[IMG_FRAME_IDR]);
+
+	generate_slice_params_template(enc, &enc->video->slice_params_template_mem[IMG_FRAME_INTRA],
+				       IMG_FRAME_INTRA, enc->video->is_interlaced,
+				       fine_y_search_size);
+	topaz_update_device_mem(str_ctx->vxe_ctx, &enc->video->slice_params_template_mem
+									[IMG_FRAME_INTRA]);
+
+	generate_slice_params_template(enc,
+				       &enc->video->slice_params_template_mem[IMG_FRAME_INTER_P],
+				       IMG_FRAME_INTER_P, enc->video->is_interlaced,
+				       fine_y_search_size);
+	topaz_update_device_mem(str_ctx->vxe_ctx, &enc->video->slice_params_template_mem
+									[IMG_FRAME_INTER_P]);
+
+	generate_slice_params_template(enc, &enc->video->slice_params_template_mem
+									[IMG_FRAME_INTER_B],
+		IMG_FRAME_INTER_B, enc->video->is_interlaced,
+		fine_y_search_size);
+	topaz_update_device_mem(str_ctx->vxe_ctx, &enc->video->slice_params_template_mem
+									[IMG_FRAME_INTER_B]);
+
+	if (video_ctx->enable_mvc) {
+		generate_slice_params_template(enc, &enc->video->slice_params_template_mem
+									[IMG_FRAME_INTER_P_IDR],
+			IMG_FRAME_INTER_P_IDR, enc->video->is_interlaced, fine_y_search_size);
+		topaz_update_device_mem(str_ctx->vxe_ctx, &enc->video->slice_params_template_mem
+									[IMG_FRAME_INTER_P_IDR]);
+	}
+
+	/* Prepare Pic Params Templates */
+	adjust_pic_flags(enc, rc_params, TRUE, &video_ctx->first_pic_flags);
+	adjust_pic_flags(enc, rc_params, FALSE, &video_ctx->non_first_pic_flags);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Prepares the header templates for the encode.
+ */
+static int topaz_video_prepare_templates(struct topaz_stream_context *str_ctx,
+					 unsigned char search_range,
+					 int fine_y_search_size)
+{
+	struct img_enc_context *enc = str_ctx->enc_ctx;
+	struct img_video_context *video = enc->video;
+	int err_value = IMG_ERROR_UNEXPECTED_STATE;
+
+	switch (video->standard) {
+	case IMG_STANDARD_H264:
+		err_value = h264_prepare_templates(str_ctx, &video->rc_params, fine_y_search_size);
+		break;
+	default:
+		break;
+	}
+
+	return err_value;
+}
+
+/*
+ * Prepare the sequence header for h.264
+ */
+int topaz_h264_prepare_sequence_header(void *topaz_str_ctx, unsigned int mb_width,
+				       unsigned int mb_height,
+				       unsigned char vui_params_present,
+				       struct h264_vui_params *params,
+				       struct h264_crop_params *crop_params,
+				       struct h264_sequence_header_params *sh_params,
+				       unsigned char mvc_sps)
+{
+	struct mtx_header_params *seq_header;
+	struct img_enc_context *enc;
+	struct topaz_stream_context *str_ctx;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+
+	enc = str_ctx->enc_ctx;
+
+	/* Ensure parameters are consistent with context */
+	if (!enc->video->custom_scaling)
+		sh_params->seq_scaling_matrix_present_flag = FALSE;
+
+	/* Get a pointer to the memory the header will be written to */
+	seq_header = (struct mtx_header_params *)(enc->video->seq_header_mem.cpu_virt);
+	h264_prepare_sequence_header(seq_header, mb_width, mb_height, vui_params_present,
+				     params, crop_params, sh_params, enc->video->arbitrary_so);
+
+	topaz_update_device_mem(str_ctx->vxe_ctx, &enc->video->seq_header_mem);
+
+	if (mvc_sps) {
+		/* prepare subset sequence parameter header */
+		struct mtx_header_params *subset_seq_header;
+
+		subset_seq_header =
+			(struct mtx_header_params *)(enc->video->subset_seq_header_mem.cpu_virt);
+		h264_prepare_mvc_sequence_header(subset_seq_header, mb_width, mb_height,
+						 vui_params_present, params, crop_params,
+			sh_params);
+		topaz_update_device_mem(str_ctx->vxe_ctx, &enc->video->subset_seq_header_mem);
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Prepare the picture header for h.264
+ */
+int topaz_h264_prepare_picture_header(void *topaz_str_ctx, signed char cqp_offset)
+{
+	struct mtx_header_params *pic_header;
+	struct topaz_stream_context *str_ctx;
+	struct img_enc_context *enc;
+	unsigned char dep_view_pps = FALSE;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+	enc = str_ctx->enc_ctx;
+
+	/* Get a pointer to the memory the header will be written to */
+	pic_header = (struct mtx_header_params *)(enc->video->pichdr_template_mem[0].cpu_virt);
+
+	if (enc->video->enable_mvc && enc->video->mvc_view_idx != 0 &&
+	    (enc->video->mvc_view_idx != (unsigned short)(NON_MVC_VIEW)))
+		dep_view_pps = TRUE;
+
+	h264_prepare_picture_header(pic_header, enc->video->cabac_enabled,
+				    enc->video->h264_8x8_transform,
+				    enc->video->h264_intra_constrained,
+				    cqp_offset, enc->video->weighted_prediction,
+				    enc->video->weighted_bi_pred,
+				    dep_view_pps, enc->video->pps_scaling,
+				    enc->video->pps_scaling && enc->video->custom_scaling);
+
+	topaz_update_device_mem(str_ctx->vxe_ctx, &enc->video->pichdr_template_mem[0]);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Prepare the AUD header for H264
+ */
+int topaz_h264_prepare_aud_header(void *str_context)
+{
+	struct mtx_header_params *aud_header;
+	struct img_enc_context *enc;
+	struct topaz_stream_context *str_ctx;
+
+	str_ctx = (struct topaz_stream_context *)str_context;
+	if (!str_ctx)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	enc = str_ctx->enc_ctx;
+
+	/* Get a pointer to the memory the header will be written to */
+	aud_header = (struct mtx_header_params *)(&enc->video->aud_header_mem);
+
+	h264_prepare_aud_header(aud_header);
+
+	topaz_update_device_mem(str_ctx->vxe_ctx, &enc->video->aud_header_mem);
+
+	return IMG_SUCCESS;
+}
+
+static unsigned int topaz_get_max_coded_data_size(enum img_standard standard, unsigned short width,
+						  unsigned short height, unsigned int initial_qp_i)
+{
+	unsigned int worst_qp_size;
+
+	if (standard == IMG_STANDARD_H264) {
+		/* allocate based on worst case qp size */
+		worst_qp_size = 400;
+		return ((unsigned int)(width / 16) * (unsigned int)(height / 16) * worst_qp_size);
+	}
+
+	if (initial_qp_i <= 5)
+		return ((unsigned int)width * (unsigned int)height * 1600) / (16 * 16);
+
+	return ((unsigned int)width * (unsigned int)height * 900) / (16 * 16);
+}
+
+static int topaz_get_context_coded_buffer_size(struct img_enc_context *enc,
+					       struct img_rc_params *rc_params,
+	unsigned int *coded_buffer_size)
+{
+	struct img_video_context *video;
+
+	video = enc->video;
+
+	*coded_buffer_size = topaz_get_max_coded_data_size(video->standard, video->width,
+							   video->picture_height,
+							   rc_params->initial_qp_i);
+
+	if (!video->disable_bit_stuffing && rc_params->rc_mode == IMG_RCMODE_CBR)
+		*coded_buffer_size = max(*coded_buffer_size,
+					 ((rc_params->bits_per_second + rc_params->frame_rate / 2) /
+					  rc_params->frame_rate) * 2);
+
+	if (video->coded_header_per_slice)
+		*coded_buffer_size += CODED_BUFFER_INFO_SECTION_SIZE * video->slices_per_picture;
+	else
+		*coded_buffer_size += CODED_BUFFER_INFO_SECTION_SIZE;
+	/* Ensure coded buffer sizes are always aligned to 1024 */
+	*coded_buffer_size = ALIGN_1024(*coded_buffer_size);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Description:	Allocate a coded package
+ */
+static int topaz_allocate_coded_package(struct topaz_stream_context *str_ctx,
+					unsigned int coded_buffersize_bytes,
+					struct coded_package_host **package)
+{
+	struct coded_package_host *this_package;
+	struct img_video_context *video = str_ctx->enc_ctx->video;
+
+	*package = kzalloc(sizeof(*package), GFP_KERNEL);
+
+	this_package = *package;
+
+	if (!this_package)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	this_package->busy = 0;
+
+	this_package->num_coded_buffers = 1;
+
+	/* Allocate FW Buffer  IMG_BUFFER  memory */
+	this_package->mtx_info.code_package_fw_buffer =
+		kzalloc(sizeof(struct img_buffer), GFP_KERNEL);
+
+	if (!this_package->mtx_info.code_package_fw_buffer)
+		goto error_handling;
+
+	/* Allocate header IMG_BUFFER memory */
+	this_package->header_buffer = kzalloc(sizeof(*this_package->header_buffer), GFP_KERNEL);
+
+	if (!this_package->header_buffer)
+		goto error_handling;
+
+	/* Allocate the FW Package (this will provide addresses
+	 * of header and the coded buffer array)
+	 */
+	if (topaz_mmu_stream_alloc
+		(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+		 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+					SYS_MEMATTRIB_WRITECOMBINE),
+		 sizeof(struct coded_package_dma_info), 64,
+		 &this_package->mtx_info.code_package_fw_buffer->mem_info))
+		goto error_handling;
+
+	if (topaz_mmu_stream_alloc
+		(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+		 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE),
+		 (video->coded_header_per_slice ? video->slices_per_picture : 1) *
+		 CODED_BUFFER_INFO_SECTION_SIZE,
+		 64, &this_package->header_buffer->mem_info))
+		goto error_handling;
+
+	this_package->header_buffer->size =
+		(video->coded_header_per_slice ? video->slices_per_picture : 1) *
+		CODED_BUFFER_INFO_SECTION_SIZE;
+
+	return IMG_SUCCESS;
+
+error_handling:
+	if (*package) {
+		kfree(*package);
+		*package = NULL;
+	}
+
+	if (this_package->mtx_info.code_package_fw_buffer) {
+		if (this_package->mtx_info.code_package_fw_buffer->mem_info.dev_virt)
+			topaz_mmu_stream_free
+				(str_ctx->mmu_ctx,
+				 &this_package->mtx_info.code_package_fw_buffer->mem_info);
+
+		kfree(this_package->mtx_info.code_package_fw_buffer);
+		this_package->mtx_info.code_package_fw_buffer = NULL;
+	}
+
+	kfree(this_package->header_buffer);
+	this_package->header_buffer = NULL;
+
+	return IMG_ERROR_OUT_OF_MEMORY;
+}
+
+/*
+ * Create the Video Encoder context
+ */
+static int topaz_video_create_context(struct topaz_stream_context *str_ctx,
+				      struct img_video_params *video_params,
+				      struct img_rc_params *rc_params)
+{
+	struct img_enc_context  *enc;
+	struct img_video_context        *video;
+	unsigned int alloc_size;
+	int index, i;
+	unsigned short picture_height;
+	unsigned int coded_buffer_size;
+	unsigned short width_in_mbs;
+	unsigned short frame_height_in_mbs;
+	unsigned char pipes_to_use;
+	unsigned int max_cores;
+	unsigned int min_slice_height;
+	unsigned int factor = 1;
+	unsigned int kick_size, kicks_per_bu;
+	int ret;
+
+	max_cores = topazdd_get_num_pipes(str_ctx->core_ctx->dev_handle);
+
+	enc = str_ctx->enc_ctx;
+
+	picture_height =
+		((video_params->frame_height >> (video_params->is_interlaced ? 1 : 0)) + 15) & ~15;
+	width_in_mbs = (video_params->width + 15) >> 4;
+	frame_height_in_mbs =  ((picture_height + 15) >> 4) <<
+		(video_params->is_interlaced ? 1 : 0);
+
+	if (topaz_get_encoder_caps(video_params->standard, video_params->width, picture_height,
+				   &enc->caps) != IMG_SUCCESS) {
+		pr_err("\nERROR: Unable to encode the size %dx%d with current hardware version\n\n",
+		       video_params->width, picture_height);
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	/*scaler input W/H limit is 4K*/
+	if (video_params->source_width > 4096) {
+		pr_err("\nERROR: Source Width is bigger than the maximum supported Source Width(4096)\n");
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	if (video_params->source_frame_height > 4096) {
+		pr_err("\nERROR: Source Height is bigger than the maximum supported Source Height(4096)\n");
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	if (video_params->width > enc->caps.max_width) {
+		pr_err("\n ERROR: Width too big for given core revision 0x%x. Maximum width is %d.\n",
+		       enc->caps.core_revision, enc->caps.max_width);
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	if (picture_height > enc->caps.max_height) {
+		pr_err("\n ERROR: Height too big for given core revision 0x%x. Maximum height is %d.\n",
+		       enc->caps.core_revision, enc->caps.max_height);
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	if (video_params->width < enc->caps.min_width) {
+		pr_err("\n ERROR: Width too small for given core revision 0x%x. Minimum width is %d.\n",
+		       enc->caps.core_revision, enc->caps.min_width);
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	if (video_params->standard == IMG_STANDARD_H264) {
+		if (video_params->slices_per_picture < enc->caps.min_slices) {
+			pr_err("WARNING: Minimum slices supported for this resolution is %d. Increasing slices per frame to %d\n",
+			       enc->caps.min_slices, video_params->slices_per_picture);
+			video_params->slices_per_picture =  (unsigned char)enc->caps.min_slices;
+		}
+		factor = min(enc->pipes_to_use, video_params->slices_per_picture);
+	}
+
+	if (video_params->standard == IMG_STANDARD_H264)
+		pipes_to_use = min(enc->pipes_to_use, video_params->slices_per_picture);
+	else
+		pipes_to_use = 1;
+
+	if (picture_height < (enc->caps.min_height * factor)) {
+		pr_err("\n ERROR: Height too small for given core revision 0x%x. Minimum height is %d.\n",
+		       enc->caps.core_revision, enc->caps.min_height * factor);
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	if ((unsigned int)((width_in_mbs) * (picture_height >> 4)) > enc->caps.max_mb_num) {
+		pr_err("\n ERROR: Number of macroblocks too high. It should not be bigger than %d.\n",
+		       enc->caps.max_mb_num);
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	calculate_kick_and_bu_size(width_in_mbs, picture_height / 16, video_params->is_interlaced,
+				   enc->caps.max_bu_per_frame, &kick_size, &kicks_per_bu,
+				   &min_slice_height);
+
+	if (enc->caps.min_slice_height > min_slice_height)
+		min_slice_height = enc->caps.min_slice_height;
+
+	if ((unsigned int)(video_params->slices_per_picture * min_slice_height) >
+	    (unsigned int)(picture_height / 16)) {
+		/* we have too many slices for this resolution */
+		pr_err("\n ERROR: Too many slices for this resolution.\n");
+		return IMG_ERROR_NOT_SUPPORTED;
+	}
+
+	video = kzalloc(sizeof(*video), GFP_KERNEL);
+	if (!video)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	enc->video = video;
+
+	memcpy(&video->rc_params, rc_params, sizeof(*rc_params));
+
+	/* Setup BU size for rate control */
+	video->rc_params.bu_size = kick_size * kicks_per_bu;
+	rc_params->bu_size = video->rc_params.bu_size;
+
+	video->kick_size = kick_size;
+	video->kicks_per_bu = kicks_per_bu;
+
+	video->debug_crcs = video_params->debug_crcs;
+
+	/* stream level params */
+	video->standard = video_params->standard;
+	video->format = video_params->format;
+	video->csc_preset = video_params->csc_preset;
+	video->width = width_in_mbs << 4;
+	video->frame_height = frame_height_in_mbs << 4;
+	video->unrounded_width = video_params->width;
+	video->unrounded_frame_height = video_params->frame_height;
+
+	video->picture_height = picture_height;
+	video->is_interlaced = video_params->is_interlaced;
+	video->is_interleaved = video_params->is_interleaved;
+	video->top_field_first = !(video_params->bottom_field_first);
+	video->encode_requested = 0;
+	video->limit_num_vectors = video_params->limit_num_vectors;
+	video->disable_bit_stuffing = video_params->disable_bit_stuffing;
+	video->vert_mv_limit = video_params->vert_mv_limit;
+	/* Cabac Parameters */
+	video->cabac_enabled = video_params->cabac_enabled;
+	video->cabac_bin_limit  =  video_params->cabac_bin_limit;
+	video->cabac_bin_flex   =  video_params->cabac_bin_flex;
+
+	video->frame_count = 0;
+	video->flush_at_frame = 0;
+	video->flushed_at_frame = 0;
+	video->encoder_idle = TRUE;
+	video->high_latency = video_params->high_latency;
+	video->slices_per_picture = (unsigned char)video_params->slices_per_picture;
+	video->deblock_idc = video_params->deblock_idc;
+	video->output_reconstructed = video_params->output_reconstructed;
+	video->arbitrary_so = video_params->arbitrary_so;
+	video->f_code = video_params->f_code;
+
+	/* Default f_code is 4 */
+	if (!video->f_code)
+		video->f_code = 4;
+
+	video->vop_time_resolution = video_params->vop_time_resolution;
+	video->frames_encoded = 0;
+	video->idr_period = video_params->idr_period;
+
+	video->intra_cnt = video_params->intra_cnt;
+	video->multi_reference_p = video_params->multi_reference_p;
+	video->spatial_direct = video_params->spatial_direct;
+	video->enable_sel_stats_flags = video_params->enable_sel_stats_flags;
+	video->enable_inp_ctrl = video_params->enable_inp_ctrl;
+	video->enable_host_bias = video_params->enable_host_bias;
+	video->enable_host_qp = video_params->enable_host_qp;
+	/* Line counter */
+	video->line_counter = video_params->line_counter_enabled;
+
+	video->enable_air = video_params->enable_air;
+	video->num_air_mbs = video_params->num_air_mbs;
+	video->air_threshold = video_params->air_threshold;
+	video->air_skip_cnt = video_params->air_skip_cnt;
+
+	video->extra_wb_retrieved = 0;
+	video->highest_storage_number = 0;
+
+	video->buffer_stride_bytes = calculate_stride(video_params->format,
+						      video_params->buffer_stride_bytes,
+						      video_params->source_width);
+	video->buffer_height = ((video_params->buffer_height ? video_params->buffer_height :
+		video_params->source_frame_height));
+
+	if (!video_params->disable_bh_rounding)
+		video->buffer_height =
+			(((video->buffer_height >> (video_params->is_interlaced ? 1 : 0)) + 15)  &
+			~15) << (video_params->is_interlaced ? 1 : 0);
+
+	video_params->buffer_stride_bytes = video->buffer_stride_bytes;
+	video_params->buffer_height = video->buffer_height;
+
+	video->next_recon = 0;
+
+	video->enable_mvc = video_params->enable_mvc;
+	video->mvc_view_idx = video_params->mvc_view_idx;
+
+	enc->pipes_to_use = pipes_to_use;
+
+	enc->requested_pipes_to_use = pipes_to_use;
+	video->slots_in_use = rc_params->bframes + 2;
+	enc->video->slots_required = enc->video->slots_in_use;
+
+	video->h264_8x8_transform = video_params->h264_8x8;
+	video->h264_intra_constrained = video_params->constrained_intra;
+	video->custom_scaling = (video_params->use_custom_scaling_lists != 0);
+	video->pps_scaling =
+		(video_params->pps_scaling &&
+		(video_params->use_default_scaling_list || video->custom_scaling));
+
+	video->encode_pic_processing = 0;
+	video->next_slice = 0;
+	video->ref_frame = NULL;
+
+	/* create topaz device context */
+	ret = topazdd_create_stream_context(global_topaz_core_context->dev_handle,
+					    str_ctx->enc_ctx->codec,
+					    handle_encoder_firmware_response, str_ctx,
+					    &str_ctx->enc_ctx->video->dd_str_ctx,
+					    &global_wb_data_info);
+
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	ret = topazdd_setup_stream_ctx
+		(str_ctx->enc_ctx->video->dd_str_ctx, video->frame_height,
+		 video->width, (unsigned char *)&video->dd_ctx_num, &video->dd_ctx_num);
+
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	/* Create MMU stream context */
+	ret = topaz_mmu_stream_create(&global_topaz_core_context->dev_handle->topaz_mmu_ctx,
+				      0x1 /*stream_id*/, str_ctx->vxe_ctx, &str_ctx->mmu_ctx);
+	if (ret)
+		return ret;
+
+	/* WEIGHTED PREDICTION */
+	if (video_params->weighted_prediction ||
+	    video_params->vp_weighted_implicit_bi_pred == WBI_EXPLICIT) {
+		video->weighted_prediction = TRUE;
+
+		for (i = 0; i < video->slots_in_use; i++) {
+			if (topaz_mmu_stream_alloc
+				(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+				 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+							SYS_MEMATTRIB_WRITECOMBINE),
+				 sizeof(struct weighted_prediction_values), 64,
+				 &video->weighted_prediction_mem[i]))
+				IMG_DBG_ASSERT("Allocation failed (A)" == NULL);
+		}
+	} else {
+		video->weighted_prediction = FALSE;
+	}
+
+	video->weighted_bi_pred = video_params->vp_weighted_implicit_bi_pred;
+
+	video->coded_skipped_index = video_params->coded_skipped_index;
+	video->inter_intra_index = video_params->inter_intra_index;
+
+	/*
+	 * patch video parameters is the user has specified a profile
+	 * calculate the number of macroblocks per second
+	 */
+	video->mbps = width_in_mbs * frame_height_in_mbs * video->rc_params.frame_rate;
+
+	patch_hw_profile(video_params, video);
+
+	enc->auto_expand_pipes = video_params->auto_expand_pipes;
+
+	/* As ui32Vp8RefStructMode is not in use the worst case
+	 * would have to be taken and hence 5 pic nodes
+	 */
+	video->pic_nodes = (rc_params->hierarchical ? MAX_REF_B_LEVELS : 0) +
+		video_params->ref_spacing + 4;
+	video->mv_stores = (video->pic_nodes * 2);
+
+	/* We're using a common MACRO here so we can guarantee the same calculation
+	 * when managing buffers either from host or within drivers
+	 */
+	video->coded_package_max_num = CALC_NUM_CODED_PACKAGES_ENCODE
+					(video_params->slice_level,
+					 video_params->slices_per_picture, pipes_to_use,
+					 video->is_interlaced);
+
+	alloc_size = MVEA_ABOVE_PARAM_REGION_SIZE * (ALIGN_64(width_in_mbs));
+
+	for (index = 0; index < (int)max_cores; index++) {
+		if (str_ctx->vxe_ctx->above_mb_params_sgt[index].sgl) {
+			video->above_params[index].buf_size = alloc_size;
+
+			topaz_mmu_stream_map_ext_sg
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID,
+			 &str_ctx->vxe_ctx->above_mb_params_sgt[index],
+			 video->above_params[index].buf_size,
+			 64, (enum sys_emem_attrib)0, video->above_params[index].cpu_virt,
+			 &video->above_params[index],
+			 &video->above_params[index].buff_id);
+		} else {
+			if (topaz_mmu_stream_alloc
+				(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+				 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+							SYS_MEMATTRIB_WRITECOMBINE),
+				 ALIGN_64(alloc_size), 64, &video->above_params[index]))
+				IMG_DBG_ASSERT("Allocation failed (C)" == NULL);
+		}
+	}
+
+	alloc_size = MVEA_MV_PARAM_REGION_SIZE * ALIGN_4(width_in_mbs) * frame_height_in_mbs;
+
+	for (index = 0; index < video->pic_nodes; index++) {
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 alloc_size, 64, &video->colocated[index]))
+			IMG_DBG_ASSERT("Allocation failed (D)" == NULL);
+	}
+
+	alloc_size = (ALIGN_64(video->width)) * (ALIGN_64(video->frame_height)) * 3 / 2;
+
+	for (index = 0; index < video->pic_nodes; index++) {
+		void *data;
+
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 alloc_size, 256, &video->recon_pictures[index]))
+			IMG_DBG_ASSERT("Allocation failed (E)" == NULL);
+
+		data = video->recon_pictures[index].cpu_virt;
+		memset(data, 0, alloc_size);
+
+		topaz_update_device_mem(str_ctx->vxe_ctx, &video->recon_pictures[index]);
+	}
+
+	video->patched_recon_buffer = NULL;
+
+	alloc_size = MVEA_MV_PARAM_REGION_SIZE * ALIGN_4(width_in_mbs) * frame_height_in_mbs;
+	for (i = 0; i < video->mv_stores; i++) {
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 alloc_size, 64, &video->mv[i]))
+			IMG_DBG_ASSERT("Allocation failed (F)" == NULL);
+		topaz_update_device_mem(str_ctx->vxe_ctx, &video->mv[i]);
+	}
+
+	if (video->enable_mvc) {
+		for (i = 0; i < 2; i++) {
+			if (topaz_mmu_stream_alloc
+				(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+				 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+							SYS_MEMATTRIB_WRITECOMBINE),
+				 alloc_size, 64, &video->inter_view_mv[i]))
+				IMG_DBG_ASSERT("Allocation failed (G)" == NULL);
+		}
+	}
+
+	/* memory for encoder context */
+	if (topaz_mmu_stream_alloc
+		(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+		 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+					SYS_MEMATTRIB_WRITECOMBINE),
+		 ALIGN_64(MTX_CONTEXT_SIZE), 64, &video->mtx_enc_ctx_mem))
+		IMG_DBG_ASSERT("Allocation failed (H)" == NULL);
+
+	video->no_sequence_headers = video_params->no_sequence_headers;
+	video->auto_encode = video_params->auto_encode;
+	video->slice_level = video_params->slice_level;
+	video->coded_header_per_slice = video_params->coded_header_per_slice;
+
+	/* partially coded headers supplied to HW */
+	if (topaz_mmu_stream_alloc
+		(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+		 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+					SYS_MEMATTRIB_WRITECOMBINE),
+		 MAX_HEADERSIZEBYTES, 64, &video->seq_header_mem))
+		IMG_DBG_ASSERT("Allocation failed (I)\n" == NULL);
+
+	/* partially coded subset sequence parameter headers supplied to HW */
+	if (video->enable_mvc) {
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 MAX_HEADERSIZEBYTES, 64, &video->subset_seq_header_mem))
+			IMG_DBG_ASSERT("Allocation failed (J)" == NULL);
+	}
+
+	if (topaz_mmu_stream_alloc
+		(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+		 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+					SYS_MEMATTRIB_WRITECOMBINE),
+		 MAX_BFRAMES * MV_ROW_STRIDE, 64, &video->mv_settings_btable))
+
+		IMG_DBG_ASSERT("Allocation failed (K)" == NULL);
+
+	if (video->rc_params.hierarchical) {
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 MAX_BFRAMES * sizeof(struct img_mv_settings), 64,
+			 &video->mv_settings_hierarchical))
+			IMG_DBG_ASSERT("Allocation failed (L)" == NULL);
+	} else {
+		video->mv_settings_hierarchical.cpu_virt = NULL;
+	}
+
+	video->insert_hrd_params = video_params->insert_hrd_params;
+	if (video_params->insert_hrd_params) {
+		alloc_size      = 64;
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 alloc_size, 64, &video->aud_header_mem))
+			IMG_DBG_ASSERT("Allocation failed (M)" == NULL);
+
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 alloc_size, 64, &video->sei_buffering_period_header_mem))
+			IMG_DBG_ASSERT("Allocation failed (N)" == NULL);
+
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 alloc_size, 64, &video->sei_picture_timing_header_mem))
+			IMG_DBG_ASSERT("Allocation failed (O)" == NULL);
+	}
+
+	for (index = 0; index < ARRAY_SIZE(video->pichdr_template_mem); index++) {
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 MAX_HEADERSIZEBYTES, 64, &video->pichdr_template_mem[index]))
+			IMG_DBG_ASSERT("Allocation failed (P)" == NULL);
+	}
+
+	for (index = 0; index < ARRAY_SIZE(video->slice_params_template_mem); index++) {
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 ALIGN_64(sizeof(struct slice_params)), 64,
+			 &video->slice_params_template_mem[index]))
+			IMG_DBG_ASSERT("Allocation failed (Q)" == NULL);
+	}
+
+	for (index = 0; index < video->slots_in_use; index++) {
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 ALIGN_64(sizeof(struct mtx_header_params)), 64,
+			 &video->ltref_header[index]))
+			IMG_DBG_ASSERT("Allocation failed (R)" == NULL);
+	}
+
+	if (topaz_mmu_stream_alloc
+		(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+		 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE),
+		 ALIGN_64(4), 64, &video->src_phys_addr))
+		IMG_DBG_ASSERT("Allocation failed (S)" == NULL);
+
+	for (index = 0; index < video->slots_in_use; index++) {
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 (1 + MAX_SLICESPERPIC * 2 + 15) & ~15, 64,
+			 &video->slice_map[index].mem_info) != IMG_SUCCESS)
+			IMG_DBG_ASSERT("Allocation failed (T)" == NULL);
+	}
+
+	if (topaz_mmu_stream_alloc
+		(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+		 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE),
+		 ALIGN_64(sizeof(unsigned short) * MAX_GOP_SIZE), 64, &video->flat_gop_struct))
+		IMG_DBG_ASSERT("Allocation failed (U)" == NULL);
+
+	if (video->rc_params.hierarchical) {
+		if (topaz_mmu_stream_alloc
+			(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+			 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+						SYS_MEMATTRIB_WRITECOMBINE),
+			 ALIGN_64(sizeof(unsigned short) * MAX_GOP_SIZE), 64,
+			 &video->hierar_gop_struct))
+			IMG_DBG_ASSERT("Allocation failed (V)" == NULL);
+	}
+
+	if (video->custom_scaling) {
+		for (index = 0; index < 2; index++) {
+			if (topaz_mmu_stream_alloc
+				(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+				 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+					 SYS_MEMATTRIB_WRITECOMBINE),
+				 ALIGN_64(QUANT_LISTS_SIZE), 64, &video->custom_quant[index]))
+				IMG_DBG_ASSERT("Allocation failed (W)" == NULL);
+
+			if (topaz_mmu_stream_alloc
+				(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+				 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+					 SYS_MEMATTRIB_WRITECOMBINE),
+				 192, 64, &video->custom_quant_regs4x4_sp[index]))
+				IMG_DBG_ASSERT("Allocation failed (X)" == NULL);
+
+			if (topaz_mmu_stream_alloc
+				(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+				 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+							SYS_MEMATTRIB_WRITECOMBINE),
+				 128 * CUSTOM_QUANT_PARAMSIZE_8x8, 64,
+				 &video->custom_quant_regs8x8_sp[index]))
+				IMG_DBG_ASSERT("Allocation failed (Y)" == NULL);
+
+			if (topaz_mmu_stream_alloc
+				(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+				 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+				 SYS_MEMATTRIB_WRITECOMBINE),
+				 128, 64, &video->custom_quant_regs4x4_q[index]))
+				IMG_DBG_ASSERT("Allocation failed (Z)" == NULL);
+
+			if (topaz_mmu_stream_alloc
+				(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+				 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+				 SYS_MEMATTRIB_WRITECOMBINE),
+				 64 * CUSTOM_QUANT_PARAMSIZE_8x8, 64,
+				 &video->custom_quant_regs8x8_q[index]))
+				IMG_DBG_ASSERT("Allocation failed (0)" == NULL);
+		}
+		video->custom_quant_slot = 0;
+	}
+
+	/* Allocate device memory for storing feedback information for all "5" slots */
+	if (video->enable_sel_stats_flags & ESF_FIRST_STAGE_STATS) {
+		for (index = 0; index < video->slots_in_use; index++) {
+			unsigned int row_size =
+				ALIGN_64(width_in_mbs * sizeof(struct img_first_stage_mb_params));
+
+			/* Allocate memory padding size of each row to be multiple of 64-bytes */
+			if (topaz_mmu_stream_alloc
+				(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+				 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+				 SYS_MEMATTRIB_WRITECOMBINE),
+				 frame_height_in_mbs * row_size, 64,
+				 &video->firstpass_out_param_buf[index].mem_info))
+				IMG_DBG_ASSERT("Allocation failed (1)" == NULL);
+
+			video->firstpass_out_param_buf[index].lock              = BUFFER_FREE;
+			video->firstpass_out_param_buf[index].bytes_written     = 0;
+			video->firstpass_out_param_buf[index].size              =
+				frame_height_in_mbs * row_size;
+		}
+	} else {
+		/* Set buffer pointers to NULL */
+		for (index = 0; index < video->slots_in_use; index++) {
+			video->firstpass_out_param_buf[index].mem_info.cpu_virt = NULL;
+			video->firstpass_out_param_buf[index].lock              = BUFFER_FREE;
+			video->firstpass_out_param_buf[index].bytes_written     = 0;
+			video->firstpass_out_param_buf[index].size              = 0;
+		}
+	}
+
+	/* Allocate device memory for storing feedback information for all "5" slots */
+	if (video->enable_sel_stats_flags & ESF_MP_BEST_MB_DECISION_STATS ||
+	    video->enable_sel_stats_flags & ESF_MP_BEST_MOTION_VECTOR_STATS) {
+		for (index = 0; index < video->slots_in_use; index++) {
+			unsigned int best_multipass_size = frame_height_in_mbs *
+				//From TRM (4.5.2)
+				(((5 * width_in_mbs) + 3) >> 2) * 64;
+
+			/* Allocate memory padding size of each row to be multiple of 64-bytes */
+			if (topaz_mmu_stream_alloc
+				(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+				 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+				 SYS_MEMATTRIB_WRITECOMBINE),
+				 best_multipass_size, 64,
+				 &video->firstpass_out_best_multipass_param_buf[index].mem_info))
+				IMG_DBG_ASSERT("Allocation failed (2)" == NULL);
+
+			video->firstpass_out_best_multipass_param_buf[index].lock               =
+				BUFFER_FREE;
+			video->firstpass_out_best_multipass_param_buf[index].bytes_written      = 0;
+			video->firstpass_out_best_multipass_param_buf[index].size               =
+				best_multipass_size;
+		}
+	} else {
+		/* Set buffer pointers to NULL */
+		for (index = 0; index < video->slots_in_use; index++) {
+			video->firstpass_out_best_multipass_param_buf[index].mem_info.cpu_virt  =
+				NULL;
+			video->firstpass_out_best_multipass_param_buf[index].lock               =
+				BUFFER_FREE;
+			video->firstpass_out_best_multipass_param_buf[index].bytes_written      = 0;
+			video->firstpass_out_best_multipass_param_buf[index].size               = 0;
+		}
+	}
+
+	if (video->enable_inp_ctrl) {
+		for (index = 0; index < video->slots_in_use; index++) {
+			alloc_size =  frame_height_in_mbs *  width_in_mbs * 2;
+
+			/*
+			 * Allocate memory for worst case slice structure
+			 * i.e. assume number-of-slices == number-of-rows
+			 */
+			if (topaz_mmu_stream_alloc
+				(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, 1,
+				 (enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED |
+				 SYS_MEMATTRIB_WRITECOMBINE), alloc_size + 64, 64,
+				 &video->mb_ctrl_in_params_buf[index].mem_info))
+				IMG_DBG_ASSERT("Allocation failed (3)" == NULL);
+
+			video->mb_ctrl_in_params_buf[index].lock = BUFFER_FREE;
+			video->mb_ctrl_in_params_buf[index].bytes_written = 0;
+			video->mb_ctrl_in_params_buf[index].size = alloc_size;
+		}
+	} else {
+		for (index = 0; index < video->slots_in_use; index++) {
+			video->mb_ctrl_in_params_buf[index].mem_info.cpu_virt   = NULL;
+			video->mb_ctrl_in_params_buf[index].lock        = BUFFER_FREE;
+			video->mb_ctrl_in_params_buf[index].bytes_written = 0;
+			video->mb_ctrl_in_params_buf[index].size        = 0;
+		}
+	}
+
+	for (index = 0; index < video->slots_in_use; index++)
+		video->source_slot_buff[index] = NULL;
+
+	/* Allocate coded package */
+	topaz_get_context_coded_buffer_size(enc, rc_params, &coded_buffer_size);
+
+	video->coded_buffer_max_size = coded_buffer_size;
+
+	for (i = 0; i < video->coded_package_max_num; i++) {
+		if (topaz_allocate_coded_package(str_ctx, coded_buffer_size,
+						 &video->coded_package[i]) != IMG_SUCCESS)
+			IMG_DBG_ASSERT("Coded package Allocation failed\n" == NULL);
+	}
+
+	video->encode_sent = 0;
+
+	topaz_video_prepare_templates(str_ctx, video_params->f_code,
+				      video_params->fine_y_search_size);
+
+	enc->video->max_chunks = video_params->max_chunks;
+	enc->video->chunks_per_mb = video_params->chunks_per_mb;
+	enc->video->priority_chunks = video_params->priority_chunks;
+
+	return topaz_video_create_mtx_context(str_ctx, video_params);
+}
+
+unsigned char topaz_validate_params(struct img_video_params *video_params,
+				    struct img_rc_params *rc_params)
+{
+	unsigned char modified = FALSE;
+	unsigned int required_core_des1 = 0;
+	unsigned int core_des1 = topazdd_get_core_des1();
+
+	if (video_params) {
+		/* Validate video params */
+		if (video_params->standard == IMG_STANDARD_H264) {
+			if (video_params->is_interlaced) {
+				if ((core_des1 &
+				    F_ENCODE
+				    (1, TOPAZHP_TOP_CR_TOPAZHP_H264_INTERLACED_SUPPORTED)) == 0) {
+					video_params->is_interlaced = FALSE;
+
+					if (!video_params->is_interleaved) {
+					/* Non-interleaved source.
+					 * Encode field pictures as frames.
+					 */
+						video_params->frame_height >>= 1;
+						video_params->buffer_height >>= 1;
+						video_params->source_frame_height >>= 1;
+					} else {
+					/* Interleaved source. Unite fields into single picture. */
+						video_params->is_interleaved = FALSE;
+					}
+
+					video_params->bottom_field_first = FALSE;
+					modified = TRUE;
+				} else {
+					required_core_des1 |= F_ENCODE(1,
+					TOPAZHP_TOP_CR_TOPAZHP_H264_INTERLACED_SUPPORTED);
+				}
+			}
+
+			if (video_params->h264_8x8) {
+				if ((core_des1 &
+				F_ENCODE(1, TOPAZHP_TOP_CR_TOPAZHP_H264_8X8_TRANSFORM_SUPPORTED)) ==
+					0) {
+					video_params->h264_8x8 = FALSE;
+					modified = TRUE;
+				} else {
+					required_core_des1 |= F_ENCODE(1,
+					TOPAZHP_TOP_CR_TOPAZHP_H264_8X8_TRANSFORM_SUPPORTED);
+				}
+			}
+
+			if (video_params->cabac_enabled) {
+				if ((core_des1 &
+				    F_ENCODE
+				    (1, TOPAZHP_TOP_CR_TOPAZHP_H264_CABAC_SUPPORTED)) == 0) {
+					video_params->cabac_enabled = FALSE;
+					modified = TRUE;
+				} else {
+					required_core_des1 |= F_ENCODE(1,
+					TOPAZHP_TOP_CR_TOPAZHP_H264_CABAC_SUPPORTED);
+				}
+			}
+
+			if (!video_params->enc_features.disable_bframes) {
+				if ((core_des1 &
+				    F_ENCODE
+				    (1, TOPAZHP_TOP_CR_TOPAZHP_H264_B_PIC_SUPPORTED)) == 0) {
+					video_params->enc_features.disable_bframes = FALSE;
+					modified = TRUE;
+				}
+			}
+
+			if (video_params->enable_sel_stats_flags) {
+				if ((core_des1 &
+				    F_ENCODE
+				    (1, TOPAZHP_TOP_CR_TOPAZHP_H264_MULTIPASS_SUPPORTED)) == 0) {
+					video_params->enable_sel_stats_flags = 0;
+					modified = TRUE;
+				} else {
+					required_core_des1 |= F_ENCODE(1,
+					TOPAZHP_TOP_CR_TOPAZHP_H264_MULTIPASS_SUPPORTED);
+				}
+			}
+
+			if (video_params->use_default_scaling_list) {
+				if ((core_des1 &
+				    F_ENCODE
+				    (1, TOPAZHP_TOP_CR_TOPAZHP_H264_DEFAULT_TABLES_SUPPORTED)) ==
+					0) {
+					video_params->use_default_scaling_list = FALSE;
+					modified = TRUE;
+				} else {
+					required_core_des1 |= F_ENCODE(1,
+					TOPAZHP_TOP_CR_TOPAZHP_H264_DEFAULT_TABLES_SUPPORTED);
+				}
+			}
+
+			if (video_params->use_custom_scaling_lists) {
+				if ((core_des1 &
+				    F_ENCODE
+				    (1, TOPAZHP_TOP_CR_TOPAZHP_H264_CUSTOM_QUANT_SUPPORTED)) == 0) {
+					video_params->use_custom_scaling_lists = 0;
+					modified = TRUE;
+				} else {
+					required_core_des1 |= F_ENCODE(1,
+					TOPAZHP_TOP_CR_TOPAZHP_H264_CUSTOM_QUANT_SUPPORTED);
+				}
+			}
+
+			if ((video_params->weighted_prediction ||
+			     video_params->vp_weighted_implicit_bi_pred)) {
+				if ((core_des1 &
+				    F_ENCODE
+				    (1, TOPAZHP_TOP_CR_TOPAZHP_H264_WEIGHTED_PRED_SUPPORTED)) ==
+				     0) {
+					video_params->weighted_prediction = FALSE;
+					video_params->vp_weighted_implicit_bi_pred = 0;
+					modified = TRUE;
+				} else {
+					required_core_des1 |= F_ENCODE(1,
+					TOPAZHP_TOP_CR_TOPAZHP_H264_WEIGHTED_PRED_SUPPORTED);
+				}
+			}
+
+			if (video_params->multi_reference_p || video_params->enable_mvc) {
+				if ((core_des1 &
+				    F_ENCODE
+				    (1, TOPAZHP_TOP_CR_TOPAZHP_H264_2_REF_ON_P_PIC_SUPPORTED)) ==
+					0) {
+					video_params->multi_reference_p = FALSE;
+					video_params->enable_mvc = FALSE;
+					modified = TRUE;
+				} else {
+					required_core_des1 |= F_ENCODE(1,
+					TOPAZHP_TOP_CR_TOPAZHP_H264_2_REF_ON_P_PIC_SUPPORTED);
+				}
+			}
+
+			if (video_params->spatial_direct) {
+				if ((core_des1 &
+					F_ENCODE
+					(1,
+					 TOPAZHP_TOP_CR_TOPAZHP_H264_SPATIAL_DIRECT_SUPPORTED)) ==
+						0) {
+					video_params->spatial_direct = FALSE;
+					modified = TRUE;
+				} else {
+					required_core_des1 |= F_ENCODE(1,
+					TOPAZHP_TOP_CR_TOPAZHP_H264_SPATIAL_DIRECT_SUPPORTED);
+				}
+			}
+
+			if (video_params->enable_lossless) {
+				if ((core_des1 &
+					F_ENCODE
+					(1, TOPAZHP_TOP_CR_TOPAZHP_H264_LOSSLESS_SUPPORTED)) == 0) {
+					video_params->enable_lossless = FALSE;
+					modified = TRUE;
+				} else {
+					required_core_des1 |= F_ENCODE(1,
+						TOPAZHP_TOP_CR_TOPAZHP_H264_LOSSLESS_SUPPORTED);
+				}
+			}
+		}
+
+		if (video_params->enable_scaler) {
+			if ((core_des1 &
+				F_ENCODE(1, TOPAZHP_TOP_CR_TOPAZHP_SCALER_SUPPORTED)) == 0) {
+				video_params->enable_scaler = FALSE;
+				modified = TRUE;
+			} else {
+				required_core_des1 |= F_ENCODE(1,
+						TOPAZHP_TOP_CR_TOPAZHP_SCALER_SUPPORTED);
+			}
+		}
+
+		if (rc_params) {
+			/* Validate RC params */
+			if (video_params->standard == IMG_STANDARD_H264) {
+				if (rc_params->bframes) {
+					if ((core_des1 &
+						F_ENCODE
+						(1, TOPAZHP_TOP_CR_TOPAZHP_H264_B_PIC_SUPPORTED)) ==
+						0) {
+						rc_params->bframes = 0;
+						rc_params->hierarchical = FALSE;
+						modified = TRUE;
+					} else {
+						required_core_des1 |= F_ENCODE(1,
+						TOPAZHP_TOP_CR_TOPAZHP_H264_B_PIC_SUPPORTED);
+					}
+				}
+
+				if (rc_params->hierarchical && rc_params->bframes > 1) {
+					if ((core_des1 &
+					    F_ENCODE
+					(1, TOPAZHP_TOP_CR_TOPAZHP_H264_SPATIAL_DIRECT_SUPPORTED))
+							== 0) {
+						rc_params->hierarchical = FALSE;
+						modified = TRUE;
+					} else {
+						required_core_des1 |= F_ENCODE(1,
+					TOPAZHP_TOP_CR_TOPAZHP_H264_SPATIAL_DIRECT_SUPPORTED);
+					}
+				}
+			}
+		}
+	}
+
+	return modified;
+}
+
+/*
+ * Creat an encoder context
+ */
+int topaz_stream_create(void *vxe_ctx, struct img_video_params *video_params,
+			unsigned char base_pipe, unsigned char pipes_to_use,
+			struct img_rc_params *rc_params, void **topaz_str_context)
+{
+	struct img_enc_context *enc;
+	struct topaz_stream_context *str_ctx;
+
+	if (!is_topaz_core_initialized)
+		return IMG_ERROR_NOT_INITIALISED;
+
+	str_ctx = kzalloc(sizeof(*str_ctx), GFP_KERNEL);
+	if (!str_ctx)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	enc = kzalloc(sizeof(*enc), GFP_KERNEL);
+	if (!enc) {
+		kfree(str_ctx);
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	*topaz_str_context = str_ctx;
+	str_ctx->enc_ctx = enc;
+	str_ctx->core_ctx = global_topaz_core_context;
+	str_ctx->vxe_ctx = (struct vxe_enc_ctx *)vxe_ctx;
+
+	enc->core_rev = topazdd_get_core_rev();
+	enc->sync_first_pass = true;
+
+	enc->requested_base_pipe = base_pipe;
+	enc->base_pipe = base_pipe;
+	enc->requested_pipes_to_use = pipes_to_use;
+	enc->pipes_to_use = pipes_to_use;
+
+	topaz_validate_params(video_params, rc_params);
+
+	switch (video_params->standard) {
+	case IMG_STANDARD_H264:
+		if (video_params->enable_mvc) {
+			switch (rc_params->rc_mode) {
+			case IMG_RCMODE_NONE:
+				enc->codec = IMG_CODEC_H264MVC_NO_RC;
+				break;
+			case IMG_RCMODE_CBR:
+				enc->codec = IMG_CODEC_H264MVC_CBR;
+				break;
+			case IMG_RCMODE_VBR:
+				enc->codec = IMG_CODEC_H264MVC_VBR;
+				break;
+			case IMG_RCMODE_ERC:
+				enc->codec = IMG_CODEC_H264MVC_ERC;
+				break;
+			case IMG_RCMODE_VCM:
+				IMG_DBG_ASSERT("VCM mode is not supported for MVC" == NULL);
+				break;
+			default:
+				break;
+			}
+		} else {
+			switch (rc_params->rc_mode) {
+			case IMG_RCMODE_NONE:
+				enc->codec = IMG_CODEC_H264_NO_RC;
+				break;
+			case IMG_RCMODE_CBR:
+				enc->codec = IMG_CODEC_H264_CBR;
+				break;
+			case IMG_RCMODE_VBR:
+				enc->codec = IMG_CODEC_H264_VBR;
+				break;
+			case IMG_RCMODE_VCM:
+				enc->codec = IMG_CODEC_H264_VCM;
+				break;
+			case IMG_RCMODE_ERC:
+				enc->codec = IMG_CODEC_H264_ERC;
+				break;
+			default:
+				break;
+			}
+		}
+		break;
+	default:
+		IMG_DBG_ASSERT("Only H264 encode is supported" == NULL);
+	}
+
+	/* initialise video context structure */
+	return (topaz_video_create_context(str_ctx, video_params, rc_params));
+}
+
+/*
+ * Sends a command to the specified core.
+ * The function returns a writeback value.  This is a unique value that will be
+ * written back by the target core after it completes its command.
+ */
+unsigned int topaz_insert_command(struct img_enc_context *enc_ctx,
+				  enum mtx_cmd_id cmd_id, unsigned int data)
+{
+	unsigned int writeback_val;
+
+	if (enc_ctx->debug_settings &&
+	    enc_ctx->debug_settings->serialized_communication_mode ==
+	     VXE_SERIALIZED_MODE_SERIAL)
+		/* in serial mode do not use the priority bit */
+		cmd_id &= ~MTX_CMDID_PRIORITY;
+
+	topazdd_send_msg(enc_ctx->video->dd_str_ctx, cmd_id, data, NULL, &writeback_val);
+
+	return writeback_val;
+}
+
+/*
+ * Sends a command to the specified core.
+ */
+unsigned int topaz_insert_command_with_sync(struct img_enc_context *enc_ctx,
+					    enum mtx_cmd_id cmd_id, unsigned int data)
+{
+	int ret;
+
+	if (enc_ctx->debug_settings &&
+	    enc_ctx->debug_settings->serialized_communication_mode ==
+	     VXE_SERIALIZED_MODE_SERIAL)
+		/* in serial mode do not use the priority bit */
+		cmd_id &= ~MTX_CMDID_PRIORITY;
+
+	ret = topazdd_send_msg_with_sync(enc_ctx->video->dd_str_ctx, cmd_id, data, NULL);
+
+	return ret;
+}
+
+/*
+ * Sends a command to the specified core.
+ * The data specified in psCommandData will be read via DMA by the MTX,
+ * so this memory must remain in scope for the duration of the execution
+ * of the command.
+ * The function returns a writeback value.  This is a unique value that will be
+ * written back by the target core after it completes its command.
+ */
+unsigned int topaz_insert_mem_command(struct img_enc_context *enc_ctx,
+				      enum mtx_cmd_id cmd_id,
+				      unsigned int data,
+				      struct vidio_ddbufinfo *command_data)
+{
+	unsigned int writeback_val;
+
+	/* Priority bit is not supported for MEM commands */
+	cmd_id &= ~MTX_CMDID_PRIORITY;
+
+	topazdd_send_msg(enc_ctx->video->dd_str_ctx, cmd_id, data, command_data, &writeback_val);
+
+	return writeback_val;
+}
+
+/*
+ * Sends a command to the specified core.
+ * The data specified in psCommandData will be read via DMA by the MTX,
+ * so this memory must remain in scope for the duration of the execution
+ * of the command.
+ */
+unsigned int topaz_insert_mem_command_with_sync(struct img_enc_context *enc_ctx,
+						enum mtx_cmd_id cmd_id,
+						unsigned int data,
+						struct vidio_ddbufinfo *command_data)
+{
+	int ret;
+
+	/* Priority bit is not supported for MEM commands */
+	cmd_id &= ~MTX_CMDID_PRIORITY;
+
+	ret = topazdd_send_msg_with_sync(enc_ctx->video->dd_str_ctx, cmd_id,
+					 data, command_data);
+	return ret;
+}
+
+/*
+ * Send the Access Unit Delimiter to the stream
+ */
+static int topaz_send_aud_header(struct img_enc_context *enc)
+{
+	if (enc->video->aborted)
+		return IMG_ERROR_UNDEFINED;
+
+	/* must use unique writeback word */
+	topaz_insert_mem_command(enc, MTX_CMDID_DO_HEADER, 0,
+				 enc->video->aud_header_mem.cpu_virt);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Transmit the picture headerts to MTX
+ */
+static int topaz_send_picture_headers(struct img_enc_context *enc)
+{
+	/* send Seqence headers only for IDR (I-frames) and only once in the beginning */
+	struct img_video_context *video = enc->video;
+
+	/* SEI_INSERTION */
+	if (video->insert_hrd_params) {
+		/* Access unit delimiter */
+		if (!video->enable_mvc || (video->enable_mvc && video->mvc_view_idx == 0))
+			/* in case of MVC, both views are a single access unit.
+			 *  delimiter should be inserted by view 0 only.
+			 */
+			topaz_send_aud_header(enc);
+	}
+
+	if (video->insert_seq_header && !video->no_sequence_headers) {
+		switch (video->standard) {
+		case IMG_STANDARD_H264:
+			IMG_DBG_ASSERT("SPS and PPS will be send from firmware." != NULL);
+			break;
+		default:
+			IMG_DBG_ASSERT("only H264 encode is supported." == NULL);
+			break;
+		}
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Encode a frame
+ */
+int topaz_encode_frame(void *topaz_str_ctx)
+{
+	struct img_enc_context *enc;
+	struct img_video_context *video;
+	struct topaz_stream_context *str_ctx;
+	/* If line counter is enabled, we add one more bit in the command data
+	 * to inform the firmware context whether it should proceed
+	 */
+	unsigned int encode_cmd_data;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+
+	enc = str_ctx->enc_ctx;
+	video = enc->video;
+
+	if (video->aborted)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	video->insert_seq_header = (video->encode_sent == 0);
+
+	topaz_send_picture_headers(enc);
+
+	encode_cmd_data = F_ENCODE(1, MTX_MSG_ENCODE_CODED_INTERRUPT);
+
+	if (video->line_counter)
+		/* Set bit 20 to 1 to inform FW that we are using the line counter feature */
+		encode_cmd_data |= F_ENCODE(1, MTX_MSG_ENCODE_USE_LINE_COUNTER);
+
+	topaz_insert_command(enc, (enum mtx_cmd_id)
+				       (MTX_CMDID_ENCODE_FRAME | MTX_CMDID_WB_INTERRUPT),
+		encode_cmd_data);
+
+	video->encode_pic_processing++;
+	video->encode_sent++;
+
+	return IMG_SUCCESS;
+}
+
+int topaz_get_pipe_usage(unsigned char pipe, unsigned char *ctx_id)
+{
+	IMG_DBG_ASSERT(pipe < TOPAZHP_MAX_NUM_PIPES);
+
+	if (pipe >= TOPAZHP_MAX_NUM_PIPES)
+		return 0;
+
+	return global_pipe_usage[pipe];
+}
+
+void topaz_set_pipe_usage(unsigned char pipe, unsigned char val)
+{
+	IMG_DBG_ASSERT(pipe < TOPAZHP_MAX_NUM_PIPES);
+
+	if (pipe < TOPAZHP_MAX_NUM_PIPES)
+		global_pipe_usage[pipe] = val;
+}
+
+/*
+ * Set the mtx context to the one implicit in the encoder context
+ */
+static int topaz_video_setup_mtx_context(struct img_enc_context *enc)
+{
+	struct img_video_context *video_context;
+	unsigned char index;
+
+	video_context = enc->video;
+
+	for (index = 0; index < enc->pipes_to_use; index++)
+		topaz_set_pipe_usage(enc->base_pipe + index, enc->ctx_num);
+
+	if (topaz_insert_mem_command_with_sync(enc, (enum mtx_cmd_id)
+					       (MTX_CMDID_SETVIDEO | MTX_CMDID_WB_INTERRUPT),
+		enc->base_pipe, &video_context->mtx_enc_ctx_mem)) {
+		pr_err("topaz mtx context setup command failed\n");
+		return IMG_ERROR_UNDEFINED;
+	}
+
+	video_context->aborted = FALSE;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Load the encoder and MTX context
+ */
+int topaz_load_context(void *topaz_str_ctx)
+{
+	struct topaz_stream_context *str_ctx;
+	struct img_enc_context *enc;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+	enc = str_ctx->enc_ctx;
+
+	enc->video->vid_ctx_num = 0;
+
+	enc->ctx_num++;
+
+	return topaz_video_setup_mtx_context(enc);
+}
+
+/*
+ * Store the encoder and MTX context
+ */
+int topaz_store_context(void *topaz_str_ctx)
+{
+	struct img_enc_context *enc;
+	struct topaz_stream_context *str_ctx;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+	enc = str_ctx->enc_ctx;
+
+	/* Update Globals */
+	if (enc->codec != IMG_CODEC_NONE && enc->codec != IMG_CODEC_JPEG) {
+		struct img_video_context *video_context;
+
+		video_context = enc->video;
+
+		if (!topaz_insert_mem_command_with_sync(enc, (enum mtx_cmd_id)
+							(MTX_CMDID_GETVIDEO |
+							 MTX_CMDID_WB_INTERRUPT),
+			enc->base_pipe, &video_context->mtx_enc_ctx_mem)) {
+			pr_err("MTX message for GETVIDEO failed\n");
+			return IMG_ERROR_UNDEFINED;
+		}
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Flush video stream
+ */
+int topaz_flush_stream(void *topaz_str_ctx, unsigned int frame_cnt)
+{
+	struct topaz_stream_context *str_ctx;
+	struct img_enc_context *enc;
+	int index;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+
+	enc = str_ctx->enc_ctx;
+
+	if (enc->video->aborted)
+		return IMG_ERROR_UNDEFINED;
+
+	/* flush the internal queues */
+	/* Check source slots */
+	for (index = 0; index < enc->video->slots_in_use; index++) {
+		if (enc->video->source_slot_buff[index]) {
+			/* Found a valid src_frame, so signal callback for the same. */
+			global_topaz_core_context->vxe_str_processed_cb(str_ctx->vxe_ctx,
+				VXE_CB_SRC_FRAME_RELEASE,
+				(void *)(enc->video->source_slot_buff[index]),
+				0, 0, 0);
+			enc->video->source_slot_buff[index] = NULL;
+		}
+	}
+
+	/* Check coded package slots */
+	for (index = 0; index < enc->video->coded_package_max_num; index++) {
+		if (enc->video->coded_package[index]->busy) {
+			/* Found a valid coded package, so, signal callback for the same */
+			global_topaz_core_context->vxe_str_processed_cb(str_ctx->vxe_ctx,
+				VXE_CB_CODED_BUFF_READY,
+				(void *)(enc->video->coded_package[index]->coded_buffer[0]),
+				0, 0, 0);
+			enc->video->coded_package[index]->busy = FALSE;
+		}
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Destroy the Video Encoder context
+ */
+static int topaz_video_destroy_context(struct topaz_stream_context *str_ctx)
+{
+	struct img_enc_context *enc;
+	struct img_video_context *video;
+	int i;
+	unsigned int max_cores;
+
+	max_cores = topazdd_get_num_pipes(str_ctx->core_ctx->dev_handle);
+	enc = str_ctx->enc_ctx;
+	video = enc->video;
+
+	for (i = 0; i < enc->pipes_to_use; i++)
+		if (topaz_get_pipe_usage(enc->base_pipe + i, NULL) == enc->ctx_num)
+			topaz_set_pipe_usage(enc->base_pipe + i, 0);
+
+	if (video->standard == IMG_STANDARD_H264 && video->weighted_prediction) {
+		for (i = 0; i < video->slots_in_use; i++) {
+			if (topaz_mmu_stream_free(str_ctx->mmu_ctx,
+						  &video->weighted_prediction_mem[i]))
+				IMG_DBG_ASSERT("Free failed" == NULL);
+		}
+	}
+
+	for (i = 0; i < video->coded_package_max_num; i++) {
+		if (topaz_mmu_stream_free
+			(str_ctx->mmu_ctx,
+			 &video->coded_package[i]->mtx_info.code_package_fw_buffer->mem_info))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+
+		kfree(video->coded_package[i]->mtx_info.code_package_fw_buffer);
+		video->coded_package[i]->mtx_info.code_package_fw_buffer = NULL;
+
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx,
+					  &video->coded_package[i]->header_buffer->mem_info))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+
+		kfree(video->coded_package[i]->header_buffer);
+		video->coded_package[i]->header_buffer = NULL;
+
+		kfree(video->coded_package[i]);
+		video->coded_package[i] = NULL;
+	}
+
+	if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->flat_gop_struct))
+		IMG_DBG_ASSERT("Free failed" == NULL);
+
+	if (video->rc_params.hierarchical)
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->hierar_gop_struct))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+
+	for (i = 0; i < video->slots_in_use; i++) {
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->slice_map[i].mem_info))
+			IMG_DBG_ASSERT("slice map free failed" == NULL);
+	}
+
+	for (i = 0; i < (int)max_cores; i++) {
+		if (str_ctx->vxe_ctx->above_mb_params_sgt[i].sgl) {
+			topaz_mmu_stream_free_sg(str_ctx->mmu_ctx, &video->above_params[i]);
+		} else {
+			if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->above_params[i]))
+				IMG_DBG_ASSERT("Free failed" == NULL);
+		}
+	}
+
+	for (i = 0; i < video->pic_nodes; i++)
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->colocated[i]))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+
+	for (i = 0; i < video->pic_nodes; i++)
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->recon_pictures[i]))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+
+	for (i = 0; i < video->mv_stores; i++)
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->mv[i]))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+
+	if (video->enable_mvc) {
+		for (i = 0; i < 2; i++) {
+			if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->inter_view_mv[i]))
+				IMG_DBG_ASSERT("Free failed" == NULL);
+		}
+	}
+
+	if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->mtx_enc_ctx_mem))
+		IMG_DBG_ASSERT("Free failed" == NULL);
+
+	if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->mv_settings_btable))
+		IMG_DBG_ASSERT("Free failed" == NULL);
+
+	if (video->mv_settings_hierarchical.cpu_virt)
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->mv_settings_hierarchical))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+
+	/* partially coded headers supplied to HW */
+	/* SEI_INSERTION */
+	if (video->insert_hrd_params) {
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->aud_header_mem))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx,
+					  &video->sei_buffering_period_header_mem))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->sei_picture_timing_header_mem))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+	}
+
+	if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->seq_header_mem))
+		IMG_DBG_ASSERT("Free failed" == NULL);
+
+	/* FREE subset sequence parameter header */
+	if (video->enable_mvc)
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->subset_seq_header_mem))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+
+	for (i = 0; i < ARRAY_SIZE(video->pichdr_template_mem); i++) {
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->pichdr_template_mem[i]))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(video->slice_params_template_mem); i++) {
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->slice_params_template_mem[i]))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+	}
+
+	if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->src_phys_addr))
+		IMG_DBG_ASSERT("Free failed" == NULL);
+
+	/* de-allocate memory corresponding to the output parameters */
+	for (i = 0; i < video->slots_in_use; i++) {
+		if (video->firstpass_out_param_buf[i].mem_info.cpu_virt)
+			if (topaz_mmu_stream_free(str_ctx->mmu_ctx,
+						  &video->firstpass_out_param_buf[i].mem_info))
+				IMG_DBG_ASSERT("Free failed" == NULL);
+
+		if (video->mb_ctrl_in_params_buf[i].mem_info.cpu_virt)
+			if (topaz_mmu_stream_free(str_ctx->mmu_ctx,
+						  &video->mb_ctrl_in_params_buf[i].mem_info))
+				IMG_DBG_ASSERT("Free failed" == NULL);
+	}
+
+	/* de-allocate memory corresponding to the selectable best MV parameters */
+	for (i = 0; i < video->slots_in_use; i++) {
+		if (video->firstpass_out_best_multipass_param_buf[i].mem_info.cpu_virt)
+			if (topaz_mmu_stream_free
+				(str_ctx->mmu_ctx,
+				 &video->firstpass_out_best_multipass_param_buf[i].mem_info))
+				IMG_DBG_ASSERT("Free failed" == NULL);
+	}
+
+	for (i = 0; i < video->slots_in_use; i++) {
+		if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->ltref_header[i]))
+			IMG_DBG_ASSERT("Free failed" == NULL);
+	}
+
+	if (video->custom_scaling) {
+		for (i = 0; i < 2; i++) {
+			if (topaz_mmu_stream_free(str_ctx->mmu_ctx, &video->custom_quant[i]))
+				IMG_DBG_ASSERT("Free failed" == NULL);
+
+			if (topaz_mmu_stream_free(str_ctx->mmu_ctx,
+						  &video->custom_quant_regs4x4_sp[i]))
+				IMG_DBG_ASSERT("Free failed" == NULL);
+
+			if (topaz_mmu_stream_free(str_ctx->mmu_ctx,
+						  &video->custom_quant_regs8x8_sp[i]))
+				IMG_DBG_ASSERT("Free failed" == NULL);
+
+			if (topaz_mmu_stream_free(str_ctx->mmu_ctx,
+						  &video->custom_quant_regs4x4_q[i]))
+				IMG_DBG_ASSERT("Free failed" == NULL);
+
+			if (topaz_mmu_stream_free(str_ctx->mmu_ctx,
+						  &video->custom_quant_regs8x8_q[i]))
+				IMG_DBG_ASSERT("Free failed" == NULL);
+		}
+	}
+
+	topazdd_destroy_stream_ctx(video->dd_str_ctx);
+
+	topaz_mmu_stream_destroy(&global_topaz_core_context->dev_handle->topaz_mmu_ctx,
+				 str_ctx->mmu_ctx);
+
+	/* free the video encoder structure itself */
+	kfree(video);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Destroy an Encoder Context
+ */
+int topaz_stream_destroy(void *str_context)
+{
+	struct img_enc_context *enc;
+	struct topaz_stream_context *str_ctx;
+	int ret;
+
+	str_ctx = (struct topaz_stream_context *)str_context;
+	if (!str_ctx)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	enc = str_ctx->enc_ctx;
+
+	ret = topaz_video_destroy_context(str_ctx);
+
+	kfree(enc->debug_settings);
+	enc->debug_settings = NULL;
+
+	kfree(enc);
+	kfree(str_context);
+
+	return ret;
+}
+
+/*
+ * Get the capabilities of the encoder for the given codec
+ */
+int topaz_get_encoder_caps(enum img_standard standard,
+			   unsigned short width, unsigned short height,
+			   struct img_enc_caps *caps)
+{
+	unsigned int width_in_mbs, height_in_mbs, kick_size, kicks_per_bu, min_slice_height, mbs;
+
+	/* get the actual number of cores */
+	caps->num_cores = topazdd_get_num_pipes(global_topaz_core_context->dev_handle);
+
+	if (caps->num_cores < 3)
+		caps->max_bu_per_frame = TOPAZHP_MAX_BU_SUPPORT_HD;
+	else
+		caps->max_bu_per_frame = TOPAZHP_MAX_BU_SUPPORT_4K;
+
+	caps->core_features = topazdd_get_core_des1();
+	caps->core_revision = topazdd_get_core_rev();
+
+	width_in_mbs = (width + 15) / 16;
+	height_in_mbs = (height + 15) / 16;
+
+	switch (standard) {
+	case IMG_STANDARD_H264:
+		/* Assume progressive video for now as we don't know either way */
+		calculate_kick_and_bu_size(width_in_mbs, height_in_mbs, FALSE,
+					   caps->max_bu_per_frame, &kick_size, &kicks_per_bu,
+					   &min_slice_height);
+		caps->max_slices = height_in_mbs / min_slice_height;
+
+		/*
+		 * Limit for number of MBs in slices is 32K-2 = 32766
+		 * Here we will limit it to 16K per slice = 16384
+		 */
+		caps->min_slices = 1;
+		mbs = width_in_mbs * height_in_mbs;
+		if (mbs >= 32768)
+			caps->min_slices = 3;
+		else if (mbs >= 16384)
+			caps->min_slices = 2;
+
+		/* if height is bigger or equal to 4000, use at least two slices */
+		if (height_in_mbs >= 250 && caps->min_slices == 1)
+			caps->min_slices = 2;
+
+		caps->recommended_slices = min(caps->num_cores, caps->max_slices);
+		caps->min_slice_height = min_slice_height;
+
+		caps->max_height = 2048;
+		caps->max_width = 2048;
+		caps->min_height = 48;
+		caps->min_width = 144;
+		caps->max_mb_num = (2048 * 2048) >> 8;
+		break;
+	default:
+		IMG_DBG_ASSERT("Only H264 encoder is supported" == NULL);
+	}
+
+	if (caps->recommended_slices < caps->min_slices)
+		caps->recommended_slices = caps->min_slices;
+	if (caps->recommended_slices > caps->max_slices)
+		caps->recommended_slices = caps->max_slices;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Supply a source frame to the encode process
+ */
+int topaz_send_source_frame(void *topaz_str_ctx, struct img_frame *src_frame,
+			    unsigned int frame_num, unsigned long long ctx)
+{
+	struct topaz_stream_context *str_ctx;
+	struct img_source_buffer_params *buffer_params;
+
+	struct img_enc_context *enc;
+	struct img_video_context *video;
+	unsigned char slot_number;
+	void *data;
+	unsigned int y_plane_base = 0;
+	unsigned int u_plane_base = 0;
+	unsigned int v_plane_base = 0;
+	struct vidio_ddbufinfo *cmd_data_mem_info = NULL;
+	unsigned char *slice_map_addr = NULL;
+	unsigned char index;
+	unsigned char round;
+	unsigned char slice_number;
+	unsigned char first_bu_in_slice;
+	unsigned char size_in_bus;
+	unsigned int slice_height;
+	unsigned char halfway_slice;
+	unsigned int halfway_bu;
+	unsigned char slices_per_picture;
+	unsigned int picture_height_remaining;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	/* if source slot is NULL then it's just a next portion of slices */
+	if (!src_frame)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+
+	enc = str_ctx->enc_ctx;
+	video = enc->video;
+
+	if (video->aborted)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	slot_number = video->source_slot_reserved;
+
+	/* mark the appropriate slot as filled */
+	video->source_slot_buff[slot_number] = src_frame;
+	video->source_slot_poc[slot_number] = frame_num;
+
+	topaz_get_cmd_data_buffer(&cmd_data_mem_info);
+
+	if (!cmd_data_mem_info)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	data = cmd_data_mem_info->cpu_virt;
+	buffer_params = (struct img_source_buffer_params *)data;
+
+	/* Prepare data */
+	if (src_frame->y_plane_buffer) {
+		populate_firmware_message(&video->src_phys_addr, 0,
+					  &src_frame->y_plane_buffer->mem_info, 0);
+
+		data = video->src_phys_addr.cpu_virt;
+		y_plane_base = *((unsigned int *)data);
+	}
+
+	if (src_frame->u_plane_buffer) {
+		populate_firmware_message(&video->src_phys_addr, 0,
+					  &src_frame->u_plane_buffer->mem_info, 0);
+
+		data = video->src_phys_addr.cpu_virt;
+		u_plane_base = *((unsigned int *)data);
+	} else {
+		u_plane_base = y_plane_base;
+	}
+
+	if (src_frame->v_plane_buffer) {
+		populate_firmware_message(&video->src_phys_addr, 0,
+					  &src_frame->v_plane_buffer->mem_info, 0);
+
+		data = video->src_phys_addr.cpu_virt;
+		v_plane_base = *((unsigned int *)data);
+	} else {
+		v_plane_base = u_plane_base;
+	}
+
+	buffer_params->slot_num = slot_number;
+	buffer_params->display_order_num = (unsigned char)(frame_num & 0xFF);
+	buffer_params->host_context = ctx;
+
+	buffer_params->phys_addr_y_plane_field_0 = y_plane_base + src_frame->y_component_offset +
+		src_frame->field0_y_offset;
+	buffer_params->phys_addr_u_plane_field_0 = u_plane_base + src_frame->u_component_offset +
+		src_frame->field0_u_offset;
+	buffer_params->phys_addr_v_plane_field_0 = v_plane_base + src_frame->v_component_offset +
+		src_frame->field0_v_offset;
+
+	buffer_params->phys_addr_y_plane_field_1 = y_plane_base + src_frame->y_component_offset +
+		src_frame->field1_y_offset;
+	buffer_params->phys_addr_u_plane_field_1 = u_plane_base + src_frame->u_component_offset +
+		src_frame->field1_u_offset;
+	buffer_params->phys_addr_v_plane_field_1 = v_plane_base + src_frame->v_component_offset +
+		src_frame->field1_v_offset;
+
+	topaz_update_device_mem(str_ctx->vxe_ctx, cmd_data_mem_info);
+
+	topaz_get_buffer(str_ctx, &video->slice_map[slot_number], (void **)&slice_map_addr,
+			 FALSE);
+
+	/* Fill standard Slice Map (non arbitrary) */
+	halfway_bu = 0;
+	first_bu_in_slice = 0;
+	slice_number = 0;
+	slices_per_picture = video->slices_per_picture;
+	picture_height_remaining = video->picture_height;
+	halfway_slice = slices_per_picture / 2;
+	*slice_map_addr = slices_per_picture;
+	slice_map_addr++;
+	round = 16 * enc->caps.min_slice_height - 1;
+
+	for (index = 0; index < slices_per_picture - 1; index++) {
+		if (index == halfway_slice)
+			halfway_bu = first_bu_in_slice;
+
+		slice_height = (picture_height_remaining / (video->slices_per_picture - index)) &
+			~round;
+		picture_height_remaining -= slice_height;
+		size_in_bus = ((slice_height / 16) * (video->width / 16)) /
+			video->rc_params.bu_size;
+
+		/* slice number */
+		*slice_map_addr = slice_number;
+		slice_map_addr++;
+
+		/* SizeInKicks BU */
+		*slice_map_addr = size_in_bus;
+		slice_map_addr++;
+
+		slice_number++;
+
+		first_bu_in_slice += (unsigned int)size_in_bus;
+	}
+
+	slice_height = picture_height_remaining;
+	if (index == halfway_slice)
+		halfway_bu = first_bu_in_slice;
+
+	/* round up for case where the last BU is smaller */
+	size_in_bus = ((slice_height / 16) * (video->width / 16) + video->rc_params.bu_size - 1) /
+		video->rc_params.bu_size;
+
+	/* slice number */
+	*slice_map_addr = slice_number;
+	slice_map_addr++;
+
+	/* last BU */
+	*slice_map_addr = size_in_bus;
+	slice_map_addr++;
+
+	topaz_release_buffer(str_ctx, &video->slice_map[slot_number], TRUE);
+
+#ifdef DEBUG_ENCODER_DRIVER
+	pr_info("\n\nAPI - IMG_V_SendSourceFrame - Sending a source slot %i to FW\n\n",
+		slot_number);
+#endif
+
+	/* Send command */
+	topaz_insert_mem_command(enc, MTX_CMDID_PROVIDE_SOURCE_BUFFER, 0, cmd_data_mem_info);
+
+	video->encode_requested++;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Supply a header buffer and an optional number of coded data buffers as part of a package
+ */
+int topaz_send_coded_package(void *topaz_str_ctx, struct img_coded_buffer *coded_buffer)
+{
+	struct img_enc_context *enc;
+	struct img_video_context *video;
+	struct topaz_stream_context *str_ctx;
+	unsigned char coded_buffer_idx;
+	unsigned int *address = NULL;
+	struct coded_package_dma_info *this_coded_header_node;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+	if (!coded_buffer)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+
+	enc = str_ctx->enc_ctx;
+	video = enc->video;
+
+	if (video->aborted)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	video->coded_package[video->coded_package_slot_reserved]->coded_buffer[0] = coded_buffer;
+
+#ifdef DEBUG_ENCODER_DRIVER
+	pr_info("\n\nEncode Context [%i] sending coded package [%i]\n", enc->ctx_num,
+		video->coded_package_slot_reserved);
+#endif
+
+	/* Get the FW buffer */
+	topaz_get_buffer
+	(str_ctx,
+	 video->coded_package[video->coded_package_slot_reserved]->mtx_info.code_package_fw_buffer,
+	 (void **)&address, FALSE);
+
+	this_coded_header_node =
+	video->coded_package[video->coded_package_slot_reserved]->mtx_info.coded_package_fw =
+							(struct coded_package_dma_info *)address;
+
+	this_coded_header_node->coded_buffer_info =
+		F_ENCODE
+		(video->coded_package[video->coded_package_slot_reserved]->num_coded_buffers,
+		 MTX_MSG_NUM_CODED_BUFFERS_PER_HEADER);
+
+	/* Inverted function: From host to MTX */
+	populate_firmware_message(&(video->coded_package
+		[video->coded_package_slot_reserved]->mtx_info.code_package_fw_buffer->mem_info),
+		(unsigned char *)&this_coded_header_node->coded_header_addr -
+		(unsigned char *)this_coded_header_node,
+		(struct vidio_ddbufinfo *)
+		(&(video->coded_package[video->coded_package_slot_reserved]->header_buffer->mem_info
+		)), 0);
+
+	/* Normal mode - An array of consecutive memory addresses */
+	for (coded_buffer_idx = 0; coded_buffer_idx <
+		video->coded_package[video->coded_package_slot_reserved]->num_coded_buffers;
+		coded_buffer_idx++) {
+		if (video->coded_package[video->coded_package_slot_reserved]->coded_buffer
+							[coded_buffer_idx]) {
+			/* Write coded buffer memory address into the structure (host to MTX) */
+			populate_firmware_message(&(video->coded_package
+		[video->coded_package_slot_reserved]->mtx_info.code_package_fw_buffer->mem_info),
+		(unsigned char *)&this_coded_header_node->coded_mem_addr[coded_buffer_idx] -
+		(unsigned char *)this_coded_header_node, (struct vidio_ddbufinfo *)
+		(&(video->coded_package
+		[video->coded_package_slot_reserved]->coded_buffer[coded_buffer_idx]->mem_info)),
+		0);
+		} else {
+			this_coded_header_node->coded_mem_addr[coded_buffer_idx] = 0;
+			break;
+		}
+	}
+
+	/* Release the FW buffer */
+	topaz_release_buffer(str_ctx, video->coded_package
+	[video->coded_package_slot_reserved]->mtx_info.code_package_fw_buffer, TRUE);
+
+	/* Send header buffers to the MTX */
+	topaz_insert_mem_command(enc, (enum mtx_cmd_id)(MTX_CMDID_PROVIDE_CODEDPACKAGE_BUFFER |
+							MTX_CMDID_WB_INTERRUPT),
+	F_ENCODE(video->coded_package[video->coded_package_slot_reserved]->coded_buffer[0]->size >>
+	10, MTX_MSG_PROVIDE_CODED_BUFFER_SIZE) |
+	F_ENCODE(video->coded_package_slot_reserved, MTX_MSG_PROVIDE_CODEDPACKAGE_BUFFER_SLOT),
+	&(video->coded_package
+		[video->coded_package_slot_reserved]->mtx_info.code_package_fw_buffer->mem_info));
+
+	return IMG_SUCCESS;
+}
+
+unsigned int topaz_get_coded_buffer_max_size(void *topaz_str_ctx, enum img_standard standard,
+					     unsigned short width, unsigned short height,
+					     struct img_rc_params *rc_params)
+{
+	/* TODO: Determine if we want to make this api str_ctx dependent
+	 * struct topaz_stream_context *str_ctx;
+	 * if (!topaz_str_ctx)
+	 * return IMG_ERROR_INVALID_CONTEXT;
+	 */
+	/* Worst-case coded buffer size: All MBs maximum size,
+	 * and a coded buffer header for each row
+	 */
+	return topaz_get_max_coded_data_size(standard, width, height, rc_params->initial_qp_i) +
+	       ((height >> 4) * CODED_BUFFER_INFO_SECTION_SIZE);
+}
+
+unsigned int topaz_get_coded_package_max_num(void *topaz_str_ctx, enum img_standard standard,
+					     unsigned short width, unsigned short height,
+					     struct img_rc_params *rc_params)
+{
+	struct topaz_stream_context *str_ctx;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+
+	return str_ctx->enc_ctx->video->coded_package_max_num;
+}
+
+/*
+ * Get a source slot to fill
+ */
+int topaz_reserve_source_slot(void *topaz_str_ctx, unsigned char *src_slot_num)
+{
+	struct img_enc_context *enc;
+	struct img_video_context *video;
+	struct topaz_stream_context *str_ctx;
+	signed char index;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+	enc = str_ctx->enc_ctx;
+	video = enc->video;
+
+	if (video->aborted)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	for (index = 0; index < video->slots_in_use; index++) {
+		if (!video->source_slot_buff[index]) {
+			/* Found an empty slot, Mark the slot as reserved */
+			video->source_slot_reserved = index;
+			*src_slot_num = index;
+			return IMG_SUCCESS;
+		}
+	}
+
+	return IMG_ERROR_UNEXPECTED_STATE;
+}
+
+/*
+ * Get a coded slot to fill
+ */
+int topaz_reserve_coded_package_slot(void *topaz_str_ctx)
+{
+	struct img_enc_context *enc;
+	struct img_video_context *video;
+	struct topaz_stream_context *str_ctx;
+	signed char index;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+
+	enc = str_ctx->enc_ctx;
+	video = enc->video;
+
+	if (video->aborted)
+		return IMG_ERROR_UNEXPECTED_STATE;
+
+	for (index = 0; index < video->coded_package_max_num; index++) {
+		if (!video->coded_package[index]->busy) {
+			/* Found an empty slot, Mark the slot as reserved */
+			video->coded_package_slot_reserved = index;
+			video->coded_package[index]->busy = TRUE;
+			return IMG_SUCCESS;
+		}
+	}
+
+	return IMG_ERROR_UNEXPECTED_STATE;
+}
+
+/*
+ * Returns number of empty source slots
+ */
+signed char topaz_query_empty_source_slots(void *topaz_str_ctx)
+{
+	struct topaz_stream_context *str_ctx;
+	struct img_enc_context *enc;
+	struct img_video_context *video;
+
+	unsigned char slot_number;
+	unsigned char empty_source_slots = 0;
+
+	if (!topaz_str_ctx) {
+		pr_err("ERROR: Invalid context handle provides to IMG_V_QueryEmptySourceSlots\n");
+		return IMG_ERROR_INVALID_CONTEXT;
+	}
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+	enc = str_ctx->enc_ctx;
+	video = enc->video;
+
+	if (video->aborted)
+		return -2;
+
+	for (slot_number = 0; slot_number < video->slots_in_use; slot_number++) {
+		if (!video->source_slot_buff[slot_number])
+			empty_source_slots++;
+	}
+
+	return empty_source_slots;
+}
+
+/*
+ * Returns number of empty coded buffer slots
+ */
+signed char topaz_query_empty_coded_slots(void *topaz_str_ctx)
+{
+	struct topaz_stream_context *str_ctx;
+	struct img_enc_context *enc;
+	struct img_video_context *video;
+
+	unsigned char slot_number;
+	unsigned char empty_coded_slots = 0;
+
+	if (!topaz_str_ctx) {
+		pr_err("ERROR: Invalid context handle provides to IMG_V_QueryEmptyCodedSlots\n");
+		return IMG_ERROR_INVALID_CONTEXT;
+	}
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+	enc = str_ctx->enc_ctx;
+	video = enc->video;
+
+	if (video->aborted)
+		return -2;
+
+	for (slot_number = 0; slot_number < video->coded_package_max_num; slot_number++) {
+		if (!video->coded_package[slot_number]->busy)
+			empty_coded_slots++;
+	}
+
+	return empty_coded_slots;
+}
+
+/*
+ * topaz_stream_map_buf_sg
+ */
+int topaz_stream_map_buf_sg(void *topaz_str_ctx, enum venc_buf_type buf_type,
+			    struct vidio_ddbufinfo *buf_info, void *sgt)
+{
+	int ret;
+	struct topaz_stream_context *str_ctx;
+
+	/*
+	 * Resource stream ID cannot be zero. If zero just warning and
+	 * proceeding further will break the code. Return IMG_ERROR_INVALID_ID.
+	 */
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	IMG_DBG_ASSERT(buf_type < VENC_BUFTYPE_MAX);
+	IMG_DBG_ASSERT(buf_info);
+	IMG_DBG_ASSERT(sgt);
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+
+	/* Map heap from VENC to MMU. Currently only one heap is used for all buffer types */
+	switch (buf_type) {
+	case VENC_BUFTYPE_BITSTREAM:
+	case VENC_BUFTYPE_PICTURE:
+		/* TODO: add logic to cache these buffers into str context list */
+		break;
+
+	default:
+		IMG_DBG_ASSERT(FALSE);
+	}
+
+	/* Map this buffer into the MMU. */
+	ret = topaz_mmu_stream_map_ext_sg(str_ctx->mmu_ctx, MMU_GENERAL_HEAP_ID, sgt,
+					  buf_info->buf_size, 64,
+					  (enum sys_emem_attrib)0, buf_info->cpu_virt, buf_info,
+					  &buf_info->buff_id);
+	IMG_DBG_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * core_stream_unmap_buf_sg
+ */
+int topaz_stream_unmap_buf_sg(void *topaz_str_ctx, struct vidio_ddbufinfo *buf_info)
+{
+	int ret;
+	struct topaz_stream_context *str_ctx;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+
+	/* Unmap this buffer from the MMU. */
+	ret = topaz_mmu_stream_free_sg(str_ctx->mmu_ctx, buf_info);
+
+	IMG_DBG_ASSERT(ret == IMG_SUCCESS);
+	if (ret != IMG_SUCCESS)
+		return ret;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * End Of Video stream
+ */
+int topaz_end_of_stream(void *topaz_str_ctx, unsigned int frame_cnt)
+{
+	struct topaz_stream_context *str_ctx;
+	struct img_enc_context *enc;
+
+	if (!topaz_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	str_ctx = (struct topaz_stream_context *)topaz_str_ctx;
+	enc = str_ctx->enc_ctx;
+
+	if (enc->video->aborted)
+		return IMG_ERROR_UNDEFINED;
+
+	enc->video->frame_count = frame_cnt;
+
+	if (frame_cnt - enc->video->flushed_at_frame < enc->video->slots_in_use)
+		enc->video->slots_required = frame_cnt - enc->video->flushed_at_frame;
+
+	/* Send PicMgmt Command */
+	topaz_insert_command(enc, (enum mtx_cmd_id)(MTX_CMDID_PICMGMT | MTX_CMDID_PRIORITY),
+			     F_ENCODE(IMG_PICMGMT_EOS, MTX_MSG_PICMGMT_SUBTYPE) |
+			     F_ENCODE(frame_cnt, MTX_MSG_PICMGMT_DATA));
+
+	return IMG_SUCCESS;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/topaz_api.h b/drivers/media/platform/img/vxe-vxd/encoder/topaz_api.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/topaz_api.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/topaz_api.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1047 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Encoder core interface header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef __TOPAZ_API_H__
+#define __TOPAZ_API_H__
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "fw_headers/topazscfwif.h"
+#include "fw_headers/vxe_common.h"
+#include "vid_buf.h"
+#include "lst.h"
+
+#define MAX_MVC_VIEWS		2
+#define MVC_BASE_VIEW_IDX	0
+#define NON_MVC_VIEW		(~0x0)
+
+#define MVC_SPS_ID		1
+#define MVC_PPS_ID		1
+
+#define NUM_SLICE_TYPES		5
+#define MAX_PLANES		3
+
+/*
+ * This type defines the buffer type categories.
+ * @brief  Buffer Types
+ */
+enum venc_buf_type {
+	VENC_BUFTYPE_BITSTREAM   = 0,
+	VENC_BUFTYPE_PICTURE,
+	VENC_BUFTYPE_ALL,
+	VENC_BUFTYPE_MAX,
+	VENC_BUFTYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * VXE callback type definitions
+ */
+enum vxe_cb_type {
+	VXE_CB_CODED_BUFF_READY,
+	VXE_CB_SRC_FRAME_RELEASE,
+	VXE_CB_STR_END,
+	VXE_CB_ERROR_FATAL,
+	VXE_CB_FORCE32BITS = 0x7FFFFFFFU
+};
+
+typedef void (*vxe_cb)(void *ctx, enum vxe_cb_type type, void *buf_ref, unsigned int size,
+		unsigned int coded_frm_cnt, enum img_frame_type frame_type);
+
+/*
+ * Enum specifying video encode profile
+ */
+enum img_video_enc_profile {
+	ENC_PROFILE_DEFAULT     = 0,
+	ENC_PROFILE_LOWCOMPLEXITY,
+	ENC_PROFILE_HIGHCOMPLEXITY,
+	ENC_PROFILE_REDUCEDMODE,
+	ENC_PROFILE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Enum describing smallest blocksize used during motion search
+ */
+enum img_ipe_minblock_size {
+	BLK_SZ_16x16       = 0,
+	BLK_SZ_8x8         = 1,
+	BLK_SZ_4x4         = 2,
+	BLK_SZ_DEFAULT     = 3,
+	BLK_SZ_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Struct specifying flags to enable/disable encode features.
+ * All boolean flags are FALSE by default
+ */
+struct img_encode_features {
+	unsigned short disable_intra4x4;
+	unsigned short disable_intra8x8;
+	unsigned short disable_intra16x16;
+	unsigned short disable_inter8x8;
+	unsigned short restrict_inter4x4;
+	unsigned short disable_bpic_ref1;
+	unsigned short disable_bpic_ref0;
+	unsigned short enable_8x16_mv_detect;
+	unsigned short enable_16x8_mv_detect;
+	unsigned short disable_bframes;
+	enum img_ipe_minblock_size min_blk_sz;
+	unsigned short restricted_intra_pred;
+};
+
+/*
+ *
+ * Struct describing Macro-block params generated by first stage.
+ * Refer T.R.M. for details
+ */
+struct img_first_stage_mb_params {
+	unsigned short ipe0_sad;
+	unsigned short ipe1_sad;
+	unsigned char ipe0_blks;
+	unsigned char ipe1_blks;
+	unsigned char carc_cmplx_val;
+	unsigned char reserved;
+};
+
+/*
+ * Size of Inter/Intra & Coded/Skipped tables
+ */
+#define TOPAZHP_SCALE_TBL_SZ                    (8)
+#define DEFAULT_CABAC_DB_MARGIN    (0x190)
+
+/*
+ *Struct describing params for video encoding
+ *@enable_sel_stats_flags:  Flags to enable selective first-pass statistics gathering by the
+ *hardware. Bit 1 - First Stage Motion Search Data, Bit 2 - Best
+ *			Multipass MB Decision Data, Bit 3 - Best Multipass Motion Vectors.
+ *			(First stage Table 2 motion vectors are always switched on)
+ *@enable_inp_ctrl:  Enable Macro-block input control
+ *@enable_air:  Enable Adaptive Intra Refresh
+ *@num_air_mbs:  n = Max number of AIR MBs per frame, 0 = _ALL_ MBs over threshold will be marked
+ *			as AIR Intras, -1 = Auto 10%
+ *@air_threshold:  n = SAD Threshold above which a MB is a AIR MB candidate,  -1 = Auto adjusting
+ *			threshold
+ *@air_skip_cnt:  n = Number of MBs to skip in AIR Table between frames, -1 = Random
+ *			(0 - NumAIRMbs) skip between frames in AIR table
+ *@disable_bit_stuffing:  Disabling bitstuffing to maintain bitrate
+ *@mpeg2_intra_dc_precision:  Only used in MPEG2, 2 bit field (0 = 8 bit, 1 = 9 bit, 2 = 10 bit
+ *			and 3=11 bit precision). Set to zero for other encode standards.
+ *@enable_mvc: True if MVC is enabled. False by default
+ *@mvc_view_idx:  MVC view index
+ *@disable_bh_rounding:  True if we wish to disable the buffer height rounding to 16 pixels
+ *			(enables contiguous YU memory for non-aligned image heights)
+ *@auto_expand_pipes:  Automatically expand a context pipe allocations when new pipes become
+ *			available
+ *@line_counter_enabled:  <! Drives the activation of low-latency encoding
+ */
+struct img_video_params {
+	enum img_standard standard;
+	enum img_format format;
+	enum img_csc_preset csc_preset;
+	unsigned char slices_per_picture;
+	unsigned short width;
+	unsigned short frame_height;
+	unsigned char is_interlaced;
+	unsigned char is_interleaved;
+	unsigned char constrained_intra;
+	unsigned char h264_8x8;
+	unsigned char bottom_field_first;
+	unsigned char arbitrary_so;
+	unsigned char cabac_enabled;
+	unsigned int cabac_bin_limit;
+	unsigned int cabac_bin_flex;
+	unsigned char deblock_idc;
+	unsigned char output_reconstructed;
+	unsigned int f_code;
+	int fine_y_search_size;
+	unsigned char no_offscreen_mv;
+	unsigned int idr_period;
+	unsigned int intra_cnt;
+	unsigned int vop_time_resolution;
+	struct img_encode_features enc_features;
+	unsigned char enable_sel_stats_flags;
+	unsigned char enable_inp_ctrl;
+	unsigned char enable_air;
+	int num_air_mbs;
+	int air_threshold;
+	short air_skip_cnt;
+	unsigned char enable_cumulative_biases;
+	unsigned char enable_host_bias;
+	unsigned char enable_host_qp;
+	unsigned char use_default_scaling_list;
+	short use_custom_scaling_lists;
+	unsigned short pps_scaling;
+	unsigned int vert_mv_limit;
+	unsigned int intra_pred_modes;
+	unsigned short limit_num_vectors;
+	unsigned short disable_bit_stuffing;
+	unsigned char coded_skipped_index;
+	unsigned char inter_intra_index;
+	unsigned char mpeg2_intra_dc_precision;
+
+	/* Contents Adaptive Rate Control parameters */
+	unsigned short carc;
+	int carc_baseline;
+	unsigned int carc_threshold;
+	unsigned int carc_cutoff;
+	unsigned int carc_neg_range;
+	unsigned int carc_neg_scale;
+	unsigned int carc_pos_range;
+	unsigned int carc_pos_scale;
+	unsigned int carc_shift;
+
+	/* Weighted prediction */
+	unsigned char weighted_prediction;
+	unsigned char vp_weighted_implicit_bi_pred;
+
+	/* SEI insertion */
+	unsigned char insert_hrd_params;
+
+	unsigned short intra_refresh;
+
+	unsigned int chunks_per_mb;
+	unsigned int max_chunks;
+	unsigned int priority_chunks;
+	unsigned int mbps;
+
+	unsigned char multi_reference_p;
+	unsigned char ref_spacing;
+	unsigned char spatial_direct;
+
+	unsigned short vp_adaptive_rounding_disable;
+	unsigned short vp_adaptive_rounding_offsets[18][4];
+
+	unsigned int debug_crcs;
+
+	unsigned char enable_mvc;
+	unsigned short mvc_view_idx;
+	unsigned char high_latency;
+
+	unsigned short buffer_stride_bytes;
+	unsigned short buffer_height;
+	unsigned char disable_bh_rounding;
+	unsigned short source_width;
+	unsigned short source_frame_height;
+
+	unsigned char no_sequence_headers;
+	unsigned char auto_encode;
+	unsigned char slice_level;
+	unsigned char coded_header_per_slice;
+
+	unsigned char auto_expand_pipes;
+	unsigned char enable_lossless;
+	unsigned char lossless_8x8_prefilter;
+
+	unsigned char enable_scaler;
+	unsigned short crop_left;
+	unsigned short crop_right;
+	unsigned short crop_top;
+	unsigned short crop_bottom;
+
+#if SECURE_IO_PORTS
+	unsigned char secure_ctx_input;
+	unsigned char secure_ctx_output;
+#endif
+	/* Low latency encoding related */
+	unsigned char line_counter_enabled;
+};
+
+/*
+ * Struct describing JPEG component info
+ */
+struct component_info {
+	unsigned int width;           /* Width of the image component */
+	unsigned int stride;          /* Stride of the image component */
+	unsigned int step;            /* Step of the image component */
+	unsigned int height;          /* Height of the image component */
+};
+
+/*
+ * Struct describing JPEG info
+ */
+struct img_unaligned_source_info {
+	unsigned int output_width;                /* Width of the JPEG image */
+	unsigned int output_height;               /* Height of the JPEG image */
+	unsigned int components;                  /* Number of components in the image ( 1 or 3 ) */
+	struct component_info comp_info[3]; /* Array containing component info */
+};
+
+/*
+ * Struct containing details of a reconstuctured picture
+ */
+struct img_recon_done {
+	unsigned int poc;		/* PicOrderCount */
+	void *buffer;		/* Buffer containing reconstructured image */
+};
+
+/*
+ * Struct containing a feedback for one frame
+ *@is_coded:  Is the frame was coded or skipped completely?
+ *@is_skipped:  Is the frame coded as a set of skipped MBs?
+ *@entire_frame:  Was the frame encoded entirely or there a still slices to come?
+ *@img_frame_type frame_type:  Frame Type (IDR, I, P, B)
+ *@source_slot:  Number of the source slot, containing the source buffer
+ *@recon_idx:  Number of the slot, conaining reconstructed picture
+ *@*src_frame:  Source buffer
+ *@*motion_search_statistics_buf:  Buffer to contain Table 1 (8 byte Motion Search Data) of the
+ *					selectable stats
+ *@*best_multipass_statistics_buf:  Buffer to contain (optionally) Table 4 (64 bytes
+ *				Multipass Motion Vectors) and table 3 (16 byte Multipass Parameters)
+ *@coded_package: Pointer to the coded package, containing the returned
+ *			header and coded buffer information
+ *@recon_list:  List of reconstructed pictures
+ *@bytes_coded:  Size of the encoded slice in bytes
+ *@first_bu:  Number of the first BU in the slice
+ *@storage_frame_num:  Last 2 bits of the Frame number in Storage Order
+ *@slice_num:  Number of the slice in a Slice Map supplied
+ *@slices_per_picture:  Number of the slices in this picture
+ *@field:  The field this slice belongs to
+ *@coded_slot_num:  Slot number of the coded buffer
+ *@poc:  PicOrderCount of the coded slice
+ *@patched_recon:  Was the reconstructed picture written to a patched buffer?
+ *@slices_in_buffer:  Number of slices contained in the coded buffer
+ *@last_frame_encoded:  True if the last frame has been encoded
+ *@coded_buffer_count:  Number of coded buffer used
+ *@host_ctx:  Host context value
+ */
+struct img_feedback_element {
+	unsigned char is_coded;
+	unsigned char is_skipped;
+	unsigned char entire_frame;
+	enum img_frame_type frame_type;
+	unsigned char source_slot;
+	unsigned char recon_idx;
+	struct img_frame *src_frame;
+	struct img_buffer *motion_search_statistics_buf;
+	struct img_buffer *best_multipass_statistics_buf;
+
+	struct coded_package_host *coded_package;
+
+	struct list_item *recon_list;
+	unsigned int bytes_coded;
+	unsigned int first_bu;
+	unsigned char storage_frame_num;
+	unsigned char slice_num;
+	unsigned char slices_per_picture;
+	unsigned char field;
+	unsigned char coded_slot_num;
+
+	unsigned char active_coded_package_idx;
+
+	unsigned int poc;
+	unsigned char patched_recon;
+	unsigned char slices_in_buffer;
+	unsigned char last_frame_encoded;
+	unsigned char coded_buffer_count;
+
+	unsigned long long host_ctx;
+};
+
+/*
+ * Bit fields for ui32CoreFeatures
+ */
+#define SCALER_SUPPORTED_MASK                           0x00000080
+#define GENERATE_PERFORMANCE_STORE_MASK                 0x00000100
+#define H264_LOSSLESS_SUPPORTED_MASK                    0x00000200
+#define H264_CUSTOM_QUANT_SUPPORTED_MASK                0x00000400
+#define MPEG2_SUPPORTED_MASK                            0x00000800
+#define SIGNATURES_SUPPORTED_SUBSET_MASK                0x00001000
+#define SIGNATURES_SUPPORTED_ALL_MASK                   0x00002000
+#define H264_WEIGHTED_PRED_ME_SUPPORTED_MASK		0x00004000
+#define H264_WEIGHTED_PRED_SUPPORTED_MASK               0x00008000
+#define H264_2_REF_ON_P_PIC_SUPPORTED_MASK              0x00010000
+#define H264_SPATIAL_DIRECT_SUPPORTED_MASK              0x00020000
+#define H264_MULTIPASS_SUPPORTED_MASK                   0x00040000
+#define H264_DEFAULT_TABLES_SUPPORTED_MASK              0x00080000
+#define H264_8X8_TRANSFORM_SUPPORTED_MASK               0x00100000
+#define H264_INTERLACED_SUPPORTED_MASK         0x00200000
+#define H264_B_PIC_SUPPORTED_MASK              0x00400000
+#define H264_16X8_8X16_SUPPORTED_MASK          0x00800000
+#define H264_CABAC_SUPPORTED_MASK              0x01000000
+#define SLAVE_JPEG_SUPPORTED_MASK              0x02000000
+#define JPEG_SUPPORTED_MASK           0x04000000
+#define H263_SUPPORTED_MASK           0x08000000
+#define MPEG4_SUPPORTED_MASK          0x10000000
+#define H264_SUPPORTED_MASK           0x20000000
+#define DMAC_SUPPORTED_MASK           0x40000000
+#define MMU_SUPPORTED_MASK            0x80000000
+
+/*
+ * Struct describing the capabilities of the encoder
+ */
+struct img_enc_caps {
+	unsigned short min_slices;              /* Minimum slices to use */
+	unsigned short max_slices;              /* Maximum slices to use */
+	unsigned short recommended_slices;      /* Recommended number of slices */
+	unsigned short num_cores;               /* Number of cores that will be used */
+	unsigned int core_features;           /* Core features flags */
+	unsigned int core_revision;           /* Core revision */
+	unsigned int max_height;              /* Maximum height supported */
+	unsigned int max_width;               /* Maximum width supported */
+	unsigned int min_height;              /* Minimum height supported */
+	unsigned int min_width;               /* Minimum width supported */
+	unsigned int max_mb_num;              /* Maximum number of macro blocks */
+	unsigned int min_slice_height;        /* Minimum number of rows that a slice can span
+					       * (not including automatic slice breaks)
+					       */
+	unsigned int max_bu_per_frame;        /* Maximum number of basic units per frame */
+};
+
+/*
+ * Struct describing driver results message
+ */
+struct driver_tohost_msg {
+	enum mtx_message_id cmd_id;
+	enum mtx_cmd_id input_cmd_id;
+	unsigned int data;
+	struct vidio_ddbufinfo *command_data_buf;
+	struct img_feedback_element feedback;
+};
+
+/*
+ * Enum describing picture coding type
+ */
+
+enum h264_picture_coding_type {
+	I_FRAME                = 0, /* An intra frame */
+	P_FRAME                = 1, /* An inter frame */
+	B_FRAME                = 2, /* A B frame */
+	FRAME_TYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Struct describing H264 VUI parameters
+ */
+struct h264_vui_params {
+	unsigned int time_scale;	/* Time scale as defined in the H.264 specification */
+	unsigned int bit_rate_value_minus1;		/* An inter framebitrate/64)-1 */
+	unsigned int cbp_size_value_minus1;		/* An inter frame(bitrate*1.5)/16 */
+	unsigned char aspect_ratio_info_present_flag;	/* aspect_ratio_info_present_flag as
+							 * defined in the H.264 specification
+							 */
+	unsigned char aspect_ratio_idc;			/* as defined in the H.264 specification */
+	unsigned short sar_width;
+	unsigned short sar_height;
+	unsigned char cbr;			/* CBR as defined in the H.264 specification */
+	/* as defined in the H.264 specification */
+	unsigned char initial_cpb_removal_delay_length_minus1;
+	unsigned char cpb_removal_delay_length_minus1;	/* as defined in the H.264 specification */
+	unsigned char dpb_output_delay_length_minus1;	/* as defined in the H.264 specification */
+	unsigned char time_offset_length;		/* as defined in the H.264 specification */
+	unsigned char num_reorder_frames;
+	unsigned char max_dec_frame_buffering;
+};
+
+/*
+ * Struct describing H264 crop parameters
+ */
+struct h264_crop_params {
+	/* Flag indicating if cropping parameters are present */
+	unsigned char clip;
+	/* Number of pixels to crop from the left side /2 */
+	unsigned short left_crop_offset;
+	/* Number of pixels to crop from the right side /2 */
+	unsigned short right_crop_offset;
+	unsigned short top_crop_offset;		/* Number of pixels to crop from the top /2 */
+	unsigned short bottom_crop_offset;	/* Number of pixels to crop from the bottom /2 */
+};
+
+/*
+ * Enum describing Profile (H264)
+ */
+enum sh_profile_type {
+	SH_PROFILE_BP          = 0,	/* H.264 Baseline Profile */
+	SH_PROFILE_MP          = 1,	/* H.264 Main Profile */
+	SH_PROFILE_HP          = 2,	/* H.264 High Profile */
+	SH_PROFILE_H10P        = 3,	/* H.264 High 10P Profile */
+	SH_PROFILE_H422P       = 4,	/* H.264 High 4:2:2 Profile */
+	SH_PROFILE_H444P       = 5,	/* H.264 High 4:4:4 Profile */
+	SH_PROFILE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Enum describing level (H264)
+ */
+enum sh_level_type {
+	SH_LEVEL_1           = 10,	/* H264 Level as specified in the specification */
+	SH_LEVEL_1B          = 1,	/* Special-case H264 Level */
+	SH_LEVEL_11          = 11,	/* H264 Level as specified in the specification */
+	SH_LEVEL_12          = 12,	/* H264 Level as specified in the specification */
+	SH_LEVEL_13          = 13,	/* H264 Level as specified in the specification */
+	SH_LEVEL_2           = 20,	/* H264 Level as specified in the specification */
+	SH_LEVEL_21          = 21,	/* H264 Level as specified in the specification */
+	SH_LEVEL_22          = 22,	/* H264 Level as specified in the specification */
+	SH_LEVEL_3           = 30,	/* H264 Level as specified in the specification */
+	SH_LEVEL_31          = 31,	/* H264 Level as specified in the specification */
+	SH_LEVEL_32          = 32,	/* H264 Level as specified in the specification */
+	SH_LEVEL_4           = 40,	/* H264 Level as specified in the specification */
+	SH_LEVEL_41          = 41,	/* H264 Level as specified in the specification */
+	SH_LEVEL_42          = 42,	/* H264 Level as specified in the specification */
+	SH_LEVEL_5           = 50,	/* H264 Level as specified in the specification */
+	SH_LEVEL_51          = 51,	/* H264 Level as specified in the specification */
+	SH_LEVEL_52          = 52,	/* H264 Level as specified in the specification */
+	SH_LEVEL_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * Struct describing SPS (sequence) parameters (H264)
+ */
+struct h264_sequence_header_params {
+	enum sh_profile_type profile;
+	enum sh_level_type level;
+	unsigned char width_in_mbs_minus1;
+	unsigned char height_in_maps_units_minus1;
+	unsigned char log2_max_pic_order_cnt;
+	unsigned char max_num_ref_frames;
+	unsigned char gaps_in_frame_num_value;
+	unsigned char frame_mbs_only_flag;
+	unsigned char vui_params_present;
+	unsigned char seq_scaling_matrix_present_flag;
+
+	unsigned char use_default_scaling_list;
+	unsigned char is_lossless;
+	struct h264_vui_params vui_params;
+};
+
+/*
+ * Struct describing Bias parameters
+ */
+struct img_henc_debug_settings {
+	unsigned int serialized_communication_mode;
+};
+
+#define VXE_SERIALIZED_MODE_OFF         (0)
+#define VXE_SERIALIZED_MODE_SYNCED      (1)
+#define VXE_SERIALIZED_MODE_SERIAL      (2)
+
+/*
+ * Struct describing input parameters to encode a video picture
+ */
+struct pic_params {
+	unsigned int flags;                           /* Picture parameter flags */
+	struct in_rc_params in_params;          /* Rate control parameters */
+};
+
+/*
+ * Video encode context
+ *@void *dd_str_ctx:		Pointer to device instance data
+ *@standard:			Video standard
+ *@frame_height:		target output height
+ *@picture_height:		target output height
+ *@buffer_stride_bytes:		input buffer stride
+ *@buffer_height:		input buffer width
+ *@format:	Pixel format of the source surface
+ *@csc_preset:	Colour space conversion to be performed on the source surface
+ *@pic_params:	Picture level parameters (supplied by driver)
+ *@above_params[TOPAZHP_MAX_NUM_PIPES]:	Picture level parameters (supplied by driver)
+ *@recon_pictures[MAX_PIC_NODES]:  Reference pictures (2 input and 1 output)
+ *@colocated[MAX_PIC_NODES]:	Colocated vector stores (2 input and 1 output)
+ *@mv[MAX_MV:	Vector stores
+ *@inter_view_mv[2]:  Inter-view vector stores
+ *@seq_header_mem:  Partially coded Sequence header
+ *@subset_seq_header_mem:  Partially coded Subset sequence header for H264 mvc
+ *@flat_gop_struct:  Flat MiniGop structure
+ *@hierar_gop_struct:  Hierarchical MiniGop structure
+ *@custom_quant[2]:  Custom quantization values
+ *@custom_quant_regs4x4_sp[2]:	Custom quantization register values for 4x4 Sp
+ *@vidio_ddbufinfo custom_quant_regs8x8_sp[2]:	Custom quantization register values for 8x8 Sp
+ *@vidio_ddbufinfo custom_quant_regs4x4_q[2]:	Custom quantization register values for 4x4 Q
+ *@vidio_ddbufinfo custom_quant_regs8x8_q[2]:	Custom quantization register values for 8x8 Q
+ *@slice_map[MAX_SOURCE_SLOTS_SL]:	Slice map of the source picture
+ *@firstpass_out_param_buf[MAX_SOURCE_SLOTS_SL]:	Output Parameters of the First Pass
+ *@firstpass_out_best_multipass_param_buf[MAX_SOURCE_SLOTS_SL]:	Output Selectable Best MV
+ *								Parameters of the First Pass
+ *@mb_ctrl_in_params_buf[MAX_SOURCE_SLOTS_SL]:	Input Parameters to the second pass
+ *@ipe_control:	common bits IPE control register for entire picture
+ *@pred_comb_control:  common bits of Predictor-combiner control register for entire picture
+ *@cabac_enabled:  FLAG to enable Cabac mode
+ *@cabac_bin_limit:  Min Bin Limit after which the Topaz hardware would encode MB as IPCM
+ *@cabac_bin_flex:  Max Flex-Limit, the Topaz-HW will encode MB as IPCM after (BinLimit+BinFlex)
+ *@vidio_ddbufinfo mv_settings_btable:	three colocated vector stores (2 input and 1 output)
+ *@img_frame *source_slot_buff[MAX_SOURCE_SLOTS_SL]:	Source slots
+ *@unsigned int source_slot_poc[MAX_SOURCE_SLOTS_SL]:	POCs of frames in slots
+ *@unsigned char slots_in_use:	Number of source slots
+ *@unsigned char slots_required:  Number of source slots to be consumed
+ *@coded_package_host *coded_package[MAX_CODED_PACKAGES]:  Collection of coded/header information
+ *@unsigned char encoder_idle:  Indicates that the encoder is waiting for data,
+ *                              Set to true at start of encode
+ *@unsigned char enable_sel_stats_flags:  Flags to enable selective first-pass
+ *					statistics gathering by the
+ *					hardware. Bit 1 - First Stage Motion Search Data, Bit 2
+ *					- Best Multipass MB Decision Data, Bit 3 - Best Multipass
+ *					 Motion Vectors. (First stage Table 2 motion vectors are
+ *					 always switched on)
+ *@enable_inp_ctrl;Enable Macro-block input control
+ *@enable_air:	Enable Adaptive Intra Refresh
+ *@num_air_mbs:	n = Max number of AIR MBs per frame, 0 = _ALL_ MBs over threshold will be marked
+ *				as AIR Intras, -1 = Auto 10%
+ *@air_threshold:  n = SAD Threshold above which a MB is a AIR MB candidate,
+ *				-1 = Auto adjusting threshold
+ *@air_skip_cnt:  n = Number of MBs to skip in AIR Table between frames,
+ *			-1 = Random (0 - NumAIRMbs) skip between frames in AIR table
+ *@enable_mvc:		True if MVC is enabled. False by default
+ *@mvc_view_idx:	View Idx of this MVC view
+ *@line_counter:	Keep track of line counter activation
+ */
+struct img_video_context {
+	/* topaz dd str context handle */
+	void *dd_str_ctx;
+	unsigned int dd_ctx_num;
+
+	/* stream level params */
+	enum img_standard standard;
+	unsigned short width;
+	unsigned short frame_height;
+	unsigned short picture_height;
+	unsigned short buffer_stride_bytes;
+	unsigned short buffer_height;
+	unsigned char frame_rate;
+
+	unsigned short unrounded_width;
+	unsigned short unrounded_frame_height;
+
+	unsigned int debug_crcs;
+	enum img_format format;
+	enum img_csc_preset csc_preset;
+
+	/* Numbers of array elements that will be allocated */
+	int pic_nodes;
+	int mv_stores;
+
+	/* per core params */
+	struct pic_params pic_params;
+	struct vidio_ddbufinfo above_params[TOPAZHP_MAX_NUM_PIPES];
+	struct vidio_ddbufinfo recon_pictures[MAX_PIC_NODES];
+	struct vidio_ddbufinfo colocated[MAX_PIC_NODES];
+	struct vidio_ddbufinfo mv[MAX_MV];
+	struct vidio_ddbufinfo inter_view_mv[2];
+
+	/* partially coded headers supplied to HW */
+	/* SEI_INSERTION */
+	struct vidio_ddbufinfo aud_header_mem;
+	struct vidio_ddbufinfo sei_buffering_period_header_mem;
+	struct vidio_ddbufinfo sei_picture_timing_header_mem;
+
+	struct vidio_ddbufinfo seq_header_mem;
+	struct vidio_ddbufinfo subset_seq_header_mem;
+	struct vidio_ddbufinfo pichdr_template_mem[4];
+	struct vidio_ddbufinfo slice_params_template_mem[NUM_SLICE_TYPES];
+
+	unsigned int f_code;
+	struct vidio_ddbufinfo src_phys_addr;
+
+	/* WEIGHTED PREDICTION */
+	struct vidio_ddbufinfo weighted_prediction_mem[MAX_SOURCE_SLOTS_SL];
+	unsigned char weighted_prediction;
+	unsigned char weighted_bi_pred;
+
+	struct vidio_ddbufinfo flat_gop_struct;
+	struct vidio_ddbufinfo hierar_gop_struct;
+
+	struct vidio_ddbufinfo ltref_header[MAX_SOURCE_SLOTS_SL];
+
+	struct vidio_ddbufinfo custom_quant[2];
+	struct vidio_ddbufinfo custom_quant_regs4x4_sp[2];
+	struct vidio_ddbufinfo custom_quant_regs8x8_sp[2];
+	struct vidio_ddbufinfo custom_quant_regs4x4_q[2];
+	struct vidio_ddbufinfo custom_quant_regs8x8_q[2];
+	unsigned char custom_quant_slot;
+
+	struct img_buffer slice_map[MAX_SOURCE_SLOTS_SL];
+
+	struct img_buffer firstpass_out_param_buf[MAX_SOURCE_SLOTS_SL];
+
+	struct img_buffer firstpass_out_best_multipass_param_buf[MAX_SOURCE_SLOTS_SL];
+	struct img_buffer mb_ctrl_in_params_buf[MAX_SOURCE_SLOTS_SL];
+
+	/* these values set at picture level & written in at slice */
+	unsigned int ipe_control;
+	unsigned int pred_comb_control;
+	unsigned char cabac_enabled;
+	unsigned int cabac_bin_limit;
+	unsigned int cabac_bin_flex;
+
+	unsigned int first_pic_flags;
+	unsigned int non_first_pic_flags;
+
+	unsigned char is_interlaced;
+	unsigned char is_interleaved;
+	unsigned char top_field_first;
+	unsigned char arbitrary_so;
+	unsigned char slices_per_picture;
+	unsigned char deblock_idc;
+	unsigned int kick_size;
+	unsigned int kicks_per_bu;
+	unsigned int vop_time_resolution;
+	unsigned int idr_period;
+	unsigned int intra_cnt;
+	unsigned char multi_reference_p;
+	unsigned char spatial_direct;
+
+	struct img_mv_settings mv_settings_idr;
+	struct img_mv_settings mv_settings_non_b[MAX_BFRAMES + 1];
+
+	/*  | MVSetingsB0 | MVSetingsB1 | ... | MVSetings Bn |  */
+
+	struct vidio_ddbufinfo mv_settings_btable;
+	struct vidio_ddbufinfo mv_settings_hierarchical;
+
+	/* Source slots */
+	struct img_frame *source_slot_buff[MAX_SOURCE_SLOTS_SL];
+	unsigned int source_slot_poc[MAX_SOURCE_SLOTS_SL];
+	unsigned char slots_in_use;
+	unsigned char slots_required;
+
+	/* Coded slots */
+	struct coded_package_host *coded_package[MAX_CODED_PACKAGES];
+	unsigned int coded_buffer_max_size;
+	unsigned char coded_package_max_num;
+
+	unsigned int frame_count;
+	unsigned int flush_at_frame;
+	unsigned int flushed_at_frame;
+	unsigned int encode_sent;
+	unsigned int encode_requested;
+	unsigned int frames_encoded;
+	unsigned char encoder_idle;
+	unsigned char aborted;
+
+	struct list_item *ref_frame;
+	unsigned int recon_poc;
+	unsigned int next_recon;
+
+	struct vidio_ddbufinfo *recon_buffer;
+	struct vidio_ddbufinfo *patched_recon_buffer;
+
+	struct img_rc_params rc_params;
+	enum img_frame_type frame_type;
+
+	unsigned int buffers_status_reg;
+
+	unsigned char insert_seq_header;
+	unsigned char output_reconstructed;
+
+	unsigned int encode_pic_processing;
+	unsigned char extra_wb_retrieved;
+
+	unsigned char enable_sel_stats_flags;
+
+	unsigned char enable_inp_ctrl;
+	unsigned char enable_air;
+	int num_air_mbs;
+	int air_threshold;
+	short air_skip_cnt;
+
+	unsigned char enable_host_bias;
+	unsigned char enable_host_qp;
+
+	unsigned char custom_scaling;
+	unsigned char pps_scaling;
+	unsigned char h264_8x8_transform;
+	unsigned char h264_intra_constrained;
+	unsigned int vert_mv_limit;
+	unsigned int intra_pred_modes;
+	unsigned char limit_num_vectors;
+	unsigned char disable_bit_stuffing;
+	unsigned char coded_skipped_index;
+	unsigned char inter_intra_index;
+	struct vidio_ddbufinfo mtx_enc_ctx_mem;
+	/* SEI_INSERTION */
+	unsigned char insert_hrd_params;
+	unsigned int chunks_per_mb;
+	unsigned int max_chunks;
+	unsigned int priority_chunks;
+
+	unsigned char source_slot_reserved;
+	unsigned char coded_package_slot_reserved;
+	void *encode_pic_signal;
+
+	unsigned char highest_storage_number;
+	unsigned char vid_ctx_num;
+	unsigned char enable_mvc;
+	unsigned short mvc_view_idx;
+	unsigned char high_latency;
+	unsigned int mbps;
+
+	unsigned char no_sequence_headers;
+	unsigned int next_slice;
+	unsigned char auto_encode;
+	unsigned char slice_level;
+	unsigned char coded_header_per_slice;
+
+	/* Scaler specific values */
+	unsigned char enable_scaler;
+	unsigned short crop_left;
+	unsigned short crop_right;
+	unsigned short crop_top;
+	unsigned short crop_bottom;
+	unsigned short source_width;
+	unsigned short source_frame_height;
+
+#if SECURE_IO_PORTS
+	unsigned char secure_ctx_input;
+	unsigned char secure_ctx_output;
+#endif
+	unsigned char line_counter;
+};
+
+/*
+ * Encoder context
+ *@codec:  encode codec
+ *@video:  Video encode context
+ *@base_pip:  The first of a contiguous set of pipes to use for the context encode
+ *@pipes_to_use:  The number of contiguous pipes (starting with ui8BasePipe) to
+ *			use for the context encode
+ *@requested_base_pipe:  The first of a contiguous set of pipes to use for the context encode
+ *@requested_pipes_to_use:  The number of contiguous pipes (starting with ui8BasePipe)
+ *				to use for the context encode
+ *@auto_expand_pipes:  Automatically expand a context pipe allocations
+ *			when new pipes become available
+ *@sync_first_pass:  true if never synced
+ */
+struct img_enc_context {
+	enum img_codec codec;
+	struct img_video_context *video;
+
+	unsigned char base_pipe;
+	unsigned char pipes_to_use;
+
+	unsigned char requested_base_pipe;
+	unsigned char requested_pipes_to_use;
+	unsigned char auto_expand_pipes;
+
+	unsigned char ctx_num;
+
+	unsigned char sync_first_pass;
+	unsigned int core_rev;
+
+	struct img_enc_caps caps;
+	struct img_henc_debug_settings *debug_settings;
+};
+
+/*
+ * Struct containing details of a reconstuctured picture
+ */
+struct img_recon_node {
+	unsigned int poc;             /* PicOrderCount */
+	void *buffer;           /* Buffer containing reconstructured image */
+};
+
+/*
+ * This structure contains the topaz Context.
+ * @brief  topaz Context
+ */
+struct topaz_core_context {
+	/* List of stream context structures */
+	struct topaz_dev_ctx *dev_handle;
+	struct lst_t topaz_stream_list;
+	vxe_cb vxe_str_processed_cb;
+	unsigned int num_pipes;
+	struct mutex *mutex;
+};
+
+struct topaz_stream_context {
+	void **link;            /* List link (allows the structure to be part of a MeOS list).*/
+	struct topaz_core_context *core_ctx;
+	struct img_enc_context *enc_ctx;
+	unsigned int stream_id; /* DMAN allocated device ID. */
+	struct vxe_enc_ctx *vxe_ctx;
+	void *mmu_ctx;    /* stream specific MMU context */
+
+};
+
+/*
+ * Function pointer type for picture management functions
+ */
+typedef void (*pic_mgmt_func)(void *app_context, unsigned int frame_num);
+
+/*
+ * @function	InitHardware
+ * @brief	Initialise the Encoder Hardware
+ * @details	Reset the hardware and set up registers, etc.
+ */
+int init_topaz_core(void *dev_handle, unsigned int *num_pipes,
+		    unsigned int mmu_flags, void *callback);
+
+/*
+ * @function		DeinitHardware
+ */
+int  deinit_topaz_core(void);
+
+/*
+ * @function		CreateContext
+ * @brief		Create an encoder context
+ * @details		Set up an encoder context with the given parameters
+ */
+int topaz_stream_create(void *vxe_ctx, struct img_video_params *video_params,
+			unsigned char base_pipe,
+			unsigned char pipes_to_use, struct img_rc_params *rc_params,
+			void **topaz_str_context);
+
+int topaz_end_of_stream(void *topaz_str_ctx, unsigned int frame_cnt);
+
+int topaz_flush_stream(void *topaz_str_ctx, unsigned int frame_cnt);
+
+int topaz_stream_destroy(void *topaz_str_ctx);
+
+/*
+ * Load the given context onto the hardware
+ */
+int topaz_load_context(void *topaz_str_ctx);
+
+/*
+ * Store the context from the hardware into given location
+ */
+int topaz_store_context(void *topaz_str_ctx);
+
+/*
+ * Destroy the given context onto the hardware
+ */
+int topaz_destroy_context(void *topaz_str_ctx);
+
+/*
+ * Get the capabilities of the encoder for the given requirements.
+ * @param    standard		: Standard setting
+ * @param    width		: Target output width
+ * @param    height		: Target output height
+ * @param    caps		: Pointer to caps structure to be filled in.
+ */
+int topaz_get_encoder_caps(enum img_standard standard, unsigned short width,
+			   unsigned short height, struct img_enc_caps *caps);
+
+int topaz_stream_map_buf_sg(void *topaz_str_ctx, enum venc_buf_type buf_type,
+			    struct vidio_ddbufinfo *buf_info, void *sgt);
+
+int topaz_stream_unmap_buf_sg(void *topaz_str_ctx, struct vidio_ddbufinfo *buf_info);
+
+/*
+ * Prepare a partially coded H264 Sequence Header (SPS).
+ * @param    mb_width				: Width of the sequence in MBs
+ * @param    mb_height			: Height of the sequence in MBs
+ * @param    vui_params_present	: IMG_TRUE to include VUI parameters
+ * @param    params				: Pointer to VUI parameters structure
+ * @param    crop				: Pointer to crop parameter structure
+ * @param    sh_params			: Pointer to sequence header params structure
+ */
+int topaz_h264_prepare_sequence_header(void *topaz_str_ctx, unsigned int mb_width,
+				       unsigned int mb_height,
+				       unsigned char vui_params_present,
+				       struct h264_vui_params *params,
+				       struct h264_crop_params *crop,
+				       struct h264_sequence_header_params *sh_params,
+				       unsigned char mvc_sps);
+/*
+ * Prepare a partially coded H264 Picture Header (PPS).
+ * @param		cqp_offset			: Chroma QP offset
+ */
+int topaz_h264_prepare_picture_header(void *topaz_str_ctx, signed char cqp_offset);
+
+/*
+ * Prepare an AUD header.
+ */
+int topaz_h264_prepare_aud_header(void *topaz_str_ctx);
+
+/*
+ * Set offsets and strides for YUV components.
+ * @param		frame				: Source frame
+ */
+int topaz_set_component_offsets(void *topaz_str_ctx, struct img_frame *frame);
+
+/*
+ * Reserves a slot to be used by a subsequent call to SendCodedPackageToFW.
+ * If internally allocated coded buffers are being used, it also gets a buffer
+ * from the encoder's internal list.
+ */
+int topaz_reserve_coded_package_slot(void *topaz_str_ctx);
+
+/*
+ * Submits a buffer to the encoder to receive coded data along with a coded header buffer.
+ * A VP8 non coded buffer can also be sent.
+ * @param	coded_buffer			: Pointer to the coded package to send to FW
+ */
+int topaz_send_coded_package(void *topaz_str_ctx, struct img_coded_buffer *coded_buffer);
+
+/*
+ * Returns the number of empty source slots available
+ * @return   unsigned char: Number of empty source slots  (negative number indicates an error)
+ */
+signed char topaz_query_empty_source_slots(void *topaz_str_ctx);
+
+/*
+ * Returns the number of empty coded buffer slots available
+ * @return   signed char: Number of empty coded slots (negative number indicates an error)
+ */
+signed char topaz_query_empty_coded_slots(void *topaz_str_ctx);
+
+/*
+ * Reserves a slot to be used by a subsequent call to SendSourceFrame.
+ * If internally allocated source buffers are being used, it also gets a buffer
+ * from the encoder's internal list.
+ * @param		src_slot_num		: Pointer to receive slot number
+ */
+int topaz_reserve_source_slot(void *topaz_str_ctx, unsigned char *src_slot_num);
+
+/*
+ * Submits a frame to the encoder for processing
+ * @param		src_frame			: Pointer to receive buffer pointer
+ * @param		frame_num		: Frame number of the given frame
+ * @param		ctx_value	: Value which will be insert into coded data buffer header
+ */
+int topaz_send_source_frame(void *topaz_str_ctx,
+			    struct img_frame *src_frame,
+			    unsigned int frame_num,
+			    unsigned long long ctx_value);
+
+/*
+ * Indicates that there are no more source frames to send. It may not be the last
+ * command, but it should inform the drivers about the length of the video stream.
+ */
+int topaz_end_of_stream(void *topaz_str_ctx, unsigned int frame_count);
+
+/*
+ * Indicates that the encoder should be flushed after the specified number of
+ * frames have been encoded.
+ * @param    frame_count: Number of frames which should have been encoded
+ *		 when the flush is complete
+ */
+int topaz_flush_stream(void *topaz_str_ctx, unsigned int frame_count);
+
+/*
+ * Get the maximum coded data length for the given parameters, which can be used
+ * to determine the size of the coded data buffer.
+ */
+unsigned int topaz_get_coded_buffer_max_size(void *topaz_str_ctx, enum img_standard standard,
+					     unsigned short width, unsigned short height,
+					     struct img_rc_params *rc_params);
+
+unsigned int topaz_get_coded_package_max_num(void *topaz_str_ctx, enum img_standard standard,
+					     unsigned short width, unsigned short height,
+					     struct img_rc_params *rc_params);
+
+/*
+ * Tell the firmware to encode a frame.
+ */
+int topaz_encode_frame(void *topaz_str_ctx);
+
+/*
+ * Tells whether or not a pipe is being used by any context.
+ * If it is being used then it returns the id (1 or 2) of the context that is using it.
+ * Else it returns zero as the context id.
+ */
+int topaz_get_pipe_usage(unsigned char pipe, unsigned char *ctx_id);
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/topaz_api_utils.c b/drivers/media/platform/img/vxe-vxd/encoder/topaz_api_utils.c
--- a/drivers/media/platform/img/vxe-vxd/encoder/topaz_api_utils.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/topaz_api_utils.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1487 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * encoder utility function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include "fw_headers/defs.h"
+#include "img_errors.h"
+#include "reg_headers/topazhp_core_regs.h"
+#include "reg_headers/topaz_coreext_regs.h"
+#include "reg_headers/topazhp_multicore_regs_old.h"
+#include "topaz_api.h"
+
+#define MV_OFFSET_IN_TABLE(distance, \
+		position) ((distance) * MV_ROW_STRIDE + (position) * sizeof(struct img_mv_settings))
+#define DEFAULT_MVCALC_CONFIG       ((0x00040303) | (MASK_TOPAZHP_CR_MVCALC_JITTER_POINTER_RST))
+
+/*
+ * Calculates the correct number of macroblocks per kick and kicks per BU
+ */
+void calculate_kick_and_bu_size(unsigned int width_in_mbs,
+				unsigned int height_in_mbs,
+				unsigned char is_interlaced,
+				unsigned int max_bu_per_frame,
+				unsigned int *kick_size,
+				unsigned int *kicks_per_bu,
+				unsigned int *min_slice_height)
+{
+	unsigned int kick_size_local, kicks_per_bu_local, bu_per_frame, min_slice_height_local;
+
+	/*
+	 * Basic unit is either an integer number of rows or an integer number of
+	 * basic units fit in a row We calculate the ideal kick size first then decide
+	 * how many kicks there will be for each basic unit
+	 */
+
+	/* Default to 1 kick per row */
+	kick_size_local = width_in_mbs;
+	kicks_per_bu_local = 1;
+	min_slice_height_local = 1;
+
+	/* See if we can use a smaller kick size */
+	if (!(kick_size_local % 3) && kick_size_local > 30) {
+		kick_size_local /= 3;
+		kicks_per_bu_local = 3;
+	} else if (!(kick_size_local % 2) && (kick_size_local > 20)) {
+		kick_size_local /= 2;
+		kicks_per_bu_local = 2;
+	}
+
+	IMG_DBG_ASSERT((kick_size_local < 256) && ("Kick Size can't be bigger than 255" != NULL));
+
+	/* Now calculate how many kicks we do per BU */
+	bu_per_frame = height_in_mbs * (is_interlaced ? 2 : 1);
+
+	while (bu_per_frame > max_bu_per_frame) {
+		/* we have too many BUs so double up the number
+		 * of rows per BU so we can half the number of BUs
+		 */
+		kicks_per_bu_local *= 2;
+		/* if we had an odd number of rows then the last BU will be half height */
+		bu_per_frame = (bu_per_frame + 1) / 2;
+		min_slice_height_local *= 2;
+	}
+
+	/* if we can afford to have 2 BUs per row then do it */
+	if ((bu_per_frame < (max_bu_per_frame / 2)) && kicks_per_bu_local == 2) {
+		kicks_per_bu_local = 1;
+		bu_per_frame *= 2;
+	}
+
+	/* if we can afford to have 3 BUs per row then do it */
+	if ((bu_per_frame < (max_bu_per_frame / 3)) && kicks_per_bu_local == 3) {
+		kicks_per_bu_local = 1;
+		bu_per_frame += 2;
+	}
+
+	*kick_size = kick_size_local;
+	*kicks_per_bu = kicks_per_bu_local;
+	*min_slice_height = min_slice_height_local;
+}
+
+/*
+ * Calculates the stride based on the input format and width
+ */
+unsigned int calculate_stride(enum img_format format, ushort requested_stride_bytes, ushort width)
+{
+	ushort stride_bytes;
+
+	if (requested_stride_bytes) {
+		stride_bytes = requested_stride_bytes;
+	} else {
+		switch (format) {
+		case IMG_CODEC_Y0UY1V_8888:
+		case IMG_CODEC_Y0VY1U_8888:
+		case IMG_CODEC_UY0VY1_8888:
+		case IMG_CODEC_VY0UY1_8888:
+			stride_bytes = width << 1;
+			break;
+		case IMG_CODEC_ABCX:
+		case IMG_CODEC_XBCA:
+			stride_bytes = width << 2;
+			break;
+		case IMG_CODEC_ABC565:
+			stride_bytes = width << 1;
+			break;
+		default:
+			stride_bytes = width;
+			break;
+		}
+	}
+
+	switch (format) {
+	case IMG_CODEC_420_YUV:
+	case IMG_CODEC_420_YV12:
+	case IMG_CODEC_420_PL8:
+	case IMG_CODEC_422_YUV:
+	case IMG_CODEC_422_YV12:
+	case IMG_CODEC_422_PL8:
+	/* although luma stride is same as chroma stride,
+	 * start address is half the stride. so we need 128-byte alignment
+	 */
+	case IMG_CODEC_420_IMC2:
+	/* although luma stride is same as chroma stride,
+	 * start address is half the stride. so we need 128-byte alignment
+	 */
+	case IMG_CODEC_422_IMC2:
+
+		/*
+		 * All strides need to be 64-byte aligned
+		 * Chroma stride is half luma stride, so (luma) stride needs
+		 * to be 64-byte aligned when divided by 2
+		 */
+		return ALIGN_128(stride_bytes);
+	default:
+		/* Stride needs to be 64-byte aligned */
+		return ALIGN_64(stride_bytes);
+	}
+}
+
+/*
+ * Patch HW profile based on the profile specified by the user
+ */
+void patch_hw_profile(struct img_video_params *video_params, struct img_video_context *video)
+{
+	unsigned int ipe_control = 0;
+	unsigned int pred_comb_control = 0;
+	struct img_encode_features *enc_features = &video_params->enc_features;
+
+	/* disable_intra4x4 */
+	if (enc_features->disable_intra4x4)
+		pred_comb_control |= F_ENCODE(1, TOPAZHP_CR_INTRA4X4_DISABLE);
+
+	/* disable_intra8x8 */
+	if (enc_features->disable_intra8x8)
+		pred_comb_control |= F_ENCODE(1, TOPAZHP_CR_INTRA8X8_DISABLE);
+
+	/* disable_intra16x16, check if at least one of the other Intra mode is enabled */
+	if (enc_features->disable_intra16x16 &&
+	    (!(enc_features->disable_intra8x8) || !(enc_features->disable_intra4x4)))
+		pred_comb_control |= F_ENCODE(1, TOPAZHP_CR_INTRA16X16_DISABLE);
+
+	if (video_params->mbps)
+		video->mbps = video_params->mbps;
+
+	if (enc_features->restrict_inter4x4)
+		ipe_control |= F_ENCODE(1, TOPAZHP_CR_IPE_MV_NUMBER_RESTRICTION);
+
+	if (enc_features->disable_inter8x8)
+		pred_comb_control |= F_ENCODE(1, TOPAZHP_CR_INTER8X8_DISABLE);
+
+	if (enc_features->disable_bpic_ref1)
+		pred_comb_control |= F_ENCODE(1, TOPAZHP_CR_B_PIC1_DISABLE);
+	else if (enc_features->disable_bpic_ref0)
+		pred_comb_control |= F_ENCODE(1, TOPAZHP_CR_B_PIC0_DISABLE);
+
+	/* save predictor combiner control in video encode parameter set */
+	video->pred_comb_control = pred_comb_control;
+
+	/* set blocksize */
+	ipe_control |= F_ENCODE(enc_features->min_blk_sz, TOPAZHP_CR_IPE_BLOCKSIZE);
+
+	if (enc_features->enable_8x16_mv_detect)
+		ipe_control |= F_ENCODE(1, TOPAZHP_CR_IPE_8X16_ENABLE);
+
+	if (enc_features->enable_16x8_mv_detect)
+		ipe_control |= F_ENCODE(1, TOPAZHP_CR_IPE_16X8_ENABLE);
+
+	if (enc_features->disable_bframes)
+		video->rc_params.bframes = 0;
+
+	if (enc_features->restricted_intra_pred)
+		video->intra_pred_modes = 0xff0f;
+
+	/* save IPE-control register */
+	video->ipe_control = ipe_control;
+}
+
+/*
+ * Set offsets and strides for YUV components of source picture
+ */
+int topaz_set_component_offsets(void *enc_ctx_handle, struct img_frame *frame)
+{
+	struct img_enc_context *enc;
+	struct img_video_context *video;
+	enum img_format format;
+	ushort stride_bytes;
+	ushort picture_height;
+
+	if (!enc_ctx_handle)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	/* if source slot is NULL then it's just a next portion of slices */
+	if (!frame)
+		return IMG_ERROR_UNDEFINED;
+
+	enc = (struct img_enc_context *)enc_ctx_handle;
+	video = enc->video;
+
+	format = video->format;
+	picture_height = video->buffer_height >> (video->is_interlaced ? 1 : 0);
+	stride_bytes = video->buffer_stride_bytes;
+
+	/*
+	 * 3 Components: Y, U, V
+	 * Y component is always at the beginning
+	 */
+	frame->y_component_offset = 0;
+	frame->src_y_stride_bytes = stride_bytes;
+
+	/* Assume for now that field 0 comes first */
+	frame->field0_y_offset = 0;
+	frame->field0_u_offset = 0;
+	frame->field0_v_offset = 0;
+
+	switch (format) {
+	case IMG_CODEC_420_YUV:
+		frame->src_uv_stride_bytes = stride_bytes / 2;
+
+		frame->u_component_offset = stride_bytes * picture_height;
+		frame->v_component_offset = stride_bytes * picture_height + (stride_bytes / 2) *
+			(picture_height / 2);
+		break;
+
+	case IMG_CODEC_420_PL8:
+		frame->src_uv_stride_bytes = stride_bytes / 2;
+
+		frame->u_component_offset = 0;
+		frame->v_component_offset = 0;
+		break;
+
+	case IMG_CODEC_420_PL12:
+	case IMG_CODEC_420_PL21:
+		frame->src_uv_stride_bytes = stride_bytes;
+
+		frame->u_component_offset = 0;
+		frame->v_component_offset = 0;
+		break;
+
+	case IMG_CODEC_420_YV12:
+		frame->src_uv_stride_bytes = stride_bytes / 2;
+		frame->u_component_offset = stride_bytes * picture_height + (stride_bytes / 2) *
+			(picture_height / 2);
+		frame->v_component_offset = stride_bytes * picture_height;
+		break;
+
+	case IMG_CODEC_420_PL12_PACKED:
+	case IMG_CODEC_420_PL21_PACKED:
+		frame->src_uv_stride_bytes = stride_bytes;
+		frame->u_component_offset = stride_bytes * picture_height;
+		frame->v_component_offset = stride_bytes * picture_height;
+		break;
+
+	case IMG_CODEC_420_IMC2:        /* IMC2 */
+		frame->src_uv_stride_bytes = stride_bytes;
+		frame->u_component_offset = stride_bytes * picture_height + (stride_bytes / 2);
+		frame->v_component_offset = stride_bytes * picture_height;
+		break;
+
+	case IMG_CODEC_422_YUV:
+		frame->src_uv_stride_bytes = stride_bytes / 2;
+		frame->u_component_offset = stride_bytes * picture_height;
+		frame->v_component_offset = stride_bytes * picture_height + (stride_bytes / 2) *
+			picture_height;
+		break;
+
+	case IMG_CODEC_422_YV12:        /* YV16 */
+		frame->src_uv_stride_bytes = stride_bytes / 2;
+		frame->u_component_offset = stride_bytes * picture_height + (stride_bytes / 2) *
+			picture_height;
+		frame->v_component_offset = stride_bytes * picture_height;
+		break;
+
+	case IMG_CODEC_422_PL8:
+		frame->src_uv_stride_bytes = stride_bytes / 2;
+		frame->u_component_offset = 0;
+		frame->v_component_offset = 0;
+		break;
+
+	case IMG_CODEC_422_IMC2:        /* IMC2 */
+		frame->src_uv_stride_bytes = stride_bytes;
+		frame->u_component_offset = stride_bytes * picture_height + (stride_bytes / 2);
+		frame->v_component_offset = stride_bytes * picture_height;
+		break;
+
+	case IMG_CODEC_422_PL12:
+	case IMG_CODEC_422_PL21:
+		frame->src_uv_stride_bytes = stride_bytes;
+		frame->u_component_offset = 0;
+		frame->v_component_offset = 0;
+		break;
+
+	case IMG_CODEC_444_YUV:
+		frame->src_uv_stride_bytes = stride_bytes;
+		frame->u_component_offset = stride_bytes * picture_height;
+		frame->v_component_offset = stride_bytes * picture_height + stride_bytes *
+			picture_height;
+		break;
+
+	case IMG_CODEC_444_YV12:        /* YV16 */
+		frame->src_uv_stride_bytes = stride_bytes;
+		frame->u_component_offset = stride_bytes * picture_height + stride_bytes *
+			picture_height;
+		frame->v_component_offset = stride_bytes * picture_height;
+		break;
+
+	case IMG_CODEC_444_PL8:
+		frame->src_uv_stride_bytes = stride_bytes;
+		frame->u_component_offset = 0;
+		frame->v_component_offset = 0;
+		break;
+
+	case IMG_CODEC_444_IMC2:        /* IMC2 */
+		frame->src_uv_stride_bytes = stride_bytes * 2;
+		frame->u_component_offset = stride_bytes * picture_height + stride_bytes;
+		frame->v_component_offset = stride_bytes * picture_height;
+		break;
+
+	case IMG_CODEC_444_PL12:
+	case IMG_CODEC_444_PL21:
+		frame->src_uv_stride_bytes = stride_bytes * 2;
+		frame->u_component_offset = 0;
+		frame->v_component_offset = 0;
+		break;
+
+	case IMG_CODEC_Y0UY1V_8888:
+	case IMG_CODEC_Y0VY1U_8888:
+	case IMG_CODEC_UY0VY1_8888:
+	case IMG_CODEC_VY0UY1_8888:
+	case IMG_CODEC_ABCX:
+	case IMG_CODEC_XBCA:
+	case IMG_CODEC_ABC565:
+		frame->src_uv_stride_bytes = stride_bytes;
+		frame->u_component_offset = 0;
+		frame->v_component_offset = 0;
+		break;
+
+	default:
+		break;
+	}
+
+	if (video->is_interlaced) {
+		if (video->is_interleaved) {
+			switch (format) {
+			case IMG_CODEC_420_IMC2:
+			case IMG_CODEC_422_IMC2:
+				frame->v_component_offset *= 2;
+				frame->u_component_offset = frame->v_component_offset +
+					(stride_bytes / 2);
+				break;
+			case IMG_CODEC_444_IMC2:
+				frame->v_component_offset *= 2;
+				frame->u_component_offset = frame->v_component_offset +
+					stride_bytes;
+				break;
+
+			default:
+				frame->u_component_offset *= 2;
+				frame->v_component_offset *= 2;
+				break;
+			}
+
+			frame->field1_y_offset = frame->field0_y_offset + frame->src_y_stride_bytes;
+			frame->field1_u_offset = frame->field0_u_offset +
+				frame->src_uv_stride_bytes;
+			frame->field1_v_offset = frame->field0_v_offset +
+				frame->src_uv_stride_bytes;
+
+			frame->src_y_stride_bytes *= 2;
+			frame->src_uv_stride_bytes *= 2;
+		} else {
+			unsigned int y_field_size, c_field_size;
+
+			switch (format) {
+			case IMG_CODEC_420_YUV:
+			case IMG_CODEC_420_YV12:
+			case IMG_CODEC_420_IMC2:
+			case IMG_CODEC_420_PL12_PACKED:
+			case IMG_CODEC_420_PL21_PACKED:
+				/* In Packed formats including PL12 packed the field offsets
+				 * should be calculated in the following manner
+				 */
+				y_field_size = picture_height * stride_bytes * 3 / 2;
+				c_field_size = y_field_size;
+				break;
+			case IMG_CODEC_420_PL8:
+				y_field_size = picture_height * stride_bytes;
+				c_field_size = picture_height * stride_bytes / 4;
+				break;
+			case IMG_CODEC_420_PL12:
+			case IMG_CODEC_420_PL21:
+				y_field_size = picture_height * stride_bytes;
+				c_field_size = picture_height * stride_bytes / 2;
+				break;
+			case IMG_CODEC_422_YUV:
+			case IMG_CODEC_422_YV12:
+			case IMG_CODEC_422_IMC2:
+				y_field_size = picture_height * stride_bytes * 2;
+				c_field_size = y_field_size;
+				break;
+			case IMG_CODEC_422_PL8:
+				y_field_size = picture_height * stride_bytes;
+				c_field_size = picture_height * stride_bytes / 2;
+				break;
+			case IMG_CODEC_422_PL12:
+			case IMG_CODEC_422_PL21:
+				y_field_size = picture_height * stride_bytes;
+				c_field_size = picture_height * stride_bytes;
+				break;
+			case IMG_CODEC_Y0UY1V_8888:
+			case IMG_CODEC_UY0VY1_8888:
+			case IMG_CODEC_Y0VY1U_8888:
+			case IMG_CODEC_VY0UY1_8888:
+				y_field_size = picture_height * stride_bytes;
+				c_field_size = y_field_size;
+				break;
+			case IMG_CODEC_444_YUV:
+			case IMG_CODEC_444_YV12:
+			case IMG_CODEC_444_IMC2:
+				y_field_size = picture_height * stride_bytes * 3;
+				c_field_size = y_field_size;
+				break;
+			case IMG_CODEC_444_PL8:
+				y_field_size = picture_height * stride_bytes;
+				c_field_size = picture_height * stride_bytes;
+				break;
+			case IMG_CODEC_444_PL12:
+			case IMG_CODEC_444_PL21:
+				y_field_size = picture_height * stride_bytes;
+				c_field_size = picture_height * stride_bytes * 2;
+				break;
+			case IMG_CODEC_ABCX:
+			case IMG_CODEC_XBCA:
+			case IMG_CODEC_ABC565:
+				y_field_size = picture_height * stride_bytes;
+				c_field_size = y_field_size;
+				break;
+			default:
+				y_field_size = picture_height * stride_bytes * 3 / 2;
+				c_field_size = y_field_size;
+				break;
+			}
+
+			frame->field1_y_offset = y_field_size;
+			frame->field1_u_offset = c_field_size;
+			frame->field1_v_offset = c_field_size;
+		}
+	} else {
+		frame->field1_y_offset = frame->field0_y_offset;
+		frame->field1_u_offset = frame->field0_u_offset;
+		frame->field1_v_offset = frame->field0_v_offset;
+	}
+	return IMG_SUCCESS;
+}
+
+void topaz_setup_input_csc(struct img_video_context *video,
+			   struct img_vxe_scaler_setup *scaler_setup,
+			   struct img_vxe_csc_setup *csc_setup,
+			   enum img_csc_preset csc_preset)
+{
+#define CSC_MINUS_1_16(X) TOPAZHP_EXT_CR_CSC_SOURCE_MOD_0 ## X ## _MINUS_1_16
+#define CSC_MINUS_1_2(X) TOPAZHP_EXT_CR_CSC_SOURCE_MOD_0 ## X ## _MINUS_1_2
+#define CSC_UNSIGNED(X) TOPAZHP_EXT_CR_CSC_SOURCE_MOD_0 ## X ## _UNSIGNED
+
+	if (csc_preset != IMG_CSC_NONE &&
+	    (video->format == IMG_CODEC_ABCX ||
+	     video->format == IMG_CODEC_XBCA || video->format == IMG_CODEC_ABC565)) {
+		unsigned char source_mode[IMG_CSC_PRESETS][3] = {
+			/* IMG_CSC_NONE - No colour-space conversion */
+			{CSC_MINUS_1_16(0), CSC_MINUS_1_2(1), CSC_MINUS_1_16(2)},
+
+			/* IMG_CSC_709_TO_601 - ITU BT.709 YUV to be converted to ITU BT.601 YUV */
+			{CSC_MINUS_1_16(0), CSC_MINUS_1_2(1), CSC_MINUS_1_16(2)},
+
+			/* IMG_CSC_601_TO_709 - ITU BT.601 YUV to be
+			 * converted to ITU BT.709 YUV
+			 */
+			{CSC_MINUS_1_16(0), CSC_MINUS_1_2(1), CSC_MINUS_1_16(2)},
+
+			/* IMG_CSC_RGB_TO_601_ANALOG - RGB to be
+			 * converted to ITU BT.601 YUV
+			 */
+			{  CSC_UNSIGNED(0),  CSC_UNSIGNED(1),  CSC_UNSIGNED(2)},
+
+			/* IMG_CSC_RGB_TO_601_DIGITAL - RGB to be
+			 * converted to ITU BT.601 YCbCr RS
+			 */
+			{  CSC_UNSIGNED(0),  CSC_UNSIGNED(1),  CSC_UNSIGNED(2)},
+
+			/* IMG_CSC_RGB_TO_601_DIGITAL_FS - RGB to be
+			 * converted to ITU BT.601 YCbCr FS
+			 */
+			{  CSC_UNSIGNED(0),  CSC_UNSIGNED(1),  CSC_UNSIGNED(2)},
+
+			/* IMG_CSC_RGB_TO_709 - RGB to be converted to ITU BT.709 YUV */
+			{  CSC_UNSIGNED(0),  CSC_UNSIGNED(1),  CSC_UNSIGNED(2)},
+
+			/* IMG_CSC_YIQ_TO_601 - YIQ to be converted to ITU BT.601 YUV */
+			{CSC_MINUS_1_16(0), CSC_MINUS_1_2(1), CSC_MINUS_1_16(2)},
+
+			/* IMG_CSC_YIQ_TO_709 - YIQ to be converted to ITU BT.709 YUV */
+			{CSC_MINUS_1_16(0), CSC_MINUS_1_2(1), CSC_MINUS_1_16(2)},
+
+			/* IMG_CSC_BRG_TO_601 - RGB to be converted to ITU BT.601 YUV */
+			{0, 0, 0},
+
+			/* IMG_CSC_RBG_TO_601 - RGB to be converted to ITU BT.709 YUV */
+			{0, 0, 0},
+
+			/* IMG_CSC_BGR_TO_601 - RGB to be converted to ITU BT.601 YUV */
+			{0, 0, 0},
+
+			/* IMG_CSC_UYV_TO_YUV - UYV to be converted to YUV */
+			{CSC_MINUS_1_2(0), CSC_MINUS_1_16(1), CSC_MINUS_1_2(2)},
+			/*{  CSC_UNSIGNED(0),  CSC_UNSIGNED(1),  CSC_UNSIGNED(2)}, */
+		};
+
+		int coeffs[IMG_CSC_PRESETS][3][3] = {
+			/* IMG_CSC_NONE - No colour-space conversion */
+			{
+				{ 1024,    0,    0 },
+				{    0, 1024,    0 },
+				{    0,    0, 1024 }
+			},
+
+			/* IMG_CSC_709_TO_601 - ITU BT.709 YUV to be converted to ITU BT.601 YUV */
+			{
+				{ 1024, (int)(0.15941 * 1024), (int)(0.11649 * 1024) },
+				{    0, (int)(-0.07844 * 1024), (int)(0.98985 * 1024) },
+				{    0, (int)(0.9834  * 1024), (int)(-0.10219 * 1024) }
+			},
+
+			/* IMG_CSC_601_TO_709 - ITU BT.601 YUV to be converted to ITU BT.709 YUV */
+			{
+				{ 1024, (int)(-0.17292 * 1024), (int)(-0.13554 * 1024) },
+				{    0, (int)(0.08125 * 1024), (int)(1.01864 * 1024) },
+				{    0, (int)(1.02532 * 1024), (int)(0.10586 * 1024) }
+			},
+
+			/* IMG_CSC_RGB_TO_601_ANALOG - RGB to be converted to ITU BT.601 YUV */
+			{ /*		R	G		B */
+				{ (int)(219 *  0.299   * 4.0157),
+				  (int)(219 *  0.587   * 4.0157),
+				  (int)(219 *  0.114   * 4.0157) },
+				{ (int)(224 * -0.14713 * 4.0157),
+				  (int)(224 * -0.28886 * 4.0157),
+				  (int)(224 *  0.446   * 4.0157) },
+				{ (int)(224 *  0.615   * 4.0157),
+				  (int)(224 * -0.51499 * 4.0157),
+				  (int)(224 * -0.10001 * 4.0157) }
+			}, /*		A	B	C */
+
+			/* IMG_CSC_RGB_TO_601_DIGITAL - RGB to be
+			 * converted to ITU BT.601 YCbCr reduced scale
+			 */
+			{ /*		R	G	B */
+				{ (int)(219 *  0.299   * 4.0157),
+				  (int)(219 *  0.587   * 4.0157),
+				  (int)(219 *  0.114   * 4.0157) },
+				{ (int)(224 * -0.172   * 4.0157),
+				  (int)(224 * -0.339   * 4.0157),
+				  (int)(224 *  0.511   * 4.0157) },
+				{ (int)(224 *  0.511   * 4.0157),
+				  (int)(224 * -0.428   * 4.0157),
+				  (int)(224 * -0.083   * 4.0157) }
+			}, /*	A		B		C */
+
+			/* IMG_CSC_RGB_TO_601_DIGITAL_FS - RGB to be
+			 * converted to ITU BT.601 YCbCr full scale
+			 */
+			{ /*		R	G	B */
+				{ (int)(219 *  0.257   * 4.0157),
+				  (int)(219 *  0.504   * 4.0157),
+				  (int)(219 *  0.098   * 4.0157) },
+				{ (int)(224 * -0.148   * 4.0157),
+				  (int)(224 * -0.291   * 4.0157),
+				  (int)(224 *  0.439   * 4.0157) },
+				{ (int)(224 *  0.439   * 4.0157),
+				  (int)(224 * -0.368   * 4.0157),
+				  (int)(224 * -0.071   * 4.0157) }
+			}, /*	A	B		C */
+
+			/* IMG_CSC_RGB_TO_709 - RGB to be converted to ITU BT.709 YUV */
+			{
+				{ (int)(219 *  0.2215 * 4.0157), (int)(219 *  0.7154 * 4.0157),
+				  (int)(219 *  0.0721 * 4.0157) },
+				{ (int)(224 * -0.1145 * 4.0157), (int)(224 * -0.3855 * 4.0157),
+				  (int)(224 *  0.5    * 4.0157) },
+				{ (int)(224 *  0.5016 * 4.0157), (int)(224 * -0.4556 * 4.0157),
+				  (int)(224 * -0.0459 * 4.0157) }
+			},
+
+			/* IMG_CSC_YIQ_TO_601 - YIQ to be converted to ITU BT.601 YUV */
+			{
+				{ 1024,                           0,                            0 },
+				{    0, (int)(0.83885 * 1024), (int)(-0.54475 * 1024) },
+				{    0, (int)(0.54484 * 1024), (int)(0.83896 * 1024) }
+			},
+
+			/* IMG_CSC_YIQ_TO_709 - YIQ to be converted to ITU BT.709 YUV */
+			{
+				{ 1024, (int)(-0.20792 * 1024), (int)(0.07122 * 1024) },
+				{    0, (int)(0.89875 * 1024), (int)(-0.48675 * 1024) },
+				{    0, (int)(0.64744 * 1024), (int)(0.80255 * 1024) }
+			},
+
+			/*
+			 * IMG_CSC_BRG_TO_601 - RGB to be converted to ITU BT.601 YUV
+			 * Entries have been reordered to provide support for xRGB format
+			 */
+			{ /*            B         R       G      */
+				{ (int)(219 *  0.114   * 4.0157),
+				  (int)(219 *  0.299   * 4.0157),
+				  (int)(219 *  0.587   * 4.0157)},
+				{ (int)(224 *  0.446   * 4.0157),
+				  (int)(224 * -0.14713 * 4.0157),
+				  (int)(224 * -0.28886 * 4.0157)},
+				{ (int)(224 * -0.10001 * 4.0157),
+				  (int)(224 *  0.615   * 4.0157),
+				  (int)(224 * -0.51499 * 4.0157)}
+			}, /*	A	B				C */
+
+			/*
+			 * IMG_CSC_RBG_TO_601 - RGB to be converted to ITU BT.601 YUV
+			 * Entries have been reordered to provide support for xBGR format
+			 */
+			{ /*              R        B        G       */
+				{ (int)(219 *  0.299   * 4.0157),
+				  (int)(219 *  0.114   * 4.0157),
+				  (int)(219 *  0.587   * 4.0157)},
+				{ (int)(224 * -0.14713 * 4.0157),
+				  (int)(224 *  0.446   * 4.0157),
+				  (int)(224 * -0.28886 * 4.0157)},
+				{ (int)(224 *  0.615   * 4.0157),
+				  (int)(224 * -0.10001 * 4.0157),
+				  (int)(224 * -0.51499 * 4.0157)}
+			}, /*		   A		B	C */
+
+			/*
+			 * IMG_CSC_BGR_TO_601 - RGB to be converted to ITU BT.601 YUV
+			 * Entries have been reordered to provide support for BGRx format
+			 */
+			{ /*              B       G          R */
+				{ (int)(219 *  0.114   * 4.0157),
+				  (int)(219 *  0.587   * 4.0157),
+				  (int)(219 *  0.299   * 4.0157)},
+				{ (int)(224 *  0.446   * 4.0157),
+				  (int)(224 * -0.28886 * 4.0157),
+				  (int)(224 * -0.14713 * 4.0157)},
+				{ (int)(224 * -0.10001 * 4.0157),
+				  (int)(224 * -0.51499 * 4.0157),
+				  (int)(224 *  0.615   * 4.0157)},
+			},	/*	A	B	C */
+
+			/* IMG_CSC_UYV_TO_YUV - UYV to YUV */
+			{
+				{ 0, 1024, 0 },
+				{ 1024, 0, 0 },
+				{ 0, 0, 1024 }
+			},
+		};
+
+		unsigned int index = csc_preset;
+
+		IMG_DBG_ASSERT(index < IMG_CSC_PRESETS);
+
+		if (index >= IMG_CSC_PRESETS)
+			return;
+
+#define SRC_MOD(X) TOPAZHP_EXT_CR_CSC_SOURCE_MOD_0 ## X
+#define OUT_MOD(X) TOPAZHP_EXT_CR_CSC_OUTPUT_MOD_0 ## X
+
+#define SOURCE_Y_ARRAY csc_setup->csc_source_y
+#define SRC_Y_PARAM(X) TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_Y
+
+#define SOURCE_CBCR_ARRAY csc_setup->csc_source_cbcr
+#define SRC_CB_PARAM(X) TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_CB
+#define SRC_CR_PARAM(X) TOPAZHP_EXT_CR_CSC_SOURCE_SRC_TO_CR
+
+#define CLIP_VALUE 255
+
+		scaler_setup->scaler_control |= F_ENCODE(1,
+				TOPAZHP_EXT_CR_ENABLE_COLOUR_SPACE_CONVERSION);
+
+		csc_setup->csc_output_clip[0] =
+			F_ENCODE(TOPAZHP_EXT_CR_CSC_OUTPUT_MOD_00_ADD_1_16, OUT_MOD(0)) |
+			F_ENCODE(CLIP_VALUE, TOPAZHP_EXT_CR_CSC_OUTPUT_MAX_CLIP) |
+			F_ENCODE(0, TOPAZHP_EXT_CR_CSC_OUTPUT_MIN_CLIP);
+
+		csc_setup->csc_output_clip[1] =
+			F_ENCODE(TOPAZHP_EXT_CR_CSC_OUTPUT_MOD_01_ADD_1_2, OUT_MOD(1)) |
+			F_ENCODE(CLIP_VALUE, TOPAZHP_EXT_CR_CSC_OUTPUT_MAX_CLIP) |
+			F_ENCODE(0, TOPAZHP_EXT_CR_CSC_OUTPUT_MIN_CLIP);
+
+		SOURCE_Y_ARRAY[0] = F_ENCODE(source_mode[index][0], SRC_MOD(0)) |
+			F_ENCODE(coeffs[index][0][0], SRC_Y_PARAM(0));
+		SOURCE_CBCR_ARRAY[0] = F_ENCODE(coeffs[index][1][0], SRC_CB_PARAM(0)) |
+			F_ENCODE(coeffs[index][2][0], SRC_CR_PARAM(0));
+
+		SOURCE_Y_ARRAY[1] = F_ENCODE(source_mode[index][1], SRC_MOD(1)) |
+			F_ENCODE(coeffs[index][0][1], SRC_Y_PARAM(1));
+		SOURCE_CBCR_ARRAY[1] = F_ENCODE(coeffs[index][1][1], SRC_CB_PARAM(1)) |
+			F_ENCODE(coeffs[index][2][1], SRC_CR_PARAM(1));
+
+		SOURCE_Y_ARRAY[2] = F_ENCODE(source_mode[index][2], SRC_MOD(2)) |
+			F_ENCODE(coeffs[index][0][2], SRC_Y_PARAM(2));
+		SOURCE_CBCR_ARRAY[2] = F_ENCODE(coeffs[index][1][2], SRC_CB_PARAM(2)) |
+			F_ENCODE(coeffs[index][2][2], SRC_CR_PARAM(2));
+	}
+}
+
+/*
+ * Calculate buffer strides
+ */
+unsigned int topaz_get_packed_buffer_strides(ushort buffer_stride_bytes,
+					     enum img_format format,
+					     unsigned char enable_scaler,
+					     unsigned char is_interlaced,
+					     unsigned char is_interleaved)
+{
+	ushort src_y_stride_bytes;
+	ushort src_uv_stride_bytes = 0;
+
+	/* 3 Components: Y, U, V */
+	src_y_stride_bytes = buffer_stride_bytes;
+
+	switch (format) {
+	case IMG_CODEC_420_YUV:
+	case IMG_CODEC_420_PL8:
+	case IMG_CODEC_420_YV12:
+		src_uv_stride_bytes = src_y_stride_bytes / 2;
+		break;
+
+	case IMG_CODEC_422_YUV:         /* Odd-numbered chroma rows unused if scaler not present */
+	case IMG_CODEC_422_YV12:        /* Odd-numbered chroma rows unused if scaler not present */
+	case IMG_CODEC_422_PL8:         /* Odd-numbered chroma rows unused if scaler not present */
+		if (!enable_scaler)
+		/* Skip alternate lines of chroma for 4:2:2 if scaler disabled/not present */
+			src_uv_stride_bytes = src_y_stride_bytes;
+		else
+			src_uv_stride_bytes = src_y_stride_bytes / 2;
+		break;
+	/* Interleaved chroma pixels (and unused odd-numbered chroma rows if scaler not present) */
+	case IMG_CODEC_422_IMC2:
+	/* Interleaved chroma rows (and unused odd-numbered chroma rows if scaler not present) */
+	case IMG_CODEC_422_PL12:
+	/* Interleaved chroma rows (and unused odd-numbered chroma rows if scaler not present) */
+	case IMG_CODEC_422_PL21:
+		if (!enable_scaler)
+		/* Skip alternate lines of chroma for 4:2:2 if scaler disabled/not present */
+			src_uv_stride_bytes = src_y_stride_bytes * 2;
+		else
+			src_uv_stride_bytes = src_y_stride_bytes;
+		break;
+
+	case IMG_CODEC_420_PL12:                /* Interleaved chroma pixels */
+	case IMG_CODEC_420_PL21:
+
+	case IMG_CODEC_420_PL12_PACKED: /* Interleaved chroma pixels */
+	case IMG_CODEC_420_PL21_PACKED: /* Interleaved chroma pixels */
+	case IMG_CODEC_420_IMC2:                /* Interleaved chroma rows */
+	case IMG_CODEC_Y0UY1V_8888:     /* Interleaved luma and chroma pixels */
+	case IMG_CODEC_Y0VY1U_8888:     /* Interleaved luma and chroma pixels */
+	case IMG_CODEC_UY0VY1_8888:     /* Interleaved luma and chroma pixels */
+	case IMG_CODEC_VY0UY1_8888:     /* Interleaved luma and chroma pixels */
+	case IMG_CODEC_ABCX:            /* Interleaved pixels of unknown colour space */
+	case IMG_CODEC_XBCA:            /* Interleaved pixels of unknown colour space */
+	case IMG_CODEC_ABC565:          /* Packed pixels of unknown coloour space */
+		src_uv_stride_bytes = src_y_stride_bytes;
+		break;
+
+	case IMG_CODEC_444_YUV:         /* Unusable if scaler not present */
+	case IMG_CODEC_444_YV12:        /* Unusable if scaler not present */
+	case IMG_CODEC_444_PL8:         /* Unusable if scaler not present */
+		src_uv_stride_bytes = src_y_stride_bytes;
+		break;
+
+	/* Interleaved chroma pixels (unusable if scaler not present) */
+	case IMG_CODEC_444_IMC2:
+	/* Interleaved chroma rows (unusable if scaler not present) */
+	case IMG_CODEC_444_PL12:
+	/* Interleaved chroma rows (unusable if scaler not present) */
+	case IMG_CODEC_444_PL21:
+		src_uv_stride_bytes = src_y_stride_bytes * 2;
+		break;
+
+	default:
+		break;
+	}
+
+	if (is_interlaced && is_interleaved) {
+		src_y_stride_bytes *= 2;
+		src_uv_stride_bytes *= 2;
+	}
+	return F_ENCODE(src_y_stride_bytes >> 6, MTX_MSG_PICMGMT_STRIDE_Y) |
+		F_ENCODE(src_uv_stride_bytes >> 6, MTX_MSG_PICMGMT_STRIDE_UV);
+}
+
+/*
+ * Setup the registers for scaling candidate motion vectors to take into account
+ * how far away (temporally) the reference pictures are
+ */
+#define RESTRICT16x16_FLAGS                             (0x1)
+#define RESTRICT8x8_FLAGS                               (0x2)
+
+void update_driver_mv_scaling(unsigned int frame_num, unsigned int ref0_num, unsigned int ref1_num,
+			      unsigned int pic_flags, unsigned int *mv_calc_below_handle,
+			      unsigned int *mv_calc_colocated_handle,
+			      unsigned int *mv_calc_config_handle)
+{
+	unsigned int mv_calc_config = 0;
+	unsigned int mv_calc_colocated = F_ENCODE(0x10, TOPAZHP_CR_TEMPORAL_BLEND);
+	unsigned int mv_calc_below = 0;
+
+	/* If b picture calculate scaling factor for colocated motion vectors */
+	if (pic_flags & ISINTERB_FLAGS) {
+		int tb, td, tx;
+		int dist_scale;
+
+		/* calculation taken from H264 spec */
+		tb = (frame_num * 2) - (ref1_num * 2);
+		td = (ref0_num  * 2) - (ref1_num * 2);
+		tx = (16384 + abs(td / 2)) / td;
+		dist_scale = (tb * tx + 32) >> 6;
+		if (dist_scale > 1023)
+			dist_scale = 1023;
+
+		if (dist_scale < -1024)
+			dist_scale = -1024;
+
+		mv_calc_colocated |= F_ENCODE(dist_scale, TOPAZHP_CR_COL_DIST_SCALE_FACT);
+
+		/*
+		 * We assume the below temporal mvs are from the latest reference frame
+		 * rather then the most recently encoded B frame (as Bs aren't reference)
+		 * Fwd temporal is same as colocated mv scale
+		 */
+		mv_calc_below |= F_ENCODE(dist_scale, TOPAZHP_CR_PIC0_DIST_SCALE_FACTOR);
+
+		/* Bkwd temporal needs to be scaled by the recipricol
+		 * amount in the other direction
+		 */
+		tb = (frame_num * 2) - (ref0_num * 2);
+		td = (ref0_num  * 2) - (ref1_num * 2);
+		tx = (16384 + abs(td / 2)) / td;
+		dist_scale = (tb * tx + 32) >> 6;
+		if (dist_scale > 1023)
+			dist_scale = 1023;
+
+		if (dist_scale < -1024)
+			dist_scale = -1024;
+
+		mv_calc_below |= F_ENCODE(dist_scale, TOPAZHP_CR_PIC1_DIST_SCALE_FACTOR);
+	} else {
+		/* Don't scale the temporal below mvs */
+		mv_calc_below |= F_ENCODE(1 << 8, TOPAZHP_CR_PIC0_DIST_SCALE_FACTOR);
+
+		if (ref0_num != ref1_num) {
+			int ref0_dist, ref1_dist;
+			int scale;
+
+			/*
+			 * Distance to second reference picture may be different when
+			 * using multiple reference frames on P. Scale based on difference
+			 * in temporal distance to ref pic 1 compared to distance to ref pic 0
+			 */
+			ref0_dist = (frame_num - ref0_num);
+			ref1_dist = (frame_num - ref1_num);
+			scale    = (ref1_dist << 8) / ref0_dist;
+
+			if (scale > 1023)
+				scale = 1023;
+			if (scale < -1024)
+				scale = -1024;
+
+			mv_calc_below |= F_ENCODE(scale, TOPAZHP_CR_PIC1_DIST_SCALE_FACTOR);
+		} else {
+			mv_calc_below |= F_ENCODE(1 << 8, TOPAZHP_CR_PIC1_DIST_SCALE_FACTOR);
+		}
+	}
+
+	if (frame_num > 0) {
+		int ref0_distance, ref1_distance;
+		int jitter0, jitter1;
+
+		ref0_distance = abs((int)frame_num - (int)ref0_num);
+		ref1_distance = abs((int)frame_num - (int)ref1_num);
+
+		if (!(pic_flags & ISINTERB_FLAGS)) {
+			jitter0 = ref0_distance * 1;
+			jitter1 = jitter0 > 1 ? 1 : 2;
+		} else {
+			jitter0 = ref1_distance * 1;
+			jitter1 = ref0_distance * 1;
+		}
+
+		/* Hardware can only cope with 1 - 4 jitter factors */
+		jitter0 = (jitter0 > 4) ? 4 : (jitter0 < 1) ? 1 : jitter0;
+		jitter1 = (jitter1 > 4) ? 4 : (jitter1 < 1) ? 1 : jitter1;
+
+		/* Hardware can only cope with 1 - 4 jitter factors */
+		IMG_DBG_ASSERT(jitter0 > 0 && jitter0 <= 4 && jitter1 > 0 && jitter1 <= 4);
+
+		mv_calc_config |= F_ENCODE(jitter0 - 1, TOPAZHP_CR_MVCALC_IPE0_JITTER_FACTOR) |
+			F_ENCODE(jitter1 - 1, TOPAZHP_CR_MVCALC_IPE1_JITTER_FACTOR);
+	}
+
+	mv_calc_config |= F_ENCODE(1, TOPAZHP_CR_MVCALC_DUP_VEC_MARGIN);
+	mv_calc_config |= F_ENCODE(7, TOPAZHP_CR_MVCALC_GRID_MB_X_STEP);
+	mv_calc_config |= F_ENCODE(13, TOPAZHP_CR_MVCALC_GRID_MB_Y_STEP);
+	mv_calc_config |= F_ENCODE(3, TOPAZHP_CR_MVCALC_GRID_SUB_STEP);
+	mv_calc_config |= F_ENCODE(1, TOPAZHP_CR_MVCALC_GRID_DISABLE);
+
+	mv_calc_config |= F_ENCODE(1, TOPAZHP_CR_MVCALC_NO_PSEUDO_DUPLICATES);
+
+	*mv_calc_below_handle = mv_calc_below;
+	*mv_calc_colocated_handle = mv_calc_colocated;
+	*mv_calc_config_handle = mv_calc_config;
+}
+
+void prepare_mv_estimates(struct img_enc_context *enc)
+{
+	struct img_video_context *vid_ctx = enc->video;
+	unsigned int distance;
+	unsigned int distance_b;
+	unsigned int position;
+	struct img_mv_settings *host_mv_settings_b_table;
+	struct img_mv_settings *host_mv_settings_hierarchical;
+	unsigned char hierarchical;
+
+	/* IDR */
+	vid_ctx->mv_settings_idr.mv_calc_config = DEFAULT_MVCALC_CONFIG; /* default based on TRM */
+	vid_ctx->mv_settings_idr.mv_calc_colocated = 0x00100100; /* default based on TRM */
+	vid_ctx->mv_settings_idr.mv_calc_below = 0x01000100;    /* default based on TRM */
+
+	update_driver_mv_scaling(0, 0, 0, 0, &vid_ctx->mv_settings_idr.mv_calc_below,
+				 &vid_ctx->mv_settings_idr.mv_calc_colocated,
+				 &vid_ctx->mv_settings_idr.mv_calc_config);
+
+	/* NonB (I or P) */
+	for (distance = 1; distance <= MAX_BFRAMES + 1; distance++) {
+		/* default based on TRM */
+		vid_ctx->mv_settings_non_b[distance - 1].mv_calc_config = DEFAULT_MVCALC_CONFIG;
+		/* default based on TRM */
+		vid_ctx->mv_settings_non_b[distance - 1].mv_calc_colocated = 0x00100100;
+		/* default based on TRM */
+		vid_ctx->mv_settings_non_b[distance - 1].mv_calc_below = 0x01000100;
+
+		update_driver_mv_scaling
+				(distance, 0, 0, 0,
+				 &vid_ctx->mv_settings_non_b[distance - 1].mv_calc_below,
+				 &vid_ctx->mv_settings_non_b[distance - 1].mv_calc_colocated,
+				 &vid_ctx->mv_settings_non_b[distance - 1].mv_calc_config);
+	}
+
+	hierarchical = (bool)(vid_ctx->mv_settings_hierarchical.cpu_virt);
+
+	host_mv_settings_b_table = (struct img_mv_settings *)(vid_ctx->mv_settings_btable.cpu_virt);
+
+	if (hierarchical)
+		host_mv_settings_hierarchical =
+			(struct img_mv_settings *)(vid_ctx->mv_settings_hierarchical.cpu_virt);
+
+	for (distance_b = 0; distance_b < MAX_BFRAMES; distance_b++) {
+		for (position = 1; position <= distance_b + 1; position++) {
+			struct img_mv_settings *mv_element =
+			(struct img_mv_settings *)((unsigned char *)host_mv_settings_b_table +
+				MV_OFFSET_IN_TABLE(distance_b, position - 1));
+
+			mv_element->mv_calc_config =
+				/* default based on TRM */
+				(DEFAULT_MVCALC_CONFIG | MASK_TOPAZHP_CR_MVCALC_GRID_DISABLE);
+
+			mv_element->mv_calc_colocated = 0x00100100;/* default based on TRM */
+			mv_element->mv_calc_below = 0x01000100; /* default based on TRM */
+
+			update_driver_mv_scaling(position, distance_b + 2, 0, ISINTERB_FLAGS,
+						 &mv_element->mv_calc_below,
+						 &mv_element->mv_calc_colocated,
+						 &mv_element->mv_calc_config);
+		}
+	}
+
+	if (hierarchical) {
+		for (distance_b = 0; distance_b < MAX_BFRAMES; distance_b++)
+			memcpy(host_mv_settings_hierarchical + distance_b,
+			       (unsigned char *)host_mv_settings_b_table +
+			       MV_OFFSET_IN_TABLE(distance_b, distance_b >> 1),
+			       sizeof(struct img_mv_settings));
+	}
+}
+
+/*
+ * Generates the video pic params template
+ */
+void adjust_pic_flags(struct img_enc_context *enc, struct img_rc_params *rc_params,
+		      unsigned char first_pic, unsigned int *flags)
+{
+	unsigned int flags_local;
+	struct pic_params *pic_params = &enc->video->pic_params;
+
+	flags_local = pic_params->flags;
+
+	if (!rc_params->rc_enable || !first_pic)
+		flags_local = 0;
+
+	*flags = flags_local;
+}
+
+/*
+ * Sets up RC Data
+ */
+void setup_rc_data(struct img_video_context *video, struct pic_params *pic_params,
+		   struct img_rc_params *rc_params)
+{
+	int tmp_qp = 0;
+	int buffer_size_in_frames;
+	short max_qp = MAX_QP_H264;
+	short min_qp = 0;
+	int mul_of_8mbits;
+	int framerate, scale = 1;
+	int l1, l2, l3, l4, l5, scaled_bpp;
+
+	/* If Bit Rate and Basic Units are not specified then set to default values. */
+	if (rc_params->bits_per_second == 0 && !video->enable_mvc)
+		rc_params->bits_per_second = 640000; /* kbps */
+
+	if (!rc_params->bu_size)
+		/* BU = 1 Frame */
+		rc_params->bu_size = (video->picture_height >> 4) * (video->width >> 4);
+
+	if (!rc_params->frame_rate)
+		rc_params->frame_rate = 30; /* fps */
+
+	/* Calculate Bits per Pixel */
+	if (video->width <= 176)
+		framerate = 30;
+	else
+		framerate = rc_params->frame_rate;
+
+	mul_of_8mbits = rc_params->bits_per_second / 8000000;
+
+	if (mul_of_8mbits == 0)
+		scale = 256;
+	else if (mul_of_8mbits > 127)
+		scale = 1;
+	else
+		scale = 128 / mul_of_8mbits;
+
+	scaled_bpp = (scale * rc_params->bits_per_second) /
+		(framerate * video->width * video->frame_height);
+
+	pic_params->in_params.se_init_qp_i      = rc_params->initial_qp_i;
+
+	pic_params->in_params.mb_per_row        = (video->width >> 4);
+	pic_params->in_params.mb_per_bu         = rc_params->bu_size;
+	pic_params->in_params.mb_per_frm                = ((unsigned int)(video->width >> 4)) *
+		(video->frame_height >> 4);
+	pic_params->in_params.bu_per_frm        = (pic_params->in_params.mb_per_frm) /
+		rc_params->bu_size;
+
+	pic_params->in_params.intra_period      = rc_params->intra_freq;
+	pic_params->in_params.bframes           = rc_params->bframes;
+	pic_params->in_params.bit_rate          = rc_params->bits_per_second;
+
+	pic_params->in_params.frm_skip_disable = rc_params->disable_frame_skipping;
+
+	pic_params->in_params.bits_per_frm      =
+		(rc_params->bits_per_second + rc_params->frame_rate / 2) / rc_params->frame_rate;
+
+	pic_params->in_params.bits_per_bu       = pic_params->in_params.bits_per_frm /
+		(4 * pic_params->in_params.bu_per_frm);
+
+	/*Disable Vcm Hardware*/
+	pic_params->in_params.disable_vcm_hardware = rc_params->disable_vcm_hardware;
+	/* Codec-dependent fields */
+	if (video->standard == IMG_STANDARD_H264) {
+		pic_params->in_params.mode.h264.transfer_rate  =
+			(rc_params->transfer_bits_per_second + rc_params->frame_rate / 2) /
+			rc_params->frame_rate;
+		pic_params->in_params.mode.h264.hierarchical_mode =   rc_params->hierarchical;
+
+		pic_params->in_params.mode.h264.enable_slice_bob =
+			(unsigned char)rc_params->enable_slice_bob;
+		pic_params->in_params.mode.h264.max_slice_bob =
+			(unsigned char)rc_params->max_slice_bob;
+		pic_params->in_params.mode.h264.slice_bob_qp =
+			(unsigned char)rc_params->slice_bob_qp;
+	}
+
+	if (pic_params->in_params.bits_per_frm) {
+		buffer_size_in_frames =
+			(rc_params->buffer_size + (pic_params->in_params.bits_per_frm / 2)) /
+			pic_params->in_params.bits_per_frm;
+	} else {
+		IMG_DBG_ASSERT(video->enable_mvc && ("Can happen only in MVC mode" != NULL));
+		/* Asigning more or less `normal` value. To be overridden by MVC RC module */
+		buffer_size_in_frames = 30;
+	}
+
+	/* select thresholds and initial Qps etc that are codec dependent */
+	switch (video->standard) {
+	case IMG_STANDARD_H264:
+		/* Setup MAX and MIN Quant Values */
+		pic_params->in_params.max_qp = (rc_params->max_qp > 0) &&
+			(rc_params->max_qp < max_qp) ? rc_params->max_qp : max_qp;
+
+		if (rc_params->min_qp == 0) {
+			if (scaled_bpp >= (scale >> 1)) {
+				tmp_qp = 4;
+			} else if (scaled_bpp > ((scale << 1) / 15)) {
+				tmp_qp = (22 * scale) - (40 * scaled_bpp);
+				tmp_qp = tmp_qp / scale;
+			} else {
+				tmp_qp = (30 * scale) - (100 * scaled_bpp);
+				tmp_qp = tmp_qp / scale;
+			}
+
+			/* Adjust minQp up for small buffer size and down for large buffer size */
+			if (buffer_size_in_frames < 5) {
+				tmp_qp += 2;
+			} else if (buffer_size_in_frames > 40) {
+				if (tmp_qp >= 1)
+					tmp_qp -= 1;
+			}
+			/* for HD content allow a lower minQp as bitrate is
+			 * more easily controlled in this case
+			 */
+			if (pic_params->in_params.mb_per_frm > 2000)
+				tmp_qp -= 6;
+		} else {
+			tmp_qp = rc_params->min_qp;
+		}
+
+		min_qp = 2;
+
+		if (tmp_qp < min_qp)
+			pic_params->in_params.min_qp = min_qp;
+		else
+			pic_params->in_params.min_qp = tmp_qp;
+
+		/* Calculate Initial QP if it has not been specified */
+		tmp_qp = pic_params->in_params.se_init_qp_i;
+		if (pic_params->in_params.se_init_qp_i == 0) {
+			l1 = scale / 20;
+			l2 = scale / 5;
+			l3 = (scale * 2) / 5;
+			l4 = (scale * 4) / 5;
+			l5 = (scale * 1011) / 1000;
+
+			tmp_qp = pic_params->in_params.min_qp;
+
+			pic_params->in_params.se_init_qp_i = tmp_qp;
+			if (scaled_bpp < l1)
+				tmp_qp = (45 * scale) - (78 * scaled_bpp);
+			else if (scaled_bpp < l2)
+				tmp_qp = (44 * scale) - (73 * scaled_bpp);
+			else if (scaled_bpp < l3)
+				tmp_qp = (34 * scale) - (25 * scaled_bpp);
+			else if (scaled_bpp < l4)
+				tmp_qp = (32 * scale) - (20 * scaled_bpp);
+			else if (scaled_bpp < l5)
+				tmp_qp = (25 * scale) - (10 * scaled_bpp);
+			else
+				tmp_qp = (18 * scale) - (5 * scaled_bpp);
+
+			/* Adjust ui8SeInitQP up for small buffer size or small fps */
+			/* Adjust ui8SeInitQP up for small gop size */
+			if (buffer_size_in_frames < 20 || rc_params->intra_freq < 20)
+				tmp_qp += 2 * scale;
+
+			/* for very small buffers increase initial Qp even more */
+			if (buffer_size_in_frames < 5)
+				tmp_qp += 8 * scale;
+
+			/* start on a lower initial Qp for HD content
+			 * as the coding is more efficient
+			 */
+			if (pic_params->in_params.mb_per_frm > 2000)
+				tmp_qp -= 2 * scale;
+
+			if (pic_params->in_params.intra_period == 1) {
+				/* for very small GOPS start with a much higher initial Qp */
+				tmp_qp += 12 * scale;
+			} else if (pic_params->in_params.intra_period < 5) {
+				tmp_qp += 6 * scale;
+			}
+
+			tmp_qp = tmp_qp / scale;
+		}
+
+		max_qp = 49;
+
+		if (tmp_qp > max_qp)
+			tmp_qp = max_qp;
+
+		if (tmp_qp < pic_params->in_params.min_qp)
+			tmp_qp = pic_params->in_params.min_qp;
+
+		pic_params->in_params.se_init_qp_i = tmp_qp;
+
+		if (scaled_bpp <= ((3 * scale) / 10))
+			pic_params->flags |= ISRC_I16BIAS;
+		break;
+
+	default:
+		/* the NO RC cases will fall here */
+		break;
+	}
+
+	if (video->rc_params.rc_mode == IMG_RCMODE_VBR) {
+		pic_params->in_params.mb_per_bu = pic_params->in_params.mb_per_frm;
+		pic_params->in_params.bu_per_frm        = 1;
+
+		/* Initialize the parameters of fluid flow traffic model. */
+		pic_params->in_params.buffer_size = rc_params->buffer_size;
+
+		/* VBR shouldn't skip frames */
+		pic_params->in_params.frm_skip_disable = TRUE;
+
+		/*
+		 * These scale factor are used only for rate control to avoid overflow
+		 * in fixed-point calculation these scale factors are decided by bit rate
+		 */
+		if (rc_params->bits_per_second < 640000)
+			pic_params->in_params.scale_factor  = 2; /* related to complexity */
+		else if (rc_params->bits_per_second < 2000000)    /* 2 Mbits */
+			pic_params->in_params.scale_factor  = 4;
+		else if (rc_params->bits_per_second < 8000000)     /* 8 Mbits */
+			pic_params->in_params.scale_factor  = 6;
+		else
+			pic_params->in_params.scale_factor  = 8;
+	} else {
+		/* Set up Input Parameters that are mode dependent */
+		switch (video->standard) {
+		case IMG_STANDARD_H264:
+			/*
+			 * H264 CBR RC: Initialize the parameters of fluid flow traffic model.
+			 */
+			pic_params->in_params.buffer_size = rc_params->buffer_size;
+
+			/* HRD consideration - These values are used by H.264 reference code. */
+			if (rc_params->bits_per_second < 1000000)         /* 1 Mbits/s */
+				pic_params->in_params.scale_factor = 0;
+			else if (rc_params->bits_per_second < 2000000)    /* 2 Mbits/s */
+				pic_params->in_params.scale_factor = 1;
+			else if (rc_params->bits_per_second < 4000000)    /* 4 Mbits/s */
+				pic_params->in_params.scale_factor = 2;
+			else if (rc_params->bits_per_second < 8000000)    /* 8 Mbits/s */
+				pic_params->in_params.scale_factor = 3;
+			else
+				pic_params->in_params.scale_factor = 4;
+
+			if (video->rc_params.rc_mode == IMG_RCMODE_VCM)
+				pic_params->in_params.buffer_size_frames = buffer_size_in_frames;
+			break;
+
+		default:
+			break;
+		}
+	}
+
+	if (rc_params->sc_detect_disable)
+		pic_params->flags  |= ISSCENE_DISABLED;
+
+	pic_params->in_params.initial_delay     = rc_params->initial_delay;
+	pic_params->in_params.initial_level     = rc_params->initial_level;
+	rc_params->initial_qp_i                 = pic_params->in_params.se_init_qp_i;
+
+	/* The rate control uses this value to adjust
+	 * the reaction rate to larger than expected frames
+	 */
+	if (video->standard == IMG_STANDARD_H264) {
+		if (pic_params->in_params.bits_per_frm) {
+			const int bits_per_gop =
+				(rc_params->bits_per_second / rc_params->frame_rate) *
+				rc_params->intra_freq;
+
+			pic_params->in_params.mode.h264.rc_scale_factor = (bits_per_gop * 256) /
+				(pic_params->in_params.buffer_size -
+				pic_params->in_params.initial_level);
+		} else {
+			pic_params->in_params.mode.h264.rc_scale_factor = 0;
+		}
+	}
+}
+
+void topaz_setup_input_format(struct img_video_context *video,
+			      struct img_vxe_scaler_setup *scaler_setup)
+{
+	const unsigned int scaler_coeff_regs_no_crop[] = {4261951490U, 4178589440U,
+						    4078580480U, 4045614080U};
+
+	if (video->enable_scaler) {
+		unsigned int pitch_x, pitch_y;
+		int phase;
+
+		pitch_x = (((unsigned int)(video->source_width - video->crop_left -
+			video->crop_right)) << 13) / video->unrounded_width;
+
+		pitch_y = (((unsigned int)(video->source_frame_height - video->crop_top -
+			video->crop_bottom)) << 13) / video->unrounded_frame_height;
+
+		/* Input size */
+		scaler_setup->scaler_input_size_reg =
+			F_ENCODE(video->source_width - 1,
+				 TOPAZHP_EXT_CR_SCALER_INPUT_WIDTH_MIN1) |
+			F_ENCODE((video->source_frame_height >>
+				 (video->is_interlaced ? 1 : 0)) - 1,
+				  TOPAZHP_EXT_CR_SCALER_INPUT_HEIGHT_MIN1);
+
+		scaler_setup->scaler_crop_reg = F_ENCODE(video->crop_left,
+							 TOPAZHP_EXT_CR_SCALER_INPUT_CROP_HOR) |
+						F_ENCODE(video->crop_top,
+							 TOPAZHP_EXT_CR_SCALER_INPUT_CROP_VER);
+
+		/* Scale factors */
+		scaler_setup->scaler_pitch_reg = 0;
+
+		if (pitch_x > 0x7FFF) {
+			scaler_setup->scaler_pitch_reg |= F_ENCODE(1,
+					TOPAZHP_EXT_CR_SCALER_HOR_BILINEAR_FILTER);
+			pitch_x >>= 1;
+		}
+
+		if (pitch_x > 0x7FFF)
+			pitch_x = 0x7FFF;
+
+		if (pitch_y > 0x7FFF) {
+			scaler_setup->scaler_pitch_reg |= F_ENCODE(1U,
+					TOPAZHP_EXT_CR_SCALER_VER_BILINEAR_FILTER);
+			pitch_y >>= 1;
+		}
+
+		if (pitch_y > 0x7FFF)
+			pitch_y = 0x7FFF;
+
+		scaler_setup->scaler_pitch_reg |=
+			F_ENCODE(pitch_x, TOPAZHP_EXT_CR_SCALER_INPUT_HOR_PITCH) |
+			F_ENCODE(pitch_y, TOPAZHP_EXT_CR_SCALER_INPUT_VER_PITCH);
+
+		/*
+		 * Coefficients
+		 * With no crop, the coefficients remain the same.
+		 * If crop is desired, new values will need to be calculated.
+		 */
+		for (phase = 0; phase < 4; phase++)
+			scaler_setup->hor_scaler_coeff_regs[phase] =
+				scaler_coeff_regs_no_crop[phase];
+
+		for (phase = 0; phase < 4; phase++)
+			scaler_setup->ver_scaler_coeff_regs[phase] =
+				scaler_coeff_regs_no_crop[phase];
+
+		scaler_setup->scaler_control = F_ENCODE(1, TOPAZHP_EXT_CR_SCALER_ENABLE);
+
+		switch (video->format) {
+		case IMG_CODEC_420_YUV:
+		case IMG_CODEC_420_PL8:
+		case IMG_CODEC_420_YV12:
+		case IMG_CODEC_420_IMC2:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_420PL111YCBCR8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_420_PL12:
+		case IMG_CODEC_420_PL12_PACKED:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_420PL12YCBCR8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_420_PL21:
+		case IMG_CODEC_420_PL21_PACKED:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_420PL12YCRCB8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_422_YUV:
+		case IMG_CODEC_422_PL8:
+		case IMG_CODEC_422_YV12:
+		case IMG_CODEC_422_IMC2:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422PL111YCBCR8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_422_PL12:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422PL12YCBCR8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_422_PL21:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422PL12YCRCB8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_Y0UY1V_8888:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422IL3YCBYCR8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_Y0VY1U_8888:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422IL3YCRYCB8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_UY0VY1_8888:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422IL3CBYCRY8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_VY0UY1_8888:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_422IL3CRYCBY8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_444_YUV:
+		case IMG_CODEC_444_PL8:
+		case IMG_CODEC_444_YV12:
+		case IMG_CODEC_444_IMC2:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_444PL111YCBCR8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_444_PL12:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_444PL12YCBCR8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_444_PL21:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_444PL12YCRCB8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_ABCX:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_444IL4ABCX8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_XBCA:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_444IL4XBCA8,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		case IMG_CODEC_ABC565:
+			scaler_setup->input_scaler_control =
+				F_ENCODE(TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT_444IL3RGB565,
+					 TOPAZHP_EXT_CR_INPUT_FRAME_STORE_FORMAT);
+			break;
+		default:
+			break;
+		}
+	} else {
+		/* Disable Scaling */
+		scaler_setup->scaler_control = 0;
+	}
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/topaz_api_utils.h b/drivers/media/platform/img/vxe-vxd/encoder/topaz_api_utils.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/topaz_api_utils.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/topaz_api_utils.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * topaz utility header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/types.h>
+#include "topaz_api.h"
+
+/*
+ * Calculates the correct number of macroblocks per kick and kicks per BU
+ */
+void calculate_kick_and_bu_size(unsigned int width_in_mbs,
+				unsigned int height_in_mbs,
+				unsigned char is_interlaced,
+				unsigned int max_bu_per_frame,
+				unsigned int *kick_size,
+				unsigned int *kicks_per_bu,
+				unsigned int *min_slice_height);
+
+unsigned int calculate_stride(enum img_format format,
+			      unsigned short requested_stride_bytes,
+			      unsigned short width);
+
+void topaz_setup_input_format(struct img_video_context *video,
+			      struct img_vxe_scaler_setup *scaler_setup);
+
+void topaz_setup_input_csc(struct img_video_context *video,
+			   struct img_vxe_scaler_setup *scaler_setup,
+			   struct img_vxe_csc_setup *csc_setup,
+			   enum img_csc_preset csc_preset);
+
+unsigned int topaz_get_packed_buffer_strides(unsigned short buffer_stride_bytes,
+					     enum img_format format,
+					     unsigned char enable_scaler,
+					     unsigned char is_interlaced,
+					     unsigned char is_interleaved);
+
+void prepare_mv_estimates(struct img_enc_context *enc);
+
+void adjust_pic_flags(struct img_enc_context *enc, struct img_rc_params *prc_params,
+		      unsigned char first_pic, unsigned int *flags);
+
+void setup_rc_data(struct img_video_context *video, struct pic_params *pic_params,
+		   struct img_rc_params *rc_params);
+
+void patch_hw_profile(struct img_video_params *video_params, struct img_video_context *video);
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/topaz_color_formats.h b/drivers/media/platform/img/vxe-vxd/encoder/topaz_color_formats.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/topaz_color_formats.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/topaz_color_formats.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * buffer sizes calculation
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include "topaz_api.h"
+#include "fw_headers/defs.h"
+
+void plane_size(enum img_format color_format, unsigned int stride,
+		unsigned int height, unsigned int *y_size, unsigned int *u_size,
+		unsigned int *v_size)
+{
+	*y_size = *u_size = *v_size = 0;
+
+	switch (color_format) {
+	case IMG_CODEC_420_PL8:
+		/* allocate frame for 4:2:0 planar format */
+		*y_size = stride * height;
+		*u_size = stride * height / 4;
+		*v_size = stride * height / 4;
+		break;
+	case IMG_CODEC_420_PL12:
+		/* allocate frame for 4:2:0 planar format (chroma interleaved) */
+		*y_size = stride * height;
+		*u_size = stride * height / 2;
+		break;
+	case IMG_CODEC_422_YUV:
+	case IMG_CODEC_422_YV12:
+	case IMG_CODEC_422_IMC2:
+		/* allocate frame for 4:2:2 format */
+		*y_size = stride * height * 2;
+		break;
+	case IMG_CODEC_422_PL8:
+		/* allocate frame for 4:2:2 planar format */
+		*y_size = stride * height;
+		*u_size = stride * height / 2;
+		*v_size = stride * height / 2;
+		break;
+	case IMG_CODEC_422_PL12:
+		/* allocate frame for 4:2:2 planar format (chroma interleaved) */
+		*y_size = stride * height;
+		*u_size = stride * height;
+		break;
+	case IMG_CODEC_Y0UY1V_8888:
+	case IMG_CODEC_UY0VY1_8888:
+	case IMG_CODEC_Y0VY1U_8888:
+	case IMG_CODEC_VY0UY1_8888:
+		/* allocate frame for 4:2:2 format */
+		*y_size = stride * height;
+		break;
+	case IMG_CODEC_444_YUV:
+	case IMG_CODEC_444_YV12:
+	case IMG_CODEC_444_IMC2:
+		/* allocate frame for 4:2:2 format */
+		*y_size = stride * height * 3;
+		break;
+	case IMG_CODEC_444_PL8:
+		/* allocate frame for 4:2:2 planar format */
+		*y_size = stride * height;
+		*u_size = stride * height;
+		*v_size = stride * height;
+		break;
+	case IMG_CODEC_444_PL12:
+		/* allocate frame for 4:2:2 planar format (chroma interleaved) */
+		*y_size = stride * height;
+		*u_size = stride * height * 2;
+		break;
+	case IMG_CODEC_ABCX:
+	case IMG_CODEC_XBCA:
+	case IMG_CODEC_ABC565:
+		/* allocate frame for RGB interleaved format */
+		*y_size = stride * height;
+		break;
+	case IMG_CODEC_420_YUV:
+	case IMG_CODEC_420_YV12:
+	case IMG_CODEC_420_IMC2:
+	case IMG_CODEC_420_PL12_PACKED:
+	case IMG_CODEC_420_PL21_PACKED:
+		/* allocate frame for 4:2:0 format */
+		*y_size = stride * height * 3 / 2;
+		break;
+	default:
+		*y_size = 0;
+		*u_size = 0;
+		*v_size = 0;
+		break;
+	}
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/topaz_device.c b/drivers/media/platform/img/vxe-vxd/encoder/topaz_device.c
--- a/drivers/media/platform/img/vxe-vxd/encoder/topaz_device.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/topaz_device.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1671 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Encoder device function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+#include <linux/string.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <linux/delay.h>
+#include <linux/time64.h>
+#include <linux/jiffies.h>
+
+#include "work_queue.h"
+#include "fw_headers/defs.h"
+#include "fw_headers/vxe_common.h"
+#include "target.h"
+#include "target_config.h"
+#include "topaz_device.h"
+#include "topazmmu.h"
+#include "vid_buf.h"
+#include "vxe_public_regdefs.h"
+#include "img_errors.h"
+
+#ifdef DEBUG_ENCODER_DRIVER
+static char command_string[][38] = {
+	"MTX_CMDID_NULL",
+	"MTX_CMDID_SHUTDOWN",
+	"MTX_CMDID_DO_HEADER",
+	"MTX_CMDID_ENCODE_FRAME",
+	"MTX_CMDID_START_FRAME",
+	"MTX_CMDID_ENCODE_SLICE",
+	"MTX_CMDID_END_FRAME",
+	"MTX_CMDID_SETVIDEO",
+	"MTX_CMDID_GETVIDEO",
+	"MTX_CMDID_DO_CHANGE_PIPEWORK",
+#if SECURE_IO_PORTS
+	"MTX_CMDID_SECUREIO",
+#endif
+	"MTX_CMDID_PICMGMT",
+	"MTX_CMDID_RC_UPDATE",
+	"MTX_CMDID_PROVIDE_SOURCE_BUFFER",
+	"MTX_CMDID_PROVIDE_REF_BUFFER",
+	"MTX_CMDID_PROVIDE_CODEDPACKAGE_BUFFER",
+	"MTX_CMDID_ABORT",
+	"MTX_CMDID_SETQUANT",
+	"MTX_CMDID_SETUP_INTERFACE",
+	"MTX_CMDID_ISSUEBUFF",
+	"MTX_CMDID_SETUP",
+	"MTX_CMDID_UPDATE_SOURCE_FORMAT",
+	"MTX_CMDID_UPDATE_CSC",
+	"MTX_CMDID_ENDMARKER"
+};
+#endif
+
+DECLARE_WAIT_QUEUE_HEAD(event_wait_queue);
+
+#define TOPAZ_DEV_SPIN_LOCK_NAME  "topaz_dev"
+/* max syncStatus value used (at least 4 * MAX_TOPAZ_CMDS_QUEUED) */
+#define MAX_TOPAZ_CMD_COUNT       (0x1000)
+
+#define COMM_WB_DATA_BUF_SIZE     (64)
+
+/* Sempahore locks */
+#define COMM_LOCK_TX          0x01
+#define COMM_LOCK_RX          0x02
+#define COMM_LOCK_BOTH        (COMM_LOCK_TX | COMM_LOCK_RX)
+
+static unsigned int topaz_timeout_retries = 817000;
+
+#define TOPAZ_TIMEOUT_JPEG    (50000)
+#define TOPAZ_TIMEOUT_RETRIES (topaz_timeout_retries)
+
+unsigned short g_load_method = MTX_LOADMETHOD_DMA; /* This is the load method used */
+
+unsigned int g_core_rev;
+unsigned int g_core_des1;
+void *g_lock;
+
+struct vidio_ddbufinfo *g_aps_wb_data_info;
+
+static unsigned char g_pipe_usage[TOPAZHP_MAX_NUM_PIPES] = { 0 };
+
+/* Order MUST match with topaz_mem_space_idx enum */
+struct mem_space topaz_mem_space[] = {
+	/* Multicore sync RAM */
+	{ "REG_TOPAZHP_MULTICORE",        MEMSPACE_REGISTER,
+	  {{0x00000000, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_DMAC",                     MEMSPACE_REGISTER,
+	  {{0x00000400, 0x000000ff, TARGET_NO_IRQ}}},
+	{ "REG_COMMS",                    MEMSPACE_REGISTER,
+	  {{0x00000500, 0x000000ff, TARGET_NO_IRQ}}},
+	{ "REG_MTX",                      MEMSPACE_REGISTER,
+	  {{0x00000800, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_MMU",                      MEMSPACE_REGISTER,
+	  {{0x00000C00, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_TEST",             MEMSPACE_REGISTER,
+	  {{0xFFFF0000, 0x000001ff, TARGET_NO_IRQ}}},
+	{ "REGMTXRAM",                    MEMSPACE_REGISTER,
+	  {{0x80000000, 0x0000ffff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_CORE_0",           MEMSPACE_REGISTER,
+	  {{0x00001000, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_VLC_CORE_0",       MEMSPACE_REGISTER,
+	  {{0x00001400, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_DEBLOCKER_CORE_0", MEMSPACE_REGISTER,
+	  {{0x00001800, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_COREEXT_0",        MEMSPACE_REGISTER,
+	  {{0x00001C00, 0x000003ff, TARGET_NO_IRQ}}},
+
+	{ "REG_TOPAZHP_CORE_1",           MEMSPACE_REGISTER,
+	  {{0x00002000, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_VLC_CORE_1",       MEMSPACE_REGISTER,
+	  {{0x00002400, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_DEBLOCKER_CORE_1", MEMSPACE_REGISTER,
+	  {{0x00002800, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_COREEXT_1",        MEMSPACE_REGISTER,
+	  {{0x00002C00, 0x000003ff, TARGET_NO_IRQ}}},
+
+	{ "REG_TOPAZHP_CORE_2",           MEMSPACE_REGISTER,
+	  {{0x00003000, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_VLC_CORE_2",       MEMSPACE_REGISTER,
+	  {{0x00003400, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_DEBLOCKER_CORE_2", MEMSPACE_REGISTER,
+	  {{0x00003800, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_COREEXT_2",        MEMSPACE_REGISTER,
+	  {{0x00003C00, 0x000003ff, TARGET_NO_IRQ}}},
+
+	{ "REG_TOPAZHP_CORE_3",           MEMSPACE_REGISTER,
+	  {{0x00004000, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_VLC_CORE_3",       MEMSPACE_REGISTER,
+	  {{0x00004400, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_DEBLOCKER_CORE_3", MEMSPACE_REGISTER,
+	  {{0x00004800, 0x000003ff, TARGET_NO_IRQ}}},
+	{ "REG_TOPAZHP_COREEXT_3",        MEMSPACE_REGISTER,
+	  {{0x00004C00, 0x000003ff, TARGET_NO_IRQ}}},
+
+	{ "FW",                           MEMSPACE_MEMORY,
+	  {{0x00000000, 0x00800000, 0            }}},
+	{ "SYSMEM",                       MEMSPACE_MEMORY,
+	  {{0x00000000, 0,          0            }}},
+	{ "MEMSYSMEM",                    MEMSPACE_MEMORY,
+	  {{0x00000000, 0,          0            }}},
+	{ "MEM",                          MEMSPACE_MEMORY,
+	  {{0x00000000, 0,          0            }}},
+	{ "FB",                           MEMSPACE_MEMORY,
+	  {{0x00000000, 0,          0            }}},
+	{ "MEMDMAC_00",                   MEMSPACE_MEMORY,
+	  {{0x00000000, 0,          0            }}},
+	{ "MEMDMAC_01",                   MEMSPACE_MEMORY,
+	  {{0x00000000, 0,          0            }}},
+	{ "MEMDMAC_02",                   MEMSPACE_MEMORY,
+	  {{0x00000000, 0,          0            }}},
+};
+
+#define MEMORYSPACES_NUM (sizeof(topaz_mem_space) / sizeof(struct mem_space))
+
+static struct target_config topaz_target_config = {
+	MEMORYSPACES_NUM,
+	&topaz_mem_space[0]
+};
+
+/*
+ * topazdd_int_enable
+ */
+static void topazdd_int_enable(struct topaz_dev_ctx *ctx, unsigned int mask)
+{
+	unsigned int reg;
+	unsigned long flags;
+
+	spin_lock_irqsave(ctx->lock, flags);
+
+	/* config interrupts on Topaz core */
+	reg = VXE_RD_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_HOST_INT_ENAB);
+
+	/* set enable interrupt bits */
+	reg |= mask;
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_HOST_INT_ENAB, reg);
+
+	spin_unlock_irqrestore(ctx->lock, (unsigned long)flags);
+}
+
+/*
+ * topazdd_int_disable
+ */
+static void topazdd_int_disable(struct topaz_dev_ctx *ctx, unsigned int mask)
+{
+	unsigned int reg;
+	unsigned long flags;
+
+	spin_lock_irqsave(ctx->lock, flags);
+
+	/* config interrupts on Topaz core */
+	reg = VXE_RD_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_HOST_INT_ENAB);
+
+	/* clear enable interrupt bits */
+	reg &= ~mask;
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_HOST_INT_ENAB, reg);
+
+	spin_unlock_irqrestore(ctx->lock, (unsigned long)flags);
+}
+
+/*
+ * Get the number of pipes present
+ */
+unsigned int topazdd_get_num_pipes(struct topaz_dev_ctx *ctx)
+{
+	static unsigned int g_pipes_avail;
+
+	if (!ctx->multi_core_mem_addr)
+		return 0;
+
+	if (g_pipes_avail == 0) {
+		/* get the actual number of cores */
+		g_pipes_avail = VXE_RD_REG32(ctx->multi_core_mem_addr,
+					     TOPAZHP_TOP_CR_MULTICORE_HW_CFG);
+		g_pipes_avail = (g_pipes_avail & MASK_TOPAZHP_TOP_CR_NUM_CORES_SUPPORTED);
+		IMG_DBG_ASSERT(g_pipes_avail != 0);
+	}
+
+	return g_pipes_avail;
+}
+
+unsigned int topazdd_get_core_rev(void)
+{
+	return g_core_rev;
+}
+
+unsigned int topazdd_get_core_des1(void)
+{
+	return g_core_des1;
+}
+
+static void wbfifo_clear(struct img_comm_socket *sock)
+{
+	sock->in_fifo_producer = 0;
+	sock->in_fifo_consumer = 0;
+}
+
+static unsigned char wbfifo_add(struct img_comm_socket *sock, struct img_writeback_msg *msg)
+{
+	unsigned int new_producer = sock->in_fifo_producer + 1;
+
+	if (new_producer == COMM_INCOMING_FIFO_SIZE)
+		new_producer = 0;
+
+	if (new_producer == sock->in_fifo_consumer)
+		return FALSE;
+
+	memcpy(&sock->in_fifo[sock->in_fifo_producer], msg, sizeof(struct img_writeback_msg));
+
+	sock->in_fifo_producer = new_producer;
+
+	return TRUE;
+}
+
+static unsigned char wbfifo_is_empty(struct img_comm_socket *sock)
+{
+	return (sock->in_fifo_producer == sock->in_fifo_consumer);
+}
+
+static unsigned char wbfifo_get(struct img_comm_socket *sock, struct img_writeback_msg *msg)
+{
+	if (wbfifo_is_empty(sock))
+		return FALSE;
+
+	memcpy(msg, &sock->in_fifo[sock->in_fifo_consumer], sizeof(struct img_writeback_msg));
+
+	sock->in_fifo_consumer++;
+
+	if (sock->in_fifo_consumer == COMM_INCOMING_FIFO_SIZE)
+		sock->in_fifo_consumer = 0;
+
+	return TRUE;
+}
+
+unsigned char topazdd_is_idle(struct img_comm_socket *sock)
+{
+	if (sock->msgs_sent == sock->ack_recv && wbfifo_is_empty(sock))
+		return TRUE;
+
+	return FALSE;
+}
+
+static void set_auto_clock_gating(struct topaz_dev_ctx *ctx, struct img_fw_context *fw_ctx,
+				  unsigned char gating)
+{
+	unsigned int reg;
+
+	reg = F_ENCODE(1U, TOPAZHP_TOP_CR_WRITES_CORE_ALL);
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_CORE_SEL_0, reg);
+
+	reg = F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_IPE0_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_IPE1_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_SPE0_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_SPE1_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_H264COMP4X4_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_H264COMP8X8_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_H264COMP16X16_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_JMCOMP_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_VLC_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_DEB_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_PC_DM_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_PC_DMS_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_CABAC_AUTO_CLK_GATE) |
+		F_ENCODE(gating, TOPAZHP_CR_TOPAZHP_INPUT_SCALER_AUTO_CLK_GATE);
+
+	VXE_WR_REG32(ctx->hp_core_reg_addr[0], TOPAZHP_CR_TOPAZHP_AUTO_CLOCK_GATING, reg);
+
+	reg = 0;
+	reg = VXE_RD_REG32(ctx->hp_core_reg_addr[0], TOPAZHP_CR_TOPAZHP_MAN_CLOCK_GATING);
+
+	/* Disable LRITC clocks */
+	reg = F_INSERT(reg, 1, TOPAZHP_CR_TOPAZHP_LRITC_MAN_CLK_GATE);
+
+	VXE_WR_REG32(ctx->hp_core_reg_addr[0], TOPAZHP_CR_TOPAZHP_MAN_CLOCK_GATING, reg);
+
+	reg = F_ENCODE(0, TOPAZHP_TOP_CR_WRITES_CORE_ALL);
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_CORE_SEL_0, reg);
+}
+
+static void comm_lock(struct topaz_dev_ctx *ctx, unsigned int flags)
+{
+	if (flags & COMM_LOCK_TX)
+		mutex_lock_nested(ctx->comm_tx_mutex, SUBCLASS_TOPAZDD_TX);
+}
+
+static void comm_unlock(struct topaz_dev_ctx *ctx, unsigned int flags)
+{
+	if (flags & COMM_LOCK_TX)
+		mutex_unlock((struct mutex *)ctx->comm_tx_mutex);
+}
+
+int comm_prepare_fw(struct img_fw_context *fw_ctx, enum img_codec codec)
+{
+	if (fw_ctx->populated || fw_ctx->initialized)
+		return IMG_SUCCESS;
+
+	return mtx_populate_fw_ctx(codec, fw_ctx);
+}
+
+static unsigned int H264_RCCONFIG_TABLE_5[27] = {
+	0x00000007, 0x00000006, 0x00000006, 0x00000006, 0x00000006, 0x00000005, 0x00000005,
+	0x00000005, 0x00000005,
+	0x00000005, 0x00000005, 0x00000004, 0x00000004,
+	0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000005,
+	0x00000005, 0x00000005,
+	0x00000005, 0x00000005, 0x00000005, 0x00000006,
+	0x00000006,
+};
+
+static unsigned int H264_RCCONFIG_TABLE_6[27] = {
+	0x00000018, 0x00000018, 0x00000018, 0x00000018, 0x00000018, 0x00000018, 0x00000018,
+	0x00000018, 0x00000024,
+	0x00000030, 0x00000030, 0x0000003c, 0x0000003c,
+	0x00000048, 0x00000048, 0x00000054, 0x00000060, 0x0000006c, 0x000000c8, 0x00000144,
+	0x00000180, 0x00000210,
+	0x000002a0, 0x00000324, 0x0000039c, 0x00000414,
+	0x00000450,
+};
+
+static unsigned int H264_RCCONFIG_TABLE_7[27] = {
+	0x00000014, 0x00000014, 0x00000014, 0x00000014, 0x00000014, 0x00000014, 0x00000032,
+	0x00000064, 0x000000d2,
+	0x000001a4, 0x000001a4, 0x000001bd, 0x000001d6,
+	0x000001ef, 0x00000208, 0x00000217, 0x00000226, 0x0000023a, 0x000002cb, 0x0000035c,
+	0x00000384, 0x000003e8,
+	0x000004b0, 0x00000578, 0x00000640, 0x00000708,
+	0x000007d0,
+};
+
+static unsigned int MPEG_RCCONFIG_TABLE_7[17] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000003c,
+	0x000000b4, 0x0000012c,
+	0x000001a4, 0x0000021c, 0x00000294, 0x0000030c,
+	0x00000384, 0x000003fc, 0x00000474, 0x000004ec,
+};
+
+/*
+ * Load the tables for H.264
+ */
+void comm_load_h264_tables(struct topaz_dev_ctx *ctx)
+{
+	int n;
+	unsigned int pipe, pipe_cnt;
+
+	pipe_cnt = topazdd_get_num_pipes(ctx);
+
+	for (n = 26; n >= 0; n--) {
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_RC_CONFIG_TABLE4, 0);
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_RC_CONFIG_TABLE5,
+			     H264_RCCONFIG_TABLE_5[n]);
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_RC_CONFIG_TABLE6,
+			     H264_RCCONFIG_TABLE_6[n]);
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_RC_CONFIG_TABLE7,
+			     H264_RCCONFIG_TABLE_7[n]);
+	}
+
+	for (pipe = 0; pipe < pipe_cnt; pipe++) {
+		VXE_WR_REG32(ctx->hp_core_reg_addr[pipe], TOPAZHP_CR_RC_CONFIG_REG8, 0x00000006);
+		VXE_WR_REG32(ctx->hp_core_reg_addr[pipe], TOPAZHP_CR_RC_CONFIG_REG9, 0x00000406);
+	}
+}
+
+/*
+ * Load the tables for mpeg4
+ */
+void comm_load_tables(struct topaz_dev_ctx *ctx)
+{
+	int n;
+	unsigned int pipe;
+
+	for (n = 16; n > 0; n--) {
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_RC_CONFIG_TABLE4, 0);
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_RC_CONFIG_TABLE6, 0);
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_RC_CONFIG_TABLE7,
+			     MPEG_RCCONFIG_TABLE_7[n]);
+	}
+
+	for (pipe = 0; pipe < topazdd_get_num_pipes(ctx); pipe++)
+		VXE_WR_REG32(ctx->hp_core_reg_addr[pipe], TOPAZHP_CR_RC_CONFIG_REG8, 0x00000006);
+}
+
+/*
+ * Load bias tables
+ */
+static int comm_load_bias(struct topaz_dev_ctx *ctx, unsigned int codec_mask)
+{
+	if ((codec_mask & CODEC_MASK_H263) || (codec_mask & CODEC_MASK_MPEG2) ||
+	    (codec_mask & CODEC_MASK_MPEG4))
+		comm_load_tables(ctx);
+
+	if ((codec_mask & CODEC_MASK_H264) || (codec_mask & CODEC_MASK_H264MVC))
+		comm_load_h264_tables(ctx);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * Loads MTX firmware
+ */
+void topaz_setup_firmware(struct topaz_dev_ctx *ctx,
+			  struct img_fw_context *fw_ctx,
+			  enum mtx_load_method load_method,
+			  enum img_codec codec, unsigned char num_pipes)
+{
+	unsigned int reg;
+	unsigned int secure_reg;
+	int ret;
+
+	fw_ctx->initialized = FALSE;
+
+	/* Reset the MTXs and Upload the code. */
+	/* start each MTX in turn MUST start with master to enable comms to other cores */
+
+#if SECURE_IO_PORTS
+	/* reset SECURE_CONFIG register to allow loading FW without security.
+	 * Default option is secure.
+	 */
+
+	secure_reg = 0x000F0F0F;
+
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_SECURE_CONFIG, secure_reg);
+#endif
+
+	ret = comm_prepare_fw(fw_ctx, codec);
+
+	if (ret != IMG_SUCCESS) {
+		pr_err("Failed to populate firmware context. Error code: %i\n", ret);
+		return;
+	}
+
+	/* initialise the MTX */
+	mtx_initialize(ctx, fw_ctx);
+
+	/* clear TOHOST register now so that our ISR doesn't see any
+	 * intermediate value before the FW has output anything
+	 */
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_FIRMWARE_REG_1 +
+		     (MTX_SCRATCHREG_TOHOST << 2), 0);
+
+	/* clear BOOTSTATUS register.  Firmware will write to
+	 * this to indicate firmware boot progress
+	 */
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_FIRMWARE_REG_1 +
+		     (MTX_SCRATCHREG_BOOTSTATUS << 2), 0);
+
+	/* Soft reset of MTX */
+	reg = 0;
+	reg = F_ENCODE(1, TOPAZHP_TOP_CR_IMG_TOPAZ_MTX_SOFT_RESET) |
+		       F_ENCODE(1, TOPAZHP_TOP_CR_IMG_TOPAZ_CORE_SOFT_RESET);
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_SRST, reg);
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_SRST, 0x0);
+
+	if (fw_ctx->initialized) {
+		set_auto_clock_gating(ctx, fw_ctx, 1);
+		mtx_load(ctx, fw_ctx, load_method);
+
+		/* flush the command FIFO */
+		reg = 0;
+		reg = F_ENCODE(1, TOPAZHP_TOP_CR_CMD_FIFO_FLUSH);
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_TOPAZ_CMD_FIFO_FLUSH, reg);
+
+		/* we do not want to run in secre FW mode so write a place holder
+		 * to the FIFO that the firmware will know to ignore
+		 */
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_CMD_FIFO_WRITE,
+			     TOPAZHP_NON_SECURE_FW_MARKER);
+
+		/* Clear FW_IDLE_STATUS register */
+		VXE_WR_REG32(ctx->multi_core_mem_addr, MTX_SCRATCHREG_IDLE, 0);
+
+		/* turn on MTX */
+		mtx_start(fw_ctx);
+		/* get MTX Clk Freq */
+
+		mtx_kick(fw_ctx, 1);
+
+		/*
+		 * We do not need to do this POLL here as it is safe to continue without it.
+		 * We do it because it serves to warn us that there is a problem if the
+		 * firmware doesn't start for some reason
+		 */
+		VXE_POLL_REG32_ISEQ(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_FIRMWARE_REG_1 +
+				    (MTX_SCRATCHREG_BOOTSTATUS << 2), TOPAZHP_FW_BOOT_SIGNAL,
+				    0xffffffff, TOPAZ_TIMEOUT_RETRIES);
+	}
+}
+
+static int comm_send(struct img_comm_socket *sock, struct mtx_tomtx_msg *msg, unsigned int *wb_val)
+{
+	struct topaz_dev_ctx *ctx;
+	struct img_fw_context *fw_ctx;
+	unsigned int space_avail;
+	unsigned int cmd_word;
+	unsigned int writeback_val;
+	enum mtx_cmd_id cmd_id = (enum mtx_cmd_id)(msg->cmd_id & 0x7F);
+
+	ctx = sock->ctx;
+	fw_ctx = &ctx->fw_ctx;
+
+	/* mark the context as active in case we need to save its state later */
+	fw_ctx->active_ctx_mask |= (1 << sock->id);
+
+	space_avail = VXE_RD_REG32(ctx->multi_core_mem_addr,
+				   TOPAZHP_TOP_CR_MULTICORE_CMD_FIFO_WRITE_SPACE);
+
+	space_avail = F_DECODE(space_avail, TOPAZHP_TOP_CR_CMD_FIFO_SPACE);
+
+	if (space_avail < 4)
+		return IMG_ERROR_RETRY;
+
+	/* Write command to FIFO */
+	cmd_word = F_ENCODE(sock->id, MTX_MSG_CORE) | msg->cmd_id;
+
+	if (msg->cmd_id & MTX_CMDID_PRIORITY) {
+		/* increment the command counter */
+		sock->high_cmd_cnt++;
+
+		/* Prepare high priority command */
+		cmd_word |= F_ENCODE(1, MTX_MSG_PRIORITY) |
+			F_ENCODE(((sock->low_cmd_cnt - 1) & 0xff) | (sock->high_cmd_cnt << 8),
+				 MTX_MSG_COUNT);
+	} else {
+		/* Prepare low priority command */
+		cmd_word |= F_ENCODE(sock->low_cmd_cnt & 0xff, MTX_MSG_COUNT);
+	}
+
+	/* write command into FIFO */
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_CMD_FIFO_WRITE, cmd_word);
+
+	/* Write data to FIFO */
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_CMD_FIFO_WRITE, msg->data);
+
+	if (msg->command_data_buf) {
+		/* Write address */
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_CMD_FIFO_WRITE,
+			     msg->command_data_buf->dev_virt);
+	} else {
+		/* Write nothing */
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_CMD_FIFO_WRITE, 0);
+	}
+
+	/* Write writeback value to FIFO */
+
+	/* prepare Writeback value */
+
+	/* We don't actually use this value, but it may be useful to customers */
+	if (msg->cmd_id & MTX_CMDID_PRIORITY) {
+		/* HIGH priority command */
+
+		writeback_val = sock->high_cmd_cnt << 24;
+
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_CMD_FIFO_WRITE,
+			     writeback_val);
+	} else {
+		/* LOW priority command */
+		writeback_val = sock->low_cmd_cnt << 16;
+
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_CMD_FIFO_WRITE,
+			     writeback_val);
+
+		/* increment the command counter */
+		sock->low_cmd_cnt++;
+	}
+
+	if (wb_val)
+		*wb_val = writeback_val;
+
+	sock->last_sync = writeback_val;
+
+	switch (cmd_id) {
+	case MTX_CMDID_PROVIDE_CODEDPACKAGE_BUFFER:
+	{
+#ifdef DEBUG_ENCODER_DRIVER
+		unsigned int slot;
+
+		slot = F_DECODE(msg->data, MTX_MSG_PROVIDE_CODEDPACKAGE_BUFFER_SLOT);
+		pr_debug("MSG_TX[%d]: %s(%d) %s %s cmd: %#08x cmd_word: %#08x data: %#08x: addr: 0x%p writeback_val: %#08x\n",
+			 sock->id, command_string[cmd_id], slot,
+			 (msg->cmd_id & MTX_CMDID_PRIORITY ? "(PRIORITY)" : "(NORMAL)"),
+			 (msg->cmd_id & MTX_CMDID_WB_INTERRUPT ? "(Interrupt)" : "(NO Interrupt)"),
+			 (msg->cmd_id), cmd_word, (msg->data), msg->command_data_buf,
+			 writeback_val);
+#endif
+		break;
+	}
+#ifdef ENABLE_PROFILING
+	case MTX_CMDID_ENCODE_FRAME:
+	{
+		struct timespec64 time;
+
+		ktime_get_real_ts64(&time);
+
+		sock->fw_lat.start_time = timespec64_to_ns((const struct timespec64 *)&time);
+	}
+#endif
+	default:
+#ifdef DEBUG_ENCODER_DRIVER
+		pr_debug("MSG_TX[%d]: %s %s %s cmd: %#08x cmd_word: %#08x data: %#08x addr: 0x%p writeback_val: %#08x\n",
+			 sock->id, command_string[cmd_id],
+			 (msg->cmd_id & MTX_CMDID_PRIORITY ? "(PRIORITY)" : "(NORMAL)"),
+			 (msg->cmd_id & MTX_CMDID_WB_INTERRUPT ? "(Interrupt)" : "(NO Interrupt)"),
+			 (msg->cmd_id), cmd_word, (msg->data), msg->command_data_buf,
+			 writeback_val);
+#endif
+		break;
+	}
+#ifdef DEBUG_ENCODER_DRIVER
+	if (msg->command_data_buf) {
+		int i;
+
+		pr_debug("Has msg->command_data_buf cpu_virt=0x%p dev_virt=%#08x\n",
+			 msg->command_data_buf->cpu_virt, msg->command_data_buf->dev_virt);
+
+		for (i = 0; i < 350; i++) {
+			pr_debug("MSG_TX %03d %#08x\n", i,
+				 ((unsigned int *)msg->command_data_buf->cpu_virt)[i]);
+		}
+	}
+#endif
+
+	/* kick the master MTX */
+	mtx_kick(fw_ctx, 1);
+
+	sock->msgs_sent++;
+
+	return IMG_SUCCESS;
+}
+
+int topazdd_send_msg(void *dd_str_ctx, enum mtx_cmd_id cmd_id,
+		     unsigned int data, struct vidio_ddbufinfo *cmd_data_buf,
+		     unsigned int *wb_val)
+{
+	struct mtx_tomtx_msg *msg;
+	struct img_comm_socket *sock;
+	int err;
+
+	if (!dd_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	sock = (struct img_comm_socket *)dd_str_ctx;
+
+	msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+	IMG_DBG_ASSERT(msg);
+	if (!msg)
+		return IMG_ERROR_UNDEFINED;
+
+	msg->command_data_buf = cmd_data_buf;
+	msg->cmd_id = cmd_id;
+	msg->data = data;
+
+	if (!wb_val) {
+		comm_lock(sock->ctx, COMM_LOCK_TX);
+		err = comm_send(sock, msg, NULL);
+		comm_unlock(sock->ctx, COMM_LOCK_TX);
+	} else {
+		unsigned int ret_wb_val;
+
+		comm_lock(sock->ctx, COMM_LOCK_TX);
+		err = comm_send(sock, msg, &ret_wb_val);
+		comm_unlock(sock->ctx, COMM_LOCK_TX);
+
+		if (err == IMG_SUCCESS)
+			*wb_val = ret_wb_val;
+	}
+
+	kfree(msg);
+	return err;
+}
+
+#define WAIT_FOR_SYNC_RETRIES 1200
+#define WAIT_FOR_SYNC_TIMEOUT 1
+
+static int wait_event_obj(void *event, unsigned char uninterruptible, unsigned int timeout)
+{
+	struct event *p_event = (struct event *)event;
+	int ret;
+
+	IMG_DBG_ASSERT(event);
+	if (!event)
+		return IMG_ERROR_GENERIC_FAILURE;
+
+	if (uninterruptible) {
+		if (timeout == (unsigned int)(-1)) {
+			ret = 0;
+			wait_event(event_wait_queue, p_event->signalled);
+		} else {
+			ret = wait_event_timeout(event_wait_queue, p_event->signalled, timeout);
+			if (!ret)
+				return IMG_ERROR_TIMEOUT;
+		}
+	} else {
+		if (timeout == (unsigned int)(-1)) {
+			ret = wait_event_interruptible(event_wait_queue, p_event->signalled);
+		} else {
+			ret = wait_event_interruptible_timeout(event_wait_queue,
+							       p_event->signalled, timeout);
+			if (!ret)
+				return IMG_ERROR_TIMEOUT;
+		}
+	}
+
+	/* If there are signals pending... */
+	if (ret == -ERESTARTSYS)
+		return IMG_ERROR_INTERRUPTED;
+
+	/* If there was no signal...*/
+	IMG_DBG_ASSERT(p_event->signalled);
+
+	/* Clear signal pending...*/
+	p_event->signalled = FALSE;
+
+	return IMG_SUCCESS;
+}
+
+static int topazdd_wait_on_sync(struct img_comm_socket *sock, unsigned int wb_val)
+{
+	unsigned int retries = 0;
+
+	if (!sock)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	while (wait_event_obj(sock->event, TRUE, WAIT_FOR_SYNC_TIMEOUT) != IMG_SUCCESS) {
+		if (retries == WAIT_FOR_SYNC_RETRIES) {
+			/*
+			 * We shouldn't wait any longer than that!
+			 * If the hardware locked up, we will get stuck otherwise.
+			 */
+			pr_err("TIMEOUT: %s timed out waiting for writeback 0x%08x.\n",
+			       __func__, sock->sync_wb_val);
+			return IMG_ERROR_TIMEOUT;
+		}
+
+		msleep(WAIT_FOR_SYNC_TIMEOUT);
+		retries++;
+		continue;
+	}
+
+	return IMG_SUCCESS;
+}
+
+int topazdd_send_msg_with_sync(void *dd_str_ctx, enum mtx_cmd_id cmd_id,
+			       unsigned int data,
+			       struct vidio_ddbufinfo *cmd_data_buf)
+{
+	struct img_comm_socket *sock;
+	unsigned int wb_val = 0;
+
+	if (!dd_str_ctx)
+		return IMG_ERROR_INVALID_CONTEXT;
+
+	sock = (struct img_comm_socket *)dd_str_ctx;
+
+	mutex_lock_nested(sock->sync_wb_mutex, SUBCLASS_TOPAZDD);
+	topazdd_send_msg(dd_str_ctx, cmd_id, data, cmd_data_buf, &wb_val);
+	sock->sync_waiting = TRUE;
+	sock->sync_wb_val = wb_val;
+	mutex_unlock((struct mutex *)sock->sync_wb_mutex);
+
+	return topazdd_wait_on_sync(sock, wb_val);
+}
+
+static void stream_worker(void *work)
+{
+	struct img_comm_socket *sock = NULL;
+	struct img_writeback_msg msg;
+	struct event *p_event;
+
+	work = get_work_buff(work, FALSE);
+	sock = container_of(work, struct img_comm_socket, work);
+
+	while (wbfifo_get(sock, &msg)) {
+		if (F_DECODE(msg.cmd_word, MTX_MSG_MESSAGE_ID) == MTX_MESSAGE_ACK)
+			sock->ack_recv++;
+
+		mutex_lock_nested(sock->sync_wb_mutex, SUBCLASS_TOPAZDD);
+		if (sock->sync_waiting && msg.writeback_val == sock->sync_wb_val) {
+			sock->sync_waiting = FALSE;
+			mutex_unlock((struct mutex *)sock->sync_wb_mutex);
+			/* signal the waiting sync event */
+			p_event = (struct event *)sock->event;
+
+			IMG_DBG_ASSERT(sock->event);
+			if (!sock->event)
+				return;
+
+			p_event->signalled = TRUE;
+			wake_up(&event_wait_queue);
+			return;
+		}
+		mutex_unlock((struct mutex *)sock->sync_wb_mutex);
+
+		if (sock->cb)
+			sock->cb(&msg, sock->str_ctx);
+	}
+}
+
+int topazdd_create_stream_context(struct topaz_dev_ctx *ctx, enum img_codec codec,
+				  enc_cb cb, void *cb_priv,
+	void **dd_str_ctx, struct vidio_ddbufinfo **wb_data_info)
+{
+	struct img_comm_socket *p_sock;
+	struct event *p_event;
+
+	p_sock = kmalloc(sizeof(*p_sock), GFP_KERNEL);
+	IMG_DBG_ASSERT(p_sock);
+	if (!p_sock)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	p_sock->sync_wb_mutex = kzalloc(sizeof(*p_sock->sync_wb_mutex), GFP_KERNEL);
+	if (!p_sock->sync_wb_mutex) {
+		kfree(p_sock);
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+	mutex_init(p_sock->sync_wb_mutex);
+
+	/* Allocate a Sync structure...*/
+	p_event = kmalloc(sizeof(struct event *), GFP_KERNEL);
+	IMG_DBG_ASSERT(p_event);
+	if (!p_event)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	memset(p_event, 0, sizeof(struct event));
+
+	p_sock->event = (void *)p_event;
+
+	if (!p_sock->event) {
+		mutex_destroy(p_sock->sync_wb_mutex);
+		kfree(p_sock->sync_wb_mutex);
+		p_sock->sync_wb_mutex = NULL;
+		kfree(p_sock);
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	p_sock->low_cmd_cnt = 0xa5a5a5a5 %  MAX_TOPAZ_CMD_COUNT;
+	p_sock->high_cmd_cnt = 0;
+	p_sock->msgs_sent = 0;
+	p_sock->ack_recv = 0;
+	p_sock->codec = codec;
+	p_sock->ctx = ctx;
+	p_sock->cb = cb;
+	p_sock->str_ctx = (struct topaz_stream_context *)cb_priv;
+
+	init_work(&p_sock->work, stream_worker, HWA_ENCODER);
+	if (!p_sock->work) {
+		mutex_destroy(p_sock->sync_wb_mutex);
+		kfree(p_sock->sync_wb_mutex);
+		p_sock->sync_wb_mutex = NULL;
+		kfree(p_sock);
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	wbfifo_clear(p_sock);
+
+	*wb_data_info = g_aps_wb_data_info;
+
+	*dd_str_ctx = (void *)p_sock;
+
+#ifdef DEBUG_ENCODER_DRIVE
+	pr_info("topazdd context created with codec %d\n", codec);
+#endif
+
+	return IMG_SUCCESS;
+}
+
+static int topaz_upload_firmware(struct topaz_dev_ctx *ctx, enum img_codec codec)
+{
+#ifdef DEBUG_ENCODER_DRIVE
+	pr_info("Loading firmware.\n");
+#endif
+	/* Upload FW */
+	/* load and start MTX cores */
+	ctx->fw_ctx.load_method = (enum mtx_load_method)g_load_method;
+
+	topaz_setup_firmware(ctx, &ctx->fw_ctx, ctx->fw_ctx.load_method,
+			     codec, topazdd_get_num_pipes(ctx));
+
+	if (!ctx->fw_ctx.initialized) {
+		pr_err("\nERROR: Firmware cannot be loaded!\n");
+		return IMG_ERROR_UNDEFINED;
+	}
+
+	comm_load_bias(ctx, ctx->fw_ctx.supported_codecs);
+	/* initialise read offset of firmware output fifo */
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_FIRMWARE_REG_1 +
+		     (MTX_SCRATCHREG_TOMTX << 2), 0);
+
+	ctx->fw_uploaded = codec;
+
+#ifdef DEBUG_ENCODER_DRIVE
+	pr_info("firmware uploaded!\n");
+#endif
+	return IMG_SUCCESS;
+}
+
+int topazdd_setup_stream_ctx(void *dd_str_ctx, unsigned short height,
+			     unsigned short width, unsigned char *ctx_num,
+			     unsigned int *used_sock)
+{
+	unsigned char idx;
+	struct img_fw_context *fw_ctx;
+	struct img_comm_socket *sock;
+	int res = IMG_ERROR_UNDEFINED;
+	unsigned int codec_mask = 0;
+
+	sock = (struct img_comm_socket *)dd_str_ctx;
+
+	comm_lock(sock->ctx, COMM_LOCK_BOTH);
+
+	fw_ctx = &sock->ctx->fw_ctx;
+
+	switch (sock->codec) {
+	case IMG_CODEC_JPEG:
+		codec_mask = CODEC_MASK_JPEG;
+		break;
+	case IMG_CODEC_H264_NO_RC:
+	case IMG_CODEC_H264_VBR:
+	case IMG_CODEC_H264_CBR:
+	case IMG_CODEC_H264_VCM:
+	case IMG_CODEC_H264_ERC:
+		codec_mask = CODEC_MASK_H264;
+		break;
+	case IMG_CODEC_H263_NO_RC:
+	case IMG_CODEC_H263_VBR:
+	case IMG_CODEC_H263_CBR:
+	case IMG_CODEC_H263_ERC:
+		codec_mask = CODEC_MASK_H263;
+		break;
+	case IMG_CODEC_MPEG4_NO_RC:
+	case IMG_CODEC_MPEG4_VBR:
+	case IMG_CODEC_MPEG4_CBR:
+	case IMG_CODEC_MPEG4_ERC:
+		codec_mask = CODEC_MASK_MPEG4;
+		break;
+	case IMG_CODEC_MPEG2_NO_RC:
+	case IMG_CODEC_MPEG2_VBR:
+	case IMG_CODEC_MPEG2_CBR:
+	case IMG_CODEC_MPEG2_ERC:
+		codec_mask = CODEC_MASK_MPEG2;
+		break;
+
+	case IMG_CODEC_H264MVC_NO_RC:
+	case IMG_CODEC_H264MVC_VBR:
+	case IMG_CODEC_H264MVC_CBR:
+	case IMG_CODEC_H264MVC_ERC:
+		codec_mask = CODEC_MASK_H264MVC;
+		break;
+	default:
+		IMG_DBG_ASSERT("Impossible use case!\n" == NULL);
+		break;
+	}
+	/* Only do the following checks if some other firmware is loaded */
+	if (sock->ctx->fw_uploaded != IMG_CODEC_NONE &&
+	    (sock->ctx->fw_uploaded != sock->codec || /* Different firmware is uploaded */
+		 /* We currently only support one JPEG context to be encoded at the same time */
+	     (sock->ctx->fw_uploaded == IMG_CODEC_JPEG && sock->ctx->used_socks))) {
+		if (!(fw_ctx->supported_codecs & codec_mask)) {
+			comm_unlock(sock->ctx, COMM_LOCK_BOTH);
+			res = IMG_ERROR_UNDEFINED;
+			pr_err("\nERROR: Incompatible firmware context types!. Required codec: 0x%x Loaded FW : 0x%x\n",
+			       codec_mask, fw_ctx->supported_codecs);
+			return res;
+		}
+	}
+
+	if (fw_ctx->initialized && sock->ctx->used_socks >= fw_ctx->num_contexts) {
+		/* the firmware can't support any more contexts */
+		comm_unlock(sock->ctx, COMM_LOCK_BOTH);
+		pr_err("\nERROR: Firmware context limit reached!\n");
+		return IMG_ERROR_UNDEFINED;
+	}
+
+	/* Search for an Available socket. */
+	IMG_DBG_ASSERT(TOPAZHP_MAX_POSSIBLE_STREAMS < (1 << 8));
+	for (idx = 0; idx < TOPAZHP_MAX_POSSIBLE_STREAMS; idx++) {
+		if (!(sock->ctx->socks[idx])) {
+			unsigned int index = idx;
+
+			sock->id = idx;
+			*ctx_num = idx;
+			*used_sock = index;
+			sock->ctx->socks[idx] = sock;
+			sock->ctx->used_socks++;
+			break;
+		}
+	}
+
+	if (idx == TOPAZHP_MAX_POSSIBLE_STREAMS) {
+		comm_unlock(sock->ctx, COMM_LOCK_BOTH);
+		return IMG_ERROR_INVALID_SIZE;
+	}
+
+	if (sock->codec == IMG_CODEC_JPEG) {
+		topaz_timeout_retries = TOPAZ_TIMEOUT_JPEG;
+	} else {
+		unsigned int mbs_per_pic = (height * width) / 256;
+
+		if (topaz_timeout_retries < (mbs_per_pic + 10) * 100)
+			topaz_timeout_retries = (mbs_per_pic + 10) * 100;
+	}
+
+	if (sock->ctx->fw_uploaded == IMG_CODEC_NONE) {
+#ifdef DEBUG_ENCODER_DRIVE
+		pr_info("Loading a different firmware.\n");
+#endif
+		res = topaz_upload_firmware(sock->ctx, (enum img_codec)sock->codec);
+		if (!res) {
+			comm_unlock(sock->ctx, COMM_LOCK_BOTH);
+			res = IMG_ERROR_UNDEFINED;
+			pr_err("\nERROR: Firmware cannot be loaded!\n");
+			return res;
+		}
+	}
+
+	res = IMG_SUCCESS;
+
+	comm_unlock(sock->ctx, COMM_LOCK_BOTH);
+
+	return res;
+}
+
+void topazdd_destroy_stream_ctx(void *dd_str_ctx)
+{
+	unsigned int idx;
+	struct img_comm_socket *sock;
+
+	sock = (struct img_comm_socket *)dd_str_ctx;
+
+	WARN_ON((!sock));
+	if (!sock) {
+		pr_err("topazdd_destroy_sock: invalid sock\n");
+		return;
+	}
+
+	flush_work(sock->work);
+
+	mutex_lock_nested(sock->sync_wb_mutex, SUBCLASS_TOPAZDD);
+	comm_lock(sock->ctx, COMM_LOCK_BOTH);
+	for (idx = 0; idx < TOPAZHP_MAX_POSSIBLE_STREAMS; idx++) {
+		if (sock->ctx->socks[idx] == sock) {
+			sock->ctx->used_socks--;
+			break;
+		}
+	}
+
+#ifdef DEBUG_ENCODER_DRIVE
+	pr_info("topazdd sock context closed\n");
+#endif
+
+	/* Flush the MMU table cache (so it we can't accidentally access
+	 * the freed device memory due to cache/table mismatch.)
+	 */
+	topaz_core_mmu_flush_cache();
+
+	/*
+	 * if nIndex == TOPAZHP_MAX_POSSIBLE_STREAMS then OpenSocket succeeded
+	 * and SetupSocket failed (maybe incompatible firmware)
+	 */
+	if (idx != TOPAZHP_MAX_POSSIBLE_STREAMS) {
+		/*
+		 * Abort the stream first.
+		 * This function can be called as a result of abnormal process
+		 * exit, and since the hardware might be encoding some frame it
+		 * means that the hardware still needs the context resources
+		 * (buffers mapped to the hardware, etc), so we need to make
+		 * sure that hardware encoding is aborted first before releasing
+		 * the resources.
+		 * This is important if you're doing several encodes
+		 * simultaneously because releasing the resources too early will
+		 * cause a page-fault that will halt all simultaneous encodes
+		 * not just the one that caused the page-fault.
+		 */
+		struct mtx_tomtx_msg msg;
+		unsigned int wb_val = 0;
+
+		wbfifo_clear(sock);
+
+		msg.cmd_id = (enum mtx_cmd_id)(MTX_CMDID_ABORT | MTX_CMDID_PRIORITY |
+				MTX_CMDID_WB_INTERRUPT);
+		msg.data = 0;
+		msg.command_data_buf = NULL;
+		comm_send(sock, &msg, &wb_val);
+		sock->sync_waiting = TRUE;
+		sock->sync_wb_val = wb_val;
+		mutex_unlock((struct mutex *)sock->sync_wb_mutex);
+
+		topazdd_wait_on_sync(sock, wb_val);
+		/*
+		 * Set it to NULL here -not any time sooner-, we need it in case
+		 * we had to abort the stream.
+		 */
+		sock->ctx->socks[idx] = NULL;
+	}
+
+	comm_unlock(sock->ctx, COMM_LOCK_BOTH);
+	kfree(sock->event);
+	mutex_destroy(sock->sync_wb_mutex);
+	kfree(sock->sync_wb_mutex);
+	sock->sync_wb_mutex = NULL;
+	kfree(sock->work);
+	kfree(sock);
+}
+
+/*
+ * topazdd_int_clear
+ */
+static void topazdd_int_clear(struct topaz_dev_ctx *ctx, unsigned int mask)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(ctx->lock, flags);
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_INT_CLEAR, mask);
+
+	spin_unlock_irqrestore(ctx->lock, (unsigned long)flags);
+}
+
+unsigned char topazdd_get_pipe_usage(unsigned char pipe)
+{
+	IMG_DBG_ASSERT(pipe < TOPAZHP_MAX_NUM_PIPES);
+	if (pipe >= TOPAZHP_MAX_NUM_PIPES)
+		return 0;
+
+	return g_pipe_usage[pipe];
+}
+
+void topazdd_set_pipe_usage(unsigned char pipe, unsigned char val)
+{
+	IMG_DBG_ASSERT(pipe < TOPAZHP_MAX_NUM_PIPES);
+	if (pipe < TOPAZHP_MAX_NUM_PIPES)
+		g_pipe_usage[pipe] = val;
+}
+
+static unsigned int comm_get_consumer(struct topaz_dev_ctx *ctx)
+{
+	unsigned int reg;
+
+	reg = VXE_RD_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_FIRMWARE_REG_1 +
+			   (MTX_SCRATCHREG_TOMTX << 2));
+
+	return F_DECODE(reg, WB_CONSUMER);
+}
+
+static void comm_set_consumer(struct topaz_dev_ctx *ctx, unsigned int consumer)
+{
+	unsigned int reg;
+
+	reg = VXE_RD_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_FIRMWARE_REG_1 +
+			   (MTX_SCRATCHREG_TOMTX << 2));
+
+	reg = F_INSERT(reg, consumer, WB_CONSUMER);
+
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_FIRMWARE_REG_1 +
+		     (MTX_SCRATCHREG_TOMTX << 2), reg);
+}
+
+static unsigned int comm_get_producer(struct topaz_dev_ctx *ctx)
+{
+	unsigned int reg;
+
+	reg = VXE_RD_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_FIRMWARE_REG_1 +
+			   (MTX_SCRATCHREG_TOHOST << 2));
+
+	return F_DECODE(reg, WB_PRODUCER);
+}
+
+static void comm_set_producer(struct topaz_dev_ctx *ctx, unsigned int producer)
+{
+	unsigned int reg;
+
+	reg = VXE_RD_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_FIRMWARE_REG_1 +
+			   (MTX_SCRATCHREG_TOHOST << 2));
+
+	reg = F_INSERT(reg, producer, WB_PRODUCER);
+
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_FIRMWARE_REG_1 +
+		     (MTX_SCRATCHREG_TOHOST << 2), reg);
+}
+
+static int topazdd_init_comms(struct topaz_dev_ctx *ctx, unsigned int mmu_flags)
+{
+	unsigned int num_cores;
+	unsigned int i;
+	unsigned int reg;
+
+	num_cores = topazdd_get_num_pipes(ctx);
+
+	for (i = 0; i < num_cores; i++) {
+		unsigned int offset = REG_TOPAZHP_CORE_0 + (i * 4);
+
+		ctx->hp_core_reg_addr[i] = (void *)topaz_mem_space[offset].cpu_addr;
+
+		offset = REG_TOPAZHP_VLC_CORE_0 + (i * 4);
+		ctx->vlc_reg_addr[i] = (void *)topaz_mem_space[offset].cpu_addr;
+	}
+
+	if (topaz_mmu_device_create(&ctx->topaz_mmu_ctx, mmu_flags) != IMG_SUCCESS) {
+		pr_err("\nERROR: Could not initialize MMU with selected parameters!\n");
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* Start up MMU support for each core (if MMU is switched on) */
+	reg = (F_ENCODE(1, TOPAZHP_TOP_CR_IMG_TOPAZ_MTX_SOFT_RESET) |
+		F_ENCODE(1, TOPAZHP_TOP_CR_IMG_TOPAZ_CORE_SOFT_RESET) |
+		F_ENCODE(1, TOPAZHP_TOP_CR_IMG_TOPAZ_IO_SOFT_RESET));
+
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_SRST, reg);
+	VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_SRST, 0x0);
+
+	for (i = 0; i < num_cores; i++) {
+		unsigned int reset_bits = F_ENCODE(1, TOPAZHP_CR_TOPAZHP_IPE_SOFT_RESET) |
+			F_ENCODE(1, TOPAZHP_CR_TOPAZHP_SPE_SOFT_RESET) |
+			F_ENCODE(1, TOPAZHP_CR_TOPAZHP_PC_SOFT_RESET) |
+			F_ENCODE(1, TOPAZHP_CR_TOPAZHP_H264COMP_SOFT_RESET) |
+			F_ENCODE(1, TOPAZHP_CR_TOPAZHP_JMCOMP_SOFT_RESET) |
+			F_ENCODE(1, TOPAZHP_CR_TOPAZHP_PREFETCH_SOFT_RESET) |
+			F_ENCODE(1, TOPAZHP_CR_TOPAZHP_VLC_SOFT_RESET) |
+			F_ENCODE(1, TOPAZHP_CR_TOPAZHP_LTRITC_SOFT_RESET) |
+			F_ENCODE(1, TOPAZHP_CR_TOPAZHP_DB_SOFT_RESET);
+
+#ifdef TOPAZHP // TODO: strangely, this doesn't seem defined in the build... but we ARE topazhp...
+		reset_bits |= F_ENCODE(1, MVEA_CR_IMG_MVEA_SPE_SOFT_RESET(1)) |
+			F_ENCODE(1, MVEA_CR_IMG_MVEA_IPE_SOFT_RESET(1));
+#endif
+
+		VXE_WR_REG32(ctx->hp_core_reg_addr[i], TOPAZHP_CR_TOPAZHP_SRST, reset_bits);
+
+		VXE_WR_REG32(ctx->hp_core_reg_addr[i], TOPAZHP_CR_TOPAZHP_SRST, 0);
+	}
+
+	ctx->topaz_mmu_ctx.ptd_phys_addr = ctx->ptd;
+	topaz_core_mmu_hw_setup(&ctx->topaz_mmu_ctx, ctx->multi_core_mem_addr);
+
+	ctx->fw_uploaded = IMG_CODEC_NONE;
+
+	g_core_rev = VXE_RD_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_TOPAZHP_CORE_REV);
+	g_core_rev &=
+		(MASK_TOPAZHP_TOP_CR_TOPAZHP_MAINT_REV | MASK_TOPAZHP_TOP_CR_TOPAZHP_MINOR_REV |
+		MASK_TOPAZHP_TOP_CR_TOPAZHP_MAJOR_REV);
+	g_core_des1 = VXE_RD_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_TOPAZHP_CORE_DES1);
+
+	ctx->comm_tx_mutex = kzalloc(sizeof(*ctx->comm_tx_mutex), GFP_KERNEL);
+	if (!(ctx->comm_tx_mutex))
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	mutex_init(ctx->comm_tx_mutex);
+
+	ctx->comm_rx_mutex = kzalloc(sizeof(*ctx->comm_rx_mutex), GFP_KERNEL);
+	if (!ctx->comm_rx_mutex) {
+		mutex_destroy(ctx->comm_tx_mutex);
+		kfree(ctx->comm_tx_mutex);
+		ctx->comm_tx_mutex = NULL;
+		pr_err("Memory allocation failed for mutex\n");
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+	mutex_init(ctx->comm_rx_mutex);
+
+	g_aps_wb_data_info = kmalloc(sizeof(*g_aps_wb_data_info) * WB_FIFO_SIZE, GFP_KERNEL);
+	if (!g_aps_wb_data_info) {
+		mutex_destroy(ctx->comm_rx_mutex);
+		kfree(ctx->comm_rx_mutex);
+		ctx->comm_rx_mutex = NULL;
+
+		mutex_destroy(ctx->comm_tx_mutex);
+		kfree(ctx->comm_tx_mutex);
+		ctx->comm_tx_mutex = NULL;
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+
+	/* Allocate WB buffers */
+	for (i = 0; i < WB_FIFO_SIZE; i++) {
+		struct vidio_ddbufinfo *mem_info = &g_aps_wb_data_info[i];
+
+		if (topaz_mmu_alloc(ctx->topaz_mmu_ctx.mmu_context_handle,
+				    ctx->vxe_arg, MMU_GENERAL_HEAP_ID, 1,
+			(enum sys_emem_attrib)(SYS_MEMATTRIB_UNCACHED | SYS_MEMATTRIB_WRITECOMBINE),
+			COMM_WB_DATA_BUF_SIZE, 64, mem_info)) {
+			pr_err("mmu_alloc failed!\n");
+			kfree(g_aps_wb_data_info);
+			return IMG_ERROR_OUT_OF_MEMORY;
+		}
+	}
+
+	/* Initialise the COMM registers */
+	comm_set_producer(ctx, 0);
+
+	/* Must reset the Consumer register too,
+	 * otherwise the COMM stack may be initialised incorrectly
+	 */
+	comm_set_consumer(ctx, 0);
+
+	for (i = 0; i < TOPAZHP_MAX_POSSIBLE_STREAMS; i++)
+		ctx->socks[i] = NULL;
+
+	ctx->used_socks = 0;
+	ctx->initialized = TRUE;
+
+	return 0;
+}
+
+static void topazdd_deinit_comms(struct topaz_dev_ctx *ctx)
+{
+	unsigned int idx;
+	struct img_fw_context *fw_ctx;
+
+	fw_ctx = &ctx->fw_ctx;
+
+	if (fw_ctx && fw_ctx->initialized) {
+		/* Stop the MTX */
+		mtx_stop(fw_ctx);
+		mtx_wait_for_completion(fw_ctx);
+	}
+
+	if (g_aps_wb_data_info) {
+		for (idx = 0; idx < WB_FIFO_SIZE; idx++) {
+			struct vidio_ddbufinfo *mem_info = &g_aps_wb_data_info[idx];
+
+			topaz_mmu_free(ctx->vxe_arg, mem_info);
+		}
+		kfree(g_aps_wb_data_info);
+	}
+
+	/* Close all of the opened sockets */
+	for (idx = 0; idx < TOPAZHP_MAX_POSSIBLE_STREAMS; idx++) {
+		if (ctx->socks[idx])
+			topazdd_destroy_stream_ctx(ctx->socks[idx]);
+	}
+
+	mutex_destroy(ctx->comm_tx_mutex);
+	kfree(ctx->comm_tx_mutex);
+	ctx->comm_tx_mutex = NULL;
+
+	mutex_destroy(ctx->comm_rx_mutex);
+	kfree(ctx->comm_rx_mutex);
+	ctx->comm_rx_mutex = NULL;
+
+	if (fw_ctx && fw_ctx->initialized)
+		mtx_deinitialize(fw_ctx);
+
+	topaz_mmu_device_destroy(&ctx->topaz_mmu_ctx);
+
+	ctx->fw_uploaded = IMG_CODEC_NONE;
+	ctx->initialized = FALSE;
+}
+
+static void setup_topaz_mem(unsigned long long reg_base, unsigned int reg_size)
+{
+	unsigned int idx;
+
+	/* set up the kernel virtual address for mem space access */
+	for (idx = 0; idx < topaz_target_config.num_mem_spaces; idx++) {
+		unsigned long long offset = topaz_target_config.mem_spaces[idx].reg.addr;
+
+		topaz_target_config.mem_spaces[idx].cpu_addr = reg_base + offset;
+	}
+}
+
+/*
+ * topazdd_init
+ */
+int topazdd_init(unsigned long long reg_base, unsigned int reg_size, unsigned int mmu_flags,
+		 void *vxe_arg, unsigned int ptd, void **data)
+{
+	struct topaz_dev_ctx *ctx;
+	int ret;
+	spinlock_t **lock; /* spinlock */
+
+	setup_topaz_mem(reg_base, reg_size);
+
+	/* Allocate device structure...*/
+	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	IMG_DBG_ASSERT(ctx);
+	if (!ctx)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	memset(ctx, 0, sizeof(*ctx));
+
+	lock = (spinlock_t **)&ctx->lock;
+	*lock = kzalloc(sizeof(spinlock_t), GFP_KERNEL);
+
+	if (!(*lock)) {
+		pr_err("Memory allocation failed for spin-lock\n");
+		kfree(ctx);
+		return IMG_ERROR_OUT_OF_MEMORY;
+	}
+	spin_lock_init(*lock);
+	g_lock = ctx->lock;
+
+	*data = ctx;
+	ctx->initialized = FALSE;
+
+	ctx->multi_core_mem_addr = (void *)topaz_mem_space[REG_TOPAZHP_MULTICORE].cpu_addr;
+
+	if (!ctx->multi_core_mem_addr) {
+		kfree(&ctx->lock);
+		kfree(ctx);
+		return IMG_ERROR_DEVICE_NOT_FOUND;
+	}
+
+	/* Now enabled interrupts */
+	topazdd_int_enable(ctx, (MASK_TOPAZHP_TOP_CR_HOST_INTEN_MTX |
+		MASK_TOPAZHP_TOP_CR_HOST_TOPAZHP_MAS_INTEN |
+		MASK_TOPAZHP_TOP_CR_HOST_INTEN_MMU_FAULT |
+		MASK_TOPAZHP_TOP_CR_HOST_INTEN_MMU_FAULT_B));
+
+	ctx->vxe_arg = vxe_arg;
+	ctx->ptd = ptd;
+
+	ret = topazdd_init_comms(ctx, mmu_flags);
+	if (ret) {
+		topazdd_int_disable(ctx, ~0);
+		kfree(&ctx->lock);
+		kfree(ctx);
+		return ret;
+	}
+
+	comm_lock(ctx, COMM_LOCK_BOTH);
+	ret = topaz_upload_firmware(ctx, IMG_CODEC_H264_NO_RC);
+	comm_unlock(ctx, COMM_LOCK_BOTH);
+
+	if (ret) {
+		topazdd_deinit_comms(ctx);
+		topazdd_int_disable(ctx, ~0);
+		kfree(&ctx->lock);
+		kfree(ctx);
+		return ret;
+	}
+
+	/* Device now initailised...*/
+	ctx->initialized = TRUE;
+
+	/* Return success...*/
+	return IMG_SUCCESS;
+}
+
+/*
+ * topazdd_deinit
+ */
+void topazdd_deinit(void *data)
+{
+	struct topaz_dev_ctx *ctx = data;
+	unsigned int reg;
+
+	/* If the interrupt was defined then it is also safe to clear interrupts
+	 * and reset the core....
+	 */
+	if (ctx->initialized) {
+		topazdd_deinit_comms(ctx);
+
+		/* Disable interrupts...*/
+		topazdd_int_disable(ctx, ~0);
+
+		/* disable interrupts on Topaz core */
+		reg =
+			VXE_RD_REG32(ctx->multi_core_mem_addr,
+				     TOPAZHP_TOP_CR_MULTICORE_HOST_INT_ENAB);
+
+		reg &= ~MASK_TOPAZHP_TOP_CR_HOST_INTEN_MTX;
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_HOST_INT_ENAB, reg);
+
+		/* clear interrupt - just in case */
+		VXE_WR_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_INT_CLEAR,
+			     MASK_TOPAZHP_TOP_CR_INTCLR_MTX);
+
+		g_lock = NULL;
+		kfree(&ctx->lock);
+	}
+
+	kfree(data);
+}
+
+static int comm_dispatch_in_msg(struct topaz_dev_ctx *ctx)
+{
+	unsigned int hw_fifo_producer;
+	unsigned int hw_fifo_consumer;
+
+	hw_fifo_consumer = comm_get_consumer(ctx);
+	hw_fifo_producer = comm_get_producer(ctx);
+
+	while (hw_fifo_consumer != hw_fifo_producer) {
+		struct img_writeback_msg *wb_msg;
+		unsigned char conn_id;
+		struct vidio_ddbufinfo *mem_info = &g_aps_wb_data_info[hw_fifo_consumer];
+		enum mtx_cmd_id cmd_id;
+
+		/* Update corresponding memory region */
+		topaz_update_host_mem(ctx->vxe_arg, mem_info);
+		wb_msg = (struct img_writeback_msg *)(mem_info->cpu_virt);
+
+		/* Copy to the corresponding SW fifo */
+		conn_id = F_DECODE(wb_msg->cmd_word, MTX_MSG_CORE);
+
+		/* Find corresponding Buffer Addr */
+		cmd_id = (enum mtx_cmd_id)F_DECODE(wb_msg->cmd_word, MTX_MSG_MESSAGE_ID);
+#ifdef DEBUG_ENCODER_DRIVER
+		if ((unsigned int)cmd_id == (unsigned int)MTX_MESSAGE_ACK) {
+			pr_debug("MSG_RX[%d]: 0x%03X %s (ACK) cmd_word: %#08x data: %#08x extra_data: %#08x writeback_val: %#08x\n",
+				 F_DECODE(wb_msg->cmd_word, MTX_MSG_CORE),
+				 hw_fifo_producer & 0x1f,
+				 command_string[wb_msg->cmd_word & 0x1f],
+				 wb_msg->cmd_word, wb_msg->data,
+				 wb_msg->extra_data, wb_msg->writeback_val);
+		} else {
+#ifdef ENABLE_PROFILING
+			struct timespec64 time;
+
+			ktime_get_real_ts64(&time);
+			ctx->socks[conn_id]->fw_lat.end_time =
+				timespec64_to_ns((const struct timespec64 *)&time);
+			pr_err("fw encode time is %llu us for msg_id x%0x\n",
+			       div_s64(ctx->socks[conn_id]->fw_lat.end_time -
+				       ctx->socks[conn_id]->fw_lat.start_time, 1000),
+			       wb_msg->writeback_val);
+#endif
+			pr_debug("MSG_RX[%d]: 0x%03X CODED_BUFFER cmd_word: %#08x coded_package_consumed: %d\n",
+				 F_DECODE(wb_msg->cmd_word, MTX_MSG_CORE),
+				 hw_fifo_producer & 0x1f,
+				 wb_msg->cmd_word,
+				 wb_msg->coded_package_consumed_idx);
+		}
+#endif
+
+		/* If corresponding socket still exists, call the callback */
+		if (ctx->socks[conn_id]) {
+			wbfifo_add(ctx->socks[conn_id], wb_msg);
+			schedule_work(ctx->socks[conn_id]->work);
+		}
+
+		/* Activate corresponding FIFO
+		 * proceed to the next one
+		 */
+		hw_fifo_consumer++;
+
+		if (hw_fifo_consumer == WB_FIFO_SIZE)
+			hw_fifo_consumer = 0;
+
+		comm_set_consumer(ctx, hw_fifo_consumer);
+
+		/*
+		 * We need to update the producer because we might have received a new
+		 * message meanwhile. This new message won't trigger an interrupt and
+		 * consequently will be lost till another message arrives
+		 */
+		hw_fifo_producer = comm_get_producer(ctx);
+	}
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * topazdd_threaded_isr
+ */
+unsigned char topazdd_threaded_isr(void *inst_data)
+{
+	struct topaz_dev_ctx *ctx = *(struct topaz_dev_ctx **)inst_data;
+
+	/* If interrupts not defined then...*/
+	if (!ctx || !ctx->initialized)
+		return FALSE;
+
+	/* Now dispatch the messages */
+	comm_dispatch_in_msg(ctx);
+
+	/* Signal this interrupt has been handled...*/
+	return TRUE;
+}
+
+/*
+ * topazdd_isr
+ */
+irqreturn_t topazdd_isr(void *inst_data)
+{
+	unsigned int reg;
+	unsigned int mmu_fault_mask = MASK_TOPAZHP_TOP_CR_INT_STAT_MMU_FAULT;
+
+	struct topaz_dev_ctx *ctx = *(struct topaz_dev_ctx **)inst_data;
+
+	/* More requesters with topaz hp */
+	mmu_fault_mask |= MASK_TOPAZHP_TOP_CR_INTCLR_MMU_FAULT_B;
+
+	/* If interrupts not defined then...*/
+	if (!ctx || !ctx->initialized)
+		return IRQ_NONE;
+
+	/* read device interrupt status */
+	reg = VXE_RD_REG32(ctx->multi_core_mem_addr, TOPAZHP_TOP_CR_MULTICORE_INT_STAT);
+
+	/* if interrupts enabled and fired...*/
+	if (((reg & MASK_TOPAZHP_TOP_CR_INT_STAT_MTX) == (MASK_TOPAZHP_TOP_CR_INT_STAT_MTX))) {
+		/* Clear interrupt source...*/
+		topazdd_int_clear(ctx, MASK_TOPAZHP_TOP_CR_INTCLR_MTX);
+
+		/* Signal this interrupt has been handled...*/
+		return IRQ_WAKE_THREAD;
+	}
+
+	/* if page fault ever happenned */
+	if (reg & (mmu_fault_mask)) {
+		static unsigned char dump_once = TRUE;
+
+		if (dump_once) {
+			VXE_WR_REG32(ctx->multi_core_mem_addr,
+				     TOPAZHP_TOP_CR_MULTICORE_HOST_INT_ENAB, 0);
+
+			dump_once = FALSE; /* only on first page fault for readability */
+		}
+
+		/* Clear interrupt source...*/
+		topazdd_int_clear(ctx, mmu_fault_mask);
+
+		/* IT served, we might never reach that point on kernel crashes */
+		return IRQ_HANDLED;
+	}
+
+	/* Signal not this device...*/
+	return IRQ_NONE;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/topaz_device.h b/drivers/media/platform/img/vxe-vxd/encoder/topaz_device.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/topaz_device.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/topaz_device.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * topaz driver data strcutures
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#if !defined(__TOPAZ_DEVICE_H__)
+#define __TOPAZ_DEVICE_H__
+
+#include <linux/interrupt.h>
+
+#include "fw_headers/topazscfwif.h"
+#include "fw_headers/mtx_fwif.h"
+#include "topazmmu.h"
+#include "vid_buf.h"
+#include "topaz_api.h"
+
+#       define CODEC_MASK_JPEG          0x0001
+#       define CODEC_MASK_MPEG2         0x0002
+#       define CODEC_MASK_MPEG4         0x0004
+#       define CODEC_MASK_H263          0x0008
+#       define CODEC_MASK_H264          0x0010
+#       define CODEC_MASK_H264MVC       0x0020
+#       define CODEC_MASK_VP8           0x0040
+#       define CODEC_MASK_H265          0x0080
+#       define CODEC_MASK_FAKE          0x007F
+
+struct img_comm_socket;
+
+/*!
+ ****************************************************************************
+ Event object structure
+ ****************************************************************************
+ */
+struct event {
+	unsigned char signalled;
+};
+
+/* prototype for callback for incoming message */
+typedef void (*enc_cb)(struct img_writeback_msg *msg, void *priv);
+
+#ifdef ENABLE_PROFILING
+struct enc_fw_latency {
+	unsigned int start_time;
+	unsigned int end_time;
+};
+#endif
+
+struct mtx_tohost_msg {
+	enum mtx_message_id cmd_id;
+	unsigned int input_cmd_word;
+	unsigned char coded_pkg_idx;
+	unsigned int wb_val;
+	unsigned int data;
+	struct vidio_ddbufinfo *command_data_buf;
+};
+
+struct mtx_tomtx_msg {
+	enum mtx_cmd_id cmd_id;
+	unsigned int data;
+	struct vidio_ddbufinfo *command_data_buf;
+};
+
+/*
+ * This structure contains the device context.
+ */
+struct topaz_dev_ctx {
+	/* Parent context, needed to pass to mmu_alloc */
+	void *vxe_arg;
+
+	/* KM addresses for mem spaces */
+	void *multi_core_mem_addr;
+	void *hp_core_reg_addr[TOPAZHP_MAX_NUM_PIPES];
+	void *vlc_reg_addr[TOPAZHP_MAX_NUM_PIPES];
+
+	unsigned char initialized; /*!< Indicates that the device driver has been initialised */
+
+	unsigned int used_socks;
+	struct img_comm_socket *socks[TOPAZHP_MAX_POSSIBLE_STREAMS];
+
+	unsigned int fw_uploaded;
+	struct img_fw_context fw_ctx;
+
+	void *lock; /* basic device level spinlock */
+	struct mutex *comm_tx_mutex;
+	struct mutex *comm_rx_mutex;
+
+	unsigned int ptd;
+	struct topaz_mmu_context topaz_mmu_ctx;
+};
+
+#define COMM_INCOMING_FIFO_SIZE (WB_FIFO_SIZE * 2)
+struct img_comm_socket {
+	unsigned char id;
+	unsigned int low_cmd_cnt;   /* count of low-priority commands sent to TOPAZ */
+	unsigned int high_cmd_cnt;  /* count of high-priority commands sent to TOPAZ */
+	unsigned int last_sync;     /* Last sync value sent */
+	struct  img_writeback_msg in_fifo[COMM_INCOMING_FIFO_SIZE];
+	unsigned int in_fifo_consumer;
+	unsigned int in_fifo_producer;
+	void *work;
+
+	enc_cb cb;                            /* User-provided callback function */
+	struct topaz_stream_context *str_ctx; /* User-provided callback data */
+
+	void *event;
+	unsigned char sync_waiting;
+	unsigned int sync_wb_val;
+	struct mutex *sync_wb_mutex;
+
+	unsigned int msgs_sent;
+	unsigned int ack_recv;
+	unsigned char is_serialized;
+
+	unsigned int codec;
+
+	struct topaz_dev_ctx *ctx;
+#ifdef ENABLE_PROFILING
+	struct enc_fw_latency fw_lat;
+#endif
+};
+
+unsigned char topazdd_threaded_isr(void *data);
+irqreturn_t topazdd_isr(void *data);
+
+int topazdd_init(unsigned long long reg_base, unsigned int reg_size,
+		 unsigned int mmu_flags,
+		 void *vxe_arg, unsigned int ptd, void **data);
+void topazdd_deinit(void *data);
+unsigned int topazdd_get_num_pipes(struct topaz_dev_ctx *ctx);
+unsigned int topazdd_get_core_rev(void);
+unsigned int topazdd_get_core_des1(void);
+unsigned char topazdd_is_idle(struct img_comm_socket *sock);
+
+int topazdd_upload_firmware(struct topaz_dev_ctx *ctx, enum img_codec codec);
+int topazdd_create_stream_context(struct topaz_dev_ctx *ctx, enum img_codec codec, enc_cb cb,
+				  void *cb_priv, void **dd_str_ctx,
+				  struct vidio_ddbufinfo **wb_data_info);
+void topazdd_destroy_stream_ctx(void *dd_str_ctx);
+int topazdd_setup_stream_ctx(void *dd_str_ctx, unsigned short height,
+			     unsigned short width, unsigned char *ctx_num,
+			     unsigned int *used_sock);
+int topazdd_send_msg(void *dd_str_ctx, enum mtx_cmd_id cmd_id,
+		     unsigned int data, struct vidio_ddbufinfo *cmd_data_buf,
+		     unsigned int *wb_val);
+int topazdd_send_msg_with_sync(void *dd_str_ctx, enum mtx_cmd_id cmd_id,
+			       unsigned int data,
+			       struct vidio_ddbufinfo *cmd_data_buf);
+
+extern unsigned int mmu_control_val;
+
+#endif /* __TOPAZ_DEVICE_H__	*/
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/topazmmu.c b/drivers/media/platform/img/vxe-vxd/encoder/topazmmu.c
--- a/drivers/media/platform/img/vxe-vxd/encoder/topazmmu.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/topazmmu.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,741 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * topaz mmu function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <linux/types.h>
+
+#include "fw_headers/defs.h"
+#include "img_errors.h"
+#include "img_mem.h"
+#include "img_mem_man.h"
+#include "talmmu_api.h"
+#include "topazmmu.h"
+#include "vxe_public_regdefs.h"
+
+int use_extended_addressing;
+unsigned int mmu_control_val;
+unsigned char device_initialized = FALSE;
+
+/*
+ * These determine the sizes of the MMU heaps we are using.
+ * The tiled heap is set arbitrarily large at present.
+ */
+#define GENERALMMUHEAPLENGTH 0x40000000
+
+/*
+ * This describes the heaps - the separate areas mapped by the MMU
+ * Currently we only use a single large heap as Topaz Core has no
+ * MMU specific memory features.
+ */
+struct talmmu_heap_info mmu_heap_info[HEAP_ID_NO_OF_HEAPS] = {
+	{ MMU_GENERAL_HEAP_ID, TALMMU_HEAP_PERCONTEXT, TALMMU_HEAPFLAGS_NONE, "MEMSYSMEM",
+	  0x00400000, GENERALMMUHEAPLENGTH }
+};
+
+/* This describes the memory being mapped by the MMU */
+struct talmmu_devmem_info mmu_device_memory_info = {
+	/* ui32DeviceId */
+	1,
+	/* eMMUType */
+	TALMMU_MMUTYPE_4K_PAGES_32BIT_ADDR,
+	/* eDevFlags */
+	TALMMU_DEVFLAGS_NONE,
+	/* pszPageDirMemSpaceName */
+	"MEMSYSMEM",
+	/* pszPageTableMemSpaceName */
+	"MEMSYSMEM",
+	/* ui32PageSize */
+	4096,
+	/* ui32PageTableDirAlignment */
+	0
+};
+
+/*
+ * mmu template is global. so we don't need to worry about maintaining device
+ * context
+ */
+void *mmu_template;
+
+/*
+ * Stream context is global. Can be modified in future to handle list of streams.
+ */
+struct mmu_str_context *str_ctx;
+
+/*
+ * Called once during initialization to initialize the MMU hardware, create
+ * the template and define the MMU heap.
+ * This is where talmmu initialization and template will be created.
+ *
+ * NOTE : We are not taking care of alignment here, need to be updated in
+ * mmu_device_memory_info.
+ */
+int topaz_mmu_device_create(struct topaz_mmu_context *mmu_context, unsigned int mmu_flags)
+{
+	void *topaz_multi_core_regid;
+	unsigned int hw_rev;
+	int result, i;
+
+	use_extended_addressing = (mmu_flags & MMU_EXTENDED_ADDR_FLAG);
+
+	/* Initialize TALMMU API and create a template */
+	result = talmmu_init();
+	IMG_DBG_ASSERT(result == 0);
+
+	if (result != 0) {
+		pr_err("talmmu_init failed!\n");
+		return IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+	}
+
+	/*
+	 * We are reading the register and finding the mmu type, if needed this
+	 * can be passed from the upper layers directly.
+	 */
+
+	topaz_multi_core_regid = (void *)topaz_mem_space[REG_TOPAZHP_MULTICORE].cpu_addr;
+
+	hw_rev = VXE_RD_REG32(topaz_multi_core_regid, TOPAZHP_TOP_CR_TOPAZHP_CORE_REV);
+	hw_rev &=
+		(MASK_TOPAZHP_TOP_CR_TOPAZHP_MAINT_REV | MASK_TOPAZHP_TOP_CR_TOPAZHP_MINOR_REV |
+		MASK_TOPAZHP_TOP_CR_TOPAZHP_MAJOR_REV);
+
+	if (use_extended_addressing) {
+		unsigned int reg_val;
+
+		/* Versions 3.6 and above may be 32-bit, 36-bit or 40-bit */
+		reg_val = VXE_RD_REG32(topaz_multi_core_regid, TOPAZHP_TOP_CR_MULTICORE_HW_CFG);
+
+		switch (F_DECODE(reg_val, TOPAZHP_TOP_CR_EXTENDED_ADDR_RANGE)) {
+		case 0:
+			mmu_device_memory_info.mmu_type = TALMMU_MMUTYPE_4K_PAGES_32BIT_ADDR;
+			break;
+		case 4:
+			mmu_device_memory_info.mmu_type = TALMMU_MMUTYPE_4K_PAGES_36BIT_ADDR;
+			break;
+		case 8:
+			mmu_device_memory_info.mmu_type = TALMMU_MMUTYPE_4K_PAGES_40BIT_ADDR;
+			break;
+		default:
+			pr_err("Unsupported MMU mode requested\n");
+			return IMG_ERROR_NOT_SUPPORTED;
+		}
+	}
+
+	result = talmmu_devmem_template_create(&mmu_device_memory_info, &mmu_template);
+	IMG_DBG_ASSERT(result == 0);
+	if (result != 0) {
+		pr_err("talmmu_devmem_template_create failed!\n");
+		talmmu_deinit();
+		return IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+	}
+
+	/* Add heaps to the template */
+	for (i = 0; i < HEAP_ID_NO_OF_HEAPS; i++) {
+		result = talmmu_devmem_heap_add(mmu_template, &mmu_heap_info[i]);
+		IMG_DBG_ASSERT(result == 0);
+		if (result != 0) {
+			pr_err("talmmu_devmem_heap_add failed!\n");
+			talmmu_devmem_template_destroy(mmu_template);
+			talmmu_deinit();
+			return IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+		}
+	}
+
+	/* Create a context from the template */
+	/* (Template, User allocated user ID) */
+	result = talmmu_devmem_ctx_create(mmu_template, 1, &mmu_context->mmu_context_handle);
+	IMG_DBG_ASSERT(result == 0);
+	if (result != 0) {
+		pr_err("talmmu_devmem_ctx_create failed!\n");
+		talmmu_devmem_template_destroy(mmu_template);
+		talmmu_deinit();
+		return IMG_ERROR_COULD_NOT_OBTAIN_RESOURCE;
+	}
+
+	topaz_core_mmu_flush_cache();
+
+	/* Initialise stream list. */
+	lst_init(&mmu_context->str_list);
+
+	device_initialized = TRUE;
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * This function is used to destroy the MMU device context.
+ * NOTE: Destroy device automatically destroys any streams and frees and
+ * memory allocated using MMU_StreamMalloc().
+ */
+int topaz_mmu_device_destroy(struct topaz_mmu_context *mmu_context)
+{
+	unsigned int result = 0;
+	struct mmu_str_context *str_ctx;
+
+	/* Destroy all streams associated with the device. */
+	str_ctx = lst_first(&mmu_context->str_list);
+	while (str_ctx) {
+		/* remove stream to list. */
+		lst_remove(&mmu_context->str_list, str_ctx);
+		topaz_mmu_stream_destroy(mmu_context, str_ctx);
+
+		/* See if there are more streams. */
+		str_ctx = lst_first(&mmu_context->str_list);
+	}
+
+	/* Destroy the device context */
+	result = talmmu_devmem_ctx_destroy(mmu_context->mmu_context_handle);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Destroy the template. */
+	return talmmu_devmem_template_destroy(mmu_template);
+}
+
+/*
+ * This function is used to create and initialize the MMU stream context.
+ */
+int topaz_mmu_stream_create(struct topaz_mmu_context *mmu_context, unsigned int km_str_id,
+			    void *vxe_enc_ctx_arg, void **mmu_str_ctx)
+{
+	struct mmu_str_context *str_ctx;
+
+	/* Validate inputs. */
+	if (!device_initialized)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Allocate a stream context structure */
+	str_ctx = kzalloc(sizeof(*str_ctx), GFP_KERNEL);
+	if (!str_ctx)
+		return IMG_ERROR_OUT_OF_MEMORY;
+
+	str_ctx->km_str_id = km_str_id;
+	str_ctx->int_reg_num = 32;
+	str_ctx->vxe_enc_context = (struct vxe_enc_ctx *)vxe_enc_ctx_arg;
+
+	/* copy the mmu context created earlier */
+	str_ctx->mmu_context_handle = mmu_context->mmu_context_handle;
+
+	*mmu_str_ctx = str_ctx;
+
+	/* Add stream to list. */
+	lst_add(&mmu_context->str_list, str_ctx);
+
+	return IMG_SUCCESS;
+}
+
+/*
+ * This function is used to destroy the MMU stream context.
+ * NOTE: Destroy automatically frees and memory allocated using
+ *	mmu_stream_malloc().
+ */
+int topaz_mmu_stream_destroy(struct topaz_mmu_context *mmu_context,
+			     struct mmu_str_context *str_ctx)
+{
+	/* Validate inputs. */
+	if (!str_ctx)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* remove stream to list. */
+	lst_remove(&mmu_context->str_list, str_ctx);
+
+	kfree(str_ctx);
+
+	return IMG_SUCCESS;
+}
+
+static unsigned int set_attributes(enum sys_emem_attrib mem_attrib)
+{
+	unsigned int attrib = 0;
+
+	if (mem_attrib & SYS_MEMATTRIB_CACHED)
+		attrib |= MEM_ATTR_CACHED;
+
+	if (mem_attrib & SYS_MEMATTRIB_UNCACHED)
+		attrib |= MEM_ATTR_UNCACHED;
+
+	if (mem_attrib & SYS_MEMATTRIB_WRITECOMBINE)
+		attrib |= MEM_ATTR_WRITECOMBINE;
+
+	if (mem_attrib & SYS_MEMATTRIB_SECURE)
+		attrib |= MEM_ATTR_SECURE;
+
+	return attrib;
+}
+
+int topaz_mmu_alloc(void *mmu_context_handle, struct vxe_enc_ctx *vxe_enc_ctx_arg,
+		    enum topaz_mmu_eheap_id heap_id, unsigned int mem_heap_id,
+		    enum sys_emem_attrib mem_attrib,  unsigned int size, unsigned int alignment,
+		    struct vidio_ddbufinfo *ddbuf_info)
+{
+	int result = 0;
+	void *devmem_heap_hndl;
+	struct vxe_enc_ctx *ctx;
+	struct vxe_dev *vxe;
+	unsigned int flags = 0;
+	unsigned int attributes = 0;
+
+	if (!mmu_context_handle)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Set buffer size. */
+	ddbuf_info->buf_size = size;
+
+	/* Round size up to next multiple of physical pages */
+	if ((size % HOST_MMU_PAGE_SIZE) != 0)
+		size = ((size / HOST_MMU_PAGE_SIZE) + 1) * HOST_MMU_PAGE_SIZE;
+
+	/* Allocate memory */
+	ctx = vxe_enc_ctx_arg;
+	vxe = ctx->dev;
+
+	attributes = set_attributes(mem_attrib);
+
+	result = img_mem_alloc(vxe->dev, ctx->mem_ctx, mem_heap_id,
+			       size, (enum mem_attr)attributes, (int *)&ddbuf_info->buff_id);
+	if (result != IMG_SUCCESS)
+		goto error_alloc;
+
+	ddbuf_info->is_internal = 1;
+
+	/* TODO need to check more on attributes from memmgr_km */
+	if (mem_attrib & SYS_MEMATTRIB_SECURE) {
+		ddbuf_info->cpu_virt = NULL;
+	} else {
+		/* Map the buffer to CPU */
+		result = img_mem_map_km(ctx->mem_ctx, ddbuf_info->buff_id);
+		if (result) {
+			dev_err(vxe->dev, "%s: failed to map buf to cpu!(%d)\n",
+				__func__, result);
+			goto error_get_heap_handle;
+		}
+		ddbuf_info->cpu_virt = img_mem_get_kptr(ctx->mem_ctx, ddbuf_info->buff_id);
+	}
+
+	/* Get heap handle */
+	result = talmmu_get_heap_handle(heap_id, mmu_context_handle, &devmem_heap_hndl);
+	if (result != IMG_SUCCESS)
+		goto error_get_heap_handle;
+
+	/* Allocate device "virtual" memory. */
+	result = talmmu_devmem_addr_alloc(mmu_context_handle, devmem_heap_hndl,
+					  size, alignment, &ddbuf_info->hndl_memory);
+	if (result != IMG_SUCCESS)
+		goto error_mem_map_ext_mem;
+
+	/* Get the device virtual address. */
+	result = talmmu_get_dev_virt_addr(ddbuf_info->hndl_memory, &ddbuf_info->dev_virt);
+	if (result != IMG_SUCCESS)
+		goto error_get_dev_virt_addr;
+
+	result = img_mmu_map(ctx->mmu_ctx, ctx->mem_ctx, ddbuf_info->buff_id, ddbuf_info->dev_virt,
+			     flags);
+	if (result != IMG_SUCCESS)
+		goto error_map_dev;
+
+	return IMG_SUCCESS;
+
+error_map_dev:
+error_get_dev_virt_addr:
+	talmmu_devmem_addr_free(ddbuf_info->hndl_memory);
+	ddbuf_info->hndl_memory = NULL;
+error_mem_map_ext_mem:
+error_get_heap_handle:
+	img_mem_free(ctx->mem_ctx, ddbuf_info->buff_id);
+error_alloc:
+	return result;
+}
+
+/*
+ * mmu_stream_malloc
+ */
+int topaz_mmu_stream_alloc(void *mmu_str_hndl, enum topaz_mmu_eheap_id heap_id,
+			   unsigned int mem_heap_id, enum sys_emem_attrib mem_attrib,
+			   unsigned int size, unsigned int alignment,
+			   struct vidio_ddbufinfo *ddbuf_info)
+{
+	struct mmu_str_context *str_ctx;
+
+	/* Validate inputs. */
+	if (!mmu_str_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	str_ctx = (struct mmu_str_context *)mmu_str_hndl;
+
+	/* Check if device level heap. */
+	switch (heap_id) {
+	case MMU_GENERAL_HEAP_ID:
+		break;
+
+	default:
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	ddbuf_info->kmstr_id = str_ctx->km_str_id;
+
+	/* Allocate device memory. */
+	return (topaz_mmu_alloc(str_ctx->mmu_context_handle, str_ctx->vxe_enc_context,
+				heap_id, mem_heap_id, mem_attrib, size, alignment, ddbuf_info));
+}
+
+/*
+ * mmu_stream_map_ext_sg
+ */
+int topaz_mmu_stream_map_ext_sg(void *mmu_str_hndl, enum topaz_mmu_eheap_id heap_id,
+				void *sgt, unsigned int size, unsigned int alignment,
+				enum sys_emem_attrib mem_attrib, void *cpu_linear_addr,
+				struct vidio_ddbufinfo *ddbuf_info, unsigned int *buff_id)
+{
+	int result;
+	void *devmem_heap_hndl;
+	struct mmu_str_context *str_ctx;
+	struct vxe_enc_ctx *ctx;
+	struct vxe_dev *vxe;
+
+	if (!mmu_str_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	str_ctx = (struct mmu_str_context *)mmu_str_hndl;
+
+	ctx = str_ctx->vxe_enc_context;
+	vxe = ctx->dev;
+
+	/* Check if device level heap. */
+	switch (heap_id) {
+	case MMU_GENERAL_HEAP_ID:
+		break;
+
+	default:
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	if (!str_ctx->mmu_context_handle)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Set buffer size. */
+	ddbuf_info->buf_size = size;
+
+	/* Round size up to next multiple of physical pages */
+	if ((size % HOST_MMU_PAGE_SIZE) != 0)
+		size = ((size / HOST_MMU_PAGE_SIZE) + 1) * HOST_MMU_PAGE_SIZE;
+
+	result = img_mem_import(vxe->dev, ctx->mem_ctx, ddbuf_info->buf_size,
+				(enum mem_attr)set_attributes(mem_attrib), (int *)buff_id);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	if (mem_attrib & SYS_MEMATTRIB_SECURE)
+		ddbuf_info->cpu_virt = NULL;
+
+	ddbuf_info->buff_id = *buff_id;
+	ddbuf_info->is_internal = 0;
+
+	ddbuf_info->kmstr_id = str_ctx->km_str_id;
+
+	/* Set buffer size. */
+	ddbuf_info->buf_size = size;
+
+	/* Ensure the address of the buffer is at least page aligned. */
+	ddbuf_info->cpu_virt = cpu_linear_addr;
+
+	/* Get heap handle */
+	result = talmmu_get_heap_handle(heap_id, str_ctx->mmu_context_handle, &devmem_heap_hndl);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Allocate device "virtual" memory. */
+	result = talmmu_devmem_addr_alloc(str_ctx->mmu_context_handle, devmem_heap_hndl,
+					  size, alignment, &ddbuf_info->hndl_memory);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Get the device virtual address. */
+	result = talmmu_get_dev_virt_addr(ddbuf_info->hndl_memory, &ddbuf_info->dev_virt);
+	if (result != IMG_SUCCESS)
+		goto error_get_dev_virt_addr;
+
+	result = img_mmu_map_sg(ctx->mmu_ctx, ctx->mem_ctx, ddbuf_info->buff_id, sgt,
+				ddbuf_info->dev_virt, mem_attrib);
+	if (result != IMG_SUCCESS)
+		goto error_map_dev;
+
+	return IMG_SUCCESS;
+
+error_map_dev:
+error_get_dev_virt_addr:
+	talmmu_devmem_addr_free(ddbuf_info->hndl_memory);
+	ddbuf_info->hndl_memory = NULL;
+	return result;
+}
+
+/*
+ * topaz_mmu_stream_map_ext
+ */
+int topaz_mmu_stream_map_ext(void *mmu_str_hndl, enum topaz_mmu_eheap_id heap_id,
+			     unsigned int buff_id, unsigned int size, unsigned int alignment,
+			     enum sys_emem_attrib mem_attrib, void *cpu_linear_addr,
+			     struct vidio_ddbufinfo *ddbuf_info)
+{
+	int result = 0;
+	void *devmem_heap_hndl;
+	struct vxe_enc_ctx *ctx;
+	struct mmu_str_context *str_ctx;
+
+	if (!mmu_str_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	str_ctx = (struct mmu_str_context *)mmu_str_hndl;
+
+	/* Check if device level heap. */
+	switch (heap_id) {
+	case MMU_GENERAL_HEAP_ID:
+		break;
+
+	default:
+		return IMG_ERROR_INVALID_PARAMETERS;
+	}
+
+	/* Round size up to next multiple of physical pages */
+	if ((size % HOST_MMU_PAGE_SIZE) != 0)
+		size = ((size / HOST_MMU_PAGE_SIZE) + 1) * HOST_MMU_PAGE_SIZE;
+
+	ddbuf_info->buff_id = buff_id;
+	ddbuf_info->is_internal = 0;
+
+	ddbuf_info->kmstr_id = str_ctx->km_str_id;
+
+	/* Set buffer size. */
+	ddbuf_info->buf_size = size;
+
+	/* Ensure the address of the buffer is at least page aligned. */
+	ddbuf_info->cpu_virt = cpu_linear_addr;
+
+	/* Get heap handle */
+	result = talmmu_get_heap_handle(heap_id, str_ctx->mmu_context_handle,
+					&devmem_heap_hndl);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Allocate device "virtual" memory. */
+	result = talmmu_devmem_addr_alloc(str_ctx->mmu_context_handle,
+					  devmem_heap_hndl, size, alignment,
+					  &ddbuf_info->hndl_memory);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/* Get the device virtual address. */
+	result = talmmu_get_dev_virt_addr(ddbuf_info->hndl_memory, &ddbuf_info->dev_virt);
+	if (result != IMG_SUCCESS)
+		return result;
+
+	/*
+	 * Map device memory (allocated from outside VDEC)
+	 * into the stream PTD.
+	 */
+	ctx = str_ctx->vxe_enc_context;
+
+	return img_mmu_map(ctx->mmu_ctx, ctx->mem_ctx, ddbuf_info->buff_id, ddbuf_info->dev_virt,
+		       mem_attrib);
+}
+
+/*
+ * topaz_mmu_free
+ */
+int topaz_mmu_free(struct vxe_enc_ctx *vxe_enc_ctx_arg, struct vidio_ddbufinfo *ddbuf_info)
+{
+	int result = 0;
+	struct vxe_enc_ctx *ctx;
+
+	/* Validate inputs. */
+	if (!ddbuf_info)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	/* Unmap the memory mapped to the device */
+	ctx = vxe_enc_ctx_arg;
+	result = img_mmu_unmap(ctx->mmu_ctx, ctx->mem_ctx, ddbuf_info->buff_id);
+
+	/*
+	 * Unmapping the memory mapped to the device - done
+	 * Free the memory.
+	 */
+	result = talmmu_devmem_addr_free(ddbuf_info->hndl_memory);
+
+	if (ddbuf_info->is_internal)
+		img_mem_free(ctx->mem_ctx, ddbuf_info->buff_id);
+
+	return result;
+}
+
+/*
+ * topaz_mmu_free_mem.
+ * This should be used only to free the stream memory.
+ */
+int topaz_mmu_stream_free(void *mmu_str_hndl, struct vidio_ddbufinfo *ddbuf_info)
+{
+	struct mmu_str_context *str_ctx;
+
+	if (!mmu_str_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	str_ctx = (struct mmu_str_context *)mmu_str_hndl;
+
+	return topaz_mmu_free(str_ctx->vxe_enc_context, ddbuf_info);
+}
+
+/*
+ * topaz_mmu_free_mem_sg.
+ * This should be used only to free the stream memory.
+ */
+int topaz_mmu_stream_free_sg(void *mmu_str_hndl, struct vidio_ddbufinfo *ddbuf_info)
+{
+	int result = 0;
+	struct vxe_enc_ctx *ctx;
+	struct mmu_str_context *str_ctx;
+
+	/* Validate inputs. */
+	if (!ddbuf_info || !mmu_str_hndl)
+		return IMG_ERROR_INVALID_PARAMETERS;
+
+	str_ctx = (struct mmu_str_context *)mmu_str_hndl;
+
+	/* Unmap the memory mapped to the device */
+	ctx = str_ctx->vxe_enc_context;
+
+	result = img_mmu_unmap(ctx->mmu_ctx, ctx->mem_ctx, ddbuf_info->buff_id);
+
+	/*
+	 * Unmapping the memory mapped to the device - done
+	 * Free the memory.
+	 */
+	result = talmmu_devmem_addr_free(ddbuf_info->hndl_memory);
+
+	/*
+	 * for external mem manager buffers, just cleanup the idr list and
+	 * buffer objects
+	 */
+	img_mem_free_bufid(ctx->mem_ctx, ddbuf_info->buff_id);
+
+	return result;
+}
+
+int topaz_update_device_mem(struct vxe_enc_ctx *vxe_enc_ctx_arg,
+			    struct vidio_ddbufinfo *ddbuf_info)
+{
+	struct vxe_enc_ctx *ctx = vxe_enc_ctx_arg;
+
+	return img_mem_sync_cpu_to_device(ctx->mem_ctx,
+		       ddbuf_info->buff_id);
+}
+
+int topaz_update_host_mem(struct vxe_enc_ctx *vxe_enc_ctx_arg,
+			  struct vidio_ddbufinfo *ddbuf_info)
+{
+	struct vxe_enc_ctx *ctx = vxe_enc_ctx_arg;
+
+	return img_mem_sync_device_to_cpu(ctx->mem_ctx,
+		       ddbuf_info->buff_id);
+}
+
+/*
+ * Called for each Topaz core when MMU support is activated, sets up the MMU
+ * hardware for the specified core.
+ */
+int topaz_core_mmu_hw_setup(struct topaz_mmu_context *mmu_context, void *core_reg)
+{
+	unsigned int cmd;
+
+	/* Bypass all requesters while MMU is being configured */
+	cmd = F_ENCODE(1, TOPAZHP_TOP_CR_MMU_BYPASS_TOPAZ);
+	VXE_WR_REG32(core_reg, TOPAZHP_TOP_CR_MMU_CONTROL0, cmd);
+
+	VXE_WR_REG32(core_reg, TOPAZHP_TOP_CR_MMU_DIR_LIST_BASE(0), mmu_context->ptd_phys_addr);
+
+	cmd = VXE_RD_REG32(core_reg, TOPAZHP_TOP_CR_MMU_DIR_LIST_BASE(0));
+
+#ifdef DEBUG_ENCODER_DRIVER
+	pr_info("Page table directory at physical address 0x%08x\n", cmd);
+#endif
+	/*
+	 * Set up the Index Register (to point to the base register)
+	 * We're setting all fields to zero (all flags pointing to directory bank 0)
+	 */
+	cmd = 0;
+
+	/*  Now enable MMU access for all requesters
+	 * 36-bit actually means "not 32-bit"
+	 */
+	cmd = F_ENCODE(use_extended_addressing ? 1 : 0, TOPAZHP_TOP_CR_MMU_ENABLE_36BIT_ADDRESSING);
+	VXE_WR_REG32(core_reg, TOPAZHP_TOP_CR_MMU_CONTROL2, cmd);
+
+	mmu_control_val = F_ENCODE(0, TOPAZHP_TOP_CR_MMU_BYPASS_TOPAZ);
+	cmd = F_ENCODE(0, TOPAZHP_TOP_CR_MMU_BYPASS_TOPAZ);
+
+	VXE_WR_REG32(core_reg, TOPAZHP_TOP_CR_MMU_CONTROL0, cmd);
+
+	return 0;
+}
+
+/*
+ * topaz_core_mmu_flush_cache
+ */
+int topaz_core_mmu_flush_cache(void)
+{
+	static void  *core_reg;
+	unsigned int reg_value;
+	unsigned long flags;
+
+	if (!core_reg)
+		core_reg = (void *)topaz_mem_space[REG_TOPAZHP_MULTICORE].cpu_addr;
+
+	/* TODO we can have global mutex or local based on need */
+	spin_lock_irqsave(g_lock, flags);
+
+	reg_value = VXE_RD_REG32(core_reg, TOPAZHP_TOP_CR_MMU_CONTROL0);
+
+	/* PAUSE */
+	reg_value |= F_ENCODE(1, TOPAZHP_TOP_CR_MMU_PAUSE);
+	VXE_WR_REG32(core_reg, TOPAZHP_TOP_CR_MMU_CONTROL0, reg_value);
+
+	{
+		unsigned int i, mem_req_reg;
+
+wait_till_idle:
+		for (i = 0; i < 10; i++) {
+			mem_req_reg = VXE_RD_REG32(core_reg, TOPAZHP_TOP_CR_MMU_MEM_REQ);
+			if (mem_req_reg != 0)
+				goto wait_till_idle;
+		}
+	}
+
+	/* Set invalidate */
+	reg_value |= F_ENCODE(1, TOPAZHP_TOP_CR_MMU_INVALDC);
+	VXE_WR_REG32(core_reg, TOPAZHP_TOP_CR_MMU_CONTROL0, reg_value);
+
+	/* Clear invalidate */
+	reg_value &= ~((unsigned int)F_ENCODE(1, TOPAZHP_TOP_CR_MMU_INVALDC));
+	VXE_WR_REG32(core_reg, TOPAZHP_TOP_CR_MMU_CONTROL0, reg_value);
+
+	/* UNPAUSE */
+	reg_value &= ~((unsigned int)F_ENCODE(1, TOPAZHP_TOP_CR_MMU_PAUSE));
+	VXE_WR_REG32(core_reg, TOPAZHP_TOP_CR_MMU_CONTROL0, reg_value);
+
+	/* TODO we can have global mutex or local based on need */
+	spin_unlock_irqrestore(g_lock, flags);
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/topazmmu.h b/drivers/media/platform/img/vxe-vxd/encoder/topazmmu.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/topazmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/topazmmu.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,199 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * topaz mmu header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef TOPAZZ_MMU_H_
+#define TOPAZZ_MMU_H_
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "talmmu_api.h"
+#include "vxe_enc.h"
+#include "img_mem.h"
+#include "target_config.h"
+
+/* Page size of the device MMU */
+#define DEV_MMU_PAGE_SIZE (0x1000)
+/* Page alignment of the device MMU */
+#define DEV_MMU_PAGE_ALIGNMENT  (0x1000)
+
+#define HOST_MMU_PAGE_SIZE PAGE_SIZE
+
+/*
+ * This structure contains the stream context.
+ * @brief MMU Stream Context
+ * @devmem_ctx_hndl: Handle for MMU context.
+ * @dev_ctx: Pointer to device context.
+ * @ctx_id: MMU context Id.
+ * km_str_id: Stream ID used in communication with new KM interface
+ */
+struct mmu_str_context {
+	void **link; // to be able to maintain in single linked list.
+	void *mmu_context_handle;
+	unsigned int int_reg_num;
+	unsigned int km_str_id;
+	/* vxe encoder context. Need in stream context to access mem_ctx. */
+	struct vxe_enc_ctx *vxe_enc_context;
+	struct lst_t ddbuf_list;
+};
+
+struct topaz_mmu_context {
+	void *mmu_context_handle;
+	unsigned int ptd_phys_addr;
+	struct lst_t str_list;
+};
+
+/*
+ * This type defines the MMU heaps.
+ * @0:	General heap ID.
+ */
+enum topaz_mmu_eheap_id {
+	MMU_GENERAL_HEAP_ID = 0x00,
+	/* Do not remove - keeps count of size */
+	HEAP_ID_NO_OF_HEAPS
+};
+
+/* Function definitions */
+
+/*
+ * Called once during initialization to initialize the MMU hardware, create
+ * the template and define the MMU heap.
+ * This is where talmmu initialization and template will be created.
+ *
+ * NOTE : We are not taking care of alignment here, need to be updated in
+ * mmu_device_memory_info.
+ */
+int topaz_mmu_device_create(struct topaz_mmu_context *mmu_context, unsigned int mmu_flags);
+
+/*
+ * @Function	mmu_device_destroy
+ * @Description
+ * This function is used to destroy the MMU device context.
+ * NOTE: Destroy device automatically destroys any streams and frees and
+ * memory allocated using MMU_StreamMalloc().
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int topaz_mmu_device_destroy(struct topaz_mmu_context *mmu_context);
+
+/*
+ * @Function	mmu_stream_create
+ * @Description
+ * This function is used to create and initialize the MMU stream context.
+ * @Input	km_str_id : Stream Id used in communication with KM driver.
+ * @Return	IMG_SUCCESS or an error code.
+ *
+ * Context ID is 1, since we are creating single stream.
+ */
+int topaz_mmu_stream_create(struct topaz_mmu_context *mmu_context, unsigned int km_str_id,
+			    void *vxe_enc_ctx_arg, void **mmu_str_ctx);
+
+/*
+ * @Function	mmu_stream_destroy
+ * @Description
+ * This function is used to destroy the MMU stream context.
+ * NOTE: Destroy automatically frees and memory allocated using
+ *	mmu_stream_malloc().
+ * @Input	str_ctx : The MMU stream handle.
+ * @Return	IMG_SUCCESS or an error code.
+ */
+int topaz_mmu_stream_destroy(struct topaz_mmu_context *mmu_context,
+			     struct mmu_str_context *str_ctx);
+
+int topaz_mmu_alloc(void *mmu_context_handle, struct vxe_enc_ctx *vxe_enc_ctx_arg,
+		    enum topaz_mmu_eheap_id heap_id, unsigned int mem_heap_id,
+		    enum sys_emem_attrib mem_attrib, unsigned int size, unsigned int alignment,
+		    struct vidio_ddbufinfo *ddbuf_info);
+/*
+ * @Function	mmu_stream_malloc
+ */
+int topaz_mmu_stream_alloc(void *mmu_str_hndl, enum topaz_mmu_eheap_id heap_id,
+			   unsigned int mem_heap_id,
+			   enum sys_emem_attrib mem_attrib,
+			   unsigned int size,
+			   unsigned int alignment,
+			   struct vidio_ddbufinfo *ddbuf_info);
+
+/*
+ * @Function	mmu_stream_map_ext_sg
+ */
+int topaz_mmu_stream_map_ext_sg(void *mmu_str_hndl, enum topaz_mmu_eheap_id heap_id,
+				void *sgt,
+				unsigned int size,
+				unsigned int alignment,
+				enum sys_emem_attrib mem_attrib,
+				void *cpu_linear_addr,
+				struct vidio_ddbufinfo *ddbuf_info,
+				unsigned int *buff_id);
+
+/*
+ * @Function	mmu_stream_map_ext
+ */
+int topaz_mmu_stream_map_ext(void *mmu_str_hndl, enum topaz_mmu_eheap_id heap_id,
+			     unsigned int buff_id, unsigned int size,
+			     unsigned int alignment,
+			     enum sys_emem_attrib mem_attrib,
+			     void *cpu_linear_addr,
+			     struct vidio_ddbufinfo *ddbuf_info);
+
+/* topaz core mmu hardware setup */
+int topaz_core_mmu_hw_setup(struct topaz_mmu_context *mmu_context, void *core_reg);
+
+/* topaz core mmu flush cache */
+int topaz_core_mmu_flush_cache(void);
+
+/*
+ * @Function    mmu_free
+ *
+ * Free memory allocated with mmu_alloc
+ */
+int topaz_mmu_free(struct vxe_enc_ctx *vxe_enc_ctx_arg,
+		   struct vidio_ddbufinfo *ddbuf_info);
+
+/*
+ * @Function	mmu_free_mem.
+ *
+ * NOTE : This should be used only to free the stream memory.
+ */
+int topaz_mmu_stream_free(void *mmu_str_hndl, struct vidio_ddbufinfo *ddbuf_info);
+
+/*
+ * @Function	mmu_free_mem_sg.
+ *
+ * NOTE : This should be used only to free the stream memory.
+ */
+int topaz_mmu_stream_free_sg(void *mmu_str_hndl, struct vidio_ddbufinfo *ddbuf_info);
+
+/*
+ * @Function    update_device_mem
+ *
+ * Update the memory to the device
+ */
+int topaz_update_device_mem(struct vxe_enc_ctx *vxe_enc_ctx_arg,
+			    struct vidio_ddbufinfo *ddbuf_info);
+
+/*
+ * @Function    update_host_mem
+ *
+ * Update the memory to the host
+ */
+int topaz_update_host_mem(struct vxe_enc_ctx *vxe_enc_ctx_arg,
+			  struct vidio_ddbufinfo *ddbuf_info);
+
+/* Global */
+extern struct mem_space topaz_mem_space[];
+extern void *g_lock;
+
+#endif /* TOPAZZ_MMU_H_ */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/vxe_enc.c b/drivers/media/platform/img/vxe-vxd/encoder/vxe_enc.c
--- a/drivers/media/platform/img/vxe-vxd/encoder/vxe_enc.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/vxe_enc.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,473 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Encoder Interface API function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "img_mem_man.h"
+#include "topazmmu.h"
+#include "vxe_enc.h"
+
+#define MAX(a, b, type) ({ \
+		type __a = a; \
+		type __b = b; \
+		(((__a) >= (__b)) ? (__a) : (__b)); })
+
+void mmu_callback(enum mmu_callback_type callback_type,
+		  int buff_id, void *data)
+{
+	topaz_core_mmu_flush_cache();
+}
+
+int vxe_init_mem(struct vxe_dev *vxe)
+{
+	int ret;
+
+	/* Create memory management context for HW buffers */
+	ret = img_mem_create_ctx(&vxe->drv_ctx.mem_ctx);
+	if (ret) {
+		dev_err(vxe->dev, "%s: failed to create mem context (err:%d)!\n",
+			__func__, ret);
+		goto create_mem_context_failed;
+	}
+
+	ret = img_mmu_ctx_create(vxe->dev, 40 /* mmu_addr_width is 40 */,
+				 vxe->drv_ctx.mem_ctx, vxe->drv_ctx.internal_heap_id,
+				 mmu_callback, vxe, &vxe->drv_ctx.mmu_ctx);
+	if (ret) {
+		dev_err(vxe->dev, "%s:%d: failed to create mmu ctx\n",
+			__func__, __LINE__);
+		goto create_mmu_context_failed;
+	}
+
+	ret = img_mmu_get_ptd(vxe->drv_ctx.mmu_ctx, &vxe->drv_ctx.ptd);
+	if (ret) {
+		dev_err(vxe->dev, "%s:%d: failed to get PTD\n",
+			__func__, __LINE__);
+		goto get_ptd_failed;
+	}
+
+	return 0;
+
+get_ptd_failed:
+	img_mmu_ctx_destroy(vxe->drv_ctx.mmu_ctx);
+create_mmu_context_failed:
+	img_mem_destroy_ctx(vxe->drv_ctx.mem_ctx);
+create_mem_context_failed:
+	return ret;
+}
+
+void vxe_deinit_mem(struct vxe_dev *vxe)
+{
+	if (vxe->drv_ctx.mmu_ctx) {
+		img_mmu_ctx_destroy(vxe->drv_ctx.mmu_ctx);
+		vxe->drv_ctx.mmu_ctx = NULL;
+	}
+
+	if (vxe->drv_ctx.mem_ctx) {
+		img_mem_destroy_ctx(vxe->drv_ctx.mem_ctx);
+		vxe->drv_ctx.mem_ctx = NULL;
+	}
+
+	/* Deinitialize memory management component */
+	while (!list_empty(&vxe->drv_ctx.heaps)) {
+		struct vxe_heap *heap;
+
+		heap = list_first_entry(&vxe->drv_ctx.heaps, struct vxe_heap, list);
+		__list_del_entry(&heap->list);
+		img_mem_del_heap(heap->id);
+		kfree(heap);
+	}
+
+	vxe->drv_ctx.internal_heap_id = VXE_INVALID_ID;
+
+	img_mem_exit();
+}
+
+void vxe_create_ctx(struct vxe_dev *vxe, struct vxe_enc_ctx *ctx)
+{
+	ctx->mem_ctx = vxe->drv_ctx.mem_ctx;
+	ctx->mmu_ctx = vxe->drv_ctx.mmu_ctx;
+}
+
+int calculate_h264_level(unsigned int width, unsigned int height, unsigned int framerate,
+			 unsigned char rc_enable, unsigned int bitrate,
+			 unsigned char lossless,
+			 enum sh_profile_type profile_type,
+			 unsigned int max_num_ref_frames)
+{
+	unsigned int level = 0, mbf = 0, mbs = 0, temp_level = 0, dpb_mbs;
+	unsigned int num = 1, den = 1;
+	unsigned int lossless_min_level = 320;
+
+	mbf = (width * height) / 256;
+	mbs = mbf * framerate;
+
+	if (mbf > 36864) {
+		pr_warn("WARNING: Frame size is too high for maximum supported level!\n");
+		level = 520;
+	} else if (mbf > 22080) {
+		level = 510;
+	} else if (mbf > 8704) {
+		level = 500;
+	} else if (mbf > 8192) {
+		level = 420;
+	} else if (mbf > 5120) {
+		level = 400;
+	} else if (mbf > 3600) {
+		level = 320;
+	} else if (mbf > 1620) {
+		level = 310;
+	} else if (mbf > 792) {
+		level = 220;
+	} else if (mbf > 396) {
+		level = 210;
+	} else if (mbf > 99) {
+		level = 110;
+	} else {
+		level = 100;
+	}
+
+	dpb_mbs = mbf * max_num_ref_frames;
+
+	if (dpb_mbs > 184320) {
+		pr_warn("ERROR: Decoded picture buffer is too high for supported level!\n");
+		return -1;
+	} else if (dpb_mbs > 110400) {
+		temp_level = 510;
+	} else if (dpb_mbs > 34816) {
+		temp_level = 500;
+	} else if (dpb_mbs > 32768) {
+		temp_level = 420;
+	} else if (dpb_mbs > 20480) {
+		temp_level = 400;
+	} else if (dpb_mbs > 18000) {
+		temp_level = 320;
+	} else if (dpb_mbs > 8100) {
+		temp_level = 310;
+	} else if (dpb_mbs > 4752) {
+		temp_level = 220;
+	} else if (dpb_mbs > 2376) {
+		temp_level = 210;
+	} else if (dpb_mbs > 900) {
+		temp_level = 120;
+	} else if (dpb_mbs > 396) {
+		temp_level = 110;
+	} else {
+		temp_level = 100;
+	}
+
+	level = MAX(level, temp_level, unsigned int);
+
+	/* now restrict based on the number of macroblocks per second */
+	if (mbs > 2073600) {
+		pr_err("ERROR: Macroblock processing rate is too high for supported level!\n");
+		return -1;
+	} else if (mbs > 983040) {
+		temp_level = 520;
+	} else if (mbs > 589824) {
+		temp_level = 510;
+	} else if (mbs > 522240) {
+		temp_level = 500;
+	} else if (mbs > 245760) {
+		temp_level = 420;
+	} else if (mbs > 216000) {
+		temp_level = 400;
+	} else if (mbs > 108000) {
+		temp_level = 320;
+	} else if (mbs > 40500) {
+		temp_level = 310;
+	} else if (mbs > 20250) {
+		temp_level = 300;
+	} else if (mbs > 19800) {
+		temp_level = 220;
+	} else if (mbs > 11880) {
+		temp_level = 210;
+	} else if (mbs > 6000) {
+		temp_level = 130;
+	} else if (mbs > 3000) {
+		temp_level = 120;
+	} else if (mbs > 1485) {
+		temp_level = 110;
+	} else {
+		temp_level = 100;
+	}
+
+	level = MAX(level, temp_level, unsigned int);
+
+	if (rc_enable) {
+		/*
+		 * SH_PROFILE_H10P and SH_PROFILE_H422P are
+		 * not valid choices for HW_3_X, skipping
+		 */
+		if (profile_type == SH_PROFILE_HP) {
+			num = 5;
+			den = 4;
+		} else if (profile_type == SH_PROFILE_H444P) {
+			num = 4;
+			den = 1;
+		}
+
+		if (bitrate > ((135000000 * num) / den))
+			temp_level = 510;
+		else if (bitrate > ((50000000 * num) / den))
+			temp_level = 500;
+		else if (bitrate > ((20000000 * num) / den))
+			temp_level = 410;
+		else if (bitrate > ((14000000 * num) / den))
+			temp_level = 320;
+		else if (bitrate > ((10000000 * num) / den))
+			temp_level = 310;
+		else if (bitrate > ((4000000 * num) / den))
+			temp_level = 300;
+		else if (bitrate > ((2000000 * num) / den))
+			temp_level = 210;
+		else if (bitrate > ((768000 * num) / den))
+			temp_level = 200;
+		else if (bitrate > ((384000 * num) / den))
+			temp_level = 130;
+		else if (bitrate > ((192000 * num) / den))
+			temp_level = 120;
+		else if (bitrate > ((128000 * num) / den))
+			temp_level = 110;
+		else if (bitrate > ((64000 * num) / den))
+			temp_level = 101;
+		else
+			temp_level = 100;
+
+		level = MAX(level, temp_level, unsigned int);
+	} else {
+		level = 510;
+	}
+
+	if (lossless)
+		level = MAX(level, lossless_min_level, unsigned int);
+
+	return level;
+}
+
+enum sh_profile_type find_h264_profile(unsigned char lossless,
+				       unsigned char h264_use_default_scaling_list,
+				       unsigned int custom_quant_mask,
+				       unsigned char h264_8x8_transform,
+				       unsigned char enable_mvc,
+				       unsigned int b_frame_count,
+				       unsigned char interlaced,
+				       unsigned char h264_cabac,
+				       unsigned int weighted_prediction_mode,
+				       unsigned int weighted_implicit_bi_pred)
+{
+	enum sh_profile_type profile = SH_PROFILE_BP;
+
+	if (lossless)
+		profile = SH_PROFILE_H444P;
+	else if (h264_use_default_scaling_list || custom_quant_mask ||
+		 h264_8x8_transform || enable_mvc)
+		profile = SH_PROFILE_HP;
+	else if ((b_frame_count > 0) || interlaced || h264_cabac ||
+		 weighted_prediction_mode || weighted_implicit_bi_pred)
+		profile = SH_PROFILE_MP;
+
+	return profile;
+}
+
+void vxe_fill_default_src_frame_params(struct vxe_buffer *buf)
+{
+	buf->src_frame.component_count = 0; /* Unset in IMG */
+	buf->src_frame.format = IMG_CODEC_420_YUV; /* Unset in IMG */
+	buf->src_frame.component_offset[0] = 0;
+	buf->src_frame.component_offset[1] = 0;
+	buf->src_frame.component_offset[2] = 0;
+	buf->src_frame.bottom_component_offset[0] = 0; /* Unset in IMG */
+	buf->src_frame.bottom_component_offset[1] = 0; /* Unset in IMG */
+	buf->src_frame.bottom_component_offset[2] = 0; /* Unset in IMG */
+	buf->src_frame.component_info[0].step = 0;
+	buf->src_frame.component_info[0].width = 0;
+	buf->src_frame.component_info[0].height = 0;
+	buf->src_frame.component_info[0].phys_width = 0;
+	buf->src_frame.component_info[0].phys_height = 0;
+	buf->src_frame.component_info[1].step = 0;
+	buf->src_frame.component_info[1].width = 0;
+	buf->src_frame.component_info[1].height = 0;
+	buf->src_frame.component_info[1].phys_width = 0;
+	buf->src_frame.component_info[1].phys_height = 0;
+	buf->src_frame.component_info[2].step = 0;
+	buf->src_frame.component_info[2].width = 0;
+	buf->src_frame.component_info[2].height = 0;
+	buf->src_frame.component_info[2].phys_width = 0;
+	buf->src_frame.component_info[2].phys_height = 0;
+	buf->src_frame.field0_y_offset = 0;
+	buf->src_frame.field1_y_offset = 0;
+	buf->src_frame.field0_u_offset = 0;
+	buf->src_frame.field1_u_offset = 0;
+	buf->src_frame.field0_v_offset = 0;
+	buf->src_frame.field1_v_offset = 0;
+	buf->src_frame.imported = FALSE;
+}
+
+void vxe_fill_default_params(struct vxe_enc_ctx *ctx)
+{
+	int i, j;
+	unsigned short h264_rounding_offsets[18][4] = {
+		{683, 683, 683, 683}, /* 0 I-Slice - INTRA4 LUMA */
+		{683, 683, 683, 683}, /* 1 P-Slice - INTRA4 LUMA */
+		{683, 683, 683, 683}, /* 2 B-Slice - INTRA4 LUMA */
+
+		{683, 683, 683, 683}, /* 3 I-Slice - INTRA8 LUMA */
+		{683, 683, 683, 683}, /* 4 P-Slice - INTRA8 LUMA */
+		{683, 683, 683, 683}, /* 5 B-Slice - INTRA8 LUMA */
+
+		{341, 341, 341, 341}, /* 6 P-Slice - INTER8 LUMA */
+		{341, 341, 341, 341}, /* 7 B-Slice - INTER8 LUMA */
+
+		{683, 683, 683, 000}, /* 8 I-Slice - INTRA16 LUMA */
+		{683, 683, 683, 000}, /* 9 P-Slice - INTRA16 LUMA */
+		{683, 683, 683, 000}, /* 10 B-Slice - INTRA16 LUMA */
+
+		{341, 341, 341, 341}, /* 11 P-Slice - INTER16 LUMA */
+		{341, 341, 341, 341}, /* 12 B-Slice - INTER16 LUMA */
+
+		{683, 683, 683, 000}, /* 13 I-Slice - INTRA16 CR */
+		{683, 683, 683, 000}, /* 14 P-Slice - INTRA16 CR */
+		{683, 683, 683, 000}, /* 15 B-Slice - INTRA16 CR */
+
+		{341, 341, 341, 000 }, /* 16 P-Slice - INTER16 CHROMA */
+		{341, 341, 341, 000 } /* 17 B-Slice - INTER16 CHROMA */
+	};
+
+	ctx->vparams.csc_preset = IMG_CSC_NONE;
+	ctx->vparams.slices_per_picture = 1;
+	ctx->vparams.is_interleaved = FALSE;
+	ctx->vparams.constrained_intra = FALSE;
+	ctx->vparams.h264_8x8 = TRUE;
+	ctx->vparams.bottom_field_first = FALSE;
+	ctx->vparams.arbitrary_so = FALSE;
+	ctx->vparams.cabac_enabled = TRUE;
+	ctx->vparams.cabac_bin_limit = 2800;
+	ctx->vparams.cabac_bin_flex = 2800;
+	ctx->vparams.deblock_idc = 0;
+	ctx->vparams.output_reconstructed = FALSE;
+	ctx->vparams.f_code = 4;
+	ctx->vparams.fine_y_search_size = 2;
+	ctx->vparams.no_offscreen_mv = FALSE;
+	ctx->vparams.idr_period = 1800; /* 60 * 30fps */
+	ctx->vparams.intra_cnt = 30;
+	ctx->vparams.vop_time_resolution = 15;
+	ctx->vparams.enc_features.disable_bpic_ref1 = FALSE;
+	ctx->vparams.enc_features.disable_bpic_ref0 = FALSE;
+	ctx->vparams.enc_features.disable_bframes = FALSE;
+	ctx->vparams.enc_features.restricted_intra_pred = FALSE;
+	ctx->vparams.enable_sel_stats_flags = 0;
+	ctx->vparams.enable_inp_ctrl = FALSE;
+	ctx->vparams.enable_air = FALSE;
+	ctx->vparams.num_air_mbs = -1;
+	ctx->vparams.air_threshold = -1;
+	ctx->vparams.air_skip_cnt = -1;
+	ctx->vparams.enable_cumulative_biases = FALSE;
+	ctx->vparams.enable_host_bias = TRUE;
+	ctx->vparams.enable_host_qp = FALSE;
+	ctx->vparams.use_default_scaling_list = FALSE;
+	ctx->vparams.use_custom_scaling_lists = 0;
+	ctx->vparams.pps_scaling = 0;
+	ctx->vparams.disable_bit_stuffing = TRUE;
+	ctx->vparams.coded_skipped_index = 3;
+	ctx->vparams.inter_intra_index = 3;
+	ctx->vparams.mpeg2_intra_dc_precision = 0;
+	ctx->vparams.carc = 0;
+	ctx->vparams.carc_baseline = 0;
+	ctx->vparams.carc_threshold = 1;
+	ctx->vparams.carc_cutoff = 15;
+	ctx->vparams.carc_neg_range = 5;
+	ctx->vparams.carc_neg_scale = 12;
+	ctx->vparams.carc_pos_range = 5;
+	ctx->vparams.carc_pos_scale = 12;
+	ctx->vparams.carc_shift = 3;
+	ctx->vparams.weighted_prediction = FALSE;
+	ctx->vparams.vp_weighted_implicit_bi_pred = 0;
+	ctx->vparams.insert_hrd_params = FALSE;
+	ctx->vparams.intra_refresh = 0;
+	ctx->vparams.chunks_per_mb = 64;
+	ctx->vparams.max_chunks = 160;
+	ctx->vparams.priority_chunks = 64;
+	ctx->vparams.mbps = 0;
+	ctx->vparams.multi_reference_p = FALSE;
+	ctx->vparams.ref_spacing = 0;
+	ctx->vparams.spatial_direct = FALSE;
+	ctx->vparams.vp_adaptive_rounding_disable = 0;
+
+	for (i = 0; i < 18; i++) {
+		for (j = 0; j < 4; j++) {
+			ctx->vparams.vp_adaptive_rounding_offsets[i][j] =
+				h264_rounding_offsets[i][j];
+		}
+	}
+
+	ctx->vparams.debug_crcs = 0;
+	ctx->vparams.enable_mvc = FALSE;
+	ctx->vparams.mvc_view_idx = 65535;
+	ctx->vparams.high_latency = TRUE;
+	ctx->vparams.disable_bh_rounding = FALSE;
+	ctx->vparams.no_sequence_headers = FALSE;
+	ctx->vparams.auto_encode = FALSE;
+	ctx->vparams.slice_level = FALSE;
+	ctx->vparams.coded_header_per_slice = FALSE;
+	ctx->vparams.auto_expand_pipes = FALSE;
+	ctx->vparams.enable_lossless = FALSE;
+	ctx->vparams.lossless_8x8_prefilter = FALSE;
+	ctx->vparams.enable_scaler = FALSE;
+	ctx->vparams.line_counter_enabled = FALSE;
+
+	ctx->rc.intra_freq = 30;
+	ctx->rc.initial_qp_i = 0;
+	ctx->rc.initial_qp_p = 0;
+	ctx->rc.initial_qp_b = 0;
+
+	ctx->rc.min_qp = 0;
+	ctx->rc.max_qp = 0;
+	ctx->rc.rc_enable = TRUE;
+
+	ctx->rc.hierarchical = FALSE;
+
+	ctx->rc.enable_slice_bob = FALSE;
+	ctx->rc.max_slice_bob = 2;
+	ctx->rc.slice_bob_qp = 44;
+
+	ctx->rc.qcp_offset = 0;
+	ctx->rc.sc_detect_disable = FALSE;
+	ctx->rc.slice_byte_limit = 0;
+	ctx->rc.slice_mb_limit = 0;
+	ctx->rc.rc_mode = IMG_RCMODE_VBR;
+	ctx->rc.rc_vcm_mode = IMG_RC_VCM_MODE_DEFAULT;
+	ctx->rc.rc_cfs_max_margin_perc = 9;
+	ctx->rc.disable_frame_skipping = FALSE;
+	ctx->rc.disable_vcm_hardware = FALSE;
+
+	ctx->s_fmt_flags = 0;
+
+	ctx->above_mb_params_sgt[0].sgl = NULL;
+	ctx->above_mb_params_sgt[1].sgl = NULL;
+}
+
+unsigned int vxe_get_sizeimage(int w, int h, struct vxe_enc_fmt *fmt, unsigned char plane_id)
+{
+	return (ALIGN_16(w) * ALIGN_16(h) * fmt->size_num[plane_id] / fmt->size_den[plane_id]);
+}
+
+unsigned int vxe_get_stride(int w, struct vxe_enc_fmt *fmt)
+{
+	return ALIGN(w * fmt->bytes_pp, HW_ALIGN);
+}
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/vxe_enc.h b/drivers/media/platform/img/vxe-vxd/encoder/vxe_enc.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/vxe_enc.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/vxe_enc.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,255 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * encoder interface header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _VXE_ENC_H
+#define _VXE_ENC_H
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include "topaz_api.h"
+
+#define HW_ALIGN 64
+#define MB_SIZE 16
+#define VXE_INVALID_ID (-1)
+#define OCM_RAM_POOL_CHUNK_SIZE (32 * 1024)
+
+enum {
+	Q_ENC_DATA_SRC         = 0,
+	Q_ENC_DATA_DST         = 1,
+	Q_ENC_DATA_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum {
+	IMG_ENC_FMT_TYPE_CAPTURE     = 0x01,
+	IMG_ENC_FMT_TYPE_OUTPUT      = 0x10,
+	IMG_ENC_FMT_TYPE_FORCE32BITS = 0x7FFFFFFFU
+};
+
+enum vxe_map_flags {
+	VXE_MAP_FLAG_NONE        = 0x0,
+	VXE_MAP_FLAG_READ_ONLY   = 0x1,
+	VXE_MAP_FLAG_WRITE_ONLY  = 0x2,
+	VXE_MAP_FLAG_FORCE32BITS = 0x7FFFFFFFU
+};
+
+/*
+ * struct vxe_enc_fmt - contains info for each supported video format
+ */
+struct vxe_enc_fmt {
+	unsigned int fourcc;
+	unsigned int num_planes;
+	unsigned int type;
+	union {
+		enum img_standard std;
+		enum img_format fmt;
+	};
+	unsigned int min_bufs;
+	unsigned int size_num[MAX_PLANES];
+	unsigned int size_den[MAX_PLANES];
+	unsigned int bytes_pp;
+	enum img_csc_preset csc_preset;
+};
+
+/*
+ * struct vxe_buffer - contains info for all buffers
+ */
+struct vxe_buffer {
+	struct v4l2_m2m_buffer buffer;
+	unsigned int index;
+	unsigned int buf_map_id;
+	struct vidio_ddbufinfo buf_info;
+	union {
+		struct img_frame src_frame;
+		struct img_coded_buffer coded_buffer;
+	};
+	struct img_buffer y_buffer;
+	struct img_buffer u_buffer;
+	struct img_buffer v_buffer;
+	unsigned char src_slot_num;
+	unsigned char mapped;
+};
+
+/*
+ * struct vxe_heap - node for heaps list
+ * @id:   heap id
+ * @list: Entry in <struct vxe_drv:heaps>
+ */
+struct vxe_heap {
+	int id;
+	struct list_head list;
+};
+
+/* Driver context */
+struct vxe_drv_ctx {
+	/* Available memory heaps. List of <struct vxe_heap> */
+	struct list_head heaps;
+	/* heap id for all internal allocations */
+	int internal_heap_id;
+	/* Memory Management context for driver */
+	struct mem_ctx *mem_ctx;
+	/* MMU context for driver */
+	struct mmu_ctx *mmu_ctx;
+	/* PTD */
+	unsigned int ptd;
+};
+
+/*
+ * struct vxe_dev - The struct containing encoder driver internal parameters.
+ */
+struct vxe_dev {
+	void *dev;
+	struct video_device *vfd;
+	struct v4l2_device ti_vxe_dev;
+	struct platform_device *plat_dev;
+	struct v4l2_m2m_dev *m2m_dev;
+	struct mutex *mutex;
+	int module_irq;
+	struct idr *streams;
+	void __iomem *reg_base;
+	void *topaz_dev_ctx;
+	struct vxe_drv_ctx drv_ctx;
+	/* dummy context for MMU mappings and allocations */
+	struct vxe_enc_ctx *ctx;
+	unsigned int num_pipes;
+
+	/* The variables defined below are used in RTOS only. */
+	/* This variable holds queue handler */
+	void *vxe_worker_queue_handle;
+	void *vxe_worker_queue_sem_handle;
+
+	/* On Chip Memory Pool for above MB params struct */
+	/* Supporting only 2 max instances (upto 1080p resolutions) to make use of this */
+	void *ocm_ram_chunk[2]; //each chunk of 32KB
+	void *ram_chunk_owner[2];
+
+};
+
+#define S_FMT_FLAG_OUT_RECV 0x1
+#define S_FMT_FLAG_CAP_RECV 0x2
+#define S_FMT_FLAG_STREAM_CREATED 0x4
+
+#define VXE_ENCODER_MAX_WIDTH 1920
+#define VXE_ENCODER_MIN_WIDTH 64
+#define VXE_ENCODER_MAX_HEIGHT 1088
+#define VXE_ENCODER_MIN_HEIGHT 64
+
+#define VXE_ENCODER_DEFAULT_HEIGHT 240
+#define VXE_ENCODER_DEFAULT_WIDTH 416
+#define VXE_ENCODER_INITIAL_QP_I 18
+#define VXE_ENCODER_DEFAULT_FRAMERATE 30
+
+/*
+ * struct vxe_enc_q_data - contains queue data information
+ *
+ * @fmt: format info
+ * @width: frame width
+ * @height: frame height
+ * @bytesperline: bytes per line in memory
+ * @size_image: image size in memory
+ */
+struct vxe_enc_q_data {
+	struct vxe_enc_fmt *fmt;
+	unsigned int width;
+	unsigned int height;
+	unsigned int bytesperline[MAX_PLANES];
+	unsigned int size_image[MAX_PLANES];
+	unsigned char streaming;
+};
+
+#ifdef ENABLE_PROFILING
+struct enc_drv_latency {
+	unsigned int start_time;
+	unsigned int end_time;
+};
+#endif
+
+/*
+ * struct vxe_ctx - The struct containing stream context parameters.
+ */
+struct vxe_enc_ctx {
+	struct v4l2_fh fh;
+	struct vxe_dev *dev;
+	void **enc_context;
+	void *topaz_str_context;
+	struct mutex *mutex;
+	unsigned char core_streaming;
+	struct img_enc_caps caps;
+	struct img_rc_params rc;
+	struct img_video_params vparams;
+	struct vxe_enc_q_data out_queue;
+	struct vxe_enc_q_data cap_queue;
+	struct mem_ctx *mem_ctx;
+	struct mmu_ctx *mmu_ctx;
+	/* list open_slots*/
+	unsigned char s_fmt_flags;
+	struct h264_vui_params vui_params;
+	struct h264_crop_params crop_params;
+	struct h264_sequence_header_params sh_params;
+	unsigned char eos;
+	unsigned char flag_last;
+	unsigned int coded_packages_per_frame; /* How many slices per frame */
+	unsigned int available_coded_packages;
+	unsigned int available_source_frames;
+	unsigned int frames_encoding;
+	unsigned int frame_num;
+	unsigned int last_frame_num;
+	unsigned int cap_seq;   /* sequence number on capture port */
+	unsigned int out_seq;   /* sequence number on output port */
+
+	enum v4l2_colorspace colorspace;
+	enum v4l2_xfer_func xfer_func;
+	enum v4l2_ycbcr_encoding ycbcr_enc;
+	enum v4l2_quantization quantization;
+	enum v4l2_hsv_encoding hsv_enc;
+
+	/* The below variable used only in Rtos */
+	void *mm_return_resource; /* Place holder for CB to application */
+	void *stream_worker_queue_handle;
+	void *stream_worker_queue_sem_handle;
+	void *work;
+	struct vxe_enc_q_data q_data[2];
+	struct v4l2_ctrl_handler v4l2_ctrl_hdl;
+	struct sg_table above_mb_params_sgt[2];
+
+#ifdef ENABLE_PROFILING
+	struct enc_drv_latency drv_lat;
+#endif
+};
+
+int vxe_init_mem(struct vxe_dev *vxe);
+void vxe_deinit_mem(struct vxe_dev *vxe);
+void vxe_create_ctx(struct vxe_dev *vxe, struct vxe_enc_ctx *ctx);
+int calculate_h264_level(unsigned int width, unsigned int height, unsigned int framerate,
+			 unsigned char rc_enable, unsigned int bitrate,
+			 unsigned char lossless,
+			 enum sh_profile_type profile_type,
+			 unsigned int max_num_ref_frames);
+enum sh_profile_type find_h264_profile(unsigned char lossless,
+				       unsigned char h264_use_default_scaling_list,
+				       unsigned int custom_quant_mask,
+				       unsigned char h264_8x8_transform,
+				       unsigned char enable_mvc,
+				       unsigned int b_frame_count,
+				       unsigned char interlaced,
+				       unsigned char h264_cabac,
+				       unsigned int weighted_prediction_mode,
+				       unsigned int weighted_implicit_bi_pred);
+void vxe_fill_default_src_frame_params(struct vxe_buffer *buf);
+void vxe_fill_default_params(struct vxe_enc_ctx *ctx);
+unsigned int vxe_get_sizeimage(int w, int h, struct vxe_enc_fmt *fmt, unsigned char plane_id);
+unsigned int vxe_get_stride(int w, struct vxe_enc_fmt *fmt);
+
+#endif /* _VXE_ENC_H */
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/vxe_public_regdefs.h b/drivers/media/platform/img/vxe-vxd/encoder/vxe_public_regdefs.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/vxe_public_regdefs.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/vxe_public_regdefs.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,926 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * encoder public register definitions
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef __VXE_PUBLIC_REGDEFS_H__
+#define __VXE_PUBLIC_REGDEFS_H__
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+
+/* Write to the register */
+#define VXE_WR_REG32(base, offs, val) \
+	(iowrite32((val), (void *)((offs) + (unsigned long)(base))))
+
+/* Read the register */
+#define VXE_RD_REG32(base, offs) \
+	(ioread32((void *)((base) + (offs))))
+
+#define VXE_POLL_REG32_ISEQ(base, offs, val, mask, cnt) \
+	(ioreg32_poll_iseq((unsigned long)(base) + (offs), val, mask, cnt))
+
+#define REG_BASE_HOST                   0x00000000
+#define REG_OFFSET_TOPAZ_MTX            0x00000800
+#define REG_START_TOPAZ_MTX_HOST        (REG_BASE_HOST + REG_OFFSET_TOPAZ_MTX)
+
+static inline int ioreg32_poll_iseq(unsigned long addr,
+				    unsigned int req_val, unsigned int mask, unsigned int cnt)
+{
+	unsigned int count, val;
+	unsigned int res = 0;
+
+	/* Add high-frequency poll loops. */
+	cnt += 10;
+
+	/*
+	 * High-frequency loop (designed for shorter hardware latency such as
+	 * reset).
+	 */
+	for (count = 0; count < cnt; count++) {
+		/* Read from the device */
+		val = ioread32((void *)addr);
+		val = (val & mask);
+
+		if (val == req_val) {
+			res = 0;
+			break;
+		}
+
+		/*
+		 * Sleep to wait for hardware.
+		 * Period is selected to allow for high-frequency polling
+		 * (5us, e.g. reset) over the first 10 iterations, then
+		 * reverting to a lower-frequency (100us, e.g. DMA) for the
+		 * remainder.
+		 */
+		if (count < 10)
+			usleep_range(5, 5);
+		else
+			usleep_range(100, 100);
+	}
+
+	if (res || count >= cnt) {
+		pr_info("Poll failed!\n");
+		res = -1;
+	}
+
+	return res;
+}
+
+/*
+ * DMAC configuration values:
+ */
+/*! The maximum number of channels in the SoC               */
+#define DMAC_MAX_CHANNELS       (1)
+
+/* Register CR_TOPAZHP_CORE_REV */
+#define TOPAZHP_TOP_CR_TOPAZHP_CORE_REV 0x03D0
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_MAINT_REV 0x000000FF
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_MAINT_REV 0
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_MAINT_REV 0x03D0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_MAINT_REV 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_MINOR_REV 0x0000FF00
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_MINOR_REV 8
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_MINOR_REV 0x03D0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_MINOR_REV 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_MAJOR_REV 0x00FF0000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_MAJOR_REV 16
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_MAJOR_REV 0x03D0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_MAJOR_REV 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_DESIGNER 0xFF000000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_DESIGNER 24
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_DESIGNER 0x03D0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_DESIGNER 0
+
+/* Register CR_TOPAZHP_CORE_DES1 */
+#define TOPAZHP_TOP_CR_TOPAZHP_CORE_DES1 0x03E0
+
+/* Register CR_MULTICORE_HW_CFG */
+#define TOPAZHP_TOP_CR_MULTICORE_HW_CFG 0x0058
+#define MASK_TOPAZHP_TOP_CR_NUM_CORES_SUPPORTED 0x0000001F
+#define SHIFT_TOPAZHP_TOP_CR_NUM_CORES_SUPPORTED 0
+#define REGNUM_TOPAZHP_TOP_CR_NUM_CORES_SUPPORTED 0x0058
+#define SIGNED_TOPAZHP_TOP_CR_NUM_CORES_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_NUM_MTX_SUPPORTED 0x00000700
+#define SHIFT_TOPAZHP_TOP_CR_NUM_MTX_SUPPORTED 8
+#define REGNUM_TOPAZHP_TOP_CR_NUM_MTX_SUPPORTED 0x0058
+#define SIGNED_TOPAZHP_TOP_CR_NUM_MTX_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_NUM_CORES_PER_MTX 0x00070000
+#define SHIFT_TOPAZHP_TOP_CR_NUM_CORES_PER_MTX 16
+#define REGNUM_TOPAZHP_TOP_CR_NUM_CORES_PER_MTX 0x0058
+#define SIGNED_TOPAZHP_TOP_CR_NUM_CORES_PER_MTX 0
+
+#define MASK_TOPAZHP_TOP_CR_EXTENDED_ADDR_RANGE 0x0F000000
+#define SHIFT_TOPAZHP_TOP_CR_EXTENDED_ADDR_RANGE 24
+#define REGNUM_TOPAZHP_TOP_CR_EXTENDED_ADDR_RANGE 0x0058
+#define SIGNED_TOPAZHP_TOP_CR_EXTENDED_ADDR_RANGE 0
+
+/* Register CR_MULTICORE_SRST */
+#define TOPAZHP_TOP_CR_MULTICORE_SRST 0x0000
+#define MASK_TOPAZHP_TOP_CR_IMG_TOPAZ_MTX_SOFT_RESET 0x00000001
+#define SHIFT_TOPAZHP_TOP_CR_IMG_TOPAZ_MTX_SOFT_RESET 0
+#define REGNUM_TOPAZHP_TOP_CR_IMG_TOPAZ_MTX_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_TOP_CR_IMG_TOPAZ_MTX_SOFT_RESET 0
+
+#define MASK_TOPAZHP_TOP_CR_IMG_TOPAZ_IO_SOFT_RESET 0x00000002
+#define SHIFT_TOPAZHP_TOP_CR_IMG_TOPAZ_IO_SOFT_RESET 1
+#define REGNUM_TOPAZHP_TOP_CR_IMG_TOPAZ_IO_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_TOP_CR_IMG_TOPAZ_IO_SOFT_RESET 0
+
+#define MASK_TOPAZHP_TOP_CR_IMG_TOPAZ_CORE_SOFT_RESET 0x00000004
+#define SHIFT_TOPAZHP_TOP_CR_IMG_TOPAZ_CORE_SOFT_RESET 2
+#define REGNUM_TOPAZHP_TOP_CR_IMG_TOPAZ_CORE_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_TOP_CR_IMG_TOPAZ_CORE_SOFT_RESET 0
+
+/* Register CR_MULTICORE_INT_STAT */
+#define TOPAZHP_TOP_CR_MULTICORE_INT_STAT 0x0004
+#define MASK_TOPAZHP_TOP_CR_INT_STAT_DMAC 0x00000001
+#define SHIFT_TOPAZHP_TOP_CR_INT_STAT_DMAC 0
+#define REGNUM_TOPAZHP_TOP_CR_INT_STAT_DMAC 0x0004
+#define SIGNED_TOPAZHP_TOP_CR_INT_STAT_DMAC 0
+
+#define MASK_TOPAZHP_TOP_CR_INT_STAT_MTX 0x00000002
+#define SHIFT_TOPAZHP_TOP_CR_INT_STAT_MTX 1
+#define REGNUM_TOPAZHP_TOP_CR_INT_STAT_MTX 0x0004
+#define SIGNED_TOPAZHP_TOP_CR_INT_STAT_MTX 0
+
+#define MASK_TOPAZHP_TOP_CR_INT_STAT_MTX_HALT 0x00000004
+#define SHIFT_TOPAZHP_TOP_CR_INT_STAT_MTX_HALT 2
+#define REGNUM_TOPAZHP_TOP_CR_INT_STAT_MTX_HALT 0x0004
+#define SIGNED_TOPAZHP_TOP_CR_INT_STAT_MTX_HALT 0
+
+#define MASK_TOPAZHP_TOP_CR_INT_STAT_MMU_FAULT 0x00000078
+#define SHIFT_TOPAZHP_TOP_CR_INT_STAT_MMU_FAULT 3
+#define REGNUM_TOPAZHP_TOP_CR_INT_STAT_MMU_FAULT 0x0004
+#define SIGNED_TOPAZHP_TOP_CR_INT_STAT_MMU_FAULT 0
+
+#define MASK_TOPAZHP_TOP_CR_INT_STAT_MTX_CORES 0x0000FF00
+#define SHIFT_TOPAZHP_TOP_CR_INT_STAT_MTX_CORES 8
+#define REGNUM_TOPAZHP_TOP_CR_INT_STAT_MTX_CORES 0x0004
+#define SIGNED_TOPAZHP_TOP_CR_INT_STAT_MTX_CORES 0
+
+#define MASK_TOPAZHP_TOP_CR_INT_STAT_HOST_CORES 0x00FF0000
+#define SHIFT_TOPAZHP_TOP_CR_INT_STAT_HOST_CORES 16
+#define REGNUM_TOPAZHP_TOP_CR_INT_STAT_HOST_CORES 0x0004
+#define SIGNED_TOPAZHP_TOP_CR_INT_STAT_HOST_CORES 0
+
+#define MASK_TOPAZHP_TOP_CR_INT_STAT_MMU_FAULT_B 0x1E000000
+#define SHIFT_TOPAZHP_TOP_CR_INT_STAT_MMU_FAULT_B 25
+#define REGNUM_TOPAZHP_TOP_CR_INT_STAT_MMU_FAULT_B 0x0004
+#define SIGNED_TOPAZHP_TOP_CR_INT_STAT_MMU_FAULT_B 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_MAS_MTX_INTS 0x40000000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_MAS_MTX_INTS 30
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_MAS_MTX_INTS 0x0004
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_MAS_MTX_INTS 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_MAS_HOST_INTS 0x80000000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_MAS_HOST_INTS 31
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_MAS_HOST_INTS 0x0004
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_MAS_HOST_INTS 0
+
+/* Register CR_MULTICORE_HOST_INT_ENAB */
+#define TOPAZHP_TOP_CR_MULTICORE_HOST_INT_ENAB 0x000C
+#define MASK_TOPAZHP_TOP_CR_HOST_INTEN_DMAC 0x00000001
+#define SHIFT_TOPAZHP_TOP_CR_HOST_INTEN_DMAC 0
+#define REGNUM_TOPAZHP_TOP_CR_HOST_INTEN_DMAC 0x000C
+#define SIGNED_TOPAZHP_TOP_CR_HOST_INTEN_DMAC 0
+
+#define MASK_TOPAZHP_TOP_CR_HOST_INTEN_MTX 0x00000002
+#define SHIFT_TOPAZHP_TOP_CR_HOST_INTEN_MTX 1
+#define REGNUM_TOPAZHP_TOP_CR_HOST_INTEN_MTX 0x000C
+#define SIGNED_TOPAZHP_TOP_CR_HOST_INTEN_MTX 0
+
+#define MASK_TOPAZHP_TOP_CR_HOST_INTEN_MTX_HALT 0x00000004
+#define SHIFT_TOPAZHP_TOP_CR_HOST_INTEN_MTX_HALT 2
+#define REGNUM_TOPAZHP_TOP_CR_HOST_INTEN_MTX_HALT 0x000C
+#define SIGNED_TOPAZHP_TOP_CR_HOST_INTEN_MTX_HALT 0
+
+#define MASK_TOPAZHP_TOP_CR_HOST_INTEN_MMU_FAULT 0x00000078
+#define SHIFT_TOPAZHP_TOP_CR_HOST_INTEN_MMU_FAULT 3
+#define REGNUM_TOPAZHP_TOP_CR_HOST_INTEN_MMU_FAULT 0x000C
+#define SIGNED_TOPAZHP_TOP_CR_HOST_INTEN_MMU_FAULT 0
+
+#define MASK_TOPAZHP_TOP_CR_HOST_INTEN_MTX_CORES 0x0000FF00
+#define SHIFT_TOPAZHP_TOP_CR_HOST_INTEN_MTX_CORES 8
+#define REGNUM_TOPAZHP_TOP_CR_HOST_INTEN_MTX_CORES 0x000C
+#define SIGNED_TOPAZHP_TOP_CR_HOST_INTEN_MTX_CORES 0
+
+#define MASK_TOPAZHP_TOP_CR_HOST_INTEN_HOST_CORES 0x00FF0000
+#define SHIFT_TOPAZHP_TOP_CR_HOST_INTEN_HOST_CORES 16
+#define REGNUM_TOPAZHP_TOP_CR_HOST_INTEN_HOST_CORES 0x000C
+#define SIGNED_TOPAZHP_TOP_CR_HOST_INTEN_HOST_CORES 0
+
+#define MASK_TOPAZHP_TOP_CR_HOST_INTEN_MMU_FAULT_B 0x1E000000
+#define SHIFT_TOPAZHP_TOP_CR_HOST_INTEN_MMU_FAULT_B 25
+#define REGNUM_TOPAZHP_TOP_CR_HOST_INTEN_MMU_FAULT_B 0x000C
+#define SIGNED_TOPAZHP_TOP_CR_HOST_INTEN_MMU_FAULT_B 0
+
+#define MASK_TOPAZHP_TOP_CR_HOST_TOPAZHP_MAS_INTEN 0x80000000
+#define SHIFT_TOPAZHP_TOP_CR_HOST_TOPAZHP_MAS_INTEN 31
+#define REGNUM_TOPAZHP_TOP_CR_HOST_TOPAZHP_MAS_INTEN 0x000C
+#define SIGNED_TOPAZHP_TOP_CR_HOST_TOPAZHP_MAS_INTEN 0
+
+/* Register CR_MULTICORE_INT_CLEAR */
+#define TOPAZHP_TOP_CR_MULTICORE_INT_CLEAR 0x0010
+#define MASK_TOPAZHP_TOP_CR_INTCLR_DMAC 0x00000001
+#define SHIFT_TOPAZHP_TOP_CR_INTCLR_DMAC 0
+#define REGNUM_TOPAZHP_TOP_CR_INTCLR_DMAC 0x0010
+#define SIGNED_TOPAZHP_TOP_CR_INTCLR_DMAC 0
+
+#define MASK_TOPAZHP_TOP_CR_INTCLR_MTX 0x00000002
+#define SHIFT_TOPAZHP_TOP_CR_INTCLR_MTX 1
+#define REGNUM_TOPAZHP_TOP_CR_INTCLR_MTX 0x0010
+#define SIGNED_TOPAZHP_TOP_CR_INTCLR_MTX 0
+
+#define MASK_TOPAZHP_TOP_CR_INTCLR_MTX_HALT 0x00000004
+#define SHIFT_TOPAZHP_TOP_CR_INTCLR_MTX_HALT 2
+#define REGNUM_TOPAZHP_TOP_CR_INTCLR_MTX_HALT 0x0010
+#define SIGNED_TOPAZHP_TOP_CR_INTCLR_MTX_HALT 0
+
+#define MASK_TOPAZHP_TOP_CR_INTCLR_MMU_FAULT 0x00000078
+#define SHIFT_TOPAZHP_TOP_CR_INTCLR_MMU_FAULT 3
+#define REGNUM_TOPAZHP_TOP_CR_INTCLR_MMU_FAULT 0x0010
+#define SIGNED_TOPAZHP_TOP_CR_INTCLR_MMU_FAULT 0
+
+#define MASK_TOPAZHP_TOP_CR_INTCLR_MMU_FAULT_B 0x1E000000
+#define SHIFT_TOPAZHP_TOP_CR_INTCLR_MMU_FAULT_B 25
+#define REGNUM_TOPAZHP_TOP_CR_INTCLR_MMU_FAULT_B 0x0010
+#define SIGNED_TOPAZHP_TOP_CR_INTCLR_MMU_FAULT_B 0
+
+/* Register CR_TOPAZ_CMD_FIFO_FLUSH */
+#define TOPAZHP_TOP_CR_TOPAZ_CMD_FIFO_FLUSH 0x0078
+#define MASK_TOPAZHP_TOP_CR_CMD_FIFO_FLUSH 0x00000001
+#define SHIFT_TOPAZHP_TOP_CR_CMD_FIFO_FLUSH 0
+#define REGNUM_TOPAZHP_TOP_CR_CMD_FIFO_FLUSH 0x0078
+#define SIGNED_TOPAZHP_TOP_CR_CMD_FIFO_FLUSH 0
+
+/* Register CR_MULTICORE_CMD_FIFO_WRITE */
+#define TOPAZHP_TOP_CR_MULTICORE_CMD_FIFO_WRITE 0x0060
+#define MASK_TOPAZHP_TOP_CR_CMD_FIFO_WDATA 0xFFFFFFFF
+#define SHIFT_TOPAZHP_TOP_CR_CMD_FIFO_WDATA 0
+#define REGNUM_TOPAZHP_TOP_CR_CMD_FIFO_WDATA 0x0060
+#define SIGNED_TOPAZHP_TOP_CR_CMD_FIFO_WDATA 0
+
+/* Register CR_MULTICORE_CMD_FIFO_WRITE_SPACE */
+#define TOPAZHP_TOP_CR_MULTICORE_CMD_FIFO_WRITE_SPACE 0x0064
+#define MASK_TOPAZHP_TOP_CR_CMD_FIFO_SPACE 0x000000FF
+#define SHIFT_TOPAZHP_TOP_CR_CMD_FIFO_SPACE 0
+#define REGNUM_TOPAZHP_TOP_CR_CMD_FIFO_SPACE 0x0064
+#define SIGNED_TOPAZHP_TOP_CR_CMD_FIFO_SPACE 0
+
+#define MASK_TOPAZHP_TOP_CR_CMD_FIFO_FULL 0x00000100
+#define SHIFT_TOPAZHP_TOP_CR_CMD_FIFO_FULL 8
+#define REGNUM_TOPAZHP_TOP_CR_CMD_FIFO_FULL 0x0064
+#define SIGNED_TOPAZHP_TOP_CR_CMD_FIFO_FULL 0
+
+/* Register CR_MULTICORE_IDLE_PWR_MAN */
+#define TOPAZHP_TOP_CR_MULTICORE_IDLE_PWR_MAN 0x0118
+#define MASK_TOPAZHP_TOP_CR_TOPAZ_IDLE_DISABLE 0x00000001
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZ_IDLE_DISABLE 0
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZ_IDLE_DISABLE 0x0118
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZ_IDLE_DISABLE 0
+
+/* Register CR_FIRMWARE_REG_1 */
+#define TOPAZHP_TOP_CR_FIRMWARE_REG_1 0x0100
+#define MASK_TOPAZHP_TOP_CR_FIRMWARE_REG_1 0xFFFFFFFF
+#define SHIFT_TOPAZHP_TOP_CR_FIRMWARE_REG_1 0
+#define REGNUM_TOPAZHP_TOP_CR_FIRMWARE_REG_1 0x0100
+#define SIGNED_TOPAZHP_TOP_CR_FIRMWARE_REG_1 0
+
+/* Register CR_FIRMWARE_REG_2 */
+#define TOPAZHP_TOP_CR_FIRMWARE_REG_2 0x0104
+#define MASK_TOPAZHP_TOP_CR_FIRMWARE_REG_2 0xFFFFFFFF
+#define SHIFT_TOPAZHP_TOP_CR_FIRMWARE_REG_2 0
+#define REGNUM_TOPAZHP_TOP_CR_FIRMWARE_REG_2 0x0104
+#define SIGNED_TOPAZHP_TOP_CR_FIRMWARE_REG_2 0
+
+/* Register CR_FIRMWARE_REG_3 */
+#define TOPAZHP_TOP_CR_FIRMWARE_REG_3 0x0108
+#define MASK_TOPAZHP_TOP_CR_FIRMWARE_REG_3 0xFFFFFFFF
+#define SHIFT_TOPAZHP_TOP_CR_FIRMWARE_REG_3 0
+#define REGNUM_TOPAZHP_TOP_CR_FIRMWARE_REG_3 0x0108
+#define SIGNED_TOPAZHP_TOP_CR_FIRMWARE_REG_3 0
+
+/* Register CR_FIRMWARE_REG_4 */
+#define TOPAZHP_TOP_CR_FIRMWARE_REG_4 0x0300
+#define MASK_TOPAZHP_TOP_CR_FIRMWARE_REG_4 0xFFFFFFFF
+#define SHIFT_TOPAZHP_TOP_CR_FIRMWARE_REG_4 0
+#define REGNUM_TOPAZHP_TOP_CR_FIRMWARE_REG_4 0x0300
+#define SIGNED_TOPAZHP_TOP_CR_FIRMWARE_REG_4 0
+
+/* Register CR_FIRMWARE_REG_5 */
+#define TOPAZHP_TOP_CR_FIRMWARE_REG_5 0x0304
+#define MASK_TOPAZHP_TOP_CR_FIRMWARE_REG_5 0xFFFFFFFF
+#define SHIFT_TOPAZHP_TOP_CR_FIRMWARE_REG_5 0
+#define REGNUM_TOPAZHP_TOP_CR_FIRMWARE_REG_5 0x0304
+#define SIGNED_TOPAZHP_TOP_CR_FIRMWARE_REG_5 0
+
+/* Register CR_FIRMWARE_REG_6 */
+#define TOPAZHP_TOP_CR_FIRMWARE_REG_6 0x0308
+#define MASK_TOPAZHP_TOP_CR_FIRMWARE_REG_6 0xFFFFFFFF
+#define SHIFT_TOPAZHP_TOP_CR_FIRMWARE_REG_6 0
+#define REGNUM_TOPAZHP_TOP_CR_FIRMWARE_REG_6 0x0308
+#define SIGNED_TOPAZHP_TOP_CR_FIRMWARE_REG_6 0
+
+/* Register CR_FIRMWARE_REG_7 */
+#define TOPAZHP_TOP_CR_FIRMWARE_REG_7 0x030C
+#define MASK_TOPAZHP_TOP_CR_FIRMWARE_REG_7 0xFFFFFFFF
+#define SHIFT_TOPAZHP_TOP_CR_FIRMWARE_REG_7 0
+#define REGNUM_TOPAZHP_TOP_CR_FIRMWARE_REG_7 0x030C
+#define SIGNED_TOPAZHP_TOP_CR_FIRMWARE_REG_7 0
+
+/* Register CR_MTX_DEBUG_MSTR */
+#define TOPAZHP_TOP_CR_MTX_DEBUG_MSTR 0x0044
+#define MASK_TOPAZHP_TOP_CR_MTX_MSTR_DBG_GPIO_IN 0x00000003
+#define SHIFT_TOPAZHP_TOP_CR_MTX_MSTR_DBG_GPIO_IN 0
+#define REGNUM_TOPAZHP_TOP_CR_MTX_MSTR_DBG_GPIO_IN 0x0044
+#define SIGNED_TOPAZHP_TOP_CR_MTX_MSTR_DBG_GPIO_IN 0
+
+#define MASK_TOPAZHP_TOP_CR_MTX_MSTR_DBG_IS_SLAVE 0x00000004
+#define SHIFT_TOPAZHP_TOP_CR_MTX_MSTR_DBG_IS_SLAVE 2
+#define REGNUM_TOPAZHP_TOP_CR_MTX_MSTR_DBG_IS_SLAVE 0x0044
+#define SIGNED_TOPAZHP_TOP_CR_MTX_MSTR_DBG_IS_SLAVE 0
+
+#define MASK_TOPAZHP_TOP_CR_MTX_MSTR_DBG_GPIO_OUT 0x00000018
+#define SHIFT_TOPAZHP_TOP_CR_MTX_MSTR_DBG_GPIO_OUT 3
+#define REGNUM_TOPAZHP_TOP_CR_MTX_MSTR_DBG_GPIO_OUT 0x0044
+#define SIGNED_TOPAZHP_TOP_CR_MTX_MSTR_DBG_GPIO_OUT 0
+
+#define MASK_TOPAZHP_TOP_CR_MTX_MSTR_RAM_BANKS 0x00000F00
+#define SHIFT_TOPAZHP_TOP_CR_MTX_MSTR_RAM_BANKS 8
+#define REGNUM_TOPAZHP_TOP_CR_MTX_MSTR_RAM_BANKS 0x0044
+#define SIGNED_TOPAZHP_TOP_CR_MTX_MSTR_RAM_BANKS 0
+
+#define MASK_TOPAZHP_TOP_CR_MTX_MSTR_RAM_BANK_SIZE 0x000F0000
+#define SHIFT_TOPAZHP_TOP_CR_MTX_MSTR_RAM_BANK_SIZE 16
+#define REGNUM_TOPAZHP_TOP_CR_MTX_MSTR_RAM_BANK_SIZE 0x0044
+#define SIGNED_TOPAZHP_TOP_CR_MTX_MSTR_RAM_BANK_SIZE 0
+
+#define MASK_TOPAZHP_TOP_CR_MTX_MSTR_LAST_RAM_BANK_SIZE 0x0F000000
+#define SHIFT_TOPAZHP_TOP_CR_MTX_MSTR_LAST_RAM_BANK_SIZE 24
+#define REGNUM_TOPAZHP_TOP_CR_MTX_MSTR_LAST_RAM_BANK_SIZE 0x0044
+#define SIGNED_TOPAZHP_TOP_CR_MTX_MSTR_LAST_RAM_BANK_SIZE 0
+
+/* Register CR_MULTICORE_CORE_SEL_0 */
+#define TOPAZHP_TOP_CR_MULTICORE_CORE_SEL_0 0x0050
+#define MASK_TOPAZHP_TOP_CR_DMAC_MTX_SELECT 0x00000007
+#define SHIFT_TOPAZHP_TOP_CR_DMAC_MTX_SELECT 0
+#define REGNUM_TOPAZHP_TOP_CR_DMAC_MTX_SELECT 0x0050
+#define SIGNED_TOPAZHP_TOP_CR_DMAC_MTX_SELECT 0
+
+#define MASK_TOPAZHP_TOP_CR_WRITES_MTX_ALL 0x40000000
+#define SHIFT_TOPAZHP_TOP_CR_WRITES_MTX_ALL 30
+#define REGNUM_TOPAZHP_TOP_CR_WRITES_MTX_ALL 0x0050
+#define SIGNED_TOPAZHP_TOP_CR_WRITES_MTX_ALL 0
+
+#define MASK_TOPAZHP_TOP_CR_WRITES_CORE_ALL 0x80000000
+#define SHIFT_TOPAZHP_TOP_CR_WRITES_CORE_ALL 31
+#define REGNUM_TOPAZHP_TOP_CR_WRITES_CORE_ALL 0x0050
+#define SIGNED_TOPAZHP_TOP_CR_WRITES_CORE_ALL 0
+
+/* Register CR_TOPAZHP_AUTO_CLOCK_GATING */
+#define TOPAZHP_CR_TOPAZHP_AUTO_CLOCK_GATING 0x0024
+#define MASK_TOPAZHP_CR_TOPAZHP_IPE0_AUTO_CLK_GATE 0x00000001
+#define SHIFT_TOPAZHP_CR_TOPAZHP_IPE0_AUTO_CLK_GATE 0
+#define REGNUM_TOPAZHP_CR_TOPAZHP_IPE0_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_IPE0_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_IPE1_AUTO_CLK_GATE 0x00000002
+#define SHIFT_TOPAZHP_CR_TOPAZHP_IPE1_AUTO_CLK_GATE 1
+#define REGNUM_TOPAZHP_CR_TOPAZHP_IPE1_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_IPE1_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_SPE0_AUTO_CLK_GATE 0x00000004
+#define SHIFT_TOPAZHP_CR_TOPAZHP_SPE0_AUTO_CLK_GATE 2
+#define REGNUM_TOPAZHP_CR_TOPAZHP_SPE0_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_SPE0_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_SPE1_AUTO_CLK_GATE 0x00000008
+#define SHIFT_TOPAZHP_CR_TOPAZHP_SPE1_AUTO_CLK_GATE 3
+#define REGNUM_TOPAZHP_CR_TOPAZHP_SPE1_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_SPE1_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_H264COMP4X4_AUTO_CLK_GATE 0x00000010
+#define SHIFT_TOPAZHP_CR_TOPAZHP_H264COMP4X4_AUTO_CLK_GATE 4
+#define REGNUM_TOPAZHP_CR_TOPAZHP_H264COMP4X4_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_H264COMP4X4_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_H264COMP8X8_AUTO_CLK_GATE 0x00000020
+#define SHIFT_TOPAZHP_CR_TOPAZHP_H264COMP8X8_AUTO_CLK_GATE 5
+#define REGNUM_TOPAZHP_CR_TOPAZHP_H264COMP8X8_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_H264COMP8X8_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_H264COMP16X16_AUTO_CLK_GATE 0x00000040
+#define SHIFT_TOPAZHP_CR_TOPAZHP_H264COMP16X16_AUTO_CLK_GATE 6
+#define REGNUM_TOPAZHP_CR_TOPAZHP_H264COMP16X16_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_H264COMP16X16_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_JMCOMP_AUTO_CLK_GATE 0x00000080
+#define SHIFT_TOPAZHP_CR_TOPAZHP_JMCOMP_AUTO_CLK_GATE 7
+#define REGNUM_TOPAZHP_CR_TOPAZHP_JMCOMP_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_JMCOMP_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_VLC_AUTO_CLK_GATE 0x00000200
+#define SHIFT_TOPAZHP_CR_TOPAZHP_VLC_AUTO_CLK_GATE 9
+#define REGNUM_TOPAZHP_CR_TOPAZHP_VLC_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_VLC_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_DEB_AUTO_CLK_GATE 0x00000400
+#define SHIFT_TOPAZHP_CR_TOPAZHP_DEB_AUTO_CLK_GATE 10
+#define REGNUM_TOPAZHP_CR_TOPAZHP_DEB_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_DEB_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_PC_DM_AUTO_CLK_GATE 0x00000800
+#define SHIFT_TOPAZHP_CR_TOPAZHP_PC_DM_AUTO_CLK_GATE 11
+#define REGNUM_TOPAZHP_CR_TOPAZHP_PC_DM_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_PC_DM_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_PC_DMS_AUTO_CLK_GATE 0x00001000
+#define SHIFT_TOPAZHP_CR_TOPAZHP_PC_DMS_AUTO_CLK_GATE 12
+#define REGNUM_TOPAZHP_CR_TOPAZHP_PC_DMS_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_PC_DMS_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_CABAC_AUTO_CLK_GATE 0x00002000
+#define SHIFT_TOPAZHP_CR_TOPAZHP_CABAC_AUTO_CLK_GATE 13
+#define REGNUM_TOPAZHP_CR_TOPAZHP_CABAC_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_CABAC_AUTO_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_INPUT_SCALER_AUTO_CLK_GATE 0x00008000
+#define SHIFT_TOPAZHP_CR_TOPAZHP_INPUT_SCALER_AUTO_CLK_GATE 15
+#define REGNUM_TOPAZHP_CR_TOPAZHP_INPUT_SCALER_AUTO_CLK_GATE 0x0024
+#define SIGNED_TOPAZHP_CR_TOPAZHP_INPUT_SCALER_AUTO_CLK_GATE 0
+
+/* Register CR_TOPAZHP_MAN_CLOCK_GATING */
+#define TOPAZHP_CR_TOPAZHP_MAN_CLOCK_GATING 0x0028
+#define MASK_TOPAZHP_CR_TOPAZHP_IPE0_MAN_CLK_GATE 0x00000001
+#define SHIFT_TOPAZHP_CR_TOPAZHP_IPE0_MAN_CLK_GATE 0
+#define REGNUM_TOPAZHP_CR_TOPAZHP_IPE0_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_IPE0_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_IPE1_MAN_CLK_GATE 0x00000002
+#define SHIFT_TOPAZHP_CR_TOPAZHP_IPE1_MAN_CLK_GATE 1
+#define REGNUM_TOPAZHP_CR_TOPAZHP_IPE1_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_IPE1_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_SPE0_MAN_CLK_GATE 0x00000004
+#define SHIFT_TOPAZHP_CR_TOPAZHP_SPE0_MAN_CLK_GATE 2
+#define REGNUM_TOPAZHP_CR_TOPAZHP_SPE0_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_SPE0_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_SPE1_MAN_CLK_GATE 0x00000008
+#define SHIFT_TOPAZHP_CR_TOPAZHP_SPE1_MAN_CLK_GATE 3
+#define REGNUM_TOPAZHP_CR_TOPAZHP_SPE1_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_SPE1_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_H264COMP4X4_MAN_CLK_GATE 0x00000010
+#define SHIFT_TOPAZHP_CR_TOPAZHP_H264COMP4X4_MAN_CLK_GATE 4
+#define REGNUM_TOPAZHP_CR_TOPAZHP_H264COMP4X4_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_H264COMP4X4_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_H264COMP8X8_MAN_CLK_GATE 0x00000020
+#define SHIFT_TOPAZHP_CR_TOPAZHP_H264COMP8X8_MAN_CLK_GATE 5
+#define REGNUM_TOPAZHP_CR_TOPAZHP_H264COMP8X8_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_H264COMP8X8_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_H264COMP16X16_MAN_CLK_GATE 0x00000040
+#define SHIFT_TOPAZHP_CR_TOPAZHP_H264COMP16X16_MAN_CLK_GATE 6
+#define REGNUM_TOPAZHP_CR_TOPAZHP_H264COMP16X16_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_H264COMP16X16_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_JMCOMP_MAN_CLK_GATE 0x00000080
+#define SHIFT_TOPAZHP_CR_TOPAZHP_JMCOMP_MAN_CLK_GATE 7
+#define REGNUM_TOPAZHP_CR_TOPAZHP_JMCOMP_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_JMCOMP_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_PREFETCH_MAN_CLK_GATE 0x00000100
+#define SHIFT_TOPAZHP_CR_TOPAZHP_PREFETCH_MAN_CLK_GATE 8
+#define REGNUM_TOPAZHP_CR_TOPAZHP_PREFETCH_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_PREFETCH_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_VLC_MAN_CLK_GATE 0x00000200
+#define SHIFT_TOPAZHP_CR_TOPAZHP_VLC_MAN_CLK_GATE 9
+#define REGNUM_TOPAZHP_CR_TOPAZHP_VLC_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_VLC_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_DEB_MAN_CLK_GATE 0x00000400
+#define SHIFT_TOPAZHP_CR_TOPAZHP_DEB_MAN_CLK_GATE 10
+#define REGNUM_TOPAZHP_CR_TOPAZHP_DEB_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_DEB_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_PC_DM_MAN_CLK_GATE 0x00000800
+#define SHIFT_TOPAZHP_CR_TOPAZHP_PC_DM_MAN_CLK_GATE 11
+#define REGNUM_TOPAZHP_CR_TOPAZHP_PC_DM_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_PC_DM_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_PC_DMS_MAN_CLK_GATE 0x00001000
+#define SHIFT_TOPAZHP_CR_TOPAZHP_PC_DMS_MAN_CLK_GATE 12
+#define REGNUM_TOPAZHP_CR_TOPAZHP_PC_DMS_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_PC_DMS_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_CABAC_MAN_CLK_GATE 0x00002000
+#define SHIFT_TOPAZHP_CR_TOPAZHP_CABAC_MAN_CLK_GATE 13
+#define REGNUM_TOPAZHP_CR_TOPAZHP_CABAC_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_CABAC_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_LRITC_MAN_CLK_GATE 0x00004000
+#define SHIFT_TOPAZHP_CR_TOPAZHP_LRITC_MAN_CLK_GATE 14
+#define REGNUM_TOPAZHP_CR_TOPAZHP_LRITC_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_LRITC_MAN_CLK_GATE 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_INPUT_SCALER_MAN_CLK_GATE 0x00008000
+#define SHIFT_TOPAZHP_CR_TOPAZHP_INPUT_SCALER_MAN_CLK_GATE 15
+#define REGNUM_TOPAZHP_CR_TOPAZHP_INPUT_SCALER_MAN_CLK_GATE 0x0028
+#define SIGNED_TOPAZHP_CR_TOPAZHP_INPUT_SCALER_MAN_CLK_GATE 0
+
+/* Register CR_TOPAZHP_SRST */
+#define TOPAZHP_CR_TOPAZHP_SRST     0x0000
+#define MASK_TOPAZHP_CR_TOPAZHP_IPE_SOFT_RESET 0x00000001
+#define SHIFT_TOPAZHP_CR_TOPAZHP_IPE_SOFT_RESET 0
+#define REGNUM_TOPAZHP_CR_TOPAZHP_IPE_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_CR_TOPAZHP_IPE_SOFT_RESET 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_SPE_SOFT_RESET 0x00000002
+#define SHIFT_TOPAZHP_CR_TOPAZHP_SPE_SOFT_RESET 1
+#define REGNUM_TOPAZHP_CR_TOPAZHP_SPE_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_CR_TOPAZHP_SPE_SOFT_RESET 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_PC_SOFT_RESET 0x00000004
+#define SHIFT_TOPAZHP_CR_TOPAZHP_PC_SOFT_RESET 2
+#define REGNUM_TOPAZHP_CR_TOPAZHP_PC_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_CR_TOPAZHP_PC_SOFT_RESET 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_H264COMP_SOFT_RESET 0x00000008
+#define SHIFT_TOPAZHP_CR_TOPAZHP_H264COMP_SOFT_RESET 3
+#define REGNUM_TOPAZHP_CR_TOPAZHP_H264COMP_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_CR_TOPAZHP_H264COMP_SOFT_RESET 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_JMCOMP_SOFT_RESET 0x00000010
+#define SHIFT_TOPAZHP_CR_TOPAZHP_JMCOMP_SOFT_RESET 4
+#define REGNUM_TOPAZHP_CR_TOPAZHP_JMCOMP_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_CR_TOPAZHP_JMCOMP_SOFT_RESET 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_PREFETCH_SOFT_RESET 0x00000020
+#define SHIFT_TOPAZHP_CR_TOPAZHP_PREFETCH_SOFT_RESET 5
+#define REGNUM_TOPAZHP_CR_TOPAZHP_PREFETCH_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_CR_TOPAZHP_PREFETCH_SOFT_RESET 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_VLC_SOFT_RESET 0x00000040
+#define SHIFT_TOPAZHP_CR_TOPAZHP_VLC_SOFT_RESET 6
+#define REGNUM_TOPAZHP_CR_TOPAZHP_VLC_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_CR_TOPAZHP_VLC_SOFT_RESET 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_DB_SOFT_RESET 0x00000080
+#define SHIFT_TOPAZHP_CR_TOPAZHP_DB_SOFT_RESET 7
+#define REGNUM_TOPAZHP_CR_TOPAZHP_DB_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_CR_TOPAZHP_DB_SOFT_RESET 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_LTRITC_SOFT_RESET 0x00000100
+#define SHIFT_TOPAZHP_CR_TOPAZHP_LTRITC_SOFT_RESET 8
+#define REGNUM_TOPAZHP_CR_TOPAZHP_LTRITC_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_CR_TOPAZHP_LTRITC_SOFT_RESET 0
+
+#define MASK_TOPAZHP_CR_TOPAZHP_SCALER_SOFT_RESET 0x00000200
+#define SHIFT_TOPAZHP_CR_TOPAZHP_SCALER_SOFT_RESET 9
+#define REGNUM_TOPAZHP_CR_TOPAZHP_SCALER_SOFT_RESET 0x0000
+#define SIGNED_TOPAZHP_CR_TOPAZHP_SCALER_SOFT_RESET 0
+
+/* Register CR_MMU_STATUS */
+#define TOPAZHP_TOP_CR_MMU_STATUS   0x001C
+#define MASK_TOPAZHP_TOP_CR_MMU_PF_N_RW 0x00000001
+#define SHIFT_TOPAZHP_TOP_CR_MMU_PF_N_RW 0
+#define REGNUM_TOPAZHP_TOP_CR_MMU_PF_N_RW 0x001C
+#define SIGNED_TOPAZHP_TOP_CR_MMU_PF_N_RW 0
+
+#define MASK_TOPAZHP_TOP_CR_MMU_FAULT_ADDR 0xFFFFF000
+#define SHIFT_TOPAZHP_TOP_CR_MMU_FAULT_ADDR 12
+#define REGNUM_TOPAZHP_TOP_CR_MMU_FAULT_ADDR 0x001C
+#define SIGNED_TOPAZHP_TOP_CR_MMU_FAULT_ADDR 0
+
+/* Register CR_MMU_MEM_REQ */
+#define TOPAZHP_TOP_CR_MMU_MEM_REQ  0x0020
+#define MASK_TOPAZHP_TOP_CR_MEM_REQ_STAT_READS 0x000000FF
+#define SHIFT_TOPAZHP_TOP_CR_MEM_REQ_STAT_READS 0
+#define REGNUM_TOPAZHP_TOP_CR_MEM_REQ_STAT_READS 0x0020
+#define SIGNED_TOPAZHP_TOP_CR_MEM_REQ_STAT_READS 0
+
+/* Register CR_MMU_CONTROL0 */
+#define TOPAZHP_TOP_CR_MMU_CONTROL0 0x0024
+#define MASK_TOPAZHP_TOP_CR_MMU_NOREORDER 0x00000001
+#define SHIFT_TOPAZHP_TOP_CR_MMU_NOREORDER 0
+#define REGNUM_TOPAZHP_TOP_CR_MMU_NOREORDER 0x0024
+#define SIGNED_TOPAZHP_TOP_CR_MMU_NOREORDER 0
+
+#define MASK_TOPAZHP_TOP_CR_MMU_PAUSE 0x00000002
+#define SHIFT_TOPAZHP_TOP_CR_MMU_PAUSE 1
+#define REGNUM_TOPAZHP_TOP_CR_MMU_PAUSE 0x0024
+#define SIGNED_TOPAZHP_TOP_CR_MMU_PAUSE 0
+
+#define MASK_TOPAZHP_TOP_CR_MMU_FLUSH 0x00000004
+#define SHIFT_TOPAZHP_TOP_CR_MMU_FLUSH 2
+#define REGNUM_TOPAZHP_TOP_CR_MMU_FLUSH 0x0024
+#define SIGNED_TOPAZHP_TOP_CR_MMU_FLUSH 0
+
+#define MASK_TOPAZHP_TOP_CR_MMU_INVALDC 0x00000008
+#define SHIFT_TOPAZHP_TOP_CR_MMU_INVALDC 3
+#define REGNUM_TOPAZHP_TOP_CR_MMU_INVALDC 0x0024
+#define SIGNED_TOPAZHP_TOP_CR_MMU_INVALDC 0
+
+#define MASK_TOPAZHP_TOP_CR_FLOWRATE_TOPAZ 0x00000700
+#define SHIFT_TOPAZHP_TOP_CR_FLOWRATE_TOPAZ 8
+#define REGNUM_TOPAZHP_TOP_CR_FLOWRATE_TOPAZ 0x0024
+#define SIGNED_TOPAZHP_TOP_CR_FLOWRATE_TOPAZ 0
+
+#define MASK_TOPAZHP_TOP_CR_MMU_BYPASS_TOPAZ 0x00010000
+#define SHIFT_TOPAZHP_TOP_CR_MMU_BYPASS_TOPAZ 16
+#define REGNUM_TOPAZHP_TOP_CR_MMU_BYPASS_TOPAZ 0x0024
+#define SIGNED_TOPAZHP_TOP_CR_MMU_BYPASS_TOPAZ 0
+
+/* Register CR_MMU_CONTROL1 */
+#define TOPAZHP_TOP_CR_MMU_CONTROL1 0x0028
+#define MASK_TOPAZHP_TOP_CR_MMU_TTE_THRESHOLD 0x00000FFF
+#define SHIFT_TOPAZHP_TOP_CR_MMU_TTE_THRESHOLD 0
+#define REGNUM_TOPAZHP_TOP_CR_MMU_TTE_THRESHOLD 0x0028
+#define SIGNED_TOPAZHP_TOP_CR_MMU_TTE_THRESHOLD 0
+
+#define MASK_TOPAZHP_TOP_CR_MMU_ADT_TTE 0x000FF000
+#define SHIFT_TOPAZHP_TOP_CR_MMU_ADT_TTE 12
+#define REGNUM_TOPAZHP_TOP_CR_MMU_ADT_TTE 0x0028
+#define SIGNED_TOPAZHP_TOP_CR_MMU_ADT_TTE 0
+
+#define MASK_TOPAZHP_TOP_CR_MMU_BEST_COUNT 0x0FF00000
+#define SHIFT_TOPAZHP_TOP_CR_MMU_BEST_COUNT 20
+#define REGNUM_TOPAZHP_TOP_CR_MMU_BEST_COUNT 0x0028
+#define SIGNED_TOPAZHP_TOP_CR_MMU_BEST_COUNT 0
+
+#define MASK_TOPAZHP_TOP_CR_MMU_PAGE_SIZE 0xF0000000
+#define SHIFT_TOPAZHP_TOP_CR_MMU_PAGE_SIZE 28
+#define REGNUM_TOPAZHP_TOP_CR_MMU_PAGE_SIZE 0x0028
+#define SIGNED_TOPAZHP_TOP_CR_MMU_PAGE_SIZE 0
+
+/* Register CR_MMU_CONTROL2 */
+#define TOPAZHP_TOP_CR_MMU_CONTROL2 0x002C
+#define MASK_TOPAZHP_TOP_CR_MMU_ENABLE_36BIT_ADDRESSING 0x00000001
+#define SHIFT_TOPAZHP_TOP_CR_MMU_ENABLE_36BIT_ADDRESSING 0
+#define REGNUM_TOPAZHP_TOP_CR_MMU_ENABLE_36BIT_ADDRESSING 0x002C
+#define SIGNED_TOPAZHP_TOP_CR_MMU_ENABLE_36BIT_ADDRESSING 0
+
+#define MASK_TOPAZHP_TOP_CR_MMU_TILING_SCHEME 0x00000008
+#define SHIFT_TOPAZHP_TOP_CR_MMU_TILING_SCHEME 3
+#define REGNUM_TOPAZHP_TOP_CR_MMU_TILING_SCHEME 0x002C
+#define SIGNED_TOPAZHP_TOP_CR_MMU_TILING_SCHEME 0
+
+/* Table MMU_DIR_LIST_BASE */
+
+/* Register CR_MMU_DIR_LIST_BASE */
+#define TOPAZHP_TOP_CR_MMU_DIR_LIST_BASE(X) (0x0030 + (4 * (X)))
+#define MASK_TOPAZHP_TOP_CR_MMU_DIR_LIST_BASE_ADDR 0xFFFFFFF0
+#define SHIFT_TOPAZHP_TOP_CR_MMU_DIR_LIST_BASE_ADDR 4
+#define REGNUM_TOPAZHP_TOP_CR_MMU_DIR_LIST_BASE_ADDR 0x0030
+#define SIGNED_TOPAZHP_TOP_CR_MMU_DIR_LIST_BASE_ADDR 0
+
+/* Number of entries in table MMU_DIR_LIST_BASE */
+
+#define TOPAZHP_TOP_MMU_DIR_LIST_BASE_SIZE_UINT32 1
+#define TOPAZHP_TOP_MMU_DIR_LIST_BASE_NUM_ENTRIES 1
+
+/* Table MMU_TILE */
+
+/* Register CR_MMU_TILE */
+#define TOPAZHP_TOP_CR_MMU_TILE(X)  (0x0038 + (4 * (X)))
+#define MASK_TOPAZHP_TOP_CR_TILE_MIN_ADDR 0x00000FFF
+#define SHIFT_TOPAZHP_TOP_CR_TILE_MIN_ADDR 0
+#define REGNUM_TOPAZHP_TOP_CR_TILE_MIN_ADDR 0x0038
+#define SIGNED_TOPAZHP_TOP_CR_TILE_MIN_ADDR 0
+
+#define MASK_TOPAZHP_TOP_CR_TILE_MAX_ADDR 0x00FFF000
+#define SHIFT_TOPAZHP_TOP_CR_TILE_MAX_ADDR 12
+#define REGNUM_TOPAZHP_TOP_CR_TILE_MAX_ADDR 0x0038
+#define SIGNED_TOPAZHP_TOP_CR_TILE_MAX_ADDR 0
+
+#define MASK_TOPAZHP_TOP_CR_TILE_STRIDE 0x07000000
+#define SHIFT_TOPAZHP_TOP_CR_TILE_STRIDE 24
+#define REGNUM_TOPAZHP_TOP_CR_TILE_STRIDE 0x0038
+#define SIGNED_TOPAZHP_TOP_CR_TILE_STRIDE 0
+
+#define MASK_TOPAZHP_TOP_CR_TILE_ENABLE 0x10000000
+#define SHIFT_TOPAZHP_TOP_CR_TILE_ENABLE 28
+#define REGNUM_TOPAZHP_TOP_CR_TILE_ENABLE 0x0038
+#define SIGNED_TOPAZHP_TOP_CR_TILE_ENABLE 0
+
+#define MASK_TOPAZHP_TOP_CR_TILE_128BYTE_INTERLEAVE 0x20000000
+#define SHIFT_TOPAZHP_TOP_CR_TILE_128BYTE_INTERLEAVE 29
+#define REGNUM_TOPAZHP_TOP_CR_TILE_128BYTE_INTERLEAVE 0x0038
+#define SIGNED_TOPAZHP_TOP_CR_TILE_128BYTE_INTERLEAVE 0
+
+/* Number of entries in table MMU_TILE */
+
+#define TOPAZHP_TOP_MMU_TILE_SIZE_UINT32 2
+#define TOPAZHP_TOP_MMU_TILE_NUM_ENTRIES 2
+
+/* Table MMU_TILE_EXT */
+
+/* Register CR_MMU_TILE_EXT */
+#define TOPAZHP_TOP_CR_MMU_TILE_EXT(X) (0x0080 + (4 * (X)))
+#define MASK_TOPAZHP_TOP_CR_TILE_MIN_ADDR_EXT 0x000000FF
+#define SHIFT_TOPAZHP_TOP_CR_TILE_MIN_ADDR_EXT 0
+#define REGNUM_TOPAZHP_TOP_CR_TILE_MIN_ADDR_EXT 0x0080
+#define SIGNED_TOPAZHP_TOP_CR_TILE_MIN_ADDR_EXT 0
+
+#define MASK_TOPAZHP_TOP_CR_TILE_MAX_ADDR_EXT 0x0000FF00
+#define SHIFT_TOPAZHP_TOP_CR_TILE_MAX_ADDR_EXT 8
+#define REGNUM_TOPAZHP_TOP_CR_TILE_MAX_ADDR_EXT 0x0080
+#define SIGNED_TOPAZHP_TOP_CR_TILE_MAX_ADDR_EXT 0
+
+/* Number of entries in table MMU_TILE_EXT */
+
+#define TOPAZHP_TOP_MMU_TILE_EXT_SIZE_UINT32 2
+#define TOPAZHP_TOP_MMU_TILE_EXT_NUM_ENTRIES 2
+
+#define TOPAZHP_CR_PROC_ESB_ACCESS_WORD0 0x00F0
+
+/* Register CR_PROC_ESB_ACCESS_CONTROL */
+#define TOPAZHP_CR_PROC_ESB_ACCESS_CONTROL 0x00EC
+#define MASK_TOPAZHP_CR_PROC_ESB_ADDR 0x00003FF0
+#define SHIFT_TOPAZHP_CR_PROC_ESB_ADDR 4
+#define REGNUM_TOPAZHP_CR_PROC_ESB_ADDR 0x00EC
+#define SIGNED_TOPAZHP_CR_PROC_ESB_ADDR 0
+
+#define MASK_TOPAZHP_CR_PROC_ESB_READ_N_WRITE 0x00010000
+#define SHIFT_TOPAZHP_CR_PROC_ESB_READ_N_WRITE 16
+#define REGNUM_TOPAZHP_CR_PROC_ESB_READ_N_WRITE 0x00EC
+#define SIGNED_TOPAZHP_CR_PROC_ESB_READ_N_WRITE 0
+
+#define MASK_TOPAZHP_CR_PROC_ESB_OP_VALID 0x00020000
+#define SHIFT_TOPAZHP_CR_PROC_ESB_OP_VALID 17
+#define REGNUM_TOPAZHP_CR_PROC_ESB_OP_VALID 0x00EC
+#define SIGNED_TOPAZHP_CR_PROC_ESB_OP_VALID 0
+
+#define MASK_TOPAZHP_CR_PROC_ACCESS_FLAG 0x03000000
+#define SHIFT_TOPAZHP_CR_PROC_ACCESS_FLAG 24
+#define REGNUM_TOPAZHP_CR_PROC_ACCESS_FLAG 0x00EC
+#define SIGNED_TOPAZHP_CR_PROC_ACCESS_FLAG 0
+
+/* Register CR_SECURE_CONFIG */
+#define TOPAZHP_TOP_CR_SECURE_CONFIG 0x0200
+
+/* Register CR_VLC_MPEG4_CFG */
+#define TOPAZ_VLC_CR_VLC_MPEG4_CFG  0x0064
+#define MASK_TOPAZ_VLC_CR_RSIZE     0x00000007
+#define SHIFT_TOPAZ_VLC_CR_RSIZE    0
+#define REGNUM_TOPAZ_VLC_CR_RSIZE   0x0064
+#define SIGNED_TOPAZ_VLC_CR_RSIZE   0
+
+/* RC Config registers and tables */
+#define TOPAZHP_TOP_CR_RC_CONFIG_TABLE7 0x012C
+#define TOPAZHP_TOP_CR_RC_CONFIG_TABLE6 0x0124
+#define TOPAZHP_TOP_CR_RC_CONFIG_TABLE4 0x0128
+#define TOPAZHP_TOP_CR_RC_CONFIG_TABLE5 0x0130
+#define TOPAZHP_CR_RC_CONFIG_REG8       0x0344
+#define TOPAZHP_CR_RC_CONFIG_REG9       0x0184
+#define TOPAZHP_CR_JMCOMP_RC_STATS      0x0340
+
+/* Register CR_TOPAZHP_CORE_DES1 */
+#define TOPAZHP_TOP_CR_TOPAZHP_CORE_DES1 0x03E0
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_SCALER_SUPPORTED 0x00000080
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_SCALER_SUPPORTED 7
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_SCALER_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_SCALER_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_GENERATE_PERFORMANCE_STORE 0x00000100
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_GENERATE_PERFORMANCE_STORE 8
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_GENERATE_PERFORMANCE_STORE 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_GENERATE_PERFORMANCE_STORE 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_LOSSLESS_SUPPORTED 0x00000200
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_LOSSLESS_SUPPORTED 9
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_LOSSLESS_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_LOSSLESS_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_CUSTOM_QUANT_SUPPORTED 0x00000400
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_CUSTOM_QUANT_SUPPORTED 10
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_CUSTOM_QUANT_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_CUSTOM_QUANT_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_MPEG2_SUPPORTED 0x00000800
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_MPEG2_SUPPORTED 11
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_MPEG2_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_MPEG2_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_SIGNATURES_SUPPORTED_SUBSET 0x00001000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_SIGNATURES_SUPPORTED_SUBSET 12
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_SIGNATURES_SUPPORTED_SUBSET 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_SIGNATURES_SUPPORTED_SUBSET 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_SIGNATURES_SUPPORTED_ALL 0x00002000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_SIGNATURES_SUPPORTED_ALL 13
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_SIGNATURES_SUPPORTED_ALL 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_SIGNATURES_SUPPORTED_ALL 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_WEIGHTED_PRED_ME_SUPPORTED 0x00004000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_WEIGHTED_PRED_ME_SUPPORTED 14
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_WEIGHTED_PRED_ME_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_WEIGHTED_PRED_ME_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_WEIGHTED_PRED_SUPPORTED 0x00008000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_WEIGHTED_PRED_SUPPORTED 15
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_WEIGHTED_PRED_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_WEIGHTED_PRED_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_2_REF_ON_P_PIC_SUPPORTED 0x00010000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_2_REF_ON_P_PIC_SUPPORTED 16
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_2_REF_ON_P_PIC_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_2_REF_ON_P_PIC_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_SPATIAL_DIRECT_SUPPORTED 0x00020000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_SPATIAL_DIRECT_SUPPORTED 17
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_SPATIAL_DIRECT_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_SPATIAL_DIRECT_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_MULTIPASS_SUPPORTED 0x00040000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_MULTIPASS_SUPPORTED 18
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_MULTIPASS_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_MULTIPASS_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_DEFAULT_TABLES_SUPPORTED 0x00080000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_DEFAULT_TABLES_SUPPORTED 19
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_DEFAULT_TABLES_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_DEFAULT_TABLES_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_8X8_TRANSFORM_SUPPORTED 0x00100000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_8X8_TRANSFORM_SUPPORTED 20
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_8X8_TRANSFORM_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_8X8_TRANSFORM_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_INTERLACED_SUPPORTED 0x00200000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_INTERLACED_SUPPORTED 21
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_INTERLACED_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_INTERLACED_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_B_PIC_SUPPORTED 0x00400000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_B_PIC_SUPPORTED 22
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_B_PIC_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_B_PIC_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_16X8_8X16_SUPPORTED 0x00800000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_16X8_8X16_SUPPORTED 23
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_16X8_8X16_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_16X8_8X16_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_CABAC_SUPPORTED 0x01000000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_CABAC_SUPPORTED 24
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_CABAC_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_CABAC_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_SLAVE_JPEG_SUPPORTED 0x02000000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_SLAVE_JPEG_SUPPORTED 25
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_SLAVE_JPEG_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_SLAVE_JPEG_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_JPEG_SUPPORTED 0x04000000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_JPEG_SUPPORTED 26
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_JPEG_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_JPEG_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H263_SUPPORTED 0x08000000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H263_SUPPORTED 27
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H263_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H263_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_MPEG4_SUPPORTED 0x10000000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_MPEG4_SUPPORTED 28
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_MPEG4_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_MPEG4_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_H264_SUPPORTED 0x20000000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_H264_SUPPORTED 29
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_H264_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_H264_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_DMAC_SUPPORTED 0x40000000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_DMAC_SUPPORTED 30
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_DMAC_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_DMAC_SUPPORTED 0
+
+#define MASK_TOPAZHP_TOP_CR_TOPAZHP_MMU_SUPPORTED 0x80000000
+#define SHIFT_TOPAZHP_TOP_CR_TOPAZHP_MMU_SUPPORTED 31
+#define REGNUM_TOPAZHP_TOP_CR_TOPAZHP_MMU_SUPPORTED 0x03E0
+#define SIGNED_TOPAZHP_TOP_CR_TOPAZHP_MMU_SUPPORTED 0
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/vxe_v4l2.c b/drivers/media/platform/img/vxe-vxd/encoder/vxe_v4l2.c
--- a/drivers/media/platform/img/vxe-vxd/encoder/vxe_v4l2.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/vxe_v4l2.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1920 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * IMG Encoder v4l2 Driver Interface function implementations
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *	David Huang <d-huang@ti.com>
+ *
+ * Re-written for upstreaming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/idr.h>
+#include <linux/slab.h>
+#include <linux/time64.h>
+#include <linux/interrupt.h>
+#include <linux/printk.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-dma-sg.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-mem2mem.h>
+
+#include "fw_headers/vxe_common.h"
+#include "img_mem_man.h"
+#include "target_config.h"
+#include "topaz_device.h"
+#include "vxe_enc.h"
+#include "vxe_v4l2.h"
+#include "img_errors.h"
+
+#define IMG_VXE_ENC_MODULE_NAME "vxe-enc"
+
+static struct heap_config vxe_enc_heap_configs[] = {
+	{
+		.type = MEM_HEAP_TYPE_UNIFIED,
+		.options.unified = {
+			.gfp_type = __GFP_DMA32 | __GFP_ZERO,
+		},
+		.to_dev_addr = NULL,
+	},
+};
+
+static struct vxe_enc_fmt vxe_enc_formats[] = {
+	{
+		.fourcc = V4L2_PIX_FMT_NV12,
+		.num_planes = 1,
+		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.fmt = IMG_CODEC_420_PL12,
+		.min_bufs = 2,
+		.size_num[0] = 3,
+		.size_den[0] = 2,
+		.bytes_pp = 1,
+		.csc_preset = IMG_CSC_NONE,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_RGB32,
+		.num_planes = 1,
+		.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE,
+		.fmt = IMG_CODEC_ABCX,
+		.min_bufs = 2,
+		.size_num[0] = 1,
+		.size_den[0] = 1,
+		.bytes_pp = 4,
+		.csc_preset = IMG_CSC_RGB_TO_601_ANALOG,
+	},
+	{
+		.fourcc = V4L2_PIX_FMT_H264,
+		.num_planes = 1,
+		.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE,
+		.std = IMG_STANDARD_H264,
+		.min_bufs = 1,
+		.size_num[0] = 1,
+		.size_den[0] = 1,
+		.bytes_pp = 1,
+		.csc_preset = IMG_CSC_NONE,
+	},
+};
+
+static struct v4l2_fract frmivals[] = {
+	{
+		.numerator = 1,
+		.denominator = 960,
+	},
+	{
+		.numerator = 1,
+		.denominator = 1,
+	},
+};
+
+static struct vxe_enc_ctx *file2ctx(struct file *file)
+{
+	return container_of(file->private_data, struct vxe_enc_ctx, fh);
+}
+
+static void vxe_eos(struct vxe_enc_ctx *ctx)
+{
+	struct v4l2_event event = {};
+	struct vb2_v4l2_buffer *vb;
+
+	event.type = V4L2_EVENT_EOS;
+	v4l2_event_queue_fh(&ctx->fh, &event);
+	/*
+	 * If a capture buffer is available, dequeue with FLAG_LAST
+	 * else, mark for next qbuf to handle
+	 */
+	if (v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) > 0) {
+		vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+		vb->flags |= V4L2_BUF_FLAG_LAST;
+		vb2_set_plane_payload(&vb->vb2_buf, 0, 0);
+		v4l2_m2m_buf_done(vb, VB2_BUF_STATE_DONE);
+	} else {
+		ctx->flag_last = TRUE;
+	}
+
+	topaz_flush_stream(ctx->topaz_str_context, ctx->last_frame_num);
+}
+
+static void vxe_return_resource(void *ctx_handle, enum vxe_cb_type type,
+				void *img_buf_ref, unsigned int size,
+	unsigned int coded_frm_cnt, enum img_frame_type frame_type)
+{
+	struct vxe_enc_ctx *ctx = ctx_handle;
+	struct device *dev = ctx->dev->dev;
+	struct vxe_buffer *buf;
+
+#ifdef ENABLE_PROFILING
+	struct timespec64 time;
+#endif
+
+	switch (type) {
+	case VXE_CB_CODED_BUFF_READY:
+		if (!img_buf_ref)
+			dev_err(dev, "VXE_CB_STRUNIT_PROCESSED had no buffer\n");
+
+		buf = container_of((struct img_coded_buffer *)img_buf_ref,
+				   struct vxe_buffer, coded_buffer);
+		vb2_set_plane_payload(&buf->buffer.vb.vb2_buf, 0, size);
+#ifdef ENABLE_PROFILING
+		ktime_get_real_ts64(&time);
+		ctx->drv_lat.end_time = timespec64_to_ns((const struct timespec64 *)&time);
+
+		pr_err("driver encode time is %llu us\n", div_s64(ctx->drv_lat.end_time -
+		       ctx->drv_lat.start_time, 1000));
+#endif
+
+		if (frame_type == IMG_INTRA_FRAME)
+			buf->buffer.vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+		else if (frame_type == IMG_INTER_P)
+			buf->buffer.vb.flags |= V4L2_BUF_FLAG_PFRAME;
+		else if (frame_type == IMG_INTER_B)
+			buf->buffer.vb.flags |= V4L2_BUF_FLAG_BFRAME;
+		else
+			buf->buffer.vb.flags |= V4L2_BUF_FLAG_KEYFRAME;
+
+		v4l2_m2m_buf_done(&buf->buffer.vb, VB2_BUF_STATE_DONE);
+
+		if ((coded_frm_cnt == ctx->last_frame_num) && (coded_frm_cnt != 0)) {
+			vxe_eos(ctx);
+			ctx->eos = TRUE;
+		}
+		if (ctx->frames_encoding < 2)
+			v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx);
+		break;
+	case VXE_CB_SRC_FRAME_RELEASE:
+		if (!img_buf_ref)
+			dev_err(dev, "VXE_CB_PICT_RELEASE had no buffer\n");
+
+		buf = container_of((struct img_frame *)img_buf_ref, struct vxe_buffer, src_frame);
+		vb2_set_plane_payload(&buf->buffer.vb.vb2_buf, 0, size);
+		v4l2_m2m_buf_done(&buf->buffer.vb, VB2_BUF_STATE_DONE);
+		ctx->frames_encoding--;
+		break;
+	case VXE_CB_ERROR_FATAL:
+		break;
+	default:
+		break;
+	}
+}
+
+static void device_run(void *priv)
+{
+	struct vxe_enc_ctx *ctx = priv;
+	struct device *dev = ctx->dev->dev;
+	struct vb2_v4l2_buffer *dst_vbuf, *src_vbuf;
+	struct vxe_buffer *buf;
+	int ret = 0;
+#ifdef ENABLE_PROFILING
+	struct timespec64 time;
+#endif
+
+	mutex_lock_nested(ctx->mutex, SUBCLASS_VXE_V4L2);
+	while (((topaz_query_empty_coded_slots(ctx->topaz_str_context) > 0) &&
+		(v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) > 0)) &&
+		((topaz_query_empty_source_slots(ctx->topaz_str_context) > 0) &&
+		(v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0))) {
+#ifdef ENABLE_PROFILING
+		ktime_get_real_ts64(&time);
+		ctx->drv_lat.start_time = timespec64_to_ns((const struct timespec64 *)&time);
+#endif
+		/*
+		 * Submit src and dst buffers one to one
+		 * Note: Will have to revisit for B frame support
+		 */
+		dst_vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+		if (!dst_vbuf)
+			dev_err(dev, "Next src buffer is null\n");
+
+		src_vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+		if (!src_vbuf)
+			dev_err(dev, "Next src buffer is null\n");
+
+		v4l2_m2m_buf_copy_metadata(src_vbuf, dst_vbuf, true);
+		dst_vbuf->vb2_buf.timestamp = src_vbuf->vb2_buf.timestamp;
+		dst_vbuf->field = V4L2_FIELD_NONE;
+		src_vbuf->field = V4L2_FIELD_NONE;
+
+		/* Handle EOS */
+		if (ctx->eos && (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) == 0)) {
+			pr_debug("%s eos found\n", __func__);
+			ret = topaz_end_of_stream(ctx->topaz_str_context, ctx->frame_num + 1);
+			if (ret)
+				dev_err(dev, "Failed to send EOS to topaz %d\n",
+					ret);
+			ctx->last_frame_num = ctx->frame_num + 1;
+		}
+
+		/* Submit coded package */
+		buf = container_of(dst_vbuf, struct vxe_buffer, buffer.vb);
+		ret = topaz_reserve_coded_package_slot(ctx->topaz_str_context);
+		if (ret)
+			dev_err(dev, "Failed to reserve coded package slot %d\n", ret);
+		ret = topaz_send_coded_package(ctx->topaz_str_context, &buf->coded_buffer);
+		if (ret)
+			dev_err(dev, "Failed to send coded package %d\n",
+				ret);
+		if (!ret)
+			ctx->available_coded_packages++;
+
+		/* Submit source frame */
+		buf = container_of(src_vbuf, struct vxe_buffer, buffer.vb);
+		ret = topaz_reserve_source_slot(ctx->topaz_str_context, &buf->src_slot_num);
+		if (ret)
+			dev_err(dev, "Failed to reserve source slot %d\n",
+				ret);
+		ret = topaz_send_source_frame(ctx->topaz_str_context, &buf->src_frame,
+					      ctx->frame_num, (unsigned long)ctx);
+		if (ret)
+			dev_err(dev, "Failed to send source frame %d\n",
+				ret);
+		ctx->frame_num++;
+		if (!ret)
+			ctx->available_source_frames++;
+	}
+
+	while ((ctx->available_source_frames > 0) && (ctx->available_coded_packages > 0)) {
+		pr_debug("Calling topaz_encode_frame #src=%d #coded=%d frames_encoding=%d\n",
+			 ctx->available_source_frames,
+			 ctx->available_coded_packages,
+			 ctx->frames_encoding);
+		ret = topaz_encode_frame(ctx->topaz_str_context);
+		if (ret) {
+			dev_err(dev, "Failed to send encode_frame command %d\n",
+				ret);
+		} else {
+			/* TODO: Account for scenarios where these are not 1 */
+			ctx->available_source_frames--;
+			ctx->available_coded_packages--;
+			ctx->frames_encoding++;
+		}
+	}
+
+	mutex_unlock((struct mutex *)ctx->mutex);
+}
+
+static int job_ready(void *priv)
+{
+	struct vxe_enc_ctx *ctx = priv;
+
+	/*
+	 * In normal play, check if we can
+	 * submit any source or coded buffers
+	 */
+	if (((topaz_query_empty_source_slots(ctx->topaz_str_context) > 0) &&
+	     (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0)) &&
+	    ((topaz_query_empty_coded_slots(ctx->topaz_str_context) > 0) &&
+	    (v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) > 0)) && ctx->core_streaming)
+		return 1;
+
+	/*
+	 * In EOS state, we only need to know
+	 * that coded buffers are available
+	 */
+	if (ctx->eos && (v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) > 0) &&
+	    (topaz_query_empty_coded_slots(ctx->topaz_str_context) > 0) && ctx->core_streaming)
+		return 1;
+
+	/*
+	 * Since we're allowing device_run for both submissions and actual
+	 * encodes, say job ready if buffers are ready in fw
+	 */
+	if (ctx->available_source_frames > 0 && ctx->available_coded_packages > 0
+			&& ctx->core_streaming)
+		return 1;
+
+	return 0;
+}
+
+static void job_abort(void *priv)
+{
+	/* TODO: stub */
+	struct vxe_enc_ctx *ctx = priv;
+
+	ctx->core_streaming = FALSE;
+}
+
+static const struct v4l2_m2m_ops m2m_ops = {
+	.device_run = device_run,
+	.job_ready = job_ready,
+	.job_abort = job_abort,
+};
+
+static struct vxe_enc_q_data *get_queue(struct vxe_enc_ctx *ctx,
+					enum v4l2_buf_type type)
+{
+	switch (type) {
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		return &ctx->out_queue;
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		return &ctx->cap_queue;
+	default:
+		return NULL;
+	}
+	return NULL;
+}
+
+static int vxe_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+			   unsigned int *nplanes, unsigned int sizes[],
+			   struct device *alloc_devs[])
+{
+	int i;
+	struct vxe_enc_ctx *ctx = vb2_get_drv_priv(vq);
+	struct vxe_enc_q_data *queue;
+
+	queue = get_queue(ctx, vq->type);
+	if (!queue)
+		return -EINVAL;
+
+	if (*nplanes) {
+		/* This is being called from CREATEBUFS, perform validation */
+		if (*nplanes != queue->fmt->num_planes)
+			return -EINVAL;
+
+		for (i = 0; i < *nplanes; i++) {
+			if (sizes[i] != queue->size_image[i])
+				return -EINVAL;
+		}
+
+		return 0;
+	}
+
+	*nplanes = queue->fmt->num_planes;
+
+	if (V4L2_TYPE_IS_OUTPUT(queue->fmt->type)) {
+		*nbuffers = max(*nbuffers, queue->fmt->min_bufs);
+	} else {
+		*nbuffers = topaz_get_coded_package_max_num(ctx->topaz_str_context,
+							    queue->fmt->std,
+							    queue->width,
+							    queue->height,
+							    &ctx->rc);
+		for (i = 0; i < *nplanes; i++) {
+			queue->size_image[i] =
+				topaz_get_coded_buffer_max_size(ctx->topaz_str_context,
+								queue->fmt->std,
+								queue->width,
+								queue->height,
+								&ctx->rc);
+		}
+	}
+
+	for (i = 0; i < *nplanes; i++)
+		sizes[i] = queue->size_image[i];
+
+	return 0;
+}
+
+static int vxe_buf_init(struct vb2_buffer *vb)
+{
+	struct vxe_enc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct device *dev = ctx->dev->dev;
+	struct vxe_enc_q_data *queue;
+	void *sgt;
+	int i, num_planes, ret;
+	struct vxe_buffer *buf = container_of(vb, struct vxe_buffer,
+			buffer.vb.vb2_buf);
+
+	queue = get_queue(ctx, vb->vb2_queue->type);
+	if (!queue) {
+		dev_err(dev, "Invalid queue type %d\n",
+			vb->vb2_queue->type);
+		return -EINVAL;
+	}
+
+	num_planes = queue->fmt->num_planes;
+
+	for (i = 0; i < num_planes; i++) {
+		if (vb2_plane_size(vb, i) < queue->size_image[i]) {
+			dev_err(dev, "data will not fit into plane(%lu < %lu)\n",
+				vb2_plane_size(vb, i),
+				(long)queue->size_image[i]);
+			return -EINVAL;
+		}
+	}
+
+	buf->buf_info.cpu_virt = vb2_plane_vaddr(vb, 0);
+	buf->buf_info.buf_size = vb2_plane_size(vb, 0);
+
+	sgt = vb2_dma_sg_plane_desc(vb, 0);
+	if (!sgt) {
+		dev_err(dev, "Could not get sg_table from plane 0\n");
+		return -EINVAL;
+	}
+
+	if (V4L2_TYPE_IS_OUTPUT(vb->type)) {
+		ret = topaz_stream_map_buf_sg(ctx->topaz_str_context, VENC_BUFTYPE_PICTURE,
+					      &buf->buf_info, sgt);
+		if (ret) {
+			dev_err(dev, "OUTPUT core_stream_map_buf_sg failed\n");
+			return ret;
+		}
+		pr_debug("Picture buffer mapped successfully, buf_id[%d], dev_virt[%x]\n",
+			 buf->buf_info.buff_id, buf->buf_info.dev_virt);
+
+		vxe_fill_default_src_frame_params(buf);
+
+		buf->y_buffer.mem_info = buf->buf_info;
+		buf->y_buffer.lock = BUFFER_FREE;
+		buf->y_buffer.size = 0; /* IMG has 0 */
+		buf->y_buffer.bytes_written = 0;
+
+		/* TODO Fill U/V img buffers if necessary */
+		buf->src_frame.y_plane_buffer = &buf->y_buffer;
+		buf->src_frame.u_plane_buffer = NULL;
+		buf->src_frame.v_plane_buffer = NULL;
+		buf->src_frame.y_component_offset = 0;
+		buf->src_frame.u_component_offset = queue->bytesperline[0] * queue->height;
+		buf->src_frame.v_component_offset = queue->bytesperline[0] * queue->height;
+
+		buf->src_frame.width_bytes = queue->bytesperline[0];
+		buf->src_frame.height = queue->height;
+		buf->src_frame.src_y_stride_bytes = queue->bytesperline[0];
+		buf->src_frame.src_uv_stride_bytes = queue->bytesperline[0];
+	} else {
+		ret = topaz_stream_map_buf_sg(ctx->topaz_str_context,
+					      VENC_BUFTYPE_BITSTREAM,
+					      &buf->buf_info, sgt);
+		if (ret) {
+			dev_err(dev, "CAPTURE core_stream_map_buf_sg failed\n");
+			return ret;
+		}
+		pr_debug("Bit-stream buffer mapped successfully, buf_id[%d], dev_virt[%x]\n",
+			 buf->buf_info.buff_id, buf->buf_info.dev_virt);
+
+		buf->coded_buffer.mem_info = buf->buf_info;
+		buf->coded_buffer.lock = BUFFER_FREE;
+		buf->coded_buffer.size = vb2_plane_size(vb, 0);
+		buf->coded_buffer.bytes_written = 0;
+	}
+
+	return 0;
+}
+
+static int vxe_buf_prepare(struct vb2_buffer *vb)
+{
+#ifdef DEBUG_ENCODER_DRIVER
+	int i;
+	struct vxe_buffer *buf = container_of(vb, struct vxe_buffer,
+			buffer.vb.vb2_buf);
+
+	pr_info("%s printing contents of buffer %d at 0x%p\n",
+		__func__, vb->index, buf->buf_info.cpu_virt);
+	for (i = 0; i < 1536; i = i + 8) {
+		pr_info("[%d] 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n",
+			((i + 1) / 8),
+			((char *)buf->buf_info.cpu_virt)[i + 0],
+			((char *)buf->buf_info.cpu_virt)[i + 1],
+			((char *)buf->buf_info.cpu_virt)[i + 2],
+			((char *)buf->buf_info.cpu_virt)[i + 3],
+			((char *)buf->buf_info.cpu_virt)[i + 4],
+			((char *)buf->buf_info.cpu_virt)[i + 5],
+			((char *)buf->buf_info.cpu_virt)[i + 6],
+			((char *)buf->buf_info.cpu_virt)[i + 7]);
+	}
+#endif
+	return 0;
+}
+
+static void vxe_buf_queue(struct vb2_buffer *vb)
+{
+	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+	struct vxe_enc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+	mutex_lock_nested(ctx->mutex, SUBCLASS_VXE_V4L2);
+	if (ctx->flag_last && (!V4L2_TYPE_IS_OUTPUT(vb->type))) {
+		/*
+		 * If EOS came and we did not have a buffer ready
+		 * to service it, service now that we have a buffer
+		 */
+		vbuf->flags |= V4L2_BUF_FLAG_LAST;
+		vb2_set_plane_payload(&vbuf->vb2_buf, 0, 0);
+		v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_DONE);
+	} else {
+		if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+			vbuf->sequence = ctx->out_seq++;
+		else
+			vbuf->sequence = ctx->cap_seq++;
+
+		v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vbuf);
+	}
+	mutex_unlock((struct mutex *)ctx->mutex);
+}
+
+static void vxe_buf_cleanup(struct vb2_buffer *vb)
+{
+	struct vxe_enc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct vxe_buffer *buf = container_of(vb, struct vxe_buffer,
+			buffer.vb.vb2_buf);
+
+	pr_debug("%s Unmapping buffer %d\n", __func__, buf->index);
+	topaz_stream_unmap_buf_sg(ctx->topaz_str_context, &buf->buf_info);
+}
+
+static int vxe_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct vxe_enc_ctx *ctx = vb2_get_drv_priv(vq);
+	struct vxe_enc_q_data *queue;
+	ctx->core_streaming = TRUE;
+
+	queue = get_queue(ctx, vq->type);
+	queue->streaming = TRUE;
+
+	return 0;
+}
+
+static void vxe_stop_streaming(struct vb2_queue *vq)
+{
+	struct vxe_enc_ctx *ctx = vb2_get_drv_priv(vq);
+	struct device *dev = ctx->dev->dev;
+	struct vb2_v4l2_buffer *vb;
+	struct vxe_enc_q_data *queue;
+
+	queue = get_queue(ctx, vq->type);
+	/* Unmap all buffers in v4l2 from mmu */
+	mutex_lock_nested(ctx->mutex, SUBCLASS_VXE_V4L2);
+	ctx->core_streaming = FALSE;
+	if (!V4L2_TYPE_IS_OUTPUT(queue->fmt->type)) {
+		while (v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx)) {
+			vb = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx);
+			if (!vb)
+				dev_err(dev, "Next dst buffer is null\n");
+			v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
+		}
+	} else {
+		while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx)) {
+			vb = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
+			if (!vb)
+				dev_err(dev, "Next dst buffer is null\n");
+			v4l2_m2m_buf_done(vb, VB2_BUF_STATE_ERROR);
+		}
+	}
+	mutex_unlock(ctx->mutex);
+}
+
+static const struct vb2_ops vxe_video_ops = {
+	.queue_setup = vxe_queue_setup,
+	.buf_init = vxe_buf_init,
+	.buf_prepare = vxe_buf_prepare,
+	.buf_queue = vxe_buf_queue,
+	.buf_cleanup = vxe_buf_cleanup,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+	.start_streaming = vxe_start_streaming,
+	.stop_streaming = vxe_stop_streaming,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+		      struct vb2_queue *dst_vq)
+{
+	struct vxe_enc_ctx *ctx = priv;
+	struct vxe_dev *vxe = ctx->dev;
+	int ret = 0;
+
+	/* src_vq */
+	memset(src_vq, 0, sizeof(*src_vq));
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	src_vq->drv_priv = ctx;
+	src_vq->buf_struct_size = sizeof(struct vxe_buffer);
+	src_vq->ops = &vxe_video_ops;
+	src_vq->mem_ops = &vb2_dma_sg_memops;
+	src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	src_vq->lock = vxe->mutex;
+	src_vq->dev = vxe->ti_vxe_dev.dev;
+
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	/* dst_vq */
+	memset(dst_vq, 0, sizeof(*dst_vq));
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes = VB2_MMAP | VB2_DMABUF;
+	dst_vq->drv_priv = ctx;
+	dst_vq->buf_struct_size = sizeof(struct vxe_buffer);
+	dst_vq->ops = &vxe_video_ops;
+	dst_vq->mem_ops = &vb2_dma_sg_memops;
+	dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+	dst_vq->lock = vxe->mutex;
+	dst_vq->dev = vxe->ti_vxe_dev.dev;
+
+	ret = vb2_queue_init(dst_vq);
+	if (ret) {
+		vb2_queue_release(src_vq);
+		return ret;
+	}
+
+	return 0;
+}
+
+static inline struct vxe_enc_ctx *vxe_ctrl_to_ctx(struct v4l2_ctrl *vctrl)
+{
+	return container_of(vctrl->handler, struct vxe_enc_ctx, v4l2_ctrl_hdl);
+}
+
+static int vxe_enc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct vxe_enc_ctx *ctx = vxe_ctrl_to_ctx(ctrl);
+
+#ifdef DEBUG_ENCODER_DRIVER
+	pr_debug("%s: name: %s | value: %d | id 0x%x | ctx 0x%p\n", __func__,
+					ctrl->name, ctrl->val, ctrl->id, ctx);
+#endif
+
+	switch (ctrl->id) {
+	case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+		ctx->vparams.idr_period = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_BITRATE:
+		ctx->rc.bits_per_second = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
+		ctx->rc.intra_freq = ctrl->val;
+		ctx->vparams.intra_cnt = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
+		/* only HP, MP and BP for now */
+		switch (ctrl->val) {
+		case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE:
+			ctx->sh_params.profile = SH_PROFILE_BP;
+			break;
+		case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN:
+			ctx->sh_params.profile = SH_PROFILE_MP;
+			break;
+		case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH:
+			ctx->sh_params.profile = SH_PROFILE_HP;
+			break;
+		default:
+			pr_info("not supported H264 profile requested\n");
+			return -EINVAL;
+		}
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
+		switch (ctrl->val) {
+		case V4L2_MPEG_VIDEO_H264_LEVEL_1_0:
+			ctx->sh_params.level = 100;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_1B:
+			ctx->sh_params.level = 101;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_1_1:
+			ctx->sh_params.level = 110;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_1_2:
+			ctx->sh_params.level = 120;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_1_3:
+			ctx->sh_params.level = 130;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_2_0:
+			ctx->sh_params.level = 200;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_2_1:
+			ctx->sh_params.level = 210;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_2_2:
+			ctx->sh_params.level = 220;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_3_0:
+			ctx->sh_params.level = 300;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_3_1:
+			ctx->sh_params.level = 310;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_3_2:
+			ctx->sh_params.level = 320;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_4_0:
+			ctx->sh_params.level = 400;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_4_1:
+			ctx->sh_params.level = 410;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_4_2:
+			ctx->sh_params.level = 420;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_5_0:
+			ctx->sh_params.level = 500;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_5_1:
+			ctx->sh_params.level = 510;
+			break;
+		case V4L2_MPEG_VIDEO_H264_LEVEL_5_2:
+			ctx->sh_params.level = 520;
+			break;
+		default:
+			pr_info("requested h264 level is not supported\n");
+			return -EINVAL;
+		}
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM:
+		ctx->vparams.h264_8x8 = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE:
+		ctx->vparams.cabac_enabled = ctrl->val;
+		break;
+	case V4L2_CID_MPEG_VIDEO_MAX_REF_PIC:
+		ctx->sh_params.max_num_ref_frames = ctrl->val;
+		break;
+	case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops vxe_enc_ctrl_ops = {
+	.s_ctrl = vxe_enc_s_ctrl,
+};
+
+static int vxe_open(struct file *file)
+{
+	struct vxe_dev *vxe = video_drvdata(file);
+	struct vxe_enc_ctx *ctx;
+	int i, ret = 0;
+	struct v4l2_ctrl_handler *v4l2_ctrl_hdl;
+
+	dev_dbg(vxe->dev, "%s:%d vxe %p\n", __func__, __LINE__, vxe);
+
+	mutex_lock((struct mutex *)vxe->mutex);
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx) {
+		mutex_unlock((struct mutex *)vxe->mutex);
+		return -ENOMEM;
+	}
+
+	v4l2_ctrl_hdl = &ctx->v4l2_ctrl_hdl;
+
+	ctx->mutex = kzalloc(sizeof(*ctx->mutex), GFP_KERNEL);
+	if (!ctx->mutex)
+		return -ENOMEM;
+
+	mutex_init(ctx->mutex);
+
+	ctx->dev = vxe;
+	ctx->s_fmt_flags = 0;
+	ctx->eos = FALSE;
+	ctx->flag_last = FALSE;
+	ctx->available_coded_packages = 0;
+	ctx->available_source_frames = 0;
+	ctx->frames_encoding = 0;
+	ctx->frame_num = 0;
+	ctx->rc.frame_rate = VXE_ENCODER_DEFAULT_FRAMERATE;
+	ctx->rc.initial_qp_i = VXE_ENCODER_INITIAL_QP_I;
+	ctx->out_queue.streaming = FALSE;
+	ctx->cap_queue.streaming = FALSE;
+
+	/* set the sequence numbers to zero */
+	ctx->cap_seq = 0;
+	ctx->out_seq = 0;
+
+	/* set some default widths and heights */
+	ctx->cap_queue.height = VXE_ENCODER_DEFAULT_HEIGHT;
+	ctx->cap_queue.width = VXE_ENCODER_DEFAULT_WIDTH;
+	ctx->out_queue.height = VXE_ENCODER_DEFAULT_HEIGHT;
+	ctx->out_queue.width = VXE_ENCODER_DEFAULT_WIDTH;
+
+	ctx->colorspace = V4L2_COLORSPACE_REC709;
+	ctx->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
+	ctx->hsv_enc = 0;
+	ctx->quantization = V4L2_QUANTIZATION_DEFAULT;
+	ctx->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+
+	/*
+	 * set some sane defaults, some of which will get overridden
+	 * latest when v4l2 starts setting up its s_ctrls
+	 */
+	vxe_fill_default_params(ctx);
+
+	for (i = 0; i < ARRAY_SIZE(vxe_enc_formats); i++) {
+		if (vxe_enc_formats[i].type ==
+			V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+			ctx->out_queue.fmt = &vxe_enc_formats[i];
+			break;
+		}
+	}
+	for (i = 0; i < ARRAY_SIZE(vxe_enc_formats); i++) {
+		if (vxe_enc_formats[i].type ==
+			V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+			ctx->cap_queue.fmt = &vxe_enc_formats[i];
+			break;
+		}
+	}
+
+	for (i = 0; i < ctx->cap_queue.fmt->num_planes; i++) {
+		ctx->cap_queue.size_image[i] = topaz_get_coded_buffer_max_size(NULL,
+									 ctx->cap_queue.fmt->fmt,
+									 ctx->cap_queue.width,
+									 ctx->cap_queue.height,
+									 &ctx->rc);
+
+		ctx->cap_queue.bytesperline[i] = 0;
+	}
+
+	for (i = 0; i < ctx->out_queue.fmt->num_planes; i++) {
+		ctx->out_queue.bytesperline[i] = vxe_get_stride(ctx->out_queue.width,
+						ctx->out_queue.fmt);
+		ctx->out_queue.size_image[i] = vxe_get_sizeimage(ctx->out_queue.bytesperline[i],
+						ctx->out_queue.height, ctx->out_queue.fmt, i);
+	}
+
+	v4l2_fh_init(&ctx->fh, video_devdata(file));
+	file->private_data = &ctx->fh;
+
+	ctx->fh.m2m_ctx = v4l2_m2m_ctx_init(vxe->m2m_dev, ctx, &queue_init);
+	if (IS_ERR_VALUE((unsigned long)ctx->fh.m2m_ctx)) {
+		ret = (long)(ctx->fh.m2m_ctx);
+		goto exit;
+	}
+
+	v4l2_ctrl_handler_init(v4l2_ctrl_hdl, 15);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &vxe_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_BITRATE,
+			  0, 700000000, 1, 100000);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &vxe_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_GOP_SIZE,
+			  0, 2047, 1, 30);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &vxe_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_MAX_REF_PIC,
+			  1, 16, 1, 1);
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &vxe_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_H264_PROFILE,
+			       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+				   0,
+			       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &vxe_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_H264_LEVEL,
+			       V4L2_MPEG_VIDEO_H264_LEVEL_5_1, 0,
+			       V4L2_MPEG_VIDEO_H264_LEVEL_1_0);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &vxe_enc_ctrl_ops,
+			  V4L2_CID_MIN_BUFFERS_FOR_OUTPUT, 1, 32, 1, 2);
+	v4l2_ctrl_new_std_menu(v4l2_ctrl_hdl, &vxe_enc_ctrl_ops,
+			       V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE,
+			       V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC, 0,
+			       V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC);
+	v4l2_ctrl_new_std(v4l2_ctrl_hdl, &vxe_enc_ctrl_ops,
+			  V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM,
+			  0, 1, 1, 1);
+
+	if (v4l2_ctrl_hdl->error) {
+		kfree(ctx->mutex);
+		kfree(ctx);
+		return -ENODEV;
+	}
+
+	ctx->fh.ctrl_handler = v4l2_ctrl_hdl;
+	v4l2_ctrl_handler_setup(v4l2_ctrl_hdl);
+
+	v4l2_fh_add(&ctx->fh);
+
+	vxe_create_ctx(vxe, ctx);
+
+	/* TODO: Add stream id creation */
+exit:
+	mutex_unlock((struct mutex *)vxe->mutex);
+	return ret;
+}
+
+static int vxe_release(struct file *file)
+{
+	struct vxe_dev *vxe = video_drvdata(file);
+	struct vxe_enc_ctx *ctx = file2ctx(file);
+	/* TODO Need correct API */
+
+	mutex_lock((struct mutex *)vxe->mutex);
+
+	v4l2_fh_del(&ctx->fh);
+	v4l2_fh_exit(&ctx->fh);
+	v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
+
+	if (ctx->s_fmt_flags & S_FMT_FLAG_STREAM_CREATED)
+		topaz_stream_destroy(ctx->topaz_str_context);
+	ctx->topaz_str_context = NULL;
+
+	mutex_destroy(ctx->mutex);
+	kfree(ctx->mutex);
+	ctx->mutex = NULL;
+	kfree(ctx);
+
+	mutex_unlock((struct mutex *)vxe->mutex);
+
+	return 0;
+}
+
+static const struct v4l2_file_operations vxe_enc_fops = {
+	.owner = THIS_MODULE,
+	.open = vxe_open,
+	.release = vxe_release,
+	.poll = v4l2_m2m_fop_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.mmap = v4l2_m2m_fop_mmap,
+};
+
+static int vxe_querycap(struct file *file, void *priv,
+			struct v4l2_capability *cap)
+{
+	strncpy(cap->driver, IMG_VXE_ENC_MODULE_NAME, sizeof(cap->driver) - 1);
+	strncpy(cap->card, IMG_VXE_ENC_MODULE_NAME, sizeof(cap->card) - 1);
+	snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", IMG_VXE_ENC_MODULE_NAME);
+	return 0;
+}
+
+static struct vxe_enc_fmt *find_format(struct v4l2_format *f)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(vxe_enc_formats); ++i) {
+		if (vxe_enc_formats[i].fourcc == f->fmt.pix_mp.pixelformat &&
+		    vxe_enc_formats[i].type == f->type)
+			return &vxe_enc_formats[i];
+	}
+	return NULL;
+}
+
+static int vxe_enum_fmt(struct file *file, void *priv, struct v4l2_fmtdesc *f)
+{
+	int i, index = 0;
+	struct vxe_enc_fmt *fmt = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(vxe_enc_formats); ++i) {
+		if (vxe_enc_formats[i].type == f->type) {
+			if (index == f->index) {
+				fmt = &vxe_enc_formats[i];
+				break;
+			}
+			index++;
+		}
+	}
+
+	if (!fmt)
+		return -EINVAL;
+
+	f->pixelformat = fmt->fourcc;
+	f->flags = 0;
+
+	return 0;
+}
+
+static int vxe_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+	struct vxe_enc_ctx *ctx = file2ctx(file);
+	struct v4l2_pix_format_mplane *pix_mp;
+	struct vxe_enc_q_data *queue;
+	int i;
+
+	pix_mp = &f->fmt.pix_mp;
+
+	queue = get_queue(ctx, f->type);
+	if (!queue)
+		return -EINVAL;
+
+	pix_mp->width = queue->width;
+	pix_mp->height = queue->height;
+	pix_mp->pixelformat = queue->fmt->fourcc;
+	pix_mp->field = V4L2_FIELD_NONE;
+
+	for (i = 0; i < queue->fmt->num_planes; i++) {
+		pix_mp->plane_fmt[i].sizeimage = queue->size_image[i];
+		pix_mp->plane_fmt[i].bytesperline = queue->bytesperline[i];
+	}
+	pix_mp->num_planes = queue->fmt->num_planes;
+
+	f->fmt.pix_mp.colorspace = ctx->colorspace;
+	f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc;
+	f->fmt.pix_mp.hsv_enc = ctx->hsv_enc;
+	f->fmt.pix_mp.quantization = ctx->quantization;
+	f->fmt.pix_mp.xfer_func = ctx->xfer_func;
+
+	return 0;
+}
+
+static int vxe_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+	struct vxe_enc_ctx *ctx = file2ctx(file);
+	struct vxe_enc_fmt *fmt;
+	struct vxe_enc_q_data *queue;
+	int i, width, height;
+	struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+	struct v4l2_plane_pix_format *plane_fmt = pix_mp->plane_fmt;
+	struct img_rc_params rc;
+
+	/* spec ambiguity see: http://www.mail-archive.com/linux-media@vger.kernel.org/msg56550.html*/
+	fmt = find_format(f);
+	if (!fmt) {
+		if (V4L2_TYPE_IS_OUTPUT(f->type))
+			f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
+		else
+			f->fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
+		/* try again now we have a default pixel type */
+		fmt = find_format(f);
+		if (!fmt)
+			return -EINVAL;  /* this should never happen */
+	}
+
+	width = clamp_t(u32, f->fmt.pix_mp.width, VXE_ENCODER_MIN_WIDTH, VXE_ENCODER_MAX_WIDTH);
+	height = clamp_t(u32, f->fmt.pix_mp.height, VXE_ENCODER_MIN_HEIGHT, VXE_ENCODER_MAX_HEIGHT);
+
+	queue = get_queue(ctx, f->type);
+	if (!queue)
+		return -EINVAL;
+
+	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+		pix_mp->num_planes = fmt->num_planes;
+		pix_mp->width = width;
+		pix_mp->height = height;
+
+		for (i = 0; i < fmt->num_planes; i++) {
+			plane_fmt[i].bytesperline = vxe_get_stride(pix_mp->width, fmt);
+			plane_fmt[i].sizeimage = vxe_get_sizeimage(plane_fmt[i].bytesperline,
+								   pix_mp->height, fmt, i);
+		}
+	} else {
+		/* Worst case estimation of sizeimage
+		 *plane_fmt[0].sizeimage = ALIGN(pix_mp->width, HW_ALIGN) *
+		 *			 ALIGN(pix_mp->height, HW_ALIGN) * 2;
+		 */
+		pix_mp->num_planes = 1;
+		rc.initial_qp_i = 18;
+		plane_fmt[0].bytesperline = 0;
+		pix_mp->width = width;
+		pix_mp->height = height;
+		plane_fmt[0].sizeimage = topaz_get_coded_buffer_max_size(NULL, fmt->std,
+									 pix_mp->width,
+									 pix_mp->height,
+									 &rc);
+
+		f->fmt.pix_mp.colorspace = ctx->colorspace;
+		f->fmt.pix_mp.ycbcr_enc = ctx->ycbcr_enc;
+		f->fmt.pix_mp.hsv_enc = ctx->hsv_enc;
+		f->fmt.pix_mp.quantization = ctx->quantization;
+		f->fmt.pix_mp.xfer_func = ctx->xfer_func;
+	}
+
+	pix_mp->field = V4L2_FIELD_NONE;
+	pix_mp->flags = 0;
+	pix_mp->xfer_func = V4L2_XFER_FUNC_DEFAULT;
+	memset(&f->fmt.pix_mp.reserved, 0, sizeof(f->fmt.pix_mp.reserved));
+
+	return 0;
+}
+
+static int vxe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+	struct vxe_enc_ctx *ctx = file2ctx(file);
+	struct v4l2_pix_format_mplane *pix_mp;
+	struct vxe_enc_fmt *fmt;
+	struct vxe_enc_q_data *queue;
+	int i, ret = 0;
+	unsigned int level_h264;
+	static int base_pipe;
+	unsigned int calculated_profile;
+
+	pix_mp = &f->fmt.pix_mp;
+
+#ifdef DEBUG_ENCODER_DRIVER
+	pr_debug("entering %s with context %p\n", __func__, ctx);
+#endif
+
+	ret = vxe_try_fmt(file, priv, f);
+	if (ret)
+		return ret;
+
+	fmt = find_format(f);
+	if (!fmt)
+		return -EINVAL;
+
+	queue = get_queue(ctx, f->type);
+	if (!queue)
+		return -EINVAL;
+
+	pix_mp = &f->fmt.pix_mp;
+
+	queue->fmt = fmt;
+	queue->width = pix_mp->width;
+	queue->height = pix_mp->height;
+
+	if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+		ctx->vparams.format = fmt->fmt;
+		ctx->vparams.source_width = pix_mp->width;
+		ctx->vparams.source_frame_height = pix_mp->height;
+		ctx->vparams.csc_preset = fmt->csc_preset;
+		if (ctx->vparams.csc_preset != IMG_CSC_NONE)
+			ctx->vparams.enable_scaler = TRUE;
+
+		ctx->colorspace = f->fmt.pix_mp.colorspace;
+		ctx->ycbcr_enc = f->fmt.pix_mp.ycbcr_enc;
+		ctx->hsv_enc = f->fmt.pix_mp.hsv_enc;
+		ctx->quantization = f->fmt.pix_mp.quantization;
+		ctx->xfer_func = f->fmt.pix_mp.xfer_func;
+
+		pr_debug("img_video_params: format=%d\n", ctx->vparams.format);
+		pr_debug("img_video_params: source_width=%d\n", ctx->vparams.source_width);
+		pr_debug("img_video_params: source_frame_height=%d\n",
+			 ctx->vparams.source_frame_height);
+		pr_debug("img_video_params: csc_preset=%d\n", ctx->vparams.csc_preset);
+		pr_debug("img_video_params: enable_scaler=%s\n",
+			 ctx->vparams.enable_scaler ? "true" : "false");
+
+		for (i = 0; i < fmt->num_planes; i++) {
+			queue->bytesperline[i] = vxe_get_stride(queue->width, fmt);
+			queue->size_image[i] = vxe_get_sizeimage(pix_mp->plane_fmt[i].bytesperline,
+								 queue->height, fmt, i);
+		}
+
+		/* Rate Control parameters */
+		ctx->rc.transfer_bits_per_second = ctx->rc.bits_per_second;
+		ctx->rc.bu_size = -1414812757; /* Pretty sure uninitialized */
+		ctx->rc.buffer_size = ctx->rc.transfer_bits_per_second;
+
+		ctx->rc.initial_level = (3 * ctx->rc.buffer_size) >> 4;
+		ctx->rc.initial_level = ((ctx->rc.initial_level +
+			((ctx->rc.bits_per_second /
+			ctx->rc.frame_rate) / 2)) /
+			(ctx->rc.bits_per_second /
+			ctx->rc.frame_rate)) *
+			(ctx->rc.bits_per_second / ctx->rc.frame_rate);
+		ctx->rc.initial_level = max((unsigned int)ctx->rc.initial_level,
+					    (unsigned int)(ctx->rc.bits_per_second /
+				ctx->rc.frame_rate));
+		ctx->rc.initial_delay = ctx->rc.buffer_size - ctx->rc.initial_level;
+		ctx->rc.bframes = 0;
+
+		pr_debug("img_rc_params: initial_level=%d\n", ctx->rc.initial_level);
+		pr_debug("img_rc_params: initial_delay=%d\n", ctx->rc.initial_delay);
+
+		pr_debug("requested profile: %d, ref frames: %d, cabac: %d, weighted pred: %d, 8x8trans: %d, level %d",
+					ctx->sh_params.profile,
+					ctx->sh_params.max_num_ref_frames,
+					ctx->vparams.cabac_enabled,
+					ctx->vparams.weighted_prediction,
+					ctx->vparams.h264_8x8,
+					ctx->sh_params.level);
+
+		calculated_profile = find_h264_profile
+					(FALSE,
+					ctx->vparams.use_default_scaling_list,
+					FALSE,
+					ctx->vparams.h264_8x8,
+					ctx->vparams.enable_mvc,
+					ctx->rc.bframes,
+					ctx->vparams.is_interlaced,
+					ctx->vparams.cabac_enabled,
+					ctx->vparams.weighted_prediction,
+					ctx->vparams.vp_weighted_implicit_bi_pred);
+
+		/* pick the higher of the requested profile and the calculated profile */
+		ctx->sh_params.profile = max(calculated_profile, ctx->sh_params.profile);
+
+		level_h264 = calculate_h264_level(pix_mp->width, pix_mp->height,
+						  ctx->rc.frame_rate,
+						  ctx->rc.rc_enable,
+						  ctx->rc.bits_per_second,
+						  /* TODO Figure out which lossless to use */
+						  FALSE,
+						  ctx->sh_params.profile,
+						  ctx->sh_params.max_num_ref_frames);
+
+		/* pick the highest of the calculate or selected level */
+		level_h264 = max(level_h264, ctx->sh_params.level);
+
+		pr_debug("selected profile: %d, ref frames: %d, cabac: %d, weighted pred: %d, 8x8trans: %d, level %d",
+					ctx->sh_params.profile,
+					ctx->sh_params.max_num_ref_frames,
+					ctx->vparams.cabac_enabled,
+					ctx->vparams.weighted_prediction,
+					ctx->vparams.h264_8x8,
+					ctx->sh_params.level);
+
+		ctx->vparams.vert_mv_limit = 255;
+		if (level_h264 >= 110)
+			ctx->vparams.vert_mv_limit = 511;
+		if (level_h264 >= 210)
+			ctx->vparams.vert_mv_limit = 1023;
+		if (level_h264 >= 310)
+			ctx->vparams.vert_mv_limit = 2047;
+
+		if (level_h264 >= 300)
+			ctx->vparams.limit_num_vectors = TRUE;
+		else
+			ctx->vparams.limit_num_vectors = FALSE;
+
+		pr_debug("ctx->vparams.vert_mv_limit=%d\n", ctx->vparams.vert_mv_limit);
+		pr_debug("ctx->vparams.limit_num_vectors=%d\n", ctx->vparams.limit_num_vectors);
+
+		/* VUI parameters */
+		ctx->vui_params.time_scale = ctx->rc.frame_rate * 2;
+		ctx->vui_params.bit_rate_value_minus1 = (ctx->rc.bits_per_second / 64)
+			- 1;
+		ctx->vui_params.cbp_size_value_minus1 = (ctx->rc.buffer_size / 64) - 1;
+		ctx->vui_params.aspect_ratio_info_present_flag = FALSE; //unset
+		ctx->vui_params.aspect_ratio_idc = 0; //unset
+		ctx->vui_params.sar_width = 0; //unset
+		ctx->vui_params.sar_height = 0; //unset
+		ctx->vui_params.cbr = (ctx->rc.rc_mode == IMG_RCMODE_CBR) ?
+			TRUE : FALSE;
+		ctx->vui_params.initial_cpb_removal_delay_length_minus1 =
+			BPH_SEI_NAL_INITIAL_CPB_REMOVAL_DELAY_SIZE - 1;
+		ctx->vui_params.cpb_removal_delay_length_minus1 =
+			PTH_SEI_NAL_CPB_REMOVAL_DELAY_SIZE - 1;
+		ctx->vui_params.dpb_output_delay_length_minus1 =
+			PTH_SEI_NAL_DPB_OUTPUT_DELAY_SIZE - 1;
+		ctx->vui_params.time_offset_length = 24; //hard coded
+		ctx->vui_params.num_reorder_frames = 0; //TODO
+		ctx->vui_params.max_dec_frame_buffering = 0; //unset
+
+		pr_debug("h264_vui_params: time_scale=%d\n", ctx->vui_params.time_scale);
+		pr_debug("h264_vui_params: bit_rate_value_minus1=%d\n",
+			 ctx->vui_params.bit_rate_value_minus1);
+		pr_debug("h264_vui_params: cbp_size_value_minus1=%d\n",
+			 ctx->vui_params.cbp_size_value_minus1);
+		pr_debug("h264_vui_params: cbr=%d\n", ctx->vui_params.cbr);
+		pr_debug("h264_vui_params: initial_cpb_removal_delay_length_minus1=%d\n",
+			 ctx->vui_params.initial_cpb_removal_delay_length_minus1);
+		pr_debug("h264_vui_params: cpb_removal_delay_length_minus1=%d\n",
+			 ctx->vui_params.cpb_removal_delay_length_minus1);
+		pr_debug("h264_vui_params: dpb_output_delay_length_minus1=%d\n",
+			 ctx->vui_params.dpb_output_delay_length_minus1);
+
+		/* Sequence Header parameters */
+		switch (level_h264) {
+		case  100:
+			ctx->sh_params.level = SH_LEVEL_1;
+			break;
+		case 101:
+			ctx->sh_params.level = SH_LEVEL_1B;
+			break;
+		case 110:
+			ctx->sh_params.level = SH_LEVEL_11;
+			break;
+		case 120:
+			ctx->sh_params.level = SH_LEVEL_12;
+			break;
+		case 130:
+			ctx->sh_params.level = SH_LEVEL_13;
+			break;
+		case 200:
+			ctx->sh_params.level = SH_LEVEL_2;
+			break;
+		case 210:
+			ctx->sh_params.level = SH_LEVEL_21;
+			break;
+		case 220:
+			ctx->sh_params.level = SH_LEVEL_22;
+			break;
+		case 300:
+			ctx->sh_params.level = SH_LEVEL_3;
+			break;
+		case 310:
+			ctx->sh_params.level = SH_LEVEL_31;
+			break;
+		case 320:
+			ctx->sh_params.level = SH_LEVEL_32;
+			break;
+		case 400:
+			ctx->sh_params.level = SH_LEVEL_4;
+			break;
+		case 410:
+			ctx->sh_params.level = SH_LEVEL_41;
+			break;
+		case 420:
+			ctx->sh_params.level = SH_LEVEL_42;
+			break;
+		case 500:
+			ctx->sh_params.level = SH_LEVEL_5;
+			break;
+		case 510:
+			ctx->sh_params.level = SH_LEVEL_51;
+			break;
+		case 520:
+			ctx->sh_params.level = SH_LEVEL_52;
+			break;
+		default:
+			pr_err("Error invalid h264 level %d\n", level_h264);
+			return -EINVAL;
+		}
+		if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+			ctx->sh_params.width_in_mbs_minus1 = ((ALIGN_16(queue->width) +
+				(MB_SIZE - 1))/MB_SIZE)-1;
+			ctx->sh_params.height_in_maps_units_minus1 = ((ALIGN_16(queue->height) +
+					(MB_SIZE - 1))/MB_SIZE) - 1;
+			pr_debug("h264_sequence_header_params: width_in_mbs_minus1=%d\n",
+				 ctx->sh_params.width_in_mbs_minus1);
+			pr_debug("h264_sequence_header_params: height_in_maps_units_minus1=%d\n",
+				 ctx->sh_params.height_in_maps_units_minus1);
+		}
+		ctx->sh_params.log2_max_pic_order_cnt = 6; //hard coded
+		ctx->sh_params.gaps_in_frame_num_value = FALSE;
+		ctx->sh_params.frame_mbs_only_flag = ctx->vparams.is_interlaced ?
+			FALSE : TRUE;
+		ctx->sh_params.vui_params_present = (ctx->rc.rc_mode == IMG_RCMODE_NONE)
+			? FALSE : TRUE;
+		ctx->sh_params.seq_scaling_matrix_present_flag = FALSE;
+		ctx->sh_params.use_default_scaling_list = FALSE;
+		ctx->sh_params.is_lossless = FALSE;
+		ctx->sh_params.vui_params = ctx->vui_params;
+
+		pr_debug("h264_sequence_header_params: frame_mbs_only_flag=%d\n",
+			 ctx->sh_params.frame_mbs_only_flag);
+		pr_debug("h264_sequence_header_params: vui_params_present=%d\n",
+			 ctx->sh_params.vui_params_present);
+
+		ctx->s_fmt_flags |= S_FMT_FLAG_OUT_RECV;
+	} else {
+		for (i = 0; i < fmt->num_planes; i++) {
+			queue->bytesperline[i] = 0;
+			queue->size_image[i] =
+				topaz_get_coded_buffer_max_size(ctx->topaz_str_context,
+								queue->fmt->std,
+								queue->width,
+								queue->height,
+								&ctx->rc);
+		}
+		ctx->vparams.standard = fmt->std;
+		ctx->vparams.width = pix_mp->width;
+		/*
+		 * Note: Do not halve height for interlaced.
+		 * App should take care of this.
+		 */
+		ctx->vparams.frame_height = pix_mp->height;
+
+		pr_debug("img_video_params: standard=%d\n", ctx->vparams.standard);
+		pr_debug("img_video_params: width=%d\n", ctx->vparams.width);
+		pr_debug("img_video_params: frame_height=%d\n", ctx->vparams.frame_height);
+
+		ctx->s_fmt_flags |= S_FMT_FLAG_CAP_RECV;
+	}
+	ctx->vparams.is_interlaced = FALSE;
+
+	ctx->vparams.intra_pred_modes = -1414812757; /* Pretty sure uninitialized */
+
+	ctx->vparams.buffer_stride_bytes = 0;
+	ctx->vparams.buffer_height = 0;
+
+	ctx->vparams.crop_left = 0;
+	ctx->vparams.crop_right = 0;
+	ctx->vparams.crop_top = 0;
+	ctx->vparams.crop_bottom = 0;
+
+	ctx->vparams.slices_per_picture = 1;
+
+	/* Crop parameters */
+	ctx->crop_params.clip = FALSE;
+	ctx->crop_params.left_crop_offset = 0;
+	ctx->crop_params.right_crop_offset = (((ctx->sh_params.width_in_mbs_minus1 + 1)*MB_SIZE) -
+			ctx->vparams.source_width)/2;
+	ctx->crop_params.top_crop_offset = 0;
+	ctx->crop_params.bottom_crop_offset = (((ctx->sh_params.height_in_maps_units_minus1 + 1)
+				*MB_SIZE) - ctx->vparams.source_frame_height)/2;
+	if (ctx->crop_params.right_crop_offset | ctx->crop_params.bottom_crop_offset)
+		ctx->crop_params.clip = TRUE;
+
+	pr_debug("s_fmt_flags=%#08x\n", ctx->s_fmt_flags);
+	if ((ctx->s_fmt_flags & S_FMT_FLAG_OUT_RECV) &&
+	    (ctx->s_fmt_flags & S_FMT_FLAG_CAP_RECV)) {
+		/* if the stream has already been created for this context */
+		/* better destroy the original, and create a new one */
+		if (ctx->s_fmt_flags & S_FMT_FLAG_STREAM_CREATED)
+			topaz_stream_destroy(ctx->topaz_str_context);
+
+		topaz_stream_create(ctx, &ctx->vparams, ((base_pipe++ % 2) ? 0 : 1), 2,
+				&ctx->rc, &ctx->topaz_str_context);
+
+		topaz_h264_prepare_sequence_header(ctx->topaz_str_context,
+						   ctx->sh_params.width_in_mbs_minus1 + 1,
+						   ctx->sh_params.height_in_maps_units_minus1 + 1,
+						   TRUE, &ctx->vui_params,
+						   &ctx->crop_params,
+						   &ctx->sh_params, FALSE);
+		/* Note: cqp_offset looks unset in img */
+		topaz_h264_prepare_picture_header(ctx->topaz_str_context, 0);
+
+		topaz_load_context(ctx->topaz_str_context);
+
+		ctx->s_fmt_flags |= S_FMT_FLAG_STREAM_CREATED;
+	}
+
+	return 0;
+}
+
+static int vxe_subscribe_event(struct v4l2_fh *fh,
+			       const struct v4l2_event_subscription *sub)
+{
+	switch (sub->type) {
+	case V4L2_EVENT_EOS:
+		return v4l2_event_subscribe(fh, sub, 0, NULL);
+	case V4L2_EVENT_SOURCE_CHANGE:
+		return -EINVAL;
+	case V4L2_EVENT_CTRL:
+		return v4l2_ctrl_subscribe_event(fh, sub);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int vxe_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *cmd)
+{
+	struct vxe_enc_ctx *ctx = file2ctx(file);
+
+	if (cmd->cmd != V4L2_DEC_CMD_STOP)
+		return -EINVAL;
+
+	mutex_lock_nested(ctx->mutex, SUBCLASS_VXE_V4L2);
+	if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0 ||
+	    !ctx->out_queue.streaming || !ctx->cap_queue.streaming) {
+		/* Buffers are still in queue for encode, set eos flag */
+		ctx->eos = TRUE;
+		mutex_unlock((struct mutex *)ctx->mutex);
+	} else if ((ctx->available_source_frames > 0) ||
+		(ctx->frames_encoding) > 0) {
+		/*
+		 * Buffers are still in firmware for encode. Tell topaz
+		 * that last frame sent is last frame in stream
+		 */
+		topaz_end_of_stream(ctx->topaz_str_context, ctx->frame_num);
+		ctx->last_frame_num = ctx->frame_num;
+		mutex_unlock((struct mutex *)ctx->mutex);
+	} else {
+		/* All buffers are encoded, so issue dummy stream end */
+		mutex_unlock((struct mutex *)ctx->mutex);
+		vxe_eos(ctx);
+	}
+	return 0;
+}
+
+
+
+static int vxe_enum_framesizes(struct file *file, void *priv,
+			       struct v4l2_frmsizeenum *fsize)
+{
+	int  i, found = 0;
+
+	if (fsize->index != 0)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(vxe_enc_formats); ++i) {
+		if (vxe_enc_formats[i].fourcc == fsize->pixel_format) {
+			found = 1;
+			break;
+		}
+	}
+	if (!found)
+		return -EINVAL;
+
+	fsize->type = V4L2_FRMSIZE_TYPE_CONTINUOUS;
+	fsize->stepwise.min_width = VXE_ENCODER_MIN_WIDTH;
+	fsize->stepwise.max_width = VXE_ENCODER_MAX_WIDTH;
+	fsize->stepwise.step_width = 1;
+	fsize->stepwise.min_height = VXE_ENCODER_MIN_HEIGHT;
+	fsize->stepwise.max_height = VXE_ENCODER_MAX_HEIGHT;
+	fsize->stepwise.step_height = 1;
+
+	fsize->reserved[0] = 0;
+	fsize->reserved[1] = 0;
+
+	return 0;
+}
+
+static int vxe_enum_frameintervals(struct file *file, void *priv,
+				   struct v4l2_frmivalenum *fival)
+{
+	int i, found = 0;
+	if (fival->index)
+		return -EINVAL;
+
+	if (fival->width > VXE_ENCODER_MAX_WIDTH ||
+	    fival->width < VXE_ENCODER_MIN_WIDTH ||
+	    fival->height > VXE_ENCODER_MAX_HEIGHT ||
+	    fival->height < VXE_ENCODER_MIN_HEIGHT)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(vxe_enc_formats); ++i) {
+		if (vxe_enc_formats[i].fourcc == fival->pixel_format) {
+			found = 1;
+			break;
+		}
+	}
+	if (!found)
+		return -EINVAL;
+
+	fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
+	fival->stepwise.min = frmivals[0];
+	fival->stepwise.max = frmivals[1];
+	fival->stepwise.step = frmivals[1];
+
+	fival->reserved[0] = 0;
+	fival->reserved[1] = 0;
+
+	return 0;
+}
+
+static int vxe_g_parm(struct file *file, void *priv,
+		      struct v4l2_streamparm *parm)
+{
+	struct vxe_enc_ctx *ctx = file2ctx(file);
+
+	if (V4L2_TYPE_IS_OUTPUT(parm->type)) {
+		parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+		parm->parm.output.timeperframe.numerator = 1;
+		parm->parm.output.timeperframe.denominator = ctx->rc.frame_rate;
+	} else {
+		parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+		parm->parm.capture.timeperframe.numerator = 1;
+		parm->parm.capture.timeperframe.denominator = ctx->rc.frame_rate;
+	}
+
+	return 0;
+}
+
+static int vxe_s_parm(struct file *file, void *priv,
+		      struct v4l2_streamparm *parm)
+{
+	struct vxe_enc_ctx *ctx = file2ctx(file);
+	unsigned int num, den;
+
+	/* Cannot change values once context is created */
+	/* TODO: Handle controls after stream is created but before streamon */
+	if (ctx->s_fmt_flags & S_FMT_FLAG_STREAM_CREATED)
+		return -EBUSY;
+
+	if (V4L2_TYPE_IS_OUTPUT(parm->type)) {
+		parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+		num = parm->parm.output.timeperframe.numerator;
+		den = parm->parm.output.timeperframe.denominator;
+	} else {
+		parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+		num = parm->parm.capture.timeperframe.numerator;
+		den = parm->parm.capture.timeperframe.denominator;
+	}
+
+	if (parm->parm.output.timeperframe.denominator &&
+			parm->parm.output.timeperframe.numerator) {
+		ctx->rc.frame_rate = den / num;
+	}
+
+	if (V4L2_TYPE_IS_OUTPUT(parm->type)) {
+		parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+		parm->parm.output.timeperframe.numerator = 1;
+		parm->parm.output.timeperframe.denominator = ctx->rc.frame_rate;
+	} else {
+		parm->parm.capture.capability = V4L2_CAP_TIMEPERFRAME;
+		parm->parm.capture.timeperframe.numerator = 1;
+		parm->parm.capture.timeperframe.denominator = ctx->rc.frame_rate;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops vxe_enc_ioctl_ops = {
+	.vidioc_querycap = vxe_querycap,
+
+	.vidioc_enum_fmt_vid_cap = vxe_enum_fmt,
+	.vidioc_g_fmt_vid_cap_mplane = vxe_g_fmt,
+	.vidioc_try_fmt_vid_cap_mplane = vxe_try_fmt,
+	.vidioc_s_fmt_vid_cap_mplane = vxe_s_fmt,
+
+	.vidioc_enum_fmt_vid_out = vxe_enum_fmt,
+	.vidioc_g_fmt_vid_out_mplane = vxe_g_fmt,
+	.vidioc_try_fmt_vid_out_mplane = vxe_try_fmt,
+	.vidioc_s_fmt_vid_out_mplane = vxe_s_fmt,
+
+	.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
+	.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
+	.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
+	.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
+	.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
+
+	.vidioc_streamon = v4l2_m2m_ioctl_streamon,
+	.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+	.vidioc_log_status = v4l2_ctrl_log_status,
+
+	.vidioc_subscribe_event = vxe_subscribe_event,
+	.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+	.vidioc_try_encoder_cmd = v4l2_m2m_ioctl_try_encoder_cmd,
+	.vidioc_encoder_cmd = vxe_cmd,
+
+	.vidioc_enum_framesizes = vxe_enum_framesizes,
+	.vidioc_enum_frameintervals = vxe_enum_frameintervals,
+
+	.vidioc_g_parm = vxe_g_parm,
+	.vidioc_s_parm = vxe_s_parm,
+};
+
+static const struct of_device_id vxe_enc_of_match[] = {
+	{.compatible = "img,vxe384"},   { /* end */},
+};
+MODULE_DEVICE_TABLE(of, vxe_enc_of_match);
+
+static irqreturn_t soft_thread_irq(int irq, void *dev_data)
+{
+	unsigned char handled;
+
+	if (!dev_data)
+		return IRQ_NONE;
+
+	handled = topazdd_threaded_isr(dev_data);
+	if (handled)
+		return IRQ_HANDLED;
+
+	return IRQ_NONE;
+}
+
+static irqreturn_t hard_isrcb(int irq, void *dev_data)
+{
+	if (!dev_data)
+		return IRQ_NONE;
+
+	return topazdd_isr(dev_data);
+}
+
+static int vxe_enc_probe(struct platform_device *pdev)
+{
+	struct vxe_dev *vxe;
+	struct resource *res;
+	const struct of_device_id *of_dev_id;
+	struct video_device *vfd;
+	int ret;
+	int module_irq;
+	struct vxe_enc_ctx *ctx;
+	struct heap_config *heap_configs = vxe_enc_heap_configs;
+	int num_heaps = ARRAY_SIZE(vxe_enc_heap_configs);
+	unsigned int i;
+
+	of_dev_id = of_match_device(vxe_enc_of_match, &pdev->dev);
+	if (!of_dev_id) {
+		dev_err(&pdev->dev, "%s: Unable to match device\n", __func__);
+		return -ENODEV;
+	}
+
+	dma_set_mask(&pdev->dev, DMA_BIT_MASK(40));
+
+	vxe = devm_kzalloc(&pdev->dev, sizeof(*vxe), GFP_KERNEL);
+	if (!vxe)
+		return -ENOMEM;
+
+	vxe->dev = &pdev->dev;
+	vxe->plat_dev = pdev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	vxe->reg_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(vxe->reg_base))
+		return PTR_ERR(vxe->reg_base);
+
+	module_irq = platform_get_irq(pdev, 0);
+	if (module_irq < 0)
+		return -ENXIO;
+	vxe->module_irq = module_irq;
+
+	ret = img_mem_init(vxe->dev);
+	if (ret) {
+		dev_err(vxe->dev, "Failed to initialize memory\n");
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&vxe->drv_ctx.heaps);
+	vxe->drv_ctx.internal_heap_id = VXE_INVALID_ID;
+
+	/* Initialise memory management component */
+	for (i = 0; i < num_heaps; i++) {
+		struct vxe_heap *heap;
+#ifdef DEBUG_ENCODER_DRIVER
+		dev_info(vxe->dev, "%s: adding heap of type %d\n",
+			 __func__, heap_configs[i].type);
+#endif
+
+		heap = kzalloc(sizeof(*heap), GFP_KERNEL);
+		if (!heap) {
+			ret = -ENOMEM;
+			goto heap_add_failed;
+		}
+
+		ret = img_mem_add_heap(&heap_configs[i], &heap->id);
+		if (ret < 0) {
+			dev_err(vxe->dev, "%s: failed to init heap (type %d)!\n",
+				__func__, heap_configs[i].type);
+			kfree(heap);
+			goto heap_add_failed;
+		}
+		list_add(&heap->list, &vxe->drv_ctx.heaps);
+
+		/* Implicitly, first heap is used for internal allocations */
+		if (vxe->drv_ctx.internal_heap_id < 0) {
+			vxe->drv_ctx.internal_heap_id = heap->id;
+			dev_err(vxe->dev, "%s: using heap %d for internal alloc\n",
+				__func__, vxe->drv_ctx.internal_heap_id);
+		}
+	}
+
+	/* Do not proceed if internal heap not defined */
+	if (vxe->drv_ctx.internal_heap_id < 0) {
+		dev_err(vxe->dev, "%s: failed to locate heap for internal alloc\n",
+			__func__);
+		ret = -EINVAL;
+		/* Loop registered heaps just for sanity */
+		goto heap_add_failed;
+	}
+
+	ret = vxe_init_mem(vxe);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to initialize memory\n");
+		return -ENOMEM;
+	}
+
+	vxe->mutex = kzalloc(sizeof(*vxe->mutex), GFP_KERNEL);
+	if (!vxe->mutex)
+		return -ENOMEM;
+
+	mutex_init(vxe->mutex);
+
+	platform_set_drvdata(pdev, vxe);
+
+	pm_runtime_enable(&pdev->dev);
+	ret = pm_runtime_get_sync(&pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "%s: failed to enable clock, status = %d\n",
+			__func__, ret);
+		goto exit;
+	}
+
+	ret = devm_request_threaded_irq(&pdev->dev, module_irq, (irq_handler_t)hard_isrcb,
+					(irq_handler_t)soft_thread_irq, IRQF_SHARED,
+					IMG_VXE_ENC_MODULE_NAME, &vxe->topaz_dev_ctx);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to get IRQ\n");
+		goto out_put_sync;
+	}
+
+	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx) {
+		free_irq(module_irq, &vxe->topaz_dev_ctx);
+		return -ENOMEM;
+	}
+	ctx->dev = vxe;
+
+	vxe_fill_default_params(ctx);
+
+	ctx->mem_ctx = vxe->drv_ctx.mem_ctx;
+	ctx->mmu_ctx = vxe->drv_ctx.mmu_ctx;
+
+	vxe->ctx = ctx;
+
+	ret = topazdd_init((unsigned long)vxe->reg_base, res->end - res->start + 1,
+			   (MMU_USE_MMU_FLAG | MMU_EXTENDED_ADDR_FLAG),
+			   ctx, vxe->drv_ctx.ptd, &vxe->topaz_dev_ctx);
+	if (ret)
+		goto out_free_irq;
+
+	vxe->streams = kzalloc(sizeof(*vxe->streams), GFP_KERNEL);
+	if (!vxe->streams) {
+		ret = -ENOMEM;
+		goto topazdd_deinit;
+	}
+	idr_init(vxe->streams);
+
+	ret = init_topaz_core(vxe->topaz_dev_ctx, &vxe->num_pipes,
+			      (MMU_USE_MMU_FLAG | MMU_EXTENDED_ADDR_FLAG),
+			      vxe_return_resource);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to initialize topaz core\n");
+		goto topazdd_deinit;
+	}
+
+	ret = v4l2_device_register(&pdev->dev, &vxe->ti_vxe_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register v4l2 device\n");
+		goto topaz_core_deinit;
+	}
+
+	vfd = video_device_alloc();
+	if (!vfd) {
+		dev_err(&pdev->dev, "Failed to allocate video device\n");
+		ret = -ENOMEM;
+		goto out_v4l2_device;
+	}
+
+	snprintf(vfd->name, sizeof(vfd->name), "%s", IMG_VXE_ENC_MODULE_NAME);
+	vfd->fops = &vxe_enc_fops;
+	vfd->ioctl_ops = &vxe_enc_ioctl_ops;
+	vfd->minor = -1;
+	vfd->release = video_device_release;
+	vfd->vfl_dir = VFL_DIR_M2M;
+	vfd->v4l2_dev = &vxe->ti_vxe_dev;
+	vfd->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+	vfd->lock = vxe->mutex;
+
+	vxe->vfd = vfd;
+	video_set_drvdata(vfd, vxe);
+
+	vxe->m2m_dev = v4l2_m2m_init(&m2m_ops);
+	if (IS_ERR_VALUE((unsigned long)vxe->m2m_dev)) {
+		dev_err(&pdev->dev, "Failed to init mem2mem device\n");
+		ret = -EINVAL;
+		goto out_vid_dev;
+	}
+
+	ret = video_register_device(vfd, VFL_TYPE_VIDEO, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register video device\n");
+		goto out_vid_reg;
+	}
+	v4l2_info(&vxe->ti_vxe_dev, "encoder registered as /dev/video%d\n",
+		  vfd->num);
+
+	return 0;
+
+out_vid_reg:
+	v4l2_m2m_release(vxe->m2m_dev);
+out_vid_dev:
+	video_device_release(vfd);
+out_v4l2_device:
+	v4l2_device_unregister(&vxe->ti_vxe_dev);
+topaz_core_deinit:
+	deinit_topaz_core();
+topazdd_deinit:
+	topazdd_deinit(vxe->topaz_dev_ctx);
+out_free_irq:
+	kfree(vxe->ctx);
+	free_irq(module_irq, &vxe->topaz_dev_ctx);
+out_put_sync:
+	pm_runtime_put_sync(&pdev->dev);
+heap_add_failed:
+	while (!list_empty(&vxe->drv_ctx.heaps)) {
+		struct vxe_heap *heap;
+
+		heap = list_first_entry(&vxe->drv_ctx.heaps, struct vxe_heap, list);
+		__list_del_entry(&heap->list);
+		img_mem_del_heap(heap->id);
+		kfree(heap);
+	}
+	vxe->drv_ctx.internal_heap_id = VXE_INVALID_ID;
+
+exit:
+	pm_runtime_disable(&pdev->dev);
+	vxe_deinit_mem(vxe);
+
+	return ret;
+}
+
+static int vxe_enc_remove(struct platform_device *pdev)
+{
+	struct vxe_dev *vxe = platform_get_drvdata(pdev);
+
+	topazdd_deinit(vxe->topaz_dev_ctx);
+
+	kfree(vxe->ctx);
+	vxe_deinit_mem(vxe);
+
+	free_irq(vxe->module_irq, &vxe->topaz_dev_ctx);
+
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver vxe_enc_driver = {
+	.probe = vxe_enc_probe,
+	.remove = vxe_enc_remove,
+	.driver = {
+		.name = "img_enc",
+		.of_match_table = vxe_enc_of_match,
+	},
+};
+module_platform_driver(vxe_enc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("IMG VXE384 video encoder driver");
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/encoder/vxe_v4l2.h b/drivers/media/platform/img/vxe-vxd/encoder/vxe_v4l2.h
--- a/drivers/media/platform/img/vxe-vxd/encoder/vxe_v4l2.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/encoder/vxe_v4l2.h	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * V4L2 interface header
+ *
+ * Copyright (c) Imagination Technologies Ltd.
+ * Copyright (c) 2021 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Authors:
+ *	Sunita Nadampalli <sunitan@ti.com>
+ *
+ * Re-written for upstreming
+ *	Sidraya Jayagond <sidraya.bj@pathpartnertech.com>
+ */
+
+#ifndef _VXE_V4L2_H
+#define _VXE_V4L2_H
+
+#include <linux/dma-mapping.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+
+/*
+ * struct vxe_ctrl - contains info for each supported v4l2 control
+ */
+struct vxe_ctrl {
+	unsigned int cid;
+	enum v4l2_ctrl_type type;
+	unsigned char name[32];
+	int minimum;
+	int maximum;
+	int step;
+	int default_value;
+	unsigned char compound;
+};
+
+extern struct mem_space topaz_mem_space[];
+
+#endif
diff -Naur --no-dereference a/drivers/media/platform/img/vxe-vxd/Makefile b/drivers/media/platform/img/vxe-vxd/Makefile
--- a/drivers/media/platform/img/vxe-vxd/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/img/vxe-vxd/Makefile	2024-01-28 14:01:31.244353788 -0500
@@ -0,0 +1,163 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# Optional Video feature configuration control
+
+# (1)
+# This config allows enabling or disabling of HEVC/H265 video
+# decoding functionality with IMG VXD Video decoder. If you
+# do not want HEVC decode capability, select N.
+# If unsure, select Y
+HAS_HEVC ?=y
+
+# (2)
+# This config enables error concealment with gray pattern.
+# Disable if you do not want error concealment capability.
+# If unsure, say Y
+ERROR_CONCEALMENT ?=y
+
+# (3)
+# This config, if enabled, configures H264 video decoder to
+# output frames in the decode order with no buffering and
+# picture reordering inside codec.
+# If unsure, say N
+REDUCED_DPB_NO_PIC_REORDERING ?=n
+
+# (4)
+# This config, if enabled, enables all the debug traces in
+# decoder driver. Enable it only for debug purpose
+# Keep it always disabled for release codebase
+DEBUG_DECODER_DRIVER ?=n
+
+# (5)
+# This config allows enabling or disabling of MJPEG video
+# decoding functionality with IMG VXD Video decoder. If you
+# do not want MJPEG decode capability, select N.
+# If unsure, select Y
+HAS_JPEG ?=y
+
+# (6)
+# This config allows simulation of Error recovery.
+# This config is only for testing, never enable it for release build.
+ERROR_RECOVERY_SIMULATION ?=n
+
+# (7)
+# This config enables allocation of capture buffers from
+# dma contiguous memory.
+# If unsure, say Y
+CAPTURE_CONTIG_ALLOC ?=n
+
+vxd-dec-y += common/img_mem_man.o \
+	common/img_mem_unified.o \
+	common/imgmmu.o \
+	common/pool_api.o \
+	common/idgen_api.o \
+	common/talmmu_api.o \
+	common/pool.o \
+	common/hash.o \
+	common/ra.o \
+	common/addr_alloc.o \
+	common/work_queue.o \
+	common/lst.o \
+	common/dq.o \
+	common/resource.o \
+	common/rman_api.o \
+
+vxd-dec-y += decoder/vxd_core.o \
+	decoder/vxd_pvdec.o \
+	decoder/dec_resources.o \
+	decoder/pixel_api.o \
+	decoder/vdecdd_utils_buf.o \
+	decoder/vdecdd_utils.o \
+	decoder/vdec_mmu_wrapper.o \
+	decoder/hw_control.o \
+	decoder/vxd_int.o \
+	decoder/translation_api.o \
+	decoder/decoder.o \
+	decoder/core.o \
+	decoder/swsr.o \
+	decoder/h264_secure_parser.o \
+	decoder/bspp.o \
+	decoder/vxd_dec.o \
+	decoder/vxd_v4l2.o \
+
+
+ifeq ($(HAS_HEVC),y)
+ccflags-y   += -DHAS_HEVC
+vxd-dec-y += decoder/hevc_secure_parser.o
+endif
+
+ifeq ($(HAS_JPEG),y)
+ccflags-y   += -DHAS_JPEG
+vxd-dec-y += decoder/jpeg_secure_parser.o
+endif
+
+ifeq ($(DEBUG_DECODER_DRIVER), y)
+ccflags-y   += -DDEBUG_DECODER_DRIVER
+ccflags-y   += -DDEBUG
+endif
+
+ifeq ($(ERROR_CONCEALMENT),y)
+ccflags-y   += -DERROR_CONCEALMENT
+endif
+
+ifeq ($(REDUCED_DPB_NO_PIC_REORDERING),y)
+ccflags-y   += -DREDUCED_DPB_NO_PIC_REORDERING
+endif
+
+ifeq ($(ERROR_RECOVERY_SIMULATION),y)
+ccflags-y   += -DERROR_RECOVERY_SIMULATION
+endif
+
+ifeq ($(CAPTURE_CONTIG_ALLOC),y)
+ccflags-y += -DCAPTURE_CONTIG_ALLOC
+endif
+
+obj-$(CONFIG_VIDEO_IMG_VXD_DEC) += vxd-dec.o
+
+# (1)
+# This config, if enabled, enables all the debug traces in
+# encoder driver. Enable it only for debug purpose
+# Keep it always disabled for release codebase
+DEBUG_ENCODER_DRIVER ?=n
+
+# (3)
+# This config enables encoder performance profiling
+# keep it always disabled. Enable it only for profiling in development
+# environments.
+ENABLE_PROFILING ?=n
+
+vxe-enc-y += common/img_mem_man.o \
+	common/img_mem_unified.o \
+	common/talmmu_api.o \
+	common/addr_alloc.o \
+	common/lst.o \
+	common/hash.o \
+	common/ra.o \
+	common/pool.o \
+	common/rman_api.o \
+	common/dq.o \
+	common/idgen_api.o \
+	common/imgmmu.o \
+	common/work_queue.o \
+
+vxe-enc-y += encoder/vxe_v4l2.o \
+	encoder/vxe_enc.o \
+	encoder/topaz_device.o \
+	encoder/topazmmu.o \
+	encoder/topaz_api.o \
+	encoder/topaz_api_utils.o \
+	encoder/header_gen.o \
+	encoder/mtx_fwif.o \
+
+obj-$(CONFIG_VIDEO_IMG_VXE_ENC) += vxe-enc.o
+
+ifeq ($(DEBUG_ENCODER_DRIVER), y)
+ccflags-y   += -DDEBUG_ENCODER_DRIVER
+ccflags-y   += -DDEBUG
+endif
+
+ifeq ($(ENABLE_PROFILING),y)
+ccflags-y	+= -DENABLE_PROFILING
+endif
+
+ccflags-y += -I$(srctree)/drivers/media/platform/img/vxe-vxd/common/
diff -Naur --no-dereference a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
--- a/drivers/media/platform/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/Kconfig	2024-01-28 14:01:31.244353788 -0500
@@ -69,6 +69,7 @@
 source "drivers/media/platform/atmel/Kconfig"
 source "drivers/media/platform/cadence/Kconfig"
 source "drivers/media/platform/chips-media/Kconfig"
+source "drivers/media/platform/img/Kconfig"
 source "drivers/media/platform/intel/Kconfig"
 source "drivers/media/platform/marvell/Kconfig"
 source "drivers/media/platform/mediatek/Kconfig"
diff -Naur --no-dereference a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
--- a/drivers/media/platform/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/Makefile	2024-01-28 14:01:31.244353788 -0500
@@ -12,6 +12,7 @@
 obj-y += atmel/
 obj-y += cadence/
 obj-y += chips-media/
+obj-y += img/
 obj-y += intel/
 obj-y += marvell/
 obj-y += mediatek/
diff -Naur --no-dereference a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
--- a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,1814 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * TI CSI2 RX driver.
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ * Author: Pratyush Yadav <p.yadav@ti.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/dmaengine.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#include <media/mipi-csi2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mc.h>
+#include <media/videobuf2-dma-contig.h>
+
+#define TI_CSI2RX_MODULE_NAME		"j721e-csi2rx"
+
+#define SHIM_CNTL			0x10
+#define SHIM_CNTL_PIX_RST		BIT(0)
+
+#define SHIM_DMACNTX(i)			(0x20 + ((i) * 0x20))
+#define SHIM_DMACNTX_EN			BIT(31)
+#define SHIM_DMACNTX_YUV422		GENMASK(27, 26)
+#define SHIM_DMACNTX_SIZE		GENMASK(21, 20)
+#define SHIM_DMACNTX_VC			GENMASK(9, 6)
+#define SHIM_DMACNTX_FMT		GENMASK(5, 0)
+#define SHIM_DMACNTX_YUV422_MODE_11	3
+#define SHIM_DMACNTX_SIZE_8		0
+#define SHIM_DMACNTX_SIZE_16		1
+#define SHIM_DMACNTX_SIZE_32		2
+
+#define SHIM_PSI_CFG0(i)		(0x24 + ((i) * 0x20))
+#define SHIM_PSI_CFG0_SRC_TAG		GENMASK(15, 0)
+#define SHIM_PSI_CFG0_DST_TAG		GENMASK(31, 16)
+
+#define PSIL_WORD_SIZE_BYTES		16
+#define TI_CSI2RX_MAX_CTX		32
+
+/*
+ * There are no hard limits on the width or height. The DMA engine can handle
+ * all sizes. The max width and height are arbitrary numbers for this driver.
+ * Use 16K * 16K as the arbitrary limit. It is large enough that it is unlikely
+ * the limit will be hit in practice.
+ */
+#define MAX_WIDTH_BYTES			SZ_16K
+#define MAX_HEIGHT_LINES		SZ_16K
+
+#define TI_CSI2RX_PAD_SINK		0
+#define TI_CSI2RX_PAD_FIRST_SOURCE	1
+#define TI_CSI2RX_MAX_SOURCE_PADS	TI_CSI2RX_MAX_CTX
+#define TI_CSI2RX_MAX_PADS		(1 + TI_CSI2RX_MAX_SOURCE_PADS)
+
+#define DRAIN_TIMEOUT_MS		50
+#define DRAIN_BUFFER_SIZE		SZ_32K
+
+struct ti_csi2rx_fmt {
+	u32				fourcc;	/* Four character code. */
+	u32				code;	/* Mbus code. */
+	u32				csi_dt;	/* CSI Data type. */
+	u8				bpp;	/* Bits per pixel. */
+	u8				size;	/* Data size shift when unpacking. */
+};
+
+struct ti_csi2rx_buffer {
+	/* Common v4l2 buffer. Must be first. */
+	struct vb2_v4l2_buffer		vb;
+	struct list_head		list;
+	struct ti_csi2rx_ctx		*ctx;
+};
+
+enum ti_csi2rx_dma_state {
+	TI_CSI2RX_DMA_STOPPED,	/* Streaming not started yet. */
+	TI_CSI2RX_DMA_IDLE,	/* Streaming but no pending DMA operation. */
+	TI_CSI2RX_DMA_ACTIVE,	/* Streaming and pending DMA operation. */
+};
+
+struct ti_csi2rx_dma {
+	/* Protects all fields in this struct. */
+	spinlock_t			lock;
+	struct dma_chan			*chan;
+	/* Buffers queued to the driver, waiting to be processed by DMA. */
+	struct list_head		queue;
+	enum ti_csi2rx_dma_state	state;
+	/*
+	 * Current buffer being processed by DMA. NULL if no buffer is being
+	 * processed.
+	 */
+	struct ti_csi2rx_buffer		*curr;
+};
+
+struct ti_csi2rx_dev;
+
+struct ti_csi2rx_ctx {
+	struct ti_csi2rx_dev		*csi;
+	struct video_device		vdev;
+	struct vb2_queue		vidq;
+	struct mutex			mutex; /* To serialize ioctls. */
+	struct v4l2_format		v_fmt;
+	struct ti_csi2rx_dma		dma;
+	struct media_pad		pad;
+	u32				sequence;
+	u32				idx;
+	u32				vc;
+	u32				stream;
+};
+
+struct ti_csi2rx_dev {
+	struct device			*dev;
+	void __iomem			*shim;
+	/* To serialize core subdev ioctls. */
+	struct mutex			mutex;
+	unsigned int			enable_count;
+	unsigned int			num_ctx;
+	struct v4l2_async_notifier	notifier;
+	struct media_device		mdev;
+	struct media_pipeline		pipe;
+	struct media_pad		pads[TI_CSI2RX_MAX_PADS];
+	struct v4l2_device		v4l2_dev;
+	struct v4l2_subdev		*source;
+	struct v4l2_subdev		subdev;
+	struct ti_csi2rx_ctx		ctx[TI_CSI2RX_MAX_CTX];
+	u64				enabled_streams_mask;
+	/* Buffer to drain stale data from PSI-L endpoint */
+	struct {
+		void			*vaddr;
+		dma_addr_t		paddr;
+		size_t			len;
+	} drain;
+};
+
+static const struct ti_csi2rx_fmt formats[] = {
+	{
+		.fourcc			= V4L2_PIX_FMT_YUYV,
+		.code			= MEDIA_BUS_FMT_YUYV8_1X16,
+		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_UYVY,
+		.code			= MEDIA_BUS_FMT_UYVY8_1X16,
+		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_YVYU,
+		.code			= MEDIA_BUS_FMT_YVYU8_1X16,
+		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_VYUY,
+		.code			= MEDIA_BUS_FMT_VYUY8_1X16,
+		.csi_dt			= MIPI_CSI2_DT_YUV422_8B,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SBGGR8,
+		.code			= MEDIA_BUS_FMT_SBGGR8_1X8,
+		.csi_dt			= MIPI_CSI2_DT_RAW8,
+		.bpp			= 8,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGBRG8,
+		.code			= MEDIA_BUS_FMT_SGBRG8_1X8,
+		.csi_dt			= MIPI_CSI2_DT_RAW8,
+		.bpp			= 8,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGRBG8,
+		.code			= MEDIA_BUS_FMT_SGRBG8_1X8,
+		.csi_dt			= MIPI_CSI2_DT_RAW8,
+		.bpp			= 8,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SRGGB8,
+		.code			= MEDIA_BUS_FMT_SRGGB8_1X8,
+		.csi_dt			= MIPI_CSI2_DT_RAW8,
+		.bpp			= 8,
+		.size			= SHIM_DMACNTX_SIZE_8,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SBGGR10,
+		.code			= MEDIA_BUS_FMT_SBGGR10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGBRG10,
+		.code			= MEDIA_BUS_FMT_SGBRG10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGRBG10,
+		.code			= MEDIA_BUS_FMT_SGRBG10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SRGGB10,
+		.code			= MEDIA_BUS_FMT_SRGGB10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SBGGR12,
+		.code			= MEDIA_BUS_FMT_SBGGR12_1X12,
+		.csi_dt			= MIPI_CSI2_DT_RAW12,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGBRG12,
+		.code			= MEDIA_BUS_FMT_SGBRG12_1X12,
+		.csi_dt			= MIPI_CSI2_DT_RAW12,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGRBG12,
+		.code			= MEDIA_BUS_FMT_SGRBG12_1X12,
+		.csi_dt			= MIPI_CSI2_DT_RAW12,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SRGGB12,
+		.code			= MEDIA_BUS_FMT_SRGGB12_1X12,
+		.csi_dt			= MIPI_CSI2_DT_RAW12,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SRGGI10,
+		.code			= MEDIA_BUS_FMT_SRGGI10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGRIG10,
+		.code			= MEDIA_BUS_FMT_SGRIG10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SBGGI10,
+		.code			= MEDIA_BUS_FMT_SBGGI10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGBIG10,
+		.code			= MEDIA_BUS_FMT_SGBIG10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGIRG10,
+		.code			= MEDIA_BUS_FMT_SGIRG10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SIGGR10,
+		.code			= MEDIA_BUS_FMT_SIGGR10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SGIBG10,
+		.code			= MEDIA_BUS_FMT_SGIBG10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	}, {
+		.fourcc			= V4L2_PIX_FMT_SIGGB10,
+		.code			= MEDIA_BUS_FMT_SIGGB10_1X10,
+		.csi_dt			= MIPI_CSI2_DT_RAW10,
+		.bpp			= 16,
+		.size			= SHIM_DMACNTX_SIZE_16,
+	},
+
+	/* More formats can be supported but they are not listed for now. */
+};
+
+static const unsigned int num_formats = ARRAY_SIZE(formats);
+
+/* Forward declaration needed by ti_csi2rx_dma_callback. */
+static int ti_csi2rx_start_dma(struct ti_csi2rx_ctx *ctx,
+			       struct ti_csi2rx_buffer *buf);
+
+static const struct ti_csi2rx_fmt *find_format_by_pix(u32 pixelformat)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_formats; i++) {
+		if (formats[i].fourcc == pixelformat)
+			return &formats[i];
+	}
+
+	return NULL;
+}
+
+static const struct ti_csi2rx_fmt *find_format_by_code(u32 code)
+{
+	unsigned int i;
+
+	for (i = 0; i < num_formats; i++) {
+		if (formats[i].code == code)
+			return &formats[i];
+	}
+
+	return NULL;
+}
+
+static void ti_csi2rx_fill_fmt(const struct ti_csi2rx_fmt *csi_fmt,
+			       struct v4l2_format *v4l2_fmt)
+{
+	struct v4l2_pix_format *pix = &v4l2_fmt->fmt.pix;
+	unsigned int pixels_in_word;
+	u8 bpp = csi_fmt->bpp;
+	u32 bpl;
+
+	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
+
+	pix->width = clamp_t(unsigned int, pix->width,
+			     pixels_in_word,
+			     MAX_WIDTH_BYTES * 8 / bpp);
+	pix->width = rounddown(pix->width, pixels_in_word);
+
+	pix->height = clamp_t(unsigned int, pix->height, 1, MAX_HEIGHT_LINES);
+
+	v4l2_fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	pix->pixelformat = csi_fmt->fourcc;
+	pix->colorspace = V4L2_COLORSPACE_SRGB;
+	pix->sizeimage = pix->height * pix->width * (bpp / 8);
+
+	bpl = (pix->width * ALIGN(bpp, 8)) >> 3;
+	pix->bytesperline = ALIGN(bpl, 16);
+}
+
+static int ti_csi2rx_querycap(struct file *file, void *priv,
+			      struct v4l2_capability *cap)
+{
+	strscpy(cap->driver, TI_CSI2RX_MODULE_NAME, sizeof(cap->driver));
+	strscpy(cap->card, TI_CSI2RX_MODULE_NAME, sizeof(cap->card));
+
+	return 0;
+}
+
+static int ti_csi2rx_enum_fmt_vid_cap(struct file *file, void *priv,
+				      struct v4l2_fmtdesc *f)
+{
+	const struct ti_csi2rx_fmt *fmt = NULL;
+
+	if (f->mbus_code) {
+		if (f->index > 0)
+			return -EINVAL;
+
+		fmt = find_format_by_code(f->mbus_code);
+	} else {
+		if (f->index >= num_formats)
+			return -EINVAL;
+
+		fmt = &formats[f->index];
+	}
+
+	if (!fmt)
+		return -EINVAL;
+
+	f->pixelformat = fmt->fourcc;
+	memset(f->reserved, 0, sizeof(f->reserved));
+	f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int ti_csi2rx_g_fmt_vid_cap(struct file *file, void *prov,
+				   struct v4l2_format *f)
+{
+	struct ti_csi2rx_ctx *ctx = video_drvdata(file);
+
+	*f = ctx->v_fmt;
+
+	return 0;
+}
+
+static int ti_csi2rx_try_fmt_vid_cap(struct file *file, void *priv,
+				     struct v4l2_format *f)
+{
+	const struct ti_csi2rx_fmt *fmt;
+
+	/*
+	 * Default to the first format if the requested pixel format code isn't
+	 * supported.
+	 */
+	fmt = find_format_by_pix(f->fmt.pix.pixelformat);
+	if (!fmt)
+		fmt = &formats[0];
+
+	if (f->fmt.pix.field == V4L2_FIELD_ANY)
+		f->fmt.pix.field = V4L2_FIELD_NONE;
+
+	if (f->fmt.pix.field != V4L2_FIELD_NONE)
+		/* Interlaced formats are not supported. */
+		f->fmt.pix.field = V4L2_FIELD_NONE;
+
+	ti_csi2rx_fill_fmt(fmt, f);
+
+	return 0;
+}
+
+static int ti_csi2rx_s_fmt_vid_cap(struct file *file, void *priv,
+				   struct v4l2_format *f)
+{
+	struct ti_csi2rx_ctx *ctx = video_drvdata(file);
+	struct vb2_queue *q = &ctx->vidq;
+	int ret;
+
+	if (vb2_is_busy(q))
+		return -EBUSY;
+
+	ret = ti_csi2rx_try_fmt_vid_cap(file, priv, f);
+	if (ret < 0)
+		return ret;
+
+	ctx->v_fmt = *f;
+
+	return 0;
+}
+
+static int ti_csi2rx_enum_framesizes(struct file *file, void *fh,
+				     struct v4l2_frmsizeenum *fsize)
+{
+	const struct ti_csi2rx_fmt *fmt;
+	unsigned int pixels_in_word;
+	u8 bpp;
+
+	fmt = find_format_by_pix(fsize->pixel_format);
+	if (!fmt || fsize->index != 0)
+		return -EINVAL;
+
+	bpp = ALIGN(fmt->bpp, 8);
+
+	/*
+	 * Number of pixels in one PSI-L word. The transfer happens in multiples
+	 * of PSI-L word sizes.
+	 */
+	pixels_in_word = PSIL_WORD_SIZE_BYTES * 8 / bpp;
+
+	fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+	fsize->stepwise.min_width = pixels_in_word;
+	fsize->stepwise.max_width = rounddown(MAX_WIDTH_BYTES * 8 / bpp,
+					      pixels_in_word);
+	fsize->stepwise.step_width = pixels_in_word;
+	fsize->stepwise.min_height = 1;
+	fsize->stepwise.max_height = MAX_HEIGHT_LINES;
+	fsize->stepwise.step_height = 1;
+
+	return 0;
+}
+
+static const struct v4l2_ioctl_ops csi_ioctl_ops = {
+	.vidioc_querycap      = ti_csi2rx_querycap,
+	.vidioc_enum_fmt_vid_cap = ti_csi2rx_enum_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap = ti_csi2rx_try_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap = ti_csi2rx_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap = ti_csi2rx_s_fmt_vid_cap,
+	.vidioc_enum_framesizes = ti_csi2rx_enum_framesizes,
+	.vidioc_reqbufs       = vb2_ioctl_reqbufs,
+	.vidioc_create_bufs   = vb2_ioctl_create_bufs,
+	.vidioc_prepare_buf   = vb2_ioctl_prepare_buf,
+	.vidioc_querybuf      = vb2_ioctl_querybuf,
+	.vidioc_qbuf          = vb2_ioctl_qbuf,
+	.vidioc_dqbuf         = vb2_ioctl_dqbuf,
+	.vidioc_expbuf        = vb2_ioctl_expbuf,
+	.vidioc_streamon      = vb2_ioctl_streamon,
+	.vidioc_streamoff     = vb2_ioctl_streamoff,
+};
+
+static const struct v4l2_file_operations csi_fops = {
+	.owner = THIS_MODULE,
+	.open = v4l2_fh_open,
+	.release = vb2_fop_release,
+	.read = vb2_fop_read,
+	.poll = vb2_fop_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.mmap = vb2_fop_mmap,
+};
+
+static inline int ti_csi2rx_video_register(struct ti_csi2rx_ctx *ctx)
+{
+	struct ti_csi2rx_dev *csi = ctx->csi;
+	struct video_device *vdev = &ctx->vdev;
+	int ret;
+
+	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
+	if (ret)
+		return ret;
+
+	ret = media_create_pad_link(&csi->subdev.entity,
+				    TI_CSI2RX_PAD_FIRST_SOURCE + ctx->idx,
+				    &vdev->entity, 0,
+				    MEDIA_LNK_FL_IMMUTABLE |
+				    MEDIA_LNK_FL_ENABLED);
+
+	if (ret) {
+		video_unregister_device(vdev);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int csi_async_notifier_bound(struct v4l2_async_notifier *notifier,
+				    struct v4l2_subdev *subdev,
+				    struct v4l2_async_subdev *asd)
+{
+	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
+
+	/* Should register only one source. */
+	WARN_ON(csi->source);
+
+	csi->source = subdev;
+
+	return 0;
+}
+
+static int csi_async_notifier_complete(struct v4l2_async_notifier *notifier)
+{
+	struct ti_csi2rx_dev *csi = dev_get_drvdata(notifier->v4l2_dev->dev);
+	int ret, i;
+
+	ret = v4l2_create_fwnode_links_to_pad(csi->source, &csi->pads[TI_CSI2RX_PAD_SINK],
+					      MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < csi->num_ctx; i++) {
+		ret = ti_csi2rx_video_register(&csi->ctx[i]);
+		if (ret)
+			return ret;
+	}
+
+	return v4l2_device_register_subdev_nodes(&csi->v4l2_dev);
+}
+
+static const struct v4l2_async_notifier_operations csi_async_notifier_ops = {
+	.bound = csi_async_notifier_bound,
+	.complete = csi_async_notifier_complete,
+};
+
+static int ti_csi2rx_init_subdev(struct ti_csi2rx_dev *csi)
+{
+	struct fwnode_handle *fwnode;
+	struct v4l2_async_subdev *asd;
+	int ret;
+
+	fwnode = fwnode_get_named_child_node(csi->dev->fwnode, "csi-bridge");
+	if (!fwnode)
+		return -EINVAL;
+
+	v4l2_async_nf_init(&csi->notifier);
+	csi->notifier.ops = &csi_async_notifier_ops;
+
+	asd = v4l2_async_nf_add_fwnode(&csi->notifier, fwnode,
+				       struct v4l2_async_subdev);
+	fwnode_handle_put(fwnode);
+	if (IS_ERR(asd)) {
+		v4l2_async_nf_cleanup(&csi->notifier);
+		return PTR_ERR(asd);
+	}
+
+	ret = v4l2_async_nf_register(&csi->v4l2_dev, &csi->notifier);
+	if (ret) {
+		v4l2_async_nf_cleanup(&csi->notifier);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void ti_csi2rx_setup_shim(struct ti_csi2rx_ctx *ctx)
+{
+	struct ti_csi2rx_dev *csi = ctx->csi;
+	const struct ti_csi2rx_fmt *fmt;
+	unsigned int reg;
+
+	fmt = find_format_by_pix(ctx->v_fmt.fmt.pix.pixelformat);
+	if (!fmt) {
+		dev_err(csi->dev, "Unknown format\n");
+		return;
+	}
+
+	/* De-assert the pixel interface reset. */
+	if (!csi->enable_count) {
+		reg = SHIM_CNTL_PIX_RST;
+		writel(reg, csi->shim + SHIM_CNTL);
+	}
+
+	reg = SHIM_DMACNTX_EN;
+	reg |= FIELD_PREP(SHIM_DMACNTX_FMT, fmt->csi_dt);
+
+	/*
+	 * The hardware assumes incoming YUV422 8-bit data on MIPI CSI2 bus
+	 * follows the spec and is packed in the order U0 -> Y0 -> V0 -> Y1 ->
+	 * ...
+	 *
+	 * There is an option to swap the bytes around before storing in
+	 * memory, to achieve different pixel formats:
+	 *
+	 * Byte3 ------------ Byte0
+	 * [ Y1 ][ V0 ][ Y0 ][ U0 ]	MODE 11
+	 * [ Y1 ][ U0 ][ Y0 ][ V0 ]	MODE 10
+	 * [ V0 ][ Y1 ][ U0 ][ Y0 ]	MODE 01
+	 * [ Y1 ][ V0 ][ Y0 ][ U0 ]	MODE 00
+	 *
+	 * We don't have any requirement to change pixelformat from what is
+	 * coming from the source, so we keep it in MODE 11, which does not
+	 * swap any bytes when storing in memory.
+	 */
+	switch (fmt->fourcc) {
+	case V4L2_PIX_FMT_UYVY:
+	case V4L2_PIX_FMT_VYUY:
+	case V4L2_PIX_FMT_YUYV:
+	case V4L2_PIX_FMT_YVYU:
+		reg |= FIELD_PREP(SHIM_DMACNTX_YUV422,
+					SHIM_DMACNTX_YUV422_MODE_11);
+		break;
+	default:
+		/* Ignore if not YUV 4:2:2 */
+		break;
+	}
+
+	reg |= FIELD_PREP(SHIM_DMACNTX_SIZE, fmt->size);
+	reg |= FIELD_PREP(SHIM_DMACNTX_VC, ctx->vc);
+
+	writel(reg, csi->shim + SHIM_DMACNTX(ctx->idx));
+
+	reg = FIELD_PREP(SHIM_PSI_CFG0_SRC_TAG, 0) |
+	      FIELD_PREP(SHIM_PSI_CFG0_DST_TAG, 0);
+	writel(reg, csi->shim + SHIM_PSI_CFG0(ctx->idx));
+}
+
+static void ti_csi2rx_drain_callback(void *param)
+{
+	struct completion *drain_complete = param;
+
+	complete(drain_complete);
+}
+
+/*
+ * Drain the stale data left at the PSI-L endpoint.
+ *
+ * This might happen if no buffers are queued in time but source is still
+ * streaming. In multi-stream scenarios this can happen when one stream is
+ * stopped but other is still streaming, and thus module-level pixel reset is
+ * not asserted.
+ *
+ * To prevent that stale data corrupting the subsequent transactions, it is
+ * required to issue DMA requests to drain it out.
+ */
+static int ti_csi2rx_drain_dma(struct ti_csi2rx_ctx *ctx)
+{
+	struct ti_csi2rx_dev *csi = ctx->csi;
+	struct dma_async_tx_descriptor *desc;
+	struct completion drain_complete;
+	dma_cookie_t cookie;
+	int ret;
+
+	init_completion(&drain_complete);
+
+	desc = dmaengine_prep_slave_single(ctx->dma.chan, csi->drain.paddr,
+					   csi->drain.len, DMA_DEV_TO_MEM,
+					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc) {
+		ret = -EIO;
+		goto out;
+	}
+
+	desc->callback = ti_csi2rx_drain_callback;
+	desc->callback_param = &drain_complete;
+
+	cookie = dmaengine_submit(desc);
+	ret = dma_submit_error(cookie);
+	if (ret)
+		goto out;
+
+	dma_async_issue_pending(ctx->dma.chan);
+
+	if (!wait_for_completion_timeout(&drain_complete,
+					 msecs_to_jiffies(DRAIN_TIMEOUT_MS))) {
+		dmaengine_terminate_sync(ctx->dma.chan);
+		dev_dbg(csi->dev, "DMA transfer timed out for drain buffer\n");
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+out:
+	return ret;
+}
+
+static void ti_csi2rx_dma_callback(void *param)
+{
+	struct ti_csi2rx_buffer *buf = param;
+	struct ti_csi2rx_ctx *ctx = buf->ctx;
+	struct ti_csi2rx_dma *dma = &ctx->dma;
+	unsigned long flags = 0;
+
+	/*
+	 * TODO: Derive the sequence number from the CSI2RX frame number
+	 * hardware monitor registers.
+	 */
+	buf->vb.vb2_buf.timestamp = ktime_get_ns();
+	buf->vb.sequence = ctx->sequence++;
+
+	spin_lock_irqsave(&dma->lock, flags);
+
+	WARN_ON(dma->curr != buf);
+	vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
+
+	/* If there are more buffers to process then start their transfer. */
+	dma->curr = NULL;
+	while (!list_empty(&dma->queue)) {
+		buf = list_entry(dma->queue.next, struct ti_csi2rx_buffer, list);
+		list_del(&buf->list);
+
+		if (ti_csi2rx_start_dma(ctx, buf)) {
+			dev_err(ctx->csi->dev,
+				"Failed to queue the next buffer for DMA\n");
+			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+		} else {
+			dma->curr = buf;
+			break;
+		}
+	}
+
+	if (!dma->curr)
+		dma->state = TI_CSI2RX_DMA_IDLE;
+
+	spin_unlock_irqrestore(&dma->lock, flags);
+}
+
+static int ti_csi2rx_start_dma(struct ti_csi2rx_ctx *ctx,
+			       struct ti_csi2rx_buffer *buf)
+{
+	unsigned long addr;
+	struct dma_async_tx_descriptor *desc;
+	size_t len = ctx->v_fmt.fmt.pix.sizeimage;
+	dma_cookie_t cookie;
+	int ret = 0;
+
+	addr = vb2_dma_contig_plane_dma_addr(&buf->vb.vb2_buf, 0);
+	desc = dmaengine_prep_slave_single(ctx->dma.chan, addr, len,
+					   DMA_DEV_TO_MEM,
+					   DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	if (!desc)
+		return -EIO;
+
+	desc->callback = ti_csi2rx_dma_callback;
+	desc->callback_param = buf;
+
+	cookie = dmaengine_submit(desc);
+	ret = dma_submit_error(cookie);
+	if (ret)
+		return ret;
+
+	dma_async_issue_pending(ctx->dma.chan);
+
+	return 0;
+}
+
+static void ti_csi2rx_cleanup_buffers(struct ti_csi2rx_ctx *ctx,
+				      enum vb2_buffer_state buf_state)
+{
+	struct ti_csi2rx_dma *dma = &ctx->dma;
+	struct ti_csi2rx_buffer *buf = NULL, *tmp;
+	enum ti_csi2rx_dma_state state;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&dma->lock, flags);
+	state = ctx->dma.state;
+	dma->state = TI_CSI2RX_DMA_STOPPED;
+	spin_unlock_irqrestore(&dma->lock, flags);
+
+	if (state != TI_CSI2RX_DMA_STOPPED) {
+		ret = ti_csi2rx_drain_dma(ctx);
+		if (ret)
+			dev_dbg(ctx->csi->dev,
+				"Failed to drain DMA. Next frame might be bogus\n");
+	}
+	dmaengine_terminate_sync(ctx->dma.chan);
+
+	spin_lock_irqsave(&dma->lock, flags);
+	list_for_each_entry_safe(buf, tmp, &ctx->dma.queue, list) {
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb.vb2_buf, buf_state);
+	}
+
+	if (dma->curr)
+		vb2_buffer_done(&dma->curr->vb.vb2_buf, buf_state);
+	spin_unlock_irqrestore(&dma->lock, flags);
+}
+
+static int ti_csi2rx_restart_dma(struct ti_csi2rx_ctx *ctx,
+				 struct ti_csi2rx_buffer *buf)
+{
+	struct ti_csi2rx_dma *dma = &ctx->dma;
+	unsigned long flags = 0;
+	int ret = 0;
+
+	ret = ti_csi2rx_drain_dma(ctx);
+	if (ret)
+		dev_warn(ctx->csi->dev,
+			 "Failed to drain DMA. Next frame might be bogus\n");
+
+	ret = ti_csi2rx_start_dma(ctx, buf);
+	if (ret) {
+		dev_err(ctx->csi->dev, "Failed to start DMA: %d\n", ret);
+		spin_lock_irqsave(&dma->lock, flags);
+		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+		dma->curr = NULL;
+		dma->state = TI_CSI2RX_DMA_IDLE;
+		spin_unlock_irqrestore(&dma->lock, flags);
+	}
+
+	return ret;
+}
+
+static int ti_csi2rx_queue_setup(struct vb2_queue *q, unsigned int *nbuffers,
+				 unsigned int *nplanes, unsigned int sizes[],
+				 struct device *alloc_devs[])
+{
+	struct ti_csi2rx_ctx *ctx = vb2_get_drv_priv(q);
+	unsigned int size = ctx->v_fmt.fmt.pix.sizeimage;
+
+	if (*nplanes) {
+		if (sizes[0] < size)
+			return -EINVAL;
+		size = sizes[0];
+	}
+
+	*nplanes = 1;
+	sizes[0] = size;
+
+	return 0;
+}
+
+static int ti_csi2rx_buffer_prepare(struct vb2_buffer *vb)
+{
+	struct ti_csi2rx_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	unsigned long size = ctx->v_fmt.fmt.pix.sizeimage;
+
+	if (vb2_plane_size(vb, 0) < size) {
+		dev_err(ctx->csi->dev, "Data will not fit into plane\n");
+		return -EINVAL;
+	}
+
+	vb2_set_plane_payload(vb, 0, size);
+	return 0;
+}
+
+static void ti_csi2rx_buffer_queue(struct vb2_buffer *vb)
+{
+	struct ti_csi2rx_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct ti_csi2rx_buffer *buf;
+	struct ti_csi2rx_dma *dma = &ctx->dma;
+	bool restart_dma = false;
+	unsigned long flags = 0;
+
+	buf = container_of(vb, struct ti_csi2rx_buffer, vb.vb2_buf);
+	buf->ctx = ctx;
+
+	spin_lock_irqsave(&dma->lock, flags);
+	/*
+	 * Usually the DMA callback takes care of queueing the pending buffers.
+	 * But if DMA has stalled due to lack of buffers, restart it now.
+	 */
+	if (dma->state == TI_CSI2RX_DMA_IDLE) {
+		/*
+		 * Do not restart DMA with the lock held because
+		 * ti_csi2rx_drain_dma() might block when allocating a buffer.
+		 * There won't be a race on queueing DMA anyway since the
+		 * callback is not being fired.
+		 */
+		restart_dma = true;
+		dma->curr = buf;
+		dma->state = TI_CSI2RX_DMA_ACTIVE;
+	} else {
+		list_add_tail(&buf->list, &dma->queue);
+	}
+	spin_unlock_irqrestore(&dma->lock, flags);
+
+	if (restart_dma) {
+		/*
+		 * Once frames start dropping, some data gets stuck in the DMA
+		 * pipeline somewhere. So the first DMA transfer after frame
+		 * drops gives a partial frame. This is obviously not useful to
+		 * the application and will only confuse it. Issue a DMA
+		 * transaction to drain that up.
+		 */
+		ti_csi2rx_restart_dma(ctx, buf);
+	}
+}
+
+static int ti_csi2rx_get_vc(struct ti_csi2rx_ctx *ctx)
+{
+	struct ti_csi2rx_dev *csi = ctx->csi;
+	struct v4l2_mbus_frame_desc fd;
+	struct media_pad *pad;
+	int ret, i;
+
+	pad = media_entity_remote_pad_unique(&csi->subdev.entity, MEDIA_PAD_FL_SOURCE);
+	if (!pad)
+		return -ENODEV;
+
+	ret = v4l2_subdev_call(csi->source, pad, get_frame_desc, pad->index,
+			       &fd);
+	if (ret)
+		return ret;
+
+	if (fd.type != V4L2_MBUS_FRAME_DESC_TYPE_CSI2)
+		return -EINVAL;
+
+	for (i = 0; i < fd.num_entries; i++) {
+		if (ctx->stream == fd.entry[i].stream)
+			return fd.entry[i].bus.csi2.vc;
+	}
+
+	return -ENODEV;
+}
+
+static int ti_csi2rx_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+	struct ti_csi2rx_ctx *ctx = vb2_get_drv_priv(vq);
+	struct ti_csi2rx_dev *csi = ctx->csi;
+	struct ti_csi2rx_dma *dma = &ctx->dma;
+	struct ti_csi2rx_buffer *buf;
+	struct v4l2_subdev_krouting *routing;
+	struct v4l2_subdev_route *route = NULL;
+	struct media_pad *remote_pad;
+	unsigned long flags = 0;
+	int ret = 0, i;
+	struct v4l2_subdev_state *state;
+
+	ret = pm_runtime_resume_and_get(csi->dev);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&dma->lock, flags);
+	if (list_empty(&dma->queue))
+		ret = -EIO;
+	spin_unlock_irqrestore(&dma->lock, flags);
+	if (ret)
+		return ret;
+
+	ret = video_device_pipeline_start(&ctx->vdev, &csi->pipe);
+	if (ret)
+		goto err;
+
+	remote_pad = media_entity_remote_source_pad_unique(ctx->pad.entity);
+	if (!remote_pad) {
+		ret = -ENODEV;
+		goto err_pipeline;
+	}
+
+	state = v4l2_subdev_lock_and_get_active_state(&csi->subdev);
+
+	routing = &state->routing;
+
+	/* Find the stream to process. */
+	for (i = 0; i < routing->num_routes; i++) {
+		struct v4l2_subdev_route *r = &routing->routes[i];
+
+		if (!(r->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))
+			continue;
+
+		if (r->source_pad != remote_pad->index)
+			continue;
+
+		route = r;
+		break;
+	}
+
+	if (!route) {
+		ret = -ENODEV;
+		v4l2_subdev_unlock_state(state);
+		goto err_pipeline;
+	}
+
+	ctx->stream = route->sink_stream;
+
+	v4l2_subdev_unlock_state(state);
+
+	ret = ti_csi2rx_get_vc(ctx);
+	if (ret == -ENOIOCTLCMD)
+		ctx->vc = 0;
+	else if (ret < 0)
+		goto err_pipeline;
+	else
+		ctx->vc = ret;
+
+	ti_csi2rx_setup_shim(ctx);
+
+	ctx->sequence = 0;
+
+	spin_lock_irqsave(&dma->lock, flags);
+	buf = list_entry(dma->queue.next, struct ti_csi2rx_buffer, list);
+	list_del(&buf->list);
+	dma->curr = buf;
+
+	ret = ti_csi2rx_start_dma(ctx, buf);
+	if (ret) {
+		dev_err(csi->dev, "Failed to start DMA: %d\n", ret);
+		spin_unlock_irqrestore(&dma->lock, flags);
+		goto err_dma;
+	}
+
+	dma->state = TI_CSI2RX_DMA_ACTIVE;
+	spin_unlock_irqrestore(&dma->lock, flags);
+
+	ret = v4l2_subdev_enable_streams(&csi->subdev,
+					 TI_CSI2RX_PAD_FIRST_SOURCE + ctx->idx,
+					 BIT(0));
+	if (ret)
+		goto err_dma;
+
+	return 0;
+
+err_dma:
+	writel(0, csi->shim + SHIM_DMACNTX(ctx->idx));
+err_pipeline:
+	video_device_pipeline_stop(&ctx->vdev);
+err:
+	ti_csi2rx_cleanup_buffers(ctx, VB2_BUF_STATE_QUEUED);
+	pm_runtime_put(csi->dev);
+	return ret;
+}
+
+static void ti_csi2rx_stop_streaming(struct vb2_queue *vq)
+{
+	struct ti_csi2rx_ctx *ctx = vb2_get_drv_priv(vq);
+	struct ti_csi2rx_dev *csi = ctx->csi;
+	int ret;
+
+	/* assert pixel reset to prevent stale data on stopping last stream */
+	if (csi->enable_count == 1)
+		writel(0, csi->shim + SHIM_CNTL);
+
+	video_device_pipeline_stop(&ctx->vdev);
+
+	ret = v4l2_subdev_disable_streams(&csi->subdev,
+					  TI_CSI2RX_PAD_FIRST_SOURCE + ctx->idx,
+					  BIT(0));
+	if (ret)
+		dev_err(csi->dev, "Failed to stop subdev stream\n");
+
+	writel(0, csi->shim + SHIM_DMACNTX(ctx->idx));
+
+	ti_csi2rx_cleanup_buffers(ctx, VB2_BUF_STATE_ERROR);
+	pm_runtime_put(csi->dev);
+}
+
+static const struct vb2_ops csi_vb2_qops = {
+	.queue_setup = ti_csi2rx_queue_setup,
+	.buf_prepare = ti_csi2rx_buffer_prepare,
+	.buf_queue = ti_csi2rx_buffer_queue,
+	.start_streaming = ti_csi2rx_start_streaming,
+	.stop_streaming = ti_csi2rx_stop_streaming,
+	.wait_prepare = vb2_ops_wait_prepare,
+	.wait_finish = vb2_ops_wait_finish,
+};
+
+static inline struct ti_csi2rx_dev *to_csi2rx_dev(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct ti_csi2rx_dev, subdev);
+}
+
+static int ti_csi2rx_sd_set_fmt(struct v4l2_subdev *sd,
+				struct v4l2_subdev_state *state,
+				struct v4l2_subdev_format *format)
+{
+	struct v4l2_mbus_framefmt *fmt;
+	int ret = 0;
+
+	/* No transcoding, don't allow setting source fmt */
+	if (format->pad >= TI_CSI2RX_PAD_FIRST_SOURCE)
+		return v4l2_subdev_get_fmt(sd, state, format);
+
+	if (!find_format_by_code(format->format.code))
+		format->format.code = formats[0].code;
+
+	fmt = v4l2_subdev_state_get_stream_format(state, format->pad,
+						  format->stream);
+	if (!fmt) {
+		ret = -EINVAL;
+		goto out;
+	}
+	*fmt = format->format;
+
+	fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
+							   format->stream);
+	if (!fmt) {
+		ret = -EINVAL;
+		goto out;
+	}
+	*fmt = format->format;
+
+out:
+	return ret;
+}
+
+static int _ti_csi2rx_sd_set_routing(struct v4l2_subdev *sd,
+				     struct v4l2_subdev_state *state,
+				     struct v4l2_subdev_krouting *routing)
+{
+	int ret;
+
+	const struct v4l2_mbus_framefmt format = {
+		.width = 640,
+		.height = 480,
+		.code = MEDIA_BUS_FMT_UYVY8_1X16,
+		.field = V4L2_FIELD_NONE,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.ycbcr_enc = V4L2_YCBCR_ENC_601,
+		.quantization = V4L2_QUANTIZATION_LIM_RANGE,
+		.xfer_func = V4L2_XFER_FUNC_SRGB,
+	};
+
+	ret = v4l2_subdev_routing_validate(sd, routing,
+					   V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
+
+	if (ret)
+		return ret;
+
+	ret = v4l2_subdev_set_routing_with_fmt(sd, state, routing, &format);
+
+	return ret;
+}
+
+static int ti_csi2rx_sd_set_routing(struct v4l2_subdev *sd,
+				    struct v4l2_subdev_state *state,
+				    enum v4l2_subdev_format_whence which,
+				    struct v4l2_subdev_krouting *routing)
+{
+	return _ti_csi2rx_sd_set_routing(sd, state, routing);
+}
+
+static int ti_csi2rx_sd_init_cfg(struct v4l2_subdev *sd,
+				 struct v4l2_subdev_state *state)
+{
+	struct v4l2_subdev_route routes[] = { {
+		.sink_pad = 0,
+		.sink_stream = 0,
+		.source_pad = TI_CSI2RX_PAD_FIRST_SOURCE,
+		.source_stream = 0,
+		.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
+	} };
+
+	struct v4l2_subdev_krouting routing = {
+		.num_routes = 1,
+		.routes = routes,
+	};
+
+	/* Initialize routing to single route to the fist source pad */
+	return _ti_csi2rx_sd_set_routing(sd, state, &routing);
+}
+
+static int ti_csi2rx_sd_all_sink_streams(struct v4l2_subdev_state *state)
+{
+	struct v4l2_subdev_krouting *routing = &state->routing;
+	u64 sink_streams = 0;
+	int i;
+
+	for (i = 0; i < routing->num_routes; i++) {
+		struct v4l2_subdev_route *r = &routing->routes[i];
+
+		if (r->sink_pad == TI_CSI2RX_PAD_SINK)
+			sink_streams |= BIT(r->sink_stream);
+	}
+
+	return sink_streams;
+}
+
+static int ti_csi2rx_sd_enable_streams(struct v4l2_subdev *sd,
+				       struct v4l2_subdev_state *state,
+				       u32 pad, u64 streams_mask)
+{
+	struct ti_csi2rx_dev *csi = to_csi2rx_dev(sd);
+	struct media_pad *remote_pad;
+	int ret = 0;
+
+	remote_pad = media_entity_remote_source_pad_unique(&csi->subdev.entity);
+	if (!remote_pad)
+		return -ENODEV;
+
+	mutex_lock(&csi->mutex);
+	if (!csi->enable_count) {
+		u64 sink_streams;
+
+		sink_streams = ti_csi2rx_sd_all_sink_streams(state);
+		dev_dbg(csi->dev, "Enabling all streams (%llx) on sink.\n",
+			sink_streams);
+		ret = v4l2_subdev_enable_streams(csi->source, remote_pad->index,
+						 sink_streams);
+		if (ret)
+			goto out;
+		csi->enabled_streams_mask = sink_streams;
+	}
+
+	csi->enable_count++;
+out:
+	mutex_unlock(&csi->mutex);
+	return ret;
+}
+
+static int ti_csi2rx_sd_disable_streams(struct v4l2_subdev *sd,
+					struct v4l2_subdev_state *state,
+					u32 pad, u64 streams_mask)
+{
+	struct ti_csi2rx_dev *csi = to_csi2rx_dev(sd);
+	struct media_pad *remote_pad;
+	int ret = 0;
+
+	remote_pad = media_entity_remote_source_pad_unique(&csi->subdev.entity);
+	if (!remote_pad)
+		return -ENODEV;
+
+	mutex_lock(&csi->mutex);
+	if (csi->enable_count == 0) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (csi->enable_count == 1) {
+		u64 sink_streams;
+
+		sink_streams = ti_csi2rx_sd_all_sink_streams(state);
+		dev_dbg(csi->dev, "Disabling all streams (%llx) on sink.\n",
+			sink_streams);
+		ret = v4l2_subdev_disable_streams(csi->source, remote_pad->index,
+						  sink_streams);
+		if (ret)
+			goto out;
+		csi->enabled_streams_mask = 0;
+	}
+
+	--csi->enable_count;
+out:
+	mutex_unlock(&csi->mutex);
+	return ret;
+}
+
+static const struct v4l2_subdev_pad_ops ti_csi2rx_subdev_pad_ops = {
+	.init_cfg = ti_csi2rx_sd_init_cfg,
+	.set_routing = ti_csi2rx_sd_set_routing,
+	.get_fmt = v4l2_subdev_get_fmt,
+	.set_fmt = ti_csi2rx_sd_set_fmt,
+	.enable_streams = ti_csi2rx_sd_enable_streams,
+	.disable_streams = ti_csi2rx_sd_disable_streams,
+};
+
+static const struct v4l2_subdev_ops ti_csi2rx_subdev_ops = {
+	.pad = &ti_csi2rx_subdev_pad_ops,
+};
+
+static void ti_csi2rx_cleanup_dma(struct ti_csi2rx_ctx *ctx)
+{
+	dma_release_channel(ctx->dma.chan);
+}
+
+static void ti_csi2rx_cleanup_v4l2(struct ti_csi2rx_dev *csi)
+{
+	media_device_unregister(&csi->mdev);
+	v4l2_device_unregister(&csi->v4l2_dev);
+	media_device_cleanup(&csi->mdev);
+}
+
+static void ti_csi2rx_cleanup_subdev(struct ti_csi2rx_dev *csi)
+{
+	v4l2_async_nf_unregister(&csi->notifier);
+	v4l2_async_nf_cleanup(&csi->notifier);
+}
+
+static void ti_csi2rx_cleanup_vb2q(struct ti_csi2rx_ctx *ctx)
+{
+	vb2_queue_release(&ctx->vidq);
+}
+
+static void ti_csi2rx_cleanup_ctx(struct ti_csi2rx_ctx *ctx)
+{
+	if (!pm_runtime_status_suspended(ctx->csi->dev))
+		ti_csi2rx_cleanup_dma(ctx);
+
+	ti_csi2rx_cleanup_vb2q(ctx);
+
+	video_unregister_device(&ctx->vdev);
+
+	mutex_destroy(&ctx->mutex);
+}
+
+static int ti_csi2rx_init_vb2q(struct ti_csi2rx_ctx *ctx)
+{
+	struct vb2_queue *q = &ctx->vidq;
+	int ret;
+
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_DMABUF;
+	q->drv_priv = ctx;
+	q->buf_struct_size = sizeof(struct ti_csi2rx_buffer);
+	q->ops = &csi_vb2_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+	q->dev = dmaengine_get_dma_device(ctx->dma.chan);
+	q->lock = &ctx->mutex;
+	q->min_buffers_needed = 1;
+
+	ret = vb2_queue_init(q);
+	if (ret)
+		return ret;
+
+	ctx->vdev.queue = q;
+
+	return 0;
+}
+
+static int ti_csi2rx_link_validate_get_fmt(struct media_pad *pad,
+					   struct v4l2_subdev_format *fmt)
+{
+	if (is_media_entity_v4l2_subdev(pad->entity)) {
+		struct v4l2_subdev *sd =
+			media_entity_to_v4l2_subdev(pad->entity);
+
+		fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		fmt->pad = pad->index;
+		return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
+	}
+
+	WARN(pad->entity->function != MEDIA_ENT_F_IO_V4L,
+	     "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
+	     pad->entity->function, pad->entity->name);
+
+	return -EINVAL;
+}
+
+static int ti_csi2rx_link_validate(struct media_link *link)
+{
+	struct media_entity *entity = link->sink->entity;
+	struct video_device *vdev = media_entity_to_video_device(entity);
+	struct ti_csi2rx_ctx *ctx = container_of(vdev, struct ti_csi2rx_ctx, vdev);
+	struct ti_csi2rx_dev *csi = ctx->csi;
+	struct v4l2_pix_format *csi_fmt = &ctx->v_fmt.fmt.pix;
+	struct v4l2_subdev_format source_fmt;
+	const struct ti_csi2rx_fmt *ti_fmt;
+	int ret;
+
+	ret = ti_csi2rx_link_validate_get_fmt(link->source, &source_fmt);
+	if (ret)
+		return ret;
+
+	if (source_fmt.format.width != csi_fmt->width) {
+		dev_dbg(csi->dev, "Width does not match (source %u, sink %u)\n",
+			source_fmt.format.width, csi_fmt->width);
+		return -EPIPE;
+	}
+
+	if (source_fmt.format.height != csi_fmt->height) {
+		dev_dbg(csi->dev, "Height does not match (source %u, sink %u)\n",
+			source_fmt.format.height, csi_fmt->height);
+		return -EPIPE;
+	}
+
+	if (source_fmt.format.field != csi_fmt->field &&
+	    csi_fmt->field != V4L2_FIELD_NONE) {
+		dev_dbg(csi->dev, "Field does not match (source %u, sink %u)\n",
+			source_fmt.format.field, csi_fmt->field);
+		return -EPIPE;
+	}
+
+	ti_fmt = find_format_by_code(source_fmt.format.code);
+	if (!ti_fmt) {
+		dev_dbg(csi->dev, "Media bus format 0x%x not supported\n",
+			source_fmt.format.code);
+		return -EPIPE;
+	}
+
+	if (ctx->v_fmt.fmt.pix.pixelformat != ti_fmt->fourcc) {
+		dev_dbg(csi->dev,
+			"Cannot transform source fmt 0x%x to sink fmt 0x%x\n",
+			ctx->v_fmt.fmt.pix.pixelformat, ti_fmt->fourcc);
+		return -EPIPE;
+	}
+
+	return 0;
+}
+
+static const struct media_entity_operations ti_csi2rx_video_entity_ops = {
+	.link_validate = ti_csi2rx_link_validate,
+};
+
+static int ti_csi2rx_init_dma(struct ti_csi2rx_ctx *ctx)
+{
+	struct dma_slave_config cfg = {
+		.src_addr_width = DMA_SLAVE_BUSWIDTH_16_BYTES };
+	char name[32];
+	int ret;
+
+	snprintf(name, sizeof(name), "rx%u", ctx->idx);
+	ctx->dma.chan = dma_request_chan(ctx->csi->dev, name);
+	if (IS_ERR(ctx->dma.chan))
+		return PTR_ERR(ctx->dma.chan);
+
+	ret = dmaengine_slave_config(ctx->dma.chan, &cfg);
+	if (ret) {
+		dma_release_channel(ctx->dma.chan);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ti_csi2rx_v4l2_init(struct ti_csi2rx_dev *csi)
+{
+	struct media_device *mdev = &csi->mdev;
+	struct v4l2_subdev *sd = &csi->subdev;
+	int ret, i;
+
+	mdev->dev = csi->dev;
+	mdev->hw_revision = 1;
+	strscpy(mdev->model, "TI-CSI2RX", sizeof(mdev->model));
+
+	media_device_init(mdev);
+
+	csi->v4l2_dev.mdev = mdev;
+
+	ret = v4l2_device_register(csi->dev, &csi->v4l2_dev);
+	if (ret)
+		goto cleanup_media;
+
+	ret = media_device_register(mdev);
+	if (ret)
+		goto unregister_v4l2;
+
+	v4l2_subdev_init(sd, &ti_csi2rx_subdev_ops);
+	sd->entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
+	sd->flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
+	strscpy(sd->name, dev_name(csi->dev), sizeof(sd->name));
+	sd->dev = csi->dev;
+
+	csi->pads[TI_CSI2RX_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+
+	for (i = TI_CSI2RX_PAD_FIRST_SOURCE;
+	     i < TI_CSI2RX_PAD_FIRST_SOURCE + csi->num_ctx; i++)
+		csi->pads[i].flags = MEDIA_PAD_FL_SOURCE;
+
+	ret = media_entity_pads_init(&sd->entity,
+				     TI_CSI2RX_PAD_FIRST_SOURCE + csi->num_ctx,
+				     csi->pads);
+	if (ret)
+		goto unregister_media;
+
+	ret = v4l2_subdev_init_finalize(sd);
+	if (ret)
+		goto unregister_media;
+
+	ret = v4l2_device_register_subdev(&csi->v4l2_dev, sd);
+	if (ret)
+		goto cleanup_subdev;
+
+	return 0;
+
+cleanup_subdev:
+	v4l2_subdev_cleanup(sd);
+unregister_media:
+	media_device_unregister(mdev);
+unregister_v4l2:
+	v4l2_device_unregister(&csi->v4l2_dev);
+cleanup_media:
+	media_device_cleanup(mdev);
+
+	return ret;
+}
+
+static int ti_csi2rx_init_ctx(struct ti_csi2rx_ctx *ctx)
+{
+	struct ti_csi2rx_dev *csi = ctx->csi;
+	struct video_device *vdev = &ctx->vdev;
+	const struct ti_csi2rx_fmt *fmt;
+	struct v4l2_pix_format *pix_fmt = &ctx->v_fmt.fmt.pix;
+	int ret;
+
+	mutex_init(&ctx->mutex);
+
+	fmt = find_format_by_pix(V4L2_PIX_FMT_UYVY);
+	if (!fmt)
+		return -EINVAL;
+
+	pix_fmt->width = 640;
+	pix_fmt->height = 480;
+
+	ti_csi2rx_fill_fmt(fmt, &ctx->v_fmt);
+
+	ctx->pad.flags = MEDIA_PAD_FL_SINK;
+	ret = media_entity_pads_init(&ctx->vdev.entity, 1, &ctx->pad);
+	if (ret)
+		return ret;
+
+	snprintf(vdev->name, sizeof(vdev->name), "%s context %u",
+		 dev_name(csi->dev), ctx->idx);
+	vdev->v4l2_dev = &csi->v4l2_dev;
+	vdev->vfl_dir = VFL_DIR_RX;
+	vdev->fops = &csi_fops;
+	vdev->ioctl_ops = &csi_ioctl_ops;
+	vdev->release = video_device_release_empty;
+	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
+			    V4L2_CAP_IO_MC;
+	vdev->lock = &ctx->mutex;
+	video_set_drvdata(vdev, ctx);
+
+	INIT_LIST_HEAD(&ctx->dma.queue);
+	spin_lock_init(&ctx->dma.lock);
+	ctx->dma.state = TI_CSI2RX_DMA_STOPPED;
+
+	ret = ti_csi2rx_init_dma(ctx);
+	if (ret)
+		return ret;
+
+	ret = ti_csi2rx_init_vb2q(ctx);
+	if (ret)
+		goto cleanup_dma;
+
+	return 0;
+
+cleanup_dma:
+	ti_csi2rx_cleanup_dma(ctx);
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int ti_csi2rx_suspend(struct device *dev)
+{
+	struct ti_csi2rx_dev *csi = dev_get_drvdata(dev);
+	enum ti_csi2rx_dma_state state;
+	struct ti_csi2rx_ctx *ctx;
+	struct ti_csi2rx_dma *dma;
+	unsigned long flags = 0;
+	int i, ret = 0;
+
+	/* If device was not in use we can simply suspend */
+	if (pm_runtime_status_suspended(dev))
+		return 0;
+
+	/*
+	 * If device is running, assert the pixel reset to cleanly stop any
+	 * on-going streams before we suspend.
+	 */
+	writel(0, csi->shim + SHIM_CNTL);
+
+	for (i = 0; i < csi->num_ctx; i++) {
+		ctx = &csi->ctx[i];
+		dma = &ctx->dma;
+
+		spin_lock_irqsave(&dma->lock, flags);
+		state = dma->state;
+		spin_unlock_irqrestore(&dma->lock, flags);
+
+		if (state != TI_CSI2RX_DMA_STOPPED) {
+			ret = v4l2_subdev_disable_streams(&csi->subdev,
+							  TI_CSI2RX_PAD_FIRST_SOURCE + ctx->idx,
+							  BIT(0));
+			if (ret)
+				dev_err(csi->dev, "Failed to stop subdev stream\n");
+
+		}
+
+		/* Stop any on-going streams */
+		writel(0, csi->shim + SHIM_DMACNTX(ctx->idx));
+
+		/* Drain DMA */
+		ti_csi2rx_drain_dma(ctx);
+
+		/* Terminate DMA */
+		ret = dmaengine_terminate_sync(ctx->dma.chan);
+		if (ret)
+			dev_err(csi->dev, "Failed to stop DMA\n");
+
+	}
+
+
+	return ret;
+}
+
+static int ti_csi2rx_resume(struct device *dev)
+{
+	struct ti_csi2rx_dev *csi = dev_get_drvdata(dev);
+	struct ti_csi2rx_ctx *ctx;
+	struct ti_csi2rx_dma *dma;
+	struct ti_csi2rx_buffer *buf;
+	unsigned long flags = 0;
+	unsigned int reg;
+	int i, ret = 0;
+
+	/* If device was not in use, we can simply wakeup */
+	if (pm_runtime_status_suspended(dev))
+		return 0;
+
+	/* If device was in use before, restore all the running streams */
+	reg = SHIM_CNTL_PIX_RST;
+	writel(reg, csi->shim + SHIM_CNTL);
+
+	for (i = 0; i < csi->num_ctx; i++) {
+		ctx = &csi->ctx[i];
+		dma = &ctx->dma;
+		spin_lock_irqsave(&dma->lock, flags);
+		if (dma->state != TI_CSI2RX_DMA_STOPPED) {
+			buf = dma->curr;
+			spin_unlock_irqrestore(&dma->lock, flags);
+
+			/* Restore stream config */
+			ti_csi2rx_setup_shim(ctx);
+
+			ret = v4l2_subdev_enable_streams(&csi->subdev,
+							 TI_CSI2RX_PAD_FIRST_SOURCE + ctx->idx,
+							 BIT(0));
+			if (ret)
+				dev_err(ctx->csi->dev, "Failed to start subdev\n");
+
+			/* Restart DMA */
+			if (buf)
+				ti_csi2rx_restart_dma(ctx, buf);
+		} else {
+			spin_unlock_irqrestore(&dma->lock, flags);
+		}
+	}
+
+	return ret;
+}
+
+static int ti_csi2rx_runtime_suspend(struct device *dev)
+{
+	struct ti_csi2rx_dev *csi = dev_get_drvdata(dev);
+	int i;
+
+	if (csi->enable_count != 0)
+		return -EBUSY;
+
+	for (i = 0; i < csi->num_ctx; i++)
+		ti_csi2rx_cleanup_dma(&csi->ctx[i]);
+
+	return 0;
+}
+
+static int ti_csi2rx_runtime_resume(struct device *dev)
+{
+	struct ti_csi2rx_dev *csi = dev_get_drvdata(dev);
+	int ret, i;
+
+	for (i = 0; i < csi->num_ctx; i++) {
+		ret = ti_csi2rx_init_dma(&csi->ctx[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops ti_csi2rx_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(ti_csi2rx_suspend, ti_csi2rx_resume)
+	SET_RUNTIME_PM_OPS(ti_csi2rx_runtime_suspend, ti_csi2rx_runtime_resume,
+			   NULL)
+};
+#endif /* CONFIG_PM */
+
+static int ti_csi2rx_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct ti_csi2rx_dev *csi;
+	struct resource *res;
+	int ret, i, count;
+
+	csi = devm_kzalloc(&pdev->dev, sizeof(*csi), GFP_KERNEL);
+	if (!csi)
+		return -ENOMEM;
+
+	csi->dev = &pdev->dev;
+	platform_set_drvdata(pdev, csi);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	csi->shim = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(csi->shim)) {
+		ret = PTR_ERR(csi->shim);
+		return ret;
+	}
+
+	/* Only use as many contexts as the number of DMA channels allocated. */
+	count = of_property_count_strings(np, "dma-names");
+	if (count < 0) {
+		dev_err(csi->dev, "Failed to get DMA channel count: %d\n",
+			count);
+		return count;
+	}
+
+	csi->num_ctx = count;
+	if (csi->num_ctx > TI_CSI2RX_MAX_CTX) {
+		dev_warn(csi->dev,
+			 "%u DMA channels passed. Maximum is %u. Ignoring the rest.\n",
+			 csi->num_ctx, TI_CSI2RX_MAX_CTX);
+		csi->num_ctx = TI_CSI2RX_MAX_CTX;
+	}
+
+	csi->drain.len = DRAIN_BUFFER_SIZE;
+	csi->drain.vaddr = dma_alloc_coherent(csi->dev, csi->drain.len,
+					      &csi->drain.paddr,
+					      GFP_KERNEL);
+	if (!csi->drain.vaddr)
+		return -ENOMEM;
+
+	mutex_init(&csi->mutex);
+
+	ret = ti_csi2rx_v4l2_init(csi);
+	if (ret)
+		goto cleanup_drain;
+
+	for (i = 0; i < csi->num_ctx; i++) {
+		csi->ctx[i].idx = i;
+		csi->ctx[i].csi = csi;
+		ret = ti_csi2rx_init_ctx(&csi->ctx[i]);
+		if (ret)
+			goto cleanup_ctx;
+	}
+
+	ret = ti_csi2rx_init_subdev(csi);
+	if (ret)
+		goto cleanup_ctx;
+
+	ret = of_platform_populate(csi->dev->of_node, NULL, NULL, csi->dev);
+	if (ret) {
+		dev_err(csi->dev, "Failed to create children: %d\n", ret);
+		goto cleanup_subdev;
+	}
+
+	pm_runtime_set_active(csi->dev);
+	pm_runtime_enable(csi->dev);
+	pm_runtime_idle(csi->dev);
+
+	return 0;
+
+cleanup_subdev:
+	ti_csi2rx_cleanup_subdev(csi);
+cleanup_ctx:
+
+	i--;
+	for (; i >= 0; i--)
+		ti_csi2rx_cleanup_ctx(&csi->ctx[i]);
+
+	ti_csi2rx_cleanup_v4l2(csi);
+cleanup_drain:
+	mutex_destroy(&csi->mutex);
+	dma_free_coherent(csi->dev, csi->drain.len, csi->drain.vaddr,
+			  csi->drain.paddr);
+	return ret;
+}
+
+static int ti_csi2rx_remove(struct platform_device *pdev)
+{
+	struct ti_csi2rx_dev *csi = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < csi->num_ctx; i++) {
+		if (vb2_is_busy(&csi->ctx[i].vidq))
+			return -EBUSY;
+	}
+
+	for (i = 0; i < csi->num_ctx; i++)
+		ti_csi2rx_cleanup_ctx(&csi->ctx[i]);
+
+	ti_csi2rx_cleanup_subdev(csi);
+	ti_csi2rx_cleanup_v4l2(csi);
+
+	mutex_destroy(&csi->mutex);
+	dma_free_coherent(csi->dev, csi->drain.len, csi->drain.vaddr,
+			  csi->drain.paddr);
+
+	pm_runtime_disable(&pdev->dev);
+	pm_runtime_set_suspended(&pdev->dev);
+
+	return 0;
+}
+
+static const struct of_device_id ti_csi2rx_of_match[] = {
+	{ .compatible = "ti,j721e-csi2rx", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, ti_csi2rx_of_match);
+
+static struct platform_driver ti_csi2rx_pdrv = {
+	.probe = ti_csi2rx_probe,
+	.remove = ti_csi2rx_remove,
+	.driver = {
+		.name		= TI_CSI2RX_MODULE_NAME,
+		.of_match_table	= ti_csi2rx_of_match,
+#ifdef CONFIG_PM
+		.pm		= &ti_csi2rx_pm_ops,
+#endif
+	},
+};
+
+module_platform_driver(ti_csi2rx_pdrv);
+
+MODULE_DESCRIPTION("TI J721E CSI2 RX Driver");
+MODULE_AUTHOR("Pratyush Yadav <p.yadav@ti.com>");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/media/platform/ti/j721e-csi2rx/Makefile b/drivers/media/platform/ti/j721e-csi2rx/Makefile
--- a/drivers/media/platform/ti/j721e-csi2rx/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/media/platform/ti/j721e-csi2rx/Makefile	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_VIDEO_TI_J721E_CSI2RX) += j721e-csi2rx.o
diff -Naur --no-dereference a/drivers/media/platform/ti/Kconfig b/drivers/media/platform/ti/Kconfig
--- a/drivers/media/platform/ti/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/ti/Kconfig	2024-01-28 14:01:31.248353800 -0500
@@ -63,6 +63,18 @@
 	help
 	  Enable debug messages on VPE driver.
 
+config VIDEO_TI_J721E_CSI2RX
+	tristate "TI J721E CSI2RX wrapper layer driver"
+	depends on VIDEO_DEV && VIDEO_V4L2_SUBDEV_API
+	depends on MEDIA_SUPPORT && MEDIA_CONTROLLER
+	depends on PHY_CADENCE_DPHY_RX && VIDEO_CADENCE_CSI2RX
+	depends on ARCH_K3 || COMPILE_TEST
+	select VIDEOBUF2_DMA_CONTIG
+	select V4L2_FWNODE
+	help
+	  Support for TI CSI2RX wrapper layer. This just enables the wrapper driver.
+	  The Cadence CSI2RX bridge driver needs to be enabled separately.
+
 source "drivers/media/platform/ti/am437x/Kconfig"
 source "drivers/media/platform/ti/davinci/Kconfig"
 source "drivers/media/platform/ti/omap/Kconfig"
diff -Naur --no-dereference a/drivers/media/platform/ti/Makefile b/drivers/media/platform/ti/Makefile
--- a/drivers/media/platform/ti/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/platform/ti/Makefile	2024-01-28 14:01:31.248353800 -0500
@@ -3,5 +3,6 @@
 obj-y += cal/
 obj-y += vpe/
 obj-y += davinci/
+obj-y += j721e-csi2rx/
 obj-y += omap/
 obj-y += omap3isp/
diff -Naur --no-dereference a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
--- a/drivers/media/v4l2-core/v4l2-ioctl.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c	2024-01-28 14:01:31.248353800 -0500
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/version.h>
 
+#include <linux/v4l2-subdev.h>
 #include <linux/videodev2.h>
 
 #include <media/media-device.h> /* for media_set_bus_info() */
@@ -1414,6 +1415,14 @@
 	case V4L2_PIX_FMT_SGBRG16:	descr = "16-bit Bayer GBGB/RGRG"; break;
 	case V4L2_PIX_FMT_SGRBG16:	descr = "16-bit Bayer GRGR/BGBG"; break;
 	case V4L2_PIX_FMT_SRGGB16:	descr = "16-bit Bayer RGRG/GBGB"; break;
+	case V4L2_PIX_FMT_SRGGI10:      descr = "10-bit Bayer RGBG/GIrGIr"; break;
+	case V4L2_PIX_FMT_SGRIG10:      descr = "10-bit Bayer GRGB/IrGIrG"; break;
+	case V4L2_PIX_FMT_SBGGI10:      descr = "10-bit Bayer BGRG/GIrGIr"; break;
+	case V4L2_PIX_FMT_SGBIG10:      descr = "10-bit Bayer GBGR/IrGIrG"; break;
+	case V4L2_PIX_FMT_SGIRG10:      descr = "10-bit Bayer GIrGIr/RGBG"; break;
+	case V4L2_PIX_FMT_SIGGR10:      descr = "10-bit Bayer IrGIrG/GRGB"; break;
+	case V4L2_PIX_FMT_SGIBG10:      descr = "10-bit Bayer GIrGIr/BGRG"; break;
+	case V4L2_PIX_FMT_SIGGB10:      descr = "10-bit Bayer IrGIrG/GBGR"; break;
 	case V4L2_PIX_FMT_SN9C20X_I420:	descr = "GSPCA SN9C20X I420"; break;
 	case V4L2_PIX_FMT_SPCA501:	descr = "GSPCA SPCA501"; break;
 	case V4L2_PIX_FMT_SPCA505:	descr = "GSPCA SPCA505"; break;
@@ -1446,6 +1455,8 @@
 	case V4L2_META_FMT_RK_ISP1_STAT_3A:	descr = "Rockchip ISP1 3A Statistics"; break;
 	case V4L2_PIX_FMT_NV12M_8L128:	descr = "NV12M (8x128 Linear)"; break;
 	case V4L2_PIX_FMT_NV12M_10BE_8L128:	descr = "10-bit NV12M (8x128 Linear, BE)"; break;
+	case V4L2_PIX_FMT_TI1210:       descr = "10-bit YUV 4:2:0 (NV12)"; break;
+	case V4L2_PIX_FMT_TI1610:       descr = "10-bit YUV 4:2:2 (NV16)"; break;
 
 	default:
 		/* Compressed formats */
@@ -3151,6 +3162,21 @@
 		ret = 1;
 		break;
 	}
+
+	case VIDIOC_SUBDEV_G_ROUTING:
+	case VIDIOC_SUBDEV_S_ROUTING: {
+		struct v4l2_subdev_routing *routing = parg;
+
+		if (routing->num_routes > 256)
+			return -E2BIG;
+
+		*user_ptr = u64_to_user_ptr(routing->routes);
+		*kernel_ptr = (void **)&routing->routes;
+		*array_size = sizeof(struct v4l2_subdev_route)
+			    * routing->num_routes;
+		ret = 1;
+		break;
+	}
 	}
 
 	return ret;
@@ -3397,8 +3423,15 @@
 	/*
 	 * Some ioctls can return an error, but still have valid
 	 * results that must be returned.
+	 *
+	 * FIXME: subdev IOCTLS are partially handled here and partially in
+	 * v4l2-subdev.c and the 'always_copy' flag can only be set for IOCTLS
+	 * defined here as part of the 'v4l2_ioctls' array. As
+	 * VIDIOC_SUBDEV_G_ROUTING needs to return results to applications even
+	 * in case of failure, but it is not defined here as part of the
+	 * 'v4l2_ioctls' array, insert an ad-hoc check to address that.
 	 */
-	if (err < 0 && !always_copy)
+	if (err < 0 && !always_copy && cmd != VIDIOC_SUBDEV_G_ROUTING)
 		goto out;
 
 	if (has_array_args) {
diff -Naur --no-dereference a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
--- a/drivers/media/v4l2-core/v4l2-mc.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/v4l2-core/v4l2-mc.c	2024-01-28 14:01:31.248353800 -0500
@@ -313,14 +313,10 @@
 				    struct media_pad *sink, u32 flags)
 {
 	struct fwnode_handle *endpoint;
-	struct v4l2_subdev *sink_sd;
 
-	if (!(sink->flags & MEDIA_PAD_FL_SINK) ||
-	    !is_media_entity_v4l2_subdev(sink->entity))
+	if (!(sink->flags & MEDIA_PAD_FL_SINK))
 		return -EINVAL;
 
-	sink_sd = media_entity_to_v4l2_subdev(sink->entity);
-
 	fwnode_graph_for_each_endpoint(dev_fwnode(src_sd->dev), endpoint) {
 		struct fwnode_handle *remote_ep;
 		int src_idx, sink_idx, ret;
@@ -340,7 +336,7 @@
 		 * ask the sink to verify it owns the remote endpoint,
 		 * and translate to a sink pad.
 		 */
-		sink_idx = media_entity_get_fwnode_pad(&sink_sd->entity,
+		sink_idx = media_entity_get_fwnode_pad(sink->entity,
 						       remote_ep,
 						       MEDIA_PAD_FL_SINK);
 		fwnode_handle_put(remote_ep);
@@ -362,17 +358,17 @@
 		if (media_entity_find_link(src, sink))
 			continue;
 
-		dev_dbg(sink_sd->dev, "creating link %s:%d -> %s:%d\n",
+		dev_dbg(src_sd->dev, "creating link %s:%d -> %s:%d\n",
 			src_sd->entity.name, src_idx,
-			sink_sd->entity.name, sink_idx);
+			sink->entity->name, sink_idx);
 
 		ret = media_create_pad_link(&src_sd->entity, src_idx,
-					    &sink_sd->entity, sink_idx, flags);
+					    sink->entity, sink_idx, flags);
 		if (ret) {
-			dev_err(sink_sd->dev,
+			dev_err(src_sd->dev,
 				"link %s:%d -> %s:%d failed with %d\n",
 				src_sd->entity.name, src_idx,
-				sink_sd->entity.name, sink_idx, ret);
+				sink->entity->name, sink_idx, ret);
 
 			fwnode_handle_put(endpoint);
 			return ret;
diff -Naur --no-dereference a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
--- a/drivers/media/v4l2-core/v4l2-subdev.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/media/v4l2-core/v4l2-subdev.c	2024-01-28 14:01:31.248353800 -0500
@@ -8,20 +8,40 @@
  *	    Sakari Ailus <sakari.ailus@iki.fi>
  */
 
+#include <linux/export.h>
 #include <linux/ioctl.h>
 #include <linux/mm.h>
 #include <linux/module.h>
+#include <linux/overflow.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/videodev2.h>
-#include <linux/export.h>
 #include <linux/version.h>
+#include <linux/videodev2.h>
 
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ioctl.h>
+
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+/*
+ * The Streams API is an experimental feature. To use the Streams API, set
+ * 'v4l2_subdev_enable_streams_api' to 1 below.
+ */
+
+static bool v4l2_subdev_enable_streams_api = 1;
+#endif
+
+/*
+ * Maximum stream ID is 63 for now, as we use u64 bitmask to represent a set
+ * of streams.
+ *
+ * Note that V4L2_FRAME_DESC_ENTRY_MAX is related: V4L2_FRAME_DESC_ENTRY_MAX
+ * restricts the total number of streams in a pad, although the stream ID is
+ * not restricted.
+ */
+#define V4L2_SUBDEV_MAX_STREAM_ID 63
 
 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd)
@@ -148,8 +168,22 @@
 	return 0;
 }
 
-static int check_state_pads(u32 which, struct v4l2_subdev_state *state)
+static int check_state(struct v4l2_subdev *sd, struct v4l2_subdev_state *state,
+		       u32 which, u32 pad, u32 stream)
 {
+	if (sd->flags & V4L2_SUBDEV_FL_STREAMS) {
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+		if (!v4l2_subdev_state_get_stream_format(state, pad, stream))
+			return -EINVAL;
+		return 0;
+#else
+		return -EINVAL;
+#endif
+	}
+
+	if (stream != 0)
+		return -EINVAL;
+
 	if (which == V4L2_SUBDEV_FORMAT_TRY && (!state || !state->pads))
 		return -EINVAL;
 
@@ -164,7 +198,7 @@
 		return -EINVAL;
 
 	return check_which(format->which) ? : check_pad(sd, format->pad) ? :
-	       check_state_pads(format->which, state);
+	       check_state(sd, state, format->which, format->pad, format->stream);
 }
 
 static int call_get_fmt(struct v4l2_subdev *sd,
@@ -191,7 +225,7 @@
 		return -EINVAL;
 
 	return check_which(code->which) ? : check_pad(sd, code->pad) ? :
-	       check_state_pads(code->which, state) ? :
+	       check_state(sd, state, code->which, code->pad, code->stream) ? :
 	       sd->ops->pad->enum_mbus_code(sd, state, code);
 }
 
@@ -203,7 +237,7 @@
 		return -EINVAL;
 
 	return check_which(fse->which) ? : check_pad(sd, fse->pad) ? :
-	       check_state_pads(fse->which, state) ? :
+	       check_state(sd, state, fse->which, fse->pad, fse->stream) ? :
 	       sd->ops->pad->enum_frame_size(sd, state, fse);
 }
 
@@ -238,7 +272,7 @@
 		return -EINVAL;
 
 	return check_which(fie->which) ? : check_pad(sd, fie->pad) ? :
-	       check_state_pads(fie->which, state) ? :
+	       check_state(sd, state, fie->which, fie->pad, fie->stream) ? :
 	       sd->ops->pad->enum_frame_interval(sd, state, fie);
 }
 
@@ -250,7 +284,7 @@
 		return -EINVAL;
 
 	return check_which(sel->which) ? : check_pad(sd, sel->pad) ? :
-	       check_state_pads(sel->which, state);
+	       check_state(sd, state, sel->which, sel->pad, sel->stream);
 }
 
 static int call_get_selection(struct v4l2_subdev *sd,
@@ -417,6 +451,10 @@
 	case VIDIOC_SUBDEV_S_SELECTION:
 		which = ((struct v4l2_subdev_selection *)arg)->which;
 		break;
+	case VIDIOC_SUBDEV_G_ROUTING:
+	case VIDIOC_SUBDEV_S_ROUTING:
+		which = ((struct v4l2_subdev_routing *)arg)->which;
+		break;
 	}
 
 	return which == V4L2_SUBDEV_FORMAT_TRY ?
@@ -431,6 +469,7 @@
 	struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
 	struct v4l2_fh *vfh = file->private_data;
 	bool ro_subdev = test_bit(V4L2_FL_SUBDEV_RO_DEVNODE, &vdev->flags);
+	bool streams_subdev = sd->flags & V4L2_SUBDEV_FL_STREAMS;
 	int rval;
 
 	switch (cmd) {
@@ -439,7 +478,9 @@
 
 		memset(cap->reserved, 0, sizeof(cap->reserved));
 		cap->version = LINUX_VERSION_CODE;
-		cap->capabilities = ro_subdev ? V4L2_SUBDEV_CAP_RO_SUBDEV : 0;
+		cap->capabilities =
+			(ro_subdev ? V4L2_SUBDEV_CAP_RO_SUBDEV : 0) |
+			(streams_subdev ? V4L2_SUBDEV_CAP_STREAMS : 0);
 
 		return 0;
 	}
@@ -730,6 +771,81 @@
 	case VIDIOC_SUBDEV_QUERYSTD:
 		return v4l2_subdev_call(sd, video, querystd, arg);
 
+	case VIDIOC_SUBDEV_G_ROUTING: {
+		struct v4l2_subdev_routing *routing = arg;
+		struct v4l2_subdev_krouting *krouting;
+
+		if (!v4l2_subdev_enable_streams_api)
+			return -ENOIOCTLCMD;
+
+		if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS))
+			return -ENOIOCTLCMD;
+
+		memset(routing->reserved, 0, sizeof(routing->reserved));
+
+		krouting = &state->routing;
+
+		if (routing->num_routes < krouting->num_routes) {
+			routing->num_routes = krouting->num_routes;
+			return -ENOSPC;
+		}
+
+		memcpy((struct v4l2_subdev_route *)(uintptr_t)routing->routes,
+		       krouting->routes,
+		       krouting->num_routes * sizeof(*krouting->routes));
+		routing->num_routes = krouting->num_routes;
+
+		return 0;
+	}
+
+	case VIDIOC_SUBDEV_S_ROUTING: {
+		struct v4l2_subdev_routing *routing = arg;
+		struct v4l2_subdev_route *routes =
+			(struct v4l2_subdev_route *)(uintptr_t)routing->routes;
+		struct v4l2_subdev_krouting krouting = {};
+		unsigned int i;
+
+		if (!v4l2_subdev_enable_streams_api)
+			return -ENOIOCTLCMD;
+
+		if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS))
+			return -ENOIOCTLCMD;
+
+		if (routing->which != V4L2_SUBDEV_FORMAT_TRY && ro_subdev)
+			return -EPERM;
+
+		memset(routing->reserved, 0, sizeof(routing->reserved));
+
+		for (i = 0; i < routing->num_routes; ++i) {
+			const struct v4l2_subdev_route *route = &routes[i];
+			const struct media_pad *pads = sd->entity.pads;
+
+			if (route->sink_stream > V4L2_SUBDEV_MAX_STREAM_ID ||
+			    route->source_stream > V4L2_SUBDEV_MAX_STREAM_ID)
+				return -EINVAL;
+
+			if (route->sink_pad >= sd->entity.num_pads)
+				return -EINVAL;
+
+			if (!(pads[route->sink_pad].flags &
+			      MEDIA_PAD_FL_SINK))
+				return -EINVAL;
+
+			if (route->source_pad >= sd->entity.num_pads)
+				return -EINVAL;
+
+			if (!(pads[route->source_pad].flags &
+			      MEDIA_PAD_FL_SOURCE))
+				return -EINVAL;
+		}
+
+		krouting.num_routes = routing->num_routes;
+		krouting.routes = routes;
+
+		return v4l2_subdev_call(sd, pad, set_routing, state,
+					routing->which, &krouting);
+	}
+
 	default:
 		return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
 	}
@@ -910,53 +1026,261 @@
 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate_default);
 
 static int
-v4l2_subdev_link_validate_get_format(struct media_pad *pad,
-				     struct v4l2_subdev_format *fmt)
+v4l2_subdev_link_validate_get_format(struct media_pad *pad, u32 stream,
+				     struct v4l2_subdev_format *fmt,
+				     bool states_locked)
 {
-	if (is_media_entity_v4l2_subdev(pad->entity)) {
-		struct v4l2_subdev *sd =
-			media_entity_to_v4l2_subdev(pad->entity);
+	struct v4l2_subdev_state *state;
+	struct v4l2_subdev *sd;
+	int ret;
 
-		fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
-		fmt->pad = pad->index;
-		return v4l2_subdev_call_state_active(sd, pad, get_fmt, fmt);
+	if (!is_media_entity_v4l2_subdev(pad->entity)) {
+		WARN(pad->entity->function != MEDIA_ENT_F_IO_V4L,
+		     "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
+		     pad->entity->function, pad->entity->name);
+
+		return -EINVAL;
 	}
 
-	WARN(pad->entity->function != MEDIA_ENT_F_IO_V4L,
-	     "Driver bug! Wrong media entity type 0x%08x, entity %s\n",
-	     pad->entity->function, pad->entity->name);
+	sd = media_entity_to_v4l2_subdev(pad->entity);
 
-	return -EINVAL;
+	fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	fmt->pad = pad->index;
+	fmt->stream = stream;
+
+	if (states_locked)
+		state = v4l2_subdev_get_locked_active_state(sd);
+	else
+		state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	ret = v4l2_subdev_call(sd, pad, get_fmt, state, fmt);
+
+	if (!states_locked && state)
+		v4l2_subdev_unlock_state(state);
+
+	return ret;
+}
+
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+
+static void __v4l2_link_validate_get_streams(struct media_pad *pad,
+					     u64 *streams_mask,
+					     bool states_locked)
+{
+	struct v4l2_subdev_route *route;
+	struct v4l2_subdev_state *state;
+	struct v4l2_subdev *subdev;
+
+	subdev = media_entity_to_v4l2_subdev(pad->entity);
+
+	*streams_mask = 0;
+
+	if (states_locked)
+		state = v4l2_subdev_get_locked_active_state(subdev);
+	else
+		state = v4l2_subdev_lock_and_get_active_state(subdev);
+
+	if (WARN_ON(!state))
+		return;
+
+	for_each_active_route(&state->routing, route) {
+		u32 route_pad;
+		u32 route_stream;
+
+		if (pad->flags & MEDIA_PAD_FL_SOURCE) {
+			route_pad = route->source_pad;
+			route_stream = route->source_stream;
+		} else {
+			route_pad = route->sink_pad;
+			route_stream = route->sink_stream;
+		}
+
+		if (route_pad != pad->index)
+			continue;
+
+		*streams_mask |= BIT_ULL(route_stream);
+	}
+
+	if (!states_locked)
+		v4l2_subdev_unlock_state(state);
+}
+
+#endif /* CONFIG_VIDEO_V4L2_SUBDEV_API */
+
+static void v4l2_link_validate_get_streams(struct media_pad *pad,
+					   u64 *streams_mask,
+					   bool states_locked)
+{
+	struct v4l2_subdev *subdev = media_entity_to_v4l2_subdev(pad->entity);
+
+	if (!(subdev->flags & V4L2_SUBDEV_FL_STREAMS)) {
+		/* Non-streams subdevs have an implicit stream 0 */
+		*streams_mask = BIT_ULL(0);
+		return;
+	}
+
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+	__v4l2_link_validate_get_streams(pad, streams_mask, states_locked);
+#else
+	/* This shouldn't happen */
+	*streams_mask = 0;
+#endif
+}
+
+static int v4l2_subdev_link_validate_locked(struct media_link *link, bool states_locked)
+{
+	struct v4l2_subdev *sink_subdev =
+		media_entity_to_v4l2_subdev(link->sink->entity);
+	struct device *dev = sink_subdev->entity.graph_obj.mdev->dev;
+	u64 source_streams_mask;
+	u64 sink_streams_mask;
+	u64 dangling_sink_streams;
+	u32 stream;
+	int ret;
+
+	dev_dbg(dev, "validating link \"%s\":%u -> \"%s\":%u\n",
+		link->source->entity->name, link->source->index,
+		link->sink->entity->name, link->sink->index);
+
+	v4l2_link_validate_get_streams(link->source, &source_streams_mask, states_locked);
+	v4l2_link_validate_get_streams(link->sink, &sink_streams_mask, states_locked);
+
+	/*
+	 * It is ok to have more source streams than sink streams as extra
+	 * source streams can just be ignored by the receiver, but having extra
+	 * sink streams is an error as streams must have a source.
+	 */
+	dangling_sink_streams = (source_streams_mask ^ sink_streams_mask) &
+				sink_streams_mask;
+	if (dangling_sink_streams) {
+		dev_err(dev, "Dangling sink streams: mask %#llx\n",
+			dangling_sink_streams);
+		return -EINVAL;
+	}
+
+	/* Validate source and sink stream formats */
+
+	for (stream = 0; stream < sizeof(sink_streams_mask) * 8; ++stream) {
+		struct v4l2_subdev_format sink_fmt, source_fmt;
+
+		if (!(sink_streams_mask & BIT_ULL(stream)))
+			continue;
+
+		dev_dbg(dev, "validating stream \"%s\":%u:%u -> \"%s\":%u:%u\n",
+			link->source->entity->name, link->source->index, stream,
+			link->sink->entity->name, link->sink->index, stream);
+
+		ret = v4l2_subdev_link_validate_get_format(link->source, stream,
+							   &source_fmt, states_locked);
+		if (ret < 0) {
+			dev_dbg(dev,
+				"Failed to get format for \"%s\":%u:%u (but that's ok)\n",
+				link->source->entity->name, link->source->index,
+				stream);
+			continue;
+		}
+
+		ret = v4l2_subdev_link_validate_get_format(link->sink, stream,
+							   &sink_fmt, states_locked);
+		if (ret < 0) {
+			dev_dbg(dev,
+				"Failed to get format for \"%s\":%u:%u (but that's ok)\n",
+				link->sink->entity->name, link->sink->index,
+				stream);
+			continue;
+		}
+
+		/* TODO: add stream number to link_validate() */
+		ret = v4l2_subdev_call(sink_subdev, pad, link_validate, link,
+				       &source_fmt, &sink_fmt);
+		if (!ret)
+			continue;
+
+		if (ret != -ENOIOCTLCMD)
+			return ret;
+
+		ret = v4l2_subdev_link_validate_default(sink_subdev, link,
+							&source_fmt, &sink_fmt);
+
+		if (ret)
+			return ret;
+	}
+
+	return 0;
 }
 
 int v4l2_subdev_link_validate(struct media_link *link)
 {
-	struct v4l2_subdev *sink;
-	struct v4l2_subdev_format sink_fmt, source_fmt;
-	int rval;
+	struct v4l2_subdev *source_sd, *sink_sd;
+	struct v4l2_subdev_state *source_state, *sink_state;
+	bool states_locked;
+	int ret;
 
-	rval = v4l2_subdev_link_validate_get_format(
-		link->source, &source_fmt);
-	if (rval < 0)
+	if (!is_media_entity_v4l2_subdev(link->sink->entity) ||
+	    !is_media_entity_v4l2_subdev(link->source->entity)) {
+		pr_warn_once("%s of link '%s':%u->'%s':%u is not a V4L2 sub-device, driver bug!\n",
+			     !is_media_entity_v4l2_subdev(link->sink->entity) ?
+			     "sink" : "source",
+			     link->source->entity->name, link->source->index,
+			     link->sink->entity->name, link->sink->index);
 		return 0;
+	}
 
-	rval = v4l2_subdev_link_validate_get_format(
-		link->sink, &sink_fmt);
-	if (rval < 0)
-		return 0;
+	sink_sd = media_entity_to_v4l2_subdev(link->sink->entity);
+	source_sd = media_entity_to_v4l2_subdev(link->source->entity);
 
-	sink = media_entity_to_v4l2_subdev(link->sink->entity);
+	sink_state = v4l2_subdev_get_unlocked_active_state(sink_sd);
+	source_state = v4l2_subdev_get_unlocked_active_state(source_sd);
 
-	rval = v4l2_subdev_call(sink, pad, link_validate, link,
-				&source_fmt, &sink_fmt);
-	if (rval != -ENOIOCTLCMD)
-		return rval;
+	states_locked = sink_state && source_state;
+
+	if (states_locked) {
+		v4l2_subdev_lock_state(sink_state);
+		v4l2_subdev_lock_state(source_state);
+	}
+
+	ret = v4l2_subdev_link_validate_locked(link, states_locked);
+
+	if (states_locked) {
+		v4l2_subdev_unlock_state(sink_state);
+		v4l2_subdev_unlock_state(source_state);
+	}
 
-	return v4l2_subdev_link_validate_default(
-		sink, link, &source_fmt, &sink_fmt);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(v4l2_subdev_link_validate);
 
+bool v4l2_subdev_has_pad_interdep(struct media_entity *entity,
+				  unsigned int pad0, unsigned int pad1)
+{
+	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+	struct v4l2_subdev_krouting *routing;
+	struct v4l2_subdev_state *state;
+	unsigned int i;
+
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	routing = &state->routing;
+
+	for (i = 0; i < routing->num_routes; ++i) {
+		struct v4l2_subdev_route *route = &routing->routes[i];
+
+		if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))
+			continue;
+
+		if ((route->sink_pad == pad0 && route->source_pad == pad1) ||
+		    (route->source_pad == pad0 && route->sink_pad == pad1)) {
+			v4l2_subdev_unlock_state(state);
+			return true;
+		}
+	}
+
+	v4l2_subdev_unlock_state(state);
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_has_pad_interdep);
+
 struct v4l2_subdev_state *
 __v4l2_subdev_state_alloc(struct v4l2_subdev *sd, const char *lock_name,
 			  struct lock_class_key *lock_key)
@@ -974,7 +1298,8 @@
 	else
 		state->lock = &state->_lock;
 
-	if (sd->entity.num_pads) {
+	/* Drivers that support streams do not need the legacy pad config */
+	if (!(sd->flags & V4L2_SUBDEV_FL_STREAMS) && sd->entity.num_pads) {
 		state->pads = kvcalloc(sd->entity.num_pads,
 				       sizeof(*state->pads), GFP_KERNEL);
 		if (!state->pads) {
@@ -1013,6 +1338,8 @@
 
 	mutex_destroy(&state->_lock);
 
+	kfree(state->routing.routes);
+	kvfree(state->stream_configs.configs);
 	kvfree(state->pads);
 	kfree(state);
 }
@@ -1042,15 +1369,68 @@
 
 #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
 
+static int
+v4l2_subdev_init_stream_configs(struct v4l2_subdev_stream_configs *stream_configs,
+				const struct v4l2_subdev_krouting *routing)
+{
+	struct v4l2_subdev_stream_configs new_configs = { 0 };
+	struct v4l2_subdev_route *route;
+	u32 idx;
+
+	/* Count number of formats needed */
+	for_each_active_route(routing, route) {
+		/*
+		 * Each route needs a format on both ends of the route.
+		 */
+		new_configs.num_configs += 2;
+	}
+
+	if (new_configs.num_configs) {
+		new_configs.configs = kvcalloc(new_configs.num_configs,
+					       sizeof(*new_configs.configs),
+					       GFP_KERNEL);
+
+		if (!new_configs.configs)
+			return -ENOMEM;
+	}
+
+	/*
+	 * Fill in the 'pad' and stream' value for each item in the array from
+	 * the routing table
+	 */
+	idx = 0;
+
+	for_each_active_route(routing, route) {
+		new_configs.configs[idx].pad = route->sink_pad;
+		new_configs.configs[idx].stream = route->sink_stream;
+
+		idx++;
+
+		new_configs.configs[idx].pad = route->source_pad;
+		new_configs.configs[idx].stream = route->source_stream;
+
+		idx++;
+	}
+
+	kvfree(stream_configs->configs);
+	*stream_configs = new_configs;
+
+	return 0;
+}
+
 int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state,
 			struct v4l2_subdev_format *format)
 {
 	struct v4l2_mbus_framefmt *fmt;
 
-	if (format->pad >= sd->entity.num_pads)
-		return -EINVAL;
+	if (sd->flags & V4L2_SUBDEV_FL_STREAMS)
+		fmt = v4l2_subdev_state_get_stream_format(state, format->pad,
+							  format->stream);
+	else if (format->pad < sd->entity.num_pads && format->stream == 0)
+		fmt = v4l2_subdev_get_pad_format(sd, state, format->pad);
+	else
+		fmt = NULL;
 
-	fmt = v4l2_subdev_get_pad_format(sd, state, format->pad);
 	if (!fmt)
 		return -EINVAL;
 
@@ -1060,6 +1440,627 @@
 }
 EXPORT_SYMBOL_GPL(v4l2_subdev_get_fmt);
 
+int v4l2_subdev_set_routing(struct v4l2_subdev *sd,
+			    struct v4l2_subdev_state *state,
+			    const struct v4l2_subdev_krouting *routing)
+{
+	struct v4l2_subdev_krouting *dst = &state->routing;
+	const struct v4l2_subdev_krouting *src = routing;
+	struct v4l2_subdev_krouting new_routing = { 0 };
+	size_t bytes;
+	int r;
+
+	if (unlikely(check_mul_overflow((size_t)src->num_routes,
+					sizeof(*src->routes), &bytes)))
+		return -EOVERFLOW;
+
+	lockdep_assert_held(state->lock);
+
+	if (src->num_routes > 0) {
+		new_routing.routes = kmemdup(src->routes, bytes, GFP_KERNEL);
+		if (!new_routing.routes)
+			return -ENOMEM;
+	}
+
+	new_routing.num_routes = src->num_routes;
+
+	r = v4l2_subdev_init_stream_configs(&state->stream_configs,
+					    &new_routing);
+	if (r) {
+		kfree(new_routing.routes);
+		return r;
+	}
+
+	kfree(dst->routes);
+	*dst = new_routing;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_set_routing);
+
+struct v4l2_subdev_route *
+__v4l2_subdev_next_active_route(const struct v4l2_subdev_krouting *routing,
+				struct v4l2_subdev_route *route)
+{
+	if (route)
+		++route;
+	else
+		route = &routing->routes[0];
+
+	for (; route < routing->routes + routing->num_routes; ++route) {
+		if (!(route->flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))
+			continue;
+
+		return route;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(__v4l2_subdev_next_active_route);
+
+int v4l2_subdev_set_routing_with_fmt(struct v4l2_subdev *sd,
+				     struct v4l2_subdev_state *state,
+				     struct v4l2_subdev_krouting *routing,
+				     const struct v4l2_mbus_framefmt *fmt)
+{
+	struct v4l2_subdev_stream_configs *stream_configs;
+	unsigned int i;
+	int ret;
+
+	ret = v4l2_subdev_set_routing(sd, state, routing);
+	if (ret)
+		return ret;
+
+	stream_configs = &state->stream_configs;
+
+	for (i = 0; i < stream_configs->num_configs; ++i)
+		stream_configs->configs[i].fmt = *fmt;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_set_routing_with_fmt);
+
+struct v4l2_mbus_framefmt *
+v4l2_subdev_state_get_stream_format(struct v4l2_subdev_state *state,
+				    unsigned int pad, u32 stream)
+{
+	struct v4l2_subdev_stream_configs *stream_configs;
+	unsigned int i;
+
+	lockdep_assert_held(state->lock);
+
+	stream_configs = &state->stream_configs;
+
+	for (i = 0; i < stream_configs->num_configs; ++i) {
+		if (stream_configs->configs[i].pad == pad &&
+		    stream_configs->configs[i].stream == stream)
+			return &stream_configs->configs[i].fmt;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_state_get_stream_format);
+
+struct v4l2_rect *
+v4l2_subdev_state_get_stream_crop(struct v4l2_subdev_state *state,
+				  unsigned int pad, u32 stream)
+{
+	struct v4l2_subdev_stream_configs *stream_configs;
+	unsigned int i;
+
+	lockdep_assert_held(state->lock);
+
+	stream_configs = &state->stream_configs;
+
+	for (i = 0; i < stream_configs->num_configs; ++i) {
+		if (stream_configs->configs[i].pad == pad &&
+		    stream_configs->configs[i].stream == stream)
+			return &stream_configs->configs[i].crop;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_state_get_stream_crop);
+
+struct v4l2_rect *
+v4l2_subdev_state_get_stream_compose(struct v4l2_subdev_state *state,
+				     unsigned int pad, u32 stream)
+{
+	struct v4l2_subdev_stream_configs *stream_configs;
+	unsigned int i;
+
+	lockdep_assert_held(state->lock);
+
+	stream_configs = &state->stream_configs;
+
+	for (i = 0; i < stream_configs->num_configs; ++i) {
+		if (stream_configs->configs[i].pad == pad &&
+		    stream_configs->configs[i].stream == stream)
+			return &stream_configs->configs[i].compose;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_state_get_stream_compose);
+
+int v4l2_subdev_routing_find_opposite_end(const struct v4l2_subdev_krouting *routing,
+					  u32 pad, u32 stream, u32 *other_pad,
+					  u32 *other_stream)
+{
+	unsigned int i;
+
+	for (i = 0; i < routing->num_routes; ++i) {
+		struct v4l2_subdev_route *route = &routing->routes[i];
+
+		if (route->source_pad == pad &&
+		    route->source_stream == stream) {
+			if (other_pad)
+				*other_pad = route->sink_pad;
+			if (other_stream)
+				*other_stream = route->sink_stream;
+			return 0;
+		}
+
+		if (route->sink_pad == pad && route->sink_stream == stream) {
+			if (other_pad)
+				*other_pad = route->source_pad;
+			if (other_stream)
+				*other_stream = route->source_stream;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_routing_find_opposite_end);
+
+struct v4l2_mbus_framefmt *
+v4l2_subdev_state_get_opposite_stream_format(struct v4l2_subdev_state *state,
+					     u32 pad, u32 stream)
+{
+	u32 other_pad, other_stream;
+	int ret;
+
+	ret = v4l2_subdev_routing_find_opposite_end(&state->routing,
+						    pad, stream,
+						    &other_pad, &other_stream);
+	if (ret)
+		return NULL;
+
+	return v4l2_subdev_state_get_stream_format(state, other_pad,
+						   other_stream);
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_state_get_opposite_stream_format);
+
+u64 v4l2_subdev_state_xlate_streams(const struct v4l2_subdev_state *state,
+				    u32 pad0, u32 pad1, u64 *streams)
+{
+	const struct v4l2_subdev_krouting *routing = &state->routing;
+	struct v4l2_subdev_route *route;
+	u64 streams0 = 0;
+	u64 streams1 = 0;
+
+	for_each_active_route(routing, route) {
+		if (route->sink_pad == pad0 && route->source_pad == pad1 &&
+		    (*streams & BIT_ULL(route->sink_stream))) {
+			streams0 |= BIT_ULL(route->sink_stream);
+			streams1 |= BIT_ULL(route->source_stream);
+		}
+		if (route->source_pad == pad0 && route->sink_pad == pad1 &&
+		    (*streams & BIT_ULL(route->source_stream))) {
+			streams0 |= BIT_ULL(route->source_stream);
+			streams1 |= BIT_ULL(route->sink_stream);
+		}
+	}
+
+	*streams = streams0;
+	return streams1;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_state_xlate_streams);
+
+int v4l2_subdev_routing_validate(struct v4l2_subdev *sd,
+				 const struct v4l2_subdev_krouting *routing,
+				 enum v4l2_subdev_routing_restriction disallow)
+{
+	u32 *remote_pads = NULL;
+	unsigned int i, j;
+	int ret = -EINVAL;
+
+	if (disallow & (V4L2_SUBDEV_ROUTING_NO_STREAM_MIX |
+			V4L2_SUBDEV_ROUTING_NO_MULTIPLEXING)) {
+		remote_pads = kcalloc(sd->entity.num_pads, sizeof(*remote_pads),
+				      GFP_KERNEL);
+		if (!remote_pads)
+			return -ENOMEM;
+
+		for (i = 0; i < sd->entity.num_pads; ++i)
+			remote_pads[i] = U32_MAX;
+	}
+
+	for (i = 0; i < routing->num_routes; ++i) {
+		const struct v4l2_subdev_route *route = &routing->routes[i];
+
+		/* Validate the sink and source pad numbers. */
+		if (route->sink_pad >= sd->entity.num_pads ||
+		    !(sd->entity.pads[route->sink_pad].flags & MEDIA_PAD_FL_SINK)) {
+			dev_dbg(sd->dev, "route %u sink (%u) is not a sink pad\n",
+				i, route->sink_pad);
+			goto out;
+		}
+
+		if (route->source_pad >= sd->entity.num_pads ||
+		    !(sd->entity.pads[route->source_pad].flags & MEDIA_PAD_FL_SOURCE)) {
+			dev_dbg(sd->dev, "route %u source (%u) is not a source pad\n",
+				i, route->source_pad);
+			goto out;
+		}
+
+		/*
+		 * V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX: all streams from a
+		 * sink pad must be routed to a single source pad.
+		 */
+		if (disallow & V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX) {
+			if (remote_pads[route->sink_pad] != U32_MAX &&
+			    remote_pads[route->sink_pad] != route->source_pad) {
+				dev_dbg(sd->dev,
+					"route %u attempts to mix %s streams\n",
+					i, "sink");
+				goto out;
+			}
+		}
+
+		/*
+		 * V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX: all streams on a
+		 * source pad must originate from a single sink pad.
+		 */
+		if (disallow & V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX) {
+			if (remote_pads[route->source_pad] != U32_MAX &&
+			    remote_pads[route->source_pad] != route->sink_pad) {
+				dev_dbg(sd->dev,
+					"route %u attempts to mix %s streams\n",
+					i, "source");
+				goto out;
+			}
+		}
+
+		/*
+		 * V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXING: Pads on the sink
+		 * side can not do stream multiplexing, i.e. there can be only
+		 * a single stream in a sink pad.
+		 */
+		if (disallow & V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXING) {
+			if (remote_pads[route->sink_pad] != U32_MAX) {
+				dev_dbg(sd->dev,
+					"route %u attempts to multiplex on %s pad %u\n",
+					i, "sink", route->sink_pad);
+				goto out;
+			}
+		}
+
+		/*
+		 * V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING: Pads on the
+		 * source side can not do stream multiplexing, i.e. there can
+		 * be only a single stream in a source pad.
+		 */
+		if (disallow & V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING) {
+			if (remote_pads[route->source_pad] != U32_MAX) {
+				dev_dbg(sd->dev,
+					"route %u attempts to multiplex on %s pad %u\n",
+					i, "source", route->source_pad);
+				goto out;
+			}
+		}
+
+		if (remote_pads) {
+			remote_pads[route->sink_pad] = route->source_pad;
+			remote_pads[route->source_pad] = route->sink_pad;
+		}
+
+		for (j = i + 1; j < routing->num_routes; ++j) {
+			const struct v4l2_subdev_route *r = &routing->routes[j];
+
+			/*
+			 * V4L2_SUBDEV_ROUTING_NO_1_TO_N: No two routes can
+			 * originate from the same (sink) stream.
+			 */
+			if ((disallow & V4L2_SUBDEV_ROUTING_NO_1_TO_N) &&
+			    route->sink_pad == r->sink_pad &&
+			    route->sink_stream == r->sink_stream) {
+				dev_dbg(sd->dev,
+					"routes %u and %u originate from same sink (%u/%u)\n",
+					i, j, route->sink_pad,
+					route->sink_stream);
+				goto out;
+			}
+
+			/*
+			 * V4L2_SUBDEV_ROUTING_NO_N_TO_1: No two routes can end
+			 * at the same (source) stream.
+			 */
+			if ((disallow & V4L2_SUBDEV_ROUTING_NO_N_TO_1) &&
+			    route->source_pad == r->source_pad &&
+			    route->source_stream == r->source_stream) {
+				dev_dbg(sd->dev,
+					"routes %u and %u end at same source (%u/%u)\n",
+					i, j, route->source_pad,
+					route->source_stream);
+				goto out;
+			}
+		}
+	}
+
+	ret = 0;
+
+out:
+	kfree(remote_pads);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_routing_validate);
+
+static int v4l2_subdev_enable_streams_fallback(struct v4l2_subdev *sd, u32 pad,
+					       u64 streams_mask)
+{
+	struct device *dev = sd->entity.graph_obj.mdev->dev;
+	unsigned int i;
+	int ret;
+
+	/*
+	 * The subdev doesn't implement pad-based stream enable, fall back
+	 * on the .s_stream() operation. This can only be done for subdevs that
+	 * have a single source pad, as sd->enabled_streams is global to the
+	 * subdev.
+	 */
+	if (!(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE))
+		return -EOPNOTSUPP;
+
+	for (i = 0; i < sd->entity.num_pads; ++i) {
+		if (i != pad && sd->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE)
+			return -EOPNOTSUPP;
+	}
+
+	if (sd->enabled_streams & streams_mask) {
+		dev_dbg(dev, "set of streams %#llx already enabled on %s:%u\n",
+			streams_mask, sd->entity.name, pad);
+		return -EALREADY;
+	}
+
+	/* Start streaming when the first streams are enabled. */
+	if (!sd->enabled_streams) {
+		ret = v4l2_subdev_call(sd, video, s_stream, 1);
+		if (ret)
+			return ret;
+	}
+
+	sd->enabled_streams |= streams_mask;
+
+	return 0;
+}
+
+int v4l2_subdev_enable_streams(struct v4l2_subdev *sd, u32 pad,
+			       u64 streams_mask)
+{
+	struct device *dev = sd->entity.graph_obj.mdev->dev;
+	struct v4l2_subdev_state *state;
+	u64 found_streams = 0;
+	unsigned int i;
+	int ret;
+
+	/* A few basic sanity checks first. */
+	if (pad >= sd->entity.num_pads)
+		return -EINVAL;
+
+	if (!streams_mask)
+		return 0;
+
+	/* Fallback on .s_stream() if .enable_streams() isn't available. */
+	if (!sd->ops->pad || !sd->ops->pad->enable_streams)
+		return v4l2_subdev_enable_streams_fallback(sd, pad,
+							   streams_mask);
+
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	/*
+	 * Verify that the requested streams exist and that they are not
+	 * already enabled.
+	 */
+	for (i = 0; i < state->stream_configs.num_configs; ++i) {
+		struct v4l2_subdev_stream_config *cfg =
+			&state->stream_configs.configs[i];
+
+		if (cfg->pad != pad || !(streams_mask & BIT_ULL(cfg->stream)))
+			continue;
+
+		found_streams |= BIT_ULL(cfg->stream);
+
+		if (cfg->enabled) {
+			dev_dbg(dev, "stream %u already enabled on %s:%u\n",
+				cfg->stream, sd->entity.name, pad);
+			ret = -EALREADY;
+			goto done;
+		}
+	}
+
+	if (found_streams != streams_mask) {
+		dev_dbg(dev, "streams 0x%llx not found on %s:%u\n",
+			streams_mask & ~found_streams, sd->entity.name, pad);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Call the .enable_streams() operation. */
+	ret = v4l2_subdev_call(sd, pad, enable_streams, state, pad,
+			       streams_mask);
+	if (ret)
+		goto done;
+
+	/* Mark the streams as enabled. */
+	for (i = 0; i < state->stream_configs.num_configs; ++i) {
+		struct v4l2_subdev_stream_config *cfg =
+			&state->stream_configs.configs[i];
+
+		if (cfg->pad == pad && (streams_mask & BIT_ULL(cfg->stream)))
+			cfg->enabled = true;
+	}
+
+done:
+	v4l2_subdev_unlock_state(state);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_enable_streams);
+
+static int v4l2_subdev_disable_streams_fallback(struct v4l2_subdev *sd, u32 pad,
+						u64 streams_mask)
+{
+	struct device *dev = sd->entity.graph_obj.mdev->dev;
+	unsigned int i;
+	int ret;
+
+	/*
+	 * If the subdev doesn't implement pad-based stream enable, fall  back
+	 * on the .s_stream() operation. This can only be done for subdevs that
+	 * have a single source pad, as sd->enabled_streams is global to the
+	 * subdev.
+	 */
+	if (!(sd->entity.pads[pad].flags & MEDIA_PAD_FL_SOURCE))
+		return -EOPNOTSUPP;
+
+	for (i = 0; i < sd->entity.num_pads; ++i) {
+		if (i != pad && sd->entity.pads[i].flags & MEDIA_PAD_FL_SOURCE)
+			return -EOPNOTSUPP;
+	}
+
+	if ((sd->enabled_streams & streams_mask) != streams_mask) {
+		dev_dbg(dev, "set of streams %#llx already disabled on %s:%u\n",
+			streams_mask, sd->entity.name, pad);
+		return -EALREADY;
+	}
+
+	/* Stop streaming when the last streams are disabled. */
+	if (!(sd->enabled_streams & ~streams_mask)) {
+		ret = v4l2_subdev_call(sd, video, s_stream, 0);
+		if (ret)
+			return ret;
+	}
+
+	sd->enabled_streams &= ~streams_mask;
+
+	return 0;
+}
+
+int v4l2_subdev_disable_streams(struct v4l2_subdev *sd, u32 pad,
+				u64 streams_mask)
+{
+	struct device *dev = sd->entity.graph_obj.mdev->dev;
+	struct v4l2_subdev_state *state;
+	u64 found_streams = 0;
+	unsigned int i;
+	int ret;
+
+	/* A few basic sanity checks first. */
+	if (pad >= sd->entity.num_pads)
+		return -EINVAL;
+
+	if (!streams_mask)
+		return 0;
+
+	/* Fallback on .s_stream() if .disable_streams() isn't available. */
+	if (!sd->ops->pad || !sd->ops->pad->disable_streams)
+		return v4l2_subdev_disable_streams_fallback(sd, pad,
+							    streams_mask);
+
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	/*
+	 * Verify that the requested streams exist and that they are not
+	 * already disabled.
+	 */
+	for (i = 0; i < state->stream_configs.num_configs; ++i) {
+		struct v4l2_subdev_stream_config *cfg =
+			&state->stream_configs.configs[i];
+
+		if (cfg->pad != pad || !(streams_mask & BIT_ULL(cfg->stream)))
+			continue;
+
+		found_streams |= BIT_ULL(cfg->stream);
+
+		if (!cfg->enabled) {
+			dev_dbg(dev, "stream %u already disabled on %s:%u\n",
+				cfg->stream, sd->entity.name, pad);
+			ret = -EALREADY;
+			goto done;
+		}
+	}
+
+	if (found_streams != streams_mask) {
+		dev_dbg(dev, "streams 0x%llx not found on %s:%u\n",
+			streams_mask & ~found_streams, sd->entity.name, pad);
+		ret = -EINVAL;
+		goto done;
+	}
+
+	/* Call the .disable_streams() operation. */
+	ret = v4l2_subdev_call(sd, pad, disable_streams, state, pad,
+			       streams_mask);
+	if (ret)
+		goto done;
+
+	/* Mark the streams as disabled. */
+	for (i = 0; i < state->stream_configs.num_configs; ++i) {
+		struct v4l2_subdev_stream_config *cfg =
+			&state->stream_configs.configs[i];
+
+		if (cfg->pad == pad && (streams_mask & BIT_ULL(cfg->stream)))
+			cfg->enabled = false;
+	}
+
+done:
+	v4l2_subdev_unlock_state(state);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_disable_streams);
+
+int v4l2_subdev_s_stream_helper(struct v4l2_subdev *sd, int enable)
+{
+	struct v4l2_subdev_state *state;
+	struct v4l2_subdev_route *route;
+	struct media_pad *pad;
+	u64 source_mask = 0;
+	int pad_index = -1;
+
+	/*
+	 * Find the source pad. This helper is meant for subdevs that have a
+	 * single source pad, so failures shouldn't happen, but catch them
+	 * loudly nonetheless as they indicate a driver bug.
+	 */
+	media_entity_for_each_pad(&sd->entity, pad) {
+		if (pad->flags & MEDIA_PAD_FL_SOURCE) {
+			pad_index = pad->index;
+			break;
+		}
+	}
+
+	if (WARN_ON(pad_index == -1))
+		return -EINVAL;
+
+	/*
+	 * As there's a single source pad, just collect all the source streams.
+	 */
+	state = v4l2_subdev_lock_and_get_active_state(sd);
+
+	for_each_active_route(&state->routing, route)
+		source_mask |= BIT_ULL(route->source_stream);
+
+	v4l2_subdev_unlock_state(state);
+
+	if (enable)
+		return v4l2_subdev_enable_streams(sd, pad_index, source_mask);
+	else
+		return v4l2_subdev_disable_streams(sd, pad_index, source_mask);
+}
+EXPORT_SYMBOL_GPL(v4l2_subdev_s_stream_helper);
+
 #endif /* CONFIG_VIDEO_V4L2_SUBDEV_API */
 
 #endif /* CONFIG_MEDIA_CONTROLLER */
diff -Naur --no-dereference a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
--- a/drivers/mfd/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/mfd/Kconfig	2024-01-28 14:01:31.248353800 -0500
@@ -1636,6 +1636,20 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called tps65218.
 
+config MFD_TPS65219
+	tristate "TI TPS65219 Power Management IC"
+	depends on I2C && OF
+	select MFD_CORE
+	select REGMAP_I2C
+	select REGMAP_IRQ
+	help
+	  If you say yes here you get support for the TPS65219 series of Power
+	  Management ICs. These include voltage regulators, GPIOs and
+	  push/power button that is often used in portable devices.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called tps65219.
+
 config MFD_TPS6586X
 	bool "TI TPS6586x Power Management chips"
 	depends on I2C=y
@@ -1687,6 +1701,38 @@
 	  If you say yes here you get support for the TPS65912 series of
 	  PM chips with SPI interface.
 
+config MFD_TPS6594
+	tristate
+	select MFD_CORE
+	select REGMAP
+	select REGMAP_IRQ
+
+config MFD_TPS6594_I2C
+	tristate "TI TPS6594 Power Management chip with I2C"
+	select MFD_TPS6594
+	select REGMAP_I2C
+	select CRC8
+	depends on I2C
+	help
+	  If you say yes here you get support for the TPS6594 series of
+	  PM chips with I2C interface.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called tps6594-i2c.
+
+config MFD_TPS6594_SPI
+	tristate "TI TPS6594 Power Management chip with SPI"
+	select MFD_TPS6594
+	select REGMAP_SPI
+	select CRC8
+	depends on SPI_MASTER
+	help
+	  If you say yes here you get support for the TPS6594 series of
+	  PM chips with SPI interface.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called tps6594-spi.
+
 config TWL4030_CORE
 	bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support"
 	depends on I2C=y
diff -Naur --no-dereference a/drivers/mfd/Makefile b/drivers/mfd/Makefile
--- a/drivers/mfd/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/mfd/Makefile	2024-01-28 14:01:31.248353800 -0500
@@ -101,10 +101,14 @@
 obj-$(CONFIG_MFD_TPS65086)	+= tps65086.o
 obj-$(CONFIG_MFD_TPS65217)	+= tps65217.o
 obj-$(CONFIG_MFD_TPS65218)	+= tps65218.o
+obj-$(CONFIG_MFD_TPS65219)	+= tps65219.o
 obj-$(CONFIG_MFD_TPS65910)	+= tps65910.o
 obj-$(CONFIG_MFD_TPS65912)	+= tps65912-core.o
 obj-$(CONFIG_MFD_TPS65912_I2C)	+= tps65912-i2c.o
 obj-$(CONFIG_MFD_TPS65912_SPI)  += tps65912-spi.o
+obj-$(CONFIG_MFD_TPS6594)	+= tps6594-core.o
+obj-$(CONFIG_MFD_TPS6594_I2C)	+= tps6594-i2c.o
+obj-$(CONFIG_MFD_TPS6594_SPI)	+= tps6594-spi.o
 obj-$(CONFIG_MENELAUS)		+= menelaus.o
 
 obj-$(CONFIG_TWL4030_CORE)	+= twl-core.o twl4030-irq.o twl6030-irq.o
diff -Naur --no-dereference a/drivers/mfd/tps65219.c b/drivers/mfd/tps65219.c
--- a/drivers/mfd/tps65219.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/mfd/tps65219.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,317 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Driver for TPS65219 Integrated Power Management Integrated Chips (PMIC)
+//
+// Copyright (C) 2022 BayLibre Incorporated - https://www.baylibre.com/
+
+#include <linux/i2c.h>
+#include <linux/reboot.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps65219.h>
+
+static int tps65219_warm_reset(struct tps65219 *tps)
+{
+	return regmap_update_bits(tps->regmap, TPS65219_REG_MFP_CTRL,
+				  TPS65219_MFP_WARM_RESET_I2C_CTRL_MASK,
+				  TPS65219_MFP_WARM_RESET_I2C_CTRL_MASK);
+}
+
+static int tps65219_cold_reset(struct tps65219 *tps)
+{
+	return regmap_update_bits(tps->regmap, TPS65219_REG_MFP_CTRL,
+				  TPS65219_MFP_COLD_RESET_I2C_CTRL_MASK,
+				  TPS65219_MFP_COLD_RESET_I2C_CTRL_MASK);
+}
+
+static int tps65219_soft_shutdown(struct tps65219 *tps)
+{
+	return regmap_update_bits(tps->regmap, TPS65219_REG_MFP_CTRL,
+				  TPS65219_MFP_I2C_OFF_REQ_MASK,
+				  TPS65219_MFP_I2C_OFF_REQ_MASK);
+}
+
+static int tps65219_power_off_handler(struct sys_off_data *data)
+{
+	tps65219_soft_shutdown(data->cb_data);
+	return NOTIFY_DONE;
+}
+
+static int tps65219_restart(struct tps65219 *tps, unsigned long reboot_mode)
+{
+	if (reboot_mode == REBOOT_WARM)
+		tps65219_warm_reset(tps);
+	else
+		tps65219_cold_reset(tps);
+
+	return NOTIFY_DONE;
+}
+
+static int tps65219_restart_handler(struct sys_off_data *data)
+{
+	tps65219_restart(data->cb_data, data->mode);
+	return NOTIFY_DONE;
+}
+
+static const struct resource tps65219_pwrbutton_resources[] = {
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_PB_FALLING_EDGE_DETECT, "falling"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_PB_RISING_EDGE_DETECT, "rising"),
+};
+
+static const struct resource tps65219_regulator_resources[] = {
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO3_SCG, "LDO3_SCG"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO3_OC, "LDO3_OC"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO3_UV, "LDO3_UV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO4_SCG, "LDO4_SCG"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO4_OC, "LDO4_OC"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO4_UV, "LDO4_UV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO1_SCG, "LDO1_SCG"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO1_OC, "LDO1_OC"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO1_UV, "LDO1_UV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO2_SCG, "LDO2_SCG"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO2_OC, "LDO2_OC"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO2_UV, "LDO2_UV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_SCG, "BUCK3_SCG"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_OC, "BUCK3_OC"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_NEG_OC, "BUCK3_NEG_OC"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_UV, "BUCK3_UV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_SCG, "BUCK1_SCG"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_OC, "BUCK1_OC"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_NEG_OC, "BUCK1_NEG_OC"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_UV, "BUCK1_UV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_SCG, "BUCK2_SCG"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_OC, "BUCK2_OC"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_NEG_OC, "BUCK2_NEG_OC"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_UV, "BUCK2_UV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_RV, "BUCK1_RV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_RV, "BUCK2_RV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_RV, "BUCK3_RV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO1_RV, "LDO1_RV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO2_RV, "LDO2_RV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO3_RV, "LDO3_RV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO4_RV, "LDO4_RV"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK1_RV_SD, "BUCK1_RV_SD"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK2_RV_SD, "BUCK2_RV_SD"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_BUCK3_RV_SD, "BUCK3_RV_SD"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO1_RV_SD, "LDO1_RV_SD"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO2_RV_SD, "LDO2_RV_SD"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO3_RV_SD, "LDO3_RV_SD"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_LDO4_RV_SD, "LDO4_RV_SD"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_TIMEOUT, "TIMEOUT"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_3_WARM, "SENSOR_3_WARM"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_2_WARM, "SENSOR_2_WARM"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_1_WARM, "SENSOR_1_WARM"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_0_WARM, "SENSOR_0_WARM"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_3_HOT, "SENSOR_3_HOT"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_2_HOT, "SENSOR_2_HOT"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_1_HOT, "SENSOR_1_HOT"),
+	DEFINE_RES_IRQ_NAMED(TPS65219_INT_SENSOR_0_HOT, "SENSOR_0_HOT"),
+};
+
+static const struct mfd_cell tps65219_cells[] = {
+	{
+		.name = "tps65219-regulator",
+		.resources = tps65219_regulator_resources,
+		.num_resources = ARRAY_SIZE(tps65219_regulator_resources),
+	},
+	{ .name = "tps65219-gpio", },
+};
+
+static const struct mfd_cell tps65219_pwrbutton_cell = {
+	.name = "tps65219-pwrbutton",
+	.resources = tps65219_pwrbutton_resources,
+	.num_resources = ARRAY_SIZE(tps65219_pwrbutton_resources),
+};
+
+static const struct regmap_config tps65219_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.max_register = TPS65219_REG_FACTORY_CONFIG_2,
+};
+
+/*
+ * Mapping of main IRQ register bits to sub-IRQ register offsets so that we can
+ * access corect sub-IRQ registers based on bits that are set in main IRQ
+ * register.
+ */
+/* Timeout Residual Voltage Shutdown */
+static unsigned int bit0_offsets[] = { TPS65219_REG_INT_TO_RV_POS };
+static unsigned int bit1_offsets[] = { TPS65219_REG_INT_RV_POS };	/* Residual Voltage */
+static unsigned int bit2_offsets[] = { TPS65219_REG_INT_SYS_POS };	/* System */
+static unsigned int bit3_offsets[] = { TPS65219_REG_INT_BUCK_1_2_POS };	/* Buck 1-2 */
+static unsigned int bit4_offsets[] = { TPS65219_REG_INT_BUCK_3_POS };	/* Buck 3 */
+static unsigned int bit5_offsets[] = { TPS65219_REG_INT_LDO_1_2_POS };	/* LDO 1-2 */
+static unsigned int bit6_offsets[] = { TPS65219_REG_INT_LDO_3_4_POS };	/* LDO 3-4 */
+static unsigned int bit7_offsets[] = { TPS65219_REG_INT_PB_POS };	/* Power Button */
+
+static struct regmap_irq_sub_irq_map tps65219_sub_irq_offsets[] = {
+	REGMAP_IRQ_MAIN_REG_OFFSET(bit0_offsets),
+	REGMAP_IRQ_MAIN_REG_OFFSET(bit1_offsets),
+	REGMAP_IRQ_MAIN_REG_OFFSET(bit2_offsets),
+	REGMAP_IRQ_MAIN_REG_OFFSET(bit3_offsets),
+	REGMAP_IRQ_MAIN_REG_OFFSET(bit4_offsets),
+	REGMAP_IRQ_MAIN_REG_OFFSET(bit5_offsets),
+	REGMAP_IRQ_MAIN_REG_OFFSET(bit6_offsets),
+	REGMAP_IRQ_MAIN_REG_OFFSET(bit7_offsets),
+};
+
+#define TPS65219_REGMAP_IRQ_REG(int_name, register_position) \
+	REGMAP_IRQ_REG(int_name, register_position, int_name##_MASK)
+
+static struct regmap_irq tps65219_irqs[] = {
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO3_SCG, TPS65219_REG_INT_LDO_3_4_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO3_OC, TPS65219_REG_INT_LDO_3_4_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO3_UV, TPS65219_REG_INT_LDO_3_4_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO4_SCG, TPS65219_REG_INT_LDO_3_4_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO4_OC, TPS65219_REG_INT_LDO_3_4_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO4_UV, TPS65219_REG_INT_LDO_3_4_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO1_SCG, TPS65219_REG_INT_LDO_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO1_OC, TPS65219_REG_INT_LDO_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO1_UV, TPS65219_REG_INT_LDO_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO2_SCG, TPS65219_REG_INT_LDO_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO2_OC, TPS65219_REG_INT_LDO_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO2_UV, TPS65219_REG_INT_LDO_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_SCG, TPS65219_REG_INT_BUCK_3_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_OC, TPS65219_REG_INT_BUCK_3_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_NEG_OC, TPS65219_REG_INT_BUCK_3_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_UV, TPS65219_REG_INT_BUCK_3_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_SCG, TPS65219_REG_INT_BUCK_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_OC, TPS65219_REG_INT_BUCK_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_NEG_OC, TPS65219_REG_INT_BUCK_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_UV, TPS65219_REG_INT_BUCK_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_SCG, TPS65219_REG_INT_BUCK_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_OC, TPS65219_REG_INT_BUCK_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_NEG_OC, TPS65219_REG_INT_BUCK_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_UV, TPS65219_REG_INT_BUCK_1_2_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_3_WARM, TPS65219_REG_INT_SYS_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_2_WARM, TPS65219_REG_INT_SYS_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_1_WARM, TPS65219_REG_INT_SYS_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_0_WARM, TPS65219_REG_INT_SYS_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_3_HOT, TPS65219_REG_INT_SYS_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_2_HOT, TPS65219_REG_INT_SYS_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_1_HOT, TPS65219_REG_INT_SYS_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_SENSOR_0_HOT, TPS65219_REG_INT_SYS_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_RV, TPS65219_REG_INT_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_RV, TPS65219_REG_INT_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_RV, TPS65219_REG_INT_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO1_RV, TPS65219_REG_INT_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO2_RV, TPS65219_REG_INT_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO3_RV, TPS65219_REG_INT_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO4_RV, TPS65219_REG_INT_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK1_RV_SD, TPS65219_REG_INT_TO_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK2_RV_SD, TPS65219_REG_INT_TO_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_BUCK3_RV_SD, TPS65219_REG_INT_TO_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO1_RV_SD, TPS65219_REG_INT_TO_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO2_RV_SD, TPS65219_REG_INT_TO_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO3_RV_SD, TPS65219_REG_INT_TO_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_LDO4_RV_SD, TPS65219_REG_INT_TO_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_TIMEOUT, TPS65219_REG_INT_TO_RV_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_PB_FALLING_EDGE_DETECT, TPS65219_REG_INT_PB_POS),
+	TPS65219_REGMAP_IRQ_REG(TPS65219_INT_PB_RISING_EDGE_DETECT, TPS65219_REG_INT_PB_POS),
+};
+
+static struct regmap_irq_chip tps65219_irq_chip = {
+	.name = "tps65219_irq",
+	.main_status = TPS65219_REG_INT_SOURCE,
+	.num_main_regs = 1,
+	.num_main_status_bits = 8,
+	.irqs = tps65219_irqs,
+	.num_irqs = ARRAY_SIZE(tps65219_irqs),
+	.status_base = TPS65219_REG_INT_LDO_3_4,
+	.ack_base = TPS65219_REG_INT_LDO_3_4,
+	.clear_ack = 1,
+	.num_regs = 8,
+	.sub_reg_offsets = tps65219_sub_irq_offsets,
+};
+
+static int tps65219_probe(struct i2c_client *client)
+{
+	struct tps65219 *tps;
+	unsigned int chipid;
+	bool pwr_button;
+	int ret;
+
+	tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+	if (!tps)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, tps);
+
+	tps->dev = &client->dev;
+
+	tps->regmap = devm_regmap_init_i2c(client, &tps65219_regmap_config);
+	if (IS_ERR(tps->regmap)) {
+		ret = PTR_ERR(tps->regmap);
+		dev_err(tps->dev, "Failed to allocate register map: %d\n", ret);
+		return ret;
+	}
+
+	ret = devm_regmap_add_irq_chip(&client->dev, tps->regmap, client->irq,
+				       IRQF_ONESHOT, 0, &tps65219_irq_chip,
+				       &tps->irq_data);
+	if (ret)
+		return ret;
+
+	ret = regmap_read(tps->regmap, TPS65219_REG_TI_DEV_ID, &chipid);
+	if (ret) {
+		dev_err(tps->dev, "Failed to read device ID: %d\n", ret);
+		return ret;
+	}
+
+	ret = devm_mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO,
+				   tps65219_cells, ARRAY_SIZE(tps65219_cells),
+				   NULL, 0, regmap_irq_get_domain(tps->irq_data));
+	if (ret) {
+		dev_err(tps->dev, "Failed to add child devices: %d\n", ret);
+		return ret;
+	}
+
+	pwr_button = of_property_read_bool(tps->dev->of_node, "ti,power-button");
+	if (pwr_button) {
+		ret = devm_mfd_add_devices(tps->dev, PLATFORM_DEVID_AUTO,
+					   &tps65219_pwrbutton_cell, 1, NULL, 0,
+					   regmap_irq_get_domain(tps->irq_data));
+		if (ret) {
+			dev_err(tps->dev, "Failed to add power-button: %d\n", ret);
+			return ret;
+		}
+	}
+
+	ret = devm_register_restart_handler(tps->dev,
+					    tps65219_restart_handler,
+					    tps);
+
+	if (ret) {
+		dev_err(tps->dev, "cannot register restart handler, %d\n", ret);
+		return ret;
+	}
+
+	ret = devm_register_power_off_handler(tps->dev,
+					      tps65219_power_off_handler,
+					      tps);
+	if (ret) {
+		dev_err(tps->dev, "failed to register power-off handler: %d\n", ret);
+		return ret;
+	}
+	return 0;
+}
+
+static const struct of_device_id of_tps65219_match_table[] = {
+	{ .compatible = "ti,tps65219", },
+	{}
+};
+MODULE_DEVICE_TABLE(of, of_tps65219_match_table);
+
+static struct i2c_driver tps65219_driver = {
+	.driver		= {
+		.name	= "tps65219",
+		.of_match_table = of_tps65219_match_table,
+	},
+	.probe_new	= tps65219_probe,
+};
+module_i2c_driver(tps65219_driver);
+
+MODULE_AUTHOR("Jerome Neanne <jneanne@baylibre.com>");
+MODULE_DESCRIPTION("TPS65219 power management IC driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/mfd/tps6594-core.c b/drivers/mfd/tps6594-core.c
--- a/drivers/mfd/tps6594-core.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/mfd/tps6594-core.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,462 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Core functions for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps6594.h>
+
+#define TPS6594_CRC_SYNC_TIMEOUT_MS 150
+
+/* Completion to synchronize CRC feature enabling on all PMICs */
+static DECLARE_COMPLETION(tps6594_crc_comp);
+
+static const struct resource tps6594_regulator_resources[] = {
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_OV, TPS6594_IRQ_NAME_BUCK1_OV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_UV, TPS6594_IRQ_NAME_BUCK1_UV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_SC, TPS6594_IRQ_NAME_BUCK1_SC),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK1_ILIM, TPS6594_IRQ_NAME_BUCK1_ILIM),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_OV, TPS6594_IRQ_NAME_BUCK2_OV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_UV, TPS6594_IRQ_NAME_BUCK2_UV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_SC, TPS6594_IRQ_NAME_BUCK2_SC),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK2_ILIM, TPS6594_IRQ_NAME_BUCK2_ILIM),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_OV, TPS6594_IRQ_NAME_BUCK3_OV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_UV, TPS6594_IRQ_NAME_BUCK3_UV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_SC, TPS6594_IRQ_NAME_BUCK3_SC),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK3_ILIM, TPS6594_IRQ_NAME_BUCK3_ILIM),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_OV, TPS6594_IRQ_NAME_BUCK4_OV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_UV, TPS6594_IRQ_NAME_BUCK4_UV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_SC, TPS6594_IRQ_NAME_BUCK4_SC),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK4_ILIM, TPS6594_IRQ_NAME_BUCK4_ILIM),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_OV, TPS6594_IRQ_NAME_BUCK5_OV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_UV, TPS6594_IRQ_NAME_BUCK5_UV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_SC, TPS6594_IRQ_NAME_BUCK5_SC),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BUCK5_ILIM, TPS6594_IRQ_NAME_BUCK5_ILIM),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_OV, TPS6594_IRQ_NAME_LDO1_OV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_UV, TPS6594_IRQ_NAME_LDO1_UV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_SC, TPS6594_IRQ_NAME_LDO1_SC),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO1_ILIM, TPS6594_IRQ_NAME_LDO1_ILIM),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_OV, TPS6594_IRQ_NAME_LDO2_OV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_UV, TPS6594_IRQ_NAME_LDO2_UV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_SC, TPS6594_IRQ_NAME_LDO2_SC),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO2_ILIM, TPS6594_IRQ_NAME_LDO2_ILIM),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_OV, TPS6594_IRQ_NAME_LDO3_OV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_UV, TPS6594_IRQ_NAME_LDO3_UV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_SC, TPS6594_IRQ_NAME_LDO3_SC),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO3_ILIM, TPS6594_IRQ_NAME_LDO3_ILIM),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_OV, TPS6594_IRQ_NAME_LDO4_OV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_UV, TPS6594_IRQ_NAME_LDO4_UV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_SC, TPS6594_IRQ_NAME_LDO4_SC),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_LDO4_ILIM, TPS6594_IRQ_NAME_LDO4_ILIM),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VCCA_OV, TPS6594_IRQ_NAME_VCCA_OV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VCCA_UV, TPS6594_IRQ_NAME_VCCA_UV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON1_OV, TPS6594_IRQ_NAME_VMON1_OV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON1_UV, TPS6594_IRQ_NAME_VMON1_UV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON1_RV, TPS6594_IRQ_NAME_VMON1_RV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON2_OV, TPS6594_IRQ_NAME_VMON2_OV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON2_UV, TPS6594_IRQ_NAME_VMON2_UV),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VMON2_RV, TPS6594_IRQ_NAME_VMON2_RV),
+};
+
+static const struct resource tps6594_pinctrl_resources[] = {
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO9, TPS6594_IRQ_NAME_GPIO9),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO10, TPS6594_IRQ_NAME_GPIO10),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO11, TPS6594_IRQ_NAME_GPIO11),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO1, TPS6594_IRQ_NAME_GPIO1),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO2, TPS6594_IRQ_NAME_GPIO2),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO3, TPS6594_IRQ_NAME_GPIO3),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO4, TPS6594_IRQ_NAME_GPIO4),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO5, TPS6594_IRQ_NAME_GPIO5),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO6, TPS6594_IRQ_NAME_GPIO6),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO7, TPS6594_IRQ_NAME_GPIO7),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_GPIO8, TPS6594_IRQ_NAME_GPIO8),
+};
+
+static const struct resource tps6594_pfsm_resources[] = {
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NPWRON_START, TPS6594_IRQ_NAME_NPWRON_START),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ENABLE, TPS6594_IRQ_NAME_ENABLE),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_FSD, TPS6594_IRQ_NAME_FSD),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_SOFT_REBOOT, TPS6594_IRQ_NAME_SOFT_REBOOT),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BIST_PASS, TPS6594_IRQ_NAME_BIST_PASS),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_EXT_CLK, TPS6594_IRQ_NAME_EXT_CLK),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TWARN, TPS6594_IRQ_NAME_TWARN),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TSD_ORD, TPS6594_IRQ_NAME_TSD_ORD),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_BIST_FAIL, TPS6594_IRQ_NAME_BIST_FAIL),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_REG_CRC_ERR, TPS6594_IRQ_NAME_REG_CRC_ERR),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_RECOV_CNT, TPS6594_IRQ_NAME_RECOV_CNT),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_SPMI_ERR, TPS6594_IRQ_NAME_SPMI_ERR),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NPWRON_LONG, TPS6594_IRQ_NAME_NPWRON_LONG),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NINT_READBACK, TPS6594_IRQ_NAME_NINT_READBACK),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NRSTOUT_READBACK, TPS6594_IRQ_NAME_NRSTOUT_READBACK),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TSD_IMM, TPS6594_IRQ_NAME_TSD_IMM),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_VCCA_OVP, TPS6594_IRQ_NAME_VCCA_OVP),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_PFSM_ERR, TPS6594_IRQ_NAME_PFSM_ERR),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_IMM_SHUTDOWN, TPS6594_IRQ_NAME_IMM_SHUTDOWN),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ORD_SHUTDOWN, TPS6594_IRQ_NAME_ORD_SHUTDOWN),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_MCU_PWR_ERR, TPS6594_IRQ_NAME_MCU_PWR_ERR),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_SOC_PWR_ERR, TPS6594_IRQ_NAME_SOC_PWR_ERR),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_COMM_FRM_ERR, TPS6594_IRQ_NAME_COMM_FRM_ERR),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_COMM_CRC_ERR, TPS6594_IRQ_NAME_COMM_CRC_ERR),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_COMM_ADR_ERR, TPS6594_IRQ_NAME_COMM_ADR_ERR),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_EN_DRV_READBACK, TPS6594_IRQ_NAME_EN_DRV_READBACK),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_NRSTOUT_SOC_READBACK,
+			     TPS6594_IRQ_NAME_NRSTOUT_SOC_READBACK),
+};
+
+static const struct resource tps6594_esm_resources[] = {
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ESM_SOC_PIN, TPS6594_IRQ_NAME_ESM_SOC_PIN),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ESM_SOC_FAIL, TPS6594_IRQ_NAME_ESM_SOC_FAIL),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ESM_SOC_RST, TPS6594_IRQ_NAME_ESM_SOC_RST),
+};
+
+static const struct resource tps6594_rtc_resources[] = {
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_TIMER, TPS6594_IRQ_NAME_TIMER),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_ALARM, TPS6594_IRQ_NAME_ALARM),
+	DEFINE_RES_IRQ_NAMED(TPS6594_IRQ_POWER_UP, TPS6594_IRQ_NAME_POWERUP),
+};
+
+static const struct mfd_cell tps6594_common_cells[] = {
+	MFD_CELL_RES("tps6594-regulator", tps6594_regulator_resources),
+	MFD_CELL_RES("tps6594-pinctrl", tps6594_pinctrl_resources),
+	MFD_CELL_RES("tps6594-pfsm", tps6594_pfsm_resources),
+	MFD_CELL_RES("tps6594-esm", tps6594_esm_resources),
+};
+
+static const struct mfd_cell tps6594_rtc_cells[] = {
+	MFD_CELL_RES("tps6594-rtc", tps6594_rtc_resources),
+};
+
+static const struct regmap_irq tps6594_irqs[] = {
+	/* INT_BUCK1_2 register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_OV, 0, TPS6594_BIT_BUCKX_OV_INT(0)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_UV, 0, TPS6594_BIT_BUCKX_UV_INT(0)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_SC, 0, TPS6594_BIT_BUCKX_SC_INT(0)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK1_ILIM, 0, TPS6594_BIT_BUCKX_ILIM_INT(0)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_OV, 0, TPS6594_BIT_BUCKX_OV_INT(1)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_UV, 0, TPS6594_BIT_BUCKX_UV_INT(1)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_SC, 0, TPS6594_BIT_BUCKX_SC_INT(1)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK2_ILIM, 0, TPS6594_BIT_BUCKX_ILIM_INT(1)),
+
+	/* INT_BUCK3_4 register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_OV, 1, TPS6594_BIT_BUCKX_OV_INT(2)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_UV, 1, TPS6594_BIT_BUCKX_UV_INT(2)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_SC, 1, TPS6594_BIT_BUCKX_SC_INT(2)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK3_ILIM, 1, TPS6594_BIT_BUCKX_ILIM_INT(2)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_OV, 1, TPS6594_BIT_BUCKX_OV_INT(3)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_UV, 1, TPS6594_BIT_BUCKX_UV_INT(3)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_SC, 1, TPS6594_BIT_BUCKX_SC_INT(3)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK4_ILIM, 1, TPS6594_BIT_BUCKX_ILIM_INT(3)),
+
+	/* INT_BUCK5 register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_OV, 2, TPS6594_BIT_BUCKX_OV_INT(4)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_UV, 2, TPS6594_BIT_BUCKX_UV_INT(4)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_SC, 2, TPS6594_BIT_BUCKX_SC_INT(4)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BUCK5_ILIM, 2, TPS6594_BIT_BUCKX_ILIM_INT(4)),
+
+	/* INT_LDO1_2 register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_OV, 3, TPS6594_BIT_LDOX_OV_INT(0)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_UV, 3, TPS6594_BIT_LDOX_UV_INT(0)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_SC, 3, TPS6594_BIT_LDOX_SC_INT(0)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO1_ILIM, 3, TPS6594_BIT_LDOX_ILIM_INT(0)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_OV, 3, TPS6594_BIT_LDOX_OV_INT(1)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_UV, 3, TPS6594_BIT_LDOX_UV_INT(1)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_SC, 3, TPS6594_BIT_LDOX_SC_INT(1)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO2_ILIM, 3, TPS6594_BIT_LDOX_ILIM_INT(1)),
+
+	/* INT_LDO3_4 register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_OV, 4, TPS6594_BIT_LDOX_OV_INT(2)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_UV, 4, TPS6594_BIT_LDOX_UV_INT(2)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_SC, 4, TPS6594_BIT_LDOX_SC_INT(2)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO3_ILIM, 4, TPS6594_BIT_LDOX_ILIM_INT(2)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_OV, 4, TPS6594_BIT_LDOX_OV_INT(3)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_UV, 4, TPS6594_BIT_LDOX_UV_INT(3)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_SC, 4, TPS6594_BIT_LDOX_SC_INT(3)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_LDO4_ILIM, 4, TPS6594_BIT_LDOX_ILIM_INT(3)),
+
+	/* INT_VMON register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_VCCA_OV, 5, TPS6594_BIT_VCCA_OV_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_VCCA_UV, 5, TPS6594_BIT_VCCA_UV_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_VMON1_OV, 5, TPS6594_BIT_VMON1_OV_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_VMON1_UV, 5, TPS6594_BIT_VMON1_UV_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_VMON1_RV, 5, TPS6594_BIT_VMON1_RV_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_VMON2_OV, 5, TPS6594_BIT_VMON2_OV_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_VMON2_UV, 5, TPS6594_BIT_VMON2_UV_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_VMON2_RV, 5, TPS6594_BIT_VMON2_RV_INT),
+
+	/* INT_GPIO register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_GPIO9, 6, TPS6594_BIT_GPIO9_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_GPIO10, 6, TPS6594_BIT_GPIO10_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_GPIO11, 6, TPS6594_BIT_GPIO11_INT),
+
+	/* INT_GPIO1_8 register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_GPIO1, 7, TPS6594_BIT_GPIOX_INT(0)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_GPIO2, 7, TPS6594_BIT_GPIOX_INT(1)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_GPIO3, 7, TPS6594_BIT_GPIOX_INT(2)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_GPIO4, 7, TPS6594_BIT_GPIOX_INT(3)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_GPIO5, 7, TPS6594_BIT_GPIOX_INT(4)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_GPIO6, 7, TPS6594_BIT_GPIOX_INT(5)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_GPIO7, 7, TPS6594_BIT_GPIOX_INT(6)),
+	REGMAP_IRQ_REG(TPS6594_IRQ_GPIO8, 7, TPS6594_BIT_GPIOX_INT(7)),
+
+	/* INT_STARTUP register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_NPWRON_START, 8, TPS6594_BIT_NPWRON_START_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_ENABLE, 8, TPS6594_BIT_ENABLE_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_FSD, 8, TPS6594_BIT_FSD_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_SOFT_REBOOT, 8, TPS6594_BIT_SOFT_REBOOT_INT),
+
+	/* INT_MISC register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_BIST_PASS, 9, TPS6594_BIT_BIST_PASS_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_EXT_CLK, 9, TPS6594_BIT_EXT_CLK_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_TWARN, 9, TPS6594_BIT_TWARN_INT),
+
+	/* INT_MODERATE_ERR register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_TSD_ORD, 10, TPS6594_BIT_TSD_ORD_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_BIST_FAIL, 10, TPS6594_BIT_BIST_FAIL_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_REG_CRC_ERR, 10, TPS6594_BIT_REG_CRC_ERR_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_RECOV_CNT, 10, TPS6594_BIT_RECOV_CNT_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_SPMI_ERR, 10, TPS6594_BIT_SPMI_ERR_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_NPWRON_LONG, 10, TPS6594_BIT_NPWRON_LONG_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_NINT_READBACK, 10, TPS6594_BIT_NINT_READBACK_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_NRSTOUT_READBACK, 10, TPS6594_BIT_NRSTOUT_READBACK_INT),
+
+	/* INT_SEVERE_ERR register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_TSD_IMM, 11, TPS6594_BIT_TSD_IMM_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_VCCA_OVP, 11, TPS6594_BIT_VCCA_OVP_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_PFSM_ERR, 11, TPS6594_BIT_PFSM_ERR_INT),
+
+	/* INT_FSM_ERR register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_IMM_SHUTDOWN, 12, TPS6594_BIT_IMM_SHUTDOWN_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_ORD_SHUTDOWN, 12, TPS6594_BIT_ORD_SHUTDOWN_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_MCU_PWR_ERR, 12, TPS6594_BIT_MCU_PWR_ERR_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_SOC_PWR_ERR, 12, TPS6594_BIT_SOC_PWR_ERR_INT),
+
+	/* INT_COMM_ERR register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_COMM_FRM_ERR, 13, TPS6594_BIT_COMM_FRM_ERR_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_COMM_CRC_ERR, 13, TPS6594_BIT_COMM_CRC_ERR_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_COMM_ADR_ERR, 13, TPS6594_BIT_COMM_ADR_ERR_INT),
+
+	/* INT_READBACK_ERR register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_EN_DRV_READBACK, 14, TPS6594_BIT_EN_DRV_READBACK_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_NRSTOUT_SOC_READBACK, 14, TPS6594_BIT_NRSTOUT_SOC_READBACK_INT),
+
+	/* INT_ESM register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_ESM_SOC_PIN, 15, TPS6594_BIT_ESM_SOC_PIN_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_ESM_SOC_FAIL, 15, TPS6594_BIT_ESM_SOC_FAIL_INT),
+	REGMAP_IRQ_REG(TPS6594_IRQ_ESM_SOC_RST, 15, TPS6594_BIT_ESM_SOC_RST_INT),
+
+	/* RTC_STATUS register */
+	REGMAP_IRQ_REG(TPS6594_IRQ_TIMER, 16, TPS6594_BIT_TIMER),
+	REGMAP_IRQ_REG(TPS6594_IRQ_ALARM, 16, TPS6594_BIT_ALARM),
+	REGMAP_IRQ_REG(TPS6594_IRQ_POWER_UP, 16, TPS6594_BIT_POWER_UP),
+};
+
+static const unsigned int tps6594_irq_reg[] = {
+	TPS6594_REG_INT_BUCK1_2,
+	TPS6594_REG_INT_BUCK3_4,
+	TPS6594_REG_INT_BUCK5,
+	TPS6594_REG_INT_LDO1_2,
+	TPS6594_REG_INT_LDO3_4,
+	TPS6594_REG_INT_VMON,
+	TPS6594_REG_INT_GPIO,
+	TPS6594_REG_INT_GPIO1_8,
+	TPS6594_REG_INT_STARTUP,
+	TPS6594_REG_INT_MISC,
+	TPS6594_REG_INT_MODERATE_ERR,
+	TPS6594_REG_INT_SEVERE_ERR,
+	TPS6594_REG_INT_FSM_ERR,
+	TPS6594_REG_INT_COMM_ERR,
+	TPS6594_REG_INT_READBACK_ERR,
+	TPS6594_REG_INT_ESM,
+	TPS6594_REG_RTC_STATUS,
+};
+
+static inline unsigned int tps6594_get_irq_reg(struct regmap_irq_chip_data *data,
+					       unsigned int base, int index)
+{
+	return tps6594_irq_reg[index];
+};
+
+static int tps6594_handle_post_irq(void *irq_drv_data)
+{
+	struct tps6594 *tps = irq_drv_data;
+	int ret = 0;
+
+	/*
+	 * When CRC is enabled, writing to a read-only bit triggers an error,
+	 * and COMM_ADR_ERR_INT bit is set. Besides, bits indicating interrupts
+	 * (that must be cleared) and read-only bits are sometimes grouped in
+	 * the same register.
+	 * Since regmap clears interrupts by doing a write per register, clearing
+	 * an interrupt bit in a register containing also a read-only bit makes
+	 * COMM_ADR_ERR_INT bit set. Clear immediately this bit to avoid raising
+	 * a new interrupt.
+	 */
+	if (tps->use_crc)
+		ret = regmap_write_bits(tps->regmap, TPS6594_REG_INT_COMM_ERR,
+					TPS6594_BIT_COMM_ADR_ERR_INT,
+					TPS6594_BIT_COMM_ADR_ERR_INT);
+
+	return ret;
+};
+
+static struct regmap_irq_chip tps6594_irq_chip = {
+	.ack_base = TPS6594_REG_INT_BUCK1_2,
+	.ack_invert = 1,
+	.clear_ack = 1,
+	.init_ack_masked = 1,
+	.num_regs = ARRAY_SIZE(tps6594_irq_reg),
+	.irqs = tps6594_irqs,
+	.num_irqs = ARRAY_SIZE(tps6594_irqs),
+	.get_irq_reg = tps6594_get_irq_reg,
+	.handle_post_irq = tps6594_handle_post_irq,
+};
+
+bool tps6594_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+	return (reg >= TPS6594_REG_INT_TOP && reg <= TPS6594_REG_STAT_READBACK_ERR) ||
+	       reg == TPS6594_REG_RTC_STATUS;
+}
+EXPORT_SYMBOL_GPL(tps6594_is_volatile_reg);
+
+static int tps6594_check_crc_mode(struct tps6594 *tps, bool primary_pmic)
+{
+	int ret;
+
+	/*
+	 * Check if CRC is enabled.
+	 * Once CRC is enabled, it can't be disabled until next power cycle.
+	 */
+	tps->use_crc = true;
+	ret = regmap_test_bits(tps->regmap, TPS6594_REG_SERIAL_IF_CONFIG,
+			       TPS6594_BIT_I2C1_SPI_CRC_EN);
+	if (ret == 0) {
+		ret = -EIO;
+	} else if (ret > 0) {
+		dev_info(tps->dev, "CRC feature enabled on %s PMIC",
+			 primary_pmic ? "primary" : "secondary");
+		ret = 0;
+	}
+
+	return ret;
+}
+
+static int tps6594_set_crc_feature(struct tps6594 *tps)
+{
+	int ret;
+
+	ret = tps6594_check_crc_mode(tps, true);
+	if (ret) {
+		/*
+		 * If CRC is not already enabled, force PFSM I2C_2 trigger to enable it
+		 * on primary PMIC.
+		 */
+		tps->use_crc = false;
+		ret = regmap_write_bits(tps->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+					TPS6594_BIT_TRIGGER_I2C(2), TPS6594_BIT_TRIGGER_I2C(2));
+		if (ret)
+			return ret;
+
+		/*
+		 * Wait for PFSM to process trigger.
+		 * The datasheet indicates 2 ms, and clock specification is +/-5%.
+		 * 4 ms should provide sufficient margin.
+		 */
+		usleep_range(4000, 5000);
+
+		ret = tps6594_check_crc_mode(tps, true);
+	}
+
+	return ret;
+}
+
+static int tps6594_enable_crc(struct tps6594 *tps)
+{
+	struct device *dev = tps->dev;
+	unsigned int is_primary;
+	unsigned long timeout = msecs_to_jiffies(TPS6594_CRC_SYNC_TIMEOUT_MS);
+	int ret;
+
+	/*
+	 * CRC mode can be used with I2C or SPI protocols.
+	 * If this mode is specified for primary PMIC, it will also be applied to secondary PMICs
+	 * through SPMI serial interface.
+	 * In this multi-PMIC synchronization scheme, the primary PMIC is the controller device
+	 * on the SPMI bus, and the secondary PMICs are the target devices on the SPMI bus.
+	 */
+	is_primary = of_property_read_bool(dev->of_node, "ti,primary-pmic");
+	if (is_primary) {
+		/* Enable CRC feature on primary PMIC */
+		ret = tps6594_set_crc_feature(tps);
+		if (ret)
+			return ret;
+
+		/* Notify secondary PMICs that CRC feature is enabled */
+		complete_all(&tps6594_crc_comp);
+	} else {
+		/* Wait for CRC feature enabling event from primary PMIC */
+		ret = wait_for_completion_interruptible_timeout(&tps6594_crc_comp, timeout);
+		if (ret == 0)
+			ret = -ETIMEDOUT;
+		else if (ret > 0)
+			ret = tps6594_check_crc_mode(tps, false);
+	}
+
+	return ret;
+}
+
+int tps6594_device_init(struct tps6594 *tps, bool enable_crc)
+{
+	struct device *dev = tps->dev;
+	int ret;
+
+	if (enable_crc) {
+		ret = tps6594_enable_crc(tps);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to enable CRC\n");
+	}
+
+	/* Keep PMIC in ACTIVE state */
+	ret = regmap_set_bits(tps->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+			      TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to set PMIC state\n");
+
+	tps6594_irq_chip.irq_drv_data = tps;
+	tps6594_irq_chip.name = devm_kasprintf(dev, GFP_KERNEL, "%s-%ld-0x%02x",
+					       dev->driver->name, tps->chip_id, tps->reg);
+
+	ret = devm_regmap_add_irq_chip(dev, tps->regmap, tps->irq, IRQF_SHARED | IRQF_ONESHOT,
+				       0, &tps6594_irq_chip, &tps->irq_data);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to add regmap IRQ\n");
+
+	ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_common_cells,
+				   ARRAY_SIZE(tps6594_common_cells), NULL, 0,
+				   regmap_irq_get_domain(tps->irq_data));
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to add common child devices\n");
+
+	/* No RTC for LP8764 */
+	if (tps->chip_id != LP8764) {
+		ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_rtc_cells,
+					   ARRAY_SIZE(tps6594_rtc_cells), NULL, 0,
+					   regmap_irq_get_domain(tps->irq_data));
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to add RTC child device\n");
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(tps6594_device_init);
+
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 Driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/mfd/tps6594-i2c.c b/drivers/mfd/tps6594-i2c.c
--- a/drivers/mfd/tps6594-i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/mfd/tps6594-i2c.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * I2C access driver for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/crc8.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/tps6594.h>
+
+static bool enable_crc;
+module_param(enable_crc, bool, 0444);
+MODULE_PARM_DESC(enable_crc, "Enable CRC feature for I2C interface");
+
+DECLARE_CRC8_TABLE(tps6594_i2c_crc_table);
+
+static int tps6594_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+	int ret = i2c_transfer(adap, msgs, num);
+
+	if (ret == num)
+		return 0;
+	else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static int tps6594_i2c_reg_read_with_crc(struct i2c_client *client, u8 page, u8 reg, u8 *val)
+{
+	struct i2c_msg msgs[2];
+	u8 buf_rx[] = { 0, 0 };
+	/* I2C address = I2C base address + Page index */
+	const u8 addr = client->addr + page;
+	/*
+	 * CRC is calculated from every bit included in the protocol
+	 * except the ACK bits from the target. Byte stream is:
+	 * - B0: (I2C_addr_7bits << 1) | WR_bit, with WR_bit = 0
+	 * - B1: reg
+	 * - B2: (I2C_addr_7bits << 1) | RD_bit, with RD_bit = 1
+	 * - B3: val
+	 * - B4: CRC from B0-B1-B2-B3
+	 */
+	u8 crc_data[] = { addr << 1, reg, addr << 1 | 1, 0 };
+	int ret;
+
+	/* Write register */
+	msgs[0].addr = addr;
+	msgs[0].flags = 0;
+	msgs[0].len = 1;
+	msgs[0].buf = &reg;
+
+	/* Read data and CRC */
+	msgs[1].addr = msgs[0].addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = 2;
+	msgs[1].buf = buf_rx;
+
+	ret = tps6594_i2c_transfer(client->adapter, msgs, 2);
+	if (ret < 0)
+		return ret;
+
+	crc_data[sizeof(crc_data) - 1] = *val = buf_rx[0];
+	if (buf_rx[1] != crc8(tps6594_i2c_crc_table, crc_data, sizeof(crc_data), CRC8_INIT_VALUE))
+		return -EIO;
+
+	return ret;
+}
+
+static int tps6594_i2c_reg_write_with_crc(struct i2c_client *client, u8 page, u8 reg, u8 val)
+{
+	struct i2c_msg msg;
+	u8 buf[] = { reg, val, 0 };
+	/* I2C address = I2C base address + Page index */
+	const u8 addr = client->addr + page;
+	/*
+	 * CRC is calculated from every bit included in the protocol
+	 * except the ACK bits from the target. Byte stream is:
+	 * - B0: (I2C_addr_7bits << 1) | WR_bit, with WR_bit = 0
+	 * - B1: reg
+	 * - B2: val
+	 * - B3: CRC from B0-B1-B2
+	 */
+	const u8 crc_data[] = { addr << 1, reg, val };
+
+	/* Write register, data and CRC */
+	msg.addr = addr;
+	msg.flags = client->flags & I2C_M_TEN;
+	msg.len = sizeof(buf);
+	msg.buf = buf;
+
+	buf[msg.len - 1] = crc8(tps6594_i2c_crc_table, crc_data, sizeof(crc_data), CRC8_INIT_VALUE);
+
+	return tps6594_i2c_transfer(client->adapter, &msg, 1);
+}
+
+static int tps6594_i2c_read(void *context, const void *reg_buf, size_t reg_size,
+			    void *val_buf, size_t val_size)
+{
+	struct i2c_client *client = context;
+	struct tps6594 *tps = i2c_get_clientdata(client);
+	struct i2c_msg msgs[2];
+	const u8 *reg_bytes = reg_buf;
+	u8 *val_bytes = val_buf;
+	const u8 page = reg_bytes[1];
+	u8 reg = reg_bytes[0];
+	int ret = 0;
+	int i;
+
+	if (tps->use_crc) {
+		/*
+		 * Auto-increment feature does not support CRC protocol.
+		 * Converts the bulk read operation into a series of single read operations.
+		 */
+		for (i = 0 ; ret == 0 && i < val_size ; i++)
+			ret = tps6594_i2c_reg_read_with_crc(client, page, reg + i, val_bytes + i);
+
+		return ret;
+	}
+
+	/* Write register: I2C address = I2C base address + Page index */
+	msgs[0].addr = client->addr + page;
+	msgs[0].flags = 0;
+	msgs[0].len = 1;
+	msgs[0].buf = &reg;
+
+	/* Read data */
+	msgs[1].addr = msgs[0].addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = val_size;
+	msgs[1].buf = val_bytes;
+
+	return tps6594_i2c_transfer(client->adapter, msgs, 2);
+}
+
+static int tps6594_i2c_write(void *context, const void *data, size_t count)
+{
+	struct i2c_client *client = context;
+	struct tps6594 *tps = i2c_get_clientdata(client);
+	struct i2c_msg msg;
+	const u8 *bytes = data;
+	u8 *buf;
+	const u8 page = bytes[1];
+	const u8 reg = bytes[0];
+	int ret = 0;
+	int i;
+
+	if (tps->use_crc) {
+		/*
+		 * Auto-increment feature does not support CRC protocol.
+		 * Converts the bulk write operation into a series of single write operations.
+		 */
+		for (i = 0 ; ret == 0 && i < count - 2 ; i++)
+			ret = tps6594_i2c_reg_write_with_crc(client, page, reg + i, bytes[i + 2]);
+
+		return ret;
+	}
+
+	/* Setup buffer: page byte is not sent */
+	buf = kzalloc(--count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	buf[0] = reg;
+	for (i = 0 ; i < count - 1 ; i++)
+		buf[i + 1] = bytes[i + 2];
+
+	/* Write register and data: I2C address = I2C base address + Page index */
+	msg.addr = client->addr + page;
+	msg.flags = client->flags & I2C_M_TEN;
+	msg.len = count;
+	msg.buf = buf;
+
+	ret = tps6594_i2c_transfer(client->adapter, &msg, 1);
+
+	kfree(buf);
+	return ret;
+}
+
+static const struct regmap_config tps6594_i2c_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
+	.volatile_reg = tps6594_is_volatile_reg,
+	.read = tps6594_i2c_read,
+	.write = tps6594_i2c_write,
+};
+
+static const struct of_device_id tps6594_i2c_of_match_table[] = {
+	{ .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, },
+	{ .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, },
+	{ .compatible = "ti,lp8764-q1",  .data = (void *)LP8764,  },
+	{}
+};
+MODULE_DEVICE_TABLE(of, tps6594_i2c_of_match_table);
+
+static int tps6594_i2c_probe(struct i2c_client *client)
+{
+	struct device *dev = &client->dev;
+	struct tps6594 *tps;
+	const struct of_device_id *match;
+
+	tps = devm_kzalloc(dev, sizeof(*tps), GFP_KERNEL);
+	if (!tps)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, tps);
+
+	tps->dev = dev;
+	tps->reg = client->addr;
+	tps->irq = client->irq;
+
+	tps->regmap = devm_regmap_init(dev, NULL, client, &tps6594_i2c_regmap_config);
+	if (IS_ERR(tps->regmap))
+		return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
+
+	match = of_match_device(tps6594_i2c_of_match_table, dev);
+	if (!match)
+		return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n");
+	tps->chip_id = (unsigned long)match->data;
+
+	crc8_populate_msb(tps6594_i2c_crc_table, TPS6594_CRC8_POLYNOMIAL);
+
+	return tps6594_device_init(tps, enable_crc);
+}
+
+static struct i2c_driver tps6594_i2c_driver = {
+	.driver	= {
+		.name = "tps6594",
+		.of_match_table = tps6594_i2c_of_match_table,
+	},
+	.probe_new = tps6594_i2c_probe,
+};
+module_i2c_driver(tps6594_i2c_driver);
+
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 I2C Interface Driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/mfd/tps6594-spi.c b/drivers/mfd/tps6594-spi.c
--- a/drivers/mfd/tps6594-spi.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/mfd/tps6594-spi.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SPI access driver for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/crc8.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include <linux/mfd/tps6594.h>
+
+#define TPS6594_SPI_PAGE_SHIFT	5
+#define TPS6594_SPI_READ_BIT	BIT(4)
+
+static bool enable_crc;
+module_param(enable_crc, bool, 0444);
+MODULE_PARM_DESC(enable_crc, "Enable CRC feature for SPI interface");
+
+DECLARE_CRC8_TABLE(tps6594_spi_crc_table);
+
+static int tps6594_spi_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+	struct spi_device *spi = context;
+	struct tps6594 *tps = spi_get_drvdata(spi);
+	u8 buf[4] = { 0 };
+	size_t count_rx = 1;
+	int ret;
+
+	buf[0] = reg;
+	buf[1] = TPS6594_REG_TO_PAGE(reg) << TPS6594_SPI_PAGE_SHIFT | TPS6594_SPI_READ_BIT;
+
+	if (tps->use_crc)
+		count_rx++;
+
+	ret = spi_write_then_read(spi, buf, 2, buf + 2, count_rx);
+	if (ret < 0)
+		return ret;
+
+	if (tps->use_crc && buf[3] != crc8(tps6594_spi_crc_table, buf, 3, CRC8_INIT_VALUE))
+		return -EIO;
+
+	*val = buf[2];
+
+	return 0;
+}
+
+static int tps6594_spi_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+	struct spi_device *spi = context;
+	struct tps6594 *tps = spi_get_drvdata(spi);
+	u8 buf[4] = { 0 };
+	size_t count = 3;
+
+	buf[0] = reg;
+	buf[1] = TPS6594_REG_TO_PAGE(reg) << TPS6594_SPI_PAGE_SHIFT;
+	buf[2] = val;
+
+	if (tps->use_crc)
+		buf[3] = crc8(tps6594_spi_crc_table, buf, count++, CRC8_INIT_VALUE);
+
+	return spi_write(spi, buf, count);
+}
+
+static const struct regmap_config tps6594_spi_regmap_config = {
+	.reg_bits = 16,
+	.val_bits = 8,
+	.max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
+	.volatile_reg = tps6594_is_volatile_reg,
+	.reg_read = tps6594_spi_reg_read,
+	.reg_write = tps6594_spi_reg_write,
+	.use_single_read = true,
+	.use_single_write = true,
+};
+
+static const struct of_device_id tps6594_spi_of_match_table[] = {
+	{ .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, },
+	{ .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, },
+	{ .compatible = "ti,lp8764-q1",  .data = (void *)LP8764,  },
+	{}
+};
+MODULE_DEVICE_TABLE(of, tps6594_spi_of_match_table);
+
+static int tps6594_spi_probe(struct spi_device *spi)
+{
+	struct device *dev = &spi->dev;
+	struct tps6594 *tps;
+	const struct of_device_id *match;
+
+	tps = devm_kzalloc(dev, sizeof(*tps), GFP_KERNEL);
+	if (!tps)
+		return -ENOMEM;
+
+	spi_set_drvdata(spi, tps);
+
+	tps->dev = dev;
+	tps->reg = spi->chip_select;
+	tps->irq = spi->irq;
+
+	tps->regmap = devm_regmap_init(dev, NULL, spi, &tps6594_spi_regmap_config);
+	if (IS_ERR(tps->regmap))
+		return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
+
+	match = of_match_device(tps6594_spi_of_match_table, dev);
+	if (!match)
+		return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n");
+	tps->chip_id = (unsigned long)match->data;
+
+	crc8_populate_msb(tps6594_spi_crc_table, TPS6594_CRC8_POLYNOMIAL);
+
+	return tps6594_device_init(tps, enable_crc);
+}
+
+static struct spi_driver tps6594_spi_driver = {
+	.driver	= {
+		.name = "tps6594",
+		.of_match_table = tps6594_spi_of_match_table,
+	},
+	.probe = tps6594_spi_probe,
+};
+module_spi_driver(tps6594_spi_driver);
+
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 SPI Interface Driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/misc/dma-buf-phys.c b/drivers/misc/dma-buf-phys.c
--- a/drivers/misc/dma-buf-phys.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/misc/dma-buf-phys.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * DMA-BUF contiguous buffer physical address user-space exporter
+ *
+ * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *	Andrew Davis <afd@ti.com>
+ */
+
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include <uapi/linux/dma_buf_phys.h>
+
+#define DEVICE_NAME "dma-buf-phys"
+
+struct dma_buf_phys_priv {
+	struct miscdevice miscdev;
+};
+
+struct dma_buf_phys_file {
+	struct device *dev;
+	struct dma_buf *dma_buf;
+	struct dma_buf_attachment *attachment;
+	struct sg_table *sgt;
+};
+
+static int dma_buf_phys_open(struct inode *inode, struct file *file)
+{
+	struct miscdevice *miscdev = file->private_data;
+	struct device *dev = miscdev->this_device;
+	struct dma_buf_phys_file *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	priv->dev = dev;
+	file->private_data = (void *)priv;
+
+	return 0;
+}
+
+static int dma_buf_phys_release(struct inode *inode, struct file *file)
+{
+	struct dma_buf_phys_file *priv = file->private_data;
+
+	if (priv->attachment && priv->sgt)
+		dma_buf_unmap_attachment(priv->attachment, priv->sgt, DMA_BIDIRECTIONAL);
+	if (priv->dma_buf && priv->attachment)
+		dma_buf_detach(priv->dma_buf, priv->attachment);
+	if (priv->dma_buf)
+		dma_buf_put(priv->dma_buf);
+
+	kfree(priv);
+
+	return 0;
+}
+
+static int dma_buf_phys_convert(struct dma_buf_phys_file *priv, int fd, u64 *phys)
+{
+	struct device *dev = priv->dev;
+	struct dma_buf *dma_buf;
+	struct dma_buf_attachment *attachment;
+	struct sg_table *sgt;
+	dma_addr_t dma_addr;
+	int ret;
+
+	dma_buf = dma_buf_get(fd);
+	if (IS_ERR(dma_buf))
+		return PTR_ERR(dma_buf);
+
+	/* Attach as the parent device as it will have the correct DMA ops set */
+	attachment = dma_buf_attach(dma_buf, dev->parent);
+	if (IS_ERR(attachment)) {
+		ret = PTR_ERR(attachment);
+		goto fail_put;
+	}
+
+	sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL);
+	if (IS_ERR(sgt)) {
+		ret = PTR_ERR(sgt);
+		goto fail_detach;
+	}
+
+	/* Without PAT only physically contiguous buffers can be supported */
+	if (sgt->orig_nents != 1) {
+		dev_err(dev, "DMA-BUF not contiguous\n");
+		ret = -EINVAL;
+		goto fail_unmap;
+	}
+
+	dma_addr = sg_dma_address(sgt->sgl);
+
+	*phys = dma_addr;
+
+	priv->dma_buf = dma_buf;
+	priv->attachment = attachment;
+	priv->sgt = sgt;
+
+	return 0;
+
+fail_unmap:
+	dma_buf_unmap_attachment(attachment, sgt, DMA_BIDIRECTIONAL);
+fail_detach:
+	dma_buf_detach(dma_buf, attachment);
+fail_put:
+	dma_buf_put(dma_buf);
+
+	return ret;
+}
+
+static long dma_buf_phys_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct dma_buf_phys_file *priv = file->private_data;
+
+	switch (cmd) {
+	case DMA_BUF_PHYS_IOC_CONVERT:
+	{
+		struct dma_buf_phys_data data;
+		int ret;
+
+		/*
+		 * TODO: this should likely be properly serialized, but I
+		 * see no reason this file would ever need to be shared.
+		 */
+		/* one attachment per file */
+		if (priv->dma_buf)
+			return -EFAULT;
+
+		if (copy_from_user(&data, (void __user *)arg, _IOC_SIZE(cmd)))
+			return -EFAULT;
+
+		ret = dma_buf_phys_convert(priv, data.fd, &data.phys);
+		if (ret)
+			return ret;
+
+		if (copy_to_user((void __user *)arg, &data, _IOC_SIZE(cmd)))
+			return -EFAULT;
+
+		break;
+	}
+	default:
+		return -ENOTTY;
+	}
+
+	return 0;
+}
+
+static const struct file_operations dma_buf_phys_fops = {
+	.owner = THIS_MODULE,
+	.open = dma_buf_phys_open,
+	.release = dma_buf_phys_release,
+	.unlocked_ioctl = dma_buf_phys_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl	= dma_buf_phys_ioctl,
+#endif
+};
+
+static int dma_buf_phys_probe(struct platform_device *pdev)
+{
+	struct dma_buf_phys_priv *priv;
+	struct device *dev = &pdev->dev;
+	int err;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	dev_set_drvdata(dev, priv);
+
+	/* No DMA restrictions */
+	dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(64));
+	dma_set_max_seg_size(dev, UINT_MAX);
+
+	priv->miscdev.minor = MISC_DYNAMIC_MINOR;
+	priv->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "%s", DEVICE_NAME);
+	priv->miscdev.fops = &dma_buf_phys_fops;
+	priv->miscdev.parent = dev;
+	err = misc_register(&priv->miscdev);
+	if (err) {
+		dev_err(dev, "unable to register DMA-BUF to Phys misc device\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int dma_buf_phys_remove(struct platform_device *pdev)
+{
+	struct dma_buf_phys_priv *priv = dev_get_drvdata(&pdev->dev);
+
+	misc_deregister(&priv->miscdev);
+
+	return 0;
+}
+
+static const struct of_device_id dma_buf_phys_of_match[] = {
+	{ .compatible = "ti,dma-buf-phys", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dma_buf_phys_of_match);
+
+static struct platform_driver dma_buf_phys_driver = {
+	.probe = dma_buf_phys_probe,
+	.remove = dma_buf_phys_remove,
+	.driver = {
+		.name = "dma_buf_phys",
+		.of_match_table = dma_buf_phys_of_match,
+	}
+};
+module_platform_driver(dma_buf_phys_driver);
+
+MODULE_AUTHOR("Andrew Davis <afd@ti.com>");
+MODULE_DESCRIPTION("DMA-BUF contiguous buffer physical address user-space exporter");
+MODULE_LICENSE("GPL v2");
diff -Naur --no-dereference a/drivers/misc/Kconfig b/drivers/misc/Kconfig
--- a/drivers/misc/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/misc/Kconfig	2024-01-28 14:01:31.248353800 -0500
@@ -426,6 +426,13 @@
 config SRAM_EXEC
 	bool
 
+config SRAM_DMA_HEAP
+	bool "Export on-chip SRAM pools using DMA-Heaps"
+	depends on DMABUF_HEAPS && SRAM
+	help
+	  This driver allows the export of on-chip SRAM marked as both pool
+	  and exportable to userspace using the DMA-Heaps interface.
+
 config DW_XDATA_PCIE
 	depends on PCI
 	tristate "Synopsys DesignWare xData PCIe driver"
@@ -497,6 +504,36 @@
 
 	  If you do not intend to run this kernel as a guest, say N.
 
+config DMA_BUF_PHYS
+	tristate "DMA-BUF physical address user-space exporter"
+	depends on DMA_SHARED_BUFFER
+	default y
+	help
+	  Exports CPU physical address of DMA-BUF to user-space.
+
+config TPS6594_ESM
+	tristate "TI TPS6594 Error Signal Monitor support"
+	depends on MFD_TPS6594
+	default MFD_TPS6594
+	help
+	  Support ESM (Error Signal Monitor) on TPS6594 PMIC devices.
+	  ESM is used typically to reboot the board in error condition.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called tps6594-esm.
+
+config TPS6594_PFSM
+	tristate "TI TPS6594 Pre-configurable Finite State Machine support"
+	depends on MFD_TPS6594
+	default MFD_TPS6594
+	help
+	  Support PFSM (Pre-configurable Finite State Machine) on TPS6594 PMIC devices.
+	  These devices integrate a finite state machine engine, which manages the state
+	  of the device during operating state transition.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called tps6594-pfsm.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
diff -Naur --no-dereference a/drivers/misc/Makefile b/drivers/misc/Makefile
--- a/drivers/misc/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/misc/Makefile	2024-01-28 14:01:31.248353800 -0500
@@ -45,6 +45,7 @@
 obj-$(CONFIG_LATTICE_ECP3_CONFIG)	+= lattice-ecp3-config.o
 obj-$(CONFIG_SRAM)		+= sram.o
 obj-$(CONFIG_SRAM_EXEC)		+= sram-exec.o
+obj-$(CONFIG_SRAM_DMA_HEAP)	+= sram-dma-heap.o
 obj-$(CONFIG_GENWQE)		+= genwqe/
 obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_CXL_BASE)		+= cxl/
@@ -62,3 +63,6 @@
 obj-$(CONFIG_OPEN_DICE)		+= open-dice.o
 obj-$(CONFIG_GP_PCI1XXXX)	+= mchp_pci1xxxx/
 obj-$(CONFIG_VCPU_STALL_DETECTOR)	+= vcpu_stall_detector.o
+obj-$(CONFIG_DMA_BUF_PHYS)	+= dma-buf-phys.o
+obj-$(CONFIG_TPS6594_ESM)	+= tps6594-esm.o
+obj-$(CONFIG_TPS6594_PFSM)	+= tps6594-pfsm.o
diff -Naur --no-dereference a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
--- a/drivers/misc/pci_endpoint_test.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/misc/pci_endpoint_test.c	2024-01-28 14:01:31.248353800 -0500
@@ -83,6 +83,9 @@
 #define PCI_DEVICE_ID_RENESAS_R8A774E1		0x0025
 #define PCI_DEVICE_ID_RENESAS_R8A779F0		0x0031
 
+#define is_j721e_pci_dev(pdev)         \
+		((pdev)->device == PCI_DEVICE_ID_TI_J721E)
+
 static DEFINE_IDA(pci_endpoint_test_ida);
 
 #define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
@@ -840,9 +843,11 @@
 
 	pci_set_master(pdev);
 
-	if (!pci_endpoint_test_alloc_irq_vectors(test, irq_type)) {
-		err = -EINVAL;
-		goto err_disable_irq;
+	if (!(is_am654_pci_dev(pdev) || is_j721e_pci_dev(pdev))) {
+		if (!pci_endpoint_test_alloc_irq_vectors(test, irq_type)) {
+			err = -EINVAL;
+			goto err_disable_irq;
+		}
 	}
 
 	for (bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
@@ -880,9 +885,11 @@
 		goto err_ida_remove;
 	}
 
-	if (!pci_endpoint_test_request_irq(test)) {
-		err = -EINVAL;
-		goto err_kfree_test_name;
+	if (!(is_am654_pci_dev(pdev) || is_j721e_pci_dev(pdev))) {
+		if (!pci_endpoint_test_request_irq(test)) {
+			err = -EINVAL;
+			goto err_kfree_test_name;
+		}
 	}
 
 	misc_device = &test->miscdev;
diff -Naur --no-dereference a/drivers/misc/sram.c b/drivers/misc/sram.c
--- a/drivers/misc/sram.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/misc/sram.c	2024-01-28 14:01:31.248353800 -0500
@@ -120,6 +120,12 @@
 		ret = sram_add_pool(sram, block, start, part);
 		if (ret)
 			return ret;
+
+		if (block->export) {
+			ret = sram_add_dma_heap(sram, block, start, part);
+			if (ret)
+				return ret;
+		}
 	}
 	if (block->export) {
 		ret = sram_add_export(sram, block, start, part);
diff -Naur --no-dereference a/drivers/misc/sram-dma-heap.c b/drivers/misc/sram-dma-heap.c
--- a/drivers/misc/sram-dma-heap.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/misc/sram-dma-heap.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SRAM DMA-Heap userspace exporter
+ *
+ * Copyright (C) 2019-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *	Andrew Davis <afd@ti.com>
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/err.h>
+#include <linux/genalloc.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-heap.h>
+
+#include "sram.h"
+
+struct sram_dma_heap {
+	struct dma_heap *heap;
+	struct gen_pool *pool;
+};
+
+struct sram_dma_heap_buffer {
+	struct gen_pool *pool;
+	struct list_head attachments;
+	struct mutex attachments_lock;
+	unsigned long len;
+	void *vaddr;
+	phys_addr_t paddr;
+};
+
+struct dma_heap_attachment {
+	struct device *dev;
+	struct sg_table *table;
+	struct list_head list;
+};
+
+static int dma_heap_attach(struct dma_buf *dmabuf,
+			   struct dma_buf_attachment *attachment)
+{
+	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
+	struct dma_heap_attachment *a;
+	struct sg_table *table;
+
+	a = kzalloc(sizeof(*a), GFP_KERNEL);
+	if (!a)
+		return -ENOMEM;
+
+	table = kmalloc(sizeof(*table), GFP_KERNEL);
+	if (!table) {
+		kfree(a);
+		return -ENOMEM;
+	}
+	if (sg_alloc_table(table, 1, GFP_KERNEL)) {
+		kfree(table);
+		kfree(a);
+		return -ENOMEM;
+	}
+	sg_set_page(table->sgl, pfn_to_page(PFN_DOWN(buffer->paddr)), buffer->len, 0);
+
+	a->table = table;
+	a->dev = attachment->dev;
+	INIT_LIST_HEAD(&a->list);
+
+	attachment->priv = a;
+
+	mutex_lock(&buffer->attachments_lock);
+	list_add(&a->list, &buffer->attachments);
+	mutex_unlock(&buffer->attachments_lock);
+
+	return 0;
+}
+
+static void dma_heap_detatch(struct dma_buf *dmabuf,
+			     struct dma_buf_attachment *attachment)
+{
+	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
+	struct dma_heap_attachment *a = attachment->priv;
+
+	mutex_lock(&buffer->attachments_lock);
+	list_del(&a->list);
+	mutex_unlock(&buffer->attachments_lock);
+
+	sg_free_table(a->table);
+	kfree(a->table);
+	kfree(a);
+}
+
+static struct sg_table *dma_heap_map_dma_buf(struct dma_buf_attachment *attachment,
+					     enum dma_data_direction direction)
+{
+	struct dma_heap_attachment *a = attachment->priv;
+	struct sg_table *table = a->table;
+
+	/*
+	 * As this heap is backed by uncached SRAM memory we do not need to
+	 * perform any sync operations on the buffer before allowing device
+	 * domain access. For this reason we use SKIP_CPU_SYNC and also do
+	 * not use or provide begin/end_cpu_access() dma-buf functions.
+	 */
+	if (!dma_map_sg_attrs(attachment->dev, table->sgl, table->nents,
+			      direction, DMA_ATTR_SKIP_CPU_SYNC))
+		return ERR_PTR(-ENOMEM);
+
+	return table;
+}
+
+static void dma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
+				   struct sg_table *table,
+				   enum dma_data_direction direction)
+{
+	dma_unmap_sg_attrs(attachment->dev, table->sgl, table->nents,
+			   direction, DMA_ATTR_SKIP_CPU_SYNC);
+}
+
+static void dma_heap_dma_buf_release(struct dma_buf *dmabuf)
+{
+	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
+
+	gen_pool_free(buffer->pool, (unsigned long)buffer->vaddr, buffer->len);
+	kfree(buffer);
+}
+
+static int dma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+{
+	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
+	int ret;
+
+	/* SRAM mappings are not cached */
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+	ret = vm_iomap_memory(vma, buffer->paddr, buffer->len);
+	if (ret)
+		pr_err("Could not map buffer to userspace\n");
+
+	return ret;
+}
+
+static int dma_heap_vmap(struct dma_buf *dmabuf, struct iosys_map *map)
+{
+	struct sram_dma_heap_buffer *buffer = dmabuf->priv;
+
+	iosys_map_set_vaddr(map, buffer->vaddr);
+
+	return 0;
+}
+
+static const struct dma_buf_ops sram_dma_heap_buf_ops = {
+	.attach = dma_heap_attach,
+	.detach = dma_heap_detatch,
+	.map_dma_buf = dma_heap_map_dma_buf,
+	.unmap_dma_buf = dma_heap_unmap_dma_buf,
+	.release = dma_heap_dma_buf_release,
+	.mmap = dma_heap_mmap,
+	.vmap = dma_heap_vmap,
+};
+
+static struct dma_buf *sram_dma_heap_allocate(struct dma_heap *heap,
+					      unsigned long len,
+					      unsigned long fd_flags,
+					      unsigned long heap_flags)
+{
+	struct sram_dma_heap *sram_dma_heap = dma_heap_get_drvdata(heap);
+	struct sram_dma_heap_buffer *buffer;
+
+	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+	struct dma_buf *dmabuf;
+	int ret;
+
+	buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+	if (!buffer)
+		return ERR_PTR(-ENOMEM);
+	buffer->pool = sram_dma_heap->pool;
+	INIT_LIST_HEAD(&buffer->attachments);
+	mutex_init(&buffer->attachments_lock);
+	buffer->len = len;
+
+	buffer->vaddr = (void *)gen_pool_alloc(buffer->pool, buffer->len);
+	if (!buffer->vaddr) {
+		ret = -ENOMEM;
+		goto free_buffer;
+	}
+
+	buffer->paddr = gen_pool_virt_to_phys(buffer->pool, (unsigned long)buffer->vaddr);
+	if (buffer->paddr == -1) {
+		ret = -ENOMEM;
+		goto free_pool;
+	}
+
+	/* create the dmabuf */
+	exp_info.exp_name = dma_heap_get_name(heap);
+	exp_info.ops = &sram_dma_heap_buf_ops;
+	exp_info.size = buffer->len;
+	exp_info.flags = fd_flags;
+	exp_info.priv = buffer;
+	dmabuf = dma_buf_export(&exp_info);
+	if (IS_ERR(dmabuf)) {
+		ret = PTR_ERR(dmabuf);
+		goto free_pool;
+	}
+
+	return dmabuf;
+
+free_pool:
+	gen_pool_free(buffer->pool, (unsigned long)buffer->vaddr, buffer->len);
+free_buffer:
+	kfree(buffer);
+
+	return ERR_PTR(ret);
+}
+
+static struct dma_heap_ops sram_dma_heap_ops = {
+	.allocate = sram_dma_heap_allocate,
+};
+
+int sram_add_dma_heap(struct sram_dev *sram,
+		      struct sram_reserve *block,
+		      phys_addr_t start,
+		      struct sram_partition *part)
+{
+	struct sram_dma_heap *sram_dma_heap;
+	struct dma_heap_export_info exp_info;
+
+	dev_info(sram->dev, "Exporting SRAM Heap '%s'\n", block->label);
+
+	sram_dma_heap = kzalloc(sizeof(*sram_dma_heap), GFP_KERNEL);
+	if (!sram_dma_heap)
+		return -ENOMEM;
+	sram_dma_heap->pool = part->pool;
+
+	exp_info.name = kasprintf(GFP_KERNEL, "sram_%s", block->label);
+	exp_info.ops = &sram_dma_heap_ops;
+	exp_info.priv = sram_dma_heap;
+	sram_dma_heap->heap = dma_heap_add(&exp_info);
+	if (IS_ERR(sram_dma_heap->heap)) {
+		int ret = PTR_ERR(sram_dma_heap->heap);
+		kfree(sram_dma_heap);
+		return ret;
+	}
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/misc/sram.h b/drivers/misc/sram.h
--- a/drivers/misc/sram.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/misc/sram.h	2024-01-28 14:01:31.248353800 -0500
@@ -61,4 +61,20 @@
 	return -ENODEV;
 }
 #endif /* CONFIG_SRAM_EXEC */
+
+#ifdef CONFIG_SRAM_DMA_HEAP
+int sram_add_dma_heap(struct sram_dev *sram,
+		      struct sram_reserve *block,
+		      phys_addr_t start,
+		      struct sram_partition *part);
+#else
+static inline int sram_add_dma_heap(struct sram_dev *sram,
+				    struct sram_reserve *block,
+				    phys_addr_t start,
+				    struct sram_partition *part)
+{
+	return 0;
+}
+#endif /* CONFIG_SRAM_DMA_HEAP */
+
 #endif /* __SRAM_H */
diff -Naur --no-dereference a/drivers/misc/tps6594-esm.c b/drivers/misc/tps6594-esm.c
--- a/drivers/misc/tps6594-esm.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/misc/tps6594-esm.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ESM (Error Signal Monitor) driver for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/tps6594.h>
+
+#define TPS6594_DEV_REV_1 0x08
+
+static irqreturn_t tps6594_esm_isr(int irq, void *dev_id)
+{
+	struct platform_device *pdev = dev_id;
+	int i;
+
+	for (i = 0 ; i < pdev->num_resources ; i++) {
+		if (irq == platform_get_irq_byname(pdev, pdev->resource[i].name)) {
+			dev_err(pdev->dev.parent, "%s error detected\n", pdev->resource[i].name);
+			return IRQ_HANDLED;
+		}
+	}
+
+	return IRQ_NONE;
+}
+
+static int tps6594_esm_probe(struct platform_device *pdev)
+{
+	struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+	struct device *dev = &pdev->dev;
+	unsigned int rev;
+	int irq;
+	int ret;
+	int i;
+
+	/*
+	 * Because of a bug on PMIC GPIO9 in revision 1, the GPIO3
+	 * (which is used for the SoC ESM function) is used to power
+	 * the load switch.
+	 * Check the version and return an error in case of revision 1.
+	 */
+	ret = regmap_read(tps->regmap, TPS6594_REG_DEV_REV, &rev);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Failed to read PMIC revision\n");
+	if (rev == TPS6594_DEV_REV_1)
+		return dev_err_probe(dev, -ENODEV,
+				     "ESM not supported for revision 1 PMIC\n");
+
+	for (i = 0; i < pdev->num_resources; i++) {
+		irq = platform_get_irq_byname(pdev, pdev->resource[i].name);
+		if (irq < 0)
+			return dev_err_probe(dev, irq, "Failed to get %s irq\n",
+					     pdev->resource[i].name);
+
+		ret = devm_request_threaded_irq(dev, irq, NULL,
+						tps6594_esm_isr, IRQF_ONESHOT,
+						pdev->resource[i].name, pdev);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to request irq\n");
+	}
+
+	ret = regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_MODE_CFG,
+			      TPS6594_BIT_ESM_SOC_EN | TPS6594_BIT_ESM_SOC_ENDRV);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to configure ESM\n");
+
+	ret = regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
+			      TPS6594_BIT_ESM_SOC_START);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to start ESM\n");
+
+	pm_runtime_enable(dev);
+	pm_runtime_get_sync(dev);
+
+	return 0;
+}
+
+static int tps6594_esm_remove(struct platform_device *pdev)
+{
+	struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
+				TPS6594_BIT_ESM_SOC_START);
+	if (ret) {
+		dev_err(dev, "Failed to stop ESM\n");
+		goto out;
+	}
+
+	ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_MODE_CFG,
+				TPS6594_BIT_ESM_SOC_EN | TPS6594_BIT_ESM_SOC_ENDRV);
+	if (ret)
+		dev_err(dev, "Failed to unconfigure ESM\n");
+
+out:
+	pm_runtime_put_sync(dev);
+	pm_runtime_disable(dev);
+
+	return ret;
+}
+
+static int tps6594_esm_suspend(struct device *dev)
+{
+	struct tps6594 *tps = dev_get_drvdata(dev->parent);
+	int ret;
+
+	ret = regmap_clear_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
+				TPS6594_BIT_ESM_SOC_START);
+
+	pm_runtime_put_sync(dev);
+
+	return ret;
+}
+
+static int tps6594_esm_resume(struct device *dev)
+{
+	struct tps6594 *tps = dev_get_drvdata(dev->parent);
+
+	pm_runtime_get_sync(dev);
+
+	return regmap_set_bits(tps->regmap, TPS6594_REG_ESM_SOC_START_REG,
+			       TPS6594_BIT_ESM_SOC_START);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(tps6594_esm_pm_ops, tps6594_esm_suspend, tps6594_esm_resume);
+
+static struct platform_driver tps6594_esm_driver = {
+	.driver	= {
+		.name = "tps6594-esm",
+		.pm = pm_sleep_ptr(&tps6594_esm_pm_ops),
+	},
+	.probe = tps6594_esm_probe,
+	.remove = tps6594_esm_remove,
+};
+
+module_platform_driver(tps6594_esm_driver);
+
+MODULE_ALIAS("platform:tps6594-esm");
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 Error Signal Monitor Driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/misc/tps6594-pfsm.c b/drivers/misc/tps6594-pfsm.c
--- a/drivers/misc/tps6594-pfsm.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/misc/tps6594-pfsm.c	2024-01-28 14:01:31.248353800 -0500
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PFSM (Pre-configurable Finite State Machine) driver for TI TPS6594/TPS6593/LP8764 PMICs
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/ioctl.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <linux/mfd/tps6594.h>
+
+#include <linux/tps6594_pfsm.h>
+
+#define TPS6594_STARTUP_DEST_MCU_ONLY_VAL 2
+#define TPS6594_STARTUP_DEST_ACTIVE_VAL   3
+#define TPS6594_STARTUP_DEST_SHIFT	  5
+#define TPS6594_STARTUP_DEST_MCU_ONLY	  (TPS6594_STARTUP_DEST_MCU_ONLY_VAL \
+					   << TPS6594_STARTUP_DEST_SHIFT)
+#define TPS6594_STARTUP_DEST_ACTIVE	  (TPS6594_STARTUP_DEST_ACTIVE_VAL \
+					   << TPS6594_STARTUP_DEST_SHIFT)
+
+/*
+ * To update the PMIC firmware, the user must be able to access
+ * page 0 (user registers) and page 1 (NVM control and configuration).
+ */
+#define TPS6594_PMIC_MAX_POS 0x200
+
+#define TPS6594_FILE_TO_PFSM(f) container_of((f)->private_data, struct tps6594_pfsm, miscdev)
+
+/**
+ * struct tps6594_pfsm - device private data structure
+ *
+ * @miscdev: misc device infos
+ * @regmap:  regmap for accessing the device registers
+ */
+struct tps6594_pfsm {
+	struct miscdevice miscdev;
+	struct regmap *regmap;
+};
+
+static ssize_t tps6594_pfsm_read(struct file *f, char __user *buf,
+				 size_t count, loff_t *ppos)
+{
+	struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f);
+	loff_t pos = *ppos;
+	unsigned int val;
+	int ret;
+	int i;
+
+	if (pos < 0)
+		return -EINVAL;
+	if (pos >= TPS6594_PMIC_MAX_POS)
+		return 0;
+	if (count > TPS6594_PMIC_MAX_POS - pos)
+		count = TPS6594_PMIC_MAX_POS - pos;
+
+	for (i = 0 ; i < count ; i++) {
+		ret = regmap_read(pfsm->regmap, pos + i, &val);
+		if (ret)
+			return ret;
+
+		if (put_user(val, buf + i))
+			return -EFAULT;
+	}
+
+	*ppos = pos + count;
+
+	return count;
+}
+
+static ssize_t tps6594_pfsm_write(struct file *f, const char __user *buf,
+				  size_t count, loff_t *ppos)
+{
+	struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f);
+	loff_t pos = *ppos;
+	char val;
+	int ret;
+	int i;
+
+	if (pos < 0)
+		return -EINVAL;
+	if (pos >= TPS6594_PMIC_MAX_POS || !count)
+		return 0;
+	if (count > TPS6594_PMIC_MAX_POS - pos)
+		count = TPS6594_PMIC_MAX_POS - pos;
+
+	for (i = 0 ; i < count ; i++) {
+		if (get_user(val, buf + i))
+			return -EFAULT;
+
+		ret = regmap_write(pfsm->regmap, pos + i, val);
+		if (ret)
+			return ret;
+	}
+
+	*ppos = pos + count;
+
+	return count;
+}
+
+static int tps6594_pfsm_configure_ret_trig(struct regmap *regmap, u8 gpio_ret, u8 ddr_ret)
+{
+	int ret;
+
+	if (gpio_ret)
+		ret = regmap_set_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+				      TPS6594_BIT_TRIGGER_I2C(5) | TPS6594_BIT_TRIGGER_I2C(6));
+	else
+		ret = regmap_clear_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+					TPS6594_BIT_TRIGGER_I2C(5) | TPS6594_BIT_TRIGGER_I2C(6));
+	if (ret)
+		return ret;
+
+	if (ddr_ret)
+		ret = regmap_set_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+				      TPS6594_BIT_TRIGGER_I2C(7));
+	else
+		ret = regmap_clear_bits(regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+					TPS6594_BIT_TRIGGER_I2C(7));
+
+	return ret;
+}
+
+static long tps6594_pfsm_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	struct tps6594_pfsm *pfsm = TPS6594_FILE_TO_PFSM(f);
+	struct pmic_state_opt state_opt;
+	void __user *argp = (void __user *)arg;
+	int ret = -ENOIOCTLCMD;
+
+	switch (cmd) {
+	case PMIC_GOTO_STANDBY:
+		/* Disable LP mode */
+		ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+					TPS6594_BIT_LP_STANDBY_SEL);
+		if (ret)
+			return ret;
+
+		/* Force trigger */
+		ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+					TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0));
+		break;
+	case PMIC_GOTO_LP_STANDBY:
+		/* Enable LP mode */
+		ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+				      TPS6594_BIT_LP_STANDBY_SEL);
+		if (ret)
+			return ret;
+
+		/* Force trigger */
+		ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+					TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0));
+		break;
+	case PMIC_UPDATE_PGM:
+		/* Force trigger */
+		ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_FSM_I2C_TRIGGERS,
+					TPS6594_BIT_TRIGGER_I2C(3), TPS6594_BIT_TRIGGER_I2C(3));
+		break;
+	case PMIC_SET_ACTIVE_STATE:
+		/* Modify NSLEEP1-2 bits */
+		ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+				      TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B);
+		break;
+	case PMIC_SET_MCU_ONLY_STATE:
+		if (copy_from_user(&state_opt, argp, sizeof(state_opt)))
+			return -EFAULT;
+
+		/* Configure retention triggers */
+		ret = tps6594_pfsm_configure_ret_trig(pfsm->regmap, state_opt.gpio_retention,
+						      state_opt.ddr_retention);
+		if (ret)
+			return ret;
+
+		/* Modify NSLEEP1-2 bits */
+		ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+					TPS6594_BIT_NSLEEP1B);
+		if (ret)
+			return ret;
+
+		ret = regmap_set_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+				      TPS6594_BIT_NSLEEP2B);
+		break;
+	case PMIC_SET_RETENTION_STATE:
+		if (copy_from_user(&state_opt, argp, sizeof(state_opt)))
+			return -EFAULT;
+
+		/* Configure wake-up destination */
+		if (state_opt.mcu_only_startup_dest)
+			ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+						TPS6594_MASK_STARTUP_DEST,
+						TPS6594_STARTUP_DEST_MCU_ONLY);
+		else
+			ret = regmap_write_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2,
+						TPS6594_MASK_STARTUP_DEST,
+						TPS6594_STARTUP_DEST_ACTIVE);
+		if (ret)
+			return ret;
+
+		/* Configure retention triggers */
+		ret = tps6594_pfsm_configure_ret_trig(pfsm->regmap, state_opt.gpio_retention,
+						      state_opt.ddr_retention);
+		if (ret)
+			return ret;
+
+		/* Modify NSLEEP1-2 bits */
+		ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS,
+					TPS6594_BIT_NSLEEP2B);
+		break;
+	}
+
+	return ret;
+}
+
+static const struct file_operations tps6594_pfsm_fops = {
+	.owner		= THIS_MODULE,
+	.llseek		= generic_file_llseek,
+	.read		= tps6594_pfsm_read,
+	.write		= tps6594_pfsm_write,
+	.unlocked_ioctl	= tps6594_pfsm_ioctl,
+	.compat_ioctl   = compat_ptr_ioctl,
+};
+
+static irqreturn_t tps6594_pfsm_isr(int irq, void *dev_id)
+{
+	struct platform_device *pdev = dev_id;
+	int i;
+
+	for (i = 0 ; i < pdev->num_resources ; i++) {
+		if (irq == platform_get_irq_byname(pdev, pdev->resource[i].name)) {
+			dev_err(pdev->dev.parent, "%s event detected\n", pdev->resource[i].name);
+			return IRQ_HANDLED;
+		}
+	}
+
+	return IRQ_NONE;
+}
+
+static int tps6594_pfsm_probe(struct platform_device *pdev)
+{
+	struct tps6594_pfsm *pfsm;
+	struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+	struct device *dev = &pdev->dev;
+	int irq;
+	int ret;
+	int i;
+
+	pfsm = devm_kzalloc(dev, sizeof(struct tps6594_pfsm), GFP_KERNEL);
+	if (!pfsm)
+		return -ENOMEM;
+
+	pfsm->regmap = tps->regmap;
+
+	pfsm->miscdev.minor = MISC_DYNAMIC_MINOR;
+	pfsm->miscdev.name = devm_kasprintf(dev, GFP_KERNEL, "pfsm-%ld-0x%02x",
+					    tps->chip_id, tps->reg);
+	pfsm->miscdev.fops = &tps6594_pfsm_fops;
+	pfsm->miscdev.parent = dev->parent;
+
+	for (i = 0 ; i < pdev->num_resources ; i++) {
+		irq = platform_get_irq_byname(pdev, pdev->resource[i].name);
+		if (irq < 0)
+			return dev_err_probe(dev, irq, "Failed to get %s irq\n",
+					     pdev->resource[i].name);
+
+		ret = devm_request_threaded_irq(dev, irq, NULL,
+						tps6594_pfsm_isr, IRQF_ONESHOT,
+						pdev->resource[i].name, pdev);
+		if (ret)
+			return dev_err_probe(dev, ret, "Failed to request irq\n");
+	}
+
+	platform_set_drvdata(pdev, pfsm);
+
+	return misc_register(&pfsm->miscdev);
+}
+
+static int tps6594_pfsm_remove(struct platform_device *pdev)
+{
+	struct tps6594_pfsm *pfsm = platform_get_drvdata(pdev);
+
+	misc_deregister(&pfsm->miscdev);
+
+	return 0;
+}
+
+static struct platform_driver tps6594_pfsm_driver = {
+	.driver	= {
+		.name = "tps6594-pfsm",
+	},
+	.probe = tps6594_pfsm_probe,
+	.remove = tps6594_pfsm_remove,
+};
+
+module_platform_driver(tps6594_pfsm_driver);
+
+MODULE_ALIAS("platform:tps6594-pfsm");
+MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 Pre-configurable Finite State Machine Driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
--- a/drivers/mmc/host/sdhci_am654.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/mmc/host/sdhci_am654.c	2024-01-28 14:01:31.248353800 -0500
@@ -85,6 +85,7 @@
 #define DRIVER_STRENGTH_40_OHM	0x4
 
 #define CLOCK_TOO_SLOW_HZ	50000000
+#define SDHCI_AM654_AUTOSUSPEND_DELAY	-1
 
 /* Command Queue Host Controller Interface Base address */
 #define SDHCI_AM654_CQE_BASE_ADDR 0x200
@@ -310,6 +311,7 @@
 	struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);
 	unsigned char timing = host->mmc->ios.timing;
 	u32 otap_del_sel;
+	u32 itap_del_sel;
 	u32 mask, val;
 
 	/* Setup DLL Output TAP delay */
@@ -321,7 +323,14 @@
 	mask = OTAPDLYENA_MASK | OTAPDLYSEL_MASK;
 	val = (0x1 << OTAPDLYENA_SHIFT) |
 	      (otap_del_sel << OTAPDLYSEL_SHIFT);
+
+	itap_del_sel = sdhci_am654->itap_del_sel[timing];
+	mask |= ITAPDLYSEL_MASK | ITAPDLYENA_MASK;
+	val |= (1 << ITAPDLYENA_SHIFT) | (itap_del_sel << ITAPDLYSEL_SHIFT);
+	regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK,
+			   1 << ITAPCHGWIN_SHIFT);
 	regmap_update_bits(sdhci_am654->base, PHY_CTRL4, mask, val);
+	regmap_update_bits(sdhci_am654->base, PHY_CTRL4, ITAPCHGWIN_MASK, 0);
 
 	regmap_update_bits(sdhci_am654->base, PHY_CTRL5, CLKBUFSEL_MASK,
 			   sdhci_am654->clkbuf_sel);
@@ -389,8 +398,18 @@
 static int sdhci_am654_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
-	int err = sdhci_execute_tuning(mmc, opcode);
+	int err;
+	bool dcrc_was_enabled = false;
+
+	if (host->ier & SDHCI_INT_DATA_CRC) {
+		host->ier &= ~SDHCI_INT_DATA_CRC | ~SDHCI_INT_DATA_END_BIT |
+			     ~SDHCI_INT_DATA_TIMEOUT;
+		dcrc_was_enabled = true;
+		sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+		sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+	}
 
+	err = sdhci_execute_tuning(mmc, opcode);
 	if (err)
 		return err;
 	/*
@@ -399,6 +418,13 @@
 	 */
 	sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
 
+	/* Reenable forbidden interrupt */
+	if (dcrc_was_enabled) {
+		host->ier |= SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_TIMEOUT;
+		sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
+		sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
+	}
+
 	return 0;
 }
 
@@ -808,16 +834,10 @@
 
 	pltfm_host->clk = clk_xin;
 
-	/* Clocks are enabled using pm_runtime */
-	pm_runtime_enable(dev);
-	ret = pm_runtime_resume_and_get(dev);
-	if (ret)
-		goto pm_runtime_disable;
-
 	base = devm_platform_ioremap_resource(pdev, 1);
 	if (IS_ERR(base)) {
 		ret = PTR_ERR(base);
-		goto pm_runtime_put;
+		goto err_pltfm_free;
 	}
 
 	sdhci_am654->base = devm_regmap_init_mmio(dev, base,
@@ -825,31 +845,47 @@
 	if (IS_ERR(sdhci_am654->base)) {
 		dev_err(dev, "Failed to initialize regmap\n");
 		ret = PTR_ERR(sdhci_am654->base);
-		goto pm_runtime_put;
+		goto err_pltfm_free;
 	}
 
 	ret = sdhci_am654_get_of_property(pdev, sdhci_am654);
 	if (ret)
-		goto pm_runtime_put;
+		goto err_pltfm_free;
 
 	ret = mmc_of_parse(host->mmc);
 	if (ret) {
-		dev_err(dev, "parsing dt failed (%d)\n", ret);
-		goto pm_runtime_put;
+		dev_err_probe(dev, ret, "parsing dt failed\n");
+		goto err_pltfm_free;
 	}
 
 	host->mmc_host_ops.execute_tuning = sdhci_am654_execute_tuning;
 
+	pm_runtime_get_noresume(dev);
+	ret = pm_runtime_set_active(dev);
+	if (ret)
+		goto pm_put;
+	pm_runtime_enable(dev);
+	ret = clk_prepare_enable(pltfm_host->clk);
+	if (ret)
+		goto pm_disable;
+
 	ret = sdhci_am654_init(host);
 	if (ret)
-		goto pm_runtime_put;
+		goto clk_disable;
 
+	/* Setting up autosuspend */
+	pm_runtime_set_autosuspend_delay(dev, SDHCI_AM654_AUTOSUSPEND_DELAY);
+	pm_runtime_use_autosuspend(dev);
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
 	return 0;
 
-pm_runtime_put:
-	pm_runtime_put_sync(dev);
-pm_runtime_disable:
+clk_disable:
+	clk_disable_unprepare(pltfm_host->clk);
+pm_disable:
 	pm_runtime_disable(dev);
+pm_put:
+	pm_runtime_put_noidle(dev);
 err_pltfm_free:
 	sdhci_pltfm_free(pdev);
 	return ret;
@@ -858,23 +894,127 @@
 static int sdhci_am654_remove(struct platform_device *pdev)
 {
 	struct sdhci_host *host = platform_get_drvdata(pdev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	int ret;
 
-	sdhci_remove_host(host, true);
-	ret = pm_runtime_put_sync(&pdev->dev);
+	ret = pm_runtime_resume_and_get(&pdev->dev);
 	if (ret < 0)
 		return ret;
 
+	sdhci_remove_host(host, true);
+	clk_disable_unprepare(pltfm_host->clk);
 	pm_runtime_disable(&pdev->dev);
+	pm_runtime_put_noidle(&pdev->dev);
 	sdhci_pltfm_free(pdev);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int sdhci_am654_restore(struct sdhci_host *host)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_am654_data *sdhci_am654 = sdhci_pltfm_priv(pltfm_host);
+	u32 ctl_cfg_2 = 0;
+	u32 val;
+	int ret;
+
+	if (sdhci_am654->flags & DLL_CALIB) {
+		regmap_read(sdhci_am654->base, PHY_STAT1, &val);
+		if (~val & CALDONE_MASK) {
+			/* Calibrate IO lines */
+			regmap_update_bits(sdhci_am654->base, PHY_CTRL1,
+					   PDB_MASK, PDB_MASK);
+			ret = regmap_read_poll_timeout(sdhci_am654->base,
+						       PHY_STAT1, val,
+						       val & CALDONE_MASK,
+						       1, 20);
+			if (ret)
+				return ret;
+		}
+	}
+
+	/* Enable pins by setting IO mux to 0 */
+	if (sdhci_am654->flags & IOMUX_PRESENT)
+		regmap_update_bits(sdhci_am654->base, PHY_CTRL1,
+				   IOMUX_ENABLE_MASK, 0);
+
+	/* Set slot type based on SD or eMMC */
+	if (host->mmc->caps & MMC_CAP_NONREMOVABLE)
+		ctl_cfg_2 = SLOTTYPE_EMBEDDED;
+
+	regmap_update_bits(sdhci_am654->base, CTL_CFG_2, SLOTTYPE_MASK,
+			   ctl_cfg_2);
+
+	regmap_read(sdhci_am654->base, CTL_CFG_3, &val);
+	if (~val & TUNINGFORSDR50_MASK)
+		/* Enable tuning for SDR50 */
+		regmap_update_bits(sdhci_am654->base, CTL_CFG_3, TUNINGFORSDR50_MASK,
+				   TUNINGFORSDR50_MASK);
 
 	return 0;
 }
 
+static int sdhci_am654_runtime_suspend(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	int ret;
+
+	if (host->tuning_mode != SDHCI_TUNING_MODE_3)
+		mmc_retune_needed(host->mmc);
+
+	ret = cqhci_suspend(host->mmc);
+	if (ret)
+		return ret;
+
+	ret = sdhci_runtime_suspend_host(host);
+	if (ret)
+		return ret;
+
+	/* disable the clock */
+	clk_disable_unprepare(pltfm_host->clk);
+	return 0;
+}
+
+static int sdhci_am654_runtime_resume(struct device *dev)
+{
+	struct sdhci_host *host = dev_get_drvdata(dev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	int ret;
+
+	/* Enable the clock */
+	ret = clk_prepare_enable(pltfm_host->clk);
+	if (ret)
+		return ret;
+
+	ret = sdhci_am654_restore(host);
+	if (ret)
+		return ret;
+
+	ret = sdhci_runtime_resume_host(host, 0);
+	if (ret)
+		return ret;
+
+	ret = cqhci_resume(host->mmc);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+#endif
+
+static const struct dev_pm_ops sdhci_am654_dev_pm_ops = {
+	SET_RUNTIME_PM_OPS(sdhci_am654_runtime_suspend,
+			   sdhci_am654_runtime_resume, NULL)
+	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				pm_runtime_force_resume)
+};
+
 static struct platform_driver sdhci_am654_driver = {
 	.driver = {
 		.name = "sdhci-am654",
 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+		.pm = &sdhci_am654_dev_pm_ops,
 		.of_match_table = sdhci_am654_of_match,
 	},
 	.probe = sdhci_am654_probe,
diff -Naur --no-dereference a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
--- a/drivers/mtd/nand/spi/core.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/mtd/nand/spi/core.c	2024-01-28 14:01:31.248353800 -0500
@@ -22,9 +22,11 @@
 
 static int spinand_read_reg_op(struct spinand_device *spinand, u8 reg, u8 *val)
 {
-	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(reg,
-						      spinand->scratchbuf);
 	int ret;
+	struct spi_mem_op op = spinand->ctrl_ops->ops.get_feature;
+
+	op.data.buf.out = spinand->scratchbuf;
+	memset(&op.addr.val, reg, op.addr.nbytes);
 
 	ret = spi_mem_exec_op(spinand->spimem, &op);
 	if (ret)
@@ -36,10 +38,12 @@
 
 static int spinand_write_reg_op(struct spinand_device *spinand, u8 reg, u8 val)
 {
-	struct spi_mem_op op = SPINAND_SET_FEATURE_OP(reg,
-						      spinand->scratchbuf);
+	struct spi_mem_op op = spinand->ctrl_ops->ops.set_feature;
+
+	op.data.buf.out = spinand->scratchbuf;
+	memset(&op.addr.val, reg, op.addr.nbytes);
+	memset(spinand->scratchbuf, val, op.data.nbytes);
 
-	*spinand->scratchbuf = val;
 	return spi_mem_exec_op(spinand->spimem, &op);
 }
 
@@ -184,9 +188,9 @@
 	if (!(spinand->flags & SPINAND_HAS_QE_BIT))
 		return 0;
 
-	if (spinand->op_templates.read_cache->data.buswidth == 4 ||
-	    spinand->op_templates.write_cache->data.buswidth == 4 ||
-	    spinand->op_templates.update_cache->data.buswidth == 4)
+	if (spinand->data_ops.read_cache->data.buswidth == 4 ||
+	    spinand->data_ops.write_cache->data.buswidth == 4 ||
+	    spinand->data_ops.update_cache->data.buswidth == 4)
 		enable = true;
 
 	return spinand_upd_cfg(spinand, CFG_QUAD_ENABLE,
@@ -339,9 +343,9 @@
 		engine_conf->status = status;
 }
 
-static int spinand_write_enable_op(struct spinand_device *spinand)
+int spinand_write_enable_op(struct spinand_device *spinand)
 {
-	struct spi_mem_op op = SPINAND_WR_EN_DIS_OP(true);
+	struct spi_mem_op op = spinand->ctrl_ops->ops.write_enable;
 
 	return spi_mem_exec_op(spinand->spimem, &op);
 }
@@ -351,7 +355,9 @@
 {
 	struct nand_device *nand = spinand_to_nand(spinand);
 	unsigned int row = nanddev_pos_to_row(nand, &req->pos);
-	struct spi_mem_op op = SPINAND_PAGE_READ_OP(row);
+	struct spi_mem_op op = spinand->ctrl_ops->ops.page_read;
+
+	op.addr.val = row;
 
 	return spi_mem_exec_op(spinand->spimem, &op);
 }
@@ -481,7 +487,9 @@
 {
 	struct nand_device *nand = spinand_to_nand(spinand);
 	unsigned int row = nanddev_pos_to_row(nand, &req->pos);
-	struct spi_mem_op op = SPINAND_PROG_EXEC_OP(row);
+	struct spi_mem_op op = spinand->ctrl_ops->ops.program_execute;
+
+	op.addr.val = row;
 
 	return spi_mem_exec_op(spinand->spimem, &op);
 }
@@ -491,7 +499,9 @@
 {
 	struct nand_device *nand = spinand_to_nand(spinand);
 	unsigned int row = nanddev_pos_to_row(nand, pos);
-	struct spi_mem_op op = SPINAND_BLK_ERASE_OP(row);
+	struct spi_mem_op op = spinand->ctrl_ops->ops.block_erase;
+
+	op.addr.val = row;
 
 	return spi_mem_exec_op(spinand->spimem, &op);
 }
@@ -501,11 +511,13 @@
 			unsigned long poll_delay_us,
 			u8 *s)
 {
-	struct spi_mem_op op = SPINAND_GET_FEATURE_OP(REG_STATUS,
-						      spinand->scratchbuf);
+	struct spi_mem_op op = spinand->ctrl_ops->ops.get_feature;
 	u8 status;
 	int ret;
 
+	op.data.buf.out = spinand->scratchbuf;
+	memset(&op.addr.val, REG_STATUS, op.addr.nbytes);
+
 	ret = spi_mem_poll_status(spinand->spimem, &op, STATUS_BUSY, 0,
 				  initial_delay_us,
 				  poll_delay_us,
@@ -548,7 +560,7 @@
 
 static int spinand_reset_op(struct spinand_device *spinand)
 {
-	struct spi_mem_op op = SPINAND_RESET_OP;
+	struct spi_mem_op op = spinand->ctrl_ops->ops.reset;
 	int ret;
 
 	ret = spi_mem_exec_op(spinand->spimem, &op);
@@ -865,7 +877,7 @@
 	/* The plane number is passed in MSB just above the column address */
 	info.offset = plane << fls(nand->memorg.pagesize);
 
-	info.op_tmpl = *spinand->op_templates.update_cache;
+	info.op_tmpl = *spinand->data_ops.update_cache;
 	desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev,
 					  spinand->spimem, &info);
 	if (IS_ERR(desc))
@@ -873,7 +885,7 @@
 
 	spinand->dirmaps[plane].wdesc = desc;
 
-	info.op_tmpl = *spinand->op_templates.read_cache;
+	info.op_tmpl = *spinand->data_ops.read_cache;
 	desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev,
 					  spinand->spimem, &info);
 	if (IS_ERR(desc))
@@ -888,7 +900,7 @@
 		return 0;
 	}
 
-	info.op_tmpl = *spinand->op_templates.update_cache;
+	info.op_tmpl = *spinand->data_ops.update_cache;
 	info.op_tmpl.data.ecc = true;
 	desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev,
 					  spinand->spimem, &info);
@@ -897,7 +909,7 @@
 
 	spinand->dirmaps[plane].wdesc_ecc = desc;
 
-	info.op_tmpl = *spinand->op_templates.read_cache;
+	info.op_tmpl = *spinand->data_ops.read_cache;
 	info.op_tmpl.data.ecc = true;
 	desc = devm_spi_mem_dirmap_create(&spinand->spimem->spi->dev,
 					  spinand->spimem, &info);
@@ -947,6 +959,16 @@
 	&xtx_spinand_manufacturer,
 };
 
+static const struct spinand_ctrl_ops spinand_default_ctrl_ops =
+			SPINAND_CTRL_OPS(SPINAND_1S_1S_1S,
+					 SPINAND_RESET_OP,
+					 SPINAND_GET_FEATURE_OP(0, NULL),
+					 SPINAND_SET_FEATURE_OP(0, NULL),
+					 SPINAND_WR_EN_DIS_OP(true),
+					 SPINAND_BLK_ERASE_OP(0),
+					 SPINAND_PAGE_READ_OP(0),
+					 SPINAND_PROG_EXEC_OP(0));
+
 static int spinand_manufacturer_match(struct spinand_device *spinand,
 				      enum spinand_readid_method rdid_method)
 {
@@ -1019,8 +1041,8 @@
 }
 
 static const struct spi_mem_op *
-spinand_select_op_variant(struct spinand_device *spinand,
-			  const struct spinand_op_variants *variants)
+spinand_select_data_op_variant(struct spinand_device *spinand,
+			       const struct spinand_op_variants *variants)
 {
 	struct nand_device *nand = spinand_to_nand(spinand);
 	unsigned int i;
@@ -1052,6 +1074,117 @@
 	return NULL;
 }
 
+static const struct spinand_ctrl_ops *
+spinand_select_ctrl_ops_variant(struct spinand_device *spinand,
+				const struct spinand_ctrl_ops_variants *variants,
+				const enum spinand_protocol protocol)
+{
+	unsigned int i;
+
+	for (i = 0; i < variants->nvariants; i++) {
+		const struct spinand_ctrl_ops *ctrl_ops =
+			&variants->ctrl_ops_list[i];
+
+		if (ctrl_ops->protocol != protocol)
+			continue;
+
+		if (!spi_mem_supports_op(spinand->spimem,
+					 &ctrl_ops->ops.reset) ||
+		    !spi_mem_supports_op(spinand->spimem,
+					 &ctrl_ops->ops.get_feature) ||
+		    !spi_mem_supports_op(spinand->spimem,
+					 &ctrl_ops->ops.set_feature) ||
+		    !spi_mem_supports_op(spinand->spimem,
+					 &ctrl_ops->ops.write_enable) ||
+		    !spi_mem_supports_op(spinand->spimem,
+					 &ctrl_ops->ops.block_erase) ||
+		    !spi_mem_supports_op(spinand->spimem,
+					 &ctrl_ops->ops.page_read) ||
+		    !spi_mem_supports_op(spinand->spimem,
+					 &ctrl_ops->ops.program_execute))
+			continue;
+
+		return ctrl_ops;
+	}
+
+	return NULL;
+}
+
+static bool spinand_op_is_octal_dtr(const struct spi_mem_op *op)
+{
+	return  op->cmd.buswidth == 8 && op->cmd.dtr &&
+		op->addr.buswidth == 8 && op->addr.dtr &&
+		op->data.buswidth == 8 && op->data.dtr;
+}
+
+static int spinand_init_octal_dtr_enable(struct spinand_device *spinand)
+{
+	struct device *dev = &spinand->spimem->spi->dev;
+	const struct spinand_ctrl_ops *octal_dtr_ctrl_ops;
+	int ret;
+
+	if (!(spinand->flags & SPINAND_HAS_OCTAL_DTR_BIT))
+		return 0;
+
+	if (!(spinand_op_is_octal_dtr(spinand->data_ops.read_cache) &&
+	      spinand_op_is_octal_dtr(spinand->data_ops.write_cache) &&
+	      spinand_op_is_octal_dtr(spinand->data_ops.update_cache)))
+		return 0;
+
+	octal_dtr_ctrl_ops = spinand_select_ctrl_ops_variant(spinand,
+					spinand->desc_entry->ctrl_ops_variants,
+					SPINAND_8D_8D_8D);
+
+	if (!octal_dtr_ctrl_ops)
+		return 0;
+
+	if (!spinand->manufacturer->ops->change_mode) {
+		dev_dbg(dev,
+			"Missing ->change_mode(), unable to switch mode\n");
+		return -EINVAL;
+	}
+
+	ret = spinand->manufacturer->ops->change_mode(spinand,
+						      SPINAND_8D_8D_8D);
+	if (ret) {
+		dev_err(dev,
+			"Failed to enable Octal DTR SPI mode (err = %d)\n",
+			ret);
+		return ret;
+	}
+
+	spinand->protocol = SPINAND_8D_8D_8D;
+	spinand->ctrl_ops = octal_dtr_ctrl_ops;
+
+	dev_dbg(dev,
+		"%s SPI NAND switched to Octal DTR SPI (8D-8D-8D) mode\n",
+		spinand->manufacturer->name);
+	return 0;
+}
+
+static int spinand_init_octal_dtr_disable(struct spinand_device *spinand)
+{
+	struct device *dev = &spinand->spimem->spi->dev;
+	int ret;
+
+	if (!spinand->manufacturer->ops->change_mode)
+		return -EINVAL;
+
+	ret = spinand->manufacturer->ops->change_mode(spinand,
+						      SPINAND_1S_1S_1S);
+
+	if (ret) {
+		dev_err(dev,
+			"Failed to disable Octal DTR SPI mode (err = %d)\n",
+			ret);
+		return ret;
+	}
+
+	spinand->protocol = SPINAND_1S_1S_1S;
+	spinand->ctrl_ops = &spinand_default_ctrl_ops;
+	return 0;
+}
+
 /**
  * spinand_match_and_init() - Try to find a match between a device ID and an
  *			      entry in a spinand_info table
@@ -1092,24 +1225,25 @@
 		spinand->flags = table[i].flags;
 		spinand->id.len = 1 + table[i].devid.len;
 		spinand->select_target = table[i].select_target;
+		spinand->desc_entry = &table[i];
 
-		op = spinand_select_op_variant(spinand,
-					       info->op_variants.read_cache);
+		op = spinand_select_data_op_variant(spinand,
+					info->data_ops_variants.read_cache);
 		if (!op)
 			return -ENOTSUPP;
 
-		spinand->op_templates.read_cache = op;
+		spinand->data_ops.read_cache = op;
 
-		op = spinand_select_op_variant(spinand,
-					       info->op_variants.write_cache);
+		op = spinand_select_data_op_variant(spinand,
+					info->data_ops_variants.write_cache);
 		if (!op)
 			return -ENOTSUPP;
 
-		spinand->op_templates.write_cache = op;
+		spinand->data_ops.write_cache = op;
 
-		op = spinand_select_op_variant(spinand,
-					       info->op_variants.update_cache);
-		spinand->op_templates.update_cache = op;
+		op = spinand_select_data_op_variant(spinand,
+					info->data_ops_variants.update_cache);
+		spinand->data_ops.update_cache = op;
 
 		return 0;
 	}
@@ -1187,6 +1321,10 @@
 			break;
 	}
 
+	ret = spinand_init_octal_dtr_enable(spinand);
+	if (ret)
+		return ret;
+
 	if (ret)
 		spinand_manufacturer_cleanup(spinand);
 
@@ -1198,6 +1336,9 @@
 	struct spinand_device *spinand = mtd_to_spinand(mtd);
 	int ret;
 
+	spinand->protocol = SPINAND_1S_1S_1S;
+	spinand->ctrl_ops = &spinand_default_ctrl_ops;
+
 	ret = spinand_reset_op(spinand);
 	if (ret)
 		return;
@@ -1209,6 +1350,16 @@
 	spinand_ecc_enable(spinand, false);
 }
 
+static int spinand_mtd_suspend(struct mtd_info *mtd)
+{
+	struct spinand_device *spinand = mtd_to_spinand(mtd);
+
+	if (spinand->ctrl_ops->protocol == SPINAND_8D_8D_8D)
+		return spinand_init_octal_dtr_disable(spinand);
+
+	return 0;
+}
+
 static int spinand_init(struct spinand_device *spinand)
 {
 	struct device *dev = &spinand->spimem->spi->dev;
@@ -1224,6 +1375,9 @@
 	if (!spinand->scratchbuf)
 		return -ENOMEM;
 
+	spinand->protocol = SPINAND_1S_1S_1S;
+	spinand->ctrl_ops = &spinand_default_ctrl_ops;
+
 	ret = spinand_detect(spinand);
 	if (ret)
 		goto err_free_bufs;
@@ -1272,6 +1426,7 @@
 	mtd->_erase = spinand_mtd_erase;
 	mtd->_max_bad_blocks = nanddev_mtd_max_bad_blocks;
 	mtd->_resume = spinand_mtd_resume;
+	mtd->_suspend = spinand_mtd_suspend;
 
 	if (nand->ecc.engine) {
 		ret = mtd_ooblayout_count_freebytes(mtd);
diff -Naur --no-dereference a/drivers/mtd/nand/spi/winbond.c b/drivers/mtd/nand/spi/winbond.c
--- a/drivers/mtd/nand/spi/winbond.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/mtd/nand/spi/winbond.c	2024-01-28 14:01:31.248353800 -0500
@@ -7,6 +7,7 @@
  *	Boris Brezillon <boris.brezillon@bootlin.com>
  */
 
+#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/mtd/spinand.h>
@@ -15,7 +16,17 @@
 
 #define WINBOND_CFG_BUF_READ		BIT(3)
 
-static SPINAND_OP_VARIANTS(read_cache_variants,
+/* Octal DTR SPI mode (8D-8D-8D) with Data Strobe output*/
+#define WINBOND_VCR_IO_MODE_OCTAL_DTR	0xE7
+#define WINBOND_VCR_IO_MODE_SINGLE_STR	0xFF
+#define WINBOND_VCR_IO_MODE_ADDR	0x00
+
+/* Use 12 dummy clk cycles for using Octal DTR SPI at max 120MHZ */
+#define WINBOND_VCR_DUMMY_CLK_COUNT	12
+#define WINBOND_VCR_DUMMY_CLK_DEFAULT	0xFF
+#define WINBOND_VCR_DUMMY_CLK_ADDR	0x01
+
+static SPINAND_OP_VARIANTS(read_cache_variants_w25xxgv,
 		SPINAND_PAGE_READ_FROM_CACHE_QUADIO_OP(0, 2, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_DUALIO_OP(0, 1, NULL, 0),
@@ -23,14 +34,45 @@
 		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
 		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
 
-static SPINAND_OP_VARIANTS(write_cache_variants,
+static SPINAND_OP_VARIANTS(write_cache_variants_w25xxgv,
 		SPINAND_PROG_LOAD_X4(true, 0, NULL, 0),
 		SPINAND_PROG_LOAD(true, 0, NULL, 0));
 
-static SPINAND_OP_VARIANTS(update_cache_variants,
+static SPINAND_OP_VARIANTS(update_cache_variants_w25xxgv,
 		SPINAND_PROG_LOAD_X4(false, 0, NULL, 0),
 		SPINAND_PROG_LOAD(false, 0, NULL, 0));
 
+static SPINAND_OP_VARIANTS(read_cache_variants_w35n01jw,
+		SPINAND_PAGE_READ_FROM_CACHE_OCTALIO_DTR_OP(0, 24, NULL, 0),
+		SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0),
+		SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0));
+
+static SPINAND_OP_VARIANTS(write_cache_variants_w35n01jw,
+		SPINAND_PROG_LOAD_OCTALIO_DTR(true, 0, NULL, 0),
+		SPINAND_PROG_LOAD(true, 0, NULL, 0));
+
+static SPINAND_OP_VARIANTS(update_cache_variants_w35n01jw,
+		SPINAND_PROG_LOAD_OCTALIO_DTR(false, 0, NULL, 0),
+		SPINAND_PROG_LOAD(false, 0, NULL, 0));
+
+static SPINAND_CTRL_OPS_VARIANTS(ctrl_ops_variants_w35n01jw,
+		SPINAND_CTRL_OPS(SPINAND_8D_8D_8D,
+				 SPINAND_RESET_OP_OCTAL_DTR,
+				 SPINAND_GET_FEATURE_OP_OCTAL_DTR(0, NULL),
+				 SPINAND_SET_FEATURE_OP_OCTAL_DTR(0, NULL),
+				 SPINAND_WR_EN_DIS_OP_OCTAL_DTR(true),
+				 SPINAND_BLK_ERASE_OP_OCTAL_DTR(0),
+				 SPINAND_PAGE_READ_OP_OCTAL_DTR(0),
+				 SPINAND_PROG_EXEC_OP_OCTAL_DTR(0)),
+		SPINAND_CTRL_OPS(SPINAND_1S_1S_1S,
+				 SPINAND_RESET_OP,
+				 SPINAND_GET_FEATURE_OP(0, NULL),
+				 SPINAND_SET_FEATURE_OP(0, NULL),
+				 SPINAND_WR_EN_DIS_OP(true),
+				 SPINAND_BLK_ERASE_OP(0),
+				 SPINAND_PAGE_READ_OP(0),
+				 SPINAND_PROG_EXEC_OP(0)));
+
 static int w25m02gv_ooblayout_ecc(struct mtd_info *mtd, int section,
 				  struct mtd_oob_region *region)
 {
@@ -55,11 +97,40 @@
 	return 0;
 }
 
+static int w35n01jw_ooblayout_ecc(struct mtd_info *mtd, int section,
+				  struct mtd_oob_region *region)
+{
+	if (section > 7)
+		return -ERANGE;
+
+	region->offset = (16 * section) + 12;
+	region->length = 4;
+
+	return 0;
+}
+
+static int w35n01jw_ooblayout_free(struct mtd_info *mtd, int section,
+				   struct mtd_oob_region *region)
+{
+	if (section > 7)
+		return -ERANGE;
+
+	region->offset = (16 * section) + 2;
+	region->length = 10;
+
+	return 0;
+}
+
 static const struct mtd_ooblayout_ops w25m02gv_ooblayout = {
 	.ecc = w25m02gv_ooblayout_ecc,
 	.free = w25m02gv_ooblayout_free,
 };
 
+static const struct mtd_ooblayout_ops w35n01jw_ooblayout = {
+	.ecc = w35n01jw_ooblayout_ecc,
+	.free = w35n01jw_ooblayout_free,
+};
+
 static int w25m02gv_select_target(struct spinand_device *spinand,
 				  unsigned int target)
 {
@@ -79,9 +150,9 @@
 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xab),
 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 2),
 		     NAND_ECCREQ(1, 512),
-		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-					      &write_cache_variants,
-					      &update_cache_variants),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_w25xxgv,
+					      &write_cache_variants_w25xxgv,
+					      &update_cache_variants_w25xxgv),
 		     0,
 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL),
 		     SPINAND_SELECT_TARGET(w25m02gv_select_target)),
@@ -89,11 +160,22 @@
 		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xaa),
 		     NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
 		     NAND_ECCREQ(1, 512),
-		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
-					      &write_cache_variants,
-					      &update_cache_variants),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_w25xxgv,
+					      &write_cache_variants_w25xxgv,
+					      &update_cache_variants_w25xxgv),
 		     0,
 		     SPINAND_ECCINFO(&w25m02gv_ooblayout, NULL)),
+	SPINAND_INFO("W35N01JW",
+		     SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0xdc),
+		     NAND_MEMORG(1, 4096, 128, 64, 512, 20, 1, 1, 1),
+		     NAND_ECCREQ(1, 512),
+		     SPINAND_INFO_OP_VARIANTS(&read_cache_variants_w35n01jw,
+					      &write_cache_variants_w35n01jw,
+					      &update_cache_variants_w35n01jw),
+		     SPINAND_HAS_OCTAL_DTR_BIT | SPINAND_HAS_CR_FEAT_BIT,
+		     SPINAND_ECCINFO(&w35n01jw_ooblayout, NULL),
+		     SPINAND_INFO_CTRL_OPS_VARIANTS(&ctrl_ops_variants_w35n01jw)),
+
 };
 
 static int winbond_spinand_init(struct spinand_device *spinand)
@@ -114,8 +196,150 @@
 	return 0;
 }
 
+/**
+ * winbond_write_vcr_op() - write values onto the volatile configuration
+ *			    registers (VCR)
+ * @spinand: the spinand device
+ * @reg: the address of the particular reg in the VCR to be written on
+ * @val: the value to be written on the reg in the VCR
+ *
+ * Volatile configuration registers are a separate set of configuration
+ * registers, i.e. they differ from the status registers SR-1/2/3. A different
+ * SPI instruction is required to write to these registers. Any changes
+ * to the Volatile Configuration Register get transferred directly to
+ * the Internal Configuration Register and instantly reflect on the
+ * device operation.
+ */
+static int winbond_write_vcr_op(struct spinand_device *spinand, u8 reg, u8 val)
+{
+	int ret;
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(0x81, 1),
+			   SPI_MEM_OP_ADDR(3, reg, 1),
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_DATA_OUT(1, spinand->scratchbuf, 1));
+
+	*spinand->scratchbuf = val;
+
+	ret = spinand_write_enable_op(spinand);
+	if (ret)
+		return ret;
+
+	ret = spi_mem_exec_op(spinand->spimem, &op);
+	if (ret)
+		return ret;
+
+	/*
+	 * Write VCR operation doesn't set the busy bit in SR, so can't perform
+	 * a status poll. Minimum time of 50ns is needed to complete the write.
+	 * So, give thrice the minimum required delay.
+	 */
+	ndelay(150);
+	return 0;
+}
+
+static int winbond_spinand_octal_dtr_enable(struct spinand_device *spinand)
+{
+	int ret;
+	struct spi_mem_op op;
+
+	ret = winbond_write_vcr_op(spinand, WINBOND_VCR_DUMMY_CLK_ADDR,
+				   WINBOND_VCR_DUMMY_CLK_COUNT);
+	if (ret)
+		return ret;
+
+	ret = winbond_write_vcr_op(spinand, WINBOND_VCR_IO_MODE_ADDR,
+				   WINBOND_VCR_IO_MODE_OCTAL_DTR);
+	if (ret)
+		return ret;
+
+	/* Read flash ID to make sure the switch was successful. */
+	op = (struct spi_mem_op)
+		SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, 0x9f9f, 8),
+			   SPI_MEM_OP_NO_ADDR,
+			   SPI_MEM_OP_DUMMY_DTR(16, 8),
+			   SPI_MEM_OP_DATA_IN_DTR(SPINAND_MAX_ID_LEN,
+						  spinand->scratchbuf, 8));
+
+	ret = spi_mem_exec_op(spinand->spimem, &op);
+	if (ret)
+		return ret;
+
+	if (memcmp(spinand->scratchbuf, spinand->id.data, SPINAND_MAX_ID_LEN))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int winbond_spinand_octal_dtr_disable(struct spinand_device *spinand)
+{
+	int ret;
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, 0x8181, 8),
+			   SPI_MEM_OP_ADDR_DTR(4, WINBOND_VCR_IO_MODE_ADDR, 8),
+			   SPI_MEM_OP_NO_DUMMY,
+			   SPI_MEM_OP_DATA_OUT_DTR(2, spinand->scratchbuf, 8));
+
+	*spinand->scratchbuf = WINBOND_VCR_IO_MODE_SINGLE_STR;
+
+	ret = spinand_write_enable_op(spinand);
+	if (ret)
+		return ret;
+
+	ret = spi_mem_exec_op(spinand->spimem, &op);
+	if (ret)
+		return ret;
+
+	ret = winbond_write_vcr_op(spinand, WINBOND_VCR_DUMMY_CLK_ADDR,
+				   WINBOND_VCR_DUMMY_CLK_DEFAULT);
+	if (ret)
+		return ret;
+
+	/* Read flash ID to make sure the switch was successful. */
+	op = (struct spi_mem_op)
+		SPI_MEM_OP(SPI_MEM_OP_CMD(0x9f, 1),
+			   SPI_MEM_OP_NO_ADDR,
+			   SPI_MEM_OP_DUMMY(1, 1),
+			   SPI_MEM_OP_DATA_IN(SPINAND_MAX_ID_LEN,
+					      spinand->scratchbuf, 1));
+
+	ret = spi_mem_exec_op(spinand->spimem, &op);
+	if (ret)
+		return ret;
+
+	if (memcmp(spinand->scratchbuf, spinand->id.data, SPINAND_MAX_ID_LEN))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int winbond_change_spi_mode(struct spinand_device *spinand,
+				   const enum spinand_protocol protocol)
+{
+	if (spinand->protocol == protocol)
+		return 0;
+
+	switch (spinand->protocol) {
+	case SPINAND_1S_1S_1S:
+		if (protocol == SPINAND_8D_8D_8D)
+			return winbond_spinand_octal_dtr_enable(spinand);
+		break;
+
+	case SPINAND_8D_8D_8D:
+		if (protocol == SPINAND_1S_1S_1S)
+			return winbond_spinand_octal_dtr_disable(spinand);
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return -EOPNOTSUPP;
+}
+
 static const struct spinand_manufacturer_ops winbond_spinand_manuf_ops = {
 	.init = winbond_spinand_init,
+	.change_mode = winbond_change_spi_mode,
 };
 
 const struct spinand_manufacturer winbond_spinand_manufacturer = {
diff -Naur --no-dereference a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
--- a/drivers/mtd/spi-nor/core.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/mtd/spi-nor/core.c	2024-01-28 14:01:31.248353800 -0500
@@ -185,6 +185,33 @@
 }
 
 /**
+ * spi_nor_spimem_get_read_op() - return a template for the spi_mem_op used for
+ *                                reading data from the flash via spi-mem.
+ * @nor:        pointer to 'struct spi_nor'
+ *
+ * Return: A template of the 'struct spi_mem_op' for used for reading data from
+ * the flash. The caller is expected to fill in the address, data length, and
+ * the data buffer.
+ */
+static struct spi_mem_op spi_nor_spimem_get_read_op(struct spi_nor *nor)
+{
+	struct spi_mem_op op =
+		SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 0),
+			   SPI_MEM_OP_ADDR(nor->addr_nbytes, 0, 0),
+			   SPI_MEM_OP_DUMMY(nor->read_dummy, 0),
+			   SPI_MEM_OP_DATA_IN(1, NULL, 0));
+
+	spi_nor_spimem_setup_op(nor, &op, nor->read_proto);
+
+	/* convert the dummy cycles to the number of bytes */
+	op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
+	if (spi_nor_protocol_is_dtr(nor->read_proto))
+		op.dummy.nbytes *= 2;
+
+	return op;
+}
+
+/**
  * spi_nor_spimem_read_data() - read data from flash's memory region via
  *                              spi-mem
  * @nor:        pointer to 'struct spi_nor'
@@ -197,21 +224,14 @@
 static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t from,
 					size_t len, u8 *buf)
 {
-	struct spi_mem_op op =
-		SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 0),
-			   SPI_MEM_OP_ADDR(nor->addr_nbytes, from, 0),
-			   SPI_MEM_OP_DUMMY(nor->read_dummy, 0),
-			   SPI_MEM_OP_DATA_IN(len, buf, 0));
+	struct spi_mem_op op = spi_nor_spimem_get_read_op(nor);
 	bool usebouncebuf;
 	ssize_t nbytes;
 	int error;
 
-	spi_nor_spimem_setup_op(nor, &op, nor->read_proto);
-
-	/* convert the dummy cycles to the number of bytes */
-	op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
-	if (spi_nor_protocol_is_dtr(nor->read_proto))
-		op.dummy.nbytes *= 2;
+	op.addr.val = from;
+	op.data.nbytes = len;
+	op.data.buf.in = buf;
 
 	usebouncebuf = spi_nor_spimem_bounce(nor, &op);
 
@@ -3053,28 +3073,10 @@
 static int spi_nor_create_read_dirmap(struct spi_nor *nor)
 {
 	struct spi_mem_dirmap_info info = {
-		.op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 0),
-				      SPI_MEM_OP_ADDR(nor->addr_nbytes, 0, 0),
-				      SPI_MEM_OP_DUMMY(nor->read_dummy, 0),
-				      SPI_MEM_OP_DATA_IN(0, NULL, 0)),
+		.op_tmpl = spi_nor_spimem_get_read_op(nor),
 		.offset = 0,
 		.length = nor->params->size,
 	};
-	struct spi_mem_op *op = &info.op_tmpl;
-
-	spi_nor_spimem_setup_op(nor, op, nor->read_proto);
-
-	/* convert the dummy cycles to the number of bytes */
-	op->dummy.nbytes = (nor->read_dummy * op->dummy.buswidth) / 8;
-	if (spi_nor_protocol_is_dtr(nor->read_proto))
-		op->dummy.nbytes *= 2;
-
-	/*
-	 * Since spi_nor_spimem_setup_op() only sets buswidth when the number
-	 * of data bytes is non-zero, the data buswidth won't be set here. So,
-	 * do it explicitly.
-	 */
-	op->data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto);
 
 	nor->dirmap.rdesc = devm_spi_mem_dirmap_create(nor->dev, nor->spimem,
 						       &info);
@@ -3120,6 +3122,7 @@
 	 * checking what's really supported using spi_mem_supports_op().
 	 */
 	const struct spi_nor_hwcaps hwcaps = { .mask = SNOR_HWCAPS_ALL };
+	struct mtd_part *part;
 	char *flash_name;
 	int ret;
 
@@ -3181,8 +3184,25 @@
 	if (ret)
 		return ret;
 
-	return mtd_device_register(&nor->mtd, data ? data->parts : NULL,
-				   data ? data->nr_parts : 0);
+	ret = mtd_device_register(&nor->mtd, data ? data->parts : NULL,
+				  data ? data->nr_parts : 0);
+	if (ret)
+		return ret;
+
+	list_for_each_entry(part, &nor->mtd.partitions, node) {
+		struct spi_mem_op op;
+		struct mtd_info *part_info = container_of(part,
+							  struct mtd_info, part);
+
+		if (part_info->name &&
+		    !strcmp(part_info->name, "ospi.phypattern")) {
+			op = spi_nor_spimem_get_read_op(nor);
+			op.addr.val = part->offset;
+			spi_mem_do_calibration(nor->spimem, &op);
+		}
+	}
+
+	return 0;
 }
 
 static int spi_nor_remove(struct spi_mem *spimem)
diff -Naur --no-dereference a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
--- a/drivers/mtd/spi-nor/sfdp.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/mtd/spi-nor/sfdp.c	2024-01-28 14:01:31.248353800 -0500
@@ -1183,10 +1183,17 @@
 	dummy = round_up(dummy, 2);
 
 	/* Update the fast read settings. */
+	nor->params->hwcaps.mask |= SNOR_HWCAPS_READ_8_8_8_DTR;
 	spi_nor_set_read_settings(&nor->params->reads[SNOR_CMD_READ_8_8_8_DTR],
 				  0, dummy, opcode,
 				  SNOR_PROTO_8_8_8_DTR);
 
+	/*
+	 * Page Program is "Required Command" in the xSPI Profile 1.0. Update
+	 * the params->hwcaps.mask here.
+	 */
+	nor->params->hwcaps.mask |= SNOR_HWCAPS_PP_8_8_8_DTR;
+
 out:
 	kfree(dwords);
 	return ret;
diff -Naur --no-dereference a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
--- a/drivers/net/can/m_can/m_can.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/can/m_can/m_can.c	2024-01-28 14:01:31.248353800 -0500
@@ -10,6 +10,7 @@
 
 #include <linux/bitfield.h>
 #include <linux/ethtool.h>
+#include <linux/hrtimer.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -307,6 +308,9 @@
 #define TX_EVENT_MM_MASK	GENMASK(31, 24)
 #define TX_EVENT_TXTS_MASK	GENMASK(15, 0)
 
+/* Hrtimer polling interval */
+#define HRTIMER_POLL_INTERVAL_MS	1
+
 /* The ID and DLC registers are adjacent in M_CAN FIFO memory,
  * and we can save a (potentially slow) bus round trip by combining
  * reads and writes to them.
@@ -1385,6 +1389,12 @@
 
 	m_can_enable_all_interrupts(cdev);
 
+	if (!dev->irq) {
+		dev_dbg(cdev->dev, "Start hrtimer\n");
+		hrtimer_start(&cdev->hrtimer, ms_to_ktime(HRTIMER_POLL_INTERVAL_MS),
+			      HRTIMER_MODE_REL_PINNED);
+	}
+
 	return 0;
 }
 
@@ -1539,6 +1549,11 @@
 {
 	struct m_can_classdev *cdev = netdev_priv(dev);
 
+	if (!dev->irq) {
+		dev_dbg(cdev->dev, "Stop hrtimer\n");
+		hrtimer_cancel(&cdev->hrtimer);
+	}
+
 	/* disable all interrupts */
 	m_can_disable_all_interrupts(cdev);
 
@@ -1764,6 +1779,18 @@
 	return NETDEV_TX_OK;
 }
 
+static enum hrtimer_restart hrtimer_callback(struct hrtimer *timer)
+{
+	struct m_can_classdev *cdev = container_of(timer, struct
+						   m_can_classdev, hrtimer);
+
+	m_can_isr(0, cdev->net);
+
+	hrtimer_forward_now(timer, ms_to_ktime(HRTIMER_POLL_INTERVAL_MS));
+
+	return HRTIMER_RESTART;
+}
+
 static int m_can_open(struct net_device *dev)
 {
 	struct m_can_classdev *cdev = netdev_priv(dev);
@@ -1802,7 +1829,7 @@
 		err = request_threaded_irq(dev->irq, NULL, m_can_isr,
 					   IRQF_ONESHOT,
 					   dev->name, dev);
-	} else {
+	} else if (dev->irq) {
 		err = request_irq(dev->irq, m_can_isr, IRQF_SHARED, dev->name,
 				  dev);
 	}
@@ -1845,8 +1872,40 @@
 	.ndo_change_mtu = can_change_mtu,
 };
 
+static void m_can_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct m_can_classdev *cdev = netdev_priv(dev);
+
+	wol->supported = device_can_wakeup(cdev->dev) ? WAKE_PHY : 0;
+	wol->wolopts = device_may_wakeup(cdev->dev) ? WAKE_PHY : 0;
+}
+
+static int m_can_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct m_can_classdev *cdev = netdev_priv(dev);
+	struct pinctrl_state *new_pinctrl_state = NULL;
+	bool wol_enable = !!wol->wolopts & WAKE_PHY;
+
+	if ((wol->wolopts & WAKE_PHY) != wol->wolopts)
+		return -EINVAL;
+
+	if (wol_enable)
+		new_pinctrl_state = cdev->pinctrl_state_wakeup;
+	else
+		new_pinctrl_state = cdev->pinctrl_state_default;
+
+	if (!IS_ERR_OR_NULL(new_pinctrl_state))
+		pinctrl_select_state(cdev->pinctrl, new_pinctrl_state);
+
+	device_set_wakeup_enable(cdev->dev, wol_enable);
+
+	return 0;
+}
+
 static const struct ethtool_ops m_can_ethtool_ops = {
 	.get_ts_info = ethtool_op_get_ts_info,
+	.get_wol = m_can_get_wol,
+	.set_wol = m_can_set_wol,
 };
 
 static int register_m_can_dev(struct net_device *dev)
@@ -1952,6 +2011,9 @@
 		goto out;
 	}
 
+	if (dev->of_node && of_property_read_bool(dev->of_node, "wakeup-source"))
+		device_set_wakeup_capable(dev, true);
+
 	/* Get TX FIFO size
 	 * Defines the total amount of echo buffers for loopback
 	 */
@@ -1970,6 +2032,14 @@
 	SET_NETDEV_DEV(net_dev, dev);
 
 	m_can_of_parse_mram(class_dev, mram_config_vals);
+
+	class_dev->pinctrl = devm_pinctrl_get(dev);
+	if (!IS_ERR_OR_NULL(class_dev->pinctrl)) {
+		class_dev->pinctrl_state_default =
+			pinctrl_lookup_state(class_dev->pinctrl, "default");
+		class_dev->pinctrl_state_wakeup =
+			pinctrl_lookup_state(class_dev->pinctrl, "wakeup");
+	}
 out:
 	return class_dev;
 }
@@ -1998,6 +2068,9 @@
 			goto clk_disable;
 	}
 
+	if (!cdev->net->irq)
+		cdev->hrtimer.function = &hrtimer_callback;
+
 	ret = m_can_dev_setup(cdev);
 	if (ret)
 		goto rx_offload_del;
diff -Naur --no-dereference a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h
--- a/drivers/net/can/m_can/m_can.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/can/m_can/m_can.h	2024-01-28 14:01:31.248353800 -0500
@@ -12,6 +12,7 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/freezer.h>
+#include <linux/hrtimer.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 #include <linux/clk.h>
@@ -93,6 +94,12 @@
 	int is_peripheral;
 
 	struct mram_cfg mcfg[MRAM_CFG_NUM];
+
+	struct hrtimer hrtimer;
+
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pinctrl_state_default;
+	struct pinctrl_state *pinctrl_state_wakeup;
 };
 
 struct m_can_classdev *m_can_class_allocate_dev(struct device *dev, int sizeof_priv);
diff -Naur --no-dereference a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c
--- a/drivers/net/can/m_can/m_can_platform.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/can/m_can/m_can_platform.c	2024-01-28 14:01:31.248353800 -0500
@@ -5,6 +5,7 @@
 //
 // Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/
 
+#include <linux/hrtimer.h>
 #include <linux/platform_device.h>
 #include <linux/phy/phy.h>
 
@@ -82,7 +83,7 @@
 	void __iomem *addr;
 	void __iomem *mram_addr;
 	struct phy *transceiver;
-	int irq, ret = 0;
+	int irq = 0, ret = 0;
 
 	mcan_class = m_can_class_allocate_dev(&pdev->dev,
 					      sizeof(struct m_can_plat_priv));
@@ -96,12 +97,24 @@
 		goto probe_fail;
 
 	addr = devm_platform_ioremap_resource_byname(pdev, "m_can");
-	irq = platform_get_irq_byname(pdev, "int0");
-	if (IS_ERR(addr) || irq < 0) {
-		ret = -EINVAL;
+	if (IS_ERR(addr)) {
+		ret = PTR_ERR(addr);
 		goto probe_fail;
 	}
 
+	if (device_property_present(mcan_class->dev, "interrupts") ||
+	    device_property_present(mcan_class->dev, "interrupt-names")) {
+		irq = platform_get_irq_byname(pdev, "int0");
+		if (irq < 0) {
+			ret = irq;
+			goto probe_fail;
+		}
+	} else {
+		dev_dbg(mcan_class->dev, "Polling enabled, initialize hrtimer");
+		hrtimer_init(&mcan_class->hrtimer, CLOCK_MONOTONIC,
+			     HRTIMER_MODE_REL_PINNED);
+	}
+
 	/* message ram could be shared */
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "message_ram");
 	if (!res) {
diff -Naur --no-dereference a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c	2024-01-28 14:01:31.248353800 -0500
@@ -13671,19 +13671,20 @@
 	return bnx2x_func_state_change(bp, &func_params);
 }
 
-static int bnx2x_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+static int bnx2x_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
 	struct bnx2x *bp = container_of(ptp, struct bnx2x, ptp_clock_info);
 	int rc;
 	int drift_dir = 1;
 	int val, period, period1, period2, dif, dif1, dif2;
 	int best_dif = BNX2X_MAX_PHC_DRIFT, best_period = 0, best_val = 0;
+	s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
 
-	DP(BNX2X_MSG_PTP, "PTP adjfreq called, ppb = %d\n", ppb);
+	DP(BNX2X_MSG_PTP, "PTP adjfine called, ppb = %d\n", ppb);
 
 	if (!netif_running(bp->dev)) {
 		DP(BNX2X_MSG_PTP,
-		   "PTP adjfreq called while the interface is down\n");
+		   "PTP adjfine called while the interface is down\n");
 		return -ENETDOWN;
 	}
 
@@ -13818,7 +13819,7 @@
 	bp->ptp_clock_info.n_ext_ts = 0;
 	bp->ptp_clock_info.n_per_out = 0;
 	bp->ptp_clock_info.pps = 0;
-	bp->ptp_clock_info.adjfreq = bnx2x_ptp_adjfreq;
+	bp->ptp_clock_info.adjfine = bnx2x_ptp_adjfine;
 	bp->ptp_clock_info.adjtime = bnx2x_ptp_adjtime;
 	bp->ptp_clock_info.gettime64 = bnx2x_ptp_gettime;
 	bp->ptp_clock_info.settime64 = bnx2x_ptp_settime;
diff -Naur --no-dereference a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c	2024-01-28 14:01:31.248353800 -0500
@@ -1512,14 +1512,17 @@
 }
 
 /**
- * liquidio_ptp_adjfreq - Adjust ptp frequency
+ * liquidio_ptp_adjfine - Adjust ptp frequency
  * @ptp: PTP clock info
- * @ppb: how much to adjust by, in parts-per-billion
+ * @scaled_ppm: how much to adjust by, in scaled parts-per-million
+ *
+ * Scaled parts per million is ppm with a 16-bit binary fractional field.
  */
-static int liquidio_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+static int liquidio_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
 	struct lio *lio = container_of(ptp, struct lio, ptp_info);
 	struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
+	s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
 	u64 comp, delta;
 	unsigned long flags;
 	bool neg_adj = false;
@@ -1643,7 +1646,7 @@
 	lio->ptp_info.n_ext_ts = 0;
 	lio->ptp_info.n_per_out = 0;
 	lio->ptp_info.pps = 0;
-	lio->ptp_info.adjfreq = liquidio_ptp_adjfreq;
+	lio->ptp_info.adjfine = liquidio_ptp_adjfine;
 	lio->ptp_info.adjtime = liquidio_ptp_adjtime;
 	lio->ptp_info.gettime64 = liquidio_ptp_gettime;
 	lio->ptp_info.settime64 = liquidio_ptp_settime;
diff -Naur --no-dereference a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_ptp.c	2024-01-28 14:01:31.248353800 -0500
@@ -194,17 +194,20 @@
 }
 
 /**
- * cxgb4_ptp_adjfreq - Adjust frequency of PHC cycle counter
+ * cxgb4_ptp_adjfine - Adjust frequency of PHC cycle counter
  * @ptp: ptp clock structure
- * @ppb: Desired frequency change in parts per billion
+ * @scaled_ppm: Desired frequency in scaled parts per billion
  *
- * Adjust the frequency of the PHC cycle counter by the indicated ppb from
+ * Adjust the frequency of the PHC cycle counter by the indicated amount from
  * the base frequency.
+ *
+ * Scaled parts per million is ppm with a 16-bit binary fractional field.
  */
-static int cxgb4_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+static int cxgb4_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
 	struct adapter *adapter = (struct adapter *)container_of(ptp,
 				   struct adapter, ptp_clock_info);
+	s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
 	struct fw_ptp_cmd c;
 	int err;
 
@@ -404,7 +407,7 @@
 	.n_ext_ts       = 0,
 	.n_per_out      = 0,
 	.pps            = 0,
-	.adjfreq        = cxgb4_ptp_adjfreq,
+	.adjfine        = cxgb4_ptp_adjfine,
 	.adjtime        = cxgb4_ptp_adjtime,
 	.gettime64      = cxgb4_ptp_gettime,
 	.settime64      = cxgb4_ptp_settime,
diff -Naur --no-dereference a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
--- a/drivers/net/ethernet/freescale/fec_ptp.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/freescale/fec_ptp.c	2024-01-28 14:01:31.248353800 -0500
@@ -263,18 +263,21 @@
 }
 
 /**
- * fec_ptp_adjfreq - adjust ptp cycle frequency
+ * fec_ptp_adjfine - adjust ptp cycle frequency
  * @ptp: the ptp clock structure
- * @ppb: parts per billion adjustment from base
+ * @scaled_ppm: scaled parts per million adjustment from base
  *
  * Adjust the frequency of the ptp cycle counter by the
- * indicated ppb from the base frequency.
+ * indicated amount from the base frequency.
+ *
+ * Scaled parts per million is ppm with a 16-bit binary fractional field.
  *
  * Because ENET hardware frequency adjust is complex,
  * using software method to do that.
  */
-static int fec_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+static int fec_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
+	s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
 	unsigned long flags;
 	int neg_adj = 0;
 	u32 i, tmp;
@@ -586,7 +589,7 @@
 	fep->ptp_caps.n_per_out = 0;
 	fep->ptp_caps.n_pins = 0;
 	fep->ptp_caps.pps = 1;
-	fep->ptp_caps.adjfreq = fec_ptp_adjfreq;
+	fep->ptp_caps.adjfine = fec_ptp_adjfine;
 	fep->ptp_caps.adjtime = fec_ptp_adjtime;
 	fep->ptp_caps.gettime64 = fec_ptp_gettime;
 	fep->ptp_caps.settime64 = fec_ptp_settime;
diff -Naur --no-dereference a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c
--- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c	2024-01-28 14:01:31.252353813 -0500
@@ -1136,9 +1136,8 @@
 		lan966x->ports[p]->config.portmode = phy_mode;
 		lan966x->ports[p]->fwnode = fwnode_handle_get(portnp);
 
-		serdes = devm_of_phy_get(lan966x->dev, to_of_node(portnp), NULL);
-		if (PTR_ERR(serdes) == -ENODEV)
-			serdes = NULL;
+		serdes = devm_of_phy_optional_get(lan966x->dev,
+						  to_of_node(portnp), NULL);
 		if (IS_ERR(serdes)) {
 			err = PTR_ERR(serdes);
 			goto cleanup_ports;
diff -Naur --no-dereference a/drivers/net/ethernet/qlogic/qede/qede_ptp.c b/drivers/net/ethernet/qlogic/qede/qede_ptp.c
--- a/drivers/net/ethernet/qlogic/qede/qede_ptp.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/qlogic/qede/qede_ptp.c	2024-01-28 14:01:31.252353813 -0500
@@ -28,16 +28,19 @@
 };
 
 /**
- * qede_ptp_adjfreq() - Adjust the frequency of the PTP cycle counter.
+ * qede_ptp_adjfine() - Adjust the frequency of the PTP cycle counter.
  *
  * @info: The PTP clock info structure.
- * @ppb: Parts per billion adjustment from base.
+ * @scaled_ppm: Scaled parts per million adjustment from base.
+ *
+ * Scaled parts per million is ppm with a 16-bit binary fractional field.
  *
  * Return: Zero on success, negative errno otherwise.
  */
-static int qede_ptp_adjfreq(struct ptp_clock_info *info, s32 ppb)
+static int qede_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm)
 {
 	struct qede_ptp *ptp = container_of(info, struct qede_ptp, clock_info);
+	s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
 	struct qede_dev *edev = ptp->edev;
 	int rc;
 
@@ -47,7 +50,7 @@
 		rc = ptp->ops->adjfreq(edev->cdev, ppb);
 		spin_unlock_bh(&ptp->lock);
 	} else {
-		DP_ERR(edev, "PTP adjfreq called while interface is down\n");
+		DP_ERR(edev, "PTP adjfine called while interface is down\n");
 		rc = -EFAULT;
 	}
 	__qede_unlock(edev);
@@ -462,7 +465,7 @@
 	ptp->clock_info.n_ext_ts = 0;
 	ptp->clock_info.n_per_out = 0;
 	ptp->clock_info.pps = 0;
-	ptp->clock_info.adjfreq = qede_ptp_adjfreq;
+	ptp->clock_info.adjfine = qede_ptp_adjfine;
 	ptp->clock_info.adjtime = qede_ptp_adjtime;
 	ptp->clock_info.gettime64 = qede_ptp_gettime;
 	ptp->clock_info.settime64 = qede_ptp_settime;
diff -Naur --no-dereference a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
--- a/drivers/net/ethernet/sfc/ptp.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/sfc/ptp.c	2024-01-28 14:01:31.252353813 -0500
@@ -351,7 +351,7 @@
 	void (*xmit_skb)(struct efx_nic *efx, struct sk_buff *skb);
 };
 
-static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta);
+static int efx_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm);
 static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta);
 static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts);
 static int efx_phc_settime(struct ptp_clock_info *ptp,
@@ -1509,7 +1509,7 @@
 	.n_per_out	= 0,
 	.n_pins		= 0,
 	.pps		= 1,
-	.adjfreq	= efx_phc_adjfreq,
+	.adjfine	= efx_phc_adjfine,
 	.adjtime	= efx_phc_adjtime,
 	.gettime64	= efx_phc_gettime,
 	.settime64	= efx_phc_settime,
@@ -2138,11 +2138,12 @@
 					ptp->ts_corrections.general_rx);
 }
 
-static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
+static int efx_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
 	struct efx_ptp_data *ptp_data = container_of(ptp,
 						     struct efx_ptp_data,
 						     phc_clock_info);
+	s32 delta = scaled_ppm_to_ppb(scaled_ppm);
 	struct efx_nic *efx = ptp_data->efx;
 	MCDI_DECLARE_BUF(inadj, MC_CMD_PTP_IN_ADJUST_LEN);
 	s64 adjustment_ns;
diff -Naur --no-dereference a/drivers/net/ethernet/sfc/siena/ptp.c b/drivers/net/ethernet/sfc/siena/ptp.c
--- a/drivers/net/ethernet/sfc/siena/ptp.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/sfc/siena/ptp.c	2024-01-28 14:01:31.252353813 -0500
@@ -347,7 +347,7 @@
 	void (*xmit_skb)(struct efx_nic *efx, struct sk_buff *skb);
 };
 
-static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta);
+static int efx_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm);
 static int efx_phc_adjtime(struct ptp_clock_info *ptp, s64 delta);
 static int efx_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts);
 static int efx_phc_settime(struct ptp_clock_info *ptp,
@@ -1429,7 +1429,7 @@
 	.n_per_out	= 0,
 	.n_pins		= 0,
 	.pps		= 1,
-	.adjfreq	= efx_phc_adjfreq,
+	.adjfine	= efx_phc_adjfine,
 	.adjtime	= efx_phc_adjtime,
 	.gettime64	= efx_phc_gettime,
 	.settime64	= efx_phc_settime,
@@ -2044,11 +2044,12 @@
 					ptp->ts_corrections.general_rx);
 }
 
-static int efx_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta)
+static int efx_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
 	struct efx_ptp_data *ptp_data = container_of(ptp,
 						     struct efx_ptp_data,
 						     phc_clock_info);
+	s32 delta = scaled_ppm_to_ppb(scaled_ppm);
 	struct efx_nic *efx = ptp_data->efx;
 	MCDI_DECLARE_BUF(inadj, MC_CMD_PTP_IN_ADJUST_LEN);
 	s64 adjustment_ns;
diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c
--- a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c	2024-01-28 14:01:31.252353813 -0500
@@ -372,7 +372,15 @@
 /* Ethtool priv_flags */
 static const char am65_cpsw_ethtool_priv_flags[][ETH_GSTRING_LEN] = {
 #define	AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN	BIT(0)
+/* common flags */
 	"p0-rx-ptype-rrobin",
+/* port specific flags */
+#define AM65_CPSW_PRIV_IET_FRAME_PREEMPTION	BIT(1)
+	"iet-frame-preemption",
+#define AM65_CPSW_PRIV_IET_MAC_VERIFY		BIT(2)
+	"iet-mac-verify",
+#define AM65_CPSW_PRIV_CUT_THRU			BIT(3)
+	"cut-thru",
 };
 
 static int am65_cpsw_ethtool_op_begin(struct net_device *ndev)
@@ -686,10 +694,19 @@
 static u32 am65_cpsw_get_ethtool_priv_flags(struct net_device *ndev)
 {
 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
+	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+	struct am65_cpsw_iet *iet = &port->qos.iet;
 	u32 priv_flags = 0;
 
 	if (common->pf_p0_rx_ptype_rrobin)
 		priv_flags |= AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN;
+	/* Port specific flags */
+	if (iet->fpe_configured)
+		priv_flags |= AM65_CPSW_PRIV_IET_FRAME_PREEMPTION;
+	if (iet->mac_verify_configured)
+		priv_flags |= AM65_CPSW_PRIV_IET_MAC_VERIFY;
+	if (port->qos.cut_thru.enable)
+		priv_flags |= AM65_CPSW_PRIV_CUT_THRU;
 
 	return priv_flags;
 }
@@ -697,20 +714,126 @@
 static int am65_cpsw_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
 {
 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
-	int rrobin;
+	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+	struct am65_cpsw_iet *iet = &port->qos.iet;
+	int rrobin, iet_fpe, mac_verify, cut_thru;
 
 	rrobin = !!(flags & AM65_CPSW_PRIV_P0_RX_PTYPE_RROBIN);
+	iet_fpe = !!(flags & AM65_CPSW_PRIV_IET_FRAME_PREEMPTION);
+	mac_verify = !!(flags & AM65_CPSW_PRIV_IET_MAC_VERIFY);
+	cut_thru =  !!(flags & AM65_CPSW_PRIV_CUT_THRU);
 
 	if (common->usage_count)
 		return -EBUSY;
 
-	if (common->est_enabled && rrobin) {
+	if ((common->est_enabled || common->iet_enabled || iet_fpe) && rrobin) {
 		netdev_err(ndev,
 			   "p0-rx-ptype-rrobin flag conflicts with QOS\n");
 		return -EINVAL;
 	}
 
+	if (common->tx_ch_num < 2 && iet_fpe) {
+		netdev_err(ndev, "IET fpe needs at least 2 h/w queues\n");
+		return -EINVAL;
+	}
+
+	if (mac_verify && (!iet->fpe_configured && !iet_fpe)) {
+		netdev_err(ndev, "Enable IET FPE for IET MAC verify\n");
+		return -EINVAL;
+	}
+
+	if (cut_thru && !(common->pdata.quirks & AM64_CPSW_QUIRK_CUT_THRU)) {
+		netdev_err(ndev, "Cut-Thru not supported\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (cut_thru && common->is_emac_mode) {
+		netdev_err(ndev, "Enable switch mode for cut-thru\n");
+		return -EINVAL;
+	}
+
 	common->pf_p0_rx_ptype_rrobin = rrobin;
+	iet->fpe_configured = iet_fpe;
+	iet->mac_verify_configured = mac_verify;
+	port->qos.cut_thru.enable = cut_thru;
+
+	return 0;
+}
+
+static int am65_cpsw_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
+				  struct kernel_ethtool_coalesce *kernel_coal,
+				  struct netlink_ext_ack *extack)
+{
+	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
+	struct am65_cpsw_tx_chn *tx_chn;
+
+	tx_chn = &common->tx_chns[0];
+
+	coal->rx_coalesce_usecs = common->rx_pace_timeout / 1000;
+	coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout / 1000;
+
+	return 0;
+}
+
+static int am65_cpsw_get_per_queue_coalesce(struct net_device *ndev, u32 queue,
+					    struct ethtool_coalesce *coal)
+{
+	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
+	struct am65_cpsw_tx_chn *tx_chn;
+
+	if (queue >= AM65_CPSW_MAX_TX_QUEUES)
+		return -EINVAL;
+
+	tx_chn = &common->tx_chns[queue];
+
+	coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout / 1000;
+
+	return 0;
+}
+
+static int am65_cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
+				  struct kernel_ethtool_coalesce *kernel_coal,
+				  struct netlink_ext_ack *extack)
+{
+	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
+	struct am65_cpsw_tx_chn *tx_chn;
+
+	tx_chn = &common->tx_chns[0];
+
+	if (coal->rx_coalesce_usecs && coal->rx_coalesce_usecs < 20) {
+		dev_info(common->dev, "defaulting to min value of 20us for rx-usecs\n");
+		coal->rx_coalesce_usecs = 20;
+	}
+
+	if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20) {
+		dev_info(common->dev, "defaulting to min value of 20us for tx-usecs\n");
+		coal->tx_coalesce_usecs = 20;
+	}
+
+	common->rx_pace_timeout = coal->rx_coalesce_usecs * 1000;
+	tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000;
+
+	return 0;
+}
+
+static int am65_cpsw_set_per_queue_coalesce(struct net_device *ndev, u32 queue,
+					    struct ethtool_coalesce *coal)
+{
+	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
+	struct am65_cpsw_tx_chn *tx_chn;
+
+	if (queue >= AM65_CPSW_MAX_TX_QUEUES)
+		return -EINVAL;
+
+	tx_chn = &common->tx_chns[queue];
+
+	if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20) {
+		dev_info(common->dev, "defaulting to min value of 20us for tx-usecs for tx-%u\n",
+			 queue);
+		coal->tx_coalesce_usecs = 20;
+	}
+
+	tx_chn->tx_pace_timeout = coal->tx_coalesce_usecs * 1000;
 
 	return 0;
 }
@@ -732,6 +855,11 @@
 	.get_ts_info		= am65_cpsw_get_ethtool_ts_info,
 	.get_priv_flags		= am65_cpsw_get_ethtool_priv_flags,
 	.set_priv_flags		= am65_cpsw_set_ethtool_priv_flags,
+	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS | ETHTOOL_COALESCE_TX_USECS,
+	.get_coalesce           = am65_cpsw_get_coalesce,
+	.set_coalesce           = am65_cpsw_set_coalesce,
+	.get_per_queue_coalesce = am65_cpsw_get_per_queue_coalesce,
+	.set_per_queue_coalesce = am65_cpsw_set_per_queue_coalesce,
 
 	.get_link		= ethtool_op_get_link,
 	.get_link_ksettings	= am65_cpsw_get_link_ksettings,
diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c	2024-01-28 14:01:31.252353813 -0500
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
+#include <linux/rtnetlink.h>
 #include <linux/mfd/syscon.h>
 #include <linux/sys_soc.h>
 #include <linux/dma/ti-cppi5.h>
@@ -75,6 +76,7 @@
 #define AM65_CPSW_PORTN_REG_TS_CTL_LTYPE2       0x31C
 
 #define AM65_CPSW_SGMII_CONTROL_REG		0x010
+#define AM65_CPSW_SGMII_MR_ADV_ABILITY_REG	0x018
 #define AM65_CPSW_SGMII_CONTROL_MR_AN_ENABLE	BIT(0)
 
 #define AM65_CPSW_CTL_VLAN_AWARE		BIT(1)
@@ -84,6 +86,7 @@
 
 /* AM65_CPSW_P0_REG_CTL */
 #define AM65_CPSW_P0_REG_CTL_RX_CHECKSUM_EN	BIT(0)
+#define AM65_CPSW_P0_REG_CTL_RX_REMAP_VLAN	BIT(16)
 
 /* AM65_CPSW_PORT_REG_PRI_CTL */
 #define AM65_CPSW_PORT_REG_PRI_CTL_RX_PTYPE_RROBIN	BIT(8)
@@ -383,8 +386,8 @@
 	/* set base flow_id */
 	writel(common->rx_flow_id_base,
 	       host_p->port_base + AM65_CPSW_PORT0_REG_FLOW_ID_OFFSET);
-	/* en tx crc offload */
-	writel(AM65_CPSW_P0_REG_CTL_RX_CHECKSUM_EN, host_p->port_base + AM65_CPSW_P0_REG_CTL);
+	writel(AM65_CPSW_P0_REG_CTL_RX_CHECKSUM_EN | AM65_CPSW_P0_REG_CTL_RX_REMAP_VLAN,
+	       host_p->port_base + AM65_CPSW_P0_REG_CTL);
 
 	am65_cpsw_nuss_set_p0_ptype(common);
 
@@ -426,6 +429,8 @@
 	else
 		am65_cpsw_init_host_port_switch(common);
 
+	am65_cpsw_qos_tx_p0_rate_init(common);
+
 	for (i = 0; i < common->rx_chns.descs_num; i++) {
 		skb = __netdev_alloc_skb_ip_align(NULL,
 						  AM65_CPSW_MAX_PACKET_SIZE,
@@ -490,8 +495,10 @@
 					msecs_to_jiffies(1000));
 	if (!i)
 		dev_err(common->dev, "tx timeout\n");
-	for (i = 0; i < common->tx_ch_num; i++)
+	for (i = 0; i < common->tx_ch_num; i++) {
 		napi_disable(&common->tx_chns[i].napi_tx);
+		hrtimer_cancel(&common->tx_chns[i].tx_hrtimer);
+	}
 
 	for (i = 0; i < common->tx_ch_num; i++) {
 		k3_udma_glue_reset_tx_chn(common->tx_chns[i].tx_chn,
@@ -510,6 +517,7 @@
 	}
 
 	napi_disable(&common->napi_rx);
+	hrtimer_cancel(&common->rx_hrtimer);
 
 	for (i = 0; i < AM65_CPSW_MAX_RX_FLOWS; i++)
 		k3_udma_glue_reset_rx_chn(common->rx_chns.rx_chn, i,
@@ -539,6 +547,10 @@
 
 	phylink_disconnect_phy(port->slave.phylink);
 
+	/* QoS cleanup */
+	am65_cpsw_qos_iet_cleanup(ndev);
+	am65_cpsw_qos_cut_thru_cleanup(port);
+
 	ret = am65_cpsw_nuss_common_stop(common);
 	if (ret)
 		return ret;
@@ -563,11 +575,26 @@
 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
 	int ret, i;
+	u32 reg;
 
 	ret = pm_runtime_resume_and_get(common->dev);
 	if (ret < 0)
 		return ret;
 
+	/* Idle MAC port */
+	cpsw_sl_ctl_set(port->slave.mac_sl, CPSW_SL_CTL_CMD_IDLE);
+	cpsw_sl_wait_for_idle(port->slave.mac_sl, 100);
+	cpsw_sl_ctl_reset(port->slave.mac_sl);
+
+	/* soft reset MAC */
+	cpsw_sl_reg_write(port->slave.mac_sl, CPSW_SL_SOFT_RESET, 1);
+	mdelay(1);
+	reg = cpsw_sl_reg_read(port->slave.mac_sl, CPSW_SL_SOFT_RESET);
+	if (reg) {
+		dev_err(common->dev, "soft RESET didn't complete\n");
+		return -ETIMEDOUT;
+	}
+
 	/* Notify the stack of the actual queue counts. */
 	ret = netif_set_real_num_tx_queues(ndev, common->tx_ch_num);
 	if (ret) {
@@ -581,8 +608,12 @@
 		goto runtime_put;
 	}
 
-	for (i = 0; i < common->tx_ch_num; i++)
-		netdev_tx_reset_queue(netdev_get_tx_queue(ndev, i));
+	for (i = 0; i < common->tx_ch_num; i++) {
+		struct netdev_queue *txq = netdev_get_tx_queue(ndev, i);
+
+		netdev_tx_reset_queue(txq);
+		txq->tx_maxrate =  common->tx_chns[i].rate_mbps;
+	}
 
 	ret = am65_cpsw_nuss_common_open(common);
 	if (ret)
@@ -607,6 +638,11 @@
 	/* restore vlan configurations */
 	vlan_for_each(ndev, cpsw_restore_vlans, port);
 
+	/* Initialize QoS */
+	am65_cpsw_qos_iet_init(ndev);
+	am65_cpsw_qos_cut_thru_init(port);
+	am65_cpsw_qos_mqprio_init(port);
+
 	phylink_start(port->slave.phylink);
 
 	return 0;
@@ -780,6 +816,15 @@
 	return ret;
 }
 
+static enum hrtimer_restart am65_cpsw_nuss_rx_timer_callback(struct hrtimer *timer)
+{
+	struct am65_cpsw_common *common =
+			container_of(timer, struct am65_cpsw_common, rx_hrtimer);
+
+	enable_irq(common->rx_chns.irq);
+	return HRTIMER_NORESTART;
+}
+
 static int am65_cpsw_nuss_rx_poll(struct napi_struct *napi_rx, int budget)
 {
 	struct am65_cpsw_common *common = am65_cpsw_napi_to_common(napi_rx);
@@ -807,7 +852,13 @@
 	if (num_rx < budget && napi_complete_done(napi_rx, num_rx)) {
 		if (common->rx_irq_disabled) {
 			common->rx_irq_disabled = false;
-			enable_irq(common->rx_chns.irq);
+			if (unlikely(common->rx_pace_timeout)) {
+				hrtimer_start(&common->rx_hrtimer,
+					      ns_to_ktime(common->rx_pace_timeout),
+					      HRTIMER_MODE_REL_PINNED);
+			} else {
+				enable_irq(common->rx_chns.irq);
+			}
 		}
 	}
 
@@ -913,7 +964,7 @@
 }
 
 static int am65_cpsw_nuss_tx_compl_packets(struct am65_cpsw_common *common,
-					   int chn, unsigned int budget)
+					   int chn, unsigned int budget, bool *tdown)
 {
 	struct device *dev = common->dev;
 	struct am65_cpsw_tx_chn *tx_chn;
@@ -936,6 +987,7 @@
 		if (cppi5_desc_is_tdcm(desc_dma)) {
 			if (atomic_dec_and_test(&common->tdown_cnt))
 				complete(&common->tdown_complete);
+			*tdown = true;
 			break;
 		}
 
@@ -958,7 +1010,7 @@
 }
 
 static int am65_cpsw_nuss_tx_compl_packets_2g(struct am65_cpsw_common *common,
-					      int chn, unsigned int budget)
+					      int chn, unsigned int budget, bool *tdown)
 {
 	struct device *dev = common->dev;
 	struct am65_cpsw_tx_chn *tx_chn;
@@ -979,6 +1031,7 @@
 		if (cppi5_desc_is_tdcm(desc_dma)) {
 			if (atomic_dec_and_test(&common->tdown_cnt))
 				complete(&common->tdown_complete);
+			*tdown = true;
 			break;
 		}
 
@@ -1004,21 +1057,40 @@
 	return num_tx;
 }
 
+static enum hrtimer_restart am65_cpsw_nuss_tx_timer_callback(struct hrtimer *timer)
+{
+	struct am65_cpsw_tx_chn *tx_chns =
+			container_of(timer, struct am65_cpsw_tx_chn, tx_hrtimer);
+
+	enable_irq(tx_chns->irq);
+	return HRTIMER_NORESTART;
+}
+
 static int am65_cpsw_nuss_tx_poll(struct napi_struct *napi_tx, int budget)
 {
 	struct am65_cpsw_tx_chn *tx_chn = am65_cpsw_napi_to_tx_chn(napi_tx);
+	bool tdown = false;
 	int num_tx;
 
 	if (AM65_CPSW_IS_CPSW2G(tx_chn->common))
-		num_tx = am65_cpsw_nuss_tx_compl_packets_2g(tx_chn->common, tx_chn->id, budget);
+		num_tx = am65_cpsw_nuss_tx_compl_packets_2g(tx_chn->common, tx_chn->id,
+							    budget, &tdown);
 	else
-		num_tx = am65_cpsw_nuss_tx_compl_packets(tx_chn->common, tx_chn->id, budget);
+		num_tx = am65_cpsw_nuss_tx_compl_packets(tx_chn->common,
+							 tx_chn->id, budget, &tdown);
 
 	if (num_tx >= budget)
 		return budget;
 
-	if (napi_complete_done(napi_tx, num_tx))
-		enable_irq(tx_chn->irq);
+	if (napi_complete_done(napi_tx, num_tx)) {
+		if (unlikely(tx_chn->tx_pace_timeout && !tdown)) {
+			hrtimer_start(&tx_chn->tx_hrtimer,
+				      ns_to_ktime(tx_chn->tx_pace_timeout),
+				      HRTIMER_MODE_REL_PINNED);
+		} else {
+			enable_irq(tx_chn->irq);
+		}
+	}
 
 	return 0;
 }
@@ -1414,9 +1486,72 @@
 	.ndo_vlan_rx_kill_vid	= am65_cpsw_nuss_ndo_slave_kill_vid,
 	.ndo_eth_ioctl		= am65_cpsw_nuss_ndo_slave_ioctl,
 	.ndo_setup_tc           = am65_cpsw_qos_ndo_setup_tc,
+	.ndo_set_tx_maxrate	= am65_cpsw_qos_ndo_tx_p0_set_maxrate,
 	.ndo_get_devlink_port   = am65_cpsw_ndo_get_devlink_port,
 };
 
+static void am65_cpsw_disable_phy(struct phy *phy)
+{
+	phy_power_off(phy);
+	phy_exit(phy);
+}
+
+static int am65_cpsw_enable_phy(struct phy *phy)
+{
+	int ret;
+
+	ret = phy_init(phy);
+	if (ret < 0)
+		return ret;
+
+	ret = phy_power_on(phy);
+	if (ret < 0) {
+		phy_exit(phy);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void am65_cpsw_disable_serdes_phy(struct am65_cpsw_common *common)
+{
+	struct am65_cpsw_port *port;
+	struct phy *phy;
+	int i;
+
+	for (i = 0; i < common->port_num; i++) {
+		port = &common->ports[i];
+		phy = port->slave.serdes_phy;
+		if (phy)
+			am65_cpsw_disable_phy(phy);
+	}
+}
+
+static int am65_cpsw_init_serdes_phy(struct device *dev, struct device_node *port_np,
+				     struct am65_cpsw_port *port)
+{
+	const char *name = "serdes";
+	struct phy *phy;
+	int ret;
+
+	phy = devm_of_phy_optional_get(dev, port_np, name);
+	if (IS_ERR_OR_NULL(phy))
+		return PTR_ERR_OR_ZERO(phy);
+
+	/* Serdes PHY exists. Store it. */
+	port->slave.serdes_phy = phy;
+
+	ret =  am65_cpsw_enable_phy(phy);
+	if (ret < 0)
+		goto err_phy;
+
+	return 0;
+
+err_phy:
+	devm_phy_put(dev, phy);
+	return ret;
+}
+
 static void am65_cpsw_nuss_mac_config(struct phylink_config *config, unsigned int mode,
 				      const struct phylink_link_state *state)
 {
@@ -1425,9 +1560,26 @@
 	struct am65_cpsw_port *port = container_of(slave, struct am65_cpsw_port, slave);
 	struct am65_cpsw_common *common = port->common;
 
-	if (common->pdata.extra_modes & BIT(state->interface))
+	if (common->pdata.extra_modes & BIT(state->interface)) {
+		if (state->interface == PHY_INTERFACE_MODE_SGMII) {
+			writel(ADVERTISE_SGMII,
+			       port->sgmii_base + AM65_CPSW_SGMII_MR_ADV_ABILITY_REG);
+			cpsw_sl_ctl_set(port->slave.mac_sl, CPSW_SL_CTL_EXT_EN);
+		} else {
+			cpsw_sl_ctl_clr(port->slave.mac_sl, CPSW_SL_CTL_EXT_EN);
+		}
+
+		if (state->interface == PHY_INTERFACE_MODE_USXGMII) {
+			cpsw_sl_ctl_set(port->slave.mac_sl,
+					CPSW_SL_CTL_XGIG | CPSW_SL_CTL_XGMII_EN);
+		} else {
+			cpsw_sl_ctl_clr(port->slave.mac_sl,
+					CPSW_SL_CTL_XGIG | CPSW_SL_CTL_XGMII_EN);
+		}
+
 		writel(AM65_CPSW_SGMII_CONTROL_MR_AN_ENABLE,
 		       port->sgmii_base + AM65_CPSW_SGMII_CONTROL_REG);
+	}
 }
 
 static void am65_cpsw_nuss_mac_link_down(struct phylink_config *config, unsigned int mode,
@@ -1438,6 +1590,7 @@
 	struct am65_cpsw_port *port = container_of(slave, struct am65_cpsw_port, slave);
 	struct am65_cpsw_common *common = port->common;
 	struct net_device *ndev = port->ndev;
+	u32 mac_control;
 	int tmo;
 
 	/* disable forwarding */
@@ -1449,7 +1602,14 @@
 	dev_dbg(common->dev, "down msc_sl %08x tmo %d\n",
 		cpsw_sl_reg_read(port->slave.mac_sl, CPSW_SL_MACSTATUS), tmo);
 
-	cpsw_sl_ctl_reset(port->slave.mac_sl);
+	/* All the bits that am65_cpsw_nuss_mac_link_up() can possibly set */
+	mac_control = CPSW_SL_CTL_GMII_EN | CPSW_SL_CTL_GIG | CPSW_SL_CTL_IFCTL_A |
+		      CPSW_SL_CTL_FULLDUPLEX | CPSW_SL_CTL_RX_FLOW_EN | CPSW_SL_CTL_TX_FLOW_EN;
+	/* If interface mode is RGMII, CPSW_SL_CTL_EXT_EN might have been set for 10 Mbps */
+	if (phy_interface_mode_is_rgmii(interface))
+		mac_control |= CPSW_SL_CTL_EXT_EN;
+	/* Only clear those bits that can be set by am65_cpsw_nuss_mac_link_up() */
+	cpsw_sl_ctl_clr(port->slave.mac_sl, mac_control);
 
 	am65_cpsw_qos_link_down(ndev);
 	netif_tx_stop_all_queues(ndev);
@@ -1466,8 +1626,12 @@
 	u32 mac_control = CPSW_SL_CTL_GMII_EN;
 	struct net_device *ndev = port->ndev;
 
+	/* Bring the port out of idle state */
+	cpsw_sl_ctl_clr(port->slave.mac_sl, CPSW_SL_CTL_CMD_IDLE);
+
 	if (speed == SPEED_1000)
 		mac_control |= CPSW_SL_CTL_GIG;
+	/* TODO: Verify whether in-band is necessary for 10 Mbps RGMII */
 	if (speed == SPEED_10 && phy_interface_mode_is_rgmii(interface))
 		/* Can be used with in band mode only */
 		mac_control |= CPSW_SL_CTL_EXT_EN;
@@ -1488,7 +1652,7 @@
 	/* enable forwarding */
 	cpsw_ale_control_set(common->ale, port->port_id, ALE_PORT_STATE, ALE_PORT_STATE_FORWARD);
 
-	am65_cpsw_qos_link_up(ndev, speed);
+	am65_cpsw_qos_link_up(ndev, speed, duplex);
 	netif_tx_wake_all_queues(ndev);
 }
 
@@ -1521,6 +1685,8 @@
 	for (i = 0; i < common->tx_ch_num; i++) {
 		struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
 
+		irq_set_affinity_hint(tx_chn->irq, NULL);
+
 		if (!IS_ERR_OR_NULL(tx_chn->desc_pool))
 			k3_cppi_desc_pool_destroy(tx_chn->desc_pool);
 
@@ -1538,11 +1704,14 @@
 
 	devm_remove_action(dev, am65_cpsw_nuss_free_tx_chns, common);
 
+	common->tx_ch_rate_msk = 0;
 	for (i = 0; i < common->tx_ch_num; i++) {
 		struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
 
-		if (tx_chn->irq)
+		if (tx_chn->irq) {
+			irq_set_affinity_hint(tx_chn->irq, NULL);
 			devm_free_irq(dev, tx_chn->irq, tx_chn);
+		}
 
 		netif_napi_del(&tx_chn->napi_tx);
 
@@ -1556,6 +1725,35 @@
 	}
 }
 
+static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
+{
+	struct device *dev = common->dev;
+	int i, ret = 0;
+
+	for (i = 0; i < common->tx_ch_num; i++) {
+		struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
+
+		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
+				  am65_cpsw_nuss_tx_poll);
+		hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
+		tx_chn->tx_hrtimer.function = &am65_cpsw_nuss_tx_timer_callback;
+
+		ret = devm_request_irq(dev, tx_chn->irq,
+				       am65_cpsw_nuss_tx_irq,
+				       IRQF_TRIGGER_HIGH,
+				       tx_chn->tx_chn_name, tx_chn);
+		if (ret) {
+			dev_err(dev, "failure requesting tx%u irq %u, %d\n",
+				tx_chn->id, tx_chn->irq, ret);
+			goto err;
+		}
+		irq_set_affinity_hint(tx_chn->irq, get_cpu_mask(i % num_online_cpus()));
+	}
+
+err:
+	return ret;
+}
+
 static int am65_cpsw_nuss_init_tx_chns(struct am65_cpsw_common *common)
 {
 	u32  max_desc_num = ALIGN(AM65_CPSW_MAX_TX_DESC, MAX_SKB_FRAGS);
@@ -1623,6 +1821,12 @@
 			 dev_name(dev), tx_chn->id);
 	}
 
+	ret = am65_cpsw_nuss_ndev_add_tx_napi(common);
+	if (ret) {
+		dev_err(dev, "Failed to add tx NAPI %d\n", ret);
+		goto err;
+	}
+
 err:
 	i = devm_add_action(dev, am65_cpsw_nuss_free_tx_chns, common);
 	if (i) {
@@ -1640,11 +1844,38 @@
 
 	rx_chn = &common->rx_chns;
 
+	irq_set_affinity_hint(rx_chn->irq, NULL);
+
+	if (!IS_ERR_OR_NULL(rx_chn->desc_pool))
+		k3_cppi_desc_pool_destroy(rx_chn->desc_pool);
+
+	if (!IS_ERR_OR_NULL(rx_chn->rx_chn))
+		k3_udma_glue_release_rx_chn(rx_chn->rx_chn);
+}
+
+static void am65_cpsw_nuss_remove_rx_chns(void *data)
+{
+	struct am65_cpsw_common *common = data;
+	struct am65_cpsw_rx_chn *rx_chn;
+	struct device *dev = common->dev;
+
+	rx_chn = &common->rx_chns;
+	devm_remove_action(dev, am65_cpsw_nuss_free_rx_chns, common);
+
+	if (!(rx_chn->irq < 0)) {
+		irq_set_affinity_hint(rx_chn->irq, NULL);
+		devm_free_irq(dev, rx_chn->irq, common);
+	}
+
+	netif_napi_del(&common->napi_rx);
+
 	if (!IS_ERR_OR_NULL(rx_chn->desc_pool))
 		k3_cppi_desc_pool_destroy(rx_chn->desc_pool);
 
 	if (!IS_ERR_OR_NULL(rx_chn->rx_chn))
 		k3_udma_glue_release_rx_chn(rx_chn->rx_chn);
+
+	common->rx_flow_id_base = -1;
 }
 
 static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
@@ -1734,6 +1965,21 @@
 		}
 	}
 
+	netif_napi_add(common->dma_ndev, &common->napi_rx,
+		       am65_cpsw_nuss_rx_poll);
+	hrtimer_init(&common->rx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
+	common->rx_hrtimer.function = &am65_cpsw_nuss_rx_timer_callback;
+
+	ret = devm_request_irq(dev, rx_chn->irq,
+			       am65_cpsw_nuss_rx_irq,
+			       IRQF_TRIGGER_HIGH, dev_name(dev), common);
+	if (ret) {
+		dev_err(dev, "failure requesting rx irq %u, %d\n",
+			rx_chn->irq, ret);
+		goto err;
+	}
+	irq_set_affinity_hint(rx_chn->irq, get_cpu_mask(cpumask_first(cpu_present_mask)));
+
 err:
 	i = devm_add_action(dev, am65_cpsw_nuss_free_rx_chns, common);
 	if (i) {
@@ -1809,11 +2055,6 @@
 		int ret = PTR_ERR(cpts);
 
 		of_node_put(node);
-		if (ret == -EOPNOTSUPP) {
-			dev_info(dev, "cpts disabled\n");
-			return 0;
-		}
-
 		dev_err(dev, "cpts create err %d\n", ret);
 		return ret;
 	}
@@ -1874,6 +2115,7 @@
 		port->fetch_ram_base =
 				common->cpsw_base + AM65_CPSW_NU_FRAM_BASE +
 				(AM65_CPSW_NU_FRAM_PORT_OFFSET * (port_id - 1));
+		port->qos.iet.addfragsize = 1;
 
 		port->slave.mac_sl = cpsw_sl_get("am65", dev, port->port_base);
 		if (IS_ERR(port->slave.mac_sl)) {
@@ -1895,6 +2137,11 @@
 			goto of_node_put;
 		}
 
+		/* Initialize the Serdes PHY for the port */
+		ret = am65_cpsw_init_serdes_phy(dev, port_np, port);
+		if (ret)
+			goto of_node_put;
+
 		port->slave.mac_only =
 				of_property_read_bool(port_np, "ti,mac-only");
 
@@ -2004,17 +2251,36 @@
 	/* Configuring Phylink */
 	port->slave.phylink_config.dev = &port->ndev->dev;
 	port->slave.phylink_config.type = PHYLINK_NETDEV;
-	port->slave.phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD;
-
-	if (phy_interface_mode_is_rgmii(port->slave.phy_if)) {
+	port->slave.phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 |
+						      MAC_1000FD | MAC_5000FD;
+	port->slave.phylink_config.mac_managed_pm = true; /* MAC does PM */
+
+	switch (port->slave.phy_if) {
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
 		phy_interface_set_rgmii(port->slave.phylink_config.supported_interfaces);
-	} else if (port->slave.phy_if == PHY_INTERFACE_MODE_RMII) {
+		break;
+
+	case PHY_INTERFACE_MODE_RMII:
 		__set_bit(PHY_INTERFACE_MODE_RMII,
 			  port->slave.phylink_config.supported_interfaces);
-	} else if (common->pdata.extra_modes & BIT(port->slave.phy_if)) {
-		__set_bit(PHY_INTERFACE_MODE_QSGMII,
-			  port->slave.phylink_config.supported_interfaces);
-	} else {
+		break;
+
+	case PHY_INTERFACE_MODE_QSGMII:
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_USXGMII:
+		if (common->pdata.extra_modes & BIT(port->slave.phy_if)) {
+			__set_bit(port->slave.phy_if,
+				  port->slave.phylink_config.supported_interfaces);
+		} else {
+			dev_err(dev, "selected phy-mode is not supported\n");
+			return -EOPNOTSUPP;
+		}
+		break;
+
+	default:
 		dev_err(dev, "selected phy-mode is not supported\n");
 		return -EOPNOTSUPP;
 	}
@@ -2058,35 +2324,6 @@
 			return ret;
 	}
 
-	netif_napi_add(common->dma_ndev, &common->napi_rx,
-		       am65_cpsw_nuss_rx_poll);
-
-	return ret;
-}
-
-static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
-{
-	struct device *dev = common->dev;
-	int i, ret = 0;
-
-	for (i = 0; i < common->tx_ch_num; i++) {
-		struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
-
-		netif_napi_add_tx(common->dma_ndev, &tx_chn->napi_tx,
-				  am65_cpsw_nuss_tx_poll);
-
-		ret = devm_request_irq(dev, tx_chn->irq,
-				       am65_cpsw_nuss_tx_irq,
-				       IRQF_TRIGGER_HIGH,
-				       tx_chn->tx_chn_name, tx_chn);
-		if (ret) {
-			dev_err(dev, "failure requesting tx%u irq %u, %d\n",
-				tx_chn->id, tx_chn->irq, ret);
-			goto err;
-		}
-	}
-
-err:
 	return ret;
 }
 
@@ -2436,8 +2673,10 @@
 
 			port = am65_ndev_to_port(sl_ndev);
 			port->slave.port_vlan = 0;
-			if (netif_running(sl_ndev))
+			if (netif_running(sl_ndev)) {
 				am65_cpsw_init_port_emac_ale(port);
+				am65_cpsw_qos_cut_thru_cleanup(port);
+			}
 		}
 	}
 	cpsw_ale_control_set(cpsw->ale, HOST_PORT_NUM, ALE_BYPASS, 0);
@@ -2553,18 +2792,13 @@
 	struct am65_cpsw_port *port;
 	int ret = 0, i;
 
-	ret = am65_cpsw_nuss_ndev_add_tx_napi(common);
+	/* init tx channels */
+	ret = am65_cpsw_nuss_init_tx_chns(common);
 	if (ret)
 		return ret;
-
-	ret = devm_request_irq(dev, common->rx_chns.irq,
-			       am65_cpsw_nuss_rx_irq,
-			       IRQF_TRIGGER_HIGH, dev_name(dev), common);
-	if (ret) {
-		dev_err(dev, "failure requesting rx irq %u, %d\n",
-			common->rx_chns.irq, ret);
+	ret = am65_cpsw_nuss_init_rx_chns(common);
+	if (ret)
 		return ret;
-	}
 
 	ret = am65_cpsw_nuss_register_devlink(common);
 	if (ret)
@@ -2573,6 +2807,10 @@
 	for (i = 0; i < common->port_num; i++) {
 		port = &common->ports[i];
 
+		ret = am65_cpsw_nuss_register_port_debugfs(port);
+		if (ret)
+			goto err_cleanup_ndev;
+
 		if (!port->ndev)
 			continue;
 
@@ -2610,10 +2848,8 @@
 
 	common->tx_ch_num = num_tx;
 	ret = am65_cpsw_nuss_init_tx_chns(common);
-	if (ret)
-		return ret;
 
-	return am65_cpsw_nuss_ndev_add_tx_napi(common);
+	return ret;
 }
 
 struct am65_cpsw_soc_pdata {
@@ -2645,7 +2881,7 @@
 };
 
 static const struct am65_cpsw_pdata am64x_cpswxg_pdata = {
-	.quirks = AM64_CPSW_QUIRK_DMA_RX_TDOWN_IRQ,
+	.quirks = AM64_CPSW_QUIRK_DMA_RX_TDOWN_IRQ | AM64_CPSW_QUIRK_CUT_THRU,
 	.ale_dev_id = "am64-cpswxg",
 	.fdqring_mode = K3_RINGACC_RING_MODE_RING,
 };
@@ -2654,7 +2890,21 @@
 	.quirks = 0,
 	.ale_dev_id = "am64-cpswxg",
 	.fdqring_mode = K3_RINGACC_RING_MODE_RING,
-	.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII),
+	.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII),
+};
+
+static const struct am65_cpsw_pdata j721e_cpswxg_pdata = {
+	.quirks = 0,
+	.ale_dev_id = "am64-cpswxg",
+	.fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE,
+	.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII),
+};
+
+static const struct am65_cpsw_pdata j784s4_cpswxg_pdata = {
+	.quirks = 0,
+	.ale_dev_id = "am64-cpswxg",
+	.fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE,
+	.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_USXGMII),
 };
 
 static const struct of_device_id am65_cpsw_nuss_of_mtable[] = {
@@ -2662,6 +2912,8 @@
 	{ .compatible = "ti,j721e-cpsw-nuss", .data = &j721e_pdata},
 	{ .compatible = "ti,am642-cpsw-nuss", .data = &am64x_cpswxg_pdata},
 	{ .compatible = "ti,j7200-cpswxg-nuss", .data = &j7200_cpswxg_pdata},
+	{ .compatible = "ti,j721e-cpswxg-nuss", .data = &j721e_cpswxg_pdata},
+	{ .compatible = "ti,j784s4-cpswxg-nuss", .data = &j784s4_cpswxg_pdata},
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, am65_cpsw_nuss_of_mtable);
@@ -2690,6 +2942,7 @@
 	struct clk *clk;
 	u64 id_temp;
 	int ret, i;
+	int ale_entries;
 
 	common = devm_kzalloc(dev, sizeof(struct am65_cpsw_common), GFP_KERNEL);
 	if (!common)
@@ -2762,14 +3015,6 @@
 
 	am65_cpsw_nuss_get_ver(common);
 
-	/* init tx channels */
-	ret = am65_cpsw_nuss_init_tx_chns(common);
-	if (ret)
-		goto err_of_clear;
-	ret = am65_cpsw_nuss_init_rx_chns(common);
-	if (ret)
-		goto err_of_clear;
-
 	ret = am65_cpsw_nuss_init_host_p(common);
 	if (ret)
 		goto err_of_clear;
@@ -2793,6 +3038,10 @@
 		goto err_of_clear;
 	}
 
+	ale_entries = common->ale->params.ale_entries;
+	common->ale_context = devm_kzalloc(dev,
+					   ale_entries * ALE_ENTRY_WORDS * sizeof(u32),
+					   GFP_KERNEL);
 	ret = am65_cpsw_init_cpts(common);
 	if (ret)
 		goto err_of_clear;
@@ -2809,10 +3058,16 @@
 	if (ret)
 		goto err_free_phylink;
 
-	ret = am65_cpsw_nuss_register_ndevs(common);
+	ret = am65_cpsw_nuss_register_debugfs(common);
 	if (ret)
 		goto err_free_phylink;
 
+	ret = am65_cpsw_nuss_register_ndevs(common);
+	if (ret) {
+		am65_cpsw_nuss_unregister_debugfs(common);
+		goto err_free_phylink;
+	}
+
 	pm_runtime_put(dev);
 	return 0;
 
@@ -2849,6 +3104,7 @@
 	am65_cpsw_nuss_cleanup_ndev(common);
 	am65_cpsw_nuss_phylink_cleanup(common);
 	am65_cpts_release(common->cpts);
+	am65_cpsw_disable_serdes_phy(common);
 
 	if (common->mdio_dev)
 		of_platform_device_destroy(common->mdio_dev, NULL);
@@ -2858,10 +3114,103 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int am65_cpsw_nuss_suspend(struct device *dev)
+{
+	struct am65_cpsw_common *common = dev_get_drvdata(dev);
+	struct am65_cpsw_host *host_p = am65_common_get_host(common);
+	struct am65_cpsw_port *port;
+	struct net_device *ndev;
+	int i, ret;
+
+	cpsw_ale_dump(common->ale, common->ale_context);
+	host_p->vid_context = readl(host_p->port_base + AM65_CPSW_PORT_VLAN_REG_OFFSET);
+	for (i = 0; i < common->port_num; i++) {
+		port = &common->ports[i];
+		ndev = port->ndev;
+
+		if (!ndev)
+			continue;
+
+		port->vid_context = readl(port->port_base + AM65_CPSW_PORT_VLAN_REG_OFFSET);
+		netif_device_detach(ndev);
+		if (netif_running(ndev)) {
+			rtnl_lock();
+			ret = am65_cpsw_nuss_ndo_slave_stop(ndev);
+			rtnl_unlock();
+			if (ret < 0) {
+				netdev_err(ndev, "failed to stop: %d", ret);
+				return ret;
+			}
+		}
+	}
+
+	am65_cpts_suspend(common->cpts);
+
+	am65_cpsw_nuss_remove_rx_chns(common);
+	am65_cpsw_nuss_remove_tx_chns(common);
+
+	return 0;
+}
+
+static int am65_cpsw_nuss_resume(struct device *dev)
+{
+	struct am65_cpsw_common *common = dev_get_drvdata(dev);
+	struct am65_cpsw_port *port;
+	struct net_device *ndev;
+	int i, ret;
+	struct am65_cpsw_host *host_p = am65_common_get_host(common);
+
+	ret = am65_cpsw_nuss_init_tx_chns(common);
+	if (ret)
+		return ret;
+	ret = am65_cpsw_nuss_init_rx_chns(common);
+	if (ret)
+		return ret;
+
+	/* If RX IRQ was disabled before suspend, keep it disabled */
+	if (common->rx_irq_disabled)
+		disable_irq(common->rx_chns.irq);
+
+	am65_cpts_resume(common->cpts);
+
+	for (i = 0; i < common->port_num; i++) {
+		port = &common->ports[i];
+		ndev = port->ndev;
+
+		if (!ndev)
+			continue;
+
+		if (netif_running(ndev)) {
+			rtnl_lock();
+			ret = am65_cpsw_nuss_ndo_slave_open(ndev);
+			rtnl_unlock();
+			if (ret < 0) {
+				netdev_err(ndev, "failed to start: %d", ret);
+				return ret;
+			}
+		}
+
+		netif_device_attach(ndev);
+		writel(port->vid_context, port->port_base + AM65_CPSW_PORT_VLAN_REG_OFFSET);
+	}
+
+	writel(host_p->vid_context, host_p->port_base + AM65_CPSW_PORT_VLAN_REG_OFFSET);
+	cpsw_ale_restore(common->ale, common->ale_context);
+
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops am65_cpsw_nuss_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(am65_cpsw_nuss_suspend, am65_cpsw_nuss_resume)
+};
+
 static struct platform_driver am65_cpsw_nuss_driver = {
 	.driver = {
 		.name	 = AM65_CPSW_DRV_NAME,
 		.of_match_table = am65_cpsw_nuss_of_mtable,
+		.pm = &am65_cpsw_nuss_dev_pm_ops,
 	},
 	.probe = am65_cpsw_nuss_probe,
 	.remove = am65_cpsw_nuss_remove,
diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h	2024-01-28 14:01:31.252353813 -0500
@@ -6,6 +6,7 @@
 #ifndef AM65_CPSW_NUSS_H_
 #define AM65_CPSW_NUSS_H_
 
+#include <linux/debugfs.h>
 #include <linux/if_ether.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -32,6 +33,7 @@
 	struct device_node		*phy_node;
 	phy_interface_t			phy_if;
 	struct phy			*ifphy;
+	struct phy			*serdes_phy;
 	bool				rx_pause;
 	bool				tx_pause;
 	u8				mac_addr[ETH_ALEN];
@@ -55,12 +57,17 @@
 	bool				rx_ts_enabled;
 	struct am65_cpsw_qos		qos;
 	struct devlink_port		devlink_port;
+	struct dentry			*debugfs_port;
+	/* Only for suspend resume context */
+	u32				vid_context;
 };
 
 struct am65_cpsw_host {
 	struct am65_cpsw_common		*common;
 	void __iomem			*port_base;
 	void __iomem			*stat_base;
+	/* Only for suspend resume context */
+	u32				vid_context;
 };
 
 struct am65_cpsw_tx_chn {
@@ -70,10 +77,13 @@
 	struct k3_cppi_desc_pool *desc_pool;
 	struct k3_udma_glue_tx_channel *tx_chn;
 	spinlock_t lock; /* protect TX rings in multi-port mode */
+	struct hrtimer tx_hrtimer;
+	unsigned long tx_pace_timeout;
 	int irq;
 	u32 id;
 	u32 descs_num;
 	char tx_chn_name[128];
+	u32 rate_mbps;
 };
 
 struct am65_cpsw_rx_chn {
@@ -87,6 +97,7 @@
 
 #define AM65_CPSW_QUIRK_I2027_NO_TX_CSUM BIT(0)
 #define AM64_CPSW_QUIRK_DMA_RX_TDOWN_IRQ BIT(1)
+#define AM64_CPSW_QUIRK_CUT_THRU	 BIT(2)
 
 struct am65_cpsw_pdata {
 	u32	quirks;
@@ -121,6 +132,7 @@
 	int			usage_count; /* number of opened ports */
 	struct cpsw_ale		*ale;
 	int			tx_ch_num;
+	u32			tx_ch_rate_msk;
 	u32			rx_flow_id_base;
 
 	struct am65_cpsw_tx_chn	tx_chns[AM65_CPSW_MAX_TX_QUEUES];
@@ -131,6 +143,8 @@
 	struct napi_struct	napi_rx;
 
 	bool			rx_irq_disabled;
+	struct hrtimer		rx_hrtimer;
+	unsigned long		rx_pace_timeout;
 
 	u32			nuss_ver;
 	u32			cpsw_ver;
@@ -138,6 +152,8 @@
 	bool			pf_p0_rx_ptype_rrobin;
 	struct am65_cpts	*cpts;
 	int			est_enabled;
+	int			iet_enabled;
+	unsigned int		cut_thru_enabled;
 
 	bool		is_emac_mode;
 	u16			br_members;
@@ -146,6 +162,10 @@
 	struct net_device *hw_bridge_dev;
 	struct notifier_block am65_cpsw_netdevice_nb;
 	unsigned char switch_id[MAX_PHYS_ITEM_ID_LEN];
+
+	struct dentry		*debugfs_root;
+	/* only for suspend/resume context restore */
+	u32			*ale_context;
 };
 
 struct am65_cpsw_ndev_stats {
@@ -190,4 +210,8 @@
 
 bool am65_cpsw_port_dev_check(const struct net_device *dev);
 
+int am65_cpsw_nuss_register_port_debugfs(struct am65_cpsw_port *port);
+int am65_cpsw_nuss_register_debugfs(struct am65_cpsw_common *common);
+void am65_cpsw_nuss_unregister_debugfs(struct am65_cpsw_common *common);
+
 #endif /* AM65_CPSW_NUSS_H_ */
diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c
--- a/drivers/net/ethernet/ti/am65-cpsw-qos.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c	2024-01-28 14:01:31.252353813 -0500
@@ -4,8 +4,11 @@
  *
  * quality of service module includes:
  * Enhanced Scheduler Traffic (EST - P802.1Qbv/D2.2)
+ * Interspersed Express Traffic (IET - P802.3br/D2.0)
  */
 
+#include <linux/bitfield.h>
+#include <linux/math64.h>
 #include <linux/pm_runtime.h>
 #include <linux/time.h>
 #include <net/pkt_cls.h>
@@ -16,14 +19,29 @@
 #include "cpsw_ale.h"
 
 #define AM65_CPSW_REG_CTL			0x004
+#define AM65_CPSW_REG_FREQ			0x05c
 #define AM65_CPSW_PN_REG_CTL			0x004
+#define AM65_CPSW_PN_REG_MAX_BLKS		0x008
+#define AM65_CPSW_PN_REG_TX_PRI_MAP		0x018
+#define AM65_CPSW_PN_REG_RX_PRI_MAP		0x020
+#define AM65_CPSW_PN_REG_IET_CTRL		0x040
+#define AM65_CPSW_PN_REG_IET_STATUS		0x044
+#define AM65_CPSW_PN_REG_IET_VERIFY		0x048
 #define AM65_CPSW_PN_REG_FIFO_STATUS		0x050
 #define AM65_CPSW_PN_REG_EST_CTL		0x060
+#define AM65_CPSW_PN_REG_PRI_CIR(pri)		(0x140 + 4 * (pri))
+#define AM65_CPSW_PN_REG_PRI_EIR(pri)		(0x160 + 4 * (pri))
+
+#define AM64_CPSW_PN_CUT_THRU			0x3C0
+#define AM64_CPSW_PN_SPEED			0x3C4
 
 /* AM65_CPSW_REG_CTL register fields */
+#define AM65_CPSW_CTL_IET_EN			BIT(17)
 #define AM65_CPSW_CTL_EST_EN			BIT(18)
+#define AM64_CPSW_CTL_CUT_THRU_EN		BIT(19)
 
 /* AM65_CPSW_PN_REG_CTL register fields */
+#define AM65_CPSW_PN_CTL_IET_PORT_EN		BIT(16)
 #define AM65_CPSW_PN_CTL_EST_PORT_EN		BIT(17)
 
 /* AM65_CPSW_PN_REG_EST_CTL register fields */
@@ -34,6 +52,27 @@
 #define AM65_CPSW_PN_EST_ONEPRI			BIT(4)
 #define AM65_CPSW_PN_EST_TS_PRI_MSK		GENMASK(7, 5)
 
+/* AM65_CPSW_PN_REG_IET_CTRL register fields */
+#define AM65_CPSW_PN_IET_MAC_PENABLE		BIT(0)
+#define AM65_CPSW_PN_IET_MAC_DISABLEVERIFY	BIT(2)
+#define AM65_CPSW_PN_IET_MAC_LINKFAIL		BIT(3)
+#define AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK	GENMASK(10, 8)
+#define AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_OFFSET	8
+#define AM65_CPSW_PN_IET_PREMPT_MASK		GENMASK(23, 16)
+#define AM65_CPSW_PN_IET_PREMPT_OFFSET		16
+
+/* AM65_CPSW_PN_REG_IET_STATUS register fields */
+#define AM65_CPSW_PN_MAC_VERIFIED		BIT(0)
+#define AM65_CPSW_PN_MAC_VERIFY_FAIL		BIT(1)
+#define AM65_CPSW_PN_MAC_RESPOND_ERR		BIT(2)
+#define AM65_CPSW_PN_MAC_VERIFY_ERR		BIT(3)
+
+/* AM65_CPSW_PN_REG_IET_VERIFY register fields */
+/* 10 msec converted to NSEC */
+#define AM65_CPSW_IET_VERIFY_CNT_MS		(10)
+#define AM65_CPSW_IET_VERIFY_CNT_NS		(AM65_CPSW_IET_VERIFY_CNT_MS * \
+						 NSEC_PER_MSEC)
+
 /* AM65_CPSW_PN_REG_FIFO_STATUS register fields */
 #define AM65_CPSW_PN_FST_TX_PRI_ACTIVE_MSK	GENMASK(7, 0)
 #define AM65_CPSW_PN_FST_TX_E_MAC_ALLOW_MSK	GENMASK(15, 8)
@@ -49,12 +88,258 @@
 #define AM65_CPSW_FETCH_ALLOW_MSK		GENMASK(7, 0)
 #define AM65_CPSW_FETCH_ALLOW_MAX		AM65_CPSW_FETCH_ALLOW_MSK
 
+/* Cut-Thru AM64_CPSW_PN_CUT_THRU */
+#define  AM64_PN_CUT_THRU_TX_PRI		GENMASK(7, 0)
+#define  AM64_PN_CUT_THRU_RX_PRI		GENMASK(15, 8)
+
+/* Cut-Thru AM64_CPSW_PN_SPEED */
+#define  AM64_PN_SPEED_VAL			GENMASK(3, 0)
+#define  AM64_PN_SPEED_AUTO_EN			BIT(8)
+#define  AM64_PN_AUTO_SPEED			GENMASK(15, 12)
+
+/* AM65_CPSW_PN_REG_MAX_BLKS fields for IET and No IET cases */
+/* 7 blocks for pn_rx_max_blks, 13 for pn_tx_max_blks*/
+#define AM65_CPSW_PN_TX_RX_MAX_BLKS_IET		0xD07
+#define AM65_CPSW_PN_TX_RX_MAX_BLKS_DEFAULT	0x1004
+
 enum timer_act {
 	TACT_PROG,		/* need program timer */
 	TACT_NEED_STOP,		/* need stop first */
 	TACT_SKIP_PROG,		/* just buffer can be updated */
 };
 
+/* number of traffic classes (fifos) per port */
+#define AM65_CPSW_PN_TC_NUM			8
+#define AM65_CPSW_PN_TX_PRI_MAP_DEF		0x76543210
+
+static int am65_cpsw_mqprio_setup(struct net_device *ndev, void *type_data);
+
+/* Fetch command count it's number of bytes in Gigabit mode or nibbles in
+ * 10/100Mb mode. So, having speed and time in ns, recalculate ns to number of
+ * bytes/nibbles that can be sent while transmission on given speed.
+ */
+static int am65_est_cmd_ns_to_cnt(u64 ns, int link_speed)
+{
+	u64 temp;
+
+	temp = ns * link_speed;
+	if (link_speed < SPEED_1000)
+		temp <<= 1;
+
+	return DIV_ROUND_UP(temp, 8 * 1000);
+}
+
+/* IET */
+
+static void am65_cpsw_iet_enable(struct am65_cpsw_common *common)
+{
+	int common_enable = 0;
+	u32 val;
+	int i;
+
+	for (i = 0; i < common->port_num; i++)
+		common_enable |= !!common->ports[i].qos.iet.mask;
+
+	val = readl(common->cpsw_base + AM65_CPSW_REG_CTL);
+
+	if (common_enable)
+		val |= AM65_CPSW_CTL_IET_EN;
+	else
+		val &= ~AM65_CPSW_CTL_IET_EN;
+
+	writel(val, common->cpsw_base + AM65_CPSW_REG_CTL);
+	common->iet_enabled = common_enable;
+}
+
+static void am65_cpsw_port_iet_enable(struct am65_cpsw_port *port,
+				      u32 mask)
+{
+	u32 val;
+
+	val = readl(port->port_base + AM65_CPSW_PN_REG_CTL);
+	if (mask)
+		val |= AM65_CPSW_PN_CTL_IET_PORT_EN;
+	else
+		val &= ~AM65_CPSW_PN_CTL_IET_PORT_EN;
+
+	writel(val, port->port_base + AM65_CPSW_PN_REG_CTL);
+	port->qos.iet.mask = mask;
+}
+
+static int am65_cpsw_iet_verify(struct am65_cpsw_port *port)
+{
+	int try;
+	u32 val;
+
+	netdev_info(port->ndev, "Starting IET/FPE MAC Verify\n");
+	/* Set verify timeout depending on link speed. It is 10 msec
+	 * in wireside clocks
+	 */
+	val = am65_est_cmd_ns_to_cnt(AM65_CPSW_IET_VERIFY_CNT_NS,
+				     port->qos.link_speed);
+	writel(val, port->port_base + AM65_CPSW_PN_REG_IET_VERIFY);
+
+	/* By experiment, keep this about 20 * 50 msec = 1000 msec.
+	 * Usually succeeds in one try. But at times it takes more
+	 * attempts especially at initial boot. Try for 20 times
+	 * before give up
+	 */
+	try = 20;
+	do {
+		/* Enable IET Preemption for the port and
+		 * reset LINKFAIL bit to start Verify.
+		 */
+		writel(AM65_CPSW_PN_IET_MAC_PENABLE,
+		       port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
+
+		/* Takes 10 msec to complete this in h/w assuming other
+		 * side is already ready. However since both side might
+		 * take variable setup/config time, need to Wait for
+		 * additional time. Chose 50 msec through trials
+		 */
+		msleep(50);
+
+		val = readl(port->port_base + AM65_CPSW_PN_REG_IET_STATUS);
+		if (val & AM65_CPSW_PN_MAC_VERIFIED)
+			break;
+
+		if (val & AM65_CPSW_PN_MAC_VERIFY_FAIL) {
+			netdev_dbg(port->ndev,
+				   "IET MAC verify failed, trying again");
+			/* Reset the verify state machine by writing 1
+			 * to LINKFAIL
+			 */
+			writel(AM65_CPSW_PN_IET_MAC_LINKFAIL,
+			       port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
+		}
+
+		if (val & AM65_CPSW_PN_MAC_RESPOND_ERR) {
+			netdev_err(port->ndev, "IET MAC respond error");
+			return -ENODEV;
+		}
+
+		if (val & AM65_CPSW_PN_MAC_VERIFY_ERR) {
+			netdev_err(port->ndev, "IET MAC verify error");
+			return -ENODEV;
+		}
+
+	} while (try-- > 0);
+
+	if (try <= 0) {
+		netdev_err(port->ndev, "IET MAC Verify/Response timeout");
+		return -ENODEV;
+	}
+
+	netdev_info(port->ndev, "IET/FPE MAC Verify Success\n");
+	return 0;
+}
+
+static void am65_cpsw_iet_config_mac_preempt(struct am65_cpsw_port *port,
+					     bool enable, bool force)
+{
+	struct am65_cpsw_iet *iet = &port->qos.iet;
+	u32 val;
+
+	/* Enable pre-emption queues and force mode if no mac verify */
+	val = 0;
+	if (enable) {
+		if (!force) {
+			/* AM65_CPSW_PN_IET_MAC_PENABLE already
+			 * set as part of MAC Verify. So read
+			 * modify
+			 */
+			val = readl(port->port_base +
+				    AM65_CPSW_PN_REG_IET_CTRL);
+		} else {
+			val |= AM65_CPSW_PN_IET_MAC_PENABLE;
+			val |= AM65_CPSW_PN_IET_MAC_DISABLEVERIFY;
+		}
+		val |= ((iet->fpe_mask_configured <<
+			AM65_CPSW_PN_IET_PREMPT_OFFSET) &
+			AM65_CPSW_PN_IET_PREMPT_MASK);
+		val |= ((iet->addfragsize <<
+			AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_OFFSET) &
+			AM65_CPSW_PN_IET_MAC_MAC_ADDFRAGSIZE_MASK);
+	}
+	writel(val, port->port_base + AM65_CPSW_PN_REG_IET_CTRL);
+	iet->fpe_enabled = enable;
+}
+
+static void am65_cpsw_iet_set(struct net_device *ndev)
+{
+	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+	struct am65_cpsw_common *common = port->common;
+	struct am65_cpsw_iet *iet = &port->qos.iet;
+
+	/* For IET, Change MAX_BLKS */
+	writel(AM65_CPSW_PN_TX_RX_MAX_BLKS_IET,
+	       port->port_base + AM65_CPSW_PN_REG_MAX_BLKS);
+
+	am65_cpsw_port_iet_enable(port, iet->fpe_mask_configured);
+	am65_cpsw_iet_enable(common);
+}
+
+static int am65_cpsw_iet_fpe_enable(struct am65_cpsw_port *port, bool verify)
+{
+	int ret;
+
+	if (verify) {
+		ret = am65_cpsw_iet_verify(port);
+		if (ret)
+			return ret;
+	}
+
+	am65_cpsw_iet_config_mac_preempt(port, true, !verify);
+
+	return 0;
+}
+
+void am65_cpsw_qos_iet_init(struct net_device *ndev)
+{
+	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+	struct am65_cpsw_common *common = port->common;
+	struct am65_cpsw_iet *iet = &port->qos.iet;
+
+	/* Enable IET FPE only if user has enabled priv flag for iet frame
+	 * preemption.
+	 */
+	if (!iet->fpe_configured) {
+		iet->fpe_mask_configured = 0;
+		return;
+	}
+	/* Use highest priority queue as express queue and others
+	 * as preemptible queues.
+	 */
+	iet->fpe_mask_configured = GENMASK(common->tx_ch_num - 2, 0);
+
+	/* Init work queue for IET MAC verify process */
+	iet->ndev = ndev;
+
+	am65_cpsw_iet_set(ndev);
+}
+
+static void am65_cpsw_iet_fpe_disable(struct am65_cpsw_port *port)
+{
+	struct am65_cpsw_iet *iet = &port->qos.iet;
+
+	am65_cpsw_iet_config_mac_preempt(port, false,
+					 !iet->mac_verify_configured);
+}
+
+void am65_cpsw_qos_iet_cleanup(struct net_device *ndev)
+{
+	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
+
+	/* restore MAX_BLKS to default */
+	writel(AM65_CPSW_PN_TX_RX_MAX_BLKS_DEFAULT,
+	       port->port_base + AM65_CPSW_PN_REG_MAX_BLKS);
+
+	am65_cpsw_iet_fpe_disable(port);
+	am65_cpsw_port_iet_enable(port, 0);
+	am65_cpsw_iet_enable(common);
+}
+
 static int am65_cpsw_port_est_enabled(struct am65_cpsw_port *port)
 {
 	return port->qos.est_oper || port->qos.est_admin;
@@ -224,21 +509,6 @@
 	am65_cpsw_admin_to_oper(ndev);
 }
 
-/* Fetch command count it's number of bytes in Gigabit mode or nibbles in
- * 10/100Mb mode. So, having speed and time in ns, recalculate ns to number of
- * bytes/nibbles that can be sent while transmission on given speed.
- */
-static int am65_est_cmd_ns_to_cnt(u64 ns, int link_speed)
-{
-	u64 temp;
-
-	temp = ns * link_speed;
-	if (link_speed < SPEED_1000)
-		temp <<= 1;
-
-	return DIV_ROUND_UP(temp, 8 * 1000);
-}
-
 static void __iomem *am65_cpsw_est_set_sched_cmds(void __iomem *addr,
 						  int fetch_cnt,
 						  int fetch_allow)
@@ -446,6 +716,7 @@
 	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 	struct am65_cpts *cpts = common->cpts;
 	int ret = 0, tact = TACT_PROG;
+	u64 cur_time, n;
 
 	am65_cpsw_est_update_state(ndev);
 
@@ -468,13 +739,21 @@
 	if (tact == TACT_PROG)
 		am65_cpsw_timer_stop(ndev);
 
-	if (!est_new->taprio.base_time)
-		est_new->taprio.base_time = am65_cpts_ns_gettime(cpts);
-
 	am65_cpsw_port_est_get_buf_num(ndev, est_new);
 	am65_cpsw_est_set_sched_list(ndev, est_new);
 	am65_cpsw_port_est_assign_buf_num(ndev, est_new->buf);
 
+	/* If the base-time is in the past, start schedule from the time:
+	 * base_time + (N*cycle_time)
+	 * where N is the smallest possible integer such that the above
+	 * time is in the future.
+	 */
+	cur_time = am65_cpts_ns_gettime(cpts);
+	if (est_new->taprio.base_time < cur_time) {
+		n = div64_u64(cur_time - est_new->taprio.base_time, est_new->taprio.cycle_time);
+		est_new->taprio.base_time += (n + 1) * est_new->taprio.cycle_time;
+	}
+
 	am65_cpsw_est_set(ndev, est_new->taprio.enable);
 
 	if (tact == TACT_PROG) {
@@ -767,6 +1046,8 @@
 	switch (type) {
 	case TC_SETUP_QDISC_TAPRIO:
 		return am65_cpsw_setup_taprio(ndev, type_data);
+	case TC_SETUP_QDISC_MQPRIO:
+		return am65_cpsw_mqprio_setup(ndev, type_data);
 	case TC_SETUP_BLOCK:
 		return am65_cpsw_qos_setup_tc_block(ndev, type_data);
 	default:
@@ -774,9 +1055,36 @@
 	}
 }
 
-void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed)
+static void am65_cpsw_iet_link_up(struct net_device *ndev)
 {
 	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+	struct am65_cpsw_iet *iet = &port->qos.iet;
+
+	if (!iet->fpe_configured)
+		return;
+
+	/* Schedule MAC Verify and enable IET FPE if configured */
+	if (iet->mac_verify_configured) {
+		am65_cpsw_iet_fpe_enable(port, true);
+	} else {
+		/* Force IET FPE here */
+		netdev_info(ndev, "IET Enable Force mode\n");
+		am65_cpsw_iet_fpe_enable(port, false);
+	}
+}
+
+static void am65_cpsw_cut_thru_link_up(struct am65_cpsw_port *port);
+static void am65_cpsw_tx_pn_shaper_link_up(struct am65_cpsw_port *port);
+
+void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed, int duplex)
+{
+	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+
+	port->qos.link_speed = link_speed;
+	port->qos.duplex = duplex;
+	am65_cpsw_iet_link_up(ndev);
+	am65_cpsw_cut_thru_link_up(port);
+	am65_cpsw_tx_pn_shaper_link_up(port);
 
 	if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS))
 		return;
@@ -789,6 +1097,8 @@
 {
 	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
 
+	am65_cpsw_iet_fpe_disable(port);
+
 	if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS))
 		return;
 
@@ -797,3 +1107,536 @@
 
 	port->qos.link_speed = SPEED_UNKNOWN;
 }
+
+static void am65_cpsw_cut_thru_dump(struct am65_cpsw_port *port)
+{
+	struct am65_cpsw_common *common = port->common;
+	u32 contro, cut_thru, speed;
+
+	contro = readl(common->cpsw_base + AM65_CPSW_REG_CTL);
+	cut_thru = readl(port->port_base + AM64_CPSW_PN_CUT_THRU);
+	speed = readl(port->port_base + AM64_CPSW_PN_SPEED);
+	dev_dbg(common->dev, "Port%u: cut_thru dump control:%08x cut_thru:%08x hwspeed:%08x\n",
+		port->port_id, contro, cut_thru, speed);
+}
+
+static void am65_cpsw_cut_thru_enable(struct am65_cpsw_common *common)
+{
+	u32 val;
+
+	if (common->cut_thru_enabled) {
+		common->cut_thru_enabled++;
+		return;
+	}
+
+	/* Populate CPSW VBUS freq for auto speed detection */
+	writel(common->bus_freq / 1000000,
+	       common->cpsw_base + AM65_CPSW_REG_FREQ);
+
+	val = readl(common->cpsw_base + AM65_CPSW_REG_CTL);
+	val |= AM64_CPSW_CTL_CUT_THRU_EN;
+	writel(val, common->cpsw_base + AM65_CPSW_REG_CTL);
+	common->cut_thru_enabled++;
+}
+
+void am65_cpsw_qos_cut_thru_init(struct am65_cpsw_port *port)
+{
+	struct am65_cpsw_cut_thru *cut_thru = &port->qos.cut_thru;
+	struct am65_cpsw_common *common = port->common;
+
+	/* Enable cut_thr only if user has enabled priv flag */
+	if (!cut_thru->enable)
+		return;
+
+	if (common->is_emac_mode) {
+		cut_thru->enable = false;
+		dev_info(common->dev, "Disable cut-thru, need Switch mode\n");
+		return;
+	}
+
+	am65_cpsw_cut_thru_enable(common);
+
+	/* en auto speed */
+	writel(AM64_PN_SPEED_AUTO_EN, port->port_base + AM64_CPSW_PN_SPEED);
+	dev_info(common->dev, "Init cut_thru\n");
+	am65_cpsw_cut_thru_dump(port);
+}
+
+static void am65_cpsw_cut_thru_disable(struct am65_cpsw_common *common)
+{
+	u32 val;
+
+	if (--common->cut_thru_enabled)
+		return;
+
+	val = readl(common->cpsw_base + AM65_CPSW_REG_CTL);
+	val &= ~AM64_CPSW_CTL_CUT_THRU_EN;
+	writel(val, common->cpsw_base + AM65_CPSW_REG_CTL);
+}
+
+void am65_cpsw_qos_cut_thru_cleanup(struct am65_cpsw_port *port)
+{
+	struct am65_cpsw_cut_thru *cut_thru = &port->qos.cut_thru;
+	struct am65_cpsw_common *common = port->common;
+
+	if (!cut_thru->enable)
+		return;
+
+	writel(0, port->port_base + AM64_CPSW_PN_CUT_THRU);
+	writel(0, port->port_base + AM64_CPSW_PN_SPEED);
+
+	am65_cpsw_cut_thru_disable(common);
+	dev_info(common->dev, "Cleanup cut_thru\n");
+	am65_cpsw_cut_thru_dump(port);
+}
+
+static u32 am65_cpsw_cut_thru_speed2hw(int link_speed)
+{
+	switch (link_speed) {
+	case SPEED_10:
+		return 1;
+	case SPEED_100:
+		return 2;
+	case SPEED_1000:
+		return 3;
+	default:
+		return 0;
+	}
+}
+
+static void am65_cpsw_cut_thru_link_up(struct am65_cpsw_port *port)
+{
+	struct am65_cpsw_cut_thru *cut_thru = &port->qos.cut_thru;
+	struct am65_cpsw_common *common = port->common;
+	u32 val, speed;
+
+	if (!cut_thru->enable)
+		return;
+
+	writel(AM64_PN_SPEED_AUTO_EN, port->port_base + AM64_CPSW_PN_SPEED);
+	/* barrier */
+	readl(port->port_base + AM64_CPSW_PN_SPEED);
+	/* HW need 15us in 10/100 mode and 3us in 1G mode auto speed detection
+	 * add delay with some margin
+	 */
+	usleep_range(40, 50);
+	val = readl(port->port_base + AM64_CPSW_PN_SPEED);
+	speed = FIELD_GET(AM64_PN_AUTO_SPEED, val);
+	if (!speed) {
+		dev_warn(common->dev,
+			 "Port%u: cut_thru no speed auto detected switch to manual\n",
+			 port->port_id);
+		speed = am65_cpsw_cut_thru_speed2hw(port->qos.link_speed);
+		if (!speed) {
+			dev_err(common->dev,
+				"Port%u: cut_thru speed configuration failed\n",
+				port->port_id);
+			return;
+		}
+		val = FIELD_PREP(AM64_PN_SPEED_VAL, speed);
+		writel(val, port->port_base + AM64_CPSW_PN_SPEED);
+	}
+
+	val = FIELD_PREP(AM64_PN_CUT_THRU_TX_PRI, cut_thru->tx_pri_mask) |
+	      FIELD_PREP(AM64_PN_CUT_THRU_RX_PRI, cut_thru->rx_pri_mask);
+
+	if (port->qos.duplex) {
+		writel(val, port->port_base + AM64_CPSW_PN_CUT_THRU);
+		dev_info(common->dev, "Port%u: Enable cut_thru rx:%08x tx:%08x hwspeed:%u (%08x)\n",
+			 port->port_id,
+			 cut_thru->rx_pri_mask, cut_thru->tx_pri_mask,
+			 speed, val);
+	} else {
+		writel(0, port->port_base + AM64_CPSW_PN_CUT_THRU);
+		dev_info(common->dev, "Port%u: Disable cut_thru duplex=%d\n",
+			 port->port_id, port->qos.duplex);
+	}
+	am65_cpsw_cut_thru_dump(port);
+}
+
+static u32
+am65_cpsw_qos_tx_rate_calc(u32 rate_mbps, unsigned long bus_freq)
+{
+	u32 ir;
+
+	bus_freq /= 1000000;
+	ir = DIV_ROUND_UP(((u64)rate_mbps * 32768),  bus_freq);
+	return ir;
+}
+
+static void
+am65_cpsw_qos_tx_p0_rate_apply(struct am65_cpsw_common *common,
+			       int tx_ch, u32 rate_mbps)
+{
+	struct am65_cpsw_host *host = am65_common_get_host(common);
+	u32 ch_cir;
+	int i;
+
+	ch_cir = am65_cpsw_qos_tx_rate_calc(rate_mbps, common->bus_freq);
+	writel(ch_cir, host->port_base + AM65_CPSW_PN_REG_PRI_CIR(tx_ch));
+
+	/* update rates for every port tx queues */
+	for (i = 0; i < common->port_num; i++) {
+		struct net_device *ndev = common->ports[i].ndev;
+
+		if (!ndev)
+			continue;
+		netdev_get_tx_queue(ndev, tx_ch)->tx_maxrate = rate_mbps;
+	}
+}
+
+int am65_cpsw_qos_ndo_tx_p0_set_maxrate(struct net_device *ndev,
+					int queue, u32 rate_mbps)
+{
+	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+	struct am65_cpsw_common *common = port->common;
+	struct am65_cpsw_tx_chn *tx_chn;
+	u32 ch_rate, tx_ch_rate_msk_new;
+	u32 ch_msk = 0;
+	int ret;
+
+	dev_dbg(common->dev, "apply TX%d rate limiting %uMbps tx_rate_msk%x\n",
+		queue, rate_mbps, common->tx_ch_rate_msk);
+
+	if (common->pf_p0_rx_ptype_rrobin) {
+		dev_err(common->dev, "TX Rate Limiting failed - rrobin mode\n");
+		return -EINVAL;
+	}
+
+	ch_rate = netdev_get_tx_queue(ndev, queue)->tx_maxrate;
+	if (ch_rate == rate_mbps)
+		return 0;
+
+	ret = pm_runtime_get_sync(common->dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(common->dev);
+		return ret;
+	}
+	ret = 0;
+
+	tx_ch_rate_msk_new = common->tx_ch_rate_msk;
+	if (rate_mbps && !(tx_ch_rate_msk_new & BIT(queue))) {
+		tx_ch_rate_msk_new |= BIT(queue);
+		ch_msk = GENMASK(common->tx_ch_num - 1, queue);
+		ch_msk = tx_ch_rate_msk_new ^ ch_msk;
+	} else if (!rate_mbps) {
+		tx_ch_rate_msk_new &= ~BIT(queue);
+		ch_msk = queue ? GENMASK(queue - 1, 0) : 0;
+		ch_msk = tx_ch_rate_msk_new & ch_msk;
+	}
+
+	if (ch_msk) {
+		dev_err(common->dev, "TX rate limiting has to be enabled sequentially hi->lo tx_rate_msk:%x tx_rate_msk_new:%x\n",
+			common->tx_ch_rate_msk, tx_ch_rate_msk_new);
+		ret = -EINVAL;
+		goto exit_put;
+	}
+
+	tx_chn = &common->tx_chns[queue];
+	tx_chn->rate_mbps = rate_mbps;
+	common->tx_ch_rate_msk = tx_ch_rate_msk_new;
+
+	if (!common->usage_count)
+		/* will be applied on next netif up */
+		goto exit_put;
+
+	am65_cpsw_qos_tx_p0_rate_apply(common, queue, rate_mbps);
+
+exit_put:
+	pm_runtime_put(common->dev);
+	return ret;
+}
+
+void am65_cpsw_qos_tx_p0_rate_init(struct am65_cpsw_common *common)
+{
+	struct am65_cpsw_host *host = am65_common_get_host(common);
+	int tx_ch;
+
+	for (tx_ch = 0; tx_ch < common->tx_ch_num; tx_ch++) {
+		struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[tx_ch];
+		u32 ch_cir;
+
+		if (!tx_chn->rate_mbps)
+			continue;
+
+		ch_cir = am65_cpsw_qos_tx_rate_calc(tx_chn->rate_mbps,
+						    common->bus_freq);
+		writel(ch_cir,
+		       host->port_base + AM65_CPSW_PN_REG_PRI_CIR(tx_ch));
+	}
+}
+
+static void am65_cpsw_tx_pn_shaper_apply(struct am65_cpsw_port *port)
+{
+	struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio;
+	struct am65_cpsw_common *common = port->common;
+	struct tc_mqprio_qopt_offload *mqprio;
+	bool shaper_en;
+	u32 rate_mbps;
+	int i;
+
+	mqprio = &p_mqprio->mqprio_hw;
+	shaper_en = p_mqprio->shaper_en && !p_mqprio->shaper_susp;
+
+	for (i = 0; i < mqprio->qopt.num_tc; i++) {
+		rate_mbps = 0;
+		if (shaper_en) {
+			rate_mbps = mqprio->min_rate[i] * 8 / 1000000;
+			rate_mbps = am65_cpsw_qos_tx_rate_calc(rate_mbps,
+							       common->bus_freq);
+		}
+
+		writel(rate_mbps,
+		       port->port_base + AM65_CPSW_PN_REG_PRI_CIR(i));
+	}
+
+	for (i = 0; i < mqprio->qopt.num_tc; i++) {
+		rate_mbps = 0;
+		if (shaper_en && mqprio->max_rate[i]) {
+			rate_mbps = mqprio->max_rate[i] - mqprio->min_rate[i];
+			rate_mbps = rate_mbps * 8 / 1000000;
+			rate_mbps = am65_cpsw_qos_tx_rate_calc(rate_mbps,
+							       common->bus_freq);
+		}
+
+		writel(rate_mbps,
+		       port->port_base + AM65_CPSW_PN_REG_PRI_EIR(i));
+	}
+}
+
+static void am65_cpsw_tx_pn_shaper_link_up(struct am65_cpsw_port *port)
+{
+	struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio;
+	struct am65_cpsw_common *common = port->common;
+	bool shaper_susp = false;
+
+	if (!p_mqprio->enable || !p_mqprio->shaper_en)
+		return;
+
+	if (p_mqprio->max_rate_total > port->qos.link_speed)
+		shaper_susp = true;
+
+	if (p_mqprio->shaper_susp == shaper_susp)
+		return;
+
+	if (shaper_susp)
+		dev_info(common->dev,
+			 "Port%u: total shaper tx rate > link speed - suspend shaper\n",
+			 port->port_id);
+	else
+		dev_info(common->dev,
+			 "Port%u: link recover - resume shaper\n",
+			 port->port_id);
+
+	p_mqprio->shaper_susp = shaper_susp;
+	am65_cpsw_tx_pn_shaper_apply(port);
+}
+
+void am65_cpsw_qos_mqprio_init(struct am65_cpsw_port *port)
+{
+	struct am65_cpsw_host *host = am65_common_get_host(port->common);
+	struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio;
+	struct tc_mqprio_qopt_offload *mqprio = &p_mqprio->mqprio_hw;
+	int i, fifo, rx_prio_map;
+
+	rx_prio_map = readl(host->port_base + AM65_CPSW_PN_REG_RX_PRI_MAP);
+
+	if (p_mqprio->enable) {
+		for (i = 0; i < AM65_CPSW_PN_TC_NUM; i++) {
+			fifo = mqprio->qopt.prio_tc_map[i];
+			p_mqprio->tx_prio_map |= fifo << (4 * i);
+		}
+
+		netdev_set_num_tc(port->ndev, mqprio->qopt.num_tc);
+		for (i = 0; i < mqprio->qopt.num_tc; i++) {
+			netdev_set_tc_queue(port->ndev, i,
+					    mqprio->qopt.count[i],
+					    mqprio->qopt.offset[i]);
+			if (!i) {
+				p_mqprio->tc0_q = mqprio->qopt.offset[i];
+				rx_prio_map &= ~(0x7 << (4 * p_mqprio->tc0_q));
+			}
+		}
+	} else {
+		/* restore default configuration */
+		netdev_reset_tc(port->ndev);
+		p_mqprio->tx_prio_map = AM65_CPSW_PN_TX_PRI_MAP_DEF;
+		rx_prio_map |= p_mqprio->tc0_q << (4 * p_mqprio->tc0_q);
+		p_mqprio->tc0_q = 0;
+	}
+
+	writel(p_mqprio->tx_prio_map,
+	       port->port_base + AM65_CPSW_PN_REG_TX_PRI_MAP);
+	writel(rx_prio_map,
+	       host->port_base + AM65_CPSW_PN_REG_RX_PRI_MAP);
+
+	am65_cpsw_tx_pn_shaper_apply(port);
+}
+
+static int am65_cpsw_mqprio_verify(struct am65_cpsw_port *port,
+				   struct tc_mqprio_qopt_offload *mqprio)
+{
+	int i;
+
+	for (i = 0; i < mqprio->qopt.num_tc; i++) {
+		unsigned int last = mqprio->qopt.offset[i] +
+				    mqprio->qopt.count[i];
+
+		if (mqprio->qopt.offset[i] >= port->ndev->real_num_tx_queues ||
+		    !mqprio->qopt.count[i] ||
+		    last >  port->ndev->real_num_tx_queues)
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int am65_cpsw_mqprio_verify_shaper(struct am65_cpsw_port *port,
+					  struct tc_mqprio_qopt_offload *mqprio,
+					  u64 *max_rate)
+{
+	struct am65_cpsw_common *common = port->common;
+	bool has_min_rate, has_max_rate;
+	u64 min_rate_total = 0, max_rate_total = 0;
+	u32 min_rate_msk = 0, max_rate_msk = 0;
+	int num_tc, i;
+
+	has_min_rate = !!(mqprio->flags & TC_MQPRIO_F_MIN_RATE);
+	has_max_rate = !!(mqprio->flags & TC_MQPRIO_F_MAX_RATE);
+
+	if (!has_min_rate && has_max_rate)
+		return -EOPNOTSUPP;
+
+	if (!has_min_rate)
+		return 0;
+
+	num_tc = mqprio->qopt.num_tc;
+
+	for (i = num_tc - 1; i >= 0; i--) {
+		u32 ch_msk;
+
+		if (mqprio->min_rate[i])
+			min_rate_msk |= BIT(i);
+		min_rate_total +=  mqprio->min_rate[i];
+
+		if (has_max_rate) {
+			if (mqprio->max_rate[i])
+				max_rate_msk |= BIT(i);
+			max_rate_total +=  mqprio->max_rate[i];
+
+			if (!mqprio->min_rate[i] && mqprio->max_rate[i]) {
+				dev_err(common->dev, "TX tc%d rate max>0 but min=0\n",
+					i);
+				return -EINVAL;
+			}
+
+			if (mqprio->max_rate[i] &&
+			    mqprio->max_rate[i] < mqprio->min_rate[i]) {
+				dev_err(common->dev, "TX tc%d rate min(%llu)>max(%llu)\n",
+					i, mqprio->min_rate[i],
+					mqprio->max_rate[i]);
+				return -EINVAL;
+			}
+		}
+
+		ch_msk = GENMASK(num_tc - 1, i);
+		if ((min_rate_msk & BIT(i)) && (min_rate_msk ^ ch_msk)) {
+			dev_err(common->dev, "TX Min rate limiting has to be enabled sequentially hi->lo tx_rate_msk%x\n",
+				min_rate_msk);
+			return -EINVAL;
+		}
+
+		if ((max_rate_msk & BIT(i)) && (max_rate_msk ^ ch_msk)) {
+			dev_err(common->dev, "TX max rate limiting has to be enabled sequentially hi->lo tx_rate_msk%x\n",
+				max_rate_msk);
+			return -EINVAL;
+		}
+	}
+	min_rate_total *= 8;
+	min_rate_total /= 1000 * 1000;
+	max_rate_total *= 8;
+	max_rate_total /= 1000 * 1000;
+
+	if (port->qos.link_speed != SPEED_UNKNOWN) {
+		if (min_rate_total > port->qos.link_speed) {
+			dev_err(common->dev, "TX rate min exceed %llu link speed %d\n",
+				min_rate_total, port->qos.link_speed);
+			return -EINVAL;
+		}
+
+		if (max_rate_total > port->qos.link_speed) {
+			dev_err(common->dev, "TX rate max exceed %llu link speed %d\n",
+				max_rate_total, port->qos.link_speed);
+			return -EINVAL;
+		}
+	}
+
+	*max_rate = max_t(u64, min_rate_total, max_rate_total);
+
+	return 0;
+}
+
+static int am65_cpsw_mqprio_setup(struct net_device *ndev, void *type_data)
+{
+	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+	struct tc_mqprio_qopt_offload *mqprio = type_data;
+	struct am65_cpsw_common *common = port->common;
+	struct am65_cpsw_mqprio *p_mqprio = &port->qos.mqprio;
+	bool has_min_rate;
+	int num_tc, ret;
+	u64 max_rate;
+
+	if (!mqprio->qopt.hw)
+		goto skip_check;
+
+	if (mqprio->mode != TC_MQPRIO_MODE_CHANNEL)
+		return -EOPNOTSUPP;
+
+	num_tc = mqprio->qopt.num_tc;
+	if (num_tc > AM65_CPSW_PN_TC_NUM)
+		return -ERANGE;
+
+	if ((mqprio->flags & TC_MQPRIO_F_SHAPER) &&
+	    mqprio->shaper != TC_MQPRIO_SHAPER_BW_RATE)
+		return -EOPNOTSUPP;
+
+	ret = am65_cpsw_mqprio_verify(port, mqprio);
+	if (ret)
+		return ret;
+
+	ret = am65_cpsw_mqprio_verify_shaper(port, mqprio, &max_rate);
+	if (ret)
+		return ret;
+
+skip_check:
+	ret = pm_runtime_get_sync(common->dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(common->dev);
+		return ret;
+	}
+
+	if (mqprio->qopt.hw) {
+		memcpy(&p_mqprio->mqprio_hw, mqprio, sizeof(*mqprio));
+		has_min_rate = !!(mqprio->flags & TC_MQPRIO_F_MIN_RATE);
+		p_mqprio->enable = 1;
+		p_mqprio->shaper_en = has_min_rate;
+		p_mqprio->shaper_susp = !has_min_rate;
+		p_mqprio->max_rate_total = max_rate;
+		p_mqprio->tx_prio_map = 0;
+	} else {
+		unsigned int tc0_q = p_mqprio->tc0_q;
+
+		memset(p_mqprio, 0, sizeof(*p_mqprio));
+		p_mqprio->mqprio_hw.qopt.num_tc = AM65_CPSW_PN_TC_NUM;
+		p_mqprio->tc0_q = tc0_q;
+	}
+
+	if (!netif_running(ndev))
+		goto exit_put;
+
+	am65_cpsw_qos_mqprio_init(port);
+
+exit_put:
+	pm_runtime_put(common->dev);
+	return 0;
+}
diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-cpsw-qos.h b/drivers/net/ethernet/ti/am65-cpsw-qos.h
--- a/drivers/net/ethernet/ti/am65-cpsw-qos.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/ti/am65-cpsw-qos.h	2024-01-28 14:01:31.252353813 -0500
@@ -7,6 +7,11 @@
 
 #include <linux/netdevice.h>
 #include <net/pkt_sched.h>
+#include <net/pkt_cls.h>
+
+struct am65_cpsw_port;
+
+struct am65_cpsw_common;
 
 struct am65_cpsw_est {
 	int buf;
@@ -14,16 +19,51 @@
 	struct tc_taprio_qopt_offload taprio;
 };
 
+struct am65_cpsw_iet {
+	struct net_device *ndev;
+	/* Set through priv flags */
+	bool fpe_configured;
+	bool mac_verify_configured;
+	/* frame preemption enabled */
+	bool fpe_enabled;
+	/* configured mask */
+	u32 fpe_mask_configured;
+	/* current mask */
+	u32 mask;
+	u32 addfragsize;
+};
+
+struct am65_cpsw_mqprio {
+	struct tc_mqprio_qopt_offload mqprio_hw;
+	u64 max_rate_total;
+	u32 tx_prio_map;
+
+	unsigned enable:1;
+	unsigned shaper_en:1;
+	unsigned shaper_susp:1;
+	unsigned tc0_q:3;
+};
+
 struct am65_cpsw_ale_ratelimit {
 	unsigned long cookie;
 	u64 rate_packet_ps;
 };
 
+struct am65_cpsw_cut_thru {
+	unsigned int rx_pri_mask;
+	unsigned int tx_pri_mask;
+	bool enable;
+};
+
 struct am65_cpsw_qos {
 	struct am65_cpsw_est *est_admin;
 	struct am65_cpsw_est *est_oper;
 	ktime_t link_down_time;
 	int link_speed;
+	int duplex;
+	struct am65_cpsw_iet iet;
+	struct am65_cpsw_mqprio mqprio;
+	struct am65_cpsw_cut_thru cut_thru;
 
 	struct am65_cpsw_ale_ratelimit ale_bc_ratelimit;
 	struct am65_cpsw_ale_ratelimit ale_mc_ratelimit;
@@ -31,7 +71,14 @@
 
 int am65_cpsw_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type,
 			       void *type_data);
-void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed);
+void am65_cpsw_qos_link_up(struct net_device *ndev, int link_speed, int duplex);
 void am65_cpsw_qos_link_down(struct net_device *ndev);
+void am65_cpsw_qos_iet_init(struct net_device *ndev);
+void am65_cpsw_qos_iet_cleanup(struct net_device *ndev);
+void am65_cpsw_qos_mqprio_init(struct am65_cpsw_port *port);
+void am65_cpsw_qos_cut_thru_init(struct am65_cpsw_port *port);
+void am65_cpsw_qos_cut_thru_cleanup(struct am65_cpsw_port *port);
+int am65_cpsw_qos_ndo_tx_p0_set_maxrate(struct net_device *ndev, int queue, u32 rate_mbps);
+void am65_cpsw_qos_tx_p0_rate_init(struct am65_cpsw_common *common);
 
 #endif /* AM65_CPSW_QOS_H_ */
diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-cpts.c b/drivers/net/ethernet/ti/am65-cpts.c
--- a/drivers/net/ethernet/ti/am65-cpts.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/ti/am65-cpts.c	2024-01-28 14:01:31.252353813 -0500
@@ -175,7 +175,22 @@
 	u64 timestamp;
 	u32 genf_enable;
 	u32 hw_ts_enable;
+	u32 estf_enable;
 	struct sk_buff_head txq;
+	bool pps_enabled;
+	bool pps_present;
+	u32 pps_hw_ts_idx;
+	u32 pps_genf_idx;
+	/* context save/restore */
+	u64 sr_cpts_ns;
+	u64 sr_ktime_ns;
+	u32 sr_control;
+	u32 sr_int_enable;
+	u32 sr_rftclk_sel;
+	u32 sr_ts_ppm_hi;
+	u32 sr_ts_ppm_low;
+	struct am65_genf_regs sr_genf[AM65_CPTS_GENF_MAX_NUM];
+	struct am65_genf_regs sr_estf[AM65_CPTS_ESTF_MAX_NUM];
 };
 
 struct am65_cpts_skb_cb_data {
@@ -309,8 +324,15 @@
 		case AM65_CPTS_EV_HW:
 			pevent.index = am65_cpts_event_get_port(event) - 1;
 			pevent.timestamp = event->timestamp;
-			pevent.type = PTP_CLOCK_EXTTS;
-			dev_dbg(cpts->dev, "AM65_CPTS_EV_HW p:%d t:%llu\n",
+			if (cpts->pps_enabled && pevent.index == cpts->pps_hw_ts_idx) {
+				pevent.type = PTP_CLOCK_PPSUSR;
+				pevent.pps_times.ts_real = ns_to_timespec64(pevent.timestamp);
+			} else {
+				pevent.type = PTP_CLOCK_EXTTS;
+			}
+			dev_dbg(cpts->dev, "AM65_CPTS_EV_HW:%s p:%d t:%llu\n",
+				pevent.type == PTP_CLOCK_EXTTS ?
+				"extts" : "pps",
 				pevent.index, event->timestamp);
 
 			ptp_clock_event(cpts->ptp_clock, &pevent);
@@ -381,12 +403,16 @@
 }
 
 /* PTP clock operations */
-static int am65_cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+static int am65_cpts_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
 	struct am65_cpts *cpts = container_of(ptp, struct am65_cpts, ptp_info);
-	int neg_adj = 0;
-	u64 adj_period;
-	u32 val;
+	u32 estf_ctrl_val = 0, estf_ppm_hi = 0, estf_ppm_low = 0;
+	s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
+	int pps_index = cpts->pps_genf_idx;
+	u64 adj_period, pps_adj_period;
+	u32 ctrl_val, ppm_hi, ppm_low;
+	unsigned long flags;
+	int neg_adj = 0, i;
 
 	if (ppb < 0) {
 		neg_adj = 1;
@@ -406,17 +432,60 @@
 
 	mutex_lock(&cpts->ptp_clk_lock);
 
-	val = am65_cpts_read32(cpts, control);
+	ctrl_val = am65_cpts_read32(cpts, control);
 	if (neg_adj)
-		val |= AM65_CPTS_CONTROL_TS_PPM_DIR;
+		ctrl_val |= AM65_CPTS_CONTROL_TS_PPM_DIR;
 	else
-		val &= ~AM65_CPTS_CONTROL_TS_PPM_DIR;
-	am65_cpts_write32(cpts, val, control);
+		ctrl_val &= ~AM65_CPTS_CONTROL_TS_PPM_DIR;
 
-	val = upper_32_bits(adj_period) & 0x3FF;
-	am65_cpts_write32(cpts, val, ts_ppm_hi);
-	val = lower_32_bits(adj_period);
-	am65_cpts_write32(cpts, val, ts_ppm_low);
+	ppm_hi = upper_32_bits(adj_period) & 0x3FF;
+	ppm_low = lower_32_bits(adj_period);
+
+	if (cpts->pps_enabled) {
+		estf_ctrl_val = am65_cpts_read32(cpts, genf[pps_index].control);
+		if (neg_adj)
+			estf_ctrl_val &= ~BIT(1);
+		else
+			estf_ctrl_val |= BIT(1);
+
+		/* GenF PPM will do correction using cpts refclk tick which is
+		 * (cpts->ts_add_val + 1) ns, so GenF length PPM adj period
+		 * need to be corrected.
+		 */
+		pps_adj_period = adj_period * (cpts->ts_add_val + 1);
+		estf_ppm_hi = upper_32_bits(pps_adj_period) & 0x3FF;
+		estf_ppm_low = lower_32_bits(pps_adj_period);
+	}
+
+	spin_lock_irqsave(&cpts->lock, flags);
+
+	/* All below writes must be done extremely fast:
+	 *  - delay between PPM dir and PPM value changes can cause err due old
+	 *    PPM correction applied in wrong direction
+	 *  - delay between CPTS-clock PPM cfg and GenF PPM cfg can cause err
+	 *    due CPTS-clock PPM working with new cfg while GenF PPM cfg still
+	 *    with old for short period of time
+	 */
+
+	am65_cpts_write32(cpts, ctrl_val, control);
+	am65_cpts_write32(cpts, ppm_hi, ts_ppm_hi);
+	am65_cpts_write32(cpts, ppm_low, ts_ppm_low);
+
+	if (cpts->pps_enabled) {
+		am65_cpts_write32(cpts, estf_ctrl_val, genf[pps_index].control);
+		am65_cpts_write32(cpts, estf_ppm_hi, genf[pps_index].ppm_hi);
+		am65_cpts_write32(cpts, estf_ppm_low, genf[pps_index].ppm_low);
+	}
+
+	for (i = 0; i < AM65_CPTS_ESTF_MAX_NUM; i++) {
+		if (cpts->estf_enable & BIT(i)) {
+			am65_cpts_write32(cpts, estf_ctrl_val, estf[i].control);
+			am65_cpts_write32(cpts, estf_ppm_hi, estf[i].ppm_hi);
+			am65_cpts_write32(cpts, estf_ppm_low, estf[i].ppm_low);
+		}
+	}
+	/* All GenF/EstF can be updated here the same way */
+	spin_unlock_irqrestore(&cpts->lock, flags);
 
 	mutex_unlock(&cpts->ptp_clk_lock);
 
@@ -496,7 +565,13 @@
 
 static int am65_cpts_extts_enable(struct am65_cpts *cpts, u32 index, int on)
 {
-	if (!!(cpts->hw_ts_enable & BIT(index)) == !!on)
+	if (index >= cpts->ptp_info.n_ext_ts)
+		return -ENXIO;
+
+	if (cpts->pps_present && index == cpts->pps_hw_ts_idx)
+		return -EINVAL;
+
+	if (((cpts->hw_ts_enable & BIT(index)) >> index) == on)
 		return 0;
 
 	mutex_lock(&cpts->ptp_clk_lock);
@@ -529,6 +604,11 @@
 	am65_cpts_write32(cpts, val, estf[idx].comp_lo);
 	val = lower_32_bits(cycles);
 	am65_cpts_write32(cpts, val, estf[idx].length);
+	am65_cpts_write32(cpts, 0, estf[idx].control);
+	am65_cpts_write32(cpts, 0, estf[idx].ppm_hi);
+	am65_cpts_write32(cpts, 0, estf[idx].ppm_low);
+
+	cpts->estf_enable |= BIT(idx);
 
 	dev_dbg(cpts->dev, "%s: ESTF:%u enabled\n", __func__, idx);
 
@@ -539,6 +619,7 @@
 void am65_cpts_estf_disable(struct am65_cpts *cpts, int idx)
 {
 	am65_cpts_write32(cpts, 0, estf[idx].length);
+	cpts->estf_enable &= ~BIT(idx);
 
 	dev_dbg(cpts->dev, "%s: ESTF:%u disabled\n", __func__, idx);
 }
@@ -569,6 +650,10 @@
 		val = lower_32_bits(cycles);
 		am65_cpts_write32(cpts, val, genf[req->index].length);
 
+		am65_cpts_write32(cpts, 0, genf[req->index].control);
+		am65_cpts_write32(cpts, 0, genf[req->index].ppm_hi);
+		am65_cpts_write32(cpts, 0, genf[req->index].ppm_low);
+
 		cpts->genf_enable |= BIT(req->index);
 	} else {
 		am65_cpts_write32(cpts, 0, genf[req->index].length);
@@ -580,6 +665,12 @@
 static int am65_cpts_perout_enable(struct am65_cpts *cpts,
 				   struct ptp_perout_request *req, int on)
 {
+	if (req->index >= cpts->ptp_info.n_per_out)
+		return -ENXIO;
+
+	if (cpts->pps_present && req->index == cpts->pps_genf_idx)
+		return -EINVAL;
+
 	if (!!(cpts->genf_enable & BIT(req->index)) == !!on)
 		return 0;
 
@@ -593,6 +684,48 @@
 	return 0;
 }
 
+static int am65_cpts_pps_enable(struct am65_cpts *cpts, int on)
+{
+	int ret = 0;
+	struct timespec64 ts;
+	struct ptp_clock_request rq;
+	u64 ns;
+
+	if (!cpts->pps_present)
+		return -EINVAL;
+
+	if (cpts->pps_enabled == !!on)
+		return 0;
+
+	mutex_lock(&cpts->ptp_clk_lock);
+
+	if (on) {
+		am65_cpts_extts_enable_hw(cpts, cpts->pps_hw_ts_idx, on);
+
+		ns = am65_cpts_gettime(cpts, NULL);
+		ts = ns_to_timespec64(ns);
+		rq.perout.period.sec = 1;
+		rq.perout.period.nsec = 0;
+		rq.perout.start.sec = ts.tv_sec + 2;
+		rq.perout.start.nsec = 0;
+		rq.perout.index = cpts->pps_genf_idx;
+
+		am65_cpts_perout_enable_hw(cpts, &rq.perout, on);
+		cpts->pps_enabled = true;
+	} else {
+		rq.perout.index = cpts->pps_genf_idx;
+		am65_cpts_perout_enable_hw(cpts, &rq.perout, on);
+		am65_cpts_extts_enable_hw(cpts, cpts->pps_hw_ts_idx, on);
+		cpts->pps_enabled = false;
+	}
+
+	mutex_unlock(&cpts->ptp_clk_lock);
+
+	dev_dbg(cpts->dev, "%s: pps: %s\n",
+		__func__, on ? "enabled" : "disabled");
+	return ret;
+}
+
 static int am65_cpts_ptp_enable(struct ptp_clock_info *ptp,
 				struct ptp_clock_request *rq, int on)
 {
@@ -603,6 +736,8 @@
 		return am65_cpts_extts_enable(cpts, rq->extts.index, on);
 	case PTP_CLK_REQ_PEROUT:
 		return am65_cpts_perout_enable(cpts, &rq->perout, on);
+	case PTP_CLK_REQ_PPS:
+		return am65_cpts_pps_enable(cpts, on);
 	default:
 		break;
 	}
@@ -615,7 +750,7 @@
 static struct ptp_clock_info am65_ptp_info = {
 	.owner		= THIS_MODULE,
 	.name		= "CTPS timer",
-	.adjfreq	= am65_cpts_ptp_adjfreq,
+	.adjfine	= am65_cpts_ptp_adjfine,
 	.adjtime	= am65_cpts_ptp_adjtime,
 	.gettimex64	= am65_cpts_ptp_gettimex,
 	.settime64	= am65_cpts_ptp_settime,
@@ -915,6 +1050,23 @@
 	if (!of_property_read_u32(node, "ti,cpts-periodic-outputs", &prop[0]))
 		cpts->genf_num = prop[0];
 
+	if (!of_property_read_u32_array(node, "ti,pps", prop, 2)) {
+		cpts->pps_present = true;
+
+		if (prop[0] > 7) {
+			dev_err(cpts->dev, "invalid HWx_TS_PUSH index: %u provided\n", prop[0]);
+			cpts->pps_present = false;
+		}
+		if (prop[1] > 1) {
+			dev_err(cpts->dev, "invalid GENFy index: %u provided\n", prop[1]);
+			cpts->pps_present = false;
+		}
+		if (cpts->pps_present) {
+			cpts->pps_hw_ts_idx = prop[0];
+			cpts->pps_genf_idx = prop[1];
+		}
+	}
+
 	return cpts_of_mux_clk_setup(cpts, node);
 }
 
@@ -981,6 +1133,8 @@
 		cpts->ptp_info.n_ext_ts = cpts->ext_ts_inputs;
 	if (cpts->genf_num)
 		cpts->ptp_info.n_per_out = cpts->genf_num;
+	if (cpts->pps_present)
+		cpts->ptp_info.pps = 1;
 
 	am65_cpts_set_add_val(cpts);
 
@@ -1010,9 +1164,9 @@
 		goto reset_ptpclk;
 	}
 
-	dev_info(dev, "CPTS ver 0x%08x, freq:%u, add_val:%u\n",
+	dev_info(dev, "CPTS ver 0x%08x, freq:%u, add_val:%u pps:%d\n",
 		 am65_cpts_read32(cpts, idver),
-		 cpts->refclk_freq, cpts->ts_add_val);
+		 cpts->refclk_freq, cpts->ts_add_val, cpts->pps_present);
 
 	return cpts;
 
@@ -1024,6 +1178,72 @@
 }
 EXPORT_SYMBOL_GPL(am65_cpts_create);
 
+void am65_cpts_suspend(struct am65_cpts *cpts)
+{
+	/* save state and disable CPTS */
+	cpts->sr_control = am65_cpts_read32(cpts, control);
+	cpts->sr_int_enable = am65_cpts_read32(cpts, int_enable);
+	cpts->sr_rftclk_sel = am65_cpts_read32(cpts, rftclk_sel);
+	cpts->sr_ts_ppm_hi = am65_cpts_read32(cpts, ts_ppm_hi);
+	cpts->sr_ts_ppm_low = am65_cpts_read32(cpts, ts_ppm_low);
+	cpts->sr_cpts_ns = am65_cpts_gettime(cpts, NULL);
+	cpts->sr_ktime_ns = ktime_to_ns(ktime_get_real());
+	am65_cpts_disable(cpts);
+	clk_disable(cpts->refclk);
+
+	/* Save GENF state */
+	memcpy_fromio(&cpts->sr_genf, &cpts->reg->genf, sizeof(cpts->sr_genf));
+
+	/* Save ESTF state */
+	memcpy_fromio(&cpts->sr_estf, &cpts->reg->estf, sizeof(cpts->sr_estf));
+}
+EXPORT_SYMBOL_GPL(am65_cpts_suspend);
+
+void am65_cpts_resume(struct am65_cpts *cpts)
+{
+	int i;
+	s64 ktime_ns;
+
+	/* restore state and enable CPTS */
+	clk_enable(cpts->refclk);
+	am65_cpts_write32(cpts, cpts->sr_rftclk_sel, rftclk_sel);
+	am65_cpts_set_add_val(cpts);
+	am65_cpts_write32(cpts, cpts->sr_control, control);
+	am65_cpts_write32(cpts, cpts->sr_int_enable, int_enable);
+
+	/* Restore time to saved CPTS time + time in suspend/resume */
+	ktime_ns = ktime_to_ns(ktime_get_real());
+	ktime_ns -= cpts->sr_ktime_ns;
+	am65_cpts_settime(cpts, cpts->sr_cpts_ns + ktime_ns);
+
+	/* Restore compensation (PPM) */
+	am65_cpts_write32(cpts, cpts->sr_ts_ppm_hi, ts_ppm_hi);
+	am65_cpts_write32(cpts, cpts->sr_ts_ppm_low, ts_ppm_low);
+
+	/* Restore GENF state */
+	for (i = 0; i < AM65_CPTS_GENF_MAX_NUM; i++) {
+		am65_cpts_write32(cpts, 0, genf[i].length);	/* TRM sequence */
+		am65_cpts_write32(cpts, cpts->sr_genf[i].comp_hi, genf[i].comp_hi);
+		am65_cpts_write32(cpts, cpts->sr_genf[i].comp_lo, genf[i].comp_lo);
+		am65_cpts_write32(cpts, cpts->sr_genf[i].length, genf[i].length);
+		am65_cpts_write32(cpts, cpts->sr_genf[i].control, genf[i].control);
+		am65_cpts_write32(cpts, cpts->sr_genf[i].ppm_hi, genf[i].ppm_hi);
+		am65_cpts_write32(cpts, cpts->sr_genf[i].ppm_low, genf[i].ppm_low);
+	}
+
+	/* Restore ESTTF state */
+	for (i = 0; i < AM65_CPTS_ESTF_MAX_NUM; i++) {
+		am65_cpts_write32(cpts, 0, estf[i].length);	/* TRM sequence */
+		am65_cpts_write32(cpts, cpts->sr_estf[i].comp_hi, estf[i].comp_hi);
+		am65_cpts_write32(cpts, cpts->sr_estf[i].comp_lo, estf[i].comp_lo);
+		am65_cpts_write32(cpts, cpts->sr_estf[i].length, estf[i].length);
+		am65_cpts_write32(cpts, cpts->sr_estf[i].control, estf[i].control);
+		am65_cpts_write32(cpts, cpts->sr_estf[i].ppm_hi, estf[i].ppm_hi);
+		am65_cpts_write32(cpts, cpts->sr_estf[i].ppm_low, estf[i].ppm_low);
+	}
+}
+EXPORT_SYMBOL_GPL(am65_cpts_resume);
+
 static int am65_cpts_probe(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-cpts.h b/drivers/net/ethernet/ti/am65-cpts.h
--- a/drivers/net/ethernet/ti/am65-cpts.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/ti/am65-cpts.h	2024-01-28 14:01:31.252353813 -0500
@@ -29,6 +29,8 @@
 int am65_cpts_estf_enable(struct am65_cpts *cpts, int idx,
 			  struct am65_cpts_estf_cfg *cfg);
 void am65_cpts_estf_disable(struct am65_cpts *cpts, int idx);
+void am65_cpts_suspend(struct am65_cpts *cpts);
+void am65_cpts_resume(struct am65_cpts *cpts);
 #else
 static inline void am65_cpts_release(struct am65_cpts *cpts)
 {
@@ -74,6 +76,14 @@
 static inline void am65_cpts_estf_disable(struct am65_cpts *cpts, int idx)
 {
 }
+
+static inline void am65_cpts_suspend(struct am65_cpts *cpts)
+{
+}
+
+static inline void am65_cpts_resume(struct am65_cpts *cpts)
+{
+}
 #endif
 
 #endif /* K3_CPTS_H_ */
diff -Naur --no-dereference a/drivers/net/ethernet/ti/am65-debugfs.c b/drivers/net/ethernet/ti/am65-debugfs.c
--- a/drivers/net/ethernet/ti/am65-debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/am65-debugfs.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Texas Instruments K3 AM65 Ethernet debugfs submodule
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include <linux/bitfield.h>
+#include <linux/debugfs.h>
+
+#include "am65-cpsw-nuss.h"
+
+int am65_cpsw_nuss_register_debugfs(struct am65_cpsw_common *common)
+{
+	common->debugfs_root = debugfs_create_dir(dev_name(common->dev), NULL);
+	if (IS_ERR(common->debugfs_root))
+		return PTR_ERR(common->debugfs_root);
+
+	return 0;
+}
+
+void am65_cpsw_nuss_unregister_debugfs(struct am65_cpsw_common *common)
+{
+	debugfs_remove_recursive(common->debugfs_root);
+}
+
+static int
+cut_thru_tx_pri_mask_get(void *data, u64 *val)
+{
+	struct am65_cpsw_port *port = data;
+	struct am65_cpsw_cut_thru *cut_thru;
+	int ret = -EINVAL;
+
+	read_lock(&dev_base_lock);
+	cut_thru = &port->qos.cut_thru;
+	if (port->ndev->reg_state == NETREG_REGISTERED) {
+		*val =  cut_thru->tx_pri_mask;
+		ret = 0;
+	}
+	read_unlock(&dev_base_lock);
+
+	return ret;
+}
+
+static int
+cut_thru_tx_pri_mask_set(void *data, u64 val)
+{
+	struct am65_cpsw_cut_thru *cut_thru;
+	struct am65_cpsw_port *port = data;
+	struct am65_cpsw_common *common;
+	int ret = 0;
+
+	if (val & ~GENMASK(7, 0))
+		return -EINVAL;
+
+	if (!rtnl_trylock())
+		return restart_syscall();
+
+	common = port->common;
+	cut_thru = &port->qos.cut_thru;
+
+	if (cut_thru->enable) {
+		dev_err(common->dev, "Port%u: can't set cut-thru tx_pri_mask while cut-thru enabled\n",
+			port->port_id);
+		ret = -EINVAL;
+		goto err;
+	}
+	cut_thru->tx_pri_mask = val;
+
+err:
+	rtnl_unlock();
+	return ret;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(fops_cut_thru_tx_pri_mask, cut_thru_tx_pri_mask_get,
+			 cut_thru_tx_pri_mask_set, "%llx\n");
+
+static int
+cut_thru_rx_pri_mask_get(void *data, u64 *val)
+{
+	struct am65_cpsw_port *port = data;
+	struct am65_cpsw_cut_thru *cut_thru;
+	int ret = -EINVAL;
+
+	read_lock(&dev_base_lock);
+	cut_thru = &port->qos.cut_thru;
+	if (port->ndev->reg_state == NETREG_REGISTERED) {
+		*val =  cut_thru->rx_pri_mask;
+		ret = 0;
+	}
+	read_unlock(&dev_base_lock);
+
+	return ret;
+}
+
+static int
+cut_thru_rx_pri_mask_set(void *data, u64 val)
+{
+	struct am65_cpsw_cut_thru *cut_thru;
+	struct am65_cpsw_port *port = data;
+	struct am65_cpsw_common *common;
+	int ret = 0;
+
+	if (val & ~GENMASK(7, 0))
+		return -EINVAL;
+
+	if (!rtnl_trylock())
+		return restart_syscall();
+
+	common = port->common;
+	cut_thru = &port->qos.cut_thru;
+
+	if (cut_thru->enable) {
+		dev_err(common->dev, "Port%u: can't set cut-thru rx_pri_mask while cut-thru enabled\n",
+			port->port_id);
+		ret = -EINVAL;
+		goto err;
+	}
+	cut_thru->rx_pri_mask = val;
+
+err:
+	rtnl_unlock();
+	return ret;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(fops_cut_thru_rx_pri_mask, cut_thru_rx_pri_mask_get,
+			 cut_thru_rx_pri_mask_set, "%llx\n");
+
+int am65_cpsw_nuss_register_port_debugfs(struct am65_cpsw_port *port)
+{
+	struct am65_cpsw_common *common = port->common;
+	char dirn[32];
+
+	scnprintf(dirn, sizeof(dirn), "Port%x", port->port_id);
+	port->debugfs_port = debugfs_create_dir(dirn, common->debugfs_root);
+	if (IS_ERR(port->debugfs_port))
+		return PTR_ERR(port->debugfs_port);
+
+	debugfs_create_bool("disabled", 0400,
+			    port->debugfs_port, &port->disabled);
+	if (port->disabled)
+		return 0;
+
+	if (common->pdata.quirks & AM64_CPSW_QUIRK_CUT_THRU) {
+		debugfs_create_file("cut_thru_tx_pri_mask", 0600,
+				    port->debugfs_port,
+				    port, &fops_cut_thru_tx_pri_mask);
+		debugfs_create_file("cut_thru_rx_pri_mask", 0600,
+				    port->debugfs_port,
+				    port, &fops_cut_thru_rx_pri_mask);
+	}
+
+	return 0;
+}
diff -Naur --no-dereference a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
--- a/drivers/net/ethernet/ti/cpsw_ale.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/ti/cpsw_ale.c	2024-01-28 14:01:31.252353813 -0500
@@ -1466,6 +1466,16 @@
 	}
 }
 
+void cpsw_ale_restore(struct cpsw_ale *ale, u32 *data)
+{
+	int i;
+
+	for (i = 0; i < ale->params.ale_entries; i++) {
+		cpsw_ale_write(ale, i, data);
+		data += ALE_ENTRY_WORDS;
+	}
+}
+
 u32 cpsw_ale_get_num_entries(struct cpsw_ale *ale)
 {
 	return ale ? ale->params.ale_entries : 0;
diff -Naur --no-dereference a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
--- a/drivers/net/ethernet/ti/cpsw_ale.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/ti/cpsw_ale.h	2024-01-28 14:01:31.252353813 -0500
@@ -127,6 +127,7 @@
 int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
 			 int control, int value);
 void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data);
+void cpsw_ale_restore(struct cpsw_ale *ale, u32 *data);
 u32 cpsw_ale_get_num_entries(struct cpsw_ale *ale);
 
 static inline int cpsw_ale_get_vlan_p0_untag(struct cpsw_ale *ale, u16 vid)
diff -Naur --no-dereference a/drivers/net/ethernet/ti/cpsw-proxy-client.c b/drivers/net/ethernet/ti/cpsw-proxy-client.c
--- a/drivers/net/ethernet/ti/cpsw-proxy-client.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/cpsw-proxy-client.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,2176 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Texas Instruments CPSW Proxy Client Driver
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/interrupt.h>
+#include <linux/inetdevice.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/kmemleak.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/rpmsg.h>
+#include <linux/dma/ti-cppi5.h>
+#include <linux/dma/k3-udma-glue.h>
+
+#include "k3-cppi-desc-pool.h"
+#include "eth_remote_msg.h"
+
+#define CPSW_PROXY_CLIENT_MIN_PACKET_SIZE	ETH_ZLEN
+#define CPSW_PROXY_CLIENT_MAX_PACKET_SIZE	(VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)
+#define CPSW_PROXY_CLIENT_MAX_RX_FLOWS		1
+#define CPSW_PROXY_CLIENT_MAX_RX_QUEUES		1
+#define CPSW_PROXY_CLIENT_MAX_TX_QUEUES		1
+#define CPSW_PROXY_CLIENT_REQ_TIMEOUT_MS	500
+
+#define CPSW_PROXY_CLIENT_MAX_TX_DESC		500
+#define CPSW_PROXY_CLIENT_MAX_RX_DESC		500
+
+#define CPSW_PROXY_CLIENT_NAV_PS_DATA_SIZE	16
+#define CPSW_PROXY_CLIENT_NAV_SW_DATA_SIZE	16
+
+enum cpsw_virt_port_type {
+	VIRT_SWITCH_PORT,
+	VIRT_MAC_ONLY_PORT,
+};
+
+struct cpsw_proxy_tx_chan {
+	struct device			*dev;
+	struct k3_cppi_desc_pool	*desc_pool;
+	struct k3_udma_glue_tx_channel	*tx_chan;
+	u32				chan_id;
+	u32				num_descs;
+	unsigned int			irq;
+};
+
+struct cpsw_proxy_rx_chan {
+	struct device			*dev;
+	struct k3_cppi_desc_pool	*desc_pool;
+	struct k3_udma_glue_rx_channel	*rx_chan;
+	u32				num_descs;
+	unsigned int			irq;
+};
+
+struct cpsw_virt_port {
+	struct cpsw_proxy_common	*common;
+	struct net_device		*ndev;
+	enum cpsw_virt_port_type	virt_port_type;
+	struct cpsw_proxy_tx_chan	virt_port_tx_chan;
+	struct cpsw_proxy_rx_chan	virt_port_rx_chan;
+	struct workqueue_struct		*virt_port_wq;
+	struct work_struct		rx_mode_work;
+	struct napi_struct		napi_tx;
+	struct napi_struct		napi_rx;
+	struct notifier_block		virt_port_inetaddr_nb;
+	struct netdev_hw_addr_list	mcast_list;
+	struct completion		tdown_complete;
+	struct hrtimer			tx_hrtimer;
+	struct mutex			mcast_filter_mutex; /* Multicast add/del ops mutex */
+	unsigned long			tx_pace_timeout;
+	struct hrtimer			rx_hrtimer;
+	unsigned long			rx_pace_timeout;
+	atomic_t			tdown_cnt;
+	bool				rx_irq_disabled;
+	bool				mcast_filter;
+	bool				promisc_enabled;
+	u32				virt_port_id;
+	u32				virt_port_token;
+	u32				tx_psil_dest_id;
+	u32				rx_psil_src_id;
+	u32				rx_flow_idx_base;
+	u32				rx_flow_idx_offset;
+	u16				vlan_id;
+	u8				ipv4_addr[ETHREMOTECFG_IPV4ADDRLEN];
+	u8				mcast_mac_addr[ETH_ALEN];
+	u8				mac_addr[ETH_ALEN];
+};
+
+struct cpsw_virt_port_ndev_stats {
+	u64 tx_packets;
+	u64 tx_bytes;
+	u64 rx_packets;
+	u64 rx_bytes;
+	struct u64_stats_sync syncp;
+};
+
+struct cpsw_virt_port_ndev_priv {
+	struct cpsw_virt_port_ndev_stats __percpu *stats;
+	struct cpsw_virt_port *virt_port;
+};
+
+struct cpsw_proxy_common {
+	struct rpmsg_device		*rpdev;
+	struct device			*dev;
+	struct cpsw_virt_port		*virt_ports;
+	struct completion		wait_for_response;
+	struct message			send_msg;
+	struct message			recv_msg;
+	const char			*dma_compatible;
+	struct device_node		*dma_node;
+	struct mutex			request_id_msg_mutex; /* RPMsg requests mutex */
+	u32				request_id;
+	u32				num_virt_ports;
+	u32				num_active_tx_channels;
+	u32				num_active_rx_channels;
+	u32				virt_mac_only_ports; /* Bitmask */
+	int				num_mac_only_ports;
+	u32				virt_switch_ports; /* Bitmask */
+	int				num_switch_ports;
+	int				recv_msg_len;
+	bool				in_recovery;
+	bool				error_handled;
+};
+
+#define cpsw_virt_port_ndev_to_priv(ndev) \
+	((struct cpsw_virt_port_ndev_priv *)netdev_priv(ndev))
+#define cpsw_virt_port_ndev_to_virt_port(ndev) (cpsw_virt_port_ndev_to_priv(ndev)->virt_port)
+
+/* Create a request message given the request type */
+static int create_request(u32 token, u32 client_id, u32 req_type, struct cpsw_proxy_common *common,
+			  struct cpsw_virt_port *virt_port)
+{
+	struct add_mcast_vlan_rx_flow_request *mcast_add_req;
+	struct del_mcast_vlan_rx_flow_request *mcast_del_req;
+	struct mac_rx_flow_register_request *mac_reg_req;
+	struct ipv4_deregister_request *ipv4_dereg_req;
+	struct common_request_message *common_req_msg;
+	struct tx_psil_release_request *tx_free_req;
+	struct rx_flow_release_request *rx_free_req;
+	struct ipv4_register_request *ipv4_reg_req;
+	struct request_message_header *req_msg_hdr;
+	struct mac_release_request *mac_free_req;
+	struct message *msg = &common->send_msg;
+	struct attach_request *attach_req;
+
+	/* Set message header fields */
+	msg->msg_hdr.token = token;
+	msg->msg_hdr.client_id = client_id;
+	msg->msg_hdr.msg_type = ETHREMOTECFG_MSG_REQUEST;
+
+	/* Handle differently based on type of request */
+	switch (req_type) {
+	case ETHREMOTECFG_ATTACH_EXT:
+		attach_req = (struct attach_request *)msg;
+		req_msg_hdr = &attach_req->request_msg_hdr;
+
+		/* Set Virtual Port ID */
+		attach_req->virt_port = virt_port->virt_port_id;
+
+		break;
+
+	case ETHREMOTECFG_DETACH:
+	case ETHREMOTECFG_PORT_LINK_STATUS:
+	case ETHREMOTECFG_PROMISC_DISABLE:
+	case ETHREMOTECFG_PROMISC_ENABLE:
+	case ETHREMOTECFG_TEARDOWN_COMPLETE:
+	case ETHREMOTECFG_VIRT_PORT_ALLOC:
+		common_req_msg = (struct common_request_message *)msg;
+		req_msg_hdr = &common_req_msg->request_msg_hdr;
+
+		break;
+
+	case ETHREMOTECFG_FILTER_MAC_ADD:
+		mcast_add_req = (struct add_mcast_vlan_rx_flow_request *)msg;
+		req_msg_hdr = &mcast_add_req->request_msg_hdr;
+
+		/* Set Multicast MAC Address */
+		ether_addr_copy(mcast_add_req->mac_addr, virt_port->mcast_mac_addr);
+		/* Set VLAN id */
+		mcast_add_req->vlan_id = virt_port->vlan_id;
+		/* Set RX Flow Index Base and Offset */
+		mcast_add_req->rx_flow_idx_base = virt_port->rx_flow_idx_base;
+		mcast_add_req->rx_flow_idx_offset = virt_port->rx_flow_idx_offset;
+
+		break;
+
+	case ETHREMOTECFG_FILTER_MAC_DEL:
+		mcast_del_req = (struct del_mcast_vlan_rx_flow_request *)msg;
+		req_msg_hdr = &mcast_del_req->request_msg_hdr;
+
+		/* Set Multicast MAC Address */
+		ether_addr_copy(mcast_del_req->mac_addr, virt_port->mcast_mac_addr);
+		/* Set VLAN id */
+		mcast_del_req->vlan_id = virt_port->vlan_id;
+
+		break;
+
+	case ETHREMOTECFG_FREE_MAC:
+		mac_free_req = (struct mac_release_request *)msg;
+		req_msg_hdr = &mac_free_req->request_msg_hdr;
+
+		/* Set MAC Address to release */
+		ether_addr_copy(mac_free_req->mac_addr, virt_port->mac_addr);
+
+		break;
+
+	case ETHREMOTECFG_FREE_RX:
+		rx_free_req = (struct rx_flow_release_request *)msg;
+		req_msg_hdr = &rx_free_req->request_msg_hdr;
+
+		/* Set RX Flow Index Base and Offset to release */
+		rx_free_req->rx_flow_idx_base = virt_port->rx_flow_idx_base;
+		rx_free_req->rx_flow_idx_offset = virt_port->rx_flow_idx_offset;
+
+		break;
+
+	case ETHREMOTECFG_FREE_TX:
+		tx_free_req = (struct tx_psil_release_request *)msg;
+		req_msg_hdr = &tx_free_req->request_msg_hdr;
+
+		tx_free_req->tx_psil_dest_id = virt_port->tx_psil_dest_id;
+
+		break;
+
+	case ETHREMOTECFG_IPv4_REGISTER:
+		ipv4_reg_req = (struct ipv4_register_request *)msg;
+		req_msg_hdr = &ipv4_reg_req->request_msg_hdr;
+
+		memcpy(&ipv4_reg_req->ipv4_addr, virt_port->ipv4_addr, ETHREMOTECFG_IPV4ADDRLEN);
+		ether_addr_copy(ipv4_reg_req->mac_addr, virt_port->mac_addr);
+
+		break;
+
+	case ETHREMOTECFG_IPv4_DEREGISTER:
+		ipv4_dereg_req = (struct ipv4_deregister_request *)msg;
+		req_msg_hdr = &ipv4_dereg_req->request_msg_hdr;
+
+		memcpy(&ipv4_dereg_req->ipv4_addr, virt_port->ipv4_addr, ETHREMOTECFG_IPV4ADDRLEN);
+
+		break;
+
+	case ETHREMOTECFG_MAC_REGISTER:
+	case ETHREMOTECFG_MAC_DEREGISTER:
+		mac_reg_req = (struct mac_rx_flow_register_request *)msg;
+		req_msg_hdr = &mac_reg_req->request_msg_hdr;
+
+		ether_addr_copy(mac_reg_req->mac_addr, virt_port->mac_addr);
+		mac_reg_req->rx_flow_idx_base = virt_port->rx_flow_idx_base;
+		mac_reg_req->rx_flow_idx_offset = virt_port->rx_flow_idx_offset;
+
+		break;
+
+	case ETHREMOTECFG_ATTACH:
+	case ETHREMOTECFG_ALLOC_TX:
+	case ETHREMOTECFG_ALLOC_RX:
+	case ETHREMOTECFG_ALLOC_MAC:
+	case ETHREMOTECFG_SET_RX_DEFAULTFLOW:
+	case ETHREMOTECFG_DEL_RX_DEFAULTFLOW:
+	case ETHREMOTECFG_REGISTER_READ:
+	case ETHREMOTECFG_REGISTER_WRITE:
+	case ETHREMOTECFG_MATCH_ETHTYPE_REGISTER:
+	case ETHREMOTECFG_MATCH_ETHTYPE_DEREGISTER:
+	case ETHREMOTECFG_REMOTE_TIMER_REGISTER:
+	case ETHREMOTECFG_REMOTE_TIMER_DEREGISTER:
+	case ETHREMOTECFG_MESSAGE_PING:
+	case ETHREMOTECFG_ETHFW_STATUS:
+	case ETHREMOTECFG_CLIENT_DUMPSTATS:
+	default:
+		pr_err("Unsupported request type\n");
+		return -EOPNOTSUPP;
+	}
+
+	/* Set request message header fields */
+	req_msg_hdr->request_id = common->request_id;
+	req_msg_hdr->request_type = req_type;
+
+	return 0;
+}
+
+static int cpsw_proxy_client_send_rpmsg(struct cpsw_proxy_common *common)
+{
+	struct rpmsg_device *rpdev = common->rpdev;
+	int ret;
+
+	reinit_completion(&common->wait_for_response);
+	ret = rpmsg_send(rpdev->ept, (void *)(&common->send_msg), sizeof(struct message));
+	if (ret) {
+		dev_err(common->dev, "failed to send rpmsg\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int
+cpsw_proxy_client_send_request(struct cpsw_proxy_common *common, struct cpsw_virt_port *virt_port,
+			       u32 token, u32 req_type, struct message *response)
+{
+	struct response_message_header *response_msg_hdr;
+	unsigned long timeout;
+	u32 response_status;
+	bool retry = 0;
+	int ret;
+
+	mutex_lock(&common->request_id_msg_mutex);
+	ret = create_request(token, ETHREMOTECFG_LINUX_CLIENT, req_type, common, virt_port);
+	if (ret) {
+		dev_err(common->dev, "failed to create request %d\n", ret);
+		goto err;
+	}
+
+	ret = cpsw_proxy_client_send_rpmsg(common);
+	if (ret) {
+		dev_err(common->dev, "failed to send request %d\n", ret);
+		goto err;
+	}
+
+	/* Ensure that response is received by the callback handler */
+	timeout = msecs_to_jiffies(CPSW_PROXY_CLIENT_REQ_TIMEOUT_MS);
+	ret = wait_for_completion_timeout(&common->wait_for_response, timeout);
+	if (!ret) {
+		dev_err(common->dev, "failed to receive response. Response Timedout\n");
+		ret = -ETIMEDOUT;
+		goto err;
+	}
+
+	/* Store response */
+	memcpy(response, &common->recv_msg, common->recv_msg_len);
+	response_msg_hdr = (struct response_message_header *)response;
+	response_status = response_msg_hdr->response_status;
+
+	if (unlikely(response_status != ETHREMOTECFG_CMDSTATUS_OK)) {
+		if (response_status == ETHREMOTECFG_CMDSTATUS_EAGAIN) {
+			dev_info(common->dev, "resending request\n");
+			retry = 1;
+			goto err;
+		} else {
+			dev_err(common->dev, "bad response status: %d\n", response_status);
+			ret = -EIO;
+			goto err;
+		}
+	}
+
+	common->request_id++;
+	mutex_unlock(&common->request_id_msg_mutex);
+
+	return 0;
+
+err:
+	common->request_id++;
+	mutex_unlock(&common->request_id_msg_mutex);
+	if (retry)
+		ret = cpsw_proxy_client_send_request(common, virt_port, token, req_type,
+						     response);
+	return ret;
+}
+
+static struct cpsw_virt_port *get_virt_port_from_token(struct cpsw_proxy_common *common, u32 token)
+{
+	struct cpsw_virt_port *virt_port;
+	int i;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+
+		if (virt_port->virt_port_token == token)
+			return virt_port;
+	}
+
+	return NULL;
+}
+
+static int cpsw_proxy_client_server_recovery_notify_handler(void *data)
+{
+	struct cpsw_virt_port *virt_port = (struct cpsw_virt_port *)data;
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct net_device *ndev;
+
+	ndev = virt_port->ndev;
+	netif_device_attach(ndev);
+	if (!netif_running(ndev)) {
+		rtnl_lock();
+		dev_open(ndev, NULL);
+		rtnl_unlock();
+	}
+
+	common->in_recovery = 0;
+	return 0;
+}
+
+static int cpsw_proxy_client_server_error_notify_handler(void *data)
+{
+	struct cpsw_virt_port *virt_port = (struct cpsw_virt_port *)data;
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct net_device *ndev;
+	struct message response;
+	int ret;
+
+	ndev = virt_port->ndev;
+	netif_device_detach(ndev);
+	if (netif_running(ndev)) {
+		rtnl_lock();
+		dev_close(ndev);
+		rtnl_unlock();
+	}
+
+	ret = cpsw_proxy_client_send_request(common, virt_port, virt_port->virt_port_token,
+					     ETHREMOTECFG_TEARDOWN_COMPLETE, &response);
+	if (ret) {
+		dev_err(common->dev, "failed to notify teardown completion err: %d\n", ret);
+		return ret;
+	}
+
+	common->error_handled = 1;
+	return 0;
+}
+
+static int cpsw_proxy_client_cb(struct rpmsg_device *rpdev, void *data,
+				int len, void *priv, u32 src)
+{
+	struct cpsw_proxy_common *common = dev_get_drvdata(&rpdev->dev);
+	struct response_message_header *response_msg_hdr;
+	struct notify_message_header *notify_msg_hdr;
+	struct message *msg = (struct message *)data;
+	struct task_struct *server_notify_handler;
+	u32 msg_type = msg->msg_hdr.msg_type;
+	u32 notify_type, response_id, token;
+	struct cpsw_virt_port *virt_port;
+	int response_status, ret = 0;
+
+	switch (msg_type) {
+	case ETHREMOTECFG_MSG_NOTIFY:
+		notify_msg_hdr = (struct notify_message_header *)msg;
+		notify_type = notify_msg_hdr->notify_type;
+		token = notify_msg_hdr->msg_hdr.token;
+
+		switch (notify_type) {
+		case ETHREMOTECFG_NOTIFYTYPE_HWERROR:
+			common->in_recovery = 1;
+			virt_port = get_virt_port_from_token(common, token);
+			if (!virt_port) {
+				dev_err(common->dev, "invalid notification received\n");
+				return -EINVAL;
+			}
+
+			server_notify_handler =
+					kthread_run(&cpsw_proxy_client_server_error_notify_handler,
+						    virt_port, "hwerr_handler");
+
+			if (IS_ERR(server_notify_handler))
+				ret = PTR_ERR(server_notify_handler);
+			break;
+
+		case ETHREMOTECFG_NOTIFYTYPE_HWRECOVERY_COMPLETE:
+			common->error_handled = 0;
+			virt_port = get_virt_port_from_token(common, token);
+			if (!virt_port) {
+				dev_err(common->dev, "invalid notification received\n");
+				return -EINVAL;
+			}
+
+			server_notify_handler =
+				kthread_run(&cpsw_proxy_client_server_recovery_notify_handler,
+					    virt_port, "recovery_handler");
+
+			if (IS_ERR(server_notify_handler))
+				ret = PTR_ERR(server_notify_handler);
+			break;
+
+		default:
+			break;
+		}
+
+		break;
+
+	case ETHREMOTECFG_MSG_RESPONSE:
+		response_msg_hdr = (struct response_message_header *)msg;
+		response_id = response_msg_hdr->response_id;
+		response_status = response_msg_hdr->response_status;
+
+		if (response_id == common->request_id - 1) {
+			dev_info(common->dev, "ignoring delayed response for request: %u\n",
+				 response_id);
+			return 0;
+		}
+
+		if (response_id != common->request_id) {
+			dev_err(common->dev, "expected response id: %u but received %u\n",
+				common->request_id, response_id);
+			return -EINVAL;
+		}
+
+		memcpy(&common->recv_msg, msg, len);
+		common->recv_msg_len = len;
+		complete(&common->wait_for_response);
+		break;
+
+	default:
+		dev_err(common->dev, "invalid message received\n");
+		return -EOPNOTSUPP;
+	}
+
+	return ret;
+}
+
+static int cpsw_virt_port_rx_push(struct cpsw_virt_port *virt_port, struct sk_buff *skb)
+{
+	struct cpsw_proxy_rx_chan *rx_chn = &virt_port->virt_port_rx_chan;
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct cppi5_host_desc_t *desc_rx;
+	struct device *dev = common->dev;
+	u32 pkt_len = skb_tailroom(skb);
+	dma_addr_t desc_dma;
+	dma_addr_t buf_dma;
+	void *swdata;
+
+	desc_rx = k3_cppi_desc_pool_alloc(rx_chn->desc_pool);
+	if (!desc_rx) {
+		dev_err(dev, "Failed to allocate RXFDQ descriptor\n");
+		return -ENOMEM;
+	}
+	desc_dma = k3_cppi_desc_pool_virt2dma(rx_chn->desc_pool, desc_rx);
+
+	buf_dma = dma_map_single(dev, skb->data, pkt_len, DMA_FROM_DEVICE);
+	if (unlikely(dma_mapping_error(dev, buf_dma))) {
+		k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
+		dev_err(dev, "Failed to map rx skb buffer\n");
+		return -EINVAL;
+	}
+
+	cppi5_hdesc_init(desc_rx, CPPI5_INFO0_HDESC_EPIB_PRESENT,
+			 CPSW_PROXY_CLIENT_NAV_PS_DATA_SIZE);
+	cppi5_hdesc_attach_buf(desc_rx, 0, 0, buf_dma, skb_tailroom(skb));
+	swdata = cppi5_hdesc_get_swdata(desc_rx);
+	*((void **)swdata) = skb;
+
+	return k3_udma_glue_push_rx_chn(rx_chn->rx_chan, 0, desc_rx, desc_dma);
+}
+
+static int cpsw_virt_port_open(struct cpsw_virt_port *virt_port, netdev_features_t features)
+{
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct sk_buff *skb;
+	int i, ret;
+
+	for (i = 0; i < virt_port->virt_port_rx_chan.num_descs; i++) {
+		skb = __netdev_alloc_skb_ip_align(NULL, CPSW_PROXY_CLIENT_MAX_PACKET_SIZE,
+						  GFP_KERNEL);
+		if (!skb)
+			return -ENOMEM;
+
+		ret = cpsw_virt_port_rx_push(virt_port, skb);
+		if (ret < 0) {
+			dev_err(common->dev,
+				"cannot submit skb to channel rx, error %d\n",
+				ret);
+			kfree_skb(skb);
+			return ret;
+		}
+		kmemleak_not_leak(skb);
+	}
+	ret = k3_udma_glue_rx_flow_enable(virt_port->virt_port_rx_chan.rx_chan, 0);
+	if (ret)
+		return ret;
+
+	ret = k3_udma_glue_enable_tx_chn(virt_port->virt_port_tx_chan.tx_chan);
+	if (ret)
+		return ret;
+
+	napi_enable(&virt_port->napi_tx);
+	napi_enable(&virt_port->napi_rx);
+	if (virt_port->rx_irq_disabled) {
+		virt_port->rx_irq_disabled = false;
+		enable_irq(virt_port->virt_port_rx_chan.irq);
+	}
+
+	return 0;
+}
+
+static int cpsw_proxy_client_register_mac(struct cpsw_virt_port *virt_port)
+{
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct message response;
+	int ret;
+
+	ret = cpsw_proxy_client_send_request(common, virt_port, virt_port->virt_port_token,
+					     ETHREMOTECFG_MAC_REGISTER, &response);
+	if (ret)
+		dev_err(common->dev, "failed to register mac err: %d\n", ret);
+
+	return ret;
+}
+
+static int cpsw_proxy_client_deregister_mac(struct cpsw_virt_port *virt_port)
+{
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct message response;
+	int ret;
+
+	ret = cpsw_proxy_client_send_request(common, virt_port, virt_port->virt_port_token,
+					     ETHREMOTECFG_MAC_DEREGISTER, &response);
+	if (ret)
+		dev_err(common->dev, "failed to deregister mac err: %d\n", ret);
+
+	return ret;
+}
+
+static void cpsw_virt_port_xmit_free(struct cpsw_proxy_tx_chan *tx_chn,
+				     struct device *dev,
+				     struct cppi5_host_desc_t *desc)
+{
+	struct cppi5_host_desc_t *first_desc, *next_desc;
+	dma_addr_t buf_dma, next_desc_dma;
+	u32 buf_dma_len;
+
+	first_desc = desc;
+	next_desc = first_desc;
+
+	cppi5_hdesc_get_obuf(first_desc, &buf_dma, &buf_dma_len);
+
+	dma_unmap_single(dev, buf_dma, buf_dma_len,
+			 DMA_TO_DEVICE);
+
+	next_desc_dma = cppi5_hdesc_get_next_hbdesc(first_desc);
+	while (next_desc_dma) {
+		next_desc = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool,
+						       next_desc_dma);
+		cppi5_hdesc_get_obuf(next_desc, &buf_dma, &buf_dma_len);
+
+		dma_unmap_page(dev, buf_dma, buf_dma_len,
+			       DMA_TO_DEVICE);
+
+		next_desc_dma = cppi5_hdesc_get_next_hbdesc(next_desc);
+
+		k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc);
+	}
+
+	k3_cppi_desc_pool_free(tx_chn->desc_pool, first_desc);
+}
+
+static void cpsw_virt_port_tx_cleanup(void *data, dma_addr_t desc_dma)
+{
+	struct cpsw_proxy_tx_chan *tx_chn = data;
+	struct cppi5_host_desc_t *desc_tx;
+	struct sk_buff *skb;
+	void **swdata;
+
+	desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma);
+	swdata = cppi5_hdesc_get_swdata(desc_tx);
+	skb = *(swdata);
+	cpsw_virt_port_xmit_free(tx_chn, tx_chn->dev, desc_tx);
+
+	dev_kfree_skb_any(skb);
+}
+
+static void cpsw_virt_port_rx_cleanup(void *data, dma_addr_t desc_dma)
+{
+	struct cpsw_proxy_rx_chan *rx_chn = data;
+	struct cppi5_host_desc_t *desc_rx;
+	struct sk_buff *skb;
+	dma_addr_t buf_dma;
+	u32 buf_dma_len;
+	void **swdata;
+
+	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
+	swdata = cppi5_hdesc_get_swdata(desc_rx);
+	skb = *swdata;
+	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
+
+	dma_unmap_single(rx_chn->dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
+	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
+
+	dev_kfree_skb_any(skb);
+}
+
+static void cpsw_virt_port_stop(struct cpsw_virt_port *virt_port)
+{
+	struct cpsw_proxy_common *common = virt_port->common;
+	int i;
+
+	/* shutdown tx channels */
+	atomic_set(&virt_port->tdown_cnt, CPSW_PROXY_CLIENT_MAX_TX_QUEUES);
+	/* ensure new tdown_cnt value is visible */
+	smp_mb__after_atomic();
+	reinit_completion(&virt_port->tdown_complete);
+
+	k3_udma_glue_tdown_tx_chn(virt_port->virt_port_tx_chan.tx_chan, false);
+
+	i = wait_for_completion_timeout(&virt_port->tdown_complete, msecs_to_jiffies(1000));
+	if (!i)
+		dev_err(common->dev, "tx teardown timeout\n");
+
+	k3_udma_glue_reset_tx_chn(virt_port->virt_port_tx_chan.tx_chan,
+				  &virt_port->virt_port_tx_chan,
+				  cpsw_virt_port_tx_cleanup);
+	k3_udma_glue_disable_tx_chn(virt_port->virt_port_tx_chan.tx_chan);
+	napi_disable(&virt_port->napi_tx);
+	hrtimer_cancel(&virt_port->tx_hrtimer);
+
+	k3_udma_glue_rx_flow_disable(virt_port->virt_port_rx_chan.rx_chan, 0);
+	/* Need some delay to process RX ring before reset */
+	msleep(100);
+	k3_udma_glue_reset_rx_chn(virt_port->virt_port_rx_chan.rx_chan, 0,
+				  &virt_port->virt_port_rx_chan,
+				  cpsw_virt_port_rx_cleanup, false);
+	napi_disable(&virt_port->napi_rx);
+	hrtimer_cancel(&virt_port->rx_hrtimer);
+	cancel_work_sync(&virt_port->rx_mode_work);
+}
+
+static int cpsw_virt_port_add_mcast(struct net_device *ndev, const u8 *addr)
+{
+	struct cpsw_virt_port *virt_port = cpsw_virt_port_ndev_to_virt_port(ndev);
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct message response;
+	int ret;
+
+	mutex_lock(&virt_port->mcast_filter_mutex);
+	ether_addr_copy(virt_port->mcast_mac_addr, addr);
+	virt_port->vlan_id = ETHREMOTECFG_ETHSWITCH_VLAN_USE_DFLT;
+
+	ret = cpsw_proxy_client_send_request(common, virt_port, virt_port->virt_port_token,
+					     ETHREMOTECFG_FILTER_MAC_ADD, &response);
+	if (ret)
+		dev_err(common->dev, "failed to add multicast mac filter err: %d\n", ret);
+
+	mutex_unlock(&virt_port->mcast_filter_mutex);
+	return ret;
+}
+
+static int cpsw_virt_port_del_mcast(struct net_device *ndev, const u8 *addr)
+{
+	struct cpsw_virt_port *virt_port = cpsw_virt_port_ndev_to_virt_port(ndev);
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct message response;
+	int ret;
+
+	mutex_lock(&virt_port->mcast_filter_mutex);
+	ether_addr_copy(virt_port->mcast_mac_addr, addr);
+	virt_port->vlan_id = ETHREMOTECFG_ETHSWITCH_VLAN_USE_DFLT;
+
+	ret = cpsw_proxy_client_send_request(common, virt_port, virt_port->virt_port_token,
+					     ETHREMOTECFG_FILTER_MAC_DEL, &response);
+	if (ret)
+		dev_err(common->dev, "failed to delete multicast mac filter err: %d\n", ret);
+
+	mutex_unlock(&virt_port->mcast_filter_mutex);
+	return ret;
+}
+
+static int cpsw_virt_port_ndo_stop(struct net_device *ndev)
+{
+	struct cpsw_virt_port *virt_port = cpsw_virt_port_ndev_to_virt_port(ndev);
+	struct cpsw_proxy_common *common = virt_port->common;
+	int ret;
+
+	netif_tx_stop_all_queues(ndev);
+	netif_carrier_off(ndev);
+
+	ret = cpsw_proxy_client_deregister_mac(virt_port);
+	if (ret)
+		dev_err(common->dev, "failed to deregister mac for virt port %u\n",
+			virt_port->virt_port_id);
+
+	__dev_mc_unsync(ndev, cpsw_virt_port_del_mcast);
+	__hw_addr_init(&virt_port->mcast_list);
+	cpsw_virt_port_stop(virt_port);
+
+	dev_info(common->dev, "stopped virt port: %u on interface: %s\n", virt_port->virt_port_id,
+		 virt_port->ndev->name);
+	return 0;
+}
+
+static int cpsw_virt_port_ndo_open(struct net_device *ndev)
+{
+	struct cpsw_virt_port *virt_port = cpsw_virt_port_ndev_to_virt_port(ndev);
+	struct cpsw_proxy_common *common = virt_port->common;
+	int ret;
+
+	netdev_tx_reset_queue(netdev_get_tx_queue(ndev, 0));
+
+	ret = cpsw_virt_port_open(virt_port, ndev->features);
+	if (ret)
+		return ret;
+
+	ret = cpsw_proxy_client_register_mac(virt_port);
+	if (ret) {
+		dev_err(common->dev, "failed to register mac for virt port %u\n",
+			virt_port->virt_port_id);
+		cpsw_virt_port_stop(virt_port);
+		return ret;
+	}
+
+	netif_tx_wake_all_queues(ndev);
+	netif_carrier_on(ndev);
+
+	dev_info(common->dev, "started virt port: %u on interface %s\n", virt_port->virt_port_id,
+		 virt_port->ndev->name);
+	return 0;
+}
+
+static netdev_tx_t cpsw_virt_port_ndo_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct cpsw_virt_port *virt_port = cpsw_virt_port_ndev_to_virt_port(ndev);
+	struct cppi5_host_desc_t *first_desc, *next_desc, *cur_desc;
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct cpsw_proxy_tx_chan *tx_chn;
+	struct device *dev = common->dev;
+	struct netdev_queue *netif_txq;
+	dma_addr_t desc_dma, buf_dma;
+	void **swdata;
+	u32 pkt_len;
+	u32 *psdata;
+	int ret, i;
+
+	/* padding enabled in hw */
+	pkt_len = skb_headlen(skb);
+
+	tx_chn = &virt_port->virt_port_tx_chan;
+	netif_txq = netdev_get_tx_queue(ndev, 0);
+
+	/* Map the linear buffer */
+	buf_dma = dma_map_single(dev, skb->data, pkt_len,
+				 DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(dev, buf_dma))) {
+		dev_err(dev, "Failed to map tx skb buffer\n");
+		ndev->stats.tx_errors++;
+		goto drop_free_skb;
+	}
+
+	first_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
+	if (!first_desc) {
+		dev_dbg(dev, "Failed to allocate descriptor\n");
+		dma_unmap_single(dev, buf_dma, pkt_len, DMA_TO_DEVICE);
+		goto busy_stop_q;
+	}
+
+	cppi5_hdesc_init(first_desc, CPPI5_INFO0_HDESC_EPIB_PRESENT,
+			 CPSW_PROXY_CLIENT_NAV_PS_DATA_SIZE);
+	cppi5_desc_set_pktids(&first_desc->hdr, 0, 0x3FFF);
+	cppi5_hdesc_set_pkttype(first_desc, 0x7);
+	/* target port has to be 0 */
+	cppi5_desc_set_tags_ids(&first_desc->hdr, 0, virt_port->virt_port_type);
+
+	cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len);
+	swdata = cppi5_hdesc_get_swdata(first_desc);
+	*(swdata) = skb;
+	psdata = cppi5_hdesc_get_psdata(first_desc);
+
+	/* HW csum offload if enabled */
+	psdata[2] = 0;
+	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+		unsigned int cs_start, cs_offset;
+
+		cs_start = skb_transport_offset(skb);
+		cs_offset = cs_start + skb->csum_offset;
+		/* HW numerates bytes starting from 1 */
+		psdata[2] = ((cs_offset + 1) << 24) |
+			    ((cs_start + 1) << 16) | (skb->len - cs_start);
+		dev_dbg(dev, "%s tx psdata:%#x\n", __func__, psdata[2]);
+	}
+
+	if (!skb_is_nonlinear(skb))
+		goto done_tx;
+
+	dev_dbg(dev, "fragmented SKB\n");
+
+	/* Handle the case where skb is fragmented in pages */
+	cur_desc = first_desc;
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+		u32 frag_size = skb_frag_size(frag);
+
+		next_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
+		if (!next_desc) {
+			dev_err(dev, "Failed to allocate descriptor\n");
+			goto busy_free_descs;
+		}
+
+		buf_dma = skb_frag_dma_map(dev, frag, 0, frag_size,
+					   DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(dev, buf_dma))) {
+			dev_err(dev, "Failed to map tx skb page\n");
+			k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc);
+			ndev->stats.tx_errors++;
+			goto drop_free_descs;
+		}
+
+		cppi5_hdesc_reset_hbdesc(next_desc);
+		cppi5_hdesc_attach_buf(next_desc,
+				       buf_dma, frag_size, buf_dma, frag_size);
+
+		desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool,
+						      next_desc);
+		cppi5_hdesc_link_hbdesc(cur_desc, desc_dma);
+
+		pkt_len += frag_size;
+		cur_desc = next_desc;
+	}
+	WARN_ON(pkt_len != skb->len);
+
+done_tx:
+	skb_tx_timestamp(skb);
+
+	/* report bql before sending packet */
+	dev_dbg(dev, "push 0 %d Bytes\n", pkt_len);
+
+	netdev_tx_sent_queue(netif_txq, pkt_len);
+
+	cppi5_hdesc_set_pktlen(first_desc, pkt_len);
+	desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, first_desc);
+	ret = k3_udma_glue_push_tx_chn(tx_chn->tx_chan, first_desc, desc_dma);
+	if (ret) {
+		dev_err(dev, "can't push desc %d\n", ret);
+		/* inform bql */
+		netdev_tx_completed_queue(netif_txq, 1, pkt_len);
+		ndev->stats.tx_errors++;
+		goto drop_free_descs;
+	}
+
+	if (k3_cppi_desc_pool_avail(tx_chn->desc_pool) < MAX_SKB_FRAGS) {
+		netif_tx_stop_queue(netif_txq);
+		/* Barrier, so that stop_queue visible to other cpus */
+		smp_mb__after_atomic();
+		dev_dbg(dev, "netif_tx_stop_queue %d\n", 0);
+
+		/* re-check for smp */
+		if (k3_cppi_desc_pool_avail(tx_chn->desc_pool) >=
+		    MAX_SKB_FRAGS) {
+			netif_tx_wake_queue(netif_txq);
+			dev_dbg(dev, "netif_tx_wake_queue %d\n", 0);
+		}
+	}
+
+	return NETDEV_TX_OK;
+
+drop_free_descs:
+	cpsw_virt_port_xmit_free(tx_chn, dev, first_desc);
+drop_free_skb:
+	ndev->stats.tx_dropped++;
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+
+busy_free_descs:
+	cpsw_virt_port_xmit_free(tx_chn, dev, first_desc);
+busy_stop_q:
+	netif_tx_stop_queue(netif_txq);
+	return NETDEV_TX_BUSY;
+}
+
+static void cpsw_virt_port_ndo_get_stats(struct net_device *ndev,
+					 struct rtnl_link_stats64 *stats)
+{
+	struct cpsw_virt_port_ndev_priv *ndev_priv = netdev_priv(ndev);
+	unsigned int start;
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		struct cpsw_virt_port_ndev_stats *cpu_stats;
+		u64 rx_packets;
+		u64 rx_bytes;
+		u64 tx_packets;
+		u64 tx_bytes;
+
+		cpu_stats = per_cpu_ptr(ndev_priv->stats, cpu);
+		do {
+			start = u64_stats_fetch_begin(&cpu_stats->syncp);
+			rx_packets = cpu_stats->rx_packets;
+			rx_bytes   = cpu_stats->rx_bytes;
+			tx_packets = cpu_stats->tx_packets;
+			tx_bytes   = cpu_stats->tx_bytes;
+		} while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
+
+		stats->rx_packets += rx_packets;
+		stats->rx_bytes   += rx_bytes;
+		stats->tx_packets += tx_packets;
+		stats->tx_bytes   += tx_bytes;
+	}
+
+	stats->rx_errors	= ndev->stats.rx_errors;
+	stats->rx_dropped	= ndev->stats.rx_dropped;
+	stats->tx_dropped	= ndev->stats.tx_dropped;
+}
+
+static void cpsw_virt_port_host_tx_timeout(struct net_device *ndev, unsigned int txqueue)
+{
+	struct cpsw_virt_port *virt_port = cpsw_virt_port_ndev_to_virt_port(ndev);
+	struct cpsw_proxy_tx_chan *tx_chn = &virt_port->virt_port_tx_chan;
+	struct netdev_queue *netif_txq;
+	unsigned long trans_start;
+
+	/* process every txq */
+	netif_txq = netdev_get_tx_queue(ndev, txqueue);
+	trans_start = netif_txq->trans_start;
+
+	netdev_err(ndev, "txq:%d DRV_XOFF:%d tmo:%u dql_avail:%d free_desc:%zu\n",
+		   txqueue,
+		   netif_tx_queue_stopped(netif_txq),
+		   jiffies_to_msecs(jiffies - trans_start),
+		   dql_avail(&netif_txq->dql),
+		   k3_cppi_desc_pool_avail(tx_chn->desc_pool));
+
+	if (netif_tx_queue_stopped(netif_txq)) {
+		/* try recover if stopped by us */
+		txq_trans_update(netif_txq);
+		netif_tx_wake_queue(netif_txq);
+	}
+}
+
+static void cpsw_virt_port_set_rx_mode_work(struct work_struct *work)
+{
+	struct cpsw_virt_port *virt_port = container_of(work, struct cpsw_virt_port, rx_mode_work);
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct net_device *ndev;
+	struct message response;
+	u32 promisc_req_type;
+	bool promisc_status;
+	int ret;
+
+	if (virt_port->virt_port_type == VIRT_MAC_ONLY_PORT) {
+		/* If current state is same as desired state, exit */
+		promisc_status = virt_port->ndev->flags & IFF_PROMISC;
+		if (promisc_status == virt_port->promisc_enabled)
+			return;
+
+		virt_port->promisc_enabled = promisc_status;
+		if (virt_port->promisc_enabled)
+			promisc_req_type = ETHREMOTECFG_PROMISC_ENABLE;
+		else
+			promisc_req_type = ETHREMOTECFG_PROMISC_DISABLE;
+
+		ret = cpsw_proxy_client_send_request(common, virt_port, virt_port->virt_port_token,
+						     promisc_req_type, &response);
+		if (ret)
+			dev_err(common->dev, "failed to send Promiscuous Mode request %d\n", ret);
+
+	} else if (virt_port->mcast_filter) {
+		ndev = virt_port->ndev;
+
+		/* make a mc list copy */
+		netif_addr_lock_bh(ndev);
+		__hw_addr_sync(&virt_port->mcast_list, &ndev->mc, ndev->addr_len);
+		netif_addr_unlock_bh(ndev);
+
+		__hw_addr_sync_dev(&virt_port->mcast_list, ndev,
+				   cpsw_virt_port_add_mcast, cpsw_virt_port_del_mcast);
+	}
+}
+
+static void cpsw_virt_port_set_rx_mode(struct net_device *ndev)
+{
+	struct cpsw_virt_port *virt_port = cpsw_virt_port_ndev_to_virt_port(ndev);
+
+	if (virt_port->virt_port_type == VIRT_MAC_ONLY_PORT || virt_port->mcast_filter)
+		queue_work(virt_port->virt_port_wq, &virt_port->rx_mode_work);
+}
+
+static const struct net_device_ops cpsw_virt_port_netdev_ops = {
+	.ndo_open		= cpsw_virt_port_ndo_open,
+	.ndo_stop		= cpsw_virt_port_ndo_stop,
+	.ndo_start_xmit		= cpsw_virt_port_ndo_xmit,
+	.ndo_get_stats64        = cpsw_virt_port_ndo_get_stats,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_tx_timeout		= cpsw_virt_port_host_tx_timeout,
+	.ndo_set_rx_mode	= cpsw_virt_port_set_rx_mode,
+};
+
+static int cpsw_virt_port_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
+				       struct kernel_ethtool_coalesce *kernel_coal,
+				       struct netlink_ext_ack *extack)
+{
+	struct cpsw_virt_port *virt_port = cpsw_virt_port_ndev_to_virt_port(ndev);
+
+	coal->tx_coalesce_usecs = virt_port->tx_pace_timeout / 1000;
+	coal->rx_coalesce_usecs = virt_port->rx_pace_timeout / 1000;
+	return 0;
+}
+
+static int cpsw_virt_port_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
+				       struct kernel_ethtool_coalesce *kernel_coal,
+				       struct netlink_ext_ack *extack)
+{
+	struct cpsw_virt_port *virt_port = cpsw_virt_port_ndev_to_virt_port(ndev);
+	struct cpsw_proxy_common *common = virt_port->common;
+
+	if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20) {
+		dev_err(common->dev, "TX coalesce must be at least 20 usecs. Defaulting to 20 usecs\n");
+		coal->tx_coalesce_usecs = 20;
+	}
+
+	if (coal->rx_coalesce_usecs && coal->rx_coalesce_usecs < 20) {
+		dev_err(common->dev, "RX coalesce must be at least 20 usecs. Defaulting to 20 usecs\n");
+		coal->rx_coalesce_usecs = 20;
+	}
+
+	virt_port->tx_pace_timeout = coal->tx_coalesce_usecs * 1000;
+	virt_port->rx_pace_timeout = coal->rx_coalesce_usecs * 1000;
+	return 0;
+}
+
+static u32 cpsw_virt_port_get_link(struct net_device *ndev)
+{
+	struct cpsw_virt_port *virt_port = cpsw_virt_port_ndev_to_virt_port(ndev);
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct port_link_status_response *link_stat;
+	struct message response;
+	bool link_up;
+	int ret;
+
+	if (virt_port->virt_port_type != VIRT_MAC_ONLY_PORT)
+		return ethtool_op_get_link(ndev);
+
+	ret = cpsw_proxy_client_send_request(common, virt_port, virt_port->virt_port_token,
+					     ETHREMOTECFG_PORT_LINK_STATUS, &response);
+	if (ret) {
+		dev_err(common->dev, "failed to get link status err: %d\n", ret);
+		/* Assume that link is down if status is not known */
+		return 0;
+	}
+
+	link_stat = (struct port_link_status_response *)&response;
+	link_up = link_stat->link_up;
+
+	return link_up;
+}
+
+const struct ethtool_ops cpsw_virt_port_ethtool_ops = {
+	.get_link		= cpsw_virt_port_get_link,
+	.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
+	.get_coalesce           = cpsw_virt_port_get_coalesce,
+	.set_coalesce           = cpsw_virt_port_set_coalesce,
+};
+
+static enum hrtimer_restart cpsw_virt_port_tx_timer_callback(struct hrtimer *timer)
+{
+	struct cpsw_virt_port *virt_port = container_of(timer, struct cpsw_virt_port, tx_hrtimer);
+
+	enable_irq(virt_port->virt_port_tx_chan.irq);
+	return HRTIMER_NORESTART;
+}
+
+static enum hrtimer_restart cpsw_virt_port_rx_timer_callback(struct hrtimer *timer)
+{
+	struct cpsw_virt_port *virt_port = container_of(timer, struct cpsw_virt_port, rx_hrtimer);
+
+	enable_irq(virt_port->virt_port_rx_chan.irq);
+	return HRTIMER_NORESTART;
+}
+
+static int cpsw_virt_port_tx_compl_packets(struct cpsw_virt_port *virt_port,
+					   int chn, unsigned int budget, bool *tdown)
+{
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct cppi5_host_desc_t *desc_tx;
+	struct cpsw_proxy_tx_chan *tx_chn;
+	struct device *dev = common->dev;
+	struct netdev_queue *netif_txq;
+	unsigned int total_bytes = 0;
+	struct net_device *ndev;
+	struct sk_buff *skb;
+	dma_addr_t desc_dma;
+	int res, num_tx = 0;
+	void **swdata;
+
+	tx_chn = &virt_port->virt_port_tx_chan;
+
+	while (budget--) {
+		struct cpsw_virt_port_ndev_priv *ndev_priv;
+		struct cpsw_virt_port_ndev_stats *stats;
+
+		res = k3_udma_glue_pop_tx_chn(tx_chn->tx_chan, &desc_dma);
+		if (res == -ENODATA)
+			break;
+
+		if (desc_dma & 0x1) {
+			if (atomic_dec_and_test(&virt_port->tdown_cnt))
+				complete(&virt_port->tdown_complete);
+			*tdown = true;
+			break;
+		}
+
+		desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool,
+						     desc_dma);
+		swdata = cppi5_hdesc_get_swdata(desc_tx);
+		skb = *(swdata);
+		cpsw_virt_port_xmit_free(tx_chn, dev, desc_tx);
+
+		ndev = skb->dev;
+
+		ndev_priv = netdev_priv(ndev);
+		stats = this_cpu_ptr(ndev_priv->stats);
+		u64_stats_update_begin(&stats->syncp);
+		stats->tx_packets++;
+		stats->tx_bytes += skb->len;
+		u64_stats_update_end(&stats->syncp);
+
+		total_bytes += skb->len;
+		napi_consume_skb(skb, budget);
+		num_tx++;
+	}
+
+	if (!num_tx)
+		return 0;
+
+	netif_txq = netdev_get_tx_queue(ndev, 0);
+
+	netdev_tx_completed_queue(netif_txq, num_tx, total_bytes);
+	dev_dbg(dev, "compl 0 %d Bytes\n", total_bytes);
+
+	if (netif_tx_queue_stopped(netif_txq)) {
+		/* Check whether the queue is stopped due to stalled tx dma,
+		 * if the queue is stopped then wake the queue as
+		 * we have free desc for tx
+		 */
+		__netif_tx_lock(netif_txq, smp_processor_id());
+		if (netif_running(ndev) &&
+		    (k3_cppi_desc_pool_avail(tx_chn->desc_pool) >=
+		     MAX_SKB_FRAGS))
+			netif_tx_wake_queue(netif_txq);
+
+		__netif_tx_unlock(netif_txq);
+	}
+	dev_dbg(dev, "%s:%u pkt:%d\n", __func__, chn, num_tx);
+
+	return num_tx;
+}
+
+static int cpsw_virt_port_tx_poll(struct napi_struct *napi_tx, int budget)
+{
+	struct cpsw_virt_port *virt_port = container_of(napi_tx, struct cpsw_virt_port, napi_tx);
+	bool tdown = false;
+	int num_tx;
+
+	/* process every unprocessed channel */
+	num_tx = cpsw_virt_port_tx_compl_packets(virt_port, 0, budget, &tdown);
+
+	if (num_tx >= budget)
+		return budget;
+
+	if (napi_complete_done(napi_tx, num_tx)) {
+		if (unlikely(virt_port->tx_pace_timeout && !tdown)) {
+			hrtimer_start(&virt_port->tx_hrtimer,
+				      ns_to_ktime(virt_port->tx_pace_timeout),
+				      HRTIMER_MODE_REL_PINNED);
+		} else {
+			enable_irq(virt_port->virt_port_tx_chan.irq);
+		}
+	}
+
+	return 0;
+}
+
+/* RX psdata[2] word format - checksum information */
+#define CPSW_RX_PSD_CSUM_ADD	GENMASK(15, 0)
+#define CPSW_RX_PSD_CSUM_ERR	BIT(16)
+#define CPSW_RX_PSD_IS_FRAGMENT	BIT(17)
+#define CPSW_RX_PSD_IS_TCP		BIT(18)
+#define CPSW_RX_PSD_IPV6_VALID	BIT(19)
+#define CPSW_RX_PSD_IPV4_VALID	BIT(20)
+
+static void cpsw_virt_port_rx_csum(struct sk_buff *skb, u32 csum_info)
+{
+	/* HW can verify IPv4/IPv6 TCP/UDP packets checksum
+	 * csum information provides in psdata[2] word:
+	 * CPSW_RX_PSD_CSUM_ERR bit - indicates csum error
+	 * CPSW_RX_PSD_IPV6_VALID and CPSW_RX_PSD_IPV4_VALID
+	 * bits - indicates IPv4/IPv6 packet
+	 * CPSW_RX_PSD_IS_FRAGMENT bit - indicates fragmented packet
+	 * CPSW_RX_PSD_CSUM_ADD has value 0xFFFF for non fragmented packets
+	 * or csum value for fragmented packets if !CPSW_RX_PSD_CSUM_ERR
+	 */
+	skb_checksum_none_assert(skb);
+
+	if (unlikely(!(skb->dev->features & NETIF_F_RXCSUM)))
+		return;
+
+	if ((csum_info & (CPSW_RX_PSD_IPV6_VALID |
+			  CPSW_RX_PSD_IPV4_VALID)) &&
+			  !(csum_info & CPSW_RX_PSD_CSUM_ERR)) {
+		/* csum for fragmented packets is unsupported */
+		if (!(csum_info & CPSW_RX_PSD_IS_FRAGMENT))
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+	}
+}
+
+static int cpsw_virt_port_rx_packets(struct cpsw_virt_port *virt_port,
+				     u32 flow_idx)
+{
+	struct cpsw_proxy_rx_chan *rx_chn = &virt_port->virt_port_rx_chan;
+	struct cpsw_proxy_common *common = virt_port->common;
+	u32 buf_dma_len, pkt_len, port_id = 0, csum_info;
+	struct cpsw_virt_port_ndev_priv *ndev_priv;
+	struct cpsw_virt_port_ndev_stats *stats;
+	struct cppi5_host_desc_t *desc_rx;
+	struct device *dev = common->dev;
+	struct sk_buff *skb, *new_skb;
+	dma_addr_t desc_dma, buf_dma;
+	struct net_device *ndev;
+	void **swdata;
+	int ret = 0;
+	u32 *psdata;
+
+	ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chan, flow_idx, &desc_dma);
+	if (ret) {
+		if (ret != -ENODATA)
+			dev_err(dev, "RX: pop chn fail %d\n", ret);
+		return ret;
+	}
+
+	if (desc_dma & 0x1) {
+		dev_dbg(dev, "%s RX tdown flow: %u\n", __func__, flow_idx);
+		return 0;
+	}
+
+	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
+	dev_dbg(dev, "%s flow_idx: %u desc %pad\n",
+		__func__, flow_idx, &desc_dma);
+
+	swdata = cppi5_hdesc_get_swdata(desc_rx);
+	skb = *swdata;
+	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
+	pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
+	cppi5_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL);
+	/* read port for dbg */
+	dev_dbg(dev, "%s rx port_id:%d\n", __func__, port_id);
+	ndev = virt_port->ndev;
+	skb->dev = ndev;
+
+	psdata = cppi5_hdesc_get_psdata(desc_rx);
+	csum_info = psdata[2];
+	dev_dbg(dev, "%s rx csum_info:%#x\n", __func__, csum_info);
+
+	dma_unmap_single(dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
+
+	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
+
+	if (unlikely(!netif_running(skb->dev))) {
+		dev_kfree_skb_any(skb);
+		return -ENODEV;
+	}
+
+	new_skb = netdev_alloc_skb_ip_align(ndev, CPSW_PROXY_CLIENT_MAX_PACKET_SIZE);
+	if (new_skb) {
+		skb_put(skb, pkt_len);
+		skb->protocol = eth_type_trans(skb, ndev);
+		cpsw_virt_port_rx_csum(skb, csum_info);
+		napi_gro_receive(&virt_port->napi_rx, skb);
+
+		ndev_priv = netdev_priv(ndev);
+		stats = this_cpu_ptr(ndev_priv->stats);
+
+		u64_stats_update_begin(&stats->syncp);
+		stats->rx_packets++;
+		stats->rx_bytes += pkt_len;
+		u64_stats_update_end(&stats->syncp);
+		kmemleak_not_leak(new_skb);
+	} else {
+		ndev->stats.rx_dropped++;
+		new_skb = skb;
+	}
+
+	if (netif_dormant(ndev)) {
+		dev_kfree_skb_any(new_skb);
+		ndev->stats.rx_dropped++;
+		return -ENODEV;
+	}
+
+	ret = cpsw_virt_port_rx_push(virt_port, new_skb);
+	if (WARN_ON(ret < 0)) {
+		dev_kfree_skb_any(new_skb);
+		ndev->stats.rx_errors++;
+		ndev->stats.rx_dropped++;
+	}
+
+	return ret;
+}
+
+static int cpsw_virt_port_rx_poll(struct napi_struct *napi_rx, int budget)
+{
+	struct cpsw_virt_port *virt_port = container_of(napi_rx, struct cpsw_virt_port, napi_rx);
+	int num_rx = 0;
+	int cur_budget;
+	int ret;
+
+	/* process every flow */
+	cur_budget = budget;
+
+	while (cur_budget--) {
+		ret = cpsw_virt_port_rx_packets(virt_port, 0);
+		if (ret)
+			break;
+		num_rx++;
+	}
+
+	if (num_rx < budget && napi_complete_done(napi_rx, num_rx)) {
+		if (virt_port->rx_irq_disabled) {
+			virt_port->rx_irq_disabled = false;
+			if (unlikely(virt_port->rx_pace_timeout)) {
+				hrtimer_start(&virt_port->rx_hrtimer,
+					      ns_to_ktime(virt_port->rx_pace_timeout),
+					      HRTIMER_MODE_REL_PINNED);
+			} else {
+				enable_irq(virt_port->virt_port_rx_chan.irq);
+			}
+		}
+	}
+
+	return num_rx;
+}
+
+static void
+cpsw_proxy_client_unreg_ndevs(struct cpsw_proxy_common *common)
+{
+	struct cpsw_virt_port *virt_port;
+	int i;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+		if (virt_port->ndev)
+			unregister_netdev(virt_port->ndev);
+	}
+}
+
+static int
+cpsw_proxy_client_init_ndev(struct cpsw_proxy_common *common, struct cpsw_virt_port *virt_port)
+{
+	struct cpsw_virt_port_ndev_priv *ndev_priv;
+	struct device *dev = common->dev;
+	int ret = 0;
+
+	virt_port->ndev = devm_alloc_etherdev(dev, sizeof(struct cpsw_virt_port_ndev_priv));
+
+	if (!virt_port->ndev) {
+		dev_err(dev, "error allocating net device for port: %u\n", virt_port->virt_port_id);
+		return -ENOMEM;
+	}
+
+	ndev_priv = netdev_priv(virt_port->ndev);
+	ndev_priv->virt_port = virt_port;
+	SET_NETDEV_DEV(virt_port->ndev, dev);
+
+	if (is_valid_ether_addr(virt_port->mac_addr))
+		eth_hw_addr_set(virt_port->ndev, virt_port->mac_addr);
+
+	virt_port->ndev->min_mtu = CPSW_PROXY_CLIENT_MIN_PACKET_SIZE;
+	virt_port->ndev->max_mtu = CPSW_PROXY_CLIENT_MAX_PACKET_SIZE;
+	virt_port->ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM;
+	virt_port->ndev->features = virt_port->ndev->hw_features;
+	virt_port->ndev->vlan_features |=  NETIF_F_SG;
+	virt_port->ndev->netdev_ops = &cpsw_virt_port_netdev_ops;
+	virt_port->ndev->ethtool_ops = &cpsw_virt_port_ethtool_ops;
+
+	ndev_priv->stats = netdev_alloc_pcpu_stats(struct cpsw_virt_port_ndev_stats);
+	if (!ndev_priv->stats)
+		return -ENOMEM;
+
+	ret = devm_add_action_or_reset(dev, (void(*)(void *))free_percpu, ndev_priv->stats);
+	if (ret) {
+		dev_err(dev, "failed to add percpu stat free action %d", ret);
+		return ret;
+	}
+
+	netif_napi_add_tx(virt_port->ndev, &virt_port->napi_tx, cpsw_virt_port_tx_poll);
+	netif_napi_add(virt_port->ndev, &virt_port->napi_rx, cpsw_virt_port_rx_poll);
+
+	hrtimer_init(&virt_port->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
+	virt_port->tx_hrtimer.function = &cpsw_virt_port_tx_timer_callback;
+	hrtimer_init(&virt_port->rx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
+	virt_port->rx_hrtimer.function = &cpsw_virt_port_rx_timer_callback;
+
+	ret = register_netdev(virt_port->ndev);
+	if (ret)
+		dev_err(dev, "error registering net device %d\n", ret);
+
+	return ret;
+}
+
+static int cpsw_proxy_client_init_ndevs(struct cpsw_proxy_common *common)
+{
+	struct cpsw_virt_port *virt_port;
+	char work_queue_name[IFNAMSIZ];
+	int ret, i;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+		snprintf(work_queue_name, sizeof(work_queue_name), "virt_port_%d",
+			 virt_port->virt_port_id);
+		__hw_addr_init(&virt_port->mcast_list);
+		INIT_WORK(&virt_port->rx_mode_work, cpsw_virt_port_set_rx_mode_work);
+		virt_port->virt_port_wq = create_singlethread_workqueue(work_queue_name);
+		if (!virt_port->virt_port_wq) {
+			dev_err(common->dev, "failed to create workqueue %s\n", work_queue_name);
+			return -ENOMEM;
+		}
+	}
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+		ret = cpsw_proxy_client_init_ndev(common, virt_port);
+		if (ret) {
+			dev_err(common->dev, "failed to initialize netdevice: %d\n", ret);
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	cpsw_proxy_client_unreg_ndevs(common);
+	return ret;
+}
+
+static void cpsw_proxy_client_destroy_wq(struct cpsw_proxy_common *common)
+{
+	struct cpsw_virt_port *virt_port;
+	int i;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+		destroy_workqueue(virt_port->virt_port_wq);
+	}
+}
+
+static irqreturn_t cpsw_virt_port_tx_irq(int irq, void *dev_id)
+{
+	struct cpsw_virt_port *virt_port = dev_id;
+
+	disable_irq_nosync(irq);
+	napi_schedule(&virt_port->napi_tx);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t cpsw_virt_port_rx_irq(int irq, void *dev_id)
+{
+	struct cpsw_virt_port *virt_port = dev_id;
+
+	virt_port->rx_irq_disabled = true;
+	disable_irq_nosync(irq);
+	napi_schedule(&virt_port->napi_rx);
+
+	return IRQ_HANDLED;
+}
+
+static int cpsw_proxy_client_setup_irq(struct cpsw_proxy_common *common)
+{
+	struct device *dev = common->dev;
+	struct cpsw_virt_port *virt_port;
+	int ret = 0, i;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+
+		ret = devm_request_irq(dev, virt_port->virt_port_tx_chan.irq,
+				       cpsw_virt_port_tx_irq, IRQF_TRIGGER_HIGH,
+				       dev_name(dev), virt_port);
+		if (ret) {
+			dev_err(dev, "failure requesting tx irq: %u err: %d\n",
+				virt_port->virt_port_tx_chan.irq, ret);
+			goto err;
+		}
+
+		ret = devm_request_irq(dev, virt_port->virt_port_rx_chan.irq,
+				       cpsw_virt_port_rx_irq, IRQF_TRIGGER_HIGH,
+				       dev_name(dev), virt_port);
+		if (ret) {
+			dev_err(dev, "failure requesting rx irq: %u err: %d\n",
+				virt_port->virt_port_rx_chan.irq, ret);
+			goto err;
+		}
+	}
+
+err:
+	return ret;
+}
+
+static void cpsw_proxy_client_detach(struct cpsw_proxy_common *common)
+{
+	struct cpsw_virt_port *virt_port;
+	struct message response;
+	u32 port_id;
+	int ret, i;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+		port_id = virt_port->virt_port_id;
+
+		/* Free MAC Request */
+		ret = cpsw_proxy_client_send_request(common, virt_port,
+						     virt_port->virt_port_token,
+						     ETHREMOTECFG_FREE_MAC, &response);
+		if (ret) {
+			dev_err(common->dev, "failed to detach port %u err: %d\n", port_id, ret);
+			return;
+		}
+
+		/* Free TX DMA Channel */
+		ret = cpsw_proxy_client_send_request(common, virt_port,
+						     virt_port->virt_port_token,
+						     ETHREMOTECFG_FREE_TX, &response);
+		if (ret) {
+			dev_err(common->dev, "failed to detach port %u err: %d\n", port_id, ret);
+			return;
+		}
+
+		/* Free RX DMA Flow */
+		ret = cpsw_proxy_client_send_request(common, virt_port,
+						     virt_port->virt_port_token,
+						     ETHREMOTECFG_FREE_RX, &response);
+		if (ret) {
+			dev_err(common->dev, "failed to detach port %u err: %d\n", port_id, ret);
+			return;
+		}
+
+		/* Send Detach Request */
+		ret = cpsw_proxy_client_send_request(common, virt_port,
+						     virt_port->virt_port_token,
+						     ETHREMOTECFG_DETACH, &response);
+		if (ret) {
+			dev_err(common->dev, "failed to detach port %u err: %d\n", port_id, ret);
+			return;
+		}
+	}
+}
+
+static int cpsw_proxy_client_attach_ext(struct cpsw_proxy_common *common)
+{
+	struct attach_ext_response *att_ext_resp;
+	struct cpsw_virt_port *virt_port;
+	struct message response;
+	int ret, ret1, i;
+	u32 port_id;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+		port_id = virt_port->virt_port_id;
+
+		/* Send Attach Ext Request */
+		ret = cpsw_proxy_client_send_request(common, virt_port, ETHREMOTECFG_TOKEN_NONE,
+						     ETHREMOTECFG_ATTACH_EXT, &response);
+		if (ret) {
+			dev_err(common->dev, "failed to attach port %u err: %d\n", port_id, ret);
+			goto err;
+		}
+
+		att_ext_resp = (struct attach_ext_response *)&response;
+		virt_port->virt_port_token = att_ext_resp->response_msg_hdr.msg_hdr.token;
+		virt_port->tx_psil_dest_id = att_ext_resp->tx_psil_dest_id;
+		virt_port->rx_psil_src_id = att_ext_resp->rx_psil_src_id;
+		virt_port->rx_flow_idx_base = att_ext_resp->rx_flow_idx_base;
+		virt_port->rx_flow_idx_offset = att_ext_resp->rx_flow_idx_offset;
+		ether_addr_copy(virt_port->mac_addr, att_ext_resp->mac_addr);
+		virt_port->mcast_filter = att_ext_resp->features & ETHREMOTECFG_FEATURE_MC_FILTER;
+	}
+
+	return 0;
+
+err:
+	while (i--) {
+		virt_port = &common->virt_ports[i];
+		port_id = virt_port->virt_port_id;
+
+		/* Send Detach Request */
+		ret1 = cpsw_proxy_client_send_request(common, virt_port,
+						      virt_port->virt_port_token,
+						      ETHREMOTECFG_DETACH, &response);
+		if (ret1)
+			dev_err(common->dev, "failed to DETACH port: %u err: %d\n", port_id, ret1);
+	}
+
+	return ret;
+}
+
+static int cpsw_proxy_client_virt_port_init(struct cpsw_proxy_common *common)
+{
+	struct virt_port_alloc_response *vpa_resp;
+	struct cpsw_virt_port *virt_port;
+	unsigned int virt_port_idx, idx;
+	struct message response;
+	int ret, i;
+
+	/* Send Virtual Port Allocation Request
+	 * Since virt_port will be allocated after this request, it is not
+	 * going to be used in sending the request. Therefore use NULL instead.
+	 */
+	ret = cpsw_proxy_client_send_request(common, NULL, ETHREMOTECFG_TOKEN_NONE,
+					     ETHREMOTECFG_VIRT_PORT_ALLOC, &response);
+	if (ret) {
+		dev_err(common->dev, "failed to request virtual port details err: %d\n", ret);
+		return ret;
+	}
+
+	vpa_resp = (struct virt_port_alloc_response *)&response;
+	common->virt_switch_ports = vpa_resp->switch_port_mask;
+	common->virt_mac_only_ports = vpa_resp->mac_port_mask;
+	common->num_switch_ports = hweight32(common->virt_switch_ports);
+	common->num_virt_ports += common->num_switch_ports;
+	common->num_mac_only_ports = hweight32(common->virt_mac_only_ports);
+	common->num_virt_ports += common->num_mac_only_ports;
+	common->virt_ports = devm_kcalloc(common->dev, common->num_virt_ports,
+					  sizeof(*common->virt_ports), GFP_KERNEL);
+
+	/* Populate details in the virtual port structures */
+	virt_port_idx = 0;
+	idx = 0;
+	for (i = 0; i < common->num_switch_ports; i++) {
+		virt_port = &common->virt_ports[virt_port_idx];
+		virt_port->common = common;
+		virt_port->virt_port_type = VIRT_SWITCH_PORT;
+		virt_port->virt_port_id = fns(common->virt_switch_ports, idx);
+		mutex_init(&virt_port->mcast_filter_mutex);
+
+		virt_port_idx++;
+		idx++;
+	}
+
+	idx = 0;
+	for (i = 0; i < common->num_mac_only_ports; i++) {
+		virt_port = &common->virt_ports[virt_port_idx];
+		virt_port->common = common;
+		virt_port->virt_port_type = VIRT_MAC_ONLY_PORT;
+		virt_port->virt_port_id = fns(common->virt_mac_only_ports, idx);
+		mutex_init(&virt_port->mcast_filter_mutex);
+
+		virt_port_idx++;
+		idx++;
+	}
+
+	return 0;
+}
+
+static void cpsw_virt_port_free_tx_chns(void *data)
+{
+	struct cpsw_proxy_common *common = data;
+	struct cpsw_proxy_tx_chan *tx_chn;
+	struct cpsw_virt_port *virt_port;
+	int i;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+		tx_chn = &virt_port->virt_port_tx_chan;
+
+		if (!IS_ERR_OR_NULL(tx_chn->desc_pool))
+			k3_cppi_desc_pool_destroy(tx_chn->desc_pool);
+
+		if (!IS_ERR_OR_NULL(tx_chn->tx_chan))
+			k3_udma_glue_release_tx_chn(tx_chn->tx_chan);
+
+		memset(tx_chn, 0, sizeof(*tx_chn));
+	}
+}
+
+static int cpsw_proxy_client_init_tx_chans(struct cpsw_proxy_common *common)
+{
+	u32 max_desc_num = ALIGN(CPSW_PROXY_CLIENT_MAX_TX_DESC, MAX_SKB_FRAGS);
+	struct k3_udma_glue_tx_channel_cfg tx_cfg = { 0 };
+	struct cpsw_proxy_tx_chan *tx_chn;
+	struct device *dev = common->dev;
+	struct cpsw_virt_port *virt_port;
+	struct k3_ring_cfg ring_cfg = {
+		.elm_size = K3_RINGACC_RING_ELSIZE_8,
+		.mode = K3_RINGACC_RING_MODE_RING,
+		.flags = 0
+	};
+	char tx_chn_name[IFNAMSIZ];
+	u32 hdesc_size, tx_chn_num;
+	int ret = 0, ret1, i;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+		tx_chn = &virt_port->virt_port_tx_chan;
+
+		tx_chn_num = common->num_active_tx_channels++;
+		snprintf(tx_chn_name, sizeof(tx_chn_name), "tx%d", tx_chn_num);
+
+		init_completion(&virt_port->tdown_complete);
+
+		hdesc_size = cppi5_hdesc_calc_size(true, CPSW_PROXY_CLIENT_NAV_PS_DATA_SIZE,
+						   CPSW_PROXY_CLIENT_NAV_SW_DATA_SIZE);
+
+		tx_cfg.swdata_size = CPSW_PROXY_CLIENT_NAV_SW_DATA_SIZE;
+		tx_cfg.tx_cfg = ring_cfg;
+		tx_cfg.txcq_cfg = ring_cfg;
+		tx_cfg.tx_cfg.size = max_desc_num;
+		tx_cfg.txcq_cfg.size = max_desc_num;
+
+		tx_chn->dev = dev;
+		tx_chn->num_descs = max_desc_num;
+		tx_chn->desc_pool = k3_cppi_desc_pool_create_name(dev,
+								  tx_chn->num_descs,
+								  hdesc_size,
+								  tx_chn_name);
+		if (IS_ERR(tx_chn->desc_pool)) {
+			ret = PTR_ERR(tx_chn->desc_pool);
+			dev_err(dev, "Failed to create tx pool %d\n", ret);
+			goto err;
+		}
+
+		tx_chn->tx_chan = k3_udma_glue_request_tx_chn_by_id(dev, &tx_cfg, common->dma_node,
+								    virt_port->tx_psil_dest_id);
+		if (IS_ERR(tx_chn->tx_chan)) {
+			ret = PTR_ERR(tx_chn->tx_chan);
+			dev_err(dev, "Failed to request tx dma channel %d\n", ret);
+			goto err;
+		}
+
+		tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chan);
+		if (tx_chn->irq <= 0) {
+			dev_err(dev, "Failed to get tx dma irq %d\n", tx_chn->irq);
+			ret = -ENXIO;
+		}
+	}
+
+err:
+	ret1 = devm_add_action(dev, cpsw_virt_port_free_tx_chns, common);
+	if (ret1) {
+		dev_err(dev, "failed to add free_tx_chns action %d", ret1);
+		return ret1;
+	}
+
+	return ret;
+}
+
+static void cpsw_proxy_client_free_rx_chns(void *data)
+{
+	struct cpsw_proxy_common *common = data;
+	struct cpsw_proxy_rx_chan *rx_chn;
+	struct cpsw_virt_port *virt_port;
+	int i;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+		rx_chn = &virt_port->virt_port_rx_chan;
+
+		if (!IS_ERR_OR_NULL(rx_chn->desc_pool))
+			k3_cppi_desc_pool_destroy(rx_chn->desc_pool);
+
+		if (!IS_ERR_OR_NULL(rx_chn->rx_chan))
+			k3_udma_glue_release_rx_chn(rx_chn->rx_chan);
+	}
+}
+
+static int cpsw_proxy_client_init_rx_chans(struct cpsw_proxy_common *common)
+{
+	u32  max_desc_num = CPSW_PROXY_CLIENT_MAX_RX_DESC;
+	struct k3_udma_glue_rx_channel_cfg rx_cfg = {0};
+	struct cpsw_proxy_rx_chan *rx_chn;
+	struct device *dev = common->dev;
+	struct cpsw_virt_port *virt_port;
+	char rx_chn_name[IFNAMSIZ];
+	u32 hdesc_size, rx_chn_num;
+	struct k3_ring_cfg rxring_cfg = {
+		.elm_size = K3_RINGACC_RING_ELSIZE_8,
+		.mode = K3_RINGACC_RING_MODE_MESSAGE,
+		.flags = 0,
+	};
+	struct k3_ring_cfg fdqring_cfg = {
+		.elm_size = K3_RINGACC_RING_ELSIZE_8,
+		.mode = K3_RINGACC_RING_MODE_MESSAGE,
+		.flags = 0,
+	};
+	struct k3_udma_glue_rx_flow_cfg rx_flow_cfg = {
+		.rx_cfg = rxring_cfg,
+		.rxfdq_cfg = fdqring_cfg,
+		.ring_rxq_id = K3_RINGACC_RING_ID_ANY,
+		.ring_rxfdq0_id = K3_RINGACC_RING_ID_ANY,
+		.src_tag_lo_sel = K3_UDMA_GLUE_SRC_TAG_LO_USE_REMOTE_SRC_TAG,
+	};
+	int ret = 0, ret1, i;
+
+	hdesc_size = cppi5_hdesc_calc_size(true, CPSW_PROXY_CLIENT_NAV_PS_DATA_SIZE,
+					   CPSW_PROXY_CLIENT_NAV_SW_DATA_SIZE);
+
+	rx_cfg.swdata_size = CPSW_PROXY_CLIENT_NAV_SW_DATA_SIZE;
+	rx_cfg.flow_id_num = CPSW_PROXY_CLIENT_MAX_RX_FLOWS;
+	rx_cfg.remote = true;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+		rx_chn = &virt_port->virt_port_rx_chan;
+
+		rx_chn_num = common->num_active_rx_channels++;
+		snprintf(rx_chn_name, sizeof(rx_chn_name), "rx%d", rx_chn_num);
+
+		rx_cfg.flow_id_base = virt_port->rx_flow_idx_base + virt_port->rx_flow_idx_offset;
+
+		/* init all flows */
+		rx_chn->dev = dev;
+		rx_chn->num_descs = max_desc_num;
+		rx_chn->desc_pool = k3_cppi_desc_pool_create_name(dev,
+								  rx_chn->num_descs,
+								  hdesc_size,
+								  rx_chn_name);
+		if (IS_ERR(rx_chn->desc_pool)) {
+			ret = PTR_ERR(rx_chn->desc_pool);
+			dev_err(dev, "Failed to create rx pool %d\n", ret);
+			goto err;
+		}
+
+		rx_chn->rx_chan =
+			k3_udma_glue_request_remote_rx_chn_by_id(dev, common->dma_node, &rx_cfg,
+								 virt_port->rx_psil_src_id);
+		if (IS_ERR(rx_chn->rx_chan)) {
+			ret = PTR_ERR(rx_chn->rx_chan);
+			dev_err(dev, "Failed to request rx dma channel %d\n", ret);
+			goto err;
+		}
+
+		rx_flow_cfg.rx_cfg.size = max_desc_num;
+		rx_flow_cfg.rxfdq_cfg.size = max_desc_num;
+		ret = k3_udma_glue_rx_flow_init(rx_chn->rx_chan,
+						0, &rx_flow_cfg);
+		if (ret) {
+			dev_err(dev, "Failed to init rx flow %d\n", ret);
+			goto err;
+		}
+
+		rx_chn->irq = k3_udma_glue_rx_get_irq(rx_chn->rx_chan, 0);
+		if (rx_chn->irq <= 0) {
+			ret = -ENXIO;
+			dev_err(dev, "Failed to get rx dma irq %d\n", rx_chn->irq);
+		}
+	}
+
+err:
+	ret1 = devm_add_action(dev, cpsw_proxy_client_free_rx_chns, common);
+	if (ret1) {
+		dev_err(dev, "failed to add free_rx_chns action %d", ret1);
+		return ret1;
+	}
+
+	return ret;
+}
+
+static int cpsw_proxy_client_register_ipv4(struct cpsw_virt_port *virt_port)
+{
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct message response;
+	int ret;
+
+	ret = cpsw_proxy_client_send_request(common, virt_port, virt_port->virt_port_token,
+					     ETHREMOTECFG_IPv4_REGISTER, &response);
+	if (ret) {
+		dev_err(common->dev, "failed to register IPv4 Address err: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int cpsw_proxy_client_deregister_ipv4(struct cpsw_virt_port *virt_port)
+{
+	struct cpsw_proxy_common *common = virt_port->common;
+	struct message response;
+	int ret;
+
+	ret = cpsw_proxy_client_send_request(common, virt_port, virt_port->virt_port_token,
+					     ETHREMOTECFG_IPv4_DEREGISTER, &response);
+	if (ret) {
+		dev_err(common->dev, "failed to deregister IPv4 Address err: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static bool cpsw_proxy_client_check(const struct net_device *ndev)
+{
+	struct cpsw_virt_port *virt_port = cpsw_virt_port_ndev_to_virt_port(ndev);
+
+	return ndev->netdev_ops == &cpsw_virt_port_netdev_ops &&
+				   virt_port->virt_port_type == VIRT_SWITCH_PORT;
+}
+
+static int cpsw_proxy_client_inetaddr_event(struct notifier_block *unused,
+					    unsigned long event, void *ptr)
+{
+	struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
+	struct cpsw_virt_port *virt_port;
+	struct cpsw_proxy_common *common;
+	struct net_device *ndev;
+	int ret = 0;
+
+	ndev = ifa->ifa_dev ? ifa->ifa_dev->dev : NULL;
+	if (!ndev)
+		return NOTIFY_DONE;
+
+	if (!cpsw_proxy_client_check(ndev))
+		return NOTIFY_DONE;
+
+	virt_port = cpsw_virt_port_ndev_to_virt_port(ndev);
+	common = virt_port->common;
+	memcpy(virt_port->ipv4_addr, &ifa->ifa_address, ETHREMOTECFG_IPV4ADDRLEN);
+	switch (event) {
+	case NETDEV_UP:
+	case NETDEV_CHANGEADDR:
+		ret = cpsw_proxy_client_register_ipv4(virt_port);
+		if (ret)
+			dev_err(common->dev, "IPV4 register failed: %d\n", ret);
+		break;
+
+	case NETDEV_DOWN:
+	case NETDEV_PRE_CHANGEADDR:
+		ret = cpsw_proxy_client_deregister_ipv4(virt_port);
+		if (ret)
+			dev_err(common->dev, "IPV4 register failed: %d\n", ret);
+		break;
+	}
+
+	return notifier_from_errno(ret);
+}
+
+static void cpsw_proxy_client_unregister_notifier(struct cpsw_proxy_common *common)
+{
+	struct cpsw_virt_port *virt_port;
+	int i;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+
+		if (virt_port->virt_port_type == VIRT_SWITCH_PORT)
+			unregister_inetaddr_notifier(&virt_port->virt_port_inetaddr_nb);
+	}
+}
+
+static void cpsw_proxy_client_register_notifier(struct cpsw_proxy_common *common)
+{
+	struct cpsw_virt_port *virt_port;
+	int i;
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+
+		if (virt_port->virt_port_type == VIRT_SWITCH_PORT) {
+			virt_port->virt_port_inetaddr_nb.notifier_call =
+								&cpsw_proxy_client_inetaddr_event;
+			register_inetaddr_notifier(&virt_port->virt_port_inetaddr_nb);
+		}
+	}
+}
+
+static void cpsw_proxy_client_show_info(struct cpsw_proxy_common *common)
+{
+	struct device *dev = common->dev;
+	struct cpsw_virt_port *virt_port;
+	int i;
+
+	dev_info(dev, "%u Virtual Switch Port(s), %u Virtual MAC Only Port(s)\n",
+		 common->num_switch_ports, common->num_mac_only_ports);
+
+	for (i = 0; i < common->num_virt_ports; i++) {
+		virt_port = &common->virt_ports[i];
+
+		if (virt_port->virt_port_type == VIRT_SWITCH_PORT)
+			dev_info(dev, "Virt Port: %u, Type: Switch Port, Iface: %s, Token: %u\n",
+				 virt_port->virt_port_id, virt_port->ndev->name,
+				 virt_port->virt_port_token);
+		else
+			dev_info(dev, "Virt Port: %u, Type: MAC Port, Iface: %s, Token: %u\n",
+				 virt_port->virt_port_id, virt_port->ndev->name,
+				 virt_port->virt_port_token);
+	}
+}
+
+static int cpsw_proxy_client_probe(struct rpmsg_device *rpdev)
+{
+	struct device *dev = &rpdev->dev;
+	struct cpsw_proxy_common *common;
+	int ret = 0;
+
+	common = devm_kzalloc(dev, sizeof(struct cpsw_proxy_common), GFP_KERNEL);
+	if (!common)
+		return -ENOMEM;
+
+	common->rpdev = rpdev;
+	common->dev = dev;
+	mutex_init(&common->request_id_msg_mutex);
+	common->dma_compatible = (const char *)rpdev->id.driver_data;
+	common->dma_node = of_find_compatible_node(NULL, NULL, common->dma_compatible);
+	if (!common->dma_node) {
+		dev_err(dev, "failed to get DMA Node\n");
+		return -ENODEV;
+	}
+
+	dev_set_drvdata(dev, common);
+
+	init_completion(&common->wait_for_response);
+
+	/* Initialize Virtual Ports */
+	ret = cpsw_proxy_client_virt_port_init(common);
+	if (ret)
+		goto err;
+
+	/* Request DMA Channel Information for each Virtual Port */
+	ret = cpsw_proxy_client_attach_ext(common);
+	if (ret)
+		goto err;
+
+	/* Set DMA Mask */
+	ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(48));
+	if (ret) {
+		dev_err(dev, "error setting dma mask: %d\n", ret);
+		goto err;
+	}
+
+	/* Initialize TX DMA Channels for each Virtual Port */
+	ret = cpsw_proxy_client_init_tx_chans(common);
+	if (ret)
+		return ret;
+
+	/* Initialize RX DMA Flows for each Virtual Port */
+	ret = cpsw_proxy_client_init_rx_chans(common);
+	if (ret)
+		return ret;
+
+	/* Create and initialize Net Device for each Virtual Port */
+	ret = cpsw_proxy_client_init_ndevs(common);
+	if (ret)
+		return ret;
+
+	/* Request Interrupts for TX and RX DMA Channels */
+	ret = cpsw_proxy_client_setup_irq(common);
+	if (ret)
+		goto err;
+
+	/* Register INETADDR events notifier for Virtual Switch Ports */
+	cpsw_proxy_client_register_notifier(common);
+
+	cpsw_proxy_client_show_info(common);
+
+	return 0;
+
+err:
+	cpsw_proxy_client_unreg_ndevs(common);
+	return ret;
+}
+
+static void cpsw_proxy_client_remove(struct rpmsg_device *rpdev)
+{
+	struct cpsw_proxy_common *common = dev_get_drvdata(&rpdev->dev);
+
+	cpsw_proxy_client_unregister_notifier(common);
+	cpsw_proxy_client_unreg_ndevs(common);
+	cpsw_proxy_client_destroy_wq(common);
+	cpsw_proxy_client_detach(common);
+}
+
+static struct rpmsg_device_id cpsw_proxy_client_id_table[] = {
+	{
+		.name = "ti.ethfw.ethdevice",
+		.driver_data = (kernel_ulong_t)"ti,j721e-navss-main-udmap"
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(rpmsg, cpsw_proxy_client_id_table);
+
+static struct rpmsg_driver cpsw_proxy_client_driver = {
+	.drv.name	= KBUILD_MODNAME,
+	.id_table	= cpsw_proxy_client_id_table,
+	.probe		= cpsw_proxy_client_probe,
+	.callback	= cpsw_proxy_client_cb,
+	.remove		= cpsw_proxy_client_remove,
+};
+module_rpmsg_driver(cpsw_proxy_client_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CPSW Virtual Client Driver");
+MODULE_AUTHOR("Siddharth Vadapalli <s-vadapalli@ti.com>");
diff -Naur --no-dereference a/drivers/net/ethernet/ti/eth_remote_msg.h b/drivers/net/ethernet/ti/eth_remote_msg.h
--- a/drivers/net/ethernet/ti/eth_remote_msg.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/eth_remote_msg.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,448 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Texas Instruments Ethernet Switch Firmware ABIs
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#ifndef __ETH_REMOTE_MSG_H__
+#define __ETH_REMOTE_MSG_H__
+
+/* Ethernet Switch Firmware Service Endpoint name */
+#define ETHREMOTECFG_FRAMEWORK_SERVICE_NAME   "ti.ethfw.ethdevice"
+
+/* Ethernet Switch Firmware response code : Success */
+#define ETHREMOTECFG_CMDSTATUS_OK		0
+
+/* Ethernet Switch Firmware response code : Try again */
+#define ETHREMOTECFG_CMDSTATUS_EAGAIN		-1
+
+/* Maximum length of message data */
+#define ETHREMOTECFG_MESSAGE_DATA_LEN		486
+
+/* Number of priorities supported by CPSW */
+#define ETHREMOTECFG_PRIORITY_NUM		8
+
+/* MAC Address length in octets */
+#define ETHREMOTECFG_MACADDRLEN		6
+
+/* IPV4 Address length in octets */
+#define ETHREMOTECFG_IPV4ADDRLEN		4
+
+/* Request Ethernet Switch Firmware to use the default VLAN id for the virtual
+ * port; i.e. Virtual MAC Port or Virtual Switch Port.
+ */
+#define ETHREMOTECFG_ETHSWITCH_VLAN_USE_DFLT	0xFFFF
+
+#define ETHREMOTECFG_FWDATE_YEARLEN		4
+#define ETHREMOTECFG_FWDATE_MONTHLEN		3
+#define ETHREMOTECFG_FWDATE_DATELEN		2
+#define ETHREMOTECFG_FW_COMMITSHALEN		8
+
+/*  Ethernet Switch Firmware Version Information
+ *
+ *  API version info for the Ethernet device RPC
+ *  Any remote core client should check API version is compatible with this
+ *  API version
+ */
+/* Ethernet Switch Firmware API version major version */
+#define ETHREMOTECFG_FW_ETHSWITCH_VERSION_MAJOR		0
+/* Ethernet Switch Firmware API version minor version */
+#define ETHREMOTECFG_FW_ETHSWITCH_VERSION_MINOR		4
+/* Ethernet Switch Firmware API version minor revision */
+#define ETHREMOTECFG_FW_ETHSWITCH_VERSION_REVISION		0
+
+/* TX checksum offload feature support */
+#define ETHREMOTECFG_FEATURE_TXCSUM			BIT(0)
+
+/* Note: Feature bit 1 and 2 are intentionally not used */
+
+/* Multicast filter feature support */
+#define ETHREMOTECFG_FEATURE_MC_FILTER			BIT(3)
+
+#define ETHREMOTECFG_TOKEN_NONE                0xFFFF
+
+#define ETHREMOTECFG_IOCTL_INARGS_LEN		480
+#define ETHREMOTECFG_IOCTL_OUTARGS_LEN		480
+
+/*!
+ * \brief Ethernet RPC messages (C2S)
+ */
+enum request_msg_type {
+	ETHREMOTECFG_VIRT_PORT_ALLOC,
+	ETHREMOTECFG_ATTACH,
+	ETHREMOTECFG_ATTACH_EXT,
+	ETHREMOTECFG_DETACH,
+	ETHREMOTECFG_PORT_LINK_STATUS,
+	ETHREMOTECFG_ALLOC_TX,
+	ETHREMOTECFG_ALLOC_RX,
+	ETHREMOTECFG_ALLOC_MAC,
+	ETHREMOTECFG_FREE_TX,
+	ETHREMOTECFG_FREE_RX,
+	ETHREMOTECFG_FREE_MAC,
+	ETHREMOTECFG_MAC_REGISTER,
+	ETHREMOTECFG_MAC_DEREGISTER,
+	ETHREMOTECFG_SET_RX_DEFAULTFLOW,
+	ETHREMOTECFG_DEL_RX_DEFAULTFLOW,
+	ETHREMOTECFG_IPv4_REGISTER,
+	ETHREMOTECFG_IPv4_DEREGISTER,
+	ETHREMOTECFG_CMD_JOIN_VLAN,
+	ETHREMOTECFG_CMD_LEAVE_VLAN,
+	ETHREMOTECFG_FILTER_MAC_ADD,
+	ETHREMOTECFG_FILTER_MAC_DEL,
+	ETHREMOTECFG_PROMISC_ENABLE,
+	ETHREMOTECFG_PROMISC_DISABLE,
+	ETHREMOTECFG_REGISTER_READ,
+	ETHREMOTECFG_REGISTER_WRITE,
+	ETHREMOTECFG_MATCH_ETHTYPE_REGISTER,
+	ETHREMOTECFG_MATCH_ETHTYPE_DEREGISTER,
+	ETHREMOTECFG_REMOTE_TIMER_REGISTER,
+	ETHREMOTECFG_REMOTE_TIMER_DEREGISTER,
+	ETHREMOTECFG_MESSAGE_PING,
+	ETHREMOTECFG_ETHFW_STATUS,
+	ETHREMOTECFG_TEARDOWN_COMPLETE,
+	ETHREMOTECFG_IOCTL,
+	ETHREMOTECFG_CLIENT_DUMPSTATS,
+};
+
+enum client_token {
+	ETHREMOTECFG_NA_CLIENT,
+	ETHREMOTECFG_AUTOSAR_CLIENT,
+	ETHREMOTECFG_RTOS_CLIENT,
+	ETHREMOTECFG_LINUX_CLIENT,
+	ETHREMOTECFG_QNX_CLIENT,
+};
+
+enum notify_msg_type {
+	ETHREMOTECFG_NOTIFYCLIENT_FWINFO,
+	ETHREMOTECFG_NOTIFYCLIENT_HWPUSH,
+	ETHREMOTECFG_NOTIFYTYPE_HWERROR,
+	ETHREMOTECFG_NOTIFYTYPE_HWRECOVERY_COMPLETE,
+	ETHREMOTECFG_NOTIFYCLIENT_CUSTOM,
+	ETHREMOTECFG_NOTIFYCLIENT_LAST,
+};
+
+enum ethfw_status {
+	ETHREMOTECFG_ETHFW_INIT,
+	ETHREMOTECFG_ETHFW_RECOVERY,
+	ETHRC_ETHFW_DEINIT,
+};
+
+enum message_type {
+	ETHREMOTECFG_MSG_REQUEST,
+	ETHREMOTECFG_MSG_NOTIFY,
+	ETHREMOTECFG_MSG_RESPONSE,
+};
+
+struct message_header {
+	u32 token;
+	u32 client_id;
+	u32 msg_type;
+} __packed;
+
+struct message {
+	struct message_header msg_hdr;
+	u32 message_data[120];
+} __packed;
+
+struct request_message_header {
+	struct message_header msg_hdr;
+	u32 request_type;
+	u32 request_id;
+} __packed;
+
+struct response_message_header {
+	struct message_header msg_hdr;
+	u32 response_type; /* Same as request_type */
+	u32 response_id;
+	int response_status;
+} __packed;
+
+struct notify_message_header {
+	struct message_header msg_hdr;
+	u32 notify_type;
+} __packed;
+
+struct ethfw_rpc_version_info {
+	u32 major;
+	u32 minor;
+	u32 rev;
+	char year[ETHREMOTECFG_FWDATE_YEARLEN];
+	char month[ETHREMOTECFG_FWDATE_MONTHLEN];
+	char date[ETHREMOTECFG_FWDATE_DATELEN];
+	char commit_hash[ETHREMOTECFG_FW_COMMITSHALEN];
+} __packed;
+
+struct ethfw_firmware_version_notify {
+	struct notify_message_header notify_msg_hdr;
+	struct ethfw_rpc_version_info ethfw_info;
+	u64 permission_flags;
+	u32 uart_connected;
+	u32 uart_id;
+} __packed;
+
+struct common_response_message {
+	struct response_message_header response_msg_hdr;
+} __packed;
+
+struct common_request_message {
+	struct request_message_header request_msg_hdr;
+} __packed;
+
+struct common_notify_message {
+	struct notify_message_header notify_msg_hdr;
+} __packed;
+
+struct virt_port_alloc_response {
+	struct response_message_header response_msg_hdr;
+	/* Port mask denoting absolute virtual switch ports allocated */
+	u32 switch_port_mask;
+	/* Port mask denoting absolute virtual MAC ports allocated */
+	u32 mac_port_mask;
+} __packed;
+
+struct attach_request {
+	struct request_message_header request_msg_hdr;
+	/* Virtual port which needs core attach */
+	u32 virt_port;
+} __packed;
+
+struct attach_response {
+	struct response_message_header response_msg_hdr;
+	/* MTU of RX packet */
+	u32 rx_mtu;
+	/* MTU of TX packet per priority */
+	u32 tx_mtu[ETHREMOTECFG_PRIORITY_NUM];
+	/* Feature bitmask based on defines ETHREMOTECFG_FEATURE_xxx */
+	u32 features;
+} __packed;
+
+struct attach_ext_response {
+	struct response_message_header response_msg_hdr;
+	/* MTU of RX packet */
+	u32 rx_mtu;
+	/* MTU of TX packet per priority */
+	u32 tx_mtu[ETHREMOTECFG_PRIORITY_NUM];
+	/* Allocated RX flow index base */
+	u32 rx_flow_idx_base;
+	/* Allocated flow index offset */
+	u32 rx_flow_idx_offset;
+	/* TX PSIL Peer destination thread id which should be paired with the TX UDMA channel */
+	u32 tx_psil_dest_id;
+	/* MAC address allocated */
+	u8 mac_addr[ETHREMOTECFG_MACADDRLEN];
+	/* Feature bitmask based on defines ETHREMOTECFG_FEATURE_xxx */
+	u32 features;
+	/* RX PSIL Peer source thread id */
+	u32 rx_psil_src_id;
+} __packed;
+
+struct rx_flow_alloc_response {
+	struct response_message_header response_msg_hdr;
+	/* Allocated RX flow index base */
+	u32 rx_flow_idx_base;
+	/* Allocated flow index offset */
+	u32 rx_flow_idx_offset;
+	/* RX PSIL Peer source thread id */
+	u32 rx_psil_src_id;
+} __packed;
+
+struct tx_psil_alloc_response {
+	struct response_message_header response_msg_hdr;
+	/* TX PSIL peer destination thread id which should be paired with the TX UDMA channel */
+	u32 tx_psil_dest_id;
+} __packed;
+
+struct mac_alloc_request {
+	struct request_message_header request_msg_hdr;
+	/* Allocated MAC address */
+	u8 mac_addr[ETHREMOTECFG_MACADDRLEN];
+} __packed;
+
+struct rx_flow_release_request {
+	struct request_message_header request_msg_hdr;
+	/* RX flow index base */
+	u32 rx_flow_idx_base;
+	/* RX flow index offset */
+	u32 rx_flow_idx_offset;
+} __packed;
+
+struct tx_psil_release_request {
+	struct request_message_header request_msg_hdr;
+	/* TX PSIL Peer destination thread id to be freed */
+	u32 tx_psil_dest_id;
+} __packed;
+
+struct mac_release_request {
+	struct request_message_header request_msg_hdr;
+	/* MAC address to be freed */
+	u8 mac_addr[ETHREMOTECFG_MACADDRLEN];
+} __packed;
+
+struct mac_rx_flow_register_request {
+	struct request_message_header request_msg_hdr;
+	/* MAC address which needs to be registered */
+	u8 mac_addr[ETHREMOTECFG_MACADDRLEN];
+	/* RX flow index Base */
+	u32 rx_flow_idx_base;
+	/* RX flow index offset to which the MAC address needs to be registered */
+	u32 rx_flow_idx_offset;
+} __packed;
+
+struct ipv4_register_request {
+	struct request_message_header request_msg_hdr;
+	/* IPv4 Address */
+	u8 ipv4_addr[ETHREMOTECFG_IPV4ADDRLEN];
+	/* MAC address associated with the IP address which should be added to
+	 * the ARP table
+	 */
+	u8 mac_addr[ETHREMOTECFG_MACADDRLEN];
+} __packed;
+
+struct ipv4_deregister_request {
+	struct request_message_header request_msg_hdr;
+	/* IPv4 Address */
+	u8 ipv4_addr[ETHREMOTECFG_IPV4ADDRLEN];
+} __packed;
+
+struct default_rx_flow_register_request {
+	struct request_message_header request_msg_hdr;
+	/* RX flow index Base */
+	u32 rx_flow_idx_base;
+	/* RX flow index offset */
+	u32 rx_flow_idx_offset;
+} __packed;
+
+struct port_link_status_response {
+	struct response_message_header response_msg_hdr;
+	/* Link status of the port */
+	bool link_up;
+	/* Link speed */
+	u32 speed;
+	/* Duplex mode */
+	u32 duplex;
+} __packed;
+
+struct add_ether_type_rx_flow_request {
+	struct request_message_header request_msg_hdr;
+	/* EtherType to be associated with the flow */
+	u16 ether_type;
+	/* Allocated flow's base */
+	u32 rx_flow_idx_base;
+	/* Allocated flow's offset */
+	u32 rx_flow_idx_offset;
+} __packed;
+
+struct del_ether_type_rx_flow_request {
+	struct request_message_header request_msg_hdr;
+	/* EtherType associated with the flow */
+	u16 ether_type;
+} __packed;
+
+struct add_mcast_vlan_rx_flow_request {
+	struct request_message_header request_msg_hdr;
+	/* Multicast MAC address to be added */
+	u8 mac_addr[ETHREMOTECFG_MACADDRLEN];
+	/* VLAN id */
+	u16 vlan_id;
+	/* RX flow index from which the MAC_address association will be added.
+	 * It's applicable only for _exclusive multicast traffic_
+	 */
+	u32 rx_flow_idx_base;
+	/* RX flow index offset */
+	u32 rx_flow_idx_offset;
+} __packed;
+
+struct del_mcast_vlan_rx_flow_request {
+	struct request_message_header request_msg_hdr;
+	/* Multicast MAC address to be added */
+	u8 mac_addr[ETHREMOTECFG_MACADDRLEN];
+	/* VLAN id */
+	u16 vlan_id;
+} __packed;
+
+struct ping_request {
+	struct request_message_header request_msg_hdr;
+	/* Data which will be responded back by the server */
+	u32 ping_request_data[ETHREMOTECFG_MESSAGE_DATA_LEN];
+} __packed;
+
+struct ping_response {
+	struct response_message_header response_msg_hdr;
+	/* Data which will be responded back by the server */
+	u32 ping_response_data[ETHREMOTECFG_MESSAGE_DATA_LEN];
+} __packed;
+
+struct remote_timer_register_request {
+	struct request_message_header request_msg_hdr;
+	/* Hardware Push Number to be used for timesync router configuration */
+	u8 hw_push_number;
+	/* Timer Id to be used for timesync router configuration */
+	u8 timer_id;
+} __packed;
+
+struct remote_timer_deregister_request {
+	struct request_message_header request_msg_hdr;
+	/* Hardware Push Number to be used for timesync router configuration */
+	u8 hw_push_number;
+} __packed;
+
+struct ioctl_request {
+	struct request_message_header request_msg_hdr;
+	/* IOCTL Command ID */
+	u32 cmd;
+	/* IOCTL input arguments length */
+	u32 in_args_len;
+	/* IOCTL input arguments */
+	u64 in_args[(ETHREMOTECFG_IOCTL_INARGS_LEN / sizeof(u64))];
+	/* IOTCL output arguments length */
+	u32 out_args_len;
+};
+
+struct ioctl_response {
+	struct request_message_header request_msg_hdr;
+	/* IOCTL Command ID */
+	u32 cmd;
+	/* IOCTL output arguments length */
+	u32 out_args_len;
+	/* IOCTL output arguments */
+	u64 out_args[(ETHREMOTECFG_IOCTL_OUTARGS_LEN / sizeof(u64))];
+};
+
+struct register_write_request {
+	struct request_message_header request_msg_hdr;
+	/* Register address */
+	u32 register_address;
+	/* Value which needs to be written */
+	u32 value;
+} __packed;
+
+struct register_read_request {
+	/* Request message common header */
+	struct request_message_header request_msg_hdr;
+	/* Register address */
+	u32 register_address;
+} __packed;
+
+struct register_read_response {
+	struct response_message_header response_msg_hdr;
+	/* Value which has been read */
+	u32 value;
+} __packed;
+
+struct server_status_response {
+	struct response_message_header response_msg_hdr;
+	/* Server status */
+	u32 status;
+};
+
+struct hw_msg_push_notify_message {
+	struct notify_message_header notify_msg_hdr;
+	/* CPTS hardware push number */
+	u32 cpts_hw_push_number;
+	/* CPTS hardware push event timestamp  */
+	u64 timestamp;
+} __packed;
+
+#endif /* __ETH_REMOTE_MSG_H__ */
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_classifier.c b/drivers/net/ethernet/ti/icssg_classifier.c
--- a/drivers/net/ethernet/ti/icssg_classifier.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_classifier.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,362 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Texas Instruments ICSSG Ethernet Driver
+ *
+ * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/types.h>
+#include <linux/regmap.h>
+
+#include "icssg_prueth.h"
+
+#define ICSSG_NUM_CLASSIFIERS	16
+#define ICSSG_NUM_FT1_SLOTS	8
+#define ICSSG_NUM_FT3_SLOTS	16
+
+#define ICSSG_NUM_CLASSIFIERS_IN_USE	5
+
+/* Filter 1 - FT1 */
+#define FT1_NUM_SLOTS	8
+#define FT1_SLOT_SIZE	0x10	/* bytes */
+
+/* offsets from FT1 slot base i.e. slot 1 start */
+#define FT1_DA0		0x0
+#define FT1_DA1		0x4
+#define FT1_DA0_MASK	0x8
+#define FT1_DA1_MASK	0xc
+
+#define FT1_N_REG(slize, n, reg)	(offs[slice].ft1_slot_base + FT1_SLOT_SIZE * (n) + (reg))
+
+#define FT1_LEN_MASK		GENMASK(19, 16)
+#define FT1_LEN_SHIFT		16
+#define FT1_LEN(len)		(((len) << FT1_LEN_SHIFT) & FT1_LEN_MASK)
+#define FT1_START_MASK		GENMASK(14, 0)
+#define FT1_START(start)	((start) & FT1_START_MASK)
+#define FT1_MATCH_SLOT(n)	(GENMASK(23, 16) & (BIT(n) << 16))
+
+enum ft1_cfg_type {
+	FT1_CFG_TYPE_DISABLED = 0,
+	FT1_CFG_TYPE_EQ,
+	FT1_CFG_TYPE_GT,
+	FT1_CFG_TYPE_LT,
+};
+
+#define FT1_CFG_SHIFT(n)	(2 * (n))
+#define FT1_CFG_MASK(n)		(0x3 << FT1_CFG_SHIFT((n)))
+
+/* Filter 3 -  FT3 */
+#define FT3_NUM_SLOTS	16
+#define FT3_SLOT_SIZE	0x20	/* bytes */
+
+/* offsets from FT3 slot n's base */
+#define FT3_START		0
+#define FT3_START_AUTO		0x4
+#define FT3_START_OFFSET	0x8
+#define FT3_JUMP_OFFSET		0xc
+#define FT3_LEN			0x10
+#define FT3_CFG			0x14
+#define FT3_T			0x18
+#define FT3_T_MASK		0x1c
+
+#define FT3_N_REG(slize, n, reg)	(offs[slice].ft3_slot_base + FT3_SLOT_SIZE * (n) + (reg))
+
+/* offsets from rx_class n's base */
+#define RX_CLASS_AND_EN		0
+#define RX_CLASS_OR_EN		0x4
+#define RX_CLASS_NUM_SLOTS	16
+#define RX_CLASS_EN_SIZE	0x8	/* bytes */
+
+#define RX_CLASS_N_REG(slice, n, reg)	(offs[slice].rx_class_base + RX_CLASS_EN_SIZE * (n) + (reg))
+
+/* RX Class Gates */
+#define RX_CLASS_GATES_SIZE	0x4	/* bytes */
+
+#define RX_CLASS_GATES_N_REG(slice, n)	\
+	(offs[slice].rx_class_gates_base + RX_CLASS_GATES_SIZE * (n))
+
+#define RX_CLASS_GATES_ALLOW_MASK	BIT(6)
+#define RX_CLASS_GATES_RAW_MASK		BIT(5)
+#define RX_CLASS_GATES_PHASE_MASK	BIT(4)
+
+/* RX Class traffic data matching bits */
+#define RX_CLASS_FT_UC			BIT(31)
+#define RX_CLASS_FT_MC			BIT(30)
+#define RX_CLASS_FT_BC			BIT(29)
+#define RX_CLASS_FT_FW			BIT(28)
+#define RX_CLASS_FT_RCV			BIT(27)
+#define RX_CLASS_FT_VLAN		BIT(26)
+#define RX_CLASS_FT_DA_P		BIT(25)
+#define RX_CLASS_FT_DA_I		BIT(24)
+#define RX_CLASS_FT_FT1_MATCH_MASK	GENMASK(23, 16)
+#define RX_CLASS_FT_FT1_MATCH_SHIFT	16
+#define RX_CLASS_FT_FT3_MATCH_MASK	GENMASK(15, 0)
+#define RX_CLASS_FT_FT3_MATCH_SHIFT	0
+
+#define RX_CLASS_FT_FT1_MATCH(slot)	\
+	((BIT(slot) << RX_CLASS_FT_FT1_MATCH_SHIFT) & RX_CLASS_FT_FT1_MATCH_MASK)
+
+enum rx_class_sel_type {
+	RX_CLASS_SEL_TYPE_OR = 0,
+	RX_CLASS_SEL_TYPE_AND = 1,
+	RX_CLASS_SEL_TYPE_OR_AND_AND = 2,
+	RX_CLASS_SEL_TYPE_OR_OR_AND = 3,
+};
+
+#define FT1_CFG_SHIFT(n)	(2 * (n))
+#define FT1_CFG_MASK(n)		(0x3 << FT1_CFG_SHIFT((n)))
+
+#define RX_CLASS_SEL_SHIFT(n)	(2 * (n))
+#define RX_CLASS_SEL_MASK(n)	(0x3 << RX_CLASS_SEL_SHIFT((n)))
+
+#define ICSSG_CFG_OFFSET	0
+#define MAC_INTERFACE_0		0x18
+#define MAC_INTERFACE_1		0x1c
+
+#define ICSSG_CFG_RX_L2_G_EN	BIT(2)
+
+/* These are register offsets per PRU */
+struct miig_rt_offsets {
+	u32 mac0;
+	u32 mac1;
+	u32 ft1_start_len;
+	u32 ft1_cfg;
+	u32 ft1_slot_base;
+	u32 ft3_slot_base;
+	u32 ft3_p_base;
+	u32 ft_rx_ptr;
+	u32 rx_class_base;
+	u32 rx_class_cfg1;
+	u32 rx_class_cfg2;
+	u32 rx_class_gates_base;
+	u32 rx_green;
+	u32 rx_rate_cfg_base;
+	u32 rx_rate_src_sel0;
+	u32 rx_rate_src_sel1;
+	u32 tx_rate_cfg_base;
+	u32 stat_base;
+	u32 tx_hsr_tag;
+	u32 tx_hsr_seq;
+	u32 tx_vlan_type;
+	u32 tx_vlan_ins;
+};
+
+/* These are the offset values for miig_rt_offsets registers */
+static const struct miig_rt_offsets offs[] = {
+	/* PRU0 */
+	{
+		0x8,
+		0xc,
+		0x80,
+		0x84,
+		0x88,
+		0x108,
+		0x308,
+		0x408,
+		0x40c,
+		0x48c,
+		0x490,
+		0x494,
+		0x4d4,
+		0x4e4,
+		0x504,
+		0x508,
+		0x50c,
+		0x54c,
+		0x63c,
+		0x640,
+		0x644,
+		0x648,
+	},
+	/* PRU1 */
+	{
+		0x10,
+		0x14,
+		0x64c,
+		0x650,
+		0x654,
+		0x6d4,
+		0x8d4,
+		0x9d4,
+		0x9d8,
+		0xa58,
+		0xa5c,
+		0xa60,
+		0xaa0,
+		0xab0,
+		0xad0,
+		0xad4,
+		0xad8,
+		0xb18,
+		0xc08,
+		0xc0c,
+		0xc10,
+		0xc14,
+	},
+};
+
+static void rx_class_ft1_set_start_len(struct regmap *miig_rt, int slice,
+				       u16 start, u8 len)
+{
+	u32 offset, val;
+
+	offset = offs[slice].ft1_start_len;
+	val = FT1_LEN(len) | FT1_START(start);
+	regmap_write(miig_rt, offset, val);
+}
+
+static void rx_class_ft1_set_da(struct regmap *miig_rt, int slice,
+				int n, const u8 *addr)
+{
+	u32 offset;
+
+	offset = FT1_N_REG(slice, n, FT1_DA0);
+	regmap_write(miig_rt, offset, (u32)(addr[0] | addr[1] << 8 |
+		     addr[2] << 16 | addr[3] << 24));
+	offset = FT1_N_REG(slice, n, FT1_DA1);
+	regmap_write(miig_rt, offset, (u32)(addr[4] | addr[5] << 8));
+}
+
+static void rx_class_ft1_set_da_mask(struct regmap *miig_rt, int slice,
+				     int n, const u8 *addr)
+{
+	u32 offset;
+
+	offset = FT1_N_REG(slice, n, FT1_DA0_MASK);
+	regmap_write(miig_rt, offset, (u32)(addr[0] | addr[1] << 8 |
+		     addr[2] << 16 | addr[3] << 24));
+	offset = FT1_N_REG(slice, n, FT1_DA1_MASK);
+	regmap_write(miig_rt, offset, (u32)(addr[4] | addr[5] << 8));
+}
+
+static void rx_class_ft1_cfg_set_type(struct regmap *miig_rt, int slice, int n,
+				      enum ft1_cfg_type type)
+{
+	u32 offset;
+
+	offset = offs[slice].ft1_cfg;
+	regmap_update_bits(miig_rt, offset, FT1_CFG_MASK(n),
+			   type << FT1_CFG_SHIFT(n));
+}
+
+static void rx_class_sel_set_type(struct regmap *miig_rt, int slice, int n,
+				  enum rx_class_sel_type type)
+{
+	u32 offset;
+
+	offset = offs[slice].rx_class_cfg1;
+	regmap_update_bits(miig_rt, offset, RX_CLASS_SEL_MASK(n),
+			   type << RX_CLASS_SEL_SHIFT(n));
+}
+
+static void rx_class_set_and(struct regmap *miig_rt, int slice, int n,
+			     u32 data)
+{
+	u32 offset;
+
+	offset = RX_CLASS_N_REG(slice, n, RX_CLASS_AND_EN);
+	regmap_write(miig_rt, offset, data);
+}
+
+static void rx_class_set_or(struct regmap *miig_rt, int slice, int n,
+			    u32 data)
+{
+	u32 offset;
+
+	offset = RX_CLASS_N_REG(slice, n, RX_CLASS_OR_EN);
+	regmap_write(miig_rt, offset, data);
+}
+
+void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac)
+{
+	regmap_write(miig_rt, MAC_INTERFACE_0, (u32)(mac[0] | mac[1] << 8 |
+		     mac[2] << 16 | mac[3] << 24));
+	regmap_write(miig_rt, MAC_INTERFACE_1, (u32)(mac[4] | mac[5] << 8));
+}
+
+void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac)
+{
+	regmap_write(miig_rt, offs[slice].mac0, (u32)(mac[0] | mac[1] << 8 |
+		     mac[2] << 16 | mac[3] << 24));
+	regmap_write(miig_rt, offs[slice].mac1, (u32)(mac[4] | mac[5] << 8));
+}
+
+/* disable all RX traffic */
+void icssg_class_disable(struct regmap *miig_rt, int slice)
+{
+	u32 data, offset;
+	int n;
+
+	/* Enable RX_L2_G */
+	regmap_update_bits(miig_rt, ICSSG_CFG_OFFSET, ICSSG_CFG_RX_L2_G_EN,
+			   ICSSG_CFG_RX_L2_G_EN);
+
+	for (n = 0; n < ICSSG_NUM_CLASSIFIERS; n++) {
+		/* AND_EN = 0 */
+		rx_class_set_and(miig_rt, slice, n, 0);
+		/* OR_EN = 0 */
+		rx_class_set_or(miig_rt, slice, n, 0);
+
+		/* set CFG1 to OR */
+		rx_class_sel_set_type(miig_rt, slice, n, RX_CLASS_SEL_TYPE_OR);
+
+		/* configure gate */
+		offset = RX_CLASS_GATES_N_REG(slice, n);
+		regmap_read(miig_rt, offset, &data);
+		/* clear class_raw so we go through filters */
+		data &= ~RX_CLASS_GATES_RAW_MASK;
+		/* set allow and phase mask */
+		data |= RX_CLASS_GATES_ALLOW_MASK | RX_CLASS_GATES_PHASE_MASK;
+		regmap_write(miig_rt, offset, data);
+	}
+
+	/* FT1 Disabled */
+	for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++) {
+		const u8 addr[] = { 0, 0, 0, 0, 0, 0, };
+
+		rx_class_ft1_cfg_set_type(miig_rt, slice, n,
+					  FT1_CFG_TYPE_DISABLED);
+		rx_class_ft1_set_da(miig_rt, slice, n, addr);
+		rx_class_ft1_set_da_mask(miig_rt, slice, n, addr);
+	}
+
+	/* clear CFG2 */
+	regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
+}
+
+void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti)
+{
+	u32 data;
+
+	/* defaults */
+	icssg_class_disable(miig_rt, slice);
+
+	/* Setup Classifier */
+	/* match on Broadcast or MAC_PRU address */
+	data = RX_CLASS_FT_BC | RX_CLASS_FT_DA_P;
+
+	/* multicast */
+	if (allmulti)
+		data |= RX_CLASS_FT_MC;
+
+	rx_class_set_or(miig_rt, slice, 0, data);
+
+	/* set CFG1 for OR_OR_AND for classifier */
+	rx_class_sel_set_type(miig_rt, slice, 0,
+			      RX_CLASS_SEL_TYPE_OR_OR_AND);
+
+	/* clear CFG2 */
+	regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
+}
+
+/* required for SAV check */
+void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr)
+{
+	const u8 mask_addr[] = { 0, 0, 0, 0, 0, 0, };
+
+	rx_class_ft1_set_start_len(miig_rt, slice, 6, 6);
+	rx_class_ft1_set_da(miig_rt, slice, 0, mac_addr);
+	rx_class_ft1_set_da_mask(miig_rt, slice, 0, mask_addr);
+	rx_class_ft1_cfg_set_type(miig_rt, slice, 0, FT1_CFG_TYPE_EQ);
+}
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_config.c b/drivers/net/ethernet/ti/icssg_config.c
--- a/drivers/net/ethernet/ti/icssg_config.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_config.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,887 @@
+// SPDX-License-Identifier: GPL-2.0
+/* ICSSG Ethernet driver
+ *
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com
+ */
+
+#include <linux/iopoll.h>
+#include <linux/regmap.h>
+#include <uapi/linux/if_ether.h>
+#include "icssg_config.h"
+#include "icssg_prueth.h"
+#include "icssg_switch_map.h"
+#include "icssg_mii_rt.h"
+
+/* TX IPG Values to be set for 100M link speed. These values are
+ * in ocp_clk cycles. So need change if ocp_clk is changed for a specific
+ * h/w design.
+ */
+
+/* IPG is in core_clk cycles */
+#define MII_RT_TX_IPG_100M	0x17
+#define MII_RT_TX_IPG_1G	0xb
+
+#define	ICSSG_QUEUES_MAX		64
+#define	ICSSG_QUEUE_OFFSET		0xd00
+#define	ICSSG_QUEUE_PEEK_OFFSET		0xe00
+#define	ICSSG_QUEUE_CNT_OFFSET		0xe40
+#define	ICSSG_QUEUE_RESET_OFFSET	0xf40
+
+#define	ICSSG_NUM_TX_QUEUES	8
+
+#define	RECYCLE_Q_SLICE0	16
+#define	RECYCLE_Q_SLICE1	17
+
+#define	ICSSG_NUM_OTHER_QUEUES	5	/* port, host and special queues */
+
+#define	PORT_HI_Q_SLICE0	32
+#define	PORT_LO_Q_SLICE0	33
+#define	HOST_HI_Q_SLICE0	34
+#define	HOST_LO_Q_SLICE0	35
+#define	HOST_SPL_Q_SLICE0	40	/* Special Queue */
+
+#define	PORT_HI_Q_SLICE1	36
+#define	PORT_LO_Q_SLICE1	37
+#define	HOST_HI_Q_SLICE1	38
+#define	HOST_LO_Q_SLICE1	39
+#define	HOST_SPL_Q_SLICE1	41	/* Special Queue */
+
+#define MII_RXCFG_DEFAULT	(PRUSS_MII_RT_RXCFG_RX_ENABLE | \
+				 PRUSS_MII_RT_RXCFG_RX_DATA_RDY_MODE_DIS | \
+				 PRUSS_MII_RT_RXCFG_RX_L2_EN | \
+				 PRUSS_MII_RT_RXCFG_RX_L2_EOF_SCLR_DIS)
+
+#define MII_TXCFG_DEFAULT	(PRUSS_MII_RT_TXCFG_TX_ENABLE | \
+				 PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE | \
+				 PRUSS_MII_RT_TXCFG_TX_32_MODE_EN | \
+				 PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN)
+
+#define ICSSG_CFG_DEFAULT	(ICSSG_CFG_TX_L1_EN | \
+				 ICSSG_CFG_TX_L2_EN | ICSSG_CFG_RX_L2_G_EN | \
+				 ICSSG_CFG_TX_PRU_EN | \
+				 ICSSG_CFG_SGMII_MODE)
+
+#define FDB_GEN_CFG1		0x60
+#define SMEM_VLAN_OFFSET	8
+#define SMEM_VLAN_OFFSET_MASK	GENMASK(25, 8)
+
+#define FDB_GEN_CFG2		0x64
+#define FDB_VLAN_EN		BIT(6)
+#define FDB_HOST_EN		BIT(2)
+#define FDB_PRU1_EN		BIT(1)
+#define FDB_PRU0_EN		BIT(0)
+#define FDB_EN_ALL		(FDB_PRU0_EN | FDB_PRU1_EN | \
+				 FDB_HOST_EN | FDB_VLAN_EN)
+
+/**
+ * struct map - ICSSG Queue Map
+ * @queue: Queue number
+ * @pd_addr_start: Packet descriptor queue reserved memory
+ * @flags: Flags
+ * @special: Indicates whether this queue is a special queue or not
+ */
+struct map {
+	int queue;
+	u32 pd_addr_start;
+	u32 flags;
+	bool special;
+};
+
+/* Hardware queue map for ICSSG */
+const struct map hwq_map[2][ICSSG_NUM_OTHER_QUEUES] = {
+	{
+		{ PORT_HI_Q_SLICE0, PORT_DESC0_HI, 0x200000, 0 },
+		{ PORT_LO_Q_SLICE0, PORT_DESC0_LO, 0, 0 },
+		{ HOST_HI_Q_SLICE0, HOST_DESC0_HI, 0x200000, 0 },
+		{ HOST_LO_Q_SLICE0, HOST_DESC0_LO, 0, 0 },
+		{ HOST_SPL_Q_SLICE0, HOST_SPPD0, 0x400000, 1 },
+	},
+	{
+		{ PORT_HI_Q_SLICE1, PORT_DESC1_HI, 0xa00000, 0 },
+		{ PORT_LO_Q_SLICE1, PORT_DESC1_LO, 0x800000, 0 },
+		{ HOST_HI_Q_SLICE1, HOST_DESC1_HI, 0xa00000, 0 },
+		{ HOST_LO_Q_SLICE1, HOST_DESC1_LO, 0x800000, 0 },
+		{ HOST_SPL_Q_SLICE1, HOST_SPPD1, 0xc00000, 1 },
+	},
+};
+
+static void icssg_config_mii_init_switch(struct prueth_emac *emac)
+{
+	struct prueth *prueth = emac->prueth;
+	struct regmap *mii_rt = prueth->mii_rt;
+	int mii = prueth_emac_slice(emac);
+	u32 txcfg_reg, pcnt_reg;
+	u32 txcfg;
+
+	txcfg_reg = (mii == ICSS_MII0) ? PRUSS_MII_RT_TXCFG0 :
+				       PRUSS_MII_RT_TXCFG1;
+	pcnt_reg = (mii == ICSS_MII0) ? PRUSS_MII_RT_RX_PCNT0 :
+				       PRUSS_MII_RT_RX_PCNT1;
+
+	txcfg = PRUSS_MII_RT_TXCFG_TX_ENABLE |
+		PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE |
+		PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN;
+
+	if (emac->phy_if == PHY_INTERFACE_MODE_MII && mii == ICSS_MII1)
+		txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL;
+	else if (emac->phy_if != PHY_INTERFACE_MODE_MII && mii == ICSS_MII0)
+		txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL;
+
+	regmap_write(mii_rt, txcfg_reg, txcfg);
+	regmap_write(mii_rt, pcnt_reg, 0x1);
+}
+
+static void icssg_config_mii_init(struct prueth_emac *emac)
+{
+	struct prueth *prueth = emac->prueth;
+	int slice = prueth_emac_slice(emac);
+	u32 txcfg, txcfg_reg, pcnt_reg;
+	struct regmap *mii_rt;
+
+	mii_rt = prueth->mii_rt;
+
+	txcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_TXCFG0 :
+				       PRUSS_MII_RT_TXCFG1;
+	pcnt_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RX_PCNT0 :
+				       PRUSS_MII_RT_RX_PCNT1;
+
+	txcfg = MII_TXCFG_DEFAULT;
+
+	/* In MII mode TX lines swapped inside ICSSG, so TX_MUX_SEL cfg need
+	 * to be swapped also comparing to RGMII mode.
+	 */
+	if (emac->phy_if == PHY_INTERFACE_MODE_MII && slice == ICSS_MII0)
+		txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL;
+	else if (emac->phy_if != PHY_INTERFACE_MODE_MII && slice == ICSS_MII1)
+		txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL;
+
+	regmap_write(mii_rt, txcfg_reg, txcfg);
+	regmap_write(mii_rt, pcnt_reg, 0x1);
+}
+
+static void icssg_miig_queues_init(struct prueth *prueth, int slice)
+{
+	struct regmap *miig_rt = prueth->miig_rt;
+	void __iomem *smem = prueth->shram.va;
+	u8 pd[ICSSG_SPECIAL_PD_SIZE];
+	int queue = 0, i, j;
+	u32 *pdword;
+
+	/* reset hwqueues */
+	if (slice)
+		queue = ICSSG_NUM_TX_QUEUES;
+
+	for (i = 0; i < ICSSG_NUM_TX_QUEUES; i++) {
+		regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue);
+		queue++;
+	}
+
+	queue = slice ? RECYCLE_Q_SLICE1 : RECYCLE_Q_SLICE0;
+	regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue);
+
+	for (i = 0; i < ICSSG_NUM_OTHER_QUEUES; i++) {
+		regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET,
+			     hwq_map[slice][i].queue);
+	}
+
+	/* initialize packet descriptors in SMEM */
+	/* push pakcet descriptors to hwqueues */
+
+	pdword = (u32 *)pd;
+	for (j = 0; j < ICSSG_NUM_OTHER_QUEUES; j++) {
+		const struct map *mp;
+		int pd_size, num_pds;
+		u32 pdaddr;
+
+		mp = &hwq_map[slice][j];
+		if (mp->special) {
+			pd_size = ICSSG_SPECIAL_PD_SIZE;
+			num_pds = ICSSG_NUM_SPECIAL_PDS;
+		} else	{
+			pd_size = ICSSG_NORMAL_PD_SIZE;
+			num_pds = ICSSG_NUM_NORMAL_PDS;
+		}
+
+		for (i = 0; i < num_pds; i++) {
+			memset(pd, 0, pd_size);
+
+			pdword[0] &= cpu_to_le32(ICSSG_FLAG_MASK);
+			pdword[0] |= cpu_to_le32(mp->flags);
+			pdaddr = mp->pd_addr_start + i * pd_size;
+
+			memcpy_toio(smem + pdaddr, pd, pd_size);
+			queue = mp->queue;
+			regmap_write(miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue,
+				     pdaddr);
+		}
+	}
+}
+
+static void icssg_config_cut_thru(struct prueth_emac *emac)
+{
+	void *config = emac->dram.va + ICSSG_CONFIG_OFFSET;
+	u8 mask = BIT(7);
+	u8 val;
+	int i;
+
+	for (i = 0; i < PRUETH_MAX_TX_QUEUES * PRUETH_NUM_MACS; i++) {
+		val = readb(config + EXPRESS_PRE_EMPTIVE_Q_MAP + i);
+		val &= ~mask;
+		if (emac->cut_thru_queue_map & BIT(i))
+			val |= mask;
+
+		writeb(val, config + EXPRESS_PRE_EMPTIVE_Q_MAP + i);
+	}
+}
+
+void icssg_config_ipg(struct prueth_emac *emac)
+{
+	struct prueth *prueth = emac->prueth;
+	int slice = prueth_emac_slice(emac);
+
+	switch (emac->speed) {
+	case SPEED_1000:
+		icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_1G);
+		break;
+	case SPEED_100:
+		icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M);
+		break;
+	case SPEED_10:
+		icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M);
+		break;
+	default:
+		/* Other links speeds not supported */
+		netdev_err(emac->ndev, "Unsupported link speed\n");
+		return;
+	}
+}
+
+static void emac_r30_cmd_init(struct prueth_emac *emac)
+{
+	struct icssg_r30_cmd *p;
+	int i;
+
+	p = emac->dram.va + MGR_R30_CMD_OFFSET;
+
+	for (i = 0; i < 4; i++)
+		writel(EMAC_NONE, &p->cmd[i]);
+}
+
+static int emac_r30_is_done(struct prueth_emac *emac)
+{
+	const struct icssg_r30_cmd *p;
+	u32 cmd;
+	int i;
+
+	p = emac->dram.va + MGR_R30_CMD_OFFSET;
+
+	for (i = 0; i < 4; i++) {
+		cmd = readl(&p->cmd[i]);
+		if (cmd != EMAC_NONE)
+			return 0;
+	}
+
+	return 1;
+}
+
+static int prueth_switch_buffer_setup(struct prueth_emac *emac)
+{
+	struct icssg_buffer_pool_cfg *bpool_cfg;
+	struct prueth *prueth = emac->prueth;
+	int slice = prueth_emac_slice(emac);
+	struct icssg_rxq_ctx *rxq_ctx;
+	u32 addr;
+	int i;
+
+	addr = lower_32_bits(prueth->msmcram.pa);
+	if (slice)
+		addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE;
+
+	if (addr % SZ_64K) {
+		dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n");
+		return -EINVAL;
+	}
+
+	bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET;
+	/* workaround for f/w bug. bpool 0 needs to be initilalized */
+	for (i = 0;
+	     i <  PRUETH_NUM_BUF_POOLS;
+	     i++) {
+		bpool_cfg[i].addr = cpu_to_le32(addr);
+		bpool_cfg[i].len = cpu_to_le32(PRUETH_EMAC_BUF_POOL_SIZE);
+		addr += PRUETH_EMAC_BUF_POOL_SIZE;
+	}
+
+	if (!slice)
+		addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE;
+	else
+		addr += PRUETH_SW_NUM_BUF_POOLS_HOST * PRUETH_SW_BUF_POOL_SIZE_HOST;
+
+	for (i = PRUETH_NUM_BUF_POOLS;
+	     i <  2 * PRUETH_SW_NUM_BUF_POOLS_HOST + PRUETH_NUM_BUF_POOLS;
+	     i++) {
+		/* The driver only uses first 4 queues per PRU so only initialize them */
+		if (i % PRUETH_SW_NUM_BUF_POOLS_HOST < PRUETH_SW_NUM_BUF_POOLS_PER_PRU) {
+			bpool_cfg[i].addr = cpu_to_le32(addr);
+			bpool_cfg[i].len = cpu_to_le32(PRUETH_SW_BUF_POOL_SIZE_HOST);
+			addr += PRUETH_SW_BUF_POOL_SIZE_HOST;
+		} else {
+			bpool_cfg[i].addr = 0;
+			bpool_cfg[i].len = 0;
+		}
+	}
+
+	if (!slice)
+		addr += PRUETH_SW_NUM_BUF_POOLS_HOST * PRUETH_SW_BUF_POOL_SIZE_HOST;
+	else
+		addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2;
+
+	/* Pre-emptible RX buffer queue */
+	rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET;
+	for (i = 0; i < 3; i++)
+		rxq_ctx->start[i] = cpu_to_le32(addr);
+
+	addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
+	rxq_ctx->end = cpu_to_le32(addr);
+
+	/* Express RX buffer queue */
+	rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET;
+	for (i = 0; i < 3; i++)
+		rxq_ctx->start[i] = cpu_to_le32(addr);
+
+	addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
+	rxq_ctx->end = cpu_to_le32(addr);
+
+	return 0;
+}
+
+static int prueth_emac_buffer_setup(struct prueth_emac *emac)
+{
+	struct icssg_buffer_pool_cfg *bpool_cfg;
+	struct prueth *prueth = emac->prueth;
+	int slice = prueth_emac_slice(emac);
+	struct icssg_rxq_ctx *rxq_ctx;
+	u32 addr;
+	int i;
+
+	/* Layout to have 64KB aligned buffer pool
+	 * |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1|
+	 */
+
+	addr = lower_32_bits(prueth->msmcram.pa);
+	if (slice)
+		addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE;
+
+	if (addr % SZ_64K) {
+		dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n");
+		return -EINVAL;
+	}
+
+	bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET;
+	/* workaround for f/w bug. bpool 0 needs to be initilalized */
+	bpool_cfg[0].addr = cpu_to_le32(addr);
+	bpool_cfg[0].len = 0;
+
+	for (i = PRUETH_EMAC_BUF_POOL_START;
+	     i < PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS;
+	     i++) {
+		bpool_cfg[i].addr = cpu_to_le32(addr);
+		bpool_cfg[i].len = cpu_to_le32(PRUETH_EMAC_BUF_POOL_SIZE);
+		addr += PRUETH_EMAC_BUF_POOL_SIZE;
+	}
+
+	if (!slice)
+		addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE;
+	else
+		addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2;
+
+	/* Pre-emptible RX buffer queue */
+	rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET;
+	for (i = 0; i < 3; i++)
+		rxq_ctx->start[i] = cpu_to_le32(addr);
+
+	addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
+	rxq_ctx->end = cpu_to_le32(addr);
+
+	/* Express RX buffer queue */
+	rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET;
+	for (i = 0; i < 3; i++)
+		rxq_ctx->start[i] = cpu_to_le32(addr);
+
+	addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
+	rxq_ctx->end = cpu_to_le32(addr);
+
+	return 0;
+}
+
+static void icssg_init_emac_mode(struct prueth *prueth)
+{
+	u32 addr = prueth->shram.pa + VLAN_STATIC_REG_TABLE_OFFSET;
+	int i;
+
+	/* When the device is configured as a bridge and it is being brought back
+	 * to the emac mode, the host mac address has to be set as 0.
+	 */
+	u8 mac[ETH_ALEN] = { 0 };
+
+	if (prueth->num_emacs_initialized)
+		return;
+
+	/* Set VLAN TABLE address base */
+	regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, SMEM_VLAN_OFFSET_MASK,
+			   addr <<  SMEM_VLAN_OFFSET);
+
+	/* Configure CFG2 register */
+	regmap_write(prueth->miig_rt, FDB_GEN_CFG2, (FDB_PRU0_EN | FDB_PRU1_EN | FDB_HOST_EN));
+
+	prueth->vlan_tbl = prueth->shram.va + VLAN_STATIC_REG_TABLE_OFFSET;
+	for (i = 0; i < SZ_4K - 1; i++) {
+		prueth->vlan_tbl[i].fid = i;
+		prueth->vlan_tbl[i].fid_c1 = 0;
+	}
+	/* Clear host MAC address */
+	icssg_class_set_host_mac_addr(prueth->miig_rt, mac);
+}
+
+static void icssg_init_switch_mode(struct prueth *prueth)
+{
+	int i;
+	u32 addr = prueth->shram.pa + EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET;
+
+	if (prueth->num_emacs_initialized)
+		return;
+
+	/* Set VLAN TABLE address base */
+	regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, SMEM_VLAN_OFFSET_MASK,
+			   addr <<  SMEM_VLAN_OFFSET);
+	/* Set enable VLAN aware mode, and FDBs for all PRUs */
+	regmap_write(prueth->miig_rt, FDB_GEN_CFG2, FDB_EN_ALL);
+	prueth->vlan_tbl = prueth->shram.va + EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET;
+	for (i = 0; i < SZ_4K - 1; i++) {
+		prueth->vlan_tbl[i].fid = i;
+		prueth->vlan_tbl[i].fid_c1 = 0;
+	}
+
+	if (prueth->hw_bridge_dev)
+		icssg_class_set_host_mac_addr(prueth->miig_rt, prueth->hw_bridge_dev->dev_addr);
+	icssg_set_pvid(prueth, prueth->default_vlan, PRUETH_PORT_HOST);
+}
+
+int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
+{
+	void *config = emac->dram.va + ICSSG_CONFIG_OFFSET;
+	struct icssg_flow_cfg *flow_cfg;
+	u8 *cfg_byte_ptr = config;
+	int ret;
+
+	if (prueth->is_switch_mode || prueth->is_hsr_offload_mode)
+		icssg_init_switch_mode(prueth);
+	else
+		icssg_init_emac_mode(prueth);
+
+	memset_io(config, 0, TAS_GATE_MASK_LIST0);
+	icssg_miig_queues_init(prueth, slice);
+
+	emac->speed = SPEED_1000;
+	emac->duplex = DUPLEX_FULL;
+	if (!phy_interface_mode_is_rgmii(emac->phy_if)) {
+		emac->speed = SPEED_100;
+		emac->duplex = DUPLEX_FULL;
+	}
+	regmap_update_bits(prueth->miig_rt, ICSSG_CFG_OFFSET, ICSSG_CFG_DEFAULT, ICSSG_CFG_DEFAULT);
+	icssg_miig_set_interface_mode(prueth->miig_rt, slice, emac->phy_if);
+	if (prueth->is_switch_mode || prueth->is_hsr_offload_mode)
+		icssg_config_mii_init_switch(emac);
+	else
+		icssg_config_mii_init(emac);
+	icssg_config_ipg(emac);
+	icssg_update_rgmii_cfg(prueth->miig_rt, emac);
+
+	/* set GPI mode */
+	pruss_cfg_gpimode(prueth->pruss, prueth->pru_id[slice],
+			  PRUSS_GPI_MODE_MII);
+
+	/* enable XFR shift for PRU and RTU */
+	pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_PRU, true);
+	pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_RTU, true);
+
+	/* set C28 to 0x100 */
+	pru_rproc_set_ctable(prueth->pru[slice], PRU_C28, 0x100 << 8);
+	pru_rproc_set_ctable(prueth->rtu[slice], PRU_C28, 0x100 << 8);
+	pru_rproc_set_ctable(prueth->txpru[slice], PRU_C28, 0x100 << 8);
+
+	flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET;
+	flow_cfg->rx_base_flow = cpu_to_le32(emac->rx_flow_id_base);
+	flow_cfg->mgm_base_flow = 0;
+	*(cfg_byte_ptr + SPL_PKT_DEFAULT_PRIORITY) = 0;
+	*(cfg_byte_ptr + QUEUE_NUM_UNTAGGED) = 0x0;
+
+	if (prueth->is_switch_mode || prueth->is_hsr_offload_mode) {
+		icssg_config_cut_thru(emac);
+		ret = prueth_switch_buffer_setup(emac);
+	} else {
+		ret = prueth_emac_buffer_setup(emac);
+	}
+
+	if (ret)
+		return ret;
+
+	emac_r30_cmd_init(emac);
+
+	return 0;
+}
+
+/* Bitmask for ICSSG r30 commands */
+static const struct icssg_r30_cmd emac_r32_bitmask[] = {
+	{{0xffff0004, 0xffff0100, 0xffff0004, EMAC_NONE}},	/* EMAC_PORT_DISABLE */
+	{{0xfffb0040, 0xfeff0200, 0xfeff0200, EMAC_NONE}},	/* EMAC_PORT_BLOCK */
+	{{0xffbb0000, 0xfcff0000, 0xdcfb0000, EMAC_NONE}},	/* EMAC_PORT_FORWARD */
+	{{0xffbb0000, 0xfcff0000, 0xfcff2000, EMAC_NONE}},	/* EMAC_PORT_FORWARD_WO_LEARNING */
+	{{0xffff0001, EMAC_NONE,  EMAC_NONE, EMAC_NONE}},	/* ACCEPT ALL */
+	{{0xfffe0002, EMAC_NONE,  EMAC_NONE, EMAC_NONE}},	/* ACCEPT TAGGED */
+	{{0xfffc0000, EMAC_NONE,  EMAC_NONE, EMAC_NONE}},	/* ACCEPT UNTAGGED and PRIO */
+	{{EMAC_NONE,  0xffff0020, EMAC_NONE, EMAC_NONE}},	/* TAS Trigger List change */
+	{{EMAC_NONE,  0xdfff1000, EMAC_NONE, EMAC_NONE}},	/* TAS set state ENABLE*/
+	{{EMAC_NONE,  0xefff2000, EMAC_NONE, EMAC_NONE}},	/* TAS set state RESET*/
+	{{EMAC_NONE,  0xcfff0000, EMAC_NONE, EMAC_NONE}},	/* TAS set state DISABLE*/
+	{{EMAC_NONE,  EMAC_NONE,  0xffff0400, EMAC_NONE}},	/* UC flooding ENABLE*/
+	{{EMAC_NONE,  EMAC_NONE,  0xfbff0000, EMAC_NONE}},	/* UC flooding DISABLE*/
+	{{EMAC_NONE,  EMAC_NONE,  0xffff0800, EMAC_NONE}},	/* MC flooding ENABLE*/
+	{{EMAC_NONE,  EMAC_NONE,  0xf7ff0000, EMAC_NONE}},	/* MC flooding DISABLE*/
+	{{EMAC_NONE,  0xffff4000, EMAC_NONE, EMAC_NONE}},	/* Preemption on Tx ENABLE*/
+	{{EMAC_NONE,  0xbfff0000, EMAC_NONE, EMAC_NONE}},	/* Preemption on Tx DISABLE*/
+	{{0xffff0010,  EMAC_NONE, 0xffff0010, EMAC_NONE}},	/* VLAN AWARE*/
+	{{0xffef0000,  EMAC_NONE, 0xffef0000, EMAC_NONE}}	/* VLAN UNWARE*/
+};
+
+int emac_set_port_state(struct prueth_emac *emac,
+			enum icssg_port_state_cmd cmd)
+{
+	struct icssg_r30_cmd *p;
+	int ret = -ETIMEDOUT;
+	int done = 0;
+	int i;
+
+	p = emac->dram.va + MGR_R30_CMD_OFFSET;
+
+	if (cmd >= ICSSG_EMAC_PORT_MAX_COMMANDS) {
+		netdev_err(emac->ndev, "invalid port command\n");
+		return -EINVAL;
+	}
+
+	/* only one command at a time allowed to firmware */
+	mutex_lock(&emac->cmd_lock);
+
+	for (i = 0; i < 4; i++)
+		writel(emac_r32_bitmask[cmd].cmd[i], &p->cmd[i]);
+
+	/* wait for done */
+	ret = read_poll_timeout(emac_r30_is_done, done, done == 1,
+				1000, 10000, false, emac);
+
+	if (ret == -ETIMEDOUT)
+		netdev_err(emac->ndev, "timeout waiting for command done\n");
+
+	mutex_unlock(&emac->cmd_lock);
+
+	return ret;
+}
+
+void icssg_config_set_speed(struct prueth_emac *emac)
+{
+	u8 fw_speed;
+
+	switch (emac->speed) {
+	case SPEED_1000:
+		fw_speed = FW_LINK_SPEED_1G;
+		break;
+	case SPEED_100:
+		fw_speed = FW_LINK_SPEED_100M;
+		break;
+	case SPEED_10:
+		fw_speed = FW_LINK_SPEED_10M;
+		break;
+	default:
+		/* Other links speeds not supported */
+		netdev_err(emac->ndev, "Unsupported link speed\n");
+		return;
+	}
+
+	if (emac->duplex == DUPLEX_HALF)
+		fw_speed |= FW_LINK_SPEED_HD;
+
+	writeb(fw_speed, emac->dram.va + PORT_LINK_SPEED_OFFSET);
+}
+
+void icssg_config_half_duplex(struct prueth_emac *emac)
+{
+	u32 val;
+
+	if (!emac->half_duplex)
+		return;
+
+	val = get_random_u32();
+	writel(val, emac->dram.va + HD_RAND_SEED_OFFSET);
+}
+
+int icssg_send_fdb_msg(struct prueth_emac *emac, struct mgmt_cmd *cmd,
+		       struct mgmt_cmd_rsp *rsp)
+{
+	struct prueth *prueth = emac->prueth;
+	int slice = prueth_emac_slice(emac);
+	int addr;
+	int i = 10000;
+
+	addr = icssg_queue_pop(prueth, slice == 0 ?
+			       ICSSG_CMD_POP_SLICE0 : ICSSG_CMD_POP_SLICE1);
+	if (addr < 0)
+		return addr;
+
+	/* First 4 bytes have FW owned buffer linking info which should
+	 * not be touched
+	 */
+	memcpy_toio(prueth->shram.va + addr + 4, cmd, sizeof(*cmd));
+	icssg_queue_push(prueth, slice == 0 ?
+			 ICSSG_CMD_PUSH_SLICE0 : ICSSG_CMD_PUSH_SLICE1, addr);
+	while (i--) {
+		addr = icssg_queue_pop(prueth, slice == 0 ?
+				       ICSSG_RSP_POP_SLICE0 : ICSSG_RSP_POP_SLICE1);
+		if (addr < 0) {
+			usleep_range(1000, 2000);
+			continue;
+		}
+
+		memcpy_fromio(rsp, prueth->shram.va + addr, sizeof(*rsp));
+		/* Return buffer back for to pool */
+		icssg_queue_push(prueth, slice == 0 ?
+				 ICSSG_RSP_PUSH_SLICE0 : ICSSG_RSP_PUSH_SLICE1, addr);
+		break;
+	}
+	if (i <= 0) {
+		netdev_err(emac->ndev, "Timedout sending HWQ message\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int icssg_fdb_add_del(struct prueth_emac *emac, const unsigned char *addr,
+		      u8 vid, u8 fid_c2, bool add)
+{
+	struct mgmt_cmd_rsp fdb_cmd_rsp = { 0 };
+	struct mgmt_cmd fdb_cmd = { 0 };
+	int slice = prueth_emac_slice(emac);
+	u8 mac_fid[ETH_ALEN + 2];
+	u8 fid = vid;
+	int ret, i;
+	u16 fdb_slot;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		mac_fid[i] = addr[i];
+
+	/* 1-1 VID-FID mapping is already setup */
+	mac_fid[ETH_ALEN] = fid;
+	mac_fid[ETH_ALEN + 1] = 0;
+
+	fdb_slot = bitrev32(crc32_le(0, mac_fid, 8)) & PRUETH_SWITCH_FDB_MASK;
+
+	fdb_cmd.header = ICSSG_FW_MGMT_CMD_HEADER;
+	fdb_cmd.type   = ICSSG_FW_MGMT_FDB_CMD_TYPE;
+	fdb_cmd.seqnum = ++(emac->prueth->icssg_hwcmdseq);
+	if (add)
+		fdb_cmd.param  = ICSS_CMD_ADD_FDB;
+	else
+		fdb_cmd.param = ICSS_CMD_DEL_FDB;
+
+	fdb_cmd.param |= (slice << 4);
+
+	fid_c2 |= ICSSG_FDB_ENTRY_VALID;
+	memcpy(&fdb_cmd.cmd_args[0], addr, 4);
+	memcpy(&fdb_cmd.cmd_args[1], &addr[4], 2);
+	fdb_cmd.cmd_args[1] |= ((fid << 16) | (fid_c2 << 24));
+	fdb_cmd.cmd_args[2] = fdb_slot;
+
+	netdev_dbg(emac->ndev, "MAC %pM slot %X vlan %X FID %X\n",
+		   addr, fdb_slot, vid, fid);
+
+	ret = icssg_send_fdb_msg(emac, &fdb_cmd, &fdb_cmd_rsp);
+	if (ret)
+		return ret;
+
+	WARN_ON(fdb_cmd.seqnum != fdb_cmd_rsp.seqnum);
+	if (fdb_cmd_rsp.status == 1)
+		return 0;
+
+	return -EINVAL;
+}
+
+int icssg_fdb_lookup(struct prueth_emac *emac, const unsigned char *addr,
+		     u8 vid)
+{
+	struct mgmt_cmd_rsp fdb_cmd_rsp = { 0 };
+	struct mgmt_cmd fdb_cmd = { 0 };
+	int slice = prueth_emac_slice(emac);
+	struct prueth_fdb_slot *slot;
+	u8 mac_fid[ETH_ALEN + 2];
+	u8 fid = vid;
+	int ret, i;
+	u16 fdb_slot;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		mac_fid[i] = addr[i];
+
+	/* 1-1 VID-FID mapping is already setup */
+	mac_fid[ETH_ALEN] = fid;
+	mac_fid[ETH_ALEN + 1] = 0;
+
+	fdb_slot = bitrev32(crc32_le(0, mac_fid, 8)) & PRUETH_SWITCH_FDB_MASK;
+
+	fdb_cmd.header = ICSSG_FW_MGMT_CMD_HEADER;
+	fdb_cmd.type   = ICSSG_FW_MGMT_FDB_CMD_TYPE;
+	fdb_cmd.seqnum = ++(emac->prueth->icssg_hwcmdseq);
+	fdb_cmd.param  = ICSS_CMD_GET_FDB_SLOT;
+
+	fdb_cmd.param |= (slice << 4);
+
+	memcpy(&fdb_cmd.cmd_args[0], addr, 4);
+	memcpy(&fdb_cmd.cmd_args[1], &addr[4], 2);
+	fdb_cmd.cmd_args[1] |= fid << 16;
+	fdb_cmd.cmd_args[2] = fdb_slot;
+
+	ret = icssg_send_fdb_msg(emac, &fdb_cmd, &fdb_cmd_rsp);
+	if (ret)
+		return ret;
+
+	WARN_ON(fdb_cmd.seqnum != fdb_cmd_rsp.seqnum);
+
+	slot = emac->dram.va + FDB_CMD_BUFFER;
+	for (i = 0; i < 4; i++) {
+		if (ether_addr_equal(addr, slot->mac) && vid == slot->fid)
+			return (slot->fid_c2 & ~ICSSG_FDB_ENTRY_VALID);
+		slot++;
+	}
+
+	return 0;
+}
+
+void icssg_vtbl_modify(struct prueth_emac *emac, u8 vid, u8 port_mask,
+		       u8 untag_mask, bool add)
+{
+	struct prueth *prueth = emac->prueth;
+	struct prueth_vlan_tbl *tbl = prueth->vlan_tbl;
+	u8 fid_c1 = tbl[vid].fid_c1;
+
+	/* FID_C1: bit0..2 port membership mask,
+	 * bit3..5 tagging mask for each port
+	 * bit6 Stream VID (not handled currently)
+	 * bit7 MC flood (not handled currently)
+	 */
+	if (add) {
+		fid_c1 |= (port_mask | port_mask << 3);
+		fid_c1 &= ~(untag_mask << 3);
+	} else {
+		fid_c1 &= ~(port_mask | port_mask << 3);
+	}
+
+	tbl[vid].fid_c1 = fid_c1;
+}
+
+u16 icssg_get_pvid(struct prueth_emac *emac)
+{
+	struct prueth *prueth = emac->prueth;
+	u32 pvid;
+
+	if (emac->port_id == PRUETH_PORT_MII0)
+		pvid = readl(prueth->shram.va + EMAC_ICSSG_SWITCH_PORT1_DEFAULT_VLAN_OFFSET);
+	else
+		pvid = readl(prueth->shram.va + EMAC_ICSSG_SWITCH_PORT2_DEFAULT_VLAN_OFFSET);
+
+	pvid = pvid >> 24;
+
+	return pvid;
+}
+
+void icssg_set_pvid(struct prueth *prueth, u8 vid, u8 port)
+{
+	u32 pvid;
+
+	/* only 256 VLANs are supported */
+	pvid = cpu_to_be32((ETH_P_8021Q << 16) | (vid & 0xff));
+
+	if (port == PRUETH_PORT_MII0)
+		writel(pvid, prueth->shram.va + EMAC_ICSSG_SWITCH_PORT1_DEFAULT_VLAN_OFFSET);
+	else if (port == PRUETH_PORT_MII1)
+		writel(pvid, prueth->shram.va + EMAC_ICSSG_SWITCH_PORT2_DEFAULT_VLAN_OFFSET);
+	else
+		writel(pvid, prueth->shram.va + EMAC_ICSSG_SWITCH_PORT0_DEFAULT_VLAN_OFFSET);
+}
+
+int emac_fdb_erase_all(struct prueth_emac *emac)
+{
+	struct mgmt_cmd_rsp fdb_cmd_rsp = { 0 };
+	int slice = prueth_emac_slice(emac);
+	struct mgmt_cmd fdb_cmd = { 0 };
+	int ret = 0;
+
+	fdb_cmd.header = ICSSG_FW_MGMT_CMD_HEADER;
+	fdb_cmd.type   = ICSSG_FW_MGMT_FDB_CMD_TYPE;
+	fdb_cmd.seqnum = ++(emac->prueth->icssg_hwcmdseq);
+	fdb_cmd.param  = ICSS_CMD_ERASE_FDB;
+
+	fdb_cmd.param |= (slice << 4);
+	fdb_cmd.cmd_args[0] = 0;
+
+	ret = icssg_send_fdb_msg(emac, &fdb_cmd, &fdb_cmd_rsp);
+
+	if (ret)
+		return ret;
+
+	WARN_ON(fdb_cmd.seqnum != fdb_cmd_rsp.seqnum);
+	if (fdb_cmd_rsp.status == 1)
+		return 0;
+
+	return -EINVAL;
+}
+
+int emac_fdb_flush_multicast(struct prueth_emac *emac)
+{
+	struct prueth *prueth = emac->prueth;
+	int ret = 0;
+	int i;
+
+	ret = emac_fdb_erase_all(emac);
+
+	for (i = 0; i < SZ_4K - 1; i++) {
+		prueth->vlan_tbl[i].fid = i;
+		prueth->vlan_tbl[i].fid_c1 = 0;
+	}
+
+	return ret;
+}
+
+int emac_fdb_flow_id_updated(struct prueth_emac *emac)
+{
+	struct mgmt_cmd_rsp fdb_cmd_rsp = { 0 };
+	int slice = prueth_emac_slice(emac);
+	struct mgmt_cmd fdb_cmd = { 0 };
+	int ret = 0;
+
+	fdb_cmd.header = ICSSG_FW_MGMT_CMD_HEADER;
+	fdb_cmd.type   = ICSSG_FW_MGMT_FDB_CMD_TYPE_RX_FLOW;
+	fdb_cmd.seqnum = ++(emac->prueth->icssg_hwcmdseq);
+	fdb_cmd.param  = 0;
+
+	fdb_cmd.param |= (slice << 4);
+	fdb_cmd.cmd_args[0] = 0;
+
+	ret = icssg_send_fdb_msg(emac, &fdb_cmd, &fdb_cmd_rsp);
+
+	if (ret)
+		return ret;
+
+	WARN_ON(fdb_cmd.seqnum != fdb_cmd_rsp.seqnum);
+	if (fdb_cmd_rsp.status == 1)
+		return 0;
+
+	return -EINVAL;
+}
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_config.h b/drivers/net/ethernet/ti/icssg_config.h
--- a/drivers/net/ethernet/ti/icssg_config.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_config.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Texas Instruments ICSSG Ethernet driver
+ *
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#ifndef __NET_TI_ICSSG_CONFIG_H
+#define __NET_TI_ICSSG_CONFIG_H
+
+struct icssg_buffer_pool_cfg {
+	__le32	addr;
+	__le32	len;
+} __packed;
+
+struct icssg_flow_cfg {
+	__le16 rx_base_flow;
+	__le16 mgm_base_flow;
+} __packed;
+
+#define PRUETH_PKT_TYPE_CMD	0x10
+#define PRUETH_NAV_PS_DATA_SIZE	16	/* Protocol specific data size */
+#define PRUETH_NAV_SW_DATA_SIZE	48	/* SW related data size */
+#define PRUETH_MAX_TX_DESC	512
+#define PRUETH_MAX_RX_DESC	512
+#define PRUETH_MAX_RX_FLOWS	1	/* excluding default flow */
+#define PRUETH_RX_FLOW_DATA	0
+
+#define PRUETH_EMAC_BUF_POOL_SIZE	SZ_8K
+#define PRUETH_EMAC_POOLS_PER_SLICE	24
+#define PRUETH_EMAC_BUF_POOL_START	8
+#define PRUETH_NUM_BUF_POOLS	8
+#define PRUETH_EMAC_RX_CTX_BUF_SIZE	SZ_16K	/* per slice */
+#define MSMC_RAM_SIZE	\
+	(2 * (PRUETH_EMAC_BUF_POOL_SIZE * PRUETH_NUM_BUF_POOLS + \
+	 PRUETH_EMAC_RX_CTX_BUF_SIZE * 2))
+
+#define PRUETH_SW_BUF_POOL_SIZE_HOST	SZ_4K
+#define PRUETH_SW_NUM_BUF_POOLS_HOST	8
+#define PRUETH_SW_NUM_BUF_POOLS_PER_PRU	4
+#define MSMC_RAM_SIZE_SWITCH_MODE \
+	(MSMC_RAM_SIZE + \
+	(2 * PRUETH_SW_BUF_POOL_SIZE_HOST * PRUETH_SW_NUM_BUF_POOLS_HOST))
+
+#define PRUETH_SWITCH_FDB_MASK ((SIZE_OF_FDB / NUMBER_OF_FDB_BUCKET_ENTRIES) - 1)
+
+struct icssg_rxq_ctx {
+	__le32 start[3];
+	__le32 end;
+} __packed;
+
+/* Load time Fiwmware Configuration */
+
+#define ICSSG_FW_MGMT_CMD_HEADER	0x81
+#define ICSSG_FW_MGMT_FDB_CMD_TYPE	0x03
+#define ICSSG_FW_MGMT_CMD_TYPE		0x04
+#define ICSSG_FW_MGMT_PKT		0x80000000
+#define ICSSG_FW_MGMT_FDB_CMD_TYPE_RX_FLOW	0x05
+
+struct icssg_r30_cmd {
+	u32 cmd[4];
+} __packed;
+
+enum icssg_port_state_cmd {
+	ICSSG_EMAC_PORT_DISABLE = 0,
+	ICSSG_EMAC_PORT_BLOCK,
+	ICSSG_EMAC_PORT_FORWARD,
+	ICSSG_EMAC_PORT_FORWARD_WO_LEARNING,
+	ICSSG_EMAC_PORT_ACCEPT_ALL,
+	ICSSG_EMAC_PORT_ACCEPT_TAGGED,
+	ICSSG_EMAC_PORT_ACCEPT_UNTAGGED_N_PRIO,
+	ICSSG_EMAC_PORT_TAS_TRIGGER,
+	ICSSG_EMAC_PORT_TAS_ENABLE,
+	ICSSG_EMAC_PORT_TAS_RESET,
+	ICSSG_EMAC_PORT_TAS_DISABLE,
+	ICSSG_EMAC_PORT_UC_FLOODING_ENABLE,
+	ICSSG_EMAC_PORT_UC_FLOODING_DISABLE,
+	ICSSG_EMAC_PORT_MC_FLOODING_ENABLE,
+	ICSSG_EMAC_PORT_MC_FLOODING_DISABLE,
+	ICSSG_EMAC_PORT_PREMPT_TX_ENABLE,
+	ICSSG_EMAC_PORT_PREMPT_TX_DISABLE,
+	ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE,
+	ICSSG_EMAC_PORT_VLAN_AWARE_DISABLE,
+	ICSSG_EMAC_PORT_MAX_COMMANDS
+};
+
+#define EMAC_NONE           0xffff0000
+#define EMAC_PRU0_P_DI      0xffff0004
+#define EMAC_PRU1_P_DI      0xffff0040
+#define EMAC_TX_P_DI        0xffff0100
+
+#define EMAC_PRU0_P_EN      0xfffb0000
+#define EMAC_PRU1_P_EN      0xffbf0000
+#define EMAC_TX_P_EN        0xfeff0000
+
+#define EMAC_P_BLOCK        0xffff0040
+#define EMAC_TX_P_BLOCK     0xffff0200
+#define EMAC_P_UNBLOCK      0xffbf0000
+#define EMAC_TX_P_UNBLOCK   0xfdff0000
+#define EMAC_LEAN_EN        0xfff70000
+#define EMAC_LEAN_DI        0xffff0008
+
+#define EMAC_ACCEPT_ALL     0xffff0001
+#define EMAC_ACCEPT_TAG     0xfffe0002
+#define EMAC_ACCEPT_PRIOR   0xfffc0000
+
+/* Config area lies in DRAM */
+#define ICSSG_CONFIG_OFFSET	0x0
+
+/* Config area lies in shared RAM */
+#define ICSSG_CONFIG_OFFSET_SLICE0   0
+#define ICSSG_CONFIG_OFFSET_SLICE1   0x8000
+
+#define ICSSG_NUM_NORMAL_PDS	64
+#define ICSSG_NUM_SPECIAL_PDS	16
+
+#define ICSSG_NORMAL_PD_SIZE	8
+#define ICSSG_SPECIAL_PD_SIZE	20
+
+#define ICSSG_FLAG_MASK		0xff00ffff
+
+struct icssg_setclock_desc {
+	u8 request;
+	u8 restore;
+	u8 acknowledgment;
+	u8 cmp_status;
+	u32 margin;
+	u32 cyclecounter0_set;
+	u32 cyclecounter1_set;
+	u32 iepcount_set;
+	u32 rsvd1;
+	u32 rsvd2;
+	u32 CMP0_current;
+	u32 iepcount_current;
+	u32 difference;
+	u32 cyclecounter0_new;
+	u32 cyclecounter1_new;
+	u32 CMP0_new;
+} __packed;
+
+#define ICSSG_CMD_POP_SLICE0	56
+#define ICSSG_CMD_POP_SLICE1	60
+
+#define ICSSG_CMD_PUSH_SLICE0	57
+#define ICSSG_CMD_PUSH_SLICE1	61
+
+#define ICSSG_RSP_POP_SLICE0	58
+#define ICSSG_RSP_POP_SLICE1	62
+
+#define ICSSG_RSP_PUSH_SLICE0	56
+#define ICSSG_RSP_PUSH_SLICE1	60
+
+#define ICSSG_TS_POP_SLICE0	59
+#define ICSSG_TS_POP_SLICE1	63
+
+#define ICSSG_TS_PUSH_SLICE0	40
+#define ICSSG_TS_PUSH_SLICE1	41
+
+struct mgmt_cmd {
+	u8 param;
+	u8 seqnum;
+	u8 type;
+	u8 header;
+	u32 cmd_args[3];
+} __packed;
+
+struct mgmt_cmd_rsp {
+	u32 reserved;
+	u8 status;
+	u8 seqnum;
+	u8 type;
+	u8 header;
+	u32 cmd_args[3];
+} __packed;
+
+/* FDB FID_C2 flag definitions */
+/* Indicates host port membership.*/
+#define ICSSG_FDB_ENTRY_P0_MEMBERSHIP         BIT(0)
+/* Indicates that MAC ID is connected to physical port 1 */
+#define ICSSG_FDB_ENTRY_P1_MEMBERSHIP         BIT(1)
+/* Indicates that MAC ID is connected to physical port 2 */
+#define ICSSG_FDB_ENTRY_P2_MEMBERSHIP         BIT(2)
+/* Ageable bit is set for learned entries and cleared for static entries */
+#define ICSSG_FDB_ENTRY_AGEABLE               BIT(3)
+/* If set for DA then packet is determined to be a special packet */
+#define ICSSG_FDB_ENTRY_BLOCK                 BIT(4)
+/* If set for DA then the SA from the packet is not learned */
+#define ICSSG_FDB_ENTRY_SECURE                BIT(5)
+/* If set, it means packet has been seen recently with source address + FID
+ * matching MAC address/FID of entry
+ */
+#define ICSSG_FDB_ENTRY_TOUCHED               BIT(6)
+/* Set if entry is valid */
+#define ICSSG_FDB_ENTRY_VALID                 BIT(7)
+
+/**
+ * struct prueth_vlan_tbl - VLAN table entries struct in ICSSG SMEM
+ * @fid_c1: membership and forwarding rules flag to this table. See
+ *          above to defines for bit definitions
+ * @fid: FDB index for this VID (there is 1-1 mapping b/w VID and FID)
+ */
+struct prueth_vlan_tbl {
+	u8 fid_c1;
+	u8 fid;
+} __packed;
+
+/**
+ * struct prueth_fdb_slot - Result of FDB slot lookup
+ * @mac: MAC address
+ * @fid: fid to be associated with MAC
+ * @fid_c2: FID_C2 entry for this MAC
+ */
+struct prueth_fdb_slot {
+	u8 mac[ETH_ALEN];
+	u8 fid;
+	u8 fid_c2;
+} __packed;
+
+enum icssg_ietfpe_verify_states {
+	ICSSG_IETFPE_STATE_UNKNOWN = 0,
+	ICSSG_IETFPE_STATE_INITIAL,
+	ICSSG_IETFPE_STATE_VERIFYING,
+	ICSSG_IETFPE_STATE_SUCCEEDED,
+	ICSSG_IETFPE_STATE_FAILED,
+	ICSSG_IETFPE_STATE_DISABLED
+};
+#endif /* __NET_TI_ICSSG_CONFIG_H */
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_ethtool.c b/drivers/net/ethernet/ti/icssg_ethtool.c
--- a/drivers/net/ethernet/ti/icssg_ethtool.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_ethtool.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,565 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Texas Instruments ICSSG Ethernet driver
+ *
+ * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#include "icssg_prueth.h"
+#include <linux/regmap.h>
+
+#define STATS_TIME_LIMIT_1G_MS    25000    /* 25 seconds @ 1G */
+#define ICSSG_TX_PACKET_OFFSET	0xA0
+#define ICSSG_TX_BYTE_OFFSET	0xEC
+
+static const u32 stats_base[] = {	0x54c,	/* Slice 0 stats start */
+					0xb18,	/* Slice 1 stats start */
+};
+
+/* ICSSG MIIG_STATS registers */
+struct miig_stats_regs {
+	/* Rx */
+	u32 rx_good_frames;
+	u32 rx_broadcast_frames;
+	u32 rx_multicast_frames;
+	u32 rx_crc_error_frames;
+	u32 rx_mii_error_frames;
+	u32 rx_odd_nibble_frames;
+	u32 rx_frame_max_size;
+	u32 rx_max_size_error_frames;
+	u32 rx_frame_min_size;
+	u32 rx_min_size_error_frames;
+	u32 rx_overrun_frames;
+	u32 rx_class0_hits;
+	u32 rx_class1_hits;
+	u32 rx_class2_hits;
+	u32 rx_class3_hits;
+	u32 rx_class4_hits;
+	u32 rx_class5_hits;
+	u32 rx_class6_hits;
+	u32 rx_class7_hits;
+	u32 rx_class8_hits;
+	u32 rx_class9_hits;
+	u32 rx_class10_hits;
+	u32 rx_class11_hits;
+	u32 rx_class12_hits;
+	u32 rx_class13_hits;
+	u32 rx_class14_hits;
+	u32 rx_class15_hits;
+	u32 rx_smd_frags;
+	u32 rx_bucket1_size;
+	u32 rx_bucket2_size;
+	u32 rx_bucket3_size;
+	u32 rx_bucket4_size;
+	u32 rx_64B_frames;
+	u32 rx_bucket1_frames;
+	u32 rx_bucket2_frames;
+	u32 rx_bucket3_frames;
+	u32 rx_bucket4_frames;
+	u32 rx_bucket5_frames;
+	u32 rx_total_bytes;
+	u32 rx_tx_total_bytes;
+	/* Tx */
+	u32 tx_good_frames;
+	u32 tx_broadcast_frames;
+	u32 tx_multicast_frames;
+	u32 tx_odd_nibble_frames;
+	u32 tx_underflow_errors;
+	u32 tx_frame_max_size;
+	u32 tx_max_size_error_frames;
+	u32 tx_frame_min_size;
+	u32 tx_min_size_error_frames;
+	u32 tx_bucket1_size;
+	u32 tx_bucket2_size;
+	u32 tx_bucket3_size;
+	u32 tx_bucket4_size;
+	u32 tx_64B_frames;
+	u32 tx_bucket1_frames;
+	u32 tx_bucket2_frames;
+	u32 tx_bucket3_frames;
+	u32 tx_bucket4_frames;
+	u32 tx_bucket5_frames;
+	u32 tx_total_bytes;
+};
+
+/* ICSSG PA_STATS registers */
+struct pa_stats_regs {
+	u32 iet_bad_frag_slice0;
+	u32 iet_bad_frag_slice1;
+	u32 iet_asm_err_slice0;
+	u32 iet_asm_err_slice1;
+	u32 iet_tx_frag_slice0;
+	u32 iet_tx_frag_slice1;
+	u32 iet_asm_ok_slice0;
+	u32 iet_asm_ok_slice1;
+	u32 iet_rx_frag_slice0;
+	u32 iet_rx_frag_slice1;
+};
+
+#define ICSSG_STATS(field)				\
+{							\
+	#field,						\
+	offsetof(struct miig_stats_regs, field),	\
+}
+
+#define ICSSG_PA_STATS(field)			\
+{						\
+	#field,					\
+	offsetof(struct pa_stats_regs, field),	\
+}
+
+/**
+ * struct icssg_stats - ICSSG Stats structure
+ * @name: Stats name
+ * @offset: ICSSG stats register offset
+ */
+struct icssg_stats {
+	char name[ETH_GSTRING_LEN];
+	u32 offset;
+};
+
+static const struct icssg_stats icssg_ethtool_stats[] = {
+	/* Rx */
+	ICSSG_STATS(rx_good_frames),
+	ICSSG_STATS(rx_broadcast_frames),
+	ICSSG_STATS(rx_multicast_frames),
+	ICSSG_STATS(rx_crc_error_frames),
+	ICSSG_STATS(rx_mii_error_frames),
+	ICSSG_STATS(rx_odd_nibble_frames),
+	ICSSG_STATS(rx_frame_max_size),
+	ICSSG_STATS(rx_max_size_error_frames),
+	ICSSG_STATS(rx_frame_min_size),
+	ICSSG_STATS(rx_min_size_error_frames),
+	ICSSG_STATS(rx_overrun_frames),
+	ICSSG_STATS(rx_class0_hits),
+	ICSSG_STATS(rx_class1_hits),
+	ICSSG_STATS(rx_class2_hits),
+	ICSSG_STATS(rx_class3_hits),
+	ICSSG_STATS(rx_class4_hits),
+	ICSSG_STATS(rx_class5_hits),
+	ICSSG_STATS(rx_class6_hits),
+	ICSSG_STATS(rx_class7_hits),
+	ICSSG_STATS(rx_class8_hits),
+	ICSSG_STATS(rx_class9_hits),
+	ICSSG_STATS(rx_class10_hits),
+	ICSSG_STATS(rx_class11_hits),
+	ICSSG_STATS(rx_class12_hits),
+	ICSSG_STATS(rx_class13_hits),
+	ICSSG_STATS(rx_class14_hits),
+	ICSSG_STATS(rx_class15_hits),
+	ICSSG_STATS(rx_smd_frags),
+	ICSSG_STATS(rx_bucket1_size),
+	ICSSG_STATS(rx_bucket2_size),
+	ICSSG_STATS(rx_bucket3_size),
+	ICSSG_STATS(rx_bucket4_size),
+	ICSSG_STATS(rx_64B_frames),
+	ICSSG_STATS(rx_bucket1_frames),
+	ICSSG_STATS(rx_bucket2_frames),
+	ICSSG_STATS(rx_bucket3_frames),
+	ICSSG_STATS(rx_bucket4_frames),
+	ICSSG_STATS(rx_bucket5_frames),
+	ICSSG_STATS(rx_total_bytes),
+	ICSSG_STATS(rx_tx_total_bytes),
+	/* Tx */
+	ICSSG_STATS(tx_good_frames),
+	ICSSG_STATS(tx_broadcast_frames),
+	ICSSG_STATS(tx_multicast_frames),
+	ICSSG_STATS(tx_odd_nibble_frames),
+	ICSSG_STATS(tx_underflow_errors),
+	ICSSG_STATS(tx_frame_max_size),
+	ICSSG_STATS(tx_max_size_error_frames),
+	ICSSG_STATS(tx_frame_min_size),
+	ICSSG_STATS(tx_min_size_error_frames),
+	ICSSG_STATS(tx_bucket1_size),
+	ICSSG_STATS(tx_bucket2_size),
+	ICSSG_STATS(tx_bucket3_size),
+	ICSSG_STATS(tx_bucket4_size),
+	ICSSG_STATS(tx_64B_frames),
+	ICSSG_STATS(tx_bucket1_frames),
+	ICSSG_STATS(tx_bucket2_frames),
+	ICSSG_STATS(tx_bucket3_frames),
+	ICSSG_STATS(tx_bucket4_frames),
+	ICSSG_STATS(tx_bucket5_frames),
+	ICSSG_STATS(tx_total_bytes),
+};
+
+static const struct icssg_stats icssg_pa_stats[] = {
+	/* PA STATS */
+	ICSSG_PA_STATS(iet_bad_frag_slice0),
+	ICSSG_PA_STATS(iet_bad_frag_slice1),
+	ICSSG_PA_STATS(iet_asm_err_slice0),
+	ICSSG_PA_STATS(iet_asm_err_slice1),
+	ICSSG_PA_STATS(iet_tx_frag_slice0),
+	ICSSG_PA_STATS(iet_tx_frag_slice1),
+	ICSSG_PA_STATS(iet_asm_ok_slice0),
+	ICSSG_PA_STATS(iet_asm_ok_slice1),
+	ICSSG_PA_STATS(iet_rx_frag_slice0),
+	ICSSG_PA_STATS(iet_rx_frag_slice1),
+};
+
+static void emac_get_drvinfo(struct net_device *ndev,
+			     struct ethtool_drvinfo *info)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth *prueth = emac->prueth;
+
+	strscpy(info->driver, dev_driver_string(prueth->dev),
+		sizeof(info->driver));
+	strscpy(info->bus_info, dev_name(prueth->dev), sizeof(info->bus_info));
+}
+
+static u32 emac_get_msglevel(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+
+	return emac->msg_enable;
+}
+
+static void emac_set_msglevel(struct net_device *ndev, u32 value)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+
+	emac->msg_enable = value;
+}
+
+static int emac_get_link_ksettings(struct net_device *ndev,
+				   struct ethtool_link_ksettings *ecmd)
+{
+	return phy_ethtool_get_link_ksettings(ndev, ecmd);
+}
+
+static int emac_set_link_ksettings(struct net_device *ndev,
+				   const struct ethtool_link_ksettings *ecmd)
+{
+	return phy_ethtool_set_link_ksettings(ndev, ecmd);
+}
+
+static int emac_get_eee(struct net_device *ndev, struct ethtool_eee *edata)
+{
+	if (!ndev->phydev)
+		return -EOPNOTSUPP;
+
+	return phy_ethtool_get_eee(ndev->phydev, edata);
+}
+
+static int emac_set_eee(struct net_device *ndev, struct ethtool_eee *edata)
+{
+	if (!ndev->phydev)
+		return -EOPNOTSUPP;
+
+	return phy_ethtool_set_eee(ndev->phydev, edata);
+}
+
+static int emac_nway_reset(struct net_device *ndev)
+{
+	return phy_ethtool_nway_reset(ndev);
+}
+
+#define EMAC_PRIV_IET_FRAME_PREEMPTION  BIT(0)
+#define EMAC_PRIV_IET_MAC_VERIFY        BIT(1)
+
+static const char emac_ethtool_priv_flags[][ETH_GSTRING_LEN] = {
+	"iet-frame-preemption",
+	"iet-mac-verify",
+};
+
+static int emac_get_sset_count(struct net_device *ndev, int stringset)
+{
+	switch (stringset) {
+	case ETH_SS_STATS:
+		return ICSSG_NUM_STATS;
+	case ETH_SS_PRIV_FLAGS:
+		return ARRAY_SIZE(emac_ethtool_priv_flags);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void emac_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+	const struct icssg_stats *hw_stats;
+	u32 i, num_stats;
+	u8 *p = data;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		num_stats = ARRAY_SIZE(icssg_ethtool_stats);
+		hw_stats = icssg_ethtool_stats;
+		for (i = 0; i < num_stats; i++) {
+			memcpy(p, hw_stats[i].name, ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
+		}
+
+		num_stats = ARRAY_SIZE(icssg_pa_stats);
+		hw_stats = icssg_pa_stats;
+		for (i = 0; i < num_stats; i++) {
+			memcpy(p, hw_stats[i].name, ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
+		}
+		break;
+	case ETH_SS_PRIV_FLAGS:
+		for (i = 0; i < ARRAY_SIZE(emac_ethtool_priv_flags); i++) {
+			memcpy(p, emac_ethtool_priv_flags[i],
+			       ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static void emac_update_hardware_stats(struct prueth_emac *emac)
+{
+	struct prueth *prueth = emac->prueth;
+	int slice = prueth_emac_slice(emac);
+	u32 base = stats_base[slice];
+	u32 tx_pkt_cnt = 0;
+	int i, j;
+	u32 val;
+
+	for (i = 0; i < ARRAY_SIZE(icssg_ethtool_stats); i++) {
+		regmap_read(prueth->miig_rt,
+			    base + icssg_ethtool_stats[i].offset,
+			    &val);
+		regmap_write(prueth->miig_rt,
+			     base + icssg_ethtool_stats[i].offset,
+			     val);
+
+		if (icssg_ethtool_stats[i].offset == ICSSG_TX_PACKET_OFFSET)
+			tx_pkt_cnt = val;
+
+		emac->stats[i] += val;
+		if (icssg_ethtool_stats[i].offset == ICSSG_TX_BYTE_OFFSET)
+			emac->stats[i] -= tx_pkt_cnt * 8;
+	}
+
+	for (j = 0; j < ARRAY_SIZE(icssg_pa_stats); j++) {
+		regmap_read(prueth->pa_stats,
+			    ICSSG_IET_STATS_BASE + icssg_pa_stats[j].offset,
+			    &val);
+		emac->stats[i + j] += val;
+	}
+}
+
+void emac_stats_work_handler(struct work_struct *work)
+{
+	struct prueth_emac *emac = container_of(work, struct prueth_emac,
+						stats_work.work);
+	emac_update_hardware_stats(emac);
+
+	queue_delayed_work(system_long_wq, &emac->stats_work,
+			   msecs_to_jiffies((STATS_TIME_LIMIT_1G_MS * 1000) / emac->speed));
+}
+
+static void emac_get_ethtool_stats(struct net_device *ndev,
+				   struct ethtool_stats *stats, u64 *data)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	int i;
+
+	emac_update_hardware_stats(emac);
+
+	for (i = 0; i < ICSSG_NUM_STATS; i++)
+		data[i] = emac->stats[i];
+}
+
+static int emac_get_ts_info(struct net_device *ndev,
+			    struct ethtool_ts_info *info)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+
+	info->so_timestamping =
+		SOF_TIMESTAMPING_TX_HARDWARE |
+		SOF_TIMESTAMPING_TX_SOFTWARE |
+		SOF_TIMESTAMPING_RX_HARDWARE |
+		SOF_TIMESTAMPING_RX_SOFTWARE |
+		SOF_TIMESTAMPING_SOFTWARE |
+		SOF_TIMESTAMPING_RAW_HARDWARE;
+
+	info->phc_index = icss_iep_get_ptp_clock_idx(emac->iep);
+	info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON);
+	info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL);
+
+	return 0;
+}
+
+static int emac_set_channels(struct net_device *ndev,
+			     struct ethtool_channels *ch)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+
+	/* Check if interface is up. Can change the num queues when
+	 * the interface is down.
+	 */
+	if (netif_running(emac->ndev))
+		return -EBUSY;
+
+	emac->tx_ch_num = ch->tx_count;
+
+	return 0;
+}
+
+static void emac_get_channels(struct net_device *ndev,
+			      struct ethtool_channels *ch)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+
+	ch->max_rx = 1;
+	ch->max_tx = PRUETH_MAX_TX_QUEUES;
+	ch->rx_count = 1;
+	ch->tx_count = emac->tx_ch_num;
+}
+
+/* TODO : This is temporary until a formal ethtool interface become available
+ * in LKML to configure IET FPE.
+ */
+static u32 emac_get_ethtool_priv_flags(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+	u32 priv_flags = 0;
+
+	/* Port specific flags */
+	if (iet->fpe_configured)
+		priv_flags |= EMAC_PRIV_IET_FRAME_PREEMPTION;
+	if (iet->mac_verify_configured)
+		priv_flags |= EMAC_PRIV_IET_MAC_VERIFY;
+
+	return priv_flags;
+}
+
+static int emac_set_ethtool_priv_flags(struct net_device *ndev, u32 flags)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+	int iet_fpe, mac_verify;
+
+	iet_fpe = !!(flags & EMAC_PRIV_IET_FRAME_PREEMPTION);
+	mac_verify = !!(flags & EMAC_PRIV_IET_MAC_VERIFY);
+
+	if (netif_running(ndev))
+		return -EBUSY;
+
+	if (emac->tx_ch_num < 2 && iet_fpe) {
+		netdev_err(ndev, "IET fpe needs at least 2 h/w queues\n");
+		return -EINVAL;
+	}
+
+	if (mac_verify && (!iet->fpe_configured && !iet_fpe)) {
+		netdev_err(ndev, "Enable IET FPE for IET MAC verify\n");
+		return -EINVAL;
+	}
+
+	iet->fpe_configured = iet_fpe;
+	iet->mac_verify_configured = mac_verify;
+
+	return 0;
+}
+
+static int emac_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
+			     struct kernel_ethtool_coalesce *kernel_coal,
+			     struct netlink_ext_ack *extack)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth_tx_chn *tx_chn;
+
+	tx_chn = &emac->tx_chns[0];
+
+	coal->rx_coalesce_usecs = emac->rx_pace_timeout_ns / 1000;
+	coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout_ns / 1000;
+
+	return 0;
+}
+
+static int emac_get_per_queue_coalesce(struct net_device *ndev, u32 queue,
+				       struct ethtool_coalesce *coal)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth_tx_chn *tx_chn;
+
+	if (queue >= PRUETH_MAX_TX_QUEUES)
+		return -EINVAL;
+
+	tx_chn = &emac->tx_chns[queue];
+
+	coal->tx_coalesce_usecs = tx_chn->tx_pace_timeout_ns / 1000;
+
+	return 0;
+}
+
+static int emac_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
+			     struct kernel_ethtool_coalesce *kernel_coal,
+			     struct netlink_ext_ack *extack)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth *prueth = emac->prueth;
+	struct prueth_tx_chn *tx_chn;
+
+	tx_chn = &emac->tx_chns[0];
+
+	if (coal->rx_coalesce_usecs && coal->rx_coalesce_usecs < ICSSG_MIN_COALESCE_USECS) {
+		dev_info(prueth->dev, "defaulting to min value of %dus for rx-usecs\n",
+			 ICSSG_MIN_COALESCE_USECS);
+		coal->rx_coalesce_usecs = ICSSG_MIN_COALESCE_USECS;
+	}
+
+	if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < ICSSG_MIN_COALESCE_USECS) {
+		dev_info(prueth->dev, "defaulting to min value of %dus for tx-usecs\n",
+			 ICSSG_MIN_COALESCE_USECS);
+		coal->tx_coalesce_usecs = ICSSG_MIN_COALESCE_USECS;
+	}
+
+	emac->rx_pace_timeout_ns = coal->rx_coalesce_usecs * 1000;
+	tx_chn->tx_pace_timeout_ns = coal->tx_coalesce_usecs * 1000;
+
+	return 0;
+}
+
+static int emac_set_per_queue_coalesce(struct net_device *ndev, u32 queue,
+				       struct ethtool_coalesce *coal)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth *prueth = emac->prueth;
+	struct prueth_tx_chn *tx_chn;
+
+	if (queue >= PRUETH_MAX_TX_QUEUES)
+		return -EINVAL;
+
+	tx_chn = &emac->tx_chns[queue];
+
+	if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < ICSSG_MIN_COALESCE_USECS) {
+		dev_info(prueth->dev, "defaulting to min value of %dus for tx-usecs for tx-%u\n",
+			 ICSSG_MIN_COALESCE_USECS, queue);
+		coal->tx_coalesce_usecs = ICSSG_MIN_COALESCE_USECS;
+	}
+
+	tx_chn->tx_pace_timeout_ns = coal->tx_coalesce_usecs * 1000;
+
+	return 0;
+}
+
+const struct ethtool_ops icssg_ethtool_ops = {
+	.get_drvinfo = emac_get_drvinfo,
+	.get_msglevel = emac_get_msglevel,
+	.set_msglevel = emac_set_msglevel,
+	.get_sset_count = emac_get_sset_count,
+	.get_ethtool_stats = emac_get_ethtool_stats,
+	.get_strings = emac_get_strings,
+	.get_ts_info = emac_get_ts_info,
+	.get_priv_flags = emac_get_ethtool_priv_flags,
+	.set_priv_flags = emac_set_ethtool_priv_flags,
+	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS | ETHTOOL_COALESCE_TX_USECS,
+	.get_coalesce           = emac_get_coalesce,
+	.set_coalesce           = emac_set_coalesce,
+	.get_per_queue_coalesce = emac_get_per_queue_coalesce,
+	.set_per_queue_coalesce = emac_set_per_queue_coalesce,
+	.get_channels = emac_get_channels,
+	.set_channels = emac_set_channels,
+	.get_link_ksettings = emac_get_link_ksettings,
+	.set_link_ksettings = emac_set_link_ksettings,
+	.get_link = ethtool_op_get_link,
+	.get_eee = emac_get_eee,
+	.set_eee = emac_set_eee,
+	.nway_reset = emac_nway_reset,
+};
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_mii_cfg.c b/drivers/net/ethernet/ti/icssg_mii_cfg.c
--- a/drivers/net/ethernet/ti/icssg_mii_cfg.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_mii_cfg.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Texas Instruments ICSSG Ethernet Driver
+ *
+ * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/regmap.h>
+#include <linux/types.h>
+
+#include "icssg_mii_rt.h"
+#include "icssg_prueth.h"
+
+void icssg_mii_update_ipg(struct regmap *mii_rt, int mii, u32 ipg)
+{
+	u32 val;
+
+	if (mii == ICSS_MII0) {
+		regmap_write(mii_rt, PRUSS_MII_RT_TX_IPG0, ipg);
+	} else {
+		regmap_read(mii_rt, PRUSS_MII_RT_TX_IPG0, &val);
+		regmap_write(mii_rt, PRUSS_MII_RT_TX_IPG1, ipg);
+		regmap_write(mii_rt, PRUSS_MII_RT_TX_IPG0, val);
+	}
+}
+
+void icssg_mii_update_mtu(struct regmap *mii_rt, int mii, int mtu)
+{
+	mtu += (ETH_HLEN + ETH_FCS_LEN);
+	if (mii == ICSS_MII0) {
+		regmap_update_bits(mii_rt,
+				   PRUSS_MII_RT_RX_FRMS0,
+				   PRUSS_MII_RT_RX_FRMS_MAX_FRM_MASK,
+				   (mtu - 1) << PRUSS_MII_RT_RX_FRMS_MAX_FRM_SHIFT);
+	} else {
+		regmap_update_bits(mii_rt,
+				   PRUSS_MII_RT_RX_FRMS1,
+				   PRUSS_MII_RT_RX_FRMS_MAX_FRM_MASK,
+				   (mtu - 1) << PRUSS_MII_RT_RX_FRMS_MAX_FRM_SHIFT);
+	}
+}
+
+void icssg_update_rgmii_cfg(struct regmap *miig_rt, struct prueth_emac *emac)
+{
+	u32 gig_en_mask, gig_val = 0, full_duplex_mask, full_duplex_val = 0;
+	int slice = prueth_emac_slice(emac);
+	u32 inband_en_mask, inband_val = 0;
+
+	gig_en_mask = (slice == ICSS_MII0) ? RGMII_CFG_GIG_EN_MII0 :
+					RGMII_CFG_GIG_EN_MII1;
+	if (emac->speed == SPEED_1000)
+		gig_val = gig_en_mask;
+	regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, gig_en_mask, gig_val);
+
+	inband_en_mask = (slice == ICSS_MII0) ? RGMII_CFG_INBAND_EN_MII0 :
+					RGMII_CFG_INBAND_EN_MII1;
+	if (emac->speed == SPEED_10 && phy_interface_mode_is_rgmii(emac->phy_if))
+		inband_val = inband_en_mask;
+	regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, inband_en_mask, inband_val);
+
+	full_duplex_mask = (slice == ICSS_MII0) ? RGMII_CFG_FULL_DUPLEX_MII0 :
+					   RGMII_CFG_FULL_DUPLEX_MII1;
+	if (emac->duplex == DUPLEX_FULL)
+		full_duplex_val = full_duplex_mask;
+	regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, full_duplex_mask,
+			   full_duplex_val);
+}
+
+void icssg_miig_set_interface_mode(struct regmap *miig_rt, int mii, phy_interface_t phy_if)
+{
+	u32 val, mask, shift;
+
+	mask = mii == ICSS_MII0 ? ICSSG_CFG_MII0_MODE : ICSSG_CFG_MII1_MODE;
+	shift =  mii == ICSS_MII0 ? ICSSG_CFG_MII0_MODE_SHIFT : ICSSG_CFG_MII1_MODE_SHIFT;
+
+	val = MII_MODE_RGMII;
+	if (phy_if == PHY_INTERFACE_MODE_MII)
+		val = MII_MODE_MII;
+
+	val <<= shift;
+	regmap_update_bits(miig_rt, ICSSG_CFG_OFFSET, mask, val);
+	regmap_read(miig_rt, ICSSG_CFG_OFFSET, &val);
+}
+
+u32 icssg_rgmii_cfg_get_bitfield(struct regmap *miig_rt, u32 mask, u32 shift)
+{
+	u32 val;
+
+	regmap_read(miig_rt, RGMII_CFG_OFFSET, &val);
+	val &= mask;
+	val >>= shift;
+
+	return val;
+}
+
+u32 icssg_rgmii_get_speed(struct regmap *miig_rt, int mii)
+{
+	u32 shift = RGMII_CFG_SPEED_MII0_SHIFT, mask = RGMII_CFG_SPEED_MII0;
+
+	if (mii == ICSS_MII1) {
+		shift = RGMII_CFG_SPEED_MII1_SHIFT;
+		mask = RGMII_CFG_SPEED_MII1;
+	}
+
+	return icssg_rgmii_cfg_get_bitfield(miig_rt, mask, shift);
+}
+
+u32 icssg_rgmii_get_fullduplex(struct regmap *miig_rt, int mii)
+{
+	u32 shift = RGMII_CFG_FULLDUPLEX_MII0_SHIFT;
+	u32 mask = RGMII_CFG_FULLDUPLEX_MII0;
+
+	if (mii == ICSS_MII1) {
+		shift = RGMII_CFG_FULLDUPLEX_MII1_SHIFT;
+		mask = RGMII_CFG_FULLDUPLEX_MII1;
+	}
+
+	return icssg_rgmii_cfg_get_bitfield(miig_rt, mask, shift);
+}
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_mii_rt.h b/drivers/net/ethernet/ti/icssg_mii_rt.h
--- a/drivers/net/ethernet/ti/icssg_mii_rt.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_mii_rt.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* PRU-ICSS MII_RT register definitions
+ *
+ * Copyright (C) 2015-2022 Texas Instruments Incorporated - https://www.ti.com
+ */
+
+#ifndef __NET_PRUSS_MII_RT_H__
+#define __NET_PRUSS_MII_RT_H__
+
+#include <linux/if_ether.h>
+#include <linux/phy.h>
+
+/* PRUSS_MII_RT Registers */
+#define PRUSS_MII_RT_RXCFG0		0x0
+#define PRUSS_MII_RT_RXCFG1		0x4
+#define PRUSS_MII_RT_TXCFG0		0x10
+#define PRUSS_MII_RT_TXCFG1		0x14
+#define PRUSS_MII_RT_TX_CRC0		0x20
+#define PRUSS_MII_RT_TX_CRC1		0x24
+#define PRUSS_MII_RT_TX_IPG0		0x30
+#define PRUSS_MII_RT_TX_IPG1		0x34
+#define PRUSS_MII_RT_PRS0		0x38
+#define PRUSS_MII_RT_PRS1		0x3c
+#define PRUSS_MII_RT_RX_FRMS0		0x40
+#define PRUSS_MII_RT_RX_FRMS1		0x44
+#define PRUSS_MII_RT_RX_PCNT0		0x48
+#define PRUSS_MII_RT_RX_PCNT1		0x4c
+#define PRUSS_MII_RT_RX_ERR0		0x50
+#define PRUSS_MII_RT_RX_ERR1		0x54
+
+/* PRUSS_MII_RT_RXCFG0/1 bits */
+#define PRUSS_MII_RT_RXCFG_RX_ENABLE		BIT(0)
+#define PRUSS_MII_RT_RXCFG_RX_DATA_RDY_MODE_DIS	BIT(1)
+#define PRUSS_MII_RT_RXCFG_RX_CUT_PREAMBLE	BIT(2)
+#define PRUSS_MII_RT_RXCFG_RX_MUX_SEL		BIT(3)
+#define PRUSS_MII_RT_RXCFG_RX_L2_EN		BIT(4)
+#define PRUSS_MII_RT_RXCFG_RX_BYTE_SWAP		BIT(5)
+#define PRUSS_MII_RT_RXCFG_RX_AUTO_FWD_PRE	BIT(6)
+#define PRUSS_MII_RT_RXCFG_RX_L2_EOF_SCLR_DIS	BIT(9)
+
+/* PRUSS_MII_RT_TXCFG0/1 bits */
+#define PRUSS_MII_RT_TXCFG_TX_ENABLE		BIT(0)
+#define PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE	BIT(1)
+#define PRUSS_MII_RT_TXCFG_TX_EN_MODE		BIT(2)
+#define PRUSS_MII_RT_TXCFG_TX_BYTE_SWAP		BIT(3)
+#define PRUSS_MII_RT_TXCFG_TX_MUX_SEL		BIT(8)
+#define PRUSS_MII_RT_TXCFG_PRE_TX_AUTO_SEQUENCE	BIT(9)
+#define PRUSS_MII_RT_TXCFG_PRE_TX_AUTO_ESC_ERR	BIT(10)
+#define PRUSS_MII_RT_TXCFG_TX_32_MODE_EN	BIT(11)
+#define PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN	BIT(12)	/* SR2.0 onwards */
+
+#define PRUSS_MII_RT_TXCFG_TX_START_DELAY_SHIFT	16
+#define PRUSS_MII_RT_TXCFG_TX_START_DELAY_MASK	GENMASK(25, 16)
+
+#define PRUSS_MII_RT_TXCFG_TX_CLK_DELAY_SHIFT	28
+#define PRUSS_MII_RT_TXCFG_TX_CLK_DELAY_MASK	GENMASK(30, 28)
+
+/* PRUSS_MII_RT_TX_IPG0/1 bits */
+#define PRUSS_MII_RT_TX_IPG_IPG_SHIFT	0
+#define PRUSS_MII_RT_TX_IPG_IPG_MASK	GENMASK(9, 0)
+
+/* PRUSS_MII_RT_PRS0/1 bits */
+#define PRUSS_MII_RT_PRS_COL	BIT(0)
+#define PRUSS_MII_RT_PRS_CRS	BIT(1)
+
+/* PRUSS_MII_RT_RX_FRMS0/1 bits */
+#define PRUSS_MII_RT_RX_FRMS_MIN_FRM_SHIFT	0
+#define PRUSS_MII_RT_RX_FRMS_MIN_FRM_MASK	GENMASK(15, 0)
+
+#define PRUSS_MII_RT_RX_FRMS_MAX_FRM_SHIFT	16
+#define PRUSS_MII_RT_RX_FRMS_MAX_FRM_MASK	GENMASK(31, 16)
+
+/* Min/Max in MII_RT_RX_FRMS */
+/* For EMAC and Switch */
+#define PRUSS_MII_RT_RX_FRMS_MAX	(VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)
+#define PRUSS_MII_RT_RX_FRMS_MIN_FRM	(64)
+
+/* for HSR and PRP */
+#define PRUSS_MII_RT_RX_FRMS_MAX_FRM_LRE	(PRUSS_MII_RT_RX_FRMS_MAX + \
+						 ICSS_LRE_TAG_RCT_SIZE)
+/* PRUSS_MII_RT_RX_PCNT0/1 bits */
+#define PRUSS_MII_RT_RX_PCNT_MIN_PCNT_SHIFT	0
+#define PRUSS_MII_RT_RX_PCNT_MIN_PCNT_MASK	GENMASK(3, 0)
+
+#define PRUSS_MII_RT_RX_PCNT_MAX_PCNT_SHIFT	4
+#define PRUSS_MII_RT_RX_PCNT_MAX_PCNT_MASK	GENMASK(7, 4)
+
+/* PRUSS_MII_RT_RX_ERR0/1 bits */
+#define PRUSS_MII_RT_RX_ERR_MIN_PCNT_ERR	BIT(0)
+#define PRUSS_MII_RT_RX_ERR_MAX_PCNT_ERR	BIT(1)
+#define PRUSS_MII_RT_RX_ERR_MIN_FRM_ERR		BIT(2)
+#define PRUSS_MII_RT_RX_ERR_MAX_FRM_ERR		BIT(3)
+
+#define ICSSG_CFG_OFFSET	0
+#define RGMII_CFG_OFFSET	4
+
+/* Constant to choose between MII0 and MII1 */
+#define ICSS_MII0	0
+#define ICSS_MII1	1
+
+/* ICSSG_CFG Register bits */
+#define ICSSG_CFG_SGMII_MODE	BIT(16)
+#define ICSSG_CFG_TX_PRU_EN	BIT(11)
+#define ICSSG_CFG_RX_SFD_TX_SOF_EN	BIT(10)
+#define ICSSG_CFG_RTU_PRU_PSI_SHARE_EN	BIT(9)
+#define ICSSG_CFG_IEP1_TX_EN	BIT(8)
+#define ICSSG_CFG_MII1_MODE	GENMASK(6, 5)
+#define ICSSG_CFG_MII1_MODE_SHIFT	5
+#define ICSSG_CFG_MII0_MODE	GENMASK(4, 3)
+#define ICSSG_CFG_MII0_MODE_SHIFT	3
+#define ICSSG_CFG_RX_L2_G_EN	BIT(2)
+#define ICSSG_CFG_TX_L2_EN	BIT(1)
+#define ICSSG_CFG_TX_L1_EN	BIT(0)
+
+enum mii_mode {
+	MII_MODE_MII = 0,
+	MII_MODE_RGMII
+};
+
+/* RGMII CFG Register bits */
+#define RGMII_CFG_INBAND_EN_MII0	BIT(16)
+#define RGMII_CFG_GIG_EN_MII0	BIT(17)
+#define RGMII_CFG_INBAND_EN_MII1	BIT(20)
+#define RGMII_CFG_GIG_EN_MII1	BIT(21)
+#define RGMII_CFG_FULL_DUPLEX_MII0	BIT(18)
+#define RGMII_CFG_FULL_DUPLEX_MII1	BIT(22)
+#define RGMII_CFG_SPEED_MII0	GENMASK(2, 1)
+#define RGMII_CFG_SPEED_MII1	GENMASK(6, 5)
+#define RGMII_CFG_SPEED_MII0_SHIFT	1
+#define RGMII_CFG_SPEED_MII1_SHIFT	5
+#define RGMII_CFG_FULLDUPLEX_MII0	BIT(3)
+#define RGMII_CFG_FULLDUPLEX_MII1	BIT(7)
+#define RGMII_CFG_FULLDUPLEX_MII0_SHIFT	3
+#define RGMII_CFG_FULLDUPLEX_MII1_SHIFT	7
+#define RGMII_CFG_SPEED_10M	0
+#define RGMII_CFG_SPEED_100M	1
+#define RGMII_CFG_SPEED_1G	2
+
+struct regmap;
+struct prueth_emac;
+
+void icssg_mii_update_ipg(struct regmap *mii_rt, int mii, u32 ipg);
+void icssg_mii_update_mtu(struct regmap *mii_rt, int mii, int mtu);
+void icssg_update_rgmii_cfg(struct regmap *miig_rt, struct prueth_emac *emac);
+u32 icssg_rgmii_cfg_get_bitfield(struct regmap *miig_rt, u32 mask, u32 shift);
+u32 icssg_rgmii_get_speed(struct regmap *miig_rt, int mii);
+u32 icssg_rgmii_get_fullduplex(struct regmap *miig_rt, int mii);
+void icssg_miig_set_interface_mode(struct regmap *miig_rt, int mii, phy_interface_t phy_if);
+
+#endif /* __NET_PRUSS_MII_RT_H__ */
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_prueth.c b/drivers/net/ethernet/ti/icssg_prueth.c
--- a/drivers/net/ethernet/ti/icssg_prueth.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_prueth.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,3547 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* Texas Instruments ICSSG Ethernet Driver
+ *
+ * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma/ti-cppi5.h>
+#include <linux/etherdevice.h>
+#include <linux/genalloc.h>
+#include <linux/if_hsr.h>
+#include <linux/if_vlan.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/phy.h>
+#include <linux/remoteproc/pruss.h>
+#include <linux/regmap.h>
+#include <linux/remoteproc.h>
+
+#include "icssg_prueth.h"
+#include "icssg_mii_rt.h"
+#include "icssg_switchdev.h"
+#include "k3-cppi-desc-pool.h"
+
+#define PRUETH_MODULE_DESCRIPTION "PRUSS ICSSG Ethernet driver"
+
+/* MAX MTU set to match MII_G_RT_RX_STAT_MAX_SIZE_PRU0/1,
+ * MII_G_RT_TX_STAT_MAX_SIZE_PORT0/1 defaults
+ */
+#define PRUETH_MAX_MTU		(2000 - ETH_HLEN - ETH_FCS_LEN)
+#define PRUETH_MIN_PKT_SIZE	(VLAN_ETH_ZLEN)
+#define PRUETH_MAX_PKT_SIZE	(PRUETH_MAX_MTU + ETH_HLEN + ETH_FCS_LEN)
+
+/* Netif debug messages possible */
+#define PRUETH_EMAC_DEBUG	(NETIF_MSG_DRV | \
+				 NETIF_MSG_PROBE | \
+				 NETIF_MSG_LINK | \
+				 NETIF_MSG_TIMER | \
+				 NETIF_MSG_IFDOWN | \
+				 NETIF_MSG_IFUP | \
+				 NETIF_MSG_RX_ERR | \
+				 NETIF_MSG_TX_ERR | \
+				 NETIF_MSG_TX_QUEUED | \
+				 NETIF_MSG_INTR | \
+				 NETIF_MSG_TX_DONE | \
+				 NETIF_MSG_RX_STATUS | \
+				 NETIF_MSG_PKTDATA | \
+				 NETIF_MSG_HW | \
+				 NETIF_MSG_WOL)
+
+#define prueth_napi_to_emac(napi) container_of(napi, struct prueth_emac, napi_rx)
+
+#define DEFAULT_VID		1
+#define DEFAULT_PORT_MASK	1
+#define DEFAULT_UNTAG_MASK	1
+
+#define NETIF_PRUETH_HSR_OFFLOAD	(NETIF_F_HW_HSR_FWD | \
+					 NETIF_F_HW_HSR_DUP)
+
+/* CTRLMMR_ICSSG_RGMII_CTRL register bits */
+#define ICSSG_CTRL_RGMII_ID_MODE		BIT(24)
+
+#define IEP_DEFAULT_CYCLE_TIME_NS	1000000	/* 1 ms */
+
+#define PRUETH_UNDIRECTED_PKT_DST_TAG	0
+
+static void prueth_cleanup_rx_chns(struct prueth_emac *emac,
+				   struct prueth_rx_chn *rx_chn,
+				   int max_rflows)
+{
+	if (rx_chn->pg_pool) {
+		page_pool_destroy(rx_chn->pg_pool);
+		rx_chn->pg_pool = NULL;
+	}
+
+	if (rx_chn->desc_pool)
+		k3_cppi_desc_pool_destroy(rx_chn->desc_pool);
+
+	if (rx_chn->rx_chn)
+		k3_udma_glue_release_rx_chn(rx_chn->rx_chn);
+}
+
+static void prueth_cleanup_tx_chns(struct prueth_emac *emac)
+{
+	int i;
+
+	for (i = 0; i < emac->tx_ch_num; i++) {
+		struct prueth_tx_chn *tx_chn = &emac->tx_chns[i];
+
+		if (tx_chn->desc_pool)
+			k3_cppi_desc_pool_destroy(tx_chn->desc_pool);
+
+		if (tx_chn->tx_chn)
+			k3_udma_glue_release_tx_chn(tx_chn->tx_chn);
+
+		/* Assume prueth_cleanup_tx_chns() is called at the
+		 * end after all channel resources are freed
+		 */
+		memset(tx_chn, 0, sizeof(*tx_chn));
+	}
+}
+
+static void prueth_ndev_del_tx_napi(struct prueth_emac *emac, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		struct prueth_tx_chn *tx_chn = &emac->tx_chns[i];
+
+		if (tx_chn->irq)
+			free_irq(tx_chn->irq, tx_chn);
+		netif_napi_del(&tx_chn->napi_tx);
+	}
+}
+
+static void prueth_xmit_free(struct prueth_tx_chn *tx_chn,
+			     struct cppi5_host_desc_t *desc)
+{
+	struct cppi5_host_desc_t *first_desc, *next_desc;
+	dma_addr_t buf_dma, next_desc_dma;
+	struct prueth_swdata *swdata;
+	u32 buf_dma_len;
+
+	first_desc = desc;
+	next_desc = first_desc;
+
+	swdata = cppi5_hdesc_get_swdata(desc);
+	if (swdata->type == PRUETH_SWDATA_PAGE) {
+		page_pool_recycle_direct(swdata->rx_chn->pg_pool,
+					 swdata->data.page);
+		goto free_desc;
+	}
+
+	cppi5_hdesc_get_obuf(first_desc, &buf_dma, &buf_dma_len);
+	k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &buf_dma);
+
+	dma_unmap_single(tx_chn->dma_dev, buf_dma, buf_dma_len,
+			 DMA_TO_DEVICE);
+
+	next_desc_dma = cppi5_hdesc_get_next_hbdesc(first_desc);
+	k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &next_desc_dma);
+	while (next_desc_dma) {
+		next_desc = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool,
+						       next_desc_dma);
+		cppi5_hdesc_get_obuf(next_desc, &buf_dma, &buf_dma_len);
+		k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &buf_dma);
+
+		dma_unmap_page(tx_chn->dma_dev, buf_dma, buf_dma_len,
+			       DMA_TO_DEVICE);
+
+		next_desc_dma = cppi5_hdesc_get_next_hbdesc(next_desc);
+		k3_udma_glue_tx_cppi5_to_dma_addr(tx_chn->tx_chn, &next_desc_dma);
+
+		k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc);
+	}
+
+free_desc:
+	k3_cppi_desc_pool_free(tx_chn->desc_pool, first_desc);
+}
+
+static int emac_tx_complete_packets(struct prueth_emac *emac, int chn,
+				    int budget, bool *tdown)
+{
+	struct net_device *ndev = emac->ndev;
+	struct cppi5_host_desc_t *desc_tx;
+	struct netdev_queue *netif_txq;
+	struct prueth_tx_chn *tx_chn;
+	unsigned int total_bytes = 0;
+	struct prueth_swdata *swdata;
+	struct xdp_frame *xdpf;
+	struct sk_buff *skb;
+	dma_addr_t desc_dma;
+	int res, num_tx = 0;
+
+	tx_chn = &emac->tx_chns[chn];
+
+	while (budget) {
+		res = k3_udma_glue_pop_tx_chn(tx_chn->tx_chn, &desc_dma);
+		if (res == -ENODATA)
+			break;
+
+		/* teardown completion */
+		if (cppi5_desc_is_tdcm(desc_dma)) {
+			if (atomic_dec_and_test(&emac->tdown_cnt))
+				complete(&emac->tdown_complete);
+			*tdown = true;
+			break;
+		}
+
+		desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool,
+						     desc_dma);
+		swdata = cppi5_hdesc_get_swdata(desc_tx);
+
+		switch (swdata->type) {
+		case PRUETH_SWDATA_SKB:
+			skb = swdata->data.skb;
+			ndev->stats.tx_bytes += skb->len;
+			ndev->stats.tx_packets++;
+			total_bytes += skb->len;
+			napi_consume_skb(skb, budget);
+			break;
+		case PRUETH_SWDATA_XDPF:
+			xdpf = swdata->data.xdpf;
+			ndev->stats.tx_bytes += xdpf->len;
+			ndev->stats.tx_packets++;
+			total_bytes += xdpf->len;
+			xdp_return_frame(xdpf);
+			break;
+		default:
+			netdev_err(ndev, "tx_complete: invalid swdata type %d\n", swdata->type);
+			prueth_xmit_free(tx_chn, desc_tx);
+			budget++;
+			continue;
+		}
+
+		prueth_xmit_free(tx_chn, desc_tx);
+		num_tx++;
+		budget--;
+	}
+
+	if (!num_tx)
+		return 0;
+
+	netif_txq = netdev_get_tx_queue(ndev, chn);
+	netdev_tx_completed_queue(netif_txq, num_tx, total_bytes);
+
+	if (netif_tx_queue_stopped(netif_txq)) {
+		/* If the TX queue was stopped, wake it now
+		 * if we have enough room.
+		 */
+		__netif_tx_lock(netif_txq, smp_processor_id());
+		if (netif_running(ndev) &&
+		    (k3_cppi_desc_pool_avail(tx_chn->desc_pool) >=
+		     MAX_SKB_FRAGS))
+			netif_tx_wake_queue(netif_txq);
+		__netif_tx_unlock(netif_txq);
+	}
+
+	return num_tx;
+}
+
+static enum hrtimer_restart emac_tx_timer_callback(struct hrtimer *timer)
+{
+	struct prueth_tx_chn *tx_chns =
+			container_of(timer, struct prueth_tx_chn, tx_hrtimer);
+
+	enable_irq(tx_chns->irq);
+	return HRTIMER_NORESTART;
+}
+
+static int emac_napi_tx_poll(struct napi_struct *napi_tx, int budget)
+{
+	struct prueth_tx_chn *tx_chn = prueth_napi_to_tx_chn(napi_tx);
+	struct prueth_emac *emac = tx_chn->emac;
+	bool tdown = false;
+	int num_tx_packets;
+
+	num_tx_packets = emac_tx_complete_packets(emac, tx_chn->id, budget, &tdown);
+
+	if (num_tx_packets < budget) {
+		napi_complete(napi_tx);
+		if (unlikely(tx_chn->tx_pace_timeout_ns && !tdown)) {
+			hrtimer_start(&tx_chn->tx_hrtimer,
+				      ns_to_ktime(tx_chn->tx_pace_timeout_ns),
+				      HRTIMER_MODE_REL_PINNED);
+		} else {
+			enable_irq(tx_chn->irq);
+		}
+	}
+
+	return num_tx_packets;
+}
+
+static irqreturn_t prueth_tx_irq(int irq, void *dev_id)
+{
+	struct prueth_tx_chn *tx_chn = dev_id;
+
+	disable_irq_nosync(irq);
+	napi_schedule(&tx_chn->napi_tx);
+
+	return IRQ_HANDLED;
+}
+
+static int prueth_ndev_add_tx_napi(struct prueth_emac *emac)
+{
+	struct prueth *prueth = emac->prueth;
+	int i, ret;
+
+	for (i = 0; i < emac->tx_ch_num; i++) {
+		struct prueth_tx_chn *tx_chn = &emac->tx_chns[i];
+
+		netif_napi_add_tx_weight(emac->ndev, &tx_chn->napi_tx,
+					 emac_napi_tx_poll, NAPI_POLL_WEIGHT);
+		hrtimer_init(&tx_chn->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
+		tx_chn->tx_hrtimer.function = &emac_tx_timer_callback;
+
+		ret = request_irq(tx_chn->irq, prueth_tx_irq,
+				  IRQF_TRIGGER_HIGH, tx_chn->name,
+				  tx_chn);
+		if (ret) {
+			netif_napi_del(&tx_chn->napi_tx);
+			dev_err(prueth->dev, "unable to request TX IRQ %d\n",
+				tx_chn->irq);
+			goto fail;
+		}
+	}
+
+	return 0;
+fail:
+	prueth_ndev_del_tx_napi(emac, i);
+	return ret;
+}
+
+static int prueth_init_tx_chns(struct prueth_emac *emac)
+{
+	static const struct k3_ring_cfg ring_cfg = {
+		.elm_size = K3_RINGACC_RING_ELSIZE_8,
+		.mode = K3_RINGACC_RING_MODE_RING,
+		.flags = 0,
+		.size = PRUETH_MAX_TX_DESC,
+	};
+	struct k3_udma_glue_tx_channel_cfg tx_cfg;
+	struct device *dev = emac->prueth->dev;
+	struct net_device *ndev = emac->ndev;
+	int ret, slice, i;
+	u32 hdesc_size;
+
+	slice = prueth_emac_slice(emac);
+	if (slice < 0)
+		return slice;
+
+	init_completion(&emac->tdown_complete);
+
+	hdesc_size = cppi5_hdesc_calc_size(true, PRUETH_NAV_PS_DATA_SIZE,
+					   PRUETH_NAV_SW_DATA_SIZE);
+	memset(&tx_cfg, 0, sizeof(tx_cfg));
+	tx_cfg.swdata_size = PRUETH_NAV_SW_DATA_SIZE;
+	tx_cfg.tx_cfg = ring_cfg;
+	tx_cfg.txcq_cfg = ring_cfg;
+
+	for (i = 0; i < emac->tx_ch_num; i++) {
+		struct prueth_tx_chn *tx_chn = &emac->tx_chns[i];
+
+		/* To differentiate channels for SLICE0 vs SLICE1 */
+		snprintf(tx_chn->name, sizeof(tx_chn->name),
+			 "tx%d-%d", slice, i);
+
+		tx_chn->emac = emac;
+		tx_chn->id = i;
+		tx_chn->descs_num = PRUETH_MAX_TX_DESC;
+
+		tx_chn->tx_chn =
+			k3_udma_glue_request_tx_chn(dev, tx_chn->name,
+						    &tx_cfg);
+		if (IS_ERR(tx_chn->tx_chn)) {
+			ret = PTR_ERR(tx_chn->tx_chn);
+			tx_chn->tx_chn = NULL;
+			netdev_err(ndev,
+				   "Failed to request tx dma ch: %d\n", ret);
+			goto fail;
+		}
+
+		tx_chn->dma_dev = k3_udma_glue_tx_get_dma_device(tx_chn->tx_chn);
+		tx_chn->desc_pool =
+			k3_cppi_desc_pool_create_name(tx_chn->dma_dev,
+						      tx_chn->descs_num,
+						      hdesc_size,
+						      tx_chn->name);
+		if (IS_ERR(tx_chn->desc_pool)) {
+			ret = PTR_ERR(tx_chn->desc_pool);
+			tx_chn->desc_pool = NULL;
+			netdev_err(ndev, "Failed to create tx pool: %d\n", ret);
+			goto fail;
+		}
+
+		tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn);
+		if (tx_chn->irq <= 0) {
+			ret = -EINVAL;
+			netdev_err(ndev, "failed to get tx irq\n");
+			goto fail;
+		}
+
+		snprintf(tx_chn->name, sizeof(tx_chn->name), "%s-tx%d",
+			 dev_name(dev), tx_chn->id);
+	}
+
+	return 0;
+
+fail:
+	prueth_cleanup_tx_chns(emac);
+	return ret;
+}
+
+static int prueth_init_rx_chns(struct prueth_emac *emac,
+			       struct prueth_rx_chn *rx_chn,
+			       char *name, u32 max_rflows,
+			       u32 max_desc_num)
+{
+	struct k3_udma_glue_rx_channel_cfg rx_cfg;
+	struct device *dev = emac->prueth->dev;
+	struct net_device *ndev = emac->ndev;
+	u32 fdqring_id, hdesc_size;
+	int i, ret = 0, slice;
+
+	slice = prueth_emac_slice(emac);
+	if (slice < 0)
+		return slice;
+
+	/* To differentiate channels for SLICE0 vs SLICE1 */
+	snprintf(rx_chn->name, sizeof(rx_chn->name), "%s%d", name, slice);
+
+	hdesc_size = cppi5_hdesc_calc_size(true, PRUETH_NAV_PS_DATA_SIZE,
+					   PRUETH_NAV_SW_DATA_SIZE);
+	memset(&rx_cfg, 0, sizeof(rx_cfg));
+	rx_cfg.swdata_size = PRUETH_NAV_SW_DATA_SIZE;
+	rx_cfg.flow_id_num = max_rflows;
+	rx_cfg.flow_id_base = -1; /* udmax will auto select flow id base */
+
+	/* init all flows */
+	rx_chn->dev = dev;
+	rx_chn->descs_num = max_desc_num;
+
+	rx_chn->rx_chn = k3_udma_glue_request_rx_chn(dev, rx_chn->name,
+						     &rx_cfg);
+	if (IS_ERR(rx_chn->rx_chn)) {
+		ret = PTR_ERR(rx_chn->rx_chn);
+		rx_chn->rx_chn = NULL;
+		netdev_err(ndev, "Failed to request rx dma ch: %d\n", ret);
+		goto fail;
+	}
+
+	rx_chn->dma_dev = k3_udma_glue_rx_get_dma_device(rx_chn->rx_chn);
+	rx_chn->desc_pool = k3_cppi_desc_pool_create_name(rx_chn->dma_dev,
+							  rx_chn->descs_num,
+							  hdesc_size,
+							  rx_chn->name);
+	if (IS_ERR(rx_chn->desc_pool)) {
+		ret = PTR_ERR(rx_chn->desc_pool);
+		rx_chn->desc_pool = NULL;
+		netdev_err(ndev, "Failed to create rx pool: %d\n", ret);
+		goto fail;
+	}
+
+	emac->rx_flow_id_base = k3_udma_glue_rx_get_flow_id_base(rx_chn->rx_chn);
+	netdev_dbg(ndev, "flow id base = %d\n", emac->rx_flow_id_base);
+
+	fdqring_id = K3_RINGACC_RING_ID_ANY;
+	for (i = 0; i < rx_cfg.flow_id_num; i++) {
+		struct k3_ring_cfg rxring_cfg = {
+			.elm_size = K3_RINGACC_RING_ELSIZE_8,
+			.mode = K3_RINGACC_RING_MODE_RING,
+			.flags = 0,
+		};
+		struct k3_ring_cfg fdqring_cfg = {
+			.elm_size = K3_RINGACC_RING_ELSIZE_8,
+			.flags = K3_RINGACC_RING_SHARED,
+		};
+		struct k3_udma_glue_rx_flow_cfg rx_flow_cfg = {
+			.rx_cfg = rxring_cfg,
+			.rxfdq_cfg = fdqring_cfg,
+			.ring_rxq_id = K3_RINGACC_RING_ID_ANY,
+			.src_tag_lo_sel =
+				K3_UDMA_GLUE_SRC_TAG_LO_USE_REMOTE_SRC_TAG,
+		};
+
+		rx_flow_cfg.ring_rxfdq0_id = fdqring_id;
+		rx_flow_cfg.rx_cfg.size = max_desc_num;
+		rx_flow_cfg.rxfdq_cfg.size = max_desc_num;
+		rx_flow_cfg.rxfdq_cfg.mode = emac->prueth->pdata.fdqring_mode;
+
+		ret = k3_udma_glue_rx_flow_init(rx_chn->rx_chn,
+						i, &rx_flow_cfg);
+		if (ret) {
+			netdev_err(ndev, "Failed to init rx flow%d %d\n",
+				   i, ret);
+			goto fail;
+		}
+		if (!i)
+			fdqring_id = k3_udma_glue_rx_flow_get_fdq_id(rx_chn->rx_chn,
+								     i);
+		rx_chn->irq[i] = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, i);
+		if (rx_chn->irq[i] <= 0) {
+			ret = rx_chn->irq[i];
+			netdev_err(ndev, "Failed to get rx dma irq");
+			goto fail;
+		}
+	}
+
+	return 0;
+
+fail:
+	prueth_cleanup_rx_chns(emac, rx_chn, max_rflows);
+	return ret;
+}
+
+static int prueth_dma_rx_push_mapped(struct prueth_emac *emac,
+				     struct prueth_rx_chn *rx_chn,
+				     struct page *page, u32 buf_len)
+{
+	struct net_device *ndev = emac->ndev;
+	struct cppi5_host_desc_t *desc_rx;
+	struct prueth_swdata *swdata;
+	dma_addr_t desc_dma;
+	dma_addr_t buf_dma;
+
+	buf_dma = page_pool_get_dma_addr(page) + PRUETH_HEADROOM;
+	desc_rx = k3_cppi_desc_pool_alloc(rx_chn->desc_pool);
+	if (!desc_rx) {
+		netdev_err(ndev, "rx push: failed to allocate descriptor\n");
+		return -ENOMEM;
+	}
+	desc_dma = k3_cppi_desc_pool_virt2dma(rx_chn->desc_pool, desc_rx);
+
+	cppi5_hdesc_init(desc_rx, CPPI5_INFO0_HDESC_EPIB_PRESENT,
+			 PRUETH_NAV_PS_DATA_SIZE);
+	k3_udma_glue_rx_dma_to_cppi5_addr(rx_chn->rx_chn, &buf_dma);
+	cppi5_hdesc_attach_buf(desc_rx, buf_dma, buf_len, buf_dma, buf_len);
+
+	swdata = cppi5_hdesc_get_swdata(desc_rx);
+	swdata->type = PRUETH_SWDATA_PAGE;
+	swdata->data.page = page;
+	swdata->rx_chn = rx_chn;
+
+	return k3_udma_glue_push_rx_chn(rx_chn->rx_chn, 0,
+					desc_rx, desc_dma);
+}
+
+static u64 icssg_ts_to_ns(u32 hi_sw, u32 hi, u32 lo, u32 cycle_time_ns)
+{
+	u32 iepcount_lo, iepcount_hi, hi_rollover_count;
+	u64 ns;
+
+	iepcount_lo = lo & GENMASK(19, 0);
+	iepcount_hi = (hi & GENMASK(11, 0)) << 12 | lo >> 20;
+	hi_rollover_count = hi >> 11;
+
+	ns = ((u64)hi_rollover_count) << 23 | (iepcount_hi + hi_sw);
+	ns = ns * cycle_time_ns + iepcount_lo;
+
+	return ns;
+}
+
+static void emac_rx_timestamp(struct prueth_emac *emac,
+			      struct sk_buff *skb, u32 *psdata)
+{
+	struct skb_shared_hwtstamps *ssh;
+	u64 ns;
+
+	u32 hi_sw = readl(emac->prueth->shram.va +
+			  TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET);
+	ns = icssg_ts_to_ns(hi_sw, psdata[1], psdata[0],
+			    IEP_DEFAULT_CYCLE_TIME_NS);
+
+	ssh = skb_hwtstamps(skb);
+	memset(ssh, 0, sizeof(*ssh));
+	ssh->hwtstamp = ns_to_ktime(ns);
+}
+
+static unsigned int prueth_rxbuf_total_len(unsigned int len)
+{
+	len += PRUETH_HEADROOM;
+	len += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+
+	return SKB_DATA_ALIGN(len);
+}
+
+static int emac_run_xdp(struct prueth_emac *emac, struct xdp_buff *xdp,
+			struct page *page);
+
+static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id, int *xdp_state)
+{
+	struct prueth_rx_chn *rx_chn = &emac->rx_chns;
+	u32 buf_dma_len, pkt_len, port_id = 0;
+	struct net_device *ndev = emac->ndev;
+	struct cppi5_host_desc_t *desc_rx;
+	dma_addr_t desc_dma, buf_dma;
+	struct prueth_swdata *swdata;
+	struct page *page, *new_page;
+	struct page_pool *pool;
+	struct sk_buff *skb;
+	struct xdp_buff xdp;
+	u32 *psdata;
+	void *pa;
+	int ret;
+
+	*xdp_state = 0;
+	pool = rx_chn->pg_pool;
+	ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_id, &desc_dma);
+	if (ret) {
+		if (ret != -ENODATA)
+			netdev_err(ndev, "rx pop: failed: %d\n", ret);
+		return ret;
+	}
+
+	if (cppi5_desc_is_tdcm(desc_dma)) /* Teardown ? */
+		return 0;
+
+	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
+
+	swdata = cppi5_hdesc_get_swdata(desc_rx);
+	if (swdata->type != PRUETH_SWDATA_PAGE) {
+		netdev_err(ndev, "rx_pkt: invliad swdata->type %d\n", swdata->type);
+		return 0;
+	}
+	page = swdata->data.page;
+
+	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
+	k3_udma_glue_rx_cppi5_to_dma_addr(rx_chn->rx_chn, &buf_dma);
+	pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
+	/* firmware adds 4 CRC bytes, strip them */
+	pkt_len -= 4;
+	cppi5_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL);
+
+	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
+
+	if (!netif_running(ndev)) {
+		page_pool_recycle_direct(pool, page);
+		return 0;
+	}
+
+	/* if allocation fails we drop the packet but push the
+	 * descriptor back to the ring with old page to prevent a stall
+	 */
+	new_page = page_pool_dev_alloc_pages(pool);
+	if (unlikely(!new_page)) {
+		new_page = page;
+		ndev->stats.rx_dropped++;
+		goto requeue;
+	}
+
+	pa = page_address(page);
+	if (emac->xdp_prog) {
+		/* xdp_init_buff(&xdp, PAGE_SIZE, rx_chn->xdp_rxq); */
+		xdp.frame_sz = PAGE_SIZE;
+		xdp.rxq = &rx_chn->xdp_rxq;
+
+		/* xdp_prepare_buff(&xdp, pa, PRUETH_HEADROOM, pkt_len, false); */
+		xdp.data_hard_start = pa;
+		xdp.data = pa + PRUETH_HEADROOM;
+		xdp.data_end = xdp.data + pkt_len;
+		xdp.data_meta = xdp.data + 1;
+
+		*xdp_state = emac_run_xdp(emac, &xdp, page);
+		if (*xdp_state != ICSSG_XDP_PASS)
+			goto requeue;
+	}
+
+	/* prepare skb and send to n/w stack */
+	skb = build_skb(pa, prueth_rxbuf_total_len(pkt_len));
+	if (!skb) {
+		ndev->stats.rx_dropped++;
+		page_pool_recycle_direct(pool, page);
+		goto requeue;
+	}
+
+	skb_reserve(skb, PRUETH_HEADROOM);
+	skb_put(skb, pkt_len);
+	skb->dev = ndev;
+
+	psdata = cppi5_hdesc_get_psdata(desc_rx);
+	/* RX HW timestamp */
+	if (emac->rx_ts_enabled)
+		emac_rx_timestamp(emac, skb, psdata);
+
+	if (emac->prueth->is_switch_mode)
+		skb->offload_fwd_mark = emac->offload_fwd_mark;
+	skb->protocol = eth_type_trans(skb, ndev);
+
+	/* unmap page as no recycling of netstack skb page */
+	page_pool_release_page(pool, page);
+	netif_receive_skb(skb);
+	ndev->stats.rx_bytes += pkt_len;
+	ndev->stats.rx_packets++;
+
+requeue:
+	/* queue another RX DMA */
+	ret = prueth_dma_rx_push_mapped(emac, &emac->rx_chns, new_page,
+					PRUETH_MAX_PKT_SIZE);
+	if (WARN_ON(ret < 0)) {
+		page_pool_recycle_direct(pool, new_page);
+		ndev->stats.rx_errors++;
+		ndev->stats.rx_dropped++;
+	}
+
+	return ret;
+}
+
+static void prueth_rx_cleanup(void *data, dma_addr_t desc_dma)
+{
+	struct prueth_rx_chn *rx_chn = data;
+	struct cppi5_host_desc_t *desc_rx;
+	struct prueth_swdata *swdata;
+	struct page_pool *pool;
+	struct page *page;
+
+	pool = rx_chn->pg_pool;
+
+	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
+	swdata = cppi5_hdesc_get_swdata(desc_rx);
+	if (swdata->type == PRUETH_SWDATA_PAGE) {
+		page = swdata->data.page;
+		page_pool_recycle_direct(pool, page);
+	}
+	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
+}
+
+static int emac_get_tx_ts(struct prueth_emac *emac,
+			  struct emac_tx_ts_response *rsp)
+{
+	struct prueth *prueth = emac->prueth;
+	int slice = prueth_emac_slice(emac);
+	int addr;
+
+	addr = icssg_queue_pop(prueth, slice == 0 ?
+			       ICSSG_TS_POP_SLICE0 : ICSSG_TS_POP_SLICE1);
+	if (addr < 0)
+		return addr;
+
+	memcpy_fromio(rsp, prueth->shram.va + addr, sizeof(*rsp));
+	/* return buffer back for to pool */
+	icssg_queue_push(prueth, slice == 0 ?
+			 ICSSG_TS_PUSH_SLICE0 : ICSSG_TS_PUSH_SLICE1, addr);
+
+	return 0;
+}
+
+static void tx_ts_work(struct prueth_emac *emac)
+{
+	u64 ns;
+	struct skb_shared_hwtstamps ssh;
+	struct sk_buff *skb;
+	int ret = 0;
+	struct emac_tx_ts_response tsr;
+	u32 hi_sw;
+
+	/* There may be more than one pending requests */
+	while (1) {
+		ret = emac_get_tx_ts(emac, &tsr);
+		if (ret)	/* nothing more */
+			break;
+
+		if (tsr.cookie >= PRUETH_MAX_TX_TS_REQUESTS ||
+		    !emac->tx_ts_skb[tsr.cookie]) {
+			netdev_err(emac->ndev, "Invalid TX TS cookie 0x%x\n",
+				   tsr.cookie);
+			break;
+		}
+
+		skb = emac->tx_ts_skb[tsr.cookie];
+		emac->tx_ts_skb[tsr.cookie] = NULL;	/* free slot */
+		if (!skb) {
+			netdev_err(emac->ndev, "Driver Bug! got NULL skb\n");
+			break;
+		}
+
+		hi_sw = readl(emac->prueth->shram.va +
+			      TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET);
+		ns = icssg_ts_to_ns(hi_sw, tsr.hi_ts, tsr.lo_ts,
+				    IEP_DEFAULT_CYCLE_TIME_NS);
+		memset(&ssh, 0, sizeof(ssh));
+		ssh.hwtstamp = ns_to_ktime(ns);
+
+		skb_tstamp_tx(skb, &ssh);
+		dev_consume_skb_any(skb);
+
+		if (atomic_dec_and_test(&emac->tx_ts_pending))	/* no more? */
+			break;
+	}
+
+	return;
+}
+
+int prueth_tx_ts_cookie_get(struct prueth_emac *emac)
+{
+	int i;
+
+	/* search and get the next free slot */
+	for (i = 0; i < PRUETH_MAX_TX_TS_REQUESTS; i++) {
+		if (!emac->tx_ts_skb[i]) {
+			emac->tx_ts_skb[i] = ERR_PTR(-EBUSY); /* reserve slot */
+			return i;
+		}
+	}
+
+	return -EBUSY;
+}
+
+/**
+ * emac_ndo_start_xmit - EMAC Transmit function
+ * @skb: SKB pointer
+ * @ndev: EMAC network adapter
+ *
+ * Called by the system to transmit a packet  - we queue the packet in
+ * EMAC hardware transmit queue
+ * Doesn't wait for completion we'll check for TX completion in
+ * emac_tx_complete_packets().
+ *
+ * Returns enum netdev_tx
+ */
+static enum netdev_tx emac_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct cppi5_host_desc_t *first_desc, *next_desc, *cur_desc;
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth *prueth = emac->prueth;
+	struct netdev_queue *netif_txq;
+	struct prueth_tx_chn *tx_chn;
+	dma_addr_t desc_dma, buf_dma;
+	struct prueth_swdata *swdata;
+	u32 pkt_len, dst_tag_id;
+	int i, ret = 0, q_idx;
+	bool in_tx_ts = 0;
+	int tx_ts_cookie;
+	u32 *epib;
+
+	pkt_len = skb_headlen(skb);
+	q_idx = skb_get_queue_mapping(skb);
+
+	tx_chn = &emac->tx_chns[q_idx];
+	netif_txq = netdev_get_tx_queue(ndev, q_idx);
+
+	/* Map the linear buffer */
+	buf_dma = dma_map_single(tx_chn->dma_dev, skb->data, pkt_len, DMA_TO_DEVICE);
+	if (dma_mapping_error(tx_chn->dma_dev, buf_dma)) {
+		netdev_err(ndev, "tx: failed to map skb buffer\n");
+		ret = NETDEV_TX_BUSY;
+		goto drop_stop_q;
+	}
+
+	first_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
+	if (!first_desc) {
+		netdev_dbg(ndev, "tx: failed to allocate descriptor\n");
+		dma_unmap_single(tx_chn->dma_dev, buf_dma, pkt_len, DMA_TO_DEVICE);
+		ret = NETDEV_TX_BUSY;
+		goto drop_stop_q_busy;
+	}
+
+	cppi5_hdesc_init(first_desc, CPPI5_INFO0_HDESC_EPIB_PRESENT,
+			 PRUETH_NAV_PS_DATA_SIZE);
+	cppi5_hdesc_set_pkttype(first_desc, 0);
+	epib = first_desc->epib;
+	epib[0] = 0;
+	epib[1] = 0;
+	if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
+	    emac->tx_ts_enabled) {
+		tx_ts_cookie = prueth_tx_ts_cookie_get(emac);
+		if (tx_ts_cookie >= 0) {
+			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+			/* Request TX timestamp */
+			epib[0] = (u32)tx_ts_cookie;
+			epib[1] = 0x80000000;	/* TX TS request */
+			emac->tx_ts_skb[tx_ts_cookie] = skb_get(skb);
+			in_tx_ts = 1;
+		}
+	}
+
+	/* set dst tag to indicate internal qid at the firmware which is at
+	 * bit8..bit15. bit0..bit7 indicates port num for directed
+	 * packets in case of switch mode operation and port num 0
+	 * for undirected packets in case of HSR offload mode
+	 */
+	dst_tag_id = emac->port_id | (q_idx << 8);
+
+	if (prueth->is_hsr_offload_mode && (ndev->features & NETIF_F_HW_HSR_DUP))
+		dst_tag_id = PRUETH_UNDIRECTED_PKT_DST_TAG;
+
+	cppi5_desc_set_tags_ids(&first_desc->hdr, 0, dst_tag_id);
+	k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma);
+	cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len);
+	swdata = cppi5_hdesc_get_swdata(first_desc);
+	swdata->type = PRUETH_SWDATA_SKB;
+	swdata->data.skb = skb;
+
+	if (!skb_is_nonlinear(skb))
+		goto tx_push;
+
+	/* Handle the case where skb is fragmented in pages */
+	cur_desc = first_desc;
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+		u32 frag_size = skb_frag_size(frag);
+
+		next_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
+		if (!next_desc) {
+			netdev_err(ndev,
+				   "tx: failed to allocate frag. descriptor\n");
+			ret = NETDEV_TX_BUSY;
+			goto cleanup_tx_ts;
+		}
+
+		buf_dma = skb_frag_dma_map(tx_chn->dma_dev, frag, 0, frag_size,
+					   DMA_TO_DEVICE);
+		if (dma_mapping_error(tx_chn->dma_dev, buf_dma)) {
+			netdev_err(ndev, "tx: Failed to map skb page\n");
+			k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc);
+			ret = NETDEV_TX_BUSY;
+			goto cleanup_tx_ts;
+		}
+
+		cppi5_hdesc_reset_hbdesc(next_desc);
+		k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma);
+		cppi5_hdesc_attach_buf(next_desc,
+				       buf_dma, frag_size, buf_dma, frag_size);
+
+		desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool,
+						      next_desc);
+		k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &desc_dma);
+		cppi5_hdesc_link_hbdesc(cur_desc, desc_dma);
+
+		pkt_len += frag_size;
+		cur_desc = next_desc;
+	}
+	WARN_ON(pkt_len != skb->len);
+
+tx_push:
+	/* report bql before sending packet */
+	netdev_tx_sent_queue(netif_txq, pkt_len);
+
+	cppi5_hdesc_set_pktlen(first_desc, pkt_len);
+	desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, first_desc);
+	/* cppi5_desc_dump(first_desc, 64); */
+
+	skb_tx_timestamp(skb);	/* SW timestamp if SKBTX_IN_PROGRESS not set */
+	ret = k3_udma_glue_push_tx_chn(tx_chn->tx_chn, first_desc, desc_dma);
+	if (ret) {
+		netdev_err(ndev, "tx: push failed: %d\n", ret);
+		goto drop_free_descs;
+	}
+
+	if (in_tx_ts)
+		atomic_inc(&emac->tx_ts_pending);
+
+	if (k3_cppi_desc_pool_avail(tx_chn->desc_pool) < MAX_SKB_FRAGS) {
+		netif_tx_stop_queue(netif_txq);
+		/* Barrier, so that stop_queue visible to other cpus */
+		smp_mb__after_atomic();
+
+		if (k3_cppi_desc_pool_avail(tx_chn->desc_pool) >=
+		    MAX_SKB_FRAGS)
+			netif_tx_wake_queue(netif_txq);
+	}
+
+	return NETDEV_TX_OK;
+
+cleanup_tx_ts:
+	if (in_tx_ts) {
+		dev_kfree_skb_any(emac->tx_ts_skb[tx_ts_cookie]);
+		emac->tx_ts_skb[tx_ts_cookie] = NULL;
+	}
+
+drop_free_descs:
+	prueth_xmit_free(tx_chn, first_desc);
+drop_stop_q:
+	netif_tx_stop_queue(netif_txq);
+	dev_kfree_skb_any(skb);
+
+	/* error */
+	ndev->stats.tx_dropped++;
+	netdev_err(ndev, "tx: error: %d\n", ret);
+
+	return ret;
+
+drop_stop_q_busy:
+	netif_tx_stop_queue(netif_txq);
+	return NETDEV_TX_BUSY;
+}
+
+static void prueth_tx_cleanup(void *data, dma_addr_t desc_dma)
+{
+	struct prueth_tx_chn *tx_chn = data;
+	struct cppi5_host_desc_t *desc_tx;
+	struct prueth_swdata *swdata;
+	struct xdp_frame *xdpf;
+	struct sk_buff *skb;
+
+	desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma);
+	swdata = cppi5_hdesc_get_swdata(desc_tx);
+
+	switch (swdata->type) {
+	case PRUETH_SWDATA_SKB:
+		skb = swdata->data.skb;
+		dev_kfree_skb_any(skb);
+		break;
+	case PRUETH_SWDATA_XDPF:
+		xdpf = swdata->data.xdpf;
+		xdp_return_frame(xdpf);
+		break;
+	default:
+		break;
+	}
+
+	prueth_xmit_free(tx_chn, desc_tx);
+}
+
+static irqreturn_t prueth_tx_ts_irq(int irq, void *dev_id)
+{
+	struct prueth_emac *emac = dev_id;
+
+	/* currently only TX timestamp is being returned */
+	tx_ts_work(emac);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t prueth_rx_irq(int irq, void *dev_id)
+{
+	struct prueth_emac *emac = dev_id;
+
+	disable_irq_nosync(irq);
+	napi_schedule(&emac->napi_rx);
+
+	return IRQ_HANDLED;
+}
+
+struct icssg_firmwares {
+	char *pru;
+	char *rtu;
+	char *txpru;
+};
+
+static struct icssg_firmwares icssg_hsr_firmwares[] = {
+	{
+		.pru = "ti-pruss/am65x-sr2-pru0-pruhsr-fw.elf",
+		.rtu = "ti-pruss/am65x-sr2-rtu0-pruhsr-fw.elf",
+		.txpru = "ti-pruss/am65x-sr2-txpru0-pruhsr-fw.elf",
+	},
+	{
+		.pru = "ti-pruss/am65x-sr2-pru1-pruhsr-fw.elf",
+		.rtu = "ti-pruss/am65x-sr2-rtu1-pruhsr-fw.elf",
+		.txpru = "ti-pruss/am65x-sr2-txpru1-pruhsr-fw.elf",
+	}
+};
+
+static struct icssg_firmwares icssg_switch_firmwares[] = {
+	{
+		.pru = "ti-pruss/am65x-sr2-pru0-prusw-fw.elf",
+		.rtu = "ti-pruss/am65x-sr2-rtu0-prusw-fw.elf",
+		.txpru = "ti-pruss/am65x-sr2-txpru0-prusw-fw.elf",
+	},
+	{
+		.pru = "ti-pruss/am65x-sr2-pru1-prusw-fw.elf",
+		.rtu = "ti-pruss/am65x-sr2-rtu1-prusw-fw.elf",
+		.txpru = "ti-pruss/am65x-sr2-txpru1-prusw-fw.elf",
+	}
+};
+
+static struct icssg_firmwares icssg_emac_firmwares[] = {
+	{
+		.pru = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf",
+		.rtu = "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf",
+		.txpru = "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf",
+	},
+	{
+		.pru = "ti-pruss/am65x-sr2-pru1-prueth-fw.elf",
+		.rtu = "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf",
+		.txpru = "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf",
+	}
+};
+
+static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac)
+{
+	struct icssg_firmwares *firmwares;
+	struct device *dev = prueth->dev;
+	int slice, ret;
+
+	if (prueth->is_switch_mode)
+		firmwares = icssg_switch_firmwares;
+	else if (prueth->is_hsr_offload_mode)
+		firmwares = icssg_hsr_firmwares;
+	else
+		firmwares = icssg_emac_firmwares;
+
+	slice = prueth_emac_slice(emac);
+	if (slice < 0) {
+		netdev_err(emac->ndev, "invalid port\n");
+		return -EINVAL;
+	}
+
+	ret = icssg_config(prueth, emac, slice);
+	if (ret)
+		return ret;
+
+	ret = rproc_set_firmware(prueth->pru[slice], firmwares[slice].pru);
+	ret = rproc_boot(prueth->pru[slice]);
+	if (ret) {
+		dev_err(dev, "failed to boot PRU%d: %d\n", slice, ret);
+		return -EINVAL;
+	}
+
+	ret = rproc_set_firmware(prueth->rtu[slice], firmwares[slice].rtu);
+	ret = rproc_boot(prueth->rtu[slice]);
+	if (ret) {
+		dev_err(dev, "failed to boot RTU%d: %d\n", slice, ret);
+		goto halt_pru;
+	}
+
+	ret = rproc_set_firmware(prueth->txpru[slice], firmwares[slice].txpru);
+	ret = rproc_boot(prueth->txpru[slice]);
+	if (ret) {
+		dev_err(dev, "failed to boot TX_PRU%d: %d\n", slice, ret);
+		goto halt_rtu;
+	}
+
+	emac->fw_running = 1;
+	return 0;
+
+halt_rtu:
+	rproc_shutdown(prueth->rtu[slice]);
+
+halt_pru:
+	rproc_shutdown(prueth->pru[slice]);
+
+	return ret;
+}
+
+static void prueth_emac_stop(struct prueth_emac *emac)
+{
+	struct prueth *prueth = emac->prueth;
+	int slice;
+
+	switch (emac->port_id) {
+	case PRUETH_PORT_MII0:
+		slice = ICSS_SLICE0;
+		break;
+	case PRUETH_PORT_MII1:
+		slice = ICSS_SLICE1;
+		break;
+	default:
+		netdev_err(emac->ndev, "invalid port\n");
+		return;
+	}
+
+	emac->fw_running = 0;
+	rproc_shutdown(prueth->txpru[slice]);
+	rproc_shutdown(prueth->rtu[slice]);
+	rproc_shutdown(prueth->pru[slice]);
+}
+
+static void prueth_cleanup_tx_ts(struct prueth_emac *emac)
+{
+	int i;
+
+	for (i = 0; i < PRUETH_MAX_TX_TS_REQUESTS; i++) {
+		if (emac->tx_ts_skb[i]) {
+			dev_kfree_skb_any(emac->tx_ts_skb[i]);
+			emac->tx_ts_skb[i] = NULL;
+		}
+	}
+}
+
+/* called back by PHY layer if there is change in link state of hw port*/
+static void emac_adjust_link(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct phy_device *phydev = ndev->phydev;
+	struct prueth *prueth = emac->prueth;
+	bool new_state = false;
+	unsigned long flags;
+
+	if (phydev->link) {
+		/* check the mode of operation - full/half duplex */
+		if (phydev->duplex != emac->duplex) {
+			new_state = true;
+			emac->duplex = phydev->duplex;
+		}
+		if (phydev->speed != emac->speed) {
+			new_state = true;
+			emac->speed = phydev->speed;
+		}
+		if (!emac->link) {
+			new_state = true;
+			emac->link = 1;
+		}
+	} else if (emac->link) {
+		new_state = true;
+		emac->link = 0;
+		/* defaults for no link */
+
+		/* f/w should support 100 & 1000 */
+		emac->speed = SPEED_1000;
+
+		/* half duplex may not be supported by f/w */
+		emac->duplex = DUPLEX_FULL;
+	}
+
+	if (new_state) {
+		phy_print_status(phydev);
+
+		/* update RGMII and MII configuration based on PHY negotiated
+		 * values
+		 */
+		if (emac->link) {
+			if (emac->duplex == DUPLEX_HALF)
+				icssg_config_half_duplex(emac);
+			/* Set the RGMII cfg for gig en and full duplex */
+			icssg_update_rgmii_cfg(prueth->miig_rt, emac);
+
+			/* update the Tx IPG based on 100M/1G speed */
+			spin_lock_irqsave(&emac->lock, flags);
+			icssg_config_ipg(emac);
+			spin_unlock_irqrestore(&emac->lock, flags);
+			icssg_config_set_speed(emac);
+			emac_set_port_state(emac, ICSSG_EMAC_PORT_FORWARD);
+
+		} else {
+			emac_set_port_state(emac, ICSSG_EMAC_PORT_DISABLE);
+		}
+
+		if (emac->link) {
+			icssg_qos_link_up(ndev);
+		} else {
+			icssg_qos_link_down(ndev);
+		}
+	}
+
+	if (emac->link) {
+		/* reactivate the transmit queue */
+		netif_tx_wake_all_queues(ndev);
+	} else {
+		netif_tx_stop_all_queues(ndev);
+		prueth_cleanup_tx_ts(emac);
+	}
+}
+
+static enum hrtimer_restart emac_rx_timer_callback(struct hrtimer *timer)
+{
+	struct prueth_emac *emac =
+			container_of(timer, struct prueth_emac, rx_hrtimer);
+	int rx_flow = PRUETH_RX_FLOW_DATA;
+
+	enable_irq(emac->rx_chns.irq[rx_flow]);
+	return HRTIMER_NORESTART;
+}
+
+static int emac_napi_rx_poll(struct napi_struct *napi_rx, int budget)
+{
+	struct prueth_emac *emac = prueth_napi_to_emac(napi_rx);
+	int rx_flow = PRUETH_RX_FLOW_DATA;
+	int flow = PRUETH_MAX_RX_FLOWS;
+	int num_rx = 0;
+	int cur_budget;
+	int ret;
+	int xdp_state;
+	int xdp_state_or = 0;
+
+	while (flow--) {
+		cur_budget = budget - num_rx;
+
+		while (cur_budget--) {
+			ret = emac_rx_packet(emac, flow, &xdp_state);
+			xdp_state_or |= xdp_state;
+			if (ret)
+				break;
+			num_rx++;
+		}
+
+		if (num_rx >= budget)
+			break;
+	}
+
+	if (xdp_state_or & ICSSG_XDP_REDIR)
+		xdp_do_flush();
+
+	if (num_rx < budget) {
+		napi_complete(napi_rx);
+		if (unlikely(emac->rx_pace_timeout_ns)) {
+			hrtimer_start(&emac->rx_hrtimer,
+				      ns_to_ktime(emac->rx_pace_timeout_ns),
+				      HRTIMER_MODE_REL_PINNED);
+		} else {
+			enable_irq(emac->rx_chns.irq[rx_flow]);
+		}
+	}
+
+	return num_rx;
+}
+
+static struct page_pool *prueth_create_page_pool(struct prueth_emac *emac,
+						 struct device *dma_dev,
+						 int size)
+{
+	struct page_pool_params pp_params;
+	struct page_pool *pool;
+
+	pp_params.order = 0;
+	pp_params.flags = PP_FLAG_DMA_MAP;
+	pp_params.pool_size = size;
+	pp_params.nid = NUMA_NO_NODE;
+	pp_params.dma_dir = DMA_BIDIRECTIONAL;
+	pp_params.dev = dma_dev;
+
+	pool = page_pool_create(&pp_params);
+	if (IS_ERR(pool))
+		netdev_err(emac->ndev, "cannot create rx page pool\n");
+
+	return pool;
+}
+
+static struct page *prueth_get_page_from_rx_chn(struct prueth_rx_chn *chn)
+{
+	struct cppi5_host_desc_t *desc_rx;
+	struct prueth_swdata *swdata;
+	dma_addr_t desc_dma;
+	struct page *page;
+
+	k3_udma_glue_pop_rx_chn(chn->rx_chn, 0, &desc_dma);
+	desc_rx = k3_cppi_desc_pool_dma2virt(chn->desc_pool, desc_dma);
+	swdata = cppi5_hdesc_get_swdata(desc_rx);
+	page = swdata->data.page;
+
+	return page;
+}
+
+static int prueth_prepare_rx_chan(struct prueth_emac *emac,
+				  struct prueth_rx_chn *chn,
+				  int buf_size)
+{
+	struct page_pool *pool;
+	struct page *page;
+	int i, ret, j;
+
+	pool = prueth_create_page_pool(emac, chn->dma_dev, chn->descs_num);
+	if (IS_ERR(pool))
+		return PTR_ERR(pool);
+
+	chn->pg_pool = pool;
+
+	for (i = 0; i < chn->descs_num; i++) {
+		/* NOTE: we're not using memory efficiently here.
+		 * 1 full page (4KB?) used here instead of
+		 * PRUETH_MAX_PKT_SIZE (~1.5KB?)
+		 */
+		page = page_pool_dev_alloc_pages(pool);
+		if (!page) {
+			netdev_err(emac->ndev, "couldn't allocate rx page\n");
+			ret = -ENOMEM;
+			goto recycle_alloc_pg;
+		}
+
+		ret = prueth_dma_rx_push_mapped(emac, chn, page, buf_size);
+		if (ret < 0) {
+			netdev_err(emac->ndev,
+				   "cannot submit skb for rx chan %s ret %d\n",
+				   chn->name, ret);
+			page_pool_recycle_direct(pool, page);
+			goto recycle_alloc_pg;
+		}
+	}
+
+	return 0;
+
+recycle_alloc_pg:
+	for (j = 0; j < i; j++) {
+		page = prueth_get_page_from_rx_chn(chn);
+		page_pool_recycle_direct(pool, page);
+	}
+	page_pool_destroy(pool);
+	chn->pg_pool = NULL;
+
+	return ret;
+}
+
+static void prueth_reset_tx_chan(struct prueth_emac *emac, int ch_num,
+				 bool free_skb)
+{
+	int i;
+
+	for (i = 0; i < ch_num; i++) {
+		if (free_skb)
+			k3_udma_glue_reset_tx_chn(emac->tx_chns[i].tx_chn,
+						  &emac->tx_chns[i],
+						  prueth_tx_cleanup);
+		k3_udma_glue_disable_tx_chn(emac->tx_chns[i].tx_chn);
+	}
+}
+
+static void prueth_reset_rx_chan(struct prueth_rx_chn *chn,
+				 int num_flows, bool disable)
+{
+	int i;
+
+	for (i = 0; i < num_flows; i++)
+		k3_udma_glue_reset_rx_chn(chn->rx_chn, i, chn,
+					  prueth_rx_cleanup, !!i);
+	if (disable)
+		k3_udma_glue_disable_rx_chn(chn->rx_chn);
+}
+
+static int emac_phy_connect(struct prueth_emac *emac)
+{
+	struct prueth *prueth = emac->prueth;
+	struct net_device *ndev = emac->ndev;
+	/* connect PHY */
+	ndev->phydev = of_phy_connect(emac->ndev, emac->phy_node,
+				      &emac_adjust_link, 0,
+				      emac->phy_if);
+	if (!ndev->phydev) {
+		dev_err(prueth->dev, "couldn't connect to phy %s\n",
+			emac->phy_node->full_name);
+		return -ENODEV;
+	}
+
+	if (!emac->half_duplex) {
+		dev_dbg(prueth->dev, "half duplex mode is not supported\n");
+		phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
+		phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
+	}
+
+	/* remove unsupported modes */
+	phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
+	phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_Pause_BIT);
+	phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT);
+
+	if (emac->phy_if == PHY_INTERFACE_MODE_MII)
+		phy_set_max_speed(ndev->phydev, SPEED_100);
+
+	return 0;
+}
+
+u64 prueth_iep_gettime(void *clockops_data, struct ptp_system_timestamp *sts)
+{
+	u32 hi_rollover_count, hi_rollover_count_r;
+	struct prueth_emac *emac = clockops_data;
+	struct prueth *prueth = emac->prueth;
+	void __iomem *fw_hi_r_count_addr;
+	void __iomem *fw_count_hi_addr;
+	u32 iepcount_hi, iepcount_hi_r;
+	unsigned long flags;
+	u32 iepcount_lo;
+	u64 ts = 0;
+
+	fw_count_hi_addr = prueth->shram.va + TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET;
+	fw_hi_r_count_addr = prueth->shram.va + TIMESYNC_FW_WC_HI_ROLLOVER_COUNT_OFFSET;
+
+	local_irq_save(flags);
+	do {
+		iepcount_hi = icss_iep_get_count_hi(emac->iep);
+		iepcount_hi += readl(fw_count_hi_addr);
+		hi_rollover_count = readl(fw_hi_r_count_addr);
+		ptp_read_system_prets(sts);
+		iepcount_lo = icss_iep_get_count_low(emac->iep);
+		ptp_read_system_postts(sts);
+
+		iepcount_hi_r = icss_iep_get_count_hi(emac->iep);
+		iepcount_hi_r += readl(fw_count_hi_addr);
+		hi_rollover_count_r = readl(fw_hi_r_count_addr);
+	} while ((iepcount_hi_r != iepcount_hi) ||
+		 (hi_rollover_count != hi_rollover_count_r));
+	local_irq_restore(flags);
+
+	ts = ((u64)hi_rollover_count) << 23 | iepcount_hi;
+	ts = ts * (u64)IEP_DEFAULT_CYCLE_TIME_NS + iepcount_lo;
+
+	return ts;
+}
+
+static void prueth_iep_settime(void *clockops_data, u64 ns)
+{
+	struct icssg_setclock_desc sc_desc, *sc_descp;
+	struct prueth_emac *emac = clockops_data;
+	u64 cyclecount;
+	u32 cycletime;
+	int timeout;
+
+	if (!emac->fw_running)
+		return;
+
+	sc_descp = emac->prueth->shram.va + TIMESYNC_FW_WC_SETCLOCK_DESC_OFFSET;
+
+	cycletime = IEP_DEFAULT_CYCLE_TIME_NS;
+	cyclecount = ns / cycletime;
+
+	memset(&sc_desc, 0, sizeof(sc_desc));
+	sc_desc.margin = cycletime - 1000;
+	sc_desc.cyclecounter0_set = cyclecount & GENMASK(31, 0);
+	sc_desc.cyclecounter1_set = (cyclecount & GENMASK(63, 32)) >> 32;
+	sc_desc.iepcount_set = ns % cycletime;
+	sc_desc.CMP0_current = cycletime - 4; //Count from 0 to (cycle time)-4
+
+	memcpy_toio(sc_descp, &sc_desc, sizeof(sc_desc));
+
+	writeb(1, &sc_descp->request);
+
+	timeout = 5;	/* fw should take 2-3 ms */
+	while (timeout--) {
+		if (readb(&sc_descp->acknowledgment))
+			return;
+
+		usleep_range(500, 1000);
+	}
+
+	dev_err(emac->prueth->dev, "settime timeout\n");
+}
+
+static int prueth_perout_enable(void *clockops_data,
+				struct ptp_perout_request *req, int on,
+				u64 *cmp)
+{
+	struct prueth_emac *emac = clockops_data;
+	u32 reduction_factor = 0, offset = 0;
+	struct timespec64 ts;
+	u64 ns_period;
+
+	if (!on)
+		return 0;
+
+	/* Any firmware specific stuff for PPS/PEROUT handling */
+	ts.tv_sec = req->period.sec;
+	ts.tv_nsec = req->period.nsec;
+	ns_period = timespec64_to_ns(&ts);
+
+	/* f/w doesn't support period less than cycle time */
+	if (ns_period < IEP_DEFAULT_CYCLE_TIME_NS)
+		return -ENXIO;
+
+	reduction_factor = ns_period / IEP_DEFAULT_CYCLE_TIME_NS;
+	offset = ns_period % IEP_DEFAULT_CYCLE_TIME_NS;
+
+	/* f/w requires at least 1uS within a cycle so CMP
+	 * can trigger after SYNC is enabled
+	 */
+	if (offset < 5 * NSEC_PER_USEC)
+		offset = 5 * NSEC_PER_USEC;
+
+	/* if offset is close to cycle time then we will miss
+	 * the CMP event for last tick when IEP rolls over.
+	 * In normal mode, IEP tick is 4ns.
+	 * In slow compensation it could be 0ns or 8ns at
+	 * every slow compensation cycle.
+	 */
+	if (offset > IEP_DEFAULT_CYCLE_TIME_NS - 8)
+		offset = IEP_DEFAULT_CYCLE_TIME_NS - 8;
+
+	/* we're in shadow mode so need to set upper 32-bits */
+	*cmp = (u64)offset << 32;
+
+	writel(reduction_factor, emac->prueth->shram.va +
+		TIMESYNC_FW_WC_SYNCOUT_REDUCTION_FACTOR_OFFSET);
+
+	/* HACK: till f/w supports START_TIME cyclcount we set it to 0 */
+	writel(0, emac->prueth->shram.va +
+		TIMESYNC_FW_WC_SYNCOUT_START_TIME_CYCLECOUNT_OFFSET);
+
+	return 0;
+}
+
+const struct icss_iep_clockops prueth_iep_clockops = {
+	.settime = prueth_iep_settime,
+	.gettime = prueth_iep_gettime,
+	/* FIXME: add adjtime to use relative mode */
+	.perout_enable = prueth_perout_enable,
+};
+
+static int prueth_create_xdp_rxqs(struct prueth_emac *emac)
+{
+	struct xdp_rxq_info *rxq = &emac->rx_chns.xdp_rxq;
+	struct page_pool *pool = emac->rx_chns.pg_pool;
+	int ret;
+
+	ret = xdp_rxq_info_reg(rxq, emac->ndev, 0, rxq->napi_id);
+	if (ret)
+		return ret;
+
+	ret = xdp_rxq_info_reg_mem_model(rxq, MEM_TYPE_PAGE_POOL, pool);
+	if (ret)
+		xdp_rxq_info_unreg(rxq);
+
+	return ret;
+}
+
+static void prueth_destroy_xdp_rxqs(struct prueth_emac *emac)
+{
+	struct xdp_rxq_info *rxq = &emac->rx_chns.xdp_rxq;
+
+	if (!xdp_rxq_info_is_reg(rxq))
+		return;
+
+	xdp_rxq_info_unreg(rxq);
+}
+
+/**
+ * emac_ndo_open - EMAC device open
+ * @ndev: network adapter device
+ *
+ * Called when system wants to start the interface.
+ *
+ * Returns 0 for a successful open, or appropriate error code
+ */
+static int emac_ndo_open(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	int ret, i, num_data_chn = emac->tx_ch_num;
+	struct icssg_flow_cfg __iomem *flow_cfg;
+	struct prueth *prueth = emac->prueth;
+	int slice = prueth_emac_slice(emac);
+	struct device *dev = prueth->dev;
+	int max_rx_flows;
+	int rx_flow;
+
+	/* clear SMEM and MSMC settings for all slices */
+	if (!prueth->num_emacs_initialized) {
+		memset_io(prueth->msmcram.va, 0, prueth->msmcram.size);
+		memset_io(prueth->shram.va, 0, ICSSG_CONFIG_OFFSET_SLICE1 * PRUETH_NUM_MACS);
+	}
+
+	/* set h/w MAC as user might have re-configured */
+	ether_addr_copy(emac->mac_addr, ndev->dev_addr);
+
+	icssg_class_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr);
+	icssg_ft1_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr);
+
+	if (!prueth->num_emacs_initialized) {
+		icssg_class_default(prueth->miig_rt, ICSS_SLICE0, 0);
+		icssg_class_default(prueth->miig_rt, ICSS_SLICE1, 0);
+	}
+
+	/* Notify the stack of the actual queue counts. */
+	ret = netif_set_real_num_tx_queues(ndev, num_data_chn);
+	if (ret) {
+		dev_err(dev, "cannot set real number of tx queues\n");
+		return ret;
+	}
+
+	init_completion(&emac->cmd_complete);
+	ret = prueth_init_tx_chns(emac);
+	if (ret) {
+		dev_err(dev, "failed to init tx channel: %d\n", ret);
+		return ret;
+	}
+
+	max_rx_flows = PRUETH_MAX_RX_FLOWS;
+	ret = prueth_init_rx_chns(emac, &emac->rx_chns, "rx",
+				  max_rx_flows, PRUETH_MAX_RX_DESC);
+	if (ret) {
+		dev_err(dev, "failed to init rx channel: %d\n", ret);
+		goto cleanup_tx;
+	}
+
+	ret = prueth_ndev_add_tx_napi(emac);
+	if (ret)
+		goto cleanup_rx;
+
+	/* we use only the highest priority flow for now i.e. @irq[3] */
+	rx_flow = PRUETH_RX_FLOW_DATA;
+	ret = request_irq(emac->rx_chns.irq[rx_flow], prueth_rx_irq,
+			  IRQF_TRIGGER_HIGH, dev_name(dev), emac);
+	if (ret) {
+		dev_err(dev, "unable to request RX IRQ\n");
+		goto cleanup_napi;
+	}
+
+	if (!prueth->num_emacs_initialized) {
+		if (prueth->emac[ICSS_SLICE0]) {
+			ret = prueth_emac_start(prueth, prueth->emac[ICSS_SLICE0]);
+			if (ret) {
+				netdev_err(ndev, "unable to start fw for slice %d", ICSS_SLICE0);
+				goto free_rx_irq;
+			}
+		}
+		if (prueth->emac[ICSS_SLICE1]) {
+			ret = prueth_emac_start(prueth, prueth->emac[ICSS_SLICE1]);
+			if (ret) {
+				netdev_err(ndev, "unable to start fw for slice %d", ICSS_SLICE1);
+				goto halt_slice0_prus;
+			}
+		}
+	}
+
+	flow_cfg = emac->dram.va + ICSSG_CONFIG_OFFSET + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET;
+	writew(emac->rx_flow_id_base, &flow_cfg->rx_base_flow);
+	ret = emac_fdb_flow_id_updated(emac);
+
+	if (ret) {
+		netdev_err(ndev, "Failed to update Rx Flow ID %d", ret);
+		goto stop;
+	}
+
+	icssg_mii_update_mtu(prueth->mii_rt, slice, ndev->max_mtu);
+
+	if (!prueth->num_emacs_initialized) {
+		ret = icss_iep_init(emac->iep, &prueth_iep_clockops,
+				    emac, IEP_DEFAULT_CYCLE_TIME_NS);
+	}
+
+	ret = request_threaded_irq(emac->tx_ts_irq, NULL, prueth_tx_ts_irq,
+				   IRQF_ONESHOT, dev_name(dev), emac);
+	if (ret)
+		goto stop;
+
+	/* Prepare RX */
+	ret = prueth_prepare_rx_chan(emac, &emac->rx_chns, PRUETH_MAX_PKT_SIZE);
+	if (ret)
+		goto destroy_xdp_rxqs;
+
+	ret = prueth_create_xdp_rxqs(emac);
+	if (ret)
+		goto free_rx_ts_irq;
+
+	ret = k3_udma_glue_enable_rx_chn(emac->rx_chns.rx_chn);
+	if (ret)
+		goto reset_rx_chn;
+
+	for (i = 0; i < emac->tx_ch_num; i++) {
+		ret = k3_udma_glue_enable_tx_chn(emac->tx_chns[i].tx_chn);
+		if (ret)
+			goto reset_tx_chan;
+	}
+
+	/* Enable NAPI in Tx and Rx direction */
+	for (i = 0; i < emac->tx_ch_num; i++)
+		napi_enable(&emac->tx_chns[i].napi_tx);
+	napi_enable(&emac->napi_rx);
+
+	icssg_qos_init(ndev);
+
+	/* start PHY */
+	phy_start(ndev->phydev);
+
+	prueth->num_emacs_initialized++;
+
+	if (prueth->is_switch_mode || prueth->is_hsr_offload_mode) {
+		icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan,
+				  ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
+				  ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
+				  ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
+				  ICSSG_FDB_ENTRY_BLOCK,
+				  true);
+		icssg_vtbl_modify(emac, emac->port_vlan, BIT(emac->port_id),
+				  BIT(emac->port_id), true);
+
+		/* In order for the packets to be received at host port, Both
+		 * HSR and switch firmware requires VLAN ID = 1 to be present
+		 * in the VLAN table
+		 */
+		icssg_vtbl_modify(emac, DEFAULT_VID, DEFAULT_PORT_MASK,
+				  DEFAULT_UNTAG_MASK, true);
+
+		icssg_set_pvid(emac->prueth, emac->port_vlan, emac->port_id);
+		emac_set_port_state(emac, ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE);
+	}
+
+	queue_work(system_long_wq, &emac->stats_work.work);
+
+	return 0;
+
+reset_tx_chan:
+	/* Since interface is not yet up, there is wouldn't be
+	 * any SKB for completion. So set false to free_skb
+	 */
+	prueth_reset_tx_chan(emac, i, false);
+reset_rx_chn:
+	prueth_reset_rx_chan(&emac->rx_chns, max_rx_flows, false);
+destroy_xdp_rxqs:
+	prueth_destroy_xdp_rxqs(emac);
+free_rx_ts_irq:
+	free_irq(emac->tx_ts_irq, emac);
+stop:
+	if (prueth->emac[ICSS_SLICE1])
+		prueth_emac_stop(prueth->emac[ICSS_SLICE1]);
+halt_slice0_prus:
+	if (prueth->emac[ICSS_SLICE0])
+		prueth_emac_stop(prueth->emac[ICSS_SLICE0]);
+free_rx_irq:
+	free_irq(emac->rx_chns.irq[rx_flow], emac);
+cleanup_napi:
+	prueth_ndev_del_tx_napi(emac, emac->tx_ch_num);
+cleanup_rx:
+	prueth_cleanup_rx_chns(emac, &emac->rx_chns, max_rx_flows);
+cleanup_tx:
+	prueth_cleanup_tx_chns(emac);
+
+	return ret;
+}
+
+/**
+ * emac_ndo_stop - EMAC device stop
+ * @ndev: network adapter device
+ *
+ * Called when system wants to stop or down the interface.
+ */
+static int emac_ndo_stop(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth *prueth = emac->prueth;
+	int rx_flow = PRUETH_RX_FLOW_DATA;
+	int max_rx_flows;
+	int ret, i;
+
+	/* inform the upper layers. */
+	netif_tx_stop_all_queues(ndev);
+
+	/* block packets from wire */
+	if (ndev->phydev)
+		phy_stop(ndev->phydev);
+
+	if (prueth->num_emacs_initialized == 1) {
+		icssg_class_disable(prueth->miig_rt, ICSS_SLICE0);
+		icssg_class_disable(prueth->miig_rt, ICSS_SLICE1);
+	}
+
+	atomic_set(&emac->tdown_cnt, emac->tx_ch_num);
+	/* ensure new tdown_cnt value is visible */
+	smp_mb__after_atomic();
+	/* tear down and disable UDMA channels */
+	reinit_completion(&emac->tdown_complete);
+	for (i = 0; i < emac->tx_ch_num; i++)
+		k3_udma_glue_tdown_tx_chn(emac->tx_chns[i].tx_chn, false);
+
+	ret = wait_for_completion_timeout(&emac->tdown_complete,
+					  msecs_to_jiffies(1000));
+	if (!ret)
+		netdev_err(ndev, "tx teardown timeout\n");
+
+	prueth_reset_tx_chan(emac, emac->tx_ch_num, true);
+	for (i = 0; i < emac->tx_ch_num; i++) {
+		napi_disable(&emac->tx_chns[i].napi_tx);
+		hrtimer_cancel(&emac->tx_chns[i].tx_hrtimer);
+	}
+
+	max_rx_flows = PRUETH_MAX_RX_FLOWS;
+	k3_udma_glue_tdown_rx_chn(emac->rx_chns.rx_chn, true);
+
+	prueth_reset_rx_chan(&emac->rx_chns, max_rx_flows, true);
+
+	prueth_destroy_xdp_rxqs(emac);
+
+	napi_disable(&emac->napi_rx);
+	hrtimer_cancel(&emac->rx_hrtimer);
+
+	cancel_work_sync(&emac->rx_mode_work);
+
+	if (prueth->num_emacs_initialized == 1) {
+		icss_iep_exit(emac->iep);
+		/* stop PRUs */
+		if (prueth->emac[ICSS_SLICE0])
+			prueth_emac_stop(prueth->emac[ICSS_SLICE0]);
+		if (prueth->emac[ICSS_SLICE1])
+			prueth_emac_stop(prueth->emac[ICSS_SLICE1]);
+	}
+
+	/* Destroying the queued work in ndo_stop() */
+	cancel_delayed_work_sync(&emac->stats_work);
+
+	free_irq(emac->tx_ts_irq, emac);
+
+	free_irq(emac->rx_chns.irq[rx_flow], emac);
+	prueth_ndev_del_tx_napi(emac, emac->tx_ch_num);
+	prueth_cleanup_tx_chns(emac);
+
+	prueth_cleanup_rx_chns(emac, &emac->rx_chns, max_rx_flows);
+	prueth_cleanup_tx_chns(emac);
+
+	prueth->num_emacs_initialized--;
+
+	return 0;
+}
+
+static void emac_ndo_tx_timeout(struct net_device *ndev, unsigned int txqueue)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+
+	if (netif_msg_tx_err(emac))
+		netdev_err(ndev, "xmit timeout");
+
+	ndev->stats.tx_errors++;
+}
+
+static void emac_ndo_set_rx_mode_work(struct work_struct *work)
+{
+	struct prueth_emac *emac = container_of(work, struct prueth_emac, rx_mode_work);
+	struct prueth *prueth = emac->prueth;
+	struct net_device *ndev = emac->ndev;
+	bool promisc, allmulti;
+
+	if (!netif_running(ndev))
+		return;
+
+	promisc = ndev->flags & IFF_PROMISC;
+	allmulti = ndev->flags & IFF_ALLMULTI;
+	emac_set_port_state(emac, ICSSG_EMAC_PORT_UC_FLOODING_DISABLE);
+	emac_set_port_state(emac, ICSSG_EMAC_PORT_MC_FLOODING_DISABLE);
+
+	if (promisc) {
+		emac_set_port_state(emac, ICSSG_EMAC_PORT_UC_FLOODING_ENABLE);
+		emac_set_port_state(emac, ICSSG_EMAC_PORT_MC_FLOODING_ENABLE);
+		return;
+	}
+
+	if (allmulti) {
+		emac_set_port_state(emac, ICSSG_EMAC_PORT_MC_FLOODING_ENABLE);
+		return;
+	}
+
+	if (!prueth->is_switch_mode) {
+		emac_fdb_flush_multicast(emac);
+
+		if (!prueth->is_hsr_offload_mode) {
+			if (!netdev_mc_empty(ndev)) {
+				struct netdev_hw_addr *ha;
+
+				/* Program multicast address list into FDB Table */
+				netdev_for_each_mc_addr(ha, ndev) {
+					icssg_fdb_add_del(emac, ha->addr, 0,
+							  BIT(emac->port_id), true);
+					icssg_vtbl_modify(emac, 0, BIT(emac->port_id),
+							  BIT(emac->port_id), true);
+				}
+				return;
+			}
+		} else {
+			/* Now that the FDB entries are flushed, restore the
+			 * entries that were added during ndo_open
+			 */
+			icssg_fdb_add_del(emac, eth_stp_addr, prueth->default_vlan,
+					  ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
+					  ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
+					  ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
+					  ICSSG_FDB_ENTRY_BLOCK,
+					  true);
+			icssg_vtbl_modify(emac, emac->port_vlan, BIT(emac->port_id),
+					  BIT(emac->port_id), true);
+
+			/* In order for the packets to be received at host port, Both
+			 * HSR firmware requires VLAN ID = 1 to be present
+			 * in the VLAN table
+			 */
+			icssg_vtbl_modify(emac, DEFAULT_VID, DEFAULT_PORT_MASK,
+					  DEFAULT_UNTAG_MASK, true);
+
+			if (!netdev_mc_empty(ndev)) {
+				struct netdev_hw_addr *ha;
+
+				/* Program multicast address list into FDB Table */
+				netdev_for_each_mc_addr(ha, ndev) {
+					icssg_fdb_add_del(emac, ha->addr, prueth->default_vlan,
+							  ICSSG_FDB_ENTRY_P0_MEMBERSHIP |
+							  ICSSG_FDB_ENTRY_P1_MEMBERSHIP |
+							  ICSSG_FDB_ENTRY_P2_MEMBERSHIP |
+							  ICSSG_FDB_ENTRY_BLOCK,
+							  true);
+				}
+
+				icssg_vtbl_modify(emac, emac->port_vlan, BIT(emac->port_id),
+						  BIT(emac->port_id), true);
+				return;
+			}
+		}
+	}
+}
+
+/**
+ * emac_ndo_set_rx_mode - EMAC set receive mode function
+ * @ndev: The EMAC network adapter
+ *
+ * Called when system wants to set the receive mode of the device.
+ *
+ */
+static void emac_ndo_set_rx_mode(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+
+	queue_work(emac->cmd_wq, &emac->rx_mode_work);
+}
+
+static int emac_set_ts_config(struct net_device *ndev, struct ifreq *ifr)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct hwtstamp_config config;
+
+	if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		emac->tx_ts_enabled = 0;
+		break;
+	case HWTSTAMP_TX_ON:
+		emac->tx_ts_enabled = 1;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	switch (config.rx_filter) {
+	case HWTSTAMP_FILTER_NONE:
+		emac->rx_ts_enabled = 0;
+		break;
+	case HWTSTAMP_FILTER_ALL:
+	case HWTSTAMP_FILTER_SOME:
+	case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+	case HWTSTAMP_FILTER_PTP_V2_EVENT:
+	case HWTSTAMP_FILTER_PTP_V2_SYNC:
+	case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+	case HWTSTAMP_FILTER_NTP_ALL:
+		emac->rx_ts_enabled = 1;
+		config.rx_filter = HWTSTAMP_FILTER_ALL;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+		-EFAULT : 0;
+}
+
+static int emac_get_ts_config(struct net_device *ndev, struct ifreq *ifr)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct hwtstamp_config config;
+
+	config.flags = 0;
+	config.tx_type = emac->tx_ts_enabled ? HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
+	config.rx_filter = emac->rx_ts_enabled ? HWTSTAMP_FILTER_ALL : HWTSTAMP_FILTER_NONE;
+
+	return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+			    -EFAULT : 0;
+}
+
+static int emac_ndo_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
+{
+	switch (cmd) {
+	case SIOCGHWTSTAMP:
+		return emac_get_ts_config(ndev, ifr);
+	case SIOCSHWTSTAMP:
+		return emac_set_ts_config(ndev, ifr);
+	default:
+		break;
+	}
+
+	return phy_do_ioctl(ndev, ifr, cmd);
+}
+
+static struct devlink_port *emac_ndo_get_devlink_port(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+
+	return &emac->devlink_port;
+}
+
+/**
+ * emac_xmit_xdp_frame - transmits an XDP frame
+ * @emac: emac device
+ * @xdpf: data to transmit
+ * @page: page from page pool if already DMA mapped
+ * @q_idx: queue id
+ **/
+static int emac_xmit_xdp_frame(struct prueth_emac *emac,
+			       struct xdp_frame *xdpf,
+			       struct page *page,
+			       unsigned int q_idx)
+{
+	struct cppi5_host_desc_t *first_desc;
+	struct net_device *ndev = emac->ndev;
+	struct prueth_tx_chn *tx_chn;
+	dma_addr_t desc_dma, buf_dma;
+	struct prueth_swdata *swdata;
+	u32 *epib;
+	int ret;
+
+	void *data = xdpf->data;
+	u32 pkt_len = xdpf->len;
+
+	if (q_idx >= PRUETH_MAX_TX_QUEUES) {
+		netdev_err(ndev, "xdp tx: invalid q_id %d\n", q_idx);
+		return ICSSG_XDP_CONSUMED;	/* drop */
+	}
+
+	tx_chn = &emac->tx_chns[q_idx];
+
+	if (page) { /* already DMA mapped by page_pool */
+		buf_dma = page_pool_get_dma_addr(page);
+		buf_dma += xdpf->headroom + sizeof(struct xdp_frame);
+	} else { /* Map the linear buffer */
+		buf_dma = dma_map_single(tx_chn->dma_dev, data, pkt_len, DMA_TO_DEVICE);
+		if (dma_mapping_error(tx_chn->dma_dev, buf_dma)) {
+			netdev_err(ndev, "xdp tx: failed to map data buffer\n");
+			return ICSSG_XDP_CONSUMED;	/* drop */
+		}
+	}
+
+	first_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
+	if (!first_desc) {
+		netdev_dbg(ndev, "xdp tx: failed to allocate descriptor\n");
+		if (!page)
+			dma_unmap_single(tx_chn->dma_dev, buf_dma, pkt_len, DMA_TO_DEVICE);
+		return ICSSG_XDP_CONSUMED;	/* drop */
+	}
+
+	cppi5_hdesc_init(first_desc, CPPI5_INFO0_HDESC_EPIB_PRESENT,
+			 PRUETH_NAV_PS_DATA_SIZE);
+	cppi5_hdesc_set_pkttype(first_desc, 0);
+	epib = first_desc->epib;
+	epib[0] = 0;
+	epib[1] = 0;
+
+	/* set dst tag to indicate internal qid at the firmware which is at
+	 * bit8..bit15. bit0..bit7 indicates port num for directed
+	 * packets in case of switch mode operation
+	 */
+	cppi5_desc_set_tags_ids(&first_desc->hdr, 0, (emac->port_id | (q_idx << 8)));
+	k3_udma_glue_tx_dma_to_cppi5_addr(tx_chn->tx_chn, &buf_dma);
+	cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len);
+	swdata = cppi5_hdesc_get_swdata(first_desc);
+	if (page) {
+		swdata->type = PRUETH_SWDATA_PAGE;
+		swdata->data.page = page;
+		/* we assume page came from RX channel page pool */
+		swdata->rx_chn = &emac->rx_chns;
+	} else {
+		swdata->type = PRUETH_SWDATA_XDPF;
+		swdata->data.xdpf = xdpf;
+	}
+
+	cppi5_hdesc_set_pktlen(first_desc, pkt_len);
+	desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, first_desc);
+
+	ret = k3_udma_glue_push_tx_chn(tx_chn->tx_chn, first_desc, desc_dma);
+	if (ret) {
+		netdev_err(ndev, "xdp tx: push failed: %d\n", ret);
+		goto drop_free_descs;
+	}
+
+	return ICSSG_XDP_TX;
+
+drop_free_descs:
+	prueth_xmit_free(tx_chn, first_desc);
+	return ICSSG_XDP_CONSUMED;
+}
+
+/**
+ * emac_xdp_xmit - Implements ndo_xdp_xmit
+ * @dev: netdev
+ * @n: number of frames
+ * @frames: array of XDP buffer pointers
+ * @flags: XDP extra info
+ *
+ * Returns number of frames successfully sent. Failed frames
+ * will be free'ed by XDP core.
+ *
+ * For error cases, a negative errno code is returned and no-frames
+ * are transmitted (caller must handle freeing frames).
+ **/
+static int emac_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
+			 u32 flags)
+{
+	struct prueth_emac *emac = netdev_priv(dev);
+	unsigned int q_idx;
+	int nxmit = 0;
+	int i;
+
+	q_idx = smp_processor_id();
+
+	if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
+		return -EINVAL;
+
+	for (i = 0; i < n; i++) {
+		struct xdp_frame *xdpf = frames[i];
+		int err;
+
+		err = emac_xmit_xdp_frame(emac, xdpf, NULL, q_idx);
+		if (err != ICSSG_XDP_TX)
+			break;
+		nxmit++;
+	}
+
+	return nxmit;
+}
+
+/**
+ * emac_run_xdp - run an XDP program
+ * @emac: emac device
+ * @xdp: XDP buffer containing the frame
+ * @page: page with RX data if already DMA mapped
+ **/
+static int emac_run_xdp(struct prueth_emac *emac, struct xdp_buff *xdp,
+			struct page *page)
+{
+	int err, result = ICSSG_XDP_PASS;
+	struct bpf_prog *xdp_prog;
+	struct xdp_frame *xdpf;
+	u32 act;
+	int q_idx;
+
+	xdp_prog = READ_ONCE(emac->xdp_prog);
+
+	if (!xdp_prog)
+		return result;
+
+	act = bpf_prog_run_xdp(xdp_prog, xdp);
+	switch (act) {
+	case XDP_PASS:
+		break;
+	case XDP_TX:
+		/* Send packet to TX ring for immediate transmission */
+		xdpf = xdp_convert_buff_to_frame(xdp);
+		if (unlikely(!xdpf))
+			goto drop;
+
+		q_idx = smp_processor_id();
+		result = emac_xmit_xdp_frame(emac, xdpf, page, q_idx);
+		if (result == ICSSG_XDP_CONSUMED)
+			goto drop;
+		break;
+	case XDP_REDIRECT:
+		err = xdp_do_redirect(emac->ndev, xdp, xdp_prog);
+		if (err)
+			goto drop;
+		result = ICSSG_XDP_REDIR;
+		break;
+	default:
+		bpf_warn_invalid_xdp_action(emac->ndev, xdp_prog, act);
+		fallthrough;
+	case XDP_ABORTED:
+drop:
+		trace_xdp_exception(emac->ndev, xdp_prog, act);
+		fallthrough; /* handle aborts by dropping packet */
+	case XDP_DROP:
+		result = ICSSG_XDP_CONSUMED;
+		page_pool_recycle_direct(emac->rx_chns.pg_pool, page);
+		break;
+	}
+
+	return result;
+}
+
+/**
+ * emac_xdp_setup - add/remove an XDP program
+ * @emac: emac device
+ * @prog: XDP program
+ **/
+static int emac_xdp_setup(struct prueth_emac *emac, struct netdev_bpf *bpf)
+{
+	struct bpf_prog *prog = bpf->prog;
+
+	if (!emac->xdpi.prog && !prog)
+		return 0;
+
+	WRITE_ONCE(emac->xdp_prog, prog);
+
+	xdp_attachment_setup(&emac->xdpi, bpf);
+
+	return 0;
+}
+
+/**
+ * emac_ndo_bpf - implements ndo_bpf for icssg_prueth
+ * @ndev: network adapter device
+ * @xdp: XDP command
+ **/
+static int emac_ndo_bpf(struct net_device *ndev, struct netdev_bpf *bpf)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+
+	switch (bpf->command) {
+	case XDP_SETUP_PROG:
+		return emac_xdp_setup(emac, bpf);
+	default:
+		return -EINVAL;
+	}
+}
+
+static inline enum prueth_port other_port_id(enum prueth_port port_id)
+{
+	enum prueth_port other_port_id =
+		(port_id == PRUETH_PORT_MII0) ? PRUETH_PORT_MII1 :
+						PRUETH_PORT_MII0;
+	return other_port_id;
+}
+
+static int emac_ndo_set_features(struct net_device *ndev,
+				 netdev_features_t features)
+{
+	netdev_features_t hsr_feature_present = ndev->features & NETIF_PRUETH_HSR_OFFLOAD;
+	netdev_features_t hsr_feature_wanted = features & NETIF_PRUETH_HSR_OFFLOAD;
+	bool hsr_change_request = ((hsr_feature_wanted ^ hsr_feature_present) != 0);
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth *prueth = emac->prueth;
+	struct prueth_emac *other_emac;
+	enum prueth_port other_port;
+	int ret = -EBUSY;
+
+	if (netif_running(ndev) && hsr_change_request) {
+		netdev_err(ndev,
+			   "Can't change feature when device is running\n");
+		return ret;
+	}
+
+	other_port = other_port_id(emac->port_id);
+	other_emac = prueth->emac[other_port - 1];
+
+	if (other_emac && netif_running(other_emac->ndev) && hsr_change_request) {
+		netdev_err(ndev,
+			   "Can't change feature when other port is running\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct net_device_ops emac_netdev_ops = {
+	.ndo_open = emac_ndo_open,
+	.ndo_stop = emac_ndo_stop,
+	.ndo_start_xmit = emac_ndo_start_xmit,
+	.ndo_set_mac_address = eth_mac_addr,
+	.ndo_validate_addr = eth_validate_addr,
+	.ndo_tx_timeout = emac_ndo_tx_timeout,
+	.ndo_set_rx_mode = emac_ndo_set_rx_mode,
+	.ndo_eth_ioctl = emac_ndo_ioctl,
+	.ndo_get_devlink_port = emac_ndo_get_devlink_port,
+	.ndo_setup_tc = icssg_qos_ndo_setup_tc,
+	.ndo_bpf = emac_ndo_bpf,
+	.ndo_xdp_xmit = emac_xdp_xmit,
+	.ndo_set_features = emac_ndo_set_features,
+};
+
+/* get emac_port corresponding to eth_node name */
+static int prueth_node_port(struct device_node *eth_node)
+{
+	u32 port_id;
+	int ret;
+
+	ret = of_property_read_u32(eth_node, "reg", &port_id);
+	if (ret)
+		return ret;
+
+	if (port_id == 0)
+		return PRUETH_PORT_MII0;
+	else if (port_id == 1)
+		return PRUETH_PORT_MII1;
+	else
+		return -EINVAL;
+}
+
+/* get MAC instance corresponding to eth_node name */
+static int prueth_node_mac(struct device_node *eth_node)
+{
+	u32 port_id;
+	int ret;
+
+	ret = of_property_read_u32(eth_node, "reg", &port_id);
+	if (ret)
+		return ret;
+
+	if (port_id == 0)
+		return PRUETH_MAC0;
+	else if (port_id == 1)
+		return PRUETH_MAC1;
+	else
+		return -EINVAL;
+}
+
+extern const struct ethtool_ops icssg_ethtool_ops;
+
+static int prueth_netdev_init(struct prueth *prueth,
+			      struct device_node *eth_node)
+{
+	int ret, num_tx_chn = PRUETH_MAX_TX_QUEUES;
+	struct prueth_emac *emac;
+	struct net_device *ndev;
+	enum prueth_port port;
+	const char *irq_name;
+	enum prueth_mac mac;
+
+	port = prueth_node_port(eth_node);
+	if (port < 0)
+		return -EINVAL;
+
+	mac = prueth_node_mac(eth_node);
+	if (mac < 0)
+		return -EINVAL;
+
+	ndev = alloc_etherdev_mq(sizeof(*emac), num_tx_chn);
+	if (!ndev)
+		return -ENOMEM;
+
+	emac = netdev_priv(ndev);
+	prueth->emac[mac] = emac;
+	emac->prueth = prueth;
+	emac->ndev = ndev;
+	emac->port_id = port;
+	emac->cmd_wq = create_singlethread_workqueue("icssg_cmd_wq");
+	if (!emac->cmd_wq) {
+		ret = -ENOMEM;
+		goto free_ndev;
+	}
+	INIT_WORK(&emac->rx_mode_work, emac_ndo_set_rx_mode_work);
+
+	INIT_DELAYED_WORK(&emac->stats_work, emac_stats_work_handler);
+
+	ret = pruss_request_mem_region(prueth->pruss,
+				       port == PRUETH_PORT_MII0 ?
+				       PRUSS_MEM_DRAM0 : PRUSS_MEM_DRAM1,
+				       &emac->dram);
+	if (ret) {
+		dev_err(prueth->dev, "unable to get DRAM: %d\n", ret);
+		ret = -ENOMEM;
+		goto free_wq;
+	}
+
+	emac->tx_ch_num = 1;
+
+	irq_name = "tx_ts0";
+	if (emac->port_id == PRUETH_PORT_MII1)
+		irq_name = "tx_ts1";
+	emac->tx_ts_irq = platform_get_irq_byname_optional(prueth->pdev, irq_name);
+	if (emac->tx_ts_irq < 0) {
+		ret = dev_err_probe(prueth->dev, emac->tx_ts_irq, "could not get tx_ts_irq\n");
+		goto free;
+	}
+
+	SET_NETDEV_DEV(ndev, prueth->dev);
+	spin_lock_init(&emac->lock);
+	mutex_init(&emac->cmd_lock);
+
+	emac->phy_node = of_parse_phandle(eth_node, "phy-handle", 0);
+	if (!emac->phy_node && !of_phy_is_fixed_link(eth_node)) {
+		dev_err(prueth->dev, "couldn't find phy-handle\n");
+		ret = -ENODEV;
+		goto free;
+	} else if (of_phy_is_fixed_link(eth_node)) {
+		ret = of_phy_register_fixed_link(eth_node);
+		if (ret) {
+			ret = dev_err_probe(prueth->dev, ret,
+					    "failed to register fixed-link phy\n");
+			goto free;
+		}
+
+		emac->phy_node = eth_node;
+	}
+
+	ret = of_get_phy_mode(eth_node, &emac->phy_if);
+	if (ret) {
+		dev_err(prueth->dev, "could not get phy-mode property\n");
+		goto free;
+	}
+
+	if (emac->phy_if != PHY_INTERFACE_MODE_MII &&
+	    !phy_interface_mode_is_rgmii(emac->phy_if)) {
+		dev_err(prueth->dev, "PHY mode unsupported %s\n", phy_modes(emac->phy_if));
+		ret = -EINVAL;
+		goto free;
+	}
+
+	/* AM65 SR2.0 has TX Internal delay always enabled by hardware
+	 * and it is not possible to disable TX Internal delay. The below
+	 * switch case block describes how we handle different phy modes
+	 * based on hardware restriction.
+	 */
+	switch (emac->phy_if) {
+	case PHY_INTERFACE_MODE_RGMII_ID:
+		emac->phy_if = PHY_INTERFACE_MODE_RGMII_RXID;
+		break;
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		emac->phy_if = PHY_INTERFACE_MODE_RGMII;
+		break;
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+		dev_err(prueth->dev, "RGMII mode without TX delay is not supported");
+		return -EINVAL;
+	default:
+		break;
+	}
+
+	/* get mac address from DT and set private and netdev addr */
+	ret = of_get_ethdev_address(eth_node, ndev);
+	if (!is_valid_ether_addr(ndev->dev_addr)) {
+		eth_hw_addr_random(ndev);
+		dev_warn(prueth->dev, "port %d: using random MAC addr: %pM\n",
+			 port, ndev->dev_addr);
+	}
+	ether_addr_copy(emac->mac_addr, ndev->dev_addr);
+
+	ndev->min_mtu = PRUETH_MIN_PKT_SIZE;
+	ndev->max_mtu = PRUETH_MAX_MTU;
+	ndev->netdev_ops = &emac_netdev_ops;
+	ndev->ethtool_ops = &icssg_ethtool_ops;
+	ndev->hw_features = NETIF_F_SG;
+	ndev->features = ndev->hw_features;
+	ndev->hw_features |= NETIF_PRUETH_HSR_OFFLOAD;
+
+	netif_napi_add(ndev, &emac->napi_rx,
+		       emac_napi_rx_poll);
+
+	hrtimer_init(&emac->rx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
+	emac->rx_hrtimer.function = &emac_rx_timer_callback;
+
+	return 0;
+
+free:
+	pruss_release_mem_region(prueth->pruss, &emac->dram);
+free_wq:
+	destroy_workqueue(emac->cmd_wq);
+free_ndev:
+	free_netdev(ndev);
+	prueth->emac[mac] = NULL;
+
+	return ret;
+}
+
+static void prueth_netdev_exit(struct prueth *prueth,
+			       struct device_node *eth_node)
+{
+	struct prueth_emac *emac;
+	enum prueth_mac mac;
+
+	mac = prueth_node_mac(eth_node);
+	if (mac < 0)
+		return;
+
+	emac = prueth->emac[mac];
+	if (!emac)
+		return;
+
+	if (of_phy_is_fixed_link(emac->phy_node))
+		of_phy_deregister_fixed_link(emac->phy_node);
+
+	netif_napi_del(&emac->napi_rx);
+
+	pruss_release_mem_region(prueth->pruss, &emac->dram);
+	destroy_workqueue(emac->cmd_wq);
+	free_netdev(emac->ndev);
+	prueth->emac[mac] = NULL;
+}
+
+static int prueth_get_cores(struct prueth *prueth, int slice)
+{
+	struct device *dev = prueth->dev;
+	enum pruss_pru_id pruss_id;
+	struct device_node *np;
+	int idx = -1, ret;
+
+	np = dev->of_node;
+
+	switch (slice) {
+	case ICSS_SLICE0:
+		idx = 0;
+		break;
+	case ICSS_SLICE1:
+		idx = 3;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	prueth->pru[slice] = pru_rproc_get(np, idx, &pruss_id);
+	if (IS_ERR(prueth->pru[slice])) {
+		ret = PTR_ERR(prueth->pru[slice]);
+		prueth->pru[slice] = NULL;
+		return dev_err_probe(dev, ret, "unable to get PRU%d\n", slice);
+	}
+	prueth->pru_id[slice] = pruss_id;
+
+	idx++;
+	prueth->rtu[slice] = pru_rproc_get(np, idx, NULL);
+	if (IS_ERR(prueth->rtu[slice])) {
+		ret = PTR_ERR(prueth->rtu[slice]);
+		prueth->rtu[slice] = NULL;
+		return dev_err_probe(dev, ret, "unable to get RTU%d\n", slice);
+	}
+
+	idx++;
+	prueth->txpru[slice] = pru_rproc_get(np, idx, NULL);
+	if (IS_ERR(prueth->txpru[slice])) {
+		ret = PTR_ERR(prueth->txpru[slice]);
+		prueth->txpru[slice] = NULL;
+		return dev_err_probe(dev, ret, "unable to get TX_PRU%d\n", slice);
+	}
+
+	return 0;
+}
+
+static void prueth_put_cores(struct prueth *prueth, int slice)
+{
+	if (prueth->txpru[slice])
+		pru_rproc_put(prueth->txpru[slice]);
+
+	if (prueth->rtu[slice])
+		pru_rproc_put(prueth->rtu[slice]);
+
+	if (prueth->pru[slice])
+		pru_rproc_put(prueth->pru[slice]);
+}
+
+static void prueth_offload_fwd_mark_update(struct prueth *prueth)
+{
+	int set_val = 0;
+	int i;
+
+	if (prueth->br_members == (PRUETH_PORT_MII0 | PRUETH_PORT_MII1))
+		set_val = 1;
+
+	dev_dbg(prueth->dev, "set offload_fwd_mark %d\n", set_val);
+
+	for (i = PRUETH_MAC0; i < PRUETH_NUM_MACS; i++) {
+		struct prueth_emac *emac = prueth->emac[i];
+
+		if (!emac || !emac->ndev)
+			continue;
+
+		emac->offload_fwd_mark = set_val;
+	}
+}
+
+bool prueth_dev_check(const struct net_device *ndev)
+{
+	if (ndev->netdev_ops == &emac_netdev_ops && netif_running(ndev)) {
+		struct prueth_emac *emac = netdev_priv(ndev);
+
+		return emac->prueth->is_switch_mode;
+	}
+
+	return false;
+}
+
+static int prueth_netdevice_port_link(struct net_device *ndev, struct net_device *br_ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth *prueth = emac->prueth;
+
+	if (!prueth->is_switch_mode)
+		return NOTIFY_DONE;
+
+	if (!prueth->br_members) {
+		prueth->hw_bridge_dev = br_ndev;
+	} else {
+		/* This is adding the port to a second bridge, this is
+		 * unsupported
+		 */
+		if (prueth->hw_bridge_dev != br_ndev)
+			return -EOPNOTSUPP;
+	}
+
+	prueth->br_members |= BIT(emac->port_id);
+
+	prueth_offload_fwd_mark_update(prueth);
+
+	return NOTIFY_DONE;
+}
+
+static void prueth_netdevice_port_unlink(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth *prueth = emac->prueth;
+
+	prueth->br_members &= ~BIT(emac->port_id);
+
+	prueth_offload_fwd_mark_update(prueth);
+
+	if (!prueth->br_members)
+		prueth->hw_bridge_dev = NULL;
+}
+
+/* netdev notifier */
+static int prueth_netdevice_event(struct notifier_block *unused,
+				  unsigned long event, void *ptr)
+{
+	struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
+	struct netdev_notifier_changeupper_info *info;
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth *prueth = emac->prueth;
+	int ret = NOTIFY_DONE;
+
+	if (ndev->netdev_ops != &emac_netdev_ops)
+		return NOTIFY_DONE;
+
+	switch (event) {
+	case NETDEV_CHANGEUPPER:
+		info = ptr;
+
+		if ((ndev->features & NETIF_PRUETH_HSR_OFFLOAD) &&
+		    is_hsr_master(info->upper_dev)) {
+			if (!prueth->hsr_dev) {
+				prueth->hsr_dev = info->upper_dev;
+
+				icssg_class_set_host_mac_addr(prueth->miig_rt,
+							      prueth->hsr_dev->dev_addr);
+			} else {
+				if (prueth->hsr_dev != info->upper_dev) {
+					dev_err(prueth->dev, "Both interfaces must be linked to same upper device\n");
+					return -EOPNOTSUPP;
+				}
+			}
+		}
+
+		if (netif_is_bridge_master(info->upper_dev)) {
+			if (info->linking)
+				ret = prueth_netdevice_port_link(ndev, info->upper_dev);
+			else
+				prueth_netdevice_port_unlink(ndev);
+		}
+		break;
+	default:
+		return NOTIFY_DONE;
+	}
+
+	return notifier_from_errno(ret);
+}
+
+static int prueth_register_notifiers(struct prueth *prueth)
+{
+	int ret = 0;
+
+	prueth->prueth_netdevice_nb.notifier_call = &prueth_netdevice_event;
+	ret = register_netdevice_notifier(&prueth->prueth_netdevice_nb);
+	if (ret) {
+		dev_err(prueth->dev, "can't register netdevice notifier\n");
+		return ret;
+	}
+
+	ret = prueth_switchdev_register_notifiers(prueth);
+	if (ret)
+		unregister_netdevice_notifier(&prueth->prueth_netdevice_nb);
+
+	return ret;
+}
+
+static void prueth_unregister_notifiers(struct prueth *prueth)
+{
+	prueth_switchdev_unregister_notifiers(prueth);
+	unregister_netdevice_notifier(&prueth->prueth_netdevice_nb);
+}
+
+static const struct devlink_ops prueth_devlink_ops = {};
+
+static u8 prueth_dl_cut_thru_check(struct prueth_emac *emac)
+{
+	void *config = emac->dram.va + ICSSG_CONFIG_OFFSET;
+	u8 queue_map = 0U;
+	u8 cut_thru_val;
+	int i;
+
+	for (i = 0; i < PRUETH_MAX_TX_QUEUES * PRUETH_NUM_MACS; i++) {
+		cut_thru_val = readb(config + EXPRESS_PRE_EMPTIVE_Q_MAP + i);
+		if (cut_thru_val & BIT(7))
+			queue_map |= BIT(i);
+	}
+
+	return queue_map;
+}
+
+static int prueth_dl_cut_thru_en_get(struct devlink *dl, u32 id,
+				     struct devlink_param_gset_ctx *ctx)
+{
+	struct prueth_devlink *dl_priv = devlink_priv(dl);
+	struct prueth *prueth = dl_priv->prueth;
+	u16 tx_queues = 0U;
+	int i;
+
+	dev_dbg(prueth->dev, "%s id:%u\n", __func__, id);
+
+	if (id != PRUETH_DL_PARAM_CUT_THRU_EN)
+		return -EOPNOTSUPP;
+
+	for (i = PRUETH_MAC0; i < PRUETH_NUM_MACS; i++) {
+		if (!(prueth->emac[i]))
+			return -EINVAL;
+
+		tx_queues |= prueth_dl_cut_thru_check(prueth->emac[i]) << (8 * i);
+	}
+
+	ctx->val.vu16 = tx_queues;
+
+	return 0;
+}
+
+static int prueth_dl_cut_thru_en_set(struct devlink *dl, u32 id,
+				     struct devlink_param_gset_ctx *ctx)
+{
+	struct prueth_devlink *dl_priv = devlink_priv(dl);
+	struct prueth *prueth = dl_priv->prueth;
+	u16 tx_queues = ctx->val.vu16;
+	struct prueth_emac *emac;
+	int i;
+
+	if (id != PRUETH_DL_PARAM_CUT_THRU_EN)
+		return -EOPNOTSUPP;
+
+	if (!prueth->is_switch_mode && !prueth->is_hsr_offload_mode) {
+		dev_err(prueth->dev, "Cut-Thru not supported in MAC mode\n");
+		return -EINVAL;
+	}
+
+	for (i = PRUETH_MAC0; i < PRUETH_NUM_MACS; i++) {
+		emac = prueth->emac[i];
+		if (netif_running(emac->ndev)) {
+			dev_err(prueth->dev, "Cannot enable cut-thru when i/f are up\n");
+			return -EINVAL;
+		}
+
+		emac->cut_thru_queue_map = tx_queues >> (8 * i);
+	}
+	return 0;
+}
+
+/* This function to be called with rtnl_lock */
+static int prueth_dl_mode_update(struct prueth *prueth, bool mode_en)
+{
+	int i;
+
+	ASSERT_RTNL();
+	prueth->default_vlan = 1;
+
+	for (i = PRUETH_MAC0; i < PRUETH_NUM_MACS; i++) {
+		struct net_device *sl_ndev = prueth->emac[i]->ndev;
+
+		if (!sl_ndev || !netif_running(sl_ndev))
+			continue;
+
+		dev_err(prueth->dev, "Cannot switch modes when i/f are up\n");
+		return -EINVAL;
+	}
+
+	for (i = PRUETH_MAC0; i < PRUETH_NUM_MACS; i++) {
+		struct net_device *sl_ndev = prueth->emac[i]->ndev;
+		struct prueth_emac *emac;
+
+		if (!sl_ndev)
+			continue;
+
+		emac = netdev_priv(sl_ndev);
+		if (mode_en)
+			emac->port_vlan = prueth->default_vlan;
+		else
+			emac->port_vlan = 0;
+	}
+
+	return 0;
+}
+
+static int prueth_dl_hsr_offload_mode_get(struct devlink *dl, u32 id,
+					  struct devlink_param_gset_ctx *ctx)
+{
+	struct prueth_devlink *dl_priv = devlink_priv(dl);
+	struct prueth *prueth = dl_priv->prueth;
+
+	dev_dbg(prueth->dev, "%s id:%u\n", __func__, id);
+
+	if (id != PRUETH_DL_PARAM_HSR_OFFLOAD_MODE)
+		return -EOPNOTSUPP;
+
+	ctx->val.vbool = prueth->is_hsr_offload_mode;
+
+	return 0;
+}
+
+static int prueth_dl_hsr_offload_mode_set(struct devlink *dl, u32 id,
+					  struct devlink_param_gset_ctx *ctx)
+{
+	struct prueth_devlink *dl_priv = devlink_priv(dl);
+	struct prueth *prueth = dl_priv->prueth;
+	bool hsr_offload_en = ctx->val.vbool;
+	int ret;
+
+	if (id != PRUETH_DL_PARAM_HSR_OFFLOAD_MODE)
+		return -EOPNOTSUPP;
+
+	if (hsr_offload_en == prueth->is_hsr_offload_mode)
+		return 0;
+
+	if (!hsr_offload_en &&
+	    (prueth->emac[PRUETH_MAC0]->ndev->features & NETIF_PRUETH_HSR_OFFLOAD) &&
+	    (prueth->emac[PRUETH_MAC1]->ndev->features & NETIF_PRUETH_HSR_OFFLOAD)) {
+		dev_err(prueth->dev, "Disable HSR offload on both interfaces\n");
+		return -EINVAL;
+	}
+
+	if (hsr_offload_en) {
+		if (!(prueth->emac[PRUETH_MAC0]->ndev->features & NETIF_PRUETH_HSR_OFFLOAD) &&
+		    !(prueth->emac[PRUETH_MAC1]->ndev->features & NETIF_PRUETH_HSR_OFFLOAD)) {
+			dev_err(prueth->dev, "Enable HSR offload on both interfaces\n");
+			return -EINVAL;
+		}
+
+		if (prueth->is_switch_mode) {
+			dev_err(prueth->dev, "Switching from bridge to HSR mode not allowed\n");
+			return -EINVAL;
+		}
+	}
+
+	rtnl_lock();
+
+	ret = prueth_dl_mode_update(prueth, hsr_offload_en);
+	if (ret)
+		goto exit;
+
+	prueth->is_hsr_offload_mode = hsr_offload_en;
+
+	if (prueth->is_hsr_offload_mode)
+		icss_iep_init_fw(prueth->iep1);
+	else
+		icss_iep_exit_fw(prueth->iep1);
+
+	dev_info(prueth->dev, "Enabling %s mode\n",
+		 hsr_offload_en ? "HSR offload" : "Dual EMAC");
+exit:
+	rtnl_unlock();
+
+	return ret;
+}
+
+static int prueth_dl_switch_mode_get(struct devlink *dl, u32 id,
+				     struct devlink_param_gset_ctx *ctx)
+{
+	struct prueth_devlink *dl_priv = devlink_priv(dl);
+	struct prueth *prueth = dl_priv->prueth;
+
+	dev_dbg(prueth->dev, "%s id:%u\n", __func__, id);
+
+	if (id != PRUETH_DL_PARAM_SWITCH_MODE)
+		return -EOPNOTSUPP;
+
+	ctx->val.vbool = prueth->is_switch_mode;
+
+	return 0;
+}
+
+static int prueth_dl_switch_mode_set(struct devlink *dl, u32 id,
+				     struct devlink_param_gset_ctx *ctx)
+{
+	struct prueth_devlink *dl_priv = devlink_priv(dl);
+	struct prueth *prueth = dl_priv->prueth;
+	bool switch_en = ctx->val.vbool;
+	int ret;
+
+	dev_dbg(prueth->dev, "%s id:%u\n", __func__, id);
+
+	if (id != PRUETH_DL_PARAM_SWITCH_MODE)
+		return -EOPNOTSUPP;
+
+	if (switch_en == prueth->is_switch_mode)
+		return 0;
+
+	if (!switch_en && prueth->br_members) {
+		dev_err(prueth->dev, "Remove ports from bridge before disabling switch mode\n");
+		return -EINVAL;
+	}
+
+	if (switch_en && prueth->is_hsr_offload_mode) {
+		dev_err(prueth->dev, "Switching from HSR offload to switch mode	not allowed\n");
+		return -EINVAL;
+	}
+
+	rtnl_lock();
+
+	ret = prueth_dl_mode_update(prueth, switch_en);
+	if (ret)
+		goto exit;
+
+	prueth->is_switch_mode = switch_en;
+
+	dev_info(prueth->dev, "Enabling %s mode\n",
+		 switch_en ? "switch" : "Dual EMAC");
+
+exit:
+	rtnl_unlock();
+
+	return ret;
+}
+
+static const struct devlink_param prueth_devlink_params[] = {
+	DEVLINK_PARAM_DRIVER(PRUETH_DL_PARAM_SWITCH_MODE, "switch_mode",
+			     DEVLINK_PARAM_TYPE_BOOL,
+			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+			     prueth_dl_switch_mode_get,
+			     prueth_dl_switch_mode_set, NULL),
+	DEVLINK_PARAM_DRIVER(PRUETH_DL_PARAM_HSR_OFFLOAD_MODE, "hsr_offload_mode",
+			     DEVLINK_PARAM_TYPE_BOOL,
+			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+			     prueth_dl_hsr_offload_mode_get,
+			     prueth_dl_hsr_offload_mode_set, NULL),
+	DEVLINK_PARAM_DRIVER(PRUETH_DL_PARAM_CUT_THRU_EN, "cut_thru",
+			     DEVLINK_PARAM_TYPE_U16,
+			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+			     prueth_dl_cut_thru_en_get,
+			     prueth_dl_cut_thru_en_set, NULL),
+};
+
+static void prueth_unregister_devlink_ports(struct prueth *prueth)
+{
+	struct devlink_port *dl_port;
+	struct prueth_emac *emac;
+	int i;
+
+	for (i = PRUETH_MAC0; i < PRUETH_NUM_MACS; i++) {
+		emac = prueth->emac[i];
+		if (!emac)
+			continue;
+
+		dl_port = &emac->devlink_port;
+
+		if (dl_port->registered)
+			devlink_port_unregister(dl_port);
+	}
+}
+
+static int prueth_register_devlink(struct prueth *prueth)
+{
+	struct devlink_port_attrs attrs = {};
+	struct prueth_devlink *dl_priv;
+	struct device *dev = prueth->dev;
+	struct devlink_port *dl_port;
+	struct prueth_emac *emac;
+	int ret = 0;
+	int i;
+
+	prueth->devlink =
+		devlink_alloc(&prueth_devlink_ops, sizeof(*dl_priv), dev);
+	if (!prueth->devlink)
+		return -ENOMEM;
+
+	dl_priv = devlink_priv(prueth->devlink);
+	dl_priv->prueth = prueth;
+
+	/* Provide devlink hook to switch mode when multiple external ports
+	 * are present NUSS switchdev driver is enabled.
+	 */
+	if (prueth->is_switchmode_supported) {
+		ret = devlink_params_register(prueth->devlink,
+					      prueth_devlink_params,
+					      ARRAY_SIZE(prueth_devlink_params));
+		if (ret) {
+			dev_err(dev, "devlink params reg fail ret:%d\n", ret);
+			goto dl_unreg;
+		}
+	}
+
+	for (i = PRUETH_MAC0; i < PRUETH_NUM_MACS; i++) {
+		emac = prueth->emac[i];
+		if (!emac)
+			continue;
+
+		dl_port = &emac->devlink_port;
+
+		attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
+		attrs.phys.port_number = emac->port_id;
+		attrs.switch_id.id_len = sizeof(resource_size_t);
+		memcpy(attrs.switch_id.id, prueth->switch_id, attrs.switch_id.id_len);
+		devlink_port_attrs_set(dl_port, &attrs);
+
+		ret = devlink_port_register(prueth->devlink, dl_port, emac->port_id);
+		if (ret) {
+			dev_err(dev, "devlink_port reg fail for port %d, ret:%d\n",
+				emac->port_id, ret);
+			goto dl_port_unreg;
+		}
+	}
+
+	devlink_register(prueth->devlink);
+	return ret;
+
+dl_port_unreg:
+	prueth_unregister_devlink_ports(prueth);
+dl_unreg:
+	devlink_free(prueth->devlink);
+
+	return ret;
+}
+
+static void prueth_unregister_devlink(struct prueth *prueth)
+{
+	devlink_unregister(prueth->devlink);
+
+	if (prueth->is_switchmode_supported) {
+		devlink_params_unregister(prueth->devlink, prueth_devlink_params,
+					  ARRAY_SIZE(prueth_devlink_params));
+	}
+
+	prueth_unregister_devlink_ports(prueth);
+	devlink_unregister(prueth->devlink);
+	devlink_free(prueth->devlink);
+}
+
+static const struct of_device_id prueth_dt_match[];
+
+static int prueth_probe(struct platform_device *pdev)
+{
+	struct device_node *eth_node, *eth0_node, *eth1_node, *eth_ports_node;
+	struct genpool_data_align gp_data = {
+		.align = SZ_64K,
+	};
+	const struct of_device_id *match;
+	struct device *dev = &pdev->dev;
+	struct device_node *np;
+	struct prueth *prueth;
+	struct pruss *pruss;
+	u32 msmc_ram_size;
+	int i, ret;
+
+	np = dev->of_node;
+
+	if (sizeof(struct prueth_swdata) > PRUETH_NAV_SW_DATA_SIZE) {
+		dev_err(dev, "insufficient SW_DATA size: %d vs %ld\n",
+			PRUETH_NAV_SW_DATA_SIZE, sizeof(struct prueth_swdata));
+		return -ENOMEM;
+	}
+
+	match = of_match_device(prueth_dt_match, dev);
+	if (!match)
+		return -ENODEV;
+
+	prueth = devm_kzalloc(dev, sizeof(*prueth), GFP_KERNEL);
+	if (!prueth)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, prueth);
+	prueth->pdev = pdev;
+	prueth->pdata = *(const struct prueth_pdata *)match->data;
+
+	prueth->dev = dev;
+	eth_ports_node = of_get_child_by_name(np, "ethernet-ports");
+	if (!eth_ports_node)
+		return -ENOENT;
+
+	for_each_child_of_node(eth_ports_node, eth_node) {
+		u32 reg;
+
+		if (strcmp(eth_node->name, "port"))
+			continue;
+		ret = of_property_read_u32(eth_node, "reg", &reg);
+		if (ret < 0) {
+			dev_err(dev, "%pOF error reading port_id %d\n",
+				eth_node, ret);
+		}
+
+		of_node_get(eth_node);
+
+		if (reg == 0) {
+			eth0_node = eth_node;
+			if (!of_device_is_available(eth0_node)) {
+				of_node_put(eth0_node);
+				eth0_node = NULL;
+			}
+		} else if (reg == 1) {
+			eth1_node = eth_node;
+			if (!of_device_is_available(eth1_node)) {
+				of_node_put(eth1_node);
+				eth1_node = NULL;
+			}
+		} else {
+			dev_err(dev, "port reg should be 0 or 1\n");
+		}
+	}
+
+	of_node_put(eth_ports_node);
+
+	/* At least one node must be present and available else we fail */
+	if (!eth0_node && !eth1_node) {
+		dev_err(dev, "neither port0 nor port1 node available\n");
+		return -ENODEV;
+	}
+
+	if (eth0_node == eth1_node) {
+		dev_err(dev, "port0 and port1 can't have same reg\n");
+		of_node_put(eth0_node);
+		return -ENODEV;
+	}
+
+	prueth->eth_node[PRUETH_MAC0] = eth0_node;
+	prueth->eth_node[PRUETH_MAC1] = eth1_node;
+
+	prueth->miig_rt = syscon_regmap_lookup_by_phandle(np, "ti,mii-g-rt");
+	if (IS_ERR(prueth->miig_rt)) {
+		dev_err(dev, "couldn't get ti,mii-g-rt syscon regmap\n");
+		return -ENODEV;
+	}
+
+	prueth->mii_rt = syscon_regmap_lookup_by_phandle(np, "ti,mii-rt");
+	if (IS_ERR(prueth->mii_rt)) {
+		dev_err(dev, "couldn't get ti,mii-rt syscon regmap\n");
+		return -ENODEV;
+	}
+
+	prueth->pa_stats = syscon_regmap_lookup_by_phandle(np, "ti,pa-stats");
+	if (IS_ERR(prueth->pa_stats)) {
+		dev_err(dev, "couldn't get ti,pa-stats syscon regmap\n");
+		return -ENODEV;
+	}
+
+	if (eth0_node) {
+		ret = prueth_get_cores(prueth, ICSS_SLICE0);
+		if (ret)
+			goto put_cores;
+	}
+
+	if (eth1_node) {
+		ret = prueth_get_cores(prueth, ICSS_SLICE1);
+		if (ret)
+			goto put_cores;
+	}
+
+	pruss = pruss_get(eth0_node ?
+			  prueth->pru[ICSS_SLICE0] : prueth->pru[ICSS_SLICE1]);
+	if (IS_ERR(pruss)) {
+		ret = PTR_ERR(pruss);
+		dev_err(dev, "unable to get pruss handle\n");
+		goto put_cores;
+	}
+
+	prueth->pruss = pruss;
+
+	ret = pruss_request_mem_region(pruss, PRUSS_MEM_SHRD_RAM2,
+				       &prueth->shram);
+	if (ret) {
+		dev_err(dev, "unable to get PRUSS SHRD RAM2: %d\n", ret);
+		pruss_put(prueth->pruss);
+	}
+
+	prueth->sram_pool = of_gen_pool_get(np, "sram", 0);
+	if (!prueth->sram_pool) {
+		dev_err(dev, "unable to get SRAM pool\n");
+		ret = -ENODEV;
+
+		goto put_mem;
+	}
+
+	msmc_ram_size = MSMC_RAM_SIZE;
+	prueth->is_switchmode_supported = prueth->pdata.switch_mode;
+	if (prueth->is_switchmode_supported)
+		msmc_ram_size = MSMC_RAM_SIZE_SWITCH_MODE;
+
+
+	/* NOTE: FW bug needs buffer base to be 64KB aligned */
+	prueth->msmcram.va =
+		(void __iomem *)gen_pool_alloc_algo(prueth->sram_pool,
+						    msmc_ram_size,
+						    gen_pool_first_fit_align,
+						    &gp_data);
+
+	if (!prueth->msmcram.va) {
+		ret = -ENOMEM;
+		dev_err(dev, "unable to allocate MSMC resource\n");
+		goto put_mem;
+	}
+	prueth->msmcram.pa = gen_pool_virt_to_phys(prueth->sram_pool,
+						   (unsigned long)prueth->msmcram.va);
+	prueth->msmcram.size = msmc_ram_size;
+	memset(prueth->msmcram.va, 0, msmc_ram_size);
+	dev_dbg(dev, "sram: pa %llx va %p size %zx\n", prueth->msmcram.pa,
+		prueth->msmcram.va, prueth->msmcram.size);
+
+	prueth->iep0 = icss_iep_get_idx(np, 0);
+	if (IS_ERR(prueth->iep0)) {
+		ret = dev_err_probe(dev, PTR_ERR(prueth->iep0), "iep0 get failed\n");
+		prueth->iep0 = NULL;
+		goto free_pool;
+	}
+
+	prueth->iep1 = icss_iep_get_idx(np, 1);
+	if (IS_ERR(prueth->iep1)) {
+		ret = dev_err_probe(dev, PTR_ERR(prueth->iep1), "iep1 get failed\n");
+		icss_iep_put(prueth->iep0);
+		prueth->iep0 = NULL;
+		prueth->iep1 = NULL;
+		goto free_pool;
+	}
+
+	if (prueth->pdata.quirk_10m_link_issue) {
+		/* Enable IEP1 for FW in 64bit mode as W/A for 10M FD link detect issue under TX
+		 * traffic.
+		 */
+		icss_iep_init_fw(prueth->iep1);
+	}
+
+	/* setup netdev interfaces */
+	if (eth0_node) {
+		ret = prueth_netdev_init(prueth, eth0_node);
+		if (ret) {
+			dev_err_probe(dev, ret, "netdev init %s failed\n",
+				      eth0_node->name);
+			goto exit_iep;
+		}
+
+		if (of_find_property(eth0_node, "ti,half-duplex-capable", NULL))
+			prueth->emac[PRUETH_MAC0]->half_duplex = 1;
+
+		prueth->emac[PRUETH_MAC0]->iep = prueth->iep0;
+	}
+
+	if (eth1_node) {
+		ret = prueth_netdev_init(prueth, eth1_node);
+		if (ret) {
+			dev_err_probe(dev, ret, "netdev init %s failed\n",
+				      eth1_node->name);
+			goto netdev_exit;
+		}
+
+		if (of_find_property(eth1_node, "ti,half-duplex-capable", NULL))
+			prueth->emac[PRUETH_MAC1]->half_duplex = 1;
+
+		prueth->emac[PRUETH_MAC1]->iep = prueth->iep0;
+	}
+
+	ret = prueth_register_devlink(prueth);
+	if (ret)
+		goto netdev_exit;
+
+	/* register the network devices */
+	if (eth0_node) {
+		ret = register_netdev(prueth->emac[PRUETH_MAC0]->ndev);
+		if (ret) {
+			dev_err(dev, "can't register netdev for port MII0");
+			goto netdev_exit;
+		}
+
+		devlink_port_type_eth_set(&prueth->emac[PRUETH_MAC0]->devlink_port,
+					  prueth->emac[PRUETH_MAC0]->ndev);
+		prueth->registered_netdevs[PRUETH_MAC0] = prueth->emac[PRUETH_MAC0]->ndev;
+
+		emac_phy_connect(prueth->emac[PRUETH_MAC0]);
+		phy_attached_info(prueth->emac[PRUETH_MAC0]->ndev->phydev);
+	}
+
+	if (eth1_node) {
+		ret = register_netdev(prueth->emac[PRUETH_MAC1]->ndev);
+		if (ret) {
+			dev_err(dev, "can't register netdev for port MII1");
+			goto netdev_unregister;
+		}
+
+		devlink_port_type_eth_set(&prueth->emac[PRUETH_MAC1]->devlink_port,
+					  prueth->emac[PRUETH_MAC1]->ndev);
+		prueth->registered_netdevs[PRUETH_MAC1] = prueth->emac[PRUETH_MAC1]->ndev;
+		emac_phy_connect(prueth->emac[PRUETH_MAC1]);
+		phy_attached_info(prueth->emac[PRUETH_MAC1]->ndev->phydev);
+	}
+
+	if (prueth->is_switchmode_supported) {
+		ret = prueth_register_notifiers(prueth);
+		if (ret)
+			goto netdev_unregister;
+
+		sprintf(prueth->switch_id, "%s", dev_name(dev));
+	}
+
+	dev_info(dev, "TI PRU ethernet driver initialized: %s EMAC mode\n",
+		 (!eth0_node || !eth1_node) ? "single" : "dual");
+
+	if (eth1_node)
+		of_node_put(eth1_node);
+	if (eth0_node)
+		of_node_put(eth0_node);
+	return 0;
+
+netdev_unregister:
+	for (i = 0; i < PRUETH_NUM_MACS; i++) {
+		if (!prueth->registered_netdevs[i])
+			continue;
+		if (prueth->emac[i]->ndev->phydev) {
+			phy_disconnect(prueth->emac[i]->ndev->phydev);
+			prueth->emac[i]->ndev->phydev = NULL;
+		}
+		unregister_netdev(prueth->registered_netdevs[i]);
+	}
+
+netdev_exit:
+	for (i = 0; i < PRUETH_NUM_MACS; i++) {
+		eth_node = prueth->eth_node[i];
+		if (!eth_node)
+			continue;
+
+		prueth_netdev_exit(prueth, eth_node);
+	}
+
+exit_iep:
+	if (prueth->pdata.quirk_10m_link_issue)
+		icss_iep_exit_fw(prueth->iep1);
+
+free_pool:
+	gen_pool_free(prueth->sram_pool,
+		      (unsigned long)prueth->msmcram.va, msmc_ram_size);
+
+put_mem:
+	pruss_release_mem_region(prueth->pruss, &prueth->shram);
+	pruss_put(prueth->pruss);
+
+put_cores:
+	if (eth1_node) {
+		prueth_put_cores(prueth, ICSS_SLICE1);
+		of_node_put(eth1_node);
+	}
+
+	if (eth0_node) {
+		prueth_put_cores(prueth, ICSS_SLICE0);
+		of_node_put(eth0_node);
+	}
+
+	return ret;
+}
+
+static int prueth_remove(struct platform_device *pdev)
+{
+	struct prueth *prueth = platform_get_drvdata(pdev);
+	struct device_node *eth_node;
+	int i;
+
+	prueth_unregister_notifiers(prueth);
+
+	for (i = 0; i < PRUETH_NUM_MACS; i++) {
+		if (!prueth->registered_netdevs[i])
+			continue;
+		phy_stop(prueth->emac[i]->ndev->phydev);
+		phy_disconnect(prueth->emac[i]->ndev->phydev);
+		prueth->emac[i]->ndev->phydev = NULL;
+		unregister_netdev(prueth->registered_netdevs[i]);
+	}
+	prueth_unregister_devlink(prueth);
+
+	for (i = 0; i < PRUETH_NUM_MACS; i++) {
+		eth_node = prueth->eth_node[i];
+		if (!eth_node)
+			continue;
+
+		prueth_netdev_exit(prueth, eth_node);
+	}
+
+	if (prueth->pdata.quirk_10m_link_issue)
+		icss_iep_exit_fw(prueth->iep1);
+
+	icss_iep_put(prueth->iep1);
+	icss_iep_put(prueth->iep0);
+
+	gen_pool_free(prueth->sram_pool,
+		      (unsigned long)prueth->msmcram.va,
+		      MSMC_RAM_SIZE);
+
+	pruss_release_mem_region(prueth->pruss, &prueth->shram);
+
+	pruss_put(prueth->pruss);
+
+	if (prueth->eth_node[PRUETH_MAC1])
+		prueth_put_cores(prueth, ICSS_SLICE1);
+
+	if (prueth->eth_node[PRUETH_MAC0])
+		prueth_put_cores(prueth, ICSS_SLICE0);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int prueth_suspend(struct device *dev)
+{
+	struct prueth *prueth = dev_get_drvdata(dev);
+	struct net_device *ndev;
+	int i, ret;
+
+	for (i = 0; i < PRUETH_NUM_MACS; i++) {
+		ndev = prueth->registered_netdevs[i];
+
+		if (!ndev)
+			continue;
+
+		if (netif_running(ndev)) {
+			netif_device_detach(ndev);
+			ret = emac_ndo_stop(ndev);
+			if (ret < 0) {
+				netdev_err(ndev, "failed to stop: %d", ret);
+				return ret;
+			}
+		}
+	}
+
+	return 0;
+}
+
+static int prueth_resume(struct device *dev)
+{
+	struct prueth *prueth = dev_get_drvdata(dev);
+	struct net_device *ndev;
+	int i, ret;
+
+	for (i = 0; i < PRUETH_NUM_MACS; i++) {
+		ndev = prueth->registered_netdevs[i];
+
+		if (!ndev)
+			continue;
+
+		if (netif_running(ndev)) {
+			ret = emac_ndo_open(ndev);
+			if (ret < 0) {
+				netdev_err(ndev, "failed to start: %d", ret);
+				return ret;
+			}
+			netif_device_attach(ndev);
+		}
+	}
+
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+static const struct dev_pm_ops prueth_dev_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(prueth_suspend, prueth_resume)
+};
+
+static const struct prueth_pdata am654_icssg_pdata = {
+	.fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE,
+	.quirk_10m_link_issue = 1,
+	.switch_mode = 1,
+};
+
+static const struct prueth_pdata am64x_icssg_pdata = {
+	.fdqring_mode = K3_RINGACC_RING_MODE_RING,
+	.switch_mode = 1,
+};
+
+static const struct of_device_id prueth_dt_match[] = {
+	{ .compatible = "ti,am654-icssg-prueth", .data = &am654_icssg_pdata },
+	{ .compatible = "ti,am642-icssg-prueth", .data = &am64x_icssg_pdata },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, prueth_dt_match);
+
+static struct platform_driver prueth_driver = {
+	.probe = prueth_probe,
+	.remove = prueth_remove,
+	.driver = {
+		.name = "icssg-prueth",
+		.of_match_table = prueth_dt_match,
+		.pm = &prueth_dev_pm_ops,
+	},
+};
+module_platform_driver(prueth_driver);
+
+MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
+MODULE_AUTHOR("Puranjay Mohan <p-mohan@ti.com>");
+MODULE_AUTHOR("Md Danish Anwar <danishanwar@ti.com>");
+MODULE_DESCRIPTION("PRUSS ICSSG Ethernet Driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_prueth.h b/drivers/net/ethernet/ti/icssg_prueth.h
--- a/drivers/net/ethernet/ti/icssg_prueth.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_prueth.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,394 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Texas Instruments ICSSG Ethernet driver
+ *
+ * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#ifndef __NET_TI_ICSSG_PRUETH_H
+#define __NET_TI_ICSSG_PRUETH_H
+
+#include <linux/bpf.h>
+#include <linux/bpf_trace.h>
+#include <linux/etherdevice.h>
+#include <linux/genalloc.h>
+#include <linux/if_vlan.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/net_tstamp.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_mdio.h>
+#include <linux/of_net.h>
+#include <linux/of_platform.h>
+#include <linux/phy.h>
+#include <linux/remoteproc/pruss.h>
+#include <linux/pruss_driver.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/remoteproc.h>
+
+#include <linux/dma-mapping.h>
+#include <linux/dma/ti-cppi5.h>
+#include <linux/dma/k3-udma-glue.h>
+
+#include <net/devlink.h>
+#include <net/page_pool.h>
+
+#include "icssg_config.h"
+#include "icss_iep.h"
+#include "icssg_switch_map.h"
+#include "icssg_qos.h"
+
+#define ICSS_SLICE0	0
+#define ICSS_SLICE1	1
+
+#define ICSS_FW_PRU	0
+#define ICSS_FW_RTU	1
+
+#define ICSSG_MAX_RFLOWS	8	/* per slice */
+
+/* Number of ICSSG related stats */
+#define ICSSG_NUM_STATS 70
+
+/* Firmware status codes */
+#define ICSS_HS_FW_READY 0x55555555
+#define ICSS_HS_FW_DEAD 0xDEAD0000	/* lower 16 bits contain error code */
+
+/* Firmware command codes */
+#define ICSS_HS_CMD_BUSY 0x40000000
+#define ICSS_HS_CMD_DONE 0x80000000
+#define ICSS_HS_CMD_CANCEL 0x10000000
+
+/* Firmware commands */
+#define ICSS_CMD_SPAD 0x20
+#define ICSS_CMD_RXTX 0x10
+#define ICSS_CMD_ADD_FDB 0x1
+#define ICSS_CMD_DEL_FDB 0x2
+#define ICSS_CMD_ERASE_FDB 0x3
+#define ICSS_CMD_SET_RUN 0x4
+#define ICSS_CMD_GET_FDB_SLOT 0x5
+#define ICSS_CMD_ENABLE_VLAN 0x5
+#define ICSS_CMD_DISABLE_VLAN 0x6
+#define ICSS_CMD_ADD_FILTER 0x7
+#define ICSS_CMD_ADD_MAC 0x8
+
+/* ICSSG IET STATS Base Address */
+#define ICSSG_IET_STATS_BASE 0x180
+
+/* In switch mode there are 3 real ports i.e. 3 mac addrs.
+ * however Linux sees only the host side port. The other 2 ports
+ * are the switch ports.
+ * In emac mode there are 2 real ports i.e. 2 mac addrs.
+ * Linux sees both the ports.
+ */
+enum prueth_port {
+	PRUETH_PORT_HOST = 0,	/* host side port */
+	PRUETH_PORT_MII0,	/* physical port RG/SG MII 0 */
+	PRUETH_PORT_MII1,	/* physical port RG/SG MII 1 */
+};
+
+enum prueth_mac {
+	PRUETH_MAC0 = 0,
+	PRUETH_MAC1,
+	PRUETH_NUM_MACS,
+};
+
+struct prueth_tx_chn {
+	struct device *dma_dev;
+	struct napi_struct napi_tx;
+	struct k3_cppi_desc_pool *desc_pool;
+	struct k3_udma_glue_tx_channel *tx_chn;
+	struct prueth_emac *emac;
+	struct hrtimer tx_hrtimer;
+	unsigned long tx_pace_timeout_ns;
+	u32 id;
+	u32 descs_num;
+	unsigned int irq;
+	char name[32];
+};
+
+struct prueth_rx_chn {
+	struct device *dev;
+	struct device *dma_dev;
+	struct k3_cppi_desc_pool *desc_pool;
+	struct k3_udma_glue_rx_channel *rx_chn;
+	u32 descs_num;
+	unsigned int irq[ICSSG_MAX_RFLOWS];	/* separate irq per flow */
+	char name[32];
+	struct page_pool *pg_pool;
+	struct xdp_rxq_info xdp_rxq;
+};
+
+enum prueth_devlink_param_id {
+	PRUETH_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
+	PRUETH_DL_PARAM_SWITCH_MODE,
+	PRUETH_DL_PARAM_HSR_OFFLOAD_MODE,
+	PRUETH_DL_PARAM_CUT_THRU_EN,
+};
+
+struct prueth_devlink {
+	struct prueth *prueth;
+};
+
+enum prueth_swdata_type {
+	PRUETH_SWDATA_INVALID = 0,
+	PRUETH_SWDATA_SKB,
+	PRUETH_SWDATA_PAGE,
+	PRUETH_SWDATA_CMD,
+	PRUETH_SWDATA_XDPF,
+};
+
+union prueth_data {
+	struct sk_buff *skb;
+	struct page *page;
+	u32 cmd;
+	struct xdp_frame *xdpf;
+};
+
+struct prueth_swdata {
+	union prueth_data data;
+	struct prueth_rx_chn *rx_chn;
+	enum prueth_swdata_type type;
+};
+
+/* There are 4 Tx DMA channels, but the highest priority is CH3 (thread 3)
+ * and lower three are lower priority channels or threads.
+ */
+#define PRUETH_MAX_TX_QUEUES	4
+
+#define PRUETH_MAX_TX_TS_REQUESTS	50	/* Max simultaneous TX_TS requests */
+
+/* XDP BPF state */
+#define ICSSG_XDP_PASS           0
+#define ICSSG_XDP_CONSUMED       BIT(0)
+#define ICSSG_XDP_TX             BIT(1)
+#define ICSSG_XDP_REDIR          BIT(2)
+
+/* Minimum coalesce time in usecs for both Tx and Rx */
+#define ICSSG_MIN_COALESCE_USECS 20
+
+/* data for each emac port */
+struct prueth_emac {
+	bool fw_running;
+	struct prueth *prueth;
+	struct net_device *ndev;
+	u8 mac_addr[6];
+	struct napi_struct napi_rx;
+	u32 msg_enable;
+
+	int link;
+	int speed;
+	int duplex;
+
+	const char *phy_id;
+	struct device_node *phy_node;
+	phy_interface_t phy_if;
+	enum prueth_port port_id;
+	struct icss_iep *iep;
+	unsigned int rx_ts_enabled : 1;
+	unsigned int tx_ts_enabled : 1;
+	unsigned int half_duplex : 1;
+
+	/* DMA related */
+	struct prueth_tx_chn tx_chns[PRUETH_MAX_TX_QUEUES];
+	struct completion tdown_complete;
+	atomic_t tdown_cnt;
+	struct prueth_rx_chn rx_chns;
+	int rx_flow_id_base;
+	int tx_ch_num;
+
+	/* Interrput Pacing Related */
+	struct hrtimer rx_hrtimer;
+	unsigned long rx_pace_timeout_ns;
+
+	spinlock_t lock;	/* serialize access */
+
+	/* TX HW Timestamping */
+	/* TX TS cookie will be index to the tx_ts_skb array */
+	struct sk_buff *tx_ts_skb[PRUETH_MAX_TX_TS_REQUESTS];
+	atomic_t tx_ts_pending;
+	int tx_ts_irq;
+
+	u8 cmd_seq;
+	/* shutdown related */
+	u32 cmd_data[4];
+	struct completion cmd_complete;
+	/* Mutex to serialize access to firmware command interface */
+	struct mutex cmd_lock;
+	struct work_struct rx_mode_work;
+	struct workqueue_struct	*cmd_wq;
+
+	struct pruss_mem_region dram;
+
+	u8 cut_thru_queue_map;
+	bool offload_fwd_mark;
+	struct devlink_port devlink_port;
+	int port_vlan;
+
+	struct prueth_qos qos;
+	struct work_struct ts_work;
+	struct delayed_work stats_work;
+	u64 stats[ICSSG_NUM_STATS];
+
+	struct bpf_prog *xdp_prog;
+	struct xdp_attachment_info xdpi;
+};
+
+/* The buf includes headroom compatible with both skb and xdpf */
+#define PRUETH_HEADROOM_NA (max(XDP_PACKET_HEADROOM, NET_SKB_PAD) + NET_IP_ALIGN)
+#define PRUETH_HEADROOM  ALIGN(PRUETH_HEADROOM_NA, sizeof(long))
+
+/**
+ * struct prueth_pdata - PRUeth platform data
+ * @fdqring_mode: Free desc queue mode
+ * @quirk_10m_link_issue: 10M link detect errata
+ * @switch_mode: switch firmware support
+ */
+struct prueth_pdata {
+	enum k3_ring_mode fdqring_mode;
+	u32	quirk_10m_link_issue:1;
+	u32	switch_mode:1;
+};
+
+/**
+ * struct prueth - PRUeth structure
+ * @dev: device
+ * @pruss: pruss handle
+ * @pru: rproc instances of PRUs
+ * @rtu: rproc instances of RTUs
+ * @txpru: rproc instances of TX_PRUs
+ * @shram: PRUSS shared RAM region
+ * @sram_pool: MSMC RAM pool for buffers
+ * @msmcram: MSMC RAM region
+ * @eth_node: DT node for the port
+ * @emac: private EMAC data structure
+ * @registered_netdevs: list of registered netdevs
+ * @fw_data: firmware names to be used with PRU remoteprocs
+ * @config: firmware load time configuration per slice
+ * @miig_rt: regmap to mii_g_rt block
+ * @mii_rt: regmap to mii_g_rt block
+ * @pa_stats: regmap to pa_stats block
+ * @pru_id: ID for each of the PRUs
+ * @pdev: pointer to ICSSG platform device
+ * @pdata: pointer to platform data for ICSSG driver
+ * @icssg_hwcmdseq: seq counter or HWQ messages
+ * @num_emacs_initialized: num of EMACs/ext ports that are up/running
+ * @iep0: pointer to IEP0 device
+ * @iep1: pointer to IEP1 device
+ * @vlan_tbl: VLAN-FID table pointer
+ * @hw_bridge_dev: pointer to HW bridge net device
+ * @hsr_dev: pointer to the HSR net device
+ * @br_members: bitmask of bridge member ports
+ * @prueth_netdevice_nb: netdevice notifier block
+ * @prueth_switchdevice_nb: switchdev notifier block
+ * @prueth_switchdev_bl_nb: switchdev blocking notifier block
+ * @is_switch_mode: flag to indicate if device is in Switch mode
+ * @is_switchmode_supported: indicates platform support for switch mode
+ * @switch_id: ID for mapping switch ports to bridge
+ * @default_vlan: Default VLAN for host
+ * @devlink: pointer to devlink
+ */
+struct prueth {
+	struct device *dev;
+	struct pruss *pruss;
+	struct rproc *pru[PRUSS_NUM_PRUS];
+	struct rproc *rtu[PRUSS_NUM_PRUS];
+	struct rproc *txpru[PRUSS_NUM_PRUS];
+	struct pruss_mem_region shram;
+	struct gen_pool *sram_pool;
+	struct pruss_mem_region msmcram;
+
+	struct device_node *eth_node[PRUETH_NUM_MACS];
+	struct prueth_emac *emac[PRUETH_NUM_MACS];
+	struct net_device *registered_netdevs[PRUETH_NUM_MACS];
+	const struct prueth_private_data *fw_data;
+	struct regmap *miig_rt;
+	struct regmap *mii_rt;
+	struct regmap *pa_stats;
+
+	enum pruss_pru_id pru_id[PRUSS_NUM_PRUS];
+	struct platform_device *pdev;
+	struct prueth_pdata pdata;
+	u8 icssg_hwcmdseq;
+	int num_emacs_initialized;
+	struct icss_iep *iep0;
+	struct icss_iep *iep1;
+	struct prueth_vlan_tbl *vlan_tbl;
+
+	struct net_device *hw_bridge_dev;
+	struct net_device *hsr_dev;
+	u8 br_members;
+	struct notifier_block prueth_netdevice_nb;
+	struct notifier_block prueth_switchdev_nb;
+	struct notifier_block prueth_switchdev_bl_nb;
+	bool is_switch_mode;
+	bool is_hsr_offload_mode;
+	bool is_switchmode_supported;
+	unsigned char switch_id[MAX_PHYS_ITEM_ID_LEN];
+	int default_vlan;
+	struct devlink *devlink;
+};
+
+struct emac_tx_ts_response {
+	u32 reserved[2];
+	u32 cookie;
+	u32 lo_ts;
+	u32 hi_ts;
+};
+
+/* Classifier helpers */
+void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac);
+void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac);
+void icssg_class_disable(struct regmap *miig_rt, int slice);
+void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti);
+void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr);
+
+/* Buffer queue helpers */
+int icssg_queue_pop(struct prueth *prueth, u8 queue);
+void icssg_queue_push(struct prueth *prueth, int queue, u16 addr);
+u32 icssg_queue_level(struct prueth *prueth, int queue);
+
+/* get PRUSS SLICE number from prueth_emac */
+static inline int prueth_emac_slice(struct prueth_emac *emac)
+{
+	switch (emac->port_id) {
+	case PRUETH_PORT_MII0:
+		return ICSS_SLICE0;
+	case PRUETH_PORT_MII1:
+		return ICSS_SLICE1;
+	default:
+		return -EINVAL;
+	}
+}
+
+/* config helpers */
+void icssg_config_ipg(struct prueth_emac *emac);
+int icssg_config(struct prueth *prueth, struct prueth_emac *emac,
+		 int slice);
+int emac_set_port_state(struct prueth_emac *emac,
+			enum icssg_port_state_cmd state);
+void icssg_config_set_speed(struct prueth_emac *emac);
+void icssg_config_half_duplex(struct prueth_emac *emac);
+
+int icssg_send_fdb_msg(struct prueth_emac *emac, struct mgmt_cmd *cmd,
+		       struct mgmt_cmd_rsp *rsp);
+int icssg_fdb_add_del(struct prueth_emac *emac,  const unsigned char *addr,
+		      u8 vid, u8 fid_c2, bool add);
+int icssg_fdb_lookup(struct prueth_emac *emac, const unsigned char *addr,
+		     u8 vid);
+void icssg_vtbl_modify(struct prueth_emac *emac, u8 vid, u8 port_mask,
+		       u8 untag_mask, bool add);
+u16 icssg_get_pvid(struct prueth_emac *emac);
+void icssg_set_pvid(struct prueth *prueth, u8 vid, u8 port);
+int emac_fdb_erase_all(struct prueth_emac *emac);
+int emac_fdb_flush_multicast(struct prueth_emac *emac);
+int emac_fdb_flow_id_updated(struct prueth_emac *emac);
+#define prueth_napi_to_tx_chn(pnapi) \
+	container_of(pnapi, struct prueth_tx_chn, napi_tx)
+
+u64 prueth_iep_gettime(void *clockops_data, struct ptp_system_timestamp *sts);
+void emac_stats_work_handler(struct work_struct *work);
+#endif /* __NET_TI_ICSSG_PRUETH_H */
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_qos.c b/drivers/net/ethernet/ti/icssg_qos.c
--- a/drivers/net/ethernet/ti/icssg_qos.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_qos.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,468 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Texas Instruments ICSSG PRUETH QoS submodule
+ * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include <linux/printk.h>
+#include "icssg_prueth.h"
+#include "icssg_switch_map.h"
+
+/* in msec */
+#define ICSSG_IET_FPE_VERIFY_TIMEOUT_MS	1000
+
+static void icssg_qos_tas_init(struct net_device *ndev);
+static void icssg_prueth_iet_fpe_disable(struct prueth_qos_iet *iet);
+static int icssg_prueth_iet_fpe_enable(struct prueth_emac *emac);
+static void icssg_prueth_iet_fpe_disable(struct prueth_qos_iet *iet);
+static void icssg_qos_enable_ietfpe(struct work_struct *work);
+
+void icssg_qos_init(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+
+	icssg_qos_tas_init(ndev);
+
+	if (!iet->fpe_configured)
+		return;
+
+	/* Init work queue for IET MAC verify process */
+	iet->emac = emac;
+	INIT_WORK(&iet->fpe_config_task, icssg_qos_enable_ietfpe);
+	init_completion(&iet->fpe_config_compl);
+
+	/* As worker may be sleeping, check this flag to abort
+	 * as soon as it comes of out of sleep and cancel the
+	 * fpe config task.
+	 */
+	atomic_set(&iet->cancel_fpe_config, 0);
+}
+
+static void tas_update_fw_list_pointers(struct prueth_emac *emac)
+{
+	struct tas_config *tas = &emac->qos.tas.config;
+
+	if ((readb(tas->active_list)) == TAS_LIST0) {
+		tas->firmware_active_list = emac->dram.va + TAS_GATE_MASK_LIST0;
+		tas->firmware_shadow_list = emac->dram.va + TAS_GATE_MASK_LIST1;
+	} else {
+		tas->firmware_active_list = emac->dram.va + TAS_GATE_MASK_LIST1;
+		tas->firmware_shadow_list = emac->dram.va + TAS_GATE_MASK_LIST0;
+	}
+}
+
+void icssg_qos_link_up(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+
+	if (!iet->fpe_configured)
+		return;
+
+	icssg_prueth_iet_fpe_enable(emac);
+}
+
+void icssg_qos_link_down(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+
+	if (iet->fpe_configured)
+		icssg_prueth_iet_fpe_disable(iet);
+}
+static void tas_update_maxsdu_table(struct prueth_emac *emac)
+{
+	struct tas_config *tas = &emac->qos.tas.config;
+	u16 *max_sdu_tbl_ptr;
+	u8 gate_idx;
+
+	/* update the maxsdu table */
+	max_sdu_tbl_ptr = emac->dram.va + TAS_QUEUE_MAX_SDU_LIST;
+
+	for (gate_idx = 0; gate_idx < TAS_MAX_NUM_QUEUES; gate_idx++)
+		writew(tas->max_sdu_table.max_sdu[gate_idx], &max_sdu_tbl_ptr[gate_idx]);
+}
+
+static void tas_reset(struct prueth_emac *emac)
+{
+	struct tas_config *tas = &emac->qos.tas.config;
+	int i;
+
+	for (i = 0; i < TAS_MAX_NUM_QUEUES; i++)
+		tas->max_sdu_table.max_sdu[i] = 2048;
+
+	tas_update_maxsdu_table(emac);
+
+	writeb(TAS_LIST0, tas->active_list);
+
+	memset_io(tas->firmware_active_list, 0, sizeof(*tas->firmware_active_list));
+	memset_io(tas->firmware_shadow_list, 0, sizeof(*tas->firmware_shadow_list));
+}
+
+static int tas_set_state(struct prueth_emac *emac, enum tas_state state)
+{
+	struct tas_config *tas = &emac->qos.tas.config;
+	int ret;
+
+	if (tas->state == state)
+		return 0;
+
+	switch (state) {
+	case TAS_STATE_RESET:
+		tas_reset(emac);
+		ret = emac_set_port_state(emac, ICSSG_EMAC_PORT_TAS_RESET);
+		tas->state = TAS_STATE_RESET;
+		break;
+	case TAS_STATE_ENABLE:
+		ret = emac_set_port_state(emac, ICSSG_EMAC_PORT_TAS_ENABLE);
+		tas->state = TAS_STATE_ENABLE;
+		break;
+	case TAS_STATE_DISABLE:
+		ret = emac_set_port_state(emac, ICSSG_EMAC_PORT_TAS_DISABLE);
+		tas->state = TAS_STATE_DISABLE;
+		break;
+	default:
+		netdev_err(emac->ndev, "%s: unsupported state\n", __func__);
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret)
+		netdev_err(emac->ndev, "TAS set state failed %d\n", ret);
+	return ret;
+}
+
+static int tas_set_trigger_list_change(struct prueth_emac *emac)
+{
+	struct tc_taprio_qopt_offload *admin_list = emac->qos.tas.taprio_admin;
+	struct tas_config *tas = &emac->qos.tas.config;
+	struct ptp_system_timestamp sts;
+	u32 change_cycle_count;
+	u32 cycle_time;
+	u64 base_time;
+	u64 cur_time;
+
+	cycle_time = admin_list->cycle_time - 4; /* -4ns to compensate for IEP wraparound time */
+	base_time = admin_list->base_time;
+	cur_time = prueth_iep_gettime(emac, &sts);
+
+	if (base_time > cur_time)
+		change_cycle_count = DIV_ROUND_UP_ULL(base_time - cur_time, cycle_time);
+	else
+		change_cycle_count = 1;
+
+	writel(cycle_time, emac->dram.va + TAS_ADMIN_CYCLE_TIME);
+	writel(change_cycle_count, emac->dram.va + TAS_CONFIG_CHANGE_CYCLE_COUNT);
+	writeb(admin_list->num_entries, emac->dram.va + TAS_ADMIN_LIST_LENGTH);
+
+	/* config_change cleared by f/w to ack reception of new shadow list */
+	writeb(1, &tas->config_list->config_change);
+	/* config_pending cleared by f/w when new shadow list is copied to active list */
+	writeb(1, &tas->config_list->config_pending);
+
+	return emac_set_port_state(emac, ICSSG_EMAC_PORT_TAS_TRIGGER);
+}
+
+static int tas_update_oper_list(struct prueth_emac *emac)
+{
+	struct tas_config *tas = &emac->qos.tas.config;
+	struct tc_taprio_qopt_offload *admin_list = emac->qos.tas.taprio_admin;
+	int ret;
+	u8 win_idx, gate_idx, val;
+	u32 tas_acc_gate_close_time = 0;
+
+	tas_update_fw_list_pointers(emac);
+
+	for (win_idx = 0; win_idx < admin_list->num_entries; win_idx++) {
+		tas->firmware_shadow_list->gate_mask_list[win_idx] = admin_list->entries[win_idx].gate_mask;
+		tas_acc_gate_close_time += admin_list->entries[win_idx].interval;
+
+		/* extend last entry till end of cycle time */
+		if (win_idx == admin_list->num_entries - 1)
+			tas->firmware_shadow_list->window_end_time_list[win_idx] = admin_list->cycle_time;
+		else
+			tas->firmware_shadow_list->window_end_time_list[win_idx] = tas_acc_gate_close_time;
+	}
+
+	/* clear remaining entries */
+	for (win_idx = admin_list->num_entries; win_idx < TAS_MAX_CMD_LISTS; win_idx++) {
+		tas->firmware_shadow_list->gate_mask_list[win_idx] = 0;
+		tas->firmware_shadow_list->window_end_time_list[win_idx] = 0;
+	}
+
+	/* update the Array of gate close time for each queue in each window */
+	for (win_idx = 0 ; win_idx < admin_list->num_entries; win_idx++) {
+		/* On Linux, only PRUETH_MAX_TX_QUEUES are supported per port */
+		for (gate_idx = 0; gate_idx < PRUETH_MAX_TX_QUEUES; gate_idx++) {
+			u32 gate_close_time = 0;
+
+			if (tas->firmware_shadow_list->gate_mask_list[win_idx] & BIT(gate_idx))
+				gate_close_time = tas->firmware_shadow_list->window_end_time_list[win_idx];
+
+			tas->firmware_shadow_list->gate_close_time_list[win_idx][gate_idx] = gate_close_time;
+		}
+	}
+
+	/* tell f/w to swap active & shadow list */
+	ret = tas_set_trigger_list_change(emac);
+	if (ret) {
+		netdev_err(emac->ndev, "failed to swap f/w config list: %d\n", ret);
+		return ret;
+	}
+
+	/* Wait for completion */
+	ret = readb_poll_timeout(&tas->config_list->config_change, val, !val,
+				 USEC_PER_MSEC, 10 * USEC_PER_MSEC);
+	if (ret) {
+		netdev_err(emac->ndev, "TAS list change completion time out\n");
+		return ret;
+	}
+
+	tas_update_fw_list_pointers(emac);
+
+	return 0;
+}
+
+static int emac_set_taprio(struct prueth_emac *emac)
+{
+	int ret;
+	struct tc_taprio_qopt_offload *taprio = emac->qos.tas.taprio_admin;
+
+	if (!taprio->enable)
+		return tas_set_state(emac, TAS_STATE_DISABLE);
+
+	ret = tas_update_oper_list(emac);
+	if (ret)
+		return ret;
+
+	return tas_set_state(emac, TAS_STATE_ENABLE);
+}
+
+static void emac_cp_taprio(struct tc_taprio_qopt_offload *from,
+			   struct tc_taprio_qopt_offload *to)
+{
+	int i;
+
+	*to = *from;
+	for (i = 0; i < from->num_entries; i++)
+		to->entries[i] = from->entries[i];
+}
+
+static int emac_setup_taprio(struct net_device *ndev, struct tc_taprio_qopt_offload *taprio)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct tc_taprio_qopt_offload *est_new;
+	int ret, win_idx;
+
+	if (!netif_running(ndev)) {
+		netdev_err(ndev, "interface is down, link speed unknown\n");
+		return -ENETDOWN;
+	}
+
+	if (taprio->cycle_time_extension) {
+		netdev_err(ndev, "Failed to set cycle time extension");
+		return -EOPNOTSUPP;
+	}
+
+	if (taprio->num_entries == 0 ||
+	    taprio->num_entries > TAS_MAX_CMD_LISTS) {
+		netdev_err(ndev, "unsupported num_entries %ld in taprio config\n",
+			   taprio->num_entries);
+		return -EINVAL;
+	}
+
+	/* If any time_interval is 0 in between the list, then exit */
+	for (win_idx = 0; win_idx < taprio->num_entries; win_idx++) {
+		if (taprio->entries[win_idx].interval == 0) {
+			netdev_err(ndev, "0 interval in taprio config not supported\n");
+			return -EINVAL;
+		}
+	}
+
+	if (emac->qos.tas.taprio_admin)
+		devm_kfree(&ndev->dev, emac->qos.tas.taprio_admin);
+
+	est_new = devm_kzalloc(&ndev->dev,
+			       struct_size(est_new, entries, taprio->num_entries),
+			       GFP_KERNEL);
+	emac_cp_taprio(taprio, est_new);
+	emac->qos.tas.taprio_admin = est_new;
+	ret = emac_set_taprio(emac);
+	if (ret)
+		devm_kfree(&ndev->dev, est_new);
+
+	return ret;
+}
+
+int icssg_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type,
+			   void *type_data)
+{
+	switch (type) {
+	case TC_SETUP_QDISC_TAPRIO:
+		return emac_setup_taprio(ndev, type_data);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void icssg_qos_tas_init(struct net_device *ndev)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct tas_config *tas = &emac->qos.tas.config;
+	bool need_setup = false;
+
+	if (tas->state == TAS_STATE_ENABLE)
+		need_setup = true;
+
+	tas->config_list = emac->dram.va + TAS_CONFIG_CHANGE_TIME;
+	tas->active_list = emac->dram.va + TAS_ACTIVE_LIST_INDEX;
+
+	tas_update_fw_list_pointers(emac);
+
+	tas_set_state(emac, TAS_STATE_RESET);
+
+	if (need_setup)
+		emac_set_taprio(emac);
+}
+
+static int icssg_config_ietfpe(struct prueth_qos_iet *iet, bool enable)
+{
+	void *config = iet->emac->dram.va + ICSSG_CONFIG_OFFSET;
+	u8 val;
+	int ret, i;
+
+	/* If FPE is to be enabled, first configure MAC Verify state
+	 * machine in firmware as firmware kicks the Verify process
+	 * as soon as ICSSG_EMAC_PORT_PREMPT_TX_ENABLE command is
+	 * received.
+	 */
+	if (enable && iet->mac_verify_configured) {
+		writeb(1, config + PRE_EMPTION_ENABLE_VERIFY);
+		/* should be a multiple of 64. TODO to configure
+		 * through ethtool.
+		 */
+		writew(64, config + PRE_EMPTION_ADD_FRAG_SIZE_LOCAL);
+		writel(ICSSG_IET_FPE_VERIFY_TIMEOUT_MS, config + PRE_EMPTION_VERIFY_TIME);
+	}
+
+	/* Send command to enable FPE Tx side. Rx is always enabled */
+	ret = emac_set_port_state(iet->emac,
+				  enable ? ICSSG_EMAC_PORT_PREMPT_TX_ENABLE :
+					   ICSSG_EMAC_PORT_PREMPT_TX_DISABLE);
+	if (ret) {
+		netdev_err(iet->emac->ndev, "TX pre-empt %s command failed\n",
+			   enable ? "enable" : "disable");
+		writeb(0, config + PRE_EMPTION_ENABLE_VERIFY);
+		return ret;
+	}
+
+	/* Update FPE Tx enable bit. Assume firmware use this bit
+	 * and enable PRE_EMPTION_ACTIVE_TX if everything looks
+	 * good at firmware
+	 */
+	writeb(enable ? 1 : 0, config + PRE_EMPTION_ENABLE_TX);
+
+	if (enable && iet->mac_verify_configured) {
+		ret = readb_poll_timeout(config + PRE_EMPTION_VERIFY_STATUS, val,
+					 (val == ICSSG_IETFPE_STATE_SUCCEEDED),
+					 USEC_PER_MSEC, 5 * USEC_PER_SEC);
+		if (ret == -ETIMEDOUT) {
+			netdev_err(iet->emac->ndev,
+				   "timeout for MAC Verify: status %x\n",
+				   val);
+			return ret;
+		}
+	} else {
+		/* Give f/w some time to update PRE_EMPTION_ACTIVE_TX state */
+		usleep_range(100, 200);
+	}
+
+	if (enable) {
+		val = readb(config + PRE_EMPTION_ACTIVE_TX);
+		if (val != 1) {
+			netdev_err(iet->emac->ndev,
+				   "F/w fails to activate IET/FPE\n");
+			writeb(0, config + PRE_EMPTION_ENABLE_TX);
+			return -ENODEV;
+		}
+	} else {
+		return ret;
+	}
+
+	/* Configure highest queue as express. Set Bit 4 for FPE,
+	 * Reset for express
+	 */
+
+	/* first set all 8 queues as Pre-emptive */
+	for (i = 0; i < PRUETH_MAX_TX_QUEUES * PRUETH_NUM_MACS; i++)
+		writeb(BIT(4), config + EXPRESS_PRE_EMPTIVE_Q_MAP + i);
+
+	/* set highest priority channel queue as express */
+	writeb(0, config + EXPRESS_PRE_EMPTIVE_Q_MAP + iet->emac->tx_ch_num - 1);
+
+	/* set up queue mask for FPE. 1 means express */
+	writeb(BIT(iet->emac->tx_ch_num - 1), config + EXPRESS_PRE_EMPTIVE_Q_MASK);
+
+	iet->fpe_enabled = true;
+
+	return ret;
+}
+
+static void icssg_qos_enable_ietfpe(struct work_struct *work)
+{
+	struct prueth_qos_iet *iet =
+		container_of(work, struct prueth_qos_iet, fpe_config_task);
+	int ret;
+
+	/* Set the required flag and send a command to ICSSG firmware to
+	 * enable FPE and start MAC verify
+	 */
+	ret = icssg_config_ietfpe(iet, true);
+
+	/* if verify configured, poll for the status and complete.
+	 * Or just do completion
+	 */
+	if (!ret)
+		netdev_err(iet->emac->ndev, "IET FPE configured successfully\n");
+	else
+		netdev_err(iet->emac->ndev, "IET FPE config error\n");
+	complete(&iet->fpe_config_compl);
+}
+
+static void icssg_prueth_iet_fpe_disable(struct prueth_qos_iet *iet)
+{
+	int ret;
+
+	atomic_set(&iet->cancel_fpe_config, 1);
+	cancel_work_sync(&iet->fpe_config_task);
+	ret = icssg_config_ietfpe(iet, false);
+	if (!ret)
+		netdev_err(iet->emac->ndev, "IET FPE disabled successfully\n");
+	else
+		netdev_err(iet->emac->ndev, "IET FPE disable failed\n");
+}
+
+static int icssg_prueth_iet_fpe_enable(struct prueth_emac *emac)
+{
+	struct prueth_qos_iet *iet = &emac->qos.iet;
+	int ret;
+
+	/* Schedule MAC Verify and enable IET FPE if configured */
+	atomic_set(&iet->cancel_fpe_config, 0);
+	reinit_completion(&iet->fpe_config_compl);
+	schedule_work(&iet->fpe_config_task);
+	/* By trial, found it takes about 1.5s. So
+	 * wait for 10s
+	 */
+	ret = wait_for_completion_timeout(&iet->fpe_config_compl,
+					  msecs_to_jiffies(10000));
+	if (!ret) {
+		netdev_err(emac->ndev,
+			   "IET verify completion timeout\n");
+		/* cancel verify in progress */
+		atomic_set(&iet->cancel_fpe_config, 1);
+		cancel_work_sync(&iet->fpe_config_task);
+	}
+
+	return ret;
+}
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_qos.h b/drivers/net/ethernet/ti/icssg_qos.h
--- a/drivers/net/ethernet/ti/icssg_qos.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_qos.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#ifndef __NET_TI_ICSSG_QOS_H
+#define __NET_TI_ICSSG_QOS_H
+
+#include <linux/atomic.h>
+#include <linux/netdevice.h>
+#include <net/pkt_sched.h>
+
+/**
+ * Maximum number of gate command entries in each list.
+ */
+#define TAS_MAX_CMD_LISTS   (16)
+
+/**
+ * Maximum number of transmit queues supported by implementation
+ */
+#define TAS_MAX_NUM_QUEUES  (8)
+
+/**
+ * Minimum cycle time supported by implementation (in ns)
+ */
+#define TAS_MIN_CYCLE_TIME  (1000000)
+
+/**
+ * Minimum TAS window duration supported by implementation (in ns)
+ */
+#define TAS_MIN_WINDOW_DURATION  (10000)
+
+/**
+ * List number 0 or 1. Also the value at memory location TAS_ACTIVE_LIST_INDEX
+ */
+enum tas_list_num {
+	TAS_LIST0 = 0,
+	TAS_LIST1 = 1
+};
+
+/**
+ * state of TAS in f/w
+ */
+enum tas_state {
+	/* PRU's are idle */
+	TAS_STATE_DISABLE = 0,
+	/* Enable TAS */
+	TAS_STATE_ENABLE = 1,
+	/* Firmware will reset the state machine */
+	TAS_STATE_RESET = 2,
+};
+
+/**
+ * Config state machine variables. See IEEE Std 802.1Q-2018 8.6.8.4
+ */
+struct tas_config_list {
+	/* New list is copied at this time */
+	u64 config_change_time;
+	/* config change error counter, incremented if
+	 * admin->BaseTime < current time and TAS_enabled is true
+	 */
+	u32 config_change_error_counter;
+	/* True if list update is pending */
+	u8 config_pending;
+	/* Set to true when application trigger updating of admin list
+	 * to active list, cleared when configChangeTime is updated
+	 */
+	u8 config_change;
+};
+
+/**
+ * Max SDU table. See IEEE Std 802.1Q-2018 12.29.1.1
+ */
+struct tas_max_sdu_table {
+	u16 max_sdu[TAS_MAX_NUM_QUEUES];
+};
+
+/**
+ * TAS List Structure based on firmware memory map
+ */
+struct tas_firmware_list {
+	/* window gate mask list */
+	u8 gate_mask_list[TAS_MAX_CMD_LISTS];
+	/* window end time list */
+	u32 window_end_time_list[TAS_MAX_CMD_LISTS];
+	/* Array of gate close time for each queue in each window */
+	u32 gate_close_time_list[TAS_MAX_CMD_LISTS][TAS_MAX_NUM_QUEUES];
+};
+
+/**
+ * Main Time Aware Shaper Handle
+ */
+struct tas_config {
+	enum tas_state state;
+	struct tas_max_sdu_table max_sdu_table;
+	/* Config change variables */
+	struct __iomem tas_config_list * config_list;
+	/* Whether list 1 or list 2 is the operating list */
+	u8 __iomem *active_list;
+	/* active List pointer, used by firmware */
+	struct __iomem tas_firmware_list * firmware_active_list;
+	/* shadow List pointer, used by driver */
+	struct __iomem tas_firmware_list * firmware_shadow_list;
+};
+
+struct prueth_qos_tas {
+	struct tc_taprio_qopt_offload *taprio_admin;
+	struct tc_taprio_qopt_offload *taprio_oper;
+	struct tas_config config;
+};
+
+struct prueth_qos_iet {
+	struct work_struct fpe_config_task;
+	struct completion fpe_config_compl;
+	struct prueth_emac *emac;
+	atomic_t cancel_fpe_config;
+	/* Set through priv flags to enable IET frame preemption */
+	bool fpe_configured;
+	/* Set if IET FPE is active */
+	bool fpe_enabled;
+	/* Set through priv flags to enable IET MAC Verify state machine
+	 * in firmware
+	 */
+	bool mac_verify_configured;
+};
+
+struct prueth_qos {
+	struct prueth_qos_iet iet;
+	struct prueth_qos_tas tas;
+};
+
+void icssg_qos_init(struct net_device *ndev);
+int icssg_qos_ndo_setup_tc(struct net_device *ndev, enum tc_setup_type type,
+			   void *type_data);
+void icssg_qos_link_up(struct net_device *ndev);
+void icssg_qos_link_down(struct net_device *ndev);
+#endif /* __NET_TI_ICSSG_QOS_H */
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_queues.c b/drivers/net/ethernet/ti/icssg_queues.c
--- a/drivers/net/ethernet/ti/icssg_queues.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_queues.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+/* ICSSG Buffer queue helpers
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com
+ */
+
+#include <linux/regmap.h>
+#include "icssg_prueth.h"
+
+#define ICSSG_QUEUES_MAX		64
+#define ICSSG_QUEUE_OFFSET		0xd00
+#define ICSSG_QUEUE_PEEK_OFFSET		0xe00
+#define ICSSG_QUEUE_CNT_OFFSET		0xe40
+#define	ICSSG_QUEUE_RESET_OFFSET	0xf40
+
+int icssg_queue_pop(struct prueth *prueth, u8 queue)
+{
+	u32 val, cnt;
+
+	if (queue >= ICSSG_QUEUES_MAX)
+		return -EINVAL;
+
+	regmap_read(prueth->miig_rt, ICSSG_QUEUE_CNT_OFFSET + 4 * queue, &cnt);
+	if (!cnt)
+		return -EINVAL;
+
+	regmap_read(prueth->miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue, &val);
+
+	return val;
+}
+
+void icssg_queue_push(struct prueth *prueth, int queue, u16 addr)
+{
+	if (queue >= ICSSG_QUEUES_MAX)
+		return;
+
+	regmap_write(prueth->miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue, addr);
+}
+
+u32 icssg_queue_level(struct prueth *prueth, int queue)
+{
+	u32 reg;
+
+	if (queue >= ICSSG_QUEUES_MAX)
+		return 0;
+
+	regmap_read(prueth->miig_rt, ICSSG_QUEUE_CNT_OFFSET + 4 * queue, &reg);
+
+	return reg;
+}
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_switchdev.c b/drivers/net/ethernet/ti/icssg_switchdev.c
--- a/drivers/net/ethernet/ti/icssg_switchdev.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_switchdev.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,477 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* Texas Instruments K3 ICSSG Ethernet Switchdev Driver
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/if_bridge.h>
+#include <linux/netdevice.h>
+#include <linux/workqueue.h>
+#include <net/switchdev.h>
+
+#include "icssg_prueth.h"
+#include "icssg_switchdev.h"
+#include "icssg_mii_rt.h"
+
+struct prueth_switchdev_event_work {
+	struct work_struct work;
+	struct switchdev_notifier_fdb_info fdb_info;
+	struct prueth_emac *emac;
+	unsigned long event;
+};
+
+static int prueth_switchdev_stp_state_set(struct prueth_emac *emac,
+					  u8 state)
+{
+	enum icssg_port_state_cmd emac_state;
+	int ret = 0;
+
+	switch (state) {
+	case BR_STATE_FORWARDING:
+		emac_state = ICSSG_EMAC_PORT_FORWARD;
+		break;
+	case BR_STATE_DISABLED:
+		emac_state = ICSSG_EMAC_PORT_DISABLE;
+		break;
+	case BR_STATE_LEARNING:
+	case BR_STATE_LISTENING:
+	case BR_STATE_BLOCKING:
+		emac_state = ICSSG_EMAC_PORT_BLOCK;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	emac_set_port_state(emac, emac_state);
+	netdev_dbg(emac->ndev, "STP state: %u\n", emac_state);
+
+	return ret;
+}
+
+static int prueth_switchdev_attr_br_flags_set(struct prueth_emac *emac,
+					      struct net_device *orig_dev,
+					      struct switchdev_brport_flags brport_flags)
+{
+	enum icssg_port_state_cmd emac_state;
+
+	if (brport_flags.mask & BR_MCAST_FLOOD)
+		emac_state = ICSSG_EMAC_PORT_MC_FLOODING_ENABLE;
+	else
+		emac_state = ICSSG_EMAC_PORT_MC_FLOODING_DISABLE;
+
+	netdev_dbg(emac->ndev, "BR_MCAST_FLOOD: %d port %u\n",
+		   emac_state, emac->port_id);
+
+	emac_set_port_state(emac, emac_state);
+
+	return 0;
+}
+
+static int prueth_switchdev_attr_br_flags_pre_set(struct net_device *netdev,
+						  struct switchdev_brport_flags brport_flags)
+{
+	if (brport_flags.mask & ~(BR_LEARNING | BR_MCAST_FLOOD))
+		return -EINVAL;
+
+	return 0;
+}
+
+static int prueth_switchdev_attr_set(struct net_device *ndev, const void *ctx,
+				     const struct switchdev_attr *attr,
+				     struct netlink_ext_ack *extack)
+{
+	struct prueth_emac *emac = netdev_priv(ndev);
+	int ret;
+
+	netdev_dbg(ndev, "attr: id %u port: %u\n", attr->id, emac->port_id);
+
+	switch (attr->id) {
+	case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
+		ret = prueth_switchdev_attr_br_flags_pre_set(ndev,
+							     attr->u.brport_flags);
+		break;
+	case SWITCHDEV_ATTR_ID_PORT_STP_STATE:
+		ret = prueth_switchdev_stp_state_set(emac,
+						     attr->u.stp_state);
+		netdev_dbg(ndev, "stp state: %u\n", attr->u.stp_state);
+		break;
+	case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
+		ret = prueth_switchdev_attr_br_flags_set(emac, attr->orig_dev,
+							 attr->u.brport_flags);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
+
+static void prueth_switchdev_fdb_offload_notify(struct net_device *ndev,
+						struct switchdev_notifier_fdb_info *rcv)
+{
+	struct switchdev_notifier_fdb_info info;
+
+	memset(&info, 0, sizeof(info));
+	info.addr = rcv->addr;
+	info.vid = rcv->vid;
+	info.offloaded = true;
+	call_switchdev_notifiers(SWITCHDEV_FDB_OFFLOADED,
+				 ndev, &info.info, NULL);
+}
+
+static void prueth_switchdev_event_work(struct work_struct *work)
+{
+	struct prueth_switchdev_event_work *switchdev_work =
+		container_of(work, struct prueth_switchdev_event_work, work);
+	struct prueth_emac *emac = switchdev_work->emac;
+	struct switchdev_notifier_fdb_info *fdb;
+	int port_id = emac->port_id;
+	int ret;
+
+	rtnl_lock();
+	switch (switchdev_work->event) {
+	case SWITCHDEV_FDB_ADD_TO_DEVICE:
+		fdb = &switchdev_work->fdb_info;
+
+		netdev_dbg(emac->ndev, "prueth_fdb_add: MACID = %pM vid = %u flags = %u %u -- port %d\n",
+			   fdb->addr, fdb->vid, fdb->added_by_user,
+			   fdb->offloaded, port_id);
+
+		if (!fdb->added_by_user)
+			break;
+		if (memcmp(emac->mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
+			break;
+
+		ret = icssg_fdb_add_del(emac, fdb->addr, fdb->vid,
+					BIT(port_id), true);
+		if (!ret)
+			prueth_switchdev_fdb_offload_notify(emac->ndev, fdb);
+		break;
+	case SWITCHDEV_FDB_DEL_TO_DEVICE:
+		fdb = &switchdev_work->fdb_info;
+
+		netdev_dbg(emac->ndev, "prueth_fdb_del: MACID = %pM vid = %u flags = %u %u -- port %d\n",
+			   fdb->addr, fdb->vid, fdb->added_by_user,
+			   fdb->offloaded, port_id);
+
+		if (!fdb->added_by_user)
+			break;
+		if (memcmp(emac->mac_addr, (u8 *)fdb->addr, ETH_ALEN) == 0)
+			break;
+		icssg_fdb_add_del(emac, fdb->addr, fdb->vid,
+				  BIT(port_id), false);
+		break;
+	default:
+		break;
+	}
+	rtnl_unlock();
+
+	kfree(switchdev_work->fdb_info.addr);
+	kfree(switchdev_work);
+	dev_put(emac->ndev);
+}
+
+static int prueth_switchdev_event(struct notifier_block *unused,
+				  unsigned long event, void *ptr)
+{
+	struct net_device *ndev = switchdev_notifier_info_to_dev(ptr);
+	struct prueth_switchdev_event_work *switchdev_work;
+	struct prueth_emac *emac = netdev_priv(ndev);
+	struct switchdev_notifier_fdb_info *fdb_info = ptr;
+	int err;
+
+	if (!prueth_dev_check(ndev))
+		return NOTIFY_DONE;
+
+	if (event == SWITCHDEV_PORT_ATTR_SET) {
+		err = switchdev_handle_port_attr_set(ndev, ptr,
+						     prueth_dev_check,
+						     prueth_switchdev_attr_set);
+		return notifier_from_errno(err);
+	}
+
+	switchdev_work = kzalloc(sizeof(*switchdev_work), GFP_ATOMIC);
+	if (WARN_ON(!switchdev_work))
+		return NOTIFY_BAD;
+
+	INIT_WORK(&switchdev_work->work, prueth_switchdev_event_work);
+	switchdev_work->emac = emac;
+	switchdev_work->event = event;
+
+	switch (event) {
+	case SWITCHDEV_FDB_ADD_TO_DEVICE:
+	case SWITCHDEV_FDB_DEL_TO_DEVICE:
+		memcpy(&switchdev_work->fdb_info, ptr,
+		       sizeof(switchdev_work->fdb_info));
+		switchdev_work->fdb_info.addr = kzalloc(ETH_ALEN, GFP_ATOMIC);
+		if (!switchdev_work->fdb_info.addr)
+			goto err_addr_alloc;
+		ether_addr_copy((u8 *)switchdev_work->fdb_info.addr,
+				fdb_info->addr);
+		dev_hold(ndev);
+		break;
+	default:
+		kfree(switchdev_work);
+		return NOTIFY_DONE;
+	}
+
+	queue_work(system_long_wq, &switchdev_work->work);
+
+	return NOTIFY_DONE;
+
+err_addr_alloc:
+	kfree(switchdev_work);
+	return NOTIFY_BAD;
+}
+
+static int prueth_switchdev_vlan_add(struct prueth_emac *emac, bool untag, bool pvid,
+				     u8 vid, struct net_device *orig_dev)
+{
+	bool cpu_port = netif_is_bridge_master(orig_dev);
+	int untag_mask = 0;
+	int port_mask;
+	int ret = 0;
+
+	if (cpu_port)
+		port_mask = BIT(PRUETH_PORT_HOST);
+	else
+		port_mask = BIT(emac->port_id);
+
+	if (untag)
+		untag_mask = port_mask;
+
+	icssg_vtbl_modify(emac, vid, port_mask, untag_mask, true);
+
+	netdev_dbg(emac->ndev, "VID add vid:%u port_mask:%X untag_mask %X PVID %d\n",
+		   vid, port_mask, untag_mask, pvid);
+
+	if (!pvid)
+		return ret;
+
+	icssg_set_pvid(emac->prueth, vid, emac->port_id);
+
+	return ret;
+}
+
+static int prueth_switchdev_vlan_del(struct prueth_emac *emac, u16 vid,
+				     struct net_device *orig_dev)
+{
+	bool cpu_port = netif_is_bridge_master(orig_dev);
+	int port_mask;
+	int ret = 0;
+
+	if (cpu_port)
+		port_mask = BIT(PRUETH_PORT_HOST);
+	else
+		port_mask = BIT(emac->port_id);
+
+	icssg_vtbl_modify(emac, vid, port_mask, 0, false);
+
+	if (cpu_port)
+		icssg_fdb_add_del(emac, emac->mac_addr, vid,
+				  BIT(PRUETH_PORT_HOST), false);
+
+	if (vid == icssg_get_pvid(emac))
+		icssg_set_pvid(emac->prueth, 0, emac->port_id);
+
+	netdev_dbg(emac->ndev, "VID del vid:%u port_mask:%X\n",
+		   vid, port_mask);
+
+	return ret;
+}
+
+static int prueth_switchdev_vlans_add(struct prueth_emac *emac,
+				      const struct switchdev_obj_port_vlan *vlan)
+{
+	bool untag = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
+	struct net_device *orig_dev = vlan->obj.orig_dev;
+	bool cpu_port = netif_is_bridge_master(orig_dev);
+	bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
+
+	netdev_dbg(emac->ndev, "VID add vid:%u flags:%X\n",
+		   vlan->vid, vlan->flags);
+
+	if (cpu_port && !(vlan->flags & BRIDGE_VLAN_INFO_BRENTRY))
+		return 0;
+
+	if (vlan->vid > 0xff)
+		return 0;
+
+	return prueth_switchdev_vlan_add(emac, untag, pvid, vlan->vid,
+					 orig_dev);
+}
+
+static int prueth_switchdev_vlans_del(struct prueth_emac *emac,
+				      const struct switchdev_obj_port_vlan *vlan)
+
+{
+	if (vlan->vid > 0xff)
+		return 0;
+
+	return prueth_switchdev_vlan_del(emac, vlan->vid,
+					 vlan->obj.orig_dev);
+}
+
+static int prueth_switchdev_mdb_add(struct prueth_emac *emac,
+				    struct switchdev_obj_port_mdb *mdb)
+
+{
+	struct net_device *orig_dev = mdb->obj.orig_dev;
+	bool cpu_port = netif_is_bridge_master(orig_dev);
+	u8 port_mask, fid_c2;
+	int err;
+
+	if (cpu_port)
+		port_mask = BIT(PRUETH_PORT_HOST);
+	else
+		port_mask = BIT(emac->port_id);
+
+	fid_c2 = icssg_fdb_lookup(emac, mdb->addr, mdb->vid);
+
+	err = icssg_fdb_add_del(emac, mdb->addr, mdb->vid, fid_c2 | port_mask, true);
+	netdev_dbg(emac->ndev, "MDB add vid %u:%pM  ports: %X\n",
+		   mdb->vid, mdb->addr, port_mask);
+
+	return err;
+}
+
+static int prueth_switchdev_mdb_del(struct prueth_emac *emac,
+				    struct switchdev_obj_port_mdb *mdb)
+
+{
+	struct net_device *orig_dev = mdb->obj.orig_dev;
+	bool cpu_port = netif_is_bridge_master(orig_dev);
+	int del_mask, ret, fid_c2;
+
+	if (cpu_port)
+		del_mask = BIT(PRUETH_PORT_HOST);
+	else
+		del_mask = BIT(emac->port_id);
+
+	fid_c2 = icssg_fdb_lookup(emac, mdb->addr, mdb->vid);
+
+	if (fid_c2 & ~del_mask)
+		ret = icssg_fdb_add_del(emac, mdb->addr, mdb->vid, fid_c2 & ~del_mask, true);
+	else
+		ret = icssg_fdb_add_del(emac, mdb->addr, mdb->vid, 0, false);
+
+	netdev_dbg(emac->ndev, "MDB del vid %u:%pM  ports: %X\n",
+		   mdb->vid, mdb->addr, del_mask);
+
+	return ret;
+}
+
+static int prueth_switchdev_obj_add(struct net_device *ndev, const void *ctx,
+				    const struct switchdev_obj *obj,
+				    struct netlink_ext_ack *extack)
+{
+	struct switchdev_obj_port_vlan *vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
+	struct switchdev_obj_port_mdb *mdb = SWITCHDEV_OBJ_PORT_MDB(obj);
+	struct prueth_emac *emac = netdev_priv(ndev);
+	int err = 0;
+
+	netdev_dbg(ndev, "obj_add: id %u port: %u\n", obj->id, emac->port_id);
+
+	switch (obj->id) {
+	case SWITCHDEV_OBJ_ID_PORT_VLAN:
+		err = prueth_switchdev_vlans_add(emac, vlan);
+		break;
+	case SWITCHDEV_OBJ_ID_PORT_MDB:
+	case SWITCHDEV_OBJ_ID_HOST_MDB:
+		err = prueth_switchdev_mdb_add(emac, mdb);
+		break;
+	default:
+		err = -EOPNOTSUPP;
+		break;
+	}
+
+	return err;
+}
+
+static int prueth_switchdev_obj_del(struct net_device *ndev, const void *ctx,
+				    const struct switchdev_obj *obj)
+{
+	struct switchdev_obj_port_vlan *vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
+	struct switchdev_obj_port_mdb *mdb = SWITCHDEV_OBJ_PORT_MDB(obj);
+	struct prueth_emac *emac = netdev_priv(ndev);
+	int err = 0;
+
+	netdev_dbg(ndev, "obj_del: id %u port: %u\n", obj->id, emac->port_id);
+
+	switch (obj->id) {
+	case SWITCHDEV_OBJ_ID_PORT_VLAN:
+		err = prueth_switchdev_vlans_del(emac, vlan);
+		break;
+	case SWITCHDEV_OBJ_ID_PORT_MDB:
+	case SWITCHDEV_OBJ_ID_HOST_MDB:
+		err = prueth_switchdev_mdb_del(emac, mdb);
+		break;
+	default:
+		err = -EOPNOTSUPP;
+		break;
+	}
+
+	return err;
+}
+
+static int prueth_switchdev_blocking_event(struct notifier_block *unused,
+					   unsigned long event, void *ptr)
+{
+	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
+	int err;
+
+	switch (event) {
+	case SWITCHDEV_PORT_OBJ_ADD:
+		err = switchdev_handle_port_obj_add(dev, ptr,
+						    prueth_dev_check,
+						    prueth_switchdev_obj_add);
+		return notifier_from_errno(err);
+	case SWITCHDEV_PORT_OBJ_DEL:
+		err = switchdev_handle_port_obj_del(dev, ptr,
+						    prueth_dev_check,
+						    prueth_switchdev_obj_del);
+		return notifier_from_errno(err);
+	case SWITCHDEV_PORT_ATTR_SET:
+		err = switchdev_handle_port_attr_set(dev, ptr,
+						     prueth_dev_check,
+						     prueth_switchdev_attr_set);
+		return notifier_from_errno(err);
+	default:
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+int prueth_switchdev_register_notifiers(struct prueth *prueth)
+{
+	int ret = 0;
+
+	prueth->prueth_switchdev_nb.notifier_call = &prueth_switchdev_event;
+	ret = register_switchdev_notifier(&prueth->prueth_switchdev_nb);
+	if (ret) {
+		dev_err(prueth->dev, "register switchdev notifier fail ret:%d\n",
+			ret);
+		return ret;
+	}
+
+	prueth->prueth_switchdev_bl_nb.notifier_call = &prueth_switchdev_blocking_event;
+	ret = register_switchdev_blocking_notifier(&prueth->prueth_switchdev_bl_nb);
+	if (ret) {
+		dev_err(prueth->dev, "register switchdev blocking notifier ret:%d\n",
+			ret);
+		unregister_switchdev_notifier(&prueth->prueth_switchdev_nb);
+	}
+
+	return ret;
+}
+
+void prueth_switchdev_unregister_notifiers(struct prueth *prueth)
+{
+	unregister_switchdev_blocking_notifier(&prueth->prueth_switchdev_bl_nb);
+	unregister_switchdev_notifier(&prueth->prueth_switchdev_nb);
+}
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_switchdev.h b/drivers/net/ethernet/ti/icssg_switchdev.h
--- a/drivers/net/ethernet/ti/icssg_switchdev.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_switchdev.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
+ */
+#ifndef __NET_TI_ICSSG_SWITCHDEV_H
+#define __NET_TI_ICSSG_SWITCHDEV_H
+
+#include "icssg_prueth.h"
+
+int prueth_switchdev_register_notifiers(struct prueth *prueth);
+void prueth_switchdev_unregister_notifiers(struct prueth *prueth);
+bool prueth_dev_check(const struct net_device *ndev);
+
+#endif /* __NET_TI_ICSSG_SWITCHDEV_H */
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icssg_switch_map.h b/drivers/net/ethernet/ti/icssg_switch_map.h
--- a/drivers/net/ethernet/ti/icssg_switch_map.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icssg_switch_map.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Texas Instruments ICSSG Ethernet driver
+ *
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#ifndef __NET_TI_ICSSG_SWITCH_MAP_H
+#define __NET_TI_ICSSG_SWITCH_MAP_H
+
+/************************* Ethernet Switch Constants *********************/
+
+/* if bucket size is changed in firmware then this too should be changed
+ * because it directly impacts FDB ageing calculation
+ */
+#define NUMBER_OF_FDB_BUCKET_ENTRIES            (4)
+
+/* This is fixed in ICSSG */
+#define SIZE_OF_FDB                             (2048)
+
+#define FW_LINK_SPEED_1G                           (0x00)
+#define FW_LINK_SPEED_100M                         (0x01)
+#define FW_LINK_SPEED_10M                          (0x02)
+#define FW_LINK_SPEED_HD                           (0x80)
+
+/* Time after which FDB entries are checked for aged out values.
+ * Values are in nanoseconds
+ */
+#define FDB_AGEING_TIMEOUT_OFFSET                          0x0014
+
+/* Default VLAN tag for Host Port */
+#define HOST_PORT_DF_VLAN_OFFSET                           0x001C
+
+/* Same as HOST_PORT_DF_VLAN_OFFSET */
+#define EMAC_ICSSG_SWITCH_PORT0_DEFAULT_VLAN_OFFSET        HOST_PORT_DF_VLAN_OFFSET
+
+/* Default VLAN tag for P1 Port */
+#define P1_PORT_DF_VLAN_OFFSET                             0x0020
+
+/* Same as P1_PORT_DF_VLAN_OFFSET */
+#define EMAC_ICSSG_SWITCH_PORT1_DEFAULT_VLAN_OFFSET        P1_PORT_DF_VLAN_OFFSET
+
+/* default VLAN tag for P2 Port */
+#define P2_PORT_DF_VLAN_OFFSET                             0x0024
+
+/* Same as P2_PORT_DF_VLAN_OFFSET */
+#define EMAC_ICSSG_SWITCH_PORT2_DEFAULT_VLAN_OFFSET        P2_PORT_DF_VLAN_OFFSET
+
+/* VLAN-FID Table offset. 4096 VIDs. 2B per VID = 8KB = 0x2000 */
+#define VLAN_STATIC_REG_TABLE_OFFSET                       0x0100
+
+/* VLAN-FID Table offset for EMAC  */
+#define EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET        VLAN_STATIC_REG_TABLE_OFFSET
+
+/* Packet descriptor Q reserved memory */
+#define PORT_DESC0_HI                                      0x2104
+
+/* Packet descriptor Q reserved memory */
+#define PORT_DESC0_LO                                      0x2F6C
+
+/* Packet descriptor Q reserved memory */
+#define PORT_DESC1_HI                                      0x3DD4
+
+/* Packet descriptor Q reserved memory */
+#define PORT_DESC1_LO                                      0x4C3C
+
+/* Packet descriptor Q reserved memory */
+#define HOST_DESC0_HI                                      0x5AA4
+
+/* Packet descriptor Q reserved memory */
+#define HOST_DESC0_LO                                      0x5F0C
+
+/* Packet descriptor Q reserved memory */
+#define HOST_DESC1_HI                                      0x6374
+
+/* Packet descriptor Q reserved memory */
+#define HOST_DESC1_LO                                      0x67DC
+
+/* Special packet descriptor Q reserved memory */
+#define HOST_SPPD0                                         0x7AAC
+
+/* Special acket descriptor Q reserved memory */
+#define HOST_SPPD1                                         0x7EAC
+
+/* _Small_Description_ */
+#define TIMESYNC_FW_WC_CYCLECOUNT_OFFSET                   0x83EC
+
+/* IEP count hi roll over count */
+#define TIMESYNC_FW_WC_HI_ROLLOVER_COUNT_OFFSET            0x83F4
+
+/* _Small_Description_ */
+#define TIMESYNC_FW_WC_COUNT_HI_SW_OFFSET_OFFSET           0x83F8
+
+/* Set clock descriptor */
+#define TIMESYNC_FW_WC_SETCLOCK_DESC_OFFSET                0x83FC
+
+/* _Small_Description_ */
+#define TIMESYNC_FW_WC_SYNCOUT_REDUCTION_FACTOR_OFFSET     0x843C
+
+/* _Small_Description_ */
+#define TIMESYNC_FW_WC_SYNCOUT_REDUCTION_COUNT_OFFSET      0x8440
+
+/* _Small_Description_ */
+#define TIMESYNC_FW_WC_SYNCOUT_START_TIME_CYCLECOUNT_OFFSET 0x8444
+
+/* Control variable to generate SYNC1 */
+#define TIMESYNC_FW_WC_ISOM_PIN_SIGNAL_EN_OFFSET           0x844C
+
+/* SystemTime Sync0 periodicity */
+#define TIMESYNC_FW_ST_SYNCOUT_PERIOD_OFFSET               0x8450
+
+/* pktTxDelay for P1 = link speed dependent p1 mac delay + p1 phy delay */
+#define TIMESYNC_FW_WC_PKTTXDELAY_P1_OFFSET                0x8454
+
+/* pktTxDelay for P2 = link speed dependent p2 mac delay + p2 phy delay */
+#define TIMESYNC_FW_WC_PKTTXDELAY_P2_OFFSET                0x8458
+
+/* Set clock operation done signal for next task */
+#define TIMESYNC_FW_SIG_PNFW_OFFSET                        0x845C
+
+/* Set clock operation done signal for next task */
+#define TIMESYNC_FW_SIG_TIMESYNCFW_OFFSET                  0x8460
+
+/* New list is copied at this time */
+#define TAS_CONFIG_CHANGE_TIME                             0x000C
+
+/* config change error counter */
+#define TAS_CONFIG_CHANGE_ERROR_COUNTER                    0x0014
+
+/* TAS List update pending flag */
+#define TAS_CONFIG_PENDING                                 0x0018
+
+/* TAS list update trigger flag */
+#define TAS_CONFIG_CHANGE                                  0x0019
+
+/* List length for new TAS schedule */
+#define TAS_ADMIN_LIST_LENGTH                              0x001A
+
+/* Currently active TAS list index */
+#define TAS_ACTIVE_LIST_INDEX                              0x001B
+
+/* Cycle time for the new TAS schedule */
+#define TAS_ADMIN_CYCLE_TIME                               0x001C
+
+/* Cycle counts remaining till the TAS list update */
+#define TAS_CONFIG_CHANGE_CYCLE_COUNT                      0x0020
+
+/* Base Flow ID for sending  Packets to Host for Slice0 */
+#define PSI_L_REGULAR_FLOW_ID_BASE_OFFSET                  0x0024
+
+/* Same as PSI_L_REGULAR_FLOW_ID_BASE_OFFSET */
+#define EMAC_ICSSG_SWITCH_PSI_L_REGULAR_FLOW_ID_BASE_OFFSET PSI_L_REGULAR_FLOW_ID_BASE_OFFSET
+
+/* Base Flow ID for sending mgmt and Tx TS to Host for Slice0 */
+#define PSI_L_MGMT_FLOW_ID_OFFSET                          0x0026
+
+/* Same as PSI_L_MGMT_FLOW_ID_OFFSET */
+#define EMAC_ICSSG_SWITCH_PSI_L_MGMT_FLOW_ID_BASE_OFFSET   PSI_L_MGMT_FLOW_ID_OFFSET
+
+/* Queue number for Special  Packets written here */
+#define SPL_PKT_DEFAULT_PRIORITY                           0x0028
+
+/* Express Preemptible Queue Mask */
+#define EXPRESS_PRE_EMPTIVE_Q_MASK                         0x0029
+
+/* Port1/Port2 Default Queue number for untagged  Packets, only 1B is used */
+#define QUEUE_NUM_UNTAGGED                                 0x002A
+
+/* Stores the table used for priority regeneration. 1B per PCP/Queue */
+#define PORT_Q_PRIORITY_REGEN_OFFSET                       0x002C
+
+/* For marking Packet as priority/express (this feature is disabled) or
+ * cut-through/S&F.
+ */
+#define EXPRESS_PRE_EMPTIVE_Q_MAP                          0x0034
+
+/* Stores the table used for priority mapping. 1B per PCP/Queue */
+#define PORT_Q_PRIORITY_MAPPING_OFFSET                     0x003C
+
+/* Used to notify the FW of the current link speed */
+#define PORT_LINK_SPEED_OFFSET                             0x00A8
+
+/* TAS gate mask for windows list0 */
+#define TAS_GATE_MASK_LIST0                                0x0100
+
+/* TAS gate mask for windows list1 */
+#define TAS_GATE_MASK_LIST1                                0x0350
+
+/* Memory to Enable/Disable Preemption on TX side */
+#define PRE_EMPTION_ENABLE_TX                              0x05A0
+
+/* Active State of Preemption on TX side */
+#define PRE_EMPTION_ACTIVE_TX                              0x05A1
+
+/* Memory to Enable/Disable Verify State Machine Preemption */
+#define PRE_EMPTION_ENABLE_VERIFY                          0x05A2
+
+/* Verify Status of State Machine */
+#define PRE_EMPTION_VERIFY_STATUS                          0x05A3
+
+/* Non Final Fragment Size supported by Link Partner */
+#define PRE_EMPTION_ADD_FRAG_SIZE_REMOTE                   0x05A4
+
+/* Non Final Fragment Size supported by Firmware */
+#define PRE_EMPTION_ADD_FRAG_SIZE_LOCAL                    0x05A6
+
+/* Time in ms the State machine waits for respond Packet */
+#define PRE_EMPTION_VERIFY_TIME                            0x05A8
+
+/* Memory used for R30 related management commands */
+#define MGR_R30_CMD_OFFSET                                 0x05AC
+
+/* HW Buffer Pool0 base address */
+#define BUFFER_POOL_0_ADDR_OFFSET                          0x05BC
+
+/* 16B for Host Egress MSMC Q (Pre-emptible) context */
+#define HOST_RX_Q_PRE_CONTEXT_OFFSET                       0x0684
+
+/* Buffer for 8 FDB entries to be added by 'Add Multiple FDB entries IOCTL' */
+#define FDB_CMD_BUFFER                                     0x0894
+
+/* TAS queue max sdu length list */
+#define TAS_QUEUE_MAX_SDU_LIST                             0x08FA
+
+/* Used by FW to generate random number with the SEED value */
+#define HD_RAND_SEED_OFFSET                                0x0934
+
+/* 16B for Host Egress MSMC Q (Express) context */
+#define HOST_RX_Q_EXP_CONTEXT_OFFSET                       0x0940
+
+/* Start of 32 bits PA_STAT counters */
+#define PA_STAT_32b_START_OFFSET                           0x0080
+
+#endif /* __NET_TI_ICSSG_SWITCH_MAP_H  */
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icss_iep.c b/drivers/net/ethernet/ti/icss_iep.c
--- a/drivers/net/ethernet/ti/icss_iep.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icss_iep.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,961 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/* Texas Instruments ICSSG Industrial Ethernet Peripheral (IEP) Driver
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/timekeeping.h>
+#include <linux/interrupt.h>
+#include <linux/of_irq.h>
+
+#include "icss_iep.h"
+
+#define IEP_MAX_DEF_INC		0xf
+#define IEP_MAX_COMPEN_INC		0xfff
+#define IEP_MAX_COMPEN_COUNT	0xffffff
+
+#define IEP_GLOBAL_CFG_CNT_ENABLE	BIT(0)
+#define IEP_GLOBAL_CFG_DEFAULT_INC_MASK		GENMASK(7, 4)
+#define IEP_GLOBAL_CFG_DEFAULT_INC_SHIFT	4
+#define IEP_GLOBAL_CFG_COMPEN_INC_MASK		GENMASK(19, 8)
+#define IEP_GLOBAL_CFG_COMPEN_INC_SHIFT		8
+
+#define IEP_GLOBAL_STATUS_CNT_OVF	BIT(0)
+
+#define CMP_INDEX(sync)			((sync) + 1)
+#define IEP_CMP_CFG_SHADOW_EN		BIT(17)
+#define IEP_CMP_CFG_CMP0_RST_CNT_EN	BIT(0)
+#define IEP_CMP_CFG_CMP_EN(cmp)		(GENMASK(16, 1) & (1 << ((cmp) + 1)))
+
+#define IEP_CMP_STATUS(cmp)		(1 << (cmp))
+
+#define IEP_SYNC_CTRL_SYNC_EN		BIT(0)
+#define IEP_SYNC_CTRL_SYNC_N_EN(n)	(GENMASK(2, 1) & (BIT(1) << (n)))
+
+#define IEP_MIN_CMP	0
+#define IEP_MAX_CMP	15
+
+#define ICSS_IEP_64BIT_COUNTER_SUPPORT		BIT(0)
+#define ICSS_IEP_SLOW_COMPEN_REG_SUPPORT	BIT(1)
+#define ICSS_IEP_SHADOW_MODE_SUPPORT		BIT(2)
+
+#define LATCH_INDEX(ts_index)			((ts_index) + 6)
+#define IEP_CAP_CFG_CAPNR_1ST_EVENT_EN(n)	BIT(LATCH_INDEX(n))
+#define IEP_CAP_CFG_CAPNF_1ST_EVENT_EN(n)	BIT(LATCH_INDEX(n) + 1)
+#define IEP_CAP_CFG_CAP_ASYNC_EN(n)		BIT(LATCH_INDEX(n) + 10)
+
+enum {
+	ICSS_IEP_GLOBAL_CFG_REG,
+	ICSS_IEP_GLOBAL_STATUS_REG,
+	ICSS_IEP_COMPEN_REG,
+	ICSS_IEP_SLOW_COMPEN_REG,
+	ICSS_IEP_COUNT_REG0,
+	ICSS_IEP_COUNT_REG1,
+	ICSS_IEP_CAPTURE_CFG_REG,
+	ICSS_IEP_CAPTURE_STAT_REG,
+
+	ICSS_IEP_CAP6_RISE_REG0,
+	ICSS_IEP_CAP6_RISE_REG1,
+
+	ICSS_IEP_CAP7_RISE_REG0,
+	ICSS_IEP_CAP7_RISE_REG1,
+
+	ICSS_IEP_CMP_CFG_REG,
+	ICSS_IEP_CMP_STAT_REG,
+	ICSS_IEP_CMP0_REG0,
+	ICSS_IEP_CMP0_REG1,
+	ICSS_IEP_CMP1_REG0,
+	ICSS_IEP_CMP1_REG1,
+
+	ICSS_IEP_CMP8_REG0,
+	ICSS_IEP_CMP8_REG1,
+	ICSS_IEP_SYNC_CTRL_REG,
+	ICSS_IEP_SYNC0_STAT_REG,
+	ICSS_IEP_SYNC1_STAT_REG,
+	ICSS_IEP_SYNC_PWIDTH_REG,
+	ICSS_IEP_SYNC0_PERIOD_REG,
+	ICSS_IEP_SYNC1_DELAY_REG,
+	ICSS_IEP_SYNC_START_REG,
+	ICSS_IEP_MAX_REGS,
+};
+
+/**
+ * struct icss_iep_plat_data - Plat data to handle SoC variants
+ * @config: Regmap configuration data
+ * @reg_offs: register offsets to capture offset differences across SoCs
+ * @flags: Flags to represent IEP properties
+ */
+struct icss_iep_plat_data {
+	struct regmap_config *config;
+	u32 reg_offs[ICSS_IEP_MAX_REGS];
+	u32 flags;
+};
+
+struct icss_iep {
+	struct device *dev;
+	void __iomem *base;
+	const struct icss_iep_plat_data *plat_data;
+	struct regmap *map;
+	struct device_node *client_np;
+	unsigned long refclk_freq;
+	int clk_tick_time;	/* one refclk tick time in ns */
+	struct ptp_clock_info ptp_info;
+	struct ptp_clock *ptp_clock;
+	struct mutex ptp_clk_mutex;	/* PHC access serializer */
+	spinlock_t irq_lock; /* CMP IRQ vs icss_iep_ptp_enable access */
+	u32 def_inc;
+	s16 slow_cmp_inc;
+	u32 slow_cmp_count;
+	const struct icss_iep_clockops *ops;
+	void *clockops_data;
+	u32 cycle_time_ns;
+	u32 perout_enabled;
+	bool pps_enabled;
+	int cap_cmp_irq;
+	u64 period;
+	u32 latch_enable;
+};
+
+static u32 icss_iep_readl(struct icss_iep *iep, int reg)
+{
+	return readl(iep->base + iep->plat_data->reg_offs[reg]);
+}
+
+static void icss_iep_writel(struct icss_iep *iep, int reg, u32 val)
+{
+	return writel(val, iep->base + iep->plat_data->reg_offs[reg]);
+}
+
+/**
+ * icss_iep_get_count_hi() - Get the upper 32 bit IEP counter
+ * @iep: Pointer to structure representing IEP.
+ *
+ * Return: upper 32 bit IEP counter
+ */
+int icss_iep_get_count_hi(struct icss_iep *iep)
+{
+	u32 val = 0;
+
+	if (iep && (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT))
+		val = icss_iep_readl(iep, ICSS_IEP_COUNT_REG1);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(icss_iep_get_count_hi);
+
+/**
+ * icss_iep_get_count_low() - Get the lower 32 bit IEP counter
+ * @iep: Pointer to structure representing IEP.
+ *
+ * Return: lower 32 bit IEP counter
+ */
+int icss_iep_get_count_low(struct icss_iep *iep)
+{
+	u32 val = 0;
+
+	if (iep)
+		val = icss_iep_readl(iep, ICSS_IEP_COUNT_REG0);
+
+	return val;
+}
+EXPORT_SYMBOL_GPL(icss_iep_get_count_low);
+
+/**
+ * icss_iep_get_ptp_clock_idx() - Get PTP clock index using IEP driver
+ * @iep: Pointer to structure representing IEP.
+ *
+ * Return: PTP clock index, -1 if not registered
+ */
+int icss_iep_get_ptp_clock_idx(struct icss_iep *iep)
+{
+	if (!iep || !iep->ptp_clock)
+		return -1;
+	return ptp_clock_index(iep->ptp_clock);
+}
+EXPORT_SYMBOL_GPL(icss_iep_get_ptp_clock_idx);
+
+static void icss_iep_set_counter(struct icss_iep *iep, u64 ns)
+{
+	if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
+		icss_iep_writel(iep, ICSS_IEP_COUNT_REG1, upper_32_bits(ns));
+	icss_iep_writel(iep, ICSS_IEP_COUNT_REG0, lower_32_bits(ns));
+}
+
+static void icss_iep_update_to_next_boundary(struct icss_iep *iep, u64 start_ns);
+
+static void icss_iep_settime(struct icss_iep *iep, u64 ns)
+{
+	unsigned long flags;
+
+	if (iep->ops && iep->ops->settime) {
+		iep->ops->settime(iep->clockops_data, ns);
+		return;
+	}
+
+	spin_lock_irqsave(&iep->irq_lock, flags);
+	if (iep->pps_enabled || iep->perout_enabled)
+		icss_iep_writel(iep, ICSS_IEP_SYNC_CTRL_REG, 0);
+
+	icss_iep_set_counter(iep, ns);
+
+	if (iep->pps_enabled || iep->perout_enabled) {
+		icss_iep_update_to_next_boundary(iep, ns);
+		icss_iep_writel(iep, ICSS_IEP_SYNC_CTRL_REG,
+				IEP_SYNC_CTRL_SYNC_N_EN(0) |
+				IEP_SYNC_CTRL_SYNC_EN);
+	}
+	spin_unlock_irqrestore(&iep->irq_lock, flags);
+}
+
+static u64 icss_iep_gettime(struct icss_iep *iep,
+			    struct ptp_system_timestamp *sts)
+{
+	u32 ts_hi = 0, ts_lo;
+	unsigned long flags;
+
+	if (iep->ops && iep->ops->gettime)
+		return iep->ops->gettime(iep->clockops_data, sts);
+
+	/* use local_irq_x() to make it work for both RT/non-RT */
+	local_irq_save(flags);
+
+	/* no need to play with hi-lo, hi is latched when lo is read */
+	ptp_read_system_prets(sts);
+	ts_lo = icss_iep_readl(iep, ICSS_IEP_COUNT_REG0);
+	ptp_read_system_postts(sts);
+	if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
+		ts_hi = icss_iep_readl(iep, ICSS_IEP_COUNT_REG1);
+
+	local_irq_restore(flags);
+
+	return (u64)ts_lo | (u64)ts_hi << 32;
+}
+
+static void icss_iep_enable(struct icss_iep *iep)
+{
+	regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG,
+			   IEP_GLOBAL_CFG_CNT_ENABLE,
+			   IEP_GLOBAL_CFG_CNT_ENABLE);
+}
+
+static void icss_iep_disable(struct icss_iep *iep)
+{
+	regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG,
+			   IEP_GLOBAL_CFG_CNT_ENABLE,
+			   0);
+}
+
+static void icss_iep_enable_shadow_mode(struct icss_iep *iep)
+{
+	u32 cycle_time;
+	int cmp;
+
+	/* FIXME: check why we need to decrement by def_inc */
+	cycle_time = iep->cycle_time_ns - iep->def_inc;
+
+	icss_iep_disable(iep);
+
+	/* disable shadow mode */
+	regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
+			   IEP_CMP_CFG_SHADOW_EN, 0);
+
+	/* enable shadow mode */
+	regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
+			   IEP_CMP_CFG_SHADOW_EN, IEP_CMP_CFG_SHADOW_EN);
+
+	/* clear counters */
+	icss_iep_set_counter(iep, 0);
+
+	/* clear overflow status */
+	regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_STATUS_REG,
+			   IEP_GLOBAL_STATUS_CNT_OVF,
+			   IEP_GLOBAL_STATUS_CNT_OVF);
+
+	/* clear compare status */
+	for (cmp = IEP_MIN_CMP; cmp < IEP_MAX_CMP; cmp++) {
+		regmap_update_bits(iep->map, ICSS_IEP_CMP_STAT_REG,
+				   IEP_CMP_STATUS(cmp), IEP_CMP_STATUS(cmp));
+	}
+
+	/* enable reset counter on CMP0 event */
+	regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
+			   IEP_CMP_CFG_CMP0_RST_CNT_EN,
+			   IEP_CMP_CFG_CMP0_RST_CNT_EN);
+	/* enable compare */
+	regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
+			   IEP_CMP_CFG_CMP_EN(0),
+			   IEP_CMP_CFG_CMP_EN(0));
+
+	/* set CMP0 value to cycle time */
+	regmap_write(iep->map, ICSS_IEP_CMP0_REG0, cycle_time);
+	if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
+		regmap_write(iep->map, ICSS_IEP_CMP0_REG1, cycle_time);
+
+	icss_iep_set_counter(iep, 0);
+	icss_iep_enable(iep);
+}
+
+static void icss_iep_set_default_inc(struct icss_iep *iep, u8 def_inc)
+{
+	regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG,
+			   IEP_GLOBAL_CFG_DEFAULT_INC_MASK,
+			   def_inc << IEP_GLOBAL_CFG_DEFAULT_INC_SHIFT);
+}
+
+static void icss_iep_set_compensation_inc(struct icss_iep *iep, u16 compen_inc)
+{
+	struct device *dev = regmap_get_device(iep->map);
+
+	if (compen_inc > IEP_MAX_COMPEN_INC) {
+		dev_err(dev, "%s: too high compensation inc %d\n",
+			__func__, compen_inc);
+		compen_inc = IEP_MAX_COMPEN_INC;
+	}
+
+	regmap_update_bits(iep->map, ICSS_IEP_GLOBAL_CFG_REG,
+			   IEP_GLOBAL_CFG_COMPEN_INC_MASK,
+			   compen_inc << IEP_GLOBAL_CFG_COMPEN_INC_SHIFT);
+}
+
+static void icss_iep_set_compensation_count(struct icss_iep *iep,
+					    u32 compen_count)
+{
+	struct device *dev = regmap_get_device(iep->map);
+
+	if (compen_count > IEP_MAX_COMPEN_COUNT) {
+		dev_err(dev, "%s: too high compensation count %d\n",
+			__func__, compen_count);
+		compen_count = IEP_MAX_COMPEN_COUNT;
+	}
+
+	regmap_write(iep->map, ICSS_IEP_COMPEN_REG, compen_count);
+}
+
+static void icss_iep_set_slow_compensation_count(struct icss_iep *iep,
+						 u32 compen_count)
+{
+	regmap_write(iep->map, ICSS_IEP_SLOW_COMPEN_REG, compen_count);
+}
+
+/* PTP PHC operations */
+static int icss_iep_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+	struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info);
+	u32 cyc_count;
+	u16 cmp_inc;
+
+	mutex_lock(&iep->ptp_clk_mutex);
+
+	/* ppb is amount of frequency we want to adjust in 1GHz (billion)
+	 * e.g. 100ppb means we need to speed up clock by 100Hz
+	 * i.e. at end of 1 second (1 billion ns) clock time, we should be
+	 * counting 100 more ns.
+	 * We use IEP slow compensation to achieve continuous freq. adjustment.
+	 * There are 2 parts. Cycle time and adjustment per cycle.
+	 * Simplest case would be 1 sec Cycle time. Then adjustment
+	 * pre cycle would be (def_inc + ppb) value.
+	 * Cycle time will have to be chosen based on how worse the ppb is.
+	 * e.g. smaller the ppb, cycle time has to be large.
+	 * The minimum adjustment we can do is +-1ns per cycle so let's
+	 * reduce the cycle time to get 1ns per cycle adjustment.
+	 *	1ppb = 1sec cycle time & 1ns adjust
+	 *	1000ppb = 1/1000 cycle time & 1ns adjust per cycle
+	 */
+
+	if (iep->cycle_time_ns)
+		iep->slow_cmp_inc = iep->clk_tick_time;	/* 4ns adj per cycle */
+	else
+		iep->slow_cmp_inc = 1;	/* 1ns adjust per cycle */
+
+	if (ppb < 0) {
+		iep->slow_cmp_inc = -iep->slow_cmp_inc;
+		ppb = -ppb;
+	}
+
+	cyc_count = NSEC_PER_SEC;		/* 1s cycle time @1GHz */
+	cyc_count /= ppb;		/* cycle time per ppb */
+
+	/* slow_cmp_count is decremented every clock cycle, e.g. @250MHz */
+	if (!iep->cycle_time_ns)
+		cyc_count /= iep->clk_tick_time;
+	iep->slow_cmp_count = cyc_count;
+
+	/* iep->clk_tick_time is def_inc */
+	cmp_inc = iep->clk_tick_time + iep->slow_cmp_inc;
+	icss_iep_set_compensation_inc(iep, cmp_inc);
+	icss_iep_set_slow_compensation_count(iep, iep->slow_cmp_count);
+
+	mutex_unlock(&iep->ptp_clk_mutex);
+
+	return 0;
+}
+
+static int icss_iep_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+	struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info);
+	s64 ns;
+
+	mutex_lock(&iep->ptp_clk_mutex);
+	if (iep->ops && iep->ops->adjtime) {
+		iep->ops->adjtime(iep->clockops_data, delta);
+	} else {
+		ns = icss_iep_gettime(iep, NULL);
+		ns += delta;
+		icss_iep_settime(iep, ns);
+	}
+	mutex_unlock(&iep->ptp_clk_mutex);
+
+	return 0;
+}
+
+static int icss_iep_ptp_gettimeex(struct ptp_clock_info *ptp,
+				  struct timespec64 *ts,
+				  struct ptp_system_timestamp *sts)
+{
+	struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info);
+	u64 ns;
+
+	mutex_lock(&iep->ptp_clk_mutex);
+	ns = icss_iep_gettime(iep, sts);
+	*ts = ns_to_timespec64(ns);
+	mutex_unlock(&iep->ptp_clk_mutex);
+
+	return 0;
+}
+
+static int icss_iep_ptp_settime(struct ptp_clock_info *ptp,
+				const struct timespec64 *ts)
+{
+	struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info);
+	u64 ns;
+
+	mutex_lock(&iep->ptp_clk_mutex);
+	ns = timespec64_to_ns(ts);
+	icss_iep_settime(iep, ns);
+	mutex_unlock(&iep->ptp_clk_mutex);
+
+	return 0;
+}
+
+static void icss_iep_update_to_next_boundary(struct icss_iep *iep, u64 start_ns)
+{
+	u64 ns, p_ns;
+	u32 offset;
+
+	ns = icss_iep_gettime(iep, NULL);
+	if (start_ns < ns)
+		start_ns = ns;
+	p_ns = iep->period;
+	/* Round up to next period boundary */
+	start_ns += p_ns - 1;
+	offset = do_div(start_ns, p_ns);
+	start_ns = start_ns * p_ns;
+	/* If it is too close to update, shift to next boundary */
+	if (p_ns - offset < 10)
+		start_ns += p_ns;
+
+	regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(start_ns));
+	if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
+		regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(start_ns));
+}
+
+static int icss_iep_perout_enable_hw(struct icss_iep *iep,
+				     struct ptp_perout_request *req, int on)
+{
+	int ret;
+	u64 cmp;
+
+	if (iep->ops && iep->ops->perout_enable) {
+		ret = iep->ops->perout_enable(iep->clockops_data, req, on, &cmp);
+		if (ret)
+			return ret;
+
+		if (on) {
+			/* Configure CMP */
+			regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp));
+			if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
+				regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp));
+			/* Configure SYNC, 1ms pulse width */
+			regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, 1000000);
+			regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
+			regmap_write(iep->map, ICSS_IEP_SYNC_START_REG, 0);
+			regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */
+			/* Enable CMP 1 */
+			regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
+					   IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1));
+		} else {
+			/* Disable CMP 1 */
+			regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
+					   IEP_CMP_CFG_CMP_EN(1), 0);
+
+			/* clear regs */
+			regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0);
+			if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
+				regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0);
+		}
+	} else {
+		if (on) {
+			u64 start_ns;
+
+			iep->period = ((u64)req->period.sec * NSEC_PER_SEC) +
+				      req->period.nsec;
+			start_ns = ((u64)req->period.sec * NSEC_PER_SEC)
+				   + req->period.nsec;
+			icss_iep_update_to_next_boundary(iep, start_ns);
+
+			/* Enable Sync in single shot mode  */
+			regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG,
+				     IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN);
+			/* Enable CMP 1 */
+			regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
+					   IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1));
+		} else {
+			/* Disable CMP 1 */
+			regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
+					   IEP_CMP_CFG_CMP_EN(1), 0);
+
+			/* clear CMP regs */
+			regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0);
+			if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
+				regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0);
+
+			/* Disable sync */
+			regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0);
+		}
+	}
+
+	return 0;
+}
+
+static int icss_iep_perout_enable(struct icss_iep *iep,
+				  struct ptp_perout_request *req, int on)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	mutex_lock(&iep->ptp_clk_mutex);
+
+	if (iep->pps_enabled) {
+		ret = -EBUSY;
+		goto exit;
+	}
+
+	if (iep->perout_enabled == !!on)
+		goto exit;
+
+	spin_lock_irqsave(&iep->irq_lock, flags);
+	ret = icss_iep_perout_enable_hw(iep, req, on);
+	if (!ret)
+		iep->perout_enabled = !!on;
+	spin_unlock_irqrestore(&iep->irq_lock, flags);
+
+exit:
+	mutex_unlock(&iep->ptp_clk_mutex);
+
+	return ret;
+}
+
+static int icss_iep_pps_enable(struct icss_iep *iep, int on)
+{
+	int ret = 0;
+	struct timespec64 ts;
+	struct ptp_clock_request rq;
+	unsigned long flags;
+	u64 ns;
+
+	mutex_lock(&iep->ptp_clk_mutex);
+
+	if (iep->perout_enabled) {
+		ret = -EBUSY;
+		goto exit;
+	}
+
+	if (iep->pps_enabled == !!on)
+		goto exit;
+
+	spin_lock_irqsave(&iep->irq_lock, flags);
+
+	rq.perout.index = 0;
+	if (on) {
+		ns = icss_iep_gettime(iep, NULL);
+		ts = ns_to_timespec64(ns);
+		rq.perout.period.sec = 1;
+		rq.perout.period.nsec = 0;
+		rq.perout.start.sec = ts.tv_sec + 2;
+		rq.perout.start.nsec = 0;
+		ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);
+	} else {
+		ret = icss_iep_perout_enable_hw(iep, &rq.perout, on);
+	}
+
+	if (!ret)
+		iep->pps_enabled = !!on;
+
+	spin_unlock_irqrestore(&iep->irq_lock, flags);
+
+exit:
+	mutex_unlock(&iep->ptp_clk_mutex);
+
+	return ret;
+}
+
+static int icss_iep_extts_enable(struct icss_iep *iep, u32 index, int on)
+{
+	u32 val, cap, ret = 0;
+
+	mutex_lock(&iep->ptp_clk_mutex);
+
+	if (iep->ops && iep->ops->extts_enable) {
+		ret = iep->ops->extts_enable(iep->clockops_data, index, on);
+		goto exit;
+	}
+
+	if (!!(iep->latch_enable & BIT(index)) == !!on)
+		goto exit;
+
+	regmap_read(iep->map, ICSS_IEP_CAPTURE_CFG_REG, &val);
+	cap = IEP_CAP_CFG_CAP_ASYNC_EN(index) | IEP_CAP_CFG_CAPNR_1ST_EVENT_EN(index);
+	if (on) {
+		val |= cap;
+		iep->latch_enable |= BIT(index);
+	} else {
+		val &= ~cap;
+		iep->latch_enable &= ~BIT(index);
+	}
+	regmap_write(iep->map, ICSS_IEP_CAPTURE_CFG_REG, val);
+
+exit:
+	mutex_unlock(&iep->ptp_clk_mutex);
+
+	return ret;
+}
+
+static int icss_iep_ptp_enable(struct ptp_clock_info *ptp,
+			       struct ptp_clock_request *rq, int on)
+{
+	struct icss_iep *iep = container_of(ptp, struct icss_iep, ptp_info);
+
+	switch (rq->type) {
+	case PTP_CLK_REQ_PEROUT:
+		return icss_iep_perout_enable(iep, &rq->perout, on);
+	case PTP_CLK_REQ_PPS:
+		return icss_iep_pps_enable(iep, on);
+	case PTP_CLK_REQ_EXTTS:
+		return icss_iep_extts_enable(iep, rq->extts.index, on);
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info icss_iep_ptp_info = {
+	.owner		= THIS_MODULE,
+	.name		= "ICSS IEP timer",
+	.max_adj	= 10000000,
+	.adjfreq	= icss_iep_ptp_adjfreq,
+	.adjtime	= icss_iep_ptp_adjtime,
+	.gettimex64	= icss_iep_ptp_gettimeex,
+	.settime64	= icss_iep_ptp_settime,
+	.enable		= icss_iep_ptp_enable,
+};
+
+struct icss_iep *icss_iep_get_idx(struct device_node *np, int idx)
+{
+	struct platform_device *pdev;
+	struct device_node *iep_np;
+	struct icss_iep *iep;
+
+	iep_np = of_parse_phandle(np, "iep", idx);
+	if (!iep_np || !of_device_is_available(iep_np))
+		return ERR_PTR(-ENODEV);
+
+	pdev = of_find_device_by_node(iep_np);
+	of_node_put(iep_np);
+
+	if (!pdev)
+		/* probably IEP not yet probed */
+		return ERR_PTR(-EPROBE_DEFER);
+
+	iep = platform_get_drvdata(pdev);
+	if (!iep)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	device_lock(iep->dev);
+	if (iep->client_np) {
+		device_unlock(iep->dev);
+		dev_err(iep->dev, "IEP is already acquired by %s",
+			iep->client_np->name);
+		return ERR_PTR(-EBUSY);
+	}
+	iep->client_np = np;
+	device_unlock(iep->dev);
+	get_device(iep->dev);
+
+	return iep;
+}
+EXPORT_SYMBOL_GPL(icss_iep_get_idx);
+
+struct icss_iep *icss_iep_get(struct device_node *np)
+{
+	return icss_iep_get_idx(np, 0);
+}
+EXPORT_SYMBOL_GPL(icss_iep_get);
+
+void icss_iep_put(struct icss_iep *iep)
+{
+	device_lock(iep->dev);
+	iep->client_np = NULL;
+	device_unlock(iep->dev);
+	put_device(iep->dev);
+}
+EXPORT_SYMBOL_GPL(icss_iep_put);
+
+void icss_iep_init_fw(struct icss_iep *iep)
+{
+	/* start IEP for FW use in raw 64bit mode, no PTP support */
+	iep->clk_tick_time = iep->def_inc;
+	iep->cycle_time_ns = 0;
+	iep->ops = NULL;
+	iep->clockops_data = NULL;
+	icss_iep_set_default_inc(iep, iep->def_inc);
+	icss_iep_set_compensation_inc(iep, iep->def_inc);
+	icss_iep_set_compensation_count(iep, 0);
+	regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, iep->refclk_freq / 10); /* 100 ms pulse */
+	regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
+	if (iep->plat_data->flags & ICSS_IEP_SLOW_COMPEN_REG_SUPPORT)
+		icss_iep_set_slow_compensation_count(iep, 0);
+
+	icss_iep_enable(iep);
+	icss_iep_settime(iep, 0);
+}
+EXPORT_SYMBOL_GPL(icss_iep_init_fw);
+
+void icss_iep_exit_fw(struct icss_iep *iep)
+{
+	icss_iep_disable(iep);
+}
+EXPORT_SYMBOL_GPL(icss_iep_exit_fw);
+
+int icss_iep_init(struct icss_iep *iep, const struct icss_iep_clockops *clkops,
+		  void *clockops_data, u32 cycle_time_ns)
+{
+	int ret = 0;
+
+	iep->cycle_time_ns = cycle_time_ns;
+	iep->clk_tick_time = iep->def_inc;
+	iep->ops = clkops;
+	iep->clockops_data = clockops_data;
+	icss_iep_set_default_inc(iep, iep->def_inc);
+	icss_iep_set_compensation_inc(iep, iep->def_inc);
+	icss_iep_set_compensation_count(iep, 0);
+	regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, iep->refclk_freq / 10); /* 100 ms pulse */
+	regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
+	if (iep->plat_data->flags & ICSS_IEP_SLOW_COMPEN_REG_SUPPORT)
+		icss_iep_set_slow_compensation_count(iep, 0);
+
+	if (!(iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT) ||
+	    !(iep->plat_data->flags & ICSS_IEP_SLOW_COMPEN_REG_SUPPORT))
+		goto skip_perout;
+
+	if (iep->ops && iep->ops->perout_enable) {
+		iep->ptp_info.n_per_out = 1;
+		iep->ptp_info.pps = 1;
+	}
+
+	if (iep->ops && iep->ops->extts_enable)
+		iep->ptp_info.n_ext_ts = 2;
+
+skip_perout:
+	if (cycle_time_ns)
+		icss_iep_enable_shadow_mode(iep);
+	else
+		icss_iep_enable(iep);
+	icss_iep_settime(iep, ktime_get_real_ns());
+
+	iep->ptp_clock = ptp_clock_register(&iep->ptp_info, iep->dev);
+	if (IS_ERR(iep->ptp_clock)) {
+		ret = PTR_ERR(iep->ptp_clock);
+		iep->ptp_clock = NULL;
+		dev_err(iep->dev, "Failed to register ptp clk %d\n", ret);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(icss_iep_init);
+
+int icss_iep_exit(struct icss_iep *iep)
+{
+	if (iep->ptp_clock) {
+		ptp_clock_unregister(iep->ptp_clock);
+		iep->ptp_clock = NULL;
+	}
+	icss_iep_disable(iep);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(icss_iep_exit);
+
+static const struct of_device_id icss_iep_of_match[];
+
+static int icss_iep_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct icss_iep *iep;
+	struct clk *iep_clk;
+
+	iep = devm_kzalloc(dev, sizeof(*iep), GFP_KERNEL);
+	if (!iep)
+		return -ENOMEM;
+
+	iep->dev = dev;
+	iep->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(iep->base))
+		return -ENODEV;
+
+	iep_clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(iep_clk))
+		return PTR_ERR(iep_clk);
+
+	iep->refclk_freq = clk_get_rate(iep_clk);
+
+	iep->def_inc = NSEC_PER_SEC / iep->refclk_freq;	/* ns per clock tick */
+	if (iep->def_inc > IEP_MAX_DEF_INC) {
+		dev_err(dev, "Failed to set def_inc %d.  IEP_clock is too slow to be supported\n",
+			iep->def_inc);
+		return -EINVAL;
+	}
+
+	iep->plat_data = of_device_get_match_data(dev);
+	if (!iep->plat_data)
+		return -EINVAL;
+
+	iep->map = devm_regmap_init(dev, NULL, iep, iep->plat_data->config);
+	if (IS_ERR(iep->map)) {
+		dev_err(dev, "Failed to create regmap for IEP %ld\n",
+			PTR_ERR(iep->map));
+		return PTR_ERR(iep->map);
+	}
+
+	iep->ptp_info = icss_iep_ptp_info;
+	mutex_init(&iep->ptp_clk_mutex);
+	spin_lock_init(&iep->irq_lock);
+	dev_set_drvdata(dev, iep);
+	icss_iep_disable(iep);
+
+	return 0;
+}
+
+static bool am654_icss_iep_valid_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case ICSS_IEP_GLOBAL_CFG_REG ... ICSS_IEP_SYNC_START_REG:
+		return true;
+	default:
+		return false;
+	}
+
+	return false;
+}
+
+static int icss_iep_regmap_write(void *context, unsigned int reg,
+				 unsigned int val)
+{
+	struct icss_iep *iep = context;
+
+	writel(val, iep->base + iep->plat_data->reg_offs[reg]);
+
+	return 0;
+}
+
+static int icss_iep_regmap_read(void *context, unsigned int reg,
+				unsigned int *val)
+{
+	struct icss_iep *iep = context;
+
+	*val = readl(iep->base + iep->plat_data->reg_offs[reg]);
+
+	return 0;
+}
+
+static struct regmap_config am654_icss_iep_regmap_config = {
+	.name = "icss iep",
+	.reg_stride = 1,
+	.reg_write = icss_iep_regmap_write,
+	.reg_read = icss_iep_regmap_read,
+	.writeable_reg = am654_icss_iep_valid_reg,
+	.readable_reg = am654_icss_iep_valid_reg,
+	.fast_io = 1,
+};
+
+static const struct icss_iep_plat_data am654_icss_iep_plat_data = {
+	.flags = ICSS_IEP_64BIT_COUNTER_SUPPORT |
+		 ICSS_IEP_SLOW_COMPEN_REG_SUPPORT |
+		 ICSS_IEP_SHADOW_MODE_SUPPORT,
+	.reg_offs = {
+		[ICSS_IEP_GLOBAL_CFG_REG] = 0x00,
+		[ICSS_IEP_COMPEN_REG] = 0x08,
+		[ICSS_IEP_SLOW_COMPEN_REG] = 0x0C,
+		[ICSS_IEP_COUNT_REG0] = 0x10,
+		[ICSS_IEP_COUNT_REG1] = 0x14,
+		[ICSS_IEP_CAPTURE_CFG_REG] = 0x18,
+		[ICSS_IEP_CAPTURE_STAT_REG] = 0x1c,
+
+		[ICSS_IEP_CAP6_RISE_REG0] = 0x50,
+		[ICSS_IEP_CAP6_RISE_REG1] = 0x54,
+
+		[ICSS_IEP_CAP7_RISE_REG0] = 0x60,
+		[ICSS_IEP_CAP7_RISE_REG1] = 0x64,
+
+		[ICSS_IEP_CMP_CFG_REG] = 0x70,
+		[ICSS_IEP_CMP_STAT_REG] = 0x74,
+		[ICSS_IEP_CMP0_REG0] = 0x78,
+		[ICSS_IEP_CMP0_REG1] = 0x7c,
+		[ICSS_IEP_CMP1_REG0] = 0x80,
+		[ICSS_IEP_CMP1_REG1] = 0x84,
+
+		[ICSS_IEP_CMP8_REG0] = 0xc0,
+		[ICSS_IEP_CMP8_REG1] = 0xc4,
+		[ICSS_IEP_SYNC_CTRL_REG] = 0x180,
+		[ICSS_IEP_SYNC0_STAT_REG] = 0x188,
+		[ICSS_IEP_SYNC1_STAT_REG] = 0x18c,
+		[ICSS_IEP_SYNC_PWIDTH_REG] = 0x190,
+		[ICSS_IEP_SYNC0_PERIOD_REG] = 0x194,
+		[ICSS_IEP_SYNC1_DELAY_REG] = 0x198,
+		[ICSS_IEP_SYNC_START_REG] = 0x19c,
+	},
+	.config = &am654_icss_iep_regmap_config,
+};
+
+static const struct of_device_id icss_iep_of_match[] = {
+	{
+		.compatible = "ti,am654-icss-iep",
+		.data = &am654_icss_iep_plat_data,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, icss_iep_of_match);
+
+static struct platform_driver icss_iep_driver = {
+	.driver = {
+		.name = "icss-iep",
+		.of_match_table = of_match_ptr(icss_iep_of_match),
+	},
+	.probe = icss_iep_probe,
+};
+module_platform_driver(icss_iep_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("TI ICSS IEP driver");
+MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
+MODULE_AUTHOR("Md Danish Anwar <danishanwar@ti.com>");
diff -Naur --no-dereference a/drivers/net/ethernet/ti/icss_iep.h b/drivers/net/ethernet/ti/icss_iep.h
--- a/drivers/net/ethernet/ti/icss_iep.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/icss_iep.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Texas Instruments ICSSG Industrial Ethernet Peripheral (IEP) Driver
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - https://www.ti.com/
+ *
+ */
+
+#ifndef __NET_TI_ICSS_IEP_H
+#define __NET_TI_ICSS_IEP_H
+
+#include <linux/mutex.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/regmap.h>
+
+struct icss_iep;
+
+/* Firmware specific clock operations */
+struct icss_iep_clockops {
+	void (*settime)(void *clockops_data, u64 ns);
+	void (*adjtime)(void *clockops_data, s64 delta);
+	u64 (*gettime)(void *clockops_data, struct ptp_system_timestamp *sts);
+	int (*perout_enable)(void *clockops_data,
+			     struct ptp_perout_request *req, int on,
+			     u64 *cmp);
+	int (*extts_enable)(void *clockops_data, u32 index, int on);
+};
+
+struct icss_iep *icss_iep_get(struct device_node *np);
+struct icss_iep *icss_iep_get_idx(struct device_node *np, int idx);
+void icss_iep_put(struct icss_iep *iep);
+int icss_iep_init(struct icss_iep *iep, const struct icss_iep_clockops *clkops,
+		  void *clockops_data, u32 cycle_time_ns);
+int icss_iep_exit(struct icss_iep *iep);
+int icss_iep_get_count_low(struct icss_iep *iep);
+int icss_iep_get_count_hi(struct icss_iep *iep);
+int icss_iep_get_ptp_clock_idx(struct icss_iep *iep);
+void icss_iep_init_fw(struct icss_iep *iep);
+void icss_iep_exit_fw(struct icss_iep *iep);
+
+#endif /* __NET_TI_ICSS_IEP_H */
diff -Naur --no-dereference a/drivers/net/ethernet/ti/j721e-cpsw-virt-mac.c b/drivers/net/ethernet/ti/j721e-cpsw-virt-mac.c
--- a/drivers/net/ethernet/ti/j721e-cpsw-virt-mac.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ethernet/ti/j721e-cpsw-virt-mac.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,1622 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Texas Instruments K3 J721 Virt Ethernet Switch MAC Driver
+ *
+ * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
+ */
+
+#include <linux/etherdevice.h>
+#include <linux/if_vlan.h>
+#include <linux/interrupt.h>
+#include <linux/inetdevice.h>
+#include <linux/kernel.h>
+#include <linux/kmemleak.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/of_net.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/dma/ti-cppi5.h>
+#include <linux/dma/k3-udma-glue.h>
+#include <linux/rpmsg-remotedev/rpmsg-remotedev.h>
+
+#include "k3-cppi-desc-pool.h"
+
+#define VIRT_CPSW_DRV_VER "0.1"
+
+#define VIRT_CPSW_MAX_TX_QUEUES	1
+#define VIRT_CPSW_MAX_RX_QUEUES	1
+#define VIRT_CPSW_MAX_RX_FLOWS	1
+
+#define VIRT_CPSW_MIN_PACKET_SIZE	ETH_ZLEN
+#define VIRT_CPSW_MAX_PACKET_SIZE	(VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)
+
+/* Number of TX/RX descriptors */
+#define VIRT_CPSW_MAX_TX_DESC	500
+#define VIRT_CPSW_MAX_RX_DESC	500
+
+#define VIRT_CPSW_NAV_PS_DATA_SIZE 16
+#define VIRT_CPSW_NAV_SW_DATA_SIZE 16
+
+#define VIRT_CPSW_DRV_NAME "j721e-cpsw-virt-mac"
+
+struct virt_cpsw_tx_chn {
+	struct device *dev;
+	struct k3_cppi_desc_pool *desc_pool;
+	struct k3_udma_glue_tx_channel *tx_chn;
+	u32 descs_num;
+	unsigned int irq;
+	u32 id;
+};
+
+struct virt_cpsw_rx_chn {
+	struct device *dev;
+	struct k3_cppi_desc_pool *desc_pool;
+	struct k3_udma_glue_rx_channel *rx_chn;
+	u32 descs_num;
+	unsigned int irq;
+};
+
+struct virt_cpsw_port {
+	struct virt_cpsw_common *common;
+	struct net_device *ndev;
+	const char *name;
+	u8 local_mac_addr[ETH_ALEN];
+};
+
+struct virt_cpsw_common {
+	struct device *dev;
+	struct virt_cpsw_port ports;
+
+	struct virt_cpsw_tx_chn tx_chns;
+	struct napi_struct napi_tx;
+	struct hrtimer tx_hrtimer;
+	unsigned long tx_pace_timeout;
+	struct completion tdown_complete;
+	atomic_t tdown_cnt;
+	struct virt_cpsw_rx_chn rx_chns;
+	struct napi_struct napi_rx;
+	bool rx_irq_disabled;
+	struct hrtimer rx_hrtimer;
+	unsigned long rx_pace_timeout;
+	u32 mac_only_port;
+
+	const char *rdev_name;
+	struct rpmsg_remotedev *rdev;
+	struct rpmsg_remotedev_eth_switch_ops *rdev_switch_ops;
+	u32 rdev_features;
+	u32 rdev_mtu;
+	u8 rdev_mac_addr[ETH_ALEN];
+	u32 rdev_tx_psil_dst_id;
+	u32 tx_psil_id_base;
+	u32 rdev_rx_flow_id;
+	struct notifier_block virt_cpsw_inetaddr_nb;
+	struct work_struct rx_mode_work;
+	struct workqueue_struct	*cmd_wq;
+	struct netdev_hw_addr_list mc_list;
+	unsigned int mac_only:1;
+	unsigned int mc_filter:1;
+};
+
+struct virt_cpsw_ndev_stats {
+	u64 tx_packets;
+	u64 tx_bytes;
+	u64 rx_packets;
+	u64 rx_bytes;
+	struct u64_stats_sync syncp;
+};
+
+struct virt_cpsw_ndev_priv {
+	struct virt_cpsw_ndev_stats __percpu *stats;
+	struct virt_cpsw_port	*port;
+};
+
+#define virt_ndev_to_priv(ndev) \
+	((struct virt_cpsw_ndev_priv *)netdev_priv(ndev))
+#define virt_ndev_to_port(ndev) (virt_ndev_to_priv(ndev)->port)
+#define virt_ndev_to_common(ndev) (virt_ndev_to_port(ndev)->common)
+
+static void virt_cpsw_nuss_ndo_host_tx_timeout(struct net_device *ndev,
+					       unsigned int txqueue)
+{
+	struct virt_cpsw_common *common = virt_ndev_to_common(ndev);
+	struct virt_cpsw_tx_chn *tx_chn = &common->tx_chns;
+	struct netdev_queue *netif_txq;
+	unsigned long trans_start;
+
+	/* process every txq*/
+	netif_txq = netdev_get_tx_queue(ndev, txqueue);
+	trans_start = netif_txq->trans_start;
+
+	netdev_err(ndev, "txq:%d DRV_XOFF:%d tmo:%u dql_avail:%d free_desc:%zu\n",
+		   txqueue,
+		   netif_tx_queue_stopped(netif_txq),
+		   jiffies_to_msecs(jiffies - trans_start),
+		   dql_avail(&netif_txq->dql),
+		   k3_cppi_desc_pool_avail(tx_chn->desc_pool));
+
+	if (netif_tx_queue_stopped(netif_txq)) {
+		/* try recover if stopped by us */
+		txq_trans_update(netif_txq);
+		netif_tx_wake_queue(netif_txq);
+	}
+}
+
+static int virt_cpsw_nuss_rx_push(struct virt_cpsw_common *common,
+				  struct sk_buff *skb)
+{
+	struct cppi5_host_desc_t *desc_rx;
+	struct virt_cpsw_rx_chn *rx_chn = &common->rx_chns;
+	struct device *dev = common->dev;
+	dma_addr_t desc_dma;
+	dma_addr_t buf_dma;
+	u32 pkt_len = skb_tailroom(skb);
+	void *swdata;
+
+	desc_rx = k3_cppi_desc_pool_alloc(rx_chn->desc_pool);
+	if (!desc_rx) {
+		dev_err(dev, "Failed to allocate RXFDQ descriptor\n");
+		return -ENOMEM;
+	}
+	desc_dma = k3_cppi_desc_pool_virt2dma(rx_chn->desc_pool, desc_rx);
+
+	buf_dma = dma_map_single(dev, skb->data, pkt_len, DMA_FROM_DEVICE);
+	if (unlikely(dma_mapping_error(dev, buf_dma))) {
+		k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
+		dev_err(dev, "Failed to map rx skb buffer\n");
+		return -EINVAL;
+	}
+
+	cppi5_hdesc_init(desc_rx, CPPI5_INFO0_HDESC_EPIB_PRESENT,
+			 VIRT_CPSW_NAV_PS_DATA_SIZE);
+	cppi5_hdesc_attach_buf(desc_rx, 0, 0, buf_dma, skb_tailroom(skb));
+	swdata = cppi5_hdesc_get_swdata(desc_rx);
+	*((void **)swdata) = skb;
+
+	return k3_udma_glue_push_rx_chn(rx_chn->rx_chn, 0, desc_rx, desc_dma);
+}
+
+static int virt_cpsw_nuss_common_open(struct virt_cpsw_common *common,
+				      netdev_features_t features)
+{
+	struct sk_buff *skb;
+	int i, ret;
+
+	for (i = 0; i < common->rx_chns.descs_num; i++) {
+		skb = __netdev_alloc_skb_ip_align(NULL,
+						  VIRT_CPSW_MAX_PACKET_SIZE,
+						  GFP_KERNEL);
+		if (!skb) {
+			dev_err(common->dev, "cannot allocate skb\n");
+			return -ENOMEM;
+		}
+
+		ret = virt_cpsw_nuss_rx_push(common, skb);
+		if (ret < 0) {
+			dev_err(common->dev,
+				"cannot submit skb to channel rx, error %d\n",
+				ret);
+			kfree_skb(skb);
+			return ret;
+		}
+		kmemleak_not_leak(skb);
+	}
+	ret = k3_udma_glue_rx_flow_enable(common->rx_chns.rx_chn, 0);
+	if (ret)
+		return ret;
+
+	ret = k3_udma_glue_enable_tx_chn(common->tx_chns.tx_chn);
+	if (ret)
+		return ret;
+
+	napi_enable(&common->napi_tx);
+	napi_enable(&common->napi_rx);
+	if (common->rx_irq_disabled) {
+		common->rx_irq_disabled = false;
+		enable_irq(common->rx_chns.irq);
+	}
+
+	return 0;
+}
+
+static void virt_cpsw_nuss_tx_cleanup(void *data, dma_addr_t desc_dma);
+static void virt_cpsw_nuss_rx_cleanup(void *data, dma_addr_t desc_dma);
+
+static void virt_cpsw_nuss_common_stop(struct virt_cpsw_common *common)
+{
+	int i;
+
+	/* shutdown tx channels */
+	atomic_set(&common->tdown_cnt, VIRT_CPSW_MAX_TX_QUEUES);
+	/* ensure new tdown_cnt value is visible */
+	smp_mb__after_atomic();
+	reinit_completion(&common->tdown_complete);
+
+	k3_udma_glue_tdown_tx_chn(common->tx_chns.tx_chn, false);
+
+	i = wait_for_completion_timeout(&common->tdown_complete,
+					msecs_to_jiffies(1000));
+	if (!i)
+		dev_err(common->dev, "tx teardown timeout\n");
+
+	k3_udma_glue_reset_tx_chn(common->tx_chns.tx_chn,
+				  &common->tx_chns,
+				  virt_cpsw_nuss_tx_cleanup);
+	k3_udma_glue_disable_tx_chn(common->tx_chns.tx_chn);
+	napi_disable(&common->napi_tx);
+	hrtimer_cancel(&common->tx_hrtimer);
+
+	k3_udma_glue_rx_flow_disable(common->rx_chns.rx_chn, 0);
+	/* Need some delay to process RX ring before reset */
+	msleep(100);
+	k3_udma_glue_reset_rx_chn(common->rx_chns.rx_chn, 0,
+				  &common->rx_chns,
+				  virt_cpsw_nuss_rx_cleanup, false);
+	napi_disable(&common->napi_rx);
+	hrtimer_cancel(&common->rx_hrtimer);
+	cancel_work_sync(&common->rx_mode_work);
+}
+
+static int virt_cpsw_nuss_del_mc(struct net_device *ndev, const u8 *addr);
+
+static int virt_cpsw_nuss_ndo_stop(struct net_device *ndev)
+{
+	struct virt_cpsw_common *common = virt_ndev_to_common(ndev);
+	struct rpmsg_remotedev_eth_switch_ops *rdev_ops;
+	struct device *dev = common->dev;
+	int ret;
+
+	rdev_ops = common->rdev_switch_ops;
+	netif_tx_stop_all_queues(ndev);
+	netif_carrier_off(ndev);
+
+	ret = rdev_ops->unregister_mac(common->rdev, (void *)ndev->dev_addr,
+				       common->rdev_rx_flow_id);
+	if (ret)
+		dev_err(dev, "unregister_mac rpmsg - fail %d\n", ret);
+
+	__dev_mc_unsync(ndev, virt_cpsw_nuss_del_mc);
+	__hw_addr_init(&common->mc_list);
+	virt_cpsw_nuss_common_stop(common);
+
+	dev_info(common->dev, "virt_cpsw_nuss mac stopped\n");
+	return 0;
+}
+
+static int virt_cpsw_nuss_ndo_open(struct net_device *ndev)
+{
+	struct virt_cpsw_common *common = virt_ndev_to_common(ndev);
+	struct rpmsg_remotedev_eth_switch_ops *rdev_ops;
+	struct device *dev = common->dev;
+	int ret;
+
+	rdev_ops = common->rdev_switch_ops;
+	netdev_tx_reset_queue(netdev_get_tx_queue(ndev, 0));
+
+	ret = virt_cpsw_nuss_common_open(common, ndev->features);
+	if (ret)
+		return ret;
+
+	ret = rdev_ops->register_mac(common->rdev,
+				     (void *)ndev->dev_addr,
+				     common->rdev_rx_flow_id);
+	if (ret) {
+		dev_err(dev, "register_mac rpmsg - fail %d\n", ret);
+		virt_cpsw_nuss_common_stop(common);
+		return ret;
+	}
+
+	netif_tx_wake_all_queues(ndev);
+	netif_carrier_on(ndev);
+
+	dev_info(common->dev, "virt_cpsw_nuss mac started\n");
+	return 0;
+}
+
+static void virt_cpsw_nuss_rx_cleanup(void *data, dma_addr_t desc_dma)
+{
+	struct virt_cpsw_rx_chn *rx_chn = data;
+	struct cppi5_host_desc_t *desc_rx;
+	struct sk_buff *skb;
+	dma_addr_t buf_dma;
+	u32 buf_dma_len;
+	void **swdata;
+
+	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
+	swdata = cppi5_hdesc_get_swdata(desc_rx);
+	skb = *swdata;
+	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
+
+	dma_unmap_single(rx_chn->dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
+	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
+
+	dev_kfree_skb_any(skb);
+}
+
+/* RX psdata[2] word format - checksum information */
+#define AM65_CPSW_RX_PSD_CSUM_ADD	GENMASK(15, 0)
+#define AM65_CPSW_RX_PSD_CSUM_ERR	BIT(16)
+#define AM65_CPSW_RX_PSD_IS_FRAGMENT	BIT(17)
+#define AM65_CPSW_RX_PSD_IS_TCP		BIT(18)
+#define AM65_CPSW_RX_PSD_IPV6_VALID	BIT(19)
+#define AM65_CPSW_RX_PSD_IPV4_VALID	BIT(20)
+
+static void virt_cpsw_nuss_rx_csum(struct sk_buff *skb, u32 csum_info)
+{
+	/* HW can verify IPv4/IPv6 TCP/UDP packets checksum
+	 * csum information provides in psdata[2] word:
+	 * AM65_CPSW_RX_PSD_CSUM_ERR bit - indicates csum error
+	 * AM65_CPSW_RX_PSD_IPV6_VALID and AM65_CPSW_RX_PSD_IPV4_VALID
+	 * bits - indicates IPv4/IPv6 packet
+	 * AM65_CPSW_RX_PSD_IS_FRAGMENT bit - indicates fragmented packet
+	 * AM65_CPSW_RX_PSD_CSUM_ADD has value 0xFFFF for non fragmented packets
+	 * or csum value for fragmented packets if !AM65_CPSW_RX_PSD_CSUM_ERR
+	 */
+	skb_checksum_none_assert(skb);
+
+	if (unlikely(!(skb->dev->features & NETIF_F_RXCSUM)))
+		return;
+
+	if ((csum_info & (AM65_CPSW_RX_PSD_IPV6_VALID |
+			  AM65_CPSW_RX_PSD_IPV4_VALID)) &&
+			  !(csum_info & AM65_CPSW_RX_PSD_CSUM_ERR)) {
+		/* csum for fragmented packets is unsupported */
+		if (!(csum_info & AM65_CPSW_RX_PSD_IS_FRAGMENT))
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+	}
+}
+
+static int virt_cpsw_nuss_rx_packets(struct virt_cpsw_common *common,
+				     u32 flow_idx)
+{
+	struct virt_cpsw_rx_chn *rx_chn = &common->rx_chns;
+	struct device *dev = common->dev;
+	struct virt_cpsw_ndev_priv *ndev_priv;
+	struct virt_cpsw_ndev_stats *stats;
+	struct net_device *ndev;
+	struct cppi5_host_desc_t *desc_rx;
+	struct sk_buff *skb, *new_skb;
+	dma_addr_t desc_dma, buf_dma;
+	u32 buf_dma_len, pkt_len, port_id = 0, csum_info;
+	int ret = 0;
+	void **swdata;
+	u32 *psdata;
+
+	ret = k3_udma_glue_pop_rx_chn(rx_chn->rx_chn, flow_idx, &desc_dma);
+	if (ret) {
+		if (ret != -ENODATA)
+			dev_err(dev, "RX: pop chn fail %d\n", ret);
+		return ret;
+	}
+
+	if (desc_dma & 0x1) {
+		dev_dbg(dev, "%s RX tdown flow: %u\n", __func__, flow_idx);
+		return 0;
+	}
+
+	desc_rx = k3_cppi_desc_pool_dma2virt(rx_chn->desc_pool, desc_dma);
+	dev_dbg(dev, "%s flow_idx: %u desc %pad\n",
+		__func__, flow_idx, &desc_dma);
+
+	swdata = cppi5_hdesc_get_swdata(desc_rx);
+	skb = *swdata;
+	cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
+	pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
+	cppi5_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL);
+	/* read port for dbg */
+	dev_dbg(dev, "%s rx port_id:%d\n", __func__, port_id);
+	ndev = common->ports.ndev;
+	skb->dev = ndev;
+
+	psdata = cppi5_hdesc_get_psdata(desc_rx);
+	csum_info = psdata[2];
+	dev_dbg(dev, "%s rx csum_info:%#x\n", __func__, csum_info);
+
+	dma_unmap_single(dev, buf_dma, buf_dma_len, DMA_FROM_DEVICE);
+
+	k3_cppi_desc_pool_free(rx_chn->desc_pool, desc_rx);
+
+	if (unlikely(!netif_running(skb->dev))) {
+		dev_kfree_skb_any(skb);
+		return -ENODEV;
+	}
+
+	new_skb = netdev_alloc_skb_ip_align(ndev, VIRT_CPSW_MAX_PACKET_SIZE);
+	if (new_skb) {
+		skb_put(skb, pkt_len);
+		skb->protocol = eth_type_trans(skb, ndev);
+		virt_cpsw_nuss_rx_csum(skb, csum_info);
+		napi_gro_receive(&common->napi_rx, skb);
+
+		ndev_priv = netdev_priv(ndev);
+		stats = this_cpu_ptr(ndev_priv->stats);
+
+		u64_stats_update_begin(&stats->syncp);
+		stats->rx_packets++;
+		stats->rx_bytes += pkt_len;
+		u64_stats_update_end(&stats->syncp);
+		kmemleak_not_leak(new_skb);
+	} else {
+		ndev->stats.rx_dropped++;
+		new_skb = skb;
+	}
+
+	if (netif_dormant(ndev)) {
+		dev_kfree_skb_any(new_skb);
+		ndev->stats.rx_dropped++;
+		return -ENODEV;
+	}
+
+	ret = virt_cpsw_nuss_rx_push(common, new_skb);
+	if (WARN_ON(ret < 0)) {
+		dev_kfree_skb_any(new_skb);
+		ndev->stats.rx_errors++;
+		ndev->stats.rx_dropped++;
+	}
+
+	return ret;
+}
+
+static enum hrtimer_restart virt_cpsw_nuss_rx_timer_callback(struct hrtimer *timer)
+{
+	struct virt_cpsw_common *common =
+			container_of(timer, struct virt_cpsw_common, rx_hrtimer);
+
+	enable_irq(common->rx_chns.irq);
+	return HRTIMER_NORESTART;
+}
+
+static int virt_cpsw_nuss_rx_poll(struct napi_struct *napi_rx, int budget)
+{
+	struct virt_cpsw_common *common =
+			container_of(napi_rx, struct virt_cpsw_common, napi_rx);
+	int num_rx = 0;
+	int cur_budget;
+	int ret;
+
+	/* process every flow */
+	cur_budget = budget;
+
+	while (cur_budget--) {
+		ret = virt_cpsw_nuss_rx_packets(common, 0);
+		if (ret)
+			break;
+		num_rx++;
+	}
+
+	dev_dbg(common->dev, "%s num_rx:%d %d\n", __func__, num_rx, budget);
+
+	if (num_rx < budget && napi_complete_done(napi_rx, num_rx)) {
+		if (common->rx_irq_disabled) {
+			common->rx_irq_disabled = false;
+			if (unlikely(common->rx_pace_timeout)) {
+				hrtimer_start(&common->rx_hrtimer,
+					      ns_to_ktime(common->rx_pace_timeout),
+					      HRTIMER_MODE_REL_PINNED);
+			} else {
+				enable_irq(common->rx_chns.irq);
+			}
+		}
+	}
+
+	return num_rx;
+}
+
+static void virt_cpsw_nuss_xmit_free(struct virt_cpsw_tx_chn *tx_chn,
+				     struct device *dev,
+				     struct cppi5_host_desc_t *desc)
+{
+	struct cppi5_host_desc_t *first_desc, *next_desc;
+	dma_addr_t buf_dma, next_desc_dma;
+	u32 buf_dma_len;
+
+	first_desc = desc;
+	next_desc = first_desc;
+
+	cppi5_hdesc_get_obuf(first_desc, &buf_dma, &buf_dma_len);
+
+	dma_unmap_single(dev, buf_dma, buf_dma_len,
+			 DMA_TO_DEVICE);
+
+	next_desc_dma = cppi5_hdesc_get_next_hbdesc(first_desc);
+	while (next_desc_dma) {
+		next_desc = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool,
+						       next_desc_dma);
+		cppi5_hdesc_get_obuf(next_desc, &buf_dma, &buf_dma_len);
+
+		dma_unmap_page(dev, buf_dma, buf_dma_len,
+			       DMA_TO_DEVICE);
+
+		next_desc_dma = cppi5_hdesc_get_next_hbdesc(next_desc);
+
+		k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc);
+	}
+
+	k3_cppi_desc_pool_free(tx_chn->desc_pool, first_desc);
+}
+
+static void virt_cpsw_nuss_tx_cleanup(void *data, dma_addr_t desc_dma)
+{
+	struct virt_cpsw_tx_chn *tx_chn = data;
+	struct cppi5_host_desc_t *desc_tx;
+	struct sk_buff *skb;
+	void **swdata;
+
+	desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool, desc_dma);
+	swdata = cppi5_hdesc_get_swdata(desc_tx);
+	skb = *(swdata);
+	virt_cpsw_nuss_xmit_free(tx_chn, tx_chn->dev, desc_tx);
+
+	dev_kfree_skb_any(skb);
+}
+
+static int virt_cpsw_nuss_tx_compl_packets(struct virt_cpsw_common *common,
+					   int chn, unsigned int budget, bool *tdown)
+{
+	struct cppi5_host_desc_t *desc_tx;
+	struct device *dev = common->dev;
+	struct netdev_queue *netif_txq;
+	struct virt_cpsw_tx_chn *tx_chn;
+	struct net_device *ndev;
+	unsigned int total_bytes = 0;
+	struct sk_buff *skb;
+	dma_addr_t desc_dma;
+	int res, num_tx = 0;
+	void **swdata;
+
+	tx_chn = &common->tx_chns;
+
+	while (budget--) {
+		struct virt_cpsw_ndev_priv *ndev_priv;
+		struct virt_cpsw_ndev_stats *stats;
+
+		res = k3_udma_glue_pop_tx_chn(tx_chn->tx_chn, &desc_dma);
+		if (res == -ENODATA)
+			break;
+
+		if (desc_dma & 0x1) {
+			if (atomic_dec_and_test(&common->tdown_cnt))
+				complete(&common->tdown_complete);
+			*tdown = true;
+			break;
+		}
+
+		desc_tx = k3_cppi_desc_pool_dma2virt(tx_chn->desc_pool,
+						     desc_dma);
+		swdata = cppi5_hdesc_get_swdata(desc_tx);
+		skb = *(swdata);
+		virt_cpsw_nuss_xmit_free(tx_chn, dev, desc_tx);
+
+		ndev = skb->dev;
+
+		ndev_priv = netdev_priv(ndev);
+		stats = this_cpu_ptr(ndev_priv->stats);
+		u64_stats_update_begin(&stats->syncp);
+		stats->tx_packets++;
+		stats->tx_bytes += skb->len;
+		u64_stats_update_end(&stats->syncp);
+
+		total_bytes += skb->len;
+		napi_consume_skb(skb, budget);
+		num_tx++;
+	}
+
+	if (!num_tx)
+		return 0;
+
+	netif_txq = netdev_get_tx_queue(ndev, 0);
+
+	netdev_tx_completed_queue(netif_txq, num_tx, total_bytes);
+	dev_dbg(dev, "compl 0 %d Bytes\n", total_bytes);
+
+	if (netif_tx_queue_stopped(netif_txq)) {
+		/* Check whether the queue is stopped due to stalled tx dma,
+		 * if the queue is stopped then wake the queue as
+		 * we have free desc for tx
+		 */
+		__netif_tx_lock(netif_txq, smp_processor_id());
+		if (netif_running(ndev) &&
+		    (k3_cppi_desc_pool_avail(tx_chn->desc_pool) >=
+		     MAX_SKB_FRAGS))
+			netif_tx_wake_queue(netif_txq);
+
+		__netif_tx_unlock(netif_txq);
+	}
+	dev_dbg(dev, "%s:%u pkt:%d\n", __func__, chn, num_tx);
+
+	return num_tx;
+}
+
+static enum hrtimer_restart virt_cpsw_nuss_tx_timer_callback(struct hrtimer *timer)
+{
+	struct virt_cpsw_common *common =
+			container_of(timer, struct virt_cpsw_common, tx_hrtimer);
+
+	enable_irq(common->tx_chns.irq);
+	return HRTIMER_NORESTART;
+}
+
+static int virt_cpsw_nuss_tx_poll(struct napi_struct *napi_tx, int budget)
+{
+	struct virt_cpsw_common *common =
+			container_of(napi_tx, struct virt_cpsw_common, napi_tx);
+	bool tdown = false;
+	int num_tx;
+
+	/* process every unprocessed channel */
+	num_tx = virt_cpsw_nuss_tx_compl_packets(common, 0, budget, &tdown);
+
+	if (num_tx >= budget)
+		return budget;
+
+	if (napi_complete_done(napi_tx, num_tx)) {
+		if (unlikely(common->tx_pace_timeout && !tdown)) {
+			hrtimer_start(&common->tx_hrtimer,
+				      ns_to_ktime(common->tx_pace_timeout),
+				      HRTIMER_MODE_REL_PINNED);
+		} else {
+			enable_irq(common->tx_chns.irq);
+		}
+	}
+
+	return 0;
+}
+
+static irqreturn_t virt_cpsw_nuss_rx_irq(int irq, void *dev_id)
+{
+	struct virt_cpsw_common *common = dev_id;
+
+	common->rx_irq_disabled = true;
+	disable_irq_nosync(irq);
+	napi_schedule(&common->napi_rx);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t virt_cpsw_nuss_tx_irq(int irq, void *dev_id)
+{
+	struct virt_cpsw_common *common = dev_id;
+
+	disable_irq_nosync(irq);
+	napi_schedule(&common->napi_tx);
+
+	return IRQ_HANDLED;
+}
+
+static netdev_tx_t virt_cpsw_nuss_ndo_xmit(struct sk_buff *skb,
+					   struct net_device *ndev)
+{
+	struct virt_cpsw_common *common = virt_ndev_to_common(ndev);
+	struct device *dev = common->dev;
+	struct cppi5_host_desc_t *first_desc, *next_desc, *cur_desc;
+	struct virt_cpsw_tx_chn *tx_chn;
+	struct netdev_queue *netif_txq;
+	dma_addr_t desc_dma, buf_dma;
+	int ret, i;
+	u32 pkt_len;
+	void **swdata;
+	u32 *psdata;
+
+	/* padding enabled in hw */
+	pkt_len = skb_headlen(skb);
+
+	tx_chn = &common->tx_chns;
+	netif_txq = netdev_get_tx_queue(ndev, 0);
+
+	/* Map the linear buffer */
+	buf_dma = dma_map_single(dev, skb->data, pkt_len,
+				 DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(dev, buf_dma))) {
+		dev_err(dev, "Failed to map tx skb buffer\n");
+		ndev->stats.tx_errors++;
+		goto drop_free_skb;
+	}
+
+	first_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
+	if (!first_desc) {
+		dev_dbg(dev, "Failed to allocate descriptor\n");
+		dma_unmap_single(dev, buf_dma, pkt_len, DMA_TO_DEVICE);
+		goto busy_stop_q;
+	}
+
+	cppi5_hdesc_init(first_desc, CPPI5_INFO0_HDESC_EPIB_PRESENT,
+			 VIRT_CPSW_NAV_PS_DATA_SIZE);
+	cppi5_desc_set_pktids(&first_desc->hdr, 0, 0x3FFF);
+	cppi5_hdesc_set_pkttype(first_desc, 0x7);
+	/* target port has to be 0 */
+	cppi5_desc_set_tags_ids(&first_desc->hdr, 0, common->mac_only_port);
+
+	cppi5_hdesc_attach_buf(first_desc, buf_dma, pkt_len, buf_dma, pkt_len);
+	swdata = cppi5_hdesc_get_swdata(first_desc);
+	*(swdata) = skb;
+	psdata = cppi5_hdesc_get_psdata(first_desc);
+
+	/* HW csum offload if enabled */
+	psdata[2] = 0;
+	if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) {
+		unsigned int cs_start, cs_offset;
+
+		cs_start = skb_transport_offset(skb);
+		cs_offset = cs_start + skb->csum_offset;
+		/* HW numerates bytes starting from 1 */
+		psdata[2] = ((cs_offset + 1) << 24) |
+			    ((cs_start + 1) << 16) | (skb->len - cs_start);
+		dev_dbg(dev, "%s tx psdata:%#x\n", __func__, psdata[2]);
+	}
+
+	if (!skb_is_nonlinear(skb))
+		goto done_tx;
+
+	dev_dbg(dev, "fragmented SKB\n");
+
+	/* Handle the case where skb is fragmented in pages */
+	cur_desc = first_desc;
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+		u32 frag_size = skb_frag_size(frag);
+
+		next_desc = k3_cppi_desc_pool_alloc(tx_chn->desc_pool);
+		if (!next_desc) {
+			dev_err(dev, "Failed to allocate descriptor\n");
+			goto busy_free_descs;
+		}
+
+		buf_dma = skb_frag_dma_map(dev, frag, 0, frag_size,
+					   DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(dev, buf_dma))) {
+			dev_err(dev, "Failed to map tx skb page\n");
+			k3_cppi_desc_pool_free(tx_chn->desc_pool, next_desc);
+			ndev->stats.tx_errors++;
+			goto drop_free_descs;
+		}
+
+		cppi5_hdesc_reset_hbdesc(next_desc);
+		cppi5_hdesc_attach_buf(next_desc,
+				       buf_dma, frag_size, buf_dma, frag_size);
+
+		desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool,
+						      next_desc);
+		cppi5_hdesc_link_hbdesc(cur_desc, desc_dma);
+
+		pkt_len += frag_size;
+		cur_desc = next_desc;
+	}
+	WARN_ON(pkt_len != skb->len);
+
+done_tx:
+	skb_tx_timestamp(skb);
+
+	/* report bql before sending packet */
+	dev_dbg(dev, "push 0 %d Bytes\n", pkt_len);
+
+	netdev_tx_sent_queue(netif_txq, pkt_len);
+
+	cppi5_hdesc_set_pktlen(first_desc, pkt_len);
+	desc_dma = k3_cppi_desc_pool_virt2dma(tx_chn->desc_pool, first_desc);
+	ret = k3_udma_glue_push_tx_chn(tx_chn->tx_chn, first_desc, desc_dma);
+	if (ret) {
+		dev_err(dev, "can't push desc %d\n", ret);
+		/* inform bql */
+		netdev_tx_completed_queue(netif_txq, 1, pkt_len);
+		ndev->stats.tx_errors++;
+		goto drop_free_descs;
+	}
+
+	if (k3_cppi_desc_pool_avail(tx_chn->desc_pool) < MAX_SKB_FRAGS) {
+		netif_tx_stop_queue(netif_txq);
+		/* Barrier, so that stop_queue visible to other cpus */
+		smp_mb__after_atomic();
+		dev_dbg(dev, "netif_tx_stop_queue %d\n", 0);
+
+		/* re-check for smp */
+		if (k3_cppi_desc_pool_avail(tx_chn->desc_pool) >=
+		    MAX_SKB_FRAGS) {
+			netif_tx_wake_queue(netif_txq);
+			dev_dbg(dev, "netif_tx_wake_queue %d\n", 0);
+		}
+	}
+
+	return NETDEV_TX_OK;
+
+drop_free_descs:
+	virt_cpsw_nuss_xmit_free(tx_chn, dev, first_desc);
+drop_free_skb:
+	ndev->stats.tx_dropped++;
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+
+busy_free_descs:
+	virt_cpsw_nuss_xmit_free(tx_chn, dev, first_desc);
+busy_stop_q:
+	netif_tx_stop_queue(netif_txq);
+	return NETDEV_TX_BUSY;
+}
+
+static void virt_cpsw_nuss_ndo_get_stats(struct net_device *dev,
+					 struct rtnl_link_stats64 *stats)
+{
+	struct virt_cpsw_ndev_priv *ndev_priv = netdev_priv(dev);
+	unsigned int start;
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		struct virt_cpsw_ndev_stats *cpu_stats;
+		u64 rx_packets;
+		u64 rx_bytes;
+		u64 tx_packets;
+		u64 tx_bytes;
+
+		cpu_stats = per_cpu_ptr(ndev_priv->stats, cpu);
+		do {
+			start = u64_stats_fetch_begin(&cpu_stats->syncp);
+			rx_packets = cpu_stats->rx_packets;
+			rx_bytes   = cpu_stats->rx_bytes;
+			tx_packets = cpu_stats->tx_packets;
+			tx_bytes   = cpu_stats->tx_bytes;
+		} while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
+
+		stats->rx_packets += rx_packets;
+		stats->rx_bytes   += rx_bytes;
+		stats->tx_packets += tx_packets;
+		stats->tx_bytes   += tx_bytes;
+	}
+
+	stats->rx_errors	= dev->stats.rx_errors;
+	stats->rx_dropped	= dev->stats.rx_dropped;
+	stats->tx_dropped	= dev->stats.tx_dropped;
+}
+
+static int virt_cpsw_nuss_add_mc(struct net_device *ndev, const u8 *addr)
+{
+	struct virt_cpsw_common *common = virt_ndev_to_common(ndev);
+	struct rpmsg_remotedev_eth_switch_ops *rdev_ops;
+	struct device *dev;
+	int ret;
+
+	dev = common->dev;
+	rdev_ops = common->rdev_switch_ops;
+
+	ret = rdev_ops->filter_add_mc(common->rdev, addr, 0, common->rdev_rx_flow_id);
+	if (ret) {
+		dev_err(dev, "filter_add_mc rpmsg - fail %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int virt_cpsw_nuss_del_mc(struct net_device *ndev, const u8 *addr)
+{
+	struct virt_cpsw_common *common = virt_ndev_to_common(ndev);
+	struct rpmsg_remotedev_eth_switch_ops *rdev_ops;
+	struct device *dev;
+	int ret;
+
+	dev = common->dev;
+	rdev_ops = common->rdev_switch_ops;
+
+	ret = rdev_ops->filter_del_mc(common->rdev, addr, 0, common->rdev_rx_flow_id);
+	if (ret) {
+		dev_err(dev, "filter_add_mc rpmsg - fail %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void virt_cpsw_nuss_ndo_set_rx_mode_work(struct work_struct *work)
+{
+	struct rpmsg_remotedev_eth_switch_ops *rdev_ops;
+	struct virt_cpsw_common *common;
+	struct net_device *ndev;
+	struct device *dev;
+	int ret;
+
+	common = container_of(work, struct virt_cpsw_common, rx_mode_work);
+	dev = common->dev;
+	rdev_ops = common->rdev_switch_ops;
+
+	if (common->mac_only) {
+		ret = rdev_ops->set_promisc_mode(common->rdev,
+						 common->ports.ndev->flags & IFF_PROMISC);
+		if (ret) {
+			dev_err(dev, "set_promisc rpmsg - fail %d\n", ret);
+			return;
+		}
+	} else if (common->mc_filter) {
+		ndev = common->ports.ndev;
+
+		/* make a mc list copy */
+		netif_addr_lock_bh(ndev);
+		__hw_addr_sync(&common->mc_list, &ndev->mc, ndev->addr_len);
+		netif_addr_unlock_bh(ndev);
+
+		__hw_addr_sync_dev(&common->mc_list, ndev,
+				   virt_cpsw_nuss_add_mc, virt_cpsw_nuss_del_mc);
+	}
+}
+
+static void virt_cpsw_nuss_ndo_set_rx_mode(struct net_device *ndev)
+{
+	struct virt_cpsw_common *common = virt_ndev_to_common(ndev);
+
+	if (common->mac_only || common->mc_filter)
+		queue_work(common->cmd_wq, &common->rx_mode_work);
+}
+
+static const struct net_device_ops virt_cpsw_nuss_netdev_ops = {
+	.ndo_open		= virt_cpsw_nuss_ndo_open,
+	.ndo_stop		= virt_cpsw_nuss_ndo_stop,
+	.ndo_start_xmit		= virt_cpsw_nuss_ndo_xmit,
+	.ndo_get_stats64        = virt_cpsw_nuss_ndo_get_stats,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_tx_timeout		= virt_cpsw_nuss_ndo_host_tx_timeout,
+	.ndo_set_rx_mode	= virt_cpsw_nuss_ndo_set_rx_mode,
+};
+
+static void virt_cpsw_nuss_get_drvinfo(struct net_device *ndev,
+				       struct ethtool_drvinfo *info)
+{
+	struct virt_cpsw_common *common = virt_ndev_to_common(ndev);
+	struct rpmsg_remotedev_eth_switch_ops *rdev_ops;
+	char fw_version[ETHTOOL_FWVERS_LEN];
+
+	rdev_ops = common->rdev_switch_ops;
+
+	strscpy(info->driver, dev_driver_string(common->dev),
+		sizeof(info->driver));
+	strscpy(info->version, VIRT_CPSW_DRV_VER, sizeof(info->version));
+	strscpy(info->bus_info, dev_name(common->dev), sizeof(info->bus_info));
+
+	rdev_ops->get_fw_ver(common->rdev, fw_version, ETHTOOL_FWVERS_LEN);
+	strscpy(info->fw_version, fw_version, ETHTOOL_FWVERS_LEN);
+}
+
+static const char virt_cpsw_nuss_ethtool_priv_flags[][ETH_GSTRING_LEN] = {
+	"RPMSG Ping test",
+	"RPMSG Read reg",
+	"RPMSG Dump stat",
+};
+
+static int
+virt_cpsw_nuss_get_sset_count(struct net_device __always_unused *ndev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_TEST:
+		return ARRAY_SIZE(virt_cpsw_nuss_ethtool_priv_flags);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void
+virt_cpsw_nuss_get_strings(struct net_device __always_unused *ndev,
+			   u32 stringset, u8 *data)
+{
+	switch (stringset) {
+	case ETH_SS_TEST:
+		memcpy(data, virt_cpsw_nuss_ethtool_priv_flags,
+		       sizeof(virt_cpsw_nuss_ethtool_priv_flags));
+		break;
+	}
+}
+
+static void virt_cpsw_nuss_self_test(struct net_device *ndev,
+				     struct ethtool_test *eth_test, u64 *data)
+{
+	struct virt_cpsw_common *common = virt_ndev_to_common(ndev);
+	struct device *dev = common->dev;
+	static const char ping_data[] = "0123456789";
+	u32 reg_val;
+	int ret;
+
+	data[0] = 0;
+	ret = common->rdev_switch_ops->ping(common->rdev,
+					    ping_data, strlen(ping_data));
+	if (ret) {
+		dev_err(dev, "rpmsg ping fail %d\n", ret);
+		eth_test->flags |= ETH_TEST_FL_FAILED;
+		data[0] = 1;
+	}
+
+	data[1] = 0;
+	ret = common->rdev_switch_ops->read_reg(common->rdev,
+						0x0C000000, &reg_val);
+	if (ret) {
+		dev_err(dev, "rpmsg read_reg fail %d\n", ret);
+		eth_test->flags |= ETH_TEST_FL_FAILED;
+		data[1] = 1;
+	}
+	dev_dbg(dev, "read_reg rpmsg cpsw_nuss_ver - 0x0C000000:%08X\n",
+		reg_val);
+
+	ret = common->rdev_switch_ops->read_reg(common->rdev,
+						0x0C020000, &reg_val);
+	if (ret) {
+		dev_err(dev, "rpmsg read_reg fail %d\n", ret);
+		eth_test->flags |= ETH_TEST_FL_FAILED;
+		data[1] = 1;
+	}
+	dev_dbg(dev, "read_reg rpmsg cpsw_ver - 0x0C020000:%08X\n",
+		reg_val);
+
+	ret = 0;
+	data[2] = 0;
+	if (common->rdev_features & RPMSG_KDRV_ETHSWITCH_FEATURE_DUMP_STATS)
+		ret = common->rdev_switch_ops->dbg_dump_stats(common->rdev);
+	if (ret) {
+		dev_err(dev, "rpmsg dump_stats fail %d\n", ret);
+		eth_test->flags |= ETH_TEST_FL_FAILED;
+		data[2] = 1;
+	}
+}
+
+static int virt_cpsw_nuss_get_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
+				       struct kernel_ethtool_coalesce *kernel_coal,
+				       struct netlink_ext_ack *extack)
+{
+	struct virt_cpsw_common *common = virt_ndev_to_common(ndev);
+
+	coal->rx_coalesce_usecs = common->rx_pace_timeout / 1000;
+	coal->tx_coalesce_usecs = common->tx_pace_timeout / 1000;
+	return 0;
+}
+
+static int virt_cpsw_nuss_set_coalesce(struct net_device *ndev, struct ethtool_coalesce *coal,
+				       struct kernel_ethtool_coalesce *kernel_coal,
+				       struct netlink_ext_ack *extack)
+{
+	struct virt_cpsw_common *common = virt_ndev_to_common(ndev);
+
+	if (coal->rx_coalesce_usecs && coal->rx_coalesce_usecs < 20)
+		coal->rx_coalesce_usecs = 20;
+
+	if (coal->tx_coalesce_usecs && coal->tx_coalesce_usecs < 20)
+		coal->tx_coalesce_usecs = 20;
+
+	common->tx_pace_timeout = coal->tx_coalesce_usecs * 1000;
+	common->rx_pace_timeout = coal->rx_coalesce_usecs * 1000;
+
+	return 0;
+}
+
+const struct ethtool_ops virt_cpsw_nuss_ethtool_ops = {
+	.get_drvinfo		= virt_cpsw_nuss_get_drvinfo,
+	.get_sset_count		= virt_cpsw_nuss_get_sset_count,
+	.get_strings		= virt_cpsw_nuss_get_strings,
+	.self_test		= virt_cpsw_nuss_self_test,
+	.get_link		= ethtool_op_get_link,
+	.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
+	.get_coalesce           = virt_cpsw_nuss_get_coalesce,
+	.set_coalesce           = virt_cpsw_nuss_set_coalesce,
+};
+
+static void virt_cpsw_nuss_free_tx_chns(void *data)
+{
+	struct virt_cpsw_common *common = data;
+	struct virt_cpsw_tx_chn	*tx_chn = &common->tx_chns;
+
+	if (!IS_ERR_OR_NULL(tx_chn->desc_pool))
+		k3_cppi_desc_pool_destroy(tx_chn->desc_pool);
+
+	if (!IS_ERR_OR_NULL(tx_chn->tx_chn))
+		k3_udma_glue_release_tx_chn(tx_chn->tx_chn);
+
+	memset(tx_chn, 0, sizeof(*tx_chn));
+}
+
+static int virt_cpsw_nuss_init_tx_chns(struct virt_cpsw_common *common)
+{
+	u32 max_desc_num = ALIGN(VIRT_CPSW_MAX_TX_DESC, MAX_SKB_FRAGS);
+	struct virt_cpsw_tx_chn	*tx_chn = &common->tx_chns;
+	struct k3_udma_glue_tx_channel_cfg tx_cfg = { 0 };
+	struct device *dev = common->dev;
+	struct k3_ring_cfg ring_cfg = {
+		.elm_size = K3_RINGACC_RING_ELSIZE_8,
+		.mode = K3_RINGACC_RING_MODE_RING,
+		.flags = 0
+	};
+	char tx_chn_name[IFNAMSIZ];
+	u32 hdesc_size, tx_chn_num;
+	int ret = 0, ret1;
+
+	/* convert to tx chn offset */
+	tx_chn_num = common->rdev_tx_psil_dst_id - common->tx_psil_id_base;
+	snprintf(tx_chn_name, sizeof(tx_chn_name), "tx%d", tx_chn_num);
+
+	init_completion(&common->tdown_complete);
+
+	hdesc_size = cppi5_hdesc_calc_size(true, VIRT_CPSW_NAV_PS_DATA_SIZE,
+					   VIRT_CPSW_NAV_SW_DATA_SIZE);
+
+	tx_cfg.swdata_size = VIRT_CPSW_NAV_SW_DATA_SIZE;
+	tx_cfg.tx_cfg = ring_cfg;
+	tx_cfg.txcq_cfg = ring_cfg;
+	tx_cfg.tx_cfg.size = max_desc_num;
+	tx_cfg.txcq_cfg.size = max_desc_num;
+
+	tx_chn->dev = dev;
+	tx_chn->id = 0;
+	tx_chn->descs_num = max_desc_num;
+	tx_chn->desc_pool = k3_cppi_desc_pool_create_name(dev,
+							  tx_chn->descs_num,
+							  hdesc_size,
+							  tx_chn_name);
+	if (IS_ERR(tx_chn->desc_pool)) {
+		ret = PTR_ERR(tx_chn->desc_pool);
+		dev_err(dev, "Failed to create poll %d\n", ret);
+		goto err;
+	}
+
+	tx_chn->tx_chn = k3_udma_glue_request_tx_chn(dev, tx_chn_name, &tx_cfg);
+	if (IS_ERR(tx_chn->tx_chn)) {
+		ret = PTR_ERR(tx_chn->tx_chn);
+		dev_err(dev, "Failed to request tx dma channel %d\n", ret);
+		goto err;
+	}
+
+	tx_chn->irq = k3_udma_glue_tx_get_irq(tx_chn->tx_chn);
+	if (tx_chn->irq <= 0) {
+		dev_err(dev, "Failed to get tx dma irq %d\n", tx_chn->irq);
+		ret = -ENXIO;
+	}
+
+err:
+	ret1 = devm_add_action(dev, virt_cpsw_nuss_free_tx_chns, common);
+	if (ret1) {
+		dev_err(dev, "failed to add free_tx_chns action %d", ret1);
+		return ret1;
+	}
+
+	return ret;
+}
+
+static void virt_cpsw_nuss_free_rx_chns(void *data)
+{
+	struct virt_cpsw_common *common = data;
+	struct virt_cpsw_rx_chn *rx_chn = &common->rx_chns;
+
+	if (!IS_ERR_OR_NULL(rx_chn->desc_pool))
+		k3_cppi_desc_pool_destroy(rx_chn->desc_pool);
+
+	if (!IS_ERR_OR_NULL(rx_chn->rx_chn))
+		k3_udma_glue_release_rx_chn(rx_chn->rx_chn);
+}
+
+static int virt_cpsw_nuss_init_rx_chns(struct virt_cpsw_common *common)
+{
+	struct virt_cpsw_rx_chn *rx_chn = &common->rx_chns;
+	struct k3_udma_glue_rx_channel_cfg rx_cfg = {0};
+	u32  max_desc_num = VIRT_CPSW_MAX_RX_DESC;
+	struct device *dev = common->dev;
+	u32 hdesc_size;
+	int ret = 0, ret1;
+	struct k3_ring_cfg rxring_cfg = {
+		.elm_size = K3_RINGACC_RING_ELSIZE_8,
+		.mode = K3_RINGACC_RING_MODE_MESSAGE,
+		.flags = 0,
+	};
+	struct k3_ring_cfg fdqring_cfg = {
+		.elm_size = K3_RINGACC_RING_ELSIZE_8,
+		.mode = K3_RINGACC_RING_MODE_MESSAGE,
+		.flags = 0,
+	};
+	struct k3_udma_glue_rx_flow_cfg rx_flow_cfg = {
+		.rx_cfg = rxring_cfg,
+		.rxfdq_cfg = fdqring_cfg,
+		.ring_rxq_id = K3_RINGACC_RING_ID_ANY,
+		.ring_rxfdq0_id = K3_RINGACC_RING_ID_ANY,
+		.src_tag_lo_sel = K3_UDMA_GLUE_SRC_TAG_LO_USE_REMOTE_SRC_TAG,
+	};
+
+	hdesc_size = cppi5_hdesc_calc_size(true, VIRT_CPSW_NAV_PS_DATA_SIZE,
+					   VIRT_CPSW_NAV_SW_DATA_SIZE);
+
+	rx_cfg.swdata_size = VIRT_CPSW_NAV_SW_DATA_SIZE;
+	rx_cfg.flow_id_num = VIRT_CPSW_MAX_RX_FLOWS;
+	rx_cfg.flow_id_base = common->rdev_rx_flow_id;
+	rx_cfg.remote = true;
+
+	/* init all flows */
+	rx_chn->dev = dev;
+	rx_chn->descs_num = max_desc_num;
+	rx_chn->desc_pool = k3_cppi_desc_pool_create_name(dev,
+							  rx_chn->descs_num,
+							  hdesc_size, "rx");
+	if (IS_ERR(rx_chn->desc_pool)) {
+		ret = PTR_ERR(rx_chn->desc_pool);
+		dev_err(dev, "Failed to create rx poll %d\n", ret);
+		goto err;
+	}
+
+	rx_chn->rx_chn = k3_udma_glue_request_rx_chn(dev, "rx", &rx_cfg);
+	if (IS_ERR(rx_chn->rx_chn)) {
+		ret = PTR_ERR(rx_chn->rx_chn);
+		dev_err(dev, "Failed to request rx dma channel %d\n", ret);
+		goto err;
+	}
+
+	common->rdev_rx_flow_id =
+			k3_udma_glue_rx_get_flow_id_base(rx_chn->rx_chn);
+	dev_dbg(dev, "used flow-id-base %u\n", common->rdev_rx_flow_id);
+
+	rx_flow_cfg.rx_cfg.size = max_desc_num;
+	rx_flow_cfg.rxfdq_cfg.size = max_desc_num;
+	ret = k3_udma_glue_rx_flow_init(rx_chn->rx_chn,
+					0, &rx_flow_cfg);
+	if (ret) {
+		dev_err(dev, "Failed to init rx flow%d %d\n", 0, ret);
+		goto err;
+	}
+
+	rx_chn->irq = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, 0);
+	if (rx_chn->irq <= 0) {
+		ret = -ENXIO;
+		dev_err(dev, "Failed to get rx dma irq %d\n", rx_chn->irq);
+	}
+
+err:
+	ret1 = devm_add_action(dev, virt_cpsw_nuss_free_rx_chns, common);
+	if (ret1) {
+		dev_err(dev, "failed to add free_rx_chns action %d", ret1);
+		return ret1;
+	}
+
+	return ret;
+}
+
+static int virt_cpsw_nuss_of(struct virt_cpsw_common *common)
+{
+	struct device *dev = common->dev;
+	struct device_node *port_np;
+	struct virt_cpsw_port *port;
+	u8 mac_addr[ETH_ALEN];
+	int ret;
+
+	ret = of_property_read_u32(dev->of_node, "ti,psil-base",
+				   &common->tx_psil_id_base);
+	if (ret) {
+		dev_err(dev, "ti,psil-base read fail %d\n", ret);
+		return ret;
+	}
+
+	port_np = of_get_child_by_name(dev->of_node, "virt-emac-port");
+	if (!port_np)
+		return -ENOENT;
+
+	port = &common->ports;
+	port->common = common;
+	port->name = of_get_property(port_np, "ti,label", NULL);
+
+	ret = of_get_mac_address(port_np, mac_addr);
+	if (!ret)
+		ether_addr_copy(port->local_mac_addr, mac_addr);
+
+	of_node_put(port_np);
+	return 0;
+}
+
+static int virt_cpsw_nuss_rdev_init(struct virt_cpsw_common *common)
+{
+	struct rpmsg_rdev_eth_switch_attach_ext_info attach_info = { 0 };
+	struct device *dev = common->dev;
+	int ret;
+
+	ret = common->rdev_switch_ops->attach_ext(common->rdev, &attach_info);
+	if (ret) {
+		dev_err(dev, "rpmsg attach - fail %d\n", ret);
+		return ret;
+	}
+	dev_err(dev, "rpmsg attach_ext - rx_mtu:%d features:%08X tx_mtu[0]:%d flow_idx:%d tx_cpsw_psil_dst_id:%d mac_addr:%pM mac-only:%d\n",
+		attach_info.rx_mtu, attach_info.features,
+		attach_info.tx_mtu[0],
+		attach_info.flow_idx,
+		attach_info.tx_cpsw_psil_dst_id,
+		attach_info.mac_addr,
+		attach_info.mac_only_port);
+	common->rdev_features = attach_info.features;
+	common->rdev_mtu = VIRT_CPSW_MAX_PACKET_SIZE;
+	common->rdev_tx_psil_dst_id = attach_info.tx_cpsw_psil_dst_id &
+				     (~0x8000);
+	common->rdev_rx_flow_id = attach_info.flow_idx;
+	ether_addr_copy(common->rdev_mac_addr, attach_info.mac_addr);
+
+	if (common->rdev_features & RPMSG_KDRV_ETHSWITCH_FEATURE_MAC_ONLY) {
+		common->mac_only = true;
+		common->mac_only_port = attach_info.mac_only_port;
+	}
+
+	if (common->rdev_features & RPMSG_KDRV_ETHSWITCH_FEATURE_MC_FILTER)
+		common->mc_filter = true;
+
+	if (!common->mac_only && common->mac_only_port)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int virt_cpsw_nuss_init_ndev(struct virt_cpsw_common *common)
+{
+	struct virt_cpsw_ndev_priv *ndev_priv;
+	struct device *dev = common->dev;
+	struct virt_cpsw_port *port;
+	int ret;
+
+	port = &common->ports;
+
+	/* alloc netdev */
+	port->ndev = devm_alloc_etherdev_mqs(common->dev,
+					     sizeof(struct virt_cpsw_ndev_priv),
+					     1, 1);
+	if (!port->ndev) {
+		dev_err(dev, "error allocating net_device\n");
+		return -ENOMEM;
+	}
+
+	ndev_priv = netdev_priv(port->ndev);
+	ndev_priv->port = port;
+	SET_NETDEV_DEV(port->ndev, dev);
+
+	if (is_valid_ether_addr(port->local_mac_addr))
+		eth_hw_addr_set(port->ndev, port->local_mac_addr);
+	else if (is_valid_ether_addr(common->rdev_mac_addr))
+		eth_hw_addr_set(port->ndev, common->rdev_mac_addr);
+
+	port->ndev->min_mtu = VIRT_CPSW_MIN_PACKET_SIZE;
+	port->ndev->max_mtu = VIRT_CPSW_MAX_PACKET_SIZE;
+	port->ndev->hw_features = NETIF_F_SG |
+				  NETIF_F_RXCSUM;
+	port->ndev->features = port->ndev->hw_features;
+	port->ndev->vlan_features |=  NETIF_F_SG;
+	port->ndev->netdev_ops = &virt_cpsw_nuss_netdev_ops;
+	port->ndev->ethtool_ops = &virt_cpsw_nuss_ethtool_ops;
+
+	/* TX checksum offload if supported */
+	if (common->rdev_features & RPMSG_KDRV_ETHSWITCH_FEATURE_TXCSUM)
+		port->ndev->features |= NETIF_F_HW_CSUM;
+
+	ndev_priv->stats = netdev_alloc_pcpu_stats(struct virt_cpsw_ndev_stats);
+	if (!ndev_priv->stats)
+		return -ENOMEM;
+
+	ret = devm_add_action_or_reset(dev, (void(*)(void *))free_percpu,
+				       ndev_priv->stats);
+	if (ret) {
+		dev_err(dev, "failed to add percpu stat free action %d", ret);
+		return ret;
+	}
+
+	netif_napi_add_tx(port->ndev, &common->napi_tx,
+			  virt_cpsw_nuss_tx_poll);
+	netif_napi_add(port->ndev, &common->napi_rx,
+		       virt_cpsw_nuss_rx_poll);
+
+	hrtimer_init(&common->tx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
+	common->tx_hrtimer.function = &virt_cpsw_nuss_tx_timer_callback;
+	hrtimer_init(&common->rx_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED);
+	common->rx_hrtimer.function = &virt_cpsw_nuss_rx_timer_callback;
+
+	ret = register_netdev(port->ndev);
+	if (ret)
+		dev_err(dev, "error registering slave net device %d\n", ret);
+
+	/* can't auto unregister ndev using devm_add_action() due to broken
+	 * devres release sequence in DD core
+	 */
+
+	return ret;
+}
+
+static void virt_cpsw_nuss_cleanup_ndev(struct virt_cpsw_common *common)
+{
+	if (common->ports.ndev)
+		unregister_netdev(common->ports.ndev);
+}
+
+static bool virt_cpsw_dev_check(const struct net_device *ndev)
+{
+	struct virt_cpsw_common *common = virt_ndev_to_common(ndev);
+
+	return ndev->netdev_ops == &virt_cpsw_nuss_netdev_ops && !common->mac_only;
+}
+
+static int virt_cpsw_inetaddr_event(struct notifier_block *unused,
+				    unsigned long event, void *ptr)
+{
+	struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
+	struct rpmsg_remotedev_eth_switch_ops *rdev_ops;
+	struct virt_cpsw_common *common;
+	struct in_ifaddr *ifa;
+	int ret = 0;
+
+	if (!ndev)
+		return NOTIFY_DONE;
+
+	if (!virt_cpsw_dev_check(ndev))
+		goto out;
+
+	ifa = (struct in_ifaddr *)ptr;
+	common = virt_ndev_to_common(ndev);
+	rdev_ops = common->rdev_switch_ops;
+	switch (event) {
+	case NETDEV_UP:
+		ret = rdev_ops->register_ipv4(common->rdev,
+					      (void *)ndev->dev_addr,
+					      ifa->ifa_address);
+		if (ret)
+			dev_err(common->dev, "register_ipv4 rpmsg - fail %d\n",
+				ret);
+		dev_dbg(common->dev, "NETDEV_UP %pI4 %s\n",
+			&ifa->ifa_address, ifa->ifa_label);
+		break;
+
+	case NETDEV_DOWN:
+		ret = rdev_ops->unregister_ipv4(common->rdev,
+						ifa->ifa_address);
+		if (ret)
+			dev_err(common->dev, "unregister_ipv4 rpmsg - fail %d\n",
+				ret);
+		dev_dbg(common->dev, "NETDEV_DOWN %pI4\n", &ifa->ifa_address);
+		break;
+	}
+
+out:
+	return notifier_from_errno(ret);
+}
+
+static const struct of_device_id virt_cpsw_virt_of_mtable[] = {
+	{ .compatible = "ti,j721e-cpsw-virt-mac", },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, virt_cpsw_virt_of_mtable);
+
+static int virt_cpsw_nuss_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct virt_cpsw_common *common;
+	int ret;
+
+	common = devm_kzalloc(dev, sizeof(struct virt_cpsw_common), GFP_KERNEL);
+	if (!common)
+		return -ENOMEM;
+	common->dev = dev;
+
+	ret = of_property_read_string(dev->of_node, "ti,remote-name",
+				      &common->rdev_name);
+	if (ret < 0) {
+		dev_info(dev, "remote-name is not set %d\n", ret);
+		return ret;
+	}
+
+	common->rdev = rpmsg_remotedev_get_named_device(common->rdev_name);
+	if (!common->rdev)
+		return -EPROBE_DEFER;
+	if (IS_ERR(common->rdev)) {
+		ret = PTR_ERR(common->rdev);
+		return ret;
+	}
+	common->rdev_switch_ops = common->rdev->device.eth_switch.ops;
+	ret = devm_add_action_or_reset(dev,
+				       (void(*)(void *))rpmsg_remotedev_put_device,
+				       common->rdev);
+	if (ret) {
+		dev_err(dev, "add remotedev put device action fail:%d", ret);
+		return ret;
+	}
+
+	ret = virt_cpsw_nuss_of(common);
+	if (ret)
+		return ret;
+
+	ret = virt_cpsw_nuss_rdev_init(common);
+	if (ret)
+		return ret;
+	/* init tx channels */
+	ret = virt_cpsw_nuss_init_tx_chns(common);
+	if (ret)
+		return ret;
+	ret = virt_cpsw_nuss_init_rx_chns(common);
+	if (ret)
+		return ret;
+
+	if (common->tx_chns.irq == 0 || common->rx_chns.irq == 0)
+		return -ENXIO;
+
+	dev_set_drvdata(dev, common);
+	__hw_addr_init(&common->mc_list);
+	INIT_WORK(&common->rx_mode_work, virt_cpsw_nuss_ndo_set_rx_mode_work);
+	common->cmd_wq = create_singlethread_workqueue("virt_cpsw");
+	if (!common->cmd_wq) {
+		dev_err(dev, "failure requesting wq\n");
+		return -ENOMEM;
+	}
+
+	ret = virt_cpsw_nuss_init_ndev(common);
+	if (ret)
+		return ret;
+
+	ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(48));
+	if (ret) {
+		dev_err(dev, "error setting dma mask: %d\n", ret);
+		goto unreg_ndev;
+	}
+
+	ret = devm_request_irq(dev, common->tx_chns.irq,
+			       virt_cpsw_nuss_tx_irq,
+			       IRQF_TRIGGER_HIGH, dev_name(dev), common);
+	if (ret) {
+		dev_err(dev, "failure requesting tx irq %u, %d\n",
+			common->tx_chns.irq, ret);
+		goto unreg_ndev;
+	}
+
+	ret = devm_request_irq(dev, common->rx_chns.irq,
+			       virt_cpsw_nuss_rx_irq,
+			       IRQF_TRIGGER_HIGH, dev_name(dev), common);
+	if (ret) {
+		dev_err(dev, "failure requesting rx irq %u, %d\n",
+			common->rx_chns.irq, ret);
+		goto unreg_ndev;
+	}
+
+	if (!common->mac_only) {
+		common->virt_cpsw_inetaddr_nb.notifier_call = &virt_cpsw_inetaddr_event;
+		register_inetaddr_notifier(&common->virt_cpsw_inetaddr_nb);
+	}
+
+	dev_info(common->dev, "virt_cpsw_nuss mac loaded\n");
+	dev_info(dev, "rdev_features:%08X rdev_mtu:%d flow_id:%d tx_psil_dst_id:%04X mac_only:%d\n",
+		 common->rdev_features,
+		 common->rdev_mtu,
+		 common->rdev_rx_flow_id,
+		 common->rdev_tx_psil_dst_id,
+		 common->mac_only_port);
+	dev_info(dev, "local_mac_addr:%pM rdev_mac_addr:%pM\n",
+		 common->ports.local_mac_addr,
+		 common->rdev_mac_addr);
+
+	return 0;
+
+unreg_ndev:
+	virt_cpsw_nuss_cleanup_ndev(common);
+	return ret;
+}
+
+static int virt_cpsw_nuss_remove(struct platform_device *pdev)
+{
+	struct virt_cpsw_common *common = platform_get_drvdata(pdev);
+	struct device *dev = common->dev;
+	int ret;
+
+	if (!common->mac_only)
+		unregister_inetaddr_notifier(&common->virt_cpsw_inetaddr_nb);
+
+	/* must unregister ndevs here because DD release_driver routine calls
+	 * dma_deconfigure(dev) before devres_release_all(dev)
+	 */
+	virt_cpsw_nuss_cleanup_ndev(common);
+	if (common->mac_only)
+		destroy_workqueue(common->cmd_wq);
+
+	ret = common->rdev_switch_ops->detach(common->rdev);
+	if (ret)
+		dev_err(dev, "rpmsg  detach - fail %d\n", ret);
+
+	return 0;
+}
+
+static struct platform_driver virt_cpsw_nuss_driver = {
+	.driver = {
+		.name = VIRT_CPSW_DRV_NAME,
+		.of_match_table = virt_cpsw_virt_of_mtable,
+	},
+	.probe = virt_cpsw_nuss_probe,
+	.remove = virt_cpsw_nuss_remove,
+};
+
+module_platform_driver(virt_cpsw_nuss_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grygorii Strashko <grygorii.strashko@ti.com>");
+MODULE_DESCRIPTION("TI J721E VIRT CPSW Ethernet mac driver");
diff -Naur --no-dereference a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
--- a/drivers/net/ethernet/ti/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/ti/Kconfig	2024-01-28 14:01:31.252353813 -0500
@@ -79,6 +79,18 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called cpsw_new.
 
+config TI_CPSW_PROXY_CLIENT
+	tristate "TI CPSW Proxy Client"
+	depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER
+	help
+	  This driver supports Ethernet functionality for CPSWnG Ethernet SubSystem
+	  which is configured by Ethernet Switch Firmware running on the MAIN R5 Core.
+	  The Ethernet Switch Firmware acts as a proxy to the Linux Client driver, by
+	  performing all the necessary configuration of the CPSW Peripheral while
+	  allowing network data transfer to/from the Linux Client over its allocated
+	  TX DMA Channels and RX DMA Flows.
+
+
 config TI_CPTS
 	tristate "TI Common Platform Time Sync (CPTS) Support"
 	depends on ARCH_OMAP2PLUS || ARCH_KEYSTONE || COMPILE_TEST
@@ -183,4 +195,37 @@
 	help
 	  TI AR7 CPMAC Ethernet support
 
+config TI_RDEV_ETH_SWITCH_VIRT_EMAC
+	tristate "TI Virtual Eth MAC driver"
+	depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER
+	help
+	  Support for 1 Port Virtual Eth MAC driver over remotedev
+	  R5F Eth Switch FW RPMSG protocol. The rpmsg-kdrv framework
+	  is utilized to communicate with Eth Switch FW via RPMSG.
+	  This is available starting with the J721E platform.
+
+config TI_ICSSG_PRUETH
+	tristate "TI Gigabit PRU Ethernet driver"
+	select PHYLIB
+	select TI_ICSS_IEP
+	select PAGE_POOL
+	depends on PRU_REMOTEPROC
+	depends on NET_SWITCHDEV
+	depends on ARCH_K3 && OF && TI_K3_UDMA_GLUE_LAYER
+	help
+	  Support dual Gigabit Ethernet ports over the ICSSG PRU Subsystem.
+	  This subsystem is available starting with the AM65 platform.
+
+	  This driver requires firmware binaries which will run on the PRUs
+	  to support the Ethernet operation. Currently, it supports Ethernet
+	  with 1G and 100M link speed.
+
+config TI_ICSS_IEP
+	tristate "TI PRU ICSS IEP driver"
+	depends on TI_PRUSS
+	default TI_PRUSS
+	help
+	  This enables support for the PRU-ICSS Industrial Ethernet Peripheral
+	  within a PRU-ICSS subsystem present on various TI SoCs.
+
 endif # NET_VENDOR_TI
diff -Naur --no-dereference a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile
--- a/drivers/net/ethernet/ti/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ethernet/ti/Makefile	2024-01-28 14:01:31.252353813 -0500
@@ -7,6 +7,9 @@
 obj-$(CONFIG_TI_DAVINCI_EMAC) += cpsw-common.o
 obj-$(CONFIG_TI_CPSW_SWITCHDEV) += cpsw-common.o
 
+obj-$(CONFIG_TI_CPSW_PROXY_CLIENT) += ti-cpsw-proxy-client.o
+ti-cpsw-proxy-client-y := cpsw-proxy-client.o k3-cppi-desc-pool.o
+
 obj-$(CONFIG_TLAN) += tlan.o
 obj-$(CONFIG_CPMAC) += cpmac.o
 obj-$(CONFIG_TI_DAVINCI_EMAC) += ti_davinci_emac.o
@@ -25,6 +28,13 @@
 keystone_netcp_ethss-y := netcp_ethss.o netcp_sgmii.o netcp_xgbepcsr.o cpsw_ale.o
 
 obj-$(CONFIG_TI_K3_AM65_CPSW_NUSS) += ti-am65-cpsw-nuss.o
-ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o k3-cppi-desc-pool.o am65-cpsw-qos.o
+ti-am65-cpsw-nuss-y := am65-cpsw-nuss.o cpsw_sl.o am65-cpsw-ethtool.o cpsw_ale.o k3-cppi-desc-pool.o am65-cpsw-qos.o am65-debugfs.o
 ti-am65-cpsw-nuss-$(CONFIG_TI_K3_AM65_CPSW_SWITCHDEV) += am65-cpsw-switchdev.o
 obj-$(CONFIG_TI_K3_AM65_CPTS) += am65-cpts.o
+
+obj-$(CONFIG_TI_RDEV_ETH_SWITCH_VIRT_EMAC) += ti-j721e-cpsw-virt-mac.o
+ti-j721e-cpsw-virt-mac-y := j721e-cpsw-virt-mac.o k3-cppi-desc-pool.o
+
+obj-$(CONFIG_TI_ICSSG_PRUETH) += icssg-prueth.o
+icssg-prueth-y := icssg_prueth.o icssg_classifier.o icssg_ethtool.o icssg_queues.o icssg_config.o k3-cppi-desc-pool.o icssg_mii_cfg.o icssg_switchdev.o icssg_qos.o
+obj-$(CONFIG_TI_ICSS_IEP) += icss_iep.o
diff -Naur --no-dereference a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig
--- a/drivers/net/ieee802154/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ieee802154/Kconfig	2024-01-28 14:01:31.252353813 -0500
@@ -66,6 +66,15 @@
 	  This driver can also be built as a module. To do so say M here.
 	  The module will be called 'atusb'.
 
+config IEEE802154_WPANUSB
+	tristate "WPANUSB driver"
+	depends on IEEE802154_DRIVERS && MAC802154 && USB
+	help
+	  Adds support for WPANUSB 802.15.4 adapters.
+
+	  This driver should work with at least the following devices:
+	  * BeagleBoard.org BeagleConnect Freedom
+
 config IEEE802154_ADF7242
 	tristate "ADF7242 transceiver driver"
 	depends on IEEE802154_DRIVERS && MAC802154
diff -Naur --no-dereference a/drivers/net/ieee802154/Makefile b/drivers/net/ieee802154/Makefile
--- a/drivers/net/ieee802154/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/ieee802154/Makefile	2024-01-28 14:01:31.252353813 -0500
@@ -4,6 +4,7 @@
 obj-$(CONFIG_IEEE802154_MRF24J40) += mrf24j40.o
 obj-$(CONFIG_IEEE802154_CC2520) += cc2520.o
 obj-$(CONFIG_IEEE802154_ATUSB) += atusb.o
+obj-$(CONFIG_IEEE802154_WPANUSB) += wpanusb.o
 obj-$(CONFIG_IEEE802154_ADF7242) += adf7242.o
 obj-$(CONFIG_IEEE802154_CA8210) += ca8210.o
 obj-$(CONFIG_IEEE802154_MCR20A) += mcr20a.o
diff -Naur --no-dereference a/drivers/net/ieee802154/wpanusb.c b/drivers/net/ieee802154/wpanusb.c
--- a/drivers/net/ieee802154/wpanusb.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ieee802154/wpanusb.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,778 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the WPANUSB IEEE 802.15.4 dongle
+ *
+ * Copyright (C) 2018 Intel Corp.
+ *
+ * The driver implements SoftMAC 802.15.4 protocol based on atusb
+ * driver for ATUSB IEEE 802.15.4 dongle.
+ *
+ * Written by Andrei Emeltchenko <andrei.emeltchenko@intel.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/usb.h>
+
+#include <net/cfg802154.h>
+#include <net/mac802154.h>
+
+#define DEBUG
+#include "wpanusb.h"
+
+#define WPANUSB_NUM_RX_URBS	4	/* allow for a bit of local latency */
+#define WPANUSB_ALLOC_DELAY_MS	100	/* delay after failed allocation */
+
+#define VENDOR_OUT		(USB_TYPE_VENDOR | USB_DIR_OUT)
+#define VENDOR_IN		(USB_TYPE_VENDOR | USB_DIR_IN)
+
+#define WPANUSB_VALID_CHANNELS	(0x07FFFFFF)
+
+struct wpanusb {
+	struct ieee802154_hw *hw;
+	struct usb_device *udev;
+	int shutdown;			/* non-zero if shutting down */
+
+	/* RX variables */
+	struct delayed_work work;	/* memory allocations */
+	struct usb_anchor idle_urbs;	/* URBs waiting to be submitted */
+	struct usb_anchor rx_urbs;	/* URBs waiting for reception */
+
+	/* TX variables */
+	struct usb_ctrlrequest tx_dr;
+	struct urb *tx_urb;
+	struct sk_buff *tx_skb;
+	u8 tx_ack_seq;			/* current TX ACK sequence number */
+};
+
+/* ----- USB commands without data ----------------------------------------- */
+
+static int wpanusb_control_send(struct wpanusb *wpanusb, unsigned int pipe,
+				u8 request, void *data, u16 size)
+{
+	struct usb_device *udev = wpanusb->udev;
+
+	return usb_control_msg(udev, pipe, request, VENDOR_OUT,
+			       0, 0, data, size, 1000);
+}
+
+static int wpanusb_control_recv(struct wpanusb *wpanusb, u8 request, void *data, u16 size)
+{
+	struct usb_device *udev = wpanusb->udev;
+
+	usb_control_msg(udev, usb_sndctrlpipe(udev, 0), request, VENDOR_OUT,
+			       0, 0, data, size, 1000);
+
+	return usb_control_msg(udev, usb_rcvbulkpipe(udev, 1), request, VENDOR_IN,
+			       0, 0, data, size, 1000);
+}
+
+/* ----- skb allocation ---------------------------------------------------- */
+
+#define MAX_PSDU	127
+#define MAX_RX_XFER	(1 + MAX_PSDU + 2 + 1)	/* PHR+PSDU+CRC+LQI */
+
+#define SKB_WPANUSB(skb)	(*(struct wpanusb **)(skb)->cb)
+
+static void wpanusb_bulk_complete(struct urb *urb);
+
+static int wpanusb_submit_rx_urb(struct wpanusb *wpanusb, struct urb *urb)
+{
+	struct usb_device *udev = wpanusb->udev;
+	struct sk_buff *skb = urb->context;
+	int ret;
+
+	if (!skb) {
+		skb = alloc_skb(MAX_RX_XFER, GFP_KERNEL);
+		if (!skb) {
+			dev_warn_ratelimited(&udev->dev,
+					     "can't allocate skb\n");
+			return -ENOMEM;
+		}
+		skb_put(skb, MAX_RX_XFER);
+		SKB_WPANUSB(skb) = wpanusb;
+	}
+
+	usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, 1),
+			  skb->data, MAX_RX_XFER, wpanusb_bulk_complete, skb);
+	usb_anchor_urb(urb, &wpanusb->rx_urbs);
+
+	ret = usb_submit_urb(urb, GFP_KERNEL);
+	if (ret) {
+		usb_unanchor_urb(urb);
+		kfree_skb(skb);
+		urb->context = NULL;
+	}
+
+	return ret;
+}
+
+static void wpanusb_work_urbs(struct work_struct *work)
+{
+	struct wpanusb *wpanusb =
+		container_of(to_delayed_work(work), struct wpanusb, work);
+	struct usb_device *udev = wpanusb->udev;
+	struct urb *urb;
+	int ret;
+
+	if (wpanusb->shutdown)
+		return;
+
+	do {
+		urb = usb_get_from_anchor(&wpanusb->idle_urbs);
+		if (!urb)
+			return;
+
+		ret = wpanusb_submit_rx_urb(wpanusb, urb);
+	} while (!ret);
+
+	usb_anchor_urb(urb, &wpanusb->idle_urbs);
+	dev_warn_ratelimited(&udev->dev, "can't allocate/submit URB (%d)\n",
+			     ret);
+	schedule_delayed_work(&wpanusb->work,
+			      msecs_to_jiffies(WPANUSB_ALLOC_DELAY_MS) + 1);
+}
+
+/* ----- Asynchronous USB -------------------------------------------------- */
+
+static void wpanusb_tx_done(struct wpanusb *wpanusb, uint8_t seq)
+{
+	struct usb_device *udev = wpanusb->udev;
+	u8 expect = wpanusb->tx_ack_seq;
+
+	dev_dbg(&udev->dev, "seq 0x%02x expect 0x%02x\n", seq, expect);
+
+	if (seq == expect) {
+		ieee802154_xmit_complete(wpanusb->hw, wpanusb->tx_skb, false);
+	} else {
+		dev_dbg(&udev->dev, "unknown ack %u\n", seq);
+
+		ieee802154_wake_queue(wpanusb->hw);
+		if (wpanusb->tx_skb)
+			dev_kfree_skb_irq(wpanusb->tx_skb);
+	}
+}
+
+static void wpanusb_process_urb(struct urb *urb)
+{
+	struct usb_device *udev = urb->dev;
+	struct sk_buff *skb = urb->context;
+	struct wpanusb *wpanusb = SKB_WPANUSB(skb);
+	u8 len, lqi;
+
+	if (!urb->actual_length) {
+		dev_dbg(&udev->dev, "zero-sized URB ?\n");
+		return;
+	}
+
+	len = *skb->data;
+
+	dev_dbg(&udev->dev, "urb %p urb len %u pkt len %u", urb,
+		urb->actual_length, len);
+
+	/* Handle ACK */
+	if (urb->actual_length == 1) {
+		wpanusb_tx_done(wpanusb, len);
+		return;
+	}
+
+	if (len + 1 > urb->actual_length - 1) {
+		dev_dbg(&udev->dev, "frame len %d+1 > URB %u-1\n",
+			len, urb->actual_length);
+		return;
+	}
+
+	if (!ieee802154_is_valid_psdu_len(len)) {
+		dev_dbg(&udev->dev, "frame corrupted\n");
+		return;
+	}
+
+	print_hex_dump_bytes("> ", DUMP_PREFIX_OFFSET, skb->data,
+			     urb->actual_length);
+
+	/* Get LQI at the end of the packet */
+	lqi = skb->data[len + 1];
+	dev_dbg(&udev->dev, "rx len %d lqi 0x%02x\n", len, lqi);
+	skb_pull(skb, 1);	/* remove length */
+	skb_trim(skb, len);	/* remove LQI */
+	ieee802154_rx_irqsafe(wpanusb->hw, skb, lqi);
+	urb->context = NULL;	/* skb is gone */
+}
+
+static void wpanusb_bulk_complete(struct urb *urb)
+{
+	struct usb_device *udev = urb->dev;
+	struct sk_buff *skb = urb->context;
+	struct wpanusb *wpanusb = SKB_WPANUSB(skb);
+
+	dev_dbg(&udev->dev, "status %d len %d\n",
+		urb->status, urb->actual_length);
+
+	if (urb->status) {
+		if (urb->status == -ENOENT) { /* being killed */
+			kfree_skb(skb);
+			urb->context = NULL;
+			return;
+		}
+
+		dev_dbg(&udev->dev, "URB error %d\n", urb->status);
+	} else {
+		wpanusb_process_urb(urb);
+	}
+
+	usb_anchor_urb(urb, &wpanusb->idle_urbs);
+	if (!wpanusb->shutdown)
+		schedule_delayed_work(&wpanusb->work, 0);
+}
+
+/* ----- URB allocation/deallocation --------------------------------------- */
+
+static void wpanusb_free_urbs(struct wpanusb *wpanusb)
+{
+	struct urb *urb;
+
+	do {
+		urb = usb_get_from_anchor(&wpanusb->idle_urbs);
+		if (!urb)
+			break;
+		kfree_skb(urb->context);
+		usb_free_urb(urb);
+	} while (true);
+}
+
+static int wpanusb_alloc_urbs(struct wpanusb *wpanusb, unsigned int n)
+{
+	struct urb *urb;
+
+	while (n--) {
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			wpanusb_free_urbs(wpanusb);
+			return -ENOMEM;
+		}
+		usb_anchor_urb(urb, &wpanusb->idle_urbs);
+	}
+
+	return 0;
+}
+
+/* ----- IEEE 802.15.4 interface operations -------------------------------- */
+
+static void wpanusb_xmit_complete(struct urb *urb)
+{
+	dev_dbg(&urb->dev->dev, "urb transmit completed");
+}
+
+static int wpanusb_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+	int ret = 0;
+
+	dev_dbg(&udev->dev, "len %u", skb->len);
+
+	/* ack_seq range is 0x01 - 0xff */
+	wpanusb->tx_ack_seq++;
+	if (!wpanusb->tx_ack_seq)
+		wpanusb->tx_ack_seq++;
+
+	wpanusb->tx_skb = skb;
+	wpanusb->tx_dr.wIndex = cpu_to_le16(wpanusb->tx_ack_seq);
+	wpanusb->tx_dr.wLength = cpu_to_le16(skb->len);
+
+	usb_fill_control_urb(wpanusb->tx_urb, udev,
+			     usb_sndctrlpipe(udev, 0),
+			     (unsigned char *)&wpanusb->tx_dr, skb->data,
+			     skb->len, wpanusb_xmit_complete, NULL);
+	ret = usb_submit_urb(wpanusb->tx_urb, GFP_ATOMIC);
+
+	dev_dbg(&udev->dev, "%s: ret %d len %u seq %u\n", __func__, ret,
+		skb->len, wpanusb->tx_ack_seq);
+
+	return ret;
+}
+
+static int wpanusb_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+	struct set_channel *req;
+	int ret;
+
+	req = kmalloc(sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	req->page = page;
+	req->channel = channel;
+
+	ret = wpanusb_control_send(wpanusb, usb_sndctrlpipe(udev, 0),
+				   SET_CHANNEL, req, sizeof(*req));
+	kfree(req);
+	if (ret < 0) {
+		dev_err(&udev->dev, "Failed set channel, ret %d", ret);
+		return ret;
+	}
+
+	dev_dbg(&udev->dev, "set page %u channel %u", page, channel);
+
+	return 0;
+}
+
+static int wpanusb_ed(struct ieee802154_hw *hw, u8 *level)
+{
+	WARN_ON(!level);
+
+	*level = 0xbe;
+
+	return 0;
+}
+
+static int wpanusb_set_hw_addr_filt(struct ieee802154_hw *hw,
+				    struct ieee802154_hw_addr_filt *filt,
+				    unsigned long changed)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+	int ret = 0;
+
+	if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
+		struct set_short_addr *req;
+
+		req = kmalloc(sizeof(*req), GFP_KERNEL);
+		if (!req)
+			return -ENOMEM;
+
+		req->short_addr = filt->short_addr;
+
+		ret = wpanusb_control_send(wpanusb, usb_sndctrlpipe(udev, 0),
+					   SET_SHORT_ADDR, req, sizeof(*req));
+		kfree(req);
+		if (ret < 0) {
+			dev_err(&udev->dev, "Failed to set short_addr, ret %d",
+				ret);
+			return ret;
+		}
+
+		dev_dbg(&udev->dev, "short addr changed to 0x%04x",
+			le16_to_cpu(filt->short_addr));
+	}
+
+	if (changed & IEEE802154_AFILT_PANID_CHANGED) {
+		struct set_pan_id *req;
+
+		req = kmalloc(sizeof(*req), GFP_KERNEL);
+		if (!req)
+			return -ENOMEM;
+
+		req->pan_id = filt->pan_id;
+
+		ret = wpanusb_control_send(wpanusb, usb_sndctrlpipe(udev, 0),
+					   SET_PAN_ID, req, sizeof(*req));
+		kfree(req);
+		if (ret < 0) {
+			dev_err(&udev->dev, "Failed to set pan_id, ret %d",
+				ret);
+			return ret;
+		}
+
+		dev_dbg(&udev->dev, "pan id changed to 0x%04x",
+			le16_to_cpu(filt->pan_id));
+	}
+
+	if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
+		struct set_ieee_addr *req;
+
+		req = kmalloc(sizeof(*req), GFP_KERNEL);
+		if (!req)
+			return -ENOMEM;
+
+		memcpy(&req->ieee_addr, &filt->ieee_addr,
+		       sizeof(req->ieee_addr));
+
+		ret = wpanusb_control_send(wpanusb, usb_sndctrlpipe(udev, 0),
+					   SET_IEEE_ADDR, req, sizeof(*req));
+		kfree(req);
+		if (ret < 0) {
+			dev_err(&udev->dev, "Failed to set ieee_addr, ret %d",
+				ret);
+			return ret;
+		}
+
+		dev_dbg(&udev->dev, "IEEE addr changed");
+	}
+
+	if (changed & IEEE802154_AFILT_PANC_CHANGED) {
+		dev_dbg(&udev->dev, "panc changed");
+
+		dev_err(&udev->dev, "Not handled AFILT_PANC_CHANGED");
+	}
+
+	return ret;
+}
+
+static int wpanusb_set_extended_addr(struct ieee802154_hw *hw)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+	unsigned char *buffer;
+	__le64 extended_addr;
+	int ret = 0;
+	u64 addr;
+
+	buffer = kmalloc(IEEE802154_EXTENDED_ADDR_LEN, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	ret = wpanusb_control_send(wpanusb, usb_sndctrlpipe(udev, 0), GET_EXTENDED_ADDR, buffer,
+					IEEE802154_EXTENDED_ADDR_LEN);
+	if (ret < 0) {
+		dev_err(&udev->dev, "failed to fetch extended address, random address set\n");
+		ieee802154_random_extended_addr(&wpanusb->hw->phy->perm_extended_addr);
+		kfree(buffer);
+		return ret;
+	}
+
+	memcpy(&extended_addr, buffer, IEEE802154_EXTENDED_ADDR_LEN);
+	/* Check if read address is not empty and the unicast bit is set correctly */
+	if (!ieee802154_is_valid_extended_unicast_addr(extended_addr)) {
+		dev_info(&udev->dev, "no permanent extended address found, random address set\n");
+		ieee802154_random_extended_addr(&wpanusb->hw->phy->perm_extended_addr);
+	} else {
+		wpanusb->hw->phy->perm_extended_addr = extended_addr;
+		addr = swab64((__force u64)wpanusb->hw->phy->perm_extended_addr);
+		dev_info(&udev->dev, "Read permanent extended address %8phC from device\n", &addr);
+	}
+
+	kfree(buffer);
+	return ret;
+}
+
+/* FIXME: these need to come as capabilities from the device */
+static const s32 wpanusb_powers[] = {
+	300, 280, 230, 180, 130, 70, 0, -100, -200, -300, -400, -500, -700,
+	-900, -1200, -1700,
+};
+
+static int wpanusb_get_device_capabilities(struct ieee802154_hw *hw)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+	unsigned char *buffer;
+	uint32_t valid_channels;
+	int ret = 0;
+
+	buffer = kmalloc(IEEE802154_EXTENDED_ADDR_LEN, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+
+	ret = wpanusb_control_send(wpanusb, usb_sndctrlpipe(udev, 0), GET_EXTENDED_ADDR, buffer,
+					IEEE802154_EXTENDED_ADDR_LEN);
+	if (ret < 0) {
+		dev_err(&udev->dev, "failed to fetch extended address, random address set\n");
+		ieee802154_random_extended_addr(&wpanusb->hw->phy->perm_extended_addr);
+		kfree(buffer);
+		return ret;
+	}
+
+	buffer = kmalloc(sizeof(valid_channels), GFP_NOIO);
+	if (!buffer)
+		return -ENOMEM;
+	ret = wpanusb_control_recv(wpanusb, GET_SUPPORTED_CHANNELS, buffer,	sizeof(valid_channels));
+	valid_channels = *(uint32_t *)buffer;
+	if (ret < 0 || !valid_channels) {
+		dev_err(&udev->dev, "failed to fetch valid channels, setting default valid channels\n");
+		valid_channels = WPANUSB_VALID_CHANNELS;
+	}
+
+	/* FIXME: these need to come from device capabilities */
+	hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT;
+
+	/* FIXME: these need to come from device capabilities */
+	hw->phy->flags = WPAN_PHY_FLAG_TXPOWER;
+
+	/* Set default and supported channels */
+	hw->phy->current_page = 0;
+	hw->phy->current_channel = ffs(valid_channels) - 1; //set to lowest valid channel
+	hw->phy->supported.channels[0] = valid_channels;
+
+	/* FIXME: these need to come from device capabilities */
+	hw->phy->supported.tx_powers = wpanusb_powers;
+	hw->phy->supported.tx_powers_size = ARRAY_SIZE(wpanusb_powers);
+	hw->phy->transmit_power = hw->phy->supported.tx_powers[0];
+
+	kfree(buffer);
+	return ret;
+}
+
+static int wpanusb_start(struct ieee802154_hw *hw)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+	int ret;
+
+	schedule_delayed_work(&wpanusb->work, 0);
+
+	ret = wpanusb_control_send(wpanusb, usb_sndctrlpipe(udev, 0),
+				   START, NULL, 0);
+	if (ret < 0) {
+		dev_err(&udev->dev, "Failed to start ieee802154");
+		usb_kill_anchored_urbs(&wpanusb->idle_urbs);
+	}
+
+	return ret;
+}
+
+static void wpanusb_stop(struct ieee802154_hw *hw)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+	int ret;
+
+	dev_dbg(&udev->dev, "stop");
+
+	usb_kill_anchored_urbs(&wpanusb->idle_urbs);
+
+	ret = wpanusb_control_send(wpanusb, usb_sndctrlpipe(udev, 0),
+				   STOP, NULL, 0);
+	if (ret < 0)
+		dev_err(&udev->dev, "Failed to stop ieee802154");
+}
+
+static int wpanusb_set_txpower(struct ieee802154_hw *hw, s32 mbm)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+
+	dev_err(&udev->dev, "%s: Not handled, mbm %d", __func__, mbm);
+
+	return -ENOTSUPP;
+}
+
+static int wpanusb_set_cca_mode(struct ieee802154_hw *hw,
+				const struct wpan_phy_cca *cca)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+
+	dev_err(&udev->dev, "%s: Not handled, mode %u opt %u",
+		__func__, cca->mode, cca->opt);
+
+	switch (cca->mode) {
+	case NL802154_CCA_ENERGY:
+		break;
+	case NL802154_CCA_CARRIER:
+		break;
+	case NL802154_CCA_ENERGY_CARRIER:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int wpanusb_set_lbt(struct ieee802154_hw *hw, bool on)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+	int ret = 0;
+
+	if (on)
+		ret = wpanusb_control_send(wpanusb, usb_sndctrlpipe(udev, 0),
+				   SET_LBT, NULL, 0);
+
+	return ret;
+}
+
+static int wpanusb_set_frame_retries(struct ieee802154_hw *hw, s8 retries)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+	int ret;
+
+	/* FIXME pass retries onwards to device */
+	ret = wpanusb_control_send(wpanusb, usb_sndctrlpipe(udev, 0),
+				   SET_FRAME_RETRIES, NULL, 0);
+
+	return ret;
+}
+
+static int wpanusb_set_cca_ed_level(struct ieee802154_hw *hw, s32 mbm)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+
+	dev_err(&udev->dev, "%s: Not handled, mbm %d", __func__, mbm);
+
+	return 0;
+}
+
+static int wpanusb_set_csma_params(struct ieee802154_hw *hw, u8 min_be,
+				   u8 max_be, u8 retries)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+
+	dev_err(&udev->dev, "%s: Not handled, min_be %u max_be %u retr %u",
+		__func__, min_be, max_be, retries);
+
+	return 0;
+}
+
+static int wpanusb_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
+{
+	struct wpanusb *wpanusb = hw->priv;
+	struct usb_device *udev = wpanusb->udev;
+
+	dev_err(&udev->dev, "%s: Not handled, on %d", __func__, on);
+
+	return 0;
+}
+
+static const struct ieee802154_ops wpanusb_ops = {
+	.owner			= THIS_MODULE,
+	.xmit_async		= wpanusb_xmit,
+	.ed			= wpanusb_ed,
+	.set_channel		= wpanusb_channel,
+	.start			= wpanusb_start,
+	.stop			= wpanusb_stop,
+	.set_hw_addr_filt	= wpanusb_set_hw_addr_filt,
+	.set_txpower		= wpanusb_set_txpower,
+	.set_lbt		= wpanusb_set_lbt,
+	.set_cca_mode		= wpanusb_set_cca_mode,
+	.set_cca_ed_level	= wpanusb_set_cca_ed_level,
+	.set_csma_params	= wpanusb_set_csma_params,
+	.set_frame_retries	= wpanusb_set_frame_retries,
+	.set_promiscuous_mode	= wpanusb_set_promiscuous_mode,
+};
+
+/* ----- Setup ------------------------------------------------------------- */
+
+static int wpanusb_probe(struct usb_interface *interface,
+			 const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct ieee802154_hw *hw;
+	struct wpanusb *wpanusb;
+	int ret;
+
+	hw = ieee802154_alloc_hw(sizeof(struct wpanusb), &wpanusb_ops);
+	if (!hw)
+		return -ENOMEM;
+
+	wpanusb = hw->priv;
+	wpanusb->hw = hw;
+	wpanusb->udev = usb_get_dev(udev);
+	usb_set_intfdata(interface, wpanusb);
+
+	wpanusb->shutdown = 0;
+	INIT_DELAYED_WORK(&wpanusb->work, wpanusb_work_urbs);
+	init_usb_anchor(&wpanusb->idle_urbs);
+	init_usb_anchor(&wpanusb->rx_urbs);
+
+	ret = wpanusb_alloc_urbs(wpanusb, WPANUSB_NUM_RX_URBS);
+	if (ret)
+		goto fail;
+
+	wpanusb->tx_dr.bRequestType = VENDOR_OUT;
+	wpanusb->tx_dr.bRequest = TX;
+	wpanusb->tx_dr.wValue = cpu_to_le16(0);
+
+	wpanusb->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!wpanusb->tx_urb)
+		goto fail;
+
+	hw->parent = &udev->dev;
+
+	ret = wpanusb_control_send(wpanusb, usb_sndctrlpipe(udev, 0), RESET,
+				   NULL, 0);
+	if (ret < 0) {
+		dev_err(&udev->dev, "Failed to RESET ieee802154");
+		goto fail;
+	}
+
+	ret = wpanusb_get_device_capabilities(hw);
+
+	if (ret < 0) {
+		dev_err(&udev->dev, "Failed to get device capabilities");
+		goto fail;
+	}
+
+	ret = wpanusb_set_extended_addr(hw);
+
+	if (ret < 0) {
+		dev_err(&udev->dev, "Failed to set permanent address");
+		goto fail;
+	}
+
+	ret = ieee802154_register_hw(hw);
+	if (ret) {
+		dev_err(&udev->dev, "Failed to register ieee802154");
+		goto fail;
+	}
+
+	dev_dbg(&udev->dev, "ieee802154 ready to go");
+
+	return 0;
+
+fail:
+	dev_err(&udev->dev, "Failed ieee802154 probe");
+	wpanusb_free_urbs(wpanusb);
+	usb_kill_urb(wpanusb->tx_urb);
+	usb_free_urb(wpanusb->tx_urb);
+	usb_put_dev(udev);
+	ieee802154_free_hw(hw);
+
+	return ret;
+}
+
+static void wpanusb_disconnect(struct usb_interface *interface)
+{
+	struct wpanusb *wpanusb = usb_get_intfdata(interface);
+
+	wpanusb->shutdown = 1;
+	cancel_delayed_work_sync(&wpanusb->work);
+
+	usb_kill_anchored_urbs(&wpanusb->rx_urbs);
+	wpanusb_free_urbs(wpanusb);
+	usb_kill_urb(wpanusb->tx_urb);
+	usb_free_urb(wpanusb->tx_urb);
+
+	ieee802154_unregister_hw(wpanusb->hw);
+
+	ieee802154_free_hw(wpanusb->hw);
+
+	usb_set_intfdata(interface, NULL);
+	usb_put_dev(wpanusb->udev);
+}
+
+/* The devices we work with */
+static const struct usb_device_id wpanusb_device_table[] = {
+	{
+		USB_DEVICE_AND_INTERFACE_INFO(WPANUSB_VENDOR_ID,
+					      WPANUSB_PRODUCT_ID,
+					      USB_CLASS_VENDOR_SPEC,
+					      0, 0),
+                USB_DEVICE_AND_INTERFACE_INFO(BEAGLECONNECT_VENDOR_ID,
+                                                BEAGLECONNECT_PRODUCT_ID,
+                                                USB_CLASS_VENDOR_SPEC,
+                                                0, 0)
+	},
+	/* end with null element */
+	{}
+};
+MODULE_DEVICE_TABLE(usb, wpanusb_device_table);
+
+static struct usb_driver wpanusb_driver = {
+	.name		= "wpanusb",
+	.probe		= wpanusb_probe,
+	.disconnect	= wpanusb_disconnect,
+	.id_table	= wpanusb_device_table,
+};
+module_usb_driver(wpanusb_driver);
+
+MODULE_AUTHOR("Andrei Emeltchenko <andrei.emeltchenko@intel.com>");
+MODULE_DESCRIPTION("WPANUSB IEEE 802.15.4 over USB Driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/net/ieee802154/wpanusb.h b/drivers/net/ieee802154/wpanusb.h
--- a/drivers/net/ieee802154/wpanusb.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/net/ieee802154/wpanusb.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Definitions shared between kernel and WPANUSB firmware
+ *
+ * Copyright (C) 2018 Intel Corp.
+ *
+ * Written by Andrei Emeltchenko <andrei.emeltchenko@intel.com>
+ */
+
+#define WPANUSB_VENDOR_ID	0x2fe3
+#define WPANUSB_PRODUCT_ID	0x0101
+
+#define BEAGLECONNECT_VENDOR_ID  0x2047
+#define BEAGLECONNECT_PRODUCT_ID 0x0aa5
+
+enum wpanusb_requests {
+	RESET,
+	TX,
+	XMIT_ASYNC,
+	ED,
+	SET_CHANNEL,
+	START,
+	STOP,
+	SET_SHORT_ADDR,
+	SET_PAN_ID,
+	SET_IEEE_ADDR,
+	SET_TXPOWER,
+	SET_CCA_MODE,
+	SET_CCA_ED_LEVEL,
+	SET_CSMA_PARAMS,
+	SET_LBT,
+	SET_FRAME_RETRIES,
+	SET_PROMISCUOUS_MODE,
+	GET_EXTENDED_ADDR,
+	GET_SUPPORTED_CHANNELS,
+};
+
+struct set_channel {
+	__u8 page;
+	__u8 channel;
+} __packed;
+
+struct set_short_addr {
+	__le16 short_addr;
+} __packed;
+
+struct set_pan_id {
+	__le16 pan_id;
+} __packed;
+
+struct set_ieee_addr {
+	__le64 ieee_addr;
+} __packed;
diff -Naur --no-dereference a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c
--- a/drivers/net/phy/dp83869.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/phy/dp83869.c	2024-01-28 14:01:31.252353813 -0500
@@ -692,8 +692,19 @@
 	/* Below init sequence for each operational mode is defined in
 	 * section 9.4.8 of the datasheet.
 	 */
+	phy_ctrl_val = dp83869->mode;
+	if (phydev->interface == PHY_INTERFACE_MODE_MII) {
+		if (dp83869->mode == DP83869_100M_MEDIA_CONVERT ||
+		    dp83869->mode == DP83869_RGMII_100_BASE) {
+			phy_ctrl_val |= DP83869_OP_MODE_MII;
+		} else {
+			phydev_err(phydev, "selected op-mode is not valid with MII mode\n");
+			return -EINVAL;
+		}
+	}
+
 	ret = phy_write_mmd(phydev, DP83869_DEVADDR, DP83869_OP_MODE,
-			    dp83869->mode);
+			    phy_ctrl_val);
 	if (ret)
 		return ret;
 
diff -Naur --no-dereference a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h
--- a/drivers/net/phy/mscc/mscc.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/phy/mscc/mscc.h	2024-01-28 14:01:31.252353813 -0500
@@ -196,6 +196,8 @@
 #define MSCC_PHY_EXTENDED_INT_MS_EGR	  BIT(9)
 
 /* Extended Page 3 Registers */
+#define MSCC_PHY_SERDES_PCS_CTRL          16
+#define MSCC_PHY_SERDES_ANEG              BIT(7)
 #define MSCC_PHY_SERDES_TX_VALID_CNT	  21
 #define MSCC_PHY_SERDES_TX_CRC_ERR_CNT	  22
 #define MSCC_PHY_SERDES_RX_VALID_CNT	  28
diff -Naur --no-dereference a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c
--- a/drivers/net/phy/mscc/mscc_main.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/net/phy/mscc/mscc_main.c	2024-01-28 14:01:31.252353813 -0500
@@ -1689,6 +1689,21 @@
 			   PROC_CMD_RST_CONF_PORT | PROC_CMD_FIBER_1000BASE_X);
 }
 
+static int vsc85xx_config_inband_aneg(struct phy_device *phydev, bool enabled)
+{
+	u16 reg_val = 0;
+	int rc;
+
+	if (enabled)
+		reg_val = MSCC_PHY_SERDES_ANEG;
+
+	rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_3,
+			      MSCC_PHY_SERDES_PCS_CTRL, MSCC_PHY_SERDES_ANEG,
+			      reg_val);
+
+	return rc;
+}
+
 static int vsc8584_config_init(struct phy_device *phydev)
 {
 	struct vsc8531_private *vsc8531 = phydev->priv;
@@ -2099,6 +2114,11 @@
 
 	if (ret)
 		return ret;
+
+	ret = vsc85xx_config_inband_aneg(phydev, true);
+
+	if (ret)
+		return ret;
 
 	for (i = 0; i < vsc8531->nleds; i++) {
 		ret = vsc85xx_led_cntl_set(phydev, i, vsc8531->leds_mode[i]);
diff -Naur --no-dereference a/drivers/of/unittest.c b/drivers/of/unittest.c
--- a/drivers/of/unittest.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest.c	2024-01-28 14:01:31.252353813 -0500
@@ -1425,12 +1425,12 @@
 	void *unittest_data_align;
 	struct device_node *unittest_data_node = NULL, *np;
 	/*
-	 * __dtb_testcases_begin[] and __dtb_testcases_end[] are magically
-	 * created by cmd_dt_S_dtb in scripts/Makefile.lib
+	 * __dtbo_testcases_begin[] and __dtbo_testcases_end[] are magically
+	 * created by cmd_dt_S_dtbo in scripts/Makefile.lib
 	 */
-	extern uint8_t __dtb_testcases_begin[];
-	extern uint8_t __dtb_testcases_end[];
-	const int size = __dtb_testcases_end - __dtb_testcases_begin;
+	extern uint8_t __dtbo_testcases_begin[];
+	extern uint8_t __dtbo_testcases_end[];
+	const int size = __dtbo_testcases_end - __dtbo_testcases_begin;
 	int rc;
 	void *ret;
 
@@ -1445,7 +1445,7 @@
 		return -ENOMEM;
 
 	unittest_data_align = PTR_ALIGN(unittest_data, FDT_ALIGN_SIZE);
-	memcpy(unittest_data_align, __dtb_testcases_begin, size);
+	memcpy(unittest_data_align, __dtbo_testcases_begin, size);
 
 	ret = of_fdt_unflatten_tree(unittest_data_align, NULL, &unittest_data_node);
 	if (!ret) {
@@ -3005,24 +3005,24 @@
 #ifdef CONFIG_OF_OVERLAY
 
 /*
- * __dtb_ot_begin[] and __dtb_ot_end[] are created by cmd_dt_S_dtb
- * in scripts/Makefile.lib
+ * __dtbo_##overlay_name##_begin[] and __dtbo_##overlay_name##_end[] are
+ * created by cmd_dt_S_dtbo in scripts/Makefile.lib
  */
 
-#define OVERLAY_INFO_EXTERN(name) \
-	extern uint8_t __dtb_##name##_begin[]; \
-	extern uint8_t __dtb_##name##_end[]
-
-#define OVERLAY_INFO(overlay_name, expected)             \
-{	.dtb_begin       = __dtb_##overlay_name##_begin, \
-	.dtb_end         = __dtb_##overlay_name##_end,   \
-	.expected_result = expected,                     \
-	.name            = #overlay_name,                \
+#define OVERLAY_INFO_EXTERN(overlay_name) \
+	extern uint8_t __dtbo_##overlay_name##_begin[]; \
+	extern uint8_t __dtbo_##overlay_name##_end[]
+
+#define OVERLAY_INFO(overlay_name, expected) \
+{	.dtbo_begin       = __dtbo_##overlay_name##_begin, \
+	.dtbo_end         = __dtbo_##overlay_name##_end, \
+	.expected_result = expected, \
+	.name            = #overlay_name, \
 }
 
 struct overlay_info {
-	uint8_t		*dtb_begin;
-	uint8_t		*dtb_end;
+	uint8_t		*dtbo_begin;
+	uint8_t		*dtbo_end;
 	int		expected_result;
 	int		ovcs_id;
 	char		*name;
@@ -3096,7 +3096,7 @@
 	OVERLAY_INFO(overlay_bad_phandle, -EINVAL),
 	OVERLAY_INFO(overlay_bad_symbol, -EINVAL),
 	/* end marker */
-	{.dtb_begin = NULL, .dtb_end = NULL, .expected_result = 0, .name = NULL}
+	{.dtbo_begin = NULL, .dtbo_end = NULL, .expected_result = 0, .name = NULL}
 };
 
 static struct device_node *overlay_base_root;
@@ -3153,13 +3153,13 @@
 		return;
 	}
 
-	data_size = info->dtb_end - info->dtb_begin;
+	data_size = info->dtbo_end - info->dtbo_begin;
 	if (!data_size) {
 		pr_err("No dtb 'overlay_base' to attach\n");
 		return;
 	}
 
-	size = fdt_totalsize(info->dtb_begin);
+	size = fdt_totalsize(info->dtbo_begin);
 	if (size != data_size) {
 		pr_err("dtb 'overlay_base' header totalsize != actual size");
 		return;
@@ -3171,7 +3171,7 @@
 		return;
 	}
 
-	memcpy(new_fdt, info->dtb_begin, size);
+	memcpy(new_fdt, info->dtbo_begin, size);
 
 	__unflatten_device_tree(new_fdt, NULL, &overlay_base_root,
 				dt_alloc_memory, true);
@@ -3206,11 +3206,11 @@
 		return 0;
 	}
 
-	size = info->dtb_end - info->dtb_begin;
+	size = info->dtbo_end - info->dtbo_begin;
 	if (!size)
 		pr_err("no overlay data for %s\n", overlay_name);
 
-	ret = of_overlay_fdt_apply(info->dtb_begin, size, &info->ovcs_id);
+	ret = of_overlay_fdt_apply(info->dtbo_begin, size, &info->ovcs_id);
 	if (ovcs_id)
 		*ovcs_id = info->ovcs_id;
 	if (ret < 0)
diff -Naur --no-dereference a/drivers/of/unittest-data/Makefile b/drivers/of/unittest-data/Makefile
--- a/drivers/of/unittest-data/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/Makefile	2024-01-28 14:01:31.252353813 -0500
@@ -1,38 +1,38 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-y += testcases.dtb.o
+obj-y += testcases.dtbo.o
 
-obj-$(CONFIG_OF_OVERLAY) += overlay.dtb.o \
-			    overlay_0.dtb.o \
-			    overlay_1.dtb.o \
-			    overlay_2.dtb.o \
-			    overlay_3.dtb.o \
-			    overlay_4.dtb.o \
-			    overlay_5.dtb.o \
-			    overlay_6.dtb.o \
-			    overlay_7.dtb.o \
-			    overlay_8.dtb.o \
-			    overlay_9.dtb.o \
-			    overlay_10.dtb.o \
-			    overlay_11.dtb.o \
-			    overlay_12.dtb.o \
-			    overlay_13.dtb.o \
-			    overlay_15.dtb.o \
-			    overlay_16.dtb.o \
-			    overlay_17.dtb.o \
-			    overlay_18.dtb.o \
-			    overlay_19.dtb.o \
-			    overlay_20.dtb.o \
-			    overlay_bad_add_dup_node.dtb.o \
-			    overlay_bad_add_dup_prop.dtb.o \
-			    overlay_bad_phandle.dtb.o \
-			    overlay_bad_symbol.dtb.o \
-			    overlay_base.dtb.o \
-			    overlay_gpio_01.dtb.o \
-			    overlay_gpio_02a.dtb.o \
-			    overlay_gpio_02b.dtb.o \
-			    overlay_gpio_03.dtb.o \
-			    overlay_gpio_04a.dtb.o \
-			    overlay_gpio_04b.dtb.o
+obj-$(CONFIG_OF_OVERLAY) += overlay.dtbo.o \
+			    overlay_0.dtbo.o \
+			    overlay_1.dtbo.o \
+			    overlay_2.dtbo.o \
+			    overlay_3.dtbo.o \
+			    overlay_4.dtbo.o \
+			    overlay_5.dtbo.o \
+			    overlay_6.dtbo.o \
+			    overlay_7.dtbo.o \
+			    overlay_8.dtbo.o \
+			    overlay_9.dtbo.o \
+			    overlay_10.dtbo.o \
+			    overlay_11.dtbo.o \
+			    overlay_12.dtbo.o \
+			    overlay_13.dtbo.o \
+			    overlay_15.dtbo.o \
+			    overlay_16.dtbo.o \
+			    overlay_17.dtbo.o \
+			    overlay_18.dtbo.o \
+			    overlay_19.dtbo.o \
+			    overlay_20.dtbo.o \
+			    overlay_bad_add_dup_node.dtbo.o \
+			    overlay_bad_add_dup_prop.dtbo.o \
+			    overlay_bad_phandle.dtbo.o \
+			    overlay_bad_symbol.dtbo.o \
+			    overlay_base.dtbo.o \
+			    overlay_gpio_01.dtbo.o \
+			    overlay_gpio_02a.dtbo.o \
+			    overlay_gpio_02b.dtbo.o \
+			    overlay_gpio_03.dtbo.o \
+			    overlay_gpio_04a.dtbo.o \
+			    overlay_gpio_04b.dtbo.o
 
 # enable creation of __symbols__ node
 DTC_FLAGS_overlay += -@
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_0.dts b/drivers/of/unittest-data/overlay_0.dts
--- a/drivers/of/unittest-data/overlay_0.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_0.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/ {
-	/* overlay_0 - enable using absolute target path */
-
-	fragment@0 {
-		target-path = "/testcase-data/overlay-node/test-bus/test-unittest0";
-		__overlay__ {
-			status = "okay";
-		};
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_0.dtso b/drivers/of/unittest-data/overlay_0.dtso
--- a/drivers/of/unittest-data/overlay_0.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_0.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/ {
+	/* overlay_0 - enable using absolute target path */
+
+	fragment@0 {
+		target-path = "/testcase-data/overlay-node/test-bus/test-unittest0";
+		__overlay__ {
+			status = "okay";
+		};
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_10.dts b/drivers/of/unittest-data/overlay_10.dts
--- a/drivers/of/unittest-data/overlay_10.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_10.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,27 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_10 */
-/* overlays 8, 9, 10, 11 application and removal in bad sequence */
-
-&unittest_test_bus {
-	/* suppress DTC warning */
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	test-unittest10 {
-		compatible = "unittest";
-		status = "okay";
-		reg = <10>;
-
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		test-unittest101 {
-			compatible = "unittest";
-			status = "okay";
-			reg = <1>;
-		};
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_10.dtso b/drivers/of/unittest-data/overlay_10.dtso
--- a/drivers/of/unittest-data/overlay_10.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_10.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_10 */
+/* overlays 8, 9, 10, 11 application and removal in bad sequence */
+
+&unittest_test_bus {
+	/* suppress DTC warning */
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	test-unittest10 {
+		compatible = "unittest";
+		status = "okay";
+		reg = <10>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		test-unittest101 {
+			compatible = "unittest";
+			status = "okay";
+			reg = <1>;
+		};
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_11.dts b/drivers/of/unittest-data/overlay_11.dts
--- a/drivers/of/unittest-data/overlay_11.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_11.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_11 */
-/* overlays 8, 9, 10, 11 application and removal in bad sequence */
-
-&unittest_test_bus {
-	/* suppress DTC warning */
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	test-unittest11 {
-		compatible = "unittest";
-		status = "okay";
-		reg = <11>;
-
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		test-unittest111 {
-			compatible = "unittest";
-			status = "okay";
-			reg = <1>;
-		};
-
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_11.dtso b/drivers/of/unittest-data/overlay_11.dtso
--- a/drivers/of/unittest-data/overlay_11.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_11.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_11 */
+/* overlays 8, 9, 10, 11 application and removal in bad sequence */
+
+&unittest_test_bus {
+	/* suppress DTC warning */
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	test-unittest11 {
+		compatible = "unittest";
+		status = "okay";
+		reg = <11>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		test-unittest111 {
+			compatible = "unittest";
+			status = "okay";
+			reg = <1>;
+		};
+
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_12.dts b/drivers/of/unittest-data/overlay_12.dts
--- a/drivers/of/unittest-data/overlay_12.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_12.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/ {
-	/* overlay_12 - enable using absolute target path (i2c) */
-
-	fragment@0 {
-		target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest12";
-		__overlay__ {
-			status = "okay";
-		};
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_12.dtso b/drivers/of/unittest-data/overlay_12.dtso
--- a/drivers/of/unittest-data/overlay_12.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_12.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/ {
+	/* overlay_12 - enable using absolute target path (i2c) */
+
+	fragment@0 {
+		target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest12";
+		__overlay__ {
+			status = "okay";
+		};
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_13.dts b/drivers/of/unittest-data/overlay_13.dts
--- a/drivers/of/unittest-data/overlay_13.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_13.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/ {
-	/* overlay_13 - disable using absolute target path (i2c) */
-
-	fragment@0 {
-		target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest13";
-		__overlay__ {
-			status = "disabled";
-		};
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_13.dtso b/drivers/of/unittest-data/overlay_13.dtso
--- a/drivers/of/unittest-data/overlay_13.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_13.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/ {
+	/* overlay_13 - disable using absolute target path (i2c) */
+
+	fragment@0 {
+		target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-unittest13";
+		__overlay__ {
+			status = "disabled";
+		};
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_15.dts b/drivers/of/unittest-data/overlay_15.dts
--- a/drivers/of/unittest-data/overlay_15.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_15.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_15 - mux overlay */
-
-&unittest_i2c_test_bus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-	test-unittest15 {
-		reg = <11>;
-		compatible = "unittest-i2c-mux";
-		status = "okay";
-
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		i2c@0 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			reg = <0>;
-
-			test-mux-dev@20 {
-				reg = <0x20>;
-				compatible = "unittest-i2c-dev";
-				status = "okay";
-			};
-		};
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_15.dtso b/drivers/of/unittest-data/overlay_15.dtso
--- a/drivers/of/unittest-data/overlay_15.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_15.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_15 - mux overlay */
+
+&unittest_i2c_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	test-unittest15 {
+		reg = <11>;
+		compatible = "unittest-i2c-mux";
+		status = "okay";
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+
+			test-mux-dev@20 {
+				reg = <0x20>;
+				compatible = "unittest-i2c-dev";
+				status = "okay";
+			};
+		};
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_16.dts b/drivers/of/unittest-data/overlay_16.dts
--- a/drivers/of/unittest-data/overlay_16.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_16.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_16 - notify test */
-
-&unittest_test_bus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	test-unittest16 {
-		compatible = "unittest";
-		reg = <16>;
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_16.dtso b/drivers/of/unittest-data/overlay_16.dtso
--- a/drivers/of/unittest-data/overlay_16.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_16.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_16 - notify test */
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	test-unittest16 {
+		compatible = "unittest";
+		reg = <16>;
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_17.dts b/drivers/of/unittest-data/overlay_17.dts
--- a/drivers/of/unittest-data/overlay_17.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_17.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_17 - notify test */
-
-&unittest_test_bus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	test-unittest17 {
-		compatible = "unittest";
-		reg = <17>;
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_17.dtso b/drivers/of/unittest-data/overlay_17.dtso
--- a/drivers/of/unittest-data/overlay_17.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_17.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_17 - notify test */
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	test-unittest17 {
+		compatible = "unittest";
+		reg = <17>;
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_18.dts b/drivers/of/unittest-data/overlay_18.dts
--- a/drivers/of/unittest-data/overlay_18.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_18.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_18 - notify test */
-
-&unittest_test_bus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	test-unittest18 {
-		compatible = "unittest";
-		reg = <18>;
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_18.dtso b/drivers/of/unittest-data/overlay_18.dtso
--- a/drivers/of/unittest-data/overlay_18.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_18.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_18 - notify test */
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	test-unittest18 {
+		compatible = "unittest";
+		reg = <18>;
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_19.dts b/drivers/of/unittest-data/overlay_19.dts
--- a/drivers/of/unittest-data/overlay_19.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_19.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_19 - notify test */
-
-&unittest_test_bus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	test-unittest19 {
-		compatible = "unittest";
-		reg = <19>;
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_19.dtso b/drivers/of/unittest-data/overlay_19.dtso
--- a/drivers/of/unittest-data/overlay_19.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_19.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_19 - notify test */
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	test-unittest19 {
+		compatible = "unittest";
+		reg = <19>;
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_1.dts b/drivers/of/unittest-data/overlay_1.dts
--- a/drivers/of/unittest-data/overlay_1.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_1.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/ {
-	/* overlay_1 - disable using absolute target path */
-
-	fragment@0 {
-		target-path = "/testcase-data/overlay-node/test-bus/test-unittest1";
-		__overlay__ {
-			status = "disabled";
-		};
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_1.dtso b/drivers/of/unittest-data/overlay_1.dtso
--- a/drivers/of/unittest-data/overlay_1.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_1.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/ {
+	/* overlay_1 - disable using absolute target path */
+
+	fragment@0 {
+		target-path = "/testcase-data/overlay-node/test-bus/test-unittest1";
+		__overlay__ {
+			status = "disabled";
+		};
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_20.dts b/drivers/of/unittest-data/overlay_20.dts
--- a/drivers/of/unittest-data/overlay_20.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_20.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_20 - notify test */
-
-&unittest_test_bus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	test-unittest20 {
-		compatible = "unittest";
-		reg = <20>;
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_20.dtso b/drivers/of/unittest-data/overlay_20.dtso
--- a/drivers/of/unittest-data/overlay_20.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_20.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_20 - notify test */
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	test-unittest20 {
+		compatible = "unittest";
+		reg = <20>;
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_2.dts b/drivers/of/unittest-data/overlay_2.dts
--- a/drivers/of/unittest-data/overlay_2.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_2.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_2 -  enable using label */
-
-&unittest2 {
-	status = "okay";
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_2.dtso b/drivers/of/unittest-data/overlay_2.dtso
--- a/drivers/of/unittest-data/overlay_2.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_2.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_2 -  enable using label */
+
+&unittest2 {
+	status = "okay";
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_3.dts b/drivers/of/unittest-data/overlay_3.dts
--- a/drivers/of/unittest-data/overlay_3.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_3.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_3 - disable using label */
-
-&unittest3 {
-	status = "disabled";
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_3.dtso b/drivers/of/unittest-data/overlay_3.dtso
--- a/drivers/of/unittest-data/overlay_3.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_3.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_3 - disable using label */
+
+&unittest3 {
+	status = "disabled";
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_4.dts b/drivers/of/unittest-data/overlay_4.dts
--- a/drivers/of/unittest-data/overlay_4.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_4.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_4 - test insertion of a full node */
-
-&unittest_test_bus {
-
-	/* suppress DTC warning */
-	#address-cells = <1>;
-	#size-cells = <0>;
-
-	test-unittest4 {
-		compatible = "unittest";
-		status = "okay";
-		reg = <4>;
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_4.dtso b/drivers/of/unittest-data/overlay_4.dtso
--- a/drivers/of/unittest-data/overlay_4.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_4.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_4 - test insertion of a full node */
+
+&unittest_test_bus {
+
+	/* suppress DTC warning */
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	test-unittest4 {
+		compatible = "unittest";
+		status = "okay";
+		reg = <4>;
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_5.dts b/drivers/of/unittest-data/overlay_5.dts
--- a/drivers/of/unittest-data/overlay_5.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_5.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_5 - test overlay apply revert */
-
-&unittest5 {
-	status = "okay";
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_5.dtso b/drivers/of/unittest-data/overlay_5.dtso
--- a/drivers/of/unittest-data/overlay_5.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_5.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_5 - test overlay apply revert */
+
+&unittest5 {
+	status = "okay";
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_6.dts b/drivers/of/unittest-data/overlay_6.dts
--- a/drivers/of/unittest-data/overlay_6.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_6.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_6 */
-/* overlays 6, 7 application and removal in sequence */
-
-&unittest6 {
-	status = "okay";
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_6.dtso b/drivers/of/unittest-data/overlay_6.dtso
--- a/drivers/of/unittest-data/overlay_6.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_6.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_6 */
+/* overlays 6, 7 application and removal in sequence */
+
+&unittest6 {
+	status = "okay";
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_7.dts b/drivers/of/unittest-data/overlay_7.dts
--- a/drivers/of/unittest-data/overlay_7.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_7.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_7 */
-/* overlays 6, 7 application and removal in sequence */
-
-&unittest7 {
-	status = "okay";
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_7.dtso b/drivers/of/unittest-data/overlay_7.dtso
--- a/drivers/of/unittest-data/overlay_7.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_7.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_7 */
+/* overlays 6, 7 application and removal in sequence */
+
+&unittest7 {
+	status = "okay";
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_8.dts b/drivers/of/unittest-data/overlay_8.dts
--- a/drivers/of/unittest-data/overlay_8.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_8.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_8 */
-/* overlays 8, 9, 10, 11 application and removal in bad sequence */
-
-&unittest8 {
-	status = "okay";
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_8.dtso b/drivers/of/unittest-data/overlay_8.dtso
--- a/drivers/of/unittest-data/overlay_8.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_8.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_8 */
+/* overlays 8, 9, 10, 11 application and removal in bad sequence */
+
+&unittest8 {
+	status = "okay";
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_9.dts b/drivers/of/unittest-data/overlay_9.dts
--- a/drivers/of/unittest-data/overlay_9.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_9.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/* overlay_9 */
-/* overlays 8, 9, 10, 11 application and removal in bad sequence */
-
-&unittest8 {
-	property-foo = "bar";
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_9.dtso b/drivers/of/unittest-data/overlay_9.dtso
--- a/drivers/of/unittest-data/overlay_9.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_9.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/* overlay_9 */
+/* overlays 8, 9, 10, 11 application and removal in bad sequence */
+
+&unittest8 {
+	property-foo = "bar";
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_bad_add_dup_node.dts b/drivers/of/unittest-data/overlay_bad_add_dup_node.dts
--- a/drivers/of/unittest-data/overlay_bad_add_dup_node.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_bad_add_dup_node.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/*
- * &electric_1/motor-1 and &spin_ctrl_1 are the same node:
- *   /testcase-data-2/substation@100/motor-1
- *
- * Thus the new node "controller" in each fragment will
- * result in an attempt to add the same node twice.
- * This will result in an error and the overlay apply
- * will fail.
- */
-
-&electric_1 {
-
-	motor-1 {
-		controller {
-			power_bus = < 0x1 0x2 >;
-		};
-	};
-};
-
-&spin_ctrl_1 {
-		controller {
-			power_bus_emergency = < 0x101 0x102 >;
-		};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_bad_add_dup_node.dtso b/drivers/of/unittest-data/overlay_bad_add_dup_node.dtso
--- a/drivers/of/unittest-data/overlay_bad_add_dup_node.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_bad_add_dup_node.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/*
+ * &electric_1/motor-1 and &spin_ctrl_1 are the same node:
+ *   /testcase-data-2/substation@100/motor-1
+ *
+ * Thus the new node "controller" in each fragment will
+ * result in an attempt to add the same node twice.
+ * This will result in an error and the overlay apply
+ * will fail.
+ */
+
+&electric_1 {
+
+	motor-1 {
+		controller {
+			power_bus = < 0x1 0x2 >;
+		};
+	};
+};
+
+&spin_ctrl_1 {
+		controller {
+			power_bus_emergency = < 0x101 0x102 >;
+		};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_bad_add_dup_prop.dts b/drivers/of/unittest-data/overlay_bad_add_dup_prop.dts
--- a/drivers/of/unittest-data/overlay_bad_add_dup_prop.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_bad_add_dup_prop.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-/*
- * &electric_1/motor-1/electric and &spin_ctrl_1/electric are the same node:
- *   /testcase-data-2/substation@100/motor-1/electric
- *
- * Thus the property "rpm_avail" in each fragment will
- * result in an attempt to update the same property twice.
- * This will result in an error and the overlay apply
- * will fail.
- *
- * The previous version of this test did not include the extra
- * level of node 'electric'.  That resulted in the 'rpm_avail'
- * property being located in the pre-existing node 'motor-1'.
- * Modifying a property results in a WARNING that a memory leak
- * will occur if the overlay is removed.  Since the overlay apply
- * fails, the memory leak does actually occur, and kmemleak will
- * further report the memory leak if CONFIG_DEBUG_KMEMLEAK is
- * enabled.  Adding the overlay node 'electric' avoids the
- * memory leak and thus people who use kmemleak will not
- * have to debug this non-problem again.
- */
-
-&electric_1 {
-
-	motor-1 {
-		electric {
-			rpm_avail = < 100 >;
-		};
-	};
-};
-
-&spin_ctrl_1 {
-		electric {
-			rpm_avail = < 100 200 >;
-		};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_bad_add_dup_prop.dtso b/drivers/of/unittest-data/overlay_bad_add_dup_prop.dtso
--- a/drivers/of/unittest-data/overlay_bad_add_dup_prop.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_bad_add_dup_prop.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+/*
+ * &electric_1/motor-1/electric and &spin_ctrl_1/electric are the same node:
+ *   /testcase-data-2/substation@100/motor-1/electric
+ *
+ * Thus the property "rpm_avail" in each fragment will
+ * result in an attempt to update the same property twice.
+ * This will result in an error and the overlay apply
+ * will fail.
+ *
+ * The previous version of this test did not include the extra
+ * level of node 'electric'.  That resulted in the 'rpm_avail'
+ * property being located in the pre-existing node 'motor-1'.
+ * Modifying a property results in a WARNING that a memory leak
+ * will occur if the overlay is removed.  Since the overlay apply
+ * fails, the memory leak does actually occur, and kmemleak will
+ * further report the memory leak if CONFIG_DEBUG_KMEMLEAK is
+ * enabled.  Adding the overlay node 'electric' avoids the
+ * memory leak and thus people who use kmemleak will not
+ * have to debug this non-problem again.
+ */
+
+&electric_1 {
+
+	motor-1 {
+		electric {
+			rpm_avail = < 100 >;
+		};
+	};
+};
+
+&spin_ctrl_1 {
+		electric {
+			rpm_avail = < 100 200 >;
+		};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_bad_phandle.dts b/drivers/of/unittest-data/overlay_bad_phandle.dts
--- a/drivers/of/unittest-data/overlay_bad_phandle.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_bad_phandle.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,14 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-&electric_1 {
-
-	// This label should cause an error when the overlay
-	// is applied.  There is already a phandle value
-	// in the base tree for motor-1.
-	spin_ctrl_1_conflict: motor-1 {
-		accelerate = < 3 >;
-		decelerate = < 5 >;
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_bad_phandle.dtso b/drivers/of/unittest-data/overlay_bad_phandle.dtso
--- a/drivers/of/unittest-data/overlay_bad_phandle.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_bad_phandle.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&electric_1 {
+
+	// This label should cause an error when the overlay
+	// is applied.  There is already a phandle value
+	// in the base tree for motor-1.
+	spin_ctrl_1_conflict: motor-1 {
+		accelerate = < 3 >;
+		decelerate = < 5 >;
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_bad_symbol.dts b/drivers/of/unittest-data/overlay_bad_symbol.dts
--- a/drivers/of/unittest-data/overlay_bad_symbol.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_bad_symbol.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-&electric_1 {
-
-	// This label should cause an error when the overlay
-	// is applied.  There is already a symbol hvac_1
-	// in the base tree
-	hvac_1: hvac-medium-2 {
-		compatible = "ot,hvac-medium";
-		heat-range = < 50 75 >;
-		cool-range = < 60 80 >;
-	};
-
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_bad_symbol.dtso b/drivers/of/unittest-data/overlay_bad_symbol.dtso
--- a/drivers/of/unittest-data/overlay_bad_symbol.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_bad_symbol.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&electric_1 {
+
+	// This label should cause an error when the overlay
+	// is applied.  There is already a symbol hvac_1
+	// in the base tree
+	hvac_1: hvac-medium-2 {
+		compatible = "ot,hvac-medium";
+		heat-range = < 50 75 >;
+		cool-range = < 60 80 >;
+	};
+
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_base.dts b/drivers/of/unittest-data/overlay_base.dts
--- a/drivers/of/unittest-data/overlay_base.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_base.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-#include "overlay_common.dtsi"
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_base.dtso b/drivers/of/unittest-data/overlay_base.dtso
--- a/drivers/of/unittest-data/overlay_base.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_base.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "overlay_common.dtsi"
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay.dts b/drivers/of/unittest-data/overlay.dts
--- a/drivers/of/unittest-data/overlay.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,64 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-&electric_1 {
-
-	status = "okay";
-
-	hvac_2: hvac-large-1 {
-		compatible = "ot,hvac-large";
-		heat-range = < 40 75 >;
-		cool-range = < 65 80 >;
-	};
-};
-
-&rides_1 {
-
-	#address-cells = <1>;
-	#size-cells = <1>;
-	status = "okay";
-
-	ride@100 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		track@30 {
-			incline-up = < 48 32 16 >;
-		};
-
-		track@40 {
-			incline-up = < 47 31 15 >;
-		};
-	};
-
-	ride_200: ride@200 {
-		#address-cells = <1>;
-		#size-cells = <1>;
-		compatible = "ot,ferris-wheel";
-		reg = < 0x00000200 0x100 >;
-		hvac-provider = < &hvac_2 >;
-		hvac-thermostat = < 27 32 > ;
-		hvac-zones = < 12 5 >;
-		hvac-zone-names = "operator", "snack-bar";
-		spin-controller = < &spin_ctrl_1 3 >;
-		spin-rph = < 30 >;
-		gondolas = < 16 >;
-		gondola-capacity = < 6 >;
-
-		ride_200_left: track@10 {
-			reg = < 0x00000010 0x10 >;
-		};
-
-		ride_200_right: track@20 {
-			reg = < 0x00000020 0x10 >;
-		};
-	};
-};
-
-&lights_2 {
-
-	status = "okay";
-	color = "purple", "white", "red", "green";
-	rate = < 3 256 >;
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay.dtso b/drivers/of/unittest-data/overlay.dtso
--- a/drivers/of/unittest-data/overlay.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&electric_1 {
+
+	status = "okay";
+
+	hvac_2: hvac-large-1 {
+		compatible = "ot,hvac-large";
+		heat-range = < 40 75 >;
+		cool-range = < 65 80 >;
+	};
+};
+
+&rides_1 {
+
+	#address-cells = <1>;
+	#size-cells = <1>;
+	status = "okay";
+
+	ride@100 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		track@30 {
+			incline-up = < 48 32 16 >;
+		};
+
+		track@40 {
+			incline-up = < 47 31 15 >;
+		};
+	};
+
+	ride_200: ride@200 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "ot,ferris-wheel";
+		reg = < 0x00000200 0x100 >;
+		hvac-provider = < &hvac_2 >;
+		hvac-thermostat = < 27 32 > ;
+		hvac-zones = < 12 5 >;
+		hvac-zone-names = "operator", "snack-bar";
+		spin-controller = < &spin_ctrl_1 3 >;
+		spin-rph = < 30 >;
+		gondolas = < 16 >;
+		gondola-capacity = < 6 >;
+
+		ride_200_left: track@10 {
+			reg = < 0x00000010 0x10 >;
+		};
+
+		ride_200_right: track@20 {
+			reg = < 0x00000020 0x10 >;
+		};
+	};
+};
+
+&lights_2 {
+
+	status = "okay";
+	color = "purple", "white", "red", "green";
+	rate = < 3 256 >;
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_gpio_01.dts b/drivers/of/unittest-data/overlay_gpio_01.dts
--- a/drivers/of/unittest-data/overlay_gpio_01.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_gpio_01.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-&unittest_test_bus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-	gpio@0 {
-		compatible = "unittest-gpio";
-		reg = <0>;
-		gpio-controller;
-		#gpio-cells = <2>;
-		ngpios = <2>;
-		gpio-line-names = "line-A", "line-B";
-
-		line-b {
-			gpio-hog;
-			gpios = <2 0>;
-			input;
-			line-name = "line-B-input";
-		};
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_gpio_01.dtso b/drivers/of/unittest-data/overlay_gpio_01.dtso
--- a/drivers/of/unittest-data/overlay_gpio_01.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_gpio_01.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpio@0 {
+		compatible = "unittest-gpio";
+		reg = <0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <2>;
+		gpio-line-names = "line-A", "line-B";
+
+		line-b {
+			gpio-hog;
+			gpios = <2 0>;
+			input;
+			line-name = "line-B-input";
+		};
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_gpio_02a.dts b/drivers/of/unittest-data/overlay_gpio_02a.dts
--- a/drivers/of/unittest-data/overlay_gpio_02a.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_gpio_02a.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-&unittest_test_bus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-	gpio@2 {
-		compatible = "unittest-gpio";
-		reg = <2>;
-		gpio-controller;
-		#gpio-cells = <2>;
-		ngpios = <2>;
-		gpio-line-names = "line-A", "line-B";
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_gpio_02a.dtso b/drivers/of/unittest-data/overlay_gpio_02a.dtso
--- a/drivers/of/unittest-data/overlay_gpio_02a.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_gpio_02a.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpio@2 {
+		compatible = "unittest-gpio";
+		reg = <2>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <2>;
+		gpio-line-names = "line-A", "line-B";
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_gpio_02b.dts b/drivers/of/unittest-data/overlay_gpio_02b.dts
--- a/drivers/of/unittest-data/overlay_gpio_02b.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_gpio_02b.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-&unittest_test_bus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-	gpio@2 {
-		line-a {
-			gpio-hog;
-			gpios = <1 0>;
-			input;
-			line-name = "line-A-input";
-		};
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_gpio_02b.dtso b/drivers/of/unittest-data/overlay_gpio_02b.dtso
--- a/drivers/of/unittest-data/overlay_gpio_02b.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_gpio_02b.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpio@2 {
+		line-a {
+			gpio-hog;
+			gpios = <1 0>;
+			input;
+			line-name = "line-A-input";
+		};
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_gpio_03.dts b/drivers/of/unittest-data/overlay_gpio_03.dts
--- a/drivers/of/unittest-data/overlay_gpio_03.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_gpio_03.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-&unittest_test_bus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-	gpio@3 {
-		compatible = "unittest-gpio";
-		reg = <3>;
-		gpio-controller;
-		#gpio-cells = <2>;
-		ngpios = <2>;
-		gpio-line-names = "line-A", "line-B", "line-C", "line-D";
-
-		line-d {
-			gpio-hog;
-			gpios = <4 0>;
-			input;
-			line-name = "line-D-input";
-		};
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_gpio_03.dtso b/drivers/of/unittest-data/overlay_gpio_03.dtso
--- a/drivers/of/unittest-data/overlay_gpio_03.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_gpio_03.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpio@3 {
+		compatible = "unittest-gpio";
+		reg = <3>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <2>;
+		gpio-line-names = "line-A", "line-B", "line-C", "line-D";
+
+		line-d {
+			gpio-hog;
+			gpios = <4 0>;
+			input;
+			line-name = "line-D-input";
+		};
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_gpio_04a.dts b/drivers/of/unittest-data/overlay_gpio_04a.dts
--- a/drivers/of/unittest-data/overlay_gpio_04a.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_gpio_04a.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-&unittest_test_bus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-	gpio@4 {
-		compatible = "unittest-gpio";
-		reg = <4>;
-		gpio-controller;
-		#gpio-cells = <2>;
-		ngpios = <2>;
-		gpio-line-names = "line-A", "line-B", "line-C", "line-D";
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_gpio_04a.dtso b/drivers/of/unittest-data/overlay_gpio_04a.dtso
--- a/drivers/of/unittest-data/overlay_gpio_04a.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_gpio_04a.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpio@4 {
+		compatible = "unittest-gpio";
+		reg = <4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		ngpios = <2>;
+		gpio-line-names = "line-A", "line-B", "line-C", "line-D";
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_gpio_04b.dts b/drivers/of/unittest-data/overlay_gpio_04b.dts
--- a/drivers/of/unittest-data/overlay_gpio_04b.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_gpio_04b.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-&unittest_test_bus {
-	#address-cells = <1>;
-	#size-cells = <0>;
-	gpio@4 {
-		line-c {
-			gpio-hog;
-			gpios = <3 0>;
-			input;
-			line-name = "line-C-input";
-		};
-	};
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/overlay_gpio_04b.dtso b/drivers/of/unittest-data/overlay_gpio_04b.dtso
--- a/drivers/of/unittest-data/overlay_gpio_04b.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/overlay_gpio_04b.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+&unittest_test_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	gpio@4 {
+		line-c {
+			gpio-hog;
+			gpios = <3 0>;
+			input;
+			line-name = "line-C-input";
+		};
+	};
+};
diff -Naur --no-dereference a/drivers/of/unittest-data/testcases.dts b/drivers/of/unittest-data/testcases.dts
--- a/drivers/of/unittest-data/testcases.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/of/unittest-data/testcases.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/dts-v1/;
-/plugin/;
-
-#include "testcases_common.dtsi"
-
-/ {
-	/*
-	 * testcase data that intentionally results in an error is located here
-	 * instead of in testcases_common.dtsi so that the static overlay apply
-	 * tests will not include the error.
-	 */
-	testcase-data {
-		testcase-device2 {
-			compatible = "testcase-device";
-			interrupt-parent = <&test_intc2>;
-			interrupts = <1>; /* invalid specifier - too short */
-		};
-	};
-
-};
diff -Naur --no-dereference a/drivers/of/unittest-data/testcases.dtso b/drivers/of/unittest-data/testcases.dtso
--- a/drivers/of/unittest-data/testcases.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/of/unittest-data/testcases.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+/plugin/;
+
+#include "testcases_common.dtsi"
+
+/ {
+	/*
+	 * testcase data that intentionally results in an error is located here
+	 * instead of in testcases_common.dtsi so that the static overlay apply
+	 * tests will not include the error.
+	 */
+	testcase-data {
+		testcase-device2 {
+			compatible = "testcase-device";
+			interrupt-parent = <&test_intc2>;
+			interrupts = <1>; /* invalid specifier - too short */
+		};
+	};
+
+};
diff -Naur --no-dereference a/drivers/pci/controller/cadence/Kconfig b/drivers/pci/controller/cadence/Kconfig
--- a/drivers/pci/controller/cadence/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pci/controller/cadence/Kconfig	2024-01-28 14:01:31.252353813 -0500
@@ -4,16 +4,16 @@
 	depends on PCI
 
 config PCIE_CADENCE
-	bool
+	tristate
 
 config PCIE_CADENCE_HOST
-	bool
+	tristate
 	depends on OF
 	select IRQ_DOMAIN
 	select PCIE_CADENCE
 
 config PCIE_CADENCE_EP
-	bool
+	tristate
 	depends on OF
 	depends on PCI_ENDPOINT
 	select PCIE_CADENCE
@@ -43,10 +43,10 @@
 	  different vendors SoCs.
 
 config PCI_J721E
-	bool
+	tristate
 
 config PCI_J721E_HOST
-	bool "TI J721E PCIe platform host controller"
+	tristate "TI J721E PCIe platform host controller"
 	depends on OF
 	select PCIE_CADENCE_HOST
 	select PCI_J721E
@@ -56,7 +56,7 @@
 	  core.
 
 config PCI_J721E_EP
-	bool "TI J721E PCIe platform endpoint controller"
+	tristate "TI J721E PCIe platform endpoint controller"
 	depends on OF
 	depends on PCI_ENDPOINT
 	select PCIE_CADENCE_EP
diff -Naur --no-dereference a/drivers/pci/controller/cadence/Makefile b/drivers/pci/controller/cadence/Makefile
--- a/drivers/pci/controller/cadence/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pci/controller/cadence/Makefile	2024-01-28 14:01:31.252353813 -0500
@@ -4,3 +4,5 @@
 obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o
 obj-$(CONFIG_PCIE_CADENCE_PLAT) += pcie-cadence-plat.o
 obj-$(CONFIG_PCI_J721E) += pci-j721e.o
+obj-$(CONFIG_PCI_J721E_HOST) += pci-j721e-host.o
+obj-$(CONFIG_PCI_J721E_EP) += pci-j721e-ep.o
diff -Naur --no-dereference a/drivers/pci/controller/cadence/pcie-cadence.c b/drivers/pci/controller/cadence/pcie-cadence.c
--- a/drivers/pci/controller/cadence/pcie-cadence.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pci/controller/cadence/pcie-cadence.c	2024-01-28 14:01:31.252353813 -0500
@@ -4,6 +4,7 @@
 // Author: Cyrille Pitchen <cyrille.pitchen@free-electrons.com>
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 
 #include "pcie-cadence.h"
 
@@ -22,6 +23,7 @@
 
 	cdns_pcie_writel(pcie, CDNS_PCIE_LTSSM_CONTROL_CAP, ltssm_control_cap);
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_detect_quiet_min_delay_set);
 
 void cdns_pcie_set_outbound_region(struct cdns_pcie *pcie, u8 busnr, u8 fn,
 				   u32 r, bool is_io,
@@ -99,6 +101,7 @@
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), addr0);
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), addr1);
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_set_outbound_region);
 
 void cdns_pcie_set_outbound_region_for_normal_msg(struct cdns_pcie *pcie,
 						  u8 busnr, u8 fn,
@@ -133,6 +136,7 @@
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), addr0);
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), addr1);
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_set_outbound_region_for_normal_msg);
 
 void cdns_pcie_reset_outbound_region(struct cdns_pcie *pcie, u32 r)
 {
@@ -145,6 +149,7 @@
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR0(r), 0);
 	cdns_pcie_writel(pcie, CDNS_PCIE_AT_OB_REGION_CPU_ADDR1(r), 0);
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_reset_outbound_region);
 
 void cdns_pcie_disable_phy(struct cdns_pcie *pcie)
 {
@@ -155,6 +160,7 @@
 		phy_exit(pcie->phy[i]);
 	}
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_disable_phy);
 
 int cdns_pcie_enable_phy(struct cdns_pcie *pcie)
 {
@@ -242,6 +248,19 @@
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_init_phy);
+
+void cdns_pcie_deinit_phy(struct cdns_pcie *pcie)
+{
+	int i = pcie->phy_count;
+
+	cdns_pcie_disable_phy(pcie);
+	while (i--) {
+		device_link_del(pcie->link[i]);
+		devm_phy_put(pcie->dev, pcie->phy[i]);
+	}
+}
+EXPORT_SYMBOL_GPL(cdns_pcie_deinit_phy);
 
 static int cdns_pcie_suspend_noirq(struct device *dev)
 {
@@ -270,3 +289,5 @@
 	NOIRQ_SYSTEM_SLEEP_PM_OPS(cdns_pcie_suspend_noirq,
 				  cdns_pcie_resume_noirq)
 };
+
+MODULE_LICENSE("GPL v2");
diff -Naur --no-dereference a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c
--- a/drivers/pci/controller/cadence/pcie-cadence-ep.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c	2024-01-28 14:01:31.252353813 -0500
@@ -5,6 +5,7 @@
 
 #include <linux/delay.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/of.h>
 #include <linux/pci-epc.h>
 #include <linux/platform_device.h>
@@ -565,7 +566,8 @@
 	struct cdns_pcie *pcie = &ep->pcie;
 	struct device *dev = pcie->dev;
 	int max_epfs = sizeof(epc->function_num_map) * 8;
-	int ret, value, epf;
+	int ret, epf, last_fn;
+	u32 reg, value;
 
 	/*
 	 * BIT(0) is hardwired to 1, hence function 0 is always enabled
@@ -573,6 +575,17 @@
 	 */
 	cdns_pcie_writel(pcie, CDNS_PCIE_LM_EP_FUNC_CFG, epc->function_num_map);
 
+	/*
+	 * Next function field in ARI_CAP_AND_CTR register for last function
+	 * should be 0.
+	 * Clearing Next Function Number field for the last function used.
+	 */
+	last_fn = find_last_bit(&epc->function_num_map, BITS_PER_LONG);
+	reg     = CDNS_PCIE_CORE_PF_I_ARI_CAP_AND_CTRL(last_fn);
+	value  = cdns_pcie_readl(pcie, reg);
+	value &= ~CDNS_PCIE_ARI_CAP_NFN_MASK;
+	cdns_pcie_writel(pcie, reg, value);
+
 	if (ep->quirk_disable_flr) {
 		for (epf = 0; epf < max_epfs; epf++) {
 			if (!(epc->function_num_map & BIT(epf)))
@@ -741,3 +754,6 @@
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_ep_setup);
+
+MODULE_LICENSE("GPL v2");
diff -Naur --no-dereference a/drivers/pci/controller/cadence/pcie-cadence.h b/drivers/pci/controller/cadence/pcie-cadence.h
--- a/drivers/pci/controller/cadence/pcie-cadence.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pci/controller/cadence/pcie-cadence.h	2024-01-28 14:01:31.252353813 -0500
@@ -117,8 +117,8 @@
 					(((aperture) - 2) << ((bar) * 8))
 
 /* PTM Control Register */
-#define CDNS_PCIE_LM_PTM_CTRL 	(CDNS_PCIE_LM_BASE + 0x0da8)
-#define CDNS_PCIE_LM_TPM_CTRL_PTMRSEN 	BIT(17)
+#define CDNS_PCIE_LM_PTM_CTRL	(CDNS_PCIE_LM_BASE + 0x0da8)
+#define CDNS_PCIE_LM_TPM_CTRL_PTMRSEN	BIT(17)
 
 /*
  * Endpoint Function Registers (PCI configuration space for endpoint functions)
@@ -131,6 +131,12 @@
 #define CDNS_PCIE_EP_FUNC_SRIOV_CAP_OFFSET	0x200
 
 /*
+ * Endpoint PF Registers
+ */
+#define CDNS_PCIE_CORE_PF_I_ARI_CAP_AND_CTRL(fn)	(0x144 + (fn) * 0x1000)
+#define CDNS_PCIE_ARI_CAP_NFN_MASK	GENMASK(15, 8)
+
+/*
  * Root Port Registers (PCI configuration space for the root port function)
  */
 #define CDNS_PCIE_RP_BASE	0x00200000
@@ -514,8 +520,9 @@
 	return true;
 }
 
-#ifdef CONFIG_PCIE_CADENCE_HOST
+#if IS_ENABLED(CONFIG_PCIE_CADENCE_HOST)
 int cdns_pcie_host_setup(struct cdns_pcie_rc *rc);
+int cdns_pcie_host_remove_setup(struct cdns_pcie_rc *rc);
 void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
 			       int where);
 #else
@@ -524,6 +531,11 @@
 	return 0;
 }
 
+static inline int cdns_pcie_host_remove_setup(struct cdns_pcie_rc *rc)
+{
+	return 0;
+}
+
 static inline void __iomem *cdns_pci_map_bus(struct pci_bus *bus, unsigned int devfn,
 					     int where)
 {
@@ -531,7 +543,7 @@
 }
 #endif
 
-#ifdef CONFIG_PCIE_CADENCE_EP
+#if IS_ENABLED(CONFIG_PCIE_CADENCE_EP)
 int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep);
 #else
 static inline int cdns_pcie_ep_setup(struct cdns_pcie_ep *ep)
@@ -554,6 +566,7 @@
 void cdns_pcie_disable_phy(struct cdns_pcie *pcie);
 int cdns_pcie_enable_phy(struct cdns_pcie *pcie);
 int cdns_pcie_init_phy(struct device *dev, struct cdns_pcie *pcie);
+void cdns_pcie_deinit_phy(struct cdns_pcie *pcie);
 extern const struct dev_pm_ops cdns_pcie_pm_ops;
 
 #endif /* _PCIE_CADENCE_H */
diff -Naur --no-dereference a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c
--- a/drivers/pci/controller/cadence/pcie-cadence-host.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pci/controller/cadence/pcie-cadence-host.c	2024-01-28 14:01:31.252353813 -0500
@@ -5,6 +5,7 @@
 
 #include <linux/delay.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/list_sort.h>
 #include <linux/of_address.h>
 #include <linux/of_pci.h>
@@ -72,6 +73,7 @@
 
 	return rc->cfg_base + (where & 0xfff);
 }
+EXPORT_SYMBOL_GPL(cdns_pci_map_bus);
 
 static struct pci_ops cdns_pcie_host_ops = {
 	.map_bus	= cdns_pci_map_bus,
@@ -158,6 +160,15 @@
 	cdns_pcie_writel(pcie, CDNS_PCIE_LM_PTM_CTRL, val | CDNS_PCIE_LM_TPM_CTRL_PTMRSEN);
 }
 
+static void cdns_pcie_host_disable_ptm_response(struct cdns_pcie *pcie)
+{
+	u32 val;
+
+	val = cdns_pcie_readl(pcie, CDNS_PCIE_LM_PTM_CTRL);
+	val &= ~CDNS_PCIE_LM_TPM_CTRL_PTMRSEN;
+	cdns_pcie_writel(pcie, CDNS_PCIE_LM_PTM_CTRL, val);
+}
+
 static int cdns_pcie_host_start_link(struct cdns_pcie_rc *rc)
 {
 	struct cdns_pcie *pcie = &rc->pcie;
@@ -385,10 +396,10 @@
 {
 	struct resource_entry *entry1, *entry2;
 
-        entry1 = container_of(a, struct resource_entry, node);
-        entry2 = container_of(b, struct resource_entry, node);
+	entry1 = container_of(a, struct resource_entry, node);
+	entry2 = container_of(b, struct resource_entry, node);
 
-        return resource_size(entry2->res) - resource_size(entry1->res);
+	return resource_size(entry2->res) - resource_size(entry1->res);
 }
 
 static int cdns_pcie_host_map_dma_ranges(struct cdns_pcie_rc *rc)
@@ -569,3 +580,19 @@
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(cdns_pcie_host_setup);
+
+int cdns_pcie_host_remove_setup(struct cdns_pcie_rc *rc)
+{
+	struct cdns_pcie *pcie = &rc->pcie;
+	struct pci_host_bridge *bridge = pci_host_bridge_from_priv(rc);
+
+	pci_stop_root_bus(bridge->bus);
+	pci_remove_root_bus(bridge->bus);
+	cdns_pcie_host_disable_ptm_response(pcie);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cdns_pcie_host_remove_setup);
+
+MODULE_LICENSE("GPL v2");
diff -Naur --no-dereference a/drivers/pci/controller/cadence/pci-j721e.c b/drivers/pci/controller/cadence/pci-j721e.c
--- a/drivers/pci/controller/cadence/pci-j721e.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pci/controller/cadence/pci-j721e.c	2024-01-28 14:01:31.252353813 -0500
@@ -2,99 +2,18 @@
 /*
  * pci-j721e - PCIe controller driver for TI's J721E SoCs
  *
- * Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com
+ * Copyright (C) 2020-2023 Texas Instruments Incorporated - http://www.ti.com
  * Author: Kishon Vijay Abraham I <kishon@ti.com>
  */
 
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio/consumer.h>
-#include <linux/io.h>
-#include <linux/irqchip/chained_irq.h>
-#include <linux/irqdomain.h>
 #include <linux/mfd/syscon.h>
-#include <linux/of.h>
+#include <linux/module.h>
 #include <linux/of_device.h>
-#include <linux/of_irq.h>
-#include <linux/pci.h>
-#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 
 #include "../../pci.h"
 #include "pcie-cadence.h"
-
-#define ENABLE_REG_SYS_2	0x108
-#define STATUS_REG_SYS_2	0x508
-#define STATUS_CLR_REG_SYS_2	0x708
-#define LINK_DOWN		BIT(1)
-#define J7200_LINK_DOWN		BIT(10)
-
-#define J721E_PCIE_USER_CMD_STATUS	0x4
-#define LINK_TRAINING_ENABLE		BIT(0)
-
-#define J721E_PCIE_USER_LINKSTATUS	0x14
-#define LINK_STATUS			GENMASK(1, 0)
-
-enum link_status {
-	NO_RECEIVERS_DETECTED,
-	LINK_TRAINING_IN_PROGRESS,
-	LINK_UP_DL_IN_PROGRESS,
-	LINK_UP_DL_COMPLETED,
-};
-
-#define J721E_MODE_RC			BIT(7)
-#define LANE_COUNT_MASK			BIT(8)
-#define LANE_COUNT(n)			((n) << 8)
-
-#define GENERATION_SEL_MASK		GENMASK(1, 0)
-
-#define MAX_LANES			2
-
-struct j721e_pcie {
-	struct cdns_pcie	*cdns_pcie;
-	struct clk		*refclk;
-	u32			mode;
-	u32			num_lanes;
-	void __iomem		*user_cfg_base;
-	void __iomem		*intd_cfg_base;
-	u32			linkdown_irq_regfield;
-};
-
-enum j721e_pcie_mode {
-	PCI_MODE_RC,
-	PCI_MODE_EP,
-};
-
-struct j721e_pcie_data {
-	enum j721e_pcie_mode	mode;
-	unsigned int		quirk_retrain_flag:1;
-	unsigned int		quirk_detect_quiet_flag:1;
-	unsigned int		quirk_disable_flr:1;
-	u32			linkdown_irq_regfield;
-	unsigned int		byte_access_allowed:1;
-};
-
-static inline u32 j721e_pcie_user_readl(struct j721e_pcie *pcie, u32 offset)
-{
-	return readl(pcie->user_cfg_base + offset);
-}
-
-static inline void j721e_pcie_user_writel(struct j721e_pcie *pcie, u32 offset,
-					  u32 value)
-{
-	writel(value, pcie->user_cfg_base + offset);
-}
-
-static inline u32 j721e_pcie_intd_readl(struct j721e_pcie *pcie, u32 offset)
-{
-	return readl(pcie->intd_cfg_base + offset);
-}
-
-static inline void j721e_pcie_intd_writel(struct j721e_pcie *pcie, u32 offset,
-					  u32 value)
-{
-	writel(value, pcie->intd_cfg_base + offset);
-}
+#include "pci-j721e.h"
 
 static irqreturn_t j721e_pcie_link_irq_handler(int irq, void *priv)
 {
@@ -121,6 +40,16 @@
 	j721e_pcie_intd_writel(pcie, ENABLE_REG_SYS_2, reg);
 }
 
+void j721e_pcie_remove_link_irq(struct j721e_pcie *pcie)
+{
+	u32 reg;
+
+	reg = j721e_pcie_intd_readl(pcie, CLEAR_REG_SYS_2);
+	reg |= pcie->linkdown_irq_regfield;
+	j721e_pcie_intd_writel(pcie, CLEAR_REG_SYS_2, reg);
+}
+EXPORT_SYMBOL_GPL(j721e_pcie_remove_link_irq);
+
 static int j721e_pcie_start_link(struct cdns_pcie *cdns_pcie)
 {
 	struct j721e_pcie *pcie = dev_get_drvdata(cdns_pcie->dev);
@@ -156,14 +85,15 @@
 	return false;
 }
 
-static const struct cdns_pcie_ops j721e_pcie_ops = {
+const struct cdns_pcie_ops j721e_pcie_ops = {
 	.start_link = j721e_pcie_start_link,
 	.stop_link = j721e_pcie_stop_link,
 	.link_up = j721e_pcie_link_up,
 };
+EXPORT_SYMBOL_GPL(j721e_pcie_ops);
 
 static int j721e_pcie_set_mode(struct j721e_pcie *pcie, struct regmap *syscon,
-			       unsigned int offset)
+				unsigned int offset)
 {
 	struct device *dev = pcie->cdns_pcie->dev;
 	u32 mask = J721E_MODE_RC;
@@ -182,7 +112,7 @@
 }
 
 static int j721e_pcie_set_link_speed(struct j721e_pcie *pcie,
-				     struct regmap *syscon, unsigned int offset)
+			     struct regmap *syscon, unsigned int offset)
 {
 	struct device *dev = pcie->cdns_pcie->dev;
 	struct device_node *np = dev->of_node;
@@ -207,11 +137,15 @@
 {
 	struct device *dev = pcie->cdns_pcie->dev;
 	u32 lanes = pcie->num_lanes;
+	u32 mask = BIT(8);
 	u32 val = 0;
 	int ret;
 
+	if (pcie->max_lanes == 4)
+		mask = GENMASK(9, 8);
+
 	val = LANE_COUNT(lanes - 1);
-	ret = regmap_update_bits(syscon, offset, LANE_COUNT_MASK, val);
+	ret = regmap_update_bits(syscon, offset, mask, val);
 	if (ret)
 		dev_err(dev, "failed to set link count\n");
 
@@ -235,7 +169,7 @@
 
 	/* Do not error out to maintain old DT compatibility */
 	ret = of_parse_phandle_with_fixed_args(node, "ti,syscon-pcie-ctrl", 1,
-					       0, &args);
+						0, &args);
 	if (!ret)
 		offset = args.args[0];
 
@@ -260,168 +194,40 @@
 	return 0;
 }
 
-static int cdns_ti_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
-				    int where, int size, u32 *value)
+static int j721e_pcie_setup_link_interrupts(struct j721e_pcie *pcie)
 {
-	if (pci_is_root_bus(bus))
-		return pci_generic_config_read32(bus, devfn, where, size,
-						 value);
-
-	return pci_generic_config_read(bus, devfn, where, size, value);
-}
+	struct device *dev = pcie->cdns_pcie->dev;
+	struct platform_device *pdev = to_platform_device(dev);
+	int ret;
 
-static int cdns_ti_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
-				     int where, int size, u32 value)
-{
-	if (pci_is_root_bus(bus))
-		return pci_generic_config_write32(bus, devfn, where, size,
-						  value);
+	ret = platform_get_irq_byname(pdev, "link_state");
+	if (ret < 0)
+		return ret;
+	ret = devm_request_irq(dev, ret, j721e_pcie_link_irq_handler, 0,
+				"j721e-pcie-link-down-irq", pcie);
+	if (ret < 0) {
+		dev_err(dev, "failed to request link state IRQ %d\n", ret);
+		return ret;
+	}
 
-	return pci_generic_config_write(bus, devfn, where, size, value);
+	j721e_pcie_config_link_irq(pcie);
+	return 0;
 }
 
-static struct pci_ops cdns_ti_pcie_host_ops = {
-	.map_bus	= cdns_pci_map_bus,
-	.read		= cdns_ti_pcie_config_read,
-	.write		= cdns_ti_pcie_config_write,
-};
-
-static const struct j721e_pcie_data j721e_pcie_rc_data = {
-	.mode = PCI_MODE_RC,
-	.quirk_retrain_flag = true,
-	.byte_access_allowed = false,
-	.linkdown_irq_regfield = LINK_DOWN,
-};
-
-static const struct j721e_pcie_data j721e_pcie_ep_data = {
-	.mode = PCI_MODE_EP,
-	.linkdown_irq_regfield = LINK_DOWN,
-};
-
-static const struct j721e_pcie_data j7200_pcie_rc_data = {
-	.mode = PCI_MODE_RC,
-	.quirk_detect_quiet_flag = true,
-	.linkdown_irq_regfield = J7200_LINK_DOWN,
-	.byte_access_allowed = true,
-};
-
-static const struct j721e_pcie_data j7200_pcie_ep_data = {
-	.mode = PCI_MODE_EP,
-	.quirk_detect_quiet_flag = true,
-	.quirk_disable_flr = true,
-};
-
-static const struct j721e_pcie_data am64_pcie_rc_data = {
-	.mode = PCI_MODE_RC,
-	.linkdown_irq_regfield = J7200_LINK_DOWN,
-	.byte_access_allowed = true,
-};
-
-static const struct j721e_pcie_data am64_pcie_ep_data = {
-	.mode = PCI_MODE_EP,
-	.linkdown_irq_regfield = J7200_LINK_DOWN,
-};
-
-static const struct of_device_id of_j721e_pcie_match[] = {
-	{
-		.compatible = "ti,j721e-pcie-host",
-		.data = &j721e_pcie_rc_data,
-	},
-	{
-		.compatible = "ti,j721e-pcie-ep",
-		.data = &j721e_pcie_ep_data,
-	},
-	{
-		.compatible = "ti,j7200-pcie-host",
-		.data = &j7200_pcie_rc_data,
-	},
-	{
-		.compatible = "ti,j7200-pcie-ep",
-		.data = &j7200_pcie_ep_data,
-	},
-	{
-		.compatible = "ti,am64-pcie-host",
-		.data = &am64_pcie_rc_data,
-	},
-	{
-		.compatible = "ti,am64-pcie-ep",
-		.data = &am64_pcie_ep_data,
-	},
-	{},
-};
-
-static int j721e_pcie_probe(struct platform_device *pdev)
+int j721e_pcie_common_init(struct j721e_pcie *pcie)
 {
-	struct device *dev = &pdev->dev;
+	struct device *dev = pcie->cdns_pcie->dev;
+	struct platform_device *pdev = to_platform_device(dev);
 	struct device_node *node = dev->of_node;
-	struct pci_host_bridge *bridge;
 	const struct j721e_pcie_data *data;
-	struct cdns_pcie *cdns_pcie;
-	struct j721e_pcie *pcie;
-	struct cdns_pcie_rc *rc = NULL;
-	struct cdns_pcie_ep *ep = NULL;
-	struct gpio_desc *gpiod;
 	void __iomem *base;
-	struct clk *clk;
 	u32 num_lanes;
-	u32 mode;
 	int ret;
-	int irq;
 
 	data = of_device_get_match_data(dev);
 	if (!data)
 		return -EINVAL;
 
-	mode = (u32)data->mode;
-
-	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
-	if (!pcie)
-		return -ENOMEM;
-
-	switch (mode) {
-	case PCI_MODE_RC:
-		if (!IS_ENABLED(CONFIG_PCIE_CADENCE_HOST))
-			return -ENODEV;
-
-		bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc));
-		if (!bridge)
-			return -ENOMEM;
-
-		if (!data->byte_access_allowed)
-			bridge->ops = &cdns_ti_pcie_host_ops;
-		rc = pci_host_bridge_priv(bridge);
-		rc->quirk_retrain_flag = data->quirk_retrain_flag;
-		rc->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag;
-
-		cdns_pcie = &rc->pcie;
-		cdns_pcie->dev = dev;
-		cdns_pcie->ops = &j721e_pcie_ops;
-		pcie->cdns_pcie = cdns_pcie;
-		break;
-	case PCI_MODE_EP:
-		if (!IS_ENABLED(CONFIG_PCIE_CADENCE_EP))
-			return -ENODEV;
-
-		ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL);
-		if (!ep)
-			return -ENOMEM;
-
-		ep->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag;
-		ep->quirk_disable_flr = data->quirk_disable_flr;
-
-		cdns_pcie = &ep->pcie;
-		cdns_pcie->dev = dev;
-		cdns_pcie->ops = &j721e_pcie_ops;
-		pcie->cdns_pcie = cdns_pcie;
-		break;
-	default:
-		dev_err(dev, "INVALID device type %d\n", mode);
-		return 0;
-	}
-
-	pcie->mode = mode;
-	pcie->linkdown_irq_regfield = data->linkdown_irq_regfield;
-
 	base = devm_platform_ioremap_resource_byname(pdev, "intd_cfg");
 	if (IS_ERR(base))
 		return PTR_ERR(base);
@@ -433,18 +239,19 @@
 	pcie->user_cfg_base = base;
 
 	ret = of_property_read_u32(node, "num-lanes", &num_lanes);
-	if (ret || num_lanes > MAX_LANES)
+	if (ret || num_lanes > data->max_lanes) {
+		dev_warn(dev, "num-lanes property not provided or invalid, setting num-lanes to 1\n");
 		num_lanes = 1;
+	}
+
 	pcie->num_lanes = num_lanes;
+	pcie->max_lanes = data->max_lanes;
 
 	if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(48)))
 		return -EINVAL;
 
-	irq = platform_get_irq_byname(pdev, "link_state");
-	if (irq < 0)
-		return irq;
-
 	dev_set_drvdata(dev, pcie);
+
 	pm_runtime_enable(dev);
 	ret = pm_runtime_get_sync(dev);
 	if (ret < 0) {
@@ -458,112 +265,28 @@
 		goto err_get_sync;
 	}
 
-	ret = devm_request_irq(dev, irq, j721e_pcie_link_irq_handler, 0,
-			       "j721e-pcie-link-down-irq", pcie);
+	ret = j721e_pcie_setup_link_interrupts(pcie);
 	if (ret < 0) {
-		dev_err(dev, "failed to request link state IRQ %d\n", irq);
+		dev_err(dev, "interrupt setup failed\n");
 		goto err_get_sync;
 	}
 
-	j721e_pcie_config_link_irq(pcie);
-
-	switch (mode) {
-	case PCI_MODE_RC:
-		gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
-		if (IS_ERR(gpiod)) {
-			ret = PTR_ERR(gpiod);
-			if (ret != -EPROBE_DEFER)
-				dev_err(dev, "Failed to get reset GPIO\n");
-			goto err_get_sync;
-		}
-
-		ret = cdns_pcie_init_phy(dev, cdns_pcie);
-		if (ret) {
-			dev_err(dev, "Failed to init phy\n");
-			goto err_get_sync;
-		}
-
-		clk = devm_clk_get_optional(dev, "pcie_refclk");
-		if (IS_ERR(clk)) {
-			ret = PTR_ERR(clk);
-			dev_err(dev, "failed to get pcie_refclk\n");
-			goto err_pcie_setup;
-		}
-
-		ret = clk_prepare_enable(clk);
-		if (ret) {
-			dev_err(dev, "failed to enable pcie_refclk\n");
-			goto err_pcie_setup;
-		}
-		pcie->refclk = clk;
-
-		/*
-		 * "Power Sequencing and Reset Signal Timings" table in
-		 * PCI EXPRESS CARD ELECTROMECHANICAL SPECIFICATION, REV. 3.0
-		 * indicates PERST# should be deasserted after minimum of 100us
-		 * once REFCLK is stable. The REFCLK to the connector in RC
-		 * mode is selected while enabling the PHY. So deassert PERST#
-		 * after 100 us.
-		 */
-		if (gpiod) {
-			usleep_range(100, 200);
-			gpiod_set_value_cansleep(gpiod, 1);
-		}
-
-		ret = cdns_pcie_host_setup(rc);
-		if (ret < 0) {
-			clk_disable_unprepare(pcie->refclk);
-			goto err_pcie_setup;
-		}
-
-		break;
-	case PCI_MODE_EP:
-		ret = cdns_pcie_init_phy(dev, cdns_pcie);
-		if (ret) {
-			dev_err(dev, "Failed to init phy\n");
-			goto err_get_sync;
-		}
-
-		ret = cdns_pcie_ep_setup(ep);
-		if (ret < 0)
-			goto err_pcie_setup;
-
-		break;
-	}
-
 	return 0;
 
-err_pcie_setup:
-	cdns_pcie_disable_phy(cdns_pcie);
-
 err_get_sync:
 	pm_runtime_put(dev);
 	pm_runtime_disable(dev);
 
 	return ret;
+
 }
+EXPORT_SYMBOL_GPL(j721e_pcie_common_init);
 
-static int j721e_pcie_remove(struct platform_device *pdev)
+void j721e_disable_common_init(struct device *dev)
 {
-	struct j721e_pcie *pcie = platform_get_drvdata(pdev);
-	struct cdns_pcie *cdns_pcie = pcie->cdns_pcie;
-	struct device *dev = &pdev->dev;
-
-	clk_disable_unprepare(pcie->refclk);
-	cdns_pcie_disable_phy(cdns_pcie);
 	pm_runtime_put(dev);
 	pm_runtime_disable(dev);
-
-	return 0;
 }
+EXPORT_SYMBOL_GPL(j721e_disable_common_init);
 
-static struct platform_driver j721e_pcie_driver = {
-	.probe  = j721e_pcie_probe,
-	.remove = j721e_pcie_remove,
-	.driver = {
-		.name	= "j721e-pcie",
-		.of_match_table = of_j721e_pcie_match,
-		.suppress_bind_attrs = true,
-	},
-};
-builtin_platform_driver(j721e_pcie_driver);
+MODULE_LICENSE("GPL v2");
diff -Naur --no-dereference a/drivers/pci/controller/cadence/pci-j721e-ep.c b/drivers/pci/controller/cadence/pci-j721e-ep.c
--- a/drivers/pci/controller/cadence/pci-j721e-ep.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/pci/controller/cadence/pci-j721e-ep.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * pci-j721e-ep - PCIe end-point controller driver for TI's J721E SoCs
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/of_device.h>
+
+#include "pcie-cadence.h"
+#include "pci-j721e.h"
+
+static const struct j721e_pcie_data j721e_pcie_ep_data = {
+	.mode = PCI_MODE_EP,
+	.linkdown_irq_regfield = LINK_DOWN,
+	.max_lanes = 2,
+};
+
+static const struct j721e_pcie_data j7200_pcie_ep_data = {
+	.mode = PCI_MODE_EP,
+	.quirk_detect_quiet_flag = true,
+	.quirk_disable_flr = true,
+	.max_lanes = 2,
+};
+
+static const struct j721e_pcie_data am64_pcie_ep_data = {
+	.mode = PCI_MODE_EP,
+	.linkdown_irq_regfield = J7200_LINK_DOWN,
+	.max_lanes = 1,
+};
+
+static const struct j721e_pcie_data j784s4_pcie_ep_data = {
+	.mode = PCI_MODE_EP,
+	.linkdown_irq_regfield = LINK_DOWN,
+	.max_lanes = 4,
+};
+
+static const struct of_device_id of_j721e_pcie_ep_match[] = {
+	{
+		.compatible = "ti,j721e-pcie-ep",
+		.data = &j721e_pcie_ep_data,
+	},
+	{
+		.compatible = "ti,j7200-pcie-ep",
+		.data = &j7200_pcie_ep_data,
+	},
+	{
+		.compatible = "ti,am64-pcie-ep",
+		.data = &am64_pcie_ep_data,
+	},
+	{
+		.compatible = "ti,j784s4-pcie-ep",
+		.data = &j784s4_pcie_ep_data,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_j721e_pcie_ep_match);
+
+static int j721e_pcie_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	const struct j721e_pcie_data *data;
+	struct cdns_pcie *cdns_pcie;
+	struct j721e_pcie *pcie;
+	struct cdns_pcie_ep *ep = NULL;
+	int ret;
+
+	data = of_device_get_match_data(dev);
+	if (!data)
+		return -EINVAL;
+
+	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
+	if (!pcie)
+		return -ENOMEM;
+
+	ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL);
+	if (!ep)
+		return -ENOMEM;
+
+	ep->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag;
+	ep->quirk_disable_flr = data->quirk_disable_flr;
+
+	cdns_pcie = &ep->pcie;
+	cdns_pcie->dev = dev;
+	cdns_pcie->ops = &j721e_pcie_ops;
+	pcie->cdns_pcie = cdns_pcie;
+
+	pcie->mode = PCI_MODE_EP;
+	pcie->linkdown_irq_regfield = data->linkdown_irq_regfield;
+
+	ret = j721e_pcie_common_init(pcie);
+	if (ret)
+		return ret;
+
+	ret = cdns_pcie_init_phy(dev, cdns_pcie);
+	if (ret) {
+		dev_err(dev, "Failed to init phy\n");
+		goto err_get_sync;
+	}
+
+	ret = cdns_pcie_ep_setup(ep);
+	if (ret < 0)
+		goto err_pcie_setup;
+
+
+	return 0;
+
+err_pcie_setup:
+	cdns_pcie_disable_phy(cdns_pcie);
+
+err_get_sync:
+	j721e_disable_common_init(dev);
+
+	return ret;
+}
+
+static int j721e_pcie_remove(struct platform_device *pdev)
+{
+	struct j721e_pcie *pcie = platform_get_drvdata(pdev);
+	struct cdns_pcie *cdns_pcie = pcie->cdns_pcie;
+	struct device *dev = &pdev->dev;
+
+	j721e_pcie_remove_link_irq(pcie);
+	cdns_pcie_stop_link(cdns_pcie);
+	cdns_pcie_deinit_phy(cdns_pcie);
+	j721e_disable_common_init(dev);
+
+	return 0;
+}
+
+static struct platform_driver j721e_pcie_ep_driver = {
+	.probe  = j721e_pcie_probe,
+	.remove = j721e_pcie_remove,
+	.driver = {
+		.name	= "j721e-pcie-ep",
+		.of_match_table = of_j721e_pcie_ep_match,
+		.suppress_bind_attrs = true,
+	},
+};
+module_platform_driver(j721e_pcie_ep_driver);
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
diff -Naur --no-dereference a/drivers/pci/controller/cadence/pci-j721e.h b/drivers/pci/controller/cadence/pci-j721e.h
--- a/drivers/pci/controller/cadence/pci-j721e.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/pci/controller/cadence/pci-j721e.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * pci-j721e - PCIe controller driver for TI's J721E SoCs
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com
+ */
+
+#ifndef _PCIE_J721E_H
+#define _PCIE_J721E_H
+
+#define ENABLE_REG_SYS_0	0x100
+#define STATUS_REG_SYS_0	0x500
+#define STATUS_CLR_REG_SYS_0	0x700
+#define ENABLE_REG_SYS_1	0x104
+#define STATUS_REG_SYS_1	0x504
+#define ENABLE_REG_SYS_2	0x108
+#define CLEAR_REG_SYS_2         0x308
+#define STATUS_REG_SYS_2	0x508
+#define STATUS_CLR_REG_SYS_2	0x708
+#define LINK_DOWN		BIT(1)
+#define J7200_LINK_DOWN		BIT(10)
+
+#define J721E_PCIE_USER_CMD_STATUS	0x4
+#define LINK_TRAINING_ENABLE		BIT(0)
+
+#define J721E_PCIE_USER_LINKSTATUS	0x14
+#define LINK_STATUS			GENMASK(1, 0)
+
+#define EOI_REG			0x10
+#define INTx_EN(num)		(1 << (num))
+#define SYS1_INTx_EN(num)	(1 << (22 + (num)))
+#define USER_EOI_REG		0xC8
+
+enum eoi_reg {
+	EOI_DOWNSTREAM_INTERRUPT,
+	EOI_FLR_INTERRUPT,
+	EOI_LEGACY_INTERRUPT,
+	EOI_POWER_STATE_INTERRUPT,
+};
+
+enum link_status {
+	NO_RECEIVERS_DETECTED,
+	LINK_TRAINING_IN_PROGRESS,
+	LINK_UP_DL_IN_PROGRESS,
+	LINK_UP_DL_COMPLETED,
+};
+
+#define J721E_MODE_RC			BIT(7)
+#define LANE_COUNT(n)			((n) << 8)
+
+#define GENERATION_SEL_MASK		GENMASK(1, 0)
+
+struct j721e_pcie {
+	struct cdns_pcie	*cdns_pcie;
+	struct clk		*refclk;
+	u32			mode;
+	u32			num_lanes;
+	u32			max_lanes;
+	void __iomem		*user_cfg_base;
+	void __iomem		*intd_cfg_base;
+	u32			linkdown_irq_regfield;
+	struct gpio_desc        *gpiod;
+	struct irq_domain	*legacy_irq_domain;
+	unsigned int		is_intc_v1:1;
+};
+
+enum j721e_pcie_mode {
+	PCI_MODE_RC,
+	PCI_MODE_EP,
+};
+
+struct j721e_pcie_data {
+	enum j721e_pcie_mode	mode;
+	unsigned int		is_intc_v1:1;
+	unsigned int		quirk_retrain_flag:1;
+	unsigned int		quirk_detect_quiet_flag:1;
+	unsigned int		quirk_disable_flr:1;
+	u32			linkdown_irq_regfield;
+	unsigned int		byte_access_allowed:1;
+	unsigned int		max_lanes;
+};
+
+static inline u32 j721e_pcie_user_readl(struct j721e_pcie *pcie, u32 offset)
+{
+	return readl(pcie->user_cfg_base + offset);
+}
+
+static inline void j721e_pcie_user_writel(struct j721e_pcie *pcie, u32 offset,
+					  u32 value)
+{
+	writel(value, pcie->user_cfg_base + offset);
+}
+
+static inline u32 j721e_pcie_intd_readl(struct j721e_pcie *pcie, u32 offset)
+{
+	return readl(pcie->intd_cfg_base + offset);
+}
+
+static inline void j721e_pcie_intd_writel(struct j721e_pcie *pcie, u32 offset,
+					  u32 value)
+{
+	writel(value, pcie->intd_cfg_base + offset);
+}
+
+extern const struct cdns_pcie_ops j721e_pcie_ops;
+int j721e_pcie_common_init(struct j721e_pcie *pcie);
+void j721e_pcie_remove_link_irq(struct j721e_pcie *pcie);
+void j721e_disable_common_init(struct device *dev);
+
+#endif /* _PCIE_J721E_H */
diff -Naur --no-dereference a/drivers/pci/controller/cadence/pci-j721e-host.c b/drivers/pci/controller/cadence/pci-j721e-host.c
--- a/drivers/pci/controller/cadence/pci-j721e-host.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/pci/controller/cadence/pci-j721e-host.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,452 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * pci-j721e-host - PCIe host controller driver for TI's J721E SoCs
+ *
+ * Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/delay.h>
+#include <linux/of_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/of_irq.h>
+#include <linux/irqchip/chained_irq.h>
+
+#include "pcie-cadence.h"
+#include "pci-j721e.h"
+
+#define CTRL_MMR_LOCK2_MASK		0xFFFFFFFF
+#define CTRL_MMR_LOCK2_KICK0_UNLOCK_VAL	0x68EF3490
+#define CTRL_MMR_LOCK2_KICK1_UNLOCK_VAL	0xD172BC5A
+#define CTRL_MMR_LOCK_KICK_LOCK_VAL	0xFFFFFFFF
+#define CTRL_MMR_ACSPCIE_PAD_MASK	0xFFFFFFFF
+#define CTRL_MMR_ACSPCIE_PAD_EN		0x01000000
+#define PCIE_REFCLK_CLKSEL_OUT_EN	BIT(8)
+#define PCIE_REFCLK_CLKSEL_MASK	GENMASK(1, 0)
+
+static int cdns_ti_pcie_config_read(struct pci_bus *bus, unsigned int devfn,
+					int where, int size, u32 *value)
+{
+	if (pci_is_root_bus(bus))
+		return pci_generic_config_read32(bus, devfn, where, size,
+						 value);
+
+	return pci_generic_config_read(bus, devfn, where, size, value);
+}
+
+static int cdns_ti_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
+					int where, int size, u32 value)
+{
+	if (pci_is_root_bus(bus))
+		return pci_generic_config_write32(bus, devfn, where, size,
+						value);
+
+	return pci_generic_config_write(bus, devfn, where, size, value);
+}
+
+static struct pci_ops cdns_ti_pcie_host_ops = {
+	.map_bus	= cdns_pci_map_bus,
+	.read		= cdns_ti_pcie_config_read,
+	.write		= cdns_ti_pcie_config_write,
+};
+
+static const struct j721e_pcie_data j721e_pcie_rc_data = {
+	.mode = PCI_MODE_RC,
+	.quirk_retrain_flag = true,
+	.byte_access_allowed = false,
+	.linkdown_irq_regfield = LINK_DOWN,
+	.max_lanes = 2,
+	.is_intc_v1 = true,
+};
+
+static const struct j721e_pcie_data j7200_pcie_rc_data = {
+	.mode = PCI_MODE_RC,
+	.quirk_detect_quiet_flag = true,
+	.linkdown_irq_regfield = J7200_LINK_DOWN,
+	.byte_access_allowed = true,
+	.max_lanes = 2,
+};
+
+static const struct j721e_pcie_data am64_pcie_rc_data = {
+	.mode = PCI_MODE_RC,
+	.linkdown_irq_regfield = J7200_LINK_DOWN,
+	.byte_access_allowed = true,
+	.max_lanes = 1,
+};
+
+static const struct j721e_pcie_data j784s4_pcie_rc_data = {
+	.mode = PCI_MODE_RC,
+	.quirk_retrain_flag = true,
+	.byte_access_allowed = false,
+	.linkdown_irq_regfield = LINK_DOWN,
+	.max_lanes = 4,
+};
+
+static const struct of_device_id of_j721e_pcie_host_match[] = {
+	{
+		.compatible = "ti,j721e-pcie-host",
+		.data = &j721e_pcie_rc_data,
+	},
+	{
+		.compatible = "ti,j7200-pcie-host",
+		.data = &j7200_pcie_rc_data,
+	},
+	{
+		.compatible = "ti,am64-pcie-host",
+		.data = &am64_pcie_rc_data,
+	},
+	{
+		.compatible = "ti,j784s4-pcie-host",
+		.data = &j784s4_pcie_rc_data,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, of_j721e_pcie_host_match);
+
+static void j721e_pcie_legacy_irq_handler(struct irq_desc *desc)
+{
+	struct j721e_pcie *pcie = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	int i, virq;
+	u32 reg;
+
+	chained_irq_enter(chip, desc);
+
+	for (i = 0; i < PCI_NUM_INTX; i++) {
+		reg = j721e_pcie_intd_readl(pcie, STATUS_REG_SYS_1);
+		if (!(reg & SYS1_INTx_EN(i)))
+			continue;
+
+		virq = irq_find_mapping(pcie->legacy_irq_domain, i);
+		generic_handle_irq(virq);
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
+static void j721e_pcie_irq_eoi(struct irq_data *data)
+{
+	struct j721e_pcie *pcie = irq_data_get_irq_chip_data(data);
+
+	j721e_pcie_user_writel(pcie, USER_EOI_REG, EOI_LEGACY_INTERRUPT);
+}
+
+struct irq_chip j721e_pcie_irq_chip = {
+	.name		= "J721E-PCIE-INTX",
+	.irq_eoi	= j721e_pcie_irq_eoi,
+};
+
+static void j721e_pcie_v1_legacy_irq_handler(struct irq_desc *desc)
+{
+	struct j721e_pcie *pcie = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	int i, virq;
+	u32 reg;
+
+	chained_irq_enter(chip, desc);
+
+	for (i = 0; i < PCI_NUM_INTX; i++) {
+		reg = j721e_pcie_intd_readl(pcie, STATUS_REG_SYS_0);
+		if (!(reg & INTx_EN(i)))
+			continue;
+
+		virq = irq_find_mapping(pcie->legacy_irq_domain, 3 - i);
+		generic_handle_irq(virq);
+		j721e_pcie_intd_writel(pcie, STATUS_CLR_REG_SYS_0, INTx_EN(i));
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
+static int j721e_pcie_intx_map(struct irq_domain *domain, unsigned int irq, irq_hw_number_t hwirq)
+{
+	struct j721e_pcie *pcie = domain->host_data;
+
+	if (pcie->is_intc_v1)
+		irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+	else
+		irq_set_chip_and_handler(irq, &j721e_pcie_irq_chip, handle_fasteoi_irq);
+
+	irq_set_chip_data(irq, pcie);
+
+	return 0;
+}
+
+static const struct irq_domain_ops j721e_pcie_intx_domain_ops = {
+	.map = j721e_pcie_intx_map,
+};
+
+static int j721e_pcie_config_legacy_irq(struct j721e_pcie *pcie)
+{
+	struct irq_domain *legacy_irq_domain;
+	struct device *dev = pcie->cdns_pcie->dev;
+	struct device_node *node = dev->of_node;
+	struct device_node *intc_node;
+	int irq, i;
+	u32 reg;
+
+	intc_node = of_get_child_by_name(node, "interrupt-controller");
+	if (!intc_node) {
+		dev_dbg(dev, "interrupt-controller node is absent. Legacy INTR not supported\n");
+		return 0;
+	}
+
+	irq = irq_of_parse_and_map(intc_node, 0);
+	if (!irq) {
+		dev_err(dev, "Failed to parse and map legacy irq\n");
+		return -EINVAL;
+	}
+
+	if (pcie->is_intc_v1)
+		irq_set_chained_handler_and_data(irq, j721e_pcie_v1_legacy_irq_handler, pcie);
+	else
+		irq_set_chained_handler_and_data(irq, j721e_pcie_legacy_irq_handler, pcie);
+
+	legacy_irq_domain = irq_domain_add_linear(intc_node, PCI_NUM_INTX,
+						  &j721e_pcie_intx_domain_ops, pcie);
+	if (!legacy_irq_domain) {
+		dev_err(dev, "Failed to add irq domain for legacy irqs\n");
+		return -EINVAL;
+	}
+	pcie->legacy_irq_domain = legacy_irq_domain;
+
+	for (i = 0; i < PCI_NUM_INTX; i++) {
+		if (pcie->is_intc_v1) {
+			reg = j721e_pcie_intd_readl(pcie, ENABLE_REG_SYS_0);
+			reg |= INTx_EN(i);
+			j721e_pcie_intd_writel(pcie, ENABLE_REG_SYS_0, reg);
+		} else {
+			reg = j721e_pcie_intd_readl(pcie, ENABLE_REG_SYS_1);
+			reg |= SYS1_INTx_EN(i);
+			j721e_pcie_intd_writel(pcie, ENABLE_REG_SYS_1, reg);
+		}
+	}
+
+	return 0;
+}
+
+static int j721e_enable_acspcie(struct j721e_pcie *pcie)
+{
+	struct device *dev = pcie->cdns_pcie->dev;
+	struct device_node *node = dev->of_node;
+	struct of_phandle_args args;
+	unsigned int lock2_kick0_offset, lock2_kick1_offset;
+	unsigned int acspcie_pad_offset, refclk_clksel_offset;
+	unsigned int refclk_clksel_source;
+	struct regmap *syscon;
+	u32 val = 0, mask = 0;
+	int ret;
+
+	/*
+	 * If property ti,syscon-pcie-refclk-out exists, believe PCIe connector
+	 * requires PCIe ref clock from Serdes, so enable ACSPCIE pads and mux
+	 * to source out PCIe ref clock else ref clock has to be supplied from
+	 * on-board clock generator.
+	 */
+	syscon = syscon_regmap_lookup_by_phandle(node, "ti,syscon-pcie-refclk-out");
+	if (IS_ERR(syscon))
+		return 0;
+
+	ret = of_parse_phandle_with_fixed_args(node, "ti,syscon-pcie-refclk-out", 5,
+						0, &args);
+	if (ret) {
+		dev_err(dev, "Failed to read ti,syscon-pcie-refclk-out property\n");
+		return ret;
+	}
+
+	lock2_kick0_offset = args.args[0];
+	lock2_kick1_offset = args.args[1];
+	acspcie_pad_offset = args.args[2];
+	refclk_clksel_offset = args.args[3];
+	refclk_clksel_source = args.args[4];
+
+	/* Un-lock Partition 2 : 8000h to 9FFFh */
+	mask = CTRL_MMR_LOCK2_MASK;
+	val = CTRL_MMR_LOCK2_KICK0_UNLOCK_VAL;
+	ret = regmap_update_bits(syscon, lock2_kick0_offset, mask, val);
+	if (ret)
+		goto err;
+
+	val = CTRL_MMR_LOCK2_KICK1_UNLOCK_VAL;
+	ret = regmap_update_bits(syscon, lock2_kick1_offset, mask, val);
+	if (ret)
+		goto err;
+
+	/* Enable ACSPCIe PADS  */
+	mask = CTRL_MMR_ACSPCIE_PAD_MASK;
+	val = CTRL_MMR_ACSPCIE_PAD_EN;
+	ret = regmap_update_bits(syscon, acspcie_pad_offset, mask, val);
+	if (ret)
+		goto err;
+
+	/* PCIE_REFCLKx_CLKSEL : EN + ref_clk_source */
+	mask = PCIE_REFCLK_CLKSEL_OUT_EN | PCIE_REFCLK_CLKSEL_MASK;
+	val = PCIE_REFCLK_CLKSEL_OUT_EN | refclk_clksel_source;
+	ret = regmap_update_bits(syscon, refclk_clksel_offset, mask, val);
+	if (ret)
+		goto err;
+
+	/* Re-lock Partition 2 : 8000h to 9FFFh */
+	mask = CTRL_MMR_LOCK_KICK_LOCK_VAL;
+	val = CTRL_MMR_LOCK_KICK_LOCK_VAL;
+	ret = regmap_update_bits(syscon, lock2_kick0_offset, mask, val);
+	if (ret)
+		goto err;
+
+	ret = regmap_update_bits(syscon, lock2_kick1_offset, mask, val);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	dev_err(dev, "Failed to enable ref clock out\n");
+	return ret;
+}
+
+static int j721e_pcie_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct pci_host_bridge *bridge;
+	const struct j721e_pcie_data *data;
+	struct cdns_pcie *cdns_pcie;
+	struct j721e_pcie *pcie;
+	struct cdns_pcie_rc *rc = NULL;
+	struct gpio_desc *gpiod;
+	struct clk *clk;
+	int ret;
+
+	data = of_device_get_match_data(dev);
+	if (!data)
+		return -EINVAL;
+
+	pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
+	if (!pcie)
+		return -ENOMEM;
+
+	bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rc));
+	if (!bridge)
+		return -ENOMEM;
+
+	if (!data->byte_access_allowed)
+		bridge->ops = &cdns_ti_pcie_host_ops;
+	rc = pci_host_bridge_priv(bridge);
+	rc->quirk_retrain_flag = data->quirk_retrain_flag;
+	rc->quirk_detect_quiet_flag = data->quirk_detect_quiet_flag;
+
+	cdns_pcie = &rc->pcie;
+	cdns_pcie->dev = dev;
+	cdns_pcie->ops = &j721e_pcie_ops;
+	pcie->cdns_pcie = cdns_pcie;
+
+	pcie->mode = PCI_MODE_RC;
+	pcie->linkdown_irq_regfield = data->linkdown_irq_regfield;
+
+	ret = j721e_pcie_common_init(pcie);
+	if (ret)
+		return ret;
+
+	pcie->is_intc_v1 = data->is_intc_v1;
+	ret = j721e_pcie_config_legacy_irq(pcie);
+	if (ret < 0)
+		goto err_get_sync;
+
+	/*
+	 * Enable ACSPCIe clock buffer to source out reference clock for EP
+	 */
+	ret = j721e_enable_acspcie(pcie);
+	if (ret < 0)
+		goto err_get_sync;
+
+	gpiod = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(gpiod)) {
+		ret = PTR_ERR(gpiod);
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "Failed to get reset GPIO\n");
+		goto err_get_sync;
+	}
+
+	ret = cdns_pcie_init_phy(dev, cdns_pcie);
+	if (ret) {
+		dev_err(dev, "Failed to init phy\n");
+		goto err_get_sync;
+	}
+
+	clk = devm_clk_get_optional(dev, "pcie_refclk");
+	if (IS_ERR(clk)) {
+		ret = PTR_ERR(clk);
+		dev_err(dev, "failed to get pcie_refclk\n");
+		goto err_pcie_setup;
+	}
+
+	ret = clk_prepare_enable(clk);
+	if (ret) {
+		dev_err(dev, "failed to enable pcie_refclk\n");
+		goto err_pcie_setup;
+	}
+	pcie->refclk = clk;
+
+	/*
+	 * "Power Sequencing and Reset Signal Timings" table in
+	 * PCI EXPRESS CARD ELECTROMECHANICAL SPECIFICATION, REV. 3.0
+	 * indicates PERST# should be deasserted after minimum of 100us
+	 * once REFCLK is stable. The REFCLK to the connector in RC
+	 * mode is selected while enabling the PHY. So deassert PERST#
+	 * after 100 us.
+	 */
+	if (gpiod) {
+		usleep_range(100, 200);
+		gpiod_set_value_cansleep(gpiod, 1);
+	}
+
+	ret = cdns_pcie_host_setup(rc);
+	if (ret < 0) {
+		clk_disable_unprepare(pcie->refclk);
+		goto err_pcie_setup;
+	}
+
+	return 0;
+
+err_pcie_setup:
+	cdns_pcie_disable_phy(cdns_pcie);
+
+err_get_sync:
+	j721e_disable_common_init(dev);
+
+	return ret;
+}
+
+static int j721e_pcie_remove(struct platform_device *pdev)
+{
+	struct j721e_pcie *pcie = platform_get_drvdata(pdev);
+	struct cdns_pcie *cdns_pcie = pcie->cdns_pcie;
+	struct cdns_pcie_rc *rc = container_of(cdns_pcie, struct cdns_pcie_rc, pcie);
+	struct device *dev = &pdev->dev;
+
+	cdns_pcie_host_remove_setup(rc);
+	j721e_pcie_remove_link_irq(pcie);
+
+	cdns_pcie_stop_link(cdns_pcie);
+	clk_disable_unprepare(pcie->refclk);
+
+	gpiod_set_value_cansleep(pcie->gpiod, 0);
+	cdns_pcie_deinit_phy(cdns_pcie);
+	j721e_disable_common_init(dev);
+
+	return 0;
+}
+
+static struct platform_driver j721e_pcie_host_driver = {
+	.probe  = j721e_pcie_probe,
+	.remove = j721e_pcie_remove,
+	.driver = {
+		.name	= "j721e-pcie-host",
+		.of_match_table = of_j721e_pcie_host_match,
+		.suppress_bind_attrs = true,
+	},
+};
+module_platform_driver(j721e_pcie_host_driver);
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
diff -Naur --no-dereference a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
--- a/drivers/pci/controller/dwc/pci-keystone.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pci/controller/dwc/pci-keystone.c	2024-01-28 14:01:31.252353813 -0500
@@ -35,6 +35,11 @@
 #define PCIE_DEVICEID_SHIFT	16
 
 /* Application registers */
+#define PID				0x000
+#define RTL				GENMASK(15, 11)
+#define RTL_SHIFT			11
+#define AM6_PCI_PG1_RTL_VER		0x15
+
 #define CMD_STATUS			0x004
 #define LTSSM_EN_VAL		        BIT(0)
 #define OB_XLAT_EN_VAL		        BIT(1)
@@ -69,6 +74,7 @@
 
 #define IRQ_STATUS(n)			(0x184 + ((n) << 4))
 #define IRQ_ENABLE_SET(n)		(0x188 + ((n) << 4))
+#define IRQ_ENABLE_CLR(n)		(0x18c + ((n) << 4))
 #define INTx_EN				BIT(0)
 
 #define ERR_IRQ_STATUS			0x1c4
@@ -105,6 +111,8 @@
 
 #define to_keystone_pcie(x)		dev_get_drvdata((x)->dev)
 
+#define PCI_DEVICE_ID_TI_AM654X		0xb00c
+
 struct ks_pcie_of_data {
 	enum dw_pcie_device_mode mode;
 	const struct dw_pcie_host_ops *host_ops;
@@ -116,8 +124,8 @@
 	struct dw_pcie		*pci;
 	/* PCI Device ID */
 	u32			device_id;
-	int			legacy_host_irqs[PCI_NUM_INTX];
 	struct			device_node *legacy_intc_np;
+	struct irq_domain	*legacy_irq_domain;
 
 	int			msi_host_irq;
 	int			num_lanes;
@@ -125,7 +133,6 @@
 	struct phy		**phy;
 	struct device_link	**link;
 	struct			device_node *msi_intc_np;
-	struct irq_domain	*legacy_irq_domain;
 	struct device_node	*np;
 
 	/* Application register space */
@@ -253,24 +260,6 @@
 	return dw_pcie_allocate_domains(pp);
 }
 
-static void ks_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie,
-				      int offset)
-{
-	struct dw_pcie *pci = ks_pcie->pci;
-	struct device *dev = pci->dev;
-	u32 pending;
-
-	pending = ks_pcie_app_readl(ks_pcie, IRQ_STATUS(offset));
-
-	if (BIT(0) & pending) {
-		dev_dbg(dev, ": irq: irq_offset %d", offset);
-		generic_handle_domain_irq(ks_pcie->legacy_irq_domain, offset);
-	}
-
-	/* EOI the INTx interrupt */
-	ks_pcie_app_writel(ks_pcie, IRQ_EOI, offset);
-}
-
 static void ks_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
 {
 	ks_pcie_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
@@ -308,39 +297,143 @@
 	return IRQ_HANDLED;
 }
 
-static void ks_pcie_ack_legacy_irq(struct irq_data *d)
+static void ks_pcie_am654_legacy_irq_handler(struct irq_desc *desc)
+{
+	struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	int virq, i;
+	u32 reg;
+
+	chained_irq_enter(chip, desc);
+
+	for (i = 0; i < PCI_NUM_INTX; i++) {
+		reg = ks_pcie_app_readl(ks_pcie, IRQ_STATUS(i));
+		if (!(reg & INTx_EN))
+			continue;
+
+		virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, i);
+		generic_handle_irq(virq);
+		ks_pcie_app_writel(ks_pcie, IRQ_STATUS(i), INTx_EN);
+		ks_pcie_app_writel(ks_pcie, IRQ_EOI, i);
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
+void ks_pcie_irq_eoi(struct irq_data *data)
 {
+	struct keystone_pcie *ks_pcie = irq_data_get_irq_chip_data(data);
+	irq_hw_number_t hwirq = data->hwirq;
+
+	ks_pcie_app_writel(ks_pcie, IRQ_EOI, hwirq);
+	irq_chip_eoi_parent(data);
 }
 
-static void ks_pcie_mask_legacy_irq(struct irq_data *d)
+void ks_pcie_irq_enable(struct irq_data *data)
 {
+	struct keystone_pcie *ks_pcie = irq_data_get_irq_chip_data(data);
+	irq_hw_number_t hwirq = data->hwirq;
+
+	ks_pcie_app_writel(ks_pcie, IRQ_ENABLE_SET(hwirq), INTx_EN);
+	irq_chip_enable_parent(data);
 }
 
-static void ks_pcie_unmask_legacy_irq(struct irq_data *d)
+void ks_pcie_irq_disable(struct irq_data *data)
 {
+	struct keystone_pcie *ks_pcie = irq_data_get_irq_chip_data(data);
+	irq_hw_number_t hwirq = data->hwirq;
+
+	ks_pcie_app_writel(ks_pcie, IRQ_ENABLE_CLR(hwirq), INTx_EN);
+	irq_chip_disable_parent(data);
 }
 
 static struct irq_chip ks_pcie_legacy_irq_chip = {
-	.name = "Keystone-PCI-Legacy-IRQ",
-	.irq_ack = ks_pcie_ack_legacy_irq,
-	.irq_mask = ks_pcie_mask_legacy_irq,
-	.irq_unmask = ks_pcie_unmask_legacy_irq,
+	.name			= "Keystone-PCI-Legacy-IRQ",
+	.irq_enable		= ks_pcie_irq_enable,
+	.irq_disable		= ks_pcie_irq_disable,
+	.irq_eoi		= ks_pcie_irq_eoi,
+	.irq_mask		= irq_chip_mask_parent,
+	.irq_unmask		= irq_chip_unmask_parent,
+	.irq_retrigger		= irq_chip_retrigger_hierarchy,
+	.irq_set_type		= irq_chip_set_type_parent,
+	.irq_set_affinity	= irq_chip_set_affinity_parent,
 };
 
-static int ks_pcie_init_legacy_irq_map(struct irq_domain *d,
-				       unsigned int irq,
-				       irq_hw_number_t hw_irq)
-{
-	irq_set_chip_and_handler(irq, &ks_pcie_legacy_irq_chip,
-				 handle_level_irq);
-	irq_set_chip_data(irq, d->host_data);
+static int ks_pcie_legacy_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+					   unsigned int nr_irqs, void *data)
+{
+	struct keystone_pcie *ks_pcie = domain->host_data;
+	struct device_node *np = ks_pcie->legacy_intc_np;
+	struct irq_fwspec parent_fwspec, *fwspec = data;
+	struct of_phandle_args out_irq;
+	int ret;
+
+	if (nr_irqs != 1)
+		return -EINVAL;
+
+	/*
+	 * Get the correct interrupt from legacy-interrupt-controller node
+	 * corresponding to INTA/INTB/INTC/INTD (passed in fwspec->param[0])
+	 * after performing mapping specified in "interrupt-map".
+	 * interrupt-map = <0 0 0 1 &pcie_intc0 0>, INTA (4th cell in
+	 * interrupt-map) corresponds to 1st entry in "interrupts" (6th cell
+	 * in interrupt-map)
+	 */
+	ret = of_irq_parse_one(np, fwspec->param[0], &out_irq);
+	if (ret < 0) {
+		pr_err("Failed to parse interrupt node\n");
+		return ret;
+	}
+
+	of_phandle_args_to_fwspec(np, out_irq.args, out_irq.args_count, &parent_fwspec);
+
+	ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec);
+	if (ret < 0) {
+		pr_err("Failed to allocate parent irq %u: %d\n",
+		       parent_fwspec.param[0], ret);
+		return ret;
+	}
+
+	ret = irq_domain_set_hwirq_and_chip(domain, virq, fwspec->param[0],
+					    &ks_pcie_legacy_irq_chip, ks_pcie);
+	if (ret < 0) {
+		pr_err("Failed to set hwirq and chip\n");
+		goto err_set_hwirq_and_chip;
+	}
 
 	return 0;
+
+err_set_hwirq_and_chip:
+	irq_domain_free_irqs_parent(domain, virq, 1);
+
+	return ret;
+}
+
+static int ks_pcie_irq_domain_translate(struct irq_domain *domain,
+					struct irq_fwspec *fwspec,
+					unsigned long *hwirq,
+					unsigned int *type)
+{
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 2)
+			return -EINVAL;
+
+		if (fwspec->param[0] >= PCI_NUM_INTX)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1];
+
+		return 0;
+	}
+
+	return -EINVAL;
 }
 
 static const struct irq_domain_ops ks_pcie_legacy_irq_domain_ops = {
-	.map = ks_pcie_init_legacy_irq_map,
-	.xlate = irq_domain_xlate_onetwocell,
+	.alloc		= ks_pcie_legacy_irq_domain_alloc,
+	.free		= irq_domain_free_irqs_common,
+	.translate	= ks_pcie_irq_domain_translate,
 };
 
 /**
@@ -433,6 +526,17 @@
 	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
 	u32 reg;
 
+	/*
+	 * Checking whether the link is up here is a last line of defense
+	 * against platforms that forward errors on the system bus as
+	 * SError upon PCI configuration transactions issued when the link
+	 * is down. This check is racy by definition and does not stop
+	 * the system from triggering an SError if the link goes down
+	 * after this check is performed.
+	 */
+	if (!dw_pcie_link_up(pci))
+		return NULL;
+
 	reg = CFG_BUS(bus->number) | CFG_DEVICE(PCI_SLOT(devfn)) |
 		CFG_FUNC(PCI_FUNC(devfn));
 	if (!pci_is_root_bus(bus->parent))
@@ -460,7 +564,7 @@
 	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 	struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
 
-	if (!pci_is_root_bus(bus))
+	if (!pci_is_root_bus(bus) || ks_pcie->is_am6)
 		return 0;
 
 	/* Configure and set up BAR0 */
@@ -528,7 +632,11 @@
 static void ks_pcie_quirk(struct pci_dev *dev)
 {
 	struct pci_bus *bus = dev->bus;
+	struct keystone_pcie *ks_pcie;
+	struct device *bridge_dev;
 	struct pci_dev *bridge;
+	u32 val;
+
 	static const struct pci_device_id rc_pci_devids[] = {
 		{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2HK),
 		 .class = PCI_CLASS_BRIDGE_PCI_NORMAL, .class_mask = ~0, },
@@ -540,6 +648,11 @@
 		 .class = PCI_CLASS_BRIDGE_PCI_NORMAL, .class_mask = ~0, },
 		{ 0, },
 	};
+	static const struct pci_device_id am6_pci_devids[] = {
+		{ PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_AM654X),
+		 .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
+		{ 0, },
+	};
 
 	if (pci_is_root_bus(bus))
 		bridge = dev;
@@ -565,6 +678,32 @@
 			pcie_set_readrq(dev, 256);
 		}
 	}
+
+	/*
+	 * Memory transactions fail with PCI controller in AM654 PG1.0
+	 * when MRRS is set to more than 128 Bytes. Force the MRRS to
+	 * 128 Bytes in all downstream devices.
+	 */
+	if (pci_match_id(am6_pci_devids, bridge)) {
+		bridge_dev = pci_get_host_bridge_device(dev);
+		if (!bridge_dev && !bridge_dev->parent)
+			return;
+
+		ks_pcie = dev_get_drvdata(bridge_dev->parent);
+		if (!ks_pcie)
+			return;
+
+		val = ks_pcie_app_readl(ks_pcie, PID);
+		val &= RTL;
+		val >>= RTL_SHIFT;
+		if (val != AM6_PCI_PG1_RTL_VER)
+			return;
+
+		if (pcie_get_readrq(dev) > 128) {
+			dev_info(&dev->dev, "limiting MRRS to 128\n");
+			pcie_set_readrq(dev, 128);
+		}
+	}
 }
 DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, ks_pcie_quirk);
 
@@ -605,34 +744,6 @@
 	chained_irq_exit(chip, desc);
 }
 
-/**
- * ks_pcie_legacy_irq_handler() - Handle legacy interrupt
- * @desc: Pointer to irq descriptor
- *
- * Traverse through pending legacy interrupts and invoke handler for each. Also
- * takes care of interrupt controller level mask/ack operation.
- */
-static void ks_pcie_legacy_irq_handler(struct irq_desc *desc)
-{
-	unsigned int irq = irq_desc_get_irq(desc);
-	struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
-	struct dw_pcie *pci = ks_pcie->pci;
-	struct device *dev = pci->dev;
-	u32 irq_offset = irq - ks_pcie->legacy_host_irqs[0];
-	struct irq_chip *chip = irq_desc_get_chip(desc);
-
-	dev_dbg(dev, ": Handling legacy irq %d\n", irq);
-
-	/*
-	 * The chained irq handler installation would have replaced normal
-	 * interrupt driver handler so we need to take care of mask/unmask and
-	 * ack operation.
-	 */
-	chained_irq_enter(chip, desc);
-	ks_pcie_handle_legacy_irq(ks_pcie, irq_offset);
-	chained_irq_exit(chip, desc);
-}
-
 static int ks_pcie_config_msi_irq(struct keystone_pcie *ks_pcie)
 {
 	struct device *dev = ks_pcie->pci->dev;
@@ -687,25 +798,86 @@
 	return ret;
 }
 
+static int ks_pcie_am654_intx_map(struct irq_domain *domain, unsigned int irq,
+				  irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
+	irq_set_chip_data(irq, domain->host_data);
+
+	return 0;
+}
+
+static const struct irq_domain_ops ks_pcie_am654_irq_domain_ops = {
+	.map = ks_pcie_am654_intx_map,
+};
+
+static int ks_pcie_am654_config_legacy_irq(struct keystone_pcie *ks_pcie)
+{
+	struct device *dev = ks_pcie->pci->dev;
+	struct irq_domain *legacy_irq_domain;
+	struct device_node *np = ks_pcie->np;
+	struct device_node *intc_np;
+	int ret = 0;
+	int irq;
+	int i;
+
+	intc_np = of_get_child_by_name(np, "interrupt-controller");
+	if (!intc_np) {
+		dev_warn(dev, "legacy interrupt-controller node is absent\n");
+		return -EINVAL;
+	}
+
+	irq = irq_of_parse_and_map(intc_np, 0);
+	if (!irq)
+		return -EINVAL;
+
+	irq_set_chained_handler_and_data(irq, ks_pcie_am654_legacy_irq_handler, ks_pcie);
+	legacy_irq_domain = irq_domain_add_linear(intc_np, PCI_NUM_INTX,
+						  &ks_pcie_am654_irq_domain_ops, ks_pcie);
+	if (!legacy_irq_domain) {
+		dev_err(dev, "Failed to add irq domain for legacy irqs\n");
+		return -EINVAL;
+	}
+	ks_pcie->legacy_irq_domain = legacy_irq_domain;
+
+	for (i = 0; i < PCI_NUM_INTX; i++)
+		ks_pcie_app_writel(ks_pcie, IRQ_ENABLE_SET(i), INTx_EN);
+
+	return ret;
+}
+
 static int ks_pcie_config_legacy_irq(struct keystone_pcie *ks_pcie)
 {
 	struct device *dev = ks_pcie->pci->dev;
 	struct irq_domain *legacy_irq_domain;
 	struct device_node *np = ks_pcie->np;
+	struct irq_domain *parent_domain;
+	struct device_node *parent_node;
 	struct device_node *intc_np;
-	int irq_count, irq, ret = 0, i;
+	int irq_count, ret = 0;
 
-	intc_np = of_get_child_by_name(np, "legacy-interrupt-controller");
+	intc_np = of_get_child_by_name(np, "interrupt-controller");
 	if (!intc_np) {
-		/*
-		 * Since legacy interrupts are modeled as edge-interrupts in
-		 * AM6, keep it disabled for now.
-		 */
-		if (ks_pcie->is_am6)
-			return 0;
 		dev_warn(dev, "legacy-interrupt-controller node is absent\n");
 		return -EINVAL;
 	}
+	ks_pcie->legacy_intc_np = intc_np;
+
+	parent_node = of_irq_find_parent(intc_np);
+	if (!parent_node) {
+		dev_err(dev, "unable to obtain parent node\n");
+		ret = -ENXIO;
+		goto err;
+	}
+
+	parent_domain = irq_find_host(parent_node);
+	if (!parent_domain) {
+		dev_err(dev, "unable to obtain parent domain\n");
+		ret = -ENXIO;
+		goto err;
+	}
+
+	of_node_put(parent_node);
 
 	irq_count = of_irq_count(intc_np);
 	if (!irq_count) {
@@ -714,31 +886,13 @@
 		goto err;
 	}
 
-	for (i = 0; i < irq_count; i++) {
-		irq = irq_of_parse_and_map(intc_np, i);
-		if (!irq) {
-			ret = -EINVAL;
-			goto err;
-		}
-		ks_pcie->legacy_host_irqs[i] = irq;
-
-		irq_set_chained_handler_and_data(irq,
-						 ks_pcie_legacy_irq_handler,
-						 ks_pcie);
-	}
-
-	legacy_irq_domain =
-		irq_domain_add_linear(intc_np, PCI_NUM_INTX,
-				      &ks_pcie_legacy_irq_domain_ops, NULL);
+	legacy_irq_domain = irq_domain_add_hierarchy(parent_domain, 0, PCI_NUM_INTX, intc_np,
+						     &ks_pcie_legacy_irq_domain_ops, ks_pcie);
 	if (!legacy_irq_domain) {
 		dev_err(dev, "Failed to add irq domain for legacy irqs\n");
 		ret = -EINVAL;
 		goto err;
 	}
-	ks_pcie->legacy_irq_domain = legacy_irq_domain;
-
-	for (i = 0; i < PCI_NUM_INTX; i++)
-		ks_pcie_app_writel(ks_pcie, IRQ_ENABLE_SET(i), INTx_EN);
 
 err:
 	of_node_put(intc_np);
@@ -806,12 +960,17 @@
 	int ret;
 
 	pp->bridge->ops = &ks_pcie_ops;
-	if (!ks_pcie->is_am6)
-		pp->bridge->child_ops = &ks_child_pcie_ops;
 
-	ret = ks_pcie_config_legacy_irq(ks_pcie);
-	if (ret)
-		return ret;
+	if (!ks_pcie->is_am6) {
+		pp->bridge->child_ops = &ks_child_pcie_ops;
+		ret = ks_pcie_config_legacy_irq(ks_pcie);
+		if (ret)
+			return ret;
+	} else {
+		ret = ks_pcie_am654_config_legacy_irq(ks_pcie);
+		if (ret)
+			return ret;
+	}
 
 	ret = ks_pcie_config_msi_irq(ks_pcie);
 	if (ret)
@@ -1069,6 +1228,7 @@
 
 static const struct ks_pcie_of_data ks_pcie_rc_of_data = {
 	.host_ops = &ks_pcie_host_ops,
+	.mode = DW_PCIE_RC_TYPE,
 	.version = DW_PCIE_VER_365A,
 };
 
@@ -1219,7 +1379,16 @@
 		goto err_link;
 	}
 
+	/* Obtain reference(s) to the phy(s) */
+	for (i = 0; i < num_lanes; i++)
+		phy_pm_runtime_get_sync(ks_pcie->phy[i]);
+
 	ret = ks_pcie_enable_phy(ks_pcie);
+
+	/* Release reference(s) to the phy(s) */
+	for (i = 0; i < num_lanes; i++)
+		phy_pm_runtime_put_sync(ks_pcie->phy[i]);
+
 	if (ret) {
 		dev_err(dev, "failed to enable phy\n");
 		goto err_link;
diff -Naur --no-dereference a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c
--- a/drivers/pci/controller/pci-tegra.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pci/controller/pci-tegra.c	2024-01-28 14:01:31.252353813 -0500
@@ -1330,12 +1330,9 @@
 	if (!name)
 		return ERR_PTR(-ENOMEM);
 
-	phy = devm_of_phy_get(dev, np, name);
+	phy = devm_of_phy_optional_get(dev, np, name);
 	kfree(name);
 
-	if (PTR_ERR(phy) == -ENODEV)
-		phy = NULL;
-
 	return phy;
 }
 
diff -Naur --no-dereference a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
--- a/drivers/pci/pcie/aspm.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pci/pcie/aspm.c	2024-01-28 14:01:31.252353813 -0500
@@ -302,7 +302,8 @@
 	pcie_capability_clear_and_set_word(parent, PCI_EXP_LNKCTL,
 					   PCI_EXP_LNKCTL_CCC, ccc);
 
-	if (pcie_retrain_link(link)) {
+	/* Retrain link and then wait for the link to become active */
+	if (pcie_retrain_link(link) || !pcie_wait_for_link(parent, true)) {
 
 		/* Training failed. Restore common clock configurations */
 		pci_err(parent, "ASPM: Could not configure common clock\n");
diff -Naur --no-dereference a/drivers/phy/cadence/cdns-dphy-rx.c b/drivers/phy/cadence/cdns-dphy-rx.c
--- a/drivers/phy/cadence/cdns-dphy-rx.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/phy/cadence/cdns-dphy-rx.c	2024-01-28 14:01:31.252353813 -0500
@@ -11,10 +11,13 @@
 #include <linux/phy/phy.h>
 #include <linux/phy/phy-mipi-dphy.h>
 #include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/sys_soc.h>
 
 #define DPHY_PMA_CMN(reg)		(reg)
 #define DPHY_PCS(reg)			(0xb00 + (reg))
 #define DPHY_ISO(reg)			(0xc00 + (reg))
+#define DPHY_WRAP(reg)			(0x1000 + (reg))
 
 #define DPHY_CMN_SSM			DPHY_PMA_CMN(0x20)
 #define DPHY_CMN_RX_MODE_EN		BIT(10)
@@ -33,6 +36,9 @@
 #define DPHY_POWER_ISLAND_EN_CLK	DPHY_PCS(0xc)
 #define DPHY_POWER_ISLAND_EN_CLK_VAL	0xaa
 
+#define DPHY_LANE			DPHY_WRAP(0x0)
+#define DPHY_LANE_RESET_CMN_EN		BIT(23)
+
 #define DPHY_ISO_CL_CTRL_L		DPHY_ISO(0x10)
 #define DPHY_ISO_DL_CTRL_L0		DPHY_ISO(0x14)
 #define DPHY_ISO_DL_CTRL_L1		DPHY_ISO(0x20)
@@ -57,6 +63,10 @@
 	unsigned int max_rate;
 };
 
+struct cdns_dphy_soc_data {
+	bool has_hw_cmn_rstb;
+};
+
 /* Order of bands is important since the index is the band number. */
 static const struct cdns_dphy_rx_band bands[] = {
 	{ 80, 100 }, { 100, 120 }, { 120, 160 }, { 160, 200 }, { 200, 240 },
@@ -142,13 +152,36 @@
 	return 0;
 }
 
+static struct cdns_dphy_soc_data j721e_soc_data = {
+	.has_hw_cmn_rstb = true,
+};
+
+static const struct soc_device_attribute cdns_dphy_socinfo[] = {
+	{
+		.family = "J721E",
+		.revision = "SR1.0",
+		.data = &j721e_soc_data,
+	},
+	{/* sentinel */}
+};
+
 static int cdns_dphy_rx_configure(struct phy *phy,
 				  union phy_configure_opts *opts)
 {
 	struct cdns_dphy_rx *dphy = phy_get_drvdata(phy);
 	unsigned int reg, lanes = opts->mipi_dphy.lanes;
+	const struct cdns_dphy_soc_data *soc_data = NULL;
+	const struct soc_device_attribute *soc;
 	int band_ctrl, ret;
 
+	soc = soc_device_match(cdns_dphy_socinfo);
+	if (soc && soc->data)
+		soc_data = soc->data;
+	if (!soc || (soc_data && !soc_data->has_hw_cmn_rstb)) {
+		reg = DPHY_LANE_RESET_CMN_EN;
+		writel(reg, dphy->regs + DPHY_LANE);
+	}
+
 	/* Data lanes. Minimum one lane is mandatory. */
 	if (lanes < DPHY_LANES_MIN || lanes > DPHY_LANES_MAX)
 		return -EINVAL;
@@ -232,6 +265,12 @@
 		return PTR_ERR(provider);
 	}
 
+	/*
+	 * PHY framework handles calls to pm_runtime_(get|put) when
+	 * phy_power_(on|off) hooks are called
+	 */
+	devm_pm_runtime_enable(dev);
+
 	return 0;
 }
 
diff -Naur --no-dereference a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c
--- a/drivers/phy/cadence/phy-cadence-sierra.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/phy/cadence/phy-cadence-sierra.c	2024-01-28 14:01:31.252353813 -0500
@@ -24,7 +24,7 @@
 #include <dt-bindings/phy/phy-cadence.h>
 
 #define NUM_SSC_MODE		3
-#define NUM_PHY_TYPE		4
+#define NUM_PHY_TYPE		5
 
 /* PHY register offsets */
 #define SIERRA_COMMON_CDB_OFFSET			0x0
@@ -46,7 +46,9 @@
 #define SIERRA_CMN_REFRCV_PREG				0x98
 #define SIERRA_CMN_REFRCV1_PREG				0xB8
 #define SIERRA_CMN_PLLLC1_GEN_PREG			0xC2
+#define SIERRA_CMN_PLLLC1_FBDIV_INT_PREG		0xC3
 #define SIERRA_CMN_PLLLC1_LF_COEFF_MODE0_PREG		0xCA
+#define SIERRA_CMN_PLLLC1_CLK0_PREG			0xCE
 #define SIERRA_CMN_PLLLC1_BWCAL_MODE0_PREG		0xD0
 #define SIERRA_CMN_PLLLC1_SS_TIME_STEPSIZE_MODE_PREG	0xE2
 
@@ -74,6 +76,7 @@
 #define SIERRA_PSC_RX_A1_PREG				0x031
 #define SIERRA_PSC_RX_A2_PREG				0x032
 #define SIERRA_PSC_RX_A3_PREG				0x033
+#define SIERRA_PLLCTRL_FBDIV_MODE01_PREG		0x039
 #define SIERRA_PLLCTRL_SUBRATE_PREG			0x03A
 #define SIERRA_PLLCTRL_GEN_A_PREG			0x03B
 #define SIERRA_PLLCTRL_GEN_D_PREG			0x03E
@@ -298,6 +301,7 @@
 	TYPE_NONE,
 	TYPE_PCIE,
 	TYPE_USB,
+	TYPE_SGMII,
 	TYPE_QSGMII
 };
 
@@ -936,6 +940,9 @@
 	case PHY_TYPE_USB3:
 		inst->phy_type = TYPE_USB;
 		break;
+	case PHY_TYPE_SGMII:
+		inst->phy_type = TYPE_SGMII;
+		break;
 	case PHY_TYPE_QSGMII:
 		inst->phy_type = TYPE_QSGMII;
 		break;
@@ -1339,7 +1346,7 @@
 			}
 		}
 
-		if (phy_t1 == TYPE_QSGMII)
+		if (phy_t1 == TYPE_SGMII || phy_t1 == TYPE_QSGMII)
 			reset_control_deassert(sp->phys[node].lnk_rst);
 	}
 
@@ -1537,6 +1544,71 @@
 	return 0;
 }
 
+/* SGMII PHY PMA lane configuration */
+static struct cdns_reg_pairs sgmii_phy_pma_ln_regs[] = {
+	{0x9010, SIERRA_PHY_PMA_XCVR_CTRL}
+};
+
+static struct cdns_sierra_vals sgmii_phy_pma_ln_vals = {
+	.reg_pairs = sgmii_phy_pma_ln_regs,
+	.num_regs = ARRAY_SIZE(sgmii_phy_pma_ln_regs),
+};
+
+/* SGMII refclk 100MHz, no ssc, opt3 and GE1 links using PLL LC1 */
+static const struct cdns_reg_pairs sgmii_100_no_ssc_plllc1_opt3_cmn_regs[] = {
+	{0x002D, SIERRA_CMN_PLLLC1_FBDIV_INT_PREG},
+	{0x2085, SIERRA_CMN_PLLLC1_LF_COEFF_MODE0_PREG},
+	{0x1005, SIERRA_CMN_PLLLC1_CLK0_PREG},
+	{0x0000, SIERRA_CMN_PLLLC1_BWCAL_MODE0_PREG},
+	{0x0800, SIERRA_CMN_PLLLC1_SS_TIME_STEPSIZE_MODE_PREG}
+};
+
+static const struct cdns_reg_pairs sgmii_100_no_ssc_plllc1_opt3_ln_regs[] = {
+	{0x688E, SIERRA_DET_STANDEC_D_PREG},
+	{0x0004, SIERRA_PSC_LN_IDLE_PREG},
+	{0x0FFE, SIERRA_PSC_RX_A0_PREG},
+	{0x0106, SIERRA_PLLCTRL_FBDIV_MODE01_PREG},
+	{0x0013, SIERRA_PLLCTRL_SUBRATE_PREG},
+	{0x0003, SIERRA_PLLCTRL_GEN_A_PREG},
+	{0x0106, SIERRA_PLLCTRL_GEN_D_PREG},
+	{0x5231, SIERRA_PLLCTRL_CPGAIN_MODE_PREG },
+	{0x0000, SIERRA_DRVCTRL_ATTEN_PREG},
+	{0x9702, SIERRA_DRVCTRL_BOOST_PREG},
+	{0x0051, SIERRA_RX_CREQ_FLTR_A_MODE0_PREG},
+	{0x3C0E, SIERRA_CREQ_CCLKDET_MODE01_PREG},
+	{0x3220, SIERRA_CREQ_FSMCLK_SEL_PREG},
+	{0x0000, SIERRA_CREQ_EQ_CTRL_PREG},
+	{0x0002, SIERRA_DEQ_PHALIGN_CTRL},
+	{0x0186, SIERRA_DEQ_GLUT0},
+	{0x0186, SIERRA_DEQ_GLUT1},
+	{0x0186, SIERRA_DEQ_GLUT2},
+	{0x0186, SIERRA_DEQ_GLUT3},
+	{0x0186, SIERRA_DEQ_GLUT4},
+	{0x0861, SIERRA_DEQ_ALUT0},
+	{0x07E0, SIERRA_DEQ_ALUT1},
+	{0x079E, SIERRA_DEQ_ALUT2},
+	{0x071D, SIERRA_DEQ_ALUT3},
+	{0x03F5, SIERRA_DEQ_DFETAP_CTRL_PREG},
+	{0x0C01, SIERRA_DEQ_TAU_CTRL1_FAST_MAINT_PREG},
+	{0x3C40, SIERRA_DEQ_TAU_CTRL1_SLOW_MAINT_PREG},
+	{0x1C04, SIERRA_DEQ_TAU_CTRL2_PREG},
+	{0x0033, SIERRA_DEQ_PICTRL_PREG},
+	{0x0000, SIERRA_CPI_OUTBUF_RATESEL_PREG},
+	{0x0B6D, SIERRA_CPI_RESBIAS_BIN_PREG},
+	{0x0102, SIERRA_RXBUFFER_CTLECTRL_PREG},
+	{0x0002, SIERRA_RXBUFFER_RCDFECTRL_PREG}
+};
+
+static struct cdns_sierra_vals sgmii_100_no_ssc_plllc1_opt3_cmn_vals = {
+	.reg_pairs = sgmii_100_no_ssc_plllc1_opt3_cmn_regs,
+	.num_regs = ARRAY_SIZE(sgmii_100_no_ssc_plllc1_opt3_cmn_regs),
+};
+
+static struct cdns_sierra_vals sgmii_100_no_ssc_plllc1_opt3_ln_vals = {
+	.reg_pairs = sgmii_100_no_ssc_plllc1_opt3_ln_regs,
+	.num_regs = ARRAY_SIZE(sgmii_100_no_ssc_plllc1_opt3_ln_regs),
+};
+
 /* QSGMII PHY PMA lane configuration */
 static struct cdns_reg_pairs qsgmii_phy_pma_ln_regs[] = {
 	{0x9010, SIERRA_PHY_PMA_XCVR_CTRL}
@@ -2363,6 +2435,11 @@
 				[EXTERNAL_SSC] = &pcie_phy_pcs_cmn_vals,
 				[INTERNAL_SSC] = &pcie_phy_pcs_cmn_vals,
 			},
+			[TYPE_SGMII] = {
+				[NO_SSC] = &pcie_phy_pcs_cmn_vals,
+				[EXTERNAL_SSC] = &pcie_phy_pcs_cmn_vals,
+				[INTERNAL_SSC] = &pcie_phy_pcs_cmn_vals,
+			},
 			[TYPE_QSGMII] = {
 				[NO_SSC] = &pcie_phy_pcs_cmn_vals,
 				[EXTERNAL_SSC] = &pcie_phy_pcs_cmn_vals,
@@ -2377,6 +2454,11 @@
 				[EXTERNAL_SSC] = &pcie_100_ext_ssc_cmn_vals,
 				[INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
 			},
+			[TYPE_SGMII] = {
+				[NO_SSC] = &pcie_100_no_ssc_plllc_cmn_vals,
+				[EXTERNAL_SSC] = &pcie_100_ext_ssc_plllc_cmn_vals,
+				[INTERNAL_SSC] = &pcie_100_int_ssc_plllc_cmn_vals,
+			},
 			[TYPE_QSGMII] = {
 				[NO_SSC] = &pcie_100_no_ssc_plllc_cmn_vals,
 				[EXTERNAL_SSC] = &pcie_100_ext_ssc_plllc_cmn_vals,
@@ -2388,6 +2470,13 @@
 				[EXTERNAL_SSC] = &usb_100_ext_ssc_cmn_vals,
 			},
 		},
+		[TYPE_SGMII] = {
+			[TYPE_PCIE] = {
+				[NO_SSC] = &sgmii_100_no_ssc_plllc1_opt3_cmn_vals,
+				[EXTERNAL_SSC] = &sgmii_100_no_ssc_plllc1_opt3_cmn_vals,
+				[INTERNAL_SSC] = &sgmii_100_no_ssc_plllc1_opt3_cmn_vals,
+			},
+		},
 		[TYPE_QSGMII] = {
 			[TYPE_PCIE] = {
 				[NO_SSC] = &qsgmii_100_no_ssc_plllc1_cmn_vals,
@@ -2414,6 +2503,13 @@
 				[EXTERNAL_SSC] = &usb_100_ext_ssc_ln_vals,
 			},
 		},
+		[TYPE_SGMII] = {
+			[TYPE_PCIE] = {
+				[NO_SSC] = &sgmii_100_no_ssc_plllc1_opt3_ln_vals,
+				[EXTERNAL_SSC] = &sgmii_100_no_ssc_plllc1_opt3_ln_vals,
+				[INTERNAL_SSC] = &sgmii_100_no_ssc_plllc1_opt3_ln_vals,
+			},
+		},
 		[TYPE_QSGMII] = {
 			[TYPE_PCIE] = {
 				[NO_SSC] = &qsgmii_100_no_ssc_plllc1_ln_vals,
@@ -2435,6 +2531,11 @@
 				[EXTERNAL_SSC] = &pcie_phy_pcs_cmn_vals,
 				[INTERNAL_SSC] = &pcie_phy_pcs_cmn_vals,
 			},
+			[TYPE_SGMII] = {
+				[NO_SSC] = &pcie_phy_pcs_cmn_vals,
+				[EXTERNAL_SSC] = &pcie_phy_pcs_cmn_vals,
+				[INTERNAL_SSC] = &pcie_phy_pcs_cmn_vals,
+			},
 			[TYPE_QSGMII] = {
 				[NO_SSC] = &pcie_phy_pcs_cmn_vals,
 				[EXTERNAL_SSC] = &pcie_phy_pcs_cmn_vals,
@@ -2443,6 +2544,13 @@
 		},
 	},
 	.phy_pma_ln_vals = {
+		[TYPE_SGMII] = {
+			[TYPE_PCIE] = {
+				[NO_SSC] = &sgmii_phy_pma_ln_vals,
+				[EXTERNAL_SSC] = &sgmii_phy_pma_ln_vals,
+				[INTERNAL_SSC] = &sgmii_phy_pma_ln_vals,
+			},
+		},
 		[TYPE_QSGMII] = {
 			[TYPE_PCIE] = {
 				[NO_SSC] = &qsgmii_phy_pma_ln_vals,
@@ -2458,6 +2566,11 @@
 				[EXTERNAL_SSC] = &pcie_100_ext_ssc_cmn_vals,
 				[INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
 			},
+			[TYPE_SGMII] = {
+				[NO_SSC] = &pcie_100_no_ssc_plllc_cmn_vals,
+				[EXTERNAL_SSC] = &pcie_100_ext_ssc_plllc_cmn_vals,
+				[INTERNAL_SSC] = &pcie_100_int_ssc_plllc_cmn_vals,
+			},
 			[TYPE_QSGMII] = {
 				[NO_SSC] = &pcie_100_no_ssc_plllc_cmn_vals,
 				[EXTERNAL_SSC] = &pcie_100_ext_ssc_plllc_cmn_vals,
@@ -2469,6 +2582,13 @@
 				[EXTERNAL_SSC] = &usb_100_ext_ssc_cmn_vals,
 			},
 		},
+		[TYPE_SGMII] = {
+			[TYPE_PCIE] = {
+				[NO_SSC] = &sgmii_100_no_ssc_plllc1_opt3_cmn_vals,
+				[EXTERNAL_SSC] = &sgmii_100_no_ssc_plllc1_opt3_cmn_vals,
+				[INTERNAL_SSC] = &sgmii_100_no_ssc_plllc1_opt3_cmn_vals,
+			},
+		},
 		[TYPE_QSGMII] = {
 			[TYPE_PCIE] = {
 				[NO_SSC] = &qsgmii_100_no_ssc_plllc1_cmn_vals,
@@ -2484,6 +2604,11 @@
 				[EXTERNAL_SSC] = &pcie_100_ext_ssc_ln_vals,
 				[INTERNAL_SSC] = &pcie_100_int_ssc_ln_vals,
 			},
+			[TYPE_SGMII] = {
+				[NO_SSC] = &ti_ml_pcie_100_no_ssc_ln_vals,
+				[EXTERNAL_SSC] = &ti_ml_pcie_100_ext_ssc_ln_vals,
+				[INTERNAL_SSC] = &ti_ml_pcie_100_int_ssc_ln_vals,
+			},
 			[TYPE_QSGMII] = {
 				[NO_SSC] = &ti_ml_pcie_100_no_ssc_ln_vals,
 				[EXTERNAL_SSC] = &ti_ml_pcie_100_ext_ssc_ln_vals,
@@ -2495,6 +2620,13 @@
 				[EXTERNAL_SSC] = &usb_100_ext_ssc_ln_vals,
 			},
 		},
+		[TYPE_SGMII] = {
+			[TYPE_PCIE] = {
+				[NO_SSC] = &sgmii_100_no_ssc_plllc1_opt3_ln_vals,
+				[EXTERNAL_SSC] = &sgmii_100_no_ssc_plllc1_opt3_ln_vals,
+				[INTERNAL_SSC] = &sgmii_100_no_ssc_plllc1_opt3_ln_vals,
+			},
+		},
 		[TYPE_QSGMII] = {
 			[TYPE_PCIE] = {
 				[NO_SSC] = &qsgmii_100_no_ssc_plllc1_ln_vals,
diff -Naur --no-dereference a/drivers/phy/cadence/phy-cadence-torrent.c b/drivers/phy/cadence/phy-cadence-torrent.c
--- a/drivers/phy/cadence/phy-cadence-torrent.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/phy/cadence/phy-cadence-torrent.c	2024-01-28 14:01:31.252353813 -0500
@@ -27,17 +27,17 @@
 #define REF_CLK_19_2MHZ		19200000
 #define REF_CLK_25MHZ		25000000
 #define REF_CLK_100MHZ		100000000
+#define REF_CLK_156_25MHZ	156250000
 
 #define MAX_NUM_LANES		4
 #define DEFAULT_MAX_BIT_RATE	8100 /* in Mbps */
 
-#define NUM_SSC_MODE		3
-#define NUM_REF_CLK		3
-#define NUM_PHY_TYPE		6
-
 #define POLL_TIMEOUT_US		5000
 #define PLL_LOCK_TIMEOUT	100000
 
+#define DP_PLL0			BIT(0)
+#define DP_PLL1			BIT(1)
+
 #define TORRENT_COMMON_CDB_OFFSET	0x0
 
 #define TORRENT_TX_LANE_CDB_OFFSET(ln, block_offset, reg_offset)	\
@@ -66,16 +66,11 @@
  */
 #define PHY_AUX_CTRL			0x04
 #define PHY_RESET			0x20
-#define PMA_TX_ELEC_IDLE_MASK		0xF0U
 #define PMA_TX_ELEC_IDLE_SHIFT		4
-#define PHY_L00_RESET_N_MASK		0x01U
 #define PHY_PMA_XCVR_PLLCLK_EN		0x24
 #define PHY_PMA_XCVR_PLLCLK_EN_ACK	0x28
 #define PHY_PMA_XCVR_POWER_STATE_REQ	0x2c
-#define PHY_POWER_STATE_LN_0	0x0000
-#define PHY_POWER_STATE_LN_1	0x0008
-#define PHY_POWER_STATE_LN_2	0x0010
-#define PHY_POWER_STATE_LN_3	0x0018
+#define PHY_POWER_STATE_LN(ln)		((ln) * 8)
 #define PMA_XCVR_POWER_STATE_REQ_LN_MASK	0x3FU
 #define PHY_PMA_XCVR_POWER_STATE_ACK	0x30
 #define PHY_PMA_CMN_READY		0x34
@@ -108,6 +103,7 @@
 #define CMN_PLL0_HIGH_THR_M0		0x0093U
 #define CMN_PLL0_DSM_DIAG_M0		0x0094U
 #define CMN_PLL0_DSM_FBH_OVRD_M0	0x0095U
+#define CMN_PLL0_DSM_FBL_OVRD_M0	0x0096U
 #define CMN_PLL0_SS_CTRL1_M0		0x0098U
 #define CMN_PLL0_SS_CTRL2_M0            0x0099U
 #define CMN_PLL0_SS_CTRL3_M0            0x009AU
@@ -198,6 +194,10 @@
 #define RX_PSC_A2			0x0002U
 #define RX_PSC_A3			0x0003U
 #define RX_PSC_CAL			0x0006U
+#define RX_SDCAL0_INIT_TMR		0x0044U
+#define RX_SDCAL0_ITER_TMR		0x0045U
+#define RX_SDCAL1_INIT_TMR		0x004CU
+#define RX_SDCAL1_ITER_TMR		0x004DU
 #define RX_CDRLF_CNFG			0x0080U
 #define RX_CDRLF_CNFG3			0x0082U
 #define RX_SIGDET_HL_FILT_TMR		0x0090U
@@ -296,20 +296,49 @@
 	TYPE_SGMII,
 	TYPE_QSGMII,
 	TYPE_USB,
+	TYPE_USXGMII,
 };
 
 enum cdns_torrent_ref_clk {
 	CLK_19_2_MHZ,
 	CLK_25_MHZ,
-	CLK_100_MHZ
+	CLK_100_MHZ,
+	CLK_156_25_MHZ,
+	CLK_ANY,
 };
 
 enum cdns_torrent_ssc_mode {
 	NO_SSC,
 	EXTERNAL_SSC,
-	INTERNAL_SSC
+	INTERNAL_SSC,
+	ANY_SSC,
 };
 
+/* Unique key id for vals table entry
+ * REFCLK0_RATE | REFCLK1_RATE | LINK0_TYPE | LINK1_TYPE | SSC_TYPE
+ */
+#define REFCLK0_SHIFT	12
+#define REFCLK0_MASK	GENMASK(14, 12)
+#define REFCLK1_SHIFT	9
+#define REFCLK1_MASK	GENMASK(11, 9)
+#define LINK0_SHIFT	6
+#define LINK0_MASK	GENMASK(8, 6)
+#define LINK1_SHIFT	3
+#define LINK1_MASK	GENMASK(5, 3)
+#define SSC_SHIFT	0
+#define SSC_MASK	GENMASK(2, 0)
+
+#define CDNS_TORRENT_KEY(refclk0, refclk1, link0, link1, ssc) \
+			((((refclk0) << REFCLK0_SHIFT) & REFCLK0_MASK) | \
+			(((refclk1) << REFCLK1_SHIFT) & REFCLK1_MASK) | \
+			(((link0) << LINK0_SHIFT) & LINK0_MASK) | \
+			(((link1) << LINK1_SHIFT) & LINK1_MASK) | \
+			(((ssc) << SSC_SHIFT) & SSC_MASK))
+
+#define CDNS_TORRENT_KEY_ANYCLK(link0, link1) \
+			CDNS_TORRENT_KEY(CLK_ANY, CLK_ANY, \
+					 (link0), (link1), ANY_SSC)
+
 struct cdns_torrent_inst {
 	struct phy *phy;
 	u32 mlane;
@@ -323,11 +352,14 @@
 	void __iomem *base;	/* DPTX registers base */
 	void __iomem *sd_base; /* SD0801 registers base */
 	u32 max_bit_rate; /* Maximum link bit rate to use (in Mbps) */
+	u32 dp_pll;
 	struct reset_control *phy_rst;
 	struct reset_control *apb_rst;
 	struct device *dev;
 	struct clk *clk;
+	struct clk *clk1;
 	enum cdns_torrent_ref_clk ref_clk_rate;
+	enum cdns_torrent_ref_clk ref_clk1_rate;
 	struct cdns_torrent_inst phys[MAX_NUM_LANES];
 	int nsubnodes;
 	const struct cdns_torrent_data *init_data;
@@ -395,21 +427,26 @@
 	u32 num_regs;
 };
 
+struct cdns_torrent_vals_entry {
+	u32 key;
+	struct cdns_torrent_vals *vals;
+};
+
+struct cdns_torrent_vals_table {
+	struct cdns_torrent_vals_entry *entries;
+	u32 num_entries;
+};
+
 struct cdns_torrent_data {
 	u8 block_offset_shift;
 	u8 reg_offset_shift;
-	struct cdns_torrent_vals *link_cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
-					       [NUM_SSC_MODE];
-	struct cdns_torrent_vals *xcvr_diag_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
-						[NUM_SSC_MODE];
-	struct cdns_torrent_vals *pcs_cmn_vals[NUM_PHY_TYPE][NUM_PHY_TYPE]
-					      [NUM_SSC_MODE];
-	struct cdns_torrent_vals *cmn_vals[NUM_REF_CLK][NUM_PHY_TYPE]
-					  [NUM_PHY_TYPE][NUM_SSC_MODE];
-	struct cdns_torrent_vals *tx_ln_vals[NUM_REF_CLK][NUM_PHY_TYPE]
-					    [NUM_PHY_TYPE][NUM_SSC_MODE];
-	struct cdns_torrent_vals *rx_ln_vals[NUM_REF_CLK][NUM_PHY_TYPE]
-					    [NUM_PHY_TYPE][NUM_SSC_MODE];
+	struct cdns_torrent_vals_table link_cmn_vals_tbl;
+	struct cdns_torrent_vals_table xcvr_diag_vals_tbl;
+	struct cdns_torrent_vals_table pcs_cmn_vals_tbl;
+	struct cdns_torrent_vals_table phy_pma_cmn_vals_tbl;
+	struct cdns_torrent_vals_table cmn_vals_tbl;
+	struct cdns_torrent_vals_table tx_ln_vals_tbl;
+	struct cdns_torrent_vals_table rx_ln_vals_tbl;
 };
 
 struct cdns_regmap_cdb_context {
@@ -418,6 +455,24 @@
 	u8 reg_offset_shift;
 };
 
+static struct cdns_torrent_vals *cdns_torrent_get_tbl_vals(const struct cdns_torrent_vals_table *tbl,
+							   enum cdns_torrent_ref_clk refclk0,
+							   enum cdns_torrent_ref_clk refclk1,
+							   enum cdns_torrent_phy_type link0,
+							   enum cdns_torrent_phy_type link1,
+							   enum cdns_torrent_ssc_mode ssc)
+{
+	int i;
+	u32 key = CDNS_TORRENT_KEY(refclk0, refclk1, link0, link1, ssc);
+
+	for (i = 0; i < tbl->num_entries; i++) {
+		if (tbl->entries[i].key == key)
+			return tbl->entries[i].vals;
+	}
+
+	return NULL;
+}
+
 static int cdns_regmap_write(void *context, unsigned int reg, unsigned int val)
 {
 	struct cdns_regmap_cdb_context *ctx = context;
@@ -645,6 +700,8 @@
 		return "QSGMII";
 	case TYPE_USB:
 		return "USB";
+	case TYPE_USXGMII:
+		return "USXGMII";
 	default:
 		return "None";
 	}
@@ -905,88 +962,129 @@
 	/* Setting VCO for 10.8GHz */
 	case 2700:
 	case 5400:
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0028);
-		cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_FBH_OVRD_M0, 0x0022);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBH_OVRD_M0, 0x0022);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBL_OVRD_M0, 0x000C);
+		if (cdns_phy->dp_pll & DP_PLL0)
+			cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_FBH_OVRD_M0, 0x0022);
+
+		if (cdns_phy->dp_pll & DP_PLL1) {
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0028);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBH_OVRD_M0, 0x0022);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_FBL_OVRD_M0, 0x000C);
+		}
 		break;
 	/* Setting VCO for 9.72GHz */
 	case 1620:
 	case 2430:
 	case 3240:
-		cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
-		cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0061);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0061);
-		cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x3333);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x3333);
-		cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
-		cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0042);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0042);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+		if (cdns_phy->dp_pll & DP_PLL0) {
+			cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
+			cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0061);
+			cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x3333);
+			cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+			cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0042);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+		}
+		if (cdns_phy->dp_pll & DP_PLL1) {
+			cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0061);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x3333);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0042);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+		}
 		break;
 	/* Setting VCO for 8.64GHz */
 	case 2160:
 	case 4320:
-		cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
-		cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0056);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0056);
-		cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x6666);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x6666);
-		cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
-		cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x003A);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x003A);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+		if (cdns_phy->dp_pll & DP_PLL0) {
+			cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
+			cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0056);
+			cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVL_M0, 0x6666);
+			cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+			cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x003A);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+		}
+		if (cdns_phy->dp_pll & DP_PLL1) {
+			cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0056);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVL_M0, 0x6666);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x003A);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+		}
 		break;
 	/* Setting VCO for 8.1GHz */
 	case 8100:
-		cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
-		cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0051);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0051);
-		cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
-		cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0036);
-		cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0036);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
-		cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+		if (cdns_phy->dp_pll & DP_PLL0) {
+			cdns_torrent_phy_write(regmap, CMN_PLL0_DSM_DIAG_M0, 0x0004);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_PADJ_M0, 0x0509);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CP_IADJ_M0, 0x0F00);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_FILT_PADJ_M0, 0x0F08);
+			cdns_torrent_phy_write(regmap, CMN_PLL0_INTDIV_M0, 0x0051);
+			cdns_torrent_phy_write(regmap, CMN_PLL0_FRACDIVH_M0, 0x0002);
+			cdns_torrent_phy_write(regmap, CMN_PLL0_HIGH_THR_M0, 0x0036);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL0_CTRL_M0, 0x0002);
+		}
+		if (cdns_phy->dp_pll & DP_PLL1) {
+			cdns_torrent_phy_write(regmap, CMN_PLL1_DSM_DIAG_M0, 0x0004);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_PADJ_M0, 0x0509);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CP_IADJ_M0, 0x0F00);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_FILT_PADJ_M0, 0x0F08);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_INTDIV_M0, 0x0051);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_FRACDIVH_M0, 0x0002);
+			cdns_torrent_phy_write(regmap, CMN_PLL1_HIGH_THR_M0, 0x0036);
+			cdns_torrent_phy_write(regmap, CMN_PDIAG_PLL1_CTRL_M0, 0x0002);
+		}
 		break;
 	}
 }
 
+/* Set PLL used for DP configuration */
+static int cdns_torrent_dp_get_pll(struct cdns_torrent_phy *cdns_phy,
+				   enum cdns_torrent_phy_type phy_t2)
+{
+	switch (phy_t2) {
+	case TYPE_PCIE:
+	case TYPE_USB:
+		cdns_phy->dp_pll = DP_PLL1;
+		break;
+	case TYPE_SGMII:
+	case TYPE_QSGMII:
+		cdns_phy->dp_pll = DP_PLL0;
+		break;
+	case TYPE_NONE:
+		cdns_phy->dp_pll = DP_PLL0 | DP_PLL1;
+		break;
+	default:
+		dev_err(cdns_phy->dev, "Unsupported PHY configuration\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 /*
  * Enable or disable PLL for selected lanes.
  */
 static int cdns_torrent_dp_set_pll_en(struct cdns_torrent_phy *cdns_phy,
+				      struct cdns_torrent_inst *inst,
 				      struct phy_configure_opts_dp *dp,
 				      bool enable)
 {
-	u32 rd_val;
-	u32 ret;
 	struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
+	u32 rd_val, pll_ack_val;
+	int ret;
 
 	/*
 	 * Used to determine, which bits to check for or enable in
@@ -996,28 +1094,18 @@
 	/* Used to enable or disable lanes. */
 	u32 pll_val;
 
-	/* Select values of registers and mask, depending on enabled lane
-	 * count.
-	 */
-	switch (dp->lanes) {
-	/* lane 0 */
-	case (1):
-		pll_bits = 0x00000001;
-		break;
-	/* lanes 0-1 */
-	case (2):
-		pll_bits = 0x00000003;
-		break;
-	/* lanes 0-3, all */
-	default:
-		pll_bits = 0x0000000F;
-		break;
-	}
+	/* Select values of registers and mask, depending on enabled lane count. */
+	pll_val = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN);
 
-	if (enable)
-		pll_val = pll_bits;
-	else
-		pll_val = 0x00000000;
+	if (enable) {
+		pll_bits = ((1 << dp->lanes) - 1);
+		pll_val |= pll_bits;
+		pll_ack_val = pll_bits;
+	} else {
+		pll_bits = ((1 << inst->num_lanes) - 1);
+		pll_val &= (~pll_bits);
+		pll_ack_val = 0;
+	}
 
 	cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, pll_val);
 
@@ -1025,22 +1113,23 @@
 	ret = regmap_read_poll_timeout(regmap,
 				       PHY_PMA_XCVR_PLLCLK_EN_ACK,
 				       rd_val,
-				       (rd_val & pll_bits) == pll_val,
+				       (rd_val & pll_bits) == pll_ack_val,
 				       0, POLL_TIMEOUT_US);
 	ndelay(100);
 	return ret;
 }
 
 static int cdns_torrent_dp_set_power_state(struct cdns_torrent_phy *cdns_phy,
+					   struct cdns_torrent_inst *inst,
 					   u32 num_lanes,
 					   enum phy_powerstate powerstate)
 {
 	/* Register value for power state for a single byte. */
-	u32 value_part;
-	u32 value;
-	u32 mask;
+	u32 value_part, i;
+	u32 value = 0;
+	u32 mask = 0;
 	u32 read_val;
-	u32 ret;
+	int ret;
 	struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
 
 	switch (powerstate) {
@@ -1056,29 +1145,11 @@
 		break;
 	}
 
-	/* Select values of registers and mask, depending on enabled
-	 * lane count.
-	 */
-	switch (num_lanes) {
-	/* lane 0 */
-	case (1):
-		value = value_part;
-		mask = 0x0000003FU;
-		break;
-	/* lanes 0-1 */
-	case (2):
-		value = (value_part
-			 | (value_part << 8));
-		mask = 0x00003F3FU;
-		break;
-	/* lanes 0-3, all */
-	default:
-		value = (value_part
-			 | (value_part << 8)
-			 | (value_part << 16)
-			 | (value_part << 24));
-		mask = 0x3F3F3F3FU;
-		break;
+	/* Select values of registers and mask, depending on enabled lane count. */
+
+	for (i = 0; i < num_lanes; i++) {
+		value |= (value_part << PHY_POWER_STATE_LN(i));
+		mask |= (PMA_XCVR_POWER_STATE_REQ_LN_MASK << PHY_POWER_STATE_LN(i));
 	}
 
 	/* Set power state A<n>. */
@@ -1093,7 +1164,8 @@
 	return ret;
 }
 
-static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy, u32 num_lanes)
+static int cdns_torrent_dp_run(struct cdns_torrent_phy *cdns_phy,
+			       struct cdns_torrent_inst *inst, u32 num_lanes)
 {
 	unsigned int read_val;
 	int ret;
@@ -1114,12 +1186,12 @@
 
 	ndelay(100);
 
-	ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
+	ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, num_lanes,
 					      POWERSTATE_A2);
 	if (ret)
 		return ret;
 
-	ret = cdns_torrent_dp_set_power_state(cdns_phy, num_lanes,
+	ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, num_lanes,
 					      POWERSTATE_A0);
 
 	return ret;
@@ -1143,6 +1215,7 @@
 }
 
 static void cdns_torrent_dp_pma_cmn_rate(struct cdns_torrent_phy *cdns_phy,
+					 struct cdns_torrent_inst *inst,
 					 u32 rate, u32 num_lanes)
 {
 	unsigned int clk_sel_val = 0;
@@ -1175,14 +1248,17 @@
 		break;
 	}
 
-	cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
-			       CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val);
-	cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
-			       CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val);
+	if (cdns_phy->dp_pll & DP_PLL0)
+		cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
+				       CMN_PDIAG_PLL0_CLK_SEL_M0, clk_sel_val);
+
+	if (cdns_phy->dp_pll & DP_PLL1)
+		cdns_torrent_phy_write(cdns_phy->regmap_common_cdb,
+				       CMN_PDIAG_PLL1_CLK_SEL_M0, clk_sel_val);
 
 	/* PMA lane configuration to deal with multi-link operation */
 	for (i = 0; i < num_lanes; i++)
-		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[i],
+		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + i],
 				       XCVR_DIAG_HSCLK_DIV, hsclk_div_val);
 }
 
@@ -1191,23 +1267,44 @@
  * set and PLL disable request was processed.
  */
 static int cdns_torrent_dp_configure_rate(struct cdns_torrent_phy *cdns_phy,
+					  struct cdns_torrent_inst *inst,
 					  struct phy_configure_opts_dp *dp)
 {
-	u32 read_val, ret;
+	u32 read_val, field_val;
+	int ret;
 
-	/* Disable the cmn_pll0_en before re-programming the new data rate. */
-	regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x0);
+	/*
+	 * Disable the associated PLL (cmn_pll0_en or cmn_pll1_en) before
+	 * re-programming the new data rate.
+	 */
+	ret = regmap_field_read(cdns_phy->phy_pma_pll_raw_ctrl, &field_val);
+	if (ret)
+		return ret;
+	field_val &= ~(cdns_phy->dp_pll);
+	regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, field_val);
 
 	/*
 	 * Wait for PLL ready de-assertion.
 	 * For PLL0 - PHY_PMA_CMN_CTRL2[2] == 1
+	 * For PLL1 - PHY_PMA_CMN_CTRL2[3] == 1
 	 */
-	ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
-					     read_val,
-					     ((read_val >> 2) & 0x01) != 0,
-					     0, POLL_TIMEOUT_US);
-	if (ret)
-		return ret;
+	if (cdns_phy->dp_pll & DP_PLL0) {
+		ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
+						     read_val,
+						     ((read_val >> 2) & 0x01) != 0,
+						     0, POLL_TIMEOUT_US);
+		if (ret)
+			return ret;
+	}
+
+	if ((cdns_phy->dp_pll & DP_PLL1) && cdns_phy->nsubnodes != 1) {
+		ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
+						     read_val,
+						     ((read_val >> 3) & 0x01) != 0,
+						     0, POLL_TIMEOUT_US);
+		if (ret)
+			return ret;
+	}
 	ndelay(200);
 
 	/* DP Rate Change - VCO Output settings. */
@@ -1221,19 +1318,35 @@
 		/* PMA common configuration 100MHz */
 		cdns_torrent_dp_pma_cmn_vco_cfg_100mhz(cdns_phy, dp->link_rate, dp->ssc);
 
-	cdns_torrent_dp_pma_cmn_rate(cdns_phy, dp->link_rate, dp->lanes);
+	cdns_torrent_dp_pma_cmn_rate(cdns_phy, inst, dp->link_rate, dp->lanes);
 
-	/* Enable the cmn_pll0_en. */
-	regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, 0x3);
+	/* Enable the associated PLL (cmn_pll0_en or cmn_pll1_en) */
+	ret = regmap_field_read(cdns_phy->phy_pma_pll_raw_ctrl, &field_val);
+	if (ret)
+		return ret;
+	field_val |= cdns_phy->dp_pll;
+	regmap_field_write(cdns_phy->phy_pma_pll_raw_ctrl, field_val);
 
 	/*
 	 * Wait for PLL ready assertion.
 	 * For PLL0 - PHY_PMA_CMN_CTRL2[0] == 1
+	 * For PLL1 - PHY_PMA_CMN_CTRL2[1] == 1
 	 */
-	ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
-					     read_val,
-					     (read_val & 0x01) != 0,
-					     0, POLL_TIMEOUT_US);
+	if (cdns_phy->dp_pll & DP_PLL0) {
+		ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
+						     read_val,
+						     (read_val & 0x01) != 0,
+						     0, POLL_TIMEOUT_US);
+		if (ret)
+			return ret;
+	}
+
+	if ((cdns_phy->dp_pll & DP_PLL1) && cdns_phy->nsubnodes != 1)
+		ret = regmap_field_read_poll_timeout(cdns_phy->phy_pma_cmn_ctrl_2,
+						     read_val,
+						     ((read_val >> 1) & 0x01) != 0,
+						     0, POLL_TIMEOUT_US);
+
 	return ret;
 }
 
@@ -1301,6 +1414,7 @@
 
 /* Set power state A0 and PLL clock enable to 0 on enabled lanes. */
 static void cdns_torrent_dp_set_a0_pll(struct cdns_torrent_phy *cdns_phy,
+				       struct cdns_torrent_inst *inst,
 				       u32 num_lanes)
 {
 	struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
@@ -1308,27 +1422,13 @@
 					     PHY_PMA_XCVR_POWER_STATE_REQ);
 	u32 pll_clk_en = cdns_torrent_dp_read(regmap,
 					      PHY_PMA_XCVR_PLLCLK_EN);
+	u32 i;
 
-	/* Lane 0 is always enabled. */
-	pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
-		       PHY_POWER_STATE_LN_0);
-	pll_clk_en &= ~0x01U;
-
-	if (num_lanes > 1) {
-		/* lane 1 */
-		pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
-			       PHY_POWER_STATE_LN_1);
-		pll_clk_en &= ~(0x01U << 1);
-	}
-
-	if (num_lanes > 2) {
-		/* lanes 2 and 3 */
-		pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
-			       PHY_POWER_STATE_LN_2);
-		pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK <<
-			       PHY_POWER_STATE_LN_3);
-		pll_clk_en &= ~(0x01U << 2);
-		pll_clk_en &= ~(0x01U << 3);
+	for (i = 0; i < num_lanes; i++) {
+		pwr_state &= ~(PMA_XCVR_POWER_STATE_REQ_LN_MASK
+			     << PHY_POWER_STATE_LN(inst->mlane + i));
+
+		pll_clk_en &= ~(0x01U << (inst->mlane + i));
 	}
 
 	cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_POWER_STATE_REQ, pwr_state);
@@ -1337,36 +1437,57 @@
 
 /* Configure lane count as required. */
 static int cdns_torrent_dp_set_lanes(struct cdns_torrent_phy *cdns_phy,
+				     struct cdns_torrent_inst *inst,
 				     struct phy_configure_opts_dp *dp)
 {
-	u32 value;
-	u32 ret;
+	u32 value, i;
+	int ret;
 	struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
 	u8 lane_mask = (1 << dp->lanes) - 1;
+	u8 pma_tx_elec_idle_mask = 0;
+	u32 clane = inst->mlane;
+
+	lane_mask <<= clane;
 
 	value = cdns_torrent_dp_read(regmap, PHY_RESET);
 	/* clear pma_tx_elec_idle_ln_* bits. */
-	value &= ~PMA_TX_ELEC_IDLE_MASK;
+	pma_tx_elec_idle_mask = ((1 << inst->num_lanes) - 1) << clane;
+
+	pma_tx_elec_idle_mask <<= PMA_TX_ELEC_IDLE_SHIFT;
+
+	value &= ~pma_tx_elec_idle_mask;
+
 	/* Assert pma_tx_elec_idle_ln_* for disabled lanes. */
 	value |= ((~lane_mask) << PMA_TX_ELEC_IDLE_SHIFT) &
-		 PMA_TX_ELEC_IDLE_MASK;
+		 pma_tx_elec_idle_mask;
+
 	cdns_torrent_dp_write(regmap, PHY_RESET, value);
 
-	/* reset the link by asserting phy_l00_reset_n low */
+	/* reset the link by asserting master lane phy_l0*_reset_n low */
 	cdns_torrent_dp_write(regmap, PHY_RESET,
-			      value & (~PHY_L00_RESET_N_MASK));
+			      value & (~(1 << clane)));
 
 	/*
-	 * Assert lane reset on unused lanes and lane 0 so they remain in reset
+	 * Assert lane reset on unused lanes and master lane so they remain in reset
 	 * and powered down when re-enabling the link
 	 */
-	value = (value & 0x0000FFF0) | (0x0000000E & lane_mask);
+	for (i = 0; i < inst->num_lanes; i++)
+		value &= (~(1 << (clane + i)));
+
+	for (i = 1; i < inst->num_lanes; i++)
+		value |= ((1 << (clane + i)) & lane_mask);
+
 	cdns_torrent_dp_write(regmap, PHY_RESET, value);
 
-	cdns_torrent_dp_set_a0_pll(cdns_phy, dp->lanes);
+	cdns_torrent_dp_set_a0_pll(cdns_phy, inst, dp->lanes);
 
 	/* release phy_l0*_reset_n based on used laneCount */
-	value = (value & 0x0000FFF0) | (0x0000000F & lane_mask);
+	for (i = 0; i < inst->num_lanes; i++)
+		value &= (~(1 << (clane + i)));
+
+	for (i = 0; i < inst->num_lanes; i++)
+		value |= ((1 << (clane + i)) & lane_mask);
+
 	cdns_torrent_dp_write(regmap, PHY_RESET, value);
 
 	/* Wait, until PHY gets ready after releasing PHY reset signal. */
@@ -1377,41 +1498,44 @@
 	ndelay(100);
 
 	/* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
-	cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001);
+	value = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN);
+	value |= (1 << clane);
+	cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, value);
 
-	ret = cdns_torrent_dp_run(cdns_phy, dp->lanes);
+	ret = cdns_torrent_dp_run(cdns_phy, inst, dp->lanes);
 
 	return ret;
 }
 
 /* Configure link rate as required. */
 static int cdns_torrent_dp_set_rate(struct cdns_torrent_phy *cdns_phy,
+				    struct cdns_torrent_inst *inst,
 				    struct phy_configure_opts_dp *dp)
 {
-	u32 ret;
+	int ret;
 
-	ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
+	ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes,
 					      POWERSTATE_A3);
 	if (ret)
 		return ret;
-	ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, false);
+	ret = cdns_torrent_dp_set_pll_en(cdns_phy, inst, dp, false);
 	if (ret)
 		return ret;
 	ndelay(200);
 
-	ret = cdns_torrent_dp_configure_rate(cdns_phy, dp);
+	ret = cdns_torrent_dp_configure_rate(cdns_phy, inst, dp);
 	if (ret)
 		return ret;
 	ndelay(200);
 
-	ret = cdns_torrent_dp_set_pll_en(cdns_phy, dp, true);
+	ret = cdns_torrent_dp_set_pll_en(cdns_phy, inst, dp, true);
 	if (ret)
 		return ret;
-	ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
+	ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes,
 					      POWERSTATE_A2);
 	if (ret)
 		return ret;
-	ret = cdns_torrent_dp_set_power_state(cdns_phy, dp->lanes,
+	ret = cdns_torrent_dp_set_power_state(cdns_phy, inst, dp->lanes,
 					      POWERSTATE_A0);
 	if (ret)
 		return ret;
@@ -1422,44 +1546,45 @@
 
 /* Configure voltage swing and pre-emphasis for all enabled lanes. */
 static void cdns_torrent_dp_set_voltages(struct cdns_torrent_phy *cdns_phy,
+					 struct cdns_torrent_inst *inst,
 					 struct phy_configure_opts_dp *dp)
 {
 	u8 lane;
 	u16 val;
 
 	for (lane = 0; lane < dp->lanes; lane++) {
-		val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane],
+		val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
 					    TX_DIAG_ACYA);
 		/*
 		 * Write 1 to register bit TX_DIAG_ACYA[0] to freeze the
 		 * current state of the analog TX driver.
 		 */
 		val |= TX_DIAG_ACYA_HBDC_MASK;
-		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
+		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
 				       TX_DIAG_ACYA, val);
 
-		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
+		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
 				       TX_TXCC_CTRL, 0x08A4);
 		val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].diag_tx_drv;
-		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
+		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
 				       DRV_DIAG_TX_DRV, val);
 		val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].mgnfs_mult;
-		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
+		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
 				       TX_TXCC_MGNFS_MULT_000,
 				       val);
 		val = vltg_coeff[dp->voltage[lane]][dp->pre[lane]].cpost_mult;
-		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
+		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
 				       TX_TXCC_CPOST_MULT_00,
 				       val);
 
-		val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[lane],
+		val = cdns_torrent_phy_read(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
 					    TX_DIAG_ACYA);
 		/*
 		 * Write 0 to register bit TX_DIAG_ACYA[0] to allow the state of
 		 * analog TX driver to reflect the new programmed one.
 		 */
 		val &= ~TX_DIAG_ACYA_HBDC_MASK;
-		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[lane],
+		cdns_torrent_phy_write(cdns_phy->regmap_tx_lane_cdb[inst->mlane + lane],
 				       TX_DIAG_ACYA, val);
 	}
 };
@@ -1478,7 +1603,7 @@
 	}
 
 	if (opts->dp.set_lanes) {
-		ret = cdns_torrent_dp_set_lanes(cdns_phy, &opts->dp);
+		ret = cdns_torrent_dp_set_lanes(cdns_phy, inst, &opts->dp);
 		if (ret) {
 			dev_err(&phy->dev, "cdns_torrent_dp_set_lanes failed\n");
 			return ret;
@@ -1486,7 +1611,7 @@
 	}
 
 	if (opts->dp.set_rate) {
-		ret = cdns_torrent_dp_set_rate(cdns_phy, &opts->dp);
+		ret = cdns_torrent_dp_set_rate(cdns_phy, inst, &opts->dp);
 		if (ret) {
 			dev_err(&phy->dev, "cdns_torrent_dp_set_rate failed\n");
 			return ret;
@@ -1494,7 +1619,7 @@
 	}
 
 	if (opts->dp.set_voltages)
-		cdns_torrent_dp_set_voltages(cdns_phy, &opts->dp);
+		cdns_torrent_dp_set_voltages(cdns_phy, inst, &opts->dp);
 
 	return ret;
 }
@@ -1562,6 +1687,7 @@
 {
 	struct regmap *regmap = cdns_phy->regmap_dptx_phy_reg;
 	unsigned char lane_bits;
+	u32 val;
 
 	cdns_torrent_dp_write(regmap, PHY_AUX_CTRL, 0x0003); /* enable AUX */
 
@@ -1569,18 +1695,23 @@
 	 * Set lines power state to A0
 	 * Set lines pll clk enable to 0
 	 */
-	cdns_torrent_dp_set_a0_pll(cdns_phy, inst->num_lanes);
+	cdns_torrent_dp_set_a0_pll(cdns_phy, inst, inst->num_lanes);
 
 	/*
 	 * release phy_l0*_reset_n and pma_tx_elec_idle_ln_* based on
 	 * used lanes
 	 */
 	lane_bits = (1 << inst->num_lanes) - 1;
-	cdns_torrent_dp_write(regmap, PHY_RESET,
-			      ((0xF & ~lane_bits) << 4) | (0xF & lane_bits));
+
+	val = cdns_torrent_dp_read(regmap, PHY_RESET);
+	val |= (0xF & lane_bits);
+	val &= ~(lane_bits << 4);
+	cdns_torrent_dp_write(regmap, PHY_RESET, val);
 
 	/* release pma_xcvr_pllclk_en_ln_*, only for the master lane */
-	cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, 0x0001);
+	val = cdns_torrent_dp_read(regmap, PHY_PMA_XCVR_PLLCLK_EN);
+	val |= 1;
+	cdns_torrent_dp_write(regmap, PHY_PMA_XCVR_PLLCLK_EN, val);
 
 	/*
 	 * PHY PMA registers configuration functions
@@ -1599,7 +1730,7 @@
 						       cdns_phy->max_bit_rate,
 						       false);
 
-	cdns_torrent_dp_pma_cmn_rate(cdns_phy, cdns_phy->max_bit_rate,
+	cdns_torrent_dp_pma_cmn_rate(cdns_phy, inst, cdns_phy->max_bit_rate,
 				     inst->num_lanes);
 
 	/* take out of reset */
@@ -1612,13 +1743,15 @@
 {
 	int ret;
 
-	cdns_torrent_phy_on(phy);
+	ret = cdns_torrent_phy_on(phy);
+	if (ret)
+		return ret;
 
 	ret = cdns_torrent_dp_wait_pma_cmn_ready(cdns_phy);
 	if (ret)
 		return ret;
 
-	ret = cdns_torrent_dp_run(cdns_phy, inst->num_lanes);
+	ret = cdns_torrent_dp_run(cdns_phy, inst, inst->num_lanes);
 
 	return ret;
 }
@@ -1627,6 +1760,7 @@
 {
 	struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
 	struct cdns_torrent_phy *cdns_phy = dev_get_drvdata(phy->dev.parent);
+	int ret;
 
 	switch (cdns_phy->ref_clk_rate) {
 	case CLK_19_2_MHZ:
@@ -1639,6 +1773,24 @@
 		return -EINVAL;
 	}
 
+	ret = cdns_torrent_dp_get_pll(cdns_phy, TYPE_NONE);
+	if (ret)
+		return ret;
+
+	cdns_torrent_dp_common_init(cdns_phy, inst);
+
+	return cdns_torrent_dp_start(cdns_phy, inst, phy);
+}
+
+static int cdns_torrent_dp_multilink_init(struct cdns_torrent_phy *cdns_phy,
+					  struct cdns_torrent_inst *inst,
+					  struct phy *phy)
+{
+	if (cdns_phy->ref_clk_rate != CLK_100_MHZ) {
+		dev_err(cdns_phy->dev, "Unsupported Ref Clock Rate\n");
+		return -EINVAL;
+	}
+
 	cdns_torrent_dp_common_init(cdns_phy, inst);
 
 	return cdns_torrent_dp_start(cdns_phy, inst, phy);
@@ -2149,24 +2301,31 @@
 	struct cdns_torrent_inst *inst = phy_get_drvdata(phy);
 	enum cdns_torrent_phy_type phy_type = inst->phy_type;
 	enum cdns_torrent_ssc_mode ssc = inst->ssc_mode;
+	struct cdns_torrent_vals *phy_pma_cmn_vals;
 	struct cdns_torrent_vals *pcs_cmn_vals;
 	struct cdns_reg_pairs *reg_pairs;
 	struct regmap *regmap;
 	u32 num_regs;
 	int i, j;
 
-	if (cdns_phy->nsubnodes > 1)
+	if (cdns_phy->nsubnodes > 1) {
+		if (phy_type == TYPE_DP)
+			return cdns_torrent_dp_multilink_init(cdns_phy, inst, phy);
 		return 0;
+	}
 
 	/**
 	 * Spread spectrum generation is not required or supported
-	 * for SGMII/QSGMII
+	 * for SGMII/QSGMII/USXGMII
 	 */
-	if (phy_type == TYPE_SGMII || phy_type == TYPE_QSGMII)
+	if (phy_type == TYPE_SGMII || phy_type == TYPE_QSGMII || phy_type == TYPE_USXGMII)
 		ssc = NO_SSC;
 
 	/* PHY configuration specific registers for single link */
-	link_cmn_vals = init_data->link_cmn_vals[phy_type][TYPE_NONE][ssc];
+	link_cmn_vals = cdns_torrent_get_tbl_vals(&init_data->link_cmn_vals_tbl,
+						  CLK_ANY, CLK_ANY,
+						  phy_type, TYPE_NONE,
+						  ANY_SSC);
 	if (link_cmn_vals) {
 		reg_pairs = link_cmn_vals->reg_pairs;
 		num_regs = link_cmn_vals->num_regs;
@@ -2183,7 +2342,10 @@
 				     reg_pairs[i].val);
 	}
 
-	xcvr_diag_vals = init_data->xcvr_diag_vals[phy_type][TYPE_NONE][ssc];
+	xcvr_diag_vals = cdns_torrent_get_tbl_vals(&init_data->xcvr_diag_vals_tbl,
+						   CLK_ANY, CLK_ANY,
+						   phy_type, TYPE_NONE,
+						   ANY_SSC);
 	if (xcvr_diag_vals) {
 		reg_pairs = xcvr_diag_vals->reg_pairs;
 		num_regs = xcvr_diag_vals->num_regs;
@@ -2196,7 +2358,10 @@
 	}
 
 	/* PHY PCS common registers configurations */
-	pcs_cmn_vals = init_data->pcs_cmn_vals[phy_type][TYPE_NONE][ssc];
+	pcs_cmn_vals = cdns_torrent_get_tbl_vals(&init_data->pcs_cmn_vals_tbl,
+						 CLK_ANY, CLK_ANY,
+						 phy_type, TYPE_NONE,
+						 ANY_SSC);
 	if (pcs_cmn_vals) {
 		reg_pairs = pcs_cmn_vals->reg_pairs;
 		num_regs = pcs_cmn_vals->num_regs;
@@ -2206,8 +2371,25 @@
 				     reg_pairs[i].val);
 	}
 
+	/* PHY PMA common registers configurations */
+	phy_pma_cmn_vals = cdns_torrent_get_tbl_vals(&init_data->phy_pma_cmn_vals_tbl,
+						     CLK_ANY, CLK_ANY,
+						     phy_type, TYPE_NONE,
+						     ANY_SSC);
+	if (phy_pma_cmn_vals) {
+		reg_pairs = phy_pma_cmn_vals->reg_pairs;
+		num_regs = phy_pma_cmn_vals->num_regs;
+		regmap = cdns_phy->regmap_phy_pma_common_cdb;
+		for (i = 0; i < num_regs; i++)
+			regmap_write(regmap, reg_pairs[i].off,
+				     reg_pairs[i].val);
+	}
+
 	/* PMA common registers configurations */
-	cmn_vals = init_data->cmn_vals[ref_clk][phy_type][TYPE_NONE][ssc];
+	cmn_vals = cdns_torrent_get_tbl_vals(&init_data->cmn_vals_tbl,
+					     ref_clk, ref_clk,
+					     phy_type, TYPE_NONE,
+					     ssc);
 	if (cmn_vals) {
 		reg_pairs = cmn_vals->reg_pairs;
 		num_regs = cmn_vals->num_regs;
@@ -2218,7 +2400,10 @@
 	}
 
 	/* PMA TX lane registers configurations */
-	tx_ln_vals = init_data->tx_ln_vals[ref_clk][phy_type][TYPE_NONE][ssc];
+	tx_ln_vals = cdns_torrent_get_tbl_vals(&init_data->tx_ln_vals_tbl,
+					       ref_clk, ref_clk,
+					       phy_type, TYPE_NONE,
+					       ssc);
 	if (tx_ln_vals) {
 		reg_pairs = tx_ln_vals->reg_pairs;
 		num_regs = tx_ln_vals->num_regs;
@@ -2231,7 +2416,10 @@
 	}
 
 	/* PMA RX lane registers configurations */
-	rx_ln_vals = init_data->rx_ln_vals[ref_clk][phy_type][TYPE_NONE][ssc];
+	rx_ln_vals = cdns_torrent_get_tbl_vals(&init_data->rx_ln_vals_tbl,
+					       ref_clk, ref_clk,
+					       phy_type, TYPE_NONE,
+					       ssc);
 	if (rx_ln_vals) {
 		reg_pairs = rx_ln_vals->reg_pairs;
 		num_regs = rx_ln_vals->num_regs;
@@ -2275,9 +2463,11 @@
 {
 	const struct cdns_torrent_data *init_data = cdns_phy->init_data;
 	struct cdns_torrent_vals *cmn_vals, *tx_ln_vals, *rx_ln_vals;
+	enum cdns_torrent_ref_clk ref_clk1 = cdns_phy->ref_clk1_rate;
 	enum cdns_torrent_ref_clk ref_clk = cdns_phy->ref_clk_rate;
 	struct cdns_torrent_vals *link_cmn_vals, *xcvr_diag_vals;
 	enum cdns_torrent_phy_type phy_t1, phy_t2;
+	struct cdns_torrent_vals *phy_pma_cmn_vals;
 	struct cdns_torrent_vals *pcs_cmn_vals;
 	int i, j, node, mlane, num_lanes, ret;
 	struct cdns_reg_pairs *reg_pairs;
@@ -2304,6 +2494,7 @@
 			 * Get the array values as [phy_t2][phy_t1][ssc].
 			 */
 			swap(phy_t1, phy_t2);
+			swap(ref_clk, ref_clk1);
 		}
 
 		mlane = cdns_phy->phys[node].mlane;
@@ -2320,7 +2511,9 @@
 		 * being configured, but these can be different for particular
 		 * PHY type and are per lane.
 		 */
-		link_cmn_vals = init_data->link_cmn_vals[phy_t1][phy_t2][ssc];
+		link_cmn_vals = cdns_torrent_get_tbl_vals(&init_data->link_cmn_vals_tbl,
+							  CLK_ANY, CLK_ANY,
+							  phy_t1, phy_t2, ANY_SSC);
 		if (link_cmn_vals) {
 			reg_pairs = link_cmn_vals->reg_pairs;
 			num_regs = link_cmn_vals->num_regs;
@@ -2338,7 +2531,9 @@
 					     reg_pairs[i].val);
 		}
 
-		xcvr_diag_vals = init_data->xcvr_diag_vals[phy_t1][phy_t2][ssc];
+		xcvr_diag_vals = cdns_torrent_get_tbl_vals(&init_data->xcvr_diag_vals_tbl,
+							   CLK_ANY, CLK_ANY,
+							   phy_t1, phy_t2, ANY_SSC);
 		if (xcvr_diag_vals) {
 			reg_pairs = xcvr_diag_vals->reg_pairs;
 			num_regs = xcvr_diag_vals->num_regs;
@@ -2351,7 +2546,9 @@
 		}
 
 		/* PHY PCS common registers configurations */
-		pcs_cmn_vals = init_data->pcs_cmn_vals[phy_t1][phy_t2][ssc];
+		pcs_cmn_vals = cdns_torrent_get_tbl_vals(&init_data->pcs_cmn_vals_tbl,
+							 CLK_ANY, CLK_ANY,
+							 phy_t1, phy_t2, ANY_SSC);
 		if (pcs_cmn_vals) {
 			reg_pairs = pcs_cmn_vals->reg_pairs;
 			num_regs = pcs_cmn_vals->num_regs;
@@ -2361,8 +2558,23 @@
 					     reg_pairs[i].val);
 		}
 
+		/* PHY PMA common registers configurations */
+		phy_pma_cmn_vals = cdns_torrent_get_tbl_vals(&init_data->phy_pma_cmn_vals_tbl,
+							     CLK_ANY, CLK_ANY,
+							     phy_t1, phy_t2, ANY_SSC);
+		if (phy_pma_cmn_vals) {
+			reg_pairs = phy_pma_cmn_vals->reg_pairs;
+			num_regs = phy_pma_cmn_vals->num_regs;
+			regmap = cdns_phy->regmap_phy_pma_common_cdb;
+			for (i = 0; i < num_regs; i++)
+				regmap_write(regmap, reg_pairs[i].off,
+					     reg_pairs[i].val);
+		}
+
 		/* PMA common registers configurations */
-		cmn_vals = init_data->cmn_vals[ref_clk][phy_t1][phy_t2][ssc];
+		cmn_vals = cdns_torrent_get_tbl_vals(&init_data->cmn_vals_tbl,
+						     ref_clk, ref_clk1,
+						     phy_t1, phy_t2, ssc);
 		if (cmn_vals) {
 			reg_pairs = cmn_vals->reg_pairs;
 			num_regs = cmn_vals->num_regs;
@@ -2373,7 +2585,9 @@
 		}
 
 		/* PMA TX lane registers configurations */
-		tx_ln_vals = init_data->tx_ln_vals[ref_clk][phy_t1][phy_t2][ssc];
+		tx_ln_vals = cdns_torrent_get_tbl_vals(&init_data->tx_ln_vals_tbl,
+						       ref_clk, ref_clk1,
+						       phy_t1, phy_t2, ssc);
 		if (tx_ln_vals) {
 			reg_pairs = tx_ln_vals->reg_pairs;
 			num_regs = tx_ln_vals->num_regs;
@@ -2386,7 +2600,9 @@
 		}
 
 		/* PMA RX lane registers configurations */
-		rx_ln_vals = init_data->rx_ln_vals[ref_clk][phy_t1][phy_t2][ssc];
+		rx_ln_vals = cdns_torrent_get_tbl_vals(&init_data->rx_ln_vals_tbl,
+						       ref_clk, ref_clk1,
+						       phy_t1, phy_t2, ssc);
 		if (rx_ln_vals) {
 			reg_pairs = rx_ln_vals->reg_pairs;
 			num_regs = rx_ln_vals->num_regs;
@@ -2398,6 +2614,12 @@
 			}
 		}
 
+		if (phy_t1 == TYPE_DP) {
+			ret = cdns_torrent_dp_get_pll(cdns_phy, phy_t2);
+			if (ret)
+				return ret;
+		}
+
 		reset_control_deassert(cdns_phy->phys[node].lnk_rst);
 	}
 
@@ -2481,9 +2703,11 @@
 static int cdns_torrent_clk(struct cdns_torrent_phy *cdns_phy)
 {
 	struct device *dev = cdns_phy->dev;
+	unsigned long ref_clk1_rate;
 	unsigned long ref_clk_rate;
 	int ret;
 
+	/* refclk: Input reference clock for PLL0 */
 	cdns_phy->clk = devm_clk_get(dev, "refclk");
 	if (IS_ERR(cdns_phy->clk)) {
 		dev_err(dev, "phy ref clock not found\n");
@@ -2513,13 +2737,63 @@
 	case REF_CLK_100MHZ:
 		cdns_phy->ref_clk_rate = CLK_100_MHZ;
 		break;
+	case REF_CLK_156_25MHZ:
+		cdns_phy->ref_clk_rate = CLK_156_25_MHZ;
+		break;
 	default:
 		dev_err(cdns_phy->dev, "Invalid Ref Clock Rate\n");
 		clk_disable_unprepare(cdns_phy->clk);
 		return -EINVAL;
 	}
 
+	/* refclk1: Input reference clock for PLL1 */
+	cdns_phy->clk1 = devm_clk_get_optional(dev, "refclk1");
+	if (IS_ERR(cdns_phy->clk1)) {
+		dev_err(dev, "phy ref clock1 not found\n");
+		return PTR_ERR(cdns_phy->clk1);
+	}
+
+	if (cdns_phy->clk1) {
+		ret = clk_prepare_enable(cdns_phy->clk1);
+		if (ret) {
+			dev_err(cdns_phy->dev, "Failed to prepare ref clock1\n");
+			clk_disable_unprepare(cdns_phy->clk);
+			return ret;
+		}
+
+		ref_clk1_rate = clk_get_rate(cdns_phy->clk1);
+		if (!ref_clk1_rate) {
+			dev_err(cdns_phy->dev, "Failed to get ref clock1 rate\n");
+			goto refclk1_err;
+		}
+
+		switch (ref_clk1_rate) {
+		case REF_CLK_19_2MHZ:
+			cdns_phy->ref_clk1_rate = CLK_19_2_MHZ;
+			break;
+		case REF_CLK_25MHZ:
+			cdns_phy->ref_clk1_rate = CLK_25_MHZ;
+			break;
+		case REF_CLK_100MHZ:
+			cdns_phy->ref_clk1_rate = CLK_100_MHZ;
+			break;
+		case REF_CLK_156_25MHZ:
+			cdns_phy->ref_clk1_rate = CLK_156_25_MHZ;
+			break;
+		default:
+			dev_err(cdns_phy->dev, "Invalid Ref Clock1 Rate\n");
+			goto refclk1_err;
+		}
+	} else {
+		cdns_phy->ref_clk1_rate = cdns_phy->ref_clk_rate;
+	}
+
 	return 0;
+
+refclk1_err:
+	clk_disable_unprepare(cdns_phy->clk1);
+	clk_disable_unprepare(cdns_phy->clk);
+	return -EINVAL;
 }
 
 static int cdns_torrent_phy_probe(struct platform_device *pdev)
@@ -2632,6 +2906,9 @@
 		case PHY_TYPE_USB3:
 			cdns_phy->phys[node].phy_type = TYPE_USB;
 			break;
+		case PHY_TYPE_USXGMII:
+			cdns_phy->phys[node].phy_type = TYPE_USXGMII;
+			break;
 		default:
 			dev_err(dev, "Unsupported protocol\n");
 			ret = -EINVAL;
@@ -2772,6 +3049,7 @@
 	of_node_put(child);
 	reset_control_assert(cdns_phy->apb_rst);
 	clk_disable_unprepare(cdns_phy->clk);
+	clk_disable_unprepare(cdns_phy->clk1);
 clk_cleanup:
 	cdns_torrent_clk_cleanup(cdns_phy);
 	return ret;
@@ -2790,11 +3068,442 @@
 	}
 
 	clk_disable_unprepare(cdns_phy->clk);
+	clk_disable_unprepare(cdns_phy->clk1);
 	cdns_torrent_clk_cleanup(cdns_phy);
 
 	return 0;
 }
 
+/* USB and DP link configuration */
+static struct cdns_reg_pairs usb_dp_link_cmn_regs[] = {
+	{0x0002, PHY_PLL_CFG},
+	{0x8600, CMN_PDIAG_PLL0_CLK_SEL_M0}
+};
+
+static struct cdns_reg_pairs usb_dp_xcvr_diag_ln_regs[] = {
+	{0x0000, XCVR_DIAG_HSCLK_SEL},
+	{0x0001, XCVR_DIAG_HSCLK_DIV},
+	{0x0041, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_reg_pairs dp_usb_xcvr_diag_ln_regs[] = {
+	{0x0001, XCVR_DIAG_HSCLK_SEL},
+	{0x0009, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_torrent_vals usb_dp_link_cmn_vals = {
+	.reg_pairs = usb_dp_link_cmn_regs,
+	.num_regs = ARRAY_SIZE(usb_dp_link_cmn_regs),
+};
+
+static struct cdns_torrent_vals usb_dp_xcvr_diag_ln_vals = {
+	.reg_pairs = usb_dp_xcvr_diag_ln_regs,
+	.num_regs = ARRAY_SIZE(usb_dp_xcvr_diag_ln_regs),
+};
+
+static struct cdns_torrent_vals dp_usb_xcvr_diag_ln_vals = {
+	.reg_pairs = dp_usb_xcvr_diag_ln_regs,
+	.num_regs = ARRAY_SIZE(dp_usb_xcvr_diag_ln_regs),
+};
+
+/* USXGMII and SGMII/QSGMII link configuration */
+static struct cdns_reg_pairs usxgmii_sgmii_link_cmn_regs[] = {
+	{0x0002, PHY_PLL_CFG},
+	{0x0400, CMN_PDIAG_PLL0_CLK_SEL_M0},
+	{0x0601, CMN_PDIAG_PLL1_CLK_SEL_M0}
+};
+
+static struct cdns_reg_pairs usxgmii_sgmii_xcvr_diag_ln_regs[] = {
+	{0x0000, XCVR_DIAG_HSCLK_SEL},
+	{0x0001, XCVR_DIAG_HSCLK_DIV},
+	{0x0001, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_reg_pairs sgmii_usxgmii_xcvr_diag_ln_regs[] = {
+	{0x0111, XCVR_DIAG_HSCLK_SEL},
+	{0x0103, XCVR_DIAG_HSCLK_DIV},
+	{0x0A9B, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_torrent_vals usxgmii_sgmii_link_cmn_vals = {
+	.reg_pairs = usxgmii_sgmii_link_cmn_regs,
+	.num_regs = ARRAY_SIZE(usxgmii_sgmii_link_cmn_regs),
+};
+
+static struct cdns_torrent_vals usxgmii_sgmii_xcvr_diag_ln_vals = {
+	.reg_pairs = usxgmii_sgmii_xcvr_diag_ln_regs,
+	.num_regs = ARRAY_SIZE(usxgmii_sgmii_xcvr_diag_ln_regs),
+};
+
+static struct cdns_torrent_vals sgmii_usxgmii_xcvr_diag_ln_vals = {
+	.reg_pairs = sgmii_usxgmii_xcvr_diag_ln_regs,
+	.num_regs = ARRAY_SIZE(sgmii_usxgmii_xcvr_diag_ln_regs),
+};
+
+/* Multilink USXGMII, using PLL0, 156.25 MHz Ref clk, no SSC */
+static struct cdns_reg_pairs ml_usxgmii_pll0_156_25_no_ssc_cmn_regs[] = {
+	{0x0014, CMN_PLL0_DSM_FBH_OVRD_M0},
+	{0x0005, CMN_PLL0_DSM_FBL_OVRD_M0},
+	{0x061B, CMN_PLL0_VCOCAL_INIT_TMR},
+	{0x0019, CMN_PLL0_VCOCAL_ITER_TMR},
+	{0x1354, CMN_PLL0_VCOCAL_REFTIM_START},
+	{0x1354, CMN_PLL0_VCOCAL_PLLCNT_START},
+	{0x0003, CMN_PLL0_VCOCAL_TCTRL},
+	{0x0138, CMN_PLL0_LOCK_REFCNT_START},
+	{0x0138, CMN_PLL0_LOCK_PLLCNT_START}
+};
+
+static struct cdns_torrent_vals ml_usxgmii_pll0_156_25_no_ssc_cmn_vals = {
+	.reg_pairs = ml_usxgmii_pll0_156_25_no_ssc_cmn_regs,
+	.num_regs = ARRAY_SIZE(ml_usxgmii_pll0_156_25_no_ssc_cmn_regs),
+};
+
+/* Multilink SGMII/QSGMII, using PLL1, 100 MHz Ref clk, no SSC */
+static struct cdns_reg_pairs ml_sgmii_pll1_100_no_ssc_cmn_regs[] = {
+	{0x0028, CMN_PDIAG_PLL1_CP_PADJ_M0},
+	{0x001E, CMN_PLL1_DSM_FBH_OVRD_M0},
+	{0x000C, CMN_PLL1_DSM_FBL_OVRD_M0},
+	{0x0003, CMN_PLL1_VCOCAL_TCTRL},
+	{0x007F, CMN_TXPUCAL_TUNE},
+	{0x007F, CMN_TXPDCAL_TUNE}
+};
+
+static struct cdns_torrent_vals ml_sgmii_pll1_100_no_ssc_cmn_vals = {
+	.reg_pairs = ml_sgmii_pll1_100_no_ssc_cmn_regs,
+	.num_regs = ARRAY_SIZE(ml_sgmii_pll1_100_no_ssc_cmn_regs),
+};
+
+/* TI J7200, Multilink USXGMII, using PLL0, 156.25 MHz Ref clk, no SSC */
+static struct cdns_reg_pairs j7200_ml_usxgmii_pll0_156_25_no_ssc_cmn_regs[] = {
+	{0x0014, CMN_SSM_BIAS_TMR},
+	{0x0028, CMN_PLLSM0_PLLPRE_TMR},
+	{0x00A4, CMN_PLLSM0_PLLLOCK_TMR},
+	{0x0062, CMN_BGCAL_INIT_TMR},
+	{0x0062, CMN_BGCAL_ITER_TMR},
+	{0x0014, CMN_IBCAL_INIT_TMR},
+	{0x0018, CMN_TXPUCAL_INIT_TMR},
+	{0x0005, CMN_TXPUCAL_ITER_TMR},
+	{0x0018, CMN_TXPDCAL_INIT_TMR},
+	{0x0005, CMN_TXPDCAL_ITER_TMR},
+	{0x024A, CMN_RXCAL_INIT_TMR},
+	{0x0005, CMN_RXCAL_ITER_TMR},
+	{0x000B, CMN_SD_CAL_REFTIM_START},
+	{0x0132, CMN_SD_CAL_PLLCNT_START},
+	{0x0014, CMN_PLL0_DSM_FBH_OVRD_M0},
+	{0x0005, CMN_PLL0_DSM_FBL_OVRD_M0},
+	{0x061B, CMN_PLL0_VCOCAL_INIT_TMR},
+	{0x0019, CMN_PLL0_VCOCAL_ITER_TMR},
+	{0x1354, CMN_PLL0_VCOCAL_REFTIM_START},
+	{0x1354, CMN_PLL0_VCOCAL_PLLCNT_START},
+	{0x0003, CMN_PLL0_VCOCAL_TCTRL},
+	{0x0138, CMN_PLL0_LOCK_REFCNT_START},
+	{0x0138, CMN_PLL0_LOCK_PLLCNT_START}
+};
+
+static struct cdns_torrent_vals j7200_ml_usxgmii_pll0_156_25_no_ssc_cmn_vals = {
+	.reg_pairs = j7200_ml_usxgmii_pll0_156_25_no_ssc_cmn_regs,
+	.num_regs = ARRAY_SIZE(j7200_ml_usxgmii_pll0_156_25_no_ssc_cmn_regs),
+};
+
+/* TI J7200, Multilink SGMII/QSGMII, using PLL1, 100 MHz Ref clk, no SSC */
+static struct cdns_reg_pairs j7200_ml_sgmii_pll1_100_no_ssc_cmn_regs[] = {
+	{0x0028, CMN_PLLSM1_PLLPRE_TMR},
+	{0x00A4, CMN_PLLSM1_PLLLOCK_TMR},
+	{0x0028, CMN_PDIAG_PLL1_CP_PADJ_M0},
+	{0x001E, CMN_PLL1_DSM_FBH_OVRD_M0},
+	{0x000C, CMN_PLL1_DSM_FBL_OVRD_M0},
+	{0x0003, CMN_PLL1_VCOCAL_TCTRL},
+	{0x007F, CMN_TXPUCAL_TUNE},
+	{0x007F, CMN_TXPDCAL_TUNE}
+};
+
+static struct cdns_torrent_vals j7200_ml_sgmii_pll1_100_no_ssc_cmn_vals = {
+	.reg_pairs = j7200_ml_sgmii_pll1_100_no_ssc_cmn_regs,
+	.num_regs = ARRAY_SIZE(j7200_ml_sgmii_pll1_100_no_ssc_cmn_regs),
+};
+
+/* PCIe and USXGMII link configuration */
+static struct cdns_reg_pairs pcie_usxgmii_link_cmn_regs[] = {
+	{0x0003, PHY_PLL_CFG},
+	{0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0},
+	{0x0400, CMN_PDIAG_PLL0_CLK_SEL_M1},
+	{0x0400, CMN_PDIAG_PLL1_CLK_SEL_M0}
+};
+
+static struct cdns_reg_pairs pcie_usxgmii_xcvr_diag_ln_regs[] = {
+	{0x0000, XCVR_DIAG_HSCLK_SEL},
+	{0x0001, XCVR_DIAG_HSCLK_DIV},
+	{0x0012, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_reg_pairs usxgmii_pcie_xcvr_diag_ln_regs[] = {
+	{0x0011, XCVR_DIAG_HSCLK_SEL},
+	{0x0001, XCVR_DIAG_HSCLK_DIV},
+	{0x0089, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_torrent_vals pcie_usxgmii_link_cmn_vals = {
+	.reg_pairs = pcie_usxgmii_link_cmn_regs,
+	.num_regs = ARRAY_SIZE(pcie_usxgmii_link_cmn_regs),
+};
+
+static struct cdns_torrent_vals pcie_usxgmii_xcvr_diag_ln_vals = {
+	.reg_pairs = pcie_usxgmii_xcvr_diag_ln_regs,
+	.num_regs = ARRAY_SIZE(pcie_usxgmii_xcvr_diag_ln_regs),
+};
+
+static struct cdns_torrent_vals usxgmii_pcie_xcvr_diag_ln_vals = {
+	.reg_pairs = usxgmii_pcie_xcvr_diag_ln_regs,
+	.num_regs = ARRAY_SIZE(usxgmii_pcie_xcvr_diag_ln_regs),
+};
+
+/*
+ * Multilink USXGMII, using PLL1, 156.25 MHz Ref clk, no SSC
+ */
+static struct cdns_reg_pairs ml_usxgmii_pll1_156_25_no_ssc_cmn_regs[] = {
+	{0x0028, CMN_PDIAG_PLL1_CP_PADJ_M0},
+	{0x0014, CMN_PLL1_DSM_FBH_OVRD_M0},
+	{0x0005, CMN_PLL1_DSM_FBL_OVRD_M0},
+	{0x061B, CMN_PLL1_VCOCAL_INIT_TMR},
+	{0x0019, CMN_PLL1_VCOCAL_ITER_TMR},
+	{0x1354, CMN_PLL1_VCOCAL_REFTIM_START},
+	{0x1354, CMN_PLL1_VCOCAL_PLLCNT_START},
+	{0x0003, CMN_PLL1_VCOCAL_TCTRL},
+	{0x0138, CMN_PLL1_LOCK_REFCNT_START},
+	{0x0138, CMN_PLL1_LOCK_PLLCNT_START},
+	{0x007F, CMN_TXPUCAL_TUNE},
+	{0x007F, CMN_TXPDCAL_TUNE}
+};
+
+static struct cdns_reg_pairs ml_usxgmii_156_25_no_ssc_tx_ln_regs[] = {
+	{0x00F3, TX_PSC_A0},
+	{0x04A2, TX_PSC_A2},
+	{0x04A2, TX_PSC_A3 },
+	{0x0000, TX_TXCC_CPOST_MULT_00},
+	{0x0000, XCVR_DIAG_PSC_OVRD}
+};
+
+static struct cdns_reg_pairs ml_usxgmii_156_25_no_ssc_rx_ln_regs[] = {
+	{0x091D, RX_PSC_A0},
+	{0x0900, RX_PSC_A2},
+	{0x0100, RX_PSC_A3},
+	{0x0030, RX_REE_SMGM_CTRL1},
+	{0x03C7, RX_REE_GCSM1_EQENM_PH1},
+	{0x01C7, RX_REE_GCSM1_EQENM_PH2},
+	{0x0000, RX_DIAG_DFE_CTRL},
+	{0x0019, RX_REE_TAP1_CLIP},
+	{0x0019, RX_REE_TAP2TON_CLIP},
+	{0x00B9, RX_DIAG_NQST_CTRL},
+	{0x0C21, RX_DIAG_DFE_AMP_TUNE_2},
+	{0x0002, RX_DIAG_DFE_AMP_TUNE_3},
+	{0x0033, RX_DIAG_PI_RATE},
+	{0x0001, RX_DIAG_ACYA},
+	{0x018C, RX_CDRLF_CNFG}
+};
+
+static struct cdns_torrent_vals ml_usxgmii_pll1_156_25_no_ssc_cmn_vals = {
+	.reg_pairs = ml_usxgmii_pll1_156_25_no_ssc_cmn_regs,
+	.num_regs = ARRAY_SIZE(ml_usxgmii_pll1_156_25_no_ssc_cmn_regs),
+};
+
+static struct cdns_torrent_vals ml_usxgmii_156_25_no_ssc_tx_ln_vals = {
+	.reg_pairs = ml_usxgmii_156_25_no_ssc_tx_ln_regs,
+	.num_regs = ARRAY_SIZE(ml_usxgmii_156_25_no_ssc_tx_ln_regs),
+};
+
+static struct cdns_torrent_vals ml_usxgmii_156_25_no_ssc_rx_ln_vals = {
+	.reg_pairs = ml_usxgmii_156_25_no_ssc_rx_ln_regs,
+	.num_regs = ARRAY_SIZE(ml_usxgmii_156_25_no_ssc_rx_ln_regs),
+};
+
+/* TI USXGMII configuration: Enable cmn_refclk_rcv_out_en */
+static struct cdns_reg_pairs ti_usxgmii_phy_pma_cmn_regs[] = {
+	{0x0040, PHY_PMA_CMN_CTRL1},
+};
+
+static struct cdns_torrent_vals ti_usxgmii_phy_pma_cmn_vals = {
+	.reg_pairs = ti_usxgmii_phy_pma_cmn_regs,
+	.num_regs = ARRAY_SIZE(ti_usxgmii_phy_pma_cmn_regs),
+};
+
+/* Single USXGMII link configuration */
+static struct cdns_reg_pairs sl_usxgmii_link_cmn_regs[] = {
+	{0x0000, PHY_PLL_CFG},
+	{0x0400, CMN_PDIAG_PLL0_CLK_SEL_M0}
+};
+
+static struct cdns_reg_pairs sl_usxgmii_xcvr_diag_ln_regs[] = {
+	{0x0000, XCVR_DIAG_HSCLK_SEL},
+	{0x0001, XCVR_DIAG_HSCLK_DIV},
+	{0x0001, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_torrent_vals sl_usxgmii_link_cmn_vals = {
+	.reg_pairs = sl_usxgmii_link_cmn_regs,
+	.num_regs = ARRAY_SIZE(sl_usxgmii_link_cmn_regs),
+};
+
+static struct cdns_torrent_vals sl_usxgmii_xcvr_diag_ln_vals = {
+	.reg_pairs = sl_usxgmii_xcvr_diag_ln_regs,
+	.num_regs = ARRAY_SIZE(sl_usxgmii_xcvr_diag_ln_regs),
+};
+
+/* Single link USXGMII, 156.25 MHz Ref clk, no SSC */
+static struct cdns_reg_pairs sl_usxgmii_156_25_no_ssc_cmn_regs[] = {
+	{0x0014, CMN_SSM_BIAS_TMR},
+	{0x0028, CMN_PLLSM0_PLLPRE_TMR},
+	{0x00A4, CMN_PLLSM0_PLLLOCK_TMR},
+	{0x0028, CMN_PLLSM1_PLLPRE_TMR},
+	{0x00A4, CMN_PLLSM1_PLLLOCK_TMR},
+	{0x0062, CMN_BGCAL_INIT_TMR},
+	{0x0062, CMN_BGCAL_ITER_TMR},
+	{0x0014, CMN_IBCAL_INIT_TMR},
+	{0x0018, CMN_TXPUCAL_INIT_TMR},
+	{0x0005, CMN_TXPUCAL_ITER_TMR},
+	{0x0018, CMN_TXPDCAL_INIT_TMR},
+	{0x0005, CMN_TXPDCAL_ITER_TMR},
+	{0x024A, CMN_RXCAL_INIT_TMR},
+	{0x0005, CMN_RXCAL_ITER_TMR},
+	{0x000B, CMN_SD_CAL_REFTIM_START},
+	{0x0132, CMN_SD_CAL_PLLCNT_START},
+	{0x0028, CMN_PDIAG_PLL1_CP_PADJ_M0},
+	{0x0014, CMN_PLL0_DSM_FBH_OVRD_M0},
+	{0x0014, CMN_PLL1_DSM_FBH_OVRD_M0},
+	{0x0005, CMN_PLL0_DSM_FBL_OVRD_M0},
+	{0x0005, CMN_PLL1_DSM_FBL_OVRD_M0},
+	{0x061B, CMN_PLL0_VCOCAL_INIT_TMR},
+	{0x061B, CMN_PLL1_VCOCAL_INIT_TMR},
+	{0x0019, CMN_PLL0_VCOCAL_ITER_TMR},
+	{0x0019, CMN_PLL1_VCOCAL_ITER_TMR},
+	{0x1354, CMN_PLL0_VCOCAL_REFTIM_START},
+	{0x1354, CMN_PLL1_VCOCAL_REFTIM_START},
+	{0x1354, CMN_PLL0_VCOCAL_PLLCNT_START},
+	{0x1354, CMN_PLL1_VCOCAL_PLLCNT_START},
+	{0x0003, CMN_PLL0_VCOCAL_TCTRL},
+	{0x0003, CMN_PLL1_VCOCAL_TCTRL},
+	{0x0138, CMN_PLL0_LOCK_REFCNT_START},
+	{0x0138, CMN_PLL1_LOCK_REFCNT_START},
+	{0x0138, CMN_PLL0_LOCK_PLLCNT_START},
+	{0x0138, CMN_PLL1_LOCK_PLLCNT_START}
+};
+
+static struct cdns_reg_pairs usxgmii_156_25_no_ssc_tx_ln_regs[] = {
+	{0x07A2, TX_RCVDET_ST_TMR},
+	{0x00F3, TX_PSC_A0},
+	{0x04A2, TX_PSC_A2},
+	{0x04A2, TX_PSC_A3},
+	{0x0000, TX_TXCC_CPOST_MULT_00},
+	{0x0000, XCVR_DIAG_PSC_OVRD}
+};
+
+static struct cdns_reg_pairs usxgmii_156_25_no_ssc_rx_ln_regs[] = {
+	{0x0014, RX_SDCAL0_INIT_TMR},
+	{0x0062, RX_SDCAL0_ITER_TMR},
+	{0x0014, RX_SDCAL1_INIT_TMR},
+	{0x0062, RX_SDCAL1_ITER_TMR},
+	{0x091D, RX_PSC_A0},
+	{0x0900, RX_PSC_A2},
+	{0x0100, RX_PSC_A3},
+	{0x0030, RX_REE_SMGM_CTRL1},
+	{0x03C7, RX_REE_GCSM1_EQENM_PH1},
+	{0x01C7, RX_REE_GCSM1_EQENM_PH2},
+	{0x0000, RX_DIAG_DFE_CTRL},
+	{0x0019, RX_REE_TAP1_CLIP},
+	{0x0019, RX_REE_TAP2TON_CLIP},
+	{0x00B9, RX_DIAG_NQST_CTRL},
+	{0x0C21, RX_DIAG_DFE_AMP_TUNE_2},
+	{0x0002, RX_DIAG_DFE_AMP_TUNE_3},
+	{0x0033, RX_DIAG_PI_RATE},
+	{0x0001, RX_DIAG_ACYA},
+	{0x018C, RX_CDRLF_CNFG}
+};
+
+static struct cdns_torrent_vals sl_usxgmii_156_25_no_ssc_cmn_vals = {
+	.reg_pairs = sl_usxgmii_156_25_no_ssc_cmn_regs,
+	.num_regs = ARRAY_SIZE(sl_usxgmii_156_25_no_ssc_cmn_regs),
+};
+
+static struct cdns_torrent_vals usxgmii_156_25_no_ssc_tx_ln_vals = {
+	.reg_pairs = usxgmii_156_25_no_ssc_tx_ln_regs,
+	.num_regs = ARRAY_SIZE(usxgmii_156_25_no_ssc_tx_ln_regs),
+};
+
+static struct cdns_torrent_vals usxgmii_156_25_no_ssc_rx_ln_vals = {
+	.reg_pairs = usxgmii_156_25_no_ssc_rx_ln_regs,
+	.num_regs = ARRAY_SIZE(usxgmii_156_25_no_ssc_rx_ln_regs),
+};
+
+/* PCIe and DP link configuration */
+static struct cdns_reg_pairs pcie_dp_link_cmn_regs[] = {
+	{0x0003, PHY_PLL_CFG},
+	{0x0601, CMN_PDIAG_PLL0_CLK_SEL_M0},
+	{0x0400, CMN_PDIAG_PLL0_CLK_SEL_M1}
+};
+
+static struct cdns_reg_pairs pcie_dp_xcvr_diag_ln_regs[] = {
+	{0x0000, XCVR_DIAG_HSCLK_SEL},
+	{0x0001, XCVR_DIAG_HSCLK_DIV},
+	{0x0012, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_reg_pairs dp_pcie_xcvr_diag_ln_regs[] = {
+	{0x0001, XCVR_DIAG_HSCLK_SEL},
+	{0x0009, XCVR_DIAG_PLLDRC_CTRL}
+};
+
+static struct cdns_torrent_vals pcie_dp_link_cmn_vals = {
+	.reg_pairs = pcie_dp_link_cmn_regs,
+	.num_regs = ARRAY_SIZE(pcie_dp_link_cmn_regs),
+};
+
+static struct cdns_torrent_vals pcie_dp_xcvr_diag_ln_vals = {
+	.reg_pairs = pcie_dp_xcvr_diag_ln_regs,
+	.num_regs = ARRAY_SIZE(pcie_dp_xcvr_diag_ln_regs),
+};
+
+static struct cdns_torrent_vals dp_pcie_xcvr_diag_ln_vals = {
+	.reg_pairs = dp_pcie_xcvr_diag_ln_regs,
+	.num_regs = ARRAY_SIZE(dp_pcie_xcvr_diag_ln_regs),
+};
+
+/* DP Multilink, 100 MHz Ref clk, no SSC */
+static struct cdns_reg_pairs dp_100_no_ssc_cmn_regs[] = {
+	{0x007F, CMN_TXPUCAL_TUNE},
+	{0x007F, CMN_TXPDCAL_TUNE}
+};
+
+static struct cdns_reg_pairs dp_100_no_ssc_tx_ln_regs[] = {
+	{0x00FB, TX_PSC_A0},
+	{0x04AA, TX_PSC_A2},
+	{0x04AA, TX_PSC_A3},
+	{0x000F, XCVR_DIAG_BIDI_CTRL}
+};
+
+static struct cdns_reg_pairs dp_100_no_ssc_rx_ln_regs[] = {
+	{0x0000, RX_PSC_A0},
+	{0x0000, RX_PSC_A2},
+	{0x0000, RX_PSC_A3},
+	{0x0000, RX_PSC_CAL},
+	{0x0000, RX_REE_GCSM1_CTRL},
+	{0x0000, RX_REE_GCSM2_CTRL},
+	{0x0000, RX_REE_PERGCSM_CTRL}
+};
+
+static struct cdns_torrent_vals dp_100_no_ssc_cmn_vals = {
+	.reg_pairs = dp_100_no_ssc_cmn_regs,
+	.num_regs = ARRAY_SIZE(dp_100_no_ssc_cmn_regs),
+};
+
+static struct cdns_torrent_vals dp_100_no_ssc_tx_ln_vals = {
+	.reg_pairs = dp_100_no_ssc_tx_ln_regs,
+	.num_regs = ARRAY_SIZE(dp_100_no_ssc_tx_ln_regs),
+};
+
+static struct cdns_torrent_vals dp_100_no_ssc_rx_ln_vals = {
+	.reg_pairs = dp_100_no_ssc_rx_ln_regs,
+	.num_regs = ARRAY_SIZE(dp_100_no_ssc_rx_ln_regs),
+};
+
 /* Single DisplayPort(DP) link configuration */
 static struct cdns_reg_pairs sl_dp_link_cmn_regs[] = {
 	{0x0000, PHY_PLL_CFG},
@@ -3384,6 +4093,50 @@
 	.num_regs = ARRAY_SIZE(sgmii_100_no_ssc_rx_ln_regs),
 };
 
+/* TI J7200, multilink SGMII */
+static struct cdns_reg_pairs j7200_sgmii_100_no_ssc_tx_ln_regs[] = {
+	{0x07A2, TX_RCVDET_ST_TMR},
+	{0x00F3, TX_PSC_A0},
+	{0x04A2, TX_PSC_A2},
+	{0x04A2, TX_PSC_A3 },
+	{0x0000, TX_TXCC_CPOST_MULT_00},
+	{0x00B3, DRV_DIAG_TX_DRV},
+	{0x0002, XCVR_DIAG_PSC_OVRD},
+	{0x4000, XCVR_DIAG_RXCLK_CTRL}
+};
+
+static struct cdns_torrent_vals j7200_sgmii_100_no_ssc_tx_ln_vals = {
+	.reg_pairs = j7200_sgmii_100_no_ssc_tx_ln_regs,
+	.num_regs = ARRAY_SIZE(j7200_sgmii_100_no_ssc_tx_ln_regs),
+};
+
+static struct cdns_reg_pairs j7200_sgmii_100_no_ssc_rx_ln_regs[] = {
+	{0x0014, RX_SDCAL0_INIT_TMR},
+	{0x0062, RX_SDCAL0_ITER_TMR},
+	{0x0014, RX_SDCAL1_INIT_TMR},
+	{0x0062, RX_SDCAL1_ITER_TMR},
+	{0x091D, RX_PSC_A0},
+	{0x0900, RX_PSC_A2},
+	{0x0100, RX_PSC_A3},
+	{0x03C7, RX_REE_GCSM1_EQENM_PH1},
+	{0x01C7, RX_REE_GCSM1_EQENM_PH2},
+	{0x0000, RX_DIAG_DFE_CTRL},
+	{0x0019, RX_REE_TAP1_CLIP},
+	{0x0019, RX_REE_TAP2TON_CLIP},
+	{0x0098, RX_DIAG_NQST_CTRL},
+	{0x0C01, RX_DIAG_DFE_AMP_TUNE_2},
+	{0x0000, RX_DIAG_DFE_AMP_TUNE_3},
+	{0x0000, RX_DIAG_PI_CAP},
+	{0x0010, RX_DIAG_PI_RATE},
+	{0x0001, RX_DIAG_ACYA},
+	{0x018C, RX_CDRLF_CNFG}
+};
+
+static struct cdns_torrent_vals j7200_sgmii_100_no_ssc_rx_ln_vals = {
+	.reg_pairs = j7200_sgmii_100_no_ssc_rx_ln_regs,
+	.num_regs = ARRAY_SIZE(j7200_sgmii_100_no_ssc_rx_ln_regs),
+};
+
 /* SGMII 100 MHz Ref clk, internal SSC */
 static struct cdns_reg_pairs sgmii_100_int_ssc_cmn_regs[] = {
 	{0x0004, CMN_PLL0_DSM_DIAG_M0},
@@ -3517,6 +4270,51 @@
 	.num_regs = ARRAY_SIZE(qsgmii_100_no_ssc_rx_ln_regs),
 };
 
+/* TI J7200, multilink QSGMII */
+static struct cdns_reg_pairs j7200_qsgmii_100_no_ssc_tx_ln_regs[] = {
+	{0x07A2, TX_RCVDET_ST_TMR},
+	{0x00F3, TX_PSC_A0},
+	{0x04A2, TX_PSC_A2},
+	{0x04A2, TX_PSC_A3 },
+	{0x0000, TX_TXCC_CPOST_MULT_00},
+	{0x0011, TX_TXCC_MGNFS_MULT_100},
+	{0x0003, DRV_DIAG_TX_DRV},
+	{0x0002, XCVR_DIAG_PSC_OVRD},
+	{0x4000, XCVR_DIAG_RXCLK_CTRL}
+};
+
+static struct cdns_torrent_vals j7200_qsgmii_100_no_ssc_tx_ln_vals = {
+	.reg_pairs = j7200_qsgmii_100_no_ssc_tx_ln_regs,
+	.num_regs = ARRAY_SIZE(j7200_qsgmii_100_no_ssc_tx_ln_regs),
+};
+
+static struct cdns_reg_pairs j7200_qsgmii_100_no_ssc_rx_ln_regs[] = {
+	{0x0014, RX_SDCAL0_INIT_TMR},
+	{0x0062, RX_SDCAL0_ITER_TMR},
+	{0x0014, RX_SDCAL1_INIT_TMR},
+	{0x0062, RX_SDCAL1_ITER_TMR},
+	{0x091D, RX_PSC_A0},
+	{0x0900, RX_PSC_A2},
+	{0x0100, RX_PSC_A3},
+	{0x03C7, RX_REE_GCSM1_EQENM_PH1},
+	{0x01C7, RX_REE_GCSM1_EQENM_PH2},
+	{0x0000, RX_DIAG_DFE_CTRL},
+	{0x0019, RX_REE_TAP1_CLIP},
+	{0x0019, RX_REE_TAP2TON_CLIP},
+	{0x0098, RX_DIAG_NQST_CTRL},
+	{0x0C01, RX_DIAG_DFE_AMP_TUNE_2},
+	{0x0000, RX_DIAG_DFE_AMP_TUNE_3},
+	{0x0000, RX_DIAG_PI_CAP},
+	{0x0010, RX_DIAG_PI_RATE},
+	{0x0001, RX_DIAG_ACYA},
+	{0x018C, RX_CDRLF_CNFG}
+};
+
+static struct cdns_torrent_vals j7200_qsgmii_100_no_ssc_rx_ln_vals = {
+	.reg_pairs = j7200_qsgmii_100_no_ssc_rx_ln_regs,
+	.num_regs = ARRAY_SIZE(j7200_qsgmii_100_no_ssc_rx_ln_regs),
+};
+
 /* QSGMII 100 MHz Ref clk, internal SSC */
 static struct cdns_reg_pairs qsgmii_100_int_ssc_cmn_regs[] = {
 	{0x0004, CMN_PLL0_DSM_DIAG_M0},
@@ -3729,967 +4527,728 @@
 	.num_regs = ARRAY_SIZE(pcie_100_ext_no_ssc_rx_ln_regs),
 };
 
+static struct cdns_torrent_vals_entry link_cmn_vals_entries[] = {
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_DP, TYPE_NONE), &sl_dp_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_DP, TYPE_PCIE), &pcie_dp_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_DP, TYPE_USB), &usb_dp_link_cmn_vals},
+
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_NONE), NULL},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_SGMII), &pcie_sgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_QSGMII), &pcie_sgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_USB), &pcie_usb_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_DP), &pcie_dp_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_USXGMII), &pcie_usxgmii_link_cmn_vals},
+
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_NONE), &sl_sgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_PCIE), &pcie_sgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_USB), &usb_sgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_USXGMII), &usxgmii_sgmii_link_cmn_vals},
+
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_NONE), &sl_sgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_PCIE), &pcie_sgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_USB), &usb_sgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_USXGMII), &usxgmii_sgmii_link_cmn_vals},
+
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_NONE), &sl_usb_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_PCIE), &pcie_usb_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_SGMII), &usb_sgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_QSGMII), &usb_sgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_DP), &usb_dp_link_cmn_vals},
+
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_NONE), &sl_usxgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_PCIE), &pcie_usxgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_SGMII), &usxgmii_sgmii_link_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_QSGMII), &usxgmii_sgmii_link_cmn_vals},
+};
+
+static struct cdns_torrent_vals_entry xcvr_diag_vals_entries[] = {
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_DP, TYPE_NONE), &sl_dp_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_DP, TYPE_PCIE), &dp_pcie_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_DP, TYPE_USB), &dp_usb_xcvr_diag_ln_vals},
+
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_NONE), NULL},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_SGMII), &pcie_sgmii_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_QSGMII), &pcie_sgmii_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_USB), &pcie_usb_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_DP), &pcie_dp_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_PCIE, TYPE_USXGMII), &pcie_usxgmii_xcvr_diag_ln_vals},
+
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_NONE), &sl_sgmii_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_PCIE), &sgmii_pcie_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_USB), &sgmii_usb_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_SGMII, TYPE_USXGMII), &sgmii_usxgmii_xcvr_diag_ln_vals},
+
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_NONE), &sl_sgmii_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_PCIE), &sgmii_pcie_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_USB), &sgmii_usb_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_QSGMII, TYPE_USXGMII), &sgmii_usxgmii_xcvr_diag_ln_vals},
+
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_NONE), &sl_usb_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_PCIE), &usb_pcie_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_SGMII), &usb_sgmii_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_QSGMII), &usb_sgmii_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_DP), &usb_dp_xcvr_diag_ln_vals},
+
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_NONE), &sl_usxgmii_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_PCIE), &usxgmii_pcie_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_SGMII), &usxgmii_sgmii_xcvr_diag_ln_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_QSGMII), &usxgmii_sgmii_xcvr_diag_ln_vals},
+};
+
+static struct cdns_torrent_vals_entry pcs_cmn_vals_entries[] = {
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_NONE), &usb_phy_pcs_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_PCIE), &usb_phy_pcs_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_SGMII), &usb_phy_pcs_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_QSGMII), &usb_phy_pcs_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USB, TYPE_DP), &usb_phy_pcs_cmn_vals},
+};
+
+static struct cdns_torrent_vals_entry cmn_vals_entries[] = {
+	{CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_PCIE, NO_SSC), &dp_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_USB, NO_SSC), &sl_dp_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, INTERNAL_SSC), &sl_pcie_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, NO_SSC), &pcie_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, EXTERNAL_SSC), &pcie_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, INTERNAL_SSC), &pcie_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, NO_SSC), &pcie_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, EXTERNAL_SSC), &pcie_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, INTERNAL_SSC), &pcie_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, NO_SSC), &pcie_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, EXTERNAL_SSC), &pcie_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, INTERNAL_SSC), &pcie_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_NONE, NO_SSC), &sl_sgmii_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, NO_SSC), &sgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_NONE, NO_SSC), &sl_qsgmii_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, NO_SSC), &qsgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, NO_SSC), &sl_usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, EXTERNAL_SSC), &sl_usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, INTERNAL_SSC), &sl_usb_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, NO_SSC), &usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, EXTERNAL_SSC), &usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, INTERNAL_SSC), &usb_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, NO_SSC), &sl_usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, EXTERNAL_SSC), &sl_usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, INTERNAL_SSC), &sl_usb_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, NO_SSC), &sl_usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, EXTERNAL_SSC), &sl_usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, INTERNAL_SSC), &sl_usb_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &sl_usxgmii_156_25_no_ssc_cmn_vals},
+
+	/* Dual refclk */
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &ml_sgmii_pll1_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &ml_sgmii_pll1_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_pll1_156_25_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &ml_usxgmii_pll0_156_25_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &ml_usxgmii_pll0_156_25_no_ssc_cmn_vals},
+};
+
+static struct cdns_torrent_vals_entry cdns_tx_ln_vals_entries[] = {
+	{CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_PCIE, NO_SSC), &dp_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_USB, NO_SSC), &dp_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, INTERNAL_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, INTERNAL_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, INTERNAL_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, INTERNAL_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_NONE, NO_SSC), &sgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, NO_SSC), &sgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_NONE, NO_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, NO_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
+
+	/* Dual refclk */
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &sgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &qsgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
+};
+
+static struct cdns_torrent_vals_entry cdns_rx_ln_vals_entries[] = {
+	{CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_PCIE, NO_SSC), &dp_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_USB, NO_SSC), &dp_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_NONE, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_NONE, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, EXTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, INTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, EXTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, INTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, EXTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, INTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, EXTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, INTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_rx_ln_vals},
+
+	/* Dual refclk */
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_156_25_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &ml_usxgmii_156_25_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &ml_usxgmii_156_25_no_ssc_rx_ln_vals},
+};
+
 static const struct cdns_torrent_data cdns_map_torrent = {
 	.block_offset_shift = 0x2,
 	.reg_offset_shift = 0x2,
-	.link_cmn_vals = {
-		[TYPE_DP] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_dp_link_cmn_vals,
-			},
-		},
-		[TYPE_PCIE] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = NULL,
-				[EXTERNAL_SSC] = NULL,
-				[INTERNAL_SSC] = NULL,
-			},
-			[TYPE_SGMII] = {
-				[NO_SSC] = &pcie_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-			},
-			[TYPE_QSGMII] = {
-				[NO_SSC] = &pcie_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-			},
-			[TYPE_USB] = {
-				[NO_SSC] = &pcie_usb_link_cmn_vals,
-				[EXTERNAL_SSC] = &pcie_usb_link_cmn_vals,
-				[INTERNAL_SSC] = &pcie_usb_link_cmn_vals,
-			},
-		},
-		[TYPE_SGMII] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_sgmii_link_cmn_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &pcie_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-			},
-			[TYPE_USB] = {
-				[NO_SSC] = &usb_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-			},
-		},
-		[TYPE_QSGMII] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_sgmii_link_cmn_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &pcie_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-			},
-			[TYPE_USB] = {
-				[NO_SSC] = &usb_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-			},
-		},
-		[TYPE_USB] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_usb_link_cmn_vals,
-				[EXTERNAL_SSC] = &sl_usb_link_cmn_vals,
-				[INTERNAL_SSC] = &sl_usb_link_cmn_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &pcie_usb_link_cmn_vals,
-				[EXTERNAL_SSC] = &pcie_usb_link_cmn_vals,
-				[INTERNAL_SSC] = &pcie_usb_link_cmn_vals,
-			},
-			[TYPE_SGMII] = {
-				[NO_SSC] = &usb_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-			},
-			[TYPE_QSGMII] = {
-				[NO_SSC] = &usb_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-			},
-		},
+	.link_cmn_vals_tbl = {
+		.entries = link_cmn_vals_entries,
+		.num_entries = ARRAY_SIZE(link_cmn_vals_entries),
 	},
-	.xcvr_diag_vals = {
-		[TYPE_DP] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_dp_xcvr_diag_ln_vals,
-			},
-		},
-		[TYPE_PCIE] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = NULL,
-				[EXTERNAL_SSC] = NULL,
-				[INTERNAL_SSC] = NULL,
-			},
-			[TYPE_SGMII] = {
-				[NO_SSC] = &pcie_sgmii_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals,
-			},
-			[TYPE_QSGMII] = {
-				[NO_SSC] = &pcie_sgmii_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals,
-			},
-			[TYPE_USB] = {
-				[NO_SSC] = &pcie_usb_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals,
-			},
-		},
-		[TYPE_SGMII] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_sgmii_xcvr_diag_ln_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &sgmii_pcie_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals,
-			},
-			[TYPE_USB] = {
-				[NO_SSC] = &sgmii_usb_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals,
-			},
-		},
-		[TYPE_QSGMII] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_sgmii_xcvr_diag_ln_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &sgmii_pcie_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals,
-			},
-			[TYPE_USB] = {
-				[NO_SSC] = &sgmii_usb_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals,
-			},
-		},
-		[TYPE_USB] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_usb_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &sl_usb_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &sl_usb_xcvr_diag_ln_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &usb_pcie_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &usb_pcie_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &usb_pcie_xcvr_diag_ln_vals,
-			},
-			[TYPE_SGMII] = {
-				[NO_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
-			},
-			[TYPE_QSGMII] = {
-				[NO_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
-			},
-		},
+	.xcvr_diag_vals_tbl = {
+		.entries = xcvr_diag_vals_entries,
+		.num_entries = ARRAY_SIZE(xcvr_diag_vals_entries),
 	},
-	.pcs_cmn_vals = {
-		[TYPE_USB] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &usb_phy_pcs_cmn_vals,
-				[EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-				[INTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &usb_phy_pcs_cmn_vals,
-				[EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-				[INTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-			},
-			[TYPE_SGMII] = {
-				[NO_SSC] = &usb_phy_pcs_cmn_vals,
-				[EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-				[INTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-			},
-			[TYPE_QSGMII] = {
-				[NO_SSC] = &usb_phy_pcs_cmn_vals,
-				[EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-				[INTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-			},
-		},
+	.pcs_cmn_vals_tbl = {
+		.entries = pcs_cmn_vals_entries,
+		.num_entries = ARRAY_SIZE(pcs_cmn_vals_entries),
 	},
-	.cmn_vals = {
-		[CLK_19_2_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_19_2_no_ssc_cmn_vals,
-				},
-			},
-		},
-		[CLK_25_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_25_no_ssc_cmn_vals,
-				},
-			},
-		},
-		[CLK_100_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_100_no_ssc_cmn_vals,
-				},
-			},
-			[TYPE_PCIE] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = NULL,
-					[EXTERNAL_SSC] = NULL,
-					[INTERNAL_SSC] = &sl_pcie_100_int_ssc_cmn_vals,
-				},
-				[TYPE_SGMII] = {
-					[NO_SSC] = &pcie_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
-				},
-				[TYPE_QSGMII] = {
-					[NO_SSC] = &pcie_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &pcie_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
-				},
-			},
-			[TYPE_SGMII] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_sgmii_100_no_ssc_cmn_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &sgmii_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &sgmii_100_int_ssc_cmn_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &sgmii_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
-				},
-			},
-			[TYPE_QSGMII] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_qsgmii_100_no_ssc_cmn_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &qsgmii_100_int_ssc_cmn_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
-				},
-			},
-			[TYPE_USB] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &usb_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &usb_100_int_ssc_cmn_vals,
-				},
-				[TYPE_SGMII] = {
-					[NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
-				},
-				[TYPE_QSGMII] = {
-					[NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
-				},
-			},
-		},
+	.cmn_vals_tbl = {
+		.entries = cmn_vals_entries,
+		.num_entries = ARRAY_SIZE(cmn_vals_entries),
 	},
-	.tx_ln_vals = {
-		[CLK_19_2_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_19_2_no_ssc_tx_ln_vals,
-				},
-			},
-		},
-		[CLK_25_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_25_no_ssc_tx_ln_vals,
-				},
-			},
-		},
-		[CLK_100_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals,
-				},
-			},
-			[TYPE_PCIE] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = NULL,
-					[EXTERNAL_SSC] = NULL,
-					[INTERNAL_SSC] = NULL,
-				},
-				[TYPE_SGMII] = {
-					[NO_SSC] = NULL,
-					[EXTERNAL_SSC] = NULL,
-					[INTERNAL_SSC] = NULL,
-				},
-				[TYPE_QSGMII] = {
-					[NO_SSC] = NULL,
-					[EXTERNAL_SSC] = NULL,
-					[INTERNAL_SSC] = NULL,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = NULL,
-					[EXTERNAL_SSC] = NULL,
-					[INTERNAL_SSC] = NULL,
-				},
-			},
-			[TYPE_SGMII] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &sgmii_100_no_ssc_tx_ln_vals,
-				},
-			},
-			[TYPE_QSGMII] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &qsgmii_100_no_ssc_tx_ln_vals,
-				},
-			},
-			[TYPE_USB] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_SGMII] = {
-					[NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_QSGMII] = {
-					[NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-				},
-			},
-		},
+	.tx_ln_vals_tbl = {
+		.entries = cdns_tx_ln_vals_entries,
+		.num_entries = ARRAY_SIZE(cdns_tx_ln_vals_entries),
 	},
-	.rx_ln_vals = {
-		[CLK_19_2_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_19_2_no_ssc_rx_ln_vals,
-				},
-			},
-		},
-		[CLK_25_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_25_no_ssc_rx_ln_vals,
-				},
-			},
-		},
-		[CLK_100_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals,
-				},
-			},
-			[TYPE_PCIE] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_SGMII] = {
-					[NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_QSGMII] = {
-					[NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-				},
-			},
-			[TYPE_SGMII] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-				},
-			},
-			[TYPE_QSGMII] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-				},
-			},
-			[TYPE_USB] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_SGMII] = {
-					[NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_QSGMII] = {
-					[NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-				},
-			},
-		},
+	.rx_ln_vals_tbl = {
+		.entries = cdns_rx_ln_vals_entries,
+		.num_entries = ARRAY_SIZE(cdns_rx_ln_vals_entries),
 	},
 };
 
+static struct cdns_torrent_vals_entry j721e_phy_pma_cmn_vals_entries[] = {
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_NONE), &ti_usxgmii_phy_pma_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_PCIE), &ti_usxgmii_phy_pma_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_SGMII), &ti_usxgmii_phy_pma_cmn_vals},
+	{CDNS_TORRENT_KEY_ANYCLK(TYPE_USXGMII, TYPE_QSGMII), &ti_usxgmii_phy_pma_cmn_vals},
+};
+
+static struct cdns_torrent_vals_entry ti_tx_ln_vals_entries[] = {
+	{CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_PCIE, NO_SSC), &dp_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_USB, NO_SSC), &dp_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, INTERNAL_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, INTERNAL_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, INTERNAL_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, INTERNAL_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_NONE, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_NONE, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
+
+	/* Dual refclk */
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
+};
+
 static const struct cdns_torrent_data ti_j721e_map_torrent = {
 	.block_offset_shift = 0x0,
 	.reg_offset_shift = 0x1,
-	.link_cmn_vals = {
-		[TYPE_DP] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_dp_link_cmn_vals,
-			},
-		},
-		[TYPE_PCIE] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = NULL,
-				[EXTERNAL_SSC] = NULL,
-				[INTERNAL_SSC] = NULL,
-			},
-			[TYPE_SGMII] = {
-				[NO_SSC] = &pcie_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-			},
-			[TYPE_QSGMII] = {
-				[NO_SSC] = &pcie_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-			},
-			[TYPE_USB] = {
-				[NO_SSC] = &pcie_usb_link_cmn_vals,
-				[EXTERNAL_SSC] = &pcie_usb_link_cmn_vals,
-				[INTERNAL_SSC] = &pcie_usb_link_cmn_vals,
-			},
-		},
-		[TYPE_SGMII] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_sgmii_link_cmn_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &pcie_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-			},
-			[TYPE_USB] = {
-				[NO_SSC] = &usb_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-			},
-		},
-		[TYPE_QSGMII] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_sgmii_link_cmn_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &pcie_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &pcie_sgmii_link_cmn_vals,
-			},
-			[TYPE_USB] = {
-				[NO_SSC] = &usb_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-			},
-		},
-		[TYPE_USB] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_usb_link_cmn_vals,
-				[EXTERNAL_SSC] = &sl_usb_link_cmn_vals,
-				[INTERNAL_SSC] = &sl_usb_link_cmn_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &pcie_usb_link_cmn_vals,
-				[EXTERNAL_SSC] = &pcie_usb_link_cmn_vals,
-				[INTERNAL_SSC] = &pcie_usb_link_cmn_vals,
-			},
-			[TYPE_SGMII] = {
-				[NO_SSC] = &usb_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-			},
-			[TYPE_QSGMII] = {
-				[NO_SSC] = &usb_sgmii_link_cmn_vals,
-				[EXTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-				[INTERNAL_SSC] = &usb_sgmii_link_cmn_vals,
-			},
-		},
+	.link_cmn_vals_tbl = {
+		.entries = link_cmn_vals_entries,
+		.num_entries = ARRAY_SIZE(link_cmn_vals_entries),
+	},
+	.xcvr_diag_vals_tbl = {
+		.entries = xcvr_diag_vals_entries,
+		.num_entries = ARRAY_SIZE(xcvr_diag_vals_entries),
+	},
+	.pcs_cmn_vals_tbl = {
+		.entries = pcs_cmn_vals_entries,
+		.num_entries = ARRAY_SIZE(pcs_cmn_vals_entries),
+	},
+	.phy_pma_cmn_vals_tbl = {
+		.entries = j721e_phy_pma_cmn_vals_entries,
+		.num_entries = ARRAY_SIZE(j721e_phy_pma_cmn_vals_entries),
+	},
+	.cmn_vals_tbl = {
+		.entries = cmn_vals_entries,
+		.num_entries = ARRAY_SIZE(cmn_vals_entries),
+	},
+	.tx_ln_vals_tbl = {
+		.entries = ti_tx_ln_vals_entries,
+		.num_entries = ARRAY_SIZE(ti_tx_ln_vals_entries),
+	},
+	.rx_ln_vals_tbl = {
+		.entries = cdns_rx_ln_vals_entries,
+		.num_entries = ARRAY_SIZE(cdns_rx_ln_vals_entries),
+	},
+};
+
+/* TI J7200 (Torrent SD0805) */
+static struct cdns_torrent_vals_entry ti_j7200_cmn_vals_entries[] = {
+	{CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_PCIE, NO_SSC), &dp_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_USB, NO_SSC), &sl_dp_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, INTERNAL_SSC), &sl_pcie_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, NO_SSC), &pcie_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, EXTERNAL_SSC), &pcie_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, INTERNAL_SSC), &pcie_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, NO_SSC), &pcie_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, EXTERNAL_SSC), &pcie_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, INTERNAL_SSC), &pcie_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, NO_SSC), &pcie_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, EXTERNAL_SSC), &pcie_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, INTERNAL_SSC), &pcie_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_NONE, NO_SSC), &sl_sgmii_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, NO_SSC), &sgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_NONE, NO_SSC), &sl_qsgmii_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, NO_SSC), &qsgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, NO_SSC), &sl_usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, EXTERNAL_SSC), &sl_usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, INTERNAL_SSC), &sl_usb_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, NO_SSC), &usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, EXTERNAL_SSC), &usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, INTERNAL_SSC), &usb_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, NO_SSC), &sl_usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, EXTERNAL_SSC), &sl_usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, INTERNAL_SSC), &sl_usb_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, NO_SSC), &sl_usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, EXTERNAL_SSC), &sl_usb_100_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, INTERNAL_SSC), &sl_usb_100_int_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &sl_usxgmii_156_25_no_ssc_cmn_vals},
+
+	/* Dual refclk */
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &j7200_ml_sgmii_pll1_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &j7200_ml_sgmii_pll1_100_no_ssc_cmn_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_pll1_156_25_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &j7200_ml_usxgmii_pll0_156_25_no_ssc_cmn_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &j7200_ml_usxgmii_pll0_156_25_no_ssc_cmn_vals},
+};
+
+static struct cdns_torrent_vals_entry ti_j7200_tx_ln_vals_entries[] = {
+	{CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_PCIE, NO_SSC), &dp_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_USB, NO_SSC), &dp_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, INTERNAL_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, INTERNAL_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, INTERNAL_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, NO_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, EXTERNAL_SSC), NULL},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, INTERNAL_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_NONE, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &ti_sgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_NONE, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &ti_qsgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, EXTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, INTERNAL_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
+
+	/* Dual refclk */
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), NULL},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &j7200_sgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &j7200_qsgmii_100_no_ssc_tx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_156_25_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &usxgmii_156_25_no_ssc_tx_ln_vals},
+};
+
+static struct cdns_torrent_vals_entry ti_j7200_rx_ln_vals_entries[] = {
+	{CDNS_TORRENT_KEY(CLK_19_2_MHZ, CLK_19_2_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_19_2_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_25_MHZ, CLK_25_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_25_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_NONE, NO_SSC), &sl_dp_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_PCIE, NO_SSC), &dp_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_DP, TYPE_USB, NO_SSC), &dp_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_NONE, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_SGMII, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_QSGMII, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, EXTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_USB, INTERNAL_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_PCIE, TYPE_DP, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_NONE, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, EXTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_PCIE, INTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, NO_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, EXTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_SGMII, TYPE_USB, INTERNAL_SSC), &sgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_NONE, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, EXTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_PCIE, INTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, NO_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, EXTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_QSGMII, TYPE_USB, INTERNAL_SSC), &qsgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, EXTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_NONE, INTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, EXTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_PCIE, INTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, EXTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_SGMII, INTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, EXTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_QSGMII, INTERNAL_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_100_MHZ, TYPE_USB, TYPE_DP, NO_SSC), &usb_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_156_25_MHZ, TYPE_USXGMII, TYPE_NONE, NO_SSC), &usxgmii_156_25_no_ssc_rx_ln_vals},
+
+	/* Dual refclk */
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_PCIE, TYPE_USXGMII, NO_SSC), &pcie_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_SGMII, TYPE_USXGMII, NO_SSC), &j7200_sgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_100_MHZ, CLK_156_25_MHZ, TYPE_QSGMII, TYPE_USXGMII, NO_SSC), &j7200_qsgmii_100_no_ssc_rx_ln_vals},
+
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_PCIE, NO_SSC), &ml_usxgmii_156_25_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_SGMII, NO_SSC), &usxgmii_156_25_no_ssc_rx_ln_vals},
+	{CDNS_TORRENT_KEY(CLK_156_25_MHZ, CLK_100_MHZ, TYPE_USXGMII, TYPE_QSGMII, NO_SSC), &usxgmii_156_25_no_ssc_rx_ln_vals},
+};
+
+static const struct cdns_torrent_data ti_j7200_map_torrent = {
+	.block_offset_shift = 0x0,
+	.reg_offset_shift = 0x1,
+	.link_cmn_vals_tbl = {
+		.entries = link_cmn_vals_entries,
+		.num_entries = ARRAY_SIZE(link_cmn_vals_entries),
+	},
+	.xcvr_diag_vals_tbl = {
+		.entries = xcvr_diag_vals_entries,
+		.num_entries = ARRAY_SIZE(xcvr_diag_vals_entries),
 	},
-	.xcvr_diag_vals = {
-		[TYPE_DP] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_dp_xcvr_diag_ln_vals,
-			},
-		},
-		[TYPE_PCIE] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = NULL,
-				[EXTERNAL_SSC] = NULL,
-				[INTERNAL_SSC] = NULL,
-			},
-			[TYPE_SGMII] = {
-				[NO_SSC] = &pcie_sgmii_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals,
-			},
-			[TYPE_QSGMII] = {
-				[NO_SSC] = &pcie_sgmii_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &pcie_sgmii_xcvr_diag_ln_vals,
-			},
-			[TYPE_USB] = {
-				[NO_SSC] = &pcie_usb_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &pcie_usb_xcvr_diag_ln_vals,
-			},
-		},
-		[TYPE_SGMII] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_sgmii_xcvr_diag_ln_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &sgmii_pcie_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals,
-			},
-			[TYPE_USB] = {
-				[NO_SSC] = &sgmii_usb_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals,
-			},
-		},
-		[TYPE_QSGMII] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_sgmii_xcvr_diag_ln_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &sgmii_pcie_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &sgmii_pcie_xcvr_diag_ln_vals,
-			},
-			[TYPE_USB] = {
-				[NO_SSC] = &sgmii_usb_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &sgmii_usb_xcvr_diag_ln_vals,
-			},
-		},
-		[TYPE_USB] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &sl_usb_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &sl_usb_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &sl_usb_xcvr_diag_ln_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &usb_pcie_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &usb_pcie_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &usb_pcie_xcvr_diag_ln_vals,
-			},
-			[TYPE_SGMII] = {
-				[NO_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
-			},
-			[TYPE_QSGMII] = {
-				[NO_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
-				[EXTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
-				[INTERNAL_SSC] = &usb_sgmii_xcvr_diag_ln_vals,
-			},
-		},
+	.pcs_cmn_vals_tbl = {
+		.entries = pcs_cmn_vals_entries,
+		.num_entries = ARRAY_SIZE(pcs_cmn_vals_entries),
 	},
-	.pcs_cmn_vals = {
-		[TYPE_USB] = {
-			[TYPE_NONE] = {
-				[NO_SSC] = &usb_phy_pcs_cmn_vals,
-				[EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-				[INTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-			},
-			[TYPE_PCIE] = {
-				[NO_SSC] = &usb_phy_pcs_cmn_vals,
-				[EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-				[INTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-			},
-			[TYPE_SGMII] = {
-				[NO_SSC] = &usb_phy_pcs_cmn_vals,
-				[EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-				[INTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-			},
-			[TYPE_QSGMII] = {
-				[NO_SSC] = &usb_phy_pcs_cmn_vals,
-				[EXTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-				[INTERNAL_SSC] = &usb_phy_pcs_cmn_vals,
-			},
-		},
+	.phy_pma_cmn_vals_tbl = {
+		.entries = j721e_phy_pma_cmn_vals_entries,
+		.num_entries = ARRAY_SIZE(j721e_phy_pma_cmn_vals_entries),
 	},
-	.cmn_vals = {
-		[CLK_19_2_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_19_2_no_ssc_cmn_vals,
-				},
-			},
-		},
-		[CLK_25_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_25_no_ssc_cmn_vals,
-				},
-			},
-		},
-		[CLK_100_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_100_no_ssc_cmn_vals,
-				},
-			},
-			[TYPE_PCIE] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = NULL,
-					[EXTERNAL_SSC] = NULL,
-					[INTERNAL_SSC] = &sl_pcie_100_int_ssc_cmn_vals,
-				},
-				[TYPE_SGMII] = {
-					[NO_SSC] = &pcie_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
-				},
-				[TYPE_QSGMII] = {
-					[NO_SSC] = &pcie_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &pcie_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &pcie_100_int_ssc_cmn_vals,
-				},
-			},
-			[TYPE_SGMII] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_sgmii_100_no_ssc_cmn_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &sgmii_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &sgmii_100_int_ssc_cmn_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &sgmii_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &sgmii_100_no_ssc_cmn_vals,
-				},
-			},
-			[TYPE_QSGMII] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_qsgmii_100_no_ssc_cmn_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &qsgmii_100_int_ssc_cmn_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &qsgmii_100_no_ssc_cmn_vals,
-				},
-			},
-			[TYPE_USB] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &usb_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &usb_100_int_ssc_cmn_vals,
-				},
-				[TYPE_SGMII] = {
-					[NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
-				},
-				[TYPE_QSGMII] = {
-					[NO_SSC] = &sl_usb_100_no_ssc_cmn_vals,
-					[EXTERNAL_SSC] = &sl_usb_100_no_ssc_cmn_vals,
-					[INTERNAL_SSC] = &sl_usb_100_int_ssc_cmn_vals,
-				},
-			},
-		},
+	.cmn_vals_tbl = {
+		.entries = ti_j7200_cmn_vals_entries,
+		.num_entries = ARRAY_SIZE(ti_j7200_cmn_vals_entries),
 	},
-	.tx_ln_vals = {
-		[CLK_19_2_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_19_2_no_ssc_tx_ln_vals,
-				},
-			},
-		},
-		[CLK_25_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_25_no_ssc_tx_ln_vals,
-				},
-			},
-		},
-		[CLK_100_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_100_no_ssc_tx_ln_vals,
-				},
-			},
-			[TYPE_PCIE] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = NULL,
-					[EXTERNAL_SSC] = NULL,
-					[INTERNAL_SSC] = NULL,
-				},
-				[TYPE_SGMII] = {
-					[NO_SSC] = NULL,
-					[EXTERNAL_SSC] = NULL,
-					[INTERNAL_SSC] = NULL,
-				},
-				[TYPE_QSGMII] = {
-					[NO_SSC] = NULL,
-					[EXTERNAL_SSC] = NULL,
-					[INTERNAL_SSC] = NULL,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = NULL,
-					[EXTERNAL_SSC] = NULL,
-					[INTERNAL_SSC] = NULL,
-				},
-			},
-			[TYPE_SGMII] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &ti_sgmii_100_no_ssc_tx_ln_vals,
-				},
-			},
-			[TYPE_QSGMII] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &ti_qsgmii_100_no_ssc_tx_ln_vals,
-				},
-			},
-			[TYPE_USB] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_SGMII] = {
-					[NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-				},
-				[TYPE_QSGMII] = {
-					[NO_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_tx_ln_vals,
-				},
-			},
-		},
+	.tx_ln_vals_tbl = {
+		.entries = ti_j7200_tx_ln_vals_entries,
+		.num_entries = ARRAY_SIZE(ti_j7200_tx_ln_vals_entries),
 	},
-	.rx_ln_vals = {
-		[CLK_19_2_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_19_2_no_ssc_rx_ln_vals,
-				},
-			},
-		},
-		[CLK_25_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_25_no_ssc_rx_ln_vals,
-				},
-			},
-		},
-		[CLK_100_MHZ] = {
-			[TYPE_DP] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sl_dp_100_no_ssc_rx_ln_vals,
-				},
-			},
-			[TYPE_PCIE] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_SGMII] = {
-					[NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_QSGMII] = {
-					[NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &pcie_100_no_ssc_rx_ln_vals,
-				},
-			},
-			[TYPE_SGMII] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &sgmii_100_no_ssc_rx_ln_vals,
-				},
-			},
-			[TYPE_QSGMII] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_USB] = {
-					[NO_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &qsgmii_100_no_ssc_rx_ln_vals,
-				},
-			},
-			[TYPE_USB] = {
-				[TYPE_NONE] = {
-					[NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_PCIE] = {
-					[NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_SGMII] = {
-					[NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-				},
-				[TYPE_QSGMII] = {
-					[NO_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[EXTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-					[INTERNAL_SSC] = &usb_100_no_ssc_rx_ln_vals,
-				},
-			},
-		},
+	.rx_ln_vals_tbl = {
+		.entries = ti_j7200_rx_ln_vals_entries,
+		.num_entries = ARRAY_SIZE(ti_j7200_rx_ln_vals_entries),
 	},
 };
 
@@ -4702,6 +5261,10 @@
 		.compatible = "ti,j721e-serdes-10g",
 		.data = &ti_j721e_map_torrent,
 	},
+	{
+		.compatible = "ti,j7200-serdes-10g",
+		.data = &ti_j7200_map_torrent,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, cdns_torrent_phy_of_match);
diff -Naur --no-dereference a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
--- a/drivers/phy/phy-core.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/phy/phy-core.c	2024-01-28 14:01:31.252353813 -0500
@@ -767,27 +767,6 @@
 EXPORT_SYMBOL_GPL(phy_get);
 
 /**
- * phy_optional_get() - lookup and obtain a reference to an optional phy.
- * @dev: device that requests this phy
- * @string: the phy name as given in the dt data or the name of the controller
- * port for non-dt case
- *
- * Returns the phy driver, after getting a refcount to it; or
- * NULL if there is no such phy.  The caller is responsible for
- * calling phy_put() to release that count.
- */
-struct phy *phy_optional_get(struct device *dev, const char *string)
-{
-	struct phy *phy = phy_get(dev, string);
-
-	if (PTR_ERR(phy) == -ENODEV)
-		phy = NULL;
-
-	return phy;
-}
-EXPORT_SYMBOL_GPL(phy_optional_get);
-
-/**
  * devm_phy_get() - lookup and obtain a reference to a phy.
  * @dev: device that requests this phy
  * @string: the phy name as given in the dt data or phy device name
@@ -880,6 +859,36 @@
 EXPORT_SYMBOL_GPL(devm_of_phy_get);
 
 /**
+ * devm_of_phy_optional_get() - lookup and obtain a reference to an optional
+ * phy.
+ * @dev: device that requests this phy
+ * @np: node containing the phy
+ * @con_id: name of the phy from device's point of view
+ *
+ * Gets the phy using of_phy_get(), and associates a device with it using
+ * devres. On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.  This differs to devm_of_phy_get() in
+ * that if the phy does not exist, it is not considered an error and
+ * -ENODEV will not be returned. Instead the NULL phy is returned,
+ * which can be passed to all other phy consumer calls.
+ */
+struct phy *devm_of_phy_optional_get(struct device *dev, struct device_node *np,
+				     const char *con_id)
+{
+	struct phy *phy = devm_of_phy_get(dev, np, con_id);
+
+	if (PTR_ERR(phy) == -ENODEV)
+		phy = NULL;
+
+	if (IS_ERR(phy))
+		dev_err_probe(dev, PTR_ERR(phy), "failed to get PHY %pOF:%s",
+			      np, con_id);
+
+	return phy;
+}
+EXPORT_SYMBOL_GPL(devm_of_phy_optional_get);
+
+/**
  * devm_of_phy_get_by_index() - lookup and obtain a reference to a phy by index.
  * @dev: device that requests this phy
  * @np: node containing the phy
diff -Naur --no-dereference a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c
--- a/drivers/phy/phy-core-mipi-dphy.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/phy/phy-core-mipi-dphy.c	2024-01-28 14:01:31.252353813 -0500
@@ -17,19 +17,21 @@
  * from the valid ranges specified in Section 6.9, Table 14, Page 41
  * of the D-PHY specification (v1.2).
  */
-int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
+static int phy_mipi_dphy_calc_config(unsigned long pixel_clock,
 				     unsigned int bpp,
 				     unsigned int lanes,
+				     unsigned long long hs_clk_rate,
 				     struct phy_configure_opts_mipi_dphy *cfg)
 {
-	unsigned long long hs_clk_rate;
 	unsigned long long ui;
 
 	if (!cfg)
 		return -EINVAL;
 
-	hs_clk_rate = pixel_clock * bpp;
-	do_div(hs_clk_rate, lanes);
+	if (!hs_clk_rate) {
+		hs_clk_rate = pixel_clock * bpp;
+		do_div(hs_clk_rate, lanes);
+	}
 
 	ui = ALIGN(PSEC_PER_SEC, hs_clk_rate);
 	do_div(ui, hs_clk_rate);
@@ -75,8 +77,29 @@
 
 	return 0;
 }
+
+int phy_mipi_dphy_get_default_config(unsigned long pixel_clock,
+				     unsigned int bpp,
+				     unsigned int lanes,
+				     struct phy_configure_opts_mipi_dphy *cfg)
+{
+	return phy_mipi_dphy_calc_config(pixel_clock, bpp, lanes, 0, cfg);
+
+}
 EXPORT_SYMBOL(phy_mipi_dphy_get_default_config);
 
+int phy_mipi_dphy_get_default_config_for_hsclk(unsigned long long hs_clk_rate,
+					       unsigned int lanes,
+					       struct phy_configure_opts_mipi_dphy *cfg)
+{
+	if (!hs_clk_rate)
+		return -EINVAL;
+
+	return phy_mipi_dphy_calc_config(0, 0, lanes, hs_clk_rate, cfg);
+
+}
+EXPORT_SYMBOL(phy_mipi_dphy_get_default_config_for_hsclk);
+
 /*
  * Validate D-PHY configuration according to MIPI D-PHY specification
  * (v1.2, Section Section 6.9 "Global Operation Timing Parameters").
diff -Naur --no-dereference a/drivers/phy/ti/phy-gmii-sel.c b/drivers/phy/ti/phy-gmii-sel.c
--- a/drivers/phy/ti/phy-gmii-sel.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/phy/ti/phy-gmii-sel.c	2024-01-28 14:01:31.252353813 -0500
@@ -23,7 +23,9 @@
 #define AM33XX_GMII_SEL_MODE_RGMII	2
 
 /* J72xx SoC specific definitions for the CONTROL port */
+#define J72XX_GMII_SEL_MODE_SGMII	3
 #define J72XX_GMII_SEL_MODE_QSGMII	4
+#define J72XX_GMII_SEL_MODE_USXGMII	5
 #define J72XX_GMII_SEL_MODE_QSGMII_SUB	6
 
 #define PHY_GMII_PORT(n)	BIT((n) - 1)
@@ -50,6 +52,7 @@
 	const struct reg_field (*regfields)[PHY_GMII_SEL_LAST];
 	bool use_of_data;
 	u64 extra_modes;
+	u32 num_qsgmii_main_ports;
 };
 
 struct phy_gmii_sel_priv {
@@ -61,6 +64,7 @@
 	u32 num_ports;
 	u32 reg_offset;
 	u32 qsgmii_main_ports;
+	bool no_offset;
 };
 
 static int phy_gmii_sel_mode(struct phy *phy, enum phy_mode mode, int submode)
@@ -105,6 +109,20 @@
 			gmii_sel_mode = J72XX_GMII_SEL_MODE_QSGMII_SUB;
 		break;
 
+	case PHY_INTERFACE_MODE_SGMII:
+		if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_SGMII)))
+			goto unsupported;
+		else
+			gmii_sel_mode = J72XX_GMII_SEL_MODE_SGMII;
+		break;
+
+	case PHY_INTERFACE_MODE_USXGMII:
+		if (!(soc_data->extra_modes & BIT(PHY_INTERFACE_MODE_USXGMII)))
+			goto unsupported;
+		else
+			gmii_sel_mode = J72XX_GMII_SEL_MODE_USXGMII;
+		break;
+
 	default:
 		goto unsupported;
 	}
@@ -212,7 +230,28 @@
 struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw5g_soc_j7200 = {
 	.use_of_data = true,
 	.regfields = phy_gmii_sel_fields_am654,
-	.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII),
+	.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII),
+	.num_ports = 4,
+	.num_qsgmii_main_ports = 1,
+};
+
+static const
+struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j721e = {
+	.use_of_data = true,
+	.regfields = phy_gmii_sel_fields_am654,
+	.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) | BIT(PHY_INTERFACE_MODE_SGMII),
+	.num_ports = 8,
+	.num_qsgmii_main_ports = 2,
+};
+
+static const
+struct phy_gmii_sel_soc_data phy_gmii_sel_cpsw9g_soc_j784s4 = {
+	.use_of_data = true,
+	.regfields = phy_gmii_sel_fields_am654,
+	.extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII) |
+		       BIT(PHY_INTERFACE_MODE_USXGMII),
+	.num_ports = 8,
+	.num_qsgmii_main_ports = 2,
 };
 
 static const struct of_device_id phy_gmii_sel_id_table[] = {
@@ -240,6 +279,14 @@
 		.compatible	= "ti,j7200-cpsw5g-phy-gmii-sel",
 		.data		= &phy_gmii_sel_cpsw5g_soc_j7200,
 	},
+	{
+		.compatible	= "ti,j721e-cpsw9g-phy-gmii-sel",
+		.data		= &phy_gmii_sel_cpsw9g_soc_j721e,
+	},
+	{
+		.compatible	= "ti,j784s4-cpsw9g-phy-gmii-sel",
+		.data		= &phy_gmii_sel_cpsw9g_soc_j784s4,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, phy_gmii_sel_id_table);
@@ -356,7 +403,8 @@
 		priv->num_ports = size / sizeof(u32);
 		if (!priv->num_ports)
 			return -EINVAL;
-		priv->reg_offset = __be32_to_cpu(*offset);
+		if (!priv->no_offset)
+			priv->reg_offset = __be32_to_cpu(*offset);
 	}
 
 	if_phys = devm_kcalloc(dev, priv->num_ports,
@@ -378,11 +426,13 @@
 static int phy_gmii_sel_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
+	const struct phy_gmii_sel_soc_data *soc_data;
 	struct device_node *node = dev->of_node;
 	const struct of_device_id *of_id;
 	struct phy_gmii_sel_priv *priv;
 	u32 main_ports = 1;
 	int ret;
+	u32 i;
 
 	of_id = of_match_node(phy_gmii_sel_id_table, pdev->dev.of_node);
 	if (!of_id)
@@ -394,22 +444,36 @@
 
 	priv->dev = &pdev->dev;
 	priv->soc_data = of_id->data;
+	soc_data = priv->soc_data;
 	priv->num_ports = priv->soc_data->num_ports;
-	of_property_read_u32(node, "ti,qsgmii-main-ports", &main_ports);
+	priv->qsgmii_main_ports = 0;
+
 	/*
-	 * Ensure that main_ports is within bounds. If the property
-	 * ti,qsgmii-main-ports is not mentioned, or the value mentioned
-	 * is out of bounds, default to 1.
+	 * Based on the compatible, try to read the appropriate number of
+	 * QSGMII main ports from the "ti,qsgmii-main-ports" property from
+	 * the device-tree node.
 	 */
-	if (main_ports < 1 || main_ports > 4)
-		main_ports = 1;
-	priv->qsgmii_main_ports = PHY_GMII_PORT(main_ports);
+	for (i = 0; i < soc_data->num_qsgmii_main_ports; i++) {
+		of_property_read_u32_index(node, "ti,qsgmii-main-ports", i, &main_ports);
+		/*
+		 * Ensure that main_ports is within bounds.
+		 */
+		if (main_ports < 1 || main_ports > soc_data->num_ports) {
+			dev_err(dev, "Invalid qsgmii main port provided\n");
+			return -EINVAL;
+		}
+		priv->qsgmii_main_ports |= PHY_GMII_PORT(main_ports);
+	}
 
 	priv->regmap = syscon_node_to_regmap(node->parent);
 	if (IS_ERR(priv->regmap)) {
-		ret = PTR_ERR(priv->regmap);
-		dev_err(dev, "Failed to get syscon %d\n", ret);
-		return ret;
+		priv->regmap = device_node_to_regmap(node);
+		if (IS_ERR(priv->regmap)) {
+			ret = PTR_ERR(priv->regmap);
+			dev_err(dev, "Failed to get syscon %d\n", ret);
+			return ret;
+		}
+		priv->no_offset = true;
 	}
 
 	ret = phy_gmii_sel_init_ports(priv);
diff -Naur --no-dereference a/drivers/phy/ti/phy-j721e-wiz.c b/drivers/phy/ti/phy-j721e-wiz.c
--- a/drivers/phy/ti/phy-j721e-wiz.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/phy/ti/phy-j721e-wiz.c	2024-01-28 14:01:31.252353813 -0500
@@ -58,6 +58,14 @@
 	LANE_MODE_GEN4,
 };
 
+/*
+ * List of master lanes used for lane swapping
+ */
+enum wiz_typec_master_lane {
+	LANE0 = 0,
+	LANE2 = 2,
+};
+
 enum wiz_refclk_mux_sel {
 	PLL0_REFCLK,
 	PLL1_REFCLK,
@@ -81,14 +89,20 @@
 static const struct reg_field phy_en_refclk = REG_FIELD(WIZ_SERDES_RST, 30, 30);
 static const struct reg_field pll1_refclk_mux_sel =
 					REG_FIELD(WIZ_SERDES_RST, 29, 29);
+static const struct reg_field pll1_refclk_mux_sel_2 =
+					REG_FIELD(WIZ_SERDES_RST, 22, 23);
 static const struct reg_field pll0_refclk_mux_sel =
 					REG_FIELD(WIZ_SERDES_RST, 28, 28);
+static const struct reg_field pll0_refclk_mux_sel_2 =
+					REG_FIELD(WIZ_SERDES_RST, 28, 29);
 static const struct reg_field refclk_dig_sel_16g =
 					REG_FIELD(WIZ_SERDES_RST, 24, 25);
 static const struct reg_field refclk_dig_sel_10g =
 					REG_FIELD(WIZ_SERDES_RST, 24, 24);
 static const struct reg_field pma_cmn_refclk_int_mode =
 					REG_FIELD(WIZ_SERDES_TOP_CTRL, 28, 29);
+static const struct reg_field pma_cmn_refclk1_int_mode =
+					REG_FIELD(WIZ_SERDES_TOP_CTRL, 20, 21);
 static const struct reg_field pma_cmn_refclk_mode =
 					REG_FIELD(WIZ_SERDES_TOP_CTRL, 30, 31);
 static const struct reg_field pma_cmn_refclk_dig_div =
@@ -188,6 +202,9 @@
 static const struct reg_field typec_ln10_swap =
 					REG_FIELD(WIZ_SERDES_TYPEC, 30, 30);
 
+static const struct reg_field typec_ln23_swap =
+					REG_FIELD(WIZ_SERDES_TYPEC, 31, 31);
+
 struct wiz_clk_mux {
 	struct clk_hw		hw;
 	struct regmap_field	*field;
@@ -315,6 +332,8 @@
 	J721E_WIZ_10G,	/* Also for J7200 SR1.0 */
 	AM64_WIZ_10G,
 	J7200_WIZ_10G,  /* J7200 SR2.0 */
+	J784S4_WIZ_10G,
+	J721S2_WIZ_10G,
 };
 
 struct wiz_data {
@@ -359,6 +378,7 @@
 	struct regmap_field	*mux_sel_field[WIZ_MUX_NUM_CLOCKS];
 	struct regmap_field	*div_sel_field[WIZ_DIV_NUM_CLOCKS_16G];
 	struct regmap_field	*typec_ln10_swap;
+	struct regmap_field	*typec_ln23_swap;
 	struct regmap_field	*sup_legacy_clk_override;
 
 	struct device		*dev;
@@ -368,6 +388,7 @@
 	struct gpio_desc	*gpio_typec_dir;
 	int			typec_dir_delay;
 	u32 lane_phy_type[WIZ_MAX_LANES];
+	u32 master_lane_num[WIZ_MAX_LANES];
 	struct clk		*input_clks[WIZ_MAX_INPUT_CLOCKS];
 	struct clk		*output_clks[WIZ_MAX_OUTPUT_CLOCKS];
 	struct clk_onecell_data	clk_data;
@@ -666,6 +687,13 @@
 		return PTR_ERR(wiz->typec_ln10_swap);
 	}
 
+	wiz->typec_ln23_swap = devm_regmap_field_alloc(dev, regmap,
+						       typec_ln23_swap);
+	if (IS_ERR(wiz->typec_ln23_swap)) {
+		dev_err(dev, "LN23_SWAP reg field init failed\n");
+		return PTR_ERR(wiz->typec_ln23_swap);
+	}
+
 	wiz->phy_en_refclk = devm_regmap_field_alloc(dev, regmap, phy_en_refclk);
 	if (IS_ERR(wiz->phy_en_refclk)) {
 		dev_err(dev, "PHY_EN_REFCLK reg field init failed\n");
@@ -991,6 +1019,8 @@
 	switch (wiz->type) {
 	case AM64_WIZ_10G:
 	case J7200_WIZ_10G:
+	case J784S4_WIZ_10G:
+	case J721S2_WIZ_10G:
 		of_clk_del_provider(dev->of_node);
 		return;
 	default:
@@ -1122,6 +1152,8 @@
 	switch (wiz->type) {
 	case AM64_WIZ_10G:
 	case J7200_WIZ_10G:
+	case J784S4_WIZ_10G:
+	case J721S2_WIZ_10G:
 		ret = wiz_clock_register(wiz);
 		if (ret)
 			dev_err(dev, "Failed to register wiz clocks\n");
@@ -1202,8 +1234,10 @@
 		if (wiz->lane_phy_type[lane] == PHY_TYPE_PCIE)
 			return regmap_field_write(wiz->p0_fullrt_div[lane], 0x1);
 		break;
+	case J721E_WIZ_16G:
 	case J721E_WIZ_10G:
 	case J7200_WIZ_10G:
+	case J721S2_WIZ_10G:
 		if (wiz->lane_phy_type[lane] == PHY_TYPE_SGMII)
 			return regmap_field_write(wiz->p0_fullrt_div[lane], 0x2);
 		break;
@@ -1220,15 +1254,39 @@
 	struct wiz *wiz = dev_get_drvdata(dev);
 	int ret;
 
-	/* if typec-dir gpio was specified, set LN10 SWAP bit based on that */
-	if (id == 0 && wiz->gpio_typec_dir) {
-		if (wiz->typec_dir_delay)
-			msleep_interruptible(wiz->typec_dir_delay);
-
-		if (gpiod_get_value_cansleep(wiz->gpio_typec_dir))
-			regmap_field_write(wiz->typec_ln10_swap, 1);
-		else
-			regmap_field_write(wiz->typec_ln10_swap, 0);
+	if (id == 0) {
+		/* if typec-dir gpio was specified, set LN10 SWAP bit based on that */
+		if (wiz->gpio_typec_dir) {
+			if (wiz->typec_dir_delay)
+				msleep_interruptible(wiz->typec_dir_delay);
+
+			if (gpiod_get_value_cansleep(wiz->gpio_typec_dir))
+				regmap_field_write(wiz->typec_ln10_swap, 1);
+			else
+				regmap_field_write(wiz->typec_ln10_swap, 0);
+		} else {
+			/* if no typec-dir gpio is specified and PHY type is USB3
+			 * with master lane number is '0' or '2', then set LN10 or
+			 * LN23 SWAP bit to '1' respectively.
+			 */
+			u32 num_lanes = wiz->num_lanes;
+			int i;
+
+			for (i = 0; i < num_lanes; i++) {
+				if (wiz->lane_phy_type[i] == PHY_TYPE_USB3) {
+					switch (wiz->master_lane_num[i]) {
+					case LANE0:
+						regmap_field_write(wiz->typec_ln10_swap, 1);
+						break;
+					case LANE2:
+						regmap_field_write(wiz->typec_ln23_swap, 1);
+						break;
+					default:
+						break;
+					}
+				}
+			}
+		}
 	}
 
 	if (id == 0) {
@@ -1298,6 +1356,25 @@
 	.clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G,
 };
 
+static struct wiz_data j784s4_10g_data = {
+	.type = J784S4_WIZ_10G,
+	.pll0_refclk_mux_sel = &pll0_refclk_mux_sel_2,
+	.pll1_refclk_mux_sel = &pll1_refclk_mux_sel_2,
+	.refclk_dig_sel = &refclk_dig_sel_16g,
+	.pma_cmn_refclk1_int_mode = &pma_cmn_refclk1_int_mode,
+	.clk_mux_sel = clk_mux_sel_10g_2_refclk,
+	.clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G,
+};
+
+static struct wiz_data j721s2_10g_data = {
+	.type = J721S2_WIZ_10G,
+	.pll0_refclk_mux_sel = &pll0_refclk_mux_sel,
+	.pll1_refclk_mux_sel = &pll1_refclk_mux_sel,
+	.refclk_dig_sel = &refclk_dig_sel_10g,
+	.clk_mux_sel = clk_mux_sel_10g,
+	.clk_div_sel_num = WIZ_DIV_NUM_CLOCKS_10G,
+};
+
 static const struct of_device_id wiz_id_table[] = {
 	{
 		.compatible = "ti,j721e-wiz-16g", .data = &j721e_16g_data,
@@ -1311,6 +1388,12 @@
 	{
 		.compatible = "ti,j7200-wiz-10g", .data = &j7200_pg2_10g_data,
 	},
+	{
+		.compatible = "ti,j784s4-wiz-10g", .data = &j784s4_10g_data,
+	},
+	{
+		.compatible = "ti,j721s2-wiz-10g", .data = &j721s2_10g_data,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, wiz_id_table);
@@ -1347,8 +1430,10 @@
 		dev_dbg(dev, "%s: Lanes %u-%u have phy-type %u\n", __func__,
 			reg, reg + num_lanes - 1, phy_type);
 
-		for (i = reg; i < reg + num_lanes; i++)
+		for (i = reg; i < reg + num_lanes; i++) {
+			wiz->master_lane_num[i] = reg;
 			wiz->lane_phy_type[i] = phy_type;
+		}
 	}
 
 	return 0;
diff -Naur --no-dereference a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
--- a/drivers/pinctrl/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pinctrl/Kconfig	2024-01-28 14:01:31.252353813 -0500
@@ -488,6 +488,16 @@
 	  rate control and direction control. This module will be
 	  called as pinctrl-thunderbay.
 
+config PINCTRL_TPS6594
+	tristate "Pinctrl and GPIO driver for TI TPS6594 PMIC"
+	depends on MFD_TPS6594
+	default MFD_TPS6594
+	select PINMUX
+	select GPIOLIB
+	help
+	  This driver supports GPIOs and pinmuxing for the TPS6594
+	  PMICs chip family.
+
 config PINCTRL_ZYNQ
 	bool "Pinctrl driver for Xilinx Zynq"
 	depends on ARCH_ZYNQ
diff -Naur --no-dereference a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
--- a/drivers/pinctrl/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pinctrl/Makefile	2024-01-28 14:01:31.252353813 -0500
@@ -48,6 +48,7 @@
 obj-$(CONFIG_PINCTRL_SX150X)	+= pinctrl-sx150x.o
 obj-$(CONFIG_PINCTRL_TB10X)	+= pinctrl-tb10x.o
 obj-$(CONFIG_PINCTRL_THUNDERBAY) += pinctrl-thunderbay.o
+obj-$(CONFIG_PINCTRL_TPS6594)	+= pinctrl-tps6594.o
 obj-$(CONFIG_PINCTRL_ZYNQMP)	+= pinctrl-zynqmp.o
 obj-$(CONFIG_PINCTRL_ZYNQ)	+= pinctrl-zynq.o
 
diff -Naur --no-dereference a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
--- a/drivers/pinctrl/pinctrl-single.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/pinctrl/pinctrl-single.c	2024-01-28 14:01:31.252353813 -0500
@@ -1955,6 +1955,12 @@
 	.irq_status_mask = (1 << 30),   /* OMAP_WAKEUP_EVENT */
 };
 
+static const struct pcs_soc_data pinctrl_single_am62 = {
+	.flags = PCS_QUIRK_SHARED_IRQ | PCS_CONTEXT_LOSS_OFF,
+	.irq_enable_mask = (1 << 29),   /* WKUP_EN */
+	.irq_status_mask = (1 << 30),   /* WKUP_EVT */
+};
+
 static const struct pcs_soc_data pinctrl_single = {
 };
 
@@ -1963,6 +1969,7 @@
 };
 
 static const struct of_device_id pcs_of_match[] = {
+	{ .compatible = "ti,am6-padconf", .data = &pinctrl_single_am62 },
 	{ .compatible = "ti,omap3-padconf", .data = &pinctrl_single_omap_wkup },
 	{ .compatible = "ti,omap4-padconf", .data = &pinctrl_single_omap_wkup },
 	{ .compatible = "ti,omap5-padconf", .data = &pinctrl_single_omap_wkup },
diff -Naur --no-dereference a/drivers/pinctrl/pinctrl-tps6594.c b/drivers/pinctrl/pinctrl-tps6594.c
--- a/drivers/pinctrl/pinctrl-tps6594.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/pinctrl/pinctrl-tps6594.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,365 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinmux and GPIO driver for tps6594 PMIC
+ *
+ * Copyright (C) 2022 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/gpio/driver.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinmux.h>
+
+#include <linux/mfd/tps6594.h>
+
+#define TPS6594_GPIO_DIR_IN 0
+#define TPS6594_GPIO_DIR_OUT TPS6594_BIT_GPIO_DIR
+#define TPS6594_PINCTRL_PINS_NB 11
+
+#define TPS6594_PINCTRL_GPIO_FUNCTION 0
+#define TPS6594_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION 1
+#define TPS6594_PINCTRL_TRIG_WDOG_FUNCTION 1
+#define TPS6594_PINCTRL_CLK32KOUT_FUNCTION 1
+#define TPS6594_PINCTRL_SCLK_SPMI_FUNCTION 1
+#define TPS6594_PINCTRL_SDATA_SPMI_FUNCTION 1
+#define TPS6594_PINCTRL_NERR_MCU_FUNCTION 1
+#define TPS6594_PINCTRL_PDOG_FUNCTION 1
+#define TPS6594_PINCTRL_SYNCCLKIN_FUNCTION 1
+#define TPS6594_PINCTRL_NRSTOUT_SOC_FUNCTION 2
+#define TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION 2
+#define TPS6594_PINCTRL_SDA_I2C2_SDO_SPI_FUNCTION 2
+#define TPS6594_PINCTRL_NERR_SOC_FUNCTION 2
+#define TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION 3
+#define TPS6594_PINCTRL_NSLEEP1_FUNCTION 4
+#define TPS6594_PINCTRL_NSLEEP2_FUNCTION 5
+#define TPS6594_PINCTRL_WKUP1_FUNCTION 6
+#define TPS6594_PINCTRL_WKUP2_FUNCTION 7
+
+/* Special muxval for recalcitrant pins */
+#define TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION_GPIO8 2
+#define TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION_GPIO8 3
+#define TPS6594_PINCTRL_CLK32KOUT_FUNCTION_GPIO9 3
+
+#define TPS6594_OFFSET_GPIO_SEL 5
+
+static const struct pinctrl_pin_desc tps6594_pins[TPS6594_PINCTRL_PINS_NB] = {
+	PINCTRL_PIN(0, "GPIO0"),   PINCTRL_PIN(1, "GPIO1"),
+	PINCTRL_PIN(2, "GPIO2"),   PINCTRL_PIN(3, "GPIO3"),
+	PINCTRL_PIN(4, "GPIO4"),   PINCTRL_PIN(5, "GPIO5"),
+	PINCTRL_PIN(6, "GPIO6"),   PINCTRL_PIN(7, "GPIO7"),
+	PINCTRL_PIN(8, "GPIO8"),   PINCTRL_PIN(9, "GPIO9"),
+	PINCTRL_PIN(10, "GPIO10"),
+};
+
+static const char *groups_name[TPS6594_PINCTRL_PINS_NB] = {
+	"GPIO0", "GPIO1", "GPIO2", "GPIO3", "GPIO4", "GPIO5",
+	"GPIO6", "GPIO7", "GPIO8", "GPIO9", "GPIO10"
+};
+
+struct tps6594_pinctrl_function {
+	const char *name;
+	u8 muxval;
+	const char **groups;
+	unsigned long ngroups;
+};
+
+static const struct tps6594_pinctrl_function pinctrl_functions[] = {
+	{ "gpio", TPS6594_PINCTRL_GPIO_FUNCTION, groups_name,
+	  TPS6594_PINCTRL_PINS_NB },
+	{ "nsleep1", TPS6594_PINCTRL_NSLEEP1_FUNCTION, groups_name,
+	  TPS6594_PINCTRL_PINS_NB },
+	{ "nsleep2", TPS6594_PINCTRL_NSLEEP2_FUNCTION, groups_name,
+	  TPS6594_PINCTRL_PINS_NB },
+	{ "wkup1", TPS6594_PINCTRL_WKUP1_FUNCTION, groups_name,
+	  TPS6594_PINCTRL_PINS_NB },
+	{ "wkup2", TPS6594_PINCTRL_WKUP2_FUNCTION, groups_name,
+	  TPS6594_PINCTRL_PINS_NB },
+	{ "scl_i2c2-cs_spi", TPS6594_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION,
+	  (const char *[]){ "GPIO0", "GPIO1" }, 2 },
+	{ "nrstout_soc", TPS6594_PINCTRL_NRSTOUT_SOC_FUNCTION,
+	  (const char *[]){ "GPIO0", "GPIO10" }, 2 },
+	{ "trig_wdog", TPS6594_PINCTRL_TRIG_WDOG_FUNCTION,
+	  (const char *[]){ "GPIO1", "GPIO10" }, 2 },
+	{ "sda_i2c2-sdo_spi", TPS6594_PINCTRL_SDA_I2C2_SDO_SPI_FUNCTION,
+	  (const char *[]){ "GPIO1" }, 1 },
+	{ "clk32kout", TPS6594_PINCTRL_CLK32KOUT_FUNCTION,
+	  (const char *[]){ "GPIO2", "GPIO3", "GPIO7" }, 3 },
+	{ "nerr_soc", TPS6594_PINCTRL_NERR_SOC_FUNCTION,
+	  (const char *[]){ "GPIO2" }, 1 },
+	{ "sclk_spmi", TPS6594_PINCTRL_SCLK_SPMI_FUNCTION,
+	  (const char *[]){ "GPIO4" }, 1 },
+	{ "sdata_spmi", TPS6594_PINCTRL_SDATA_SPMI_FUNCTION,
+	  (const char *[]){ "GPIO5" }, 1 },
+	{ "nerr_mcu", TPS6594_PINCTRL_NERR_MCU_FUNCTION,
+	  (const char *[]){ "GPIO6" }, 1 },
+	{ "syncclkout", TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION,
+	  (const char *[]){ "GPIO7", "GPIO9" }, 2 },
+	{ "disable_wdog", TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION,
+	  (const char *[]){ "GPIO7", "GPIO8" }, 2 },
+	{ "pdog", TPS6594_PINCTRL_PDOG_FUNCTION, (const char *[]){ "GPIO8" },
+	  1 },
+	{ "syncclkin", TPS6594_PINCTRL_SYNCCLKIN_FUNCTION,
+	  (const char *[]){ "GPIO9" }, 1 },
+};
+
+struct tps6594_pinctrl {
+	struct tps6594 *tps;
+	struct gpio_chip gpio_chip;
+	struct pinctrl_dev *pctl_dev;
+	const struct tps6594_pinctrl_function *funcs;
+	const struct pinctrl_pin_desc *pins;
+};
+
+static int tps6594_gpio_get(struct gpio_chip *gc, unsigned int offset)
+{
+	struct tps6594_pinctrl *pinctrl = gpiochip_get_data(gc);
+	int ret, val;
+
+	ret = regmap_read(pinctrl->tps->regmap, TPS6594_REG_GPIOX_IN(offset),
+			  &val);
+	if (ret < 0)
+		return ret;
+
+	val = (val & TPS6594_BIT_GPIOX_IN(offset)) > 0;
+
+	return val;
+}
+
+static void tps6594_gpio_set(struct gpio_chip *gc, unsigned int offset,
+			     int value)
+{
+	struct tps6594_pinctrl *pinctrl = gpiochip_get_data(gc);
+	unsigned int set_register = TPS6594_REG_GPIOX_OUT(offset);
+	int ret;
+
+	ret = regmap_update_bits(pinctrl->tps->regmap, set_register,
+				 TPS6594_BIT_GPIOX_OUT(offset),
+				 value ? TPS6594_BIT_GPIOX_OUT(offset) : 0);
+	if (ret < 0)
+		dev_err(pinctrl->tps->dev,
+			"gpio_set failed to set GPIO%d to %d: %d\n", offset,
+			value, ret);
+}
+
+static int tps6594_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+	struct tps6594_pinctrl *pinctrl = gpiochip_get_data(gc);
+	int ret;
+
+	ret = regmap_test_bits(pinctrl->tps->regmap,
+			       TPS6594_REG_GPIOX_CONF(offset),
+			       TPS6594_BIT_GPIO_DIR);
+	if (ret < 0) {
+		dev_err(pinctrl->tps->dev,
+			"gpio_get_direction for GPIO%d failed: %d\n", offset,
+			ret);
+		return ret;
+	}
+
+	/*
+	 * TPS6594 direction is 0 = input and 1 = output but Linux direction is 0 = output and
+	 * 1 = input
+	 * Let's invert our value
+	 */
+	return !ret;
+}
+
+static int tps6594_gpio_change_direction(struct gpio_chip *gc,
+					 unsigned int offset,
+					 unsigned int direction)
+{
+	struct tps6594_pinctrl *pinctrl = gpiochip_get_data(gc);
+	int ret;
+
+	ret = regmap_update_bits(pinctrl->tps->regmap,
+				 TPS6594_REG_GPIOX_CONF(offset),
+				 TPS6594_BIT_GPIO_DIR, direction);
+	if (ret < 0)
+		dev_err(pinctrl->tps->dev,
+			"gpio_change_direction for GPIO%d to %u direction failed: %d\n",
+			offset, direction, ret);
+
+	return ret;
+}
+
+static int tps6594_gpio_direction_input(struct gpio_chip *gc,
+					unsigned int offset)
+{
+	return tps6594_gpio_change_direction(gc, offset, TPS6594_GPIO_DIR_IN);
+}
+
+static int tps6594_gpio_direction_output(struct gpio_chip *gc,
+					 unsigned int offset, int value)
+{
+	tps6594_gpio_set(gc, offset, value);
+
+	return tps6594_gpio_change_direction(gc, offset, TPS6594_GPIO_DIR_OUT);
+}
+
+static const struct gpio_chip template_gpio_chip = {
+	.label = "tps6594-gpio",
+	.owner = THIS_MODULE,
+	.get_direction = tps6594_gpio_get_direction,
+	.direction_input = tps6594_gpio_direction_input,
+	.direction_output = tps6594_gpio_direction_output,
+	.get = tps6594_gpio_get,
+	.set = tps6594_gpio_set,
+	.base = -1,
+	.ngpio = TPS6594_PINCTRL_PINS_NB,
+	.can_sleep = true,
+};
+
+static int tps6594_pmx_func_cnt(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(pinctrl_functions);
+}
+
+static const char *tps6594_pmx_func_name(struct pinctrl_dev *pctldev,
+					 unsigned int selector)
+{
+	struct tps6594_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pinctrl->funcs[selector].name;
+}
+
+static int tps6594_pmx_func_groups(struct pinctrl_dev *pctldev,
+				   unsigned int selector,
+				   const char *const **groups,
+				   unsigned int *num_groups)
+{
+	struct tps6594_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	*groups = pinctrl->funcs[selector].groups;
+	*num_groups = pinctrl->funcs[selector].ngroups;
+
+	return 0;
+}
+
+static int tps6594_pmx_set(struct tps6594_pinctrl *pinctrl, unsigned int pin,
+			   u8 muxval)
+{
+	u8 mux_sel_val = muxval << TPS6594_OFFSET_GPIO_SEL;
+
+	return regmap_update_bits(pinctrl->tps->regmap,
+				  TPS6594_REG_GPIOX_CONF(pin),
+				  TPS6594_MASK_GPIO_SEL, mux_sel_val);
+}
+
+static int tps6594_pmx_set_mux(struct pinctrl_dev *pctldev,
+			       unsigned int function, unsigned int group)
+{
+	struct tps6594_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+	u8 muxval = pinctrl->funcs[function].muxval;
+
+	/* Some pins don't have the same muxval for the same function... */
+	if (group == 8) {
+		if (muxval == TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION)
+			muxval = TPS6594_PINCTRL_DISABLE_WDOG_FUNCTION_GPIO8;
+		else if (muxval == TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION)
+			muxval = TPS6594_PINCTRL_SYNCCLKOUT_FUNCTION_GPIO8;
+	} else if (group == 9) {
+		if (muxval == TPS6594_PINCTRL_CLK32KOUT_FUNCTION)
+			muxval = TPS6594_PINCTRL_CLK32KOUT_FUNCTION_GPIO9;
+	}
+
+	return tps6594_pmx_set(pinctrl, group, muxval);
+}
+
+static int tps6594_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+					  struct pinctrl_gpio_range *range,
+					  unsigned int offset, bool input)
+{
+	struct tps6594_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+	u8 muxval = pinctrl->funcs[TPS6594_PINCTRL_GPIO_FUNCTION].muxval;
+
+	return tps6594_pmx_set(pinctrl, offset, muxval);
+}
+
+static const struct pinmux_ops tps6594_pmx_ops = {
+	.get_functions_count = tps6594_pmx_func_cnt,
+	.get_function_name = tps6594_pmx_func_name,
+	.get_function_groups = tps6594_pmx_func_groups,
+	.set_mux = tps6594_pmx_set_mux,
+	.gpio_set_direction = tps6594_pmx_gpio_set_direction,
+	.strict = true,
+};
+
+static int tps6594_groups_cnt(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(tps6594_pins);
+}
+
+static int tps6594_group_pins(struct pinctrl_dev *pctldev,
+			      unsigned int selector, const unsigned int **pins,
+			      unsigned int *num_pins)
+{
+	struct tps6594_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	*pins = (unsigned int *)&pinctrl->pins[selector];
+	*num_pins = 1;
+
+	return 0;
+}
+
+static const char *tps6594_group_name(struct pinctrl_dev *pctldev,
+				      unsigned int selector)
+{
+	struct tps6594_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctldev);
+
+	return pinctrl->pins[selector].name;
+}
+
+static const struct pinctrl_ops tps6594_pctrl_ops = {
+	.dt_node_to_map = pinconf_generic_dt_node_to_map_group,
+	.dt_free_map = pinconf_generic_dt_free_map,
+	.get_groups_count = tps6594_groups_cnt,
+	.get_group_name = tps6594_group_name,
+	.get_group_pins = tps6594_group_pins,
+};
+
+static int tps6594_pinctrl_probe(struct platform_device *pdev)
+{
+	struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+	struct tps6594_pinctrl *pinctrl;
+	struct pinctrl_desc *pctrl_desc;
+
+	pinctrl = devm_kzalloc(&pdev->dev, sizeof(*pinctrl), GFP_KERNEL);
+	if (!pinctrl)
+		return -ENOMEM;
+
+	pinctrl->tps = dev_get_drvdata(pdev->dev.parent);
+	pinctrl->gpio_chip = template_gpio_chip;
+	pinctrl->gpio_chip.parent = tps->dev;
+
+	pctrl_desc = devm_kzalloc(&pdev->dev, sizeof(*pctrl_desc), GFP_KERNEL);
+	if (!pctrl_desc)
+		return -ENOMEM;
+
+	pctrl_desc->name = dev_name(&pdev->dev);
+	pctrl_desc->owner = THIS_MODULE;
+	pctrl_desc->pins = tps6594_pins;
+	pctrl_desc->npins = ARRAY_SIZE(tps6594_pins);
+	pctrl_desc->pctlops = &tps6594_pctrl_ops;
+	pctrl_desc->pmxops = &tps6594_pmx_ops;
+	pinctrl->funcs = pinctrl_functions;
+	pinctrl->pins = tps6594_pins;
+	pinctrl->pctl_dev =
+		devm_pinctrl_register(&pdev->dev, pctrl_desc, pinctrl);
+	if (IS_ERR(pinctrl->pctl_dev)) {
+		dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
+		return PTR_ERR(pinctrl->pctl_dev);
+	}
+
+	return devm_gpiochip_add_data(&pdev->dev, &pinctrl->gpio_chip, pinctrl);
+}
+
+static struct platform_driver tps6594_pinctrl_driver = {
+	.driver = { .name = "tps6594-pinctrl" },
+	.probe = tps6594_pinctrl_probe,
+};
+module_platform_driver(tps6594_pinctrl_driver);
+
+MODULE_ALIAS("platform:tps6594-pinctrl");
+MODULE_AUTHOR("Esteban Blanc <eblanc@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 pinctrl and GPIO driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/ptp/ptp_dte.c b/drivers/ptp/ptp_dte.c
--- a/drivers/ptp/ptp_dte.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/ptp/ptp_dte.c	2024-01-28 14:01:31.252353813 -0500
@@ -134,8 +134,9 @@
 	return ns;
 }
 
-static int ptp_dte_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+static int ptp_dte_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
 {
+	s32 ppb = scaled_ppm_to_ppb(scaled_ppm);
 	u32 nco_incr;
 	unsigned long flags;
 	struct ptp_dte *ptp_dte = container_of(ptp, struct ptp_dte, caps);
@@ -219,7 +220,7 @@
 	.n_ext_ts	= 0,
 	.n_pins		= 0,
 	.pps		= 0,
-	.adjfreq	= ptp_dte_adjfreq,
+	.adjfine	= ptp_dte_adjfine,
 	.adjtime	= ptp_dte_adjtime,
 	.gettime64	= ptp_dte_gettime,
 	.settime64	= ptp_dte_settime,
diff -Naur --no-dereference a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
--- a/drivers/regulator/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/regulator/Kconfig	2024-01-28 14:01:31.252353813 -0500
@@ -1412,6 +1412,19 @@
 	  voltage regulators. It supports software based voltage control
 	  for different voltage domains.
 
+config REGULATOR_TPS6594
+	tristate "TI TPS6594 Power regulators"
+	depends on MFD_TPS6594 && OF
+	default MFD_TPS6594
+	help
+	  This driver supports TPS6594 voltage regulator chips.
+	  TPS6594 series of PMICs have 5 BUCKs and 4 LDOs
+	  voltage regulators.
+	  BUCKs 1,2,3,4 can be used in single phase or multiphase mode.
+	  Part number defines which single or multiphase mode is i used.
+	  It supports software based voltage control
+	  for different voltage domains.
+
 config REGULATOR_TPS6524X
 	tristate "TI TPS6524X Power regulators"
 	depends on SPI
diff -Naur --no-dereference a/drivers/regulator/Makefile b/drivers/regulator/Makefile
--- a/drivers/regulator/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/regulator/Makefile	2024-01-28 14:01:31.252353813 -0500
@@ -169,6 +169,7 @@
 obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
+obj-$(CONFIG_REGULATOR_TPS6594) += tps6594-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65132) += tps65132-regulator.o
 obj-$(CONFIG_REGULATOR_TPS68470) += tps68470-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o twl6030-regulator.o
diff -Naur --no-dereference a/drivers/regulator/tps6594-regulator.c b/drivers/regulator/tps6594-regulator.c
--- a/drivers/regulator/tps6594-regulator.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/regulator/tps6594-regulator.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,614 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Regulator driver for tps6594 PMIC
+//
+// Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#include <linux/mfd/tps6594.h>
+
+#define BUCK_NB		5
+#define LDO_NB		4
+#define MULTI_PHASE_NB	4
+#define REGS_INT_NB	4
+
+enum tps6594_regulator_id {
+	/* DCDC's */
+	TPS6594_BUCK_1,
+	TPS6594_BUCK_2,
+	TPS6594_BUCK_3,
+	TPS6594_BUCK_4,
+	TPS6594_BUCK_5,
+
+	/* LDOs */
+	TPS6594_LDO_1,
+	TPS6594_LDO_2,
+	TPS6594_LDO_3,
+	TPS6594_LDO_4,
+};
+
+enum tps6594_multi_regulator_id {
+	/* Multi-phase DCDC's */
+	TPS6594_BUCK_12,
+	TPS6594_BUCK_34,
+	TPS6594_BUCK_123,
+	TPS6594_BUCK_1234,
+};
+
+struct tps6594_regulator_irq_type {
+	const char *irq_name;
+	const char *regulator_name;
+	const char *event_name;
+	unsigned long event;
+};
+
+static struct tps6594_regulator_irq_type tps6594_ext_regulator_irq_types[] = {
+	{ TPS6594_IRQ_NAME_VCCA_OV, "VCCA", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_VCCA_UV, "VCCA", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+	{ TPS6594_IRQ_NAME_VMON1_OV, "VMON1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_VMON1_UV, "VMON1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+	{ TPS6594_IRQ_NAME_VMON1_RV, "VMON1", "residual voltage",
+	  REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_VMON2_OV, "VMON2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_VMON2_UV, "VMON2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+	{ TPS6594_IRQ_NAME_VMON2_RV, "VMON2", "residual voltage",
+	  REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+};
+
+struct tps6594_regulator_irq_data {
+	struct device *dev;
+	struct tps6594_regulator_irq_type *type;
+	struct regulator_dev *rdev;
+};
+
+struct tps6594_ext_regulator_irq_data {
+	struct device *dev;
+	struct tps6594_regulator_irq_type *type;
+};
+
+#define TPS6594_REGULATOR(_name, _of, _id, _type, _ops, _n, _vr, _vm, _er, \
+			   _em, _cr, _cm, _lr, _nlr, _delay, _fuv, \
+			   _ct, _ncl, _bpm) \
+	{								\
+		.name			= _name,			\
+		.of_match		= _of,				\
+		.regulators_node	= of_match_ptr("regulators"),	\
+		.supply_name		= _of,				\
+		.id			= _id,				\
+		.ops			= &(_ops),			\
+		.n_voltages		= _n,				\
+		.type			= _type,			\
+		.owner			= THIS_MODULE,			\
+		.vsel_reg		= _vr,				\
+		.vsel_mask		= _vm,				\
+		.csel_reg		= _cr,				\
+		.csel_mask		= _cm,				\
+		.curr_table		= _ct,				\
+		.n_current_limits	= _ncl,				\
+		.enable_reg		= _er,				\
+		.enable_mask		= _em,				\
+		.volt_table		= NULL,				\
+		.linear_ranges		= _lr,				\
+		.n_linear_ranges	= _nlr,				\
+		.ramp_delay		= _delay,			\
+		.fixed_uV		= _fuv,				\
+		.bypass_reg		= _vr,				\
+		.bypass_mask		= _bpm,				\
+	}								\
+
+static const struct linear_range bucks_ranges[] = {
+	REGULATOR_LINEAR_RANGE(300000, 0x0, 0xe, 20000),
+	REGULATOR_LINEAR_RANGE(600000, 0xf, 0x72, 5000),
+	REGULATOR_LINEAR_RANGE(1100000, 0x73, 0xaa, 10000),
+	REGULATOR_LINEAR_RANGE(1660000, 0xab, 0xff, 20000),
+};
+
+static const struct linear_range ldos_1_2_3_ranges[] = {
+	REGULATOR_LINEAR_RANGE(600000, 0x4, 0x3a, 50000),
+};
+
+static const struct linear_range ldos_4_ranges[] = {
+	REGULATOR_LINEAR_RANGE(1200000, 0x20, 0x74, 25000),
+};
+
+/* Operations permitted on BUCK1/2/3/4/5 */
+static const struct regulator_ops tps6594_bucks_ops = {
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.map_voltage		= regulator_map_voltage_linear_range,
+	.set_voltage_time_sel	= regulator_set_voltage_time_sel,
+
+};
+
+/* Operations permitted on LDO1/2/3 */
+static const struct regulator_ops tps6594_ldos_1_2_3_ops = {
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.map_voltage		= regulator_map_voltage_linear_range,
+	.set_bypass		= regulator_set_bypass_regmap,
+	.get_bypass		= regulator_get_bypass_regmap,
+};
+
+/* Operations permitted on LDO4 */
+static const struct regulator_ops tps6594_ldos_4_ops = {
+	.is_enabled		= regulator_is_enabled_regmap,
+	.enable			= regulator_enable_regmap,
+	.disable		= regulator_disable_regmap,
+	.get_voltage_sel	= regulator_get_voltage_sel_regmap,
+	.set_voltage_sel	= regulator_set_voltage_sel_regmap,
+	.list_voltage		= regulator_list_voltage_linear_range,
+	.map_voltage		= regulator_map_voltage_linear_range,
+};
+
+static const struct regulator_desc buck_regs[] = {
+	TPS6594_REGULATOR("BUCK1", "buck1", TPS6594_BUCK_1,
+			  REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_VOUT_1(0),
+			  TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_CTRL(0),
+			  TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+			  4, 0, 0, NULL, 0, 0),
+	TPS6594_REGULATOR("BUCK2", "buck2", TPS6594_BUCK_2,
+			  REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_VOUT_1(1),
+			  TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_CTRL(1),
+			  TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+			  4, 0, 0, NULL, 0, 0),
+	TPS6594_REGULATOR("BUCK3", "buck3", TPS6594_BUCK_3,
+			  REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_VOUT_1(2),
+			  TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_CTRL(2),
+			  TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+			  4, 0, 0, NULL, 0, 0),
+	TPS6594_REGULATOR("BUCK4", "buck4", TPS6594_BUCK_4,
+			  REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_VOUT_1(3),
+			  TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_CTRL(3),
+			  TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+			  4, 0, 0, NULL, 0, 0),
+	TPS6594_REGULATOR("BUCK5", "buck5", TPS6594_BUCK_5,
+			  REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_VOUT_1(4),
+			  TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_CTRL(4),
+			  TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+			  4, 0, 0, NULL, 0, 0),
+};
+
+static struct tps6594_regulator_irq_type tps6594_buck1_irq_types[] = {
+	{ TPS6594_IRQ_NAME_BUCK1_OV, "BUCK1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_BUCK1_UV, "BUCK1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+	{ TPS6594_IRQ_NAME_BUCK1_SC, "BUCK1", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+	{ TPS6594_IRQ_NAME_BUCK1_ILIM, "BUCK1", "reach ilim, overcurrent",
+	  REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_buck2_irq_types[] = {
+	{ TPS6594_IRQ_NAME_BUCK2_OV, "BUCK2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_BUCK2_UV, "BUCK2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+	{ TPS6594_IRQ_NAME_BUCK2_SC, "BUCK2", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+	{ TPS6594_IRQ_NAME_BUCK2_ILIM, "BUCK2", "reach ilim, overcurrent",
+	  REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_buck3_irq_types[] = {
+	{ TPS6594_IRQ_NAME_BUCK3_OV, "BUCK3", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_BUCK3_UV, "BUCK3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+	{ TPS6594_IRQ_NAME_BUCK3_SC, "BUCK3", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+	{ TPS6594_IRQ_NAME_BUCK3_ILIM, "BUCK3", "reach ilim, overcurrent",
+	  REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_buck4_irq_types[] = {
+	{ TPS6594_IRQ_NAME_BUCK4_OV, "BUCK4", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_BUCK4_UV, "BUCK4", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+	{ TPS6594_IRQ_NAME_BUCK4_SC, "BUCK4", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+	{ TPS6594_IRQ_NAME_BUCK4_ILIM, "BUCK4", "reach ilim, overcurrent",
+	  REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_buck5_irq_types[] = {
+	{ TPS6594_IRQ_NAME_BUCK5_OV, "BUCK5", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_BUCK5_UV, "BUCK5", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+	{ TPS6594_IRQ_NAME_BUCK5_SC, "BUCK5", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+	{ TPS6594_IRQ_NAME_BUCK5_ILIM, "BUCK5", "reach ilim, overcurrent",
+	  REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_ldo1_irq_types[] = {
+	{ TPS6594_IRQ_NAME_LDO1_OV, "LDO1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_LDO1_UV, "LDO1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+	{ TPS6594_IRQ_NAME_LDO1_SC, "LDO1", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+	{ TPS6594_IRQ_NAME_LDO1_ILIM, "LDO1", "reach ilim, overcurrent",
+	  REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_ldo2_irq_types[] = {
+	{ TPS6594_IRQ_NAME_LDO2_OV, "LDO2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_LDO2_UV, "LDO2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+	{ TPS6594_IRQ_NAME_LDO2_SC, "LDO2", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+	{ TPS6594_IRQ_NAME_LDO2_ILIM, "LDO2", "reach ilim, overcurrent",
+	  REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_ldo3_irq_types[] = {
+	{ TPS6594_IRQ_NAME_LDO3_OV, "LDO3", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_LDO3_UV, "LDO3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+	{ TPS6594_IRQ_NAME_LDO3_SC, "LDO3", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+	{ TPS6594_IRQ_NAME_LDO3_ILIM, "LDO3", "reach ilim, overcurrent",
+	  REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type tps6594_ldo4_irq_types[] = {
+	{ TPS6594_IRQ_NAME_LDO4_OV, "LDO4", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+	{ TPS6594_IRQ_NAME_LDO4_UV, "LDO4", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE },
+	{ TPS6594_IRQ_NAME_LDO4_SC, "LDO4", "short circuit", REGULATOR_EVENT_REGULATION_OUT },
+	{ TPS6594_IRQ_NAME_LDO4_ILIM, "LDO4", "reach ilim, overcurrent",
+	  REGULATOR_EVENT_OVER_CURRENT },
+};
+
+static struct tps6594_regulator_irq_type *tps6594_bucks_irq_types[] = {
+	tps6594_buck1_irq_types,
+	tps6594_buck2_irq_types,
+	tps6594_buck3_irq_types,
+	tps6594_buck4_irq_types,
+	tps6594_buck5_irq_types,
+};
+
+static struct tps6594_regulator_irq_type *tps6594_ldos_irq_types[] = {
+	tps6594_ldo1_irq_types,
+	tps6594_ldo2_irq_types,
+	tps6594_ldo3_irq_types,
+	tps6594_ldo4_irq_types,
+};
+
+static const struct regulator_desc multi_regs[] = {
+	TPS6594_REGULATOR("BUCK12", "buck12", TPS6594_BUCK_1,
+			  REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_VOUT_1(1),
+			  TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_CTRL(1),
+			  TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+			  4, 4000, 0, NULL, 0, 0),
+	TPS6594_REGULATOR("BUCK34", "buck34", TPS6594_BUCK_3,
+			  REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_VOUT_1(3),
+			  TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_CTRL(3),
+			  TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+			  4, 0, 0, NULL, 0, 0),
+	TPS6594_REGULATOR("BUCK123", "buck123", TPS6594_BUCK_1,
+			  REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_VOUT_1(1),
+			  TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_CTRL(1),
+			  TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+			  4, 4000, 0, NULL, 0, 0),
+	TPS6594_REGULATOR("BUCK1234", "buck1234", TPS6594_BUCK_1,
+			  REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_VOUT_1(1),
+			  TPS6594_MASK_BUCKS_VSET,
+			  TPS6594_REG_BUCKX_CTRL(1),
+			  TPS6594_BIT_BUCK_EN, 0, 0, bucks_ranges,
+			  4, 4000, 0, NULL, 0, 0),
+};
+
+static const struct regulator_desc ldo_regs[] = {
+	TPS6594_REGULATOR("LDO1", "ldo1", TPS6594_LDO_1,
+			  REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET,
+			  TPS6594_REG_LDOX_VOUT(0),
+			  TPS6594_MASK_LDO123_VSET,
+			  TPS6594_REG_LDOX_CTRL(0),
+			  TPS6594_BIT_LDO_EN, 0, 0, ldos_1_2_3_ranges,
+			  1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS),
+	TPS6594_REGULATOR("LDO2", "ldo2", TPS6594_LDO_2,
+			  REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET,
+			  TPS6594_REG_LDOX_VOUT(1),
+			  TPS6594_MASK_LDO123_VSET,
+			  TPS6594_REG_LDOX_CTRL(1),
+			  TPS6594_BIT_LDO_EN, 0, 0, ldos_1_2_3_ranges,
+			  1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS),
+	TPS6594_REGULATOR("LDO3", "ldo3", TPS6594_LDO_3,
+			  REGULATOR_VOLTAGE, tps6594_ldos_1_2_3_ops, TPS6594_MASK_LDO123_VSET,
+			  TPS6594_REG_LDOX_VOUT(2),
+			  TPS6594_MASK_LDO123_VSET,
+			  TPS6594_REG_LDOX_CTRL(2),
+			  TPS6594_BIT_LDO_EN, 0, 0, ldos_1_2_3_ranges,
+			  1, 0, 0, NULL, 0, TPS6594_BIT_LDO_BYPASS),
+	TPS6594_REGULATOR("LDO4", "ldo4", TPS6594_LDO_4,
+			  REGULATOR_VOLTAGE, tps6594_ldos_4_ops, TPS6594_MASK_LDO4_VSET >> 1,
+			  TPS6594_REG_LDOX_VOUT(3),
+			  TPS6594_MASK_LDO4_VSET,
+			  TPS6594_REG_LDOX_CTRL(3),
+			  TPS6594_BIT_LDO_EN, 0, 0, ldos_4_ranges,
+			  1, 0, 0, NULL, 0, 0),
+};
+
+static irqreturn_t tps6594_regulator_irq_handler(int irq, void *data)
+{
+	struct tps6594_regulator_irq_data *irq_data = data;
+
+	if (irq_data->type->event_name[0] == '\0') {
+		/* This is the timeout interrupt no specific regulator */
+		dev_err(irq_data->dev,
+			"System was put in shutdown due to timeout during an active or standby transition.\n");
+		return IRQ_HANDLED;
+	}
+
+	dev_err(irq_data->dev, "Error IRQ trap %s for %s\n",
+		irq_data->type->event_name, irq_data->type->regulator_name);
+
+	regulator_notifier_call_chain(irq_data->rdev,
+				      irq_data->type->event, NULL);
+
+	return IRQ_HANDLED;
+}
+
+static int tps6594_request_reg_irqs(struct platform_device *pdev,
+				    struct regulator_dev *rdev,
+				    struct tps6594_regulator_irq_data *irq_data,
+				    struct tps6594_regulator_irq_type *tps6594_regs_irq_types,
+				    int *irq_idx)
+{
+	struct tps6594_regulator_irq_type *irq_type;
+	struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+	int j;
+	int irq;
+	int error;
+
+	for (j = 0; j < REGS_INT_NB; j++) {
+		irq_type = &tps6594_regs_irq_types[j];
+		irq = platform_get_irq_byname(pdev, irq_type->irq_name);
+		if (irq < 0)
+			return -EINVAL;
+
+		irq_data[*irq_idx].dev = tps->dev;
+		irq_data[*irq_idx].type = irq_type;
+		irq_data[*irq_idx].rdev = rdev;
+
+		error = devm_request_threaded_irq(tps->dev, irq, NULL,
+						  tps6594_regulator_irq_handler,
+						  IRQF_ONESHOT,
+						  irq_type->irq_name,
+						  &irq_data[*irq_idx]);
+		if (error) {
+			dev_err(tps->dev, "tps6594 failed to request %s IRQ %d: %d\n",
+				irq_type->irq_name, irq, error);
+			return error;
+		}
+		(*irq_idx)++;
+	}
+	return 0;
+}
+
+static int tps6594_regulator_probe(struct platform_device *pdev)
+{
+	struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent);
+	struct regulator_dev *rdev;
+	struct device_node *np = NULL;
+	struct device_node *np_pmic_parent = NULL;
+	struct regulator_config config = {};
+	struct tps6594_regulator_irq_data *irq_data;
+	struct tps6594_ext_regulator_irq_data *irq_ext_reg_data;
+	struct tps6594_regulator_irq_type *irq_type;
+	u8 buck_configured[BUCK_NB] = { 0 };
+	u8 buck_multi[MULTI_PHASE_NB] = { 0 };
+	static const char *multiphases[] = {"buck12", "buck123", "buck1234", "buck34"};
+	static const char *npname;
+	int error, i, irq, multi, delta;
+	int irq_idx = 0;
+	int buck_idx = 0;
+	size_t ext_reg_irq_nb = 2;
+	size_t reg_irq_nb;
+
+	enum {
+	MULTI_BUCK12,
+	MULTI_BUCK123,
+	MULTI_BUCK1234,
+	MULTI_BUCK12_34,
+	MULTI_FIRST = MULTI_BUCK12,
+	MULTI_LAST = MULTI_BUCK12_34,
+	MULTI_NUM = MULTI_LAST - MULTI_FIRST + 1
+	};
+
+	config.dev = tps->dev;
+	config.driver_data = tps;
+	config.regmap = tps->regmap;
+
+	/*
+	 * Switch case defines different possible multi phase config
+	 * This is based on dts buck node name.
+	 * Buck node name must be chosen accordingly.
+	 * Default case is no Multiphase buck.
+	 * In case of Multiphase configuration, value should be defined for
+	 * buck_configured to avoid creating bucks for every buck in multiphase
+	 */
+	for (multi = MULTI_FIRST ; multi < MULTI_NUM ; multi++) {
+		np = of_find_node_by_name(tps->dev->of_node, multiphases[multi]);
+		npname = of_node_full_name(np);
+		np_pmic_parent = of_get_parent(of_get_parent(np));
+		if (strcmp((of_node_full_name(np_pmic_parent)), tps->dev->of_node->full_name))
+			continue;
+		delta = strcmp(npname, multiphases[multi]);
+		if (!delta) {
+			switch (multi) {
+			case MULTI_BUCK12:
+				buck_multi[0] = 1;
+				buck_configured[0] = 1;
+				buck_configured[1] = 1;
+				break;
+			/* multiphase buck34 is supported only with buck12 */
+			case MULTI_BUCK12_34:
+				buck_multi[0] = 1;
+				buck_configured[0] = 1;
+				buck_configured[1] = 1;
+				buck_multi[1] = 1;
+				buck_configured[2] = 1;
+				buck_configured[3] = 1;
+				break;
+			case MULTI_BUCK123:
+				buck_multi[2] = 1;
+				buck_configured[0] = 1;
+				buck_configured[1] = 1;
+				buck_configured[2] = 1;
+				break;
+			case MULTI_BUCK1234:
+				buck_multi[3] = 1;
+				buck_configured[0] = 1;
+				buck_configured[1] = 1;
+				buck_configured[2] = 1;
+				buck_configured[3] = 1;
+				break;
+			}
+		}
+	}
+
+	if (tps->chip_id == LP8764) {
+		/* There is only 4 buck on LP8764 */
+		buck_configured[4] = 1;
+		reg_irq_nb = (BUCK_NB - 1) * REGS_INT_NB;
+	} else {
+		reg_irq_nb = BUCK_NB * REGS_INT_NB + LDO_NB * REGS_INT_NB;
+	}
+
+	irq_data = devm_kmalloc_array(tps->dev, reg_irq_nb,
+				      sizeof(struct tps6594_regulator_irq_data), GFP_KERNEL);
+	if (!irq_data)
+		return -ENOMEM;
+
+	for (i = 0; i < MULTI_PHASE_NB; i++) {
+		if (buck_multi[i] == 0)
+			continue;
+
+		rdev = devm_regulator_register(&pdev->dev, &multi_regs[i], &config);
+		if (IS_ERR(rdev)) {
+			dev_err(&pdev->dev, "failed to register %s regulator\n", pdev->name);
+			return PTR_ERR(rdev);
+		}
+		/* config multiphase buck12+buck34 */
+		if (i == 1)
+			buck_idx = 2;
+		error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
+						 tps6594_bucks_irq_types[buck_idx], &irq_idx);
+		if (error)
+			return error;
+
+		error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
+						 tps6594_bucks_irq_types[buck_idx + 1], &irq_idx);
+		if (error)
+			return error;
+
+		if (i == 2 || i == 3) {
+			error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
+							 tps6594_bucks_irq_types[buck_idx + 2],
+							 &irq_idx);
+			if (error)
+				return error;
+		}
+		if (i == 3) {
+			error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
+							 tps6594_bucks_irq_types[buck_idx + 3],
+							 &irq_idx);
+			if (error)
+				return error;
+		}
+	}
+
+	for (i = 0; i < BUCK_NB; i++) {
+		if (buck_configured[i] == 1)
+			continue;
+
+		rdev = devm_regulator_register(&pdev->dev, &buck_regs[i], &config);
+		if (IS_ERR(rdev)) {
+			dev_err(tps->dev, "failed to register %s regulator\n", pdev->name);
+			return PTR_ERR(rdev);
+		}
+		error = tps6594_request_reg_irqs(pdev, rdev, irq_data, tps6594_bucks_irq_types[i],
+						 &irq_idx);
+		if (error)
+			return error;
+	}
+
+	/* LP8764 dosen't have LDO */
+	if (tps->chip_id != LP8764) {
+		for (i = 0; i < ARRAY_SIZE(ldo_regs); i++) {
+			rdev = devm_regulator_register(&pdev->dev, &ldo_regs[i], &config);
+			if (IS_ERR(rdev)) {
+				dev_err(tps->dev,
+					"failed to register %s regulator\n", pdev->name);
+				return PTR_ERR(rdev);
+			}
+			error = tps6594_request_reg_irqs(pdev, rdev, irq_data,
+							 tps6594_ldos_irq_types[i], &irq_idx);
+			if (error)
+				return error;
+		}
+	}
+
+	if (tps->chip_id == LP8764)
+		ext_reg_irq_nb = ARRAY_SIZE(tps6594_ext_regulator_irq_types);
+
+	irq_ext_reg_data = devm_kmalloc_array(tps->dev, ext_reg_irq_nb,
+					      sizeof(struct tps6594_ext_regulator_irq_data),
+					      GFP_KERNEL);
+	if (!irq_ext_reg_data)
+		return -ENOMEM;
+
+	for (i = 0; i < ext_reg_irq_nb; ++i) {
+		irq_type = &tps6594_ext_regulator_irq_types[i];
+
+		irq = platform_get_irq_byname(pdev, irq_type->irq_name);
+		if (irq < 0)
+			return -EINVAL;
+
+		irq_ext_reg_data[i].dev = tps->dev;
+		irq_ext_reg_data[i].type = irq_type;
+
+		error = devm_request_threaded_irq(tps->dev, irq, NULL,
+						  tps6594_regulator_irq_handler,
+						  IRQF_ONESHOT, irq_type->irq_name,
+						  &irq_ext_reg_data[i]);
+		if (error) {
+			dev_err(tps->dev, "failed to request %s IRQ %d: %d\n",
+				irq_type->irq_name, irq, error);
+			return error;
+		}
+	}
+	return 0;
+}
+
+static struct platform_driver tps6594_regulator_driver = {
+	.driver = {
+		.name = "tps6594-regulator",
+	},
+	.probe = tps6594_regulator_probe,
+};
+
+module_platform_driver(tps6594_regulator_driver);
+
+MODULE_ALIAS("platform:tps6594-regulator");
+MODULE_AUTHOR("Jerome Neanne <jneanne@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 voltage regulator driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
--- a/drivers/remoteproc/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/remoteproc/Kconfig	2024-01-28 14:01:31.252353813 -0500
@@ -339,6 +339,19 @@
 	  It's safe to say N here if you're not interested in utilizing
 	  the DSP slave processors.
 
+config TI_K3_M4_REMOTEPROC
+	tristate "TI K3 M4 remoteproc support"
+	depends on ARCH_K3
+	select MAILBOX
+	select OMAP2PLUS_MBOX
+	help
+	  Say m here to support TI's M4 remote processor subsystems
+	  on various TI K3 family of SoCs through the remote processor
+	  framework.
+
+	  It's safe to say N here if you're not interested in utilizing
+	  a remote processor.
+
 config TI_K3_R5_REMOTEPROC
 	tristate "TI K3 R5 remoteproc support"
 	depends on ARCH_K3
diff -Naur --no-dereference a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
--- a/drivers/remoteproc/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/remoteproc/Makefile	2024-01-28 14:01:31.252353813 -0500
@@ -36,5 +36,6 @@
 obj-$(CONFIG_ST_REMOTEPROC)		+= st_remoteproc.o
 obj-$(CONFIG_ST_SLIM_REMOTEPROC)	+= st_slim_rproc.o
 obj-$(CONFIG_STM32_RPROC)		+= stm32_rproc.o
-obj-$(CONFIG_TI_K3_DSP_REMOTEPROC)	+= ti_k3_dsp_remoteproc.o
+obj-$(CONFIG_TI_K3_DSP_REMOTEPROC)	+= ti_k3_dsp_remoteproc.o ti_k3_common.o
+obj-$(CONFIG_TI_K3_M4_REMOTEPROC)	+= ti_k3_m4_remoteproc.o ti_k3_common.o
 obj-$(CONFIG_TI_K3_R5_REMOTEPROC)	+= ti_k3_r5_remoteproc.o
diff -Naur --no-dereference a/drivers/remoteproc/omap_remoteproc.h b/drivers/remoteproc/omap_remoteproc.h
--- a/drivers/remoteproc/omap_remoteproc.h	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/remoteproc/omap_remoteproc.h	2024-01-28 14:01:31.252353813 -0500
@@ -59,7 +59,9 @@
 	RP_MBOX_SUSPEND_SYSTEM	= 0xFFFFFF11,
 	RP_MBOX_SUSPEND_ACK	= 0xFFFFFF12,
 	RP_MBOX_SUSPEND_CANCEL	= 0xFFFFFF13,
-	RP_MBOX_END_MSG		= 0xFFFFFF14,
+	RP_MBOX_SHUTDOWN	= 0xFFFFFF14,
+	RP_MBOX_SHUTDOWN_ACK	= 0xFFFFFF15,
+	RP_MBOX_END_MSG		= 0xFFFFFF16,
 };
 
 #endif /* _OMAP_RPMSG_H */
diff -Naur --no-dereference a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c
--- a/drivers/remoteproc/pru_rproc.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/remoteproc/pru_rproc.c	2024-01-28 14:01:31.252353813 -0500
@@ -2,20 +2,24 @@
 /*
  * PRU-ICSS remoteproc driver for various TI SoCs
  *
- * Copyright (C) 2014-2020 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2014-2022 Texas Instruments Incorporated - https://www.ti.com/
  *
  * Author(s):
  *	Suman Anna <s-anna@ti.com>
  *	Andrew F. Davis <afd@ti.com>
  *	Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org> for Texas Instruments
+ *	Puranjay Mohan <p-mohan@ti.com>
+ *	Md Danish Anwar <danishanwar@ti.com>
  */
 
 #include <linux/bitops.h>
 #include <linux/debugfs.h>
+#include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
 #include <linux/of_irq.h>
+#include <linux/remoteproc/pruss.h>
 #include <linux/pruss_driver.h>
 #include <linux/remoteproc.h>
 
@@ -79,21 +83,6 @@
 };
 
 /**
- * enum pru_type - PRU core type identifier
- *
- * @PRU_TYPE_PRU: Programmable Real-time Unit
- * @PRU_TYPE_RTU: Auxiliary Programmable Real-Time Unit
- * @PRU_TYPE_TX_PRU: Transmit Programmable Real-Time Unit
- * @PRU_TYPE_MAX: just keep this one at the end
- */
-enum pru_type {
-	PRU_TYPE_PRU = 0,
-	PRU_TYPE_RTU,
-	PRU_TYPE_TX_PRU,
-	PRU_TYPE_MAX,
-};
-
-/**
  * struct pru_private_data - device data for a PRU core
  * @type: type of the PRU core (PRU, RTU, Tx_PRU)
  * @is_k3: flag used to identify the need for special load handling
@@ -111,10 +100,14 @@
  * @rproc: remoteproc pointer for this PRU core
  * @data: PRU core specific data
  * @mem_regions: data for each of the PRU memory regions
+ * @client_np: client device node
+ * @lock: mutex to protect client usage
  * @fw_name: name of firmware image used during loading
  * @mapped_irq: virtual interrupt numbers of created fw specific mapping
  * @pru_interrupt_map: pointer to interrupt mapping description (firmware)
  * @pru_interrupt_map_sz: pru_interrupt_map size
+ * @rmw_lock: lock for read, modify, write operations on registers
+ * @irq_vring: IRQ number to use for processing vring buffers
  * @dbg_single_step: debug state variable to set PRU into single step mode
  * @dbg_continuous: debug state variable to restore PRU execution mode
  * @evt_count: number of mapped events
@@ -126,10 +119,14 @@
 	struct rproc *rproc;
 	const struct pru_private_data *data;
 	struct pruss_mem_region mem_regions[PRU_IOMEM_MAX];
+	struct device_node *client_np;
+	struct mutex lock;
 	const char *fw_name;
 	unsigned int *mapped_irq;
 	struct pru_irq_rsc *pru_interrupt_map;
 	size_t pru_interrupt_map_sz;
+	spinlock_t rmw_lock; /* register access lock */
+	int irq_vring;
 	u32 dbg_single_step;
 	u32 dbg_continuous;
 	u8 evt_count;
@@ -146,6 +143,212 @@
 	writel_relaxed(val, pru->mem_regions[PRU_IOMEM_CTRL].va + reg);
 }
 
+static inline
+void pru_control_set_reg(struct pru_rproc *pru, unsigned int reg,
+			 u32 mask, u32 set)
+{
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pru->rmw_lock, flags);
+
+	val = pru_control_read_reg(pru, reg);
+	val &= ~mask;
+	val |= (set & mask);
+	pru_control_write_reg(pru, reg, val);
+
+	spin_unlock_irqrestore(&pru->rmw_lock, flags);
+}
+
+/**
+ * pru_rproc_set_firmware() - set firmware for a PRU core
+ * @rproc: the rproc instance of the PRU
+ * @fw_name: the new firmware name, or NULL if default is desired
+ *
+ * Return: 0 on success, or errno in error case.
+ */
+static int pru_rproc_set_firmware(struct rproc *rproc, const char *fw_name)
+{
+	struct pru_rproc *pru = rproc->priv;
+
+	if (!fw_name)
+		fw_name = pru->fw_name;
+
+	return rproc_set_firmware(rproc, fw_name);
+}
+
+static struct rproc *__pru_rproc_get(struct device_node *np, int index)
+{
+	struct rproc *rproc;
+	phandle rproc_phandle;
+	int ret;
+
+	ret = of_property_read_u32_index(np, "ti,prus", index, &rproc_phandle);
+	if (ret)
+		return ERR_PTR(ret);
+
+	rproc = rproc_get_by_phandle(rproc_phandle);
+	if (!rproc) {
+		ret = -EPROBE_DEFER;
+		return ERR_PTR(ret);
+	}
+
+	/* make sure it is PRU rproc */
+	if (!is_pru_rproc(rproc->dev.parent)) {
+		rproc_put(rproc);
+		return ERR_PTR(-ENODEV);
+	}
+
+	return rproc;
+}
+
+/**
+ * pru_rproc_get() - get the PRU rproc instance from a device node
+ * @np: the user/client device node
+ * @index: index to use for the ti,prus property
+ * @pru_id: optional pointer to return the PRU remoteproc processor id
+ *
+ * This function looks through a client device node's "ti,prus" property at
+ * index @index and returns the rproc handle for a valid PRU remote processor if
+ * found. The function allows only one user to own the PRU rproc resource at a
+ * time. Caller must call pru_rproc_put() when done with using the rproc, not
+ * required if the function returns a failure.
+ *
+ * When optional @pru_id pointer is passed the PRU remoteproc processor id is
+ * returned.
+ *
+ * Return: rproc handle on success, and an ERR_PTR on failure using one
+ * of the following error values
+ *    -ENODEV if device is not found
+ *    -EBUSY if PRU is already acquired by anyone
+ *    -EPROBE_DEFER is PRU device is not probed yet
+ */
+struct rproc *pru_rproc_get(struct device_node *np, int index,
+			    enum pruss_pru_id *pru_id)
+{
+	struct rproc *rproc;
+	struct pru_rproc *pru;
+	struct device *dev;
+	const char *fw_name;
+	int ret;
+
+	rproc = __pru_rproc_get(np, index);
+	if (IS_ERR(rproc))
+		return rproc;
+
+	pru = rproc->priv;
+	dev = &rproc->dev;
+
+	mutex_lock(&pru->lock);
+
+	if (pru->client_np) {
+		mutex_unlock(&pru->lock);
+		ret = -EBUSY;
+		goto err_no_rproc_handle;
+	}
+
+	pru->client_np = np;
+	rproc->sysfs_read_only = true;
+
+	mutex_unlock(&pru->lock);
+
+	if (pru_id)
+		*pru_id = pru->id;
+
+	ret = of_property_read_string_index(np, "firmware-name", index,
+					    &fw_name);
+	if (!ret) {
+		ret = pru_rproc_set_firmware(rproc, fw_name);
+		if (ret) {
+			dev_err(dev, "failed to set firmware: %d\n", ret);
+			goto err;
+		}
+	}
+
+	return rproc;
+
+err_no_rproc_handle:
+	rproc_put(rproc);
+	return ERR_PTR(ret);
+
+err:
+	pru_rproc_put(rproc);
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(pru_rproc_get);
+
+/**
+ * pru_rproc_put() - release the PRU rproc resource
+ * @rproc: the rproc resource to release
+ *
+ * Releases the PRU rproc resource and makes it available to other
+ * users.
+ */
+void pru_rproc_put(struct rproc *rproc)
+{
+	struct pru_rproc *pru;
+
+	if (IS_ERR_OR_NULL(rproc) || !is_pru_rproc(rproc->dev.parent))
+		return;
+
+	pru = rproc->priv;
+
+	pru_rproc_set_firmware(rproc, NULL);
+
+	mutex_lock(&pru->lock);
+
+	if (!pru->client_np) {
+		mutex_unlock(&pru->lock);
+		return;
+	}
+
+	pru->client_np = NULL;
+	rproc->sysfs_read_only = false;
+	mutex_unlock(&pru->lock);
+
+	rproc_put(rproc);
+}
+EXPORT_SYMBOL_GPL(pru_rproc_put);
+
+/**
+ * pru_rproc_set_ctable() - set the constant table index for the PRU
+ * @rproc: the rproc instance of the PRU
+ * @c: constant table index to set
+ * @addr: physical address to set it to
+ *
+ * Return: 0 on success, or errno in error case.
+ */
+int pru_rproc_set_ctable(struct rproc *rproc, enum pru_ctable_idx c, u32 addr)
+{
+	struct pru_rproc *pru = rproc->priv;
+	unsigned int reg;
+	u32 mask, set;
+	u16 idx;
+	u16 idx_mask;
+
+	if (IS_ERR_OR_NULL(rproc))
+		return -EINVAL;
+
+	if (!rproc->dev.parent || !is_pru_rproc(rproc->dev.parent))
+		return -ENODEV;
+
+	/* pointer is 16 bit and index is 8-bit so mask out the rest */
+	idx_mask = (c >= PRU_C28) ? 0xFFFF : 0xFF;
+
+	/* ctable uses bit 8 and upwards only */
+	idx = (addr >> 8) & idx_mask;
+
+	/* configurable ctable (i.e. C24) starts at PRU_CTRL_CTBIR0 */
+	reg = PRU_CTRL_CTBIR0 + 4 * (c >> 1);
+	mask = idx_mask << (16 * (c & 1));
+	set = idx << (16 * (c & 1));
+
+	pru_control_set_reg(pru, reg, mask, set);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pru_rproc_set_ctable);
+
 static inline u32 pru_debug_read_reg(struct pru_rproc *pru, unsigned int reg)
 {
 	return readl_relaxed(pru->mem_regions[PRU_IOMEM_DEBUG].va + reg);
@@ -280,6 +483,83 @@
 }
 
 /*
+ * pru_rproc_vring_interrupt() - interrupt handler for processing vrings
+ * @irq: irq number associated with the PRU event MPU is listening on
+ * @data: interrupt handler data, will be a PRU rproc structure
+ *
+ * This handler is used by the PRU remoteproc driver when using PRU system
+ * events for processing the virtqueues. Unlike the mailbox IP, there is
+ * no payload associated with an interrupt, so either a unique event is
+ * used for each virtqueue kick, or both virtqueues are processed on a
+ * single event. The latter is chosen to conserve the usable PRU system
+ * events.
+ */
+static irqreturn_t pru_rproc_vring_interrupt(int irq, void *data)
+{
+	struct pru_rproc *pru = data;
+
+	dev_dbg(&pru->rproc->dev, "got vring irq\n");
+
+	/* process incoming buffers on both the Rx and Tx vrings */
+	rproc_vq_interrupt(pru->rproc, 0);
+	rproc_vq_interrupt(pru->rproc, 1);
+
+	return IRQ_HANDLED;
+}
+
+/* Kick a virtqueue. */
+static void pru_rproc_kick(struct rproc *rproc, int vq_id)
+{
+	struct device *dev = &rproc->dev;
+	struct pru_rproc *pru = rproc->priv;
+	int ret;
+	const char *names[PRU_TYPE_MAX] = { "PRU", "RTU", "Tx_PRU" };
+
+	if (list_empty(&pru->rproc->rvdevs))
+		return;
+
+	dev_dbg(dev, "kicking vqid %d on %s%d\n", vq_id,
+		names[pru->data->type], pru->id);
+
+	ret = irq_set_irqchip_state(pru->mapped_irq[0], IRQCHIP_STATE_PENDING, true);
+	if (ret < 0)
+		dev_err(dev, "pruss_intc_trigger failed: %d\n", ret);
+}
+
+/* Register vring irq handler if needed. */
+static int pru_vring_interrupt_setup(struct rproc *rproc)
+{
+	struct device *dev = &rproc->dev;
+	struct pru_rproc *pru = rproc->priv;
+	struct platform_device *pdev = to_platform_device(pru->dev);
+	int ret;
+
+	if (list_empty(&pru->rproc->rvdevs))
+		return 0;
+
+	/* get vring interrupts for supporting virtio rpmsg */
+	pru->irq_vring = platform_get_irq_byname(pdev, "vring");
+	if (pru->irq_vring <= 0) {
+		ret = pru->irq_vring;
+		if (ret != -EPROBE_DEFER)
+			dev_err(dev, "unable to get vring interrupt, status = %d\n",
+				ret);
+
+		return ret;
+	}
+
+	ret = request_threaded_irq(pru->irq_vring, NULL,
+				   pru_rproc_vring_interrupt, IRQF_ONESHOT,
+				   dev_name(dev), pru);
+	if (ret) {
+		dev_err(dev, "failed to register vring irq handler: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
  * Parse the custom PRU interrupt map resource and configure the INTC
  * appropriately.
  */
@@ -391,10 +671,21 @@
 	if (ret)
 		return ret;
 
+	ret = pru_vring_interrupt_setup(rproc);
+	if (ret)
+		goto fail;
+
 	val = CTRL_CTRL_EN | ((rproc->bootaddr >> 2) << 16);
 	pru_control_write_reg(pru, PRU_CTRL_CTRL, val);
 
 	return 0;
+
+fail:
+	/* dispose irq mapping - new firmware can provide new mapping */
+	if (pru->mapped_irq)
+		pru_dispose_irq_mapping(pru);
+
+	return ret;
 }
 
 static int pru_rproc_stop(struct rproc *rproc)
@@ -410,9 +701,16 @@
 	val &= ~CTRL_CTRL_EN;
 	pru_control_write_reg(pru, PRU_CTRL_CTRL, val);
 
+	if (!list_empty(&pru->rproc->rvdevs) && pru->irq_vring > 0)
+		free_irq(pru->irq_vring, pru);
+
 	/* dispose irq mapping - new firmware can provide new mapping */
 	pru_dispose_irq_mapping(pru);
 
+	/* dispose vring mapping as well */
+	if (pru->irq_vring > 0)
+		irq_dispose_mapping(pru->irq_vring);
+
 	return 0;
 }
 
@@ -438,7 +736,7 @@
 	dram0 = pruss->mem_regions[PRUSS_MEM_DRAM0];
 	dram1 = pruss->mem_regions[PRUSS_MEM_DRAM1];
 	/* PRU1 has its local RAM addresses reversed */
-	if (pru->id == 1)
+	if (pru->id == PRUSS_PRU1)
 		swap(dram0, dram1);
 	shrd_ram = pruss->mem_regions[PRUSS_MEM_SHRD_RAM2];
 
@@ -530,6 +828,7 @@
 static struct rproc_ops pru_rproc_ops = {
 	.start		= pru_rproc_start,
 	.stop		= pru_rproc_stop,
+	.kick		= pru_rproc_kick,
 	.da_to_va	= pru_rproc_da_to_va,
 };
 
@@ -747,14 +1046,14 @@
 	case RTU0_IRAM_ADDR_MASK:
 		fallthrough;
 	case PRU0_IRAM_ADDR_MASK:
-		pru->id = 0;
+		pru->id = PRUSS_PRU0;
 		break;
 	case TX_PRU1_IRAM_ADDR_MASK:
 		fallthrough;
 	case RTU1_IRAM_ADDR_MASK:
 		fallthrough;
 	case PRU1_IRAM_ADDR_MASK:
-		pru->id = 1;
+		pru->id = PRUSS_PRU1;
 		break;
 	default:
 		ret = -EINVAL;
@@ -816,6 +1115,9 @@
 	pru->pruss = platform_get_drvdata(ppdev);
 	pru->rproc = rproc;
 	pru->fw_name = fw_name;
+	pru->client_np = NULL;
+	spin_lock_init(&pru->rmw_lock);
+	mutex_init(&pru->lock);
 
 	for (i = 0; i < ARRAY_SIZE(mem_names); i++) {
 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
@@ -904,7 +1206,7 @@
 
 static struct platform_driver pru_rproc_driver = {
 	.driver = {
-		.name   = "pru-rproc",
+		.name   = PRU_RPROC_DRVNAME,
 		.of_match_table = pru_rproc_match,
 		.suppress_bind_attrs = true,
 	},
@@ -916,5 +1218,7 @@
 MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");
 MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
 MODULE_AUTHOR("Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org>");
+MODULE_AUTHOR("Puranjay Mohan <p-mohan@ti.com>");
+MODULE_AUTHOR("Md Danish Anwar <danishanwar@ti.com>");
 MODULE_DESCRIPTION("PRU-ICSS Remote Processor Driver");
 MODULE_LICENSE("GPL v2");
diff -Naur --no-dereference a/drivers/remoteproc/ti_k3_common.c b/drivers/remoteproc/ti_k3_common.c
--- a/drivers/remoteproc/ti_k3_common.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/remoteproc/ti_k3_common.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,375 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * TI K3 Remote Processor(s) driver common code
+ *
+ * Refactored from ti_k3_dsp_remoteproc.c.
+ *
+ * ti_k3_dsp_remoteproc.c:
+ * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *	Suman Anna <s-anna@ti.com>
+ */
+
+#include <linux/io.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/omap-mailbox.h>
+#include <linux/platform_device.h>
+#include <linux/remoteproc.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+
+#include "omap_remoteproc.h"
+#include "remoteproc_internal.h"
+#include "ti_sci_proc.h"
+#include "ti_k3_common.h"
+
+/*
+ * Kick the remote processor to notify about pending unprocessed messages.
+ * The vqid usage is not used and is inconsequential, as the kick is performed
+ * through a simulated GPIO (a bit in an IPC interrupt-triggering register),
+ * the remote processor is expected to process both its Tx and Rx virtqueues.
+ */
+void k3_rproc_kick(struct rproc *rproc, int vqid)
+{
+	struct k3_rproc *kproc = rproc->priv;
+	struct device *dev = rproc->dev.parent;
+	mbox_msg_t msg = (mbox_msg_t)vqid;
+	int ret;
+
+	/* send the index of the triggered virtqueue in the mailbox payload */
+	ret = mbox_send_message(kproc->mbox, (void *)msg);
+	if (ret < 0)
+		dev_err(dev, "failed to send mailbox message, status = %d\n",
+			ret);
+}
+EXPORT_SYMBOL_GPL(k3_rproc_kick);
+
+/* Put the remote processor into reset */
+int k3_rproc_reset(struct k3_rproc *kproc)
+{
+	struct device *dev = kproc->dev;
+	int ret;
+
+	ret = reset_control_assert(kproc->reset);
+	if (ret) {
+		dev_err(dev, "local-reset assert failed, ret = %d\n", ret);
+		return ret;
+	}
+
+	if (kproc->data->uses_lreset)
+		return ret;
+
+	ret = kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci,
+						    kproc->ti_sci_id);
+	if (ret) {
+		dev_err(dev, "module-reset assert failed, ret = %d\n", ret);
+		if (reset_control_deassert(kproc->reset))
+			dev_warn(dev, "local-reset deassert back failed\n");
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(k3_rproc_reset);
+
+/* Release the remote processor from reset */
+int k3_rproc_release(struct k3_rproc *kproc)
+{
+	struct device *dev = kproc->dev;
+	int ret;
+
+	if (kproc->data->uses_lreset)
+		goto lreset;
+
+	ret = kproc->ti_sci->ops.dev_ops.get_device(kproc->ti_sci,
+						    kproc->ti_sci_id);
+	if (ret) {
+		dev_err(dev, "module-reset deassert failed, ret = %d\n", ret);
+		return ret;
+	}
+
+lreset:
+	ret = reset_control_deassert(kproc->reset);
+	if (ret) {
+		dev_err(dev, "local-reset deassert failed, ret = %d\n", ret);
+		if (kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci,
+							  kproc->ti_sci_id))
+			dev_warn(dev, "module-reset assert back failed\n");
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(k3_rproc_release);
+
+/*
+ * This function implements the .get_loaded_rsc_table() callback and is used
+ * to provide the resource table for a booted remote processor in IPC-only
+ * mode. The remote processor firmwares follow a design-by-contract approach
+ * and are expected to have the resource table at the base of the DDR region
+ * reserved for firmware usage. This provides flexibility for the remote
+ * processor to be booted by different bootloaders that may or may not have the
+ * ability to publish the resource table address and size through a DT
+ * property.
+ */
+struct resource_table *k3_get_loaded_rsc_table(struct rproc *rproc,
+					       size_t *rsc_table_sz)
+{
+	struct k3_rproc *kproc = rproc->priv;
+	struct device *dev = kproc->dev;
+
+	if (!kproc->rmem[0].cpu_addr) {
+		dev_err(dev, "memory-region #1 does not exist, loaded rsc table can't be found");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/*
+	 * NOTE: The resource table size is currently hard-coded to a maximum
+	 * of 256 bytes. The most common resource table usage for K3 firmwares
+	 * is to only have the vdev resource entry and an optional trace entry.
+	 * The exact size could be computed based on resource table address, but
+	 * the hard-coded value suffices to support the IPC-only mode.
+	 */
+	*rsc_table_sz = 256;
+	return (struct resource_table *)kproc->rmem[0].cpu_addr;
+}
+EXPORT_SYMBOL_GPL(k3_get_loaded_rsc_table);
+
+/*
+ * Custom function to translate a remote processor device address (internal
+ * RAMs only) to a kernel virtual address.  The remote processors can access
+ * their RAMs at either an internal address visible only from a remote
+ * processor, or at the SoC-level bus address. Both these addresses need to be
+ * looked through for translation. The translated addresses can be used either
+ * by the remoteproc core for loading (when using kernel remoteproc loader), or
+ * by any rpmsg bus drivers.
+ */
+void *k3_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
+{
+	struct k3_rproc *kproc = rproc->priv;
+	void __iomem *va = NULL;
+	phys_addr_t bus_addr;
+	u32 dev_addr, offset;
+	size_t size;
+	int i;
+
+	if (len == 0)
+		return NULL;
+
+	for (i = 0; i < kproc->num_mems; i++) {
+		bus_addr = kproc->mem[i].bus_addr;
+		dev_addr = kproc->mem[i].dev_addr;
+		size = kproc->mem[i].size;
+
+		if (da < KEYSTONE_RPROC_LOCAL_ADDRESS_MASK) {
+			/* handle remote-view addresses */
+			if (da >= dev_addr &&
+			    ((da + len) <= (dev_addr + size))) {
+				offset = da - dev_addr;
+				va = kproc->mem[i].cpu_addr + offset;
+				return (__force void *)va;
+			}
+		} else {
+			/* handle SoC-view addresses */
+			if (da >= bus_addr &&
+			    (da + len) <= (bus_addr + size)) {
+				offset = da - bus_addr;
+				va = kproc->mem[i].cpu_addr + offset;
+				return (__force void *)va;
+			}
+		}
+	}
+
+	/* handle static DDR reserved memory regions */
+	for (i = 0; i < kproc->num_rmems; i++) {
+		dev_addr = kproc->rmem[i].dev_addr;
+		size = kproc->rmem[i].size;
+
+		if (da >= dev_addr && ((da + len) <= (dev_addr + size))) {
+			offset = da - dev_addr;
+			va = kproc->rmem[i].cpu_addr + offset;
+			return (__force void *)va;
+		}
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(k3_rproc_da_to_va);
+
+int k3_rproc_of_get_memories(struct platform_device *pdev,
+			     struct k3_rproc *kproc)
+{
+	const struct k3_rproc_dev_data *data = kproc->data;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	int num_mems = 0;
+	int i;
+
+	num_mems = kproc->data->num_mems;
+	kproc->mem = devm_kcalloc(kproc->dev, num_mems,
+				  sizeof(*kproc->mem), GFP_KERNEL);
+	if (!kproc->mem)
+		return -ENOMEM;
+
+	for (i = 0; i < num_mems; i++) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						   data->mems[i].name);
+		if (!res) {
+			dev_err(dev, "found no memory resource for %s\n",
+				data->mems[i].name);
+			return -EINVAL;
+		}
+		if (!devm_request_mem_region(dev, res->start,
+					     resource_size(res),
+					     dev_name(dev))) {
+			dev_err(dev, "could not request %s region for resource\n",
+				data->mems[i].name);
+			return -EBUSY;
+		}
+
+		kproc->mem[i].cpu_addr = devm_ioremap_wc(dev, res->start,
+							 resource_size(res));
+		if (!kproc->mem[i].cpu_addr) {
+			dev_err(dev, "failed to map %s memory\n",
+				data->mems[i].name);
+			return -ENOMEM;
+		}
+		kproc->mem[i].bus_addr = res->start;
+		kproc->mem[i].dev_addr = data->mems[i].dev_addr;
+		kproc->mem[i].size = resource_size(res);
+
+		dev_dbg(dev, "memory %8s: bus addr %pa size 0x%zx va %pK da 0x%x\n",
+			data->mems[i].name, &kproc->mem[i].bus_addr,
+			kproc->mem[i].size, kproc->mem[i].cpu_addr,
+			kproc->mem[i].dev_addr);
+	}
+	kproc->num_mems = num_mems;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(k3_rproc_of_get_memories);
+
+int k3_reserved_mem_init(struct k3_rproc *kproc)
+{
+	struct device *dev = kproc->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *rmem_np;
+	struct reserved_mem *rmem;
+	int num_rmems;
+	int ret, i;
+
+	num_rmems = of_property_count_elems_of_size(np, "memory-region",
+						    sizeof(phandle));
+	if (num_rmems <= 0) {
+		dev_err(dev, "device does not reserved memory regions, ret = %d\n",
+			num_rmems);
+		return -EINVAL;
+	}
+	if (num_rmems < 2) {
+		dev_err(dev, "device needs at least two memory regions to be defined, num = %d\n",
+			num_rmems);
+		return -EINVAL;
+	}
+
+	/* use reserved memory region 0 for vring DMA allocations */
+	ret = of_reserved_mem_device_init_by_idx(dev, np, 0);
+	if (ret) {
+		dev_err(dev, "device cannot initialize DMA pool, ret = %d\n",
+			ret);
+		return ret;
+	}
+
+	num_rmems--;
+	kproc->rmem = kcalloc(num_rmems, sizeof(*kproc->rmem), GFP_KERNEL);
+	if (!kproc->rmem) {
+		ret = -ENOMEM;
+		goto release_rmem;
+	}
+
+	/* use remaining reserved memory regions for static carveouts */
+	for (i = 0; i < num_rmems; i++) {
+		rmem_np = of_parse_phandle(np, "memory-region", i + 1);
+		if (!rmem_np) {
+			ret = -EINVAL;
+			goto unmap_rmem;
+		}
+
+		rmem = of_reserved_mem_lookup(rmem_np);
+		if (!rmem) {
+			of_node_put(rmem_np);
+			ret = -EINVAL;
+			goto unmap_rmem;
+		}
+		of_node_put(rmem_np);
+
+		kproc->rmem[i].bus_addr = rmem->base;
+		/* 64-bit address regions currently not supported */
+		kproc->rmem[i].dev_addr = (u32)rmem->base;
+		kproc->rmem[i].size = rmem->size;
+		kproc->rmem[i].cpu_addr = ioremap_wc(rmem->base, rmem->size);
+		if (!kproc->rmem[i].cpu_addr) {
+			dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n",
+				i + 1, &rmem->base, &rmem->size);
+			ret = -ENOMEM;
+			goto unmap_rmem;
+		}
+
+		dev_dbg(dev, "reserved memory%d: bus addr %pa size 0x%zx va %pK da 0x%x\n",
+			i + 1, &kproc->rmem[i].bus_addr,
+			kproc->rmem[i].size, kproc->rmem[i].cpu_addr,
+			kproc->rmem[i].dev_addr);
+	}
+	kproc->num_rmems = num_rmems;
+
+	return 0;
+
+unmap_rmem:
+	for (i--; i >= 0; i--)
+		iounmap(kproc->rmem[i].cpu_addr);
+	kfree(kproc->rmem);
+release_rmem:
+	of_reserved_mem_device_release(kproc->dev);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(k3_reserved_mem_init);
+
+void k3_reserved_mem_exit(struct k3_rproc *kproc)
+{
+	int i;
+
+	for (i = 0; i < kproc->num_rmems; i++)
+		iounmap(kproc->rmem[i].cpu_addr);
+	kfree(kproc->rmem);
+
+	of_reserved_mem_device_release(kproc->dev);
+}
+EXPORT_SYMBOL_GPL(k3_reserved_mem_exit);
+
+struct ti_sci_proc *k3_rproc_of_get_tsp(struct device *dev,
+					const struct ti_sci_handle *sci)
+{
+	struct ti_sci_proc *tsp;
+	u32 temp[2];
+	int ret;
+
+	ret = of_property_read_u32_array(dev->of_node, "ti,sci-proc-ids",
+					 temp, 2);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	tsp = kzalloc(sizeof(*tsp), GFP_KERNEL);
+	if (!tsp)
+		return ERR_PTR(-ENOMEM);
+
+	tsp->dev = dev;
+	tsp->sci = sci;
+	tsp->ops = &sci->ops.proc_ops;
+	tsp->proc_id = temp[0];
+	tsp->host_id = temp[1];
+
+	return tsp;
+}
+EXPORT_SYMBOL_GPL(k3_rproc_of_get_tsp);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI K3 common Remoteproc support");
diff -Naur --no-dereference a/drivers/remoteproc/ti_k3_common.h b/drivers/remoteproc/ti_k3_common.h
--- a/drivers/remoteproc/ti_k3_common.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/remoteproc/ti_k3_common.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * TI K3 Remote Processor(s) driver common code
+ *
+ * Refactored from ti_k3_dsp_remoteproc.c and ti_k3_m4_remoteproc.c.
+ *
+ * ti_k3_dsp_remoteproc.c:
+ * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
+ *	Suman Anna <s-anna@ti.com>
+ *
+ * ti_k3_m4_remoteproc.c:
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
+ *	Hari Nagalla <hnagalla@ti.com>
+ */
+
+#ifndef REMOTEPROC_TI_K3_COMMON_H
+#define REMOTEPROC_TI_K3_COMMON_H
+
+#define KEYSTONE_RPROC_LOCAL_ADDRESS_MASK	(SZ_16M - 1)
+
+/**
+ * struct k3_rproc_mem - internal memory structure
+ * @cpu_addr: MPU virtual address of the memory region
+ * @bus_addr: Bus address used to access the memory region
+ * @dev_addr: Device address of the memory region from DSP view
+ * @size: Size of the memory region
+ */
+struct k3_rproc_mem {
+	void __iomem *cpu_addr;
+	phys_addr_t bus_addr;
+	u32 dev_addr;
+	size_t size;
+};
+
+/**
+ * struct k3_rproc_mem_data - memory definitions for a DSP
+ * @name: name for this memory entry
+ * @dev_addr: device address for the memory entry
+ */
+struct k3_rproc_mem_data {
+	const char *name;
+	const u32 dev_addr;
+};
+
+/**
+ * struct k3_rproc_dev_data - device data structure for a DSP
+ * @mems: pointer to memory definitions for a DSP
+ * @num_mems: number of memory regions in @mems
+ * @boot_align_addr: boot vector address alignment granularity
+ * @uses_lreset: flag to denote the need for local reset management
+ */
+struct k3_rproc_dev_data {
+	const struct k3_rproc_mem_data *mems;
+	u32 num_mems;
+	u32 boot_align_addr;
+	bool uses_lreset;
+};
+
+/**
+ * struct k3_rproc - k3 remote processor driver structure
+ * @dev: cached device pointer
+ * @rproc: remoteproc device handle
+ * @mem: internal memory regions data
+ * @num_mems: number of internal memory regions
+ * @rmem: reserved memory regions data
+ * @num_rmems: number of reserved memory regions
+ * @reset: reset control handle
+ * @data: pointer to device data
+ * @tsp: TI-SCI processor control handle
+ * @ti_sci: TI-SCI handle
+ * @ti_sci_id: TI-SCI device identifier
+ * @mbox: mailbox channel handle
+ * @client: mailbox client to request the mailbox channel
+ * @ipc_only: flag to indicate IPC-only mode
+ */
+struct k3_rproc {
+	struct device *dev;
+	struct rproc *rproc;
+	struct k3_rproc_mem *mem;
+	int num_mems;
+	struct k3_rproc_mem *rmem;
+	int num_rmems;
+	struct reset_control *reset;
+	const struct k3_rproc_dev_data *data;
+	struct ti_sci_proc *tsp;
+	const struct ti_sci_handle *ti_sci;
+	u32 ti_sci_id;
+	struct mbox_chan *mbox;
+	struct mbox_client client;
+	bool ipc_only;
+	struct completion shut_comp;
+	struct completion suspend_comp;
+	struct notifier_block pm_notifier;
+};
+
+void k3_rproc_kick(struct rproc *rproc, int vqid);
+int k3_rproc_reset(struct k3_rproc *kproc);
+int k3_rproc_release(struct k3_rproc *kproc);
+struct resource_table *k3_get_loaded_rsc_table(struct rproc *rproc,
+					       size_t *rsc_table_sz);
+void *k3_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len,
+			bool *is_iomem);
+int k3_rproc_of_get_memories(struct platform_device *pdev,
+			     struct k3_rproc *kproc);
+int k3_reserved_mem_init(struct k3_rproc *kproc);
+void k3_reserved_mem_exit(struct k3_rproc *kproc);
+struct ti_sci_proc *k3_rproc_of_get_tsp(struct device *dev,
+					const struct ti_sci_handle *sci);
+
+#endif /* REMOTEPROC_TI_K3_COMMON_H */
diff -Naur --no-dereference a/drivers/remoteproc/ti_k3_dsp_remoteproc.c b/drivers/remoteproc/ti_k3_dsp_remoteproc.c
--- a/drivers/remoteproc/ti_k3_dsp_remoteproc.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/remoteproc/ti_k3_dsp_remoteproc.c	2024-01-28 14:01:31.252353813 -0500
@@ -20,78 +20,7 @@
 #include "omap_remoteproc.h"
 #include "remoteproc_internal.h"
 #include "ti_sci_proc.h"
-
-#define KEYSTONE_RPROC_LOCAL_ADDRESS_MASK	(SZ_16M - 1)
-
-/**
- * struct k3_dsp_mem - internal memory structure
- * @cpu_addr: MPU virtual address of the memory region
- * @bus_addr: Bus address used to access the memory region
- * @dev_addr: Device address of the memory region from DSP view
- * @size: Size of the memory region
- */
-struct k3_dsp_mem {
-	void __iomem *cpu_addr;
-	phys_addr_t bus_addr;
-	u32 dev_addr;
-	size_t size;
-};
-
-/**
- * struct k3_dsp_mem_data - memory definitions for a DSP
- * @name: name for this memory entry
- * @dev_addr: device address for the memory entry
- */
-struct k3_dsp_mem_data {
-	const char *name;
-	const u32 dev_addr;
-};
-
-/**
- * struct k3_dsp_dev_data - device data structure for a DSP
- * @mems: pointer to memory definitions for a DSP
- * @num_mems: number of memory regions in @mems
- * @boot_align_addr: boot vector address alignment granularity
- * @uses_lreset: flag to denote the need for local reset management
- */
-struct k3_dsp_dev_data {
-	const struct k3_dsp_mem_data *mems;
-	u32 num_mems;
-	u32 boot_align_addr;
-	bool uses_lreset;
-};
-
-/**
- * struct k3_dsp_rproc - k3 DSP remote processor driver structure
- * @dev: cached device pointer
- * @rproc: remoteproc device handle
- * @mem: internal memory regions data
- * @num_mems: number of internal memory regions
- * @rmem: reserved memory regions data
- * @num_rmems: number of reserved memory regions
- * @reset: reset control handle
- * @data: pointer to DSP-specific device data
- * @tsp: TI-SCI processor control handle
- * @ti_sci: TI-SCI handle
- * @ti_sci_id: TI-SCI device identifier
- * @mbox: mailbox channel handle
- * @client: mailbox client to request the mailbox channel
- */
-struct k3_dsp_rproc {
-	struct device *dev;
-	struct rproc *rproc;
-	struct k3_dsp_mem *mem;
-	int num_mems;
-	struct k3_dsp_mem *rmem;
-	int num_rmems;
-	struct reset_control *reset;
-	const struct k3_dsp_dev_data *data;
-	struct ti_sci_proc *tsp;
-	const struct ti_sci_handle *ti_sci;
-	u32 ti_sci_id;
-	struct mbox_chan *mbox;
-	struct mbox_client client;
-};
+#include "ti_k3_common.h"
 
 /**
  * k3_dsp_rproc_mbox_callback() - inbound mailbox message handler
@@ -109,7 +38,7 @@
  */
 static void k3_dsp_rproc_mbox_callback(struct mbox_client *client, void *data)
 {
-	struct k3_dsp_rproc *kproc = container_of(client, struct k3_dsp_rproc,
+	struct k3_rproc *kproc = container_of(client, struct k3_rproc,
 						  client);
 	struct device *dev = kproc->rproc->dev.parent;
 	const char *name = kproc->rproc->name;
@@ -142,83 +71,9 @@
 	}
 }
 
-/*
- * Kick the remote processor to notify about pending unprocessed messages.
- * The vqid usage is not used and is inconsequential, as the kick is performed
- * through a simulated GPIO (a bit in an IPC interrupt-triggering register),
- * the remote processor is expected to process both its Tx and Rx virtqueues.
- */
-static void k3_dsp_rproc_kick(struct rproc *rproc, int vqid)
-{
-	struct k3_dsp_rproc *kproc = rproc->priv;
-	struct device *dev = rproc->dev.parent;
-	mbox_msg_t msg = (mbox_msg_t)vqid;
-	int ret;
-
-	/* send the index of the triggered virtqueue in the mailbox payload */
-	ret = mbox_send_message(kproc->mbox, (void *)msg);
-	if (ret < 0)
-		dev_err(dev, "failed to send mailbox message, status = %d\n",
-			ret);
-}
-
-/* Put the DSP processor into reset */
-static int k3_dsp_rproc_reset(struct k3_dsp_rproc *kproc)
-{
-	struct device *dev = kproc->dev;
-	int ret;
-
-	ret = reset_control_assert(kproc->reset);
-	if (ret) {
-		dev_err(dev, "local-reset assert failed, ret = %d\n", ret);
-		return ret;
-	}
-
-	if (kproc->data->uses_lreset)
-		return ret;
-
-	ret = kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci,
-						    kproc->ti_sci_id);
-	if (ret) {
-		dev_err(dev, "module-reset assert failed, ret = %d\n", ret);
-		if (reset_control_deassert(kproc->reset))
-			dev_warn(dev, "local-reset deassert back failed\n");
-	}
-
-	return ret;
-}
-
-/* Release the DSP processor from reset */
-static int k3_dsp_rproc_release(struct k3_dsp_rproc *kproc)
-{
-	struct device *dev = kproc->dev;
-	int ret;
-
-	if (kproc->data->uses_lreset)
-		goto lreset;
-
-	ret = kproc->ti_sci->ops.dev_ops.get_device(kproc->ti_sci,
-						    kproc->ti_sci_id);
-	if (ret) {
-		dev_err(dev, "module-reset deassert failed, ret = %d\n", ret);
-		return ret;
-	}
-
-lreset:
-	ret = reset_control_deassert(kproc->reset);
-	if (ret) {
-		dev_err(dev, "local-reset deassert failed, ret = %d\n", ret);
-		if (kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci,
-							  kproc->ti_sci_id))
-			dev_warn(dev, "module-reset assert back failed\n");
-	}
-
-	return ret;
-}
-
 static int k3_dsp_rproc_request_mbox(struct rproc *rproc)
 {
-	struct k3_dsp_rproc *kproc = rproc->priv;
+	struct k3_rproc *kproc = rproc->priv;
 	struct mbox_client *client = &kproc->client;
 	struct device *dev = kproc->dev;
 	int ret;
@@ -253,6 +108,7 @@
 
 	return 0;
 }
+
 /*
  * The C66x DSP cores have a local reset that affects only the CPU, and a
  * generic module reset that powers on the device and allows the DSP internal
@@ -265,7 +121,7 @@
  */
 static int k3_dsp_rproc_prepare(struct rproc *rproc)
 {
-	struct k3_dsp_rproc *kproc = rproc->priv;
+	struct k3_rproc *kproc = rproc->priv;
 	struct device *dev = kproc->dev;
 	int ret;
 
@@ -289,7 +145,7 @@
  */
 static int k3_dsp_rproc_unprepare(struct rproc *rproc)
 {
-	struct k3_dsp_rproc *kproc = rproc->priv;
+	struct k3_rproc *kproc = rproc->priv;
 	struct device *dev = kproc->dev;
 	int ret;
 
@@ -310,7 +166,7 @@
  */
 static int k3_dsp_rproc_start(struct rproc *rproc)
 {
-	struct k3_dsp_rproc *kproc = rproc->priv;
+	struct k3_rproc *kproc = rproc->priv;
 	struct device *dev = kproc->dev;
 	u32 boot_addr;
 	int ret;
@@ -332,7 +188,7 @@
 	if (ret)
 		goto put_mbox;
 
-	ret = k3_dsp_rproc_release(kproc);
+	ret = k3_rproc_release(kproc);
 	if (ret)
 		goto put_mbox;
 
@@ -351,11 +207,11 @@
  */
 static int k3_dsp_rproc_stop(struct rproc *rproc)
 {
-	struct k3_dsp_rproc *kproc = rproc->priv;
+	struct k3_rproc *kproc = rproc->priv;
 
 	mbox_free_channel(kproc->mbox);
 
-	k3_dsp_rproc_reset(kproc);
+	k3_rproc_reset(kproc);
 
 	return 0;
 }
@@ -370,7 +226,7 @@
  */
 static int k3_dsp_rproc_attach(struct rproc *rproc)
 {
-	struct k3_dsp_rproc *kproc = rproc->priv;
+	struct k3_rproc *kproc = rproc->priv;
 	struct device *dev = kproc->dev;
 	int ret;
 
@@ -392,7 +248,7 @@
  */
 static int k3_dsp_rproc_detach(struct rproc *rproc)
 {
-	struct k3_dsp_rproc *kproc = rproc->priv;
+	struct k3_rproc *kproc = rproc->priv;
 	struct device *dev = kproc->dev;
 
 	mbox_free_channel(kproc->mbox);
@@ -400,282 +256,20 @@
 	return 0;
 }
 
-/*
- * This function implements the .get_loaded_rsc_table() callback and is used
- * to provide the resource table for a booted DSP in IPC-only mode. The K3 DSP
- * firmwares follow a design-by-contract approach and are expected to have the
- * resource table at the base of the DDR region reserved for firmware usage.
- * This provides flexibility for the remote processor to be booted by different
- * bootloaders that may or may not have the ability to publish the resource table
- * address and size through a DT property. This callback is invoked only in
- * IPC-only mode.
- */
-static struct resource_table *k3_dsp_get_loaded_rsc_table(struct rproc *rproc,
-							  size_t *rsc_table_sz)
-{
-	struct k3_dsp_rproc *kproc = rproc->priv;
-	struct device *dev = kproc->dev;
-
-	if (!kproc->rmem[0].cpu_addr) {
-		dev_err(dev, "memory-region #1 does not exist, loaded rsc table can't be found");
-		return ERR_PTR(-ENOMEM);
-	}
-
-	/*
-	 * NOTE: The resource table size is currently hard-coded to a maximum
-	 * of 256 bytes. The most common resource table usage for K3 firmwares
-	 * is to only have the vdev resource entry and an optional trace entry.
-	 * The exact size could be computed based on resource table address, but
-	 * the hard-coded value suffices to support the IPC-only mode.
-	 */
-	*rsc_table_sz = 256;
-	return (struct resource_table *)kproc->rmem[0].cpu_addr;
-}
-
-/*
- * Custom function to translate a DSP device address (internal RAMs only) to a
- * kernel virtual address.  The DSPs can access their RAMs at either an internal
- * address visible only from a DSP, or at the SoC-level bus address. Both these
- * addresses need to be looked through for translation. The translated addresses
- * can be used either by the remoteproc core for loading (when using kernel
- * remoteproc loader), or by any rpmsg bus drivers.
- */
-static void *k3_dsp_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
-{
-	struct k3_dsp_rproc *kproc = rproc->priv;
-	void __iomem *va = NULL;
-	phys_addr_t bus_addr;
-	u32 dev_addr, offset;
-	size_t size;
-	int i;
-
-	if (len == 0)
-		return NULL;
-
-	for (i = 0; i < kproc->num_mems; i++) {
-		bus_addr = kproc->mem[i].bus_addr;
-		dev_addr = kproc->mem[i].dev_addr;
-		size = kproc->mem[i].size;
-
-		if (da < KEYSTONE_RPROC_LOCAL_ADDRESS_MASK) {
-			/* handle DSP-view addresses */
-			if (da >= dev_addr &&
-			    ((da + len) <= (dev_addr + size))) {
-				offset = da - dev_addr;
-				va = kproc->mem[i].cpu_addr + offset;
-				return (__force void *)va;
-			}
-		} else {
-			/* handle SoC-view addresses */
-			if (da >= bus_addr &&
-			    (da + len) <= (bus_addr + size)) {
-				offset = da - bus_addr;
-				va = kproc->mem[i].cpu_addr + offset;
-				return (__force void *)va;
-			}
-		}
-	}
-
-	/* handle static DDR reserved memory regions */
-	for (i = 0; i < kproc->num_rmems; i++) {
-		dev_addr = kproc->rmem[i].dev_addr;
-		size = kproc->rmem[i].size;
-
-		if (da >= dev_addr && ((da + len) <= (dev_addr + size))) {
-			offset = da - dev_addr;
-			va = kproc->rmem[i].cpu_addr + offset;
-			return (__force void *)va;
-		}
-	}
-
-	return NULL;
-}
 
 static const struct rproc_ops k3_dsp_rproc_ops = {
 	.start		= k3_dsp_rproc_start,
 	.stop		= k3_dsp_rproc_stop,
-	.kick		= k3_dsp_rproc_kick,
-	.da_to_va	= k3_dsp_rproc_da_to_va,
+	.kick		= k3_rproc_kick,
+	.da_to_va	= k3_rproc_da_to_va,
 };
 
-static int k3_dsp_rproc_of_get_memories(struct platform_device *pdev,
-					struct k3_dsp_rproc *kproc)
-{
-	const struct k3_dsp_dev_data *data = kproc->data;
-	struct device *dev = &pdev->dev;
-	struct resource *res;
-	int num_mems = 0;
-	int i;
-
-	num_mems = kproc->data->num_mems;
-	kproc->mem = devm_kcalloc(kproc->dev, num_mems,
-				  sizeof(*kproc->mem), GFP_KERNEL);
-	if (!kproc->mem)
-		return -ENOMEM;
-
-	for (i = 0; i < num_mems; i++) {
-		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						   data->mems[i].name);
-		if (!res) {
-			dev_err(dev, "found no memory resource for %s\n",
-				data->mems[i].name);
-			return -EINVAL;
-		}
-		if (!devm_request_mem_region(dev, res->start,
-					     resource_size(res),
-					     dev_name(dev))) {
-			dev_err(dev, "could not request %s region for resource\n",
-				data->mems[i].name);
-			return -EBUSY;
-		}
-
-		kproc->mem[i].cpu_addr = devm_ioremap_wc(dev, res->start,
-							 resource_size(res));
-		if (!kproc->mem[i].cpu_addr) {
-			dev_err(dev, "failed to map %s memory\n",
-				data->mems[i].name);
-			return -ENOMEM;
-		}
-		kproc->mem[i].bus_addr = res->start;
-		kproc->mem[i].dev_addr = data->mems[i].dev_addr;
-		kproc->mem[i].size = resource_size(res);
-
-		dev_dbg(dev, "memory %8s: bus addr %pa size 0x%zx va %pK da 0x%x\n",
-			data->mems[i].name, &kproc->mem[i].bus_addr,
-			kproc->mem[i].size, kproc->mem[i].cpu_addr,
-			kproc->mem[i].dev_addr);
-	}
-	kproc->num_mems = num_mems;
-
-	return 0;
-}
-
-static int k3_dsp_reserved_mem_init(struct k3_dsp_rproc *kproc)
-{
-	struct device *dev = kproc->dev;
-	struct device_node *np = dev->of_node;
-	struct device_node *rmem_np;
-	struct reserved_mem *rmem;
-	int num_rmems;
-	int ret, i;
-
-	num_rmems = of_property_count_elems_of_size(np, "memory-region",
-						    sizeof(phandle));
-	if (num_rmems <= 0) {
-		dev_err(dev, "device does not reserved memory regions, ret = %d\n",
-			num_rmems);
-		return -EINVAL;
-	}
-	if (num_rmems < 2) {
-		dev_err(dev, "device needs at least two memory regions to be defined, num = %d\n",
-			num_rmems);
-		return -EINVAL;
-	}
-
-	/* use reserved memory region 0 for vring DMA allocations */
-	ret = of_reserved_mem_device_init_by_idx(dev, np, 0);
-	if (ret) {
-		dev_err(dev, "device cannot initialize DMA pool, ret = %d\n",
-			ret);
-		return ret;
-	}
-
-	num_rmems--;
-	kproc->rmem = kcalloc(num_rmems, sizeof(*kproc->rmem), GFP_KERNEL);
-	if (!kproc->rmem) {
-		ret = -ENOMEM;
-		goto release_rmem;
-	}
-
-	/* use remaining reserved memory regions for static carveouts */
-	for (i = 0; i < num_rmems; i++) {
-		rmem_np = of_parse_phandle(np, "memory-region", i + 1);
-		if (!rmem_np) {
-			ret = -EINVAL;
-			goto unmap_rmem;
-		}
-
-		rmem = of_reserved_mem_lookup(rmem_np);
-		if (!rmem) {
-			of_node_put(rmem_np);
-			ret = -EINVAL;
-			goto unmap_rmem;
-		}
-		of_node_put(rmem_np);
-
-		kproc->rmem[i].bus_addr = rmem->base;
-		/* 64-bit address regions currently not supported */
-		kproc->rmem[i].dev_addr = (u32)rmem->base;
-		kproc->rmem[i].size = rmem->size;
-		kproc->rmem[i].cpu_addr = ioremap_wc(rmem->base, rmem->size);
-		if (!kproc->rmem[i].cpu_addr) {
-			dev_err(dev, "failed to map reserved memory#%d at %pa of size %pa\n",
-				i + 1, &rmem->base, &rmem->size);
-			ret = -ENOMEM;
-			goto unmap_rmem;
-		}
-
-		dev_dbg(dev, "reserved memory%d: bus addr %pa size 0x%zx va %pK da 0x%x\n",
-			i + 1, &kproc->rmem[i].bus_addr,
-			kproc->rmem[i].size, kproc->rmem[i].cpu_addr,
-			kproc->rmem[i].dev_addr);
-	}
-	kproc->num_rmems = num_rmems;
-
-	return 0;
-
-unmap_rmem:
-	for (i--; i >= 0; i--)
-		iounmap(kproc->rmem[i].cpu_addr);
-	kfree(kproc->rmem);
-release_rmem:
-	of_reserved_mem_device_release(kproc->dev);
-	return ret;
-}
-
-static void k3_dsp_reserved_mem_exit(struct k3_dsp_rproc *kproc)
-{
-	int i;
-
-	for (i = 0; i < kproc->num_rmems; i++)
-		iounmap(kproc->rmem[i].cpu_addr);
-	kfree(kproc->rmem);
-
-	of_reserved_mem_device_release(kproc->dev);
-}
-
-static
-struct ti_sci_proc *k3_dsp_rproc_of_get_tsp(struct device *dev,
-					    const struct ti_sci_handle *sci)
-{
-	struct ti_sci_proc *tsp;
-	u32 temp[2];
-	int ret;
-
-	ret = of_property_read_u32_array(dev->of_node, "ti,sci-proc-ids",
-					 temp, 2);
-	if (ret < 0)
-		return ERR_PTR(ret);
-
-	tsp = kzalloc(sizeof(*tsp), GFP_KERNEL);
-	if (!tsp)
-		return ERR_PTR(-ENOMEM);
-
-	tsp->dev = dev;
-	tsp->sci = sci;
-	tsp->ops = &sci->ops.proc_ops;
-	tsp->proc_id = temp[0];
-	tsp->host_id = temp[1];
-
-	return tsp;
-}
-
 static int k3_dsp_rproc_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct device_node *np = dev->of_node;
-	const struct k3_dsp_dev_data *data;
-	struct k3_dsp_rproc *kproc;
+	const struct k3_rproc_dev_data *data;
+	struct k3_rproc *kproc;
 	struct rproc *rproc;
 	const char *fw_name;
 	bool p_state = false;
@@ -733,7 +327,7 @@
 		goto put_sci;
 	}
 
-	kproc->tsp = k3_dsp_rproc_of_get_tsp(dev, kproc->ti_sci);
+	kproc->tsp = k3_rproc_of_get_tsp(dev, kproc->ti_sci);
 	if (IS_ERR(kproc->tsp)) {
 		dev_err(dev, "failed to construct ti-sci proc control, ret = %d\n",
 			ret);
@@ -747,11 +341,11 @@
 		goto free_tsp;
 	}
 
-	ret = k3_dsp_rproc_of_get_memories(pdev, kproc);
+	ret = k3_rproc_of_get_memories(pdev, kproc);
 	if (ret)
 		goto release_tsp;
 
-	ret = k3_dsp_reserved_mem_init(kproc);
+	ret = k3_reserved_mem_init(kproc);
 	if (ret) {
 		dev_err(dev, "reserved memory init failed, ret = %d\n", ret);
 		goto release_tsp;
@@ -776,7 +370,7 @@
 		rproc->ops->stop = NULL;
 		rproc->ops->attach = k3_dsp_rproc_attach;
 		rproc->ops->detach = k3_dsp_rproc_detach;
-		rproc->ops->get_loaded_rsc_table = k3_dsp_get_loaded_rsc_table;
+		rproc->ops->get_loaded_rsc_table = k3_get_loaded_rsc_table;
 	} else {
 		dev_info(dev, "configured DSP for remoteproc mode\n");
 		/*
@@ -792,7 +386,7 @@
 				goto release_mem;
 			} else if (ret == 0) {
 				dev_warn(dev, "local reset is deasserted for device\n");
-				k3_dsp_rproc_reset(kproc);
+				k3_rproc_reset(kproc);
 			}
 		}
 	}
@@ -809,7 +403,7 @@
 	return 0;
 
 release_mem:
-	k3_dsp_reserved_mem_exit(kproc);
+	k3_reserved_mem_exit(kproc);
 release_tsp:
 	ret1 = ti_sci_proc_release(kproc->tsp);
 	if (ret1)
@@ -827,7 +421,7 @@
 
 static int k3_dsp_rproc_remove(struct platform_device *pdev)
 {
-	struct k3_dsp_rproc *kproc = platform_get_drvdata(pdev);
+	struct k3_rproc *kproc = platform_get_drvdata(pdev);
 	struct rproc *rproc = kproc->rproc;
 	struct device *dev = &pdev->dev;
 	int ret;
@@ -852,42 +446,54 @@
 	if (ret)
 		dev_err(dev, "failed to put ti_sci handle, ret = %d\n", ret);
 
-	k3_dsp_reserved_mem_exit(kproc);
+	k3_reserved_mem_exit(kproc);
 	rproc_free(kproc->rproc);
 
 	return 0;
 }
 
-static const struct k3_dsp_mem_data c66_mems[] = {
+static const struct k3_rproc_mem_data c66_mems[] = {
 	{ .name = "l2sram", .dev_addr = 0x800000 },
 	{ .name = "l1pram", .dev_addr = 0xe00000 },
 	{ .name = "l1dram", .dev_addr = 0xf00000 },
 };
 
 /* C71x cores only have a L1P Cache, there are no L1P SRAMs */
-static const struct k3_dsp_mem_data c71_mems[] = {
+static const struct k3_rproc_mem_data c71_mems[] = {
 	{ .name = "l2sram", .dev_addr = 0x800000 },
 	{ .name = "l1dram", .dev_addr = 0xe00000 },
 };
 
-static const struct k3_dsp_dev_data c66_data = {
+static const struct k3_rproc_mem_data c7xv_mems[] = {
+	{ .name = "l2sram", .dev_addr = 0x800000 },
+};
+
+static const struct k3_rproc_dev_data c66_data = {
 	.mems = c66_mems,
 	.num_mems = ARRAY_SIZE(c66_mems),
 	.boot_align_addr = SZ_1K,
 	.uses_lreset = true,
 };
 
-static const struct k3_dsp_dev_data c71_data = {
+static const struct k3_rproc_dev_data c71_data = {
 	.mems = c71_mems,
 	.num_mems = ARRAY_SIZE(c71_mems),
 	.boot_align_addr = SZ_2M,
 	.uses_lreset = false,
 };
 
+static const struct k3_rproc_dev_data c7xv_data = {
+	.mems = c7xv_mems,
+	.num_mems = ARRAY_SIZE(c7xv_mems),
+	.boot_align_addr = SZ_2M,
+	.uses_lreset = false,
+};
+
 static const struct of_device_id k3_dsp_of_match[] = {
 	{ .compatible = "ti,j721e-c66-dsp", .data = &c66_data, },
 	{ .compatible = "ti,j721e-c71-dsp", .data = &c71_data, },
 	{ .compatible = "ti,j721s2-c71-dsp", .data = &c71_data, },
+	{ .compatible = "ti,am62a-c7xv-dsp", .data = &c7xv_data, },
 	{ /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, k3_dsp_of_match);
diff -Naur --no-dereference a/drivers/remoteproc/ti_k3_m4_remoteproc.c b/drivers/remoteproc/ti_k3_m4_remoteproc.c
--- a/drivers/remoteproc/ti_k3_m4_remoteproc.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/remoteproc/ti_k3_m4_remoteproc.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,592 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * TI K3 Cortex-M4 Remote Processor(s) driver
+ *
+ * Copyright (C) 2021 Texas Instruments Incorporated - https://www.ti.com/
+ *	Hari Nagalla <hnagalla@ti.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mailbox_client.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/omap-mailbox.h>
+#include <linux/platform_device.h>
+#include <linux/remoteproc.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
+
+#include "omap_remoteproc.h"
+#include "remoteproc_internal.h"
+#include "ti_sci_proc.h"
+#include "ti_k3_common.h"
+
+/**
+ * k3_m4_rproc_mbox_callback() - inbound mailbox message handler
+ * @client: mailbox client pointer used for requesting the mailbox channel
+ * @data: mailbox payload
+ *
+ * This handler is invoked by the OMAP mailbox driver whenever a mailbox
+ * message is received. Usually, the mailbox payload simply contains
+ * the index of the virtqueue that is kicked by the remote processor,
+ * and we let remoteproc core handle it.
+ *
+ * In addition to virtqueue indices, we also have some out-of-band values
+ * that indicate different events. Those values are deliberately very
+ * large so they don't coincide with virtqueue indices.
+ */
+static void k3_m4_rproc_mbox_callback(struct mbox_client *client, void *data)
+{
+	struct k3_rproc *kproc = container_of(client, struct k3_rproc,
+						  client);
+	struct device *dev = kproc->rproc->dev.parent;
+	const char *name = kproc->rproc->name;
+	u32 msg = omap_mbox_message(data);
+
+	switch (msg) {
+	case RP_MBOX_CRASH:
+		/*
+		 * remoteproc detected an exception, but error recovery is not
+		 * supported. So, just log this for now
+		 */
+		dev_err(dev, "K3 M4 rproc %s crashed\n", name);
+		break;
+	case RP_MBOX_ECHO_REPLY:
+		dev_info(dev, "received echo reply from %s\n", name);
+		break;
+	case RP_MBOX_SHUTDOWN_ACK:
+		dev_dbg(dev, "received shutdown_ack from %s\n", name);
+		complete(&kproc->shut_comp);
+		break;
+	case RP_MBOX_SUSPEND_ACK:
+		dev_dbg(dev, "received suspend_ack from %s\n", name);
+		complete(&kproc->suspend_comp);
+		break;
+	default:
+		/* silently handle all other valid messages */
+		if (msg >= RP_MBOX_READY && msg < RP_MBOX_END_MSG)
+			return;
+		if (msg > kproc->rproc->max_notifyid) {
+			dev_dbg(dev, "dropping unknown message 0x%x", msg);
+			return;
+		}
+		/* msg contains the index of the triggered vring */
+		if (rproc_vq_interrupt(kproc->rproc, msg) == IRQ_NONE)
+			dev_dbg(dev, "no message was found in vqid %d\n", msg);
+	}
+}
+
+static int k3_m4_rproc_request_mbox(struct rproc *rproc)
+{
+	struct k3_rproc *kproc = rproc->priv;
+	struct mbox_client *client = &kproc->client;
+	struct device *dev = kproc->dev;
+	int ret;
+
+	client->dev = dev;
+	client->tx_done = NULL;
+	client->rx_callback = k3_m4_rproc_mbox_callback;
+	client->tx_block = false;
+	client->knows_txdone = false;
+
+	kproc->mbox = mbox_request_channel(client, 0);
+	if (IS_ERR(kproc->mbox)) {
+		ret = -EBUSY;
+		dev_err(dev, "mbox_request_channel failed: %ld\n",
+			PTR_ERR(kproc->mbox));
+		return ret;
+	}
+
+	/*
+	 * Ping the remote processor, this is only for sanity-sake for now;
+	 * there is no functional effect whatsoever.
+	 *
+	 * Note that the reply will _not_ arrive immediately: this message
+	 * will wait in the mailbox fifo until the remote processor is booted.
+	 */
+	ret = mbox_send_message(kproc->mbox, (void *)RP_MBOX_ECHO_REQUEST);
+	if (ret < 0) {
+		dev_err(dev, "mbox_send_message failed: %d\n", ret);
+		mbox_free_channel(kproc->mbox);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * The M4F cores have a local reset that affects only the CPU, and a
+ * generic module reset that powers on the device and allows the M4 internal
+ * memories to be accessed while the local reset is asserted. This function is
+ * used to release the global reset on M4F to allow loading into the M4F
+ * internal RAMs. The .prepare() ops is invoked by remoteproc core before any
+ * firmware loading, and is followed by the .start() ops after loading to
+ * actually let the M4F core run.
+ */
+static int k3_m4_rproc_prepare(struct rproc *rproc)
+{
+	struct k3_rproc *kproc = rproc->priv;
+	struct device *dev = kproc->dev;
+	int ret;
+
+	/* IPC-only mode does not require the core to be released from reset */
+	if (kproc->ipc_only)
+		return 0;
+
+	ret = kproc->ti_sci->ops.dev_ops.get_device(kproc->ti_sci,
+						    kproc->ti_sci_id);
+	if (ret)
+		dev_err(dev, "module-reset deassert failed, cannot enable internal RAM loading, ret = %d\n",
+			ret);
+
+	return ret;
+}
+
+/*
+ * This function implements the .unprepare() ops and performs the complimentary
+ * operations to that of the .prepare() ops. The function is used to assert the
+ * global reset on applicable M4F cores. This completes the second portion of
+ * powering down the M4F cores. The cores themselves are only halted in the
+ * .stop() callback through the local reset, and the .unprepare() ops is invoked
+ * by the remoteproc core after the remoteproc is stopped to balance the global
+ * reset.
+ */
+static int k3_m4_rproc_unprepare(struct rproc *rproc)
+{
+	struct k3_rproc *kproc = rproc->priv;
+	struct device *dev = kproc->dev;
+	int ret;
+
+	/* do not put back the cores into reset in IPC-only mode */
+	if (kproc->ipc_only)
+		return 0;
+
+	ret = kproc->ti_sci->ops.dev_ops.put_device(kproc->ti_sci,
+						    kproc->ti_sci_id);
+	if (ret)
+		dev_err(dev, "module-reset assert failed, ret = %d\n", ret);
+
+	return ret;
+}
+
+/*
+ * PM notifier call.
+ * This is a callback function for PM notifications. On a resume completion
+ * i.e after all the resume driver calls are handled on PM_POST_SUSPEND,
+ * on a deep sleep the remote core is rebooted.
+ */
+static int m4f_pm_notifier_call(struct notifier_block *bl,
+				unsigned long state, void *unused)
+{
+	struct k3_rproc *kproc = container_of(bl, struct k3_rproc, pm_notifier);
+	unsigned long msg = RP_MBOX_SUSPEND_SYSTEM;
+	unsigned long to = msecs_to_jiffies(3000);
+	int ret;
+
+	switch (state) {
+	case PM_HIBERNATION_PREPARE:
+	case PM_RESTORE_PREPARE:
+	case PM_SUSPEND_PREPARE:
+		if (!device_may_wakeup(kproc->dev)) {
+			rproc_shutdown(kproc->rproc);
+		} else {
+			reinit_completion(&kproc->suspend_comp);
+			ret = mbox_send_message(kproc->mbox, (void *)msg);
+			if (ret < 0) {
+				dev_err(kproc->dev, "PM mbox_send_message failed: %d\n", ret);
+				return ret;
+			}
+			ret = wait_for_completion_timeout(&kproc->suspend_comp, to);
+			if (ret == 0) {
+				dev_err(kproc->dev,
+					"%s: timedout waiting for rproc completion event\n", __func__);
+				return -EBUSY;
+			};
+		}
+		kproc->rproc->state = RPROC_SUSPENDED;
+		break;
+	case PM_POST_HIBERNATION:
+	case PM_POST_RESTORE:
+	case PM_POST_SUSPEND:
+		if (kproc->rproc->state == RPROC_SUSPENDED) {
+			if (!device_may_wakeup(kproc->dev)) {
+				rproc_boot(kproc->rproc);
+			} else {
+				msg = RP_MBOX_ECHO_REQUEST;
+				ret = mbox_send_message(kproc->mbox, (void *)msg);
+				if (ret < 0) {
+					dev_err(kproc->dev,
+						"PM mbox_send_message failed: %d\n", ret);
+					return ret;
+				}
+			}
+			kproc->rproc->state = RPROC_RUNNING;
+		}
+		break;
+	}
+	return 0;
+}
+
+/*
+ * Power up the M4F remote processor.
+ *
+ * This function will be invoked only after the firmware for this rproc
+ * was loaded, parsed successfully, and all of its resource requirements
+ * were met.
+ */
+static int k3_m4_rproc_start(struct rproc *rproc)
+{
+	struct k3_rproc *kproc = rproc->priv;
+	struct device *dev = kproc->dev;
+	int ret;
+
+	if (kproc->ipc_only) {
+		dev_err(dev, "%s cannot be invoked in IPC-only mode\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	ret = k3_m4_rproc_request_mbox(rproc);
+	if (ret)
+		return ret;
+
+	ret = k3_rproc_release(kproc);
+	if (ret)
+		goto put_mbox;
+
+	return 0;
+
+put_mbox:
+	mbox_free_channel(kproc->mbox);
+	return ret;
+}
+
+/*
+ * Stop the M4 remote processor.
+ *
+ * This function puts the M4 processor into reset, and finishes processing
+ * of any pending messages.
+ */
+static int k3_m4_rproc_stop(struct rproc *rproc)
+{
+	unsigned long to = msecs_to_jiffies(3000);
+	struct k3_rproc *kproc = rproc->priv;
+	struct device *dev = kproc->dev;
+	unsigned long msg = RP_MBOX_SHUTDOWN;
+	int ret;
+
+	if (kproc->ipc_only) {
+		dev_err(dev, "%s cannot be invoked in IPC-only mode\n",
+			__func__);
+		return -EINVAL;
+	}
+
+	reinit_completion(&kproc->shut_comp);
+	ret = mbox_send_message(kproc->mbox, (void *)msg);
+	if (ret < 0) {
+		dev_err(dev, "PM mbox_send_message failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = wait_for_completion_timeout(&kproc->shut_comp, to);
+	if (ret == 0) {
+		dev_err(dev, "%s: timedout waiting for rproc completion event\n", __func__);
+		return -EBUSY;
+	};
+
+	mbox_free_channel(kproc->mbox);
+	/* allow some time for the remote core to enter quiescent state
+	 * (ex:wfi) after sending SHUTDOWN ack. Typically, remote core is
+	 * expected to enter 'wfi' right after sending the ack. 1 ms is
+	 * more than sufficient for this prupose
+	 */
+	msleep(1);
+
+	k3_rproc_reset(kproc);
+
+	return 0;
+}
+
+/*
+ * Attach to a running M4 remote processor (IPC-only mode)
+ *
+ * This rproc attach callback only needs to request the mailbox, the remote
+ * processor is already booted, so there is no need to issue any TI-SCI
+ * commands to boot the M4 core.
+ */
+static int k3_m4_rproc_attach(struct rproc *rproc)
+{
+	struct k3_rproc *kproc = rproc->priv;
+	struct device *dev = kproc->dev;
+	int ret;
+
+	if (!kproc->ipc_only || rproc->state != RPROC_DETACHED) {
+		dev_err(dev, "M4 is expected to be in IPC-only mode and RPROC_DETACHED state\n");
+		return -EINVAL;
+	}
+
+	ret = k3_m4_rproc_request_mbox(rproc);
+	if (ret)
+		return ret;
+
+	dev_err(dev, "M4 initialized in IPC-only mode\n");
+	return 0;
+}
+
+/*
+ * Detach from a running M4 remote processor (IPC-only mode)
+ *
+ * This rproc detach callback performs the opposite operation to attach callback
+ * and only needs to release the mailbox, the M4 core is not stopped and will
+ * be left to continue to run its booted firmware.
+ */
+static int k3_m4_rproc_detach(struct rproc *rproc)
+{
+	struct k3_rproc *kproc = rproc->priv;
+	struct device *dev = kproc->dev;
+
+	if (!kproc->ipc_only || rproc->state != RPROC_ATTACHED) {
+		dev_err(dev, "M4 is expected to be in IPC-only mode and RPROC_ATTACHED state\n");
+		return -EINVAL;
+	}
+
+	mbox_free_channel(kproc->mbox);
+	dev_err(dev, "M4 deinitialized in IPC-only mode\n");
+	return 0;
+}
+
+
+
+static const struct rproc_ops k3_m4_rproc_ops = {
+	.start		= k3_m4_rproc_start,
+	.stop		= k3_m4_rproc_stop,
+	.attach		= k3_m4_rproc_attach,
+	.detach		= k3_m4_rproc_detach,
+	.kick		= k3_rproc_kick,
+	.da_to_va	= k3_rproc_da_to_va,
+	.get_loaded_rsc_table = k3_get_loaded_rsc_table,
+};
+
+static int k3_m4_rproc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	const struct k3_rproc_dev_data *data;
+	struct k3_rproc *kproc;
+	struct rproc *rproc;
+	const char *fw_name;
+	bool r_state = false;
+	bool p_state = false;
+	int ret = 0;
+	int ret1;
+
+	data = of_device_get_match_data(dev);
+	if (!data)
+		return -ENODEV;
+
+	ret = rproc_of_parse_firmware(dev, 0, &fw_name);
+	if (ret) {
+		dev_err(dev, "failed to parse firmware-name property, ret = %d\n",
+			ret);
+		return ret;
+	}
+
+	rproc = rproc_alloc(dev, dev_name(dev), &k3_m4_rproc_ops, fw_name,
+			    sizeof(*kproc));
+	if (!rproc)
+		return -ENOMEM;
+
+	rproc->has_iommu = false;
+	rproc->recovery_disabled = true;
+	if (data->uses_lreset) {
+		rproc->ops->prepare = k3_m4_rproc_prepare;
+		rproc->ops->unprepare = k3_m4_rproc_unprepare;
+	}
+	kproc = rproc->priv;
+	kproc->rproc = rproc;
+	kproc->dev = dev;
+	kproc->data = data;
+
+	kproc->ti_sci = ti_sci_get_by_phandle(np, "ti,sci");
+	if (IS_ERR(kproc->ti_sci)) {
+		ret = PTR_ERR(kproc->ti_sci);
+		if (ret != -EPROBE_DEFER) {
+			dev_err(dev, "failed to get ti-sci handle, ret = %d\n",
+				ret);
+		}
+		kproc->ti_sci = NULL;
+		goto free_rproc;
+	}
+
+	ret = of_property_read_u32(np, "ti,sci-dev-id", &kproc->ti_sci_id);
+	if (ret) {
+		dev_err(dev, "missing 'ti,sci-dev-id' property\n");
+		goto put_sci;
+	}
+
+	if (device_property_present(dev, "wakeup-source")) {
+		dev_dbg(dev, "registering as wakeup source\n");
+		device_set_wakeup_capable(dev, true);
+	}
+
+	kproc->reset = devm_reset_control_get_exclusive(dev, NULL);
+	if (IS_ERR(kproc->reset)) {
+		ret = PTR_ERR(kproc->reset);
+		dev_err(dev, "failed to get reset, status = %d\n", ret);
+		goto put_sci;
+	}
+
+	kproc->tsp = k3_rproc_of_get_tsp(dev, kproc->ti_sci);
+	if (IS_ERR(kproc->tsp)) {
+		dev_err(dev, "failed to construct ti-sci proc control, ret = %d\n",
+			ret);
+		ret = PTR_ERR(kproc->tsp);
+		goto put_sci;
+	}
+
+	init_completion(&kproc->shut_comp);
+	init_completion(&kproc->suspend_comp);
+
+	ret = ti_sci_proc_request(kproc->tsp);
+	if (ret < 0) {
+		dev_err(dev, "ti_sci_proc_request failed, ret = %d\n", ret);
+		goto free_tsp;
+	}
+
+	ret = k3_rproc_of_get_memories(pdev, kproc);
+	if (ret)
+		goto release_tsp;
+
+	ret = k3_reserved_mem_init(kproc);
+	if (ret) {
+		dev_err(dev, "reserved memory init failed, ret = %d\n", ret);
+		goto release_tsp;
+	}
+
+	ret = kproc->ti_sci->ops.dev_ops.is_on(kproc->ti_sci, kproc->ti_sci_id,
+					       &r_state, &p_state);
+	if (ret) {
+		dev_err(dev, "failed to get initial state, mode cannot be determined, ret = %d\n",
+			ret);
+		goto release_mem;
+	}
+
+	/* configure devices for either remoteproc or IPC-only mode */
+	if (p_state) {
+		dev_err(dev, "configured M4 for IPC-only mode\n");
+		rproc->state = RPROC_DETACHED;
+		kproc->ipc_only = true;
+	} else {
+		dev_err(dev, "configured M4 for remoteproc mode\n");
+		/*
+		 * ensure the M4 local reset is asserted to ensure the core
+		 * doesn't execute bogus code in .prepare() when the module
+		 * reset is released.
+		 */
+		if (data->uses_lreset) {
+			ret = reset_control_status(kproc->reset);
+			if (ret < 0) {
+				dev_err(dev, "failed to get reset status, status = %d\n",
+					ret);
+				goto release_mem;
+			} else if (ret == 0) {
+				dev_warn(dev, "local reset is deasserted for device\n");
+				k3_rproc_reset(kproc);
+			}
+		}
+	}
+
+	ret = rproc_add(rproc);
+	if (ret) {
+		dev_err(dev, "failed to add register device with remoteproc core, status = %d\n",
+			ret);
+		goto release_mem;
+	}
+
+	platform_set_drvdata(pdev, kproc);
+
+	/* configure pm notifier calls */
+	kproc->pm_notifier.notifier_call = m4f_pm_notifier_call;
+	register_pm_notifier(&kproc->pm_notifier);
+
+	return 0;
+
+release_mem:
+	k3_reserved_mem_exit(kproc);
+release_tsp:
+	ret1 = ti_sci_proc_release(kproc->tsp);
+	if (ret1)
+		dev_err(dev, "failed to release proc, ret = %d\n", ret1);
+free_tsp:
+	kfree(kproc->tsp);
+put_sci:
+	ret1 = ti_sci_put_handle(kproc->ti_sci);
+	if (ret1)
+		dev_err(dev, "failed to put ti_sci handle, ret = %d\n", ret1);
+free_rproc:
+	rproc_free(rproc);
+	return ret;
+}
+
+static int k3_m4_rproc_remove(struct platform_device *pdev)
+{
+	struct k3_rproc *kproc = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	rproc_del(kproc->rproc);
+
+	ret = ti_sci_proc_release(kproc->tsp);
+	if (ret)
+		dev_err(dev, "failed to release proc, ret = %d\n", ret);
+
+	kfree(kproc->tsp);
+
+	ret = ti_sci_put_handle(kproc->ti_sci);
+	if (ret)
+		dev_err(dev, "failed to put ti_sci handle, ret = %d\n", ret);
+
+	k3_reserved_mem_exit(kproc);
+
+	unregister_pm_notifier(&kproc->pm_notifier);
+
+	rproc_free(kproc->rproc);
+
+	return 0;
+}
+
+static const struct k3_rproc_mem_data am64_m4_mems[] = {
+	{ .name = "iram", .dev_addr = 0x0 },
+	{ .name = "dram", .dev_addr = 0x30000 },
+};
+
+static const struct k3_rproc_dev_data am64_m4_data = {
+	.mems = am64_m4_mems,
+	.num_mems = ARRAY_SIZE(am64_m4_mems),
+	.boot_align_addr = SZ_1K,
+	.uses_lreset = true,
+};
+
+static const struct of_device_id k3_m4_of_match[] = {
+	{ .compatible = "ti,am64-m4fss", .data = &am64_m4_data, },
+	{ /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, k3_m4_of_match);
+
+static struct platform_driver k3_m4_rproc_driver = {
+	.probe	= k3_m4_rproc_probe,
+	.remove	= k3_m4_rproc_remove,
+	.driver	= {
+		.name = "k3-m4-rproc",
+		.of_match_table = k3_m4_of_match,
+	},
+};
+
+module_platform_driver(k3_m4_rproc_driver);
+
+MODULE_AUTHOR("Hari Nagalla <hnagalla@ti.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI K3 M4 Remoteproc driver");
diff -Naur --no-dereference a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c
--- a/drivers/remoteproc/ti_k3_r5_remoteproc.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c	2024-01-28 14:01:31.252353813 -0500
@@ -6,9 +6,11 @@
  *	Suman Anna <s-anna@ti.com>
  */
 
+#include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
+#include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/mailbox_client.h>
 #include <linux/module.h>
@@ -21,6 +23,7 @@
 #include <linux/remoteproc.h>
 #include <linux/reset.h>
 #include <linux/slab.h>
+#include <linux/suspend.h>
 
 #include "omap_remoteproc.h"
 #include "remoteproc_internal.h"
@@ -71,14 +74,16 @@
 /*
  * All cluster mode values are not applicable on all SoCs. The following
  * are the modes supported on various SoCs:
- *   Split mode      : AM65x, J721E, J7200 and AM64x SoCs
- *   LockStep mode   : AM65x, J721E and J7200 SoCs
- *   Single-CPU mode : AM64x SoCs only
+ *   Split mode       : AM65x, J721E, J7200 and AM64x SoCs
+ *   LockStep mode    : AM65x, J721E and J7200 SoCs
+ *   Single-CPU mode  : AM64x SoCs only
+ *   Single-Core mode : AM62x, AM62A SoCs
  */
 enum cluster_mode {
 	CLUSTER_MODE_SPLIT = 0,
 	CLUSTER_MODE_LOCKSTEP,
 	CLUSTER_MODE_SINGLECPU,
+	CLUSTER_MODE_SINGLECORE
 };
 
 /**
@@ -86,11 +91,13 @@
  * @tcm_is_double: flag to denote the larger unified TCMs in certain modes
  * @tcm_ecc_autoinit: flag to denote the auto-initialization of TCMs for ECC
  * @single_cpu_mode: flag to denote if SoC/IP supports Single-CPU mode
+ * @is_single_core: flag to denote if SoC/IP has only single core R5
  */
 struct k3_r5_soc_data {
 	bool tcm_is_double;
 	bool tcm_ecc_autoinit;
 	bool single_cpu_mode;
+	bool is_single_core;
 };
 
 /**
@@ -161,9 +168,33 @@
 	struct k3_r5_core *core;
 	struct k3_r5_mem *rmem;
 	int num_rmems;
+	struct completion shut_comp;
+	struct completion suspend_comp;
+	struct notifier_block pm_notifier;
 };
 
 /**
+ * is_core_in_wfi - local utility function to check core status
+ * @core: remote core pointer used for checking core status
+ *
+ * This utility function is invoked by the shutdown sequence to ensure
+ * the remote core is in wfi, before asserting a reset.
+ */
+static int is_core_in_wfi(struct k3_r5_core *core)
+{
+	int ret;
+	u64 boot_vec = 0;
+	u32 cfg = 0, ctrl = 0, stat = 0;
+
+	ret = ti_sci_proc_get_status(core->tsp, &boot_vec, &cfg, &ctrl, &stat);
+
+	if (ret < 0)
+		return 0;
+
+	return (stat & PROC_BOOT_STATUS_FLAG_R5_WFI);
+}
+
+/**
  * k3_r5_rproc_mbox_callback() - inbound mailbox message handler
  * @client: mailbox client pointer used for requesting the mailbox channel
  * @data: mailbox payload
@@ -198,6 +229,14 @@
 	case RP_MBOX_ECHO_REPLY:
 		dev_info(dev, "received echo reply from %s\n", name);
 		break;
+	case RP_MBOX_SHUTDOWN_ACK:
+		dev_dbg(dev, "received shutdown_ack from %s\n", name);
+		complete(&kproc->shut_comp);
+		break;
+	case RP_MBOX_SUSPEND_ACK:
+		dev_dbg(dev, "received suspend_ack from %s\n", name);
+		complete(&kproc->suspend_comp);
+		break;
 	default:
 		/* silently handle all other valid messages */
 		if (msg >= RP_MBOX_READY && msg < RP_MBOX_END_MSG)
@@ -238,15 +277,6 @@
 		return ret;
 	}
 
-	ret = core->ti_sci->ops.dev_ops.put_device(core->ti_sci,
-						   core->ti_sci_id);
-	if (ret) {
-		dev_err(core->dev, "module-reset assert failed, ret = %d\n",
-			ret);
-		if (reset_control_deassert(core->reset))
-			dev_warn(core->dev, "local-reset deassert back failed\n");
-	}
-
 	return ret;
 }
 
@@ -414,6 +444,73 @@
 	return 0;
 }
 
+
+/* PM notifier call.
+ * This is a callback function for PM notifications. On a resume completion
+ * i.e after all the resume driver calls are handled on PM_POST_SUSPEND,
+ * on a deep sleep the remote core is rebooted.
+ */
+static int r5f_pm_notifier_call(struct notifier_block *bl,
+				unsigned long state, void *unused)
+{
+	struct k3_r5_rproc *kproc = container_of(bl, struct k3_r5_rproc, pm_notifier);
+	unsigned long msg = RP_MBOX_SUSPEND_SYSTEM;
+	unsigned long to = msecs_to_jiffies(5000);
+	int ret;
+
+	switch (state) {
+	case PM_HIBERNATION_PREPARE:
+	case PM_RESTORE_PREPARE:
+	case PM_SUSPEND_PREPARE:
+		if (!device_may_wakeup(kproc->dev)) {
+			rproc_shutdown(kproc->rproc);
+			ret = kproc->core->ti_sci->ops.dev_ops.put_device(kproc->core->ti_sci,
+									kproc->core->ti_sci_id);
+			if (ret) {
+				dev_err(kproc->core->dev, "module-reset assert failed, ret = %d\n",
+						ret);
+				if (reset_control_deassert(kproc->core->reset))
+					dev_warn(kproc->core->dev, "local-reset deassert back failed\n");
+			}
+
+		} else {
+			reinit_completion(&kproc->suspend_comp);
+			ret = mbox_send_message(kproc->mbox, (void *)msg);
+			if (ret < 0) {
+				dev_err(kproc->dev, "PM mbox_send_message failed: %d\n", ret);
+				return ret;
+			}
+			ret = wait_for_completion_timeout(&kproc->suspend_comp, to);
+			if (ret == 0) {
+				dev_err(kproc->dev,
+					"%s: timedout waiting for rproc completion event\n", __func__);
+				return -EBUSY;
+			};
+		}
+		kproc->rproc->state = RPROC_SUSPENDED;
+		break;
+	case PM_POST_HIBERNATION:
+	case PM_POST_RESTORE:
+	case PM_POST_SUSPEND:
+		if (kproc->rproc->state == RPROC_SUSPENDED) {
+			if (!device_may_wakeup(kproc->dev)) {
+				rproc_boot(kproc->rproc);
+			} else {
+				msg = RP_MBOX_ECHO_REQUEST;
+				ret = mbox_send_message(kproc->mbox, (void *)msg);
+				if (ret < 0) {
+					dev_err(kproc->dev,
+						"PM mbox_send_message failed: %d\n", ret);
+					return ret;
+				}
+			}
+			kproc->rproc->state = RPROC_RUNNING;
+		}
+		break;
+	}
+	return 0;
+}
+
 /*
  * The R5F cores have controls for both a reset and a halt/run. The code
  * execution from DDR requires the initial boot-strapping code to be run
@@ -606,10 +703,14 @@
  */
 static int k3_r5_rproc_stop(struct rproc *rproc)
 {
+	unsigned long to  = msecs_to_jiffies(5000);
 	struct k3_r5_rproc *kproc = rproc->priv;
 	struct k3_r5_cluster *cluster = kproc->cluster;
 	struct k3_r5_core *core = kproc->core;
+	struct device *dev = kproc->dev;
+	unsigned long msg = RP_MBOX_SHUTDOWN;
 	int ret;
+	u32 stat = 0;
 
 	/* halt all applicable cores */
 	if (cluster->mode == CLUSTER_MODE_LOCKSTEP) {
@@ -621,13 +722,29 @@
 			}
 		}
 	} else {
+		reinit_completion(&kproc->shut_comp);
+		ret = mbox_send_message(kproc->mbox, (void *)msg);
+		if (ret < 0) {
+			dev_err(dev, "PM mbox_send_message failed: %d\n", ret);
+			return ret;
+		}
+
+		ret = wait_for_completion_timeout(&kproc->shut_comp, to);
+		if (ret == 0) {
+			dev_err(dev, "%s: timeout waiting for rproc completion event\n", __func__);
+			return -EBUSY;
+		}
+
+		mbox_free_channel(kproc->mbox);
+		ret = readx_poll_timeout(is_core_in_wfi, core, stat, stat, 200, 2000);
+		if (ret)
+			goto out;
+
 		ret = k3_r5_core_halt(core);
 		if (ret)
 			goto out;
 	}
 
-	mbox_free_channel(kproc->mbox);
-
 	return 0;
 
 unroll_core_halt:
@@ -838,7 +955,8 @@
 
 	core0 = list_first_entry(&cluster->cores, struct k3_r5_core, elem);
 	if (cluster->mode == CLUSTER_MODE_LOCKSTEP ||
-	    cluster->mode == CLUSTER_MODE_SINGLECPU) {
+	    cluster->mode == CLUSTER_MODE_SINGLECPU ||
+	    cluster->mode == CLUSTER_MODE_SINGLECORE) {
 		core = core0;
 	} else {
 		core = kproc->core;
@@ -852,38 +970,34 @@
 	dev_dbg(dev, "boot_vector = 0x%llx, cfg = 0x%x ctrl = 0x%x stat = 0x%x\n",
 		boot_vec, cfg, ctrl, stat);
 
-	/* check if only Single-CPU mode is supported on applicable SoCs */
-	if (cluster->soc_data->single_cpu_mode) {
-		single_cpu =
-			!!(stat & PROC_BOOT_STATUS_FLAG_R5_SINGLECORE_ONLY);
-		if (single_cpu && cluster->mode == CLUSTER_MODE_SPLIT) {
-			dev_err(cluster->dev, "split-mode not permitted, force configuring for single-cpu mode\n");
-			cluster->mode = CLUSTER_MODE_SINGLECPU;
-		}
-		goto config;
+	single_cpu = !!(stat & PROC_BOOT_STATUS_FLAG_R5_SINGLECORE_ONLY);
+	lockstep_en = !!(stat & PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED);
+
+	/* Override to single CPU mode if set in status flag */
+	if (single_cpu && cluster->mode == CLUSTER_MODE_SPLIT) {
+		dev_err(cluster->dev, "split-mode not permitted, force configuring for single-cpu mode\n");
+		cluster->mode = CLUSTER_MODE_SINGLECPU;
 	}
 
-	/* check conventional LockStep vs Split mode configuration */
-	lockstep_en = !!(stat & PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED);
+	/* Override to split mode if lockstep enable bit is not set in status flag */
 	if (!lockstep_en && cluster->mode == CLUSTER_MODE_LOCKSTEP) {
 		dev_err(cluster->dev, "lockstep mode not permitted, force configuring for split-mode\n");
 		cluster->mode = CLUSTER_MODE_SPLIT;
 	}
 
-config:
 	/* always enable ARM mode and set boot vector to 0 */
 	boot_vec = 0x0;
 	if (core == core0) {
 		clr_cfg = PROC_BOOT_CFG_FLAG_R5_TEINIT;
-		if (cluster->soc_data->single_cpu_mode) {
-			/*
-			 * Single-CPU configuration bit can only be configured
-			 * on Core0 and system firmware will NACK any requests
-			 * with the bit configured, so program it only on
-			 * permitted cores
-			 */
-			if (cluster->mode == CLUSTER_MODE_SINGLECPU)
-				set_cfg = PROC_BOOT_CFG_FLAG_R5_SINGLE_CORE;
+		/*
+		 * Single-CPU configuration bit can only be configured
+		 * on Core0 and system firmware will NACK any requests
+		 * with the bit configured, so program it only on
+		 * permitted cores
+		 */
+		if (cluster->mode == CLUSTER_MODE_SINGLECPU ||
+		    cluster->mode == CLUSTER_MODE_SINGLECORE) {
+			set_cfg = PROC_BOOT_CFG_FLAG_R5_SINGLE_CORE;
 		} else {
 			/*
 			 * LockStep configuration bit is Read-only on Split-mode
@@ -1074,6 +1188,7 @@
 
 	if (cluster->mode == CLUSTER_MODE_LOCKSTEP ||
 	    cluster->mode == CLUSTER_MODE_SINGLECPU ||
+	    cluster->mode == CLUSTER_MODE_SINGLECORE ||
 	    !cluster->soc_data->tcm_is_double)
 		return;
 
@@ -1108,12 +1223,12 @@
 	struct k3_r5_cluster *cluster = kproc->cluster;
 	struct k3_r5_core *core = kproc->core;
 	struct device *cdev = core->dev;
-	bool r_state = false, c_state = false;
+	bool r_state = false, c_state = false, lockstep_en = false, single_cpu = false;
 	u32 ctrl = 0, cfg = 0, stat = 0, halted = 0;
 	u64 boot_vec = 0;
 	u32 atcm_enable, btcm_enable, loczrama;
 	struct k3_r5_core *core0;
-	enum cluster_mode mode;
+	enum cluster_mode mode = cluster->mode;
 	int ret;
 
 	core0 = list_first_entry(&cluster->cores, struct k3_r5_core, elem);
@@ -1147,13 +1262,14 @@
 	atcm_enable = cfg & PROC_BOOT_CFG_FLAG_R5_ATCM_EN ?  1 : 0;
 	btcm_enable = cfg & PROC_BOOT_CFG_FLAG_R5_BTCM_EN ?  1 : 0;
 	loczrama = cfg & PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE ?  1 : 0;
-	if (cluster->soc_data->single_cpu_mode) {
-		mode = cfg & PROC_BOOT_CFG_FLAG_R5_SINGLE_CORE ?
-				CLUSTER_MODE_SINGLECPU : CLUSTER_MODE_SPLIT;
-	} else {
-		mode = cfg & PROC_BOOT_CFG_FLAG_R5_LOCKSTEP ?
-				CLUSTER_MODE_LOCKSTEP : CLUSTER_MODE_SPLIT;
-	}
+	single_cpu = cfg & PROC_BOOT_CFG_FLAG_R5_SINGLE_CORE ? 1 : 0;
+	lockstep_en = cfg & PROC_BOOT_CFG_FLAG_R5_LOCKSTEP ? 1 : 0;
+
+	if (single_cpu && mode != CLUSTER_MODE_SINGLECORE)
+		mode = CLUSTER_MODE_SINGLECPU;
+	if (lockstep_en)
+		mode = CLUSTER_MODE_LOCKSTEP;
+
 	halted = ctrl & PROC_BOOT_CTRL_FLAG_R5_CORE_HALT;
 
 	/*
@@ -1253,6 +1369,8 @@
 			goto err_config;
 		}
 
+		init_completion(&kproc->shut_comp);
+		init_completion(&kproc->suspend_comp);
 init_rmem:
 		k3_r5_adjust_tcm_sizes(kproc);
 
@@ -1269,9 +1387,15 @@
 			goto err_add;
 		}
 
-		/* create only one rproc in lockstep mode or single-cpu mode */
+		kproc->pm_notifier.notifier_call = r5f_pm_notifier_call;
+		register_pm_notifier(&kproc->pm_notifier);
+
+		/* create only one rproc in lockstep, single-cpu or
+		 * single core mode
+		 */
 		if (cluster->mode == CLUSTER_MODE_LOCKSTEP ||
-		    cluster->mode == CLUSTER_MODE_SINGLECPU)
+		    cluster->mode == CLUSTER_MODE_SINGLECPU ||
+		    cluster->mode == CLUSTER_MODE_SINGLECORE)
 			break;
 	}
 
@@ -1335,9 +1459,8 @@
 		}
 
 		rproc_del(rproc);
-
 		k3_r5_reserved_mem_exit(kproc);
-
+		unregister_pm_notifier(&kproc->pm_notifier);
 		rproc_free(rproc);
 		core->rproc = NULL;
 	}
@@ -1560,6 +1683,11 @@
 		goto err;
 	}
 
+	if (device_property_present(dev, "wakeup-source")) {
+		dev_dbg(dev, "registering as wakeup source\n");
+		device_set_wakeup_capable(dev, true);
+	}
+
 	core->reset = devm_reset_control_get_exclusive(dev, NULL);
 	if (IS_ERR_OR_NULL(core->reset)) {
 		ret = PTR_ERR_OR_ZERO(core->reset);
@@ -1700,12 +1828,6 @@
 		return -ENOMEM;
 
 	cluster->dev = dev;
-	/*
-	 * default to most common efuse configurations - Split-mode on AM64x
-	 * and LockStep-mode on all others
-	 */
-	cluster->mode = data->single_cpu_mode ?
-				CLUSTER_MODE_SPLIT : CLUSTER_MODE_LOCKSTEP;
 	cluster->soc_data = data;
 	INIT_LIST_HEAD(&cluster->cores);
 
@@ -1716,9 +1838,37 @@
 		return ret;
 	}
 
+	if (ret == -EINVAL) {
+		/*
+		 * default to most common efuse configurations - Split-mode on AM64x
+		 * and LockStep-mode on all others
+		 * default to most common efuse configurations -
+		 * Split-mode on AM64x
+		 * Single core on AM62x
+		 * LockStep-mode on all others
+		 */
+		if (!data->is_single_core)
+			cluster->mode = data->single_cpu_mode ?
+					CLUSTER_MODE_SPLIT : CLUSTER_MODE_LOCKSTEP;
+		else
+			cluster->mode = CLUSTER_MODE_SINGLECORE;
+	}
+
+	if  ((cluster->mode == CLUSTER_MODE_SINGLECPU && !data->single_cpu_mode) ||
+	     (cluster->mode == CLUSTER_MODE_SINGLECORE && !data->is_single_core)) {
+		dev_err(dev, "Cluster mode = %d is not supported on this SoC\n", cluster->mode);
+		return -EINVAL;
+	}
+
 	num_cores = of_get_available_child_count(np);
-	if (num_cores != 2) {
-		dev_err(dev, "MCU cluster requires both R5F cores to be enabled, num_cores = %d\n",
+	if (num_cores != 2 && !data->is_single_core) {
+		dev_err(dev, "MCU cluster requires both R5F cores to be enabled but num_cores is set to = %d\n",
+			num_cores);
+		return -ENODEV;
+	}
+
+	if (num_cores != 1 && data->is_single_core) {
+		dev_err(dev, "SoC supports only single core R5 but num_cores is set to %d\n",
 			num_cores);
 		return -ENODEV;
 	}
@@ -1760,18 +1910,28 @@
 	.tcm_is_double = false,
 	.tcm_ecc_autoinit = false,
 	.single_cpu_mode = false,
+	.is_single_core = false,
 };
 
 static const struct k3_r5_soc_data j7200_j721s2_soc_data = {
 	.tcm_is_double = true,
 	.tcm_ecc_autoinit = true,
 	.single_cpu_mode = false,
+	.is_single_core = false,
 };
 
 static const struct k3_r5_soc_data am64_soc_data = {
 	.tcm_is_double = true,
 	.tcm_ecc_autoinit = true,
 	.single_cpu_mode = true,
+	.is_single_core = false,
+};
+
+static const struct k3_r5_soc_data am62_soc_data = {
+	.tcm_is_double = false,
+	.tcm_ecc_autoinit = true,
+	.single_cpu_mode = false,
+	.is_single_core = true,
 };
 
 static const struct of_device_id k3_r5_of_match[] = {
@@ -1779,6 +1939,7 @@
 	{ .compatible = "ti,j721e-r5fss", .data = &am65_j721e_soc_data, },
 	{ .compatible = "ti,j7200-r5fss", .data = &j7200_j721s2_soc_data, },
 	{ .compatible = "ti,am64-r5fss",  .data = &am64_soc_data, },
+	{ .compatible = "ti,am62-r5fss",  .data = &am62_soc_data, },
 	{ .compatible = "ti,j721s2-r5fss",  .data = &j7200_j721s2_soc_data, },
 	{ /* sentinel */ },
 };
diff -Naur --no-dereference a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
--- a/drivers/rpmsg/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/rpmsg/Kconfig	2024-01-28 14:01:31.252353813 -0500
@@ -81,4 +81,17 @@
 	select RPMSG_NS
 	select VIRTIO
 
+config RPMSG_PRU
+	tristate "PRU RPMsg Communication driver"
+	depends on RPMSG_VIRTIO
+	depends on REMOTEPROC
+	depends on PRU_REMOTEPROC
+	help
+	  An rpmsg driver that exposes interfaces to user space, to allow
+	  applications to communicate with the PRU processors on available
+	  TI SoCs. This is restricted to SoCs that have the PRUSS remoteproc
+	  support.
+
+	  If unsure, say N.
+
 endmenu
diff -Naur --no-dereference a/drivers/rpmsg/Makefile b/drivers/rpmsg/Makefile
--- a/drivers/rpmsg/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/rpmsg/Makefile	2024-01-28 14:01:31.252353813 -0500
@@ -10,3 +10,4 @@
 obj-$(CONFIG_RPMSG_QCOM_GLINK_SMEM) += qcom_glink_smem.o
 obj-$(CONFIG_RPMSG_QCOM_SMD)	+= qcom_smd.o
 obj-$(CONFIG_RPMSG_VIRTIO)	+= virtio_rpmsg_bus.o
+obj-$(CONFIG_RPMSG_PRU)		+= rpmsg_pru.o
diff -Naur --no-dereference a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
--- a/drivers/rpmsg/rpmsg_char.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/rpmsg/rpmsg_char.c	2024-01-28 14:01:31.252353813 -0500
@@ -147,6 +147,9 @@
 	}
 
 	eptdev->ept = ept;
+	if (eptdev->chinfo.src == RPMSG_ADDR_ANY)
+		eptdev->chinfo.src = ept->addr;
+
 	filp->private_data = eptdev;
 	mutex_unlock(&eptdev->ept_lock);
 
@@ -472,6 +475,7 @@
 
 static struct rpmsg_device_id rpmsg_chrdev_id_table[] = {
 	{ .name	= "rpmsg-raw" },
+	{ .name	= "rpmsg_chrdev" },
 	{ },
 };
 
diff -Naur --no-dereference a/drivers/rpmsg/rpmsg_pru.c b/drivers/rpmsg/rpmsg_pru.c
--- a/drivers/rpmsg/rpmsg_pru.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg/rpmsg_pru.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,351 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * PRU Remote Processor Messaging Driver
+ *
+ * Copyright (C) 2015-2021 Texas Instruments Incorporated - https://www.ti.com/
+ *	Jason Reeder <jreeder@ti.com>
+ *	Suman Anna <s-anna@ti.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/rpmsg.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/module.h>
+#include <linux/kfifo.h>
+#include <linux/uaccess.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+
+#define PRU_MAX_DEVICES				(16)
+/* Matches the RPMSG_BUF_SIZE definition in virtio_rpmsg_bus.c */
+#define FIFO_MSG_SIZE				(512)
+#define MAX_FIFO_MSG				(32)
+
+/**
+ * struct rpmsg_pru_dev - Structure that contains the per-device data
+ * @rpdev: rpmsg channel device that is associated with this rpmsg_pru device
+ * @dev: device
+ * @cdev: character device
+ * @locked: boolean used to determine whether or not the device file is in use
+ * @devt: dev_t structure for the rpmsg_pru device
+ * @msg_fifo: kernel fifo used to buffer the messages between userspace and PRU
+ * @msg_len: array storing the lengths of each message in the kernel fifo
+ * @msg_idx_rd: kernel fifo read index
+ * @msg_idx_wr: kernel fifo write index
+ * @wait_list: wait queue used to implement the poll operation of the character
+ *             device
+ *
+ * Each rpmsg_pru device provides an interface, using an rpmsg channel (rpdev),
+ * between a user space character device (cdev) and a PRU core. A kernel fifo
+ * (msg_fifo) is used to buffer the messages in the kernel that are
+ * being passed between the character device and the PRU.
+ */
+struct rpmsg_pru_dev {
+	struct rpmsg_device *rpdev;
+	struct device *dev;
+	struct cdev cdev;
+	bool locked;
+	dev_t devt;
+	struct kfifo msg_fifo;
+	u32 msg_len[MAX_FIFO_MSG];
+	int msg_idx_rd;
+	int msg_idx_wr;
+	wait_queue_head_t wait_list;
+};
+
+static struct class *rpmsg_pru_class;
+static dev_t rpmsg_pru_devt;
+static DEFINE_MUTEX(rpmsg_pru_lock);
+static DEFINE_IDR(rpmsg_pru_minors);
+
+static int rpmsg_pru_open(struct inode *inode, struct file *filp)
+{
+	struct rpmsg_pru_dev *prudev;
+	int ret = -EACCES;
+
+	prudev = container_of(inode->i_cdev, struct rpmsg_pru_dev, cdev);
+
+	mutex_lock(&rpmsg_pru_lock);
+	if (!prudev->locked) {
+		prudev->locked = true;
+		filp->private_data = prudev;
+		ret = 0;
+	}
+	mutex_unlock(&rpmsg_pru_lock);
+
+	if (ret)
+		dev_err(prudev->dev, "Device already open\n");
+
+	return ret;
+}
+
+static int rpmsg_pru_release(struct inode *inode, struct file *filp)
+{
+	struct rpmsg_pru_dev *prudev;
+
+	prudev = container_of(inode->i_cdev, struct rpmsg_pru_dev, cdev);
+	mutex_lock(&rpmsg_pru_lock);
+	prudev->locked = false;
+	mutex_unlock(&rpmsg_pru_lock);
+	return 0;
+}
+
+static ssize_t rpmsg_pru_read(struct file *filp, char __user *buf,
+			      size_t count, loff_t *f_pos)
+{
+	int ret;
+	u32 length;
+	struct rpmsg_pru_dev *prudev;
+
+	prudev = filp->private_data;
+
+	if (kfifo_is_empty(&prudev->msg_fifo) &&
+	    (filp->f_flags & O_NONBLOCK))
+		return -EAGAIN;
+
+	ret = wait_event_interruptible(prudev->wait_list,
+				       !kfifo_is_empty(&prudev->msg_fifo));
+	if (ret)
+		return -EINTR;
+
+	ret = kfifo_to_user(&prudev->msg_fifo, buf,
+			    prudev->msg_len[prudev->msg_idx_rd], &length);
+	prudev->msg_idx_rd = (prudev->msg_idx_rd + 1) % MAX_FIFO_MSG;
+
+	return ret ? ret : length;
+}
+
+static ssize_t rpmsg_pru_write(struct file *filp, const char __user *buf,
+			       size_t count, loff_t *f_pos)
+{
+	int ret;
+	struct rpmsg_pru_dev *prudev;
+	static char rpmsg_pru_buf[FIFO_MSG_SIZE];
+	ssize_t max_payload;
+
+	prudev = filp->private_data;
+	max_payload = rpmsg_get_mtu(prudev->rpdev->ept);
+
+	if (count > max_payload) {
+		dev_err(prudev->dev, "Data too large for RPMsg Buffer\n");
+		return -EINVAL;
+	}
+
+	if (copy_from_user(rpmsg_pru_buf, buf, count)) {
+		dev_err(prudev->dev, "Error copying buffer from user space");
+		return -EFAULT;
+	}
+
+	ret = rpmsg_send(prudev->rpdev->ept, (void *)rpmsg_pru_buf, count);
+	if (ret)
+		dev_err(prudev->dev, "rpmsg_send failed: %d\n", ret);
+
+	return ret ? ret : count;
+}
+
+static unsigned int rpmsg_pru_poll(struct file *filp,
+				   struct poll_table_struct *wait)
+{
+	int mask;
+	struct rpmsg_pru_dev *prudev;
+
+	prudev = filp->private_data;
+
+	poll_wait(filp, &prudev->wait_list, wait);
+
+	mask = POLLOUT | POLLWRNORM;
+
+	if (!kfifo_is_empty(&prudev->msg_fifo))
+		mask |= POLLIN | POLLRDNORM;
+
+	return mask;
+}
+
+static const struct file_operations rpmsg_pru_fops = {
+	.owner = THIS_MODULE,
+	.open = rpmsg_pru_open,
+	.release = rpmsg_pru_release,
+	.read = rpmsg_pru_read,
+	.write = rpmsg_pru_write,
+	.poll = rpmsg_pru_poll,
+	.llseek = noop_llseek,
+};
+
+static int rpmsg_pru_cb(struct rpmsg_device *rpdev, void *data, int len,
+			void *priv, u32 src)
+{
+	u32 length;
+	struct rpmsg_pru_dev *prudev;
+
+	prudev = dev_get_drvdata(&rpdev->dev);
+
+	if (kfifo_avail(&prudev->msg_fifo) < len) {
+		dev_err(&rpdev->dev, "Not enough space on the FIFO\n");
+		return -ENOSPC;
+	}
+
+	if ((prudev->msg_idx_wr + 1) % MAX_FIFO_MSG ==
+		prudev->msg_idx_rd) {
+		dev_err(&rpdev->dev, "Message length table is full\n");
+		return -ENOSPC;
+	}
+
+	length = kfifo_in(&prudev->msg_fifo, data, len);
+	prudev->msg_len[prudev->msg_idx_wr] = length;
+	prudev->msg_idx_wr = (prudev->msg_idx_wr + 1) % MAX_FIFO_MSG;
+
+	wake_up_interruptible(&prudev->wait_list);
+
+	return 0;
+}
+
+static int rpmsg_pru_probe(struct rpmsg_device *rpdev)
+{
+	int ret;
+	struct rpmsg_pru_dev *prudev;
+	int minor_got;
+
+	prudev = devm_kzalloc(&rpdev->dev, sizeof(*prudev), GFP_KERNEL);
+	if (!prudev)
+		return -ENOMEM;
+
+	mutex_lock(&rpmsg_pru_lock);
+	minor_got = idr_alloc(&rpmsg_pru_minors, prudev, 0, PRU_MAX_DEVICES,
+			      GFP_KERNEL);
+	mutex_unlock(&rpmsg_pru_lock);
+	if (minor_got < 0) {
+		ret = minor_got;
+		dev_err(&rpdev->dev, "Failed to get a minor number for the rpmsg_pru device: %d\n",
+			ret);
+		goto fail_alloc_minor;
+	}
+
+	prudev->devt = MKDEV(MAJOR(rpmsg_pru_devt), minor_got);
+
+	cdev_init(&prudev->cdev, &rpmsg_pru_fops);
+	prudev->cdev.owner = THIS_MODULE;
+	ret = cdev_add(&prudev->cdev, prudev->devt, 1);
+	if (ret) {
+		dev_err(&rpdev->dev, "Unable to add cdev for the rpmsg_pru device\n");
+		goto fail_add_cdev;
+	}
+
+	prudev->dev = device_create(rpmsg_pru_class, &rpdev->dev, prudev->devt,
+				    NULL, "rpmsg_pru%d", rpdev->dst);
+	if (IS_ERR(prudev->dev)) {
+		dev_err(&rpdev->dev, "Unable to create the rpmsg_pru device\n");
+		ret = PTR_ERR(prudev->dev);
+		goto fail_create_device;
+	}
+
+	prudev->rpdev = rpdev;
+
+	ret = kfifo_alloc(&prudev->msg_fifo, MAX_FIFO_MSG * FIFO_MSG_SIZE,
+			  GFP_KERNEL);
+	if (ret) {
+		dev_err(&rpdev->dev, "Unable to allocate fifo for the rpmsg_pru device\n");
+		goto fail_alloc_fifo;
+	}
+
+	init_waitqueue_head(&prudev->wait_list);
+
+	dev_set_drvdata(&rpdev->dev, prudev);
+
+	dev_info(&rpdev->dev, "new rpmsg_pru device: /dev/rpmsg_pru%d",
+		 rpdev->dst);
+
+	return 0;
+
+fail_alloc_fifo:
+	device_destroy(rpmsg_pru_class, prudev->devt);
+fail_create_device:
+	cdev_del(&prudev->cdev);
+fail_add_cdev:
+	mutex_lock(&rpmsg_pru_lock);
+	idr_remove(&rpmsg_pru_minors, minor_got);
+	mutex_unlock(&rpmsg_pru_lock);
+fail_alloc_minor:
+	return ret;
+}
+
+static void rpmsg_pru_remove(struct rpmsg_device *rpdev)
+{
+	struct rpmsg_pru_dev *prudev;
+
+	prudev = dev_get_drvdata(&rpdev->dev);
+
+	kfifo_free(&prudev->msg_fifo);
+	device_destroy(rpmsg_pru_class, prudev->devt);
+	cdev_del(&prudev->cdev);
+	mutex_lock(&rpmsg_pru_lock);
+	idr_remove(&rpmsg_pru_minors, MINOR(prudev->devt));
+	mutex_unlock(&rpmsg_pru_lock);
+}
+
+/* .name matches on RPMsg Channels and causes a probe */
+static const struct rpmsg_device_id rpmsg_driver_pru_id_table[] = {
+	{ .name	= "rpmsg-pru" },
+	{ },
+};
+MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_pru_id_table);
+
+static struct rpmsg_driver rpmsg_pru_driver = {
+	.drv.name	= KBUILD_MODNAME,
+	.id_table	= rpmsg_driver_pru_id_table,
+	.probe		= rpmsg_pru_probe,
+	.callback	= rpmsg_pru_cb,
+	.remove		= rpmsg_pru_remove,
+};
+
+static int __init rpmsg_pru_init(void)
+{
+	int ret;
+
+	rpmsg_pru_class = class_create(THIS_MODULE, "rpmsg_pru");
+	if (IS_ERR(rpmsg_pru_class)) {
+		pr_err("Unable to create class\n");
+		ret = PTR_ERR(rpmsg_pru_class);
+		goto fail_create_class;
+	}
+
+	ret = alloc_chrdev_region(&rpmsg_pru_devt, 0, PRU_MAX_DEVICES,
+				  "rpmsg_pru");
+	if (ret) {
+		pr_err("Unable to allocate chrdev region\n");
+		goto fail_alloc_region;
+	}
+
+	ret = register_rpmsg_driver(&rpmsg_pru_driver);
+	if (ret) {
+		pr_err("Unable to register rpmsg driver");
+		goto fail_register_rpmsg_driver;
+	}
+
+	return 0;
+
+fail_register_rpmsg_driver:
+	unregister_chrdev_region(rpmsg_pru_devt, PRU_MAX_DEVICES);
+fail_alloc_region:
+	class_destroy(rpmsg_pru_class);
+fail_create_class:
+	return ret;
+}
+
+static void __exit rpmsg_pru_exit(void)
+{
+	unregister_rpmsg_driver(&rpmsg_pru_driver);
+	idr_destroy(&rpmsg_pru_minors);
+	mutex_destroy(&rpmsg_pru_lock);
+	class_destroy(rpmsg_pru_class);
+	unregister_chrdev_region(rpmsg_pru_devt, PRU_MAX_DEVICES);
+}
+
+module_init(rpmsg_pru_init);
+module_exit(rpmsg_pru_exit);
+
+MODULE_AUTHOR("Jason Reeder <jreeder@ti.com>");
+MODULE_DESCRIPTION("PRU Remote Processor Messaging Driver");
+MODULE_LICENSE("GPL v2");
diff -Naur --no-dereference a/drivers/rpmsg-kdrv/Kconfig b/drivers/rpmsg-kdrv/Kconfig
--- a/drivers/rpmsg-kdrv/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg-kdrv/Kconfig	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: GPL-2.0
+
+menu "Rpmsg virtual device drivers"
+
+# RPMSG always gets selected by whoever wants it
+config RPMSG_KDRV
+	tristate "RPMSG virtual device interface"
+	select RPMSG
+	help
+	  Say Y here enable support for RPMSG based remote devices, usually
+	  exported by a firmware running rpmsg stack and remote_device stack.
+	  This feature enables the framework for para-virtualizing entire H/W
+	  or specific resources of a hardware
+
+
+config RPMSG_KDRV_DEMO
+	tristate "RPMSG virtual demo device support"
+	select RPMSG_KDRV
+	help
+	  Say Y here to enable support for remote device based demo device.
+	  This setup expects that the demo device server will be running on a
+	  remoteproc and a client (sample) driver will be able to call demo device
+	  APIs using remote_device framework.
+
+	  The demo device is no real device. It serves the purpose of providing
+	  a sample driver to be used as a reference for developing more
+	  remote_device drivers (like display or ethernet)
+
+config RPMSG_KDRV_DISPLAY
+	tristate "RPMSG virtual display device support"
+	select RPMSG_KDRV
+	help
+	  Say Y here to enable support for remote device based display
+	  virtualization. This setup expects that the display will be driven
+	  by a remoteproc and DRM driver will be able to use display features
+	  using remote_device framework
+
+config RPMSG_KDRV_ETH_SWITCH
+	tristate "RPMSG virtual eth switch device support"
+	select RPMSG_KDRV
+	default m
+	help
+	  Say Y here to enable support for remote device based Eth switch
+	  virtualization. This setup expects that the Eth switch will be driven
+	  by a remoteproc and virtual Network device will be able to use
+	  Eth switch features using remote_device framework
+
+endmenu
diff -Naur --no-dereference a/drivers/rpmsg-kdrv/Makefile b/drivers/rpmsg-kdrv/Makefile
--- a/drivers/rpmsg-kdrv/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg-kdrv/Makefile	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_RPMSG_KDRV)		+= rpmsg_kdrv.o
+obj-$(CONFIG_RPMSG_KDRV_DEMO)		+= rpmsg_kdrv_demo.o
+obj-$(CONFIG_RPMSG_KDRV_DISPLAY)	+= rpmsg_kdrv_display.o
+obj-$(CONFIG_RPMSG_KDRV_ETH_SWITCH)	+= rpmsg_kdrv_switch.o
diff -Naur --no-dereference a/drivers/rpmsg-kdrv/rpmsg_kdrv.c b/drivers/rpmsg-kdrv/rpmsg_kdrv.c
--- a/drivers/rpmsg-kdrv/rpmsg_kdrv.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg-kdrv/rpmsg_kdrv.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,745 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Subhajit Paul <subahjit_paul@ti.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+
+#include <linux/rpmsg.h>
+#include <linux/rpmsg-remotedev/rpmsg-remotedev.h>
+#include "shared/rpmsg-kdrv-transport.h"
+#include "rpmsg_kdrv_internal.h"
+
+struct rpmsg_kdrv_priv {
+	struct rpmsg_device *rpdev;
+
+	struct idr message_idr;
+	struct mutex message_lock;	/* Protect access to messages. */
+
+	int num_raw_devices;
+	struct rpmsg_kdrv_init_device_info raw_devices[RPMSG_KDRV_TP_MAX_DEVICES];
+	void *raw_device_data[RPMSG_KDRV_TP_MAX_DEVICES];
+	int raw_device_data_size[RPMSG_KDRV_TP_MAX_DEVICES];
+};
+
+struct rpmsg_kdrv_ctx {
+	struct rpmsg_device *rpdev;
+	bool wait_for_response;
+	request_cb_t callback;
+	void *cb_data;
+	bool response_recv;
+	struct wait_queue_head response_wq;
+
+	struct rpmsg_kdrv_device_header *dev_hdr;
+	void *req;
+	void *resp;
+	int req_size;
+	int resp_size;
+};
+
+static struct bus_type rpmsg_kdrv_bus;
+
+#define to_rpmsg_kdrv_device(d) container_of(d, struct rpmsg_kdrv_device, dev)
+#define to_rpmsg_kdrv_driver(d) container_of(d, struct rpmsg_kdrv_driver, drv)
+
+static int rpmsg_kdrv_match_id(struct device *dev, const void *data)
+{
+	const u32 *idptr = data;
+	struct rpmsg_kdrv_device *kddev = to_rpmsg_kdrv_device(dev);
+
+	if (kddev->device_id == *idptr)
+		return 1;
+	return 0;
+}
+
+static int rpmsg_kdrv_match_remotedev(struct device *dev, const void *data)
+{
+	const struct rpmsg_remotedev *rdev = data;
+	struct rpmsg_kdrv_device *kddev = container_of(dev, struct rpmsg_kdrv_device, dev);
+
+	if (kddev->remotedev == rdev)
+		return 1;
+	return 0;
+}
+
+static int rpmsg_kdrv_match_name(struct device *dev, const void *data)
+{
+	const char *name = data;
+	struct rpmsg_kdrv_device *kddev = to_rpmsg_kdrv_device(dev);
+
+	if (strcmp(kddev->device_name, name) == 0)
+		return 1;
+	return 0;
+}
+
+int rpmsg_kdrv_register_driver(struct rpmsg_kdrv_driver *drv)
+{
+	int ret;
+
+	drv->drv.bus = &rpmsg_kdrv_bus;
+	drv->drv.owner = THIS_MODULE;
+
+	ret = driver_register(&drv->drv);
+	if (ret)
+		pr_err("%s: driver_register failed\n", __func__);
+
+	return ret;
+}
+EXPORT_SYMBOL(rpmsg_kdrv_register_driver);
+
+static void rpmsg_kdrv_driver_handle_data(struct rpmsg_device *rpdev, void *data, int len,
+					  void *private, u32 src)
+{
+	struct device *dev;
+	struct rpmsg_kdrv_device_header *hdr = data;
+	struct rpmsg_kdrv_device *kddev = NULL;
+	struct rpmsg_kdrv_driver *kddrv = NULL;
+	void *message;
+	int message_size;
+	u32 msg_device_id;
+	int ret;
+
+	msg_device_id = hdr->device_id;
+	dev = bus_find_device(&rpmsg_kdrv_bus, NULL, &(msg_device_id), rpmsg_kdrv_match_id);
+	if (!dev) {
+		dev_err(&rpdev->dev, "%s: message received for unknown device\n", __func__);
+		return;
+	}
+	kddev = to_rpmsg_kdrv_device(dev);
+	kddrv = to_rpmsg_kdrv_driver(kddev->dev.driver);
+	if (!kddrv) {
+		dev_err(&rpdev->dev, "%s: message received for device with no driver\n", __func__);
+		return;
+	}
+
+	message = (void *)(&hdr[1]);
+	message_size = len - sizeof(*hdr);
+	ret = kddrv->callback(kddev, message, message_size);
+	if (ret)
+		dev_err(&rpdev->dev, "%s: message callback returns %d\n", __func__, ret);
+}
+
+static int rpmsg_kdrv_connect(struct rpmsg_device *rpdev, struct rpmsg_kdrv_device *kddev)
+{
+	int ret;
+	struct rpmsg_kdrv_init_connect_message *connect_req;
+
+	connect_req = devm_kzalloc(&rpdev->dev, sizeof(*connect_req), GFP_KERNEL);
+	if (!connect_req)
+		return -ENOMEM;
+
+	connect_req->header.message_type = RPMSG_KDRV_TP_INIT_CONNECT_MESSAGE;
+	connect_req->device_id = kddev->device_id;
+
+	ret = rpmsg_kdrv_send_message(rpdev, RPMSG_KDRV_TP_DEVICE_ID_INIT,
+				      connect_req, sizeof(*connect_req));
+
+	devm_kfree(&rpdev->dev, connect_req);
+	return ret;
+}
+
+static int rpmsg_kdrv_disconnect(struct rpmsg_device *rpdev, struct rpmsg_kdrv_device *kddev)
+{
+	int ret;
+	struct rpmsg_kdrv_init_disconnect_message *disconnect_req;
+
+	disconnect_req = devm_kzalloc(&rpdev->dev, sizeof(*disconnect_req), GFP_KERNEL);
+	if (!disconnect_req)
+		return -ENOMEM;
+
+	disconnect_req->header.message_type = RPMSG_KDRV_TP_INIT_DISCONNECT_MESSAGE;
+	disconnect_req->device_id = kddev->device_id;
+
+	ret = rpmsg_kdrv_send_message(rpdev, RPMSG_KDRV_TP_DEVICE_ID_INIT,
+				      disconnect_req, sizeof(*disconnect_req));
+
+	devm_kfree(&rpdev->dev, disconnect_req);
+	return ret;
+}
+
+struct rpmsg_remotedev *rpmsg_remotedev_get_named_device(const char *device_name)
+{
+	struct device *dev;
+	struct rpmsg_kdrv_device *kddev = NULL;
+
+	dev = bus_find_device(&rpmsg_kdrv_bus, NULL, (void *)device_name, rpmsg_kdrv_match_name);
+	if (!dev)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	kddev = container_of(dev, struct rpmsg_kdrv_device, dev);
+	if (!kddev->remotedev)
+		return ERR_PTR(-EPROBE_DEFER);
+
+	rpmsg_kdrv_connect(kddev->rpdev, kddev);
+
+	return kddev->remotedev;
+}
+EXPORT_SYMBOL(rpmsg_remotedev_get_named_device);
+
+void rpmsg_remotedev_put_device(struct rpmsg_remotedev *rdev)
+{
+	struct device *dev;
+	struct rpmsg_kdrv_device *kddev = NULL;
+
+	dev = bus_find_device(&rpmsg_kdrv_bus, NULL, (void *)rdev, rpmsg_kdrv_match_remotedev);
+	if (!dev) {
+		pr_err("%s: could not find device for remotedev\n", __func__);
+		return;
+	}
+
+	kddev = container_of(dev, struct rpmsg_kdrv_device, dev);
+
+	rpmsg_kdrv_disconnect(kddev->rpdev, kddev);
+}
+EXPORT_SYMBOL(rpmsg_remotedev_put_device);
+
+static void rpmsg_kdrv_release_device(struct device *dev)
+{
+	struct rpmsg_kdrv_device *kddev = to_rpmsg_kdrv_device(dev);
+
+	devm_kfree(&kddev->rpdev->dev, kddev);
+}
+
+static struct rpmsg_kdrv_device *rpmsg_kdrv_device_create(struct rpmsg_device *rpdev, int index)
+{
+	struct rpmsg_kdrv_device *kddev = devm_kzalloc(&rpdev->dev, sizeof(*kddev), GFP_KERNEL);
+	struct rpmsg_kdrv_priv *priv = dev_get_drvdata(&rpdev->dev);
+	struct rpmsg_kdrv_init_device_info *dev = &priv->raw_devices[index];
+	int ret;
+
+	if (!kddev) {
+		dev_err(&rpdev->dev, "%s: could not allocate kddev\n", __func__);
+		return NULL;
+	}
+
+	kddev->rpdev = rpdev;
+	kddev->device_id = dev->device_id;
+	kddev->device_type = dev->device_type;
+	kddev->device_data_len = priv->raw_device_data_size[index];
+	kddev->device_data = priv->raw_device_data[index];
+	kddev->device_name = devm_kstrdup(&rpdev->dev, dev->device_name, GFP_KERNEL);
+	if (!kddev->device_name) {
+		dev_err(&rpdev->dev, "%s: could not allocate device name\n", __func__);
+		devm_kfree(&rpdev->dev, kddev);
+		return NULL;
+	}
+
+	kddev->dev.parent = &rpdev->dev;
+	kddev->dev.release = rpmsg_kdrv_release_device;
+	kddev->dev.bus = &rpmsg_kdrv_bus;
+
+	dev_set_name(&kddev->dev, "rpmsg-kdrv-%u-%s", dev->device_id, dev->device_name);
+
+	ret = device_register(&kddev->dev);
+	if (ret) {
+		dev_err(&rpdev->dev, "%s: device_register failed: %d\n", __func__, ret);
+		put_device(&kddev->dev);
+		return NULL;
+	}
+	dev_dbg(&rpdev->dev, "%s: registered new device : %s\n", __func__, dev_name(&kddev->dev));
+
+	return kddev;
+}
+
+static int rpmsg_kdrv_get_devices_cb(void *cb_data, void *req, int req_sz, void *resp, int resp_sz)
+{
+	int i, cnt;
+	struct rpmsg_device *rpdev = cb_data;
+	struct rpmsg_kdrv_priv *priv = dev_get_drvdata(&rpdev->dev);
+	struct rpmsg_kdrv_init_dev_info_response *info_resp = resp;
+	struct rpmsg_kdrv_init_device_info *dev;
+	int ret = 0;
+
+	if (info_resp->header.message_type != RPMSG_KDRV_TP_INIT_DEV_INFO_RESPONSE) {
+		dev_err(&rpdev->dev, "%s: wrong response type\n", __func__);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	for (i = 0; i < info_resp->num_devices; i++) {
+		dev = &info_resp->devices[i];
+		cnt = priv->num_raw_devices;
+
+		priv->raw_device_data_size[cnt] = dev->device_data_len;
+		priv->raw_device_data[cnt] = devm_kzalloc(&rpdev->dev, dev->device_data_len,
+							  GFP_KERNEL);
+		if (!priv->raw_device_data[cnt]) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		memcpy(priv->raw_device_data[cnt],
+		       &info_resp->device_data[dev->device_data_offset],
+		       dev->device_data_len);
+		memcpy(&priv->raw_devices[cnt], dev, sizeof(*dev));
+		priv->num_raw_devices++;
+
+		dev_dbg(&rpdev->dev, "new device: %s\n", dev->device_name);
+	}
+
+	for (i = 0; i < priv->num_raw_devices; i++)
+		rpmsg_kdrv_device_create(rpdev, i);
+
+out:
+	devm_kfree(&rpdev->dev, req);
+	return ret;
+}
+
+static int rpmsg_kdrv_get_devices(struct rpmsg_device *rpdev)
+{
+	int ret;
+	struct rpmsg_kdrv_init_dev_info_request *info_req;
+
+	info_req = devm_kzalloc(&rpdev->dev, sizeof(*info_req), GFP_KERNEL);
+	if (!info_req)
+		return -ENOMEM;
+
+	info_req->header.message_type = RPMSG_KDRV_TP_INIT_DEV_INFO_REQUEST;
+
+	ret = rpmsg_kdrv_send_request_with_callback(rpdev, RPMSG_KDRV_TP_DEVICE_ID_INIT,
+						    info_req, sizeof(*info_req), rpdev,
+						    rpmsg_kdrv_get_devices_cb);
+	if (ret)
+		goto nosend;
+
+	return 0;
+
+nosend:
+	devm_kfree(&rpdev->dev, info_req);
+	return ret;
+}
+
+static void rpmsg_kdrv_del_packet_id(struct rpmsg_device *rpdev, int id)
+{
+	struct rpmsg_kdrv_priv *priv = dev_get_drvdata(&rpdev->dev);
+
+	mutex_lock(&priv->message_lock);
+	idr_remove(&priv->message_idr, id);
+	mutex_unlock(&priv->message_lock);
+}
+
+static uint32_t rpmsg_kdrv_new_packet_id(struct rpmsg_device *rpdev, void *data)
+{
+	struct rpmsg_kdrv_priv *priv = dev_get_drvdata(&rpdev->dev);
+	int id;
+
+	mutex_lock(&priv->message_lock);
+	id = idr_alloc(&priv->message_idr, data, RPMSG_KDRV_TP_PACKET_ID_FIRST, 0, GFP_KERNEL);
+	mutex_unlock(&priv->message_lock);
+
+	if (id < 0)
+		return 0;
+
+	return id;
+}
+
+static void rpmsg_kdrv_dev_hdr_delete(struct rpmsg_device *rpdev,
+				      struct rpmsg_kdrv_device_header *hdr)
+{
+	rpmsg_kdrv_del_packet_id(rpdev, hdr->packet_id);
+	devm_kfree(&rpdev->dev, hdr);
+}
+
+static struct rpmsg_kdrv_device_header *rpmsg_kdrv_dev_hdr_alloc(struct rpmsg_device *rpdev,
+								 int device_id, int size,
+								 int pkt_type, int pkt_src,
+								 void *msg, int len,
+								 struct rpmsg_kdrv_ctx *ctx)
+{
+	struct rpmsg_kdrv_device_header *dev_hdr;
+	void *dst;
+
+	dev_hdr = devm_kzalloc(&rpdev->dev, size, GFP_KERNEL);
+	if (!dev_hdr)
+		return NULL;
+
+	dev_hdr->device_id = device_id;
+	dev_hdr->packet_type = pkt_type;
+	dev_hdr->packet_source = pkt_src;
+	dev_hdr->packet_size = size;
+	dev_hdr->packet_id = RPMSG_KDRV_TP_PACKET_ID_NONE;
+
+	dst = (void *)(&dev_hdr[1]);
+	memcpy(dst, msg, len);
+
+	if (pkt_type == RPMSG_KDRV_TP_PACKET_TYPE_MESSAGE)
+		return dev_hdr;
+
+	dev_hdr->packet_id = rpmsg_kdrv_new_packet_id(rpdev, ctx);
+	if (!dev_hdr->packet_id) {
+		devm_kfree(&rpdev->dev, dev_hdr);
+		return NULL;
+	}
+
+	ctx->dev_hdr = dev_hdr;
+
+	return dev_hdr;
+}
+
+static struct rpmsg_kdrv_ctx *rpmsg_kdrv_ctx_alloc(struct rpmsg_device *rpdev, bool blocking,
+						   request_cb_t callback, void *cb_data, void *req,
+						   int req_size, void *resp, int resp_size)
+{
+	struct rpmsg_kdrv_ctx *ctx;
+
+	ctx = devm_kzalloc(&rpdev->dev, sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return NULL;
+
+	ctx->rpdev = rpdev;
+	if (blocking) {
+		ctx->wait_for_response = true;
+		ctx->response_recv = false;
+		init_waitqueue_head(&ctx->response_wq);
+	} else {
+		ctx->wait_for_response = false;
+		ctx->callback = callback;
+	}
+
+	ctx->cb_data = cb_data;
+	ctx->req = req;
+	ctx->req_size = req_size;
+	ctx->resp = resp;
+	ctx->resp_size = resp_size;
+
+	return ctx;
+}
+
+static int rpmsg_kdrv_send_packet(struct rpmsg_device *rpdev, void *data, int len)
+{
+	return rpmsg_send(rpdev->ept, data, len);
+}
+
+/*
+ * rpmsg_kdrv_send_request_with_callback
+ *
+ * Send a message where
+ * a) the caller does not block
+ * b) the caller expects multile responses
+ *
+ * The callback function must return
+ * a) RRMSG_KDRV_CALLBACK_DONE when no more responses are expected
+ * b) RPMSG_KDRV_CALLBACK_MORE when more responses are awaited
+ *
+ * The caller is expected to destroy message when it does not
+ * expect any more responses
+ */
+int rpmsg_kdrv_send_request_with_callback(struct rpmsg_device *rpdev, uint32_t device_id,
+					  void *message, uint32_t message_size, void *cb_data,
+					  request_cb_t callback)
+{
+	struct rpmsg_kdrv_device_header *dev_hdr;
+	int total_size = message_size + sizeof(*dev_hdr);
+	struct rpmsg_kdrv_ctx *ctx = NULL;
+	int ret;
+
+	ctx = rpmsg_kdrv_ctx_alloc(rpdev, false, callback, cb_data, message, message_size, NULL, 0);
+	if (!ctx) {
+		dev_err(&rpdev->dev, "%s: ctx allocation failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	dev_hdr = rpmsg_kdrv_dev_hdr_alloc(rpdev, device_id, total_size,
+					   RPMSG_KDRV_TP_PACKET_TYPE_REQUEST,
+					   RPMSG_KDRV_TP_PACKET_SOURCE_CLIENT,
+					   message, message_size, ctx);
+	if (!dev_hdr) {
+		dev_err(&rpdev->dev, "%s: device header allocation failed\n", __func__);
+		ret = -ENOMEM;
+		goto dev_hdr_fail;
+	}
+
+	ret = rpmsg_kdrv_send_packet(rpdev, dev_hdr, total_size);
+	if (ret) {
+		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
+		goto nosend;
+	}
+
+	return 0;
+
+nosend:
+	rpmsg_kdrv_dev_hdr_delete(rpdev, dev_hdr);
+dev_hdr_fail:
+	devm_kfree(&rpdev->dev, ctx);
+	return ret;
+}
+EXPORT_SYMBOL(rpmsg_kdrv_send_request_with_callback);
+
+/*
+ * rpmsg_kdrv_send_request_with_response
+ *
+ * Send a message where the caller will block for a response
+ *
+ * The caller is expected to destroy message and response
+ * when this function returns
+ */
+int rpmsg_kdrv_send_request_with_response(struct rpmsg_device *rpdev, uint32_t device_id,
+					  void *message, uint32_t message_size,
+					  void *response, uint32_t response_size)
+{
+	struct rpmsg_kdrv_device_header *dev_hdr;
+	int total_size = message_size + sizeof(*dev_hdr);
+	struct rpmsg_kdrv_ctx *ctx = NULL;
+	int ret;
+
+	ctx = rpmsg_kdrv_ctx_alloc(rpdev, true, NULL, NULL, message, message_size, response,
+				   response_size);
+	if (!ctx) {
+		dev_err(&rpdev->dev, "%s: ctx allocation failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	dev_hdr = rpmsg_kdrv_dev_hdr_alloc(rpdev, device_id, total_size,
+					   RPMSG_KDRV_TP_PACKET_TYPE_REQUEST,
+					   RPMSG_KDRV_TP_PACKET_SOURCE_CLIENT,
+					   message, message_size, ctx);
+	if (!dev_hdr) {
+		dev_err(&rpdev->dev, "%s: device header allocation failed\n", __func__);
+		ret = -ENOMEM;
+		goto dev_hdr_fail;
+	}
+
+	ret = rpmsg_kdrv_send_packet(rpdev, dev_hdr, total_size);
+	if (ret) {
+		dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret);
+		goto nosend;
+	}
+
+	wait_event(ctx->response_wq, ctx->response_recv);
+
+nosend:
+	rpmsg_kdrv_dev_hdr_delete(rpdev, dev_hdr);
+dev_hdr_fail:
+	devm_kfree(&rpdev->dev, ctx);
+	return ret;
+}
+EXPORT_SYMBOL(rpmsg_kdrv_send_request_with_response);
+
+/*
+ * rpmsg_kdrv_send_message
+ *
+ * Send a message and dont expect a response
+ *
+ * The caller is expected to destroy message when
+ * this function returns
+ */
+int rpmsg_kdrv_send_message(struct rpmsg_device *rpdev, uint32_t device_id,
+			    void *message, uint32_t message_size)
+{
+	struct rpmsg_kdrv_device_header *dev_hdr;
+	int total_size = message_size + sizeof(*dev_hdr);
+	int ret;
+
+	/* We dont need a ctx for direct messages */
+
+	dev_hdr = rpmsg_kdrv_dev_hdr_alloc(rpdev, device_id, total_size,
+					   RPMSG_KDRV_TP_PACKET_TYPE_MESSAGE,
+					   RPMSG_KDRV_TP_PACKET_SOURCE_CLIENT,
+					   message, message_size, NULL);
+	if (!dev_hdr) {
+		dev_err(&rpdev->dev, "%s: device header allocation failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	ret = rpmsg_kdrv_send_packet(rpdev, dev_hdr, total_size);
+	if (ret) {
+		dev_err(&rpdev->dev, "%s: rpmsg_send failed: %d\n", __func__, ret);
+		goto out;
+	}
+
+out:
+	rpmsg_kdrv_dev_hdr_delete(rpdev, dev_hdr);
+	return ret;
+}
+EXPORT_SYMBOL(rpmsg_kdrv_send_message);
+
+static int rpmsg_kdrv_cb(struct rpmsg_device *rpdev, void *data, int len,
+			 void *private, u32 src)
+{
+	struct rpmsg_kdrv_priv *priv = dev_get_drvdata(&rpdev->dev);
+	struct rpmsg_kdrv_device_header *hdr = data;
+	struct rpmsg_kdrv_message_header *msg;
+	int msg_len;
+	struct rpmsg_kdrv_ctx *ctx;
+	int ret;
+
+	if (hdr->packet_type != RPMSG_KDRV_TP_PACKET_TYPE_RESPONSE) {
+		rpmsg_kdrv_driver_handle_data(rpdev, data, len, private, src);
+		return 0;
+	}
+
+	mutex_lock(&priv->message_lock);
+	ctx = idr_find(&priv->message_idr, hdr->packet_id);
+	mutex_unlock(&priv->message_lock);
+
+	if (!ctx) {
+		dev_err(&rpdev->dev, "%s: response received with no pending request\n", __func__);
+		return 0;
+	}
+
+	msg = (struct rpmsg_kdrv_message_header *)((void *)(&hdr[1]));
+	msg_len = len - sizeof(*hdr);
+
+	/* process callback if expected */
+	if (ctx->callback) {
+		ret = ctx->callback(ctx->cb_data, ctx->req, ctx->req_size, msg, msg_len);
+		if (ret == RRMSG_KDRV_CALLBACK_DONE) {
+			/* No need to keep the ctx alive */
+			rpmsg_kdrv_dev_hdr_delete(rpdev, ctx->dev_hdr);
+			devm_kfree(&rpdev->dev, ctx);
+		}
+		return 0;
+	}
+
+	/* copy the response and wake up caller, caller will destroy ctx & dev_hdr */
+	memcpy(ctx->resp, msg, min(msg_len, ctx->resp_size));
+
+	ctx->response_recv = true;
+	wake_up(&ctx->response_wq);
+
+	return 0;
+}
+
+static int rpmsg_kdrv_dev_match(struct device *dev, struct device_driver *drv)
+{
+	struct rpmsg_kdrv_device *kddev = to_rpmsg_kdrv_device(dev);
+	struct rpmsg_kdrv_driver *kddrv = to_rpmsg_kdrv_driver(drv);
+
+	if (kddrv->device_type == kddev->device_type) {
+		dev_dbg(dev, "%s: matching with driver %s\n", __func__, drv->name);
+		return 1;
+	}
+
+	dev_dbg(dev, "%s: does not match driver %s\n", __func__, drv->name);
+	return 0;
+}
+
+static int rpmsg_kdrv_dev_probe(struct device *dev)
+{
+	struct rpmsg_kdrv_device *kddev = to_rpmsg_kdrv_device(dev);
+	struct rpmsg_kdrv_driver *kddrv = to_rpmsg_kdrv_driver(kddev->dev.driver);
+	int ret;
+
+	dev_dbg(dev, "%s: probe\n", __func__);
+
+	ret = kddrv->probe(kddev);
+	if (ret) {
+		dev_err(dev, "%s: child probe failed\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void rpmsg_kdrv_dev_remove(struct device *dev)
+{
+	struct rpmsg_kdrv_device *kddev = to_rpmsg_kdrv_device(dev);
+	struct rpmsg_kdrv_driver *kddrv = to_rpmsg_kdrv_driver(kddev->dev.driver);
+
+	dev_dbg(dev, "%s: remove\n", __func__);
+
+	kddrv->remove(kddev);
+}
+
+static int rpmsg_kdrv_probe(struct rpmsg_device *rpdev)
+{
+	int ret;
+	struct rpmsg_kdrv_priv *priv;
+
+	dev_dbg(&rpdev->dev, "%s: probing rpmsg kdrv driver\n", __func__);
+
+	priv = devm_kzalloc(&rpdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	dev_set_drvdata(&rpdev->dev, priv);
+	priv->rpdev = rpdev;
+
+	idr_init(&priv->message_idr);
+	mutex_init(&priv->message_lock);
+
+	dev_dbg(&rpdev->dev, "%s: sending device info request\n", __func__);
+	ret = rpmsg_kdrv_get_devices(rpdev);
+	if (ret) {
+		dev_err(&rpdev->dev, "%s: error collecting device info\n", __func__);
+		goto out;
+	}
+
+	return 0;
+
+out:
+	dev_set_drvdata(&rpdev->dev, NULL);
+	devm_kfree(&rpdev->dev, priv);
+	return ret;
+}
+
+static void rpmsg_kdrv_remove(struct rpmsg_device *rpdev)
+{
+	dev_dbg(&rpdev->dev, "removing rpmsg kdrv driver\n");
+
+	/* TODO check for pending responses for any of the child devices */
+	/* TODO disconnect them all */
+}
+
+static struct bus_type rpmsg_kdrv_bus = {
+	.name		= "rpmsg_kdrv",
+	.match		= rpmsg_kdrv_dev_match,
+	.probe		= rpmsg_kdrv_dev_probe,
+	.remove		= rpmsg_kdrv_dev_remove,
+};
+
+static struct rpmsg_device_id rpmsg_kdrv_id_table[] = {
+	{ .name	= "rpmsg-kdrv" },
+	{ },
+};
+
+static struct rpmsg_driver rpmsg_kdrv = {
+	.drv.name	= "rpmsg-kdrv",
+	.id_table	= rpmsg_kdrv_id_table,
+	.probe		= rpmsg_kdrv_probe,
+	.callback	= rpmsg_kdrv_cb,
+	.remove		= rpmsg_kdrv_remove,
+};
+
+static int __init rpmsg_kdrv_init(void)
+{
+	int ret;
+
+	ret = bus_register(&rpmsg_kdrv_bus);
+	if (ret) {
+		pr_err("failed to register rpmsg kdrv bus: %d\n", ret);
+		goto out;
+	}
+
+	ret = register_rpmsg_driver(&rpmsg_kdrv);
+	if (ret) {
+		pr_err("failed to register rpmsg kdrv driver: %d\n", ret);
+		goto rpdrv_fail;
+	}
+
+	pr_debug("registered rpmsg kdrv driver\n");
+
+	return 0;
+
+rpdrv_fail:
+	bus_unregister(&rpmsg_kdrv_bus);
+out:
+	return ret;
+}
+module_init(rpmsg_kdrv_init);
+
+static void __exit rpmsg_kdrv_fini(void)
+{
+	pr_debug("unregistering rpmsg kdrv driver\n");
+
+	unregister_rpmsg_driver(&rpmsg_kdrv);
+	bus_unregister(&rpmsg_kdrv_bus);
+}
+module_exit(rpmsg_kdrv_fini);
+
+MODULE_AUTHOR("Subhajit Paul <subhajit_paul@ti.com>");
+MODULE_DESCRIPTION("TI Remote-device framework Driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/rpmsg-kdrv/rpmsg_kdrv_demo.c b/drivers/rpmsg-kdrv/rpmsg_kdrv_demo.c
--- a/drivers/rpmsg-kdrv/rpmsg_kdrv_demo.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg-kdrv/rpmsg_kdrv_demo.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Subhajit Paul <subahjit_paul@ti.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/rpmsg.h>
+#include <linux/rpmsg-remotedev/rpmsg-remotedev.h>
+
+#include "shared/rpmsg-kdrv-transport-demo.h"
+#include "rpmsg_kdrv_internal.h"
+
+struct rpmsg_kdrv_demo_private {
+	struct rpmsg_kdrv_device *kddev;
+	struct rpmsg_remotedev rdev;
+
+	void *data;
+	ssize_t data_len;
+};
+
+static int rpmsg_kdrv_demo_get_data(struct rpmsg_remotedev *rdev, void *data, ssize_t len)
+{
+	struct rpmsg_kdrv_demo_private *priv = container_of(rdev, struct rpmsg_kdrv_demo_private,
+							    rdev);
+
+	if (!data) {
+		if (!len)
+			return priv->data_len;
+		else
+			return -EINVAL;
+	} else if (len < priv->data_len) {
+		return -EINVAL;
+	}
+
+	memcpy(data, priv->data, priv->data_len);
+	return priv->data_len;
+}
+
+static int rpmsg_kdrv_demo_ping(struct rpmsg_remotedev *rdev, void *ping_data, ssize_t ping_len)
+{
+	struct rpmsg_kdrv_demo_private *priv = container_of(rdev, struct rpmsg_kdrv_demo_private,
+							    rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_demodev_ping_request *req;
+	struct rpmsg_kdrv_demodev_ping_response *resp;
+	int ret;
+
+	if (!ping_len)
+		return 0;
+
+	if (ping_len > RPMSG_KDRV_TP_DEMODEV_MESSAGE_DATA_LEN)
+		return -EINVAL;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_DEMODEV_PING_REQUEST;
+	memcpy(req->data, ping_data, ping_len);
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id, req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret) {
+		dev_err(&kddev->dev, "%s: rpmsg_kdrv_send_request_with_response\n", __func__);
+		goto out;
+	}
+
+	if (resp->header.message_type != RPMSG_KDRV_TP_DEMODEV_PING_RESPONSE) {
+		dev_err(&kddev->dev, "%s: wrong response type\n", __func__);
+		ret = -EIO;
+		goto out;
+	}
+
+	memcpy(ping_data, resp->data, RPMSG_KDRV_TP_DEMODEV_MESSAGE_DATA_LEN);
+
+out:
+	devm_kfree(&kddev->dev, req);
+	devm_kfree(&kddev->dev, resp);
+	return ret;
+}
+
+static int rpmsg_kdrv_demo_c2s_message(struct rpmsg_remotedev *rdev, void *c2s_msg_data,
+				       ssize_t len)
+{
+	struct rpmsg_kdrv_demo_private *priv = container_of(rdev, struct rpmsg_kdrv_demo_private,
+							    rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_demodev_c2s_message *msg;
+	int ret;
+
+	if (!len)
+		return 0;
+
+	if (len > RPMSG_KDRV_TP_DEMODEV_MESSAGE_DATA_LEN)
+		return -EINVAL;
+
+	msg = devm_kzalloc(&kddev->dev, sizeof(*msg), GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+
+	msg->header.message_type = RPMSG_KDRV_TP_DEMODEV_C2S_MESSAGE;
+	memcpy(msg->data, c2s_msg_data, len);
+
+	ret = rpmsg_kdrv_send_message(rpdev, kddev->device_id, msg, sizeof(*msg));
+	if (ret)
+		dev_err(&kddev->dev, "%s: rpmsg_kdrv_send_message\n", __func__);
+
+	devm_kfree(&kddev->dev, msg);
+	return ret;
+}
+
+static struct rpmsg_remotedev_demo_ops demo_ops = {
+	.get_data = rpmsg_kdrv_demo_get_data,
+	.ping = rpmsg_kdrv_demo_ping,
+	.c2s_message = rpmsg_kdrv_demo_c2s_message,
+};
+
+static void rpmsg_kdrv_demo_device_init(struct rpmsg_kdrv_device *dev, void *data, int len)
+{
+	struct rpmsg_kdrv_demo_private *priv = dev->driver_private;
+
+	priv->data = devm_kzalloc(&dev->dev, len, GFP_KERNEL);
+	if (!priv->data)
+		return;
+
+	memcpy(priv->data, data, len);
+	priv->data_len = len;
+}
+
+static int rpmsg_kdrv_demo_probe(struct rpmsg_kdrv_device *dev)
+{
+	struct rpmsg_kdrv_demo_private *priv;
+
+	priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->rdev.type = RPMSG_REMOTEDEV_DEMO_DEVICE;
+	priv->rdev.device.demo.ops = &demo_ops;
+
+	priv->kddev = dev;
+	dev->driver_private = priv;
+	dev->remotedev = &priv->rdev;
+
+	rpmsg_kdrv_demo_device_init(dev, dev->device_data, dev->device_data_len);
+
+	return 0;
+}
+
+static void rpmsg_kdrv_demo_remove(struct rpmsg_kdrv_device *dev)
+{
+}
+
+static void rpmsg_kdrv_demo_handle_s2c_message(struct rpmsg_kdrv_device *dev, void *msg,
+					       ssize_t len)
+{
+	struct rpmsg_kdrv_demo_private *priv = dev->driver_private;
+	struct rpmsg_remotedev *rdev = &priv->rdev;
+
+	if (rdev->device.demo.cb_ops && rdev->device.demo.cb_ops->s2c_message)
+		rdev->device.demo.cb_ops->s2c_message(msg, len, rdev->cb_data);
+}
+
+static int rpmsg_kdrv_demo_callback(struct rpmsg_kdrv_device *dev, void *msg, int len)
+{
+	struct rpmsg_kdrv_demodev_message_header *hdr = msg;
+
+	if (hdr->message_type == RPMSG_KDRV_TP_DEMODEV_S2C_MESSAGE) {
+		struct rpmsg_kdrv_demodev_s2c_message *s2c = msg;
+
+		rpmsg_kdrv_demo_handle_s2c_message(dev, s2c->data,
+						   RPMSG_KDRV_TP_DEMODEV_MESSAGE_DATA_LEN);
+	} else {
+		dev_err(&dev->dev, "%s: unknown message type (%d) for demo device\n", __func__,
+			hdr->message_type);
+	}
+
+	return 0;
+}
+
+static struct rpmsg_kdrv_driver rpmsg_kdrv_demo = {
+	.drv.name = "rpmsg-kdrv-demo",
+	.device_type = RPMSG_KDRV_TP_DEVICE_TYPE_DEMO,
+	.probe = rpmsg_kdrv_demo_probe,
+	.remove = rpmsg_kdrv_demo_remove,
+	.callback = rpmsg_kdrv_demo_callback,
+};
+
+static int __init rpmsg_kdrv_demo_driver_init(void)
+{
+	return rpmsg_kdrv_register_driver(&rpmsg_kdrv_demo);
+}
+module_init(rpmsg_kdrv_demo_driver_init);
+
+static void rpmsg_kdrv_demo_driver_fini(void)
+{
+}
+module_exit(rpmsg_kdrv_demo_driver_fini);
+
+MODULE_AUTHOR("Subhajit Paul <subhajit_paul@ti.com>");
+MODULE_DESCRIPTION("TI Remote-device Demo Device Driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/rpmsg-kdrv/rpmsg_kdrv_display.c b/drivers/rpmsg-kdrv/rpmsg_kdrv_display.c
--- a/drivers/rpmsg-kdrv/rpmsg_kdrv_display.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg-kdrv/rpmsg_kdrv_display.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,488 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Subhajit Paul <subahjit_paul@ti.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <drm/drm_fourcc.h>
+#include <linux/rpmsg.h>
+#include <linux/rpmsg-remotedev/rpmsg-remotedev.h>
+
+#include "shared/rpmsg-kdrv-transport-display.h"
+#include "rpmsg_kdrv_internal.h"
+
+#define RPMSG_KDRV_DISPLAY_RES_ID_FIRST		(0x10)
+
+struct rpmsg_kdrv_display_private {
+	struct rpmsg_kdrv_device *kddev;
+
+	struct rpmsg_remotedev rdev;
+
+	struct idr res_idr;
+	struct mutex res_lock;	/* Protect access to resource. */
+
+};
+
+static u32 check_min(u32 a, u32 b, int line)
+{
+	u32 res = min(a, b);
+
+	if (res != b) {
+		pr_err("Copy mismatch at Line %d\n", line);
+		WARN_ON(1);
+	}
+
+	return res;
+}
+
+static inline enum rpmsg_kdrv_display_format rpmsg_kdrv_display_fmt_to_rpmsg_fmt(u32 in_fmt)
+{
+	switch (in_fmt) {
+	case DRM_FORMAT_ARGB8888:
+		return RPMSG_KDRV_TP_DISPLAY_FORMAT_ARGB8888;
+	case DRM_FORMAT_XRGB8888:
+		return RPMSG_KDRV_TP_DISPLAY_FORMAT_XRGB8888;
+	default:
+		return RPMSG_KDRV_TP_DISPLAY_FORMAT_MAX;
+	}
+}
+
+static inline u32 rpmsg_kdrv_display_fmt_to_drm_fmt(u32 in_fmt)
+{
+	switch (in_fmt) {
+	case RPMSG_KDRV_TP_DISPLAY_FORMAT_ARGB8888:
+		return DRM_FORMAT_ARGB8888;
+	case RPMSG_KDRV_TP_DISPLAY_FORMAT_XRGB8888:
+		return DRM_FORMAT_XRGB8888;
+	default:
+		return 0;
+	}
+}
+
+static bool rpmsg_kdrv_display_ready(struct rpmsg_remotedev *rdev)
+{
+	struct rpmsg_kdrv_display_private *priv = container_of(rdev,
+							       struct rpmsg_kdrv_display_private,
+							       rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_display_ready_query_request *req;
+	struct rpmsg_kdrv_display_ready_query_response *resp;
+	int ret;
+	bool retval;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return false;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return false;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_DISPLAY_READY_QUERY_REQUEST;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id, req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret) {
+		dev_err(&kddev->dev, "%s: rpmsg_kdrv_send_request_with_response\n", __func__);
+		retval = false;
+		goto out;
+	}
+
+	if (resp->header.message_type != RPMSG_KDRV_TP_DISPLAY_READY_QUERY_RESPONSE) {
+		dev_err(&kddev->dev, "%s: wrong response type\n", __func__);
+		retval = false;
+		goto out;
+	}
+
+	retval = resp->ready ? true : false;
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return retval;
+}
+
+static void rpmsg_kdrv_display_copy_vid_info(struct rpmsg_remotedev_display_pipe *dst,
+					     struct rpmsg_kdrv_display_vid_info *src)
+{
+	int cnt;
+	u32 out_fmt;
+
+	dst->pipe_id = src->id;
+	dst->can_scale = src->can_scale ? true : false;
+	dst->can_mod_win = src->mutable_window ? true : false;
+	if (dst->can_mod_win) {
+		dst->fixed_win_x = 0;
+		dst->fixed_win_y = 0;
+		dst->fixed_win_w = 0;
+		dst->fixed_win_h = 0;
+	} else {
+		dst->fixed_win_x = src->fixed_window_x;
+		dst->fixed_win_y = src->fixed_window_y;
+		dst->fixed_win_w = src->fixed_window_w;
+		dst->fixed_win_h = src->fixed_window_h;
+	}
+	dst->initial_zorder = src->init_zorder;
+	dst->num_formats = check_min(RPMSG_REMOTEDEV_DISPLAY_MAX_FORMATS, src->num_formats,
+				     __LINE__);
+
+	dst->num_allowed_zorders = check_min(RPMSG_REMOTEDEV_DISPLAY_MAX_ZORDERS, src->num_zorders,
+					     __LINE__);
+
+	for (cnt = 0; cnt < dst->num_formats; cnt++) {
+		out_fmt = rpmsg_kdrv_display_fmt_to_drm_fmt(src->format[cnt]);
+		WARN_ON(out_fmt == 0);
+		dst->formats[cnt] = out_fmt;
+	}
+
+	for (cnt = 0; cnt < dst->num_allowed_zorders; cnt++)
+		dst->allowed_zorders[cnt] = src->zorder[cnt];
+}
+
+static void rpmsg_kdrv_display_copy_vp_info(struct rpmsg_remotedev_display_disp *dst,
+					    struct rpmsg_kdrv_display_vp_info *src)
+{
+	int vidcnt;
+
+	dst->disp_id = src->id;
+	dst->width = src->width;
+	dst->height = src->height;
+	dst->refresh = src->refresh;
+	dst->num_pipes = check_min(RPMSG_REMOTEDEV_DISPLAY_MAX_PIPES, src->num_vids, __LINE__);
+
+	for (vidcnt = 0; vidcnt < dst->num_pipes; vidcnt++)
+		rpmsg_kdrv_display_copy_vid_info(&dst->pipes[vidcnt], &src->vid[vidcnt]);
+}
+
+static int rpmsg_kdrv_display_get_res(struct rpmsg_remotedev *rdev,
+				      struct rpmsg_remotedev_display_resinfo *res)
+{
+	struct rpmsg_kdrv_display_private *priv = container_of(rdev,
+							       struct rpmsg_kdrv_display_private,
+							       rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_display_res_info_request *req;
+	struct rpmsg_kdrv_display_res_info_response *resp;
+	int ret, vpcnt;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_DISPLAY_RES_INFO_REQUEST;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id, req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret) {
+		dev_err(&kddev->dev, "%s: rpmsg_kdrv_send_request_with_response\n", __func__);
+		goto out;
+	}
+
+	if (resp->header.message_type != RPMSG_KDRV_TP_DISPLAY_RES_INFO_RESPONSE) {
+		dev_err(&kddev->dev, "%s: wrong response type\n", __func__);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	res->num_disps = check_min(RPMSG_REMOTEDEV_DISPLAY_MAX_DISPS, resp->num_vps, __LINE__);
+
+	for (vpcnt = 0; vpcnt < res->num_disps; vpcnt++)
+		rpmsg_kdrv_display_copy_vp_info(&res->disps[vpcnt], &resp->vp[vpcnt]);
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static u32 rpmsg_kdrv_display_res_id_new(struct rpmsg_kdrv_device *kddev, void *data)
+{
+	struct rpmsg_kdrv_display_private *priv = kddev->driver_private;
+	int id;
+
+	mutex_lock(&priv->res_lock);
+	id = idr_alloc(&priv->res_idr, data, RPMSG_KDRV_DISPLAY_RES_ID_FIRST, 0, GFP_KERNEL);
+	mutex_unlock(&priv->res_lock);
+
+	if (id < 0)
+		return 0;
+
+	return id;
+}
+
+static void rpmsg_kdrv_display_free_res_id(struct rpmsg_kdrv_device *kddev, u32 id)
+{
+	struct rpmsg_kdrv_display_private *priv = kddev->driver_private;
+
+	mutex_lock(&priv->res_lock);
+	idr_remove(&priv->res_idr, id);
+	mutex_unlock(&priv->res_lock);
+}
+
+static void rpmsg_kdrv_free_request_res(struct rpmsg_kdrv_device *kddev,
+					struct rpmsg_kdrv_display_commit_request *req)
+{
+	int i;
+
+	rpmsg_kdrv_display_free_res_id(kddev, req->commit_id);
+
+	for (i = 0; i < req->num_vid_updates; i++)
+		if (req->vid[i].enabled)
+			rpmsg_kdrv_display_free_res_id(kddev, req->vid[i].buffer.buffer_id);
+}
+
+static bool rpmsg_kdrv_display_copy_buffer(struct rpmsg_kdrv_device *kddev,
+					   struct rpmsg_kdrv_display_buffer_info *dst,
+					   struct rpmsg_remotedev_display_buffer *src)
+{
+	int i;
+
+	dst->width = src->width;
+	dst->height = src->height;
+
+	dst->format = rpmsg_kdrv_display_fmt_to_rpmsg_fmt(src->format);
+	if (WARN_ON(dst->format == RPMSG_KDRV_TP_DISPLAY_FORMAT_MAX))
+		return false;
+
+	dst->num_planes = check_min(RPMSG_KDRV_TP_DISPLAY_MAX_PLANES, src->num_planes, __LINE__);
+	if (dst->num_planes != src->num_planes)
+		return false;
+
+	for (i = 0; i < dst->num_planes; i++) {
+		dst->plane[i] = (uint64_t)src->planes[i];
+		dst->pitch[i] = src->pitches[i];
+	}
+
+	dst->buffer_id = rpmsg_kdrv_display_res_id_new(kddev, src);
+	if (!dst->buffer_id)
+		return false;
+
+	return true;
+}
+
+static bool rpmsg_kdrv_display_copy_vid_commit(struct rpmsg_kdrv_device *kddev,
+					       struct rpmsg_kdrv_display_vid_update_info *dst,
+					       struct rpmsg_remotedev_display_pipe_update *src)
+{
+	dst->id = src->pipe_id;
+	dst->enabled = src->enabled ? 1 : 0;
+	if (dst->enabled) {
+		dst->dst_w = src->dst_w;
+		dst->dst_h = src->dst_h;
+		dst->dst_x = src->dst_x;
+		dst->dst_y = src->dst_y;
+
+		if (!rpmsg_kdrv_display_copy_buffer(kddev, &dst->buffer, src->buffer))
+			return false;
+	}
+
+	return true;
+}
+
+static bool rpmsg_kdrv_display_copy_commit(struct rpmsg_kdrv_device *kddev,
+					   struct rpmsg_kdrv_display_commit_request *dst,
+					   struct rpmsg_remotedev_display_commit *src)
+{
+	int i, copied_vids;
+
+	dst->id = src->disp_id;
+	dst->num_vid_updates = check_min(RPMSG_KDRV_TP_DISPLAY_MAX_VIDS, src->num_pipe_updates,
+					 __LINE__);
+
+	for (i = 0, copied_vids = 0; i < dst->num_vid_updates; i++, copied_vids++)
+		if (!rpmsg_kdrv_display_copy_vid_commit(kddev, &dst->vid[i], &src->pipes[i]))
+			goto free_vid_res;
+
+	dst->commit_id = rpmsg_kdrv_display_res_id_new(kddev, src);
+	if (!dst->commit_id)
+		goto free_vid_res;
+
+	return true;
+
+free_vid_res:
+	for (i = 0; i < copied_vids; i++)
+		if (dst->vid[i].enabled)
+			rpmsg_kdrv_display_free_res_id(kddev, dst->vid[i].buffer.buffer_id);
+	return false;
+}
+
+static int rpmsg_kdrv_display_commit(struct rpmsg_remotedev *rdev,
+				     struct rpmsg_remotedev_display_commit *commit)
+{
+	struct rpmsg_kdrv_display_private *priv = container_of(rdev,
+							       struct rpmsg_kdrv_display_private,
+							       rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_display_commit_request *req;
+	struct rpmsg_kdrv_display_commit_response *resp;
+	int ret;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_DISPLAY_COMMIT_REQUEST;
+
+	if (!rpmsg_kdrv_display_copy_commit(kddev, req, commit)) {
+		dev_err(&kddev->dev, "%s: failed to copy commit request\n", __func__);
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id, req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret) {
+		dev_err(&kddev->dev, "%s: rpmsg_kdrv_send_request_with_response\n", __func__);
+		goto nosend;
+	}
+
+	if (resp->header.message_type != RPMSG_KDRV_TP_DISPLAY_COMMIT_RESPONSE) {
+		dev_err(&kddev->dev, "%s: wrong response type\n", __func__);
+		goto out;
+	}
+
+	ret = ((resp->status == 0) ? 0 : -EINVAL);
+	goto out;
+
+nosend:
+	rpmsg_kdrv_free_request_res(kddev, req);
+out:
+	devm_kfree(&kddev->dev, req);
+	devm_kfree(&kddev->dev, resp);
+	return ret;
+}
+
+static struct rpmsg_remotedev_display_ops disp_ops = {
+	.ready = rpmsg_kdrv_display_ready,
+	.get_res_info = rpmsg_kdrv_display_get_res,
+	.commit = rpmsg_kdrv_display_commit,
+};
+
+static void rpmsg_kdrv_display_device_init(struct rpmsg_kdrv_device *kddev, void *data, int len)
+{
+}
+
+static int rpmsg_kdrv_display_probe(struct rpmsg_kdrv_device *dev)
+{
+	struct rpmsg_kdrv_display_private *priv;
+
+	priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->rdev.type = RPMSG_REMOTEDEV_DISPLAY_DEVICE;
+	priv->rdev.device.display.ops = &disp_ops;
+
+	mutex_init(&priv->res_lock);
+	idr_init(&priv->res_idr);
+
+	priv->kddev = dev;
+	dev->driver_private = priv;
+	dev->remotedev = &priv->rdev;
+
+	rpmsg_kdrv_display_device_init(dev, dev->device_data, dev->device_data_len);
+
+	return 0;
+}
+
+static void rpmsg_kdrv_display_remove(struct rpmsg_kdrv_device *dev)
+{
+}
+
+static void rpmsg_kdrv_display_handle_commit(struct rpmsg_kdrv_device *dev,
+					     struct rpmsg_kdrv_display_commit_done_message *msg)
+{
+	struct rpmsg_kdrv_display_private *priv = dev->driver_private;
+	struct rpmsg_remotedev *rdev = &priv->rdev;
+	struct rpmsg_remotedev_display_commit *commit;
+
+	mutex_lock(&priv->res_lock);
+	commit = idr_find(&priv->res_idr, msg->commit_id);
+	idr_remove(&priv->res_idr, msg->commit_id);
+	mutex_unlock(&priv->res_lock);
+
+	if (!commit) {
+		dev_err(&dev->dev, "%s: no pending commit found\n", __func__);
+		return;
+	}
+
+	if (rdev->device.display.cb_ops && rdev->device.display.cb_ops->commit_done)
+		rdev->device.display.cb_ops->commit_done(commit, rdev->cb_data);
+}
+
+static void rpmsg_kdrv_display_handle_buffer(struct rpmsg_kdrv_device *dev,
+					     struct rpmsg_kdrv_display_buffer_done_message *msg)
+{
+	struct rpmsg_kdrv_display_private *priv = dev->driver_private;
+	struct rpmsg_remotedev *rdev = &priv->rdev;
+	struct rpmsg_remotedev_display_buffer *buffer;
+
+	mutex_lock(&priv->res_lock);
+	buffer = idr_find(&priv->res_idr, msg->buffer_id);
+	idr_remove(&priv->res_idr, msg->buffer_id);
+	mutex_unlock(&priv->res_lock);
+
+	if (!buffer) {
+		dev_err(&dev->dev, "%s: no pending buffer found\n", __func__);
+		return;
+	}
+
+	if (rdev->device.display.cb_ops && rdev->device.display.cb_ops->buffer_done)
+		rdev->device.display.cb_ops->buffer_done(buffer, rdev->cb_data);
+}
+
+static int rpmsg_kdrv_display_callback(struct rpmsg_kdrv_device *dev, void *msg, int len)
+{
+	struct rpmsg_kdrv_display_message_header *hdr = msg;
+
+	if (hdr->message_type == RPMSG_KDRV_TP_DISPLAY_COMMIT_DONE_MESSAGE)
+		rpmsg_kdrv_display_handle_commit(dev, msg);
+	else if (hdr->message_type == RPMSG_KDRV_TP_DISPLAY_BUFFER_DONE_MESSAGE)
+		rpmsg_kdrv_display_handle_buffer(dev, msg);
+
+	return 0;
+}
+
+static struct rpmsg_kdrv_driver rpmsg_kdrv_display = {
+	.drv.name = "rpmsg-kdrv-display",
+	.device_type = RPMSG_KDRV_TP_DEVICE_TYPE_DISPLAY,
+	.probe = rpmsg_kdrv_display_probe,
+	.remove = rpmsg_kdrv_display_remove,
+	.callback = rpmsg_kdrv_display_callback,
+};
+
+static int __init rpmsg_kdrv_display_driver_init(void)
+{
+	return rpmsg_kdrv_register_driver(&rpmsg_kdrv_display);
+}
+module_init(rpmsg_kdrv_display_driver_init);
+
+static void rpmsg_kdrv_display_driver_fini(void)
+{
+}
+module_exit(rpmsg_kdrv_display_driver_fini);
+
+MODULE_AUTHOR("Subhajit Paul <subhajit_paul@ti.com>");
+MODULE_DESCRIPTION("TI Remote-device Virtual Display Driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/rpmsg-kdrv/rpmsg_kdrv_internal.h b/drivers/rpmsg-kdrv/rpmsg_kdrv_internal.h
--- a/drivers/rpmsg-kdrv/rpmsg_kdrv_internal.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg-kdrv/rpmsg_kdrv_internal.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Subhajit Paul <subhajit_paul@ti.com>
+ */
+
+#ifndef __RPMSG_KDRV_INTERNAL_H__
+#define __RPMSG_KDRV_INTERNAL_H__
+
+#define RRMSG_KDRV_CALLBACK_DONE		(0)
+#define RRMSG_KDRV_CALLBACK_MORE		(1)
+
+struct rpmsg_kdrv_device {
+	struct device dev;
+	struct rpmsg_device *rpdev;
+	int device_type;
+	int device_id;
+	void *device_data;
+	int device_data_len;
+	char *device_name;
+	void *device_private;
+	void *driver_private;
+	struct rpmsg_remotedev *remotedev;
+};
+
+struct rpmsg_kdrv_driver {
+	struct device_driver drv;
+	int device_type;
+	int (*probe)(struct rpmsg_kdrv_device *dev);
+	void (*remove)(struct rpmsg_kdrv_device *dev);
+	int (*callback)(struct rpmsg_kdrv_device *dev, void *msg, int len);
+};
+
+typedef int (*request_cb_t)(void *data, void *req, int req_sz, void *resp, int resp_sz);
+
+int rpmsg_kdrv_register_driver(struct rpmsg_kdrv_driver *drv);
+
+int rpmsg_kdrv_send_request_with_callback(struct rpmsg_device *rpdev, u32 device_id, void *message,
+					  u32 message_size, void *cb_data, request_cb_t callback);
+int rpmsg_kdrv_send_request_with_response(struct rpmsg_device *rpdev, u32 device_id, void *message,
+					  u32 message_size, void *response, u32 response_size);
+int rpmsg_kdrv_send_message(struct rpmsg_device *rpdev, u32 device_id, void *message,
+			    u32 message_size);
+
+#endif
diff -Naur --no-dereference a/drivers/rpmsg-kdrv/rpmsg_kdrv_switch.c b/drivers/rpmsg-kdrv/rpmsg_kdrv_switch.c
--- a/drivers/rpmsg-kdrv/rpmsg_kdrv_switch.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg-kdrv/rpmsg_kdrv_switch.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,937 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Grygorii Strashko <grygorii.strashko@ti.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rpmsg.h>
+#include <linux/rpmsg-remotedev/rpmsg-remotedev.h>
+
+#include "rpmsg_kdrv_internal.h"
+#include "shared/rpmsg-kdrv-transport-switch.h"
+
+struct rpmsg_kdrv_switch_private {
+	struct rpmsg_kdrv_device *kddev;
+	struct rpmsg_remotedev rdev;
+	u64	session_id;
+	u32	core_key;
+	u32	permissions;
+	u32	uart_id;
+	u32	attached:1;
+	u32	uart_connected:1;
+};
+
+static bool
+rpmsg_kdrv_switch_check_perm(struct rpmsg_kdrv_switch_private *priv,
+			     enum rpmsg_kdrv_ethswitch_message_type msg_type)
+{
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+
+	if (priv->permissions & BIT(msg_type))
+		return true;
+
+	dev_err_ratelimited(&kddev->dev, "permission denied msg: 0x%02X\n",
+			    msg_type);
+	return false;
+}
+
+static int
+rpmsg_kdrv_switch_check_resp_status(struct rpmsg_kdrv_ethswitch_common_resp_info *info)
+{
+	if (info->status == RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_EAGAIN)
+		return -EAGAIN;
+	if (info->status == RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_EFAIL)
+		return -EIO;
+	return 0;
+}
+
+static int rpmsg_kdrv_switch_ping(struct rpmsg_remotedev *rdev,
+				  const u8 *data, int size)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_ping_req *req;
+	struct rpmsg_kdrv_ethswitch_ping_resp *resp;
+	int ret;
+
+	if (!rpmsg_kdrv_switch_check_perm(priv,
+					  RPMSG_KDRV_TP_ETHSWITCH_PING_REQUEST))
+		return -EPERM;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	if (size > RPMSG_KDRV_TP_ETHSWITCH_MESSAGE_DATA_LEN)
+		size = RPMSG_KDRV_TP_ETHSWITCH_MESSAGE_DATA_LEN;
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_PING_REQUEST;
+	memcpy(req->data, data, size);
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret) {
+		dev_dbg(&kddev->dev, "%s: send: %d\n", __func__, ret);
+		goto out;
+	}
+
+	if (memcmp(req->data, resp->data, size)) {
+		dev_dbg(&kddev->dev, "%s: ping fail - data\n", __func__);
+		ret = -EINVAL;
+	}
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int
+rpmsg_kdrv_switch_attach(struct rpmsg_remotedev *rdev,
+			 struct rpmsg_rdev_eth_switch_attach_info *attach_info)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_attach_req *req;
+	struct rpmsg_kdrv_ethswitch_attach_resp *resp;
+	int ret;
+
+	if (priv->attached)
+		return -EBUSY;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_ATTACH;
+	req->cpsw_type = RPMSG_KDRV_TP_ETHSWITCH_CPSWTYPE_MAIN_CPSW;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret) {
+		dev_dbg(&kddev->dev, "%s: send: %d\n", __func__, ret);
+		goto out;
+	}
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+	if (ret)
+		goto out;
+
+	priv->session_id = resp->id;
+	priv->core_key = resp->core_key;
+	priv->attached = true;
+
+	dev_dbg(&kddev->dev, "%s: done id:%llX core_key:%08X\n",
+		__func__, priv->session_id, priv->core_key);
+
+	attach_info->rx_mtu = resp->rx_mtu;
+	memcpy(attach_info->tx_mtu, resp->tx_mtu, sizeof(attach_info->tx_mtu));
+	attach_info->features = resp->features;
+	if (priv->uart_connected)
+		attach_info->features |=
+				RPMSG_KDRV_ETHSWITCH_FEATURE_DUMP_STATS;
+	attach_info->mac_only_port = resp->mac_only_port;
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int
+rpmsg_kdrv_switch_attach_ext(struct rpmsg_remotedev *rdev,
+			     struct rpmsg_rdev_eth_switch_attach_ext_info *attach_ext_info)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_attach_extended_req *req;
+	struct rpmsg_kdrv_ethswitch_attach_extended_resp *resp;
+	int ret;
+
+	if (priv->attached)
+		return -EBUSY;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_ATTACH_EXT;
+	req->cpsw_type = RPMSG_KDRV_TP_ETHSWITCH_CPSWTYPE_MAIN_CPSW;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret) {
+		dev_dbg(&kddev->dev, "%s: send: %d\n", __func__, ret);
+		goto out;
+	}
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+	if (ret)
+		goto out;
+
+	priv->session_id = resp->id;
+	priv->core_key = resp->core_key;
+	priv->attached = true;
+
+	dev_dbg(&kddev->dev, "%s: done id:%llX core_key:%08X\n",
+		__func__, priv->session_id, priv->core_key);
+
+	attach_ext_info->rx_mtu = resp->rx_mtu;
+	memcpy(attach_ext_info->tx_mtu, resp->tx_mtu,
+	       sizeof(attach_ext_info->tx_mtu));
+	attach_ext_info->features = resp->features;
+	if (priv->uart_connected)
+		attach_ext_info->features |=
+				RPMSG_KDRV_ETHSWITCH_FEATURE_DUMP_STATS;
+	attach_ext_info->flow_idx = resp->alloc_flow_idx;
+	attach_ext_info->tx_cpsw_psil_dst_id = resp->tx_cpsw_psil_dst_id;
+	ether_addr_copy(attach_ext_info->mac_addr, resp->mac_address);
+	if (attach_ext_info->features | RPMSG_KDRV_ETHSWITCH_FEATURE_MAC_ONLY)
+		attach_ext_info->mac_only_port = resp->mac_only_port;
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int rpmsg_kdrv_switch_detach(struct rpmsg_remotedev *rdev)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_detach_req *req;
+	struct rpmsg_kdrv_ethswitch_detach_resp *resp;
+	int ret;
+
+	if (!priv->attached)
+		return -EINVAL;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_DETACH;
+	req->info.id = priv->session_id;
+	req->info.core_key = priv->core_key;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret) {
+		dev_dbg(&kddev->dev, "%s: send: %d\n", __func__, ret);
+		goto out;
+	}
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+
+	priv->attached = false;
+
+	dev_dbg(&kddev->dev, "%s: done ret:%d\n", __func__, ret);
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int
+rpmsg_kdrv_switch_get_tx_info(struct rpmsg_remotedev *rdev,
+			      struct rpmsg_rdev_eth_switch_tx_info *info)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_alloc_req *req;
+	struct rpmsg_kdrv_ethswitch_alloc_tx_resp *resp;
+	int ret;
+
+	if (!priv->attached)
+		return -EINVAL;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_ALLOC_TX;
+	req->info.id = priv->session_id;
+	req->info.core_key = priv->core_key;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret) {
+		dev_dbg(&kddev->dev, "%s: send: %d\n", __func__, ret);
+		goto out;
+	}
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+	if (ret)
+		goto out;
+
+	info->tx_cpsw_psil_dst_id = resp->tx_cpsw_psil_dst_id;
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int
+rpmsg_kdrv_switch_get_rx_info(struct rpmsg_remotedev *rdev,
+			      struct rpmsg_rdev_eth_switch_rx_info *info)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_alloc_req *req;
+	struct rpmsg_kdrv_ethswitch_alloc_rx_resp *resp;
+	int ret;
+
+	if (!priv->attached)
+		return -EINVAL;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_ALLOC_RX;
+	req->info.id = priv->session_id;
+	req->info.core_key = priv->core_key;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret)
+		goto out;
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+	if (ret)
+		goto out;
+
+	info->flow_idx = resp->alloc_flow_idx;
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int rpmsg_kdrv_switch_get_mac(struct rpmsg_remotedev *rdev,
+				     void *mac_addr)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_alloc_req *req;
+	struct rpmsg_kdrv_ethswitch_alloc_mac_resp *resp;
+	int ret;
+
+	if (!priv->attached)
+		return -EINVAL;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_ALLOC_MAC;
+	req->info.id = priv->session_id;
+	req->info.core_key = priv->core_key;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret)
+		goto out;
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+	if (ret)
+		goto out;
+
+	ether_addr_copy(mac_addr, resp->mac_address);
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int rpmsg_kdrv_switch_register_mac(struct rpmsg_remotedev *rdev,
+					  void *mac_addr, u32 flow_idx_offset)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_register_mac_req *req;
+	struct rpmsg_kdrv_ethswitch_register_mac_resp *resp;
+	int ret;
+
+	if (!priv->attached)
+		return -EINVAL;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_REGISTER_MAC;
+	req->info.id = priv->session_id;
+	req->info.core_key = priv->core_key;
+	ether_addr_copy(req->mac_address, mac_addr);
+	req->flow_idx = flow_idx_offset;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret)
+		goto out;
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int
+rpmsg_kdrv_switch_unregister_mac(struct rpmsg_remotedev *rdev,
+				 void *mac_addr, u32 flow_idx_offset)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_unregister_mac_req *req;
+	struct rpmsg_kdrv_ethswitch_unregister_mac_resp *resp;
+	int ret;
+
+	if (!priv->attached)
+		return -EINVAL;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_UNREGISTER_MAC;
+	req->info.id = priv->session_id;
+	req->info.core_key = priv->core_key;
+	ether_addr_copy(req->mac_address, mac_addr);
+	req->flow_idx = flow_idx_offset;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret)
+		goto out;
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int rpmsg_kdrv_switch_reg_ipv4(struct rpmsg_remotedev *rdev,
+				      void *mac_addr, __be32 ipv4)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_ipv4_register_mac_req *req;
+	struct rpmsg_kdrv_ethswitch_ipv4_register_mac_resp *resp;
+	int ret;
+
+	if (!priv->attached)
+		return -EINVAL;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_IPV4_MAC_REGISTER;
+	req->info.id = priv->session_id;
+	req->info.core_key = priv->core_key;
+	ether_addr_copy(req->mac_address, mac_addr);
+	memcpy(req->ipv4_addr, &ipv4, RPMSG_KDRV_TP_ETHSWITCH_IPV4ADDRLEN);
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret)
+		goto out;
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int rpmsg_kdrv_switch_unreg_ipv4(struct rpmsg_remotedev *rdev,
+					__be32 ipv4)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_ipv4_unregister_mac_req *req;
+	struct rpmsg_kdrv_ethswitch_ipv4_unregister_mac_resp *resp;
+	int ret;
+
+	if (!priv->attached)
+		return -EINVAL;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_IPV4_MAC_UNREGISTER;
+	req->info.id = priv->session_id;
+	req->info.core_key = priv->core_key;
+	memcpy(req->ipv4_addr, &ipv4, RPMSG_KDRV_TP_ETHSWITCH_IPV4ADDRLEN);
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret)
+		goto out;
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int rpmsg_kdrv_switch_reg_read(struct rpmsg_remotedev *rdev,
+				      u32 reg_addr, u32 *val)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_regrd_req *req;
+	struct rpmsg_kdrv_ethswitch_regrd_resp *resp;
+	int ret;
+
+	if (!rpmsg_kdrv_switch_check_perm(priv, RPMSG_KDRV_TP_ETHSWITCH_REGRD))
+		return -EPERM;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_REGRD;
+	req->regaddr = reg_addr;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret)
+		goto out;
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+	if (ret)
+		goto out;
+
+	*val = resp->regval;
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int rpmsg_kdrv_switch_c2s_dbg_dump_stats(struct rpmsg_remotedev *rdev)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_c2s_notify *req;
+	int ret;
+
+	if (!priv->attached)
+		return -EINVAL;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_C2S_NOTIFY;
+	req->info.id = priv->session_id;
+	req->info.core_key = priv->core_key;
+	req->notifyid = RPMSG_KDRV_TP_ETHSWITCH_CLIENTNOTIFY_DUMPSTATS;
+
+	ret = rpmsg_kdrv_send_message(rpdev, kddev->device_id,
+				      req, sizeof(*req));
+
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int rpmsg_kdrv_switch_set_promisc(struct rpmsg_remotedev *rdev, u32 enable)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_set_promisc_mode_req *req;
+	struct rpmsg_kdrv_ethswitch_set_promisc_mode_resp *resp;
+	int ret;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_SET_PROMISC_MODE;
+	req->info.id = priv->session_id;
+	req->info.core_key = priv->core_key;
+	req->enable = enable ? 1 : 0;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret) {
+		dev_dbg(&kddev->dev, "%s: send: %d\n", __func__, ret);
+		goto out;
+	}
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+	if (ret)
+		goto out;
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int rpmsg_kdrv_switch_filter_add_mc(struct rpmsg_remotedev *rdev,
+					   const void *mac_addr, u16 vlan_id, u32 flow_idx)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_filter_add_mc_req *req;
+	struct rpmsg_kdrv_ethswitch_filter_add_mc_resp *resp;
+	int ret;
+
+	if (!priv->attached)
+		return -EINVAL;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_FILTER_ADD_MAC;
+	req->info.id = priv->session_id;
+	req->info.core_key = priv->core_key;
+	ether_addr_copy(req->mac_address, mac_addr);
+	req->flow_idx = flow_idx;
+	req->vlan_id = vlan_id;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret) {
+		dev_dbg(&kddev->dev, "%s: send: %d\n", __func__, ret);
+		goto out;
+	}
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static int rpmsg_kdrv_switch_filter_del_mc(struct rpmsg_remotedev *rdev,
+					   const void *mac_addr, u16 vlan_id, u32 flow_idx)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_device *kddev = priv->kddev;
+	struct rpmsg_device *rpdev = kddev->rpdev;
+	struct rpmsg_kdrv_ethswitch_filter_del_mc_req *req;
+	struct rpmsg_kdrv_ethswitch_filter_del_mc_resp *resp;
+	int ret;
+
+	if (!priv->attached)
+		return -EINVAL;
+
+	req = devm_kzalloc(&kddev->dev, sizeof(*req), GFP_KERNEL);
+	if (!req)
+		return -ENOMEM;
+
+	resp = devm_kzalloc(&kddev->dev, sizeof(*resp), GFP_KERNEL);
+	if (!resp) {
+		devm_kfree(&kddev->dev, req);
+		return -ENOMEM;
+	}
+
+	req->header.message_type = RPMSG_KDRV_TP_ETHSWITCH_FILTER_DEL_MAC;
+	req->info.id = priv->session_id;
+	req->info.core_key = priv->core_key;
+	ether_addr_copy(req->mac_address, mac_addr);
+	req->flow_idx = flow_idx;
+	req->vlan_id = vlan_id;
+
+	ret = rpmsg_kdrv_send_request_with_response(rpdev, kddev->device_id,
+						    req, sizeof(*req),
+						    resp, sizeof(*resp));
+	if (ret) {
+		dev_dbg(&kddev->dev, "%s: send: %d\n", __func__, ret);
+		goto out;
+	}
+
+	ret = rpmsg_kdrv_switch_check_resp_status(&resp->info);
+
+out:
+	devm_kfree(&kddev->dev, resp);
+	devm_kfree(&kddev->dev, req);
+	return ret;
+}
+
+static void rpmsg_kdrv_switch_get_fw_ver(struct rpmsg_remotedev *rdev,
+					 char *buf, size_t size)
+{
+	struct rpmsg_kdrv_switch_private *priv =
+		container_of(rdev, struct rpmsg_kdrv_switch_private, rdev);
+	struct rpmsg_kdrv_ethswitch_fw_version_info *fw_info;
+	struct rpmsg_kdrv_ethswitch_device_data *kddev_data;
+
+	kddev_data = priv->kddev->device_data;
+	fw_info = &kddev_data->fw_ver;
+
+	snprintf(buf, size, "%u.%u.%u %.*s/%.*s/%.*s SHA:%.*s",
+		 fw_info->major, fw_info->minor, fw_info->rev,
+		 RPMSG_KDRV_TP_ETHSWITCH_DATELEN, fw_info->date,
+		 RPMSG_KDRV_TP_ETHSWITCH_MONTHLEN, fw_info->month,
+		 RPMSG_KDRV_TP_ETHSWITCH_YEARLEN, fw_info->year,
+		 RPMSG_KDRV_TP_ETHSWITCH_COMMITSHALEN, fw_info->commit_hash);
+}
+
+static struct rpmsg_remotedev_eth_switch_ops switch_ops = {
+	.get_fw_ver = rpmsg_kdrv_switch_get_fw_ver,
+	.attach = rpmsg_kdrv_switch_attach,
+	.attach_ext = rpmsg_kdrv_switch_attach_ext,
+	.detach = rpmsg_kdrv_switch_detach,
+	.get_tx_info = rpmsg_kdrv_switch_get_tx_info,
+	.get_rx_info = rpmsg_kdrv_switch_get_rx_info,
+	.get_mac = rpmsg_kdrv_switch_get_mac,
+	.register_mac = rpmsg_kdrv_switch_register_mac,
+	.unregister_mac = rpmsg_kdrv_switch_unregister_mac,
+	.register_ipv4 = rpmsg_kdrv_switch_reg_ipv4,
+	.unregister_ipv4 = rpmsg_kdrv_switch_unreg_ipv4,
+	.ping = rpmsg_kdrv_switch_ping,
+	.read_reg = rpmsg_kdrv_switch_reg_read,
+	.dbg_dump_stats = rpmsg_kdrv_switch_c2s_dbg_dump_stats,
+	.set_promisc_mode = rpmsg_kdrv_switch_set_promisc,
+	.filter_add_mc = rpmsg_kdrv_switch_filter_add_mc,
+	.filter_del_mc = rpmsg_kdrv_switch_filter_del_mc,
+};
+
+static int rpmsg_kdrv_switch_callback(struct rpmsg_kdrv_device *dev,
+				      void *msg, int len)
+{
+	return 0;
+}
+
+static int
+rpmsg_kdrv_switch_dev_data_parse(struct rpmsg_kdrv_device *kddev,
+				 void *data, int len,
+				 struct rpmsg_kdrv_switch_private *priv)
+{
+	struct rpmsg_kdrv_ethswitch_device_data *kddev_data = data;
+	struct rpmsg_kdrv_ethswitch_fw_version_info *fw_info;
+
+	if (sizeof(*kddev_data) != len)
+		return -EINVAL;
+
+	dev_info(&kddev->dev, "Device info: permissions: %08X uart_id: %d\n",
+		 kddev_data->permission_flags,
+		 kddev_data->uart_connected ? kddev_data->uart_id : -1);
+
+	fw_info = &kddev_data->fw_ver;
+
+	dev_info(&kddev->dev, "FW ver %u.%u (rev %u) %.*s/%.*s/%.*s SHA:%.*s\n",
+		 fw_info->major, fw_info->minor, fw_info->rev,
+		 RPMSG_KDRV_TP_ETHSWITCH_DATELEN, fw_info->date,
+		 RPMSG_KDRV_TP_ETHSWITCH_MONTHLEN, fw_info->month,
+		 RPMSG_KDRV_TP_ETHSWITCH_YEARLEN, fw_info->year,
+		 RPMSG_KDRV_TP_ETHSWITCH_COMMITSHALEN, fw_info->commit_hash);
+
+	if (fw_info->major != RPMSG_KDRV_TP_ETHSWITCH_VERSION_MAJOR &&
+	    fw_info->minor != RPMSG_KDRV_TP_ETHSWITCH_VERSION_MINOR) {
+		dev_err(&kddev->dev, "Unsupported EthSwitch FW version\n");
+		return -EOPNOTSUPP;
+	}
+
+	priv->uart_connected = kddev_data->uart_connected;
+	priv->uart_id = kddev_data->uart_connected ? kddev_data->uart_id : -1;
+	priv->permissions = kddev_data->permission_flags;
+
+	return 0;
+}
+
+static int rpmsg_kdrv_switch_probe(struct rpmsg_kdrv_device *dev)
+{
+	struct rpmsg_kdrv_switch_private *priv;
+	int ret;
+
+	priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->rdev.type = RPMSG_REMOTEDEV_ETH_SWITCH_DEVICE;
+	priv->rdev.device.eth_switch.ops = &switch_ops;
+
+	priv->kddev = dev;
+
+	ret = rpmsg_kdrv_switch_dev_data_parse(dev, dev->device_data,
+					       dev->device_data_len, priv);
+	if (ret)
+		return ret;
+
+	dev->driver_private = priv;
+	dev->remotedev = &priv->rdev;
+
+	return 0;
+}
+
+static void rpmsg_kdrv_switch_remove(struct rpmsg_kdrv_device *dev)
+{
+	dev->driver_private = NULL;
+	dev->remotedev = NULL;
+}
+
+static struct rpmsg_kdrv_driver rpmsg_kdrv_switch = {
+	.drv = {
+		.name = "rpmsg-kdrv-eth-switch",
+	},
+	.device_type = RPMSG_KDRV_TP_DEVICE_TYPE_ETHSWITCH,
+	.probe = rpmsg_kdrv_switch_probe,
+	.remove = rpmsg_kdrv_switch_remove,
+	.callback = rpmsg_kdrv_switch_callback,
+};
+
+static int __init rpmsg_kdrv_display_driver_init(void)
+{
+	return rpmsg_kdrv_register_driver(&rpmsg_kdrv_switch);
+}
+module_init(rpmsg_kdrv_display_driver_init);
+
+static void rpmsg_kdrv_display_driver_fini(void)
+{
+}
+module_exit(rpmsg_kdrv_display_driver_fini);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grygorii Strashko <grygorii.strashko@ti.com>");
+MODULE_DESCRIPTION("TI J721E RPMSG KDRV Ethernet switch driver");
diff -Naur --no-dereference a/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-common.h b/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-common.h
--- a/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-common.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-common.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Subhajit Paul <subhajit_paul@ti.com>
+ */
+
+#ifndef __RPMSG_KDRV_TRANSPORT_COMMON_H__
+#define __RPMSG_KDRV_TRANSPORT_COMMON_H__
+
+/*
+ * Device types supported by RPMSG-KDRV framework
+ * Currently supported device types: display
+ * Planned future support for capture and i2c devices
+ */
+#define RPMSG_KDRV_TP_DEVICE_TYPE_INIT		(0x0)
+#define RPMSG_KDRV_TP_DEVICE_TYPE_DISPLAY	(0x1)
+#define RPMSG_KDRV_TP_DEVICE_TYPE_DEMO		(0x2)
+#define RPMSG_KDRV_TP_DEVICE_TYPE_ETHSWITCH	(0x3)
+
+/* More device types here*/
+#define RPMSG_KDRV_TP_DEVICE_TYPE_MAX		(0x4)
+
+/*
+ * Maximum number of proxy devices per remotecore
+ */
+#define RPMSG_KDRV_TP_MAX_DEVICES		(4)
+
+/*
+ * Maximum length of proxy device name
+ */
+#define RPMSG_KDRV_TP_DEVICE_NAME_LEN		(32)
+
+/*
+ * Statically assigned device ID for init device
+ * Remote device framework dynamically assigns device
+ * IDs for other devices. All dynamically assigned IDs
+ * are greater than RPMSG_KDRV_TP_DEVICE_ID_INIT
+ */
+#define RPMSG_KDRV_TP_DEVICE_ID_INIT		(0)
+
+/*
+ * Packet IDs are assigned dynamically (for REQUEST packets)
+ * starting from RPMSG_KDRV_TP_PACKET_ID_FIRST
+ * For MESSAGE packets, framework can use RPMSG_KDRV_TP_PACKET_ID_NONE
+ */
+#define RPMSG_KDRV_TP_PACKET_ID_NONE		(0x10)
+#define RPMSG_KDRV_TP_PACKET_ID_FIRST		(RPMSG_KDRV_TP_PACKET_ID_NONE + 1)
+
+enum rpmsg_kdrv_packet_source {
+	RPMSG_KDRV_TP_PACKET_SOURCE_SERVER,
+	RPMSG_KDRV_TP_PACKET_SOURCE_CLIENT,
+	RPMSG_KDRV_TP_PACKET_SOURCE_MAX,
+};
+
+enum rpmsg_kdrv_packet_type {
+	RPMSG_KDRV_TP_PACKET_TYPE_REQUEST,
+	RPMSG_KDRV_TP_PACKET_TYPE_RESPONSE,
+	RPMSG_KDRV_TP_PACKET_TYPE_MESSAGE,
+	RPMSG_KDRV_TP_PACKET_TYPE_MAX,
+};
+
+/*RPMSG_KDRV message :
+ * => device_header
+ * => message_header : defined by each device type
+ * => request / response / message payload
+ */
+struct rpmsg_kdrv_device_header {
+	/* ID of device sending the packet */
+	u8 device_id;
+	/* enum: rpmsg_kdrv_packet_type */
+	u8 packet_type;
+	/* enum: rpmsg_kdrv_packet_source */
+	u8 packet_source;
+	/* dynamically assigned packet ID for response matching */
+	u32 packet_id;
+	/* size of packet */
+	u32 packet_size;
+} __packed;
+
+#endif
diff -Naur --no-dereference a/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-demo.h b/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-demo.h
--- a/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-demo.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-demo.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Subhajit Paul <subhajit_paul@ti.com>
+ */
+
+#ifndef __RPMSG_KDRV_TRANSPORT_DEMODEV_H__
+#define __RPMSG_KDRV_TRANSPORT_DEMODEV_H__
+
+#include "rpmsg-kdrv-transport-common.h"
+
+enum rpmsg_kdrv_display_message_type {
+	RPMSG_KDRV_TP_DEMODEV_PING_REQUEST,
+	RPMSG_KDRV_TP_DEMODEV_PING_RESPONSE,
+	RPMSG_KDRV_TP_DEMODEV_S2C_MESSAGE,
+	RPMSG_KDRV_TP_DEMODEV_C2S_MESSAGE,
+	RPMSG_KDRV_TP_DEMODEV_MAX,
+};
+
+/*
+ * Maximum length of demo device data
+ */
+#define RPMSG_KDRV_TP_DEMODEV_DEVICE_DATA_LEN	(32)
+
+/*
+ * Maximum length of demo device message data
+ */
+#define RPMSG_KDRV_TP_DEMODEV_MESSAGE_DATA_LEN	(128)
+
+/*
+ * per-device data for demo device
+ */
+struct rpmsg_kdrv_demodev_device_data {
+	/* Does the device send all vsyncs? */
+	u8 charString[RPMSG_KDRV_TP_DEMODEV_DEVICE_DATA_LEN];
+} __packed;
+
+/*
+ * message header for demo device
+ */
+struct rpmsg_kdrv_demodev_message_header {
+	/* enum: rpmsg_kdrv_demodev_message_type */
+	u8 message_type;
+} __packed;
+
+/* demo device ping request - always client to server */
+struct rpmsg_kdrv_demodev_ping_request {
+	/* message header */
+	struct rpmsg_kdrv_demodev_message_header header;
+	/* ping data */
+	u8 data[RPMSG_KDRV_TP_DEMODEV_MESSAGE_DATA_LEN];
+} __packed;
+
+/* demo device ping response - always server to client */
+struct rpmsg_kdrv_demodev_ping_response {
+	/* message header */
+	struct rpmsg_kdrv_demodev_message_header header;
+	/* ping data */
+	u8 data[RPMSG_KDRV_TP_DEMODEV_MESSAGE_DATA_LEN];
+} __packed;
+
+/* demo device server to client one-way message */
+struct rpmsg_kdrv_demodev_s2c_message {
+	/* message header */
+	struct rpmsg_kdrv_demodev_message_header header;
+	/* message data */
+	u8 data[RPMSG_KDRV_TP_DEMODEV_MESSAGE_DATA_LEN];
+} __packed;
+
+/* demo device client to server one-way message */
+struct rpmsg_kdrv_demodev_c2s_message {
+	/* message header */
+	struct rpmsg_kdrv_demodev_message_header header;
+	/* message data */
+	u8 data[RPMSG_KDRV_TP_DEMODEV_MESSAGE_DATA_LEN];
+} __packed;
+
+#endif
diff -Naur --no-dereference a/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-display.h b/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-display.h
--- a/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-display.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-display.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,223 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Subhajit Paul <subhajit_paul@ti.com>
+ */
+
+#ifndef __RPMSG_KDRV_TRANSPORT_DISPLAY_H__
+#define __RPMSG_KDRV_TRANSPORT_DISPLAY_H__
+
+#include "rpmsg-kdrv-transport-common.h"
+
+/*
+ * Maximum number of planes per buffer
+ */
+#define RPMSG_KDRV_TP_DISPLAY_MAX_PLANES	(2)
+
+/*
+ * Maximum number of shared displays
+ */
+#define RPMSG_KDRV_TP_DISPLAY_MAX_VPS		(2)
+
+/*
+ * Maximum number of pipes per shared display
+ */
+#define RPMSG_KDRV_TP_DISPLAY_MAX_VIDS		(4)
+
+/*
+ * Maximum number of formats supported per pipe
+ */
+#define RPMSG_KDRV_TP_DISPLAY_MAX_FORMATS	(2)
+
+/*
+ * Maximum number of zorders supported per pipe
+ */
+#define RPMSG_KDRV_TP_DISPLAY_MAX_ZORDERS	(4)
+
+enum rpmsg_kdrv_display_format {
+	RPMSG_KDRV_TP_DISPLAY_FORMAT_ARGB8888,
+	RPMSG_KDRV_TP_DISPLAY_FORMAT_XRGB8888,
+	RPMSG_KDRV_TP_DISPLAY_FORMAT_MAX,
+};
+
+enum rpmsg_kdrv_display_message_type {
+	RPMSG_KDRV_TP_DISPLAY_READY_QUERY_REQUEST,
+	RPMSG_KDRV_TP_DISPLAY_READY_QUERY_RESPONSE,
+	RPMSG_KDRV_TP_DISPLAY_RES_INFO_REQUEST,
+	RPMSG_KDRV_TP_DISPLAY_RES_INFO_RESPONSE,
+	RPMSG_KDRV_TP_DISPLAY_COMMIT_REQUEST,
+	RPMSG_KDRV_TP_DISPLAY_COMMIT_RESPONSE,
+	RPMSG_KDRV_TP_DISPLAY_COMMIT_DONE_MESSAGE,
+	RPMSG_KDRV_TP_DISPLAY_BUFFER_DONE_MESSAGE,
+	RPMSG_KDRV_TP_DISPLAY_MAX,
+};
+
+/*
+ * per-device data for display device
+ */
+struct rpmsg_kdrv_display_device_data {
+	/* Does the device send all vsyncs? */
+	u8 periodic_vsync;
+	/*Does the device defer the use of buffers? */
+	u8 deferred_buffer_usage;
+} __packed;
+
+/*
+ * message header for display device
+ */
+struct rpmsg_kdrv_display_message_header {
+	/* enum: rpmsg_kdrv_display_message_type */
+	u8 message_type;
+} __packed;
+
+/* display device request to provide ready / not-ready info */
+struct rpmsg_kdrv_display_ready_query_request {
+	/* message header */
+	struct rpmsg_kdrv_display_message_header header;
+} __packed;
+
+/* display device response indicating ready / not-ready status */
+struct rpmsg_kdrv_display_ready_query_response {
+	/* message header */
+	struct rpmsg_kdrv_display_message_header header;
+	/* can be 0 : if not ready 1: if ready */
+	u8 ready;
+} __packed;
+
+/* display device buffer update info */
+struct rpmsg_kdrv_display_buffer_info {
+	/* buffer width */
+	u16 width;
+	/* buffer height */
+	u16 height;
+	/* enum: rpmsg_kdrv_display_format */
+	u8 format;
+	/* number of planes */
+	u8 num_planes;
+	/* per plane start addresses */
+	u64 plane[RPMSG_KDRV_TP_DISPLAY_MAX_PLANES];
+	/* per plane pitch */
+	u16 pitch[RPMSG_KDRV_TP_DISPLAY_MAX_PLANES];
+	/* buffer id : to be used in buffer-done message */
+	u32 buffer_id;
+} __packed;
+
+/* display device pipe update info */
+struct rpmsg_kdrv_display_vid_update_info {
+	/* pipe ID */
+	u8 id;
+	/*enable / disable request */
+	u8 enabled;
+	/* window width */
+	u16 dst_w;
+	/* window height */
+	u16 dst_h;
+	/* window position X */
+	u16 dst_x;
+	/* window position Y */
+	u16 dst_y;
+	/* buffer */
+	struct rpmsg_kdrv_display_buffer_info buffer;
+} __packed;
+
+/* display device commit request */
+struct rpmsg_kdrv_display_commit_request {
+	/* message header */
+	struct rpmsg_kdrv_display_message_header header;
+	/*ID of shared display */
+	u8 id;
+	/* number of pipe updates in the commit */
+	u8 num_vid_updates;
+	/* list of pipe updates */
+	struct rpmsg_kdrv_display_vid_update_info vid[RPMSG_KDRV_TP_DISPLAY_MAX_VIDS];
+	/*commit id : to be used in commit-done message */
+	u32 commit_id;
+} __packed;
+
+/* display device commit response */
+struct rpmsg_kdrv_display_commit_response {
+	/* message header */
+	struct rpmsg_kdrv_display_message_header header;
+	/*commit id : from commit request */
+	u32 commit_id;
+	/*status : 0 = accepted, 1 = rejected */
+	u8 status;
+} __packed;
+
+/* display device commit done message */
+struct rpmsg_kdrv_display_commit_done_message {
+	/* message header */
+	struct rpmsg_kdrv_display_message_header header;
+	/* commit id : from commit request */
+	u32 commit_id;
+} __packed;
+
+/*display device buffer deferred release message */
+struct rpmsg_kdrv_display_buffer_done_message {
+	/* message header */
+	struct rpmsg_kdrv_display_message_header header;
+	/* buffer id: from bufer_info */
+	u32 buffer_id;
+} __packed;
+
+/* display device request to provide list of shared resources */
+struct rpmsg_kdrv_display_res_info_request {
+	/* message header */
+	struct rpmsg_kdrv_display_message_header header;
+} __packed;
+
+/* display device shared pipe */
+struct rpmsg_kdrv_display_vid_info {
+	/* pipe ID */
+	u8 id;
+	/* is pipe window fixed on display? */
+	u8 mutable_window;
+	/* fixed window position X, if applicable */
+	u16 fixed_window_x;
+	/* fixed window position Y, if applicable */
+	u16 fixed_window_y;
+	/* fixed window width, if applicable */
+	u16 fixed_window_w;
+	/* fixed window height, if applicable */
+	u16 fixed_window_h;
+	/* can pipe scale buffers? */
+	u8 can_scale;
+	/* number of formats supported */
+	u8 num_formats;
+	/*enum: rpmsg_kdrv_display_format */
+	u8 format[RPMSG_KDRV_TP_DISPLAY_MAX_FORMATS];
+	/* initial zorder of pipe */
+	u8 init_zorder;
+	/* number of allowed zorders */
+	u8 num_zorders;
+	/* list of allowed zorders */
+	u8 zorder[RPMSG_KDRV_TP_DISPLAY_MAX_ZORDERS];
+} __packed;
+
+/* display device shared display */
+struct rpmsg_kdrv_display_vp_info {
+	/* ID of shared display */
+	u8 id;
+	/* raster width */
+	u16 width;
+	/* raster height */
+	u16 height;
+	/* refresh rate */
+	u8 refresh;
+	/* number of pipes for this display */
+	u8 num_vids;
+	/* list of pipes */
+	struct rpmsg_kdrv_display_vid_info vid[RPMSG_KDRV_TP_DISPLAY_MAX_VIDS];
+} __packed;
+
+/* display device response providing list of shared resources */
+struct rpmsg_kdrv_display_res_info_response {
+	/* message header */
+	struct rpmsg_kdrv_display_message_header header;
+	/* number of shared displays */
+	u8 num_vps;
+	/* list of shared displays */
+	struct rpmsg_kdrv_display_vp_info vp[RPMSG_KDRV_TP_DISPLAY_MAX_VPS];
+} __packed;
+
+#endif
diff -Naur --no-dereference a/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport.h b/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport.h
--- a/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Subhajit Paul <subhajit_paul@ti.com>
+ */
+
+#ifndef __RPMSG_KDRV_TRANSPORT_H__
+#define __RPMSG_KDRV_TRANSPORT_H__
+
+#include "rpmsg-kdrv-transport-common.h"
+
+enum rpmsg_kdrv_init_message_type {
+	RPMSG_KDRV_TP_INIT_DEV_INFO_REQUEST,
+	RPMSG_KDRV_TP_INIT_DEV_INFO_RESPONSE,
+	RPMSG_KDRV_TP_INIT_CONNECT_MESSAGE,
+	RPMSG_KDRV_TP_INIT_DISCONNECT_MESSAGE,
+	RPMSG_KDRV_TP_INIT_MAX,
+};
+
+/*
+ * message header for init device
+ */
+struct rpmsg_kdrv_init_message_header {
+	/* enum: rpmsg_kdrv_init_message_type */
+	u8 message_type;
+} __packed;
+
+/*
+ * init device request to provide list of devices
+ */
+struct rpmsg_kdrv_init_dev_info_request {
+	/* message header */
+	struct rpmsg_kdrv_init_message_header header;
+} __packed;
+
+struct rpmsg_kdrv_init_device_info {
+	/* device id */
+	u8 device_id;
+	/* device type (display, capture etc) */
+	u8 device_type;
+	/* name of device */
+	u8 device_name[RPMSG_KDRV_TP_DEVICE_NAME_LEN];
+	/* device specific info length */
+	u16 device_data_len;
+	/* per device-type info offset */
+	u16 device_data_offset;
+} __packed;
+
+/*
+ * init device response with list of devices
+ */
+struct rpmsg_kdrv_init_dev_info_response {
+	/* message header */
+	struct rpmsg_kdrv_init_message_header header;
+	/*number of exported devices */
+	u8 num_devices;
+	/* list of exported devices */
+	struct rpmsg_kdrv_init_device_info devices[RPMSG_KDRV_TP_MAX_DEVICES];
+	/* device specific data */
+	u8 device_data[0];
+} __packed;
+
+/*
+ * init device per-device connect message
+ */
+struct rpmsg_kdrv_init_connect_message {
+	/* message header */
+	struct rpmsg_kdrv_init_message_header header;
+	/* device ID to connect */
+	u8 device_id;
+} __packed;
+
+/*
+ * init device per-device disconnect message
+ */
+struct rpmsg_kdrv_init_disconnect_message {
+	/* message header */
+	struct rpmsg_kdrv_init_message_header header;
+	/* device ID to disconnect */
+	u8 device_id;
+} __packed;
+
+#endif
diff -Naur --no-dereference a/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-switch.h b/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-switch.h
--- a/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-switch.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rpmsg-kdrv/shared/rpmsg-kdrv-transport-switch.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,664 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Grygorii Strashko <grygorii.strashko@ti.com>
+ */
+
+#ifndef DRIVERS_RPMSG_KDRV_SHARED_RPMSG_KDRV_TRANSPORT_SWITCH_H_
+#define DRIVERS_RPMSG_KDRV_SHARED_RPMSG_KDRV_TRANSPORT_SWITCH_H_
+
+#include <linux/etherdevice.h>
+#include "rpmsg-kdrv-transport-common.h"
+
+#define RPMSG_KDRV_TP_ETHSWITCH_VERSION_MAJOR             (0)
+#define RPMSG_KDRV_TP_ETHSWITCH_VERSION_MINOR             (1)
+#define RPMSG_KDRV_TP_ETHSWITCH_VERSION_REVISION          (1)
+
+/**
+ * enum rpmsg_kdrv_ethswitch_message_type - Eth switch rpmsg protocol messages
+ */
+enum rpmsg_kdrv_ethswitch_message_type {
+	RPMSG_KDRV_TP_ETHSWITCH_ATTACH = 0x00,
+	RPMSG_KDRV_TP_ETHSWITCH_ATTACH_EXT = 0x01,
+	RPMSG_KDRV_TP_ETHSWITCH_ALLOC_TX = 0x02,
+	RPMSG_KDRV_TP_ETHSWITCH_ALLOC_RX = 0x03,
+	RPMSG_KDRV_TP_ETHSWITCH_REGISTER_DEFAULTFLOW = 0x04,
+	RPMSG_KDRV_TP_ETHSWITCH_ALLOC_MAC = 0x05,
+	RPMSG_KDRV_TP_ETHSWITCH_REGISTER_MAC = 0x06,
+	RPMSG_KDRV_TP_ETHSWITCH_UNREGISTER_MAC = 0x07,
+	RPMSG_KDRV_TP_ETHSWITCH_UNREGISTER_DEFAULTFLOW = 0x08,
+	RPMSG_KDRV_TP_ETHSWITCH_FREE_MAC = 0x09,
+	RPMSG_KDRV_TP_ETHSWITCH_FREE_TX = 0x0A,
+	RPMSG_KDRV_TP_ETHSWITCH_FREE_RX = 0x0B,
+	RPMSG_KDRV_TP_ETHSWITCH_DETACH = 0x0C,
+	RPMSG_KDRV_TP_ETHSWITCH_IOCTL = 0x0D,
+	RPMSG_KDRV_TP_ETHSWITCH_REGWR = 0x0E,
+	RPMSG_KDRV_TP_ETHSWITCH_REGRD = 0x0F,
+	RPMSG_KDRV_TP_ETHSWITCH_IPV4_MAC_REGISTER = 0x10,
+	RPMSG_KDRV_TP_ETHSWITCH_IPV6_MAC_REGISTER = 0x11,
+	RPMSG_KDRV_TP_ETHSWITCH_IPV4_MAC_UNREGISTER = 0x12,
+	RPMSG_KDRV_TP_ETHSWITCH_IPV6_MAC_UNREGISTER = 0x13,
+	RPMSG_KDRV_TP_ETHSWITCH_PING_REQUEST = 0x14,
+	RPMSG_KDRV_TP_ETHSWITCH_S2C_NOTIFY = 0x15,
+	RPMSG_KDRV_TP_ETHSWITCH_C2S_NOTIFY = 0x16,
+	RPMSG_KDRV_TP_ETHSWITCH_REGISTER_ETHTYPE = 0x17,
+	RPMSG_KDRV_TP_ETHSWITCH_UNREGISTER_ETHTYPE = 0x18,
+	RPMSG_KDRV_TP_ETHSWITCH_REGISTER_REMOTETIMER = 0x19,
+	RPMSG_KDRV_TP_ETHSWITCH_UNREGISTER_REMOTETIMER = 0x1A,
+	RPMSG_KDRV_TP_ETHSWITCH_SET_PROMISC_MODE = 0x1B,
+	RPMSG_KDRV_TP_ETHSWITCH_FILTER_ADD_MAC = 0x1C,
+	RPMSG_KDRV_TP_ETHSWITCH_FILTER_DEL_MAC = 0x1D,
+	RPMSG_KDRV_TP_ETHSWITCH_MAX = 0x1E,
+};
+
+/**
+ * Client to Eth switch notification events @RPMSG_KDRV_TP_ETHSWITCH_C2S_NOTIFY
+ */
+enum rpmsg_kdrv_ethswitch_c2s_notify_type {
+	RPMSG_KDRV_TP_ETHSWITCH_CLIENTNOTIFY_DUMPSTATS = 0x00,
+	RPMSG_KDRV_TP_ETHSWITCH_CLIENTNOTIFY_MAX,
+};
+
+/**
+ * Eth switch HW ID
+ */
+enum rpmsg_kdrv_ethswitch_cpsw_type {
+	RPMSG_KDRV_TP_ETHSWITCH_CPSWTYPE_MCU_CPSW,
+	RPMSG_KDRV_TP_ETHSWITCH_CPSWTYPE_MAIN_CPSW,
+	RPMSG_KDRV_TP_ETHSWITCH_CPSWTYPE_MAX,
+};
+
+/**
+ * Response status codes returned by Eth switch FW in
+ * struct @rpmsg_kdrv_ethswitch_common_resp_info
+ */
+#define RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK		(0)
+#define RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_EAGAIN	(-1)
+#define RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_EFAIL		(-2)
+#define RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_EACCESS	(-3)
+
+/* Maximum length of message data */
+#define RPMSG_KDRV_TP_ETHSWITCH_MESSAGE_DATA_LEN	(128)
+
+/* Number of priorities supported by CPSW */
+#define RPMSG_KDRV_TP_ETHSWITCH_PRIORITY_NUM   (8)
+
+/* IPv4 Address length in octets */
+#define RPMSG_KDRV_TP_ETHSWITCH_IPV4ADDRLEN         (4)
+
+/**
+ * struct rpmsg_kdrv_ethswitch_msg_header - Message Header for outgoing messages
+ *
+ * @message_type: Type of messages: One of
+ *	enum @rpmsg_kdrv_ethswitch_message_type values
+ */
+struct rpmsg_kdrv_ethswitch_msg_header {
+	u8 message_type;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_common_req_info - common request msgs data
+ *
+ * @id: unique handle
+ * @core_key: core specific key to indicate attached core
+ *
+ * Common structure used for all Eth switch FW request msgs except
+ * @RPMSG_KDRV_TP_ETHSWITCH_ATTACH. It has to be filled with values returned
+ * by @RPMSG_KDRV_TP_ETHSWITCH_ATTACH.
+ */
+struct rpmsg_kdrv_ethswitch_common_req_info {
+	u64 id;
+	u32 core_key;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_common_resp_info - common response data
+ *
+ * @status: status of request
+ *
+ * Common data returned by Eth switch FW in all response messages to identify
+ * status of request message processing.
+ */
+struct rpmsg_kdrv_ethswitch_common_resp_info {
+	s32 status;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_attach_req - attach cmd client request msg
+ *
+ * @header: msg header
+ * @cpsw_type: CPSW HW type enum @rpmsg_kdrv_ethswitch_cpsw_type
+ *
+ * Client attach message @RPMSG_KDRV_TP_ETHSWITCH_ATTACH. it should be always
+ * sent first before other requests to Eth switch FW.
+ */
+struct rpmsg_kdrv_ethswitch_attach_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	u8 cpsw_type;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_attach_resp - attach client response msg
+ *
+ * @info: common response data. Status of the request processing
+ * @id: unique handle used by all further CMDs
+ * @core_key: core specific key to indicate attached core
+ * @rx_mtu: MTU of rx packets
+ * @tx_mtu: MTU of tx packet per priority
+ * @features: supported features mask
+ * @mac_only_port: 1-relative MAC port number for ports in MAC-only mode, 0
+ *                 for switch ports.
+ *
+ * Attach client response msg received as response to client attach request
+ * @RPMSG_KDRV_TP_ETHSWITCH_ATTACH. The @id and @core_key should be used to
+ * fill struct @rpmsg_kdrv_ethswitch_common_req_info in all further request
+ * messages.
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_attach_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+	u64 id;
+	u32 core_key;
+	u32 rx_mtu;
+	u32 tx_mtu[RPMSG_KDRV_TP_ETHSWITCH_PRIORITY_NUM];
+	u32 features;
+#define RPMSG_KDRV_TP_ETHSWITCH_FEATURE_TXCSUM BIT(0)
+#define RPMSG_KDRV_ETHSWITCH_FEATURE_MAC_ONLY BIT(2)
+#define RPMSG_KDRV_ETHSWITCH_FEATURE_MC_FILTER BIT(3)
+	u32 mac_only_port;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_attach_extended_req - extended attach request msg
+ *
+ * @header: msg header
+ * @cpsw_type: CPSW HW type enum @rpmsg_kdrv_ethswitch_cpsw_type
+ *
+ * Client extended attach request @RPMSG_KDRV_TP_ETHSWITCH_ATTACH_EXT. It can
+ * be used instead of @RPMSG_KDRV_TP_ETHSWITCH_ATTACH and has to sent first
+ * before other requests to Eth switch FW.
+ */
+struct rpmsg_kdrv_ethswitch_attach_extended_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	u8 cpsw_type;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_common_response_info - extended attach resp msg
+ *
+ * @info: common response data. Status of the request processing
+ * @id: unique handle used by all further CMDs
+ * @core_key: core specific key to indicate attached core
+ * @rx_mtu: MTU of rx packets
+ * @tx_mtu: MTU of tx packet per priority
+ * @features: supported features mask
+ * @alloc_flow_idx: RX UDMA flow ID
+ * @tx_cpsw_psil_dst_id: PSI-L dest thread id
+ * @mac_address: default eth MAC address assigned to this client
+ * @mac_only_port: 1-relative MAC port number for ports in MAC-only mode, 0
+ *                 for switch ports.
+ *
+ * Extended attach response msg received as response to client extended attach
+ * request @RPMSG_KDRV_TP_ETHSWITCH_ATTACH_EXT. The @id and @core_key should be
+ * used to fill struct @rpmsg_kdrv_ethswitch_common_req_info in all further
+ * request messages. In addition, it provides allocated DMA resources and
+ * MAC address.
+ *
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_attach_extended_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+	u64 id;
+	u32 core_key;
+	u32 rx_mtu;
+	u32 tx_mtu[RPMSG_KDRV_TP_ETHSWITCH_PRIORITY_NUM];
+	u32 features;
+	u32 alloc_flow_idx;
+	u32 tx_cpsw_psil_dst_id;
+	u8 mac_address[ETH_ALEN];
+	u32 mac_only_port;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_detach_req  - detach client request msg
+ *
+ * @header: msg header
+ * @info: common request msgs data
+ *
+ * Client detach request message @RPMSG_KDRV_TP_ETHSWITCH_DETACH.
+ * it should be always sent as the last message to Eth switch FW.
+ */
+struct rpmsg_kdrv_ethswitch_detach_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	struct rpmsg_kdrv_ethswitch_common_req_info info;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_detach_resp - detach client response msg
+ *
+ * @info: common response data. Status of the request processing
+ *
+ * Client detach response msg received as response to client detach request
+ * @RPMSG_KDRV_TP_ETHSWITCH_DETACH.
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_detach_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_alloc_req  - alloc resources request msg
+ *
+ * @header: msg header
+ * @info: common request msgs data
+ *
+ * Client resources allocation request messages
+ * @RPMSG_KDRV_TP_ETHSWITCH_ALLOC_RX: get RX DMA resources
+ * @RPMSG_KDRV_TP_ETHSWITCH_ALLOC_TX: get TX DMA resources
+ * @RPMSG_KDRV_TP_ETHSWITCH_ALLOC_MAC: get MAC address
+ */
+struct rpmsg_kdrv_ethswitch_alloc_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	struct rpmsg_kdrv_ethswitch_common_req_info info;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_alloc_rx_resp - alloc rx resources response msg
+ *
+ * @info: common response data. Status of the request processing
+ * @alloc_flow_idx: RX UDMA flow ID
+ *
+ * Client alloc rx resources response msg received as response to request
+ * @RPMSG_KDRV_TP_ETHSWITCH_ALLOC_RX. The @alloc_flow_idx is RX UDMA flow ID
+ * to be used for ingress packets reception.
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_alloc_rx_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+	u32 alloc_flow_idx;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_alloc_tx_resp - alloc tx resources response msg
+ *
+ * @info: common response data. Status of the request processing
+ * @tx_cpsw_psil_dst_id: PSI-L dest thread id
+ *
+ * Client alloc tx resources response msg received as response to request
+ * @RPMSG_KDRV_TP_ETHSWITCH_ALLOC_TX. The @tx_cpsw_psil_dst_id is TX PSI-L dest
+ * thread ID to be used for TX UDMA channel setup.
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_alloc_tx_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+	u32 tx_cpsw_psil_dst_id;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_alloc_mac_resp - alloc MAC resources response msg
+ *
+ * @info: common response data. Status of the request processing
+ * @mac_address: default eth MAC address assigned to this client
+ *
+ * Client alloc MAC resources response msg received as response to request
+ * @RPMSG_KDRV_TP_ETHSWITCH_ALLOC_MAC.
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_alloc_mac_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+	u8 mac_address[ETH_ALEN];
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_register_mac_req - register MAC addr
+ *
+ * @header: msg header
+ * @info: common request msgs data
+ * @mac_address: eth MAC address used by client
+ * @flow_idx: RX UDMA flow ID
+ *
+ * Client register MAC addr message @RPMSG_KDRV_TP_ETHSWITCH_REGISTER_MAC.
+ * it should be sent to Eth switch FW to configure HW network traffic
+ * classifiers so all network traffic directed to @mac_address will be
+ * redirected to this client and can be received through allocated RX UDMA flow
+ * @flow_idx.
+ *
+ * This message has to be sent by client when it's ready to receive network
+ * traffic.
+ */
+struct rpmsg_kdrv_ethswitch_register_mac_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	struct rpmsg_kdrv_ethswitch_common_req_info info;
+	u8 mac_address[ETH_ALEN];
+	u32 flow_idx;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_register_mac_resp - register MAC addr response
+ *
+ * @info: common response data. Status of the request processing
+ *
+ * Client register MAC addr response msg received as response to
+ * request @RPMSG_KDRV_TP_ETHSWITCH_REGISTER_MAC.
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_register_mac_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_unregister_mac_req - unregister MAC addr
+ *
+ * @header: msg header
+ * @info: common request msgs data
+ * @mac_address: eth MAC address used by client
+ * @flow_idx: RX UDMA flow ID
+ *
+ * Client unregister MAC addr message @RPMSG_KDRV_TP_ETHSWITCH_UNREGISTER_MAC.
+ * it should be sent to Eth switch FW to disable HW network traffic
+ * classifiers so all network traffic directed to @mac_address will be dropped.
+ *
+ * This message has to be sent by client when it does not want to receive any
+ * more network traffic.
+ */
+struct rpmsg_kdrv_ethswitch_unregister_mac_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	struct rpmsg_kdrv_ethswitch_common_req_info info;
+	u8 mac_address[ETH_ALEN];
+	u32 flow_idx;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_unregister_mac_resp - unregister MAC addr resp
+ *
+ * @info: common response data. Status of the request processing
+ *
+ * Client unregister MAC addr response msg received as response to
+ * request @RPMSG_KDRV_TP_ETHSWITCH_UNREGISTER_MAC.
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_unregister_mac_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_ipv4_register_mac_req - register IPv4:MAC pair
+ *
+ * @header: msg header
+ * @info: common request msgs data
+ * @mac_address: eth MAC address used by client
+ * @ipv4_addr: IPv4 addr
+ *
+ * Client register IPv4:MAC addr pair message
+ * @RPMSG_KDRV_TP_ETHSWITCH_IPV4_MAC_REGISTER registers pair of IPv4 @ipv4_addr
+ * and Eth MAC @mac_address addresses in Eth switch FW ARP database.
+ *
+ * This message has to be sent by client when there is new IPv4 addr assigned.
+ */
+struct rpmsg_kdrv_ethswitch_ipv4_register_mac_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	struct rpmsg_kdrv_ethswitch_common_req_info info;
+	u8 mac_address[ETH_ALEN];
+	u8 ipv4_addr[RPMSG_KDRV_TP_ETHSWITCH_IPV4ADDRLEN];
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_ipv4_register_mac_resp - register IPv4:MAC pair
+ *	response
+ *
+ * @info: common response data. Status of the request processing
+ *
+ * Client register IPv4:MAC addr pair response msg received as response to
+ * request @RPMSG_KDRV_TP_ETHSWITCH_IPV4_MAC_REGISTER.
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_ipv4_register_mac_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_ipv4_unregister_mac_req - unregister IPv4 addr
+ *
+ * @header: msg header
+ * @info: common request msgs data
+ * @ipv4_addr: IPv4 addr
+ *
+ * Client unregister IPv4 addr message
+ * @RPMSG_KDRV_TP_ETHSWITCH_IPV4_MAC_UNREGISTER. It removes IPv4 @ipv4_addr
+ * address from Eth switch FW ARP database.
+ *
+ * This message has to be sent by client when there is IPv4 addr unassigned.
+ */
+struct rpmsg_kdrv_ethswitch_ipv4_unregister_mac_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	struct rpmsg_kdrv_ethswitch_common_req_info info;
+	u8 ipv4_addr[RPMSG_KDRV_TP_ETHSWITCH_IPV4ADDRLEN];
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_ipv4_unregister_mac_resp - unregister IPv4 addr
+ *
+ * @info: common response data. Status of the request processing
+ *
+ * Client unregister IPv4 addr response msg received as response to
+ * request @RPMSG_KDRV_TP_ETHSWITCH_IPV4_MAC_UNREGISTER.
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_ipv4_unregister_mac_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_ping_req - ping request
+ *
+ * @header: msg header
+ * @data: custom data
+ *
+ * Client ping request @RPMSG_KDRV_TP_ETHSWITCH_PING_REQUEST. The Eth switch FW
+ * should return the same @data in struct @rpmsg_kdrv_ethswitch_ping_resp.
+ * Can be used any time - no attach required.
+ */
+struct rpmsg_kdrv_ethswitch_ping_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	u8 data[RPMSG_KDRV_TP_ETHSWITCH_MESSAGE_DATA_LEN];
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_ping_resp - ping response
+ *
+ * @data: custom data
+ *
+ * The ping response msg received as response to request
+ * @RPMSG_KDRV_TP_ETHSWITCH_PING_REQUEST. The Eth switch FW should return
+ * the same @data as was provided in struct @rpmsg_kdrv_ethswitch_ping_req.
+ */
+struct rpmsg_kdrv_ethswitch_ping_resp {
+	u8 data[RPMSG_KDRV_TP_ETHSWITCH_MESSAGE_DATA_LEN];
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_regrd_req - read hw register request
+ *
+ * @header: msg header
+ * @regaddr: phys register address
+ *
+ * The read hw register request @RPMSG_KDRV_TP_ETHSWITCH_REGRD.
+ * The Eth switch FW should return the @regaddr register value.
+ * Can be used any time - no attach required.
+ */
+struct rpmsg_kdrv_ethswitch_regrd_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	u32 regaddr;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_regrd_resp - read hw register response
+ *
+ * @info: common response data. Status of the request processing
+ * @regval: register value
+ *
+ * The read hw register response received as response to request
+ * @RPMSG_KDRV_TP_ETHSWITCH_REGRD. The @regval is hw register value from
+ * @regaddr phys register address provided in
+ * struct @rpmsg_kdrv_ethswitch_regrd_req
+ *
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_regrd_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+	u32 regval;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_c2s_notify - notification request
+ *
+ * @header: msg header
+ * @info: common request msg data
+ * @notifyid: enum @rpmsg_kdrv_ethswitch_c2s_notify_type
+ * @notify_info_len: length of @notify_info
+ * @notify_info: notification message data
+ *
+ * The notification request message @RPMSG_KDRV_TP_ETHSWITCH_C2S_NOTIFY is one
+ * way message to Eth switch FW without response.
+ */
+struct rpmsg_kdrv_ethswitch_c2s_notify {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	struct rpmsg_kdrv_ethswitch_common_req_info info;
+	u8 notifyid;
+	u32 notify_info_len;
+	u8 notify_info[RPMSG_KDRV_TP_ETHSWITCH_MESSAGE_DATA_LEN];
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_set_promisc_mode_req - set promiscuous mode
+ *
+ * @header: msg header
+ * @info: common request msg data
+ * @enable: promiscuous mode (enable or disable)
+ *
+ * Client message @RPMSG_KDRV_TP_ETHSWITCH_SET_PROMISC_MODE is sent to change
+ * the promiscuous mode.
+ */
+struct rpmsg_kdrv_ethswitch_set_promisc_mode_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	struct rpmsg_kdrv_ethswitch_common_req_info info;
+	u32 enable;
+} __packed;
+
+/**
+ * Set promiscuous mode response msg received as response to client's mode change
+ * request @RPMSG_KDRV_TP_ETHSWITCH_SET_PROMISC_MODE.
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_set_promisc_mode_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_filter_add_mc_req - add multicast MAC address to filter
+ *
+ * @header: msg header
+ * @info: common request msg data
+ * @mac_address: Multicast address to be added
+ * @vlan_id: VLAN id
+ * @flow_idx: RX UDMA flow ID (used for multicast addresses marked as 'exclusive' in
+ *            switch firmware)
+ *
+ * Client message @RPMSG_KDRV_TP_ETHSWITCH_FILTER_ADD_MAC is sent to add a multicast
+ * address to the receive filter.
+ */
+struct rpmsg_kdrv_ethswitch_filter_add_mc_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	struct rpmsg_kdrv_ethswitch_common_req_info info;
+	u8 mac_address[ETH_ALEN];
+	u16 vlan_id;
+	u32 flow_idx;
+} __packed;
+
+/**
+ * Response msg received as response to client's request to add a multicas address to
+ * receive filter via @RPMSG_KDRV_TP_ETHSWITCH_FILTER_ADD_MAC.
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_filter_add_mc_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_filter_del_mac_req - delete multicast MAC address
+ * from filter
+ *
+ * @header: msg header
+ * @info: common request msg data
+ * @mac_address: Multicast address to be removed
+ * @vlan_id: VLAN id
+ * @flow_idx: RX UDMA flow ID (used for multicast addresses marked as 'exclusive' in
+ *            switch firmware)
+ *
+ * Client message @RPMSG_KDRV_TP_ETHSWITCH_FILTER_DEL_MAC is sent to delete a multicast
+ * address from the receive filter.
+ */
+struct rpmsg_kdrv_ethswitch_filter_del_mc_req {
+	struct rpmsg_kdrv_ethswitch_msg_header header;
+	struct rpmsg_kdrv_ethswitch_common_req_info info;
+	u8 mac_address[ETH_ALEN];
+	u16 vlan_id;
+	u32 flow_idx;
+} __packed;
+
+/**
+ * Response msg received as response to client's request to delete a multicas address to
+ * receive filter via @RPMSG_KDRV_TP_ETHSWITCH_FILTER_DEL_MAC.
+ * The @info.status field is @RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK on success.
+ */
+struct rpmsg_kdrv_ethswitch_filter_del_mc_resp {
+	struct rpmsg_kdrv_ethswitch_common_resp_info info;
+} __packed;
+
+/**
+ * struct rpmsg_kdrv_ethswitch_fw_version_info - fw version info
+ *
+ * @major: major
+ * @minor: minor
+ * @rev: revision
+ * @year:
+ * @month:
+ * @date: build date
+ * @commit_hash: commit hash
+ */
+struct rpmsg_kdrv_ethswitch_fw_version_info {
+#define RPMSG_KDRV_TP_ETHSWITCH_YEARLEN		(4)
+#define RPMSG_KDRV_TP_ETHSWITCH_MONTHLEN	(3)
+#define RPMSG_KDRV_TP_ETHSWITCH_DATELEN		(2)
+#define RPMSG_KDRV_TP_ETHSWITCH_COMMITSHALEN	(8)
+	u32 major;
+	u32 minor;
+	u32 rev;
+	char year[RPMSG_KDRV_TP_ETHSWITCH_YEARLEN];
+	char month[RPMSG_KDRV_TP_ETHSWITCH_MONTHLEN];
+	char date[RPMSG_KDRV_TP_ETHSWITCH_DATELEN];
+	char commit_hash[RPMSG_KDRV_TP_ETHSWITCH_COMMITSHALEN];
+} __packed;
+
+/*
+ * per-device data for ethswitch device
+ */
+/**
+ * struct rpmsg_kdrv_ethswitch_device_data - rpmsg_kdrv_device data
+ *
+ * @fw_ver: fw version info
+ * @permission_flags: permission enabled for each
+ *	enum @rpmsg_kdrv_ethswitch_message_type command
+ * @uart_connected: flag indicating if UART is connected
+ * @uart_id: UART ID used by firmware for log prints
+ *
+ * Provided as part of RPMSG KDRV device discovery protocol
+ */
+struct rpmsg_kdrv_ethswitch_device_data {
+	struct rpmsg_kdrv_ethswitch_fw_version_info fw_ver;
+	u32 permission_flags;
+	u32 uart_connected;
+	u32 uart_id;
+} __packed;
+
+#endif /* DRIVERS_RPMSG_KDRV_SHARED_RPMSG_KDRV_TRANSPORT_SWITCH_H_ */
diff -Naur --no-dereference a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
--- a/drivers/rtc/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/rtc/Kconfig	2024-01-28 14:01:31.252353813 -0500
@@ -584,6 +584,15 @@
 	  along with alarm. This driver supports the RTC driver for
 	  the TPS6586X RTC module.
 
+config RTC_DRV_TPS6594
+	tristate "TI TPS6594 RTC driver"
+	depends on MFD_TPS6594
+	default MFD_TPS6594
+	help
+	  TI Power Management IC TPS6594 supports RTC functionality
+	  along with alarm. This driver supports the RTC driver for
+	  the TPS6594 RTC module.
+
 config RTC_DRV_TPS65910
 	tristate "TI TPS65910 RTC driver"
 	depends on MFD_TPS65910
diff -Naur --no-dereference a/drivers/rtc/Makefile b/drivers/rtc/Makefile
--- a/drivers/rtc/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/rtc/Makefile	2024-01-28 14:01:31.252353813 -0500
@@ -176,6 +176,7 @@
 obj-$(CONFIG_RTC_DRV_TEST)	+= rtc-test.o
 obj-$(CONFIG_RTC_DRV_TI_K3)	+= rtc-ti-k3.o
 obj-$(CONFIG_RTC_DRV_TPS6586X)	+= rtc-tps6586x.o
+obj-$(CONFIG_RTC_DRV_TPS6594)	+= rtc-tps6594.o
 obj-$(CONFIG_RTC_DRV_TPS65910)	+= rtc-tps65910.o
 obj-$(CONFIG_RTC_DRV_TWL4030)	+= rtc-twl.o
 obj-$(CONFIG_RTC_DRV_V3020)	+= rtc-v3020.o
diff -Naur --no-dereference a/drivers/rtc/rtc-tps6594.c b/drivers/rtc/rtc-tps6594.c
--- a/drivers/rtc/rtc-tps6594.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/rtc/rtc-tps6594.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,473 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RTC driver for tps6594 PMIC
+ *
+ * Copyright (C) 2022 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#include <linux/bcd.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+
+#include <linux/mfd/tps6594.h>
+
+#define TPS6594_GET_TIME_ON TPS6594_BIT_GET_TIME
+#define TPS6594_GET_TIME_OFF 0
+#define TPS6594_IT_ALARM_ON TPS6594_BIT_IT_ALARM
+#define TPS6594_IT_ALARM_OFF 0
+#define TPS6594_AUTO_COMP_ON TPS6594_BIT_IT_ALARM
+
+/* Total number of RTC registers needed to set time*/
+#define NUM_TIME_REGS (TPS6594_REG_RTC_WEEKS - TPS6594_REG_RTC_SECONDS + 1)
+
+/* Total number of RTC alarm register */
+#define NUM_TIME_ALARM_REGS (NUM_TIME_REGS - 1)
+
+/* Total number of RTC registers needed to set compensation registers */
+#define NUM_COMP_REGS (TPS6594_REG_RTC_COMP_MSB - TPS6594_REG_RTC_COMP_LSB + 1)
+
+/*
+ * Min and max values supported with 'offset' interface (swapped sign)
+ * After conversion, the values does not exceed the range [-32767, 33767] which COMP_REG must
+ * conform to
+ */
+#define MIN_OFFSET (-277774)
+#define MAX_OFFSET (277774)
+
+/* Number of ticks per hour */
+#define TICKS_PER_HOUR (32768 * 3600)
+
+/* Multiplier for ppb conversions */
+#define PPB_MULT (1000000000LL)
+
+static int tps6594_rtc_alarm_irq_enable(struct device *dev,
+					unsigned int enabled)
+{
+	struct tps6594 *tps = dev_get_drvdata(dev->parent);
+	u8 val = 0;
+	int ret;
+
+	val = enabled ? TPS6594_IT_ALARM_ON : TPS6594_IT_ALARM_OFF;
+
+	ret = regmap_update_bits(tps->regmap, TPS6594_REG_RTC_INTERRUPTS,
+				 TPS6594_BIT_IT_ALARM, val);
+
+	return ret;
+}
+
+/* Pulse GET_TIME field of RTC_CTRL_1 to store a timestamp in shadow registers */
+static int tps6594_rtc_shadow_timestamp(struct device *dev, struct tps6594 *tps)
+{
+	int ret;
+
+	/*
+	 * Set GET_TIME to 0. This way, next time we set GET_TIME to 1 we are sure to store an
+	 * up-to-date timestamp
+	 */
+	ret = regmap_clear_bits(tps->regmap, TPS6594_REG_RTC_CTRL_1,
+				TPS6594_BIT_GET_TIME);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * Copy content of RTC registers to shadow registers or latches to read a coherent
+	 * timestamp
+	 */
+	return regmap_set_bits(tps->regmap, TPS6594_REG_RTC_CTRL_1,
+			       TPS6594_BIT_GET_TIME);
+}
+
+/*
+ * Gets current tps6594 RTC time and date parameters.
+ *
+ * The RTC's time/alarm representation is not what gmtime(3) requires
+ * Linux to use:
+ *
+ *  - Months are 1..12 vs Linux 0-11
+ *  - Years are 0..99 vs Linux 1900..N (we assume 21st century)
+ */
+static int tps6594_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	unsigned char rtc_data[NUM_TIME_REGS];
+	struct tps6594 *tps = dev_get_drvdata(dev->parent);
+	int ret;
+
+	/* Check if RTC is running. */
+	ret = regmap_test_bits(tps->regmap, TPS6594_REG_RTC_STATUS,
+			       TPS6594_BIT_RUN);
+	if (ret < 0)
+		return ret;
+	if (ret == 0)
+		return -EINVAL;
+
+	ret = tps6594_rtc_shadow_timestamp(dev, tps);
+	if (ret < 0)
+		return ret;
+
+	/* Read shadowed RTC registers */
+	ret = regmap_bulk_read(tps->regmap, TPS6594_REG_RTC_SECONDS, rtc_data,
+			       NUM_TIME_REGS);
+	if (ret < 0)
+		return ret;
+
+	tm->tm_sec = bcd2bin(rtc_data[0]);
+	tm->tm_min = bcd2bin(rtc_data[1]);
+	tm->tm_hour = bcd2bin(rtc_data[2]);
+	tm->tm_mday = bcd2bin(rtc_data[3]);
+	tm->tm_mon = bcd2bin(rtc_data[4]) - 1;
+	tm->tm_year = bcd2bin(rtc_data[5]) + 100;
+	tm->tm_wday = bcd2bin(rtc_data[6]);
+
+	return ret;
+}
+
+/*
+ * Sets current tps6594 RTC time and date parameters.
+ *
+ * The RTC's time/alarm representation is not what gmtime(3) requires
+ * Linux to use:
+ *
+ *  - Months are 1..12 vs Linux 0-11
+ *  - Years are 0..99 vs Linux 1900..N (we assume 21st century)
+ */
+static int tps6594_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	unsigned char rtc_data[NUM_TIME_REGS];
+	struct tps6594 *tps = dev_get_drvdata(dev->parent);
+	int ret;
+
+	rtc_data[0] = bin2bcd(tm->tm_sec);
+	rtc_data[1] = bin2bcd(tm->tm_min);
+	rtc_data[2] = bin2bcd(tm->tm_hour);
+	rtc_data[3] = bin2bcd(tm->tm_mday);
+	rtc_data[4] = bin2bcd(tm->tm_mon + 1);
+	rtc_data[5] = bin2bcd(tm->tm_year - 100);
+	rtc_data[6] = bin2bcd(tm->tm_wday);
+
+	/* Stop RTC while updating the RTC time registers */
+	ret = regmap_clear_bits(tps->regmap, TPS6594_REG_RTC_CTRL_1,
+				TPS6594_BIT_STOP_RTC);
+	if (ret < 0)
+		return ret;
+
+	/* Update all the time registers in one shot */
+	ret = regmap_bulk_write(tps->regmap, TPS6594_REG_RTC_SECONDS, rtc_data,
+				NUM_TIME_REGS);
+	if (ret < 0)
+		return ret;
+
+	/* Start back RTC */
+	return regmap_set_bits(tps->regmap, TPS6594_REG_RTC_CTRL_1,
+			       TPS6594_BIT_STOP_RTC);
+}
+
+/*
+ * Gets current tps6594 RTC alarm time.
+ */
+static int tps6594_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+	unsigned char alarm_data[NUM_TIME_ALARM_REGS];
+	u32 int_val;
+	struct tps6594 *tps = dev_get_drvdata(dev->parent);
+	int ret;
+
+	ret = regmap_bulk_read(tps->regmap, TPS6594_REG_ALARM_SECONDS,
+			       alarm_data, NUM_TIME_ALARM_REGS);
+	if (ret < 0)
+		return ret;
+
+	alm->time.tm_sec = bcd2bin(alarm_data[0]);
+	alm->time.tm_min = bcd2bin(alarm_data[1]);
+	alm->time.tm_hour = bcd2bin(alarm_data[2]);
+	alm->time.tm_mday = bcd2bin(alarm_data[3]);
+	alm->time.tm_mon = bcd2bin(alarm_data[4]) - 1;
+	alm->time.tm_year = bcd2bin(alarm_data[5]) + 100;
+
+	ret = regmap_read(tps->regmap, TPS6594_REG_RTC_INTERRUPTS, &int_val);
+	if (ret < 0)
+		return ret;
+
+	alm->enabled = int_val & TPS6594_BIT_IT_ALARM ? 1 : 0;
+
+	return ret;
+}
+
+static int tps6594_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+	unsigned char alarm_data[NUM_TIME_ALARM_REGS];
+	struct tps6594 *tps = dev_get_drvdata(dev->parent);
+	int ret;
+
+	/* Disable alarm irq before changing the alarm timestamp */
+	ret = tps6594_rtc_alarm_irq_enable(dev, 0);
+	if (ret)
+		return ret;
+
+	alarm_data[0] = bin2bcd(alm->time.tm_sec);
+	alarm_data[1] = bin2bcd(alm->time.tm_min);
+	alarm_data[2] = bin2bcd(alm->time.tm_hour);
+	alarm_data[3] = bin2bcd(alm->time.tm_mday);
+	alarm_data[4] = bin2bcd(alm->time.tm_mon + 1);
+	alarm_data[5] = bin2bcd(alm->time.tm_year - 100);
+
+	/* Update all the alarm registers in one shot */
+	ret = regmap_bulk_write(tps->regmap, TPS6594_REG_ALARM_SECONDS,
+				alarm_data, NUM_TIME_ALARM_REGS);
+	if (ret < 0)
+		return ret;
+
+	if (alm->enabled)
+		ret = tps6594_rtc_alarm_irq_enable(dev, 1);
+
+	return ret;
+}
+
+static int tps6594_rtc_set_calibration(struct device *dev, int calibration)
+{
+	unsigned char comp_data[NUM_COMP_REGS];
+	struct tps6594 *tps = dev_get_drvdata(dev->parent);
+	s16 value;
+	int ret;
+
+	/*
+	 * TPS6594 uses two's complement 16 bit value for compensation for RTC
+	 * crystal inaccuracies. One time every hour when seconds counter
+	 * increments from 0 to 1 compensation value will be added to internal
+	 * RTC counter value.
+	 *
+	 *
+	 * Valid range for compensation value: [-32767 .. 32767]
+	 */
+	if (calibration < -32767 || calibration > 32767) {
+		dev_err(dev, "RTC calibration value out of range: %d\n",
+			calibration);
+		return -EINVAL;
+	}
+
+	value = (s16)calibration;
+
+	comp_data[0] = (u16)value & 0xFF;
+	comp_data[1] = ((u16)value >> 8) & 0xFF;
+
+	/* Update all the compensation registers in one shot */
+	ret = regmap_bulk_write(tps->regmap, TPS6594_REG_RTC_COMP_LSB,
+				comp_data, NUM_COMP_REGS);
+	if (ret < 0)
+		return ret;
+
+	/* Enable automatic compensation */
+	return regmap_set_bits(tps->regmap, TPS6594_REG_RTC_CTRL_1,
+			       TPS6594_BIT_AUTO_COMP);
+}
+
+static int tps6594_rtc_get_calibration(struct device *dev, int *calibration)
+{
+	unsigned char comp_data[NUM_COMP_REGS];
+	struct tps6594 *tps = dev_get_drvdata(dev->parent);
+	unsigned int ctrl;
+	u16 value;
+	int ret;
+
+	ret = regmap_read(tps->regmap, TPS6594_REG_RTC_CTRL_1, &ctrl);
+	if (ret < 0)
+		return ret;
+
+	/* If automatic compensation is not enabled report back zero */
+	if (!(ctrl & TPS6594_BIT_AUTO_COMP)) {
+		*calibration = 0;
+		return 0;
+	}
+
+	ret = regmap_bulk_read(tps->regmap, TPS6594_REG_RTC_COMP_LSB, comp_data,
+			       NUM_COMP_REGS);
+	if (ret < 0)
+		return ret;
+
+	value = (u16)comp_data[0] | ((u16)comp_data[1] << 8);
+
+	*calibration = (s16)value;
+
+	return ret;
+}
+
+static int tps6594_rtc_read_offset(struct device *dev, long *offset)
+{
+	int calibration;
+	s64 tmp;
+	int ret;
+
+	ret = tps6594_rtc_get_calibration(dev, &calibration);
+	if (ret < 0)
+		return ret;
+
+	/* Convert from RTC calibration register format to ppb format */
+	tmp = calibration * (s64)PPB_MULT;
+	if (tmp < 0)
+		tmp -= TICKS_PER_HOUR / 2LL;
+	else
+		tmp += TICKS_PER_HOUR / 2LL;
+	tmp = div_s64(tmp, TICKS_PER_HOUR);
+
+	/*
+	 * Offset value operates in negative way, so swap sign.
+	 * See 8.3.10.5, (32768 - COMP_REG)
+	 */
+	*offset = (long)-tmp;
+
+	return ret;
+}
+
+static int tps6594_rtc_set_offset(struct device *dev, long offset)
+{
+	int calibration;
+	s64 tmp;
+
+	/* Make sure offset value is within supported range */
+	if (offset < MIN_OFFSET || offset > MAX_OFFSET)
+		return -ERANGE;
+
+	/* Convert from ppb format to RTC calibration register format */
+	tmp = offset * (s64)TICKS_PER_HOUR;
+	if (tmp < 0)
+		tmp -= PPB_MULT / 2LL;
+	else
+		tmp += PPB_MULT / 2LL;
+	tmp = div_s64(tmp, PPB_MULT);
+
+	/* Offset value operates in negative way, so swap sign */
+	calibration = (int)-tmp;
+
+	return tps6594_rtc_set_calibration(dev, calibration);
+}
+
+static irqreturn_t tps6594_rtc_interrupt(int irq, void *rtc)
+{
+	struct device *dev = rtc;
+	unsigned long events = 0;
+	struct tps6594 *tps = dev_get_drvdata(dev->parent);
+	struct rtc_device *rtc_dev = dev_get_drvdata(dev);
+	int ret;
+	u32 rtc_reg;
+
+	ret = regmap_read(tps->regmap, TPS6594_REG_RTC_STATUS, &rtc_reg);
+	if (ret)
+		return IRQ_NONE;
+
+	if (rtc_reg & TPS6594_BIT_ALARM)
+		events = RTC_IRQF | RTC_AF;
+
+	/* Notify RTC core on event */
+	rtc_update_irq(rtc_dev, 1, events);
+
+	return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops tps6594_rtc_ops = {
+	.read_time = tps6594_rtc_read_time,
+	.set_time = tps6594_rtc_set_time,
+	.read_alarm = tps6594_rtc_read_alarm,
+	.set_alarm = tps6594_rtc_set_alarm,
+	.alarm_irq_enable = tps6594_rtc_alarm_irq_enable,
+	.read_offset = tps6594_rtc_read_offset,
+	.set_offset = tps6594_rtc_set_offset,
+};
+
+static int tps6594_rtc_probe(struct platform_device *pdev)
+{
+	struct tps6594 *tps;
+	struct rtc_device *rtc;
+	int irq;
+	int ret;
+
+	tps = dev_get_drvdata(pdev->dev.parent);
+
+	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+	if (!rtc)
+		return -ENOMEM;
+
+	rtc = devm_rtc_allocate_device(&pdev->dev);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
+
+	/* Enable crystal oscillator */
+	ret = regmap_set_bits(tps->regmap, TPS6594_REG_RTC_CTRL_2,
+			      TPS6594_BIT_XTAL_EN);
+	if (ret < 0)
+		return ret;
+
+	ret = regmap_test_bits(tps->regmap, TPS6594_REG_RTC_STATUS,
+			       TPS6594_BIT_RUN);
+	if (ret < 0)
+		return ret;
+	/* RTC not running */
+	if (ret == 0) {
+		/* Start rtc */
+		ret = regmap_set_bits(tps->regmap, TPS6594_REG_RTC_CTRL_1,
+				      TPS6594_BIT_STOP_RTC);
+		if (ret < 0)
+			return ret;
+
+		mdelay(100);
+
+		/*
+		 * RTC should be running now. Check if this is the case.
+		 * If not it might be a missing oscillator.
+		 */
+		ret = regmap_test_bits(tps->regmap, TPS6594_REG_RTC_STATUS,
+				       TPS6594_BIT_RUN);
+		if (ret < 0)
+			return ret;
+		if (ret == 0)
+			return -ENODEV;
+
+		/* Stop RTC until first call to `tps6594_rtc_set_time */
+		ret = regmap_clear_bits(tps->regmap, TPS6594_REG_RTC_CTRL_1,
+					TPS6594_BIT_STOP_RTC);
+		if (ret < 0)
+			return ret;
+	}
+
+	platform_set_drvdata(pdev, rtc);
+
+	irq = platform_get_irq_byname(pdev, TPS6594_IRQ_NAME_ALARM);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "Failed to get irq\n");
+		return irq;
+	}
+
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+					tps6594_rtc_interrupt, IRQF_ONESHOT,
+					TPS6594_IRQ_NAME_ALARM, &pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "Failed to request_threaded_irq\n");
+		return ret;
+	}
+
+	rtc->ops = &tps6594_rtc_ops;
+	rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+	rtc->range_max = RTC_TIMESTAMP_END_2099;
+
+	return devm_rtc_register_device(rtc);
+}
+
+static struct platform_driver tps6594_rtc_driver = {
+	.probe		= tps6594_rtc_probe,
+	.driver		= {
+		.name	= "tps6594-rtc",
+	},
+};
+
+module_platform_driver(tps6594_rtc_driver);
+
+MODULE_ALIAS("platform:tps6594-rtc");
+MODULE_AUTHOR("Esteban Blanc <eblanc@baylibre.com>");
+MODULE_DESCRIPTION("TPS6594 RTC driver");
+MODULE_LICENSE("GPL");
diff -Naur --no-dereference a/drivers/soc/ti/k3-ringacc.c b/drivers/soc/ti/k3-ringacc.c
--- a/drivers/soc/ti/k3-ringacc.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/soc/ti/k3-ringacc.c	2024-01-28 14:01:31.252353813 -0500
@@ -1359,7 +1359,6 @@
 	dev->msi.domain = of_msi_get_domain(dev, dev->of_node,
 					    DOMAIN_BUS_TI_SCI_INTA_MSI);
 	if (!dev->msi.domain) {
-		dev_err(dev, "Failed to get MSI domain\n");
 		return -EPROBE_DEFER;
 	}
 
diff -Naur --no-dereference a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c
--- a/drivers/soc/ti/k3-socinfo.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/soc/ti/k3-socinfo.c	2024-01-28 14:01:31.252353813 -0500
@@ -43,6 +43,10 @@
 	{ 0xBB38, "AM64X" },
 	{ 0xBB75, "J721S2"},
 	{ 0xBB7E, "AM62X" },
+	{ 0xBB8D, "AM62AX" },
+	{ 0xBB80, "J784S4" },
+	{ 0xBB9D, "AM62PX" },
+	{ 0xBBA0, "J722S" },
 };
 
 static int
diff -Naur --no-dereference a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c
--- a/drivers/soc/ti/pruss.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/soc/ti/pruss.c	2024-01-28 14:01:31.252353813 -0500
@@ -6,6 +6,7 @@
  * Author(s):
  *	Suman Anna <s-anna@ti.com>
  *	Andrew F. Davis <afd@ti.com>
+ *	Tero Kristo <t-kristo@ti.com>
  */
 
 #include <linux/clk-provider.h>
@@ -18,7 +19,9 @@
 #include <linux/pm_runtime.h>
 #include <linux/pruss_driver.h>
 #include <linux/regmap.h>
+#include <linux/remoteproc.h>
 #include <linux/slab.h>
+#include "pruss.h"
 
 /**
  * struct pruss_private_data - PRUSS driver private data
@@ -30,6 +33,257 @@
 	bool has_core_mux_clock;
 };
 
+/**
+ * pruss_get() - get the pruss for a given PRU remoteproc
+ * @rproc: remoteproc handle of a PRU instance
+ *
+ * Finds the parent pruss device for a PRU given the @rproc handle of the
+ * PRU remote processor. This function increments the pruss device's refcount,
+ * so always use pruss_put() to decrement it back once pruss isn't needed
+ * anymore.
+ *
+ * This API doesn't check if @rproc is valid or not. It is expected the caller
+ * will have done a pru_rproc_get() on @rproc, before calling this API to make
+ * sure that @rproc is valid.
+ *
+ * Return: pruss handle on success, and an ERR_PTR on failure using one
+ * of the following error values
+ *    -EINVAL if invalid parameter
+ *    -ENODEV if PRU device or PRUSS device is not found
+ */
+struct pruss *pruss_get(struct rproc *rproc)
+{
+	struct pruss *pruss;
+	struct device *dev;
+	struct platform_device *ppdev;
+
+	if (IS_ERR_OR_NULL(rproc))
+		return ERR_PTR(-EINVAL);
+
+	dev = &rproc->dev;
+
+	/* make sure it is PRU rproc */
+	if (!dev->parent || !is_pru_rproc(dev->parent))
+		return ERR_PTR(-ENODEV);
+
+	ppdev = to_platform_device(dev->parent->parent);
+	pruss = platform_get_drvdata(ppdev);
+	if (!pruss)
+		return ERR_PTR(-ENODEV);
+
+	get_device(pruss->dev);
+
+	return pruss;
+}
+EXPORT_SYMBOL_GPL(pruss_get);
+
+/**
+ * pruss_put() - decrement pruss device's usecount
+ * @pruss: pruss handle
+ *
+ * Complimentary function for pruss_get(). Needs to be called
+ * after the PRUSS is used, and only if the pruss_get() succeeds.
+ */
+void pruss_put(struct pruss *pruss)
+{
+	if (IS_ERR_OR_NULL(pruss))
+		return;
+
+	put_device(pruss->dev);
+}
+EXPORT_SYMBOL_GPL(pruss_put);
+
+/**
+ * pruss_request_mem_region() - request a memory resource
+ * @pruss: the pruss instance
+ * @mem_id: the memory resource id
+ * @region: pointer to memory region structure to be filled in
+ *
+ * This function allows a client driver to request a memory resource,
+ * and if successful, will let the client driver own the particular
+ * memory region until released using the pruss_release_mem_region()
+ * API.
+ *
+ * Return: 0 if requested memory region is available (in such case pointer to
+ * memory region is returned via @region), an error otherwise
+ */
+int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id,
+			     struct pruss_mem_region *region)
+{
+	if (!pruss || !region || mem_id >= PRUSS_MEM_MAX)
+		return -EINVAL;
+
+	mutex_lock(&pruss->lock);
+
+	if (pruss->mem_in_use[mem_id]) {
+		mutex_unlock(&pruss->lock);
+		return -EBUSY;
+	}
+
+	*region = pruss->mem_regions[mem_id];
+	pruss->mem_in_use[mem_id] = region;
+
+	mutex_unlock(&pruss->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pruss_request_mem_region);
+
+/**
+ * pruss_release_mem_region() - release a memory resource
+ * @pruss: the pruss instance
+ * @region: the memory region to release
+ *
+ * This function is the complimentary function to
+ * pruss_request_mem_region(), and allows the client drivers to
+ * release back a memory resource.
+ *
+ * Return: 0 on success, an error code otherwise
+ */
+int pruss_release_mem_region(struct pruss *pruss,
+			     struct pruss_mem_region *region)
+{
+	int id;
+
+	if (!pruss || !region)
+		return -EINVAL;
+
+	mutex_lock(&pruss->lock);
+
+	/* find out the memory region being released */
+	for (id = 0; id < PRUSS_MEM_MAX; id++) {
+		if (pruss->mem_in_use[id] == region)
+			break;
+	}
+
+	if (id == PRUSS_MEM_MAX) {
+		mutex_unlock(&pruss->lock);
+		return -EINVAL;
+	}
+
+	pruss->mem_in_use[id] = NULL;
+
+	mutex_unlock(&pruss->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pruss_release_mem_region);
+
+/**
+ * pruss_cfg_get_gpmux() - get the current GPMUX value for a PRU device
+ * @pruss: pruss instance
+ * @pru_id: PRU identifier (0-1)
+ * @mux: pointer to store the current mux value into
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int pruss_cfg_get_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 *mux)
+{
+	int ret;
+	u32 val;
+
+	if (pru_id >= PRUSS_NUM_PRUS || !mux)
+		return -EINVAL;
+
+	ret = pruss_cfg_read(pruss, PRUSS_CFG_GPCFG(pru_id), &val);
+	if (!ret)
+		*mux = (u8)((val & PRUSS_GPCFG_PRU_MUX_SEL_MASK) >>
+			    PRUSS_GPCFG_PRU_MUX_SEL_SHIFT);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pruss_cfg_get_gpmux);
+
+/**
+ * pruss_cfg_set_gpmux() - set the GPMUX value for a PRU device
+ * @pruss: pruss instance
+ * @pru_id: PRU identifier (0-1)
+ * @mux: new mux value for PRU
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux)
+{
+	if (mux >= PRUSS_GP_MUX_SEL_MAX ||
+	    pru_id >= PRUSS_NUM_PRUS)
+		return -EINVAL;
+
+	return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id),
+				PRUSS_GPCFG_PRU_MUX_SEL_MASK,
+				(u32)mux << PRUSS_GPCFG_PRU_MUX_SEL_SHIFT);
+}
+EXPORT_SYMBOL_GPL(pruss_cfg_set_gpmux);
+
+/**
+ * pruss_cfg_gpimode() - set the GPI mode of the PRU
+ * @pruss: the pruss instance handle
+ * @pru_id: id of the PRU core within the PRUSS
+ * @mode: GPI mode to set
+ *
+ * Sets the GPI mode for a given PRU by programming the
+ * corresponding PRUSS_CFG_GPCFGx register
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int pruss_cfg_gpimode(struct pruss *pruss, enum pruss_pru_id pru_id,
+		      enum pruss_gpi_mode mode)
+{
+	if (pru_id >= PRUSS_NUM_PRUS || mode >= PRUSS_GPI_MODE_MAX)
+		return -EINVAL;
+
+	return pruss_cfg_update(pruss, PRUSS_CFG_GPCFG(pru_id),
+				PRUSS_GPCFG_PRU_GPI_MODE_MASK,
+				mode << PRUSS_GPCFG_PRU_GPI_MODE_SHIFT);
+}
+EXPORT_SYMBOL_GPL(pruss_cfg_gpimode);
+
+/**
+ * pruss_cfg_miirt_enable() - Enable/disable MII RT Events
+ * @pruss: the pruss instance
+ * @enable: enable/disable
+ *
+ * Enable/disable the MII RT Events for the PRUSS.
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int pruss_cfg_miirt_enable(struct pruss *pruss, bool enable)
+{
+	u32 set = enable ? PRUSS_MII_RT_EVENT_EN : 0;
+
+	return pruss_cfg_update(pruss, PRUSS_CFG_MII_RT,
+				PRUSS_MII_RT_EVENT_EN, set);
+}
+EXPORT_SYMBOL_GPL(pruss_cfg_miirt_enable);
+
+/**
+ * pruss_cfg_xfr_enable() - Enable/disable XIN XOUT shift functionality
+ * @pruss: the pruss instance
+ * @pru_type: PRU core type identifier
+ * @enable: enable/disable
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+int pruss_cfg_xfr_enable(struct pruss *pruss, enum pru_type pru_type,
+			 bool enable)
+{
+	u32 mask, set;
+
+	switch (pru_type) {
+	case PRU_TYPE_PRU:
+		mask = PRUSS_SPP_XFER_SHIFT_EN;
+		break;
+	case PRU_TYPE_RTU:
+		mask = PRUSS_SPP_RTU_XFR_SHIFT_EN;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	set = enable ? mask : 0;
+
+	return pruss_cfg_update(pruss, PRUSS_CFG_SPP, mask, set);
+}
+EXPORT_SYMBOL_GPL(pruss_cfg_xfr_enable);
+
 static void pruss_of_free_clk_provider(void *data)
 {
 	struct device_node *clk_mux_np = data;
@@ -232,6 +486,7 @@
 		return -ENOMEM;
 
 	pruss->dev = dev;
+	mutex_init(&pruss->lock);
 
 	child = of_get_child_by_name(np, "memories");
 	if (!child) {
diff -Naur --no-dereference a/drivers/soc/ti/pruss.h b/drivers/soc/ti/pruss.h
--- a/drivers/soc/ti/pruss.h	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/soc/ti/pruss.h	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * PRU-ICSS Subsystem user interfaces
+ *
+ * Copyright (C) 2015-2023 Texas Instruments Incorporated - http://www.ti.com
+ *	MD Danish Anwar <danishanwar@ti.com>
+ */
+
+#ifndef _SOC_TI_PRUSS_H_
+#define _SOC_TI_PRUSS_H_
+
+#include <linux/bits.h>
+#include <linux/regmap.h>
+
+/*
+ * PRU_ICSS_CFG registers
+ * SYSCFG, ISRP, ISP, IESP, IECP, SCRP applicable on AMxxxx devices only
+ */
+#define PRUSS_CFG_REVID         0x00
+#define PRUSS_CFG_SYSCFG        0x04
+#define PRUSS_CFG_GPCFG(x)      (0x08 + (x) * 4)
+#define PRUSS_CFG_CGR           0x10
+#define PRUSS_CFG_ISRP          0x14
+#define PRUSS_CFG_ISP           0x18
+#define PRUSS_CFG_IESP          0x1C
+#define PRUSS_CFG_IECP          0x20
+#define PRUSS_CFG_SCRP          0x24
+#define PRUSS_CFG_PMAO          0x28
+#define PRUSS_CFG_MII_RT        0x2C
+#define PRUSS_CFG_IEPCLK        0x30
+#define PRUSS_CFG_SPP           0x34
+#define PRUSS_CFG_PIN_MX        0x40
+
+/* PRUSS_GPCFG register bits */
+#define PRUSS_GPCFG_PRU_GPI_MODE_MASK           GENMASK(1, 0)
+#define PRUSS_GPCFG_PRU_GPI_MODE_SHIFT          0
+
+#define PRUSS_GPCFG_PRU_MUX_SEL_SHIFT           26
+#define PRUSS_GPCFG_PRU_MUX_SEL_MASK            GENMASK(29, 26)
+
+/* PRUSS_MII_RT register bits */
+#define PRUSS_MII_RT_EVENT_EN                   BIT(0)
+
+/* PRUSS_SPP register bits */
+#define PRUSS_SPP_XFER_SHIFT_EN                 BIT(1)
+#define PRUSS_SPP_PRU1_PAD_HP_EN                BIT(0)
+#define PRUSS_SPP_RTU_XFR_SHIFT_EN              BIT(3)
+
+/**
+ * pruss_cfg_read() - read a PRUSS CFG sub-module register
+ * @pruss: the pruss instance handle
+ * @reg: register offset within the CFG sub-module
+ * @val: pointer to return the value in
+ *
+ * Reads a given register within the PRUSS CFG sub-module and
+ * returns it through the passed-in @val pointer
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+static int pruss_cfg_read(struct pruss *pruss, unsigned int reg, unsigned int *val)
+{
+	if (IS_ERR_OR_NULL(pruss))
+		return -EINVAL;
+
+	return regmap_read(pruss->cfg_regmap, reg, val);
+}
+
+/**
+ * pruss_cfg_update() - configure a PRUSS CFG sub-module register
+ * @pruss: the pruss instance handle
+ * @reg: register offset within the CFG sub-module
+ * @mask: bit mask to use for programming the @val
+ * @val: value to write
+ *
+ * Programs a given register within the PRUSS CFG sub-module
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
+static int pruss_cfg_update(struct pruss *pruss, unsigned int reg,
+			    unsigned int mask, unsigned int val)
+{
+	if (IS_ERR_OR_NULL(pruss))
+		return -EINVAL;
+
+	return regmap_update_bits(pruss->cfg_regmap, reg, mask, val);
+}
+
+#endif  /* _SOC_TI_PRUSS_H_ */
diff -Naur --no-dereference a/drivers/spi/spi.c b/drivers/spi/spi.c
--- a/drivers/spi/spi.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/spi/spi.c	2024-01-28 14:01:31.252353813 -0500
@@ -360,6 +360,18 @@
 }
 EXPORT_SYMBOL_GPL(spi_get_device_id);
 
+const void *spi_get_device_match_data(const struct spi_device *sdev)
+{
+	const void *match;
+
+	match = device_get_match_data(&sdev->dev);
+	if (match)
+		return match;
+
+	return (const void *)spi_get_device_id(sdev)->driver_data;
+}
+EXPORT_SYMBOL_GPL(spi_get_device_match_data);
+
 static int spi_match_device(struct device *dev, struct device_driver *drv)
 {
 	const struct spi_device	*spi = to_spi_device(dev);
@@ -592,7 +604,7 @@
 	}
 
 	dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->controller->dev),
-		     spi->chip_select);
+		     spi_get_chipselect(spi, 0));
 }
 
 static int spi_dev_check(struct device *dev, void *data)
@@ -601,7 +613,7 @@
 	struct spi_device *new_spi = data;
 
 	if (spi->controller == new_spi->controller &&
-	    spi->chip_select == new_spi->chip_select)
+	    spi_get_chipselect(spi, 0) == spi_get_chipselect(new_spi, 0))
 		return -EBUSY;
 	return 0;
 }
@@ -626,7 +638,7 @@
 	status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check);
 	if (status) {
 		dev_err(dev, "chipselect %d already in use\n",
-				spi->chip_select);
+				spi_get_chipselect(spi, 0));
 		return status;
 	}
 
@@ -637,7 +649,7 @@
 	}
 
 	if (ctlr->cs_gpiods)
-		spi->cs_gpiod = ctlr->cs_gpiods[spi->chip_select];
+		spi_set_csgpiod(spi, 0, ctlr->cs_gpiods[spi_get_chipselect(spi, 0)]);
 
 	/*
 	 * Drivers may modify this initial i/o setup, but will
@@ -680,8 +692,8 @@
 	int status;
 
 	/* Chipselects are numbered 0..max; validate. */
-	if (spi->chip_select >= ctlr->num_chipselect) {
-		dev_err(dev, "cs%d >= max %d\n", spi->chip_select,
+	if (spi_get_chipselect(spi, 0) >= ctlr->num_chipselect) {
+		dev_err(dev, "cs%d >= max %d\n", spi_get_chipselect(spi, 0),
 			ctlr->num_chipselect);
 		return -EINVAL;
 	}
@@ -702,8 +714,8 @@
 	struct device *dev = ctlr->dev.parent;
 
 	/* Chipselects are numbered 0..max; validate. */
-	if (spi->chip_select >= ctlr->num_chipselect) {
-		dev_err(dev, "cs%d >= max %d\n", spi->chip_select,
+	if (spi_get_chipselect(spi, 0) >= ctlr->num_chipselect) {
+		dev_err(dev, "cs%d >= max %d\n", spi_get_chipselect(spi, 0),
 			ctlr->num_chipselect);
 		return -EINVAL;
 	}
@@ -749,7 +761,7 @@
 
 	WARN_ON(strlen(chip->modalias) >= sizeof(proxy->modalias));
 
-	proxy->chip_select = chip->chip_select;
+	spi_set_chipselect(proxy, 0, chip->chip_select);
 	proxy->max_speed_hz = chip->max_speed_hz;
 	proxy->mode = chip->mode;
 	proxy->irq = chip->irq;
@@ -958,24 +970,23 @@
 	 * Avoid calling into the driver (or doing delays) if the chip select
 	 * isn't actually changing from the last time this was called.
 	 */
-	if (!force && ((enable && spi->controller->last_cs == spi->chip_select) ||
-				(!enable && spi->controller->last_cs != spi->chip_select)) &&
+	if (!force && ((enable && spi->controller->last_cs == spi_get_chipselect(spi, 0)) ||
+		       (!enable && spi->controller->last_cs != spi_get_chipselect(spi, 0))) &&
 	    (spi->controller->last_cs_mode_high == (spi->mode & SPI_CS_HIGH)))
 		return;
 
 	trace_spi_set_cs(spi, activate);
 
-	spi->controller->last_cs = enable ? spi->chip_select : -1;
+	spi->controller->last_cs = enable ? spi_get_chipselect(spi, 0) : -1;
 	spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH;
 
-	if ((spi->cs_gpiod || !spi->controller->set_cs_timing) && !activate) {
+	if ((spi_get_csgpiod(spi, 0) || !spi->controller->set_cs_timing) && !activate)
 		spi_delay_exec(&spi->cs_hold, NULL);
-	}
 
 	if (spi->mode & SPI_CS_HIGH)
 		enable = !enable;
 
-	if (spi->cs_gpiod) {
+	if (spi_get_csgpiod(spi, 0)) {
 		if (!(spi->mode & SPI_NO_CS)) {
 			/*
 			 * Historically ACPI has no means of the GPIO polarity and
@@ -988,10 +999,10 @@
 			 * into account.
 			 */
 			if (has_acpi_companion(&spi->dev))
-				gpiod_set_value_cansleep(spi->cs_gpiod, !enable);
+				gpiod_set_value_cansleep(spi_get_csgpiod(spi, 0), !enable);
 			else
 				/* Polarity handled by GPIO library */
-				gpiod_set_value_cansleep(spi->cs_gpiod, activate);
+				gpiod_set_value_cansleep(spi_get_csgpiod(spi, 0), activate);
 		}
 		/* Some SPI masters need both GPIO CS & slave_select */
 		if ((spi->controller->flags & SPI_MASTER_GPIO_SS) &&
@@ -1001,7 +1012,7 @@
 		spi->controller->set_cs(spi, !enable);
 	}
 
-	if (spi->cs_gpiod || !spi->controller->set_cs_timing) {
+	if (spi_get_csgpiod(spi, 0) || !spi->controller->set_cs_timing) {
 		if (activate)
 			spi_delay_exec(&spi->cs_setup, NULL);
 		else
@@ -2291,7 +2302,7 @@
 			nc, rc);
 		return rc;
 	}
-	spi->chip_select = value;
+	spi_set_chipselect(spi, 0, value);
 
 	/* Device speed */
 	if (!of_property_read_u32(nc, "spi-max-frequency", &value))
@@ -2405,7 +2416,7 @@
 	strscpy(ancillary->modalias, "dummy", sizeof(ancillary->modalias));
 
 	/* Use provided chip-select for ancillary device */
-	ancillary->chip_select = chip_select;
+	spi_set_chipselect(ancillary, 0, chip_select);
 
 	/* Take over SPI mode/speed from SPI main device */
 	ancillary->max_speed_hz = spi->max_speed_hz;
@@ -2652,7 +2663,7 @@
 	spi->mode		|= lookup.mode;
 	spi->irq		= lookup.irq;
 	spi->bits_per_word	= lookup.bits_per_word;
-	spi->chip_select	= lookup.chip_select;
+	spi_set_chipselect(spi, 0, lookup.chip_select);
 
 	return spi;
 }
@@ -3612,6 +3623,37 @@
 }
 
 /**
+ * spi_set_cs_timing - configure CS setup, hold, and inactive delays
+ * @spi: the device that requires specific CS timing configuration
+ *
+ * Return: zero on success, else a negative error code.
+ */
+static int spi_set_cs_timing(struct spi_device *spi)
+{
+	struct device *parent = spi->controller->dev.parent;
+	int status = 0;
+
+	if (spi->controller->set_cs_timing && !spi_get_csgpiod(spi, 0)) {
+		if (spi->controller->auto_runtime_pm) {
+			status = pm_runtime_get_sync(parent);
+			if (status < 0) {
+				pm_runtime_put_noidle(parent);
+				dev_err(&spi->controller->dev, "Failed to power device: %d\n",
+					status);
+				return status;
+			}
+
+			status = spi->controller->set_cs_timing(spi);
+			pm_runtime_mark_last_busy(parent);
+			pm_runtime_put_autosuspend(parent);
+		} else {
+			status = spi->controller->set_cs_timing(spi);
+		}
+	}
+	return status;
+}
+
+/**
  * spi_setup - setup SPI mode and clock rate
  * @spi: the device whose settings are being modified
  * Context: can sleep, and no requests are queued to the device
@@ -3707,6 +3749,12 @@
 		}
 	}
 
+	status = spi_set_cs_timing(spi);
+	if (status) {
+		mutex_unlock(&spi->controller->io_mutex);
+		return status;
+	}
+
 	if (spi->controller->auto_runtime_pm && spi->controller->set_cs) {
 		status = pm_runtime_resume_and_get(spi->controller->dev.parent);
 		if (status < 0) {
@@ -3790,7 +3838,7 @@
 	 * cs_change is set for each transfer.
 	 */
 	if ((spi->mode & SPI_CS_WORD) && (!(ctlr->mode_bits & SPI_CS_WORD) ||
-					  spi->cs_gpiod)) {
+					  spi_get_csgpiod(spi, 0))) {
 		size_t maxsize;
 		int ret;
 
diff -Naur --no-dereference a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
--- a/drivers/spi/spi-cadence-quadspi.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/spi/spi-cadence-quadspi.c	2024-01-28 14:01:31.252353813 -0500
@@ -48,15 +48,30 @@
 
 struct cqspi_st;
 
+struct phy_setting {
+	u8		rx;
+	u8		tx;
+	u8		read_delay;
+};
+
 struct cqspi_flash_pdata {
-	struct cqspi_st	*cqspi;
-	u32		clk_rate;
-	u32		read_delay;
-	u32		tshsl_ns;
-	u32		tsd2d_ns;
-	u32		tchsh_ns;
-	u32		tslch_ns;
-	u8		cs;
+	struct cqspi_st		*cqspi;
+	u32			clk_rate;
+	u32			read_delay;
+	u32			tshsl_ns;
+	u32			tsd2d_ns;
+	u32			tchsh_ns;
+	u32			tslch_ns;
+	u8			inst_width;
+	u8			addr_width;
+	u8			data_width;
+	bool			dtr;
+	u8			cs;
+	bool			use_phy;
+	struct phy_setting	phy_setting;
+	struct spi_mem_op	phy_read_op;
+	u32			phy_tx_start;
+	u32			phy_tx_end;
 };
 
 struct cqspi_st {
@@ -84,6 +99,7 @@
 	u32			trigger_address;
 	u32			wr_delay;
 	bool			use_direct_mode;
+	bool			use_direct_mode_wr;
 	struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT];
 	bool			use_dma_read;
 	u32			pd_dev_id;
@@ -103,6 +119,9 @@
 #define CQSPI_TIMEOUT_MS			500
 #define CQSPI_READ_TIMEOUT_MS			10
 
+/* Runtime_pm autosuspend delay */
+#define CQSPI_AUTOSUSPEND_TIMEOUT		2000
+
 #define CQSPI_DUMMY_CLKS_PER_BYTE		8
 #define CQSPI_DUMMY_BYTES_MAX			4
 #define CQSPI_DUMMY_CLKS_MAX			31
@@ -112,12 +131,14 @@
 /* Register map */
 #define CQSPI_REG_CONFIG			0x00
 #define CQSPI_REG_CONFIG_ENABLE_MASK		BIT(0)
+#define CQSPI_REG_CONFIG_PHY_EN			BIT(3)
 #define CQSPI_REG_CONFIG_ENB_DIR_ACC_CTRL	BIT(7)
 #define CQSPI_REG_CONFIG_DECODE_MASK		BIT(9)
 #define CQSPI_REG_CONFIG_CHIPSELECT_LSB		10
 #define CQSPI_REG_CONFIG_DMA_MASK		BIT(15)
 #define CQSPI_REG_CONFIG_BAUD_LSB		19
 #define CQSPI_REG_CONFIG_DTR_PROTO		BIT(24)
+#define CQSPI_REG_CONFIG_PHY_PIPELINE		BIT(25)
 #define CQSPI_REG_CONFIG_DUAL_OPCODE		BIT(30)
 #define CQSPI_REG_CONFIG_IDLE_LSB		31
 #define CQSPI_REG_CONFIG_CHIPSELECT_MASK	0xF
@@ -154,6 +175,7 @@
 #define CQSPI_REG_READCAPTURE_BYPASS_LSB	0
 #define CQSPI_REG_READCAPTURE_DELAY_LSB		1
 #define CQSPI_REG_READCAPTURE_DELAY_MASK	0xF
+#define CQSPI_REG_READCAPTURE_DQS_LSB		8
 
 #define CQSPI_REG_SIZE				0x14
 #define CQSPI_REG_SIZE_ADDRESS_LSB		0
@@ -232,6 +254,13 @@
 #define CQSPI_REG_POLLING_STATUS		0xB0
 #define CQSPI_REG_POLLING_STATUS_DUMMY_LSB	16
 
+#define CQSPI_REG_PHY_CONFIG			0xB4
+#define CQSPI_REG_PHY_CONFIG_RX_DEL_LSB		0
+#define CQSPI_REG_PHY_CONFIG_RX_DEL_MASK	0x7F
+#define CQSPI_REG_PHY_CONFIG_TX_DEL_LSB		16
+#define CQSPI_REG_PHY_CONFIG_TX_DEL_MASK	0x7F
+#define CQSPI_REG_PHY_CONFIG_RESYNC		BIT(31)
+
 #define CQSPI_REG_OP_EXT_LOWER			0xE0
 #define CQSPI_REG_OP_EXT_READ_LSB		24
 #define CQSPI_REG_OP_EXT_WRITE_LSB		16
@@ -277,6 +306,578 @@
 
 #define CQSPI_REG_VERSAL_DMA_VAL		0x602
 
+#define CQSPI_PHY_INIT_RD		1
+#define CQSPI_PHY_MAX_RD		4
+#define CQSPI_PHY_MAX_RX		63
+#define CQSPI_PHY_MAX_TX		63
+#define CQSPI_PHY_LOW_RX_BOUND		15
+#define CQSPI_PHY_HIGH_RX_BOUND		25
+#define CQSPI_PHY_LOW_TX_BOUND		32
+#define CQSPI_PHY_HIGH_TX_BOUND		48
+#define CQSPI_PHY_TX_LOOKUP_LOW_BOUND	24
+#define CQSPI_PHY_TX_LOOKUP_HIGH_BOUND	38
+
+#define CQSPI_PHY_DEFAULT_TEMP		45
+#define CQSPI_PHY_MIN_TEMP		-45
+#define CQSPI_PHY_MAX_TEMP		130
+#define CQSPI_PHY_MID_TEMP		(CQSPI_PHY_MIN_TEMP +	\
+					 ((CQSPI_PHY_MAX_TEMP - CQSPI_PHY_MIN_TEMP) / 2))
+
+static const u8 phy_tuning_pattern[] = {
+0xFE, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xFE, 0xFE, 0x01, 0x01,
+0x01, 0x01, 0x00, 0x00, 0xFE, 0xFE, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+0x00, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFE, 0xFF, 0x01,
+0x01, 0x01, 0x01, 0x01, 0xFE, 0x00, 0xFE, 0xFE, 0x01, 0x01, 0x01, 0x01, 0xFE,
+0x00, 0xFE, 0xFE, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0xFE, 0xFE,
+0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0xFE, 0xFE, 0xFF, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x00, 0xFE, 0xFE, 0xFE, 0x01, 0x01, 0x01, 0x01, 0x00, 0xFE, 0xFE, 0xFE,
+0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
+0xFF, 0x00, 0xFE, 0xFE, 0xFE, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFE, 0xFE,
+0xFE, 0xFE, 0x01, 0x01, 0x01, 0x01, 0xFE, 0xFE, 0xFE, 0xFE, 0x01,
+};
+
+static void cqspi_set_tx_dll(void __iomem *reg_base, u8 dll)
+{
+	unsigned int reg;
+
+	reg = readl(reg_base + CQSPI_REG_PHY_CONFIG);
+	reg &= ~(CQSPI_REG_PHY_CONFIG_TX_DEL_MASK <<
+		CQSPI_REG_PHY_CONFIG_TX_DEL_LSB);
+	reg |= (dll & CQSPI_REG_PHY_CONFIG_TX_DEL_MASK) <<
+		CQSPI_REG_PHY_CONFIG_TX_DEL_LSB;
+	reg |= CQSPI_REG_PHY_CONFIG_RESYNC;
+	writel(reg, reg_base + CQSPI_REG_PHY_CONFIG);
+}
+
+static void cqspi_set_rx_dll(void __iomem *reg_base, u8 dll)
+{
+	unsigned int reg;
+
+	reg = readl(reg_base + CQSPI_REG_PHY_CONFIG);
+	reg &= ~(CQSPI_REG_PHY_CONFIG_RX_DEL_MASK <<
+		CQSPI_REG_PHY_CONFIG_RX_DEL_LSB);
+	reg |= (dll & CQSPI_REG_PHY_CONFIG_RX_DEL_MASK) <<
+		CQSPI_REG_PHY_CONFIG_RX_DEL_LSB;
+	reg |= CQSPI_REG_PHY_CONFIG_RESYNC;
+	writel(reg, reg_base + CQSPI_REG_PHY_CONFIG);
+}
+
+/* TODO: Figure out how to get the temperature here. */
+static int cqspi_get_temp(int *temp)
+{
+	return -EOPNOTSUPP;
+}
+
+static void cqspi_phy_apply_setting(struct cqspi_flash_pdata *f_pdata,
+				    struct phy_setting *phy)
+{
+	struct cqspi_st *cqspi = f_pdata->cqspi;
+
+	cqspi_set_rx_dll(cqspi->iobase, phy->rx);
+	cqspi_set_tx_dll(cqspi->iobase, phy->tx);
+	f_pdata->phy_setting.read_delay = phy->read_delay;
+}
+
+static int cqspi_phy_check_pattern(struct cqspi_flash_pdata *f_pdata,
+				   struct spi_mem *mem)
+{
+	struct spi_mem_op op = f_pdata->phy_read_op;
+	u8 *read_data;
+	unsigned int size = sizeof(phy_tuning_pattern);
+	int ret;
+
+	read_data = kmalloc(size, GFP_KERNEL);
+	if (!read_data)
+		return -ENOMEM;
+
+	op.data.buf.in = read_data;
+	op.data.nbytes = size;
+
+	ret = spi_mem_exec_op(mem, &op);
+	if (ret)
+		goto out;
+
+	if (memcmp(read_data, phy_tuning_pattern,
+		   ARRAY_SIZE(phy_tuning_pattern))) {
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	ret = 0;
+
+out:
+	kfree(read_data);
+	return ret;
+}
+
+static int cqspi_find_rx_low(struct cqspi_flash_pdata *f_pdata,
+			     struct spi_mem *mem, struct phy_setting *phy)
+{
+	struct device *dev = &f_pdata->cqspi->pdev->dev;
+	int ret;
+
+	do {
+		phy->rx = 0;
+		do {
+			cqspi_phy_apply_setting(f_pdata, phy);
+			ret = cqspi_phy_check_pattern(f_pdata, mem);
+			if (!ret)
+				return 0;
+
+			phy->rx++;
+		} while (phy->rx <= CQSPI_PHY_LOW_RX_BOUND);
+
+		phy->read_delay++;
+	} while (phy->read_delay <= CQSPI_PHY_MAX_RD);
+
+	dev_dbg(dev, "Unable to find RX low\n");
+	return -ENOENT;
+}
+
+static int cqspi_find_rx_high(struct cqspi_flash_pdata *f_pdata,
+			      struct spi_mem *mem, struct phy_setting *phy)
+{
+	struct device *dev = &f_pdata->cqspi->pdev->dev;
+	int ret;
+
+	do {
+		phy->rx = CQSPI_PHY_MAX_RX;
+		do {
+			cqspi_phy_apply_setting(f_pdata, phy);
+			ret = cqspi_phy_check_pattern(f_pdata, mem);
+			if (!ret)
+				return 0;
+
+			phy->rx--;
+		} while (phy->rx >= CQSPI_PHY_HIGH_RX_BOUND);
+
+		phy->read_delay++;
+	} while (phy->read_delay <= CQSPI_PHY_MAX_RD);
+
+	dev_dbg(dev, "Unable to find RX high\n");
+	return -ENOENT;
+}
+
+static int cqspi_find_tx_low(struct cqspi_flash_pdata *f_pdata,
+			     struct spi_mem *mem, struct phy_setting *phy)
+{
+	struct device *dev = &f_pdata->cqspi->pdev->dev;
+	int ret;
+
+	do {
+		phy->tx = 0;
+		do {
+			cqspi_phy_apply_setting(f_pdata, phy);
+			ret = cqspi_phy_check_pattern(f_pdata, mem);
+			if (!ret)
+				return 0;
+
+			phy->tx++;
+		} while (phy->tx <= CQSPI_PHY_LOW_TX_BOUND);
+
+		phy->read_delay++;
+	} while (phy->read_delay <= CQSPI_PHY_MAX_RD);
+
+	dev_dbg(dev, "Unable to find TX low\n");
+	return -ENOENT;
+}
+
+static int cqspi_find_tx_high(struct cqspi_flash_pdata *f_pdata,
+			      struct spi_mem *mem, struct phy_setting *phy)
+{
+	struct device *dev = &f_pdata->cqspi->pdev->dev;
+	int ret;
+
+	do {
+		phy->tx = CQSPI_PHY_MAX_TX;
+		do {
+			cqspi_phy_apply_setting(f_pdata, phy);
+			ret = cqspi_phy_check_pattern(f_pdata, mem);
+			if (!ret)
+				return 0;
+
+			phy->tx--;
+		} while (phy->tx >= CQSPI_PHY_HIGH_TX_BOUND);
+
+		phy->read_delay++;
+	} while (phy->read_delay <= CQSPI_PHY_MAX_RD);
+
+	dev_dbg(dev, "Unable to find TX high\n");
+	return -ENOENT;
+}
+
+static int cqspi_phy_find_gaplow(struct cqspi_flash_pdata *f_pdata,
+				 struct spi_mem *mem,
+				 struct phy_setting *bottomleft,
+				 struct phy_setting *topright,
+				 struct phy_setting *gaplow)
+{
+	struct phy_setting left, right, mid;
+	int ret;
+
+	left = *bottomleft;
+	right = *topright;
+
+	mid.tx = left.tx + ((right.tx - left.tx) / 2);
+	mid.rx = left.rx + ((right.rx - left.rx) / 2);
+	mid.read_delay = left.read_delay;
+
+	do {
+		cqspi_phy_apply_setting(f_pdata, &mid);
+		ret = cqspi_phy_check_pattern(f_pdata, mem);
+		if (ret) {
+			/* The pattern was not found. Go to the lower half. */
+			right.tx = mid.tx;
+			right.rx = mid.rx;
+
+			mid.tx = left.tx + ((mid.tx - left.tx) / 2);
+			mid.rx = left.rx + ((mid.rx - left.rx) / 2);
+		} else {
+			/* The pattern was found. Go to the upper half. */
+			left.tx = mid.tx;
+			left.rx = mid.rx;
+
+			mid.tx = mid.tx + ((right.tx - mid.tx) / 2);
+			mid.rx = mid.rx + ((right.rx - mid.rx) / 2);
+		}
+
+	/* Break the loop if the window has closed. */
+	} while ((right.tx - left.tx >= 2) && (right.rx - left.rx >= 2));
+
+	*gaplow = mid;
+	return 0;
+}
+
+static int cqspi_phy_find_gaphigh(struct cqspi_flash_pdata *f_pdata,
+				  struct spi_mem *mem,
+				  struct phy_setting *bottomleft,
+				  struct phy_setting *topright,
+				  struct phy_setting *gaphigh)
+{
+	struct phy_setting left, right, mid;
+	int ret;
+
+	left = *bottomleft;
+	right = *topright;
+
+	mid.tx = left.tx + ((right.tx - left.tx) / 2);
+	mid.rx = left.rx + ((right.rx - left.rx) / 2);
+	mid.read_delay = right.read_delay;
+
+	do {
+		cqspi_phy_apply_setting(f_pdata, &mid);
+		ret = cqspi_phy_check_pattern(f_pdata, mem);
+		if (ret) {
+			/* The pattern was not found. Go to the upper half. */
+			left.tx = mid.tx;
+			left.rx = mid.rx;
+
+			mid.tx = mid.tx + ((right.tx - mid.tx) / 2);
+			mid.rx = mid.rx + ((right.rx - mid.rx) / 2);
+		} else {
+			/* The pattern was found. Go to the lower half. */
+			right.tx = mid.tx;
+			right.rx = mid.rx;
+
+			mid.tx = left.tx + ((mid.tx - left.tx) / 2);
+			mid.rx = left.rx + ((mid.rx - left.rx) / 2);
+		}
+
+	/* Break the loop if the window has closed. */
+	} while ((right.tx - left.tx >= 2) && (right.rx - left.rx >= 2));
+
+	*gaphigh = mid;
+	return 0;
+}
+
+static int cqspi_phy_calibrate(struct cqspi_flash_pdata *f_pdata,
+			       struct spi_mem *mem)
+{
+	struct cqspi_st *cqspi = f_pdata->cqspi;
+	struct device *dev = &cqspi->pdev->dev;
+	struct phy_setting rxlow, rxhigh, txlow, txhigh, temp;
+	struct phy_setting bottomleft, topright, searchpoint, gaplow, gaphigh;
+	int ret, tmp;
+
+	f_pdata->use_phy = true;
+
+	/* Look for RX boundaries at lower TX range. */
+	rxlow.tx = f_pdata->phy_tx_start;
+
+	do {
+		dev_dbg(dev, "Searching for rxlow on TX = %d\n", rxlow.tx);
+		rxlow.read_delay = CQSPI_PHY_INIT_RD;
+		ret = cqspi_find_rx_low(f_pdata, mem, &rxlow);
+	} while (ret && ++rxlow.tx <= CQSPI_PHY_TX_LOOKUP_LOW_BOUND);
+
+	if (ret)
+		goto out;
+	dev_dbg(dev, "rxlow: RX: %d TX: %d RD: %d\n", rxlow.rx, rxlow.tx,
+		rxlow.read_delay);
+
+	rxhigh.tx = rxlow.tx;
+	rxhigh.read_delay = rxlow.read_delay;
+	cqspi_find_rx_high(f_pdata, mem, &rxhigh);
+	if (ret)
+		goto out;
+	dev_dbg(dev, "rxhigh: RX: %d TX: %d RD: %d\n", rxhigh.rx, rxhigh.tx,
+		rxhigh.read_delay);
+
+	/*
+	 * Check a different point if rxlow and rxhigh are on the same read
+	 * delay. This avoids mistaking the failing region for an RX boundary.
+	 */
+	if (rxlow.read_delay == rxhigh.read_delay) {
+		dev_dbg(dev,
+			"rxlow and rxhigh at the same read delay.\n");
+
+		/* Look for RX boundaries at upper TX range. */
+		temp.tx = f_pdata->phy_tx_end;
+
+		do {
+			dev_dbg(dev, "Searching for rxlow on TX = %d\n",
+				temp.tx);
+			temp.read_delay = CQSPI_PHY_INIT_RD;
+			ret = cqspi_find_rx_low(f_pdata, mem, &temp);
+		} while (ret && --temp.tx >= CQSPI_PHY_TX_LOOKUP_HIGH_BOUND);
+
+		if (ret)
+			goto out;
+		dev_dbg(dev, "rxlow: RX: %d TX: %d RD: %d\n", temp.rx, temp.tx,
+			temp.read_delay);
+
+		if (temp.rx < rxlow.rx) {
+			rxlow = temp;
+			dev_dbg(dev, "Updating rxlow to the one at TX = 48\n");
+		}
+
+		/* Find RX max. */
+		ret = cqspi_find_rx_high(f_pdata, mem, &temp);
+		if (ret)
+			goto out;
+		dev_dbg(dev, "rxhigh: RX: %d TX: %d RD: %d\n", temp.rx, temp.tx,
+			temp.read_delay);
+
+		if (temp.rx < rxhigh.rx) {
+			rxhigh = temp;
+			dev_dbg(dev, "Updating rxhigh to the one at TX = 48\n");
+		}
+	}
+
+	/* Look for TX boundaries at 1/4 of RX window. */
+	txlow.rx = rxlow.rx + ((rxhigh.rx - rxlow.rx) / 4);
+	txhigh.rx = txlow.rx;
+
+	txlow.read_delay = CQSPI_PHY_INIT_RD;
+	ret = cqspi_find_tx_low(f_pdata, mem, &txlow);
+	if (ret)
+		goto out;
+	dev_dbg(dev, "txlow: RX: %d TX: %d RD: %d\n", txlow.rx, txlow.tx,
+		txlow.read_delay);
+
+	txhigh.read_delay = txlow.read_delay;
+	ret = cqspi_find_tx_high(f_pdata, mem, &txhigh);
+	if (ret)
+		goto out;
+	dev_dbg(dev, "txhigh: RX: %d TX: %d RD: %d\n", txhigh.rx, txhigh.tx,
+		txhigh.read_delay);
+
+	/*
+	 * Check a different point if txlow and txhigh are on the same read
+	 * delay. This avoids mistaking the failing region for an TX boundary.
+	 */
+	if (txlow.read_delay == txhigh.read_delay) {
+		/* Look for TX boundaries at 3/4 of RX window. */
+		temp.rx = rxlow.rx + (3 * (rxhigh.rx - rxlow.rx) / 4);
+		temp.read_delay = CQSPI_PHY_INIT_RD;
+		dev_dbg(dev,
+			"txlow and txhigh at the same read delay. Searching at RX = %d\n",
+			temp.rx);
+
+		ret = cqspi_find_tx_low(f_pdata, mem, &temp);
+		if (ret)
+			goto out;
+		dev_dbg(dev, "txlow: RX: %d TX: %d RD: %d\n", temp.rx, temp.tx,
+			temp.read_delay);
+
+		if (temp.tx < txlow.tx) {
+			txlow = temp;
+			dev_dbg(dev, "Updating txlow with the one at RX = %d\n",
+				txlow.rx);
+		}
+
+		ret = cqspi_find_tx_high(f_pdata, mem, &temp);
+		if (ret)
+			goto out;
+		dev_dbg(dev, "txhigh: RX: %d TX: %d RD: %d\n", temp.rx, temp.tx,
+			temp.read_delay);
+
+		if (temp.tx < txhigh.tx) {
+			txhigh = temp;
+			dev_dbg(dev, "Updating txhigh with the one at RX = %d\n",
+				txhigh.rx);
+		}
+	}
+
+	/*
+	 * Set bottom left and top right corners. These are theoretical
+	 * corners. They may not actually be "good" points. But the longest
+	 * diagonal will be between these corners.
+	 */
+	bottomleft.tx = txlow.tx;
+	bottomleft.rx = rxlow.rx;
+	if (txlow.read_delay <= rxlow.read_delay)
+		bottomleft.read_delay = txlow.read_delay;
+	else
+		bottomleft.read_delay = rxlow.read_delay;
+
+	temp = bottomleft;
+	temp.tx += 4;
+	temp.rx += 4;
+	cqspi_phy_apply_setting(f_pdata, &temp);
+	ret = cqspi_phy_check_pattern(f_pdata, mem);
+	if (ret) {
+		temp.read_delay--;
+		cqspi_phy_apply_setting(f_pdata, &temp);
+		ret = cqspi_phy_check_pattern(f_pdata, mem);
+	}
+
+	if (!ret)
+		bottomleft.read_delay = temp.read_delay;
+
+	topright.tx = txhigh.tx;
+	topright.rx = rxhigh.rx;
+	if (txhigh.read_delay >= rxhigh.read_delay)
+		topright.read_delay = txhigh.read_delay;
+	else
+		topright.read_delay = rxhigh.read_delay;
+
+	temp = topright;
+	temp.tx -= 4;
+	temp.rx -= 4;
+	cqspi_phy_apply_setting(f_pdata, &temp);
+	ret = cqspi_phy_check_pattern(f_pdata, mem);
+	if (ret) {
+		temp.read_delay++;
+		cqspi_phy_apply_setting(f_pdata, &temp);
+		ret = cqspi_phy_check_pattern(f_pdata, mem);
+	}
+
+	if (!ret)
+		topright.read_delay = temp.read_delay;
+
+	dev_dbg(dev, "topright: RX: %d TX: %d RD: %d\n", topright.rx,
+		topright.tx, topright.read_delay);
+	dev_dbg(dev, "bottomleft: RX: %d TX: %d RD: %d\n", bottomleft.rx,
+		bottomleft.tx, bottomleft.read_delay);
+
+	ret = cqspi_phy_find_gaplow(f_pdata, mem, &bottomleft, &topright,
+				    &gaplow);
+	if (ret)
+		goto out;
+	dev_dbg(dev, "gaplow: RX: %d TX: %d RD: %d\n", gaplow.rx, gaplow.tx,
+		gaplow.read_delay);
+
+	if (bottomleft.read_delay == topright.read_delay) {
+		/*
+		 * If there is only one passing region, it means that the "true"
+		 * topright is too small to find, so the start of the failing
+		 * region is a good approximation. Put the tuning point in the
+		 * middle and adjust for temperature.
+		 */
+		topright = gaplow;
+		searchpoint.read_delay = bottomleft.read_delay;
+		searchpoint.tx = bottomleft.tx +
+				 ((topright.tx - bottomleft.tx) / 2);
+		searchpoint.rx = bottomleft.rx +
+				 ((topright.rx - bottomleft.rx) / 2);
+
+		ret = cqspi_get_temp(&tmp);
+		if (ret) {
+			/*
+			 * Assume room temperature if it couldn't be obtained
+			 * from the thermal sensor.
+			 *
+			 * TODO: Change it to dev_warn once support for finding
+			 * out the temperature is added.
+			 */
+			dev_dbg(dev,
+				"Unable to get temperature. Assuming room temperature\n");
+			tmp = CQSPI_PHY_DEFAULT_TEMP;
+		}
+
+		if (tmp < CQSPI_PHY_MIN_TEMP || tmp > CQSPI_PHY_MAX_TEMP) {
+			dev_err(dev,
+				"Temperature outside operating range: %dC\n",
+				tmp);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		/* Avoid a divide-by-zero. */
+		if (tmp == CQSPI_PHY_MID_TEMP)
+			tmp++;
+		dev_dbg(dev, "Temperature: %dC\n", tmp);
+
+		searchpoint.tx += (topright.tx - bottomleft.tx) /
+				  (330 / (tmp - CQSPI_PHY_MID_TEMP));
+		searchpoint.rx += (topright.rx - bottomleft.rx) /
+				  (330 / (tmp - CQSPI_PHY_MID_TEMP));
+	} else {
+		/*
+		 * If there are two passing regions, find the start and end of
+		 * the second one.
+		 */
+		ret = cqspi_phy_find_gaphigh(f_pdata, mem, &bottomleft,
+					     &topright, &gaphigh);
+		if (ret)
+			goto out;
+		dev_dbg(dev, "gaphigh: RX: %d TX: %d RD: %d\n", gaphigh.rx,
+			gaphigh.tx, gaphigh.read_delay);
+
+		/*
+		 * Place the final tuning point in the corner furthest from the
+		 * failing region but leave some margin for temperature changes.
+		 */
+		if ((abs(gaplow.tx - bottomleft.tx) +
+		     abs(gaplow.rx - bottomleft.rx)) <
+		    (abs(gaphigh.tx - topright.tx) +
+		     abs(gaphigh.rx - topright.rx))) {
+			searchpoint = topright;
+			searchpoint.tx -= 16;
+			searchpoint.rx -= (16 * (topright.rx - bottomleft.rx)) /
+					   (topright.tx - bottomleft.tx);
+		} else {
+			searchpoint = bottomleft;
+			searchpoint.tx += 16;
+			searchpoint.rx += (16 * (topright.rx - bottomleft.rx)) /
+					   (topright.tx - bottomleft.tx);
+		}
+	}
+
+	/* Set the final PHY settings and check if they are working. */
+	cqspi_phy_apply_setting(f_pdata, &searchpoint);
+	dev_dbg(dev, "Final tuning point: RX: %d TX: %d RD: %d\n",
+		searchpoint.rx, searchpoint.tx, searchpoint.read_delay);
+
+	ret = cqspi_phy_check_pattern(f_pdata, mem);
+	if (ret) {
+		dev_err(dev,
+			"Failed to find pattern at final calibration point\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = 0;
+	f_pdata->phy_setting.read_delay = searchpoint.read_delay;
+	f_pdata->phy_setting.rx = searchpoint.rx;
+	f_pdata->phy_setting.tx = searchpoint.tx;
+out:
+	if (ret)
+		f_pdata->use_phy = false;
+	return ret;
+}
+
 static int cqspi_wait_for_bit(void __iomem *reg, const u32 mask, bool clr)
 {
 	u32 val;
@@ -531,6 +1132,17 @@
 	/* 0 means 1 byte. */
 	reg |= (((n_rx - 1) & CQSPI_REG_CMDCTRL_RD_BYTES_MASK)
 		<< CQSPI_REG_CMDCTRL_RD_BYTES_LSB);
+
+	/* setup ADDR BIT field */
+	if (op->addr.nbytes) {
+		reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB);
+		reg |= ((op->addr.nbytes - 1) &
+			CQSPI_REG_CMDCTRL_ADD_BYTES_MASK)
+			<< CQSPI_REG_CMDCTRL_ADD_BYTES_LSB;
+
+		writel(op->addr.val, reg_base + CQSPI_REG_CMDADDRESS);
+	}
+
 	status = cqspi_exec_flash_cmd(cqspi, reg);
 	if (status)
 		return status;
@@ -549,6 +1161,9 @@
 		memcpy(rxbuf, &reg, read_len);
 	}
 
+	/* Reset CMD_CTRL Reg once command read completes */
+	writel(0, reg_base + CQSPI_REG_CMDCTRL);
+
 	return 0;
 }
 
@@ -613,7 +1228,12 @@
 		}
 	}
 
-	return cqspi_exec_flash_cmd(cqspi, reg);
+	ret = cqspi_exec_flash_cmd(cqspi, reg);
+
+	/* Reset CMD_CTRL Reg once command write completes */
+	writel(0, reg_base + CQSPI_REG_CMDCTRL);
+
+	return ret;
 }
 
 static int cqspi_read_setup(struct cqspi_flash_pdata *f_pdata,
@@ -937,6 +1557,12 @@
 		reg = readl(reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
 		reg |= CQSPI_REG_WR_DISABLE_AUTO_POLL;
 		writel(reg, reg_base + CQSPI_REG_WR_COMPLETION_CTRL);
+		/*
+		 * DAC mode require auto polling as flash needs to be polled
+		 * for write completion in case of bubble in SPI transaction
+		 * due to slow CPU/DMA master.
+		 */
+		cqspi->use_direct_mode_wr = false;
 	}
 
 	reg = readl(reg_base + CQSPI_REG_SIZE);
@@ -1127,6 +1753,7 @@
 
 static void cqspi_readdata_capture(struct cqspi_st *cqspi,
 				   const bool bypass,
+				   const bool dqs,
 				   const unsigned int delay)
 {
 	void __iomem *reg_base = cqspi->iobase;
@@ -1145,6 +1772,11 @@
 	reg |= (delay & CQSPI_REG_READCAPTURE_DELAY_MASK)
 		<< CQSPI_REG_READCAPTURE_DELAY_LSB;
 
+	if (dqs)
+		reg |= (1 << CQSPI_REG_READCAPTURE_DQS_LSB);
+	else
+		reg &= ~(1 << CQSPI_REG_READCAPTURE_DQS_LSB);
+
 	writel(reg, reg_base + CQSPI_REG_READCAPTURE);
 }
 
@@ -1163,6 +1795,64 @@
 	writel(reg, reg_base + CQSPI_REG_CONFIG);
 }
 
+static void cqspi_phy_enable(struct cqspi_flash_pdata *f_pdata, bool enable)
+{
+	struct cqspi_st *cqspi = f_pdata->cqspi;
+	void __iomem *reg_base = cqspi->iobase;
+	u32 reg;
+	u8 dummy;
+
+	if (enable) {
+		cqspi_readdata_capture(cqspi, 1, true,
+				       f_pdata->phy_setting.read_delay);
+
+		reg = readl(reg_base + CQSPI_REG_CONFIG);
+		reg |= CQSPI_REG_CONFIG_PHY_EN |
+		       CQSPI_REG_CONFIG_PHY_PIPELINE;
+		writel(reg, reg_base + CQSPI_REG_CONFIG);
+
+		/*
+		 * Reduce dummy cycle by 1. This is a requirement of PHY mode
+		 * operation for correctly reading the data.
+		 */
+		reg = readl(reg_base + CQSPI_REG_RD_INSTR);
+		dummy = (reg >> CQSPI_REG_RD_INSTR_DUMMY_LSB) &
+			CQSPI_REG_RD_INSTR_DUMMY_MASK;
+		dummy--;
+		reg &= ~(CQSPI_REG_RD_INSTR_DUMMY_MASK <<
+			 CQSPI_REG_RD_INSTR_DUMMY_LSB);
+
+		reg |= (dummy & CQSPI_REG_RD_INSTR_DUMMY_MASK)
+		       << CQSPI_REG_RD_INSTR_DUMMY_LSB;
+		writel(reg, reg_base + CQSPI_REG_RD_INSTR);
+	} else {
+		cqspi_readdata_capture(cqspi, !cqspi->rclk_en, false,
+				       f_pdata->read_delay);
+
+		reg = readl(reg_base + CQSPI_REG_CONFIG);
+		reg &= ~(CQSPI_REG_CONFIG_PHY_EN |
+			 CQSPI_REG_CONFIG_PHY_PIPELINE);
+		writel(reg, reg_base + CQSPI_REG_CONFIG);
+
+		/*
+		 * Dummy cycles were decremented when enabling PHY. Increment
+		 * dummy cycle by 1 to restore the original value.
+		 */
+		reg = readl(reg_base + CQSPI_REG_RD_INSTR);
+		dummy = (reg >> CQSPI_REG_RD_INSTR_DUMMY_LSB) &
+			CQSPI_REG_RD_INSTR_DUMMY_MASK;
+		dummy++;
+		reg &= ~(CQSPI_REG_RD_INSTR_DUMMY_MASK <<
+			 CQSPI_REG_RD_INSTR_DUMMY_LSB);
+
+		reg |= (dummy & CQSPI_REG_RD_INSTR_DUMMY_MASK)
+		       << CQSPI_REG_RD_INSTR_DUMMY_LSB;
+		writel(reg, reg_base + CQSPI_REG_RD_INSTR);
+	}
+
+	cqspi_wait_idle(cqspi);
+}
+
 static void cqspi_configure(struct cqspi_flash_pdata *f_pdata,
 			    unsigned long sclk)
 {
@@ -1184,7 +1874,7 @@
 		cqspi->sclk = sclk;
 		cqspi_config_baudrate_div(cqspi);
 		cqspi_delay(f_pdata);
-		cqspi_readdata_capture(cqspi, !cqspi->rclk_en,
+		cqspi_readdata_capture(cqspi, !cqspi->rclk_en, false,
 				       f_pdata->read_delay);
 	}
 
@@ -1214,7 +1904,7 @@
 	 * data.
 	 */
 	if (!op->cmd.dtr && cqspi->use_direct_mode &&
-	    ((to + len) <= cqspi->ahb_size)) {
+	    cqspi->use_direct_mode_wr && ((to + len) <= cqspi->ahb_size)) {
 		memcpy_toio(cqspi->ahb_base + to, buf, len);
 		return cqspi_wait_idle(cqspi);
 	}
@@ -1222,6 +1912,39 @@
 	return cqspi_indirect_write_execute(f_pdata, to, buf, len);
 }
 
+/*
+ * Check if PHY mode can be used on the given op. This is assuming it will be a
+ * DAC mode read, since PHY won't work on any other type of operation anyway.
+ */
+static bool cqspi_phy_op_eligible(const struct spi_mem_op *op)
+{
+	/* PHY is only tuned for 8D-8D-8D. */
+	if (!(op->cmd.dtr && op->addr.dtr && op->dummy.dtr && op->data.dtr))
+		return false;
+	if (op->cmd.buswidth != 8)
+		return false;
+	if (op->addr.nbytes && op->addr.buswidth != 8)
+		return false;
+	if (op->dummy.nbytes && op->dummy.buswidth != 8)
+		return false;
+	if (op->data.nbytes && op->data.buswidth != 8)
+		return false;
+
+	return true;
+}
+
+static bool cqspi_use_phy(struct cqspi_flash_pdata *f_pdata,
+			  const struct spi_mem_op *op)
+{
+	if (!f_pdata->use_phy)
+		return false;
+
+	if (op->data.nbytes < 16)
+		return false;
+
+	return cqspi_phy_op_eligible(op);
+}
+
 static void cqspi_rx_dma_callback(void *param)
 {
 	struct cqspi_st *cqspi = param;
@@ -1229,8 +1952,8 @@
 	complete(&cqspi->rx_dma_complete);
 }
 
-static int cqspi_direct_read_execute(struct cqspi_flash_pdata *f_pdata,
-				     u_char *buf, loff_t from, size_t len)
+static int cqspi_direct_read_dma(struct cqspi_flash_pdata *f_pdata,
+				 u_char *buf, loff_t from, size_t len)
 {
 	struct cqspi_st *cqspi = f_pdata->cqspi;
 	struct device *dev = &cqspi->pdev->dev;
@@ -1242,11 +1965,6 @@
 	dma_addr_t dma_dst;
 	struct device *ddev;
 
-	if (!cqspi->rx_chan || !virt_addr_valid(buf)) {
-		memcpy_fromio(buf, cqspi->ahb_base + from, len);
-		return 0;
-	}
-
 	ddev = cqspi->rx_chan->device->dev;
 	dma_dst = dma_map_single(ddev, buf, len, DMA_FROM_DEVICE);
 	if (dma_mapping_error(ddev, dma_dst)) {
@@ -1288,6 +2006,64 @@
 	return ret;
 }
 
+static int cqspi_direct_read_execute(struct cqspi_flash_pdata *f_pdata,
+				     const struct spi_mem_op *op)
+{
+	struct cqspi_st *cqspi = f_pdata->cqspi;
+	loff_t from = op->addr.val;
+	loff_t from_aligned, to_aligned;
+	size_t len = op->data.nbytes;
+	size_t len_aligned;
+	u_char *buf = op->data.buf.in;
+	int ret;
+
+	if (!cqspi->rx_chan || !virt_addr_valid(buf)) {
+		memcpy_fromio(buf, cqspi->ahb_base + from, len);
+		return 0;
+	}
+
+	if (!cqspi_use_phy(f_pdata, op))
+		return cqspi_direct_read_dma(f_pdata, buf, from, len);
+
+	/*
+	 * PHY reads must be 16-byte aligned, and they must be a multiple of 16
+	 * bytes.
+	 */
+	from_aligned = (from + 0xF) & ~0xF;
+	to_aligned = (from + len) & ~0xF;
+	len_aligned = to_aligned - from_aligned;
+
+	/* Read the unaligned part at the start. */
+	if (from != from_aligned) {
+		ret = cqspi_direct_read_dma(f_pdata, buf, from,
+					    from_aligned - from);
+		if (ret)
+			return ret;
+		buf += from_aligned - from;
+	}
+
+	if (len_aligned) {
+		cqspi_phy_enable(f_pdata, true);
+		ret = cqspi_direct_read_dma(f_pdata, buf, from_aligned,
+					    len_aligned);
+		cqspi_phy_enable(f_pdata, false);
+		if (ret)
+			return ret;
+		buf += len_aligned;
+	}
+
+	/* Now read the remaining part, if any. */
+	if (to_aligned != (from + len)) {
+		ret = cqspi_direct_read_dma(f_pdata, buf, to_aligned,
+					    (from + len) - to_aligned);
+		if (ret)
+			return ret;
+		buf += (from + len) - to_aligned;
+	}
+
+	return 0;
+}
+
 static ssize_t cqspi_read(struct cqspi_flash_pdata *f_pdata,
 			  const struct spi_mem_op *op)
 {
@@ -1307,7 +2083,7 @@
 		return ret;
 
 	if (cqspi->use_direct_mode && ((from + len) <= cqspi->ahb_size))
-		return cqspi_direct_read_execute(f_pdata, buf, from, len);
+		return cqspi_direct_read_execute(f_pdata, op);
 
 	if (cqspi->use_dma_read && ddata && ddata->indirect_read_dma &&
 	    virt_addr_valid(buf) && ((dma_align & CQSPI_DMA_UNALIGN) == 0))
@@ -1325,7 +2101,13 @@
 	cqspi_configure(f_pdata, mem->spi->max_speed_hz);
 
 	if (op->data.dir == SPI_MEM_DATA_IN && op->data.buf.in) {
-		if (!op->addr.nbytes)
+	/*
+	 * Performing reads in DAC mode forces to read minimum 4 bytes
+	 * which is unsupported on some flash devices during register
+	 * reads, prefer STIG mode for such small reads.
+	 */
+		if (!op->addr.nbytes ||
+		    op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX)
 			return cqspi_command_read(f_pdata, op);
 
 		return cqspi_read(f_pdata, op);
@@ -1340,8 +2122,20 @@
 static int cqspi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op)
 {
 	int ret;
+	struct cqspi_st *cqspi = spi_master_get_devdata(mem->spi->master);
+	struct device *dev = &cqspi->pdev->dev;
+
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret < 0) {
+		dev_err(dev, "failed to get sync: %d\n", ret);
+		return ret;
+	}
 
 	ret = cqspi_mem_process(mem, op);
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+
 	if (ret)
 		dev_err(&mem->spi->dev, "operation failed with %d\n", ret);
 
@@ -1381,6 +2175,42 @@
 	return spi_mem_default_supports_op(mem, op);
 }
 
+static void cqspi_mem_do_calibration(struct spi_mem *mem,
+				     const struct spi_mem_op *op)
+{
+	struct cqspi_st *cqspi = spi_master_get_devdata(mem->spi->master);
+	struct cqspi_flash_pdata *f_pdata;
+	struct device *dev = &cqspi->pdev->dev;
+	int ret;
+
+	f_pdata = &cqspi->f_pdata[mem->spi->chip_select];
+
+	ret = pm_runtime_resume_and_get(dev);
+	if (ret < 0) {
+		dev_err(dev, "failed to get sync: %d\n", ret);
+		return;
+	}
+
+	/* Check if the op is eligible for PHY mode operation. */
+	if (!cqspi_phy_op_eligible(op))
+		return;
+
+	f_pdata->phy_read_op = *op;
+
+	ret = cqspi_phy_check_pattern(f_pdata, mem);
+	if (ret) {
+		dev_dbg(dev, "Pattern not found. Skipping calibration.\n");
+		return;
+	}
+
+	ret = cqspi_phy_calibrate(f_pdata, mem);
+	if (ret)
+		dev_info(&cqspi->pdev->dev, "PHY calibration failed: %d\n", ret);
+
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+}
+
 static int cqspi_of_get_flash_pdata(struct platform_device *pdev,
 				    struct cqspi_flash_pdata *f_pdata,
 				    struct device_node *np)
@@ -1415,6 +2245,12 @@
 		return -ENXIO;
 	}
 
+	if (of_property_read_u32(np, "cdns,phy-tx-start", &f_pdata->phy_tx_start))
+		f_pdata->phy_tx_start = 16;
+
+	if (of_property_read_u32(np, "cdns,phy-tx-end", &f_pdata->phy_tx_end))
+		f_pdata->phy_tx_end = 48;
+
 	return 0;
 }
 
@@ -1508,6 +2344,9 @@
 	if (IS_ERR(cqspi->rx_chan)) {
 		int ret = PTR_ERR(cqspi->rx_chan);
 
+		if (ret == -ENODEV)
+			ret = -EPROBE_DEFER;
+
 		cqspi->rx_chan = NULL;
 		return dev_err_probe(&cqspi->pdev->dev, ret, "No Rx DMA available\n");
 	}
@@ -1528,6 +2367,7 @@
 	.exec_op = cqspi_exec_mem_op,
 	.get_name = cqspi_get_name,
 	.supports_op = cqspi_supports_mem_op,
+	.do_calibration = cqspi_mem_do_calibration,
 };
 
 static const struct spi_controller_mem_caps cqspi_mem_caps = {
@@ -1642,10 +2482,10 @@
 	if (irq < 0)
 		return -ENXIO;
 
-	pm_runtime_enable(dev);
-	ret = pm_runtime_resume_and_get(dev);
-	if (ret < 0)
-		goto probe_pm_failed;
+	ret = pm_runtime_set_active(dev);
+	if (ret)
+		return ret;
+
 
 	ret = clk_prepare_enable(cqspi->clk);
 	if (ret) {
@@ -1687,8 +2527,10 @@
 						cqspi->master_ref_clk_hz);
 		if (ddata->hwcaps_mask & CQSPI_SUPPORTS_OCTAL)
 			master->mode_bits |= SPI_RX_OCTAL | SPI_TX_OCTAL;
-		if (!(ddata->quirks & CQSPI_DISABLE_DAC_MODE))
+		if (!(ddata->quirks & CQSPI_DISABLE_DAC_MODE)) {
 			cqspi->use_direct_mode = true;
+			cqspi->use_direct_mode_wr = true;
+		}
 		if (ddata->quirks & CQSPI_SUPPORT_EXTERNAL_DMA)
 			cqspi->use_dma_read = true;
 		if (ddata->quirks & CQSPI_NO_SUPPORT_WR_COMPLETION)
@@ -1730,11 +2572,18 @@
 			goto probe_setup_failed;
 	}
 
+	devm_pm_runtime_enable(dev);
+	pm_runtime_set_autosuspend_delay(dev, CQSPI_AUTOSUSPEND_TIMEOUT);
+	pm_runtime_use_autosuspend(dev);
+	pm_runtime_get_noresume(dev);
+
 	ret = spi_register_master(master);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to register SPI ctlr %d\n", ret);
 		goto probe_setup_failed;
 	}
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
 
 	return 0;
 probe_setup_failed:
@@ -1742,9 +2591,6 @@
 probe_reset_failed:
 	clk_disable_unprepare(cqspi->clk);
 probe_clk_failed:
-	pm_runtime_put_sync(dev);
-probe_pm_failed:
-	pm_runtime_disable(dev);
 	return ret;
 }
 
@@ -1766,6 +2612,12 @@
 	return 0;
 }
 
+static void __maybe_unused cqspi_restore_context(struct cqspi_st *cqspi)
+{
+	cqspi_phy_apply_setting(cqspi->f_pdata,
+				&cqspi->f_pdata->phy_setting);
+}
+
 static int cqspi_suspend(struct device *dev)
 {
 	struct cqspi_st *cqspi = dev_get_drvdata(dev);
@@ -1792,10 +2644,17 @@
 	cqspi->current_cs = -1;
 	cqspi->sclk = 0;
 
+	/*
+	 * Only restore context if PHY is enabled, or else skip this step
+	 */
+	if ((cqspi->f_pdata->use_phy) == true)
+		cqspi_restore_context(cqspi);
+
 	return spi_master_resume(master);
 }
 
-static DEFINE_SIMPLE_DEV_PM_OPS(cqspi_dev_pm_ops, cqspi_suspend, cqspi_resume);
+static DEFINE_RUNTIME_DEV_PM_OPS(cqspi_dev_pm_ops, cqspi_suspend,
+				 cqspi_resume, NULL);
 
 static const struct cqspi_driver_platdata cdns_qspi = {
 	.quirks = CQSPI_DISABLE_DAC_MODE,
@@ -1862,7 +2721,7 @@
 	.remove = cqspi_remove,
 	.driver = {
 		.name = CQSPI_NAME,
-		.pm = &cqspi_dev_pm_ops,
+		.pm = pm_ptr(&cqspi_dev_pm_ops),
 		.of_match_table = cqspi_dt_ids,
 	},
 };
diff -Naur --no-dereference a/drivers/spi/spi-mem.c b/drivers/spi/spi-mem.c
--- a/drivers/spi/spi-mem.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/spi/spi-mem.c	2024-01-28 14:01:31.252353813 -0500
@@ -478,6 +478,18 @@
 }
 EXPORT_SYMBOL_GPL(spi_mem_adjust_op_size);
 
+int spi_mem_do_calibration(struct spi_mem *mem, const struct spi_mem_op *op)
+{
+	struct spi_controller *ctlr = mem->spi->controller;
+
+	if (!ctlr->mem_ops || !ctlr->mem_ops->do_calibration)
+		return -EOPNOTSUPP;
+
+	ctlr->mem_ops->do_calibration(mem, op);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(spi_mem_do_calibration);
+
 static ssize_t spi_mem_no_dirmap_read(struct spi_mem_dirmap_desc *desc,
 				      u64 offs, size_t len, void *buf)
 {
diff -Naur --no-dereference a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
--- a/drivers/spi/spi-omap2-mcspi.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/spi/spi-omap2-mcspi.c	2024-01-28 14:01:31.252353813 -0500
@@ -91,10 +91,6 @@
 struct omap2_mcspi_dma {
 	struct dma_chan *dma_tx;
 	struct dma_chan *dma_rx;
-
-	struct completion dma_tx_completion;
-	struct completion dma_rx_completion;
-
 	char dma_rx_ch_name[14];
 	char dma_tx_ch_name[14];
 };
@@ -116,7 +112,7 @@
 };
 
 struct omap2_mcspi {
-	struct completion	txdone;
+	struct completion	txrxdone;
 	struct spi_master	*master;
 	/* Virtual base address of the controller */
 	void __iomem		*base;
@@ -125,10 +121,12 @@
 	struct omap2_mcspi_dma	*dma_channels;
 	struct device		*dev;
 	struct omap2_mcspi_regs ctx;
+	struct clk		*ref_clk;
 	int			fifo_depth;
 	bool			slave_aborted;
 	unsigned int		pin_dir:1;
 	size_t			max_xfer_len;
+	u32			ref_clk_hz;
 };
 
 struct omap2_mcspi_cs {
@@ -375,30 +373,6 @@
 	return 0;
 }
 
-static void omap2_mcspi_rx_callback(void *data)
-{
-	struct spi_device *spi = data;
-	struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
-	struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select];
-
-	/* We must disable the DMA RX request */
-	omap2_mcspi_set_dma_req(spi, 1, 0);
-
-	complete(&mcspi_dma->dma_rx_completion);
-}
-
-static void omap2_mcspi_tx_callback(void *data)
-{
-	struct spi_device *spi = data;
-	struct omap2_mcspi *mcspi = spi_master_get_devdata(spi->master);
-	struct omap2_mcspi_dma *mcspi_dma = &mcspi->dma_channels[spi->chip_select];
-
-	/* We must disable the DMA TX request */
-	omap2_mcspi_set_dma_req(spi, 0, 0);
-
-	complete(&mcspi_dma->dma_tx_completion);
-}
-
 static void omap2_mcspi_tx_dma(struct spi_device *spi,
 				struct spi_transfer *xfer,
 				struct dma_slave_config cfg)
@@ -413,12 +387,9 @@
 	dmaengine_slave_config(mcspi_dma->dma_tx, &cfg);
 
 	tx = dmaengine_prep_slave_sg(mcspi_dma->dma_tx, xfer->tx_sg.sgl,
-				     xfer->tx_sg.nents,
-				     DMA_MEM_TO_DEV,
-				     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+					xfer->tx_sg.nents, DMA_MEM_TO_DEV, DMA_CTRL_ACK);
+
 	if (tx) {
-		tx->callback = omap2_mcspi_tx_callback;
-		tx->callback_param = spi;
 		dmaengine_submit(tx);
 	} else {
 		/* FIXME: fall back to PIO? */
@@ -444,6 +415,9 @@
 	struct omap2_mcspi_cs	*cs = spi->controller_state;
 	void __iomem		*chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
 	struct dma_async_tx_descriptor *tx;
+	dma_cookie_t dma_rx_cookie = 0;
+	struct dma_tx_state mcspi_dma_rxstate;
+	enum dma_status dma_status;
 
 	mcspi = spi_master_get_devdata(spi->master);
 	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
@@ -500,12 +474,10 @@
 	}
 
 	tx = dmaengine_prep_slave_sg(mcspi_dma->dma_rx, sg_out[0],
-				     out_mapped_nents[0], DMA_DEV_TO_MEM,
-				     DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+				     out_mapped_nents[0], DMA_DEV_TO_MEM, DMA_CTRL_ACK);
+
 	if (tx) {
-		tx->callback = omap2_mcspi_rx_callback;
-		tx->callback_param = spi;
-		dmaengine_submit(tx);
+		dma_rx_cookie = dmaengine_submit(tx);
 	} else {
 		/* FIXME: fall back to PIO? */
 	}
@@ -513,10 +485,20 @@
 	dma_async_issue_pending(mcspi_dma->dma_rx);
 	omap2_mcspi_set_dma_req(spi, 1, 1);
 
-	ret = mcspi_wait_for_completion(mcspi, &mcspi_dma->dma_rx_completion);
+	ret = mcspi_wait_for_completion(mcspi, &mcspi->txrxdone);
+
+	/*
+	 * Before disabling RX DMA we need to confirm whether DMA RX is complete.
+	 * This polling completes on the first attempt itself in most cases.
+	 */
+	do {
+		dma_status = dmaengine_tx_status(mcspi_dma->dma_rx, dma_rx_cookie,
+						 &mcspi_dma_rxstate);
+	} while (dma_status != DMA_COMPLETE);
+
+	omap2_mcspi_set_dma_req(spi, 1, 0);
 	if (ret || mcspi->slave_aborted) {
 		dmaengine_terminate_sync(mcspi_dma->dma_rx);
-		omap2_mcspi_set_dma_req(spi, 1, 0);
 		return 0;
 	}
 
@@ -579,7 +561,6 @@
 {
 	struct omap2_mcspi	*mcspi;
 	struct omap2_mcspi_cs	*cs = spi->controller_state;
-	struct omap2_mcspi_dma  *mcspi_dma;
 	unsigned int		count;
 	u8			*rx;
 	const u8		*tx;
@@ -587,11 +568,10 @@
 	enum dma_slave_buswidth width;
 	unsigned es;
 	void __iomem		*chstat_reg;
-	void __iomem            *irqstat_reg;
 	int			wait_res;
+	int ret;
 
 	mcspi = spi_master_get_devdata(spi->master);
-	mcspi_dma = &mcspi->dma_channels[spi->chip_select];
 
 	if (cs->word_len <= 8) {
 		width = DMA_SLAVE_BUSWIDTH_1_BYTE;
@@ -618,68 +598,36 @@
 	tx = xfer->tx_buf;
 
 	mcspi->slave_aborted = false;
-	reinit_completion(&mcspi_dma->dma_tx_completion);
-	reinit_completion(&mcspi_dma->dma_rx_completion);
-	reinit_completion(&mcspi->txdone);
-	if (tx) {
-		/* Enable EOW IRQ to know end of tx in slave mode */
-		if (spi_controller_is_slave(spi->master))
-			mcspi_write_reg(spi->master,
-					OMAP2_MCSPI_IRQENABLE,
-					OMAP2_MCSPI_IRQSTATUS_EOW);
+	reinit_completion(&mcspi->txrxdone);
+	mcspi_write_reg(spi->master, OMAP2_MCSPI_IRQENABLE,	OMAP2_MCSPI_IRQSTATUS_EOW);
+	if (tx)
 		omap2_mcspi_tx_dma(spi, xfer, cfg);
-	}
 
-	if (rx != NULL)
+	if (rx)
 		count = omap2_mcspi_rx_dma(spi, xfer, cfg, es);
 
-	if (tx != NULL) {
-		int ret;
-
-		ret = mcspi_wait_for_completion(mcspi, &mcspi_dma->dma_tx_completion);
-		if (ret || mcspi->slave_aborted) {
-			dmaengine_terminate_sync(mcspi_dma->dma_tx);
-			omap2_mcspi_set_dma_req(spi, 0, 0);
-			return 0;
-		}
-
-		if (spi_controller_is_slave(mcspi->master)) {
-			ret = mcspi_wait_for_completion(mcspi, &mcspi->txdone);
-			if (ret || mcspi->slave_aborted)
-				return 0;
-		}
+	ret = mcspi_wait_for_completion(mcspi, &mcspi->txrxdone);
+	omap2_mcspi_set_dma_req(spi, 0, 0);
+	if (ret || mcspi->slave_aborted)
+		return 0;
 
+	/* for TX_ONLY mode, be sure all words have shifted out */
+	if (tx && !rx) {
+		chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
 		if (mcspi->fifo_depth > 0) {
-			irqstat_reg = mcspi->base + OMAP2_MCSPI_IRQSTATUS;
-
-			if (mcspi_wait_for_reg_bit(irqstat_reg,
-						OMAP2_MCSPI_IRQSTATUS_EOW) < 0)
-				dev_err(&spi->dev, "EOW timed out\n");
-
-			mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS,
-					OMAP2_MCSPI_IRQSTATUS_EOW);
-		}
-
-		/* for TX_ONLY mode, be sure all words have shifted out */
-		if (rx == NULL) {
-			chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
-			if (mcspi->fifo_depth > 0) {
-				wait_res = mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_TXFFE);
-				if (wait_res < 0)
-					dev_err(&spi->dev, "TXFFE timed out\n");
-			} else {
-				wait_res = mcspi_wait_for_reg_bit(chstat_reg,
-						OMAP2_MCSPI_CHSTAT_TXS);
-				if (wait_res < 0)
-					dev_err(&spi->dev, "TXS timed out\n");
-			}
-			if (wait_res >= 0 &&
-				(mcspi_wait_for_reg_bit(chstat_reg,
-					OMAP2_MCSPI_CHSTAT_EOT) < 0))
-				dev_err(&spi->dev, "EOT timed out\n");
+			wait_res = mcspi_wait_for_reg_bit(chstat_reg, OMAP2_MCSPI_CHSTAT_TXFFE);
+			if (wait_res < 0)
+				dev_err(&spi->dev, "TXFFE timed out\n");
+		} else {
+			wait_res = mcspi_wait_for_reg_bit(chstat_reg, OMAP2_MCSPI_CHSTAT_TXS);
+			if (wait_res < 0)
+				dev_err(&spi->dev, "TXS timed out\n");
 		}
+		if (wait_res >= 0 && (mcspi_wait_for_reg_bit(chstat_reg,
+							     OMAP2_MCSPI_CHSTAT_EOT) < 0))
+			dev_err(&spi->dev, "EOT timed out\n");
 	}
+
 	return count;
 }
 
@@ -880,12 +828,12 @@
 	return count - c;
 }
 
-static u32 omap2_mcspi_calc_divisor(u32 speed_hz)
+static u32 omap2_mcspi_calc_divisor(u32 speed_hz, u32 ref_clk_hz)
 {
 	u32 div;
 
 	for (div = 0; div < 15; div++)
-		if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div))
+		if (speed_hz >= (ref_clk_hz >> div))
 			return div;
 
 	return 15;
@@ -897,7 +845,7 @@
 {
 	struct omap2_mcspi_cs *cs = spi->controller_state;
 	struct omap2_mcspi *mcspi;
-	u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0;
+	u32 ref_clk_hz, l = 0, clkd = 0, div, extclk = 0, clkg = 0;
 	u8 word_len = spi->bits_per_word;
 	u32 speed_hz = spi->max_speed_hz;
 
@@ -911,14 +859,15 @@
 	if (t && t->speed_hz)
 		speed_hz = t->speed_hz;
 
-	speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
-	if (speed_hz < (OMAP2_MCSPI_MAX_FREQ / OMAP2_MCSPI_MAX_DIVIDER)) {
-		clkd = omap2_mcspi_calc_divisor(speed_hz);
-		speed_hz = OMAP2_MCSPI_MAX_FREQ >> clkd;
+	ref_clk_hz = mcspi->ref_clk_hz;
+	speed_hz = min_t(u32, speed_hz, ref_clk_hz);
+	if (speed_hz < (ref_clk_hz / OMAP2_MCSPI_MAX_DIVIDER)) {
+		clkd = omap2_mcspi_calc_divisor(speed_hz, ref_clk_hz);
+		speed_hz = ref_clk_hz >> clkd;
 		clkg = 0;
 	} else {
-		div = (OMAP2_MCSPI_MAX_FREQ + speed_hz - 1) / speed_hz;
-		speed_hz = OMAP2_MCSPI_MAX_FREQ / div;
+		div = (ref_clk_hz + speed_hz - 1) / speed_hz;
+		speed_hz = ref_clk_hz / div;
 		clkd = (div - 1) & 0xf;
 		extclk = (div - 1) >> 4;
 		clkg = OMAP2_MCSPI_CHCONF_CLKG;
@@ -1010,9 +959,6 @@
 		mcspi_dma->dma_rx = NULL;
 	}
 
-	init_completion(&mcspi_dma->dma_rx_completion);
-	init_completion(&mcspi_dma->dma_tx_completion);
-
 no_dma:
 	return ret;
 }
@@ -1102,8 +1048,10 @@
 
 	/* Disable IRQ and wakeup slave xfer task */
 	mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQENABLE, 0);
-	if (irqstat & OMAP2_MCSPI_IRQSTATUS_EOW)
-		complete(&mcspi->txdone);
+	if (irqstat & OMAP2_MCSPI_IRQSTATUS_EOW) {
+		complete_all(&mcspi->txrxdone);
+		mcspi_write_reg(mcspi->master, OMAP2_MCSPI_IRQSTATUS, OMAP2_MCSPI_IRQSTATUS_EOW);
+	}
 
 	return IRQ_HANDLED;
 }
@@ -1111,12 +1059,9 @@
 static int omap2_mcspi_slave_abort(struct spi_master *master)
 {
 	struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
-	struct omap2_mcspi_dma *mcspi_dma = mcspi->dma_channels;
 
 	mcspi->slave_aborted = true;
-	complete(&mcspi_dma->dma_rx_completion);
-	complete(&mcspi_dma->dma_tx_completion);
-	complete(&mcspi->txdone);
+	complete_all(&mcspi->txrxdone);
 
 	return 0;
 }
@@ -1448,8 +1393,6 @@
 	master->cleanup = omap2_mcspi_cleanup;
 	master->slave_abort = omap2_mcspi_slave_abort;
 	master->dev.of_node = node;
-	master->max_speed_hz = OMAP2_MCSPI_MAX_FREQ;
-	master->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15;
 	master->use_gpio_descriptors = true;
 
 	platform_set_drvdata(pdev, master);
@@ -1513,7 +1456,7 @@
 		dev_err_probe(&pdev->dev, status, "no irq resource found\n");
 		goto free_master;
 	}
-	init_completion(&mcspi->txdone);
+	init_completion(&mcspi->txrxdone);
 	status = devm_request_irq(&pdev->dev, status,
 				  omap2_mcspi_irq_handler, 0, pdev->name,
 				  mcspi);
@@ -1522,6 +1465,14 @@
 		goto free_master;
 	}
 
+	mcspi->ref_clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
+	if (mcspi->ref_clk)
+		mcspi->ref_clk_hz = clk_get_rate(mcspi->ref_clk);
+	else
+		mcspi->ref_clk_hz = OMAP2_MCSPI_MAX_FREQ;
+	master->max_speed_hz = mcspi->ref_clk_hz;
+	master->min_speed_hz = mcspi->ref_clk_hz >> 15;
+
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
 	pm_runtime_enable(&pdev->dev);
diff -Naur --no-dereference a/drivers/staging/fbtft/fb_ssd1306.c b/drivers/staging/fbtft/fb_ssd1306.c
--- a/drivers/staging/fbtft/fb_ssd1306.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/staging/fbtft/fb_ssd1306.c	2024-01-28 14:01:31.252353813 -0500
@@ -55,6 +55,9 @@
 		write_reg(par, 0x3F);
 	else if (par->info->var.yres == 48)
 		write_reg(par, 0x2F);
+	else if (par->info->var.yres == 39)
+		/* https://libstock.mikroe.com/projects/download/1111/2577/1411057038_oled_b_click___e_mikroc_arm.zip */
+		write_reg(par, 0x27);
 	else
 		write_reg(par, 0x1F);
 
@@ -76,19 +79,27 @@
 	write_reg(par, 0x01);
 
 	/* Set Segment Re-map */
-	/* column address 127 is mapped to SEG0 */
-	write_reg(par, 0xA0 | 0x1);
+	if (par->info->var.yres == 39)
+		/* no segment re-map */
+		write_reg(par, 0xA0 | 0x0);
+	else
+		/* column address 127 is mapped to SEG0 */
+		write_reg(par, 0xA0 | 0x1);
 
 	/* Set COM Output Scan Direction */
-	/* remapped mode. Scan from COM[N-1] to COM0 */
-	write_reg(par, 0xC8);
+	if (par->info->var.yres == 39)
+		/* no columnt re-map mode. Scan from COM0 to COM[N-1] */
+		write_reg(par, 0xC0);
+	else
+		/* remapped mode. Scan from COM[N-1] to COM0 */
+		write_reg(par, 0xC8);
 
 	/* Set COM Pins Hardware Configuration */
 	write_reg(par, 0xDA);
 	if (par->info->var.yres == 64)
 		/* A[4]=1b, Alternative COM pin configuration */
 		write_reg(par, 0x12);
-	else if (par->info->var.yres == 48)
+	else if (par->info->var.yres == 48 || par->info->var.yres == 39)
 		/* A[4]=1b, Alternative COM pin configuration */
 		write_reg(par, 0x12);
 	else
@@ -97,12 +108,18 @@
 
 	/* Set Pre-charge Period */
 	write_reg(par, 0xD9);
-	write_reg(par, 0xF1);
+	if (par->info->var.yres == 39)
+		write_reg(par, 0x25);
+	else
+		write_reg(par, 0xF1);
 
 	/* Set VCOMH Deselect Level */
 	write_reg(par, 0xDB);
-	/* according to the datasheet, this value is out of bounds */
-	write_reg(par, 0x40);
+	if (par->info->var.yres == 39)
+		write_reg(par, 0x20);
+	else
+		/* according to the datasheet, this value is out of bounds */
+		write_reg(par, 0x40);
 
 	/* Entire Display ON */
 	/* Resume to RAM content display. Output follows RAM content */
@@ -133,6 +150,20 @@
 	write_reg(par, 0x5);
 }
 
+static void set_addr_win_96x39(struct fbtft_par *par)
+{
+	/* Set Page Address */
+	write_reg(par, 0xB0);
+	/* Set Column Address */
+	write_reg(par, 0x21);
+	write_reg(par, 0x00);
+	write_reg(par, 0x5F);
+	/* Set Page Address Range */
+	write_reg(par, 0x22);
+	write_reg(par, 0x0);
+	write_reg(par, 0x4);
+}
+
 static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
 {
 	/* Set Lower Column Start Address for Page Addressing Mode */
@@ -144,6 +175,8 @@
 
 	if (par->info->var.xres == 64 && par->info->var.yres == 48)
 		set_addr_win_64x48(par);
+	else if (par->info->var.xres == 96 && par->info->var.yres == 39)
+		set_addr_win_96x39(par);
 }
 
 static int blank(struct fbtft_par *par, bool on)
@@ -188,11 +221,19 @@
 					*buf |= BIT(i);
 			buf++;
 		}
+		if (yres % 8) {
+			*buf = 0x00;
+			for (i = 0; i < (yres - (y * 8)); i++)
+				if (vmem16[(y * 8 + i) * xres + x])
+					*buf |= BIT(i);
+			buf++;
+			y++;
+		}
 	}
 
 	/* Write data */
 	gpiod_set_value(par->gpio.dc, 1);
-	ret = par->fbtftops.write(par, par->txbuf.buf, xres * yres / 8);
+	ret = par->fbtftops.write(par, par->txbuf.buf, xres * (yres / 8 + (yres % 8 != 0)));
 	if (ret < 0)
 		dev_err(par->info->device, "write failed and returned: %d\n",
 			ret);
diff -Naur --no-dereference a/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts b/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts
--- a/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-// Definitions for Pi433
-/dts-v1/;
-/plugin/;
-
-/ {
-	compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
-};
-
-&spi0 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-	status = "okay";
-
-	spidev@0{
-		reg = <0>;
-		status = "disabled";
-	};
-
-	spidev@1{
-		reg = <1>;
-		status = "disabled";
-	};
-};
-
-&gpio {
-	pi433_pins: pi433_pins {
-		brcm,pins = <7 25 24>;
-		brcm,function = <0 0 0>; // in in in
-	};
-};
-
-&spi0 {
-	#address-cells = <1>;
-	#size-cells = <0>;
-	status = "okay";
-
-	pi433: pi433@0 {
-		compatible = "Smarthome-Wolf,pi433";
-		reg = <0>;
-		spi-max-frequency = <10000000>;
-		status = "okay";
-
-		pinctrl-0 = <&pi433_pins>;
-		DIO0-gpio = <&gpio 24 0>;
-		DIO1-gpio = <&gpio 25 0>;
-		DIO2-gpio = <&gpio  7 0>;
-	};
-};
diff -Naur --no-dereference a/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dtso b/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dtso
--- a/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dtso	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dtso	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,48 @@
+// Definitions for Pi433
+/dts-v1/;
+/plugin/;
+
+/ {
+	compatible = "brcm,bcm2835", "brcm,bcm2708", "brcm,bcm2709";
+};
+
+&spi0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	spidev@0{
+		reg = <0>;
+		status = "disabled";
+	};
+
+	spidev@1{
+		reg = <1>;
+		status = "disabled";
+	};
+};
+
+&gpio {
+	pi433_pins: pi433_pins {
+		brcm,pins = <7 25 24>;
+		brcm,function = <0 0 0>; // in in in
+	};
+};
+
+&spi0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	status = "okay";
+
+	pi433: pi433@0 {
+		compatible = "Smarthome-Wolf,pi433";
+		reg = <0>;
+		spi-max-frequency = <10000000>;
+		status = "okay";
+
+		pinctrl-0 = <&pi433_pins>;
+		DIO0-gpio = <&gpio 24 0>;
+		DIO1-gpio = <&gpio 25 0>;
+		DIO2-gpio = <&gpio  7 0>;
+	};
+};
diff -Naur --no-dereference a/drivers/staging/pi433/Documentation/devicetree/pi433.txt b/drivers/staging/pi433/Documentation/devicetree/pi433.txt
--- a/drivers/staging/pi433/Documentation/devicetree/pi433.txt	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/staging/pi433/Documentation/devicetree/pi433.txt	2024-01-28 14:01:31.252353813 -0500
@@ -48,13 +48,13 @@
 =======================
 Since Raspbian supports device tree overlays, you may use an overlay instead
 of editing your boards device tree.
-To use the overlay, you need to compile the file pi433-overlay.dts which can
+To use the overlay, you need to compile the file pi433-overlay.dtso which can
 be found alongside this documentation.
 The file needs to be compiled - either manually or by integration in your kernel
 source tree. For a manual compile, you may use a command line like the following:
-'linux/scripts/dtc/dtc -@ -I dts -O dtb -o pi433.dtbo pi433-overlay.dts'
+'linux/scripts/dtc/dtc -@ -I dts -O dtb -o pi433.dtbo pi433-overlay.dtso'
 
-For compiling inside of the kernel tree, you need to copy pi433-overlay.dts to
+For compiling inside of the kernel tree, you need to copy pi433-overlay.dtso to
 arch/arm/boot/dts/overlays and you need to add the file to the list of files
 in the Makefile over there. Execute 'make dtbs' in kernel tree root to make the
 kernel make files compile the device tree overlay for you.
diff -Naur --no-dereference a/drivers/thermal/k3_j72xx_bandgap.c b/drivers/thermal/k3_j72xx_bandgap.c
--- a/drivers/thermal/k3_j72xx_bandgap.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/thermal/k3_j72xx_bandgap.c	2024-01-28 14:01:31.252353813 -0500
@@ -19,6 +19,9 @@
 #include <linux/of.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/cpufreq.h>
+#include <linux/cpumask.h>
+#include <linux/cpu_cooling.h>
 
 #define K3_VTM_DEVINFO_PWR0_OFFSET		0x4
 #define K3_VTM_DEVINFO_PWR0_TEMPSENS_CT_MASK	0xf0
@@ -177,17 +180,34 @@
 	struct device *dev;
 	void __iomem *base;
 	void __iomem *cfg2_base;
-	void __iomem *fuse_base;
 	struct k3_thermal_data *ts_data[K3_VTM_MAX_NUM_TS];
 };
 
 /* common data structures */
 struct k3_thermal_data {
 	struct k3_j72xx_bandgap *bgp;
+	struct cpufreq_policy *policy;
+	struct thermal_zone_device *ti_thermal;
+	struct thermal_cooling_device *cool_dev;
+	struct work_struct thermal_wq;
 	u32 ctrl_offset;
 	u32 stat_offset;
+	enum thermal_device_mode mode;
+	int prev_temp;
+	int sensor_id;
 };
 
+static void k3_thermal_work(struct work_struct *work)
+{
+	struct k3_thermal_data *data = container_of(work,
+					struct k3_thermal_data, thermal_wq);
+
+	thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED);
+
+	dev_info(&data->ti_thermal->device, "updated thermal zone %s\n",
+		 data->ti_thermal->type);
+}
+
 static int two_cmp(int tmp, int mask)
 {
 	tmp = ~(tmp);
@@ -249,18 +269,44 @@
 /* Get temperature callback function for thermal zone */
 static int k3_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
 {
+	return k3_bgp_read_temp(tz->devdata, temp);
+}
+
+static int k3_thermal_get_trend(struct thermal_zone_device *tz, int trip, enum thermal_trend *trend)
+{
 	struct k3_thermal_data *data = tz->devdata;
-	int ret = 0;
+	struct k3_j72xx_bandgap *bgp;
+	u32 temp1, temp2;
+	int id, tr, ret = 0;
+
+	bgp = data->bgp;
+	id = data->sensor_id;
 
-	ret = k3_bgp_read_temp(data, temp);
+	ret = k3_thermal_get_temp(tz, &temp1);
 	if (ret)
 		return ret;
+	temp2 = data->prev_temp;
+
+	tr = temp1 - temp2;
+
+	data->prev_temp = temp1;
+
+	if (tr > 0)
+		*trend = THERMAL_TREND_RAISING;
+	else if (tr < 0)
+		*trend = THERMAL_TREND_DROPPING;
+	else
+		*trend = THERMAL_TREND_STABLE;
+
+	dev_dbg(bgp->dev, "The temperatures are t1 = %d and t2 = %d and trend =%d\n",
+		temp1, temp2, *trend);
 
 	return ret;
 }
 
 static const struct thermal_zone_device_ops k3_of_thermal_ops = {
 	.get_temp = k3_thermal_get_temp,
+	.get_trend = k3_thermal_get_trend,
 };
 
 static int k3_j72xx_bandgap_temp_to_adc_code(int temp)
@@ -283,7 +329,7 @@
 }
 
 static void get_efuse_values(int id, struct k3_thermal_data *data, int *err,
-			     struct k3_j72xx_bandgap *bgp)
+			     void __iomem *fuse_base)
 {
 	int i, tmp, pow;
 	int ct_offsets[5][K3_VTM_CORRECTION_TEMP_CNT] = {
@@ -305,16 +351,16 @@
 		/* Extract the offset value using bit-mask */
 		if (ct_offsets[id][i] == -1 && i == 1) {
 			/* 25C offset Case of Sensor 2 split between 2 regs */
-			tmp = (readl(bgp->fuse_base + 0x8) & 0xE0000000) >> (29);
-			tmp |= ((readl(bgp->fuse_base + 0xC) & 0x1F) << 3);
+			tmp = (readl(fuse_base + 0x8) & 0xE0000000) >> (29);
+			tmp |= ((readl(fuse_base + 0xC) & 0x1F) << 3);
 			pow = tmp & 0x80;
 		} else if (ct_offsets[id][i] == -1 && i == 2) {
 			/* 125C Case of Sensor 3 split between 2 regs */
-			tmp = (readl(bgp->fuse_base + 0x4) & 0xF8000000) >> (27);
-			tmp |= ((readl(bgp->fuse_base + 0x8) & 0xF) << 5);
+			tmp = (readl(fuse_base + 0x4) & 0xF8000000) >> (27);
+			tmp |= ((readl(fuse_base + 0x8) & 0xF) << 5);
 			pow = tmp & 0x100;
 		} else {
-			tmp = readl(bgp->fuse_base + ct_offsets[id][i]);
+			tmp = readl(fuse_base + ct_offsets[id][i]);
 			tmp &= ct_bm[id][i];
 			tmp = tmp >> __ffs(ct_bm[id][i]);
 
@@ -347,9 +393,66 @@
 }
 
 struct k3_j72xx_bandgap_data {
-	unsigned int has_errata_i2128;
+	const bool has_errata_i2128;
 };
 
+int k3_thermal_register_cpu_cooling(struct k3_j72xx_bandgap *bgp, int id)
+{
+	struct k3_thermal_data *data;
+	struct device_node *np = bgp->dev->of_node;
+
+	/*
+	 * We are assuming here that if one deploys the zone
+	 * using DT, then it must be aware that the cooling device
+	 * loading has to happen via cpufreq driver.
+	 */
+	if (of_find_property(np, "#thermal-sensor-cells", NULL))
+		return 0;
+
+	data = bgp->ts_data[id];
+	if (!data)
+		return -EINVAL;
+
+	data->policy = cpufreq_cpu_get(0);
+	if (!data->policy) {
+		pr_debug("%s: CPUFreq policy not found\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	/* Register cooling device */
+	data->cool_dev = cpufreq_cooling_register(data->policy);
+	if (IS_ERR(data->cool_dev)) {
+		int ret = PTR_ERR(data->cool_dev);
+
+		dev_err(bgp->dev, "Failed to register cpu cooling device %d\n",
+			ret);
+		cpufreq_cpu_put(data->policy);
+
+		return ret;
+	}
+
+	data->mode = THERMAL_DEVICE_ENABLED;
+
+	INIT_WORK(&data->thermal_wq, k3_thermal_work);
+
+	return 0;
+}
+
+int ti_thermal_unregister_cpu_cooling(struct k3_j72xx_bandgap *bgp, int id)
+{
+	struct k3_thermal_data *data;
+
+	data = bgp->ts_data[id];
+
+	if (!IS_ERR_OR_NULL(data)) {
+		cpufreq_cooling_unregister(data->cool_dev);
+		if (data->policy)
+			cpufreq_cpu_put(data->policy);
+	}
+
+	return 0;
+}
+
 static int k3_j72xx_bandgap_probe(struct platform_device *pdev)
 {
 	int ret = 0, cnt, val, id;
@@ -358,11 +461,12 @@
 	struct device *dev = &pdev->dev;
 	struct k3_j72xx_bandgap *bgp;
 	struct k3_thermal_data *data;
-	int workaround_needed = 0;
+	bool workaround_needed = false;
 	const struct k3_j72xx_bandgap_data *driver_data;
 	struct thermal_zone_device *ti_thermal;
 	int *ref_table;
 	struct err_values err_vals;
+	void __iomem *fuse_base;
 
 	const s64 golden_factors[] = {
 		-490019999999999936,
@@ -393,15 +497,32 @@
 	if (IS_ERR(bgp->cfg2_base))
 		return PTR_ERR(bgp->cfg2_base);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-	bgp->fuse_base = devm_ioremap_resource(dev, res);
-	if (IS_ERR(bgp->fuse_base))
-		return PTR_ERR(bgp->fuse_base);
-
 	driver_data = of_device_get_match_data(dev);
 	if (driver_data)
 		workaround_needed = driver_data->has_errata_i2128;
 
+	/*
+	 * Some of TI's J721E SoCs require a software trimming procedure
+	 * for the temperature monitors to function properly. To determine
+	 * if this particular SoC is NOT affected, both bits in the
+	 * WKUP_SPARE_FUSE0[31:30] will be set (0xC0000000) indicating
+	 * when software trimming should NOT be applied.
+	 *
+	 * https://www.ti.com/lit/er/sprz455c/sprz455c.pdf
+	 */
+	if (workaround_needed) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+		fuse_base = devm_ioremap_resource(dev, res);
+		if (IS_ERR(fuse_base))
+			return PTR_ERR(fuse_base);
+
+		if ((readl(fuse_base) & 0xc0000000) == 0xc0000000)
+			workaround_needed = false;
+	}
+
+	dev_dbg(bgp->dev, "Work around %sneeded\n",
+		workaround_needed ? "" : "not ");
+
 	pm_runtime_enable(dev);
 	ret = pm_runtime_get_sync(dev);
 	if (ret < 0) {
@@ -434,13 +555,6 @@
 		goto err_free_ref_table;
 	}
 
-	/* Workaround not needed if bit30/bit31 is set even for J721e */
-	if (workaround_needed && (readl(bgp->fuse_base + 0x0) & 0xc0000000) == 0xc0000000)
-		workaround_needed = false;
-
-	dev_dbg(bgp->dev, "Work around %sneeded\n",
-		workaround_needed ? "" : "not ");
-
 	if (!workaround_needed)
 		init_table(5, ref_table, golden_factors);
 	else
@@ -449,6 +563,7 @@
 	/* Register the thermal sensors */
 	for (id = 0; id < cnt; id++) {
 		data[id].bgp = bgp;
+		data[id].sensor_id = id;
 		data[id].ctrl_offset = K3_VTM_TMPSENS0_CTRL_OFFSET + id * 0x20;
 		data[id].stat_offset = data[id].ctrl_offset +
 					K3_VTM_TMPSENS_STAT_OFFSET;
@@ -459,7 +574,7 @@
 			err_vals.refs[1] = PLUS30CREF;
 			err_vals.refs[2] = PLUS125CREF;
 			err_vals.refs[3] = PLUS150CREF;
-			get_efuse_values(id, &data[id], err_vals.errs, bgp);
+			get_efuse_values(id, &data[id], err_vals.errs, fuse_base);
 		}
 
 		if (id == 0 && workaround_needed)
@@ -474,6 +589,12 @@
 		writel(val, data[id].bgp->cfg2_base + data[id].ctrl_offset);
 
 		bgp->ts_data[id] = &data[id];
+
+		if (id == 1)
+			ret = k3_thermal_register_cpu_cooling(bgp, 1);
+		if (ret)
+			goto err_alloc;
+
 		ti_thermal = devm_thermal_of_zone_register(bgp->dev, id, &data[id],
 							   &k3_of_thermal_ops);
 		if (IS_ERR(ti_thermal)) {
@@ -529,11 +650,11 @@
 }
 
 static const struct k3_j72xx_bandgap_data k3_j72xx_bandgap_j721e_data = {
-	.has_errata_i2128 = 1,
+	.has_errata_i2128 = true,
 };
 
 static const struct k3_j72xx_bandgap_data k3_j72xx_bandgap_j7200_data = {
-	.has_errata_i2128 = 0,
+	.has_errata_i2128 = false,
 };
 
 static const struct of_device_id of_k3_j72xx_bandgap_match[] = {
diff -Naur --no-dereference a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
--- a/drivers/tty/serial/8250/8250_omap.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/tty/serial/8250/8250_omap.c	2024-01-28 14:01:31.252353813 -0500
@@ -27,6 +27,7 @@
 #include <linux/pm_qos.h>
 #include <linux/pm_wakeirq.h>
 #include <linux/dma-mapping.h>
+#include <linux/reboot.h>
 #include <linux/sys_soc.h>
 
 #include "8250.h"
@@ -126,7 +127,6 @@
 	u8 rx_trigger;
 	bool is_suspending;
 	int wakeirq;
-	int wakeups_enabled;
 	u32 latency;
 	u32 calc_latency;
 	struct pm_qos_request pm_qos_request;
@@ -135,6 +135,10 @@
 	spinlock_t rx_dma_lock;
 	bool rx_dma_broken;
 	bool throttled;
+
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *pinctrl_default;
+	struct pinctrl_state *pinctrl_wakeup;
 };
 
 struct omap8250_dma_params {
@@ -1235,6 +1239,28 @@
 	return 0;
 }
 
+static int omap8250_sysoff_handler(struct sys_off_data *data)
+{
+	struct omap8250_priv *priv = dev_get_drvdata(data->dev);
+	int ret;
+
+	dev_dbg(data->dev, "sysoff handler\n");
+
+	if (IS_ERR_OR_NULL(priv->pinctrl_wakeup))
+		return NOTIFY_DONE;
+
+	if (!device_may_wakeup(data->dev))
+		return NOTIFY_DONE;
+
+	ret = pinctrl_select_state(priv->pinctrl, priv->pinctrl_wakeup);
+	if (ret)
+		dev_err(data->dev, "Failed to select pinctrl state 'wakeup', continuing poweroff\n");
+
+	dev_dbg(data->dev, "Setup wakeup pinctrl\n");
+
+	return NOTIFY_DONE;
+}
+
 static struct omap8250_dma_params am654_dma = {
 	.rx_size = SZ_2K,
 	.rx_trigger = 1,
@@ -1396,7 +1422,7 @@
 
 	platform_set_drvdata(pdev, priv);
 
-	device_init_wakeup(&pdev->dev, true);
+	device_set_wakeup_capable(&pdev->dev, true);
 	pm_runtime_enable(&pdev->dev);
 	pm_runtime_use_autosuspend(&pdev->dev);
 
@@ -1459,6 +1485,18 @@
 	priv->line = ret;
 	pm_runtime_mark_last_busy(&pdev->dev);
 	pm_runtime_put_autosuspend(&pdev->dev);
+
+	priv->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (!IS_ERR_OR_NULL(priv->pinctrl)) {
+		priv->pinctrl_default = pinctrl_lookup_state(priv->pinctrl, "default");
+		priv->pinctrl_wakeup = pinctrl_lookup_state(priv->pinctrl, "wakeup");
+	}
+
+	devm_register_sys_off_handler(&pdev->dev,
+				      SYS_OFF_MODE_POWER_OFF_PREPARE,
+				      SYS_OFF_PRIO_DEFAULT,
+				      omap8250_sysoff_handler, NULL);
+
 	return 0;
 err:
 	pm_runtime_dont_use_autosuspend(&pdev->dev);
@@ -1692,10 +1730,10 @@
 	}
 
 	add_preferred_console("ttyS", idx, options);
-	pr_err("WARNING: Your 'console=ttyO%d' has been replaced by 'ttyS%d'\n",
+	pr_info("WARNING: Your 'console=ttyO%d' has been replaced by 'ttyS%d'\n",
 	       idx, idx);
-	pr_err("This ensures that you still see kernel messages. Please\n");
-	pr_err("update your kernel commandline.\n");
+	pr_info("This ensures that you still see kernel messages. Please\n");
+	pr_info("update your kernel commandline.\n");
 	return 0;
 }
 console_initcall(omap8250_console_fixup);
diff -Naur --no-dereference a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
--- a/drivers/tty/serial/8250/8250_port.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/tty/serial/8250/8250_port.c	2024-01-28 14:01:31.252353813 -0500
@@ -543,11 +543,30 @@
  */
 static void serial8250_clear_fifos(struct uart_8250_port *p)
 {
+	unsigned char fcr;
+	unsigned char clr_mask = UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT;
+
 	if (p->capabilities & UART_CAP_FIFO) {
-		serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO);
-		serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO |
-			       UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
-		serial_out(p, UART_FCR, 0);
+		/*
+		 * Make sure to avoid changing FCR[7:3] and ENABLE_FIFO bits.
+		 * In case ENABLE_FIFO is not set, there is nothing to flush
+		 * so just return. Furthermore, on certain implementations of
+		 * the 8250 core, the FCR[7:3] bits may only be changed under
+		 * specific conditions and changing them if those conditions
+		 * are not met can have nasty side effects. One such core is
+		 * the 8250-omap present in TI AM335x.
+		 */
+		fcr = serial_in(p, UART_FCR);
+
+		/* FIFO is not enabled, there's nothing to clear. */
+		if (!(fcr & UART_FCR_ENABLE_FIFO))
+			return;
+
+		fcr |= clr_mask;
+		serial_out(p, UART_FCR, fcr);
+
+		fcr &= ~clr_mask;
+		serial_out(p, UART_FCR, fcr);
 	}
 }
 
@@ -1451,7 +1470,7 @@
 	 * Enable previously disabled RX interrupts.
 	 */
 	if (!(p->port.rs485.flags & SER_RS485_RX_DURING_TX)) {
-		serial8250_clear_and_reinit_fifos(p);
+		serial8250_clear_fifos(p);
 
 		p->ier |= UART_IER_RLSI | UART_IER_RDI;
 		serial_port_out(&p->port, UART_IER, p->ier);
diff -Naur --no-dereference a/drivers/tty/serial/8250/8250_pruss.c b/drivers/tty/serial/8250/8250_pruss.c
--- a/drivers/tty/serial/8250/8250_pruss.c	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/tty/serial/8250/8250_pruss.c	2024-01-28 14:01:31.252353813 -0500
@@ -0,0 +1,214 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  Serial Port driver for PRUSS UART on TI platforms
+ *
+ *  Copyright (C) 2020-2021 by Texas Instruments Incorporated - http://www.ti.com/
+ *  Author: Bin Liu <b-liu@ti.com>
+ */
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/serial_reg.h>
+#include <linux/serial_core.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/remoteproc.h>
+#include "8250.h"
+
+#define DEFAULT_CLK_SPEED	192000000
+
+/* extra registers */
+#define PRUSS_UART_PEREMU_MGMT	12
+#define PRUSS_UART_TX_EN	BIT(14)
+#define PRUSS_UART_RX_EN	BIT(13)
+#define PRUSS_UART_FREE_RUN	BIT(0)
+
+#define PRUSS_UART_MDR			13
+#define PRUSS_UART_MDR_OSM_SEL_MASK	BIT(0)
+#define PRUSS_UART_MDR_16X_MODE		0
+#define PRUSS_UART_MDR_13X_MODE		1
+
+struct pruss8250_info {
+	int type;
+	int line;
+};
+
+static inline void uart_writel(struct uart_port *p, u32 offset, int value)
+{
+	writel(value, p->membase + (offset << p->regshift));
+}
+
+static int pruss8250_startup(struct uart_port *port)
+{
+	int ret;
+
+	uart_writel(port, PRUSS_UART_PEREMU_MGMT, 0);
+
+	ret = serial8250_do_startup(port);
+	if (!ret)
+		uart_writel(port, PRUSS_UART_PEREMU_MGMT, PRUSS_UART_TX_EN |
+							  PRUSS_UART_RX_EN |
+							  PRUSS_UART_FREE_RUN);
+	return ret;
+}
+
+static unsigned int pruss8250_get_divisor(struct uart_port *port,
+					  unsigned int baud,
+					  unsigned int *frac)
+{
+	unsigned int uartclk = port->uartclk;
+	unsigned int div_13, div_16;
+	unsigned int abs_d13, abs_d16;
+	u16 quot;
+
+	/* Old custom speed handling */
+	if (baud == 38400 && (port->flags & UPF_SPD_MASK) == UPF_SPD_CUST) {
+		quot = port->custom_divisor & UART_DIV_MAX;
+		if (port->custom_divisor & (1 << 16))
+			*frac = PRUSS_UART_MDR_13X_MODE;
+		else
+			*frac = PRUSS_UART_MDR_16X_MODE;
+
+		return quot;
+	}
+
+	div_13 = DIV_ROUND_CLOSEST(uartclk, 13 * baud);
+	div_16 = DIV_ROUND_CLOSEST(uartclk, 16 * baud);
+	div_13 = div_13 ? : 1;
+	div_16 = div_16 ? : 1;
+
+	abs_d13 = abs(baud - uartclk / 13 / div_13);
+	abs_d16 = abs(baud - uartclk / 16 / div_16);
+
+	if (abs_d13 >= abs_d16) {
+		*frac = PRUSS_UART_MDR_16X_MODE;
+		quot = div_16;
+	} else {
+		*frac = PRUSS_UART_MDR_13X_MODE;
+		quot = div_13;
+	}
+
+	return quot;
+}
+
+static void pruss8250_set_divisor(struct uart_port *port, unsigned int baud,
+				  unsigned int quot, unsigned int quot_frac)
+{
+	serial8250_do_set_divisor(port, baud, quot, quot_frac);
+	/*
+	 * quot_frac holds the MDR over-sampling mode
+	 * which is set in pruss8250_get_divisor()
+	 */
+	quot_frac &= PRUSS_UART_MDR_OSM_SEL_MASK;
+	serial_port_out(port, PRUSS_UART_MDR, quot_frac);
+}
+
+static int pruss8250_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct uart_8250_port port8250;
+	struct uart_port *up = &port8250.port;
+	struct pruss8250_info *info;
+	struct resource resource;
+	unsigned int port_type;
+	struct clk *clk;
+	int ret;
+
+	port_type = (unsigned long)of_device_get_match_data(&pdev->dev);
+	if (port_type == PORT_UNKNOWN)
+		return -EINVAL;
+
+	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	memset(&port8250, 0, sizeof(port8250));
+
+	ret = of_address_to_resource(np, 0, &resource);
+	if (ret) {
+		dev_err(&pdev->dev, "invalid address\n");
+		return ret;
+	}
+
+	ret = of_alias_get_id(np, "serial");
+	if (ret > 0)
+		up->line = ret;
+
+	clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		if (PTR_ERR(clk) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		up->uartclk = DEFAULT_CLK_SPEED;
+	} else {
+		up->uartclk = clk_get_rate(clk);
+		devm_clk_put(&pdev->dev, clk);
+	}
+
+	up->dev = &pdev->dev;
+	up->mapbase = resource.start;
+	up->mapsize = resource_size(&resource);
+	up->type = port_type;
+	up->iotype = UPIO_MEM;
+	up->regshift = 2;
+	up->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_FIXED_PORT |
+		    UPF_FIXED_TYPE | UPF_IOREMAP;
+	up->irqflags |= IRQF_SHARED;
+	up->startup = pruss8250_startup;
+	up->rs485_config = serial8250_em485_config;
+	up->get_divisor = pruss8250_get_divisor;
+	up->set_divisor = pruss8250_set_divisor;
+
+	ret = of_irq_get(np, 0);
+	if (ret < 0) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "missing irq\n");
+		return ret;
+	}
+
+	up->irq = ret;
+	spin_lock_init(&port8250.port.lock);
+	port8250.capabilities = UART_CAP_FIFO | UART_CAP_AFE;
+
+	ret = serial8250_register_8250_port(&port8250);
+	if (ret < 0)
+		goto err_dispose;
+
+	info->type = port_type;
+	info->line = ret;
+	platform_set_drvdata(pdev, info);
+
+	return 0;
+
+err_dispose:
+	irq_dispose_mapping(port8250.port.irq);
+	return ret;
+}
+
+static int pruss8250_remove(struct platform_device *pdev)
+{
+	struct pruss8250_info *info = platform_get_drvdata(pdev);
+
+	serial8250_unregister_port(info->line);
+	return 0;
+}
+
+static const struct of_device_id pruss8250_table[] = {
+	{ .compatible = "ti,pruss-uart", .data = (void *)PORT_16550A, },
+	{ /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, pruss8250_table);
+
+static struct platform_driver pruss8250_driver = {
+	.driver = {
+		.name = "pruss8250",
+		.of_match_table = pruss8250_table,
+	},
+	.probe = pruss8250_probe,
+	.remove = pruss8250_remove,
+};
+
+module_platform_driver(pruss8250_driver);
+
+MODULE_AUTHOR("Bin Liu <b-liu@ti.com");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Serial Port driver for PRUSS UART on TI platforms");
diff -Naur --no-dereference a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
--- a/drivers/tty/serial/8250/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/tty/serial/8250/Kconfig	2024-01-28 14:01:31.252353813 -0500
@@ -539,6 +539,16 @@
 	  including DMA support and high accuracy BAUD rates, say
 	  Y to this option. If unsure, say N.
 
+config SERIAL_8250_PRUSS
+	tristate "TI PRU-ICSS UART support"
+	depends on SERIAL_8250
+	depends on PRU_REMOTEPROC && TI_PRUSS_INTC
+	help
+	  This driver is to support the UART module in PRU-ICSS which is
+	  available in some TI platforms.
+	  Say 'Y' here if you wish to use PRU-ICSS UART.
+	  Otherwise, say 'N'.
+
 config SERIAL_OF_PLATFORM
 	tristate "Devicetree based probing for 8250 ports"
 	depends on SERIAL_8250 && OF
diff -Naur --no-dereference a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
--- a/drivers/tty/serial/8250/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/tty/serial/8250/Makefile	2024-01-28 14:01:31.252353813 -0500
@@ -39,6 +39,7 @@
 obj-$(CONFIG_SERIAL_8250_LPSS)		+= 8250_lpss.o
 obj-$(CONFIG_SERIAL_8250_MID)		+= 8250_mid.o
 obj-$(CONFIG_SERIAL_8250_PERICOM)	+= 8250_pericom.o
+obj-$(CONFIG_SERIAL_8250_PRUSS)		+= 8250_pruss.o
 obj-$(CONFIG_SERIAL_8250_PXA)		+= 8250_pxa.o
 obj-$(CONFIG_SERIAL_8250_TEGRA)		+= 8250_tegra.o
 obj-$(CONFIG_SERIAL_8250_BCM7271)	+= 8250_bcm7271.o
diff -Naur --no-dereference a/drivers/ufs/host/ti-j721e-ufs.c b/drivers/ufs/host/ti-j721e-ufs.c
--- a/drivers/ufs/host/ti-j721e-ufs.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/ufs/host/ti-j721e-ufs.c	2024-01-28 14:01:31.252353813 -0500
@@ -81,6 +81,8 @@
 	{ },
 };
 
+MODULE_DEVICE_TABLE(of, ti_j721e_ufs_of_match);
+
 static struct platform_driver ti_j721e_ufs_driver = {
 	.probe	= ti_j721e_ufs_probe,
 	.remove	= ti_j721e_ufs_remove,
diff -Naur --no-dereference a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
--- a/drivers/uio/uio_pdrv_genirq.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/uio/uio_pdrv_genirq.c	2024-01-28 14:01:31.252353813 -0500
@@ -276,11 +276,13 @@
 
 #ifdef CONFIG_OF
 static struct of_device_id uio_of_genirq_match[] = {
+	{ .compatible = "uio" },
+	{ .compatible = "ti,pruss-shmem" },
 	{ /* This is filled with module_parm */ },
 	{ /* Sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, uio_of_genirq_match);
-module_param_string(of_id, uio_of_genirq_match[0].compatible, 128, 0);
+module_param_string(of_id, uio_of_genirq_match[2].compatible, 128, 0);
 MODULE_PARM_DESC(of_id, "Openfirmware id of the device to be handled by uio");
 #endif
 
diff -Naur --no-dereference a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
--- a/drivers/uio/uio_pruss.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/uio/uio_pruss.c	2024-01-28 14:01:31.252353813 -0500
@@ -1,4 +1,3 @@
-// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Programmable Real-Time Unit Sub System (PRUSS) UIO driver (uio_pruss)
  *
@@ -6,6 +5,15 @@
  * and DDR RAM to user space for applications interacting with PRUSS firmware
  *
  * Copyright (C) 2010-11 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 #include <linux/device.h>
 #include <linux/module.h>
@@ -18,14 +26,22 @@
 #include <linux/dma-mapping.h>
 #include <linux/sizes.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#ifdef CONFIG_ARCH_DAVINCI_DA850
 #include <linux/genalloc.h>
+#else
+#include <linux/pm_runtime.h>
+#endif
 
 #define DRV_NAME "pruss_uio"
 #define DRV_VERSION "1.0"
 
+#ifdef CONFIG_ARCH_DAVINCI_DA850
 static int sram_pool_sz = SZ_16K;
 module_param(sram_pool_sz, int, 0);
-MODULE_PARM_DESC(sram_pool_sz, "sram pool size to allocate ");
+MODULE_PARM_DESC(sram_pool_sz, "sram pool size to allocate");
+#endif
+
 
 static int extram_pool_sz = SZ_256K;
 module_param(extram_pool_sz, int, 0);
@@ -53,22 +69,23 @@
 #define PINTC_HIER	0x1500
 
 struct uio_pruss_dev {
-	struct uio_info *info;
-	struct clk *pruss_clk;
-	dma_addr_t sram_paddr;
+	struct uio_info info[MAX_PRUSS_EVT];
 	dma_addr_t ddr_paddr;
 	void __iomem *prussio_vaddr;
-	unsigned long sram_vaddr;
 	void *ddr_vaddr;
-	unsigned int hostirq_start;
 	unsigned int pintc_base;
+#ifdef CONFIG_ARCH_DAVINCI_DA850
+	struct clk *pruss_clk;
 	struct gen_pool *sram_pool;
+	dma_addr_t sram_paddr;
+	unsigned long sram_vaddr;
+#endif
 };
 
 static irqreturn_t pruss_handler(int irq, struct uio_info *info)
 {
 	struct uio_pruss_dev *gdev = info->priv;
-	int intr_bit = (irq - gdev->hostirq_start + 2);
+	int intr_bit = 2 + (info - gdev->info);
 	int val, intr_mask = (1 << intr_bit);
 	void __iomem *base = gdev->prussio_vaddr + gdev->pintc_base;
 	void __iomem *intren_reg = base + PINTC_HIER;
@@ -86,53 +103,66 @@
 
 static void pruss_cleanup(struct device *dev, struct uio_pruss_dev *gdev)
 {
-	int cnt;
-	struct uio_info *p = gdev->info;
+	int i;
 
-	for (cnt = 0; cnt < MAX_PRUSS_EVT; cnt++, p++) {
-		uio_unregister_device(p);
+	for (i = 0; i < MAX_PRUSS_EVT; i++) {
+		uio_unregister_device(&gdev->info[i]);
+		kfree(gdev->info[i].name);
 	}
 	iounmap(gdev->prussio_vaddr);
 	if (gdev->ddr_vaddr) {
 		dma_free_coherent(dev, extram_pool_sz, gdev->ddr_vaddr,
 			gdev->ddr_paddr);
 	}
+#ifdef CONFIG_ARCH_DAVINCI_DA850
 	if (gdev->sram_vaddr)
 		gen_pool_free(gdev->sram_pool,
 			      gdev->sram_vaddr,
 			      sram_pool_sz);
 	clk_disable(gdev->pruss_clk);
+	clk_put(gdev->pruss_clk);
+#else
+	pm_runtime_put(dev);
+	pm_runtime_disable(dev);
+#endif
+	kfree(gdev);
 }
 
 static int pruss_probe(struct platform_device *pdev)
 {
-	struct uio_info *p;
 	struct uio_pruss_dev *gdev;
 	struct resource *regs_prussio;
 	struct device *dev = &pdev->dev;
-	int ret, cnt, i, len;
+	int ret, i, len;
 	struct uio_pruss_pdata *pdata = dev_get_platdata(dev);
 
-	gdev = devm_kzalloc(dev, sizeof(struct uio_pruss_dev), GFP_KERNEL);
+	gdev = kzalloc(sizeof(struct uio_pruss_dev), GFP_KERNEL);
 	if (!gdev)
 		return -ENOMEM;
 
-	gdev->info = devm_kcalloc(dev, MAX_PRUSS_EVT, sizeof(*p), GFP_KERNEL);
-	if (!gdev->info)
-		return -ENOMEM;
-
+#ifdef CONFIG_ARCH_DAVINCI_DA850
 	/* Power on PRU in case its not done as part of boot-loader */
-	gdev->pruss_clk = devm_clk_get(dev, "pruss");
+	gdev->pruss_clk = clk_get(dev, "pruss");
 	if (IS_ERR(gdev->pruss_clk)) {
 		dev_err(dev, "Failed to get clock\n");
-		return PTR_ERR(gdev->pruss_clk);
+		ret = PTR_ERR(gdev->pruss_clk);
+		goto err_free_gdev;
 	}
 
 	ret = clk_enable(gdev->pruss_clk);
 	if (ret) {
 		dev_err(dev, "Failed to enable clock\n");
-		return ret;
+		goto err_clk_put;
+	}
+#else
+	pm_runtime_enable(dev);
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		dev_err(dev, "pm_runtime_get_sync() failed\n");
+		pm_runtime_disable(dev);
+		goto err_free_gdev;
 	}
+#endif
 
 	regs_prussio = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!regs_prussio) {
@@ -147,6 +177,18 @@
 		goto err_clk_disable;
 	}
 
+	if (dev->of_node) {
+		ret = of_property_read_u32(dev->of_node,
+					   "ti,pintc-offset",
+					   &gdev->pintc_base);
+		if (ret < 0) {
+			dev_err(dev, "Can't parse ti,pintc-offset property\n");
+			goto err_clk_disable;
+		}
+	} else
+		gdev->pintc_base = pdata->pintc_base;
+
+#ifdef CONFIG_ARCH_DAVINCI_DA850
 	if (pdata->sram_pool) {
 		gdev->sram_pool = pdata->sram_pool;
 		gdev->sram_vaddr =
@@ -158,9 +200,10 @@
 			goto err_clk_disable;
 		}
 	}
+#endif
 
 	gdev->ddr_vaddr = dma_alloc_coherent(dev, extram_pool_sz,
-				&(gdev->ddr_paddr), GFP_KERNEL | GFP_DMA);
+				&gdev->ddr_paddr, GFP_KERNEL | GFP_DMA);
 	if (!gdev->ddr_vaddr) {
 		dev_err(dev, "Could not allocate external memory\n");
 		ret = -ENOMEM;
@@ -170,56 +213,85 @@
 	len = resource_size(regs_prussio);
 	gdev->prussio_vaddr = ioremap(regs_prussio->start, len);
 	if (!gdev->prussio_vaddr) {
-		dev_err(dev, "Can't remap PRUSS I/O  address range\n");
+		dev_err(dev, "Can't remap PRUSS I/O address range\n");
 		ret = -ENOMEM;
 		goto err_free_ddr_vaddr;
 	}
 
-	gdev->pintc_base = pdata->pintc_base;
-	gdev->hostirq_start = platform_get_irq(pdev, 0);
+	for (i = 0; i < MAX_PRUSS_EVT; i++) {
+		struct uio_info *p = &gdev->info[i];
 
-	for (cnt = 0, p = gdev->info; cnt < MAX_PRUSS_EVT; cnt++, p++) {
+		p->mem[0].name = "pruss";
 		p->mem[0].addr = regs_prussio->start;
 		p->mem[0].size = resource_size(regs_prussio);
 		p->mem[0].memtype = UIO_MEM_PHYS;
 
+		/* note: some userspace code uses hardcoded mem indices... */
+#ifdef CONFIG_ARCH_DAVINCI_DA850
+		p->mem[1].name = "sram";
 		p->mem[1].addr = gdev->sram_paddr;
 		p->mem[1].size = sram_pool_sz;
 		p->mem[1].memtype = UIO_MEM_PHYS;
 
+		p->mem[2].name = "ddr";
 		p->mem[2].addr = gdev->ddr_paddr;
 		p->mem[2].size = extram_pool_sz;
 		p->mem[2].memtype = UIO_MEM_PHYS;
+#else
+		p->mem[1].name = "ddr";
+		p->mem[1].addr = gdev->ddr_paddr;
+		p->mem[1].size = extram_pool_sz;
+		p->mem[1].memtype = UIO_MEM_PHYS;
+#endif
 
-		p->name = devm_kasprintf(dev, GFP_KERNEL, "pruss_evt%d", cnt);
+		ret = platform_get_irq(pdev, i);
+		if (ret < 0) {
+			dev_err(dev, "Failed to obtain irq %d (%d)\n", i, ret);
+			goto err_unloop;
+		}
+
+		p->name = kasprintf(GFP_KERNEL, "pruss_evt%d", i);
 		p->version = DRV_VERSION;
 
 		/* Register PRUSS IRQ lines */
-		p->irq = gdev->hostirq_start + cnt;
+		p->irq = ret;
 		p->handler = pruss_handler;
 		p->priv = gdev;
 
 		ret = uio_register_device(dev, p);
-		if (ret < 0)
+		if (ret < 0) {
+			kfree(p->name);
 			goto err_unloop;
+		}
 	}
 
 	platform_set_drvdata(pdev, gdev);
 	return 0;
 
 err_unloop:
-	for (i = 0, p = gdev->info; i < cnt; i++, p++) {
-		uio_unregister_device(p);
+	while( --i >= 0 ) {
+		uio_unregister_device(&gdev->info[i]);
+		kfree(gdev->info[i].name);
 	}
 	iounmap(gdev->prussio_vaddr);
 err_free_ddr_vaddr:
 	dma_free_coherent(dev, extram_pool_sz, gdev->ddr_vaddr,
 			  gdev->ddr_paddr);
 err_free_sram:
+#ifdef CONFIG_ARCH_DAVINCI_DA850
 	if (pdata->sram_pool)
 		gen_pool_free(gdev->sram_pool, gdev->sram_vaddr, sram_pool_sz);
 err_clk_disable:
 	clk_disable(gdev->pruss_clk);
+err_clk_put:
+	clk_put(gdev->pruss_clk);
+#else
+err_clk_disable:
+	pm_runtime_put(dev);
+	pm_runtime_disable(dev);
+#endif
+err_free_gdev:
+	kfree(gdev);
 
 	return ret;
 }
@@ -232,11 +304,19 @@
 	return 0;
 }
 
+static const struct of_device_id pruss_dt_ids[] = {
+	{ .compatible = "ti,pruss-v1" },
+	{ .compatible = "ti,pruss-v2" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pruss_dt_ids);
+
 static struct platform_driver pruss_driver = {
 	.probe = pruss_probe,
 	.remove = pruss_remove,
 	.driver = {
 		   .name = DRV_NAME,
+		   .of_match_table = pruss_dt_ids,
 		   },
 };
 
diff -Naur --no-dereference a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
--- a/drivers/usb/cdns3/cdns3-gadget.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/usb/cdns3/cdns3-gadget.c	2024-01-28 14:01:31.252353813 -0500
@@ -68,6 +68,8 @@
 #include "cdns3-trace.h"
 #include "drd.h"
 
+#define CDNS3_DEFAULT_EP_BUFFER_SIZE	4
+
 static int __cdns3_gadget_ep_queue(struct usb_ep *ep,
 				   struct usb_request *request,
 				   gfp_t gfp_flags);
@@ -2930,6 +2932,7 @@
 
 	spin_lock_irqsave(&priv_dev->lock, flags);
 	priv_dev->gadget_driver = driver;
+	priv_dev->ep_buf_size = CDNS3_DEFAULT_EP_BUFFER_SIZE;
 
 	/* limit speed if necessary */
 	max_speed = min(driver->max_speed, gadget->max_speed);
@@ -2978,6 +2981,7 @@
 
 	priv_dev->onchip_used_size = 0;
 	priv_dev->out_mem_is_allocated = 0;
+	priv_dev->ep_buf_size = 0;
 	priv_dev->gadget.speed = USB_SPEED_UNKNOWN;
 
 	list_for_each_entry(ep, &priv_dev->gadget.ep_list, ep_list) {
diff -Naur --no-dereference a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
--- a/drivers/usb/dwc3/core.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/usb/dwc3/core.c	2024-01-28 14:01:31.256353824 -0500
@@ -1271,6 +1271,13 @@
 		goto err0a;
 	}
 
+	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+	if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
+		dev_err(dwc->dev, "WARNING: DWC3_GUSB2PHYCFG_SUSPHY is set by default\n");
+		reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+		dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+	}
+
 	ret = dwc3_core_soft_reset(dwc);
 	if (ret)
 		goto err1;
diff -Naur --no-dereference a/drivers/usb/dwc3/dwc3-am62.c b/drivers/usb/dwc3/dwc3-am62.c
--- a/drivers/usb/dwc3/dwc3-am62.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/usb/dwc3/dwc3-am62.c	2024-01-28 14:01:31.256353824 -0500
@@ -17,6 +17,8 @@
 #include <linux/regmap.h>
 #include <linux/pinctrl/consumer.h>
 
+#include "core.h"
+
 /* USB WRAPPER register offsets */
 #define USBSS_PID			0x0
 #define USBSS_OVERCURRENT_CTRL		0x4
@@ -45,6 +47,10 @@
 #define USBSS_PHY_VBUS_SEL_SHIFT	1
 #define USBSS_PHY_LANE_REVERSE		BIT(0)
 
+/* CORE STAT register bits */
+#define USBSS_CORE_OPERATIONAL_MODE_MASK	GENMASK(13, 12)
+#define USBSS_CORE_OPERATIONAL_MODE_SHIFT	12
+
 /* MODE CONTROL register bits */
 #define USBSS_MODE_VALID	BIT(0)
 
@@ -54,6 +60,13 @@
 #define USBSS_WAKEUP_CFG_SESSVALID_EN	BIT(1)
 #define USBSS_WAKEUP_CFG_VBUSVALID_EN	BIT(0)
 
+#define USBSS_WAKEUP_CFG_ALL	(USBSS_WAKEUP_CFG_VBUSVALID_EN | \
+				 USBSS_WAKEUP_CFG_SESSVALID_EN | \
+				 USBSS_WAKEUP_CFG_LINESTATE_EN | \
+				 USBSS_WAKEUP_CFG_OVERCURRENT_EN)
+
+#define USBSS_WAKEUP_CFG_NONE	0
+
 /* WAKEUP STAT register bits */
 #define USBSS_WAKEUP_STAT_OVERCURRENT	BIT(4)
 #define USBSS_WAKEUP_STAT_LINESTATE	BIT(3)
@@ -84,7 +97,8 @@
 #define USBSS_VBUS_STAT_SESSVALID	BIT(2)
 #define USBSS_VBUS_STAT_VBUSVALID	BIT(0)
 
-/* Mask for PHY PLL REFCLK */
+/* USB_PHY_CTRL register bits in CTRL_MMR */
+#define PHY_CORE_VOLTAGE_MASK	BIT(31)
 #define PHY_PLL_REFCLK_MASK	GENMASK(3, 0)
 
 #define DWC3_AM62_AUTOSUSPEND_DELAY	100
@@ -93,10 +107,10 @@
 	struct device *dev;
 	void __iomem *usbss;
 	struct clk *usb2_refclk;
-	int rate_code;
 	struct regmap *syscon;
 	unsigned int offset;
 	unsigned int vbus_divider;
+	u32 wakeup_stat;
 };
 
 static const int dwc3_ti_rate_table[] = {	/* in KHZ */
@@ -125,14 +139,16 @@
 	writel(value, (data->usbss) + offset);
 }
 
-static int phy_syscon_pll_refclk(struct dwc3_data *data)
+static int phy_syscon_pll_refclk_and_voltage(struct dwc3_data *data)
 {
+	int i, ret;
 	struct device *dev = data->dev;
-	struct device_node *node = dev->of_node;
 	struct of_phandle_args args;
+	struct device_node *node;
 	struct regmap *syscon;
-	int ret;
+	unsigned long rate;
 
+	node = dev->of_node;
 	syscon = syscon_regmap_lookup_by_phandle(node, "ti,syscon-phy-pll-refclk");
 	if (IS_ERR(syscon)) {
 		dev_err(dev, "unable to get ti,syscon-phy-pll-refclk regmap\n");
@@ -148,7 +164,28 @@
 
 	data->offset = args.args[0];
 
-	ret = regmap_update_bits(data->syscon, data->offset, PHY_PLL_REFCLK_MASK, data->rate_code);
+	/* Core voltage. PHY_CORE_VOLTAGE bit Recommended to be 0 always */
+	ret = regmap_update_bits(data->syscon, data->offset,
+				 PHY_CORE_VOLTAGE_MASK, 0);
+	if (ret) {
+		dev_err(dev, "failed to set phy core voltage\n");
+		return ret;
+	}
+
+	/* PLL ref clock frequency selector */
+	rate = clk_get_rate(data->usb2_refclk);
+	rate /= 1000;	// To KHz
+	for (i = 0; i < ARRAY_SIZE(dwc3_ti_rate_table); i++) {
+		if (dwc3_ti_rate_table[i] == rate)
+			break;
+	}
+
+	if (i == ARRAY_SIZE(dwc3_ti_rate_table)) {
+		dev_err(dev, "unsupported usb2_refclk rate: %lu KHz\n", rate);
+		return -EINVAL;
+	}
+
+	ret = regmap_update_bits(data->syscon, data->offset, PHY_PLL_REFCLK_MASK, i);
 	if (ret) {
 		dev_err(dev, "failed to set phy pll reference clock rate\n");
 		return ret;
@@ -162,8 +199,7 @@
 	struct device *dev = &pdev->dev;
 	struct device_node *node = pdev->dev.of_node;
 	struct dwc3_data *data;
-	int i, ret;
-	unsigned long rate;
+	int ret;
 	u32 reg;
 
 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
@@ -185,25 +221,25 @@
 		return PTR_ERR(data->usb2_refclk);
 	}
 
-	/* Calculate the rate code */
-	rate = clk_get_rate(data->usb2_refclk);
-	rate /= 1000;	// To KHz
-	for (i = 0; i < ARRAY_SIZE(dwc3_ti_rate_table); i++) {
-		if (dwc3_ti_rate_table[i] == rate)
-			break;
-	}
+	clk_prepare_enable(data->usb2_refclk);
+	pm_runtime_set_active(dev);
+	pm_runtime_enable(dev);
 
-	if (i == ARRAY_SIZE(dwc3_ti_rate_table)) {
-		dev_err(dev, "unsupported usb2_refclk rate: %lu KHz\n", rate);
+	/* Turn OFF the USB power domain so we can set proper PHY clock and
+	 * core voltage before the USB power domain turns ON
+	 */
+	pm_runtime_suspend(dev);
+
+	/* Read the syscon property and set the rate code and voltage */
+	ret = phy_syscon_pll_refclk_and_voltage(data);
+	if (ret) {
+		pm_runtime_disable(dev);
+		pm_runtime_set_suspended(dev);
 		return -EINVAL;
 	}
 
-	data->rate_code = i;
-
-	/* Read the syscon property and set the rate code */
-	ret = phy_syscon_pll_refclk(data);
-	if (ret)
-		return ret;
+	/* Turn ON the USB power domain */
+	pm_runtime_resume(dev);
 
 	/* VBUS divider select */
 	data->vbus_divider = device_property_read_bool(dev, "ti,vbus-divider");
@@ -213,13 +249,10 @@
 
 	dwc3_ti_writel(data, USBSS_PHY_CONFIG, reg);
 
-	pm_runtime_set_active(dev);
-	pm_runtime_enable(dev);
 	/*
 	 * Don't ignore its dependencies with its children
 	 */
 	pm_suspend_ignore_children(dev, false);
-	clk_prepare_enable(data->usb2_refclk);
 	pm_runtime_get_noresume(dev);
 
 	ret = of_platform_populate(node, NULL, NULL, dev);
@@ -233,6 +266,12 @@
 	reg |= USBSS_MODE_VALID;
 	dwc3_ti_writel(data, USBSS_MODE_CONTROL, reg);
 
+	/* Device has capability to wakeup system from sleep */
+	device_set_wakeup_capable(dev, true);
+	ret = device_wakeup_enable(dev);
+	if (ret)
+		dev_err(dev, "couldn't enable device as a wakeup source: %d\n", ret);
+
 	/* Setting up autosuspend */
 	pm_runtime_set_autosuspend_delay(dev, DWC3_AM62_AUTOSUSPEND_DELAY);
 	pm_runtime_use_autosuspend(dev);
@@ -247,21 +286,18 @@
 	return ret;
 }
 
-static int dwc3_ti_remove_core(struct device *dev, void *c)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-
-	platform_device_unregister(pdev);
-	return 0;
-}
-
 static int dwc3_ti_remove(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct dwc3_data *data = platform_get_drvdata(pdev);
 	u32 reg;
 
-	device_for_each_child(dev, NULL, dwc3_ti_remove_core);
+	pm_runtime_get_sync(dev);
+
+	device_wakeup_disable(dev);
+	device_set_wakeup_capable(dev, false);
+
+	of_platform_depopulate(dev);
 
 	/* Clear mode valid bit */
 	reg = dwc3_ti_readl(data, USBSS_MODE_CONTROL);
@@ -269,7 +305,6 @@
 	dwc3_ti_writel(data, USBSS_MODE_CONTROL, reg);
 
 	pm_runtime_put_sync(dev);
-	clk_disable_unprepare(data->usb2_refclk);
 	pm_runtime_disable(dev);
 	pm_runtime_set_suspended(dev);
 
@@ -281,6 +316,27 @@
 static int dwc3_ti_suspend_common(struct device *dev)
 {
 	struct dwc3_data *data = dev_get_drvdata(dev);
+	u32 reg, current_prtcap_dir;
+
+	if (device_may_wakeup(dev)) {
+		reg = dwc3_ti_readl(data, USBSS_CORE_STAT);
+		current_prtcap_dir = (reg & USBSS_CORE_OPERATIONAL_MODE_MASK)
+				     >> USBSS_CORE_OPERATIONAL_MODE_SHIFT;
+		/* Set wakeup config enable bits */
+		reg = dwc3_ti_readl(data, USBSS_WAKEUP_CONFIG);
+		if (current_prtcap_dir == DWC3_GCTL_PRTCAP_HOST) {
+			reg = USBSS_WAKEUP_CFG_LINESTATE_EN | USBSS_WAKEUP_CFG_OVERCURRENT_EN;
+		} else {
+			reg = USBSS_WAKEUP_CFG_VBUSVALID_EN | USBSS_WAKEUP_CFG_SESSVALID_EN;
+			/*
+			 * Enable LINESTATE wake up only if connected to bus
+			 * and in U2/L3 state else it causes spurious wake-up.
+			 */
+		}
+		dwc3_ti_writel(data, USBSS_WAKEUP_CONFIG, reg);
+		/* clear wakeup status so we know what caused the wake up */
+		dwc3_ti_writel(data, USBSS_WAKEUP_STAT, USBSS_WAKEUP_STAT_CLR);
+	}
 
 	clk_disable_unprepare(data->usb2_refclk);
 
@@ -290,9 +346,18 @@
 static int dwc3_ti_resume_common(struct device *dev)
 {
 	struct dwc3_data *data = dev_get_drvdata(dev);
+	u32 reg;
 
 	clk_prepare_enable(data->usb2_refclk);
 
+	if (device_may_wakeup(dev)) {
+		/* Clear wakeup config enable bits */
+		dwc3_ti_writel(data, USBSS_WAKEUP_CONFIG, USBSS_WAKEUP_CFG_NONE);
+	}
+
+	reg = dwc3_ti_readl(data, USBSS_WAKEUP_STAT);
+	data->wakeup_stat = reg;
+
 	return 0;
 }
 
diff -Naur --no-dereference a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
--- a/drivers/usb/host/ehci-exynos.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/usb/host/ehci-exynos.c	2024-01-28 14:01:31.256353824 -0500
@@ -80,19 +80,11 @@
 			return -EINVAL;
 		}
 
-		phy = devm_of_phy_get(dev, child, NULL);
+		phy = devm_of_phy_optional_get(dev, child, NULL);
 		exynos_ehci->phy[phy_number] = phy;
 		if (IS_ERR(phy)) {
-			ret = PTR_ERR(phy);
-			if (ret == -EPROBE_DEFER) {
-				of_node_put(child);
-				return ret;
-			} else if (ret != -ENOSYS && ret != -ENODEV) {
-				dev_err(dev,
-					"Error retrieving usb2 phy: %d\n", ret);
-				of_node_put(child);
-				return ret;
-			}
+			of_node_put(child);
+			return PTR_ERR(phy);
 		}
 	}
 
@@ -108,12 +100,10 @@
 	int ret = 0;
 
 	for (i = 0; ret == 0 && i < PHY_NUMBER; i++)
-		if (!IS_ERR(exynos_ehci->phy[i]))
-			ret = phy_power_on(exynos_ehci->phy[i]);
+		ret = phy_power_on(exynos_ehci->phy[i]);
 	if (ret)
 		for (i--; i >= 0; i--)
-			if (!IS_ERR(exynos_ehci->phy[i]))
-				phy_power_off(exynos_ehci->phy[i]);
+			phy_power_off(exynos_ehci->phy[i]);
 
 	return ret;
 }
@@ -125,8 +115,7 @@
 	int i;
 
 	for (i = 0; i < PHY_NUMBER; i++)
-		if (!IS_ERR(exynos_ehci->phy[i]))
-			phy_power_off(exynos_ehci->phy[i]);
+		phy_power_off(exynos_ehci->phy[i]);
 }
 
 static void exynos_setup_vbus_gpio(struct device *dev)
diff -Naur --no-dereference a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
--- a/drivers/usb/host/ohci-exynos.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/usb/host/ohci-exynos.c	2024-01-28 14:01:31.256353824 -0500
@@ -69,19 +69,11 @@
 			return -EINVAL;
 		}
 
-		phy = devm_of_phy_get(dev, child, NULL);
+		phy = devm_of_phy_optional_get(dev, child, NULL);
 		exynos_ohci->phy[phy_number] = phy;
 		if (IS_ERR(phy)) {
-			ret = PTR_ERR(phy);
-			if (ret == -EPROBE_DEFER) {
-				of_node_put(child);
-				return ret;
-			} else if (ret != -ENOSYS && ret != -ENODEV) {
-				dev_err(dev,
-					"Error retrieving usb2 phy: %d\n", ret);
-				of_node_put(child);
-				return ret;
-			}
+			of_node_put(child);
+			return PTR_ERR(phy);
 		}
 	}
 
@@ -97,12 +89,10 @@
 	int ret = 0;
 
 	for (i = 0; ret == 0 && i < PHY_NUMBER; i++)
-		if (!IS_ERR(exynos_ohci->phy[i]))
-			ret = phy_power_on(exynos_ohci->phy[i]);
+		ret = phy_power_on(exynos_ohci->phy[i]);
 	if (ret)
 		for (i--; i >= 0; i--)
-			if (!IS_ERR(exynos_ohci->phy[i]))
-				phy_power_off(exynos_ohci->phy[i]);
+			phy_power_off(exynos_ohci->phy[i]);
 
 	return ret;
 }
@@ -114,8 +104,7 @@
 	int i;
 
 	for (i = 0; i < PHY_NUMBER; i++)
-		if (!IS_ERR(exynos_ohci->phy[i]))
-			phy_power_off(exynos_ohci->phy[i]);
+		phy_power_off(exynos_ohci->phy[i]);
 }
 
 static int exynos_ohci_probe(struct platform_device *pdev)
diff -Naur --no-dereference a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c
--- a/drivers/usb/typec/tipd/core.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/usb/typec/tipd/core.c	2024-01-28 14:01:31.256353824 -0500
@@ -14,7 +14,9 @@
 #include <linux/regmap.h>
 #include <linux/interrupt.h>
 #include <linux/usb/typec.h>
+#include <linux/usb/typec_altmode.h>
 #include <linux/usb/role.h>
+#include <linux/workqueue.h>
 
 #include "tps6598x.h"
 #include "trace.h"
@@ -94,7 +96,10 @@
 	struct power_supply_desc psy_desc;
 	enum power_supply_usb_type usb_type;
 
+	int wakeup;
 	u16 pwr_status;
+	struct delayed_work	wq_poll;
+	irq_handler_t irq_handler;
 };
 
 static enum power_supply_property tps6598x_psy_props[] = {
@@ -175,16 +180,6 @@
 	return tps6598x_block_read(tps, reg, val, sizeof(u64));
 }
 
-static inline int tps6598x_write16(struct tps6598x *tps, u8 reg, u16 val)
-{
-	return tps6598x_block_write(tps, reg, &val, sizeof(u16));
-}
-
-static inline int tps6598x_write32(struct tps6598x *tps, u8 reg, u32 val)
-{
-	return tps6598x_block_write(tps, reg, &val, sizeof(u32));
-}
-
 static inline int tps6598x_write64(struct tps6598x *tps, u8 reg, u64 val)
 {
 	return tps6598x_block_write(tps, reg, &val, sizeof(u64));
@@ -257,6 +252,7 @@
 		typec_set_orientation(tps->port, TYPEC_ORIENTATION_REVERSE);
 	else
 		typec_set_orientation(tps->port, TYPEC_ORIENTATION_NORMAL);
+	typec_set_mode(tps->port, TYPEC_STATE_USB);
 	tps6598x_set_data_role(tps, TPS_STATUS_TO_TYPEC_DATAROLE(status), true);
 
 	tps->partner = typec_register_partner(tps->port, &desc);
@@ -280,6 +276,7 @@
 	typec_set_pwr_role(tps->port, TPS_STATUS_TO_TYPEC_PORTROLE(status));
 	typec_set_vconn_role(tps->port, TPS_STATUS_TO_TYPEC_VCONN(status));
 	typec_set_orientation(tps->port, TYPEC_ORIENTATION_NONE);
+	typec_set_mode(tps->port, TYPEC_STATE_SAFE);
 	tps6598x_set_data_role(tps, TPS_STATUS_TO_TYPEC_DATAROLE(status), false);
 
 	power_supply_changed(tps->psy);
@@ -564,6 +561,18 @@
 	return IRQ_NONE;
 }
 
+/* Time interval for Polling */
+#define POLL_INTERVAL	500 /* msecs */
+static void tps6598x_poll_work(struct work_struct *work)
+{
+	struct tps6598x *tps = container_of(to_delayed_work(work),
+					    struct tps6598x, wq_poll);
+
+	tps->irq_handler(0, tps);
+	queue_delayed_work(system_power_efficient_wq,
+			   &tps->wq_poll, msecs_to_jiffies(POLL_INTERVAL));
+}
+
 static int tps6598x_check_mode(struct tps6598x *tps)
 {
 	char mode[5] = { };
@@ -742,6 +751,7 @@
 			TPS_REG_INT_PLUG_EVENT;
 	}
 
+	tps->irq_handler = irq_handler;
 	/* Make sure the controller has application firmware running */
 	ret = tps6598x_check_mode(tps);
 	if (ret)
@@ -833,20 +843,34 @@
 			dev_err(&client->dev, "failed to register partner\n");
 	}
 
-	ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
-					irq_handler,
-					IRQF_SHARED | IRQF_ONESHOT,
-					dev_name(&client->dev), tps);
-	if (ret) {
-		tps6598x_disconnect(tps, 0);
-		goto err_unregister_port;
+	if (client->irq) {
+		ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+						irq_handler,
+						IRQF_SHARED | IRQF_ONESHOT,
+						dev_name(&client->dev), tps);
+	} else {
+		dev_warn(tps->dev, "Unable to find the interrupt, switching to polling\n");
+		INIT_DELAYED_WORK(&tps->wq_poll, tps6598x_poll_work);
+		queue_delayed_work(system_power_efficient_wq, &tps->wq_poll,
+				   msecs_to_jiffies(POLL_INTERVAL));
 	}
 
+	if (ret)
+		goto err_disconnect;
+
 	i2c_set_clientdata(client, tps);
 	fwnode_handle_put(fwnode);
 
+	tps->wakeup = device_property_read_bool(tps->dev, "wakeup-source");
+	if (tps->wakeup && client->irq) {
+		device_init_wakeup(&client->dev, true);
+		enable_irq_wake(client->irq);
+	}
+
 	return 0;
 
+err_disconnect:
+	tps6598x_disconnect(tps, 0);
 err_unregister_port:
 	typec_unregister_port(tps->port);
 err_role_put:
@@ -862,11 +886,51 @@
 {
 	struct tps6598x *tps = i2c_get_clientdata(client);
 
+	if (!client->irq)
+		cancel_delayed_work_sync(&tps->wq_poll);
+
 	tps6598x_disconnect(tps, 0);
 	typec_unregister_port(tps->port);
 	usb_role_switch_put(tps->role_sw);
 }
 
+static int __maybe_unused tps6598x_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tps6598x *tps = i2c_get_clientdata(client);
+
+	if (tps->wakeup) {
+		disable_irq(client->irq);
+		enable_irq_wake(client->irq);
+	}
+
+	if (!client->irq)
+		cancel_delayed_work_sync(&tps->wq_poll);
+
+	return 0;
+}
+
+static int __maybe_unused tps6598x_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tps6598x *tps = i2c_get_clientdata(client);
+
+	if (tps->wakeup) {
+		disable_irq_wake(client->irq);
+		enable_irq(client->irq);
+	}
+
+	if (!client->irq)
+		queue_delayed_work(system_power_efficient_wq, &tps->wq_poll,
+				   msecs_to_jiffies(POLL_INTERVAL));
+
+	return 0;
+}
+
+static const struct dev_pm_ops tps6598x_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(tps6598x_suspend, tps6598x_resume)
+};
+
 static const struct of_device_id tps6598x_of_match[] = {
 	{ .compatible = "ti,tps6598x", },
 	{ .compatible = "apple,cd321x", },
@@ -883,6 +947,7 @@
 static struct i2c_driver tps6598x_i2c_driver = {
 	.driver = {
 		.name = "tps6598x",
+		.pm = &tps6598x_pm_ops,
 		.of_match_table = tps6598x_of_match,
 	},
 	.probe_new = tps6598x_probe,
diff -Naur --no-dereference a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
--- a/drivers/video/logo/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/video/logo/Kconfig	2024-01-28 14:01:31.256353824 -0500
@@ -28,6 +28,10 @@
 	bool "Standard 224-color Linux logo"
 	default y
 
+config LOGO_BEAGLE_CLUT224
+	bool "224-color Linux logo with BeagleBoard.org mascot Boris"
+	default y
+
 config LOGO_DEC_CLUT224
 	bool "224-color Digital Equipment Corporation Linux logo"
 	depends on MACH_DECSTATION || ALPHA
diff -Naur --no-dereference a/drivers/video/logo/logo_beagle_clut224.ppm b/drivers/video/logo/logo_beagle_clut224.ppm
--- a/drivers/video/logo/logo_beagle_clut224.ppm	1969-12-31 19:00:00.000000000 -0500
+++ b/drivers/video/logo/logo_beagle_clut224.ppm	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,1123 @@
+P3
+80 80
+255
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+6 6 6  6 6 6  10 10 10  10 10 10  10 10 10  6 6 6
+6 6 6  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  6 6 6  10 10 10  14 14 14
+22 22 22  26 26 26  30 30 30  34 34 34  30 30 30  30 30 30
+26 26 26  18 18 18  14 14 14  10 10 10  6 6 6  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 1
+0 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  6 6 6  14 14 14  26 26 26  42 42 42
+54 54 54  66 66 66  78 78 78  78 78 78  78 78 78  74 74 74
+66 66 66  54 54 54  42 42 42  26 26 26  18 18 18  10 10 10
+6 6 6  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 1  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  10 10 10  22 22 22  42 42 42  66 66 66  86 86 86
+66 66 66  38 38 38  38 38 38  22 22 22  26 26 26  34 34 34
+54 54 54  66 66 66  86 86 86  70 70 70  46 46 46  26 26 26
+14 14 14  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 1  0 0 1
+0 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+10 10 10  26 26 26  50 50 50  82 82 82  58 58 58  6 6 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  6 6 6  54 54 54  86 86 86  66 66 66
+38 38 38  18 18 18  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  6 6 6
+22 22 22  50 50 50  78 78 78  34 34 34  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  6 6 6  70 70 70
+78 78 78  46 46 46  22 22 22  6 6 6  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 1  0 0 1
+0 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  6 6 6  18 18 18
+42 42 42  82 82 82  26 26 26  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  14 14 14  46 46 46  34 34 34  6 6 6  2 2 6
+42 42 42  78 78 78  42 42 42  18 18 18  6 6 6  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 1  0 0 0
+0 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  10 10 10  30 30 30
+66 66 66  58 58 58  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  26 26 26  86 86 86  101 101 101  46 46 46  10 10 10
+2 2 6  58 58 58  70 70 70  34 34 34  10 10 10  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 1  0 0 1
+0 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  14 14 14  42 42 42
+86 86 86  10 10 10  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  30 30 30  94 94 94  94 94 94  58 58 58  26 26 26
+2 2 6  6 6 6  78 78 78  54 54 54  22 22 22  6 6 6
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  6 6 6  22 22 22  62 62 62
+62 62 62  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  26 26 26  54 54 54  38 38 38  18 18 18  10 10 10
+2 2 6  2 2 6  34 34 34  82 82 82  38 38 38  14 14 14
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 1
+0 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  6 6 6  30 30 30  78 78 78
+30 30 30  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  10 10 10  10 10 10  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  78 78 78  50 50 50  18 18 18
+6 6 6  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 1  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  10 10 10  38 38 38  86 86 86
+14 14 14  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  54 54 54  66 66 66  26 26 26
+6 6 6  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 1
+0 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  14 14 14  42 42 42  82 82 82
+2 2 6  2 2 6  2 2 6  6 6 6  10 10 10  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  6 6 6  14 14 14  10 10 10  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  18 18 18  82 82 82  34 34 34
+10 10 10  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 1  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  14 14 14  46 46 46  86 86 86
+2 2 6  2 2 6  6 6 6  6 6 6  22 22 22  34 34 34
+6 6 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+18 18 18  34 34 34  10 10 10  50 50 50  22 22 22  2 2 6
+2 2 6  2 2 6  2 2 6  10 10 10  86 86 86  42 42 42
+14 14 14  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 1  0 0 1
+0 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  14 14 14  46 46 46  86 86 86
+2 2 6  2 2 6  38 38 38  116 116 116  94 94 94  22 22 22
+22 22 22  2 2 6  2 2 6  2 2 6  14 14 14  86 86 86
+138 138 138  162 162 162  158 155 152  38 38 38  26 26 26  6 6 6
+2 2 6  2 2 6  2 2 6  2 2 6  86 86 86  46 46 46
+14 14 14  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  14 14 14  46 46 46  86 86 86
+2 2 6  14 14 14  138 138 138  198 198 198  195 195 195  116 116 116
+10 10 10  2 2 6  2 2 6  6 6 6  101 98 89  187 187 187
+210 210 210  218 218 218  218 218 218  138 138 138  14 14 14  6 6 6
+2 2 6  2 2 6  2 2 6  2 2 6  86 86 86  50 50 50
+18 18 18  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 1  0 0 0  0 0 1  0 0 1
+0 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  14 14 14  46 46 46  86 86 86
+2 2 6  54 54 54  218 218 218  195 195 195  226 226 226  246 246 246
+58 58 58  2 2 6  2 2 6  30 30 30  210 210 210  253 253 253
+171 170 170  123 123 123  221 221 221  234 234 234  74 74 74  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  70 70 70  58 58 58
+22 22 22  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  14 14 14  46 46 46  82 82 82
+2 2 6  106 106 106  171 170 170  26 26 26  86 86 86  226 226 226
+123 123 123  10 10 10  14 14 14  46 46 46  231 231 231  190 190 190
+6 6 6  70 70 70  90 90 90  238 238 238  158 158 158  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  70 70 70  58 58 58
+22 22 22  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 1  0 0 0  0 0 1  0 0 1
+0 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  14 14 14  42 42 42  86 86 86
+6 6 6  116 116 116  106 106 106  6 6 6  70 70 70  144 144 144
+128 128 128  18 18 18  38 38 38  54 54 54  221 221 221  106 106 106
+2 2 6  14 14 14  46 46 46  190 190 190  198 198 198  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  74 74 74  62 62 62
+22 22 22  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 1  0 0 0  0 0 1  0 0 0
+0 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  14 14 14  42 42 42  94 94 94
+14 14 14  101 101 101  128 128 128  2 2 6  18 18 18  116 116 116
+118 98 46  121 92 8  121 92 8  98 77 21  162 162 162  106 106 106
+2 2 6  2 2 6  2 2 6  195 195 195  195 195 195  6 6 6
+2 2 6  2 2 6  2 2 6  2 2 6  74 74 74  62 62 62
+22 22 22  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 1  0 0 1  0 0 1  0 0 0
+0 0 1  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  10 10 10  38 38 38  90 90 90
+14 14 14  58 58 58  210 210 210  26 26 26  61 42 6  156 107 11
+226 170 11  236 186 11  225 175 15  184 144 12  225 175 15  175 146 61
+37 26 9  2 2 6  70 70 70  246 246 246  138 138 138  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  70 70 70  66 66 66
+26 26 26  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  10 10 10  38 38 38  86 86 86
+14 14 14  10 10 10  195 195 195  188 164 115  192 133 9  225 175 15
+239 182 13  236 186 11  232 195 16  232 195 16  246 215 20  241 208 19
+232 195 16  184 144 12  218 194 134  219 214 185  42 42 42  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  50 50 50  74 74 74
+30 30 30  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  10 10 10  34 34 34  86 86 86
+14 14 14  2 2 6  121 87 25  192 133 9  219 162 10  239 182 13
+236 186 11  232 195 16  241 208 19  246 215 20  246 215 20  246 215 20
+246 215 20  241 208 19  241 208 19  226 184 13  121 87 25  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  50 50 50  82 82 82
+34 34 34  10 10 10  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  10 10 10  34 34 34  82 82 82
+30 30 30  61 42 6  180 123 7  206 145 10  230 174 11  239 182 13
+236 186 11  238 202 15  241 208 19  235 218 115  246 215 20  246 215 20
+246 215 20  246 215 20  226 184 13  225 175 15  184 144 12  6 6 6
+2 2 6  2 2 6  2 2 6  2 2 6  26 26 26  94 94 94
+42 42 42  14 14 14  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  10 10 10  30 30 30  78 78 78
+50 50 50  104 69 6  192 133 9  216 158 10  236 178 12  236 186 11
+232 195 16  241 208 19  246 215 20  246 215 20  246 215 20  246 215 20
+241 208 19  200 144 11  200 144 11  216 158 10  163 110 8  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  6 6 6  90 90 90
+54 54 54  18 18 18  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  10 10 10  30 30 30  78 78 78
+46 46 46  22 22 22  137 92 6  210 162 10  239 182 13  236 186 11
+238 202 15  241 208 19  246 215 20  246 215 20  241 208 19  210 162 10
+185 133 11  210 150 10  216 158 10  210 150 10  104 69 6  2 2 6
+6 6 6  54 54 54  14 14 14  2 2 6  2 2 6  62 62 62
+74 74 74  30 30 30  10 10 10  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  10 10 10  34 34 34  78 78 78
+50 50 50  6 6 6  92 69 23  138 101 21  190 146 13  226 184 13
+232 195 16  232 195 16  225 175 15  190 146 13  167 114 7  192 133 9
+210 150 10  213 154 11  190 142 34  188 164 115  101 98 89  2 2 6
+2 2 6  78 78 78  116 116 116  58 58 58  2 2 6  22 22 22
+90 90 90  46 46 46  18 18 18  6 6 6  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  10 10 10  38 38 38  86 86 86
+50 50 50  6 6 6  128 128 128  172 154 116  156 107 11  167 114 7
+200 144 11  184 144 12  197 138 11  200 144 11  206 145 10  206 145 10
+197 138 11  188 164 115  195 195 195  198 198 198  171 170 170  14 14 14
+2 2 6  22 22 22  116 116 116  116 116 116  22 22 22  2 2 6
+74 74 74  70 70 70  30 30 30  10 10 10  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  6 6 6  18 18 18  50 50 50  101 101 101
+26 26 26  10 10 10  138 138 138  190 190 190  172 154 116  156 107 11
+197 138 11  200 144 11  197 138 11  192 133 9  180 123 7  190 142 34
+181 170 141  187 187 187  202 202 202  221 221 221  218 218 218  66 66 66
+2 2 6  2 2 6  50 50 50  62 62 62  6 6 6  2 2 6
+10 10 10  90 90 90  50 50 50  18 18 18  6 6 6  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  10 10 10  34 34 34  74 74 74  74 74 74
+2 2 6  6 6 6  144 144 144  198 198 198  190 190 190  181 170 141
+150 121 62  156 107 11  156 107 11  166 123 43  172 154 116  187 187 187
+190 190 190  210 210 210  246 246 246  253 253 253  253 253 253  182 182 182
+6 6 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  62 62 62  74 74 74  34 34 34  14 14 14  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  10 10 10  22 22 22  54 54 54  94 94 94  18 18 18
+2 2 6  46 46 46  234 234 234  221 221 221  190 190 190  190 190 190
+190 190 190  187 187 187  187 187 187  190 190 190  190 190 190  195 195 195
+218 218 218  242 242 242  253 253 253  253 253 253  253 253 253  253 253 253
+82 82 82  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  14 14 14  86 86 86  54 54 54  22 22 22  6 6 6
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+6 6 6  18 18 18  46 46 46  90 90 90  46 46 46  18 18 18
+6 6 6  182 182 182  253 253 253  246 246 246  206 206 206  190 190 190
+190 190 190  190 190 190  190 190 190  190 190 190  206 206 206  231 231 231
+250 250 250  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+202 202 202  14 14 14  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  42 42 42  86 86 86  42 42 42  18 18 18
+6 6 6  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  6 6 6
+14 14 14  38 38 38  74 74 74  66 66 66  2 2 6  6 6 6
+90 90 90  250 250 250  253 253 253  253 253 253  238 238 238  138 138 138
+97 87 74  110 93 64  119 103 79  103 95 84  108 105 106  238 238 238
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  82 82 82  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  78 78 78  70 70 70  34 34 34
+14 14 14  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  14 14 14
+34 34 34  66 66 66  78 78 78  6 6 6  2 2 6  18 18 18
+218 218 218  253 253 253  253 253 253  210 210 210  80 72 61  103 75 39
+169 127 44  169 127 44  167 127 47  207 184 137  167 127 47  104 86 63
+234 234 234  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  182 182 182  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  18 18 18  90 90 90  62 62 62
+30 30 30  10 10 10  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  10 10 10  26 26 26
+58 58 58  90 90 90  18 18 18  2 2 6  2 2 6  108 105 106
+253 253 253  253 253 253  218 218 218  103 75 39  169 127 44  143 114 43
+118 84 23  169 127 44  169 127 44  188 164 115  183 152 86  169 127 44
+97 87 74  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  231 231 231  18 18 18  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  18 18 18  94 94 94
+54 54 54  26 26 26  10 10 10  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  6 6 6  22 22 22  50 50 50
+90 90 90  26 26 26  2 2 6  2 2 6  14 14 14  195 195 195
+250 250 250  253 253 253  89 81 69  166 123 43  169 127 44  169 127 44
+98 77 21  163 123 43  120 94 48  156 118 43  225 216 182  161 124 51
+80 72 61  171 170 170  253 253 253  253 253 253  253 253 253  253 253 253
+250 250 250  242 242 242  54 54 54  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  38 38 38
+86 86 86  50 50 50  22 22 22  6 6 6  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  6 6 6  14 14 14  38 38 38  82 82 82
+34 34 34  2 2 6  2 2 6  2 2 6  42 42 42  195 195 195
+246 246 246  231 231 231  104 86 51  169 127 44  169 127 44  169 127 44
+121 87 25  105 82 38  72 65 62  105 82 38  211 190 148  239 232 219
+154 139 110  89 81 69  210 210 210  250 250 250  246 246 246  238 238 238
+226 226 226  231 231 231  101 101 101  6 6 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+38 38 38  82 82 82  42 42 42  14 14 14  6 6 6  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  10 10 10  26 26 26  62 62 62  66 66 66
+2 2 6  2 2 6  2 2 6  6 6 6  70 70 70  171 170 170
+206 206 206  101 98 89  157 117 39  169 127 44  169 127 44  169 127 44
+163 123 43  105 82 38  163 123 43  169 127 44  211 190 148  255 255 255
+255 255 255  253 253 253  144 144 144  90 90 90  190 190 190  202 202 202
+198 198 198  202 202 202  182 182 182  18 18 18  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  62 62 62  66 66 66  30 30 30  10 10 10  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  14 14 14  42 42 42  82 82 82  18 18 18
+2 2 6  2 2 6  2 2 6  10 10 10  94 94 94  182 182 182
+210 210 210  99 81 49  169 127 44  169 127 44  169 127 44  169 127 44
+169 127 44  98 77 21  169 127 44  188 164 115  252 252 252  255 255 255
+255 255 255  255 255 255  255 255 255  158 155 152  108 105 106  138 138 138
+195 195 195  195 195 195  210 210 210  158 158 158  6 6 6  14 14 14
+50 50 50  14 14 14  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  6 6 6  86 86 86  46 46 46  18 18 18  6 6 6
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  6 6 6  22 22 22  54 54 54  70 70 70  2 2 6
+2 2 6  10 10 10  2 2 6  22 22 22  169 168 166  231 231 231
+128 128 128  143 114 43  169 127 44  169 127 44  169 127 44  169 127 44
+169 127 44  118 84 23  167 127 47  247 245 242  255 255 255  255 255 255
+255 255 255  255 255 255  182 182 182  116 116 116  128 128 128  38 38 38
+206 206 206  206 206 206  198 198 198  226 226 226  94 94 94  2 2 6
+6 6 6  38 38 38  30 30 30  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  62 62 62  66 66 66  26 26 26  10 10 10
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  10 10 10  30 30 30  74 74 74  50 50 50  2 2 6
+26 26 26  26 26 26  2 2 6  106 106 106  238 238 238  253 253 253
+89 81 66  169 127 44  169 127 44  169 127 44  169 127 44  169 127 44
+169 127 44  157 117 39  138 113 67  255 255 255  255 255 255  255 255 255
+255 255 255  255 255 255  202 202 202  50 50 50  34 34 34  50 50 50
+231 231 231  246 246 246  218 218 218  202 202 202  210 210 210  14 14 14
+2 2 6  2 2 6  30 30 30  22 22 22  2 2 6  2 2 6
+2 2 6  2 2 6  18 18 18  86 86 86  42 42 42  14 14 14
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  14 14 14  42 42 42  90 90 90  22 22 22  2 2 6
+42 42 42  2 2 6  18 18 18  218 218 218  253 253 253  253 253 253
+104 86 63  169 127 44  169 127 44  169 127 44  169 127 44  169 127 44
+166 123 43  156 118 43  105 82 38  255 255 255  255 255 255  255 255 255
+255 255 255  255 255 255  255 255 255  221 221 221  182 182 182  90 90 90
+232 232 232  253 253 253  248 248 248  221 221 221  218 218 218  101 101 101
+2 2 6  14 14 14  18 18 18  38 38 38  10 10 10  2 2 6
+2 2 6  2 2 6  2 2 6  78 78 78  58 58 58  22 22 22
+6 6 6  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+6 6 6  18 18 18  54 54 54  82 82 82  2 2 6  26 26 26
+22 22 22  2 2 6  123 123 123  253 253 253  253 253 253  253 253 253
+89 81 66  169 127 44  169 127 44  169 127 44  169 127 44  166 123 43
+141 109 45  157 117 39  118 84 23  240 237 231  255 255 255  255 255 255
+255 255 255  255 255 255  255 255 255  226 226 226  97 87 74  72 54 38
+253 253 253  253 253 253  251 251 250  250 250 250  238 238 238  198 198 198
+6 6 6  38 38 38  58 58 58  26 26 26  38 38 38  2 2 6
+2 2 6  2 2 6  2 2 6  46 46 46  78 78 78  30 30 30
+10 10 10  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+10 10 10  30 30 30  74 74 74  58 58 58  2 2 6  42 42 42
+2 2 6  22 22 22  231 231 231  253 253 253  253 253 253  253 253 253
+162 161 160  104 86 51  169 127 44  169 127 44  156 118 43  141 109 45
+145 111 45  105 82 38  157 117 39  216 197 160  255 255 255  203 202 203
+158 155 152  116 116 116  72 65 62  95 51 32  175 118 6  145 90 47
+250 250 250  253 253 253  252 252 252  253 253 253  253 253 253  246 246 246
+46 46 46  38 38 38  42 42 42  14 14 14  38 38 38  14 14 14
+2 2 6  2 2 6  2 2 6  6 6 6  86 86 86  46 46 46
+14 14 14  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  6 6 6
+14 14 14  42 42 42  90 90 90  18 18 18  18 18 18  26 26 26
+2 2 6  116 116 116  253 253 253  253 253 253  253 253 253  253 253 253
+248 248 248  138 138 138  99 81 49  105 82 38  125 96 44  121 87 25
+98 77 21  125 96 44  169 127 44  216 197 160  255 255 255  190 190 190
+108 105 106  70 70 70  58 58 58  72 54 38  192 133 9  120 94 48
+250 250 250  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+94 94 94  6 6 6  2 2 6  2 2 6  10 10 10  34 34 34
+2 2 6  2 2 6  2 2 6  2 2 6  74 74 74  58 58 58
+22 22 22  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  10 10 10
+26 26 26  66 66 66  82 82 82  2 2 6  38 38 38  6 6 6
+14 14 14  210 210 210  253 253 253  253 253 253  253 253 253  253 253 253
+101 101 101  90 90 90  244 244 244  89 81 69  145 111 45  161 124 51
+197 178 128  207 184 137  216 197 160  218 218 218  171 170 170  151 148 137
+141 130 107  80 72 61  169 168 166  226 226 226  109 101 93  187 187 187
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+144 144 144  2 2 6  2 2 6  2 2 6  2 2 6  46 46 46
+2 2 6  2 2 6  2 2 6  2 2 6  42 42 42  74 74 74
+30 30 30  10 10 10  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  6 6 6  14 14 14
+42 42 42  90 90 90  26 26 26  6 6 6  42 42 42  2 2 6
+74 74 74  250 250 250  253 253 253  253 253 253  253 253 253  253 253 253
+106 106 106  131 116 91  210 209 209  110 93 64  169 127 44  233 229 220
+255 255 255  255 255 255  255 255 255  255 255 255  255 255 255  239 232 219
+169 127 44  120 94 48  244 244 244  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+182 182 182  2 2 6  2 2 6  2 2 6  2 2 6  46 46 46
+2 2 6  2 2 6  2 2 6  2 2 6  10 10 10  86 86 86
+38 38 38  10 10 10  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  10 10 10  26 26 26
+66 66 66  82 82 82  2 2 6  22 22 22  18 18 18  2 2 6
+144 144 144  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+171 170 170  125 96 44  103 95 84  110 93 64  175 146 61  255 255 255
+255 255 255  255 255 255  255 255 255  255 255 255  255 255 255  255 255 255
+183 152 86  145 111 45  195 195 194  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  252 252 252  253 253 253  253 253 253  253 253 253
+206 206 206  2 2 6  2 2 6  2 2 6  2 2 6  38 38 38
+2 2 6  2 2 6  2 2 6  2 2 6  6 6 6  86 86 86
+46 46 46  14 14 14  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  6 6 6  18 18 18  46 46 46
+86 86 86  18 18 18  2 2 6  34 34 34  10 10 10  6 6 6
+210 210 210  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+246 246 246  100 88 68  145 111 45  120 94 48  159 135 84  249 249 249
+255 255 255  255 255 255  255 255 255  255 255 255  255 255 255  255 255 255
+152 137 111  156 118 43  158 158 158  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  251 251 250  253 253 253  253 253 253  253 253 253
+221 221 221  6 6 6  2 2 6  2 2 6  6 6 6  30 30 30
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  82 82 82
+54 54 54  18 18 18  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  10 10 10  26 26 26  66 66 66
+62 62 62  2 2 6  2 2 6  38 38 38  10 10 10  26 26 26
+238 238 238  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  144 144 144  138 113 67  166 123 43  138 119 85  246 246 246
+255 255 255  242 242 242  255 255 255  255 255 255  234 234 234  255 255 255
+152 137 111  156 118 43  162 161 160  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  250 250 250  253 253 253  253 253 253  253 253 253
+231 231 231  6 6 6  2 2 6  2 2 6  10 10 10  30 30 30
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  66 66 66
+58 58 58  22 22 22  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  10 10 10  38 38 38  78 78 78
+6 6 6  2 2 6  2 2 6  46 46 46  14 14 14  42 42 42
+246 246 246  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  250 250 250  94 90 86  154 122 46  138 119 85  253 253 253
+244 243 244  195 195 194  255 255 255  244 244 244  182 182 182  255 255 255
+147 140 128  145 111 45  187 187 187  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  249 249 249  249 249 249  253 253 253  253 253 253
+234 234 234  10 10 10  2 2 6  2 2 6  22 22 22  14 14 14
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  66 66 66
+62 62 62  22 22 22  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  6 6 6  18 18 18  50 50 50  74 74 74
+2 2 6  2 2 6  14 14 14  70 70 70  34 34 34  62 62 62
+250 250 250  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  231 231 231  104 86 63  141 130 107  255 255 255
+246 246 246  182 182 182  255 255 255  231 231 231  196 195 196  255 255 255
+147 140 128  119 100 63  242 242 242  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  242 242 242  253 253 253  253 253 253
+234 234 234  14 14 14  2 2 6  2 2 6  30 30 30  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  66 66 66
+62 62 62  22 22 22  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  6 6 6  18 18 18  54 54 54  62 62 62
+2 2 6  2 2 6  2 2 6  30 30 30  46 46 46  70 70 70
+250 250 250  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  210 210 210  89 81 66  152 137 111  255 255 255
+254 254 254  171 170 170  255 255 255  218 218 218  210 209 209  255 255 255
+151 148 137  123 99 54  169 168 166  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  252 252 252  253 253 253  253 253 253
+226 226 226  10 10 10  2 2 6  6 6 6  30 30 30  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  66 66 66
+58 58 58  22 22 22  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  6 6 6  22 22 22  58 58 58  62 62 62
+2 2 6  2 2 6  2 2 6  2 2 6  30 30 30  78 78 78
+250 250 250  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  249 249 249  97 87 74  169 127 44  152 137 111  255 255 255
+255 255 255  171 170 170  255 255 255  203 202 203  226 226 226  255 255 255
+158 155 152  169 127 44  120 94 48  234 234 234  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+206 206 206  2 2 6  22 22 22  34 34 34  18 14 6  22 22 22
+26 26 26  18 18 18  6 6 6  2 2 6  2 2 6  82 82 82
+54 54 54  18 18 18  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  6 6 6  26 26 26  62 62 62  106 106 106
+78 53 15  185 133 11  210 162 10  121 92 8  6 6 6  62 62 62
+238 238 238  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  238 238 238  110 93 64  166 123 43  162 161 160  255 255 255
+255 255 255  108 105 106  94 94 94  82 82 82  244 244 244  255 255 255
+202 202 202  150 121 62  141 109 45  202 202 202  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+158 158 158  18 18 18  14 14 14  2 2 6  2 2 6  2 2 6
+6 6 6  18 18 18  66 66 66  38 38 38  6 6 6  94 94 94
+50 50 50  18 18 18  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  6 6 6
+10 10 10  10 10 10  18 18 18  38 38 38  78 78 78  141 130 107
+216 158 10  242 186 14  246 190 14  246 190 14  163 110 8  10 10 10
+90 90 90  238 238 238  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  252 252 252  144 144 144  80 72 61  218 218 218  255 255 255
+206 206 206  123 123 123  253 253 253  128 128 128  169 168 166  254 254 254
+254 254 254  101 98 89  128 128 128  252 252 252  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  225 216 182  219 191 94  219 191 94
+180 133 36  37 26 9  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  38 38 38  46 46 46  26 26 26  106 106 106
+54 54 54  18 18 18  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  6 6 6  14 14 14  22 22 22
+30 30 30  38 38 38  50 50 50  70 70 70  106 106 106  190 142 34
+226 170 11  242 186 14  246 190 14  246 190 14  246 190 14  156 107 11
+6 6 6  74 74 74  226 226 226  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  182 182 182  108 105 106  116 116 116
+123 123 123  244 244 244  253 253 253  244 244 244  128 128 128  116 116 116
+116 116 116  169 168 166  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  201 174 68  241 196 14  241 208 19
+232 195 16  38 30 10  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  6 6 6  30 30 30  26 26 26  210 162 10  159 135 84
+66 66 66  26 26 26  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  6 6 6  18 18 18  38 38 38  58 58 58
+78 78 78  86 86 86  101 101 101  123 123 123  175 146 61  210 150 10
+234 174 13  246 186 14  246 190 14  246 190 14  246 190 14  236 186 11
+104 69 6  2 2 6  46 46 46  198 198 198  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  234 234 234  242 242 242
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  201 174 68  242 186 14  241 196 14
+210 162 10  22 18 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  6 6 6  121 92 8  238 202 15  232 195 16
+82 82 82  34 34 34  10 10 10  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  14 14 14  38 38 38  70 70 70  154 122 46
+190 142 34  200 144 11  197 138 11  197 138 11  213 154 11  226 170 11
+242 186 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+225 175 15  45 32 11  2 2 6  22 22 22  158 158 158  250 250 250
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  250 250 250  242 242 242  201 174 68  239 182 13  236 186 11
+213 154 11  45 32 11  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  61 42 6  225 175 15  236 186 11  236 186 11
+119 103 79  42 42 42  14 14 14  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  6 6 6  22 22 22  54 54 54  154 122 46  213 154 11
+226 170 11  230 174 11  226 170 11  226 170 11  236 178 12  242 186 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+241 196 14  184 144 12  10 10 10  2 2 6  6 6 6  116 116 116
+242 242 242  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  231 231 231  198 198 198  201 174 68  236 178 12  236 178 12
+210 150 10  137 92 6  18 14 6  2 2 6  2 2 6  2 2 6
+6 6 6  61 42 6  200 144 11  236 178 12  239 182 13  239 182 13
+124 112 88  58 58 58  22 22 22  6 6 6  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  10 10 10  30 30 30  70 70 70  180 133 36  226 170 11
+239 182 13  242 186 14  242 186 14  246 186 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  232 195 16  104 69 6  2 2 6  2 2 6  2 2 6
+66 66 66  221 221 221  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  206 206 206  198 198 198  201 174 68  230 174 11  230 174 11
+216 158 10  192 133 9  163 110 8  116 81 8  104 69 6  116 81 8
+167 114 7  197 138 11  226 170 11  239 182 13  242 186 14  242 186 14
+165 145 105  78 78 78  34 34 34  14 14 14  6 6 6  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  6 6 6  30 30 30  78 78 78  190 142 34  226 170 11
+239 182 13  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  241 196 14  210 162 10  22 18 6  2 2 6  2 2 6
+2 2 6  38 38 38  218 218 218  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+250 250 250  206 206 206  198 198 198  201 174 68  226 170 11  236 178 12
+224 166 10  210 150 10  200 144 11  197 138 11  192 133 9  197 138 11
+210 150 10  226 170 11  242 186 14  246 190 14  246 190 14  246 186 14
+225 175 15  124 112 88  62 62 62  30 30 30  14 14 14  6 6 6
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  10 10 10  30 30 30  78 78 78  167 127 47  224 166 10
+239 182 13  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  241 196 14  138 101 21  2 2 6  2 2 6
+2 2 6  2 2 6  78 78 78  250 250 250  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+250 250 250  218 218 218  198 198 198  190 142 34  219 162 10  236 178 12
+234 174 13  224 166 10  216 158 10  213 154 11  213 154 11  216 158 10
+226 170 11  239 182 13  246 190 14  246 190 14  246 190 14  246 190 14
+242 186 14  197 166 45  101 101 101  58 58 58  30 30 30  14 14 14
+6 6 6  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  10 10 10  30 30 30  74 74 74  167 127 47  216 158 10
+236 178 12  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  241 196 14  226 184 13  61 42 6  2 2 6
+2 2 6  2 2 6  22 22 22  238 238 238  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  226 226 226  187 187 187  180 133 36  216 158 10  236 178 12
+239 182 13  236 178 12  230 174 11  226 170 11  226 170 11  230 174 11
+236 178 12  242 186 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 186 14  239 182 13  197 166 45  106 106 106  66 66 66  34 34 34
+14 14 14  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  6 6 6  26 26 26  70 70 70  163 133 67  213 154 11
+236 178 12  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  241 196 14  190 146 13  18 14 6
+2 2 6  2 2 6  46 46 46  246 246 246  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  221 221 221  86 86 86  156 107 11  216 158 10  236 178 12
+242 186 14  246 186 14  242 186 14  239 182 13  239 182 13  242 186 14
+242 186 14  246 186 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  242 186 14  225 175 15  142 114 66  66 66 66
+30 30 30  10 10 10  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  6 6 6  26 26 26  70 70 70  163 133 67  210 150 10
+236 178 12  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  232 195 16  121 92 8
+34 34 34  106 106 106  221 221 221  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+242 242 242  82 82 82  18 14 6  163 110 8  216 158 10  236 178 12
+242 186 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  242 186 14  163 133 67
+46 46 46  18 18 18  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  10 10 10  30 30 30  78 78 78  163 133 67  210 150 10
+236 178 12  246 186 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  241 196 14  225 175 15
+181 170 141  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  218 218 218
+58 58 58  2 2 6  22 18 6  167 114 7  216 158 10  236 178 12
+246 186 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 186 14  242 186 14  190 142 34
+54 54 54  22 22 22  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  14 14 14  38 38 38  86 86 86  180 133 36  213 154 11
+236 178 12  246 186 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  232 195 16
+190 146 13  218 218 218  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  250 250 250  171 170 170  26 26 26
+2 2 6  2 2 6  37 26 9  163 110 8  219 162 10  239 182 13
+246 186 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 186 14  236 178 12  224 166 10  142 114 66
+46 46 46  18 18 18  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+6 6 6  18 18 18  50 50 50  109 101 93  192 133 9  224 166 10
+242 186 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  242 186 14  226 184 13
+210 162 10  141 109 45  226 226 226  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  253 253 253  253 253 253  253 253 253  253 253 253
+253 253 253  253 253 253  198 198 198  66 66 66  2 2 6  2 2 6
+2 2 6  2 2 6  45 32 11  156 107 11  219 162 10  239 182 13
+246 186 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  242 186 14  234 174 13  213 154 11  154 122 46  66 66 66
+30 30 30  10 10 10  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+6 6 6  22 22 22  58 58 58  150 121 62  206 145 10  234 174 13
+242 186 14  246 186 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 186 14  236 178 12
+210 162 10  163 110 8  61 42 6  138 138 138  218 218 218  250 250 250
+253 253 253  253 253 253  253 253 253  250 250 250  242 242 242  210 210 210
+144 144 144  66 66 66  6 6 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  61 42 6  163 110 8  216 158 10  236 178 12
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  239 182 13
+230 174 11  216 158 10  190 142 34  124 112 88  70 70 70  38 38 38
+18 18 18  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+6 6 6  22 22 22  62 62 62  166 123 43  206 145 10  224 166 10
+236 178 12  239 182 13  242 186 14  242 186 14  246 186 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  236 178 12
+216 158 10  175 118 6  78 53 15  2 2 6  6 6 6  30 30 30
+54 54 54  62 62 62  50 50 50  38 38 38  14 14 14  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  6 6 6  78 53 15  167 114 7  213 154 11  236 178 12
+246 190 14  246 190 14  246 190 14  246 190 14  246 190 14  246 190 14
+246 190 14  242 186 14  239 182 13  239 182 13  230 174 11  210 150 10
+167 127 47  124 112 88  82 82 82  54 54 54  34 34 34  18 18 18
+6 6 6  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+6 6 6  18 18 18  50 50 50  157 117 39  192 133 9  200 144 11
+216 158 10  219 162 10  224 166 10  226 170 11  230 174 11  236 178 12
+239 182 13  239 182 13  242 186 14  246 186 14  246 190 14  246 190 14
+246 190 14  246 190 14  246 190 14  246 190 14  246 186 14  230 174 11
+210 150 10  163 110 8  104 69 6  10 10 10  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  6 6 6  85 60 19  167 114 7  206 145 10  230 174 11
+242 186 14  246 190 14  246 190 14  246 190 14  246 186 14  242 186 14
+239 182 13  230 174 11  224 166 10  213 154 11  180 133 36  124 112 88
+86 86 86  58 58 58  38 38 38  22 22 22  10 10 10  6 6 6
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  14 14 14  34 34 34  70 70 70  141 109 45  157 117 39
+167 114 7  180 123 7  192 133 9  197 138 11  200 144 11  206 145 10
+213 154 11  219 162 10  224 166 10  230 174 11  239 182 13  242 186 14
+246 186 14  246 186 14  246 186 14  246 186 14  239 182 13  216 158 10
+185 133 11  152 99 6  104 69 6  18 14 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  2 2 6  2 2 6  2 2 6  2 2 6  2 2 6
+2 2 6  6 6 6  78 53 15  152 99 6  192 133 9  219 162 10
+236 178 12  239 182 13  246 186 14  242 186 14  239 182 13  236 178 12
+224 166 10  206 145 10  192 133 9  150 121 62  94 94 94  62 62 62
+42 42 42  22 22 22  14 14 14  6 6 6  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  6 6 6  18 18 18  34 34 34  58 58 58  78 78 78
+101 98 89  124 112 88  141 109 45  156 107 11  163 110 8  167 114 7
+175 118 6  180 123 7  185 133 11  197 138 11  210 150 10  219 162 10
+226 170 11  236 178 12  236 178 12  234 174 13  219 162 10  197 138 11
+163 110 8  137 92 6  85 60 19  10 10 10  2 2 6  2 2 6
+18 18 18  38 38 38  38 38 38  38 38 38  38 38 38  38 38 38
+38 38 38  38 38 38  38 38 38  38 38 38  26 26 26  2 2 6
+2 2 6  6 6 6  61 42 6  137 92 6  175 118 6  200 144 11
+219 162 10  230 174 11  234 174 13  230 174 11  219 162 10  210 150 10
+192 133 9  163 110 8  124 112 88  82 82 82  50 50 50  30 30 30
+14 14 14  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  6 6 6  14 14 14  22 22 22  34 34 34
+42 42 42  58 58 58  74 74 74  86 86 86  101 98 89  119 100 63
+125 96 44  121 87 25  137 92 6  152 99 6  163 110 8  180 123 7
+185 133 11  197 138 11  206 145 10  200 144 11  180 123 7  156 107 11
+137 92 6  104 69 6  45 32 11  54 54 54  108 105 106  101 98 89
+86 86 86  82 82 82  78 78 78  78 78 78  78 78 78  78 78 78
+78 78 78  78 78 78  78 78 78  82 82 82  86 86 86  94 94 94
+106 106 106  101 101 101  86 66 32  116 81 8  156 107 11  180 123 7
+192 133 9  200 144 11  206 145 10  200 144 11  192 133 9  175 118 6
+138 101 21  109 101 93  70 70 70  42 42 42  22 22 22  10 10 10
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  6 6 6  10 10 10
+14 14 14  22 22 22  30 30 30  38 38 38  50 50 50  62 62 62
+74 74 74  90 90 90  101 98 89  119 103 79  121 87 25  116 81 8
+137 92 6  152 99 6  152 99 6  152 99 6  137 92 6  116 81 8
+104 69 6  86 66 32  101 98 89  82 82 82  58 58 58  46 46 46
+38 38 38  34 34 34  34 34 34  34 34 34  34 34 34  34 34 34
+34 34 34  34 34 34  34 34 34  34 34 34  38 38 38  42 42 42
+54 54 54  82 82 82  97 87 74  85 60 19  137 92 6  156 107 11
+167 114 7  175 118 6  175 118 6  167 114 7  152 99 6  121 87 25
+101 98 89  62 62 62  34 34 34  18 18 18  6 6 6  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  6 6 6  6 6 6  10 10 10  18 18 18  22 22 22
+30 30 30  42 42 42  50 50 50  66 66 66  86 86 86  101 98 89
+104 86 63  104 69 6  104 69 6  104 69 6  104 69 6  85 60 19
+86 66 32  90 90 90  62 62 62  38 38 38  22 22 22  14 14 14
+10 10 10  10 10 10  10 10 10  10 10 10  10 10 10  10 10 10
+6 6 6  10 10 10  10 10 10  10 10 10  10 10 10  14 14 14
+22 22 22  42 42 42  70 70 70  89 81 66  78 53 15  104 69 6
+116 81 8  137 92 6  137 92 6  116 81 8  99 81 49  86 86 86
+58 58 58  30 30 30  14 14 14  6 6 6  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  6 6 6
+10 10 10  14 14 14  18 18 18  26 26 26  38 38 38  54 54 54
+70 70 70  86 86 86  97 87 74  89 81 66  89 81 66  86 86 86
+74 74 74  50 50 50  30 30 30  14 14 14  6 6 6  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+6 6 6  18 18 18  34 34 34  58 58 58  82 82 82  89 81 66
+89 81 66  89 81 66  100 88 68  97 87 74  74 74 74  50 50 50
+26 26 26  14 14 14  6 6 6  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  6 6 6  6 6 6  14 14 14  18 18 18
+30 30 30  38 38 38  46 46 46  54 54 54  50 50 50  42 42 42
+30 30 30  18 18 18  10 10 10  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  6 6 6  14 14 14  26 26 26  38 38 38  50 50 50
+58 58 58  58 58 58  54 54 54  42 42 42  30 30 30  18 18 18
+10 10 10  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  6 6 6
+6 6 6  10 10 10  14 14 14  18 18 18  18 18 18  14 14 14
+10 10 10  6 6 6  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  6 6 6  14 14 14  18 18 18
+22 22 22  22 22 22  18 18 18  14 14 14  10 10 10  6 6 6
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0  0 0 0  0 0 0  0 0 0  0 0 0
+0 0 0  0 0 0
diff -Naur --no-dereference a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
--- a/drivers/video/logo/logo.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/video/logo/logo.c	2024-01-28 14:01:31.256353824 -0500
@@ -100,6 +100,10 @@
 		/* SuperH Linux logo */
 		logo = &logo_superh_clut224;
 #endif
+#ifdef CONFIG_LOGO_BEAGLE_CLUT224
+		/* Generic Linux logo */
+		logo = &logo_beagle_clut224;
+#endif
 	}
 	return logo;
 }
diff -Naur --no-dereference a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
--- a/drivers/video/logo/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/video/logo/Makefile	2024-01-28 14:01:31.256353824 -0500
@@ -5,6 +5,7 @@
 obj-$(CONFIG_LOGO_LINUX_MONO)		+= logo_linux_mono.o
 obj-$(CONFIG_LOGO_LINUX_VGA16)		+= logo_linux_vga16.o
 obj-$(CONFIG_LOGO_LINUX_CLUT224)	+= logo_linux_clut224.o
+obj-$(CONFIG_LOGO_BEAGLE_CLUT224)	+= logo_beagle_clut224.o
 obj-$(CONFIG_LOGO_DEC_CLUT224)		+= logo_dec_clut224.o
 obj-$(CONFIG_LOGO_MAC_CLUT224)		+= logo_mac_clut224.o
 obj-$(CONFIG_LOGO_PARISC_CLUT224)	+= logo_parisc_clut224.o
diff -Naur --no-dereference a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c
--- a/drivers/watchdog/rti_wdt.c	2023-12-20 11:00:29.000000000 -0500
+++ b/drivers/watchdog/rti_wdt.c	2024-01-28 14:01:31.256353824 -0500
@@ -71,6 +71,9 @@
 	u32 timer_margin;
 	struct rti_wdt_device *wdt = watchdog_get_drvdata(wdd);
 
+	if (pm_runtime_suspended(wdd->parent))
+		pm_runtime_get_sync(wdd->parent);
+
 	/* set timeout period */
 	timer_margin = (u64)wdd->timeout * wdt->freq;
 	timer_margin >>= WDT_PRELOAD_SHIFT;
@@ -224,12 +227,8 @@
 	if (wdt->freq < 32768)
 		wdt->freq = wdt->freq * 9 / 10;
 
-	pm_runtime_enable(dev);
-	ret = pm_runtime_resume_and_get(dev);
-	if (ret < 0) {
-		pm_runtime_disable(&pdev->dev);
-		return dev_err_probe(dev, ret, "runtime pm failed\n");
-	}
+	devm_pm_runtime_enable(dev);
+	pm_runtime_get_noresume(dev);
 
 	platform_set_drvdata(pdev, wdt);
 
@@ -248,7 +247,7 @@
 	wdt->base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(wdt->base)) {
 		ret = PTR_ERR(wdt->base);
-		goto err_iomap;
+		return ret;
 	}
 
 	if (readl(wdt->base + RTIDWDCTRL) == WDENABLE_KEY) {
@@ -274,7 +273,7 @@
 		ret = rti_wdt_setup_hw_hb(wdd, wsize);
 		if (ret) {
 			dev_err(dev, "bad window size.\n");
-			goto err_iomap;
+			return ret;
 		}
 
 		last_ping = heartbeat_ms - time_left_ms;
@@ -289,19 +288,16 @@
 	ret = watchdog_register_device(wdd);
 	if (ret) {
 		dev_err(dev, "cannot register watchdog device\n");
-		goto err_iomap;
+		return ret;
 	}
 
 	if (last_ping)
 		watchdog_set_last_hw_keepalive(wdd, last_ping);
 
-	return 0;
-
-err_iomap:
-	pm_runtime_put_sync(&pdev->dev);
-	pm_runtime_disable(&pdev->dev);
+	if (!watchdog_hw_running(wdd))
+		pm_runtime_put_sync(&pdev->dev);
 
-	return ret;
+	return 0;
 }
 
 static int rti_wdt_remove(struct platform_device *pdev)
@@ -309,8 +305,9 @@
 	struct rti_wdt_device *wdt = platform_get_drvdata(pdev);
 
 	watchdog_unregister_device(&wdt->wdd);
-	pm_runtime_put(&pdev->dev);
-	pm_runtime_disable(&pdev->dev);
+
+	if (!pm_runtime_suspended(&pdev->dev))
+		pm_runtime_put_sync(&pdev->dev);
 
 	return 0;
 }
diff -Naur --no-dereference a/firmware/am335x-bone-scale-data.bin b/firmware/am335x-bone-scale-data.bin
--- a/firmware/am335x-bone-scale-data.bin	1969-12-31 19:00:00.000000000 -0500
+++ b/firmware/am335x-bone-scale-data.bin	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1 @@
+W#d$m$$m$$l$�$l$�d$m$$m$$l$�$l$�
\ No newline at end of file
diff -Naur --no-dereference a/firmware/am335x-evm-scale-data.bin b/firmware/am335x-evm-scale-data.bin
--- a/firmware/am335x-evm-scale-data.bin	1969-12-31 19:00:00.000000000 -0500
+++ b/firmware/am335x-evm-scale-data.bin	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1 @@
+Wd-%d-%+
\ No newline at end of file
diff -Naur --no-dereference a/firmware/am335x-pm-firmware.bin b/firmware/am335x-pm-firmware.bin
--- a/firmware/am335x-pm-firmware.bin	1969-12-31 19:00:00.000000000 -0500
+++ b/firmware/am335x-pm-firmware.bin	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,34 @@
+�����������������������������������������E
Y
�
�
����
�
�
)=Qey����JhC��s`pG0�D�<�KD�hpG��D8KD�`pG��D8KJh��`pG,�D�KhZ*	�J���h0� pG pG��#J$Khh�#M�"J/`"N���p!L"H��!J��%7`���#p%pHhJh`S��h�HI��0P`�D��hH�Gi��I	h)ИI��dh�T`��I��Q�$@,����<�D8�D�����0�D4�D��O��3�HLIJ#``]�K``pG4�D0�D8�D<�DJhC��s`pG0�DJh��C�@`pG�,�DJh#��C`pG�@�DKJh��|pG��KJh��X|pG������$��� F4��4,��K��Jh�B������r������� ���5 �~����� ��O��rI �� � F�������X$�����0���������@��������@�" �}���@" �P�����" �r���@" �E���$ F�S� F4�c�4,��K��Jh�B����� �,�5 �)� ��� ��U�@�� F�2� F�C���pG�pG�pG�pG�pG�2�FɲD��B��pG�xC!��+*��FpG��LF!h
+MI�K�B#`�Kp�#` ��O�8F����9F��� 8�Fx8�%F�����(��`8����Fxx�i�F<F}�B	������(�����F��0F����K0�h���B� ���0@�pG���r�KJhR�  LH`�>��FD����D
+ ������� F���0@�pG�T�$�$K`pG�T-��O$F�F'F���Fe�(t���r��FvF��%(!F��/��;FO� :F�����#u��W������������ �%.........������������������������������P����������U������^�c�m|����\����� F�����
+ ��#�i�ځ�@���#������oк���I�y��
+	�^#rF��0�F
�SF�F�fF�����3�L�\Y���a����O�O� ��۲�F�;F*�������sqF�
+к���+���+���s��E����	�����- L�����S�����+����+�����M�0xP���~��
4(�ѹ�?����+?������	����	��6>@F��d�s��LD�� �c�pxC�@.F��pxC�s.F����Q�4���c����(���px.F��pxC�c.F��pxC��.F��pxC�c.F���j@�c�pxO�0.F������0��0	(���j�.F�	�L����0��0	(��HF����eFbF��� C�S�����4�����F�pxC�.F��@�3�#�pxC�.F������@�C�"F�����#�a� ����*@��C�s ����#�i���pxC�.Fc���������&�HF��������ՐB�F�F�F���"��v�À��;>���;@F�������?��QFHF����4DD����pxC� .F+��C�i��@�Ӏ
+ �#��������@�#�C�,��pF����'D��H����D��HF.F�jO���$�$��	AѸ�0������+����9	��9@F��F����?���D�+@�Ӏ�+����O�	�������+����9	��9@F��'����?���D0x(?���O�	�������+��+?􏮺�?�}��0��p��Ԛ��^��{ջ������0�`{�
+ ������pxC�.F��px�� .F���HFQF��
+���9D>�	��9@F�������?��4D���T�#�s��vx��0��0	(�F���0FbF.F]�pxC�.FX��3���3���Ԙ��Z��O�
+*ջ��������Z��'���0��� ��X���0 4�����px����vB�.F#�^�g�������Z�^��������X�u���0�p��!FO�	���$�����S�F������]���pG����JK�B
��CD
H!�1FDS��BB���H	IO��B��@�+����ǻ��4*�������������������������� �6���� ��A���`pG�@���hpG#AB��X�JB(��0@��`@�@�a@`pG#AB��X�JB(��0J@B� 0pG���#AB��X�JB(��0J@B� 0pG���JhC�`pG��JhC�`pG��� ���� ���Kh`���D� ������0���8�������FH���������D���@ ���� ��0���@ ���� ������@ ��� F��,���@ ��w���! ������@! ���$ F��{� F4����4,��K��	Jh�Bн�@��� F��h� F��y���@�������# ��Z���@# �����$ ��P���@$ �����( ��F���@( �y���) ��<���@) �o���* ��2���@* �e���+ ��(���@+ �[���, �����@, �Q���- �����@- �G���. ��
+���@. �=���/ �����@/ �3���0 ������@0 �)���1 ������@1 ����2 ������@2 ����3 ������@3 ����4 ������@4 ����5 ������>���F�������0���V���@5 ���� ��B���@5 ���� ������@5 �����Khhh���pG�Khhh���pG�KhS�  h#�`pG�KhS�  hC�`pG�K�DKh�B�K���B�pGKJ`pGKJ`pG���)�&"K`Z`�`�`aZapG� K�DKh�B�K���B�pG	K	H
+I
+J�a�abpGKH	I	J�a�abpG�� `)())�)�)�)
+Jp�j�A��mhT�1�h-h��Pf`�``p� pG� Kp��i��EyYk�i�i����@��@$��@hXh!C��!��@�h�h
+C���i"��@C1�[i���@ �(Cp�pG Jy�ip��j
hHh��@��$�iMi�@"C����h"��@�hC�� ��@Cp�pG K�@j�R�0 [h`pG� Kj��Chh�pG� 
+Kj��	hhJ@�� pG�h�hhhX@�� pG� �Dh�����Y� x�!��O�0�$��U�� ��X��! D��N�Kh,���S��� F�����@ ����8�7K7JhF���|Dh+Y�(��h������� h.K@���O��� F��.�F F��X�!���!(F���������� �H��b�#x��Kx+���F�u ������K�DKh�B�K���B�� ��]�(��J hC�`��{� ��b�Kx+�ѽ�8@ ������Kh+���������� �D�8�"K"JhF���|Dh��(����#x�(�������� hK@ӱ��O�]� F����F F����!����!(F�����Q� ���Kx[���F�u �B����+����F��� ��8@𸾜���8�!K!JhF���|Dhs�(���#x�%������7� hK@����O�� F��`�F F����!��A�!(F��=���
Kx[���F�u ��������������� ��8@�m������8�KJhF���|DhS�(��Q�������� hK@˱��O��� F���F F��A�!����!(F���� �7�	Kx���8�F�u ������������Ch؈������@ ��8�F lh� �(��	������� F����F F���!����(F!����#y�+� �����8@ ����pG�p�F��J�(E�(M)L+h���h+;ИG0F����khx���D�h���+h���|C� �C�$ F���� F4����4,��K��Jh�B� F���� F������_���� ��p�5 ��m���p@ �����G�+h���|+�����pG�K�DK�h�B!�K���B!�����F ���� ���� ������5��A��+� F��d�����@ �o�Kh+�� ���� ������������F ��o� ��l� �S��	��� F��:��v���@ �E�����q�F ��S� ��P� �7���� F�� �@���@�Y�����Y�F ��;� ��8�����8� F��	��E���@ ����=���@ �����9�F ��� ������� F�����%� �����@ �
��KFhA��q`h���pG$@�DKFh!��q`h���pG$@�D"�K`Z`��E���@�
���
KHhI�J��4``hJ��#`�H������4������@����D��@�D�J hC�3`pG�p�DJ h#�3`pG�p�DJhC`pG�p�DO�qKJ`hC`pG��D�DJh#�s`pG�D8�IK�t`d#h+,�ch+/�#j+2�#i+5�ci+8ѣi+;ѣh+>��h+A��i+D�K��9M*h�BGУj+d�#k+]��j+M�K��*h�BP�8�! ����ch+��( ����#j+��3 ����#i+��- ����ci+��. �����i+��/ �����h+��* �����h+��, �����i+��2 ����K��M*h�B��ck+�� ����O�qKJ`hC`��0 ����K��*h�B�ѽ�8@4 ����$ ������# �������D��D�D"8�"K! `����( ����) ����* ����+ ����, ����- ����. ����/ ����0 ����1 ���2 ��|�3 ��y�# ��v�$ ��s�K��M,h�B�8�	J h#�s`��d�+h�B�ѽ�8@4 ��\�D��D�����%���
Kx�������� ���� �t� �q� �n� �k���@ �f��� �z� �w� �t� �q� �n� �����I� ���l�	KxC����K�DJh�B����V����@����8�O��s�B�F ��F ��� �?�F
� F8� �� F8�$ F8�����Kx��pG��Kx��pG��K��I�hINMLH	h6hK-h$hh�B`^`�`�`a�IJ	hhYa�a�pG��D��D�D@�DD�DHH�DL�D������Kh#�
Kh;+
�JK
O
NMLIH:`2`+`#``��
JhC��S`������?���@�DD�D�D�D�D�	���D8�����MKLHIJ+`#```h+�+�8�O�`o�bIK``8�%O��0
JhC�s`D�<\A�@8��@�D�?D�DH�DL�D��D�D`�DK�DKh�B�K���B�pG���������K�DJ�h�B�K��KHh]hL�h`�h%`iM�`.`dh�BњiXiIK``�pGKh+��
Kh;+��Ih#��S`����H�D�D@�DH�DL�D���D !	KF``hA�@`h�A�``h���pG��DKh+�"KJK`pG��D�	Kx�� �F�#IJ	h �@`��@�M�����q�D�	Kx�� �,�#IJ	h �@`��@�3�����q�DKh+�JhC�C`pG��DKh+�Jh#�C`pG��D J�h,:�#hY7�Ph���P�3P��.hJh2C*`P�3PJi.h2C*`P�3`�h�h2h=C*C2`P�3P
+i.h2C*`P�3P�i*h"�*`P�3 �ih#�`Kj�j	jChB��T�?Z���pGd#J�h.@�3hY=жFUh���U�4 ��h�iC`j�jhB��U�4 �ihC`jBjhB��U�4i
+h^�?"�
+`U�4p�h�h:h1C"�:`U�4Gi
+h"�
+`U�4@h
+h"�
+`Z����dK���Zh����j� h �A�!`k�`h+��]�KpGd
+K���Zh��h���j�)`�pGkh+��pG�dK���[h��Ckh��pGd"K�`�`aZa�apGdK�DKh�B
+�K���B�pG	K	I
+JY``pG	JK	IhY`*��J`pG��d''�p%`%�K��
���L�#h+����As��S�S�����&@�DK�DKh�B�K���B�pGKH	I	J��pGKHI	J��pG���d(<(4(�(�(�(K(hO�S�! h#��C�C�`pG��8�F	hJ�F�8�(F����T�K��8�8� ���KhS� 8�h�������@	pG�KhS�  h#�C�`pG��KhS�  h#�C�`pG��K Yh��K Yh��K �h��-��OO�	FFhJiK���������fMgHgI���(�-����	�`������������sx�{������G�'���%�FHF����-��5/�;F#�������rRQ��)@��!O�r�;��+@��#%O�BO��wBH�BM�8+����>KAI����x*DМFH�k���������Fl09O�zs�;P�
���Ԯ�pfxU��`����� 2F������#D��p�K�B���5O�zrt�[�:�������O��rO��0 K��������pr]*�� ��PKI�J
���PL���P%���@���0!��<B��������O��rO��0K������#��!"u牲s盲y����D���D���D���D���D(��D,��D���D���DhZ5��F%Jh`�W�#@O��r `�:�#h��C+��V�?j\�F���
�<�B�(��"hO��sW�"`�;��
+h�@?��<�B�� �pG pG��K�DKh�B�K���B�pGKH	I	J��pGKHI	J��pG����&�&�&$%%�$"IO��s	hQ� 
+`�;�
+h�@?��pG�#IO��r	hQ� `�:�h��C+��pG��KhS� 0h�������@	pG���K Yh��\� ���K Yh��R� ���K �h��H� ���K �h��>� ��Booted version 0x%x of CM3 PM Firmware.�$�$�$�$�$[%08x]%s:   ERR WARN INFO DEBUG0123456789abcdefghijklmnopqrstuvwxyz(null)0x
+	��������L�D(�D��D�D��D��D��D��Dd�D �D`�D�D,�D�����D� �D��Dp�D��D�D� �D��DH�DT�D�D� �D��D4�D@�D��D �D,�D��D\�Dh�D�D�D
+	����
����8*�D ��D0��Dh+�D@+�D(��D ��D@��D���D���D ��D ��DP��D8��D ��DK�]�a�e�����D� �D�-�D�-�D�-�D�D� �D .�D$.�D,.�D�D� �D�-�D�-�D�-�D`-�Dd-�Dl-�D -�D$-�D,-�D����
����)�D��D��D��D��D��D��D��D��D��D��D+�D����

+	�����DP�DD�D@�D�D�D�D�D�DH�D,�D�D�D�D�D�D�D	
+
+	@�D@�D�D�D�D�D ��@GNUe���ge�WӅ;��q2W�I��I�����������������|=1|=1�p�ap�aXq�-dY�� � ������������������������������log_buf
\ No newline at end of file
diff -Naur --no-dereference a/firmware/am335x-pm-firmware.elf b/firmware/am335x-pm-firmware.elf
--- a/firmware/am335x-pm-firmware.elf	1969-12-31 19:00:00.000000000 -0500
+++ b/firmware/am335x-pm-firmware.elf	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,388 @@
+ELF(4M4 (4*4*4*�Q�td�����������������������������������������E
Y
�
�
����
�
�
)=Qey����JhC��s`pG0�D�<�KD�hpG��D8KD�`pG��D8KJh��`pG,�D�KhZ*	�J���h0� pG pG��#J$Khh�#M�"J/`"N���p!L"H��!J��%7`���#p%pHhJh`S��h�HI��0P`�D��hH�Gi��I	h)ИI��dh�T`��I��Q�$@,����<�D8�D�����0�D4�D��O��3�HLIJ#``]�K``pG4�D0�D8�D<�DJhC��s`pG0�DJh��C�@`pG�,�DJh#��C`pG�@�DKJh��|pG��KJh��X|pG������$��� F4��4,��K��Jh�B������r������� ���5 �~����� ��O��rI �� � F�������X$�����0���������@��������@�" �}���@" �P�����" �r���@" �E���$ F�S� F4�c�4,��K��Jh�B����� �,�5 �)� ��� ��U�@�� F�2� F�C���pG�pG�pG�pG�pG�2�FɲD��B��pG�xC!��+*��FpG��LF!h
+MI�K�B#`�Kp�#` ��O�8F����9F��� 8�Fx8�%F�����(��`8����Fxx�i�F<F}�B	������(�����F��0F����K0�h���B� ���0@�pG���r�KJhR�  LH`�>��FD����D
+ ������� F���0@�pG�T�$�$K`pG�T-��O$F�F'F���Fe�(t���r��FvF��%(!F��/��;FO� :F�����#u��W������������ �%.........������������������������������P����������U������^�c�m|����\����� F�����
+ ��#�i�ځ�@���#������oк���I�y��
+	�^#rF��0�F
�SF�F�fF�����3�L�\Y���a����O�O� ��۲�F�;F*�������sqF�
+к���+���+���s��E����	�����- L�����S�����+����+�����M�0xP���~��
4(�ѹ�?����+?������	����	��6>@F��d�s��LD�� �c�pxC�@.F��pxC�s.F����Q�4���c����(���px.F��pxC�c.F��pxC��.F��pxC�c.F���j@�c�pxO�0.F������0��0	(���j�.F�	�L����0��0	(��HF����eFbF��� C�S�����4�����F�pxC�.F��@�3�#�pxC�.F������@�C�"F�����#�a� ����*@��C�s ����#�i���pxC�.Fc���������&�HF��������ՐB�F�F�F���"��v�À��;>���;@F�������?��QFHF����4DD����pxC� .F+��C�i��@�Ӏ
+ �#��������@�#�C�,��pF����'D��H����D��HF.F�jO���$�$��	AѸ�0������+����9	��9@F��F����?���D�+@�Ӏ�+����O�	�������+����9	��9@F��'����?���D0x(?���O�	�������+��+?􏮺�?�}��0��p��Ԛ��^��{ջ������0�`{�
+ ������pxC�.F��px�� .F���HFQF��
+���9D>�	��9@F�������?��4D���T�#�s��vx��0��0	(�F���0FbF.F]�pxC�.FX��3���3���Ԙ��Z��O�
+*ջ��������Z��'���0��� ��X���0 4�����px����vB�.F#�^�g�������Z�^��������X�u���0�p��!FO�	���$�����S�F������]���pG����JK�B
��CD
H!�1FDS��BB���H	IO��B��@�+����ǻ��4*�������������������������� �6���� ��A���`pG�@���hpG#AB��X�JB(��0@��`@�@�a@`pG#AB��X�JB(��0J@B� 0pG���#AB��X�JB(��0J@B� 0pG���JhC�`pG��JhC�`pG��� ���� ���Kh`���D� ������0���8�������FH���������D���@ ���� ��0���@ ���� ������@ ��� F��,���@ ��w���! ������@! ���$ F��{� F4����4,��K��	Jh�Bн�@��� F��h� F��y���@�������# ��Z���@# �����$ ��P���@$ �����( ��F���@( �y���) ��<���@) �o���* ��2���@* �e���+ ��(���@+ �[���, �����@, �Q���- �����@- �G���. ��
+���@. �=���/ �����@/ �3���0 ������@0 �)���1 ������@1 ����2 ������@2 ����3 ������@3 ����4 ������@4 ����5 ������>���F�������0���V���@5 ���� ��B���@5 ���� ������@5 �����Khhh���pG�Khhh���pG�KhS�  h#�`pG�KhS�  hC�`pG�K�DKh�B�K���B�pGKJ`pGKJ`pG���)�&"K`Z`�`�`aZapG� K�DKh�B�K���B�pG	K	H
+I
+J�a�abpGKH	I	J�a�abpG�� `)())�)�)�)
+Jp�j�A��mhT�1�h-h��Pf`�``p� pG� Kp��i��EyYk�i�i����@��@$��@hXh!C��!��@�h�h
+C���i"��@C1�[i���@ �(Cp�pG Jy�ip��j
hHh��@��$�iMi�@"C����h"��@�hC�� ��@Cp�pG K�@j�R�0 [h`pG� Kj��Chh�pG� 
+Kj��	hhJ@�� pG�h�hhhX@�� pG� �Dh�����Y� x�!��O�0�$��U�� ��X��! D��N�Kh,���S��� F�����@ ����8�7K7JhF���|Dh+Y�(��h������� h.K@���O��� F��.�F F��X�!���!(F���������� �H��b�#x��Kx+���F�u ������K�DKh�B�K���B�� ��]�(��J hC�`��{� ��b�Kx+�ѽ�8@ ������Kh+���������� �D�8�"K"JhF���|Dh��(����#x�(�������� hK@ӱ��O�]� F����F F����!����!(F�����Q� ���Kx[���F�u �B����+����F��� ��8@𸾜���8�!K!JhF���|Dhs�(���#x�%������7� hK@����O�� F��`�F F����!��A�!(F��=���
Kx[���F�u ��������������� ��8@�m������8�KJhF���|DhS�(��Q�������� hK@˱��O��� F���F F��A�!����!(F���� �7�	Kx���8�F�u ������������Ch؈������@ ��8�F lh� �(��	������� F����F F���!����(F!����#y�+� �����8@ ����pG�p�F��J�(E�(M)L+h���h+;ИG0F����khx���D�h���+h���|C� �C�$ F���� F4����4,��K��Jh�B� F���� F������_���� ��p�5 ��m���p@ �����G�+h���|+�����pG�K�DK�h�B!�K���B!�����F ���� ���� ������5��A��+� F��d�����@ �o�Kh+�� ���� ������������F ��o� ��l� �S��	��� F��:��v���@ �E�����q�F ��S� ��P� �7���� F�� �@���@�Y�����Y�F ��;� ��8�����8� F��	��E���@ ����=���@ �����9�F ��� ������� F�����%� �����@ �
��KFhA��q`h���pG$@�DKFh!��q`h���pG$@�D"�K`Z`��E���@�
���
KHhI�J��4``hJ��#`�H������4������@����D��@�D�J hC�3`pG�p�DJ h#�3`pG�p�DJhC`pG�p�DO�qKJ`hC`pG��D�DJh#�s`pG�D8�IK�t`d#h+,�ch+/�#j+2�#i+5�ci+8ѣi+;ѣh+>��h+A��i+D�K��9M*h�BGУj+d�#k+]��j+M�K��*h�BP�8�! ����ch+��( ����#j+��3 ����#i+��- ����ci+��. �����i+��/ �����h+��* �����h+��, �����i+��2 ����K��M*h�B��ck+�� ����O�qKJ`hC`��0 ����K��*h�B�ѽ�8@4 ����$ ������# �������D��D�D"8�"K! `����( ����) ����* ����+ ����, ����- ����. ����/ ����0 ����1 ���2 ��|�3 ��y�# ��v�$ ��s�K��M,h�B�8�	J h#�s`��d�+h�B�ѽ�8@4 ��\�D��D�����%���
Kx�������� ���� �t� �q� �n� �k���@ �f��� �z� �w� �t� �q� �n� �����I� ���l�	KxC����K�DJh�B����V����@����8�O��s�B�F ��F ��� �?�F
� F8� �� F8�$ F8�����Kx��pG��Kx��pG��K��I�hINMLH	h6hK-h$hh�B`^`�`�`a�IJ	hhYa�a�pG��D��D�D@�DD�DHH�DL�D������Kh#�
Kh;+
�JK
O
NMLIH:`2`+`#``��
JhC��S`������?���@�DD�D�D�D�D�	���D8�����MKLHIJ+`#```h+�+�8�O�`o�bIK``8�%O��0
JhC�s`D�<\A�@8��@�D�?D�DH�DL�D��D�D`�DK�DKh�B�K���B�pG���������K�DJ�h�B�K��KHh]hL�h`�h%`iM�`.`dh�BњiXiIK``�pGKh+��
Kh;+��Ih#��S`����H�D�D@�DH�DL�D���D !	KF``hA�@`h�A�``h���pG��DKh+�"KJK`pG��D�	Kx�� �F�#IJ	h �@`��@�M�����q�D�	Kx�� �,�#IJ	h �@`��@�3�����q�DKh+�JhC�C`pG��DKh+�Jh#�C`pG��D J�h,:�#hY7�Ph���P�3P��.hJh2C*`P�3PJi.h2C*`P�3`�h�h2h=C*C2`P�3P
+i.h2C*`P�3P�i*h"�*`P�3 �ih#�`Kj�j	jChB��T�?Z���pGd#J�h.@�3hY=жFUh���U�4 ��h�iC`j�jhB��U�4 �ihC`jBjhB��U�4i
+h^�?"�
+`U�4p�h�h:h1C"�:`U�4Gi
+h"�
+`U�4@h
+h"�
+`Z����dK���Zh����j� h �A�!`k�`h+��]�KpGd
+K���Zh��h���j�)`�pGkh+��pG�dK���[h��Ckh��pGd"K�`�`aZa�apGdK�DKh�B
+�K���B�pG	K	I
+JY``pG	JK	IhY`*��J`pG��d''�p%`%�K��
���L�#h+����As��S�S�����&@�DK�DKh�B�K���B�pGKH	I	J��pGKHI	J��pG���d(<(4(�(�(�(K(hO�S�! h#��C�C�`pG��8�F	hJ�F�8�(F����T�K��8�8� ���KhS� 8�h�������@	pG�KhS�  h#�C�`pG��KhS�  h#�C�`pG��K Yh��K Yh��K �h��-��OO�	FFhJiK���������fMgHgI���(�-����	�`������������sx�{������G�'���%�FHF����-��5/�;F#�������rRQ��)@��!O�r�;��+@��#%O�BO��wBH�BM�8+����>KAI����x*DМFH�k���������Fl09O�zs�;P�
���Ԯ�pfxU��`����� 2F������#D��p�K�B���5O�zrt�[�:�������O��rO��0 K��������pr]*�� ��PKI�J
���PL���P%���@���0!��<B��������O��rO��0K������#��!"u牲s盲y����D���D���D���D���D(��D,��D���D���DhZ5��F%Jh`�W�#@O��r `�:�#h��C+��V�?j\�F���
�<�B�(��"hO��sW�"`�;��
+h�@?��<�B�� �pG pG��K�DKh�B�K���B�pGKH	I	J��pGKHI	J��pG����&�&�&$%%�$"IO��s	hQ� 
+`�;�
+h�@?��pG�#IO��r	hQ� `�:�h��C+��pG��KhS� 0h�������@	pG���K Yh��\� ���K Yh��R� ���K �h��H� ���K �h��>� ��Booted version 0x%x of CM3 PM Firmware.�$�$�$�$�$[%08x]%s:   ERR WARN INFO DEBUG0123456789abcdefghijklmnopqrstuvwxyz(null)0x
+	��������L�D(�D��D�D��D��D��D��Dd�D �D`�D�D,�D�����D� �D��Dp�D��D�D� �D��DH�DT�D�D� �D��D4�D@�D��D �D,�D��D\�Dh�D�D�D
+	����
����8*�D ��D0��Dh+�D@+�D(��D ��D@��D���D���D ��D ��DP��D8��D ��DK�]�a�e�����D� �D�-�D�-�D�-�D�D� �D .�D$.�D,.�D�D� �D�-�D�-�D�-�D`-�Dd-�Dl-�D -�D$-�D,-�D����
����)�D��D��D��D��D��D��D��D��D��D��D+�D����

+	�����DP�DD�D@�D�D�D�D�D�DH�D,�D�D�D�D�D�D�D	
+
+	@�D@�D�D�D�D�D ��@GNUe���ge�WӅ;��q2W�I��I�����������������|=1|=1�p�ap�aXq�-dY�� � ������������������������������log_buf������0*PP�%`GP9�!	�olz��@5	]N
[xS�M��NPQ��RPgSPCVP�XPYP�ZPO[P`\P�^P)_P0`PzaP�bPecP�ePTjP	p
+�qP
+crPHm6n�
rtco�
raws�vs
+EwW
+4xs
+Cyy
+�zy
+�}�
+�~s
+�s
+���
+M��
+��%
+��%
+h�%��6����Preg�Q��E��Preg���]��P���4�PE!Q�۽"$�9'.;`$,�4$�N0� �0�-o "@�O!.P!9Q"0�P�~#�P��$��%d,�"����Z%id�Z���Pc�Pj�Pq�P&�����&��0�'&��H�1'&��`�J'(�)P�*int"��T,�&"Txќ9�.�&"Z���9."&"^���97.K#"`��9`.t E��e+QS���B�"��9�.�"������Z�,��P����"�
+�9.+"��Kj�Z>,��P_���(}"�
+�9�.�$��%��$��%��-A.�7P/X6�0��1�~/q)�/�Z�/�%�/Z�/�%�/�%�.�.�.0.O.x.L.�.9.42jjF����U*`J�int��0aHm3,V��verhnum hT!��"�h�	�~h�
+��%�&h4'V
+��,*Mda+hlen,hT-h
.MV]	��D1��2z�4�*5��6h�	��H�l��iH�
��
���Pt
�
 �
$
(.-PO4AP5
8(>3]P0J>�P3QX$R
+�T�Pt�GH`
+��
f�v5,�9]���+��,��)���}}��9��:88(�������	
+ ����l��*`���UJ�e��;0�	�
+��
$�int����	�l
+��
+��r�P�P
�x�u���zP
+�0~�P�P��dP"��P"
�&����&�Q���P�P���P"��P"
j/�X��i1�r��
+N!
+����P0��5Pt��IPt��
��nPO���P5��P;���Pt��Pt�R�v5,���qq*88(��)}}��9��(91��z2!%��f�O���H0[g���s�Pc��n%�cs�		int
+�Q`%(��s�'ret
%R
+��b����<�H0[n	~<<�~c	~�f\PwRuwint�~x��str��	���
+�>�Q��~�.�(str�
�%s	���
+�>�9?H�?v?gg������x�[���l��lvl��fmt��t�%�ret�	ap�d
+���P�$QtR�P2$�$"
+��P�\Q�`�P:
intQ��		)0�Blvl)�P��T���tt~���$d����nno�Q	�<V[�>*^^�%`1	R��padR�qR�	retT�
+intQ	B��L	B�numB^�B�n	B	C3	pE�	cE����Z�<8��
fmtZ�)
apZ��L	`���pa���	a�chb�nb�&
+numc^}
+�d�+tmpd��h	d��g	e��
b	f��9	g3�reth��i%��	y%	
+*	>	�J�	j��R ����4�L�a���R���JehA��]uh�tFPxe����u��	FPxe�	,W��u�	��	FPxe�	9���u�	��	FPxe�
+���5u��
+FPx XF!F�P- @F �F FF!�Q"Py!	\<PyQz d	\!p	g\P�$!�
+\vPyQz"FP0�"�#��$	�%&��'� ~(�Q�t� )fmtQ��p*+apS��d+retT�P�P�PQ�T&�0'�$s	;A�$" ,nn,``,��,���O
+��	��L�*`�	Ȕ�c��H�}�	�}`�	�}��,	�	,	�	,	�	,	�	,
+���E~
�	\����"�
+��N�
+��^
+��L
+��;
+ ���
+&���
+,��p
+2�,
+8�CQ�p�(�*`����
+Q�
+9�
+[��
+�
+	
+��
f.�
+$int����;	P>
+C�val,Preg���
+ ,$�;reg ��
��.5���0�	80(�f�f�f$�mSint`�X(���fM�fn�mSq&�(���&f��(f��)mS�1���3mS�;���=mS���	
��Fj	*`���=
R�:oP@�EP@int('�^�^�:�PO	�P	�[	�f	
q	
|
+
��PO
�P2
+"
�PO(
�'P1
+2
�:PO8
�NPtB
�POJCD
��L
:�P!V
EP![JX
D�iL�b
:�Ptj
��Pt
�
|�
:�Pt�
�Pt
�
|l]�
�W�
:FP#�
EP#}d�
���
:�P$�
EP$g
k�
���
:�P(�
EP(x
r�
��
:�P)�
EP)�
y�
�?�
:.P*�
EP*��y:hP+EP+���:�P,&EP,9�(��0:�P-:EP-V
�<�'D:P.NEP.E
�P�aX:PP/bEP/,
�d��l:�P0vEP0��x���:�P1�EP1�����:�P2�EP2����I�:8P3�EP3������:rP4�EP4���F�/�:�P5	�P	�[	�f	�|
+���P5���P2
+��P5�P1�P5v5,��)��00�����������88(�������qq*Q�
��
���
+ HH�
�
`�
�qid%P'!$��id!%P�
'8��id'%Pval)HS�
1P��id1%Pval3HS�
;h8�	
+Hv5H
4?)�
O))I�y�9*`���UJ�e��;0�	�
+��
$�int���~	$
+P�$%	����	+
+8!%	���
+^)'�$	��������*`Q0�R,gS,CV,�X,Y,�Z,O[,`\,�^,)_,0`,za,�b,ec,�e,Tj,C,T���0"��#,�$,�%,�&,�',�(,�),�*,�+, #,,$m-,(�.,,�81��2,3,<4,45,L6,`7,,8,�9,�:, �;,$�<,(#=,,m>,0�?,4�B��C,qD,o��,�,�,,.	var,
+�,
+),Em,S	valm,	vm,Rg,x	valg,	vg,�a,�	vala,	va,�[,�	val[,	v[,�t,�	valt,	vt,�U,	valU,	vU,�O,1	valO,	vO,TI,V	valI,	vI,\z,{	valz,	vz,.���	pd�7��,t�,int
1(��
C2�X��?,0�val?,.pd?7M�,@\��4��nv�,��@ �c���SJ8��nc��JPi"�.zh�I> ��p"B3��,�H�L4��Uv�,vV���qvf�
���npd�7P�,��pd�7�l��0�$���{��������{.��.�S�
+�58; T�Q<W �m@s �!��"�~�!x #v5,#;#�W!s�$#� �#�;#W#x� �|��=��*`�ff�����int�8"�$�$Y $�!$�"$�#$1$$'%$�'$ �($$�)$(+$,y,$0�-$4	92
+2~m�Op%"	dd
+2+eOz`%TvC���
 @@�
�
`^WW~@t�&G����H�j
�0*`G79�!	�olz��@5	]N
[xS�M��N7Q��R7gS7CV7�X7Y7�Z7O[7`\7�^7)_70`7za7�b7ec7�e7Tj7p�	�q7	cr7
+Hmn�rtco�raws�vZ	Ew>	4xZ	Cy`	�z`
+
��}�	�~Z	�Z	���	M��	��%	��%	h�%��

�
��cc�
+Q�
+9�
+[��
+�
+	
+��
f.�
+$int�c�UJ�e��;0�	�
+��
$�C7����c9����� 7\�
�
�!H\�)4!��#)>$7QRV"n-�P@<$Q�t8�P�|-�Q��C�N�YPt�YP?
��P����4P�l�R���S7�DT7'�Uc:��d�o�z�Pt���Pt���Q0���PuQ1��C�Y,P1N&oJP
+uj,�F�fP1Z�yP0`��P0rY�P?v�
������4��\������7�D�7���d�o�z/Pt��CPt��VQ0��oPuQ1��Y�P1o�P
+uj� �,YP?K�<���4���ͩa��7tD�7�Zjdzo�zBPt��VPt��iQ0���PuQ1���o�P
+uj�����YP?k�����	4������TD�7���7��doz@	Pt�T	Pt �g	Q0(��	PuQ1.Y�	P1@o�	P
+ujF��X�
+4�.��OfdpYP1�pR��
+4�r�!���"7�D#7�|�j
+P3��d�z�
+Pt���
+Pt���
+Q0���
+PuQ1���
+P5�YP1�;��4;�P �A���4hAc�!iCc���	iPv�*�P15�Pt&@�Pt<5�PtB@�PtFKJVPaPOVaP5`**P;fl"$}�����p�%
��c[�w���P1���P0���P?�����������Pt����
P1��
P0#��P0���6��
��cy�w�g
P1�z
P0��
P?�� ��
Pt$�.�P1��0.�[��c�6w>�P1D�!P0J�4P?N�T�QPt$^��`0����c�fwn��P1t��P0x�|����Pt����P1,�������P1��6���c��w��`P1��sP0�������Pt�����P1��P3%��&%'v57'�67'X�(g)'q��'��%*wwF*��	G*CC	I*�
+�
+	H*��,*��+*WW)*//@*]]?*N*��O*��J*88-*��0*QQ<*L*�
�
*''*''C*~~3*��)*���*�*��=*FFG*��(*��
+)*qq
+**}}*��9*88
+(*��D*llQ*

K***��,*ZZ1*		+*��.*���*vvA*�
�
*�
�
*��-*��4��������0*PP�%`���UJ�e��;0�	�
+��
$�int������� P3�
�
GP9�!	�olz��@5	]N
[xS	�M�
+�NP	Q�
+�RP
+gSP
+CVP
+�XP
+YP
+�ZP
+O[P
+`\P
+�^P
+)_P
+0`P
+zaP
+�bP
+ecP
+�eP
+TjPp��qPcrP
Hmn�rtco�raws�	vOEw34xOCyU�zU
+�P�varP�P)P~u�=
w�&��=
��AA��C�WO��Q���������,��;�T���D$L��varFP;H�L�PT\QV�p��vXPY\vZ �l wl lY�a���JvcP�\�e �� w� l�]l���!�l��vnP�\�p �� w l�����������//��8�@!���S"���,#���$J)@%P!$V)T%P($b)h%P3$n)|%P-$z)�%P.$�)�%P/$�)�%P*$�)�%P,$�)�%P2$�)�%P@$�)%P0&�)%P4$�)/%P$'�)%P#v����(����x)���$4�%P!$$4�%P($*4�%P)$04�%P*$64�%P+$<4�%P,$B4%P-$H4%P.$N4,%P/$T4@%P0$Z4T%P1$`4h%P2$f4|%P3$l4�%P#$r4�%P$$�4�%P@*�4%P4'�H��	"��
+�		#�
++����?�J�U�`$�k@	%P1$�vS	%P4$�vf	%P2$�vy	%P1$�v�	%P0*�v%P3,��d��
+-�(��	)�+�D$���	%P3$�
+%P0$�
+%P1$�'
+%P2$�:
+%P4$�M
+%P1�$$�i
+%P1(�2�N�.F1�X:�1/�1U�0n311ret4�
)�2�7%N$j��
+%P4$r�
+%P4$z� %Pt�� '��%P47H���`+�������+��3�4PD4v6P�4�7P�4�8P�5X�5��%611G6ss86��(6��'6CCH6��96�
�
688	(6��	)6((
+6��
+6
+6��
+6�
�
6~~36��46�
�
666
+6��(6��
+6
+
+
+6
+6ll*6��6��)�L��*`���UJ�e��;0�	�
+��
$�int���~	$
+i��&	����	+
+w#�&	�
+1,�&	�n��������0*PP�%`���UJ�e��;0�	�
+��
$�int	"=
+:#=
+�$=
+�%=
+�'=
+(=
+F)=
+�*=[�/�Zd
var\PD�d�$>l��var?PS"DL�x��X�@�Xa�D�z$�Ls
+�$��#var�PS6��0�Hvar�Pt��� ���4��[�P3&fP3�44��D[�P3ZfP3(�h��var�P���var�P��-�Hv5P�6P�����%����(��)�D����8;*`�nn�����int�8*�,�,Y ,�!,�",�#,1$,'%,�', �(,$�),(+,,y,,0�-,4	a!M
+�!3var#,�v����
ixn�*�f{6��fA�	SJ�
+�J3varL,Z(��
+
i�nX �<���l �� ~��4�/��3� ���0�T��3� ��, ����3!
val�,!!s�8��
i�n9!��LT���,�8�����h��n�!~n��)h/upEdK3,`�Plv5,�6,/����K�e�����q��|����U*`�ff�����int�8"�$�$Y $�!$�"$�#$1$$'%$�'$ �($$�)$(+$,y,$0�-$4	92
+2~m�O'"	dd
+2+qOz'T0m���`*�MG�NQD�RgSCV�XY�ZO[`\�^)_0`za�bec�eTjpe�qcrHm�nG	rtco+	rawsD
+�e�
+�nep
+0e�
+O-e�
+x@e�
+LQe�
+�ae|
+9~ed
+4�eX���� ��0*PP�%`����
+Q�
+9�
+[��
+�
+	
+��
f.�
+$int	P

+varP�P)PV,0
+reg,�
var.P�5S
+reg5�
var7P�>�y�>�
+id>W��T�S, (�Uc�!nQ�cn
6 A6 $�!�< 
+1���!0F C<F GS�F :��qH�T &���H��!idsH�B"retJ�y"iK��"j SPu �!W"�Q%|  ��idQW�"varSP##W^� �t$id^WP
� `6#� $S#�� 1f#�z#�S##c� ��$idcWP0� e<�#� G�#�� :�#��#��##�h� �%� UP1#�m� �7%� UP2#�r� �\%� UP2&�m� s!P&���&3��'v5P(s�)'��!�(��)'��!�',�!�'c�!�'B!�'�!�/9���*`����
+Q�
+9�
+[��
+�
+	
+��
f.�
+$int���~	$
+c�d(	����		+
+B!<(	���
+�/-4(	/���z*`����
+Q�
+9�
+[��
+�
+	
+��
f.�
+$int���~	$
+���(	����
+	+
+�!�(	���
+,0-�(	�B��C::��`�0"��#:�$:�%:�&:�':�(:�):�*:�+: #,:$m-:(�.:,�81��2:3:<4:45:L6:`7:,8:�9:�:: �;:$�<:(#=:,m>:0�?:4�B��C:qD:��`)A#�()�	��
+�~�x4)������� �:*`�nn�����into,�val,�reg,n		1��reg1n
+D6	}=n�ret?ni@n	�NnretPniQn
�T�3b�bn
�dn
�en
�fn
�gnsclhn
%in
jn��n� �������#len��o$����$e��X
*��
���
���
 ��
��u� �'���!0�D��$�!X�a��$�!x�~��$�!�����$�!����%R!���&%�1?%<G]%Rp%]�%h�%s�%u�!�;�?&�T&u�!0�]�h&�u�!��}&�V!�^!�Pyu�!H����&��&u�!h����&��&��!��u�!�9��&��&u�!��B�'�&'u�!��`��u�!��~����!�����<'�]'��!I�u�!9��'��'��!@C�u�!X���'�(�"�Qu"9�<(�Q(�"p��p�f(�( ��!
�&"U��(�0"�^u0"�9��(�
+)uL"����,)�A)uN"��#�U)�j)uX"�I�~)��)u`"(�o��)��)uj"ԕ��)��)up"���)�*"�H#�[$��;$��6vi!�P�p @@�
�
`^WW~@�
t�)G�!�}��"���0*`���UJ�e��;0�	�
+��
$�int�9�	reg9�
+i;��/�	reg/�
+i1�kC%	regC��H��"|��
�H�"*idsH�\*iJ��*��"N���*�"��*�#R�7+#�Q+�>�H#T��W�#$�!idW>P��#@Y��+@��+�\�#(�kid\>P��#`^�,`�1,la%�# ��ida>�,��#c�,8k�$��$P0�s�$��($P2�{�0$�'<$P0	��D$�PP$P2Ia�g7?��e�� v57!g�" P��!��" 8�� ^�� i�� w�� 1
+��#����C::��`�0"��#:�$:�%:�&:�':�(:�):�*:�+: #,:$m-:(�.:,�81��2:3:<4:45:L6:`7:,8:�9:�:: �;:$�<:(#=:,m>:0�?:4�B��C:qD:��)A�#��)�	��
+�~�2�)�%:;I$>I:;(I:;:;
:;I
8	:;
+
:;I8:;
:;I

:;II'I'.?:;'I :;I.?:;' :;I4:;I.:;'@�B:;I1XY411XY1:;I���B1 .1@�B!1".?:;'@�B#1RUXY$.?:;'I@�B%4:;I&1RUXY'1(���B)���B*$>+41,4:;I-4:;I.4:;I?</4:;I?0I1!I/2.?<n:;%U$>$>:;I:;
:;I8
:;I8I	!I/
+!I.?:;'I@�B4:;I
��1��1���B��1.?:;'I�@�B4:;I?<4:;I?.?<n:;%$>I:;((
$>.?:;' :;I	.1@�B
+1��1���B
.?:;'@�B:;I1XY��1���B14:;I��1.?:;'@�B4:;I?<.?<n:;%.?:;' .1@�B%U:;I$>.?:;'I@�B:;I:;I4:;I	$>
+I&I%:;I$>.?:;'I@�B:;I��1���B$>	4:;I
+��1I&I
:;I4:;I4:;I?<.?<n%$>.?:;'I@�B:;I:;I4:;I4:;I	4:;I
+��1���B��1
$>I&I:;
I84.?:;'@�B4:;II!I/.?<n:;%$>:;II:;(.:;'I :;I:;I	4:;I
+$>I.?:;'I@�B
:;I4:;I4:;I4:;I4:;I
+:;
+:;
+:;1XY141141��1���B1XY1RUXYU ��1!��1"&I#:;$
I84%&I'!I/(.?:;'I@�B):;I*+4:;I,.?<n:;%$>.?:;'�@�B.?:;'@�B4:;I4:;I���B1I	4:;I?<
+I!I/
4:;I?.?<n:;%.?:;'�@�B%$>I:;((
$>.?:;'I@�B��1	���B
+.?:;'@�B:;I:;I
.?<n:;%.?:;'@�B:;I4:;I4:;I$>$>.?:;'@�B%$>.?:;'@�B4:;I��1���B��1$>	��1
+���B1���B14:;I
���B14:;I?<.?<n:;%I:;($>.?:;'@�B:;I4:;I.?:;'@�B	4:;I
+I&I4:;I?<
I!%$>I:;((
$>I!I/	&I
+4:;I?%$>:;
:;I
8I:;(
:;I8.:;'I 	:;I
+:;I4:;I$>
.?:;'@�B.?:;'I@�B:;I:;I4:;I1RUXY111RUXY1XYI.?:;'@�B:;I1XY411414:;I &I!I"!I/#4:;I?<$!%$>I:;((
$>:;
:;I8	I
+!I/&I4:;I?%I:;($>I!I/&I4:;I?%:;I$>I:;(:;
:;I
8:;	
:;I8
+:;
:;I
:;I
I'I'(
$>.?:;'@�B:;I4:;I��1��1���B���B1���B14:;I.?:;'@�B:;I4:;I:;I .?:;'@�B!4:;I".?:;'@�B#��1$���B1%4:;I&&I'4:;I?<(I)!*.?<n:;%:;I$>I:;(I:;(
$>	:;
+
:;I
8:;
:;I8
:;
:;I
:;II.:;'I :;I:;I.?:;' 4:;I.?:;' 4:;I.1@�B41.?:;'@�B��1���B14:;I.?:;'I@�B1XY 1!:;I"1XY#$��1%���B&���B1'��1(1RUXY)U*���B1+41,.?:;'@�B-1RUXY..?:;'I@�B/:;I04:;I14:;I24:;I34:;I44:;I?54:;I?<6.?<n:;%$>I:;((
$>I!I/	&I
+4:;I?%:;I$>I:;(I:;(
$>	:;
+
:;I8.?:;' .?:;' 
4:;I.1@�B.?:;'@�B4:;I��1.1@�B4141���B14:;I.?:;'@�B��1���B���B14:;I4:;I?<.?<n:;%$>I:;((
$>:;
:;I8	.:;' 
+:;I4:;I.?:;'@�B
4:;I1XY1411RUXYU:;I.?:;'I@�B.?:;'@�B4:;I4:;II!I/&II4:;I?<!%$>I:;((
$>:;
:;I8	I
+!I/&I4:;I?%$>:;
:;I
8:;
:;I8:;
:;I	
:;I
+4:;I?%:;I$>I:;(I:;(
$>	.:;'I 
+:;I:;I.:;' 
4:;I.?:;'I .?:;'@�B.1@�B11U111XY4141.:;'I@�B:;I:;I4:;I��1���B I!&I".?:;'I@�B#.?:;'@�B$:;I%���B1&4:;I'4:;I?<(I)!%$>I:;((
$>I!I/	&I
+4:;I?%$>I:;((
$>I!I/	&I
+4:;I?%I:;($>:;
:;I84:;I?&I	I
+!I/%$>I:;((
$>.:;' :;I	.:;'I 
+.:;' 4:;I
4:;I:;I.?:;'I@�B:;I4:;I4:;I4:;I1RUXY11U41411XY��1��1���B1RUXY1XY U!41"I#&I$.?<n:;%I:;($>I!I/&I4:;I?%:;I$>I:;((
$>.:;' 	:;I
+4:;I.:;'I .:;'I@�B
:;I:;I4:;I1XY1411XYI&I.?:;'@�B.?:;'@�B:;I1RUXYU.?:;'I@�B��1���B4:;I 4:;I?<!I"!%I:;($>:;
:;I84:;I?&I	I
+!I/S2�2�SP�P� P (�P�8>1���S����<Sx~5�<L2�<L	��LN3�LN	��NT4�NT	��TV5�TV	��hl2�tv2�tvS|�P���P���S��P|�1���1���P��P���P���S��P��6���6���PTPt�`TP
+�P�P$�P�P�P�$)P):�P�<@0�@JTJMPMNt�N�Tx�0�Q&�Q�Rr�P$S(,P,4S48s�(.0�.0p s"�08QP V &P&<V<BPBNTNTt�@BPBFTFTUTV�P�X^P^jWjnt�nvTv~t�~�W��t�X`Q`jq�~�q�\^P^�WP�P�.P.l�P� VU:VTVlPPU^@FVFU
+�U��V��v��8UQ,Q�Vv�V��Y��V<HYP,>P>@~���FP
+~���
+P\|#�@BPBF|#�FHPHP|#�PRPRZ|#�Z]PbdPd~|#�~�P��|#���P��|#���P��|#���P��|#���P��Y��Y��P��|#��P	|#�P|#�P,|#�,4P4J|#�JLPLP|#�P^P^n|#�npPpx|#�x�P��|#���P��|#���P�|#�P|#�$P$'|#�8LY��|#��<|#�dtPtx|0�x�V��P��|#���P��|#���P��|#��,|#���0���\��\��R8L\jp0�p�\
+0�.@ZhnZ
+Z.8ZL�Z��Z
+Z$Z��Z��Z��ZZZ,8Z@��Pn@��:�.8��L�����:��
+��$:�dj@�������:��������:�,8����S������S�@��.8��L���������S������S������S����,8��@0�@��
+0�
+������$@Y@p��pxPx���������V�.��8d��djSj�����S���<��<dVd�����P������V�8��@R
+R@]Rb�R�	R:RJRRn�R������R��R'R8LR$<Rj�R��R��R��R��R@ �
+ �
+0�*W,.1�.8W
+0�QT,ZQZ\T\�^��Q��t���T
+t�
+T<>ty"�>@T@]Q]bTb	Q	
+t�
+T>Q>JTJ�Q��T�"Q".T68T8jQ��t��"���Q��T�
+Q
+T<Q<dTd�Q��T�Q,T@S
+S�Y@]Sb	S@SJhShnYn�S������S��S�YS'S8LSLPY��Y�
+Y
+S$Y$<Sd�S��Y��S��S��S�Y$SFP~0.�P\r0.�\�q0.�F���F���F\Z\^R^fS��S��RF������S�����F\���\^V^jv�jV.8VL�V��V��V��V,8Vj�S,0Y02V28v�8<V��V��[��{���[fjSjnYnty�tzY��S��Y��y���YJPYPVy�V\Y S &s|�&(SQq����{�q����{� P $p����{�$&p����{�&(�P�P(�P�p �(�P �(BPBP�P�(Bp �BP�P �PjPjx�P�Pjp �jx�P ���0���T��P��t���T��Tp�P��qp�Q���Q���P���P���0���
+p�3&����u3&����p�3&�s$����P#�3&�s$���s���P#�	�$3&����Q�
+P
+D�P��0��p���S`hPhx�P�x�0���Q��R��PP\�P�T,0	t�p"�\vPv�U���P���U�*�P�*-P-0U0X�P�r$T*XT��P��U�$U0XU��Ps2!�SXpPp�U���P���U��P��U���P�n�T��P��U��U��P�P:U:Z�P�ZjUjmPmpUp��P�
+vT:<P<ZUpvU@EP��P��U���P���U��P�U��P��P��UP(�P�p�P#(.P.LULz�P�0tTLNPNtURWP��P�V�P�<V��0���T��P��t��T\^P^�T��P��T��P�T "P"BT`bPb�T
+q@D$!�
+Q"	q���w�"0QR^SdjS��S��@=$���S��0���@=$���P���P���S��P��
+�����S��s����SPl�P�lnPnqDq8�P���S��s�����S��P���P���P���P���0���P��T��0���T��U"S
+QQ��S��S0�S $V$,R.0V0HRHJvJLVL`R`budlSlnr��0���S��Q��S��Q��S�R2P2P�P�PdPd��P���P���P���p����0���1���2���3���4���5�sHJ$�"sHC$�"&ST^P^|�P�dhS|�P��U���P���U��P���P�|�Q��T���Q���T|�0���P��0���P��P��0�|�0���0���P���P���p3���P��p���p2$�"��S��1���3���p2$�"��S��2���3� P LTLZVZ�T�t�Rr�"RNTt���t���T��RPTtZ�W��W>��>D,�DN��NR��RZ��Z�w
+�����w
+���`bPblUflUv�U��Uz�S��S��sy���S��S��S��r{���Q��r{���Q��r{���Q��r{�������0�������������������0���	����(���	��������0���	����
+�s���
+�s���
+�s���
+�s���(���(���	����	��T��$T$@p@D���DJNp(�	��8D	��JN0�&,
+�r�,.
+�r�.8
+�r�JN
+�r�.2$�8D(�JN(�8D	��JN	��T`��T`0�`d��`d�Ldl��dl�Hlr��lr�Drx��rx�Tx�,�x��PnPnr�P�rtPt|�P�BQBpu�pr�Q�r|Q0�2U2BRr|0�s2$w"0�1� @<$r� "
+��r�",@<$r�LXt2$w"LX0�XZ1�Z\@<$s�\^
+��s�^l@<$s���p2$�"��0���1���@<$s���
+��s���@<$s��p2$�"�0�1�@<$r�
+
+��r�
+@<$r�&P&<�P�&p2$�"�$��l`
+�l��9(<���x5<V��L��;(�0���Fz#��$�%���-/�/H�B���N
P��S�8]W�X[� -``a�b�d� ��kl�"�p8:<>xz|~z|~���������<@DFJLBDLNFHRTHJTV�``j<DHJ\����������������������PVhn�������TVXZ^n8<48<>"&>D*,DFLN .0NR "02RTXZZ������������������������������������������������������������������&<@DJN&*.88<@DJNTVZ\^`VZ\^bd`bdhjlhjlr�����������Qv�
src/sys_execsrc/includemsg.cmsg.hprcm_core.hpm_state_data.hstddef.hsync.h��./�.�J�.KQ�s q  |\�#j_!J
 =">!P.1 -";O ).W *  r 
 "&//1Yu /JwI�B>.B �f�.�.���./�.�J��.!�.�X��./� �Xuwu^�
src/sys_exec/home/a0274052local/toolchains/gcc-linaro-5.3-2016.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/includesrc/includesys_init.cstdint.hrsc_table.hprcm_core.hcm3.hmsg.htrace.hsync.hdebug.h�
+ 22!-2j0001=>3>ke.	`�'2�m�
src/sys_execsrc/includesync.cmsg.hcm3.htrace.hprcm_core.hhwmod.hl!/Az /
+ >-@!1>-N$"=#+5k01=CJ<=$.=f@+�
src/sys_exectrace.c!X>�
src/libsrc/includestring.ctypes.hK-11�u<�
src/libsrc/includeputs.ctypes.h<	!!"$!","0z.	� "=-[1 "t/-w�V�
src/libsrc/includedebug.cprintf.hputs.h<built-in>�%%%/ sX?�!"!>?0!��c�
src/libsrc/includeprintf.cputs.hstring.hstddef.h<built-in><�
.s .t  =0+�.	t�a�~J�  /0= �</=0�~.�g�>�JX=LMY",>2!1.=MMM/-03JJ�~t=;�.�~.� ?�.� �.)&(/!"=K!l<Dx.	 0u. v.,# Yc.#.-0\�" K-0I$��>�.K>.C.> "==�.�.>=��� 2K3y &-//0�.� "�.</"L�~.Y;�<I!z J�.�   � �.0K��2=/�<_y (j �~X\ ��<</�~XK;�</N�.�~XK;�<0�~t� Xy�SJ000/IX�t�.� �JF.<g. �<�~J�.�~ =;�<x x<E<0;!:^ �<�.�.LjJ000K�.� �<00/t�<!�~J/j.�.=X=�.� �<=��<A!2S/�
src/foundationstartup.c��_.�,",	 
�
V:�
src/foundationexception_handlers.c�4444444dH�
src/foundationsrc/includertc.cclockdomain.h!]1jYV+�
src/foundationcm3.c0�r"O�0��0�/0N/0,��
src/foundationsrc/includeext_intr_handlers.ccm3.hpm_handlers.hmsg.hsync.hprcm_core.h�"=A/]!>0CMA2-v<<-s<<-y<D-O!>-O$"=#+3l-*=@-]!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>-O!>4?B2-y<D-u<<-�l�
src/pm_servicessrc/includeldo.cprcm_core.hldo_335x.hldo_43xx.hldo.h>=M>=MY/\Y/\hYH
PJ�
src/pm_servicessrc/includehwmod_335x.chwmod.h7��
src/pm_servicessrc/includepowerdomain.cio.hmsg.hpowerdomain.hprcm_core.hpowerdomain_335x.hpowerdomain_43xx.h�(=!!!!\jY/!!!z./!!!	."//-!!/!!#:fu u  !� �t� �J� �tMn k  (�[�gfv/-!"V/"XNH�
src/includesrc/pm_servicesdpll.hdpll_335x.cLF�
src/includesrc/pm_servicesldo.hldo_335x.c<��
src/pm_servicessrc/includepm_handlers.cmsg.hclockdomain.hhwmod.hpowerdomain.hdpll.hldo.hprcm_core.hrtc.hcm3.htrace.hstddef.hH!!#?0&z !Ah>LZ11	<y.f&z<&S%1>[KNKA?M010>1<UJX0fLZ$">/AN-H<'<<%7%T$#??[KNK??M0>pJxXz< <#+�%7%T$#??[KNK??M0rJxXz<<#+�%7%T$#>[KNK??L>sXvX�#i-@ %$0>ZK??LY?-O4 	 K�2">K0>	ta<$ =",4g=?01=@-`J5�.9#<P>=>>0000>1-g<L= �#>=>>00>1-
+J#>=>>0?#-	<#>=>/0>1-C!1-	<#>=>00>0?-���
src/pm_servicessrc/includeprcm_core.cio.hhwmod.hdpll.hldo.hmsg.hpowerdomain.hclockdomain.hcm3.hddr.hi2c.hstddef.h��$">=>$">=�}<!/"0-\"#&/!"!L///0-�'y @ �.#M'y � �.#M�.�<\?#!�1	f!#+#M????????f???Mf>=>=>=>=>=>=>=>=>f=H<?#!�<>Z-z<G
�z &##/=============>�t� � #�<1@+�!00�.�X0>===>-\!====>>1><.H<0�-t$YK=Y%*@u. [�PJ�
src/pm_servicessrc/includehwmod_43xx.chwmod.hSg�
src/pm_servicessrc/includeddr.cprcm_core.hmsg.hhwmod.hstddef.h�/y.!'z !"!"z ""!"y !!"!"!!!!"L#1<`$!#!&u.!#!&o.//�#1/!!"!!!"D>4z.&z &v.!)//"/XhY,^8$<y.=/$$"!">/!"m.KL/0f# p ##!?"/-!#=N?,0�!M>L1-�!M>L1-�L//kL//p�
src/pm_servicessrc/includedpll.cdpll.hprcm_core.hdpll_335x.hdpll_43xx.h��#�tu/#/!!#/-!/#/!!#/!/#/!/[6<LN#L�u/?@/!!?@/" _./#/-!=#/!/#/!/ kI!ge%=[�:">x�M�kY/!)/!/	 !![(x !"?0/	NH�
src/includesrc/pm_servicesdpll.hdpll_43xx.cQK�
src/includesrc/pm_servicesmsg.hpm_state_data.c��
src/pm_servicessrc/includeclockdomain.cio.hprcm_core.hclockdomain_335x.hclockdomain_43xx.hstddef.hclockdomain.h�jY/!zJ/! J!%j.h<#t M #X!;M)D[#u?P.h<J2XT._<#J.Xjj\V�
src/pm_servicessrc/includeclockdomain_43xx.cclockdomain.h\V�
src/pm_servicessrc/includeclockdomain_335x.cclockdomain.h\V�
src/includesrc/pm_servicespowerdomain.hpowerdomain_43xx.c2B�
src/pm_servicessrc/includei2c.cdpll.h� ��.�. s � � �.���.� � �.� )3�X�<�J�.: ><>H"/=>h!>�J��~<�� �<q. k.�.�~.�.�~ �.�~<�X-�~ � �f)`.#.X<�.�~.�.�~<�.�~<�X1�~<�.�~.�.�<)LF�
src/includesrc/pm_servicesldo.hldo_43xx.c���
src/pm_servicessrc/includehwmod.cprcm_core.hhwmod_335x.hhwmod_43xx.hstddef.hhwmod.h�"�93;o h/J�//` h/J3G�jY/!zJ/!8JZ' Y '.Y L/)f_" ^ ".^ L/$�b.</�"[M"[M![M![\V�
src/includesrc/pm_servicespowerdomain.hpowerdomain_335x.cCMD_ID_CPUIDLE_V2cmd_datapd_mpu_ram_ret_statemsg_cmd_read_idCMD_ID_DS2_V2CMD_ID_STANDBY_V2a8_reset_handlercmd_handlerssizetypeGNU C11 5.3.1 20160113 -mcpu=cortex-m3 -mthumb -mfloat-abi=hard -mfpu=vfpv3-d16 -mtls-dialect=gnu -g -O2 -fno-delete-null-pointer-checks -fno-strict-overflow -fno-exceptionsCMD_ID_STANDALONEcmd_idspd_mpu_l2_ret_stateparam2param3param4CMD_ID_CPUIDLE/home/a0274052local/git-repos/amx3-cm3m3_firmware_versiondebug_haltpd_mpu_l1_ret_stateboolcmd_stat_valuemsg_cmd_is_validmsg_cmd_dispatcherdeep_sleep_datapd_per_icss_mem_ret_statevdd_mpu_valds0_data_hsCMD_ID_VERSIONinit_m3_state_machinemsg_cmd_stat_updatea8_version_handlersoc_typemsg_cmd_needs_triggerCMD_ID_RTC_FASTds2_datastate_handlerrtc_datasrc/sys_exec/msg.cCMD_ID_RTCCMD_ID_RESETCMD_ID_INVALIDds0_dataidle_datai2c_sleep_offsetreservedCMD_ID_STANDBYCMD_ID_DS0_V2pd_per_ocmc_ret_statefalsei2c_wake_offsetpd_per_stateparam1io_isolationrtc_mode_datartc_timeout_valmsg_cmd_fast_triggermosc_statevtt_gpio_pinshort unsigned inttrue_Boolpd_per_mem_ret_statecmd_idds1_data_hscmd_global_datado_ddrCMD_ID_DS0CMD_ID_DS1CMD_ID_DS2msg_writemsg_readcmd_handlerCMD_ID_DS1_V2m3_param_reseths_datavtt_togglepd_per_ocmc2_ret_statemem_typepd_mpu_statedeep_sleepmsg_cmd_wakeup_reason_updateidle_v2_datacustom_state_dataCMD_ID_COUNTres1res2wakeup_sourceds1_datagp_datastandby_datadebug_printfshort intmainnvic_disable_irqa8_notifyam335_inituint8_tscr_enable_sleeponexitrsc_tablong long intnamesrc/sys_exec/sys_init.ccm3_trace_hdrnvic_enable_irqunsigned charlong long unsigned intuint32_tsoc_idtrace_initscr_enable_sleepdeepfw_rsc_hdrsetup_socpm_resetbasefw_rsc_tracecm3_resource_tablecm3_tracehwmod_ida8_m3_low_power_syncHWMOD_COUNTHWMOD_OTFA_EMIFHWMOD_OCPWPHWMOD_L4FWHWMOD_L3_INSTRHWMOD_EMIFHWMOD_CLKDIV32KHWMOD_GPIO0nvic_clear_irqHWMOD_L3HWMOD_MPUHWMOD_I2C0HWMOD_OCMCRAMHWMOD_L4HSHWMOD_L4LSa8_m3_low_power_fastHWMOD_ENDHWMOD_EMIF_FWtimer_syncsrc/sys_exec/sync.cHWMOD_IEEE5000src/sys_exec/trace.ctrace_set_current_possize_tsrc/lib/string.cstrlenmemsetputchar_logbuf_endsrc/lib/puts.c_logbuf_startmaxlenputsnputslogbuf_posflags__va_listdebug_levelsrc/lib/debug.clevelsvprintfdebug_idxdebug_set_level__apksprintnupperhandle_signput_padstophandle_nosignnbufsrc/lib/printf.cpadcdwidthlenphex2ascii_datapercentreswitchnumberdummy_handlersrc/foundation/startup.cpulsrc_end_textpuldestvector_table_end_stack_start_data_end_datasrc/foundation/exception_handlers.cpendsv_handlerbusfault_handlermemmanage_handlerhardfault_handlerdebugmon_handlersvc_handlerusagefault_handlernmi_handlerCLKDM_L3S_TSCrtc_reg_readCLKDM_L3SCLKDM_COUNTCLKDM_CLK_24MHZCLKDM_EMIFCLKDM_L4FWCLKDM_CPSWCLKDM_LCDCCLKDM_L4HSCLKDM_ENDCLKDM_WKUPCLKDM_DSSrtc_reg_writeCLKDM_MPUCLKDM_ICSSCLKDM_RTCsrc/foundation/rtc.cclkdm_idCLKDM_L4LSclkdm_activeCLKDM_L3rtc_enable_checkCLKDM_OCPWP_L3irq_noscr_regsrc/foundation/cm3.creg_offsetirq_regextint43_handlerextint44_handlerextint31_handlerextint45_handlerextint33_handlerextint34_handlerextint35_handlerextint36_handlergeneric_wake_handlerextint50_handlerextint51_handlerextint52_handlerextint49_handlerextint53_handlerextint16_handlersrc/foundation/ext_intr_handlers.cextint48_handlerreg_valextint47_handlerextint46_handlerextint40_handlerextint41_handlerextint42_handlerldo_power_upldo_wait_for_onam43xx_ldo_regssrc/pm_services/ldo.cLDO_COUNTldo_power_downldo_initLDO_CORELDO_MPUam335x_ldo_regsldo_idldo_wait_for_retam335x_essential_hwmodsam335x_hwmodsam335x_interconnect_hwmodssrc/pm_services/hwmod_335x.cpowerdomain_regsPD_MPUicss_retst_shiftl1_retst_shiftper_powerst_changestctrl_next_valsrc/pm_services/powerdomain.cam335x_pd_regsper_retst_shiftverify_pd_transitionpowerdomain_initmpu_ram_ret_state_changepwrst_maskam43xx_pd_regspwrstst_prev_valstctrlpd_mpu_bitsl2_retst_shiftstctrl_prev_valget_pd_mpu_stctrl_valresultram_retst_shiftpd_per_bitsget_pd_per_stctrl_valam335x_mpu_bitsbit_valpowerdomain_resetpowerdomain_idocmc_mem_ret_state_changeverify_pd_transitionspd_state_changelogicretst_maskam335x_per_bitsam43xx_mpu_bitspd_statesper_mem_ret_state_changeicss_mem_ret_state_changelpstchg_shiftpd_state_restorepd_read_stateicss_retst_maskram1_retst_maskram2_retst_maskmpu_powerst_changepowerdomain_statelpstchg_maskPD_PERram_retst_maskmpu_l2_ret_state_changeper_retst_maskl1_retst_maskmpu_l1_ret_state_changepwrst_shiftl2_retst_maskam43xx_per_bitsvar_modlogicretst_shiftram1_retst_shiftocmc2_mem_ret_state_changeram2_retst_shiftpwrststidlest_regpgoodout_status_bitret_bitponout_status_bitDPLL_COREDPLL_COUNTiso_bitdpll_pwr_sw_ctrl_regDPLL_DDRreset_bitsw_ctrl_dpll_bitclkmode_regDPLL_DISPDPLL_PERponin_bitpgoodin_bitsrc/pm_services/dpll_335x.cisoscan_bitam335x_pg2_power_down_pllsDPLL_ENDclksel_regdpll_idam335x_dpll_regsdpll_pwr_sw_status_regDPLL_MPUsrc/pm_services/ldo_335x.ca8_wake_ds2_handlera8_cpuidle_handlera8_wake_standby_handlerds_saveconfigure_wake_sourcesa8_i2c_wake_handlerplls_power_upwakeup_reasonclear_wake_sourcesper_stclkdms_standby_wakea8_standalone_handlera8_lp_ds0_handlerclkdms_waketempa8_lp_rtc_handleressential_hwmods_enableclkdm_waketimeouta8_lp_ds1_handlera8_wake_cpuidle_handlermpu_sta8_lp_ds2_handlerconfigure_deepsleep_counta8_i2c_sleep_handlera8_cpuidle_v2_handlerclkdms_sleepds_restoreplls_power_downhalt_on_resumea8_wake_ds0_handlerinterconnect_hwmods_disableinterconnect_hwmods_enablea8_wake_rtc_handleressential_hwmods_disabledisable_master_oscillatora8_standby_handlerpll_bypassa8_wake_ds1_handlera8_wake_cpuidle_v2_handlersoc_revenable_master_oscillatorpll_locklocal_cmdsrc/pm_services/pm_handlers.cddr_io_resumeclear_ddr_resetset_ddr_resetvtp_enableprcm_enable_isolationprcm_disable_isolationdmemdpll_resetenable_iodpll_initddr_io_suspendi2c_writewas_enabledvtp_disablehwmod_initvtt_highclockdomain_initcmd_wake_sourcesds_countsrc/pm_services/prcm_core.cvtt_lowdisable_ioam43xx_interconnect_hwmodssrc/pm_services/hwmod_43xx.cam43xx_hwmodsam43xx_essential_hwmodsddr_am437x_io_suspendcmd1_ioctrlio_ctxdata0_ioctrldata3_ioctrlsrc/pm_services/ddr.ccmd2_ioctrlddr_io_save_contextdata1_ioctrlddr_io_contextddr_am335x_io_suspendcmd0_ioctrldata2_ioctrldpll_power_updpll_power_downam43xx_power_down_pllsdpll_get_divpll_modeam43xx_dpll_regsxtal_freqssrc/pm_services/dpll.cdpllindexget_master_xtal_khzsrc/pm_services/dpll_43xx.csrc/pm_services/pm_state_data.cam335x_standby_clkdmsam43xx_sleep_clkdms_clkdm_sleepam43xx_clkdmsclkdms_state_changeclkdm_state_changeam335x_clkdmsam335x_sleep_clkdmssrc/pm_services/clockdomain.cam43xx_standby_clkdms_clkdm_wakeupsrc/pm_services/clockdomain_43xx.csrc/pm_services/clockdomain_335x.csrc/pm_services/powerdomain_43xx.corig_sysci2c_reg_writei2c_wait_for_bborig_irq_enn2_divorig_pscper_clkoutm2sequencei2c_wait_for_ardyspeed_khzstati2c_fclksrc/pm_services/i2c.cxtal_freqi2c_reg_readorig_sclhorig_scllorig_coni2c_program_freqi2c_ack_allsrc/pm_services/ldo_43xx.c_hwmod_is_enabledsrc/pm_services/hwmod.c_hwmod_disable_hwmod_enablehwmods_state_changesrc/pm_services/powerdomain_335x.cGCC: (Linaro GCC 5.3-2016.02) 5.3.1 20160113A6aeabi,Cortex-M3
+M	
+"����|
,0@Pd,$��E����k
+����AT,C�H����������|
�lA��`
+A������|
Dl
+A��DxA��H��D�A��G��D�XA��D����|
��������|
(����|
L<<A������LxA����L�.A����������|
D��lA���B���B D
+B���A���A\B���A����0����|
, <8B$�	��������Eh|
+$B0 tA����A�A HB�A��������|
����H����|
������������������|
TA��TT$����|
�0(�X(��(��������|
��A��0��^A��S
+��CE
+��CE
+��CE���D
A��E�� �X
DA��R
+��BH����
A��E����
A��E����
A��E����
A��E����
A��E���A��E���A��E���(A��E���<A��E���PA��E���dA��E���xA��E����A��E����A��E����A��E��(��FA��O
+��CE
+��CE������|
hh$h8hPhh8����|
����X�0B���Q����@\B���i�����HD���]�������0����|
�H\A��g��$���A����c
+����C ���A����C���� �<�A����@�������A�����XA��H�� �pRA����e������$���A����H
+����C����pD��b
+��C��6A��W���0.A��T���`0A��T����A��D����6A��W������|
t
+�t
+�t
+B��G��t
+$LE��U��t
+pt
+�t
+�t
+�t
+�$t
+�8A�����
+����C t
+�B����C����t
+�HA��^��t
+�dA��j��t
+X:A����t
+�t
+�t
+�����|
 ��dD����Z�����lA��������xA�����$$�$�D����]
+����A��0�� �4A��P���44A��P���h������|
 
��B��������
(�B�����
�4E�R�
�0
 
8
LT
�8A��BS����|
�
�T�
, (�
T &A�����
|  �
� �
� �
� �
� �
� ����|
8�� �B$�	��������U@�
+$B^
+$BG
+$B����|
 ��"|D����t�����H#T��#$��#(��# �$A���$A���0$A���D$A��.symtab.strtab.shstrtab.text.data.resource_table.bss.aux_data.logbuf.debug_info.debug_abbrev.debug_loc.debug_aranges.debug_ranges.debug_line.debug_str.comment.ARM.attributes.debug_frame�	
+
���������!(,4-<@LP\d�� Tp����������EW���X`�X$b��l�Ti���q��,z��<lx�\���� 08�$��$T�T�$�����<�>�	�	pt�$��$%�$0��������d���0|��������������
�
��� $48LPdh�x
���$������<@�����D ( 28;<D@�L��`%X���&c��H����,<��HXx����q���}����� $\p��������������PX���D�D�
+����&�����\�� $�����(4\h|��H�H����$(���� 48HL����&d�d�hl,

��'��X)��� , P T 7U &� � � � � � � � � � � �K�R�_��
n��4(����(���)���� �"�����)����"��"|D#H#|#�#�#�#�#�#$$$$,$0$@$D$T$�����������)=<�&6�A�W� c0y�"���)8�����H�)�	��d��H�u'�)%�.>TK�)Z`%u$����!��"���� ��
�lX
�"0.�07Y
DHeY� �cq)���
�����x��"����"%�(@3�"C�TqnI#Ty��1�)�������"�y��"��4�'��
.�"?1H�"YynU,}�p����"���	��p��"�	$�.�;�^LY(]�8qe,�4��"��T������Y:��F�m
+	�"	�+	� 7	�"H	iV	4*`	�p	Q�	�8�	1$�	�"�	��	�X�	��	�
+p%
+�
+(
+=80
+%�>
+�"N
+()8^
+�l
+�"}
+�
+�"�
+��
+Q�
+$%<�
+�(�
+� �
+�"�
+�"�($Y7�L�"]9h�
y���"������.�54��"��$9�)0/�"@Q��\�dp~�6�y��&�a0�=�����#$�a
+
%L

.
	?
QO
�Xe
do
�"�
�# �
��
E$�
��
- (�
��
�"�
�0}   !�*�;� G�"X�"i�Hq�&�1(���$������l�4(�d(@��
+�2
HqR^�r%�����i8���
���%��"A�I\)� 6��FE
W�"h�~=��|����(,����D��6�`)0�l)#1.7A\M%Z�"k�"|��������"�<((��&<��#(��MT#�,�"startup.c$tzero_loop$dmsg.ca8_version_handlera8_reset_handlercustom_state_datasys_init.csync.ctrace.cstring.cputs.clogbuf_posdebug.clevelsdebug_leveldebug_idxprintf.chex2ascii_dataexception_handlers.crtc.ccm3.cext_intr_handlers.cldo.cldo_regshwmod_335x.cpowerdomain.cpd_statesmpu_bitsper_bitspd_regsdpll_335x.cldo_335x.cpm_handlers.cprcm_core.cprcm_enable_isolation.part.0prcm_disable_isolation.part.1cmd_wake_sourceshwmod_43xx.cddr.cio_ctxdpll.cpower_down_pllsdpll_regspll_modedpll_43xx.cpm_state_data.cclockdomain.cclkdms_state_changeclkdmssleep_clkdmsstandby_clkdmsclockdomain_43xx.cclockdomain_335x.cpowerdomain_43xx.ci2c.cldo_43xx.chwmod.chwmods_state_changehwmodsessential_hwmodsinterconnect_hwmodspowerdomain_335x.cputcharam43xx_interconnect_hwmodsdisable_ioa8_standalone_handlervtp_disableverify_pd_transitionsextint8_handlertimer_syncam335x_per_bitsa8_lp_ds0_handlerreset_handleram43xx_pd_regspm_resetds_restoreget_pd_mpu_stctrl_valprintfam43xx_dpll_regsam43xx_ldo_regsds1_data_aux_data_startcmd_handlersam335x_pd_regsam335x_pg2_power_down_pllsessential_hwmods_enablea8_lp_ds1_handlerdpll_get_divextint27_handlersoc_revclkdms_standby_wakeextint36_handlerddr_am335x_io_suspendidle_v2_dataextint26_handlerpd_state_changepll_lockextint34_handlerextint48_handleri2c_writepd_read_stateplls_power_up_start_dataextint41_handlerprcm_disable_isolationtrace_set_current_posddr_am437x_io_suspendextint4_handlera8_m3_low_power_fastextint50_handlerextint0_handleram335x_clkdmsextint7_handlerbusfault_handlerdisable_master_oscillatorhwmod_init_end_datadebug_set_levelextint45_handlerclear_wake_sourcesa8_standby_handlerextint9_handlerputssystick_handlerpll_bypassam43xx_power_down_pllsds1_data_hsextint40_handlerextint37_handlermsg_readextint12_handlera8_m3_low_power_syncm3_param_resettrace_initstandby_datamemmanage_handlerextint30_handlerm3_firmware_versiontrace_updatea8_wake_ds0_handlerextint5_handleressential_hwmods_disablea8_wake_cpuidle_handlerio_isolationextint31_handlernvic_disable_irqget_master_xtal_khzmsg_cmd_is_validvtt_highextint19_handlerclockdomain_initextint16_handler_start_textsvc_handlera8_i2c_wake_handlerextint53_handlera8_notifyextint1_handlermsg_cmd_needs_triggerclkdms_wakeextint15_handlerset_ddr_reset_end_textclear_ddr_resetextint47_handlerconfigure_wake_sourcesinterconnect_hwmods_disableextint18_handlerdummy_handlerpowerdomain_initds0_data_hsextint52_handleram335x_dpll_regssoc_typevector_tablevprintfddr_io_resumeextint6_handleram43xx_per_bitsrtc_mode_dataextint23_handlerldo_wait_for_onextint20_handlerscr_enable_sleeponexitldo_power_downam335x_hwmodsnvic_clear_irqclkdm_wakeextint38_handlerextint22_handleram335x_standby_clkdmsa8_cpuidle_handlerscr_enable_sleepdeepextint39_handlerdpll_resetextint42_handlermsg_cmd_wakeup_reason_updateextint21_handler_logbuf_startgeneric_wake_handlerputsnvtt_lowextint32_handleram335x_interconnect_hwmods_aux_data_endldo_power_upam335x_mpu_bitsextint28_handlerdebugmon_handler_end_stackddr_io_save_contextrtc_reg_writea8_wake_ds1_handlerextint49_handleram43xx_essential_hwmodsa8_wake_standby_handlerextint46_handlermemsetsoc_idhwmod_enablemainsetup_socpendsv_handlerextint43_handlerrtc_enable_checkmsg_cmd_read_idinit_m3_state_machineidle_dataextint25_handlerhwmod_is_enabledvtt_toggleinterconnect_hwmods_enablecmd_global_dataclkdm_state_changeusagefault_handlerextint3_handlervtp_enableclkdm_active_logbuf_endds0_dataextint51_handlerclkdm_sleepextint24_handlerextint10_handlerds_saveam335x_ldo_regsnvic_enable_irqpowerdomain_resetddr_io_suspendpd_state_restoredebug_haltam335_initam43xx_standby_clkdmsam43xx_clkdmsvtt_gpio_pin_end_resource_tablea8_wake_rtc_handlertrace_get_current_posa8_cpuidle_v2_handlermsg_cmd_stat_updateldo_wait_for_ret_end_bsshardfault_handlerldo_init_start_bssextint35_handlermsg_cmd_fast_triggeram335x_essential_hwmodsextint14_handlermsg_writenmi_handlera8_lp_rtc_handlerclkdms_sleepplls_power_downextint33_handlerextint13_handlerprcm_enable_isolationa8_lp_ds2_handlerds2_dataa8_i2c_sleep_handleram335x_sleep_clkdmsconfigure_deepsleep_countrsc_taba8_wake_cpuidle_v2_handleram43xx_mpu_bitsdebug_printfstrlena8_wake_ds2_handlerget_pd_per_stctrl_valrtc_reg_readextint29_handlerextint11_handler_start_resource_tableextint44_handlerenable_ioenable_master_oscillatorextint2_handleram43xx_sleep_clkdmsam43xx_hwmodshwmod_disablemsg_cmd_dispatcherdpll_initmem_typeextint17_handler4*!�'��D7�<FN3rZ;t'$hb��,s$�������t�#�0����0�-�p�7�����lp$U	�:=
\ No newline at end of file
diff -Naur --no-dereference a/firmware/am43x-evm-scale-data.bin b/firmware/am43x-evm-scale-data.bin
--- a/firmware/am43x-evm-scale-data.bin	1969-12-31 19:00:00.000000000 -0500
+++ b/firmware/am43x-evm-scale-data.bin	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1 @@
+Wd$k$�$g$�d$k$�$g$�
\ No newline at end of file
diff -Naur --no-dereference a/firmware/regulatory.db b/firmware/regulatory.db
--- a/firmware/regulatory.db	1969-12-31 19:00:00.000000000 -0500
+++ b/firmware/regulatory.db	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,22 @@
+RGDB00�AD�AEqAF~AI�AL�AM`AN~ARqASAAT�AU�AW~AZuBA�BB�BD�BE�BFqBG�BHcBL~BMABN�BO�BR$BS�BT~BY~BZ�CA1CFfCH�CIqCL�CN�COqCR\CUCX�CY�CZ�DE�DK�DM:DO:DZ�ECEE�EG�ES�ET~FI�FMAFR�GB�GD=GExGF�GHqGL�GP�GR�GT:GU6GY�HK)HNqHR�HTAHU�IDIE�ILPIN�IR�IS�IT�JMqJO�JPKKE�KH~KN�KPEKR
KW{KY�KZ�LBqLC�LI�LK\LS~LT�LU�LV�MA{MC�MD�ME�MF�MHAMK�MN�MO�MPAMQ�MR~MT�MU�MV�MW~MXqMY�NG�NIANL�NO�NP�NZ�OM~PA-PEqPF�PGqPH�PKTPL�PM�PR=PT�PWAPY�QA	RE�RO�RS�RURWqSA~SE�SGSI�SK�SNqSR~SVYSYITC�TD~TGjTHqTN{TR�TTqTW TZ�UAUG�US�UY�UZ{VC~VE�VIAVNmVUqWF�WSjYEIYT�ZA�ZW~#4JJ#4FJ��8)��
�p
�@��
�@	�>��
�8	���	�)@�$�%�@�@�$�%�,�@�$�%�,�@�$�%�,�@�$�%�,�@
+�$�%�,�@�$�%�,�@$�%�,�@$�%�,�@�$��%�@�@�$��%�@�@�$��%�PN �$��%�P�@�$��%�P�@�$��%�P�@�$��%�,�@�%}�%�PN �%�&0N 	�%�&0N �J�L$0�@�N�0OͰ�@�N�0P�8��N�0P�8���N�0P�8��N�0P�8���N�0P�8��N�0P�8���N�0P�8��N�0P�8���N�0P�8��N�0P�8��
+�N�0P�8��N�0P�8�N�0P�8��N�0Pi�8��N�0Q�p8��N�0Q�p8�
+�N�0Q�p8��N�0Q�pq�N�PP�N N�PP�N �N�PP�N �N�PP��@�N�PP��@�N�PP�8��N�PP�8�N�PP�8��N�PP�8��N�PP�8���N�PP�8��N�PP�8��N�PP�8�	`N�PP�8�	`N�PP�8���OͰP�N P�QTPN �P�QTPN �P�QTPN 	`P�QTPN �P�QTP�@	`P�QTP�@P�QTP8��P�QTP8��P�QTP8���P�QTP8���P�QTP8��P�QTP8�	`P�QTP8�	`P�QTP8�	`P�QTP8���P�QTP8��P�Q�p8��P�Q�p8���P�Q�p8��P�Q�p8��0P�Q�p8��P�Q�p8��P�Q�p8��P�Q�p8���P�Q�p8�	`P�Q�p8�	`P�Q�p8�
+�P�Q�p8��P�Q�p8��Pi�Q�p8�	`Sw0Us8�
+�Sw0Us8��Sw0U�8�	]Sw0W[H8��Sw0W[Hq�Sw0W[Hq�Sw0W[Hq�0Sw0W[Hq	`Sw0W[Hq
+�Sw0W[Hq�
+�Sw0W[Hq�
+�Sw0W[Hq
+�Sw0W[Hq�
+�Sw0W[Hq�Sw0W[Hq�Sw0Wn�q	`Sw0Wn�q
+�Sw0Wn�q�
+�Sw0Wn�q�S�PT��8��S�PU�0N 	`S�PV6Pq�S�PV�pq
+�S�PW ��@
+�S�PW �q
+�S�PW �q��S�PW �q�S�PW �q	`S�PWn�N 	`S�PWn��@	`S�PWn�8��S�PWn�q�S�PWn�q	`S�PWn�q	`S�PWn�q��S�PWn�q�S��b	�q��U�W[H8�	`V6PWn�8�
+�V6PWn�8��V6PYC�q�W[HX��8��W[HYC�8��W[HYC�8��W[HYC�8��W[HYC�8��W[HYC�8�	`W[HYC�8��W[HYC�8��W[HYC�8��W[HYC�8�W[HYC�8�uW[HY�88��W[HY�88��W[HY�88��W[HY�88��Wn�YC�8�Wn�YC�8�Wn�YC�8��W�XX��@�W�XX��N �W�XX��8��W�XY�N �W�XY�N �W�XY��@�W�XY�8��W�XY�8��W�XY�8�	`W�XY�8��W�XY�8�uYC�Y�8N 
+�YC�Y�X�@xZh�b	�q�Zh�b	�q�Zh�b	�q	]Zh�b	�q	]Zh�b	�q��Zh�l�q�Zh�l��
+�Zh�l���Z��b	�q��Z��b	�q��e�@А ���e�@�� ��Be�@�� ��	`e�@�� ���e�@�� ���e�@�� ���e�@�� ���e�@;_� ���e�@;_� ��
+�ii��_@ ��ii��J@ ���ii�;_� ��0�_@�J@ ��
+��J@�?� ��	��
���>�����*rRs����E�2�Nb��*	O���3�B���7�a���<���@Sw��IS�ISw��ISw��IS|��IS��Iv�f��^�����j�Z��%F���EB
+����>�k��*�]���f:��b��!K��*	n���N"f�s��3
{V�V&j��3.�Jo�n��2���J����J����J�v��&�����^��EX�Z*6���n�2�n��2�r��v�.�z��6�~������J����J����������������������*���:������"��B�������J����F����J����J��J��J�J�J���JRO���J���J��JJ	.��
\ No newline at end of file
diff -Naur --no-dereference a/firmware/regulatory.db.p7s b/firmware/regulatory.db.p7s
--- a/firmware/regulatory.db.p7s	1969-12-31 19:00:00.000000000 -0500
+++ b/firmware/regulatory.db.p7s	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,5 @@
+0��	*�H��
���0��10
	`�He0	*�H��
���0��0��	���G��Χ0
	*�H��
010Usforshee0 
171006194035Z21170912194035Z010Usforshee0�"0
	*�H��
�0�
+��@�(�9�9�f,A8�~��q%~�|h�o?��Y8�|jR�*-~f��p [ԗ2=q�;ka�W���$�	�h���Q�E�D���v��`-(��-ꈘ��V!�S�o�F��_(��6�h#qWV����}*�sE�'��z�ˀ�06�S���1�6��c�e[%uh���~\�^� 2w)f6s�A7��r+��) |�y+����l?����xRz��h���F��ǡ���F���_�f�����0
	*�H��
�����ݯ|D/��_L�H���!�%#N�"�s��F|u��IWG�3����@u�F"�]�y����/{�?ȶ�j(�4\#?2����UtGs���"V$}�	���7[�mٌ�Pj�Y��B�X��сW�8�X���.�Z'���g\�rg�o�-5y׊���!0J����yV��}�Q�/G�}K
+�U
+}N;+/�(�i4က�⯹�0�T�#��QLE}es��ϔ�
:`�</3�!�P���f�y1��0��0 010Usforshee	���G��Χ0
	`�He�i0	*�H��
	1	*�H��
0	*�H��
	1
230901195657Z0/	*�H��
	1" 
+J�z�
�pd)7̲):r�PG0�Zi��Y�Xch0
	*�H��
���>�:�JD�&z�\x�5k�_1�>=>�iU,[?0>�cw�=E��i{����?~x�?@$%;V�`+��6���A�C&��b����[��t�6"!�2(8j�������F5>����v�a_�Ɏ�ގ���M��Fٷߊ ��pJ�:�r��W����`%~@/�E�[���#��WF��uy{�*�_h�ѐ���"�̄!Q��7�Χ؅����[��Ճ�l���h}�N��y�b�: ��-޺n�i��
\ No newline at end of file
diff -Naur --no-dereference a/.github/FUNDING.yml b/.github/FUNDING.yml
--- a/.github/FUNDING.yml	1969-12-31 19:00:00.000000000 -0500
+++ b/.github/FUNDING.yml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: beagleboard # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+patreon: beagleboard # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: https://paypal.me/beagleboard # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff -Naur --no-dereference a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
--- a/.github/ISSUE_TEMPLATE/bug_report.md	1969-12-31 19:00:00.000000000 -0500
+++ b/.github/ISSUE_TEMPLATE/bug_report.md	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,20 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**Describe how to reproduce the bug**
+List all the steps needed to reproduce the bug
+
+**REQUIRED INFORMATION**
+Run this command and paste the output here:
+```
+sudo /opt/scripts/tools/version.sh
+```
diff -Naur --no-dereference a/.gitignore b/.gitignore
--- a/.gitignore	2023-12-20 11:00:29.000000000 -0500
+++ b/.gitignore	2024-01-28 14:01:31.232353751 -0500
@@ -20,6 +20,7 @@
 *.dtb
 *.dtbo
 *.dtb.S
+*.dtbo.S
 *.dwo
 *.elf
 *.gcno
diff -Naur --no-dereference a/.gitlab-ci.yml b/.gitlab-ci.yml
--- a/.gitlab-ci.yml	1969-12-31 19:00:00.000000000 -0500
+++ b/.gitlab-ci.yml	2024-01-28 14:01:31.232353751 -0500
@@ -0,0 +1,30 @@
+image: robertcnelson/beagle-devscripts-kernel-debian-12-amd64
+# https://git.beagleboard.org/beagleboard/ci-docker-images
+
+cache:
+  key: "$CI_PROJECT_NAME-ti-linux-6.1.y"
+  paths:
+    - ccache.tar.gz
+
+build:
+  tags:
+    - docker-amd64
+  stage: build
+  script:
+    - mkdir -p /root/.cache/ccache/ || true
+    - ccache -s
+    - tar -xf ccache.tar.gz -C / || true
+    - ccache -s
+    - CORES=$(getconf _NPROCESSORS_ONLN)
+    - make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabihf- clean
+    - make ARCH=arm CROSS_COMPILE=/usr/bin/arm-linux-gnueabihf- bb.org_defconfig
+    - echo "make -j${CORES} ARCH=arm KBUILD_DEBARCH=armhf CROSS_COMPILE=/usr/bin/arm-linux-gnueabihf- LOCALVERSION=-ti-r$CI_JOB_ID KDEB_SOURCENAME=linux-upstream KDEB_COMPRESS=xz bindeb-pkg"
+    - make -j${CORES} ARCH=arm KBUILD_DEBARCH=armhf KDEB_PKGVERSION=1xross CROSS_COMPILE="ccache /usr/bin/arm-linux-gnueabihf-" LOCALVERSION=-ti-r$CI_JOB_ID KDEB_SOURCENAME=linux-upstream KDEB_COMPRESS=xz bindeb-pkg
+    - mv ../*.deb ./
+    - ccache -s
+    - tar -cf ccache.tar.gz /root/.cache/ccache/
+  artifacts:
+    expire_in: 28 days
+    name: "$CI_PROJECT_NAME-$CI_JOB_ID"
+    paths:
+      - "linux-image-*.deb"
diff -Naur --no-dereference a/include/drm/drm_panel.h b/include/drm/drm_panel.h
--- a/include/drm/drm_panel.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/drm/drm_panel.h	2024-01-28 14:01:31.256353824 -0500
@@ -188,6 +188,16 @@
 	 * Panel entry in registry.
 	 */
 	struct list_head list;
+
+	/**
+	 * @prepare_upstream_first:
+	 *
+	 * The upstream controller should be prepared first, before the prepare
+	 * for the panel is called. This is largely required for DSI panels
+	 * where the DSI host controller should be initialised to LP-11 before
+	 * the panel is powered up.
+	 */
+	bool prepare_upstream_first;
 };
 
 void drm_panel_init(struct drm_panel *panel, struct device *dev,
diff -Naur --no-dereference a/include/dt-bindings/board/am335x-bone-pins.h b/include/dt-bindings/board/am335x-bone-pins.h
--- a/include/dt-bindings/board/am335x-bone-pins.h	1969-12-31 19:00:00.000000000 -0500
+++ b/include/dt-bindings/board/am335x-bone-pins.h	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2020 Deepak Khatri <deepaklorkhatri7@gmail.com>
+ * See Cape Interface Spec page for more info on Bone Buses
+ * https://elinux.org/Beagleboard:BeagleBone_cape_interface_spec
+ */
+
+#ifndef _DT_BINDINGS_BOARD_AM335X_BONE_PINS_H
+#define _DT_BINDINGS_BOARD_AM335X_BONE_PINS_H
+
+#define bb_device 0
+#define board_soc AM335X
+
+#define gpio_P8_03 &gpio1 6
+#define gpio_P8_04 &gpio1 7
+#define gpio_P8_05 &gpio1 2
+#define gpio_P8_06 &gpio1 3
+#define gpio_P8_07 &gpio2 2
+#define gpio_P8_08 &gpio2 3
+#define gpio_P8_09 &gpio2 5
+#define gpio_P8_10 &gpio2 4
+#define gpio_P8_11 &gpio1 13
+#define gpio_P8_12 &gpio1 12
+#define gpio_P8_13 &gpio0 23
+#define gpio_P8_14 &gpio0 26
+#define gpio_P8_15 &gpio1 15
+#define gpio_P8_16 &gpio1 14
+#define gpio_P8_17 &gpio0 27
+#define gpio_P8_18 &gpio2 1
+#define gpio_P8_19 &gpio0 22
+#define gpio_P8_20 &gpio1 31
+#define gpio_P8_21 &gpio1 30
+#define gpio_P8_22 &gpio1 5
+#define gpio_P8_23 &gpio1 4
+#define gpio_P8_24 &gpio1 1
+#define gpio_P8_25 &gpio1 0
+#define gpio_P8_26 &gpio1 29
+#define gpio_P8_27 &gpio2 22
+#define gpio_P8_28 &gpio2 24
+#define gpio_P8_29 &gpio2 23
+#define gpio_P8_30 &gpio2 25
+#define gpio_P8_31 &gpio0 10
+#define gpio_P8_32 &gpio0 11
+#define gpio_P8_33 &gpio0 9
+#define gpio_P8_34 &gpio2 17
+#define gpio_P8_35 &gpio0 8
+#define gpio_P8_36 &gpio2 16
+#define gpio_P8_37 &gpio2 14
+#define gpio_P8_38 &gpio2 15
+#define gpio_P8_39 &gpio2 12
+#define gpio_P8_40 &gpio2 13
+#define gpio_P8_41 &gpio2 10
+#define gpio_P8_42 &gpio2 11
+#define gpio_P8_43 &gpio2 8
+#define gpio_P8_44 &gpio2 9
+#define gpio_P8_45 &gpio2 6
+#define gpio_P8_46 &gpio2 7
+#define gpio_P9_11 &gpio0 30
+#define gpio_P9_12 &gpio1 28
+#define gpio_P9_13 &gpio0 31
+#define gpio_P9_14 &gpio1 18
+#define gpio_P9_15 &gpio1 16
+#define gpio_P9_16 &gpio1 19
+#define gpio_P9_17 &gpio0 5
+#define gpio_P9_18 &gpio0 4
+#define gpio_P9_19 &gpio0 13
+#define gpio_P9_20 &gpio0 12
+#define gpio_P9_21 &gpio0 3
+#define gpio_P9_22 &gpio0 2
+#define gpio_P9_23 &gpio1 17
+#define gpio_P9_24 &gpio0 15
+#define gpio_P9_25 &gpio3 21
+#define gpio_P9_26 &gpio0 14
+#define gpio_P9_27 &gpio3 19
+#define gpio_P9_28 &gpio3 17
+#define gpio_P9_29 &gpio3 15
+#define gpio_P9_30 &gpio3 16
+#define gpio_P9_31 &gpio3 14
+#define gpio_P9_41 &gpio0 20
+#define gpio_P9_41A &gpio0 20
+#define gpio_P9_41B &gpio3 20
+#define gpio_P9_91 &gpio3 20
+#define gpio_P9_42 &gpio0 7
+#define gpio_P9_42A &gpio0 7
+#define gpio_P9_42B &gpio3 18
+#define gpio_P9_92 &gpio3 18
+#define gpio_A15 &gpio0 19
+
+#define P8_03(mode) AM33XX_IOPAD(0x0818, mode)  /* R9: gpmc_ad6 */
+#define P8_04(mode) AM33XX_IOPAD(0x081c, mode)  /* T9: gpmc_ad7 */
+#define P8_05(mode) AM33XX_IOPAD(0x0808, mode)  /* R8: gpmc_ad2 */
+#define P8_06(mode) AM33XX_IOPAD(0x080c, mode)  /* T8: gpmc_ad3 */
+#define P8_07(mode) AM33XX_IOPAD(0x0890, mode)  /* R7: gpmc_advn_ale */
+#define P8_08(mode) AM33XX_IOPAD(0x0894, mode)  /* T7: gpmc_oen_ren */
+#define P8_09(mode) AM33XX_IOPAD(0x089c, mode)  /* T6: gpmc_be0n_cle */
+#define P8_10(mode) AM33XX_IOPAD(0x0898, mode)  /* U6: gpmc_wen */
+#define P8_11(mode) AM33XX_IOPAD(0x0834, mode)  /* R12: gpmc_ad13 */
+#define P8_12(mode) AM33XX_IOPAD(0x0830, mode)  /* T12: gpmc_ad12 */
+#define P8_13(mode) AM33XX_IOPAD(0x0824, mode)  /* T10: gpmc_ad9 */
+#define P8_14(mode) AM33XX_IOPAD(0x0828, mode)  /* T11: gpmc_ad10 */
+#define P8_15(mode) AM33XX_IOPAD(0x083c, mode)  /* U13: gpmc_ad15 */
+#define P8_16(mode) AM33XX_IOPAD(0x0838, mode)  /* V13: gpmc_ad14 */
+#define P8_17(mode) AM33XX_IOPAD(0x082c, mode)  /* U12: gpmc_ad11 */
+#define P8_18(mode) AM33XX_IOPAD(0x088c, mode)  /* V12: gpmc_clk */
+#define P8_19(mode) AM33XX_IOPAD(0x0820, mode)  /* U10: gpmc_ad8 */
+#define P8_20(mode) AM33XX_IOPAD(0x0884, mode)  /* V9: gpmc_csn2 */
+#define P8_21(mode) AM33XX_IOPAD(0x0880, mode)  /* U9: gpmc_csn1 */
+#define P8_22(mode) AM33XX_IOPAD(0x0814, mode)  /* V8: gpmc_ad5 */
+#define P8_23(mode) AM33XX_IOPAD(0x0810, mode)  /* U8: gpmc_ad4 */
+#define P8_24(mode) AM33XX_IOPAD(0x0804, mode)  /* V7: gpmc_ad1 */
+#define P8_25(mode) AM33XX_IOPAD(0x0800, mode)  /* U7: gpmc_ad0 */
+#define P8_26(mode) AM33XX_IOPAD(0x087c, mode)  /* V6: gpmc_csn0 */
+#define P8_27(mode) AM33XX_IOPAD(0x08e0, mode)  /* U5: lcd_vsync */
+#define P8_28(mode) AM33XX_IOPAD(0x08e8, mode)  /* V5: lcd_pclk */
+#define P8_29(mode) AM33XX_IOPAD(0x08e4, mode)  /* R5: lcd_hsync */
+#define P8_30(mode) AM33XX_IOPAD(0x08ec, mode)  /* R6: lcd_ac_bias_en */
+#define P8_31(mode) AM33XX_IOPAD(0x08d8, mode)  /* V4: lcd_data14 */
+#define P8_32(mode) AM33XX_IOPAD(0x08dc, mode)  /* T5: lcd_data15 */
+#define P8_33(mode) AM33XX_IOPAD(0x08d4, mode)  /* V3: lcd_data13 */
+#define P8_34(mode) AM33XX_IOPAD(0x08cc, mode)  /* U4: lcd_data11 */
+#define P8_35(mode) AM33XX_IOPAD(0x08d0, mode)  /* V2: lcd_data12 */
+#define P8_36(mode) AM33XX_IOPAD(0x08c8, mode)  /* U3: lcd_data10 */
+#define P8_37(mode) AM33XX_IOPAD(0x08c0, mode)  /* U1: lcd_data8 */
+#define P8_38(mode) AM33XX_IOPAD(0x08c4, mode)  /* U2: lcd_data9 */
+#define P8_39(mode) AM33XX_IOPAD(0x08b8, mode)  /* T3: lcd_data6 */
+#define P8_40(mode) AM33XX_IOPAD(0x08bc, mode)  /* T4: lcd_data7 */
+#define P8_41(mode) AM33XX_IOPAD(0x08b0, mode)  /* T1: lcd_data4 */
+#define P8_42(mode) AM33XX_IOPAD(0x08b4, mode)  /* T2: lcd_data5 */
+#define P8_43(mode) AM33XX_IOPAD(0x08a8, mode)  /* R3: lcd_data2 */
+#define P8_44(mode) AM33XX_IOPAD(0x08ac, mode)  /* R4: lcd_data3 */
+#define P8_45(mode) AM33XX_IOPAD(0x08a0, mode)  /* R1: lcd_data0 */
+#define P8_46(mode) AM33XX_IOPAD(0x08a4, mode)  /* R2: lcd_data1 */
+#define P9_11(mode) AM33XX_IOPAD(0x0870, mode)  /* T17: gpmc_wait0 */
+#define P9_12(mode) AM33XX_IOPAD(0x0878, mode)  /* U18: gpmc_be1n */
+#define P9_13(mode) AM33XX_IOPAD(0x0874, mode)  /* U17: gpmc_wpn */
+#define P9_14(mode) AM33XX_IOPAD(0x0848, mode)  /* U14: gpmc_a2 */
+#define P9_15(mode) AM33XX_IOPAD(0x0840, mode)  /* R13: gpmc_a0 */
+#define P9_16(mode) AM33XX_IOPAD(0x084c, mode)  /* T14: gpmc_a3 */
+#define P9_17(mode) AM33XX_IOPAD(0x095c, mode)  /* A16: spi0_cs0 */
+#define P9_18(mode) AM33XX_IOPAD(0x0958, mode)  /* B16: spi0_d1 */
+#define P9_19(mode) AM33XX_IOPAD(0x097c, mode)  /* D17: uart1_rtsn */
+#define P9_20(mode) AM33XX_IOPAD(0x0978, mode)  /* D18: uart1_ctsn */
+#define P9_21(mode) AM33XX_IOPAD(0x0954, mode)  /* B17: spi0_d0 */
+#define P9_22(mode) AM33XX_IOPAD(0x0950, mode)  /* A17: spi0_sclk */
+#define P9_23(mode) AM33XX_IOPAD(0x0844, mode)  /* V14: gpmc_a1 */
+#define P9_24(mode) AM33XX_IOPAD(0x0984, mode)  /* D15: uart1_txd */
+#define P9_25(mode) AM33XX_IOPAD(0x09ac, mode)  /* A14: mcasp0_ahclkx */
+#define P9_26(mode) AM33XX_IOPAD(0x0980, mode)  /* D16: uart1_rxd */
+#define P9_27(mode) AM33XX_IOPAD(0x09a4, mode)  /* C13: mcasp0_fsr */
+#define P9_28(mode) AM33XX_IOPAD(0x099c, mode)  /* C12: mcasp0_ahclkr */
+#define P9_29(mode) AM33XX_IOPAD(0x0994, mode)  /* B13: mcasp0_fsx */
+#define P9_30(mode) AM33XX_IOPAD(0x0998, mode)  /* D12: mcasp0_axr0 */
+#define P9_31(mode) AM33XX_IOPAD(0x0990, mode)  /* A13: mcasp0_aclkx */
+#define P9_41(mode) AM33XX_IOPAD(0x09b4, mode)  /* D14: xdma_event_intr1 */
+#define P9_41A(mode) AM33XX_IOPAD(0x09b4, mode) /* D14: xdma_event_intr1 */
+#define P9_41B(mode) AM33XX_IOPAD(0x09a8, mode) /* D13: mcasp0_axr1 */
+#define P9_91(mode) AM33XX_IOPAD(0x09a8, mode) /* D13: mcasp0_axr1 */
+#define P9_42(mode) AM33XX_IOPAD(0x0964, mode) /* C18: P0_in_PWM0_out */
+#define P9_42A(mode) AM33XX_IOPAD(0x0964, mode) /* C18: P0_in_PWM0_out */
+#define P9_42B(mode) AM33XX_IOPAD(0x09a0, mode) /* B12: mcasp0_aclkr */
+#define P9_92(mode) AM33XX_IOPAD(0x09a0, mode) /* B12: mcasp0_aclkr */
+
+#define gpio_P1_02 &gpio2 23
+#define gpio_P1_04 &gpio2 25
+#define gpio_P1_06 &gpio0 5
+#define gpio_P1_08 &gpio0 2
+#define gpio_P1_10 &gpio0 3
+#define gpio_P1_12 &gpio0 4
+#define gpio_P1_20 &gpio0 20
+#define gpio_P1_26 &gpio0 12
+#define gpio_P1_28 &gpio0 13
+#define gpio_P1_29 &gpio3 21
+#define gpio_P1_30 &gpio1 11
+#define gpio_P1_31 &gpio3 18
+#define gpio_P1_32 &gpio1 10
+#define gpio_P1_33 &gpio3 15
+#define gpio_P1_34 &gpio0 26
+#define gpio_P1_35 &gpio2 24
+#define gpio_P1_36 &gpio3 14
+#define gpio_P2_01 &gpio1 18
+#define gpio_P2_02 &gpio1 27
+#define gpio_P2_03 &gpio0 23
+#define gpio_P2_04 &gpio1 26
+#define gpio_P2_05 &gpio0 30
+#define gpio_P2_06 &gpio1 25
+#define gpio_P2_07 &gpio0 31
+#define gpio_P2_08 &gpio1 28
+#define gpio_P2_09 &gpio0 15
+#define gpio_P2_10 &gpio1 20
+#define gpio_P2_11 &gpio0 14
+#define gpio_P2_17 &gpio2 1
+#define gpio_P2_18 &gpio1 15
+#define gpio_P2_19 &gpio0 27
+#define gpio_P2_20 &gpio2 0
+#define gpio_P2_22 &gpio1 14
+#define gpio_P2_24 &gpio1 12
+#define gpio_P2_25 &gpio1 9
+#define gpio_P2_27 &gpio1 8
+#define gpio_P2_28 &gpio3 20
+#define gpio_P2_29 &gpio0 7
+#define gpio_P2_30 &gpio3 17
+#define gpio_P2_31 &gpio0 19
+#define gpio_P2_32 &gpio3 16
+#define gpio_P2_33 &gpio1 13
+#define gpio_P2_34 &gpio3 19
+#define gpio_P2_35 &gpio2 22
+
+#define P1_02(mode) AM33XX_IOPAD(0x08e4, mode)  /* R5: lcd_hsync */
+#define P1_04(mode) AM33XX_IOPAD(0x08ec, mode)  /* R6: lcd_ac_bias_en */
+#define P1_06(mode) AM33XX_IOPAD(0x095c, mode)  /* A16: spi0_cs0 */
+#define P1_08(mode) AM33XX_IOPAD(0x0950, mode)  /* A17: spi0_sclk */
+#define P1_10(mode) AM33XX_IOPAD(0x0954, mode)  /* B17: spi0_d0 */
+#define P1_12(mode) AM33XX_IOPAD(0x0958, mode)  /* B16: spi0_d1 */
+#define P1_20(mode) AM33XX_IOPAD(0x09b4, mode)  /* D14: xdma_event_intr1 */
+#define P1_26(mode) AM33XX_IOPAD(0x0978, mode)  /* D18: uart1_ctsn */
+#define P1_28(mode) AM33XX_IOPAD(0x097c, mode)  /* D17: uart1_rtsn */
+#define P1_29(mode) AM33XX_IOPAD(0x09ac, mode)  /* A14: mcasp0_ahclkx */
+#define P1_30(mode) AM33XX_IOPAD(0x0974, mode)  /* E16: uart0_txd */
+#define P1_31(mode) AM33XX_IOPAD(0x09a0, mode)  /* B12: mcasp0_aclkr */
+#define P1_32(mode) AM33XX_IOPAD(0x0970, mode)  /* E15: uart0_rxd */
+#define P1_33(mode) AM33XX_IOPAD(0x0994, mode)  /* B13: mcasp0_fsx */
+#define P1_34(mode) AM33XX_IOPAD(0x0828, mode)  /* T11: gpmc_ad10 */
+#define P1_35(mode) AM33XX_IOPAD(0x08e8, mode)  /* V5: lcd_pclk */
+#define P1_36(mode) AM33XX_IOPAD(0x0990, mode)  /* A13: mcasp0_aclkx */
+#define P2_01(mode) AM33XX_IOPAD(0x0848, mode)  /* U14: gpmc_a2 */
+#define P2_02(mode) AM33XX_IOPAD(0x086c, mode)  /* V17: gpmc_a11 */
+#define P2_03(mode) AM33XX_IOPAD(0x0824, mode)  /* T10: gpmc_ad9 */
+#define P2_04(mode) AM33XX_IOPAD(0x0868, mode)  /* T16: gpmc_a10 */
+#define P2_05(mode) AM33XX_IOPAD(0x0870, mode)  /* T17: gpmc_wait0 */
+#define P2_06(mode) AM33XX_IOPAD(0x0864, mode)  /* U16: gpmc_a9 */
+#define P2_07(mode) AM33XX_IOPAD(0x0874, mode)  /* U17: gpmc_wpn */
+#define P2_08(mode) AM33XX_IOPAD(0x0878, mode)  /* U18: gpmc_be1n */
+#define P2_09(mode) AM33XX_IOPAD(0x0984, mode)  /* D15: uart1_txd */
+#define P2_10(mode) AM33XX_IOPAD(0x0850, mode)  /* R14: gpmc_a4 */
+#define P2_11(mode) AM33XX_IOPAD(0x0980, mode)  /* D16: uart1_rxd */
+#define P2_17(mode) AM33XX_IOPAD(0x088c, mode)  /* V12: gpmc_clk */
+#define P2_18(mode) AM33XX_IOPAD(0x083c, mode)  /* U13: gpmc_ad15 */
+#define P2_19(mode) AM33XX_IOPAD(0x082c, mode)  /* U12: gpmc_ad11 */
+#define P2_20(mode) AM33XX_IOPAD(0x0888, mode)  /* T13: gpmc_csn3 */
+#define P2_22(mode) AM33XX_IOPAD(0x0838, mode)  /* V13: gpmc_ad14 */
+#define P2_24(mode) AM33XX_IOPAD(0x0830, mode)  /* T12: gpmc_ad12 */
+#define P2_25(mode) AM33XX_IOPAD(0x096c, mode)  /* E17: uart0_rtsn */
+#define P2_27(mode) AM33XX_IOPAD(0x0968, mode)  /* E18: uart0_ctsn */
+#define P2_28(mode) AM33XX_IOPAD(0x09a8, mode)  /* D13: mcasp0_axr1 */
+#define P2_29(mode) AM33XX_IOPAD(0x0964, mode)  /* C18: eCAP0_in_PWM0_out */
+#define P2_30(mode) AM33XX_IOPAD(0x099c, mode)  /* C12: mcasp0_ahclkr */
+#define P2_31(mode) AM33XX_IOPAD(0x09b0, mode)  /* A15: xdma_event_intr0 */
+#define P2_32(mode) AM33XX_IOPAD(0x0998, mode)  /* D12: mcasp0_axr0 */
+#define P2_33(mode) AM33XX_IOPAD(0x0834, mode)  /* R12: gpmc_ad13 */
+#define P2_34(mode) AM33XX_IOPAD(0x09a4, mode)  /* C13: mcasp0_fsr */
+#define P2_35(mode) AM33XX_IOPAD(0x08e0, mode)  /* U5: lcd_vsync */
+
+#endif
diff -Naur --no-dereference a/include/dt-bindings/mailbox/miv-ihc.h b/include/dt-bindings/mailbox/miv-ihc.h
--- a/include/dt-bindings/mailbox/miv-ihc.h	1969-12-31 19:00:00.000000000 -0500
+++ b/include/dt-bindings/mailbox/miv-ihc.h	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
+/*
+ * Copyright (c) 2021 Microchip Technology Inc. All rights reserved.
+ */
+
+#ifndef __DT_BINDINGS_MIV_IHC_H
+#define __DT_BINDINGS_MIV_IHC_H
+
+#define IHC_CONTEXT_A	5
+#define IHC_CONTEXT_B	6
+
+#define IHC_HART1_INT	180
+#define IHC_HART2_INT	179
+#define IHC_HART3_INT	178
+#define IHC_HART4_INT	177
+
+#endif
diff -Naur --no-dereference a/include/dt-bindings/mux/ti-serdes.h b/include/dt-bindings/mux/ti-serdes.h
--- a/include/dt-bindings/mux/ti-serdes.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/dt-bindings/mux/ti-serdes.h	2024-01-28 14:01:31.256353824 -0500
@@ -99,7 +99,7 @@
 
 #define J721S2_SERDES0_LANE0_EDP_LANE0		0x0
 #define J721S2_SERDES0_LANE0_PCIE1_LANE0	0x1
-#define J721S2_SERDES0_LANE0_IP3_UNUSED		0x2
+#define J721S2_SERDES0_LANE0_USB_SWAP		0x2
 #define J721S2_SERDES0_LANE0_IP4_UNUSED		0x3
 
 #define J721S2_SERDES0_LANE1_EDP_LANE1		0x0
@@ -109,7 +109,7 @@
 
 #define J721S2_SERDES0_LANE2_EDP_LANE2		0x0
 #define J721S2_SERDES0_LANE2_PCIE1_LANE2	0x1
-#define J721S2_SERDES0_LANE2_IP3_UNUSED		0x2
+#define J721S2_SERDES0_LANE2_USB_SWAP		0x2
 #define J721S2_SERDES0_LANE2_IP4_UNUSED		0x3
 
 #define J721S2_SERDES0_LANE3_EDP_LANE3		0x0
@@ -117,4 +117,86 @@
 #define J721S2_SERDES0_LANE3_USB		0x2
 #define J721S2_SERDES0_LANE3_IP4_UNUSED		0x3
 
+/* J784S4 */
+
+#define J784S4_SERDES0_LANE0_IP1_UNUSED		0x0
+#define J784S4_SERDES0_LANE0_PCIE1_LANE0	0x1
+#define J784S4_SERDES0_LANE0_IP3_UNUSED		0x2
+#define J784S4_SERDES0_LANE0_IP4_UNUSED		0x3
+
+#define J784S4_SERDES0_LANE1_IP1_UNUSED		0x0
+#define J784S4_SERDES0_LANE1_PCIE1_LANE1	0x1
+#define J784S4_SERDES0_LANE1_IP3_UNUSED		0x2
+#define J784S4_SERDES0_LANE1_IP4_UNUSED		0x3
+
+#define J784S4_SERDES0_LANE2_PCIE3_LANE0	0x0
+#define J784S4_SERDES0_LANE2_PCIE1_LANE2	0x1
+#define J784S4_SERDES0_LANE2_IP3_UNUSED		0x2
+#define J784S4_SERDES0_LANE2_IP4_UNUSED		0x3
+
+#define J784S4_SERDES0_LANE3_PCIE3_LANE1	0x0
+#define J784S4_SERDES0_LANE3_PCIE1_LANE3	0x1
+#define J784S4_SERDES0_LANE3_USB		0x2
+#define J784S4_SERDES0_LANE3_IP4_UNUSED		0x3
+
+#define J784S4_SERDES1_LANE0_QSGMII_LANE3	0x0
+#define J784S4_SERDES1_LANE0_PCIE0_LANE0	0x1
+#define J784S4_SERDES1_LANE0_IP3_UNUSED		0x2
+#define J784S4_SERDES1_LANE0_IP4_UNUSED		0x3
+
+#define J784S4_SERDES1_LANE1_QSGMII_LANE4	0x0
+#define J784S4_SERDES1_LANE1_PCIE0_LANE1	0x1
+#define J784S4_SERDES1_LANE1_IP3_UNUSED		0x2
+#define J784S4_SERDES1_LANE1_IP4_UNUSED		0x3
+
+#define J784S4_SERDES1_LANE2_QSGMII_LANE1	0x0
+#define J784S4_SERDES1_LANE2_PCIE0_LANE2	0x1
+#define J784S4_SERDES1_LANE2_PCIE2_LANE0	0x2
+#define J784S4_SERDES1_LANE2_IP4_UNUSED		0x3
+
+#define J784S4_SERDES1_LANE3_QSGMII_LANE2	0x0
+#define J784S4_SERDES1_LANE3_PCIE0_LANE3	0x1
+#define J784S4_SERDES1_LANE3_PCIE2_LANE1	0x2
+#define J784S4_SERDES1_LANE3_IP4_UNUSED		0x3
+
+#define J784S4_SERDES2_LANE0_QSGMII_LANE5	0x0
+#define J784S4_SERDES2_LANE0_IP2_UNUSED		0x1
+#define J784S4_SERDES2_LANE0_IP3_UNUSED		0x2
+#define J784S4_SERDES2_LANE0_IP4_UNUSED		0x3
+
+#define J784S4_SERDES2_LANE1_QSGMII_LANE6	0x0
+#define J784S4_SERDES2_LANE1_IP2_UNUSED		0x1
+#define J784S4_SERDES2_LANE1_IP3_UNUSED		0x2
+#define J784S4_SERDES2_LANE1_IP4_UNUSED		0x3
+
+#define J784S4_SERDES2_LANE2_QSGMII_LANE7	0x0
+#define J784S4_SERDES2_LANE2_QSGMII_LANE1	0x1
+#define J784S4_SERDES2_LANE2_IP3_UNUSED		0x2
+#define J784S4_SERDES2_LANE2_IP4_UNUSED		0x3
+
+#define J784S4_SERDES2_LANE3_QSGMII_LANE8	0x0
+#define J784S4_SERDES2_LANE3_QSGMII_LANE2	0x1
+#define J784S4_SERDES2_LANE3_IP3_UNUSED		0x2
+#define J784S4_SERDES2_LANE3_IP4_UNUSED		0x3
+
+#define J784S4_SERDES4_LANE0_EDP_LANE0		0x0
+#define J784S4_SERDES4_LANE0_QSGMII_LANE5	0x1
+#define J784S4_SERDES4_LANE0_IP3_UNUSED		0x2
+#define J784S4_SERDES4_LANE0_IP4_UNUSED		0x3
+
+#define J784S4_SERDES4_LANE1_EDP_LANE1		0x0
+#define J784S4_SERDES4_LANE1_QSGMII_LANE6	0x1
+#define J784S4_SERDES4_LANE1_IP3_UNUSED		0x2
+#define J784S4_SERDES4_LANE1_IP4_UNUSED		0x3
+
+#define J784S4_SERDES4_LANE2_EDP_LANE2		0x0
+#define J784S4_SERDES4_LANE2_QSGMII_LANE7	0x1
+#define J784S4_SERDES4_LANE2_IP3_UNUSED		0x2
+#define J784S4_SERDES4_LANE2_IP4_UNUSED		0x3
+
+#define J784S4_SERDES4_LANE3_EDP_LANE3		0x0
+#define J784S4_SERDES4_LANE3_QSGMII_LANE8	0x1
+#define J784S4_SERDES4_LANE3_USB		0x2
+#define J784S4_SERDES4_LANE3_IP4_UNUSED		0x3
+
 #endif /* _DT_BINDINGS_MUX_TI_SERDES */
diff -Naur --no-dereference a/include/dt-bindings/pinctrl/k3.h b/include/dt-bindings/pinctrl/k3.h
--- a/include/dt-bindings/pinctrl/k3.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/dt-bindings/pinctrl/k3.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * This header provides constants for pinctrl bindings for TI's K3 SoC
- * family.
- *
- * Copyright (C) 2018-2021 Texas Instruments Incorporated - https://www.ti.com/
- */
-#ifndef _DT_BINDINGS_PINCTRL_TI_K3_H
-#define _DT_BINDINGS_PINCTRL_TI_K3_H
-
-#define PULLUDEN_SHIFT		(16)
-#define PULLTYPESEL_SHIFT	(17)
-#define RXACTIVE_SHIFT		(18)
-
-#define PULL_DISABLE		(1 << PULLUDEN_SHIFT)
-#define PULL_ENABLE		(0 << PULLUDEN_SHIFT)
-
-#define PULL_UP			(1 << PULLTYPESEL_SHIFT | PULL_ENABLE)
-#define PULL_DOWN		(0 << PULLTYPESEL_SHIFT | PULL_ENABLE)
-
-#define INPUT_EN		(1 << RXACTIVE_SHIFT)
-#define INPUT_DISABLE		(0 << RXACTIVE_SHIFT)
-
-/* Only these macros are expected be used directly in device tree files */
-#define PIN_OUTPUT		(INPUT_DISABLE | PULL_DISABLE)
-#define PIN_OUTPUT_PULLUP	(INPUT_DISABLE | PULL_UP)
-#define PIN_OUTPUT_PULLDOWN	(INPUT_DISABLE | PULL_DOWN)
-#define PIN_INPUT		(INPUT_EN | PULL_DISABLE)
-#define PIN_INPUT_PULLUP	(INPUT_EN | PULL_UP)
-#define PIN_INPUT_PULLDOWN	(INPUT_EN | PULL_DOWN)
-
-#define AM62AX_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
-#define AM62AX_MCU_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
-
-#define AM62X_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
-#define AM62X_MCU_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
-
-#define AM64X_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
-#define AM64X_MCU_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
-
-#define AM65X_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
-#define AM65X_WKUP_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
-
-#define J721E_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
-#define J721E_WKUP_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
-
-#define J721S2_IOPAD(pa, val, muxmode)		(((pa) & 0x1fff)) ((val) | (muxmode))
-#define J721S2_WKUP_IOPAD(pa, val, muxmode)	(((pa) & 0x1fff)) ((val) | (muxmode))
-
-#endif
diff -Naur --no-dereference a/include/dt-bindings/pinctrl/omap.h b/include/dt-bindings/pinctrl/omap.h
--- a/include/dt-bindings/pinctrl/omap.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/dt-bindings/pinctrl/omap.h	2024-01-28 14:01:31.256353824 -0500
@@ -64,8 +64,12 @@
 #define OMAP3_WKUP_IOPAD(pa, val)	OMAP_IOPAD_OFFSET((pa), 0x2a00) (val)
 #define DM814X_IOPAD(pa, val)		OMAP_IOPAD_OFFSET((pa), 0x0800) (val)
 #define DM816X_IOPAD(pa, val)		OMAP_IOPAD_OFFSET((pa), 0x0800) (val)
-#define AM33XX_IOPAD(pa, val)		OMAP_IOPAD_OFFSET((pa), 0x0800) (val) (0)
-#define AM33XX_PADCONF(pa, conf, mux)	OMAP_IOPAD_OFFSET((pa), 0x0800) (conf) (mux)
+//Mainline
+//#define AM33XX_IOPAD(pa, val)		OMAP_IOPAD_OFFSET((pa), 0x0800) (val) (0)
+//#define AM33XX_PADCONF(pa, conf, mux)	OMAP_IOPAD_OFFSET((pa), 0x0800) (conf) (mux)
+//BeagleBoard.org (compabitliy with ancient overlays)
+#define AM33XX_IOPAD(pa, val)		OMAP_IOPAD_OFFSET((pa), 0x0800) (val)
+#define AM33XX_PADCONF(pa, dir, mux)	OMAP_IOPAD_OFFSET((pa), 0x0800) ((dir) | (mux))
 
 /*
  * Macros to allow using the offset from the padconf physical address
diff -Naur --no-dereference a/include/linux/dma/k3-udma-glue.h b/include/linux/dma/k3-udma-glue.h
--- a/include/linux/dma/k3-udma-glue.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/dma/k3-udma-glue.h	2024-01-28 14:01:31.256353824 -0500
@@ -26,6 +26,10 @@
 struct k3_udma_glue_tx_channel *k3_udma_glue_request_tx_chn(struct device *dev,
 		const char *name, struct k3_udma_glue_tx_channel_cfg *cfg);
 
+struct k3_udma_glue_tx_channel *
+k3_udma_glue_request_tx_chn_by_id(struct device *dev, struct k3_udma_glue_tx_channel_cfg *cfg,
+				  struct device_node *udmax_np, u32 thread_id);
+
 void k3_udma_glue_release_tx_chn(struct k3_udma_glue_tx_channel *tx_chn);
 int k3_udma_glue_push_tx_chn(struct k3_udma_glue_tx_channel *tx_chn,
 			     struct cppi5_host_desc_t *desc_tx,
@@ -104,6 +108,10 @@
 
 struct k3_udma_glue_rx_channel;
 
+struct k3_udma_glue_rx_channel *
+k3_udma_glue_request_remote_rx_chn_by_id(struct device *dev, struct device_node *udmax_np,
+					 struct k3_udma_glue_rx_channel_cfg *cfg, u32 thread_id);
+
 struct k3_udma_glue_rx_channel *k3_udma_glue_request_rx_chn(
 		struct device *dev,
 		const char *name,
diff -Naur --no-dereference a/include/linux/dma/ti-cppi5.h b/include/linux/dma/ti-cppi5.h
--- a/include/linux/dma/ti-cppi5.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/dma/ti-cppi5.h	2024-01-28 14:01:31.256353824 -0500
@@ -616,6 +616,7 @@
 #define   CPPI5_TR_CSF_SUPR_EVT			BIT(2)
 #define   CPPI5_TR_CSF_EOL_ADV_SHIFT		(4U)
 #define   CPPI5_TR_CSF_EOL_ADV_MASK		GENMASK(6, 4)
+#define   CPPI5_TR_CSF_EOL_ICNT0		BIT(4)
 #define   CPPI5_TR_CSF_EOP			BIT(7)
 
 /**
diff -Naur --no-dereference a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
--- a/include/linux/gpio_keys.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/gpio_keys.h	2024-01-28 14:01:31.256353824 -0500
@@ -21,6 +21,7 @@
  *			disable button via sysfs
  * @value:		axis value for %EV_ABS
  * @irq:		Irq number in case of interrupt keys
+ * @wakeirq:		Optional dedicated wake-up interrupt
  */
 struct gpio_keys_button {
 	unsigned int code;
@@ -34,6 +35,7 @@
 	bool can_disable;
 	int value;
 	unsigned int irq;
+	unsigned int wakeirq;
 };
 
 /**
diff -Naur --no-dereference a/include/linux/i2c-atr.h b/include/linux/i2c-atr.h
--- a/include/linux/i2c-atr.h	1969-12-31 19:00:00.000000000 -0500
+++ b/include/linux/i2c-atr.h	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * I2C Address Translator
+ *
+ * Copyright (c) 2019,2022 Luca Ceresoli <luca@lucaceresoli.net>
+ * Copyright (c) 2022,2023 Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+ *
+ * Based on i2c-mux.h
+ */
+
+#ifndef _LINUX_I2C_ATR_H
+#define _LINUX_I2C_ATR_H
+
+#include <linux/i2c.h>
+#include <linux/types.h>
+
+struct device;
+struct fwnode_handle;
+struct i2c_atr;
+
+/**
+ * struct i2c_atr_ops - Callbacks from ATR to the device driver.
+ * @attach_client: Notify the driver of a new device connected on a child
+ *                 bus, with the alias assigned to it. The driver must
+ *                 configure the hardware to use the alias.
+ * @detach_client: Notify the driver of a device getting disconnected. The
+ *                 driver must configure the hardware to stop using the
+ *                 alias.
+ *
+ * All these functions return 0 on success, a negative error code otherwise.
+ */
+struct i2c_atr_ops {
+	int (*attach_client)(struct i2c_atr *atr, u32 chan_id,
+			     const struct i2c_client *client, u16 alias);
+	void (*detach_client)(struct i2c_atr *atr, u32 chan_id,
+			      const struct i2c_client *client);
+};
+
+/**
+ * i2c_atr_new() - Allocate and initialize an I2C ATR helper.
+ * @parent:       The parent (upstream) adapter
+ * @dev:          The device acting as an ATR
+ * @ops:          Driver-specific callbacks
+ * @max_adapters: Maximum number of child adapters
+ *
+ * The new ATR helper is connected to the parent adapter but has no child
+ * adapters. Call i2c_atr_add_adapter() to add some.
+ *
+ * Call i2c_atr_delete() to remove.
+ *
+ * Return: pointer to the new ATR helper object, or ERR_PTR
+ */
+struct i2c_atr *i2c_atr_new(struct i2c_adapter *parent, struct device *dev,
+			    const struct i2c_atr_ops *ops, int max_adapters);
+
+/**
+ * i2c_atr_delete - Delete an I2C ATR helper.
+ * @atr: I2C ATR helper to be deleted.
+ *
+ * Precondition: all the adapters added with i2c_atr_add_adapter() must be
+ * removed by calling i2c_atr_del_adapter().
+ */
+void i2c_atr_delete(struct i2c_atr *atr);
+
+/**
+ * i2c_atr_add_adapter - Create a child ("downstream") I2C bus.
+ * @atr:        The I2C ATR
+ * @chan_id:    Index of the new adapter (0 .. max_adapters-1).  This value is
+ *              passed to the callbacks in `struct i2c_atr_ops`.
+ * @adapter_parent: The device used as the parent of the new i2c adapter, or NULL
+ *                  to use the i2c-atr device as the parent.
+ * @bus_handle: The fwnode handle that points to the adapter's i2c
+ *              peripherals, or NULL.
+ *
+ * After calling this function a new i2c bus will appear. Adding and removing
+ * devices on the downstream bus will result in calls to the
+ * &i2c_atr_ops->attach_client and &i2c_atr_ops->detach_client callbacks for the
+ * driver to assign an alias to the device.
+ *
+ * The adapter's fwnode is set to @bus_handle, or if @bus_handle is NULL the
+ * function looks for a child node whose 'reg' property matches the chan_id
+ * under the i2c-atr device's 'i2c-atr' node.
+ *
+ * Call i2c_atr_del_adapter() to remove the adapter.
+ *
+ * Return: 0 on success, a negative error code otherwise.
+ */
+int i2c_atr_add_adapter(struct i2c_atr *atr, u32 chan_id,
+			struct device *adapter_parent,
+			struct fwnode_handle *bus_handle);
+
+/**
+ * i2c_atr_del_adapter - Remove a child ("downstream") I2C bus added by
+ *                       i2c_atr_add_adapter(). If no I2C bus has been added
+ *                       this function is a no-op.
+ * @atr:     The I2C ATR
+ * @chan_id: Index of the adapter to be removed (0 .. max_adapters-1)
+ */
+void i2c_atr_del_adapter(struct i2c_atr *atr, u32 chan_id);
+
+/**
+ * i2c_atr_set_driver_data - Set private driver data to the i2c-atr instance.
+ * @atr:  The I2C ATR
+ * @data: Pointer to the data to store
+ */
+void i2c_atr_set_driver_data(struct i2c_atr *atr, void *data);
+
+/**
+ * i2c_atr_get_driver_data - Get the stored drive data.
+ * @atr:     The I2C ATR
+ *
+ * Return: Pointer to the stored data
+ */
+void *i2c_atr_get_driver_data(struct i2c_atr *atr);
+
+#endif /* _LINUX_I2C_ATR_H */
diff -Naur --no-dereference a/include/linux/iopoll.h b/include/linux/iopoll.h
--- a/include/linux/iopoll.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/iopoll.h	2024-01-28 14:01:31.256353824 -0500
@@ -74,6 +74,10 @@
  * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
  * case, the last read value at @args is stored in @val.
  *
+ * This macro does not rely on timekeeping.  Hence it is safe to call even when
+ * timekeeping is suspended, at the expense of an underestimation of wall clock
+ * time, which is rather minimal with a non-zero delay_us.
+ *
  * When available, you'll probably want to use one of the specialized
  * macros defined below rather than this macro directly.
  */
@@ -81,22 +85,30 @@
 					delay_before_read, args...) \
 ({ \
 	u64 __timeout_us = (timeout_us); \
+	s64 __left_ns = __timeout_us * NSEC_PER_USEC; \
 	unsigned long __delay_us = (delay_us); \
-	ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
-	if (delay_before_read && __delay_us) \
+	u64 __delay_ns = __delay_us * NSEC_PER_USEC; \
+	if (delay_before_read && __delay_us) { \
 		udelay(__delay_us); \
+		if (__timeout_us) \
+			__left_ns -= __delay_ns; \
+	} \
 	for (;;) { \
 		(val) = op(args); \
 		if (cond) \
 			break; \
-		if (__timeout_us && \
-		    ktime_compare(ktime_get(), __timeout) > 0) { \
+		if (__timeout_us && __left_ns < 0) { \
 			(val) = op(args); \
 			break; \
 		} \
-		if (__delay_us) \
+		if (__delay_us) { \
 			udelay(__delay_us); \
+			if (__timeout_us) \
+				__left_ns -= __delay_ns; \
+		} \
 		cpu_relax(); \
+		if (__timeout_us) \
+			__left_ns--; \
 	} \
 	(cond) ? 0 : -ETIMEDOUT; \
 })
diff -Naur --no-dereference a/include/linux/linux_logo.h b/include/linux/linux_logo.h
--- a/include/linux/linux_logo.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/linux_logo.h	2024-01-28 14:01:31.256353824 -0500
@@ -45,6 +45,7 @@
 extern const struct linux_logo logo_superh_vga16;
 extern const struct linux_logo logo_superh_clut224;
 extern const struct linux_logo logo_spe_clut224;
+extern const struct linux_logo logo_beagle_clut224;
 
 extern const struct linux_logo *fb_find_logo(int depth);
 #ifdef CONFIG_FB_LOGO_EXTRA
diff -Naur --no-dereference a/include/linux/mfd/tps65219.h b/include/linux/mfd/tps65219.h
--- a/include/linux/mfd/tps65219.h	1969-12-31 19:00:00.000000000 -0500
+++ b/include/linux/mfd/tps65219.h	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,345 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Functions to access TPS65219 Power Management IC.
+ *
+ * Copyright (C) 2022 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#ifndef MFD_TPS65219_H
+#define MFD_TPS65219_H
+
+#include <linux/bitops.h>
+#include <linux/notifier.h>
+#include <linux/regulator/driver.h>
+
+struct regmap;
+struct regmap_irq_chip_data;
+
+#define TPS65219_1V35					1350000
+#define TPS65219_1V8					1800000
+
+/* TPS chip id list */
+#define TPS65219					0xF0
+
+/* I2C ID for TPS65219 part */
+#define TPS65219_I2C_ID					0x24
+
+/* All register addresses */
+#define TPS65219_REG_TI_DEV_ID				0x00
+#define TPS65219_REG_NVM_ID				0x01
+#define TPS65219_REG_ENABLE_CTRL			0x02
+#define TPS65219_REG_BUCKS_CONFIG			0x03
+#define TPS65219_REG_LDO4_VOUT				0x04
+#define TPS65219_REG_LDO3_VOUT				0x05
+#define TPS65219_REG_LDO2_VOUT				0x06
+#define TPS65219_REG_LDO1_VOUT				0x07
+#define TPS65219_REG_BUCK3_VOUT				0x8
+#define TPS65219_REG_BUCK2_VOUT				0x9
+#define TPS65219_REG_BUCK1_VOUT				0xA
+#define TPS65219_REG_LDO4_SEQUENCE_SLOT			0xB
+#define TPS65219_REG_LDO3_SEQUENCE_SLOT			0xC
+#define TPS65219_REG_LDO2_SEQUENCE_SLOT			0xD
+#define TPS65219_REG_LDO1_SEQUENCE_SLOT			0xE
+#define TPS65219_REG_BUCK3_SEQUENCE_SLOT		0xF
+#define TPS65219_REG_BUCK2_SEQUENCE_SLOT		0x10
+#define TPS65219_REG_BUCK1_SEQUENCE_SLOT		0x11
+#define TPS65219_REG_nRST_SEQUENCE_SLOT			0x12
+#define TPS65219_REG_GPIO_SEQUENCE_SLOT			0x13
+#define TPS65219_REG_GPO2_SEQUENCE_SLOT			0x14
+#define TPS65219_REG_GPO1_SEQUENCE_SLOT			0x15
+#define TPS65219_REG_POWER_UP_SLOT_DURATION_1		0x16
+#define TPS65219_REG_POWER_UP_SLOT_DURATION_2		0x17
+#define TPS65219_REG_POWER_UP_SLOT_DURATION_3		0x18
+#define TPS65219_REG_POWER_UP_SLOT_DURATION_4		0x19
+#define TPS65219_REG_POWER_DOWN_SLOT_DURATION_1		0x1A
+#define TPS65219_REG_POWER_DOWN_SLOT_DURATION_2		0x1B
+#define TPS65219_REG_POWER_DOWN_SLOT_DURATION_3		0x1C
+#define TPS65219_REG_POWER_DOWN_SLOT_DURATION_4		0x1D
+#define TPS65219_REG_GENERAL_CONFIG			0x1E
+#define TPS65219_REG_MFP_1_CONFIG			0x1F
+#define TPS65219_REG_MFP_2_CONFIG			0x20
+#define TPS65219_REG_STBY_1_CONFIG			0x21
+#define TPS65219_REG_STBY_2_CONFIG			0x22
+#define TPS65219_REG_OC_DEGL_CONFIG			0x23
+/* 'sub irq' MASK registers */
+#define TPS65219_REG_INT_MASK_UV			0x24
+#define TPS65219_REG_MASK_CONFIG			0x25
+
+#define TPS65219_REG_I2C_ADDRESS_REG			0x26
+#define TPS65219_REG_USER_GENERAL_NVM_STORAGE		0x27
+#define TPS65219_REG_MANUFACTURING_VER			0x28
+#define TPS65219_REG_MFP_CTRL				0x29
+#define TPS65219_REG_DISCHARGE_CONFIG			0x2A
+/* main irq registers */
+#define TPS65219_REG_INT_SOURCE				0x2B
+/* 'sub irq' registers */
+#define TPS65219_REG_INT_LDO_3_4			0x2C
+#define TPS65219_REG_INT_LDO_1_2			0x2D
+#define TPS65219_REG_INT_BUCK_3				0x2E
+#define TPS65219_REG_INT_BUCK_1_2			0x2F
+#define TPS65219_REG_INT_SYSTEM				0x30
+#define TPS65219_REG_INT_RV				0x31
+#define TPS65219_REG_INT_TIMEOUT_RV_SD			0x32
+#define TPS65219_REG_INT_PB				0x33
+
+#define TPS65219_REG_INT_LDO_3_4_POS			0
+#define TPS65219_REG_INT_LDO_1_2_POS			1
+#define TPS65219_REG_INT_BUCK_3_POS			2
+#define TPS65219_REG_INT_BUCK_1_2_POS			3
+#define TPS65219_REG_INT_SYS_POS			4
+#define TPS65219_REG_INT_RV_POS				5
+#define TPS65219_REG_INT_TO_RV_POS			6
+#define TPS65219_REG_INT_PB_POS				7
+
+#define TPS65219_REG_USER_NVM_CMD			0x34
+#define TPS65219_REG_POWER_UP_STATUS			0x35
+#define TPS65219_REG_SPARE_2				0x36
+#define TPS65219_REG_SPARE_3				0x37
+#define TPS65219_REG_FACTORY_CONFIG_2			0x41
+
+/* Register field definitions */
+#define TPS65219_DEVID_REV_MASK				GENMASK(7, 0)
+#define TPS65219_BUCKS_LDOS_VOUT_VSET_MASK		GENMASK(5, 0)
+#define TPS65219_BUCKS_UV_THR_SEL_MASK			BIT(6)
+#define TPS65219_BUCKS_BW_SEL_MASK			BIT(7)
+#define LDO_BYP_SHIFT					6
+#define TPS65219_LDOS_BYP_CONFIG_MASK			BIT(LDO_BYP_SHIFT)
+#define TPS65219_LDOS_LSW_CONFIG_MASK			BIT(7)
+/* Regulators enable control */
+#define TPS65219_ENABLE_BUCK1_EN_MASK			BIT(0)
+#define TPS65219_ENABLE_BUCK2_EN_MASK			BIT(1)
+#define TPS65219_ENABLE_BUCK3_EN_MASK			BIT(2)
+#define TPS65219_ENABLE_LDO1_EN_MASK			BIT(3)
+#define TPS65219_ENABLE_LDO2_EN_MASK			BIT(4)
+#define TPS65219_ENABLE_LDO3_EN_MASK			BIT(5)
+#define TPS65219_ENABLE_LDO4_EN_MASK			BIT(6)
+/* power ON-OFF sequence slot */
+#define TPS65219_BUCKS_LDOS_SEQUENCE_OFF_SLOT_MASK	GENMASK(3, 0)
+#define TPS65219_BUCKS_LDOS_SEQUENCE_ON_SLOT_MASK	GENMASK(7, 4)
+/* TODO: Not needed, same mapping as TPS65219_ENABLE_REGNAME_EN, factorize */
+#define TPS65219_STBY1_BUCK1_STBY_EN_MASK		BIT(0)
+#define TPS65219_STBY1_BUCK2_STBY_EN_MASK		BIT(1)
+#define TPS65219_STBY1_BUCK3_STBY_EN_MASK		BIT(2)
+#define TPS65219_STBY1_LDO1_STBY_EN_MASK		BIT(3)
+#define TPS65219_STBY1_LDO2_STBY_EN_MASK		BIT(4)
+#define TPS65219_STBY1_LDO3_STBY_EN_MASK		BIT(5)
+#define TPS65219_STBY1_LDO4_STBY_EN_MASK		BIT(6)
+/* STBY_2 config */
+#define TPS65219_STBY2_GPO1_STBY_EN_MASK		BIT(0)
+#define TPS65219_STBY2_GPO2_STBY_EN_MASK		BIT(1)
+#define TPS65219_STBY2_GPIO_STBY_EN_MASK		BIT(2)
+/* MFP Control */
+#define TPS65219_MFP_I2C_OFF_REQ_MASK			BIT(0)
+#define TPS65219_MFP_STBY_I2C_CTRL_MASK			BIT(1)
+#define TPS65219_MFP_COLD_RESET_I2C_CTRL_MASK		BIT(2)
+#define TPS65219_MFP_WARM_RESET_I2C_CTRL_MASK		BIT(3)
+#define TPS65219_MFP_GPIO_STATUS_MASK			BIT(4)
+/* MFP_1 Config */
+#define TPS65219_MFP_1_VSEL_DDR_SEL_MASK		BIT(0)
+#define TPS65219_MFP_1_VSEL_SD_POL_MASK			BIT(1)
+#define TPS65219_MFP_1_VSEL_RAIL_MASK			BIT(2)
+/* MFP_2 Config */
+#define TPS65219_MFP_2_MODE_STBY_MASK			GENMASK(1, 0)
+#define TPS65219_MFP_2_MODE_RESET_MASK			BIT(2)
+#define TPS65219_MFP_2_EN_PB_VSENSE_DEGL_MASK		BIT(3)
+#define TPS65219_MFP_2_EN_PB_VSENSE_MASK		GENMASK(5, 4)
+#define TPS65219_MFP_2_WARM_COLD_RESET_MASK		BIT(6)
+#define TPS65219_MFP_2_PU_ON_FSD_MASK			BIT(7)
+#define TPS65219_MFP_2_EN				0
+#define TPS65219_MFP_2_PB				BIT(4)
+#define TPS65219_MFP_2_VSENSE				BIT(5)
+/* MASK_UV Config */
+#define TPS65219_REG_MASK_UV_LDO1_UV_MASK		BIT(0)
+#define TPS65219_REG_MASK_UV_LDO2_UV_MASK		BIT(1)
+#define TPS65219_REG_MASK_UV_LDO3_UV_MASK		BIT(2)
+#define TPS65219_REG_MASK_UV_LDO4_UV_MASK		BIT(3)
+#define TPS65219_REG_MASK_UV_BUCK1_UV_MASK		BIT(4)
+#define TPS65219_REG_MASK_UV_BUCK2_UV_MASK		BIT(5)
+#define TPS65219_REG_MASK_UV_BUCK3_UV_MASK		BIT(6)
+#define TPS65219_REG_MASK_UV_RETRY_MASK			BIT(7)
+/* MASK Config */
+// SENSOR_N_WARM_MASK already defined in Thermal
+#define TPS65219_REG_MASK_INT_FOR_RV_MASK		BIT(4)
+#define TPS65219_REG_MASK_EFFECT_MASK			GENMASK(2, 1)
+#define TPS65219_REG_MASK_INT_FOR_PB_MASK		BIT(7)
+/* UnderVoltage - Short to GND - OverCurrent*/
+/* LDO3-4 */
+#define TPS65219_INT_LDO3_SCG_MASK			BIT(0)
+#define TPS65219_INT_LDO3_OC_MASK			BIT(1)
+#define TPS65219_INT_LDO3_UV_MASK			BIT(2)
+#define TPS65219_INT_LDO4_SCG_MASK			BIT(3)
+#define TPS65219_INT_LDO4_OC_MASK			BIT(4)
+#define TPS65219_INT_LDO4_UV_MASK			BIT(5)
+/* LDO1-2 */
+#define TPS65219_INT_LDO1_SCG_MASK			BIT(0)
+#define TPS65219_INT_LDO1_OC_MASK			BIT(1)
+#define TPS65219_INT_LDO1_UV_MASK			BIT(2)
+#define TPS65219_INT_LDO2_SCG_MASK			BIT(3)
+#define TPS65219_INT_LDO2_OC_MASK			BIT(4)
+#define TPS65219_INT_LDO2_UV_MASK			BIT(5)
+/* BUCK3 */
+#define TPS65219_INT_BUCK3_SCG_MASK			BIT(0)
+#define TPS65219_INT_BUCK3_OC_MASK			BIT(1)
+#define TPS65219_INT_BUCK3_NEG_OC_MASK			BIT(2)
+#define TPS65219_INT_BUCK3_UV_MASK			BIT(3)
+/* BUCK1-2 */
+#define TPS65219_INT_BUCK1_SCG_MASK			BIT(0)
+#define TPS65219_INT_BUCK1_OC_MASK			BIT(1)
+#define TPS65219_INT_BUCK1_NEG_OC_MASK			BIT(2)
+#define TPS65219_INT_BUCK1_UV_MASK			BIT(3)
+#define TPS65219_INT_BUCK2_SCG_MASK			BIT(4)
+#define TPS65219_INT_BUCK2_OC_MASK			BIT(5)
+#define TPS65219_INT_BUCK2_NEG_OC_MASK			BIT(6)
+#define TPS65219_INT_BUCK2_UV_MASK			BIT(7)
+/* Thermal Sensor  */
+#define TPS65219_INT_SENSOR_3_WARM_MASK			BIT(0)
+#define TPS65219_INT_SENSOR_2_WARM_MASK			BIT(1)
+#define TPS65219_INT_SENSOR_1_WARM_MASK			BIT(2)
+#define TPS65219_INT_SENSOR_0_WARM_MASK			BIT(3)
+#define TPS65219_INT_SENSOR_3_HOT_MASK			BIT(4)
+#define TPS65219_INT_SENSOR_2_HOT_MASK			BIT(5)
+#define TPS65219_INT_SENSOR_1_HOT_MASK			BIT(6)
+#define TPS65219_INT_SENSOR_0_HOT_MASK			BIT(7)
+/* Residual Voltage */
+#define TPS65219_INT_BUCK1_RV_MASK			BIT(0)
+#define TPS65219_INT_BUCK2_RV_MASK			BIT(1)
+#define TPS65219_INT_BUCK3_RV_MASK			BIT(2)
+#define TPS65219_INT_LDO1_RV_MASK			BIT(3)
+#define TPS65219_INT_LDO2_RV_MASK			BIT(4)
+#define TPS65219_INT_LDO3_RV_MASK			BIT(5)
+#define TPS65219_INT_LDO4_RV_MASK			BIT(6)
+/* Residual Voltage ShutDown */
+#define TPS65219_INT_BUCK1_RV_SD_MASK			BIT(0)
+#define TPS65219_INT_BUCK2_RV_SD_MASK			BIT(1)
+#define TPS65219_INT_BUCK3_RV_SD_MASK			BIT(2)
+#define TPS65219_INT_LDO1_RV_SD_MASK			BIT(3)
+#define TPS65219_INT_LDO2_RV_SD_MASK			BIT(4)
+#define TPS65219_INT_LDO3_RV_SD_MASK			BIT(5)
+#define TPS65219_INT_LDO4_RV_SD_MASK			BIT(6)
+#define TPS65219_INT_TIMEOUT_MASK			BIT(7)
+/* Power Button */
+#define TPS65219_INT_PB_FALLING_EDGE_DETECT_MASK	BIT(0)
+#define TPS65219_INT_PB_RISING_EDGE_DETECT_MASK		BIT(1)
+#define TPS65219_INT_PB_REAL_TIME_STATUS_MASK		BIT(2)
+
+#define TPS65219_PB_POS					7
+#define TPS65219_TO_RV_POS				6
+#define TPS65219_RV_POS					5
+#define TPS65219_SYS_POS				4
+#define TPS65219_BUCK_1_2_POS				3
+#define TPS65219_BUCK_3_POS				2
+#define TPS65219_LDO_1_2_POS				1
+#define TPS65219_LDO_3_4_POS				0
+
+/* IRQs */
+enum {
+	/* LDO3-4 register IRQs */
+	TPS65219_INT_LDO3_SCG,
+	TPS65219_INT_LDO3_OC,
+	TPS65219_INT_LDO3_UV,
+	TPS65219_INT_LDO4_SCG,
+	TPS65219_INT_LDO4_OC,
+	TPS65219_INT_LDO4_UV,
+	/* LDO1-2 */
+	TPS65219_INT_LDO1_SCG,
+	TPS65219_INT_LDO1_OC,
+	TPS65219_INT_LDO1_UV,
+	TPS65219_INT_LDO2_SCG,
+	TPS65219_INT_LDO2_OC,
+	TPS65219_INT_LDO2_UV,
+	/* BUCK3 */
+	TPS65219_INT_BUCK3_SCG,
+	TPS65219_INT_BUCK3_OC,
+	TPS65219_INT_BUCK3_NEG_OC,
+	TPS65219_INT_BUCK3_UV,
+	/* BUCK1-2 */
+	TPS65219_INT_BUCK1_SCG,
+	TPS65219_INT_BUCK1_OC,
+	TPS65219_INT_BUCK1_NEG_OC,
+	TPS65219_INT_BUCK1_UV,
+	TPS65219_INT_BUCK2_SCG,
+	TPS65219_INT_BUCK2_OC,
+	TPS65219_INT_BUCK2_NEG_OC,
+	TPS65219_INT_BUCK2_UV,
+	/* Thermal Sensor  */
+	TPS65219_INT_SENSOR_3_WARM,
+	TPS65219_INT_SENSOR_2_WARM,
+	TPS65219_INT_SENSOR_1_WARM,
+	TPS65219_INT_SENSOR_0_WARM,
+	TPS65219_INT_SENSOR_3_HOT,
+	TPS65219_INT_SENSOR_2_HOT,
+	TPS65219_INT_SENSOR_1_HOT,
+	TPS65219_INT_SENSOR_0_HOT,
+	/* Residual Voltage */
+	TPS65219_INT_BUCK1_RV,
+	TPS65219_INT_BUCK2_RV,
+	TPS65219_INT_BUCK3_RV,
+	TPS65219_INT_LDO1_RV,
+	TPS65219_INT_LDO2_RV,
+	TPS65219_INT_LDO3_RV,
+	TPS65219_INT_LDO4_RV,
+	/* Residual Voltage ShutDown */
+	TPS65219_INT_BUCK1_RV_SD,
+	TPS65219_INT_BUCK2_RV_SD,
+	TPS65219_INT_BUCK3_RV_SD,
+	TPS65219_INT_LDO1_RV_SD,
+	TPS65219_INT_LDO2_RV_SD,
+	TPS65219_INT_LDO3_RV_SD,
+	TPS65219_INT_LDO4_RV_SD,
+	TPS65219_INT_TIMEOUT,
+	/* Power Button */
+	TPS65219_INT_PB_FALLING_EDGE_DETECT,
+	TPS65219_INT_PB_RISING_EDGE_DETECT,
+};
+
+enum tps65219_regulator_id {
+	/* DCDC's */
+	TPS65219_BUCK_1,
+	TPS65219_BUCK_2,
+	TPS65219_BUCK_3,
+	/* LDOs */
+	TPS65219_LDO_1,
+	TPS65219_LDO_2,
+	TPS65219_LDO_3,
+	TPS65219_LDO_4,
+};
+
+/* Number of step-down converters available */
+#define TPS65219_NUM_DCDC		3
+/* Number of LDO voltage regulators available */
+#define TPS65219_NUM_LDO		4
+/* Number of total regulators available */
+#define TPS65219_NUM_REGULATOR		(TPS65219_NUM_DCDC + TPS65219_NUM_LDO)
+
+/* Define the TPS65219 IRQ numbers */
+enum tps65219_irqs {
+	/* INT source registers */
+	TPS65219_TO_RV_SD_SET_IRQ,
+	TPS65219_RV_SET_IRQ,
+	TPS65219_SYS_SET_IRQ,
+	TPS65219_BUCK_1_2_SET_IRQ,
+	TPS65219_BUCK_3_SET_IRQ,
+	TPS65219_LDO_1_2_SET_IRQ,
+	TPS65219_LDO_3_4_SET_IRQ,
+	TPS65219_PB_SET_IRQ,
+};
+
+/**
+ * struct tps65219 - tps65219 sub-driver chip access routines
+ *
+ * Device data may be used to access the TPS65219 chip
+ *
+ * @dev: MFD device
+ * @regmap: Regmap for accessing the device registers
+ * @irq_data: Regmap irq data used for the irq chip
+ * @nb: notifier block for the restart handler
+ */
+struct tps65219 {
+	struct device *dev;
+	struct regmap *regmap;
+
+	struct regmap_irq_chip_data *irq_data;
+	struct notifier_block nb;
+};
+
+#endif /* MFD_TPS65219_H */
diff -Naur --no-dereference a/include/linux/mfd/tps6594.h b/include/linux/mfd/tps6594.h
--- a/include/linux/mfd/tps6594.h	1969-12-31 19:00:00.000000000 -0500
+++ b/include/linux/mfd/tps6594.h	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,1020 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Functions to access TPS6594 Power Management IC
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#ifndef __LINUX_MFD_TPS6594_H
+#define __LINUX_MFD_TPS6594_H
+
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+struct regmap_irq_chip_data;
+
+/* Chip id list */
+enum pmic_id {
+	TPS6594,
+	TPS6593,
+	LP8764,
+};
+
+/* Macro to get page index from register address */
+#define TPS6594_REG_TO_PAGE(reg)	((reg) >> 8)
+
+/* Registers for page 0 of TPS6594 */
+#define TPS6594_REG_DEV_REV				0x01
+
+#define TPS6594_REG_NVM_CODE_1				0x02
+#define TPS6594_REG_NVM_CODE_2				0x03
+
+#define TPS6594_REG_BUCKX_CTRL(buck_inst)		(0x04 + ((buck_inst) << 1))
+#define TPS6594_REG_BUCKX_CONF(buck_inst)		(0x05 + ((buck_inst) << 1))
+#define TPS6594_REG_BUCKX_VOUT_1(buck_inst)		(0x0e + ((buck_inst) << 1))
+#define TPS6594_REG_BUCKX_VOUT_2(buck_inst)		(0x0f + ((buck_inst) << 1))
+#define TPS6594_REG_BUCKX_PG_WINDOW(buck_inst)		(0x18 + (buck_inst))
+
+#define TPS6594_REG_LDOX_CTRL(ldo_inst)			(0x1d + (ldo_inst))
+#define TPS6594_REG_LDORTC_CTRL				0x22
+#define TPS6594_REG_LDOX_VOUT(ldo_inst)			(0x23 + (ldo_inst))
+#define TPS6594_REG_LDOX_PG_WINDOW(ldo_inst)		(0x27 + (ldo_inst))
+
+#define TPS6594_REG_VCCA_VMON_CTRL			0x2b
+#define TPS6594_REG_VCCA_PG_WINDOW			0x2c
+#define TPS6594_REG_VMON1_PG_WINDOW			0x2d
+#define TPS6594_REG_VMON1_PG_LEVEL			0x2e
+#define TPS6594_REG_VMON2_PG_WINDOW			0x2f
+#define TPS6594_REG_VMON2_PG_LEVEL			0x30
+
+#define TPS6594_REG_GPIOX_CONF(gpio_inst)		(0x31 + (gpio_inst))
+#define TPS6594_REG_NPWRON_CONF				0x3c
+#define TPS6594_REG_GPIO_OUT_1				0x3d
+#define TPS6594_REG_GPIO_OUT_2				0x3e
+#define TPS6594_REG_GPIO_IN_1				0x3f
+#define TPS6594_REG_GPIO_IN_2				0x40
+#define TPS6594_REG_GPIOX_OUT(gpio_inst)		(TPS6594_REG_GPIO_OUT_1 + (gpio_inst) / 8)
+#define TPS6594_REG_GPIOX_IN(gpio_inst)			(TPS6594_REG_GPIO_IN_1 + (gpio_inst) / 8)
+
+#define TPS6594_REG_GPIO_IN_1				0x3f
+#define TPS6594_REG_GPIO_IN_2				0x40
+
+#define TPS6594_REG_RAIL_SEL_1				0x41
+#define TPS6594_REG_RAIL_SEL_2				0x42
+#define TPS6594_REG_RAIL_SEL_3				0x43
+
+#define TPS6594_REG_FSM_TRIG_SEL_1			0x44
+#define TPS6594_REG_FSM_TRIG_SEL_2			0x45
+#define TPS6594_REG_FSM_TRIG_MASK_1			0x46
+#define TPS6594_REG_FSM_TRIG_MASK_2			0x47
+#define TPS6594_REG_FSM_TRIG_MASK_3			0x48
+
+#define TPS6594_REG_MASK_BUCK1_2			0x49
+#define TPS6594_REG_MASK_BUCK3_4			0x4a
+#define TPS6594_REG_MASK_BUCK5				0x4b
+#define TPS6594_REG_MASK_LDO1_2				0x4c
+#define TPS6594_REG_MASK_LDO3_4				0x4d
+#define TPS6594_REG_MASK_VMON				0x4e
+#define TPS6594_REG_MASK_GPIO1_8_FALL			0x4f
+#define TPS6594_REG_MASK_GPIO1_8_RISE			0x50
+#define TPS6594_REG_MASK_GPIO9_11			0x51
+#define TPS6594_REG_MASK_STARTUP			0x52
+#define TPS6594_REG_MASK_MISC				0x53
+#define TPS6594_REG_MASK_MODERATE_ERR			0x54
+#define TPS6594_REG_MASK_FSM_ERR			0x56
+#define TPS6594_REG_MASK_COMM_ERR			0x57
+#define TPS6594_REG_MASK_READBACK_ERR			0x58
+#define TPS6594_REG_MASK_ESM				0x59
+
+#define TPS6594_REG_INT_TOP				0x5a
+#define TPS6594_REG_INT_BUCK				0x5b
+#define TPS6594_REG_INT_BUCK1_2				0x5c
+#define TPS6594_REG_INT_BUCK3_4				0x5d
+#define TPS6594_REG_INT_BUCK5				0x5e
+#define TPS6594_REG_INT_LDO_VMON			0x5f
+#define TPS6594_REG_INT_LDO1_2				0x60
+#define TPS6594_REG_INT_LDO3_4				0x61
+#define TPS6594_REG_INT_VMON				0x62
+#define TPS6594_REG_INT_GPIO				0x63
+#define TPS6594_REG_INT_GPIO1_8				0x64
+#define TPS6594_REG_INT_STARTUP				0x65
+#define TPS6594_REG_INT_MISC				0x66
+#define TPS6594_REG_INT_MODERATE_ERR			0x67
+#define TPS6594_REG_INT_SEVERE_ERR			0x68
+#define TPS6594_REG_INT_FSM_ERR				0x69
+#define TPS6594_REG_INT_COMM_ERR			0x6a
+#define TPS6594_REG_INT_READBACK_ERR			0x6b
+#define TPS6594_REG_INT_ESM				0x6c
+
+#define TPS6594_REG_STAT_BUCK1_2			0x6d
+#define TPS6594_REG_STAT_BUCK3_4			0x6e
+#define TPS6594_REG_STAT_BUCK5				0x6f
+#define TPS6594_REG_STAT_LDO1_2				0x70
+#define TPS6594_REG_STAT_LDO3_4				0x71
+#define TPS6594_REG_STAT_VMON				0x72
+#define TPS6594_REG_STAT_STARTUP			0x73
+#define TPS6594_REG_STAT_MISC				0x74
+#define TPS6594_REG_STAT_MODERATE_ERR			0x75
+#define TPS6594_REG_STAT_SEVERE_ERR			0x76
+#define TPS6594_REG_STAT_READBACK_ERR			0x77
+
+#define TPS6594_REG_PGOOD_SEL_1				0x78
+#define TPS6594_REG_PGOOD_SEL_2				0x79
+#define TPS6594_REG_PGOOD_SEL_3				0x7a
+#define TPS6594_REG_PGOOD_SEL_4				0x7b
+
+#define TPS6594_REG_PLL_CTRL				0x7c
+
+#define TPS6594_REG_CONFIG_1				0x7d
+#define TPS6594_REG_CONFIG_2				0x7e
+
+#define TPS6594_REG_ENABLE_DRV_REG			0x80
+
+#define TPS6594_REG_MISC_CTRL				0x81
+
+#define TPS6594_REG_ENABLE_DRV_STAT			0x82
+
+#define TPS6594_REG_RECOV_CNT_REG_1			0x83
+#define TPS6594_REG_RECOV_CNT_REG_2			0x84
+
+#define TPS6594_REG_FSM_I2C_TRIGGERS			0x85
+#define TPS6594_REG_FSM_NSLEEP_TRIGGERS			0x86
+
+#define TPS6594_REG_BUCK_RESET_REG			0x87
+
+#define TPS6594_REG_SPREAD_SPECTRUM_1			0x88
+
+#define TPS6594_REG_FREQ_SEL				0x8a
+
+#define TPS6594_REG_FSM_STEP_SIZE			0x8b
+
+#define TPS6594_REG_LDO_RV_TIMEOUT_REG_1		0x8c
+#define TPS6594_REG_LDO_RV_TIMEOUT_REG_2		0x8d
+
+#define TPS6594_REG_USER_SPARE_REGS			0x8e
+
+#define TPS6594_REG_ESM_MCU_START_REG			0x8f
+#define TPS6594_REG_ESM_MCU_DELAY1_REG			0x90
+#define TPS6594_REG_ESM_MCU_DELAY2_REG			0x91
+#define TPS6594_REG_ESM_MCU_MODE_CFG			0x92
+#define TPS6594_REG_ESM_MCU_HMAX_REG			0x93
+#define TPS6594_REG_ESM_MCU_HMIN_REG			0x94
+#define TPS6594_REG_ESM_MCU_LMAX_REG			0x95
+#define TPS6594_REG_ESM_MCU_LMIN_REG			0x96
+#define TPS6594_REG_ESM_MCU_ERR_CNT_REG			0x97
+#define TPS6594_REG_ESM_SOC_START_REG			0x98
+#define TPS6594_REG_ESM_SOC_DELAY1_REG			0x99
+#define TPS6594_REG_ESM_SOC_DELAY2_REG			0x9a
+#define TPS6594_REG_ESM_SOC_MODE_CFG			0x9b
+#define TPS6594_REG_ESM_SOC_HMAX_REG			0x9c
+#define TPS6594_REG_ESM_SOC_HMIN_REG			0x9d
+#define TPS6594_REG_ESM_SOC_LMAX_REG			0x9e
+#define TPS6594_REG_ESM_SOC_LMIN_REG			0x9f
+#define TPS6594_REG_ESM_SOC_ERR_CNT_REG			0xa0
+
+#define TPS6594_REG_REGISTER_LOCK			0xa1
+
+#define TPS6594_REG_MANUFACTURING_VER			0xa6
+
+#define TPS6594_REG_CUSTOMER_NVM_ID_REG			0xa7
+
+#define TPS6594_REG_VMON_CONF_REG			0xa8
+
+#define TPS6594_REG_SOFT_REBOOT_REG			0xab
+
+#define TPS6594_REG_RTC_SECONDS				0xb5
+#define TPS6594_REG_RTC_MINUTES				0xb6
+#define TPS6594_REG_RTC_HOURS				0xb7
+#define TPS6594_REG_RTC_DAYS				0xb8
+#define TPS6594_REG_RTC_MONTHS				0xb9
+#define TPS6594_REG_RTC_YEARS				0xba
+#define TPS6594_REG_RTC_WEEKS				0xbb
+
+#define TPS6594_REG_ALARM_SECONDS			0xbc
+#define TPS6594_REG_ALARM_MINUTES			0xbd
+#define TPS6594_REG_ALARM_HOURS				0xbe
+#define TPS6594_REG_ALARM_DAYS				0xbf
+#define TPS6594_REG_ALARM_MONTHS			0xc0
+#define TPS6594_REG_ALARM_YEARS				0xc1
+
+#define TPS6594_REG_RTC_CTRL_1				0xc2
+#define TPS6594_REG_RTC_CTRL_2				0xc3
+#define TPS6594_REG_RTC_STATUS				0xc4
+#define TPS6594_REG_RTC_INTERRUPTS			0xc5
+#define TPS6594_REG_RTC_COMP_LSB			0xc6
+#define TPS6594_REG_RTC_COMP_MSB			0xc7
+#define TPS6594_REG_RTC_RESET_STATUS			0xc8
+
+#define TPS6594_REG_SCRATCH_PAD_REG_1			0xc9
+#define TPS6594_REG_SCRATCH_PAD_REG_2			0xca
+#define TPS6594_REG_SCRATCH_PAD_REG_3			0xcb
+#define TPS6594_REG_SCRATCH_PAD_REG_4			0xcc
+
+#define TPS6594_REG_PFSM_DELAY_REG_1			0xcd
+#define TPS6594_REG_PFSM_DELAY_REG_2			0xce
+#define TPS6594_REG_PFSM_DELAY_REG_3			0xcf
+#define TPS6594_REG_PFSM_DELAY_REG_4			0xd0
+
+/* Registers for page 1 of TPS6594 */
+#define TPS6594_REG_SERIAL_IF_CONFIG			0x11a
+#define TPS6594_REG_I2C1_ID				0x122
+#define TPS6594_REG_I2C2_ID				0x123
+
+/* Registers for page 4 of TPS6594 */
+#define TPS6594_REG_WD_ANSWER_REG			0x401
+#define TPS6594_REG_WD_QUESTION_ANSW_CNT		0x402
+#define TPS6594_REG_WD_WIN1_CFG				0x403
+#define TPS6594_REG_WD_WIN2_CFG				0x404
+#define TPS6594_REG_WD_LONGWIN_CFG			0x405
+#define TPS6594_REG_WD_MODE_REG				0x406
+#define TPS6594_REG_WD_QA_CFG				0x407
+#define TPS6594_REG_WD_ERR_STATUS			0x408
+#define TPS6594_REG_WD_THR_CFG				0x409
+#define TPS6594_REG_DWD_FAIL_CNT_REG			0x40a
+
+/* BUCKX_CTRL register field definition */
+#define TPS6594_BIT_BUCK_EN				BIT(0)
+#define TPS6594_BIT_BUCK_FPWM				BIT(1)
+#define TPS6594_BIT_BUCK_FPWM_MP			BIT(2)
+#define TPS6594_BIT_BUCK_VSEL				BIT(3)
+#define TPS6594_BIT_BUCK_VMON_EN			BIT(4)
+#define TPS6594_BIT_BUCK_PLDN				BIT(5)
+#define TPS6594_BIT_BUCK_RV_SEL				BIT(7)
+
+/* BUCKX_CONF register field definition */
+#define TPS6594_MASK_BUCK_SLEW_RATE			GENMASK(2, 0)
+#define TPS6594_MASK_BUCK_ILIM				GENMASK(5, 3)
+
+/* BUCKX_PG_WINDOW register field definition */
+#define TPS6594_MASK_BUCK_OV_THR			GENMASK(2, 0)
+#define TPS6594_MASK_BUCK_UV_THR			GENMASK(5, 3)
+
+/* BUCKX VSET */
+#define TPS6594_MASK_BUCKS_VSET GENMASK(7, 0)
+
+/* LDOX_CTRL register field definition */
+#define TPS6594_BIT_LDO_EN				BIT(0)
+#define TPS6594_BIT_LDO_SLOW_RAMP			BIT(1)
+#define TPS6594_BIT_LDO_VMON_EN				BIT(4)
+#define TPS6594_MASK_LDO_PLDN				GENMASK(6, 5)
+#define TPS6594_BIT_LDO_RV_SEL				BIT(7)
+
+/* LDORTC_CTRL register field definition */
+#define TPS6594_BIT_LDORTC_DIS				BIT(0)
+
+/* LDOX_VOUT register field definition */
+#define TPS6594_MASK_LDO123_VSET			GENMASK(6, 1)
+#define TPS6594_MASK_LDO4_VSET				GENMASK(6, 0)
+#define TPS6594_BIT_LDO_BYPASS				BIT(7)
+
+/* LDOX_PG_WINDOW register field definition */
+#define TPS6594_MASK_LDO_OV_THR				GENMASK(2, 0)
+#define TPS6594_MASK_LDO_UV_THR				GENMASK(5, 3)
+
+/* VCCA_VMON_CTRL register field definition */
+#define TPS6594_BIT_VMON_EN				BIT(0)
+#define TPS6594_BIT_VMON1_EN				BIT(1)
+#define TPS6594_BIT_VMON1_RV_SEL			BIT(2)
+#define TPS6594_BIT_VMON2_EN				BIT(3)
+#define TPS6594_BIT_VMON2_RV_SEL			BIT(4)
+#define TPS6594_BIT_VMON_DEGLITCH_SEL			BIT(5)
+
+/* VCCA_PG_WINDOW register field definition */
+#define TPS6594_MASK_VCCA_OV_THR			GENMASK(2, 0)
+#define TPS6594_MASK_VCCA_UV_THR			GENMASK(5, 3)
+#define TPS6594_BIT_VCCA_PG_SET				BIT(6)
+
+/* VMONX_PG_WINDOW register field definition */
+#define TPS6594_MASK_VMONX_OV_THR			GENMASK(2, 0)
+#define TPS6594_MASK_VMONX_UV_THR			GENMASK(5, 3)
+#define TPS6594_BIT_VMONX_RANGE				BIT(6)
+
+/* GPIOX_CONF register field definition */
+#define TPS6594_BIT_GPIO_DIR				BIT(0)
+#define TPS6594_BIT_GPIO_OD				BIT(1)
+#define TPS6594_BIT_GPIO_PU_SEL				BIT(2)
+#define TPS6594_BIT_GPIO_PU_PD_EN			BIT(3)
+#define TPS6594_BIT_GPIO_DEGLITCH_EN			BIT(4)
+#define TPS6594_MASK_GPIO_SEL				GENMASK(7, 5)
+
+/* NPWRON_CONF register field definition */
+#define TPS6594_BIT_NRSTOUT_OD				BIT(0)
+#define TPS6594_BIT_ENABLE_PU_SEL			BIT(2)
+#define TPS6594_BIT_ENABLE_PU_PD_EN			BIT(3)
+#define TPS6594_BIT_ENABLE_DEGLITCH_EN			BIT(4)
+#define TPS6594_BIT_ENABLE_POL				BIT(5)
+#define TPS6594_MASK_NPWRON_SEL				GENMASK(7, 6)
+
+/* GPIO_OUT_X register field definition */
+#define TPS6594_BIT_GPIOX_OUT(gpio_inst)		BIT((gpio_inst) % 8)
+
+/* GPIO_IN_X register field definition */
+#define TPS6594_BIT_GPIOX_IN(gpio_inst)			BIT((gpio_inst) % 8)
+#define TPS6594_BIT_NPWRON_IN				BIT(3)
+
+/* RAIL_SEL_1 register field definition */
+#define TPS6594_MASK_BUCK1_GRP_SEL			GENMASK(1, 0)
+#define TPS6594_MASK_BUCK2_GRP_SEL			GENMASK(3, 2)
+#define TPS6594_MASK_BUCK3_GRP_SEL			GENMASK(5, 4)
+#define TPS6594_MASK_BUCK4_GRP_SEL			GENMASK(7, 6)
+
+/* RAIL_SEL_2 register field definition */
+#define TPS6594_MASK_BUCK5_GRP_SEL			GENMASK(1, 0)
+#define TPS6594_MASK_LDO1_GRP_SEL			GENMASK(3, 2)
+#define TPS6594_MASK_LDO2_GRP_SEL			GENMASK(5, 4)
+#define TPS6594_MASK_LDO3_GRP_SEL			GENMASK(7, 6)
+
+/* RAIL_SEL_3 register field definition */
+#define TPS6594_MASK_LDO4_GRP_SEL			GENMASK(1, 0)
+#define TPS6594_MASK_VCCA_GRP_SEL			GENMASK(3, 2)
+#define TPS6594_MASK_VMON1_GRP_SEL			GENMASK(5, 4)
+#define TPS6594_MASK_VMON2_GRP_SEL			GENMASK(7, 6)
+
+/* FSM_TRIG_SEL_1 register field definition */
+#define TPS6594_MASK_MCU_RAIL_TRIG			GENMASK(1, 0)
+#define TPS6594_MASK_SOC_RAIL_TRIG			GENMASK(3, 2)
+#define TPS6594_MASK_OTHER_RAIL_TRIG			GENMASK(5, 4)
+#define TPS6594_MASK_SEVERE_ERR_TRIG			GENMASK(7, 6)
+
+/* FSM_TRIG_SEL_2 register field definition */
+#define TPS6594_MASK_MODERATE_ERR_TRIG			GENMASK(1, 0)
+
+/* FSM_TRIG_MASK_X register field definition */
+#define TPS6594_BIT_GPIOX_FSM_MASK(gpio_inst)		BIT(((gpio_inst) << 1) % 8)
+#define TPS6594_BIT_GPIOX_FSM_MASK_POL(gpio_inst)	BIT(((gpio_inst) << 1) % 8 + 1)
+
+/* MASK_BUCKX register field definition */
+#define TPS6594_BIT_BUCKX_OV_MASK(buck_inst)		BIT(((buck_inst) << 2) % 8)
+#define TPS6594_BIT_BUCKX_UV_MASK(buck_inst)		BIT(((buck_inst) << 2) % 8 + 1)
+#define TPS6594_BIT_BUCKX_ILIM_MASK(buck_inst)		BIT(((buck_inst) << 2) % 8 + 3)
+
+/* MASK_LDOX register field definition */
+#define TPS6594_BIT_LDOX_OV_MASK(ldo_inst)		BIT(((ldo_inst) << 2) % 8)
+#define TPS6594_BIT_LDOX_UV_MASK(ldo_inst)		BIT(((ldo_inst) << 2) % 8 + 1)
+#define TPS6594_BIT_LDOX_ILIM_MASK(ldo_inst)		BIT(((ldo_inst) << 2) % 8 + 3)
+
+/* MASK_VMON register field definition */
+#define TPS6594_BIT_VCCA_OV_MASK			BIT(0)
+#define TPS6594_BIT_VCCA_UV_MASK			BIT(1)
+#define TPS6594_BIT_VMON1_OV_MASK			BIT(2)
+#define TPS6594_BIT_VMON1_UV_MASK			BIT(3)
+#define TPS6594_BIT_VMON2_OV_MASK			BIT(5)
+#define TPS6594_BIT_VMON2_UV_MASK			BIT(6)
+
+/* MASK_GPIOX register field definition */
+#define TPS6594_BIT_GPIOX_FALL_MASK(gpio_inst)		BIT((gpio_inst) < 8 ? \
+							    (gpio_inst) : (gpio_inst) % 8)
+#define TPS6594_BIT_GPIOX_RISE_MASK(gpio_inst)		BIT((gpio_inst) < 8 ? \
+							    (gpio_inst) : (gpio_inst) % 8 + 3)
+
+/* MASK_STARTUP register field definition */
+#define TPS6594_BIT_NPWRON_START_MASK			BIT(0)
+#define TPS6594_BIT_ENABLE_MASK				BIT(1)
+#define TPS6594_BIT_FSD_MASK				BIT(4)
+#define TPS6594_BIT_SOFT_REBOOT_MASK			BIT(5)
+
+/* MASK_MISC register field definition */
+#define TPS6594_BIT_BIST_PASS_MASK			BIT(0)
+#define TPS6594_BIT_EXT_CLK_MASK			BIT(1)
+#define TPS6594_BIT_TWARN_MASK				BIT(3)
+
+/* MASK_MODERATE_ERR register field definition */
+#define TPS6594_BIT_BIST_FAIL_MASK			BIT(1)
+#define TPS6594_BIT_REG_CRC_ERR_MASK			BIT(2)
+#define TPS6594_BIT_SPMI_ERR_MASK			BIT(4)
+#define TPS6594_BIT_NPWRON_LONG_MASK			BIT(5)
+#define TPS6594_BIT_NINT_READBACK_MASK			BIT(6)
+#define TPS6594_BIT_NRSTOUT_READBACK_MASK		BIT(7)
+
+/* MASK_FSM_ERR register field definition */
+#define TPS6594_BIT_IMM_SHUTDOWN_MASK			BIT(0)
+#define TPS6594_BIT_ORD_SHUTDOWN_MASK			BIT(1)
+#define TPS6594_BIT_MCU_PWR_ERR_MASK			BIT(2)
+#define TPS6594_BIT_SOC_PWR_ERR_MASK			BIT(3)
+
+/* MASK_COMM_ERR register field definition */
+#define TPS6594_BIT_COMM_FRM_ERR_MASK			BIT(0)
+#define TPS6594_BIT_COMM_CRC_ERR_MASK			BIT(1)
+#define TPS6594_BIT_COMM_ADR_ERR_MASK			BIT(3)
+#define TPS6594_BIT_I2C2_CRC_ERR_MASK			BIT(5)
+#define TPS6594_BIT_I2C2_ADR_ERR_MASK			BIT(7)
+
+/* MASK_READBACK_ERR register field definition */
+#define TPS6594_BIT_EN_DRV_READBACK_MASK		BIT(0)
+#define TPS6594_BIT_NRSTOUT_SOC_READBACK_MASK		BIT(3)
+
+/* MASK_ESM register field definition */
+#define TPS6594_BIT_ESM_SOC_PIN_MASK			BIT(0)
+#define TPS6594_BIT_ESM_SOC_FAIL_MASK			BIT(1)
+#define TPS6594_BIT_ESM_SOC_RST_MASK			BIT(2)
+#define TPS6594_BIT_ESM_MCU_PIN_MASK			BIT(3)
+#define TPS6594_BIT_ESM_MCU_FAIL_MASK			BIT(4)
+#define TPS6594_BIT_ESM_MCU_RST_MASK			BIT(5)
+
+/* INT_TOP register field definition */
+#define TPS6594_BIT_BUCK_INT				BIT(0)
+#define TPS6594_BIT_LDO_VMON_INT			BIT(1)
+#define TPS6594_BIT_GPIO_INT				BIT(2)
+#define TPS6594_BIT_STARTUP_INT				BIT(3)
+#define TPS6594_BIT_MISC_INT				BIT(4)
+#define TPS6594_BIT_MODERATE_ERR_INT			BIT(5)
+#define TPS6594_BIT_SEVERE_ERR_INT			BIT(6)
+#define TPS6594_BIT_FSM_ERR_INT				BIT(7)
+
+/* INT_BUCK register field definition */
+#define TPS6594_BIT_BUCK1_2_INT				BIT(0)
+#define TPS6594_BIT_BUCK3_4_INT				BIT(1)
+#define TPS6594_BIT_BUCK5_INT				BIT(2)
+
+/* INT_BUCKX register field definition */
+#define TPS6594_BIT_BUCKX_OV_INT(buck_inst)		BIT(((buck_inst) << 2) % 8)
+#define TPS6594_BIT_BUCKX_UV_INT(buck_inst)		BIT(((buck_inst) << 2) % 8 + 1)
+#define TPS6594_BIT_BUCKX_SC_INT(buck_inst)		BIT(((buck_inst) << 2) % 8 + 2)
+#define TPS6594_BIT_BUCKX_ILIM_INT(buck_inst)		BIT(((buck_inst) << 2) % 8 + 3)
+
+/* INT_LDO_VMON register field definition */
+#define TPS6594_BIT_LDO1_2_INT				BIT(0)
+#define TPS6594_BIT_LDO3_4_INT				BIT(1)
+#define TPS6594_BIT_VCCA_INT				BIT(4)
+
+/* INT_LDOX register field definition */
+#define TPS6594_BIT_LDOX_OV_INT(ldo_inst)		BIT(((ldo_inst) << 2) % 8)
+#define TPS6594_BIT_LDOX_UV_INT(ldo_inst)		BIT(((ldo_inst) << 2) % 8 + 1)
+#define TPS6594_BIT_LDOX_SC_INT(ldo_inst)		BIT(((ldo_inst) << 2) % 8 + 2)
+#define TPS6594_BIT_LDOX_ILIM_INT(ldo_inst)		BIT(((ldo_inst) << 2) % 8 + 3)
+
+/* INT_VMON register field definition */
+#define TPS6594_BIT_VCCA_OV_INT				BIT(0)
+#define TPS6594_BIT_VCCA_UV_INT				BIT(1)
+#define TPS6594_BIT_VMON1_OV_INT			BIT(2)
+#define TPS6594_BIT_VMON1_UV_INT			BIT(3)
+#define TPS6594_BIT_VMON1_RV_INT			BIT(4)
+#define TPS6594_BIT_VMON2_OV_INT			BIT(5)
+#define TPS6594_BIT_VMON2_UV_INT			BIT(6)
+#define TPS6594_BIT_VMON2_RV_INT			BIT(7)
+
+/* INT_GPIO register field definition */
+#define TPS6594_BIT_GPIO9_INT				BIT(0)
+#define TPS6594_BIT_GPIO10_INT				BIT(1)
+#define TPS6594_BIT_GPIO11_INT				BIT(2)
+#define TPS6594_BIT_GPIO1_8_INT				BIT(3)
+
+/* INT_GPIOX register field definition */
+#define TPS6594_BIT_GPIOX_INT(gpio_inst)		BIT(gpio_inst)
+
+/* INT_STARTUP register field definition */
+#define TPS6594_BIT_NPWRON_START_INT			BIT(0)
+#define TPS6594_BIT_ENABLE_INT				BIT(1)
+#define TPS6594_BIT_RTC_INT				BIT(2)
+#define TPS6594_BIT_FSD_INT				BIT(4)
+#define TPS6594_BIT_SOFT_REBOOT_INT			BIT(5)
+
+/* INT_MISC register field definition */
+#define TPS6594_BIT_BIST_PASS_INT			BIT(0)
+#define TPS6594_BIT_EXT_CLK_INT				BIT(1)
+#define TPS6594_BIT_TWARN_INT				BIT(3)
+
+/* INT_MODERATE_ERR register field definition */
+#define TPS6594_BIT_TSD_ORD_INT				BIT(0)
+#define TPS6594_BIT_BIST_FAIL_INT			BIT(1)
+#define TPS6594_BIT_REG_CRC_ERR_INT			BIT(2)
+#define TPS6594_BIT_RECOV_CNT_INT			BIT(3)
+#define TPS6594_BIT_SPMI_ERR_INT			BIT(4)
+#define TPS6594_BIT_NPWRON_LONG_INT			BIT(5)
+#define TPS6594_BIT_NINT_READBACK_INT			BIT(6)
+#define TPS6594_BIT_NRSTOUT_READBACK_INT		BIT(7)
+
+/* INT_SEVERE_ERR register field definition */
+#define TPS6594_BIT_TSD_IMM_INT				BIT(0)
+#define TPS6594_BIT_VCCA_OVP_INT			BIT(1)
+#define TPS6594_BIT_PFSM_ERR_INT			BIT(2)
+
+/* INT_FSM_ERR register field definition */
+#define TPS6594_BIT_IMM_SHUTDOWN_INT			BIT(0)
+#define TPS6594_BIT_ORD_SHUTDOWN_INT			BIT(1)
+#define TPS6594_BIT_MCU_PWR_ERR_INT			BIT(2)
+#define TPS6594_BIT_SOC_PWR_ERR_INT			BIT(3)
+#define TPS6594_BIT_COMM_ERR_INT			BIT(4)
+#define TPS6594_BIT_READBACK_ERR_INT			BIT(5)
+#define TPS6594_BIT_ESM_INT				BIT(6)
+#define TPS6594_BIT_WD_INT				BIT(7)
+
+/* INT_COMM_ERR register field definition */
+#define TPS6594_BIT_COMM_FRM_ERR_INT			BIT(0)
+#define TPS6594_BIT_COMM_CRC_ERR_INT			BIT(1)
+#define TPS6594_BIT_COMM_ADR_ERR_INT			BIT(3)
+#define TPS6594_BIT_I2C2_CRC_ERR_INT			BIT(5)
+#define TPS6594_BIT_I2C2_ADR_ERR_INT			BIT(7)
+
+/* INT_READBACK_ERR register field definition */
+#define TPS6594_BIT_EN_DRV_READBACK_INT			BIT(0)
+#define TPS6594_BIT_NRSTOUT_SOC_READBACK_INT		BIT(3)
+
+/* INT_ESM register field definition */
+#define TPS6594_BIT_ESM_SOC_PIN_INT			BIT(0)
+#define TPS6594_BIT_ESM_SOC_FAIL_INT			BIT(1)
+#define TPS6594_BIT_ESM_SOC_RST_INT			BIT(2)
+#define TPS6594_BIT_ESM_MCU_PIN_INT			BIT(3)
+#define TPS6594_BIT_ESM_MCU_FAIL_INT			BIT(4)
+#define TPS6594_BIT_ESM_MCU_RST_INT			BIT(5)
+
+/* STAT_BUCKX register field definition */
+#define TPS6594_BIT_BUCKX_OV_STAT(buck_inst)		BIT(((buck_inst) << 2) % 8)
+#define TPS6594_BIT_BUCKX_UV_STAT(buck_inst)		BIT(((buck_inst) << 2) % 8 + 1)
+#define TPS6594_BIT_BUCKX_ILIM_STAT(buck_inst)		BIT(((buck_inst) << 2) % 8 + 3)
+
+/* STAT_LDOX register field definition */
+#define TPS6594_BIT_LDOX_OV_STAT(ldo_inst)		BIT(((ldo_inst) << 2) % 8)
+#define TPS6594_BIT_LDOX_UV_STAT(ldo_inst)		BIT(((ldo_inst) << 2) % 8 + 1)
+#define TPS6594_BIT_LDOX_ILIM_STAT(ldo_inst)		BIT(((ldo_inst) << 2) % 8 + 3)
+
+/* STAT_VMON register field definition */
+#define TPS6594_BIT_VCCA_OV_STAT			BIT(0)
+#define TPS6594_BIT_VCCA_UV_STAT			BIT(1)
+#define TPS6594_BIT_VMON1_OV_STAT			BIT(2)
+#define TPS6594_BIT_VMON1_UV_STAT			BIT(3)
+#define TPS6594_BIT_VMON2_OV_STAT			BIT(5)
+#define TPS6594_BIT_VMON2_UV_STAT			BIT(6)
+
+/* STAT_STARTUP register field definition */
+#define TPS6594_BIT_ENABLE_STAT				BIT(1)
+
+/* STAT_MISC register field definition */
+#define TPS6594_BIT_EXT_CLK_STAT			BIT(1)
+#define TPS6594_BIT_TWARN_STAT				BIT(3)
+
+/* STAT_MODERATE_ERR register field definition */
+#define TPS6594_BIT_TSD_ORD_STAT			BIT(0)
+
+/* STAT_SEVERE_ERR register field definition */
+#define TPS6594_BIT_TSD_IMM_STAT			BIT(0)
+#define TPS6594_BIT_VCCA_OVP_STAT			BIT(1)
+
+/* STAT_READBACK_ERR register field definition */
+#define TPS6594_BIT_EN_DRV_READBACK_STAT		BIT(0)
+#define TPS6594_BIT_NINT_READBACK_STAT			BIT(1)
+#define TPS6594_BIT_NRSTOUT_READBACK_STAT		BIT(2)
+#define TPS6594_BIT_NRSTOUT_SOC_READBACK_STAT		BIT(3)
+
+/* PGOOD_SEL_1 register field definition */
+#define TPS6594_MASK_PGOOD_SEL_BUCK1			GENMASK(1, 0)
+#define TPS6594_MASK_PGOOD_SEL_BUCK2			GENMASK(3, 2)
+#define TPS6594_MASK_PGOOD_SEL_BUCK3			GENMASK(5, 4)
+#define TPS6594_MASK_PGOOD_SEL_BUCK4			GENMASK(7, 6)
+
+/* PGOOD_SEL_2 register field definition */
+#define TPS6594_MASK_PGOOD_SEL_BUCK5			GENMASK(1, 0)
+
+/* PGOOD_SEL_3 register field definition */
+#define TPS6594_MASK_PGOOD_SEL_LDO1			GENMASK(1, 0)
+#define TPS6594_MASK_PGOOD_SEL_LDO2			GENMASK(3, 2)
+#define TPS6594_MASK_PGOOD_SEL_LDO3			GENMASK(5, 4)
+#define TPS6594_MASK_PGOOD_SEL_LDO4			GENMASK(7, 6)
+
+/* PGOOD_SEL_4 register field definition */
+#define TPS6594_BIT_PGOOD_SEL_VCCA			BIT(0)
+#define TPS6594_BIT_PGOOD_SEL_VMON1			BIT(1)
+#define TPS6594_BIT_PGOOD_SEL_VMON2			BIT(2)
+#define TPS6594_BIT_PGOOD_SEL_TDIE_WARN			BIT(3)
+#define TPS6594_BIT_PGOOD_SEL_NRSTOUT			BIT(4)
+#define TPS6594_BIT_PGOOD_SEL_NRSTOUT_SOC		BIT(5)
+#define TPS6594_BIT_PGOOD_POL				BIT(6)
+#define TPS6594_BIT_PGOOD_WINDOW			BIT(7)
+
+/* PLL_CTRL register field definition */
+#define TPS6594_MASK_EXT_CLK_FREQ			GENMASK(1, 0)
+
+/* CONFIG_1 register field definition */
+#define TPS6594_BIT_TWARN_LEVEL				BIT(0)
+#define TPS6594_BIT_TSD_ORD_LEVEL			BIT(1)
+#define TPS6594_BIT_I2C1_HS				BIT(3)
+#define TPS6594_BIT_I2C2_HS				BIT(4)
+#define TPS6594_BIT_EN_ILIM_FSM_CTRL			BIT(5)
+#define TPS6594_BIT_NSLEEP1_MASK			BIT(6)
+#define TPS6594_BIT_NSLEEP2_MASK			BIT(7)
+
+/* CONFIG_2 register field definition */
+#define TPS6594_BIT_BB_CHARGER_EN			BIT(0)
+#define TPS6594_BIT_BB_ICHR				BIT(1)
+#define TPS6594_MASK_BB_VEOC				GENMASK(3, 2)
+#define TPS6594_BB_EOC_RDY				BIT(7)
+
+/* ENABLE_DRV_REG register field definition */
+#define TPS6594_BIT_ENABLE_DRV				BIT(0)
+
+/* MISC_CTRL register field definition */
+#define TPS6594_BIT_NRSTOUT				BIT(0)
+#define TPS6594_BIT_NRSTOUT_SOC				BIT(1)
+#define TPS6594_BIT_LPM_EN				BIT(2)
+#define TPS6594_BIT_CLKMON_EN				BIT(3)
+#define TPS6594_BIT_AMUXOUT_EN				BIT(4)
+#define TPS6594_BIT_SEL_EXT_CLK				BIT(5)
+#define TPS6594_MASK_SYNCCLKOUT_FREQ_SEL		GENMASK(7, 6)
+
+/* ENABLE_DRV_STAT register field definition */
+#define TPS6594_BIT_EN_DRV_IN				BIT(0)
+#define TPS6594_BIT_NRSTOUT_IN				BIT(1)
+#define TPS6594_BIT_NRSTOUT_SOC_IN			BIT(2)
+#define TPS6594_BIT_FORCE_EN_DRV_LOW			BIT(3)
+#define TPS6594_BIT_SPMI_LPM_EN				BIT(4)
+
+/* RECOV_CNT_REG_1 register field definition */
+#define TPS6594_MASK_RECOV_CNT				GENMASK(3, 0)
+
+/* RECOV_CNT_REG_2 register field definition */
+#define TPS6594_MASK_RECOV_CNT_THR			GENMASK(3, 0)
+#define TPS6594_BIT_RECOV_CNT_CLR			BIT(4)
+
+/* FSM_I2C_TRIGGERS register field definition */
+#define TPS6594_BIT_TRIGGER_I2C(bit)			BIT(bit)
+
+/* FSM_NSLEEP_TRIGGERS register field definition */
+#define TPS6594_BIT_NSLEEP1B				BIT(0)
+#define TPS6594_BIT_NSLEEP2B				BIT(1)
+
+/* BUCK_RESET_REG register field definition */
+#define TPS6594_BIT_BUCKX_RESET(buck_inst)		BIT(buck_inst)
+
+/* SPREAD_SPECTRUM_1 register field definition */
+#define TPS6594_MASK_SS_DEPTH				GENMASK(1, 0)
+#define TPS6594_BIT_SS_EN				BIT(2)
+
+/* FREQ_SEL register field definition */
+#define TPS6594_BIT_BUCKX_FREQ_SEL(buck_inst)		BIT(buck_inst)
+
+/* FSM_STEP_SIZE register field definition */
+#define TPS6594_MASK_PFSM_DELAY_STEP			GENMASK(4, 0)
+
+/* LDO_RV_TIMEOUT_REG_1 register field definition */
+#define TPS6594_MASK_LDO1_RV_TIMEOUT			GENMASK(3, 0)
+#define TPS6594_MASK_LDO2_RV_TIMEOUT			GENMASK(7, 4)
+
+/* LDO_RV_TIMEOUT_REG_2 register field definition */
+#define TPS6594_MASK_LDO3_RV_TIMEOUT			GENMASK(3, 0)
+#define TPS6594_MASK_LDO4_RV_TIMEOUT			GENMASK(7, 4)
+
+/* USER_SPARE_REGS register field definition */
+#define TPS6594_BIT_USER_SPARE(bit)			BIT(bit)
+
+/* ESM_MCU_START_REG register field definition */
+#define TPS6594_BIT_ESM_MCU_START			BIT(0)
+
+/* ESM_MCU_MODE_CFG register field definition */
+#define TPS6594_MASK_ESM_MCU_ERR_CNT_TH			GENMASK(3, 0)
+#define TPS6594_BIT_ESM_MCU_ENDRV			BIT(5)
+#define TPS6594_BIT_ESM_MCU_EN				BIT(6)
+#define TPS6594_BIT_ESM_MCU_MODE			BIT(7)
+
+/* ESM_MCU_ERR_CNT_REG register field definition */
+#define TPS6594_MASK_ESM_MCU_ERR_CNT			GENMASK(4, 0)
+
+/* ESM_SOC_START_REG register field definition */
+#define TPS6594_BIT_ESM_SOC_START			BIT(0)
+
+/* ESM_SOC_MODE_CFG register field definition */
+#define TPS6594_MASK_ESM_SOC_ERR_CNT_TH			GENMASK(3, 0)
+#define TPS6594_BIT_ESM_SOC_ENDRV			BIT(5)
+#define TPS6594_BIT_ESM_SOC_EN				BIT(6)
+#define TPS6594_BIT_ESM_SOC_MODE			BIT(7)
+
+/* ESM_SOC_ERR_CNT_REG register field definition */
+#define TPS6594_MASK_ESM_SOC_ERR_CNT			GENMASK(4, 0)
+
+/* REGISTER_LOCK register field definition */
+#define TPS6594_BIT_REGISTER_LOCK_STATUS		BIT(0)
+
+/* VMON_CONF register field definition */
+#define TPS6594_MASK_VMON1_SLEW_RATE			GENMASK(2, 0)
+#define TPS6594_MASK_VMON2_SLEW_RATE			GENMASK(5, 3)
+
+/* SOFT_REBOOT_REG register field definition */
+#define TPS6594_BIT_SOFT_REBOOT				BIT(0)
+
+/* RTC_SECONDS & ALARM_SECONDS register field definition */
+#define TPS6594_MASK_SECOND_0				GENMASK(3, 0)
+#define TPS6594_MASK_SECOND_1				GENMASK(6, 4)
+
+/* RTC_MINUTES & ALARM_MINUTES register field definition */
+#define TPS6594_MASK_MINUTE_0				GENMASK(3, 0)
+#define TPS6594_MASK_MINUTE_1				GENMASK(6, 4)
+
+/* RTC_HOURS & ALARM_HOURS register field definition */
+#define TPS6594_MASK_HOUR_0				GENMASK(3, 0)
+#define TPS6594_MASK_HOUR_1				GENMASK(5, 4)
+#define TPS6594_BIT_PM_NAM				BIT(7)
+
+/* RTC_DAYS & ALARM_DAYS register field definition */
+#define TPS6594_MASK_DAY_0				GENMASK(3, 0)
+#define TPS6594_MASK_DAY_1				GENMASK(5, 4)
+
+/* RTC_MONTHS & ALARM_MONTHS register field definition */
+#define TPS6594_MASK_MONTH_0				GENMASK(3, 0)
+#define TPS6594_BIT_MONTH_1				BIT(4)
+
+/* RTC_YEARS & ALARM_YEARS register field definition */
+#define TPS6594_MASK_YEAR_0				GENMASK(3, 0)
+#define TPS6594_MASK_YEAR_1				GENMASK(7, 4)
+
+/* RTC_WEEKS register field definition */
+#define TPS6594_MASK_WEEK				GENMASK(2, 0)
+
+/* RTC_CTRL_1 register field definition */
+#define TPS6594_BIT_STOP_RTC				BIT(0)
+#define TPS6594_BIT_ROUND_30S				BIT(1)
+#define TPS6594_BIT_AUTO_COMP				BIT(2)
+#define TPS6594_BIT_MODE_12_24				BIT(3)
+#define TPS6594_BIT_SET_32_COUNTER			BIT(5)
+#define TPS6594_BIT_GET_TIME				BIT(6)
+#define TPS6594_BIT_RTC_V_OPT				BIT(7)
+
+/* RTC_CTRL_2 register field definition */
+#define TPS6594_BIT_XTAL_EN				BIT(0)
+#define TPS6594_MASK_XTAL_SEL				GENMASK(2, 1)
+#define TPS6594_BIT_LP_STANDBY_SEL			BIT(3)
+#define TPS6594_BIT_FAST_BIST				BIT(4)
+#define TPS6594_MASK_STARTUP_DEST			GENMASK(6, 5)
+#define TPS6594_BIT_FIRST_STARTUP_DONE			BIT(7)
+
+/* RTC_STATUS register field definition */
+#define TPS6594_BIT_RUN					BIT(1)
+#define TPS6594_BIT_TIMER				BIT(5)
+#define TPS6594_BIT_ALARM				BIT(6)
+#define TPS6594_BIT_POWER_UP				BIT(7)
+
+/* RTC_INTERRUPTS register field definition */
+#define TPS6594_MASK_EVERY				GENMASK(1, 0)
+#define TPS6594_BIT_IT_TIMER				BIT(2)
+#define TPS6594_BIT_IT_ALARM				BIT(3)
+
+/* RTC_RESET_STATUS register field definition */
+#define TPS6594_BIT_RESET_STATUS_RTC			BIT(0)
+
+/* SERIAL_IF_CONFIG register field definition */
+#define TPS6594_BIT_I2C_SPI_SEL				BIT(0)
+#define TPS6594_BIT_I2C1_SPI_CRC_EN			BIT(1)
+#define TPS6594_BIT_I2C2_CRC_EN				BIT(2)
+#define TPS6594_MASK_T_CRC				GENMASK(7, 3)
+
+/* WD_QUESTION_ANSW_CNT register field definition */
+#define TPS6594_MASK_WD_QUESTION			GENMASK(3, 0)
+#define TPS6594_MASK_WD_ANSW_CNT			GENMASK(5, 4)
+
+/* WD_MODE_REG register field definition */
+#define TPS6594_BIT_WD_RETURN_LONGWIN			BIT(0)
+#define TPS6594_BIT_WD_MODE_SELECT			BIT(1)
+#define TPS6594_BIT_WD_PWRHOLD				BIT(2)
+
+/* WD_QA_CFG register field definition */
+#define TPS6594_MASK_WD_QUESTION_SEED			GENMASK(3, 0)
+#define TPS6594_MASK_WD_QA_LFSR				GENMASK(5, 4)
+#define TPS6594_MASK_WD_QA_FDBK				GENMASK(7, 6)
+
+/* WD_ERR_STATUS register field definition */
+#define TPS6594_BIT_WD_LONGWIN_TIMEOUT_INT		BIT(0)
+#define TPS6594_BIT_WD_TIMEOUT				BIT(1)
+#define TPS6594_BIT_WD_TRIG_EARLY			BIT(2)
+#define TPS6594_BIT_WD_ANSW_EARLY			BIT(3)
+#define TPS6594_BIT_WD_SEQ_ERR				BIT(4)
+#define TPS6594_BIT_WD_ANSW_ERR				BIT(5)
+#define TPS6594_BIT_WD_FAIL_INT				BIT(6)
+#define TPS6594_BIT_WD_RST_INT				BIT(7)
+
+/* WD_THR_CFG register field definition */
+#define TPS6594_MASK_WD_RST_TH				GENMASK(2, 0)
+#define TPS6594_MASK_WD_FAIL_TH				GENMASK(5, 3)
+#define TPS6594_BIT_WD_EN				BIT(6)
+#define TPS6594_BIT_WD_RST_EN				BIT(7)
+
+/* WD_FAIL_CNT_REG register field definition */
+#define TPS6594_MASK_WD_FAIL_CNT			GENMASK(3, 0)
+#define TPS6594_BIT_WD_FIRST_OK				BIT(5)
+#define TPS6594_BIT_WD_BAD_EVENT			BIT(6)
+
+/* CRC8 polynomial for I2C & SPI protocols */
+#define TPS6594_CRC8_POLYNOMIAL	0x07
+
+/* IRQs */
+enum tps6594_irqs {
+	/* INT_BUCK1_2 register */
+	TPS6594_IRQ_BUCK1_OV,
+	TPS6594_IRQ_BUCK1_UV,
+	TPS6594_IRQ_BUCK1_SC,
+	TPS6594_IRQ_BUCK1_ILIM,
+	TPS6594_IRQ_BUCK2_OV,
+	TPS6594_IRQ_BUCK2_UV,
+	TPS6594_IRQ_BUCK2_SC,
+	TPS6594_IRQ_BUCK2_ILIM,
+	/* INT_BUCK3_4 register */
+	TPS6594_IRQ_BUCK3_OV,
+	TPS6594_IRQ_BUCK3_UV,
+	TPS6594_IRQ_BUCK3_SC,
+	TPS6594_IRQ_BUCK3_ILIM,
+	TPS6594_IRQ_BUCK4_OV,
+	TPS6594_IRQ_BUCK4_UV,
+	TPS6594_IRQ_BUCK4_SC,
+	TPS6594_IRQ_BUCK4_ILIM,
+	/* INT_BUCK5 register */
+	TPS6594_IRQ_BUCK5_OV,
+	TPS6594_IRQ_BUCK5_UV,
+	TPS6594_IRQ_BUCK5_SC,
+	TPS6594_IRQ_BUCK5_ILIM,
+	/* INT_LDO1_2 register */
+	TPS6594_IRQ_LDO1_OV,
+	TPS6594_IRQ_LDO1_UV,
+	TPS6594_IRQ_LDO1_SC,
+	TPS6594_IRQ_LDO1_ILIM,
+	TPS6594_IRQ_LDO2_OV,
+	TPS6594_IRQ_LDO2_UV,
+	TPS6594_IRQ_LDO2_SC,
+	TPS6594_IRQ_LDO2_ILIM,
+	/* INT_LDO3_4 register */
+	TPS6594_IRQ_LDO3_OV,
+	TPS6594_IRQ_LDO3_UV,
+	TPS6594_IRQ_LDO3_SC,
+	TPS6594_IRQ_LDO3_ILIM,
+	TPS6594_IRQ_LDO4_OV,
+	TPS6594_IRQ_LDO4_UV,
+	TPS6594_IRQ_LDO4_SC,
+	TPS6594_IRQ_LDO4_ILIM,
+	/* INT_VMON register */
+	TPS6594_IRQ_VCCA_OV,
+	TPS6594_IRQ_VCCA_UV,
+	TPS6594_IRQ_VMON1_OV,
+	TPS6594_IRQ_VMON1_UV,
+	TPS6594_IRQ_VMON1_RV,
+	TPS6594_IRQ_VMON2_OV,
+	TPS6594_IRQ_VMON2_UV,
+	TPS6594_IRQ_VMON2_RV,
+	/* INT_GPIO register */
+	TPS6594_IRQ_GPIO9,
+	TPS6594_IRQ_GPIO10,
+	TPS6594_IRQ_GPIO11,
+	/* INT_GPIO1_8 register */
+	TPS6594_IRQ_GPIO1,
+	TPS6594_IRQ_GPIO2,
+	TPS6594_IRQ_GPIO3,
+	TPS6594_IRQ_GPIO4,
+	TPS6594_IRQ_GPIO5,
+	TPS6594_IRQ_GPIO6,
+	TPS6594_IRQ_GPIO7,
+	TPS6594_IRQ_GPIO8,
+	/* INT_STARTUP register */
+	TPS6594_IRQ_NPWRON_START,
+	TPS6594_IRQ_ENABLE,
+	TPS6594_IRQ_FSD,
+	TPS6594_IRQ_SOFT_REBOOT,
+	/* INT_MISC register */
+	TPS6594_IRQ_BIST_PASS,
+	TPS6594_IRQ_EXT_CLK,
+	TPS6594_IRQ_TWARN,
+	/* INT_MODERATE_ERR register */
+	TPS6594_IRQ_TSD_ORD,
+	TPS6594_IRQ_BIST_FAIL,
+	TPS6594_IRQ_REG_CRC_ERR,
+	TPS6594_IRQ_RECOV_CNT,
+	TPS6594_IRQ_SPMI_ERR,
+	TPS6594_IRQ_NPWRON_LONG,
+	TPS6594_IRQ_NINT_READBACK,
+	TPS6594_IRQ_NRSTOUT_READBACK,
+	/* INT_SEVERE_ERR register */
+	TPS6594_IRQ_TSD_IMM,
+	TPS6594_IRQ_VCCA_OVP,
+	TPS6594_IRQ_PFSM_ERR,
+	/* INT_FSM_ERR register */
+	TPS6594_IRQ_IMM_SHUTDOWN,
+	TPS6594_IRQ_ORD_SHUTDOWN,
+	TPS6594_IRQ_MCU_PWR_ERR,
+	TPS6594_IRQ_SOC_PWR_ERR,
+	/* INT_COMM_ERR register */
+	TPS6594_IRQ_COMM_FRM_ERR,
+	TPS6594_IRQ_COMM_CRC_ERR,
+	TPS6594_IRQ_COMM_ADR_ERR,
+	TPS6594_IRQ_I2C2_CRC_ERR,
+	TPS6594_IRQ_I2C2_ADR_ERR,
+	/* INT_READBACK_ERR register */
+	TPS6594_IRQ_EN_DRV_READBACK,
+	TPS6594_IRQ_NRSTOUT_SOC_READBACK,
+	/* INT_ESM register */
+	TPS6594_IRQ_ESM_SOC_PIN,
+	TPS6594_IRQ_ESM_SOC_FAIL,
+	TPS6594_IRQ_ESM_SOC_RST,
+	/* RTC_STATUS register */
+	TPS6594_IRQ_TIMER,
+	TPS6594_IRQ_ALARM,
+	TPS6594_IRQ_POWER_UP,
+};
+
+#define TPS6594_IRQ_NAME_BUCK1_OV		"buck1_ov"
+#define TPS6594_IRQ_NAME_BUCK1_UV		"buck1_uv"
+#define TPS6594_IRQ_NAME_BUCK1_SC		"buck1_sc"
+#define TPS6594_IRQ_NAME_BUCK1_ILIM		"buck1_ilim"
+#define TPS6594_IRQ_NAME_BUCK2_OV		"buck2_ov"
+#define TPS6594_IRQ_NAME_BUCK2_UV		"buck2_uv"
+#define TPS6594_IRQ_NAME_BUCK2_SC		"buck2_sc"
+#define TPS6594_IRQ_NAME_BUCK2_ILIM		"buck2_ilim"
+#define TPS6594_IRQ_NAME_BUCK3_OV		"buck3_ov"
+#define TPS6594_IRQ_NAME_BUCK3_UV		"buck3_uv"
+#define TPS6594_IRQ_NAME_BUCK3_SC		"buck3_sc"
+#define TPS6594_IRQ_NAME_BUCK3_ILIM		"buck3_ilim"
+#define TPS6594_IRQ_NAME_BUCK4_OV		"buck4_ov"
+#define TPS6594_IRQ_NAME_BUCK4_UV		"buck4_uv"
+#define TPS6594_IRQ_NAME_BUCK4_SC		"buck4_sc"
+#define TPS6594_IRQ_NAME_BUCK4_ILIM		"buck4_ilim"
+#define TPS6594_IRQ_NAME_BUCK5_OV		"buck5_ov"
+#define TPS6594_IRQ_NAME_BUCK5_UV		"buck5_uv"
+#define TPS6594_IRQ_NAME_BUCK5_SC		"buck5_sc"
+#define TPS6594_IRQ_NAME_BUCK5_ILIM		"buck5_ilim"
+#define TPS6594_IRQ_NAME_LDO1_OV		"ldo1_ov"
+#define TPS6594_IRQ_NAME_LDO1_UV		"ldo1_uv"
+#define TPS6594_IRQ_NAME_LDO1_SC		"ldo1_sc"
+#define TPS6594_IRQ_NAME_LDO1_ILIM		"ldo1_ilim"
+#define TPS6594_IRQ_NAME_LDO2_OV		"ldo2_ov"
+#define TPS6594_IRQ_NAME_LDO2_UV		"ldo2_uv"
+#define TPS6594_IRQ_NAME_LDO2_SC		"ldo2_sc"
+#define TPS6594_IRQ_NAME_LDO2_ILIM		"ldo2_ilim"
+#define TPS6594_IRQ_NAME_LDO3_OV		"ldo3_ov"
+#define TPS6594_IRQ_NAME_LDO3_UV		"ldo3_uv"
+#define TPS6594_IRQ_NAME_LDO3_SC		"ldo3_sc"
+#define TPS6594_IRQ_NAME_LDO3_ILIM		"ldo3_ilim"
+#define TPS6594_IRQ_NAME_LDO4_OV		"ldo4_ov"
+#define TPS6594_IRQ_NAME_LDO4_UV		"ldo4_uv"
+#define TPS6594_IRQ_NAME_LDO4_SC		"ldo4_sc"
+#define TPS6594_IRQ_NAME_LDO4_ILIM		"ldo4_ilim"
+#define TPS6594_IRQ_NAME_VCCA_OV		"vcca_ov"
+#define TPS6594_IRQ_NAME_VCCA_UV		"vcca_uv"
+#define TPS6594_IRQ_NAME_VMON1_OV		"vmon1_ov"
+#define TPS6594_IRQ_NAME_VMON1_UV		"vmon1_uv"
+#define TPS6594_IRQ_NAME_VMON1_RV		"vmon1_rv"
+#define TPS6594_IRQ_NAME_VMON2_OV		"vmon2_ov"
+#define TPS6594_IRQ_NAME_VMON2_UV		"vmon2_uv"
+#define TPS6594_IRQ_NAME_VMON2_RV		"vmon2_rv"
+#define TPS6594_IRQ_NAME_GPIO9			"gpio9"
+#define TPS6594_IRQ_NAME_GPIO10			"gpio10"
+#define TPS6594_IRQ_NAME_GPIO11			"gpio11"
+#define TPS6594_IRQ_NAME_GPIO1			"gpio1"
+#define TPS6594_IRQ_NAME_GPIO2			"gpio2"
+#define TPS6594_IRQ_NAME_GPIO3			"gpio3"
+#define TPS6594_IRQ_NAME_GPIO4			"gpio4"
+#define TPS6594_IRQ_NAME_GPIO5			"gpio5"
+#define TPS6594_IRQ_NAME_GPIO6			"gpio6"
+#define TPS6594_IRQ_NAME_GPIO7			"gpio7"
+#define TPS6594_IRQ_NAME_GPIO8			"gpio8"
+#define TPS6594_IRQ_NAME_NPWRON_START		"npwron_start"
+#define TPS6594_IRQ_NAME_ENABLE			"enable"
+#define TPS6594_IRQ_NAME_FSD			"fsd"
+#define TPS6594_IRQ_NAME_SOFT_REBOOT		"soft_reboot"
+#define TPS6594_IRQ_NAME_BIST_PASS		"bist_pass"
+#define TPS6594_IRQ_NAME_EXT_CLK		"ext_clk"
+#define TPS6594_IRQ_NAME_TWARN			"twarn"
+#define TPS6594_IRQ_NAME_TSD_ORD		"tsd_ord"
+#define TPS6594_IRQ_NAME_BIST_FAIL		"bist_fail"
+#define TPS6594_IRQ_NAME_REG_CRC_ERR		"reg_crc_err"
+#define TPS6594_IRQ_NAME_RECOV_CNT		"recov_cnt"
+#define TPS6594_IRQ_NAME_SPMI_ERR		"spmi_err"
+#define TPS6594_IRQ_NAME_NPWRON_LONG		"npwron_long"
+#define TPS6594_IRQ_NAME_NINT_READBACK		"nint_readback"
+#define TPS6594_IRQ_NAME_NRSTOUT_READBACK	"nrstout_readback"
+#define TPS6594_IRQ_NAME_TSD_IMM		"tsd_imm"
+#define TPS6594_IRQ_NAME_VCCA_OVP		"vcca_ovp"
+#define TPS6594_IRQ_NAME_PFSM_ERR		"pfsm_err"
+#define TPS6594_IRQ_NAME_IMM_SHUTDOWN		"imm_shutdown"
+#define TPS6594_IRQ_NAME_ORD_SHUTDOWN		"ord_shutdown"
+#define TPS6594_IRQ_NAME_MCU_PWR_ERR		"mcu_pwr_err"
+#define TPS6594_IRQ_NAME_SOC_PWR_ERR		"soc_pwr_err"
+#define TPS6594_IRQ_NAME_COMM_FRM_ERR		"comm_frm_err"
+#define TPS6594_IRQ_NAME_COMM_CRC_ERR		"comm_crc_err"
+#define TPS6594_IRQ_NAME_COMM_ADR_ERR		"comm_adr_err"
+#define TPS6594_IRQ_NAME_EN_DRV_READBACK	"en_drv_readback"
+#define TPS6594_IRQ_NAME_NRSTOUT_SOC_READBACK	"nrstout_soc_readback"
+#define TPS6594_IRQ_NAME_ESM_SOC_PIN		"esm_soc_pin"
+#define TPS6594_IRQ_NAME_ESM_SOC_FAIL		"esm_soc_fail"
+#define TPS6594_IRQ_NAME_ESM_SOC_RST		"esm_soc_rst"
+#define TPS6594_IRQ_NAME_TIMER			"timer"
+#define TPS6594_IRQ_NAME_ALARM			"alarm"
+#define TPS6594_IRQ_NAME_POWERUP		"powerup"
+
+/**
+ * struct tps6594 - device private data structure
+ *
+ * @dev:      MFD parent device
+ * @chip_id:  chip ID
+ * @reg:      I2C slave address or SPI chip select number
+ * @use_crc:  if true, use CRC for I2C and SPI interface protocols
+ * @regmap:   regmap for accessing the device registers
+ * @irq:      irq generated by the device
+ * @irq_data: regmap irq data used for the irq chip
+ */
+struct tps6594 {
+	struct device *dev;
+	unsigned long chip_id;
+	unsigned short reg;
+	bool use_crc;
+	struct regmap *regmap;
+	int irq;
+	struct regmap_irq_chip_data *irq_data;
+};
+
+bool tps6594_is_volatile_reg(struct device *dev, unsigned int reg);
+int tps6594_device_init(struct tps6594 *tps, bool enable_crc);
+
+#endif /*  __LINUX_MFD_TPS6594_H */
diff -Naur --no-dereference a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
--- a/include/linux/mtd/spinand.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/mtd/spinand.h	2024-01-28 14:01:31.256353824 -0500
@@ -26,12 +26,24 @@
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_NO_DATA)
 
+#define SPINAND_RESET_OP_OCTAL_DTR					\
+	SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, 0xffff, 8),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
 #define SPINAND_WR_EN_DIS_OP(enable)					\
 	SPI_MEM_OP(SPI_MEM_OP_CMD((enable) ? 0x06 : 0x04, 1),		\
 		   SPI_MEM_OP_NO_ADDR,					\
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_NO_DATA)
 
+#define SPINAND_WR_EN_DIS_OP_OCTAL_DTR(enable)				\
+	SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, (enable) ? 0x0606 : 0x0404, 8),\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
 #define SPINAND_READID_OP(naddr, ndummy, buf, len)			\
 	SPI_MEM_OP(SPI_MEM_OP_CMD(0x9f, 1),				\
 		   SPI_MEM_OP_ADDR(naddr, 0, 1),			\
@@ -44,24 +56,48 @@
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_DATA_OUT(1, valptr, 1))
 
+#define SPINAND_SET_FEATURE_OP_OCTAL_DTR(reg, valptr)			\
+	SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, 0x1f1f, 8),			\
+		   SPI_MEM_OP_ADDR_DTR(2, reg, 8),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT_DTR(2, valptr, 8))
+
 #define SPINAND_GET_FEATURE_OP(reg, valptr)				\
 	SPI_MEM_OP(SPI_MEM_OP_CMD(0x0f, 1),				\
 		   SPI_MEM_OP_ADDR(1, reg, 1),				\
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_DATA_IN(1, valptr, 1))
 
+#define SPINAND_GET_FEATURE_OP_OCTAL_DTR(reg, valptr)			\
+	SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, 0x0f0f, 8),			\
+		   SPI_MEM_OP_ADDR_DTR(2, reg, 8),			\
+		   SPI_MEM_OP_DUMMY_DTR(14, 8),				\
+		   SPI_MEM_OP_DATA_IN_DTR(2, valptr, 8))
+
 #define SPINAND_BLK_ERASE_OP(addr)					\
 	SPI_MEM_OP(SPI_MEM_OP_CMD(0xd8, 1),				\
 		   SPI_MEM_OP_ADDR(3, addr, 1),				\
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_NO_DATA)
 
+#define SPINAND_BLK_ERASE_OP_OCTAL_DTR(addr)				\
+	SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, 0xd8d8, 8),			\
+		   SPI_MEM_OP_ADDR_DTR(2, addr, 8),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
 #define SPINAND_PAGE_READ_OP(addr)					\
 	SPI_MEM_OP(SPI_MEM_OP_CMD(0x13, 1),				\
 		   SPI_MEM_OP_ADDR(3, addr, 1),				\
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_NO_DATA)
 
+#define SPINAND_PAGE_READ_OP_OCTAL_DTR(addr)				\
+	SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, 0x1313, 8),			\
+		   SPI_MEM_OP_ADDR_DTR(2, addr, 8),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
 #define SPINAND_PAGE_READ_FROM_CACHE_OP(fast, addr, ndummy, buf, len)	\
 	SPI_MEM_OP(SPI_MEM_OP_CMD(fast ? 0x0b : 0x03, 1),		\
 		   SPI_MEM_OP_ADDR(2, addr, 1),				\
@@ -122,12 +158,24 @@
 		   SPI_MEM_OP_DUMMY(ndummy, 4),				\
 		   SPI_MEM_OP_DATA_IN(len, buf, 4))
 
+#define SPINAND_PAGE_READ_FROM_CACHE_OCTALIO_DTR_OP(addr, ndummy, buf, len) \
+	SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, 0x9d9d, 8),			\
+		   SPI_MEM_OP_ADDR_DTR(2, addr, 8),			\
+		   SPI_MEM_OP_DUMMY_DTR(ndummy, 8),			\
+		   SPI_MEM_OP_DATA_IN_DTR(len, buf, 8))
+
 #define SPINAND_PROG_EXEC_OP(addr)					\
 	SPI_MEM_OP(SPI_MEM_OP_CMD(0x10, 1),				\
 		   SPI_MEM_OP_ADDR(3, addr, 1),				\
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_NO_DATA)
 
+#define SPINAND_PROG_EXEC_OP_OCTAL_DTR(addr)				\
+	SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, 0x1010, 8),			\
+		   SPI_MEM_OP_ADDR_DTR(2, addr, 8),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
 #define SPINAND_PROG_LOAD(reset, addr, buf, len)			\
 	SPI_MEM_OP(SPI_MEM_OP_CMD(reset ? 0x02 : 0x84, 1),		\
 		   SPI_MEM_OP_ADDR(2, addr, 1),				\
@@ -140,6 +188,24 @@
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_DATA_OUT(len, buf, 4))
 
+#define SPINAND_PROG_LOAD_OCTALIO_DTR(reset, addr, buf, len)		\
+	SPI_MEM_OP(SPI_MEM_OP_CMD_DTR(2, reset ? 0x0202 : 0x8484, 8),	\
+		   SPI_MEM_OP_ADDR_DTR(2, addr, 8),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT_DTR(len, buf, 8))
+
+/**
+ * enum spinand_protocol - List of SPI protocols to denote the op protocol and
+ *			   SPI NAND flash IO modes.
+ */
+enum spinand_protocol {
+	SPINAND_1S_1S_1S,
+	SPINAND_2S_2S_2S,
+	SPINAND_4S_4S_4S,
+	SPINAND_8S_8S_8S,
+	SPINAND_8D_8D_8D,
+};
+
 /**
  * Standard SPI NAND flash commands
  */
@@ -232,6 +298,7 @@
 /**
  * struct manufacurer_ops - SPI NAND manufacturer specific operations
  * @init: initialize a SPI NAND device
+ * @change_mode: switch the SPI NAND flash to a specific SPI protocol
  * @cleanup: cleanup a SPI NAND device
  *
  * Each SPI NAND manufacturer driver should implement this interface so that
@@ -239,6 +306,8 @@
  */
 struct spinand_manufacturer_ops {
 	int (*init)(struct spinand_device *spinand);
+	int (*change_mode)(struct spinand_device *spinand,
+			   const enum spinand_protocol protocol);
 	void (*cleanup)(struct spinand_device *spinand);
 };
 
@@ -292,6 +361,47 @@
 			sizeof(struct spi_mem_op),			\
 	}
 
+struct spinand_ctrl_ops {
+	const struct {
+		struct spi_mem_op reset;
+		struct spi_mem_op get_feature;
+		struct spi_mem_op set_feature;
+		struct spi_mem_op write_enable;
+		struct spi_mem_op block_erase;
+		struct spi_mem_op page_read;
+		struct spi_mem_op program_execute;
+	} ops;
+	const enum spinand_protocol protocol;
+};
+
+#define SPINAND_CTRL_OPS(__protocol, __reset, __get_feature, __set_feature,	\
+			 __write_enable, __block_erase, __page_read,		\
+			 __program_execute)					\
+	{									\
+		.ops = {							\
+			.reset = __reset,					\
+			.get_feature = __get_feature,				\
+			.set_feature = __set_feature,				\
+			.write_enable = __write_enable,				\
+			.block_erase = __block_erase,				\
+			.page_read = __page_read,				\
+			.program_execute = __program_execute,			\
+		},								\
+		.protocol = __protocol,						\
+	}
+
+struct spinand_ctrl_ops_variants {
+	const struct spinand_ctrl_ops *ctrl_ops_list;
+	unsigned int nvariants;
+};
+
+#define SPINAND_CTRL_OPS_VARIANTS(name, ...)					\
+	const struct spinand_ctrl_ops_variants name = {				\
+		.ctrl_ops_list = (struct spinand_ctrl_ops[]){ __VA_ARGS__ },	\
+		.nvariants = sizeof((struct spinand_ctrl_ops[]){ __VA_ARGS__ })/\
+			     sizeof(struct spinand_ctrl_ops),			\
+	}
+
 /**
  * spinand_ecc_info - description of the on-die ECC implemented by a SPI NAND
  *		      chip
@@ -309,6 +419,7 @@
 
 #define SPINAND_HAS_QE_BIT		BIT(0)
 #define SPINAND_HAS_CR_FEAT_BIT		BIT(1)
+#define SPINAND_HAS_OCTAL_DTR_BIT	BIT(2)
 
 /**
  * struct spinand_ondie_ecc_conf - private SPI-NAND on-die ECC engine structure
@@ -327,10 +438,10 @@
  * @memorg: memory organization
  * @eccreq: ECC requirements
  * @eccinfo: on-die ECC info
- * @op_variants: operations variants
- * @op_variants.read_cache: variants of the read-cache operation
- * @op_variants.write_cache: variants of the write-cache operation
- * @op_variants.update_cache: variants of the update-cache operation
+ * @data_ops_variants: operations variants for page read/writes
+ * @data_ops_variants.read_cache: variants of the read-cache operation
+ * @data_ops_variants.write_cache: variants of the write-cache operation
+ * @data_ops_variants.update_cache: variants of the update-cache operation
  * @select_target: function used to select a target/die. Required only for
  *		   multi-die chips
  *
@@ -348,7 +459,9 @@
 		const struct spinand_op_variants *read_cache;
 		const struct spinand_op_variants *write_cache;
 		const struct spinand_op_variants *update_cache;
-	} op_variants;
+	} data_ops_variants;
+
+	const struct spinand_ctrl_ops_variants *ctrl_ops_variants;
 	int (*select_target)(struct spinand_device *spinand,
 			     unsigned int target);
 };
@@ -367,6 +480,9 @@
 		.update_cache = __update,				\
 	}
 
+#define SPINAND_INFO_CTRL_OPS_VARIANTS(__ctrl_ops_variants)		\
+	.ctrl_ops_variants = __ctrl_ops_variants
+
 #define SPINAND_ECCINFO(__ooblayout, __get_status)			\
 	.eccinfo = {							\
 		.ooblayout = __ooblayout,				\
@@ -376,14 +492,14 @@
 #define SPINAND_SELECT_TARGET(__func)					\
 	.select_target = __func,
 
-#define SPINAND_INFO(__model, __id, __memorg, __eccreq, __op_variants,	\
-		     __flags, ...)					\
+#define SPINAND_INFO(__model, __id, __memorg, __eccreq,			\
+		     __data_ops_variants, __flags, ...)			\
 	{								\
 		.model = __model,					\
 		.devid = __id,						\
 		.memorg = __memorg,					\
 		.eccreq = __eccreq,					\
-		.op_variants = __op_variants,				\
+		.data_ops_variants = __data_ops_variants,		\
 		.flags = __flags,					\
 		__VA_ARGS__						\
 	}
@@ -402,15 +518,19 @@
  * @lock: lock used to serialize accesses to the NAND
  * @id: NAND ID as returned by READ_ID
  * @flags: NAND flags
- * @op_templates: various SPI mem op templates
- * @op_templates.read_cache: read cache op template
- * @op_templates.write_cache: write cache op template
- * @op_templates.update_cache: update cache op template
+ * @data_ops: various SPI mem op templates for reading and writing on pages
+ * @data_ops.read_cache: read cache op template
+ * @data_ops.write_cache: write cache op template
+ * @data_ops.update_cache: update cache op template
+ * @ctrl_ops: various SPI mem op templates for handling the flash device, i.e.
+ *	      non page-read/write ops.
  * @select_target: select a specific target/die. Usually called before sending
  *		   a command addressing a page or an eraseblock embedded in
  *		   this die. Only required if your chip exposes several dies
  * @cur_target: currently selected target/die
  * @eccinfo: on-die ECC information
+ * @protocol: SPI IO protocol in operation. Update on successful transition into
+ *	      a different SPI IO protocol.
  * @cfg_cache: config register cache. One entry per die
  * @databuf: bounce buffer for data
  * @oobbuf: bounce buffer for OOB data
@@ -419,6 +539,8 @@
  *		passed in spi_mem_op be DMA-able, so we can't based the bufs on
  *		the stack
  * @manufacturer: SPI NAND manufacturer information
+ * @desc_entry: pointer to device description entry in the manufacturer's
+ *		spinand_info tables
  * @priv: manufacturer private data
  */
 struct spinand_device {
@@ -432,7 +554,9 @@
 		const struct spi_mem_op *read_cache;
 		const struct spi_mem_op *write_cache;
 		const struct spi_mem_op *update_cache;
-	} op_templates;
+	} data_ops;
+
+	const struct spinand_ctrl_ops *ctrl_ops;
 
 	struct spinand_dirmap *dirmaps;
 
@@ -442,11 +566,14 @@
 
 	struct spinand_ecc_info eccinfo;
 
+	enum spinand_protocol protocol;
+
 	u8 *cfg_cache;
 	u8 *databuf;
 	u8 *oobbuf;
 	u8 *scratchbuf;
 	const struct spinand_manufacturer *manufacturer;
+	const struct spinand_info *desc_entry;
 	void *priv;
 };
 
@@ -515,5 +642,6 @@
 
 int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val);
 int spinand_select_target(struct spinand_device *spinand, unsigned int target);
+int spinand_write_enable_op(struct spinand_device *spinand);
 
 #endif /* __LINUX_MTD_SPINAND_H */
diff -Naur --no-dereference a/include/linux/phy/phy.h b/include/linux/phy/phy.h
--- a/include/linux/phy/phy.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/phy/phy.h	2024-01-28 14:01:31.256353824 -0500
@@ -250,11 +250,12 @@
 	phy->attrs.bus_width = bus_width;
 }
 struct phy *phy_get(struct device *dev, const char *string);
-struct phy *phy_optional_get(struct device *dev, const char *string);
 struct phy *devm_phy_get(struct device *dev, const char *string);
 struct phy *devm_phy_optional_get(struct device *dev, const char *string);
 struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
 			    const char *con_id);
+struct phy *devm_of_phy_optional_get(struct device *dev, struct device_node *np,
+				     const char *con_id);
 struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np,
 				     int index);
 void of_phy_put(struct phy *phy);
@@ -426,12 +427,6 @@
 	return ERR_PTR(-ENOSYS);
 }
 
-static inline struct phy *phy_optional_get(struct device *dev,
-					   const char *string)
-{
-	return ERR_PTR(-ENOSYS);
-}
-
 static inline struct phy *devm_phy_get(struct device *dev, const char *string)
 {
 	return ERR_PTR(-ENOSYS);
@@ -450,6 +445,13 @@
 	return ERR_PTR(-ENOSYS);
 }
 
+static inline struct phy *devm_of_phy_optional_get(struct device *dev,
+						   struct device_node *np,
+						   const char *con_id)
+{
+	return NULL;
+}
+
 static inline struct phy *devm_of_phy_get_by_index(struct device *dev,
 						   struct device_node *np,
 						   int index)
diff -Naur --no-dereference a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h
--- a/include/linux/phy/phy-mipi-dphy.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/phy/phy-mipi-dphy.h	2024-01-28 14:01:31.256353824 -0500
@@ -279,6 +279,9 @@
 				     unsigned int bpp,
 				     unsigned int lanes,
 				     struct phy_configure_opts_mipi_dphy *cfg);
+int phy_mipi_dphy_get_default_config_for_hsclk(unsigned long long hs_clk_rate,
+					       unsigned int lanes,
+					       struct phy_configure_opts_mipi_dphy *cfg);
 int phy_mipi_dphy_config_validate(struct phy_configure_opts_mipi_dphy *cfg);
 
 #endif /* __PHY_MIPI_DPHY_H_ */
diff -Naur --no-dereference a/include/linux/pruss_driver.h b/include/linux/pruss_driver.h
--- a/include/linux/pruss_driver.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/pruss_driver.h	2024-01-28 14:01:31.256353824 -0500
@@ -9,7 +9,55 @@
 #ifndef _PRUSS_DRIVER_H_
 #define _PRUSS_DRIVER_H_
 
+#include <linux/mutex.h>
+#include <linux/remoteproc/pruss.h>
 #include <linux/types.h>
+#include <linux/err.h>
+
+/*
+ * enum pruss_gp_mux_sel - PRUSS GPI/O Mux modes for the
+ * PRUSS_GPCFG0/1 registers
+ *
+ * NOTE: The below defines are the most common values, but there
+ * are some exceptions like on 66AK2G, where the RESERVED and MII2
+ * values are interchanged. Also, this bit-field does not exist on
+ * AM335x SoCs
+ */
+enum pruss_gp_mux_sel {
+	PRUSS_GP_MUX_SEL_GP,
+	PRUSS_GP_MUX_SEL_ENDAT,
+	PRUSS_GP_MUX_SEL_RESERVED,
+	PRUSS_GP_MUX_SEL_SD,
+	PRUSS_GP_MUX_SEL_MII2,
+	PRUSS_GP_MUX_SEL_MAX,
+};
+
+/*
+ * enum pruss_gpi_mode - PRUSS GPI configuration modes, used
+ *			 to program the PRUSS_GPCFG0/1 registers
+ */
+enum pruss_gpi_mode {
+	PRUSS_GPI_MODE_DIRECT,
+	PRUSS_GPI_MODE_PARALLEL,
+	PRUSS_GPI_MODE_28BIT_SHIFT,
+	PRUSS_GPI_MODE_MII,
+	PRUSS_GPI_MODE_MAX,
+};
+
+/**
+ * enum pru_type - PRU core type identifier
+ *
+ * @PRU_TYPE_PRU: Programmable Real-time Unit
+ * @PRU_TYPE_RTU: Auxiliary Programmable Real-Time Unit
+ * @PRU_TYPE_TX_PRU: Transmit Programmable Real-Time Unit
+ * @PRU_TYPE_MAX: just keep this one at the end
+ */
+enum pru_type {
+	PRU_TYPE_PRU,
+	PRU_TYPE_RTU,
+	PRU_TYPE_TX_PRU,
+	PRU_TYPE_MAX,
+};
 
 /*
  * enum pruss_mem - PRUSS memory range identifiers
@@ -39,6 +87,8 @@
  * @cfg_base: base iomap for CFG region
  * @cfg_regmap: regmap for config region
  * @mem_regions: data for each of the PRUSS memory regions
+ * @mem_in_use: to indicate if memory resource is in use
+ * @lock: mutex to serialize access to resources
  * @core_clk_mux: clk handle for PRUSS CORE_CLK_MUX
  * @iep_clk_mux: clk handle for PRUSS IEP_CLK_MUX
  */
@@ -47,8 +97,81 @@
 	void __iomem *cfg_base;
 	struct regmap *cfg_regmap;
 	struct pruss_mem_region mem_regions[PRUSS_MEM_MAX];
+	struct pruss_mem_region *mem_in_use[PRUSS_MEM_MAX];
+	struct mutex lock; /* PRU resource lock */
 	struct clk *core_clk_mux;
 	struct clk *iep_clk_mux;
 };
 
+#if IS_ENABLED(CONFIG_TI_PRUSS)
+
+struct pruss *pruss_get(struct rproc *rproc);
+void pruss_put(struct pruss *pruss);
+int pruss_request_mem_region(struct pruss *pruss, enum pruss_mem mem_id,
+			     struct pruss_mem_region *region);
+int pruss_release_mem_region(struct pruss *pruss,
+			     struct pruss_mem_region *region);
+int pruss_cfg_get_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 *mux);
+int pruss_cfg_set_gpmux(struct pruss *pruss, enum pruss_pru_id pru_id, u8 mux);
+int pruss_cfg_gpimode(struct pruss *pruss, enum pruss_pru_id pru_id,
+		      enum pruss_gpi_mode mode);
+int pruss_cfg_miirt_enable(struct pruss *pruss, bool enable);
+int pruss_cfg_xfr_enable(struct pruss *pruss, enum pru_type pru_type,
+			 bool enable);
+
+#else
+
+static inline struct pruss *pruss_get(struct rproc *rproc)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void pruss_put(struct pruss *pruss) { }
+
+static inline int pruss_request_mem_region(struct pruss *pruss,
+					   enum pruss_mem mem_id,
+					   struct pruss_mem_region *region)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int pruss_release_mem_region(struct pruss *pruss,
+					   struct pruss_mem_region *region)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int pruss_cfg_get_gpmux(struct pruss *pruss,
+				      enum pruss_pru_id pru_id, u8 *mux)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline int pruss_cfg_set_gpmux(struct pruss *pruss,
+				      enum pruss_pru_id pru_id, u8 mux)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline int pruss_cfg_gpimode(struct pruss *pruss,
+				    enum pruss_pru_id pru_id,
+				    enum pruss_gpi_mode mode)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline int pruss_cfg_miirt_enable(struct pruss *pruss, bool enable)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline int pruss_cfg_xfr_enable(struct pruss *pruss,
+				       enum pru_type pru_type,
+				       bool enable);
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+#endif /* CONFIG_TI_PRUSS */
+
 #endif	/* _PRUSS_DRIVER_H_ */
diff -Naur --no-dereference a/include/linux/reboot.h b/include/linux/reboot.h
--- a/include/linux/reboot.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/reboot.h	2024-01-28 14:01:31.256353824 -0500
@@ -129,11 +129,14 @@
  * @cb_data: User's callback data.
  * @cmd: Command string. Currently used only by the sys-off restart mode,
  *       NULL otherwise.
+ * @dev: Device of the sys-off handler. Only if known (devm_register_*),
+ *       NULL otherwise.
  */
 struct sys_off_data {
 	int mode;
 	void *cb_data;
 	const char *cmd;
+	struct device *dev;
 };
 
 struct sys_off_handler *
diff -Naur --no-dereference a/include/linux/remoteproc/pruss.h b/include/linux/remoteproc/pruss.h
--- a/include/linux/remoteproc/pruss.h	1969-12-31 19:00:00.000000000 -0500
+++ b/include/linux/remoteproc/pruss.h	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * PRU-ICSS Subsystem user interfaces
+ *
+ * Copyright (C) 2015-2022 Texas Instruments Incorporated - http://www.ti.com
+ *	Suman Anna <s-anna@ti.com>
+ */
+
+#ifndef __LINUX_PRUSS_H
+#define __LINUX_PRUSS_H
+
+#include <linux/device.h>
+#include <linux/types.h>
+
+#define PRU_RPROC_DRVNAME "pru-rproc"
+
+/**
+ * enum pruss_pru_id - PRU core identifiers
+ * @PRUSS_PRU0: PRU Core 0.
+ * @PRUSS_PRU1: PRU Core 1.
+ * @PRUSS_NUM_PRUS: Total number of PRU Cores available.
+ *
+ */
+
+enum pruss_pru_id {
+	PRUSS_PRU0 = 0,
+	PRUSS_PRU1,
+	PRUSS_NUM_PRUS,
+};
+
+/*
+ * enum pru_ctable_idx - Configurable Constant table index identifiers
+ */
+enum pru_ctable_idx {
+	PRU_C24 = 0,
+	PRU_C25,
+	PRU_C26,
+	PRU_C27,
+	PRU_C28,
+	PRU_C29,
+	PRU_C30,
+	PRU_C31,
+};
+
+struct device_node;
+struct rproc;
+
+#if IS_ENABLED(CONFIG_PRU_REMOTEPROC)
+
+struct rproc *pru_rproc_get(struct device_node *np, int index,
+			    enum pruss_pru_id *pru_id);
+void pru_rproc_put(struct rproc *rproc);
+int pru_rproc_set_ctable(struct rproc *rproc, enum pru_ctable_idx c, u32 addr);
+
+#else
+
+static inline struct rproc *
+pru_rproc_get(struct device_node *np, int index, enum pruss_pru_id *pru_id)
+{
+	return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void pru_rproc_put(struct rproc *rproc) { }
+
+static inline int pru_rproc_set_ctable(struct rproc *rproc,
+				       enum pru_ctable_idx c, u32 addr)
+{
+	return -EOPNOTSUPP;
+}
+
+#endif /* CONFIG_PRU_REMOTEPROC */
+
+static inline bool is_pru_rproc(struct device *dev)
+{
+	const char *drv_name = dev_driver_string(dev);
+
+	if (strncmp(drv_name, PRU_RPROC_DRVNAME, sizeof(PRU_RPROC_DRVNAME)))
+		return false;
+
+	return true;
+}
+
+#endif /* __LINUX_PRUSS_H */
diff -Naur --no-dereference a/include/linux/rpmsg-remotedev/rpmsg-remotedev.h b/include/linux/rpmsg-remotedev/rpmsg-remotedev.h
--- a/include/linux/rpmsg-remotedev/rpmsg-remotedev.h	1969-12-31 19:00:00.000000000 -0500
+++ b/include/linux/rpmsg-remotedev/rpmsg-remotedev.h	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
+ * Author: Subhajit Paul <subhajit_paul@ti.com>
+ */
+
+#ifndef __RPMSG_REMOTEDEV_H__
+#define __RPMSG_REMOTEDEV_H__
+
+#include <linux/etherdevice.h>
+
+struct rpmsg_remotedev;
+
+/* Defines for demo device */
+#define REMOTEDEV_DEMO_MSG_LEN		(128)
+
+/* Defines for display device */
+#define RPMSG_REMOTEDEV_DISPLAY_MAX_PLANES		(3)
+#define RPMSG_REMOTEDEV_DISPLAY_MAX_DISPS		(8)
+#define RPMSG_REMOTEDEV_DISPLAY_MAX_PIPES		(8)
+#define RPMSG_REMOTEDEV_DISPLAY_MAX_FORMATS		(32)
+#define RPMSG_REMOTEDEV_DISPLAY_MAX_ZORDERS		(8)
+
+/* Struct definitions for display device */
+struct rpmsg_remotedev_display_buffer {
+	u32 width;
+	u32 height;
+	u32 format;
+	u32 num_planes;
+	dma_addr_t planes[RPMSG_REMOTEDEV_DISPLAY_MAX_PLANES];
+	u32 pitches[RPMSG_REMOTEDEV_DISPLAY_MAX_PLANES];
+	struct rpmsg_remotedev *rdev;
+	void *priv;
+};
+
+struct rpmsg_remotedev_display_pipe_update {
+	u32 pipe_id;
+	bool enabled;
+	u32 dst_w;
+	u32 dst_h;
+	u32 dst_x;
+	u32 dst_y;
+	struct rpmsg_remotedev_display_buffer *buffer;
+};
+
+struct rpmsg_remotedev_display_commit {
+	u32 disp_id;
+	u32 num_pipe_updates;
+	struct rpmsg_remotedev_display_pipe_update pipes[RPMSG_REMOTEDEV_DISPLAY_MAX_PIPES];
+	struct rpmsg_remotedev *rdev;
+	void *priv;
+};
+
+struct rpmsg_remotedev_display_pipe {
+	u32 pipe_id;
+	bool can_scale;
+	bool can_mod_win;
+	u32 fixed_win_x;
+	u32 fixed_win_y;
+	u32 fixed_win_w;
+	u32 fixed_win_h;
+	u32 initial_zorder;
+	u32 num_formats;
+	u32 formats[RPMSG_REMOTEDEV_DISPLAY_MAX_FORMATS];
+	u32 num_allowed_zorders;
+	u32 allowed_zorders[RPMSG_REMOTEDEV_DISPLAY_MAX_ZORDERS];
+};
+
+struct rpmsg_remotedev_display_disp {
+	u32 disp_id;
+	u32 width;
+	u32 height;
+	u32 refresh;
+	u32 num_pipes;
+	struct rpmsg_remotedev_display_pipe pipes[RPMSG_REMOTEDEV_DISPLAY_MAX_PIPES];
+};
+
+struct rpmsg_remotedev_display_resinfo {
+	u32 num_disps;
+	struct rpmsg_remotedev_display_disp disps[RPMSG_REMOTEDEV_DISPLAY_MAX_DISPS];
+};
+
+/* callbacks for demo device */
+struct rpmsg_remotedev_demo_cb {
+	void (*s2c_message)(void *data, ssize_t len, void *cb_data);
+};
+
+/* callbacks for display device */
+struct rpmsg_remotedev_display_cb {
+	void (*commit_done)(struct rpmsg_remotedev_display_commit *commit, void *cb_data);
+	void (*buffer_done)(struct rpmsg_remotedev_display_buffer *buffer, void *cb_data);
+};
+
+/* requests for demo device */
+struct rpmsg_remotedev_demo_ops {
+	int (*get_data)(struct rpmsg_remotedev *rdev, void *data, ssize_t len);
+	int (*ping)(struct rpmsg_remotedev *rdev, void *ping_data, ssize_t ping_len);
+	int (*c2s_message)(struct rpmsg_remotedev *rdev, void *c2s_msg_data, ssize_t len);
+};
+
+/* requests for display device */
+struct rpmsg_remotedev_display_ops {
+	bool (*ready)(struct rpmsg_remotedev *rdev);
+	int (*get_res_info)(struct rpmsg_remotedev *rdev,
+			    struct rpmsg_remotedev_display_resinfo *res);
+	int (*commit)(struct rpmsg_remotedev *rdev, struct rpmsg_remotedev_display_commit *commit);
+};
+
+#define RPMSG_RDEV_ETHSWITCH_CPSW_PRIORITY_NUM   (8)
+
+/* features bits */
+#define RPMSG_KDRV_ETHSWITCH_FEATURE_TXCSUM BIT(0)
+#define RPMSG_KDRV_ETHSWITCH_FEATURE_DUMP_STATS BIT(1)
+#define RPMSG_KDRV_ETHSWITCH_FEATURE_MAC_ONLY BIT(2)
+#define RPMSG_KDRV_ETHSWITCH_FEATURE_MC_FILTER BIT(3)
+
+struct rpmsg_rdev_eth_switch_attach_info {
+	/* MTU of rx packet */
+	u32 rx_mtu;
+	/* MTU of tx packet per priority */
+	u32 tx_mtu[RPMSG_RDEV_ETHSWITCH_CPSW_PRIORITY_NUM];
+	/* Supported Features mask */
+	u32 features;
+	u32 mac_only_port;
+};
+
+struct rpmsg_rdev_eth_switch_attach_ext_info {
+	/* MTU of rx packet */
+	u32 rx_mtu;
+	/* MTU of tx packet per priority */
+	u32 tx_mtu[RPMSG_RDEV_ETHSWITCH_CPSW_PRIORITY_NUM];
+	/* Supported Features mask */
+	u32 features;
+	u32 flow_idx;
+	u32 tx_cpsw_psil_dst_id;
+	u8 mac_addr[ETH_ALEN];
+	u32 mac_only_port;
+};
+
+struct rpmsg_rdev_eth_switch_tx_info {
+	/* Tx PSIL Peer destination thread id */
+	u32 tx_cpsw_psil_dst_id;
+};
+
+struct rpmsg_rdev_eth_switch_rx_info {
+	/* Allocated flow's index */
+	u32 flow_idx;
+};
+
+struct rpmsg_remotedev_eth_switch_ops {
+	void (*get_fw_ver)(struct rpmsg_remotedev *rdev,
+			   char *buf, size_t size);
+	int (*attach)(struct rpmsg_remotedev *rdev,
+		      struct rpmsg_rdev_eth_switch_attach_info *attach_info);
+	int (*attach_ext)(struct rpmsg_remotedev *rdev,
+			  struct rpmsg_rdev_eth_switch_attach_ext_info *attach_ext_info);
+	int (*detach)(struct rpmsg_remotedev *rdev);
+	int (*get_tx_info)(struct rpmsg_remotedev *rdev,
+			   struct rpmsg_rdev_eth_switch_tx_info *info);
+	int (*get_rx_info)(struct rpmsg_remotedev *rdev,
+			   struct rpmsg_rdev_eth_switch_rx_info *info);
+	int (*get_mac)(struct rpmsg_remotedev *rdev, void *mac_addr);
+	int (*register_mac)(struct rpmsg_remotedev *rdev,
+			    void *mac_addr, u32 flow_idx_offset);
+	int (*unregister_mac)(struct rpmsg_remotedev *rdev,
+			      void *mac_addr, u32 flow_idx_offset);
+	int (*register_ipv4)(struct rpmsg_remotedev *rdev,
+			     void *mac_addr, __be32 ipv4);
+	int (*unregister_ipv4)(struct rpmsg_remotedev *rdev, __be32 ipv4);
+	int (*ping)(struct rpmsg_remotedev *rdev, const u8 *data, int size);
+	int (*read_reg)(struct rpmsg_remotedev *rdev, u32 reg_addr, u32 *val);
+	int (*dbg_dump_stats)(struct rpmsg_remotedev *rdev);
+	int (*set_promisc_mode)(struct rpmsg_remotedev *rdev, u32 enable);
+	int (*filter_add_mc)(struct rpmsg_remotedev *rdev,
+			     const void *mac_addr, u16 vlan_id, u32 flow_idx);
+	int (*filter_del_mc)(struct rpmsg_remotedev *rdev,
+			     const void *mac_addr, u16 vlan_id, u32 flow_idx);
+};
+
+enum rpmsg_remotedev_type {
+	RPMSG_REMOTEDEV_DEMO_DEVICE,
+	RPMSG_REMOTEDEV_DISPLAY_DEVICE,
+	RPMSG_REMOTEDEV_ETH_SWITCH_DEVICE,
+};
+
+struct rpmsg_remotedev {
+	enum rpmsg_remotedev_type type;
+	union {
+		struct {
+			struct rpmsg_remotedev_demo_ops *ops;
+			struct rpmsg_remotedev_demo_cb *cb_ops;
+		} demo;
+		struct {
+			struct rpmsg_remotedev_display_ops *ops;
+			struct rpmsg_remotedev_display_cb *cb_ops;
+		} display;
+
+		struct {
+			struct rpmsg_remotedev_eth_switch_ops *ops;
+		} eth_switch;
+	} device;
+	void *cb_data;
+};
+
+#if IS_REACHABLE(CONFIG_RPMSG_KDRV)
+struct rpmsg_remotedev *rpmsg_remotedev_get_named_device(const char *device_name);
+void rpmsg_remotedev_put_device(struct rpmsg_remotedev *rdev);
+#else
+static inline struct rpmsg_remotedev * __maybe_unused rpmsg_remotedev_get_named_device(const char
+										       *device_name)
+{
+	return NULL;
+}
+
+static inline void __maybe_unused rpmsg_remotedev_put_device(struct rpmsg_remotedev *rdev)
+{
+}
+#endif
+
+#endif
diff -Naur --no-dereference a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
--- a/include/linux/soc/ti/ti_sci_protocol.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/soc/ti/ti_sci_protocol.h	2024-01-28 14:01:31.256353824 -0500
@@ -195,6 +195,49 @@
 			u64 *current_freq);
 };
 
+/* TISCI LPM wake up sources */
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_I2C0	0x00
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_UART0	0x10
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MCU_GPIO0	0x20
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_ICEMELTER0	0x30
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_TIMER0	0x40
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_TIMER1	0x41
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_WKUP_RTC0	0x50
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_RESET		0x60
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_USB0		0x70
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_USB1		0x71
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MAIN_IO		0x80
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_MCU_IO		0x81
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_CAN_IO		0x82
+#define TISCI_MSG_VALUE_LPM_WAKE_SOURCE_INVALID		0xFF
+
+/* TISCI LPM IO isolation control values */
+#define TISCI_MSG_VALUE_IO_ENABLE			1
+#define TISCI_MSG_VALUE_IO_DISABLE			0
+
+/**
+ * struct ti_sci_pm_ops - Low Power Mode (LPM) control operations
+ * @prepare_sleep: Prepare to enter low power mode
+ *		- mode: Low power mode to enter.
+ *		- ctx_lo: Low 32-bits of physical address for context save.
+ *		- ctx_hi: High 32-bits of physical address for context save.
+ *		- ctx_lo: 'true' if frequency change is desired.
+ *		- debug_flags: JTAG control flags for debug.
+ * @lpm_wake_reason: Get the wake up source that woke the SoC from LPM
+ *		- source: The wake up source that woke soc from LPM.
+ *		- timestamp: Timestamp at which soc woke.
+ * @set_io_isolation: Enable or disable IO isolation
+ *		- state: The desired state of the IO isolation.
+ */
+struct ti_sci_pm_ops {
+	int (*prepare_sleep)(const struct ti_sci_handle *handle, u8 mode,
+			     u32 ctx_lo, u32 ctx_hi, u32 flags);
+	int (*lpm_wake_reason)(const struct ti_sci_handle *handle,
+			       u32 *source, u64 *timestamp);
+	int (*set_io_isolation)(const struct ti_sci_handle *handle,
+				u8 state);
+};
+
 /**
  * struct ti_sci_resource_desc - Description of TI SCI resource instance range.
  * @start:	Start index of the first resource range.
@@ -539,6 +582,7 @@
 	struct ti_sci_core_ops core_ops;
 	struct ti_sci_dev_ops dev_ops;
 	struct ti_sci_clk_ops clk_ops;
+	struct ti_sci_pm_ops pm_ops;
 	struct ti_sci_rm_core_ops rm_core_ops;
 	struct ti_sci_rm_irq_ops rm_irq_ops;
 	struct ti_sci_rm_ringacc_ops rm_ring_ops;
diff -Naur --no-dereference a/include/linux/spi/spi.h b/include/linux/spi/spi.h
--- a/include/linux/spi/spi.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/spi/spi.h	2024-01-28 14:01:31.256353824 -0500
@@ -263,6 +263,26 @@
 	return dev_get_drvdata(&spi->dev);
 }
 
+static inline u8 spi_get_chipselect(const struct spi_device *spi, u8 idx)
+{
+	return spi->chip_select;
+}
+
+static inline void spi_set_chipselect(struct spi_device *spi, u8 idx, u8 chipselect)
+{
+	spi->chip_select = chipselect;
+}
+
+static inline struct gpio_desc *spi_get_csgpiod(const struct spi_device *spi, u8 idx)
+{
+	return spi->cs_gpiod;
+}
+
+static inline void spi_set_csgpiod(struct spi_device *spi, u8 idx, struct gpio_desc *csgpiod)
+{
+	spi->cs_gpiod = csgpiod;
+}
+
 struct spi_message;
 
 /**
@@ -1515,6 +1535,9 @@
 extern const struct spi_device_id *
 spi_get_device_id(const struct spi_device *sdev);
 
+extern const void *
+spi_get_device_match_data(const struct spi_device *sdev);
+
 static inline bool
 spi_transfer_is_last(struct spi_controller *ctlr, struct spi_transfer *xfer)
 {
diff -Naur --no-dereference a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h
--- a/include/linux/spi/spi-mem.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/linux/spi/spi-mem.h	2024-01-28 14:01:31.256353824 -0500
@@ -20,6 +20,14 @@
 		.nbytes = 1,					\
 	}
 
+#define SPI_MEM_OP_CMD_DTR(__nbytes, __opcode, __buswidth)	\
+	{							\
+		.nbytes = __nbytes,				\
+		.opcode = __opcode,				\
+		.buswidth = __buswidth,				\
+		.dtr = 1,					\
+	}
+
 #define SPI_MEM_OP_ADDR(__nbytes, __val, __buswidth)		\
 	{							\
 		.nbytes = __nbytes,				\
@@ -27,6 +35,14 @@
 		.buswidth = __buswidth,				\
 	}
 
+#define SPI_MEM_OP_ADDR_DTR(__nbytes, __val, __buswidth)	\
+	{							\
+		.nbytes = __nbytes,				\
+		.val = __val,					\
+		.buswidth = __buswidth,				\
+		.dtr = 1,					\
+	}
+
 #define SPI_MEM_OP_NO_ADDR	{ }
 
 #define SPI_MEM_OP_DUMMY(__nbytes, __buswidth)			\
@@ -35,6 +51,13 @@
 		.buswidth = __buswidth,				\
 	}
 
+#define SPI_MEM_OP_DUMMY_DTR(__nbytes, __buswidth)		\
+	{							\
+		.nbytes = __nbytes,				\
+		.buswidth = __buswidth,				\
+		.dtr = 1,					\
+	}
+
 #define SPI_MEM_OP_NO_DUMMY	{ }
 
 #define SPI_MEM_OP_DATA_IN(__nbytes, __buf, __buswidth)		\
@@ -45,6 +68,15 @@
 		.buswidth = __buswidth,				\
 	}
 
+#define SPI_MEM_OP_DATA_IN_DTR(__nbytes, __buf, __buswidth)	\
+	{							\
+		.dir = SPI_MEM_DATA_IN,				\
+		.nbytes = __nbytes,				\
+		.buf.in = __buf,				\
+		.buswidth = __buswidth,				\
+		.dtr = 1,					\
+	}
+
 #define SPI_MEM_OP_DATA_OUT(__nbytes, __buf, __buswidth)	\
 	{							\
 		.dir = SPI_MEM_DATA_OUT,			\
@@ -53,6 +85,15 @@
 		.buswidth = __buswidth,				\
 	}
 
+#define SPI_MEM_OP_DATA_OUT_DTR(__nbytes, __buf, __buswidth)	\
+	{							\
+		.dir = SPI_MEM_DATA_OUT,			\
+		.nbytes = __nbytes,				\
+		.buf.out = __buf,				\
+		.buswidth = __buswidth,				\
+		.dtr = 1,					\
+	}
+
 #define SPI_MEM_OP_NO_DATA	{ }
 
 /**
@@ -255,6 +296,12 @@
  * @poll_status: poll memory device status until (status & mask) == match or
  *               when the timeout has expired. It fills the data buffer with
  *               the last status value.
+ * @do_calibration: perform calibration needed for high SPI clock speed
+ *		    operation. Should be called after the SPI memory device has
+ *		    been completely initialized. The op passed should contain
+ *		    a template for the read operation used for the device so
+ *		    the controller can decide what type of calibration is
+ *		    required for this type of read.
  *
  * This interface should be implemented by SPI controllers providing an
  * high-level interface to execute SPI memory operation, which is usually the
@@ -285,6 +332,8 @@
 			   unsigned long initial_delay_us,
 			   unsigned long polling_rate_us,
 			   unsigned long timeout_ms);
+	void (*do_calibration)(struct spi_mem *mem,
+			       const struct spi_mem_op *op);
 };
 
 /**
@@ -359,6 +408,7 @@
 #endif /* CONFIG_SPI_MEM */
 
 int spi_mem_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op);
+int spi_mem_do_calibration(struct spi_mem *mem, const struct spi_mem_op *op);
 
 bool spi_mem_supports_op(struct spi_mem *mem,
 			 const struct spi_mem_op *op);
diff -Naur --no-dereference a/include/media/i2c/ds90ub9xx.h b/include/media/i2c/ds90ub9xx.h
--- a/include/media/i2c/ds90ub9xx.h	1969-12-31 19:00:00.000000000 -0500
+++ b/include/media/i2c/ds90ub9xx.h	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __MEDIA_I2C_DS90UB9XX_H__
+#define __MEDIA_I2C_DS90UB9XX_H__
+
+#include <linux/types.h>
+
+struct i2c_atr;
+
+/**
+ * struct ds90ub9xx_platform_data - platform data for FPD-Link Serializers.
+ * @port: Deserializer RX port for this Serializer
+ * @atr: I2C ATR
+ * @bc_rate: back-channel clock rate
+ */
+struct ds90ub9xx_platform_data {
+	u32 port;
+	struct i2c_atr *atr;
+	unsigned long bc_rate;
+};
+
+#endif /* __MEDIA_I2C_DS90UB9XX_H__ */
diff -Naur --no-dereference a/include/media/v4l2-mc.h b/include/media/v4l2-mc.h
--- a/include/media/v4l2-mc.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/media/v4l2-mc.h	2024-01-28 14:01:31.256353824 -0500
@@ -87,17 +87,17 @@
 
 /**
  * v4l2_create_fwnode_links_to_pad - Create fwnode-based links from a
- *                                   source subdev to a sink subdev pad.
+ *                                   source subdev to a sink pad.
  *
  * @src_sd: pointer to a source subdev
- * @sink:  pointer to a subdev sink pad
+ * @sink:  pointer to a sink pad
  * @flags: the link flags
  *
  * This function searches for fwnode endpoint connections from a source
  * subdevice to a single sink pad, and if suitable connections are found,
  * translates them into media links to that pad. The function can be
- * called by the sink subdevice, in its v4l2-async notifier subdev bound
- * callback, to create links from a bound source subdevice.
+ * called by the sink, in its v4l2-async notifier bound callback, to create
+ * links from a bound source subdevice.
  *
  * The @flags argument specifies the link flags. The caller shall ensure that
  * the flags are valid regardless of the number of links that may be created.
diff -Naur --no-dereference a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
--- a/include/media/v4l2-subdev.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/media/v4l2-subdev.h	2024-01-28 14:01:31.256353824 -0500
@@ -342,6 +342,7 @@
  * struct v4l2_mbus_frame_desc_entry - media bus frame description structure
  *
  * @flags:	bitmask flags, as defined by &enum v4l2_mbus_frame_desc_flags.
+ * @stream:	stream in routing configuration
  * @pixelcode:	media bus pixel code, valid if @flags
  *		%FRAME_DESC_FL_BLOB is not set.
  * @length:	number of octets per frame, valid if @flags
@@ -351,6 +352,7 @@
  */
 struct v4l2_mbus_frame_desc_entry {
 	enum v4l2_mbus_frame_desc_flags flags;
+	u32 stream;
 	u32 pixelcode;
 	u32 length;
 	union {
@@ -696,11 +698,59 @@
 };
 
 /**
+ * struct v4l2_subdev_stream_config - Used for storing stream configuration.
+ *
+ * @pad: pad number
+ * @stream: stream number
+ * @enabled: has the stream been enabled with v4l2_subdev_enable_stream()
+ * @fmt: &struct v4l2_mbus_framefmt
+ * @crop: &struct v4l2_rect to be used for crop
+ * @compose: &struct v4l2_rect to be used for compose
+ *
+ * This structure stores configuration for a stream.
+ */
+struct v4l2_subdev_stream_config {
+	u32 pad;
+	u32 stream;
+	bool enabled;
+
+	struct v4l2_mbus_framefmt fmt;
+	struct v4l2_rect crop;
+	struct v4l2_rect compose;
+};
+
+/**
+ * struct v4l2_subdev_stream_configs - A collection of stream configs.
+ *
+ * @num_configs: number of entries in @config.
+ * @configs: an array of &struct v4l2_subdev_stream_configs.
+ */
+struct v4l2_subdev_stream_configs {
+	u32 num_configs;
+	struct v4l2_subdev_stream_config *configs;
+};
+
+/**
+ * struct v4l2_subdev_krouting - subdev routing table
+ *
+ * @num_routes: number of routes
+ * @routes: &struct v4l2_subdev_route
+ *
+ * This structure contains the routing table for a subdev.
+ */
+struct v4l2_subdev_krouting {
+	unsigned int num_routes;
+	struct v4l2_subdev_route *routes;
+};
+
+/**
  * struct v4l2_subdev_state - Used for storing subdev state information.
  *
  * @_lock: default for 'lock'
  * @lock: mutex for the state. May be replaced by the user.
  * @pads: &struct v4l2_subdev_pad_config array
+ * @routing: routing table for the subdev
+ * @stream_configs: stream configurations (only for V4L2_SUBDEV_FL_STREAMS)
  *
  * This structure only needs to be passed to the pad op if the 'which' field
  * of the main argument is set to %V4L2_SUBDEV_FORMAT_TRY. For
@@ -711,6 +761,8 @@
 	struct mutex _lock;
 	struct mutex *lock;
 	struct v4l2_subdev_pad_config *pads;
+	struct v4l2_subdev_krouting routing;
+	struct v4l2_subdev_stream_configs stream_configs;
 };
 
 /**
@@ -763,6 +815,21 @@
  *		     this operation as close as possible to stream on time. The
  *		     operation shall fail if the pad index it has been called on
  *		     is not valid or in case of unrecoverable failures.
+ *
+ * @set_routing: enable or disable data connection routes described in the
+ *		 subdevice routing table.
+ *
+ * @enable_streams: Enable the streams defined in streams_mask on the given
+ *	source pad. Subdevs that implement this operation must use the active
+ *	state management provided by the subdev core (enabled through a call to
+ *	v4l2_subdev_init_finalize() at initialization time). Do not call
+ *	directly, use v4l2_subdev_enable_streams() instead.
+ *
+ * @disable_streams: Disable the streams defined in streams_mask on the given
+ *	source pad. Subdevs that implement this operation must use the active
+ *	state management provided by the subdev core (enabled through a call to
+ *	v4l2_subdev_init_finalize() at initialization time). Do not call
+ *	directly, use v4l2_subdev_disable_streams() instead.
  */
 struct v4l2_subdev_pad_ops {
 	int (*init_cfg)(struct v4l2_subdev *sd,
@@ -805,6 +872,16 @@
 			      struct v4l2_mbus_frame_desc *fd);
 	int (*get_mbus_config)(struct v4l2_subdev *sd, unsigned int pad,
 			       struct v4l2_mbus_config *config);
+	int (*set_routing)(struct v4l2_subdev *sd,
+			   struct v4l2_subdev_state *state,
+			   enum v4l2_subdev_format_whence which,
+			   struct v4l2_subdev_krouting *route);
+	int (*enable_streams)(struct v4l2_subdev *sd,
+			      struct v4l2_subdev_state *state, u32 pad,
+			      u64 streams_mask);
+	int (*disable_streams)(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_state *state, u32 pad,
+			       u64 streams_mask);
 };
 
 /**
@@ -879,6 +956,17 @@
  * should set this flag.
  */
 #define V4L2_SUBDEV_FL_HAS_EVENTS		(1U << 3)
+/*
+ * Set this flag if this subdev supports multiplexed streams. This means
+ * that the driver supports routing and handles the stream parameter in its
+ * v4l2_subdev_pad_ops handlers. More specifically, this means:
+ *
+ * - Centrally managed subdev active state is enabled
+ * - Legacy pad config is _not_ supported (state->pads is NULL)
+ * - Routing ioctls are available
+ * - Multiple streams per pad are supported
+ */
+#define V4L2_SUBDEV_FL_STREAMS			(1U << 4)
 
 struct regulator_bulk_data;
 
@@ -939,6 +1027,10 @@
  * @active_state: Active state for the subdev (NULL for subdevs tracking the
  *		  state internally). Initialized by calling
  *		  v4l2_subdev_init_finalize().
+ * @enabled_streams: Bitmask of enabled streams used by
+ *		     v4l2_subdev_enable_streams() and
+ *		     v4l2_subdev_disable_streams() helper functions for fallback
+ *		     cases.
  *
  * Each instance of a subdev driver should create this struct, either
  * stand-alone or embedded in a larger struct.
@@ -984,6 +1076,7 @@
 	 * doesn't support it.
 	 */
 	struct v4l2_subdev_state *active_state;
+	u64 enabled_streams;
 };
 
 
@@ -1209,6 +1302,24 @@
 int v4l2_subdev_link_validate(struct media_link *link);
 
 /**
+ * v4l2_subdev_has_pad_interdep - MC has_pad_interdep implementation for subdevs
+ *
+ * @entity: pointer to &struct media_entity
+ * @pad0: pad number for the first pad
+ * @pad1: pad number for the second pad
+ *
+ * This function is an implementation of the
+ * media_entity_operations.has_pad_interdep operation for subdevs that
+ * implement the multiplexed streams API (as indicated by the
+ * V4L2_SUBDEV_FL_STREAMS subdev flag).
+ *
+ * It considers two pads interdependent if there is an active route between pad0
+ * and pad1.
+ */
+bool v4l2_subdev_has_pad_interdep(struct media_entity *entity,
+				  unsigned int pad0, unsigned int pad1);
+
+/**
  * __v4l2_subdev_state_alloc - allocate v4l2_subdev_state
  *
  * @sd: pointer to &struct v4l2_subdev for which the state is being allocated.
@@ -1368,6 +1479,294 @@
 int v4l2_subdev_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_state *state,
 			struct v4l2_subdev_format *format);
 
+/**
+ * v4l2_subdev_set_routing() - Set given routing to subdev state
+ * @sd: The subdevice
+ * @state: The subdevice state
+ * @routing: Routing that will be copied to subdev state
+ *
+ * This will release old routing table (if any) from the state, allocate
+ * enough space for the given routing, and copy the routing.
+ *
+ * This can be used from the subdev driver's set_routing op, after validating
+ * the routing.
+ */
+int v4l2_subdev_set_routing(struct v4l2_subdev *sd,
+			    struct v4l2_subdev_state *state,
+			    const struct v4l2_subdev_krouting *routing);
+
+struct v4l2_subdev_route *
+__v4l2_subdev_next_active_route(const struct v4l2_subdev_krouting *routing,
+				struct v4l2_subdev_route *route);
+
+/**
+ * for_each_active_route - iterate on all active routes of a routing table
+ * @routing: The routing table
+ * @route: The route iterator
+ */
+#define for_each_active_route(routing, route) \
+	for ((route) = NULL;                  \
+	     ((route) = __v4l2_subdev_next_active_route((routing), (route)));)
+
+/**
+ * v4l2_subdev_set_routing_with_fmt() - Set given routing and format to subdev
+ *					state
+ * @sd: The subdevice
+ * @state: The subdevice state
+ * @routing: Routing that will be copied to subdev state
+ * @fmt: Format used to initialize all the streams
+ *
+ * This is the same as v4l2_subdev_set_routing, but additionally initializes
+ * all the streams using the given format.
+ */
+int v4l2_subdev_set_routing_with_fmt(struct v4l2_subdev *sd,
+				     struct v4l2_subdev_state *state,
+				     struct v4l2_subdev_krouting *routing,
+				     const struct v4l2_mbus_framefmt *fmt);
+
+/**
+ * v4l2_subdev_state_get_stream_format() - Get pointer to a stream format
+ * @state: subdevice state
+ * @pad: pad id
+ * @stream: stream id
+ *
+ * This returns a pointer to &struct v4l2_mbus_framefmt for the given pad +
+ * stream in the subdev state.
+ *
+ * If the state does not contain the given pad + stream, NULL is returned.
+ */
+struct v4l2_mbus_framefmt *
+v4l2_subdev_state_get_stream_format(struct v4l2_subdev_state *state,
+				    unsigned int pad, u32 stream);
+
+/**
+ * v4l2_subdev_state_get_stream_crop() - Get pointer to a stream crop rectangle
+ * @state: subdevice state
+ * @pad: pad id
+ * @stream: stream id
+ *
+ * This returns a pointer to crop rectangle for the given pad + stream in the
+ * subdev state.
+ *
+ * If the state does not contain the given pad + stream, NULL is returned.
+ */
+struct v4l2_rect *
+v4l2_subdev_state_get_stream_crop(struct v4l2_subdev_state *state,
+				  unsigned int pad, u32 stream);
+
+/**
+ * v4l2_subdev_state_get_stream_compose() - Get pointer to a stream compose
+ *					    rectangle
+ * @state: subdevice state
+ * @pad: pad id
+ * @stream: stream id
+ *
+ * This returns a pointer to compose rectangle for the given pad + stream in the
+ * subdev state.
+ *
+ * If the state does not contain the given pad + stream, NULL is returned.
+ */
+struct v4l2_rect *
+v4l2_subdev_state_get_stream_compose(struct v4l2_subdev_state *state,
+				     unsigned int pad, u32 stream);
+
+/**
+ * v4l2_subdev_routing_find_opposite_end() - Find the opposite stream
+ * @routing: routing used to find the opposite side
+ * @pad: pad id
+ * @stream: stream id
+ * @other_pad: pointer used to return the opposite pad
+ * @other_stream: pointer used to return the opposite stream
+ *
+ * This function uses the routing table to find the pad + stream which is
+ * opposite the given pad + stream.
+ *
+ * @other_pad and/or @other_stream can be NULL if the caller does not need the
+ * value.
+ *
+ * Returns 0 on success, or -EINVAL if no matching route is found.
+ */
+int v4l2_subdev_routing_find_opposite_end(const struct v4l2_subdev_krouting *routing,
+					  u32 pad, u32 stream, u32 *other_pad,
+					  u32 *other_stream);
+
+/**
+ * v4l2_subdev_state_get_opposite_stream_format() - Get pointer to opposite
+ *                                                  stream format
+ * @state: subdevice state
+ * @pad: pad id
+ * @stream: stream id
+ *
+ * This returns a pointer to &struct v4l2_mbus_framefmt for the pad + stream
+ * that is opposite the given pad + stream in the subdev state.
+ *
+ * If the state does not contain the given pad + stream, NULL is returned.
+ */
+struct v4l2_mbus_framefmt *
+v4l2_subdev_state_get_opposite_stream_format(struct v4l2_subdev_state *state,
+					     u32 pad, u32 stream);
+
+/**
+ * v4l2_subdev_state_xlate_streams() - Translate streams from one pad to another
+ *
+ * @state: Subdevice state
+ * @pad0: The first pad
+ * @pad1: The second pad
+ * @streams: Streams bitmask on the first pad
+ *
+ * Streams on sink pads of a subdev are routed to source pads as expressed in
+ * the subdev state routing table. Stream numbers don't necessarily match on
+ * the sink and source side of a route. This function translates stream numbers
+ * on @pad0, expressed as a bitmask in @streams, to the corresponding streams
+ * on @pad1 using the routing table from the @state. It returns the stream mask
+ * on @pad1, and updates @streams with the streams that have been found in the
+ * routing table.
+ *
+ * @pad0 and @pad1 must be a sink and a source, in any order.
+ *
+ * Return: The bitmask of streams of @pad1 that are routed to @streams on @pad0.
+ */
+u64 v4l2_subdev_state_xlate_streams(const struct v4l2_subdev_state *state,
+				    u32 pad0, u32 pad1, u64 *streams);
+
+/**
+ * enum v4l2_subdev_routing_restriction - Subdevice internal routing restrictions
+ *
+ * @V4L2_SUBDEV_ROUTING_NO_1_TO_N:
+ *	an input stream shall not be routed to multiple output streams (stream
+ *	duplication)
+ * @V4L2_SUBDEV_ROUTING_NO_N_TO_1:
+ *	multiple input streams shall not be routed to the same output stream
+ *	(stream merging)
+ * @V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX:
+ *	all streams from a sink pad must be routed to a single source pad
+ * @V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX:
+ *	all streams on a source pad must originate from a single sink pad
+ * @V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING:
+ *	source pads shall not contain multiplexed streams
+ * @V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXING:
+ *	sink pads shall not contain multiplexed streams
+ * @V4L2_SUBDEV_ROUTING_ONLY_1_TO_1:
+ *	only non-overlapping 1-to-1 stream routing is allowed (a combination of
+ *	@V4L2_SUBDEV_ROUTING_NO_1_TO_N and @V4L2_SUBDEV_ROUTING_NO_N_TO_1)
+ * @V4L2_SUBDEV_ROUTING_NO_STREAM_MIX:
+ *	all streams from a sink pad must be routed to a single source pad, and
+ *	that source pad shall not get routes from any other sink pad
+ *	(a combination of @V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX and
+ *	@V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX)
+ * @V4L2_SUBDEV_ROUTING_NO_MULTIPLEXING:
+ *	no multiplexed streams allowed on either source or sink sides.
+ */
+enum v4l2_subdev_routing_restriction {
+	V4L2_SUBDEV_ROUTING_NO_1_TO_N = BIT(0),
+	V4L2_SUBDEV_ROUTING_NO_N_TO_1 = BIT(1),
+	V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX = BIT(2),
+	V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX = BIT(3),
+	V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXING = BIT(4),
+	V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING = BIT(5),
+	V4L2_SUBDEV_ROUTING_ONLY_1_TO_1 =
+		V4L2_SUBDEV_ROUTING_NO_1_TO_N |
+		V4L2_SUBDEV_ROUTING_NO_N_TO_1,
+	V4L2_SUBDEV_ROUTING_NO_STREAM_MIX =
+		V4L2_SUBDEV_ROUTING_NO_SINK_STREAM_MIX |
+		V4L2_SUBDEV_ROUTING_NO_SOURCE_STREAM_MIX,
+	V4L2_SUBDEV_ROUTING_NO_MULTIPLEXING =
+		V4L2_SUBDEV_ROUTING_NO_SINK_MULTIPLEXING |
+		V4L2_SUBDEV_ROUTING_NO_SOURCE_MULTIPLEXING,
+};
+
+/**
+ * v4l2_subdev_routing_validate() - Verify that routes comply with driver
+ *				    constraints
+ * @sd: The subdevice
+ * @routing: Routing to verify
+ * @disallow: Restrictions on routes
+ *
+ * This verifies that the given routing complies with the @disallow constraints.
+ *
+ * Returns 0 on success, error value otherwise.
+ */
+int v4l2_subdev_routing_validate(struct v4l2_subdev *sd,
+				 const struct v4l2_subdev_krouting *routing,
+				 enum v4l2_subdev_routing_restriction disallow);
+
+/**
+ * v4l2_subdev_enable_streams() - Enable streams on a pad
+ * @sd: The subdevice
+ * @pad: The pad
+ * @streams_mask: Bitmask of streams to enable
+ *
+ * This function enables streams on a source @pad of a subdevice. The pad is
+ * identified by its index, while the streams are identified by the
+ * @streams_mask bitmask. This allows enabling multiple streams on a pad at
+ * once.
+ *
+ * Enabling a stream that is already enabled isn't allowed. If @streams_mask
+ * contains an already enabled stream, this function returns -EALREADY without
+ * performing any operation.
+ *
+ * Per-stream enable is only available for subdevs that implement the
+ * .enable_streams() and .disable_streams() operations. For other subdevs, this
+ * function implements a best-effort compatibility by calling the .s_stream()
+ * operation, limited to subdevs that have a single source pad.
+ *
+ * Return:
+ * * 0: Success
+ * * -EALREADY: One of the streams in streams_mask is already enabled
+ * * -EINVAL: The pad index is invalid, or doesn't correspond to a source pad
+ * * -EOPNOTSUPP: Falling back to the legacy .s_stream() operation is
+ *   impossible because the subdev has multiple source pads
+ */
+int v4l2_subdev_enable_streams(struct v4l2_subdev *sd, u32 pad,
+			       u64 streams_mask);
+
+/**
+ * v4l2_subdev_disable_streams() - Disable streams on a pad
+ * @sd: The subdevice
+ * @pad: The pad
+ * @streams_mask: Bitmask of streams to disable
+ *
+ * This function disables streams on a source @pad of a subdevice. The pad is
+ * identified by its index, while the streams are identified by the
+ * @streams_mask bitmask. This allows disabling multiple streams on a pad at
+ * once.
+ *
+ * Disabling a streams that is not enabled isn't allowed. If @streams_mask
+ * contains a disabled stream, this function returns -EALREADY without
+ * performing any operation.
+ *
+ * Per-stream disable is only available for subdevs that implement the
+ * .enable_streams() and .disable_streams() operations. For other subdevs, this
+ * function implements a best-effort compatibility by calling the .s_stream()
+ * operation, limited to subdevs that have a single source pad.
+ *
+ * Return:
+ * * 0: Success
+ * * -EALREADY: One of the streams in streams_mask is not enabled
+ * * -EINVAL: The pad index is invalid, or doesn't correspond to a source pad
+ * * -EOPNOTSUPP: Falling back to the legacy .s_stream() operation is
+ *   impossible because the subdev has multiple source pads
+ */
+int v4l2_subdev_disable_streams(struct v4l2_subdev *sd, u32 pad,
+				u64 streams_mask);
+
+/**
+ * v4l2_subdev_s_stream_helper() - Helper to implement the subdev s_stream
+ *	operation using enable_streams and disable_streams
+ * @sd: The subdevice
+ * @enable: Enable or disable streaming
+ *
+ * Subdevice drivers that implement the streams-aware
+ * &v4l2_subdev_pad_ops.enable_streams and &v4l2_subdev_pad_ops.disable_streams
+ * operations can use this helper to implement the legacy
+ * &v4l2_subdev_video_ops.s_stream operation.
+ *
+ * This helper can only be used by subdevs that have a single source pad.
+ *
+ * Return: 0 on success, or a negative error code otherwise.
+ */
+int v4l2_subdev_s_stream_helper(struct v4l2_subdev *sd, int enable);
+
 #endif /* CONFIG_VIDEO_V4L2_SUBDEV_API */
 
 #endif /* CONFIG_MEDIA_CONTROLLER */
diff -Naur --no-dereference a/include/uapi/linux/counter.h b/include/uapi/linux/counter.h
--- a/include/uapi/linux/counter.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/uapi/linux/counter.h	2024-01-28 14:01:31.256353824 -0500
@@ -65,6 +65,10 @@
 	COUNTER_EVENT_CHANGE_OF_STATE,
 	/* Count value captured */
 	COUNTER_EVENT_CAPTURE,
+	/* Direction change detected */
+	COUNTER_EVENT_DIRECTION_CHANGE,
+	/* Timer exceeded timeout */
+	COUNTER_EVENT_TIMEOUT,
 };
 
 /**
diff -Naur --no-dereference a/include/uapi/linux/dma_buf_phys.h b/include/uapi/linux/dma_buf_phys.h
--- a/include/uapi/linux/dma_buf_phys.h	1969-12-31 19:00:00.000000000 -0500
+++ b/include/uapi/linux/dma_buf_phys.h	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * DMA-BUF contiguous buffer physical address user-space exporter
+ *
+ * Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
+ *	Andrew F. Davis <afd@ti.com>
+ */
+
+#ifndef DMA_BUF_PHYS_H
+#define DMA_BUF_PHYS_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/**
+ * struct dma_buf_phys_data - metadata passed from userspace for conversion
+ * @fd:		DMA-BUF fd for conversion
+ * @phys:	populated with CPU physical address of DMA-BUF
+ */
+struct dma_buf_phys_data {
+	__u32 fd;
+	__u64 phys;
+};
+
+#define DMA_BUF_PHYS_IOC_MAGIC 'D'
+
+/**
+ * DOC: DMA_BUF_PHYS_IOC_CONVERT - Convert DMA-BUF to physical address
+ *
+ * Takes a dma_buf_phys_data struct containing a fd for a physicaly contigous
+ * buffer. Pins this buffer and populates phys field with the CPU physical address.
+ */
+#define DMA_BUF_PHYS_IOC_CONVERT _IOWR(DMA_BUF_PHYS_IOC_MAGIC, 0, struct dma_buf_phys_data)
+
+#endif /* DMA_BUF_PHYS_H */
diff -Naur --no-dereference a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h
--- a/include/uapi/linux/media-bus-format.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/uapi/linux/media-bus-format.h	2024-01-28 14:01:31.256353824 -0500
@@ -116,7 +116,7 @@
 #define MEDIA_BUS_FMT_YUV16_1X48		0x202a
 #define MEDIA_BUS_FMT_UYYVYY16_0_5X48		0x202b
 
-/* Bayer - next is	0x3021 */
+/* Bayer - next is	0x3029 */
 #define MEDIA_BUS_FMT_SBGGR8_1X8		0x3001
 #define MEDIA_BUS_FMT_SGBRG8_1X8		0x3013
 #define MEDIA_BUS_FMT_SGRBG8_1X8		0x3002
@@ -149,6 +149,14 @@
 #define MEDIA_BUS_FMT_SGBRG16_1X16		0x301e
 #define MEDIA_BUS_FMT_SGRBG16_1X16		0x301f
 #define MEDIA_BUS_FMT_SRGGB16_1X16		0x3020
+#define MEDIA_BUS_FMT_SRGGI10_1X10		0x3021
+#define MEDIA_BUS_FMT_SGRIG10_1X10		0x3022
+#define MEDIA_BUS_FMT_SBGGI10_1X10		0x3023
+#define MEDIA_BUS_FMT_SGBIG10_1X10		0x3024
+#define MEDIA_BUS_FMT_SGIRG10_1X10		0x3025
+#define MEDIA_BUS_FMT_SIGGR10_1X10		0x3026
+#define MEDIA_BUS_FMT_SGIBG10_1X10		0x3027
+#define MEDIA_BUS_FMT_SIGGB10_1X10		0x3028
 
 /* JPEG compressed formats - next is	0x4002 */
 #define MEDIA_BUS_FMT_JPEG_1X8			0x4001
diff -Naur --no-dereference a/include/uapi/linux/tps6594_pfsm.h b/include/uapi/linux/tps6594_pfsm.h
--- a/include/uapi/linux/tps6594_pfsm.h	1969-12-31 19:00:00.000000000 -0500
+++ b/include/uapi/linux/tps6594_pfsm.h	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Userspace ABI for TPS6594 PMIC Pre-configurable Finite State Machine
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ */
+
+#ifndef __TPS6594_PFSM_H
+#define __TPS6594_PFSM_H
+
+#include <linux/const.h>
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/**
+ * struct pmic_state_opt - PMIC state options
+ * @gpio_retention: if enabled, power rails associated with GPIO retention remain active
+ * @ddr_retention: if enabled, power rails associated with DDR retention remain active
+ * @mcu_only_startup_dest: if enabled, startup destination state is MCU_ONLY
+ */
+struct pmic_state_opt {
+	__u8 gpio_retention;
+	__u8 ddr_retention;
+	__u8 mcu_only_startup_dest;
+};
+
+/* Commands */
+#define PMIC_BASE			'P'
+
+#define PMIC_GOTO_STANDBY		_IO(PMIC_BASE, 0)
+#define PMIC_GOTO_LP_STANDBY		_IO(PMIC_BASE, 1)
+#define PMIC_UPDATE_PGM			_IO(PMIC_BASE, 2)
+#define PMIC_SET_ACTIVE_STATE		_IO(PMIC_BASE, 3)
+#define PMIC_SET_MCU_ONLY_STATE		_IOW(PMIC_BASE, 4, struct pmic_state_opt)
+#define PMIC_SET_RETENTION_STATE	_IOW(PMIC_BASE, 5, struct pmic_state_opt)
+
+#endif /*  __TPS6594_PFSM_H */
diff -Naur --no-dereference a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
--- a/include/uapi/linux/v4l2-subdev.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/uapi/linux/v4l2-subdev.h	2024-01-28 14:01:31.256353824 -0500
@@ -24,6 +24,7 @@
 #ifndef __LINUX_V4L2_SUBDEV_H
 #define __LINUX_V4L2_SUBDEV_H
 
+#include <linux/const.h>
 #include <linux/ioctl.h>
 #include <linux/types.h>
 #include <linux/v4l2-common.h>
@@ -44,13 +45,15 @@
  * @which: format type (from enum v4l2_subdev_format_whence)
  * @pad: pad number, as reported by the media API
  * @format: media bus format (format code and frame size)
+ * @stream: stream number, defined in subdev routing
  * @reserved: drivers and applications must zero this array
  */
 struct v4l2_subdev_format {
 	__u32 which;
 	__u32 pad;
 	struct v4l2_mbus_framefmt format;
-	__u32 reserved[8];
+	__u32 stream;
+	__u32 reserved[7];
 };
 
 /**
@@ -58,13 +61,15 @@
  * @which: format type (from enum v4l2_subdev_format_whence)
  * @pad: pad number, as reported by the media API
  * @rect: pad crop rectangle boundaries
+ * @stream: stream number, defined in subdev routing
  * @reserved: drivers and applications must zero this array
  */
 struct v4l2_subdev_crop {
 	__u32 which;
 	__u32 pad;
 	struct v4l2_rect rect;
-	__u32 reserved[8];
+	__u32 stream;
+	__u32 reserved[7];
 };
 
 #define V4L2_SUBDEV_MBUS_CODE_CSC_COLORSPACE	0x00000001
@@ -80,6 +85,7 @@
  * @code: format code (MEDIA_BUS_FMT_ definitions)
  * @which: format type (from enum v4l2_subdev_format_whence)
  * @flags: flags set by the driver, (V4L2_SUBDEV_MBUS_CODE_*)
+ * @stream: stream number, defined in subdev routing
  * @reserved: drivers and applications must zero this array
  */
 struct v4l2_subdev_mbus_code_enum {
@@ -88,7 +94,8 @@
 	__u32 code;
 	__u32 which;
 	__u32 flags;
-	__u32 reserved[7];
+	__u32 stream;
+	__u32 reserved[6];
 };
 
 /**
@@ -101,6 +108,7 @@
  * @min_height: minimum frame height, in pixels
  * @max_height: maximum frame height, in pixels
  * @which: format type (from enum v4l2_subdev_format_whence)
+ * @stream: stream number, defined in subdev routing
  * @reserved: drivers and applications must zero this array
  */
 struct v4l2_subdev_frame_size_enum {
@@ -112,19 +120,22 @@
 	__u32 min_height;
 	__u32 max_height;
 	__u32 which;
-	__u32 reserved[8];
+	__u32 stream;
+	__u32 reserved[7];
 };
 
 /**
  * struct v4l2_subdev_frame_interval - Pad-level frame rate
  * @pad: pad number, as reported by the media API
  * @interval: frame interval in seconds
+ * @stream: stream number, defined in subdev routing
  * @reserved: drivers and applications must zero this array
  */
 struct v4l2_subdev_frame_interval {
 	__u32 pad;
 	struct v4l2_fract interval;
-	__u32 reserved[9];
+	__u32 stream;
+	__u32 reserved[8];
 };
 
 /**
@@ -136,6 +147,7 @@
  * @height: frame height in pixels
  * @interval: frame interval in seconds
  * @which: format type (from enum v4l2_subdev_format_whence)
+ * @stream: stream number, defined in subdev routing
  * @reserved: drivers and applications must zero this array
  */
 struct v4l2_subdev_frame_interval_enum {
@@ -146,7 +158,8 @@
 	__u32 height;
 	struct v4l2_fract interval;
 	__u32 which;
-	__u32 reserved[8];
+	__u32 stream;
+	__u32 reserved[7];
 };
 
 /**
@@ -158,6 +171,7 @@
  *	    defined in v4l2-common.h; V4L2_SEL_TGT_* .
  * @flags: constraint flags, defined in v4l2-common.h; V4L2_SEL_FLAG_*.
  * @r: coordinates of the selection window
+ * @stream: stream number, defined in subdev routing
  * @reserved: for future use, set to zero for now
  *
  * Hardware may use multiple helper windows to process a video stream.
@@ -170,7 +184,8 @@
 	__u32 target;
 	__u32 flags;
 	struct v4l2_rect r;
-	__u32 reserved[8];
+	__u32 stream;
+	__u32 reserved[7];
 };
 
 /**
@@ -188,6 +203,49 @@
 /* The v4l2 sub-device video device node is registered in read-only mode. */
 #define V4L2_SUBDEV_CAP_RO_SUBDEV		0x00000001
 
+/* The v4l2 sub-device supports routing and multiplexed streams. */
+#define V4L2_SUBDEV_CAP_STREAMS			0x00000002
+
+/*
+ * Is the route active? An active route will start when streaming is enabled
+ * on a video node.
+ */
+#define V4L2_SUBDEV_ROUTE_FL_ACTIVE		(1U << 0)
+
+/**
+ * struct v4l2_subdev_route - A route inside a subdev
+ *
+ * @sink_pad: the sink pad index
+ * @sink_stream: the sink stream identifier
+ * @source_pad: the source pad index
+ * @source_stream: the source stream identifier
+ * @flags: route flags V4L2_SUBDEV_ROUTE_FL_*
+ * @reserved: drivers and applications must zero this array
+ */
+struct v4l2_subdev_route {
+	__u32 sink_pad;
+	__u32 sink_stream;
+	__u32 source_pad;
+	__u32 source_stream;
+	__u32 flags;
+	__u32 reserved[5];
+};
+
+/**
+ * struct v4l2_subdev_routing - Subdev routing information
+ *
+ * @which: configuration type (from enum v4l2_subdev_format_whence)
+ * @num_routes: the total number of routes in the routes array
+ * @routes: pointer to the routes array
+ * @reserved: drivers and applications must zero this array
+ */
+struct v4l2_subdev_routing {
+	__u32 which;
+	__u32 num_routes;
+	__u64 routes;
+	__u32 reserved[6];
+};
+
 /* Backwards compatibility define --- to be removed */
 #define v4l2_subdev_edid v4l2_edid
 
@@ -203,6 +261,8 @@
 #define VIDIOC_SUBDEV_S_CROP			_IOWR('V', 60, struct v4l2_subdev_crop)
 #define VIDIOC_SUBDEV_G_SELECTION		_IOWR('V', 61, struct v4l2_subdev_selection)
 #define VIDIOC_SUBDEV_S_SELECTION		_IOWR('V', 62, struct v4l2_subdev_selection)
+#define VIDIOC_SUBDEV_G_ROUTING			_IOWR('V', 38, struct v4l2_subdev_routing)
+#define VIDIOC_SUBDEV_S_ROUTING			_IOWR('V', 39, struct v4l2_subdev_routing)
 /* The following ioctls are identical to the ioctls in videodev2.h */
 #define VIDIOC_SUBDEV_G_STD			_IOR('V', 23, v4l2_std_id)
 #define VIDIOC_SUBDEV_S_STD			_IOW('V', 24, v4l2_std_id)
diff -Naur --no-dereference a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
--- a/include/uapi/linux/videodev2.h	2023-12-20 11:00:29.000000000 -0500
+++ b/include/uapi/linux/videodev2.h	2024-01-28 14:01:31.256353824 -0500
@@ -707,6 +707,15 @@
 #define V4L2_PIX_FMT_SGBRG16 v4l2_fourcc('G', 'B', '1', '6') /* 16  GBGB.. RGRG.. */
 #define V4L2_PIX_FMT_SGRBG16 v4l2_fourcc('G', 'R', '1', '6') /* 16  GRGR.. BGBG.. */
 #define V4L2_PIX_FMT_SRGGB16 v4l2_fourcc('R', 'G', '1', '6') /* 16  RGRG.. GBGB.. */
+	/* 10bit raw bayer with IR (4x4) */
+#define V4L2_PIX_FMT_SRGGI10 v4l2_fourcc('R', 'G', 'I', '0') /* 10 RGBG.. GIrGIr.. */
+#define V4L2_PIX_FMT_SGRIG10 v4l2_fourcc('G', 'R', 'I', '0') /* 10 GRGB.. IrGIrG.. */
+#define V4L2_PIX_FMT_SBGGI10 v4l2_fourcc('B', 'G', 'I', '0') /* 10 BGRG.. GIrGIr.. */
+#define V4L2_PIX_FMT_SGBIG10 v4l2_fourcc('G', 'B', 'I', '0') /* 10 GBGR.. IrGIrG.. */
+#define V4L2_PIX_FMT_SGIRG10 v4l2_fourcc('G', 'I', 'R', '0') /* 10 GIrGIr.. RGBG.. */
+#define V4L2_PIX_FMT_SIGGR10 v4l2_fourcc('I', 'G', 'R', '0') /* 10 IrGIrG.. GRGB.. */
+#define V4L2_PIX_FMT_SGIBG10 v4l2_fourcc('G', 'I', 'B', '0') /* 10 GIrGIr.. BGRG.. */
+#define V4L2_PIX_FMT_SIGGB10 v4l2_fourcc('I', 'G', 'B', '0') /* 10 IrGIrG.. GBGR.. */
 
 /* HSV formats */
 #define V4L2_PIX_FMT_HSV24 v4l2_fourcc('H', 'S', 'V', '3')
@@ -775,6 +784,8 @@
 #define V4L2_PIX_FMT_HI240    v4l2_fourcc('H', 'I', '2', '4') /* BTTV 8-bit dithered RGB */
 #define V4L2_PIX_FMT_QC08C    v4l2_fourcc('Q', '0', '8', 'C') /* Qualcomm 8-bit compressed */
 #define V4L2_PIX_FMT_QC10C    v4l2_fourcc('Q', '1', '0', 'C') /* Qualcomm 10-bit compressed */
+#define V4L2_PIX_FMT_TI1210   v4l2_fourcc('T', 'I', '1', '2') /* TI NV12 10-bit, two bytes per channel */
+#define V4L2_PIX_FMT_TI1610   v4l2_fourcc('T', 'I', '1', '6') /* TI NV16 10-bit, two bytes per channel */
 
 /* 10bit raw packed, 32 bytes for every 25 pixels, last LSB 6 bits unused */
 #define V4L2_PIX_FMT_IPU3_SBGGR10	v4l2_fourcc('i', 'p', '3', 'b') /* IPU3 packed 10-bit BGGR bayer */
diff -Naur --no-dereference a/kernel/configs/debug.config b/kernel/configs/debug.config
--- a/kernel/configs/debug.config	2023-12-20 11:00:29.000000000 -0500
+++ b/kernel/configs/debug.config	2024-01-28 14:01:31.256353824 -0500
@@ -104,3 +104,13 @@
 CONFIG_DYNAMIC_FTRACE=y
 CONFIG_FTRACE=y
 CONFIG_FUNCTION_TRACER=y
+
+#
+# Power Management
+#
+CONFIG_PM_DEBUG=y
+
+#
+# Crypto Libraries
+#
+CONFIG_CRYPTO_TEST=m
diff -Naur --no-dereference a/kernel/configs/no_smp.config b/kernel/configs/no_smp.config
--- a/kernel/configs/no_smp.config	1969-12-31 19:00:00.000000000 -0500
+++ b/kernel/configs/no_smp.config	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,6 @@
+##################################################
+# NO SMP Config
+##################################################
+
+CONFIG_SMP=n
+CONFIG_CPUSETS=n
diff -Naur --no-dereference a/kernel/configs/ti_arm64_prune.config b/kernel/configs/ti_arm64_prune.config
--- a/kernel/configs/ti_arm64_prune.config	1969-12-31 19:00:00.000000000 -0500
+++ b/kernel/configs/ti_arm64_prune.config	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,445 @@
+# Add config flags here that appear in the multi_v7_defconfig but are not
+# used by a kernel targetting only the currently supported TI EVMs
+
+# Non-TI Architectures
+CONFIG_ARCH_ACTIONS=n
+CONFIG_ARCH_SUNXI=n
+CONFIG_ARCH_AGILEX=n
+CONFIG_ARCH_ALPINE=n
+CONFIG_ARCH_APPLE=n
+CONFIG_ARCH_BCM=n
+CONFIG_ARCH_BCM2835=n
+CONFIG_ARCH_BCM_IPROC=n
+CONFIG_ARCH_BCMBCA=n
+CONFIG_ARCH_BERLIN=n
+CONFIG_ARCH_BRCMSTB=n
+CONFIG_ARCH_EXYNOS=n
+CONFIG_ARCH_LAYERSCAPE=n
+CONFIG_ARCH_LG1K=n
+CONFIG_ARCH_HISI=n
+CONFIG_ARCH_KEEMBAY=n
+CONFIG_ARCH_MEDIATEK=n
+CONFIG_ARCH_MESON=n
+CONFIG_ARCH_MVEBU=n
+CONFIG_ARCH_NXP=n
+CONFIG_ARCH_MXC=n
+CONFIG_ARCH_NPCM=n
+CONFIG_ARCH_QCOM=n
+CONFIG_ARCH_ROCKCHIP=n
+CONFIG_ARCH_SEATTLE=n
+CONFIG_ARCH_RENESAS=n
+CONFIG_ARCH_R8A7795=n
+CONFIG_ARCH_R8A7796=n
+CONFIG_ARCH_S32=n
+CONFIG_ARCH_STRATIX10=n
+CONFIG_ARCH_INTEL_SOCFPGA=n
+CONFIG_ARCH_SYNQUACER=n
+CONFIG_ARCH_TEGRA=n
+CONFIG_ARCH_SPRD=n
+CONFIG_ARCH_THUNDER=n
+CONFIG_ARCH_THUNDER2=n
+CONFIG_ARCH_UNIPHIER=n
+CONFIG_ARCH_VEXPRESS=n
+CONFIG_ARCH_VISCONTI=n
+CONFIG_ARCH_XGENE=n
+CONFIG_ARCH_ZX=n
+CONFIG_ARCH_ZYNQMP=n
+CONFIG_ARCH_TEGRA_132_SOC=n
+CONFIG_ARCH_TEGRA_210_SOC=n
+CONFIG_ARCH_TEGRA_186_SOC=n
+
+CONFIG_QCOM_FALKOR_ERRATUM_1003=n
+CONFIG_QCOM_FALKOR_ERRATUM_1009=n
+CONFIG_QCOM_QDF2400_ERRATUM_0065=n
+CONFIG_QCOM_FALKOR_ERRATUM_E1041=n
+
+CONFIG_CAVIUM_ERRATUM_22375=n
+CONFIG_CAVIUM_ERRATUM_23144=n
+CONFIG_CAVIUM_ERRATUM_23154=n
+CONFIG_CAVIUM_ERRATUM_27456=n
+CONFIG_CAVIUM_ERRATUM_30115=n
+
+CONFIG_HISILICON_ERRATUM_161600802=n
+
+# Disable Errata fixes not relevant for Cortex A53 and Cortext A72 cores.
+# The Socionext Synquacer GICv3 pre-ITS workaround is used on K3 devices
+# as well, thats why its left enabled.
+CONFIG_AMPERE_ERRATUM_AC03_CPU_38=n
+CONFIG_ARM64_ERRATUM_832075=n
+CONFIG_ARM64_ERRATUM_1024718=n
+CONFIG_ARM64_ERRATUM_1418040=n
+CONFIG_ARM64_ERRATUM_1165522=n
+CONFIG_ARM64_ERRATUM_1530923=n
+CONFIG_ARM64_ERRATUM_2441007=n
+CONFIG_ARM64_ERRATUM_1286807=n
+CONFIG_ARM64_ERRATUM_1463225=n
+CONFIG_ARM64_ERRATUM_1542419=n
+CONFIG_ARM64_ERRATUM_1508412=n
+CONFIG_ARM64_ERRATUM_2051678=n
+CONFIG_ARM64_ERRATUM_2077057=n
+CONFIG_ARM64_ERRATUM_2658417=n
+CONFIG_ARM64_ERRATUM_2054223=n
+CONFIG_ARM64_ERRATUM_2067961=n
+CONFIG_ARM64_ERRATUM_2441009=n
+CONFIG_CAVIUM_TX2_ERRATUM_219=n
+CONFIG_FUJITSU_ERRATUM_010001=n
+CONFIG_NVIDIA_CARMEL_CNP_ERRATUM=n
+
+# Serial
+CONFIG_SERIAL_8250_FSL=n
+CONFIG_SERIAL_8250_DW=n
+CONFIG_SERIAL_AMBA_PL011=n
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=n
+CONFIG_SERIAL_XILINX_PS_UART=n
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=n
+
+CONFIG_ARM_SCPI_PROTOCOL=n
+CONFIG_ARM_SCPI_POWER_DOMAIN=n
+CONFIG_ARM_SCPI_CPUFREQ=n
+CONFIG_SENSORS_ARM_SCPI=n
+CONFIG_COMMON_CLK_SCPI=n
+
+CONFIG_ARM_MHU=n
+CONFIG_PLATFORM_MHU=n
+
+CONFIG_ACPI=n
+
+CONFIG_NUMA=n
+
+CONFIG_XEN=n
+CONFIG_KVM=n
+
+CONFIG_ARM_BIG_LITTLE_CPUFREQ=n
+
+CONFIG_PCI_XGENE=n
+CONFIG_PCI_HISI=n
+CONFIG_PCIE_KIRIN=n
+
+# DRM
+CONFIG_DRM_NOUVEAU=n
+CONFIG_DRM_I2C_ADV7511=n
+CONFIG_DRM_ETNAVIV=n
+CONFIG_DRM_HISI_HIBMC=n
+CONFIG_DRM_HISI_KIRIN=n
+CONFIG_DRM_MXSFB=n
+CONFIG_DRM_PL111=n
+CONFIG_DRM_LIMA=n
+CONFIG_DRM_PANFROST=n
+
+# Video
+CONFIG_VGA_ARB=n
+CONFIG_FB_EFI=n
+
+# V4L2
+CONFIG_RC_CORE=n
+
+# Sound
+CONFIG_SND_SPI=n
+CONFIG_SND_SOC_FSL_SAI=n
+CONFIG_SND_SOC_AK4613=n
+CONFIG_SND_SOC_ES7134=n
+CONFIG_SND_SOC_ES7241=n
+CONFIG_SND_SOC_TAS571X=n
+
+# USB
+CONFIG_USB_MUSB_HDRC=n
+CONFIG_USB_DWC2=n
+CONFIG_USB_CHIPIDEA=n
+CONFIG_USB_ISP1760=n
+CONFIG_USB_HSIC_USB3503=n
+
+# Generic kernel
+
+# We recommend to turn off Real-Time group scheduling in the
+# kernel when using systemd. RT group scheduling effectively
+# makes RT scheduling unavailable for most userspace, since it
+# requires explicit assignment of RT budgets to each unit whose
+# processes making use of RT. As there's no sensible way to
+# assign these budgets automatically this cannot really be
+# fixed, and it's best to disable group scheduling hence.
+CONFIG_RT_GROUP_SCHED=n
+
+# Remove debug features.
+CONFIG_SLUB_DEBUG=n
+
+# We are not a crash kernel
+CONFIG_CRASH_DUMP=n
+
+# ARM Scalable Vector Extension (SVE) is available only with ARMv8.2-A
+# and above. Since current TI SoCs are based on ARMv8.0, disable SVE
+CONFIG_ARM64_SVE=n
+
+# Plan 9 is a distributed resource sharing protocol thats not
+# typically used on TI processors
+CONFIG_NET_9P=n
+
+# Non-TI hardware vendor specific drivers
+CONFIG_KEYBOARD_CROS_EC=n
+CONFIG_I2C_CROS_EC_TUNNEL=n
+CONFIG_QRTR=n
+CONFIG_SPI_NXP_FLEXSPI=n
+CONFIG_GPIO_ALTERA=n
+CONFIG_GPIO_DWAPB=n
+CONFIG_GPIO_MB86S7X=n
+CONFIG_GPIO_PL061=n
+CONFIG_GPIO_XGENE=n
+CONFIG_POWER_RESET_XGENE=n
+CONFIG_ARM_SP805_WATCHDOG=n
+CONFIG_ARM_SBSA_WATCHDOG=n
+CONFIG_DW_WATCHDOG=n
+CONFIG_MFD_SEC_CORE=n
+CONFIG_REGULATOR_QCOM_SPMI=n
+CONFIG_DRM_MALI_DISPLAY=n
+CONFIG_DRM_RCAR_DW_HDMI=n
+CONFIG_DRM_DW_HDMI_AHB_AUDIO=n
+CONFIG_DRM_DW_HDMI_CEC=n
+CONFIG_FB_SSD1307=n
+CONFIG_MMC_ARMMMCI=n
+CONFIG_MMC_SDHCI_XENON=n
+CONFIG_RTC_DRV_S5M=n
+CONFIG_RTC_DRV_CROS_EC=n
+CONFIG_RTC_DRV_PL031=n
+CONFIG_FSL_EDMA=n
+CONFIG_MV_XOR_V2=n
+CONFIG_PL330_DMA=n
+CONFIG_QCOM_HIDMA_MGMT=n
+CONFIG_QCOM_HIDMA=n
+CONFIG_CHROME_PLATFORMS=n
+CONFIG_CROS_EC=n
+CONFIG_CROS_EC_I2C=n
+CONFIG_CROS_EC_SPI=n
+CONFIG_CROS_EC_CHARDEV=n
+CONFIG_SURFACE_PLATFORMS=n
+CONFIG_COMMON_CLK_S2MPS11=n
+CONFIG_COMMON_CLK_VC5=n
+CONFIG_COMMON_CLK_BD718XX=n
+CONFIG_FSL_ERRATUM_A008585=n
+CONFIG_HISILICON_ERRATUM_161010101=n
+CONFIG_RPMSG_QCOM_GLINK_RPM=n
+CONFIG_SOUNDWIRE_QCOM=n
+CONFIG_EXTCON_USBC_CROS_EC=n
+CONFIG_QCOM_SPMI_ADC5=n
+CONFIG_IIO_CROS_EC_SENSORS_CORE=n
+CONFIG_IIO_CROS_EC_SENSORS=n
+CONFIG_IIO_CROS_EC_LIGHT_PROX=n
+CONFIG_IIO_CROS_EC_BARO=n
+CONFIG_PWM_CROS_EC=n
+CONFIG_SLIM_QCOM_CTRL=n
+CONFIG_SPI_PL022=n
+CONFIG_SLIMBUS=n
+CONFIG_REGMAP_SLIMBUS=n
+CONFIG_SCSI_HISI_SAS=n
+CONFIG_AHCI_CEVA=n
+CONFIG_AHCI_XGENE=n
+CONFIG_AHCI_QORIQ=n
+CONFIG_SATA_SIL24=n
+CONFIG_BCMGENET=n
+CONFIG_SYSTEMPORT=n
+CONFIG_HNS_DSAF=n
+CONFIG_HNS_ENET=n
+CONFIG_HNS3=n
+CONFIG_NET_VENDOR_NVIDIA=n
+CONFIG_NET_VENDOR_RENESAS=n
+CONFIG_NET_VENDOR_SAMSUNG=n
+CONFIG_NET_VENDOR_STMICRO=n
+CONFIG_NET_VENDOR_XILINX=n
+CONFIG_BROADCOM_PHY=n
+CONFIG_BCM54140_PHY=n
+CONFIG_ROCKCHIP_PHY=n
+CONFIG_PCS_XPCS=n
+CONFIG_HW_RANDOM_ARM_SMCCC_TRNG=n
+CONFIG_HW_RANDOM_CN10K=n
+CONFIG_I2C_CADENCE=n
+CONFIG_I2C_DESIGNWARE_SLAVE=n
+CONFIG_I2C_DESIGNWARE_PLATFORM=n
+CONFIG_I2C_RK3X=n
+CONFIG_PINCTRL_MAX77620=n
+CONFIG_DRM_RCAR_USE_LVDS=n
+CONFIG_DRM_RCAR_USE_MIPI_DSI=n
+CONFIG_SND_SOC_FSL_ASRC=n
+CONFIG_SND_SOC_FSL_AUDMIX=n
+CONFIG_SND_SOC_FSL_SSI=n
+CONFIG_SND_SOC_FSL_SPDIF=n
+CONFIG_SND_SOC_FSL_ESAI=n
+CONFIG_SND_SOC_FSL_MICFIL=n
+CONFIG_SND_SOC_IMX_AUDMUX=n
+CONFIG_MMC_SDHCI_OF_DWCMSHC=n
+CONFIG_MMC_SDHCI_CADENCE=n
+CONFIG_MMC_SDHCI_F_SDH30=n
+CONFIG_MMC_DW=n
+CONFIG_MMC_MTK=n
+CONFIG_PCIE_ALTERA=n
+CONFIG_PCI_HOST_THUNDER_PEM=n
+CONFIG_PCI_HOST_THUNDER_ECAM=n
+CONFIG_PCI_MESON=n
+CONFIG_BRCMSTB_GISB_ARB=n
+CONFIG_VEXPRESS_CONFIG=n
+CONFIG_MTD_NAND_DENALI_DT=n
+CONFIG_MTD_NAND_BRCMNAND=n
+CONFIG_B53=n
+CONFIG_NET_DSA_BCM_SF2=n
+CONFIG_CAN_FLEXCAN=n
+CONFIG_SPI_DESIGNWARE=n
+CONFIG_SPI_ROCKCHIP=n
+CONFIG_DRM_HDLCD=n
+CONFIG_DRM_KOMEDA=n
+CONFIG_COMMON_CLK_RK808=n
+CONFIG_COMMON_CLK_XGENE=n
+CONFIG_SOC_BRCMSTB=n
+
+# Serial Power Management Interface (SPMI) has not been used on TI
+# platforms (yet)
+CONFIG_SPMI=n
+
+# DVB and TV tuner cards are rarely used on TI platforms, if at all
+CONFIG_CXD2880_SPI_DRV=n
+CONFIG_MEDIA_TUNER_E4000=n
+CONFIG_MEDIA_TUNER_FC0011=n
+CONFIG_MEDIA_TUNER_FC0012=n
+CONFIG_MEDIA_TUNER_FC0013=n
+CONFIG_MEDIA_TUNER_FC2580=n
+CONFIG_MEDIA_TUNER_IT913X=n
+CONFIG_MEDIA_TUNER_M88RS6000T=n
+CONFIG_MEDIA_TUNER_MAX2165=n
+CONFIG_MEDIA_TUNER_MC44S803=n
+CONFIG_MEDIA_TUNER_MSI001=n
+CONFIG_MEDIA_TUNER_MT2060=n
+CONFIG_MEDIA_TUNER_MT2063=n
+CONFIG_MEDIA_TUNER_MT20XX=n
+CONFIG_MEDIA_TUNER_MT2131=n
+CONFIG_MEDIA_TUNER_MT2266=n
+CONFIG_MEDIA_TUNER_MXL301RF=n
+CONFIG_MEDIA_TUNER_MXL5005S=n
+CONFIG_MEDIA_TUNER_MXL5007T=n
+CONFIG_MEDIA_TUNER_QM1D1B0004=n
+CONFIG_MEDIA_TUNER_QM1D1C0042=n
+CONFIG_MEDIA_TUNER_QT1010=n
+CONFIG_MEDIA_TUNER_R820T=n
+CONFIG_MEDIA_TUNER_SI2157=n
+CONFIG_MEDIA_TUNER_SIMPLE=n
+CONFIG_MEDIA_TUNER_TDA18212=n
+CONFIG_MEDIA_TUNER_TDA18218=n
+CONFIG_MEDIA_TUNER_TDA18250=n
+CONFIG_MEDIA_TUNER_TDA18271=n
+CONFIG_MEDIA_TUNER_TDA827X=n
+CONFIG_MEDIA_TUNER_TDA8290=n
+CONFIG_MEDIA_TUNER_TDA9887=n
+CONFIG_MEDIA_TUNER_TEA5761=n
+CONFIG_MEDIA_TUNER_TEA5767=n
+CONFIG_MEDIA_TUNER_TUA9001=n
+CONFIG_MEDIA_TUNER_XC2028=n
+CONFIG_MEDIA_TUNER_XC4000=n
+CONFIG_MEDIA_TUNER_XC5000=n
+CONFIG_DVB_M88DS3103=n
+CONFIG_DVB_MXL5XX=n
+CONFIG_DVB_STB0899=n
+CONFIG_DVB_STB6100=n
+CONFIG_DVB_STV090x=n
+CONFIG_DVB_STV0910=n
+CONFIG_DVB_STV6110x=n
+CONFIG_DVB_STV6111=n
+CONFIG_DVB_DRXK=n
+CONFIG_DVB_MN88472=n
+CONFIG_DVB_MN88473=n
+CONFIG_DVB_SI2165=n
+CONFIG_DVB_TDA18271C2DD=n
+CONFIG_DVB_CX24110=n
+CONFIG_DVB_CX24116=n
+CONFIG_DVB_CX24117=n
+CONFIG_DVB_CX24120=n
+CONFIG_DVB_CX24123=n
+CONFIG_DVB_DS3000=n
+CONFIG_DVB_MB86A16=n
+CONFIG_DVB_MT312=n
+CONFIG_DVB_S5H1420=n
+CONFIG_DVB_SI21XX=n
+CONFIG_DVB_STB6000=n
+CONFIG_DVB_STV0288=n
+CONFIG_DVB_STV0299=n
+CONFIG_DVB_STV0900=n
+CONFIG_DVB_STV6110=n
+CONFIG_DVB_TDA10071=n
+CONFIG_DVB_TDA10086=n
+CONFIG_DVB_TDA8083=n
+CONFIG_DVB_TDA8261=n
+CONFIG_DVB_TDA826X=n
+CONFIG_DVB_TS2020=n
+CONFIG_DVB_TUA6100=n
+CONFIG_DVB_TUNER_CX24113=n
+CONFIG_DVB_TUNER_ITD1000=n
+CONFIG_DVB_VES1X93=n
+CONFIG_DVB_ZL10036=n
+CONFIG_DVB_ZL10039=n
+CONFIG_DVB_AF9013=n
+CONFIG_DVB_CX22700=n
+CONFIG_DVB_CX22702=n
+CONFIG_DVB_CXD2820R=n
+CONFIG_DVB_CXD2841ER=n
+CONFIG_DVB_DIB3000MB=n
+CONFIG_DVB_DIB3000MC=n
+CONFIG_DVB_DIB7000M=n
+CONFIG_DVB_DIB7000P=n
+CONFIG_DVB_DIB9000=n
+CONFIG_DVB_DRXD=n
+CONFIG_DVB_EC100=n
+CONFIG_DVB_L64781=n
+CONFIG_DVB_MT352=n
+CONFIG_DVB_NXT6000=n
+CONFIG_DVB_RTL2830=n
+CONFIG_DVB_RTL2832=n
+CONFIG_DVB_RTL2832_SDR=n
+CONFIG_DVB_S5H1432=n
+CONFIG_DVB_SI2168=n
+CONFIG_DVB_SP887X=n
+CONFIG_DVB_STV0367=n
+CONFIG_DVB_TDA10048=n
+CONFIG_DVB_TDA1004X=n
+CONFIG_DVB_ZD1301_DEMOD=n
+CONFIG_DVB_ZL10353=n
+CONFIG_DVB_CXD2880=n
+CONFIG_DVB_STV0297=n
+CONFIG_DVB_TDA10021=n
+CONFIG_DVB_TDA10023=n
+CONFIG_DVB_VES1820=n
+CONFIG_DVB_AU8522_DTV=n
+CONFIG_DVB_AU8522_V4L=n
+CONFIG_DVB_BCM3510=n
+CONFIG_DVB_LG2160=n
+CONFIG_DVB_LGDT3305=n
+CONFIG_DVB_LGDT3306A=n
+CONFIG_DVB_LGDT330X=n
+CONFIG_DVB_MXL692=n
+CONFIG_DVB_NXT200X=n
+CONFIG_DVB_OR51132=n
+CONFIG_DVB_OR51211=n
+CONFIG_DVB_S5H1409=n
+CONFIG_DVB_S5H1411=n
+CONFIG_DVB_DIB8000=n
+CONFIG_DVB_MB86A20S=n
+CONFIG_DVB_S921=n
+CONFIG_DVB_MN88443X=n
+CONFIG_DVB_TC90522=n
+CONFIG_DVB_PLL=n
+CONFIG_DVB_TUNER_DIB0070=n
+CONFIG_DVB_TUNER_DIB0090=n
+CONFIG_DVB_A8293=n
+CONFIG_DVB_AF9033=n
+CONFIG_DVB_ASCOT2E=n
+CONFIG_DVB_ATBM8830=n
+CONFIG_DVB_HELENE=n
+CONFIG_DVB_HORUS3A=n
+CONFIG_DVB_ISL6405=n
+CONFIG_DVB_ISL6421=n
+CONFIG_DVB_ISL6423=n
+CONFIG_DVB_IX2505V=n
+CONFIG_DVB_LGS8GL5=n
+CONFIG_DVB_LGS8GXX=n
+CONFIG_DVB_LNBH25=n
+CONFIG_DVB_LNBH29=n
+CONFIG_DVB_LNBP21=n
+CONFIG_DVB_LNBP22=n
+CONFIG_DVB_M88RS2000=n
+CONFIG_DVB_TDA665x=n
+CONFIG_DVB_DRX39XYJ=n
+CONFIG_DVB_CXD2099=n
+CONFIG_DVB_SP2=n
diff -Naur --no-dereference a/kernel/configs/ti_multi_v7_prune.config b/kernel/configs/ti_multi_v7_prune.config
--- a/kernel/configs/ti_multi_v7_prune.config	1969-12-31 19:00:00.000000000 -0500
+++ b/kernel/configs/ti_multi_v7_prune.config	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,173 @@
+# Add config flags here that appear in the multi_v7_defconfig but are not
+# used by a kernel targetting only the currently supported TI EVMs
+
+# Non-TI Architectures
+CONFIG_ARCH_ACTIONS=n
+CONFIG_ARCH_AIROHA=n
+CONFIG_ARCH_ALPINE=n
+CONFIG_ARCH_ARTPEC=n
+CONFIG_ARCH_ASPEED=n
+CONFIG_ARCH_AT91=n
+CONFIG_ARCH_BCM=n
+CONFIG_ARCH_BCM_CYGNUS=n
+CONFIG_ARCH_BCM_NSP=n
+CONFIG_ARCH_BCM_5301X=n
+CONFIG_ARCH_BCM_281XX=n
+CONFIG_ARCH_BCM_21664=n
+CONFIG_ARCH_BRCMSTB=n
+CONFIG_ARCH_BERLIN=n
+CONFIG_ARCH_DIGICOLOR=n
+CONFIG_ARCH_HIGHBANK=n
+CONFIG_ARCH_HISI=n
+CONFIG_ARCH_HI3xxx=n
+CONFIG_ARCH_HIP01=n
+CONFIG_ARCH_HIP04=n
+CONFIG_ARCH_HIX5HD2=n
+CONFIG_ARCH_HPE=n
+CONFIG_ARCH_MESON=n
+CONFIG_ARCH_MXC=n
+CONFIG_ARCH_MEDIATEK=n
+CONFIG_ARCH_MILBEAUT=n
+CONFIG_ARCH_QCOM=n
+CONFIG_ARCH_MMP=n
+CONFIG_ARCH_MSM8X60=n
+CONFIG_ARCH_MSM8960=n
+CONFIG_ARCH_MSM8974=n
+CONFIG_ARCH_ROCKCHIP=n
+CONFIG_ARCH_SOCFPGA=n
+CONFIG_ARCH_SPEAR13XX=n
+CONFIG_ARCH_STI=n
+CONFIG_ARCH_EXYNOS=n
+CONFIG_ARCH_SHMOBILE_MULTI=n
+CONFIG_ARCH_EMEV2=n
+CONFIG_ARCH_R7S72100=n
+CONFIG_ARCH_R8A73A4=n
+CONFIG_ARCH_R8A7740=n
+CONFIG_ARCH_R8A7778=n
+CONFIG_ARCH_R8A7779=n
+CONFIG_ARCH_R8A7790=n
+CONFIG_ARCH_R8A7791=n
+CONFIG_ARCH_R8A7793=n
+CONFIG_ARCH_R8A7794=n
+CONFIG_ARCH_RENESAS=n
+CONFIG_ARCH_SH73A0=n
+CONFIG_ARCH_SUNXI=n
+CONFIG_ARCH_STM32=n
+CONFIG_ARCH_SIRF=n
+CONFIG_ARCH_TEGRA=n
+CONFIG_ARCH_TEGRA_2x_SOC=n
+CONFIG_ARCH_TEGRA_3x_SOC=n
+CONFIG_ARCH_TEGRA_114_SOC=n
+CONFIG_ARCH_TEGRA_124_SOC=n
+CONFIG_ARCH_UNIPHIER=n
+CONFIG_ARCH_U8500=n
+CONFIG_ARCH_VEXPRESS=n
+CONFIG_ARCH_VEXPRESS_TC2_PM=n
+CONFIG_ARCH_WM8850=n
+CONFIG_ARCH_ZYNQ=n
+CONFIG_ARCH_VIRT=n
+CONFIG_ARCH_MVEBU=n
+CONFIG_PLAT_SPEAR=n
+CONFIG_CHROME_PLATFORMS=n
+CONFIG_ARCH_INTEL_SOCFPGA=n
+CONFIG_ARCH_SUNPLUS=n
+
+# Multifunction device drivers
+CONFIG_MFD_AS3711=n
+CONFIG_MFD_AS3722=n
+CONFIG_MFD_ATMEL_FLEXCOM=n
+CONFIG_MFD_ATMEL_HLCDC=n
+CONFIG_MFD_BCM590XX=n
+CONFIG_MFD_AXP20X_I2C=n
+CONFIG_MFD_DA9063=n
+CONFIG_MFD_MAX14577=n
+CONFIG_MFD_MAX77686=n
+CONFIG_MFD_MAX77693=n
+CONFIG_MFD_MAX8907=n
+CONFIG_MFD_MAX8997=n
+CONFIG_MFD_MAX8998=n
+CONFIG_MFD_PM8XXX=n
+CONFIG_MFD_RK808=n
+CONFIG_MFD_RN5T618=n
+CONFIG_MFD_SEC_CORE=n
+CONFIG_MFD_STMPE=n
+
+# Regulators
+CONFIG_REGULATOR_ACT8865=n
+CONFIG_REGULATOR_DA9210=n
+CONFIG_REGULATOR_FAN53555=n
+CONFIG_REGULATOR_LP872X=n
+CONFIG_REGULATOR_MAX8952=n
+CONFIG_REGULATOR_MAX8973=n
+CONFIG_REGULATOR_PWM=n
+CONFIG_REGULATOR_TPS51632=n
+CONFIG_REGULATOR_TWL4030=n
+
+# RTC drivers
+CONFIG_RTC_DRV_HYM8563=n
+CONFIG_RTC_DRV_RS5C372=n
+CONFIG_RTC_DRV_BQ32K=n
+CONFIG_RTC_DRV_S35390A=n
+CONFIG_RTC_DRV_RX8581=n
+CONFIG_RTC_DRV_EM3027=n
+
+# Watchdog Device Drivers
+CONFIG_XILINX_WATCHDOG=n
+CONFIG_DW_WATCHDOG=n
+
+# GPIO
+CONFIG_GPIO_DWAPB=n
+CONFIG_GPIO_XILINX=n
+CONFIG_GPIO_TPS6586X=n
+
+# Sound
+CONFIG_SND_ARM=n
+CONFIG_SND_SPI=n
+CONFIG_SND_ATMEL_SOC=n
+CONFIG_SND_SOC_FSL_SAI=n
+CONFIG_SND_SOC_AK4642=n
+CONFIG_SND_SOC_CPCAP=n
+CONFIG_SND_SOC_SGTL5000=n
+CONFIG_SND_SOC_STI_SAS=n
+CONFIG_SND_SOC_WM8978=n
+
+# DRM
+CONFIG_VGA_ARB=n
+CONFIG_DRM_I2C_ADV7511=n
+CONFIG_DRM_NOUVEAU=n
+CONFIG_DRM_EXYNOS=n
+CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=n
+CONFIG_DRM_NXP_PTN3460=n
+CONFIG_DRM_PARADE_PS8622=n
+CONFIG_DRM_STI=n
+CONFIG_DRM_PANEL_SAMSUNG_LD9040=n
+CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=n
+CONFIG_DRM_DUMB_VGA_DAC=n
+CONFIG_DRM_HISI_KIRIN=n
+CONFIG_DRM_RCAR_LVDS=n
+CONFIG_DRM_FSL_DCU=n
+CONFIG_DRM_SII9234=n
+CONFIG_DRM_MXSFB=n
+CONFIG_DRM_HISI_HIBMC=n
+CONFIG_DRM_ATMEL_HLCDC=n
+CONFIG_DRM_STM=n
+CONFIG_DRM_PANEL_ORISETECH_OTM8009A=n
+CONFIG_DRM_PANEL_RAYDIUM_RM68200=n
+CONFIG_DRM_TOSHIBA_TC358764=n
+CONFIG_DRM_ETNAVIV=n
+CONFIG_DRM_PL111=n
+CONFIG_DRM_LIMA=n
+CONFIG_DRM_PANFROST=n
+
+# Video
+CONFIG_LCD_CLASS_DEVICE=n
+CONFIG_FB_EFI=n
+CONFIG_FB_SIMPLE=n
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=n
+CONFIG_FB_ARMCLCD=n
+CONFIG_XEN_FBDEV_FRONTEND=n
+
+# USB
+CONFIG_USB_DWC2=n
+CONFIG_USB_CHIPIDEA=n
+CONFIG_USB_ISP1760=n
diff -Naur --no-dereference a/kernel/configs/ti_rt.config b/kernel/configs/ti_rt.config
--- a/kernel/configs/ti_rt.config	1969-12-31 19:00:00.000000000 -0500
+++ b/kernel/configs/ti_rt.config	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,188 @@
+##################################################
+# Real Time Linux Configs
+##################################################
+
+CONFIG_PREEMPT=y
+CONFIG_PREEMPT_RT=y
+
+# max out the kernel's tick
+#
+# Ideally this is a balance. Increasing this means we
+# spend more time in the scheduler deciding what we
+# should do and less time on doing it however this
+# also minimizes the time spent running a low-priority
+# task while a real-time priority task is awake
+CONFIG_HZ_1000=y
+CONFIG_HZ=1000
+
+# omit scheduling ticks for CPUs with a single task
+#
+# If a CPU has only one runnable task there is little
+# need to contiguously interrupt it as there is no other
+# task for it to switch to. This comes at the cost of having
+# to offload the CPU's RCU callbacks to another CPU with
+# an active tick.
+#
+# For workloads with many short-lived tasks HZ_PERIODIC may
+# be the better selection as adaptive-tick modes does not
+# come without tradeoffs. For example the user-to kernel
+# transitions are slightly more expensive
+CONFIG_NO_HZ_FULL=y
+CONFIG_CONTEXT_TRACKING_USER=y
+
+# track our RCU callbacks
+#
+# there are situations in which idle CPUs cannot enter
+# a dynctick or adaptive-tick mode, the most common reason
+# being when a CPU has RCU callbacks pending. However boosting
+# this thread will compete with the realtime task. So let's
+# disable this for now.
+CONFIG_RCU_NOCB_CPU_DEFAULT_ALL=n
+CONFIG_RCU_BOOST=n
+
+# memory management tuning
+#
+# The SLUB allocator (default allocator used by the kernel)
+# uses per-cpu caches to accelerate allocation and freeing of
+# objects local to that processor. This comes at the cost of
+# more indeterminism when freeing. Remove this to remove jitter
+CONFIG_SLUB_CPU_PARTIAL=n
+
+# RCU system tuning
+#
+# The scheduler heavily utilizes the RCU subsystem to avoid
+# large amounts of locking that would be needed otherwise.
+# Removing this is showing to improve the am62x latency numbers
+# using stress-ng and cyclictest.
+CONFIG_RCU_TRACE=n
+
+# remove have kmemleak support
+#
+# Even-though the kmemleak detector is disabled, removing it
+# completely from the build is showing improvements for the
+# am62x latency numbers when monitoring with cyclictest and
+# stress-ng to generate a synthetic background load.
+CONFIG_HAVE_DEBUG_KMEMLEAK=n
+
+# Disable debug features
+
+# CoreSight debug and trace drivers are not typically used in
+# production. Keep them disabled by default. Users can enable
+# when debugging is needed.
+CONFIG_CORESIGHT=n
+
+# Remove support for symbolic crash dumps. These are useful
+# while debugging and not must have for production. This also
+# helps reduce kernel size.
+CONFIG_KALLSYMS=n
+
+# Disable profiling support. Not needed on a production system.
+CONFIG_PROFILING=n
+
+# Disable support for performance events. These are used only
+# for development and debug. Not needed on production system.
+CONFIG_PERF_EVENTS=n
+
+# Disable eBPF support which is typically used for tracing and
+# profiling. This prevents users from loading eBPF programs
+# but BPF usage within the kernel should still work. Disabling
+# JIT compiler will slow down packet filtering.
+CONFIG_BPF_SYSCALL=n
+CONFIG_BPF_JIT=n
+
+# Fine granularity IRQ time accounting is not needed on a
+# production system.
+CONFIG_IRQ_TIME_ACCOUNTING=n
+
+# HACK: speed up event stream timer
+#
+# More of a TODO for myself... however something is putting
+# the CPUs in WFE. Turning this off will increase the
+# frequency this timer that takes the CPUs our of WFE.
+#
+# Ideally this should have a negative effect on our measurements
+# as our CPUs are interrupted more often.
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=n
+
+# Disable ARMv8.1+ architecture featurres. TI processors are based
+# on ARMv8.0, and these feaures are not applicable. If enabled
+# they increase worst case latency from 41 usec to 83 usec when
+# tested on AM62x silicon with 1 hour cyclictest.
+CONFIG_ARM64_HW_AFDBM=n
+CONFIG_ARM64_PAN=n
+CONFIG_ARM64_USE_LSE_ATOMICS=n
+CONFIG_ARM64_RAS_EXTN=n
+CONFIG_ARM64_CNP=n
+CONFIG_ARM64_PTR_AUTH=n
+CONFIG_ARM64_AMU_EXTN=n
+CONFIG_ARM64_TLB_RANGE=n
+CONFIG_ARM64_BTI=n
+CONFIG_ARM64_E0PD=n
+
+# Disable group scheduling. We already disable RT_GROUP_SCHEDULING since
+# there is no way to meaningfully use it (see kernel/configs/ti_arm64_prune.config).
+# Disable group scheduling as such on RT kernel - the main focus anyway
+# is on RT tasks there.
+CONFIG_SCHED_AUTOGROUP=n
+
+# Disable symmetric multi-threading scheduler. Its not used on ARM64
+CONFIG_SCHED_SMT=n
+
+# Kernel stack base address randomization helps frustate attacks that depend on
+# stack address determinism. But it has an impact on RT latency. Using 1 hour
+# cyclictest on AM62x, it was found to increase worst case latency from 50 usecs
+# to 69 usecs. For RT kernel alone, be biased towards better latency over extra
+# security.
+CONFIG_RANDOMIZE_KSTACK_OFFSET=n
+
+# Kernel can apply read-only permissions to linear aliases of VM areas. This
+# provides extra layer of protection against advertent/inadvertent modification
+# of read-only data through the linear alias. While its a useful security
+# feature, it has performance and RT latency impact. When testing on AM62x
+# hardware using cyclictest running for 1 hour, the worst case latency increased
+# from 50 usecs to 58 usecs when this feature was enabled.
+CONFIG_RODATA_FULL_DEFAULT_ENABLED=n
+
+# Kernel page table isolation (KAISER)  unmaps kernel page tables when in EL0
+# to mitigate speculation attacks that enable privilege bypass. Note that CPUs
+# used on K3 SoCs are not impacted by meltdown vulnerability (CVE-2017-5754).
+# Using a 6 hour cyclictest, enabling KAISER was seen to increase worst case
+# latency by about 20 usecs (increase from 50 usecs to 70 usecs on AM62x hardware
+# using cutdown configuration designed to minimizeRT latency)
+CONFIG_UNMAP_KERNEL_AT_EL0=n
+
+# Disable control groups which are not minimum required by systemd and docker.
+# These can be enabled as per need of end application.
+#
+# Keeping device control group enabled as docker example does not start without
+# it.
+#
+# Having these enabled has an impact on RT latency. Using AM62x, using cyclictest,
+# a 40 usecs latency impact was seen (worst case latency went from 50 usecs to 90
+# usecs)
+CONFIG_MEMCG=n
+CONFIG_BLK_CGROUP=n
+CONFIG_CGROUP_SCHED=n
+CONFIG_CGROUP_PIDS=n
+CONFIG_CGROUP_FREEZER=n
+CONFIG_CGROUP_HUGETLB=n
+CONFIG_CPUSETS=n
+CONFIG_CGROUP_CPUACCT=n
+CONFIG_CGROUP_PERF=n
+CONFIG_CGROUP_BPF=n
+
+# HACK: Remove security features with real-time latency effects.
+# Unless you have aggressive latency goals you will most likely
+# want these feature enabled. ;)
+CONFIG_ARM64_TAGGED_ADDR_ABI=n
+CONFIG_SECCOMP=n
+CONFIG_STACKPROTECTOR=n
+CONFIG_VMAP_STACK=n
+CONFIG_GCC_PLUGINS=n
+CONFIG_RANDOMIZE_BASE=n
+
+#Disable PM features
+CONFIG_HOTPLUG_CPU=n
+CONFIG_CPU_IDLE=n
+CONFIG_CPU_FREQ=n
+CONFIG_SUSPEND=n
diff -Naur --no-dereference a/kernel/reboot.c b/kernel/reboot.c
--- a/kernel/reboot.c	2023-12-20 11:00:29.000000000 -0500
+++ b/kernel/reboot.c	2024-01-28 14:01:31.256353824 -0500
@@ -55,6 +55,7 @@
 	enum sys_off_mode mode;
 	bool blocking;
 	void *list;
+	struct device *dev;
 };
 
 /*
@@ -324,6 +325,7 @@
 	data.cb_data = handler->cb_data;
 	data.mode = mode;
 	data.cmd = cmd;
+	data.dev = handler->dev;
 
 	return handler->sys_off_cb(&data);
 }
@@ -511,6 +513,7 @@
 	handler = register_sys_off_handler(mode, priority, callback, cb_data);
 	if (IS_ERR(handler))
 		return PTR_ERR(handler);
+	handler->dev = dev;
 
 	return devm_add_action_or_reset(dev, devm_unregister_sys_off_handler,
 					handler);
diff -Naur --no-dereference a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	2023-12-20 11:00:29.000000000 -0500
+++ b/MAINTAINERS	2024-01-28 14:01:31.236353764 -0500
@@ -2994,7 +2994,6 @@
 F:	Documentation/devicetree/bindings/hwinfo/ti,k3-socinfo.yaml
 F:	arch/arm64/boot/dts/ti/Makefile
 F:	arch/arm64/boot/dts/ti/k3-*
-F:	include/dt-bindings/pinctrl/k3.h
 
 ARM/THECUS N2100 MACHINE SUPPORT
 M:	Lennert Buytenhek <kernel@wantstofly.org>
@@ -5140,7 +5139,7 @@
 L:	linux-media@vger.kernel.org
 S:	Maintained
 F:	Documentation/devicetree/bindings/media/coda.yaml
-F:	drivers/media/platform/chips-media/
+F:	drivers/media/platform/chips-media/coda
 
 CODE OF CONDUCT
 M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -9563,6 +9562,14 @@
 S:	Maintained
 F:	drivers/i2c/i2c-core-acpi.c
 
+I2C ADDRESS TRANSLATOR (ATR)
+M:	Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+R:	Luca Ceresoli <luca.ceresoli@bootlin.com>
+L:	linux-i2c@vger.kernel.org
+S:	Maintained
+F:	drivers/i2c/i2c-atr.c
+F:	include/linux/i2c-atr.h
+
 I2C CONTROLLER DRIVER FOR NVIDIA GPU
 M:	Ajay Gupta <ajayg@nvidia.com>
 L:	linux-i2c@vger.kernel.org
@@ -9990,10 +9997,25 @@
 F:	Documentation/devicetree/bindings/auxdisplay/img,ascii-lcd.yaml
 F:	drivers/auxdisplay/img-ascii-lcd.c
 
+IMGTEC VIDEO CODEC V4L2 DRIVER
+M:	Darren Etheridge <detheridge@ti.com>
+M:	Brandon Brnich <b-brnich@ti.com>
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/img,d5500-vxd.yaml
+F:	Documentation/devicetree/bindings/media/img,vxe384.yaml
+F:	drivers/media/platform/img/vxe-vxd
+
 IMGTEC IR DECODER DRIVER
 S:	Orphan
 F:	drivers/media/rc/img-ir/
 
+IMGTEC JPEG ENCODER DRIVER
+M:	Devarsh Thakkar <devarsht@ti.com>
+L:	linux-media@vger.kernel.org
+S:	Supported
+F:	Documentation/devicetree/bindings/media/img,e5010-jpeg-enc.yaml
+F:	drivers/media/platform/img/e5010/
+
 IMON SOUNDGRAPH USB IR RECEIVER
 M:	Sean Young <sean@mess.org>
 L:	linux-media@vger.kernel.org
@@ -15129,6 +15151,7 @@
 F:	drivers/mfd/palmas.c
 F:	drivers/mfd/tps65217.c
 F:	drivers/mfd/tps65218.c
+F:	drivers/mfd/tps65219.c
 F:	drivers/mfd/tps65910.c
 F:	drivers/mfd/twl-core.[ch]
 F:	drivers/mfd/twl4030*.c
@@ -20620,6 +20643,14 @@
 F:	drivers/mmc/host/tifm_sd.c
 F:	include/linux/tifm.h
 
+TI FPD-LINK DRIVERS
+M:	Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/i2c/ti,ds90*
+F:	drivers/media/i2c/ds90*
+F:	include/media/i2c/ds90*
+
 TI KEYSTONE MULTICORE NAVIGATOR DRIVERS
 M:	Nishanth Menon <nm@ti.com>
 M:	Santosh Shilimkar <ssantosh@kernel.org>
@@ -22144,6 +22175,15 @@
 F:	include/uapi/linux/watchdog.h
 F:	include/trace/events/watchdog.h
 
+WAVE5 VPU CODEC DRIVER
+M:	Nas Chung <nas.chung@chipsnmedia.com>
+M:	Robert Beckett <bob.beckett@collabora.com>
+M:	Sebastian Fricke <sebastian.fricke@collabora.com>
+L:	linux-media@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/media/cnm,wave5.yaml
+F:	drivers/media/platform/chips-media/wave5/
+
 WHISKEYCOVE PMIC GPIO DRIVER
 M:	Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
 L:	linux-gpio@vger.kernel.org
diff -Naur --no-dereference a/Makefile b/Makefile
--- a/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/Makefile	2024-01-28 14:01:31.236353764 -0500
@@ -2023,7 +2023,9 @@
 	@find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
 		\( -name '*.[aios]' -o -name '*.rsi' -o -name '*.ko' -o -name '.*.cmd' \
 		-o -name '*.ko.*' \
-		-o -name '*.dtb' -o -name '*.dtbo' -o -name '*.dtb.S' -o -name '*.dt.yaml' \
+		-o -name '*.dtb' -o -name '*.dtbo' \
+		-o -name '*.dtb.S' -o -name '*.dtbo.S' \
+		-o -name '*.dt.yaml' \
 		-o -name '*.dwo' -o -name '*.lst' \
 		-o -name '*.su' -o -name '*.mod' -o -name '*.usyms' \
 		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
diff -Naur --no-dereference a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
--- a/net/hsr/hsr_device.c	2023-12-20 11:00:29.000000000 -0500
+++ b/net/hsr/hsr_device.c	2024-01-28 14:01:31.256353824 -0500
@@ -173,7 +173,24 @@
 
 static int hsr_dev_close(struct net_device *dev)
 {
-	/* Nothing to do here. */
+	struct hsr_port *port;
+	struct hsr_priv *hsr;
+
+	hsr = netdev_priv(dev);
+	hsr_for_each_port(hsr, port) {
+		if (port->type == HSR_PT_MASTER)
+			continue;
+		switch (port->type) {
+		case HSR_PT_SLAVE_A:
+		case HSR_PT_SLAVE_B:
+			dev_uc_unsync(port->dev, dev);
+			dev_mc_unsync(port->dev, dev);
+			break;
+		default:
+			break;
+		}
+	}
+
 	return 0;
 }
 
@@ -404,12 +421,60 @@
 		hsr_del_port(port);
 }
 
+static void hsr_set_rx_mode(struct net_device *dev)
+{
+	struct hsr_port *port;
+	struct hsr_priv *hsr;
+
+	hsr = netdev_priv(dev);
+
+	hsr_for_each_port(hsr, port) {
+		if (port->type == HSR_PT_MASTER)
+			continue;
+		switch (port->type) {
+		case HSR_PT_SLAVE_A:
+		case HSR_PT_SLAVE_B:
+			dev_mc_sync_multiple(port->dev, dev);
+			dev_uc_sync_multiple(port->dev, dev);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+static void hsr_change_rx_flags(struct net_device *dev, int change)
+{
+	struct hsr_port *port;
+	struct hsr_priv *hsr;
+
+	hsr = netdev_priv(dev);
+
+	hsr_for_each_port(hsr, port) {
+		if (port->type == HSR_PT_MASTER)
+			continue;
+		switch (port->type) {
+		case HSR_PT_SLAVE_A:
+		case HSR_PT_SLAVE_B:
+			if (change & IFF_ALLMULTI)
+				dev_set_allmulti(port->dev,
+						 dev->flags &
+						 IFF_ALLMULTI ? 1 : -1);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
 static const struct net_device_ops hsr_device_ops = {
 	.ndo_change_mtu = hsr_dev_change_mtu,
 	.ndo_open = hsr_dev_open,
 	.ndo_stop = hsr_dev_close,
 	.ndo_start_xmit = hsr_dev_xmit,
+	.ndo_change_rx_flags = hsr_change_rx_flags,
 	.ndo_fix_features = hsr_fix_features,
+	.ndo_set_rx_mode = hsr_set_rx_mode,
 };
 
 static struct device_type hsr_type = {
@@ -532,6 +597,11 @@
 	if (res)
 		goto err_add_master;
 
+	/* HSR forwarding offload supported in lower device? */
+	if ((slave[0]->features & NETIF_F_HW_HSR_FWD) &&
+	    (slave[1]->features & NETIF_F_HW_HSR_FWD))
+		hsr->fwd_offloaded = true;
+
 	res = register_netdevice(hsr_dev);
 	if (res)
 		goto err_unregister;
diff -Naur --no-dereference a/net/hsr/hsr_main.h b/net/hsr/hsr_main.h
--- a/net/hsr/hsr_main.h	2023-12-20 11:00:29.000000000 -0500
+++ b/net/hsr/hsr_main.h	2024-01-28 14:01:31.256353824 -0500
@@ -189,6 +189,7 @@
 	struct list_head	self_node_db;	/* MACs of slaves */
 	struct timer_list	announce_timer;	/* Supervision frame dispatch */
 	struct timer_list	prune_timer;
+	unsigned int		fwd_offloaded : 1; /* Forwarding offloaded to HW */
 	int announce_count;
 	u16 sequence_nr;
 	u16 sup_sequence_nr;	/* For HSRv1 separate seq_nr for supervision */
diff -Naur --no-dereference a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c
--- a/net/hsr/hsr_slave.c	2023-12-20 11:00:29.000000000 -0500
+++ b/net/hsr/hsr_slave.c	2024-01-28 14:01:31.256353824 -0500
@@ -131,9 +131,14 @@
 	struct hsr_port *master;
 	int res;
 
-	res = dev_set_promiscuity(dev, 1);
-	if (res)
-		return res;
+	/* Don't use promiscuous mode for offload since L2 frame forward
+	 * happens at the offloaded hardware.
+	 */
+	if (!port->hsr->fwd_offloaded) {
+		res = dev_set_promiscuity(dev, 1);
+		if (res)
+			return res;
+	}
 
 	master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
 	hsr_dev = master->dev;
@@ -152,7 +157,9 @@
 fail_rx_handler:
 	netdev_upper_dev_unlink(dev, hsr_dev);
 fail_upper_dev_link:
-	dev_set_promiscuity(dev, -1);
+	if (port->hsr->fwd_offloaded)
+		dev_set_promiscuity(dev, -1);
+
 	return res;
 }
 
diff -Naur --no-dereference a/README.md b/README.md
--- a/README.md	1969-12-31 19:00:00.000000000 -0500
+++ b/README.md	2024-01-28 14:01:31.236353764 -0500
@@ -0,0 +1,3 @@
+# Gitlab CI
+
+Job Status: https://git.beagleboard.org/beagleboard/linux/-/jobs
diff -Naur --no-dereference a/samples/Kconfig b/samples/Kconfig
--- a/samples/Kconfig	2023-12-20 11:00:29.000000000 -0500
+++ b/samples/Kconfig	2024-01-28 14:01:31.256353824 -0500
@@ -243,6 +243,13 @@
 	help
 	  Build a sample program to work with mei device.
 
+config SAMPLE_TPS6594_PFSM
+	bool "Build example program working with TPS6594 PFSM driver"
+	depends on HEADERS_INSTALL
+	depends on CC_CAN_LINK
+	help
+	  Build a sample program to work with PFSM devices.
+
 config SAMPLE_WATCHDOG
 	bool "watchdog sample"
 	depends on CC_CAN_LINK
diff -Naur --no-dereference a/samples/Makefile b/samples/Makefile
--- a/samples/Makefile	2023-12-20 11:00:29.000000000 -0500
+++ b/samples/Makefile	2024-01-28 14:01:31.256353824 -0500
@@ -30,6 +30,7 @@
 obj-y					+= vfio-mdev/
 subdir-$(CONFIG_SAMPLE_VFS)		+= vfs
 obj-$(CONFIG_SAMPLE_INTEL_MEI)		+= mei/
+obj-$(CONFIG_SAMPLE_TPS6594_PFSM)	+= pfsm/
 subdir-$(CONFIG_SAMPLE_WATCHDOG)	+= watchdog
 subdir-$(CONFIG_SAMPLE_WATCH_QUEUE)	+= watch_queue
 obj-$(CONFIG_DEBUG_KMEMLEAK_TEST)	+= kmemleak/
diff -Naur --no-dereference a/samples/pfsm/.gitignore b/samples/pfsm/.gitignore
--- a/samples/pfsm/.gitignore	1969-12-31 19:00:00.000000000 -0500
+++ b/samples/pfsm/.gitignore	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+/pfsm-wakeup
diff -Naur --no-dereference a/samples/pfsm/Makefile b/samples/pfsm/Makefile
--- a/samples/pfsm/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ b/samples/pfsm/Makefile	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+userprogs-always-y += pfsm-wakeup
+
+userccflags += -I usr/include
diff -Naur --no-dereference a/samples/pfsm/pfsm-wakeup.c b/samples/pfsm/pfsm-wakeup.c
--- a/samples/pfsm/pfsm-wakeup.c	1969-12-31 19:00:00.000000000 -0500
+++ b/samples/pfsm/pfsm-wakeup.c	2024-01-28 14:01:31.256353824 -0500
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * TPS6594 PFSM userspace example
+ *
+ * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
+ *
+ * This example shows how to use PFSMs from a userspace application,
+ * on TI j721s2 platform. The PMIC is armed to be triggered by a RTC
+ * alarm to execute state transition (RETENTION to ACTIVE).
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <linux/rtc.h>
+#include <linux/tps6594_pfsm.h>
+
+#define ALARM_DELTA_SEC 30
+
+#define RTC_A "/dev/rtc0"
+
+#define PMIC_NB 3
+#define PMIC_A "/dev/pfsm-0-0x48"
+#define PMIC_B "/dev/pfsm-0-0x4c"
+#define PMIC_C "/dev/pfsm-2-0x58"
+
+static const char * const dev_pfsm[] = {PMIC_A, PMIC_B, PMIC_C};
+
+int main(int argc, char *argv[])
+{
+	int i, ret, fd_rtc, fd_pfsm[PMIC_NB] = { 0 };
+	struct rtc_time rtc_tm;
+	struct pmic_state_opt pmic_opt = { 0 };
+	unsigned long data;
+
+	fd_rtc = open(RTC_A, O_RDONLY);
+	if (fd_rtc < 0) {
+		perror("Failed to open RTC device.");
+		goto out;
+	}
+
+	for (i = 0 ; i < PMIC_NB ; i++) {
+		fd_pfsm[i] = open(dev_pfsm[i], O_RDWR);
+		if (fd_pfsm[i] < 0) {
+			perror("Failed to open PFSM device.");
+			goto out;
+		}
+	}
+
+	/* Read RTC date/time */
+	ret = ioctl(fd_rtc, RTC_RD_TIME, &rtc_tm);
+	if (ret < 0) {
+		perror("Failed to read RTC date/time.");
+		goto out;
+	}
+	printf("Current RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
+	       rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
+	       rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
+
+	/* Set RTC alarm to ALARM_DELTA_SEC sec in the future, and check for rollover */
+	rtc_tm.tm_sec += ALARM_DELTA_SEC;
+	if (rtc_tm.tm_sec >= 60) {
+		rtc_tm.tm_sec %= 60;
+		rtc_tm.tm_min++;
+	}
+	if (rtc_tm.tm_min == 60) {
+		rtc_tm.tm_min = 0;
+		rtc_tm.tm_hour++;
+	}
+	if (rtc_tm.tm_hour == 24)
+		rtc_tm.tm_hour = 0;
+	ret = ioctl(fd_rtc, RTC_ALM_SET, &rtc_tm);
+	if (ret < 0) {
+		perror("Failed to set RTC alarm.");
+		goto out;
+	}
+
+	/* Enable alarm interrupts */
+	ret = ioctl(fd_rtc, RTC_AIE_ON, 0);
+	if (ret < 0) {
+		perror("Failed to enable alarm interrupts.");
+		goto out;
+	}
+	printf("Waiting %d seconds for alarm...\n", ALARM_DELTA_SEC);
+
+	/*
+	 * Set RETENTION state with options for PMIC_C/B/A respectively.
+	 * Since PMIC_A is master, it should be the last one to be configured.
+	 */
+	pmic_opt.ddr_retention = 1;
+	for (i = PMIC_NB - 1 ; i >= 0 ; i--) {
+		printf("Set RETENTION state for PMIC_%d.\n", i);
+		sleep(1);
+		ret = ioctl(fd_pfsm[i], PMIC_SET_RETENTION_STATE, &pmic_opt);
+		if (ret < 0) {
+			perror("Failed to set RETENTION state.");
+			goto out_reset;
+		}
+	}
+
+	/* This blocks until the alarm ring causes an interrupt */
+	ret = read(fd_rtc, &data, sizeof(unsigned long));
+	if (ret < 0)
+		perror("Failed to get RTC alarm.");
+	else
+		puts("Alarm rang.\n");
+
+out_reset:
+	ioctl(fd_rtc, RTC_AIE_OFF, 0);
+
+	/* Set ACTIVE state for PMIC_A */
+	ioctl(fd_pfsm[0], PMIC_SET_ACTIVE_STATE, 0);
+
+out:
+	for (i = 0 ; i < PMIC_NB ; i++)
+		if (fd_pfsm[i])
+			close(fd_pfsm[i]);
+
+	if (fd_rtc)
+		close(fd_rtc);
+
+	return 0;
+}
diff -Naur --no-dereference a/samples/rpmsg/rpmsg_client_sample.c b/samples/rpmsg/rpmsg_client_sample.c
--- a/samples/rpmsg/rpmsg_client_sample.c	2023-12-20 11:00:29.000000000 -0500
+++ b/samples/rpmsg/rpmsg_client_sample.c	2024-01-28 14:01:31.256353824 -0500
@@ -79,6 +79,7 @@
 
 static struct rpmsg_device_id rpmsg_driver_sample_id_table[] = {
 	{ .name	= "rpmsg-client-sample" },
+	{ .name = "ti.ipc4.ping-pong" },
 	{ },
 };
 MODULE_DEVICE_TABLE(rpmsg, rpmsg_driver_sample_id_table);
diff -Naur --no-dereference a/scripts/Makefile.build b/scripts/Makefile.build
--- a/scripts/Makefile.build	2023-12-20 11:00:29.000000000 -0500
+++ b/scripts/Makefile.build	2024-01-28 14:01:31.256353824 -0500
@@ -468,10 +468,12 @@
 					$(filter %$(strip $(1)), $(targets))))
 # %.asn1.o <- %.asn1.[ch] <- %.asn1
 # %.dtb.o <- %.dtb.S <- %.dtb <- %.dts
+# %.dtbo.o <- %.dtbo.S <- %.dtbo <- %.dtso
 # %.lex.o <- %.lex.c <- %.l
 # %.tab.o <- %.tab.[ch] <- %.y
 targets += $(call intermediate_targets, .asn1.o, .asn1.c .asn1.h) \
 	   $(call intermediate_targets, .dtb.o, .dtb.S .dtb) \
+	   $(call intermediate_targets, .dtbo.o, .dtbo.S .dtbo) \
 	   $(call intermediate_targets, .lex.o, .lex.c) \
 	   $(call intermediate_targets, .tab.o, .tab.c .tab.h)
 
diff -Naur --no-dereference a/scripts/Makefile.lib b/scripts/Makefile.lib
--- a/scripts/Makefile.lib	2023-12-20 11:00:29.000000000 -0500
+++ b/scripts/Makefile.lib	2024-01-28 14:01:31.256353824 -0500
@@ -358,7 +358,7 @@
 DTC_FLAGS += $(if $(filter $(patsubst $(obj)/%,%,$@), $(base-dtb-y)), -@)
 
 # Generate an assembly file to wrap the output of the device tree compiler
-quiet_cmd_dt_S_dtb= DTB     $@
+quiet_cmd_dt_S_dtb= DTBS    $@
 cmd_dt_S_dtb=						\
 {							\
 	echo '\#include <asm-generic/vmlinux.lds.h>'; 	\
@@ -375,6 +375,24 @@
 $(obj)/%.dtb.S: $(obj)/%.dtb FORCE
 	$(call if_changed,dt_S_dtb)
 
+# Generate an assembly file to wrap the output of the device tree compiler
+quiet_cmd_dt_S_dtbo= DTBOS   $@
+cmd_dt_S_dtbo=						\
+{							\
+	echo '\#include <asm-generic/vmlinux.lds.h>';	\
+	echo '.section .dtb.init.rodata,"a"';		\
+	echo '.balign STRUCT_ALIGNMENT';		\
+	echo '.global __dtbo_$(subst -,_,$(*F))_begin';	\
+	echo '__dtbo_$(subst -,_,$(*F))_begin:';	\
+	echo '.incbin "$<" ';				\
+	echo '__dtbo_$(subst -,_,$(*F))_end:';		\
+	echo '.global __dtbo_$(subst -,_,$(*F))_end';	\
+	echo '.balign STRUCT_ALIGNMENT';		\
+} > $@
+
+$(obj)/%.dtbo.S: $(obj)/%.dtbo FORCE
+	$(call if_changed,dt_S_dtbo)
+
 quiet_cmd_dtc = DTC     $@
 cmd_dtc = $(HOSTCC) -E $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
 	$(DTC) -o $@ -b 0 \
@@ -405,7 +423,7 @@
 $(obj)/%.dtb: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE
 	$(call if_changed_dep,dtb)
 
-$(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE
+$(obj)/%.dtbo: $(src)/%.dtso $(DTC) FORCE
 	$(call if_changed_dep,dtc)
 
 dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
diff -Naur --no-dereference a/scripts/package/builddeb b/scripts/package/builddeb
--- a/scripts/package/builddeb	2023-12-20 11:00:29.000000000 -0500
+++ b/scripts/package/builddeb	2024-01-28 14:01:31.256353824 -0500
@@ -153,6 +153,7 @@
 	# Only some architectures with OF support have this target
 	if [ -d "${srctree}/arch/$SRCARCH/boot/dts" ]; then
 		$MAKE -f $srctree/Makefile INSTALL_DTBS_PATH="$tmpdir/usr/lib/$packagename" dtbs_install
+		$MAKE -f $srctree/Makefile INSTALL_DTBS_PATH="$tmpdir/boot/dtbs/$version" dtbs_install
 	fi
 fi
 
